{"context":{"domain":"natura-x-piloto"},"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":"688179c2a93dd170ce61e598","name":"piloto","domain":"natura-x-piloto","visibility":"public","settings":{"defaultAccessPolicy":"private"},"updatedAt":"2026-08-20T21:21:52.609Z","createdAt":"2025-07-24T00:09:38.924Z"}]}},{"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":"6a47f208ea22d868558c5be0","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotKpiCard","package":"natura-x-piloto","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 T = {\n  ink: '#101828', muted: '#757575', line: 'rgba(16,24,40,0.08)',\n  surface: '#FFFFFF', blue: '#0078DC', green: '#29AC56', orange: '#EC6718',\n  font: \"'Inter', -apple-system, system-ui, sans-serif\"\n};\nexport default {\n  css: `\n    .kpi{box-sizing:border-box;height:100%;width:100%;display:flex;flex-direction:column;\n      justify-content:space-between;gap:10px;padding:18px 20px;background:${T.surface};\n      border:1px solid ${T.line};border-radius:14px;\n      box-shadow:0 1px 3px rgba(16,24,40,0.06),0 1px 2px rgba(16,24,40,0.04);font-family:${T.font}}\n    .kpi .lbl{font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:${T.muted}}\n    .kpi .val{font-size:30px;font-weight:800;line-height:1.05;color:${T.ink};font-variant-numeric:tabular-nums}\n    .kpi .sub{font-size:13px;font-weight:500;color:${T.muted}}\n    .kpi .bar{height:4px;width:36px;border-radius:999px;margin-top:2px}\n  `,\n  render(d2){\n    const accent = d2.param('accent') || T.blue;\n    const label = String(d2.param('label','') || '');\n    const kind = String(d2.param('kind','text') || 'text');\n    let raw = d2.param('value','');\n    let value;\n    if (raw === null || raw === undefined || raw === '') value = '—';\n    else if (kind === 'currency') value = 'R$ ' + (Number(raw)||0).toLocaleString('pt-BR', {maximumFractionDigits:0});\n    else if (kind === 'number') value = (Number(raw)||0).toLocaleString('pt-BR');\n    else value = String(raw);\n    const sub = d2.param('sub','');\n    return `<div class=\"kpi\">\n      <div class=\"lbl\">${label}</div>\n      <div>\n        <div class=\"val\">${value}</div>\n        ${sub ? `<div class=\"sub\">${sub}</div>` : ''}\n      </div>\n      <div class=\"bar\" style=\"background:${accent}\"></div>\n    </div>`;\n  }\n};"}},"label":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"label"}}}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"sub":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"sub"}}}},"accent":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"accent"}}}},"kind":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"kind"}}}}}}}}}},{"_id":"6a47f21a9c748d97fd564173","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotLeaderRow","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"code"}}}},"name":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"name"}}}},"nivel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"nivel"}}}},"remuneracao":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"remuneracao"}}}},"onClick":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onClick"}}}}}}}}}},{"_id":"6a47f226d135f62a64ef1919","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotTotalizadorCard","package":"natura-x-piloto","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 T = {\n  ink: '#101828', line: 'rgba(255,255,255,0.22)',\n  blue: '#0078DC', blueDark: '#005CB0',\n  font: \"'Inter', -apple-system, system-ui, sans-serif\"\n};\nexport default {\n  css: `\n    .tot{box-sizing:border-box;height:100%;width:100%;display:flex;flex-direction:column;\n      justify-content:center;gap:8px;padding:26px 30px;border-radius:16px;color:#fff;\n      background:linear-gradient(135deg,${T.blue} 0%,${T.blueDark} 100%);\n      box-shadow:0 8px 24px rgba(0,92,176,0.28);font-family:${T.font}}\n    .tot .lbl{font-size:13px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;opacity:.85}\n    .tot .val{font-size:44px;font-weight:800;line-height:1;font-variant-numeric:tabular-nums}\n    .tot .meta{display:flex;align-items:center;gap:8px;margin-top:6px;font-size:13px;font-weight:500;opacity:.92}\n    .tot .pill{background:rgba(255,255,255,0.18);border:1px solid ${T.line};border-radius:999px;\n      padding:3px 12px;font-weight:700}\n  `,\n  render(d2){\n    const label = String(d2.param('label','Total do Setor')||'Total do Setor');\n    const total = 'R$ ' + (Number(d2.param('total',0))||0).toLocaleString('pt-BR', {maximumFractionDigits:0});\n    const n = Number(d2.param('leaderCount',0))||0;\n    const caption = String(d2.param('caption','')||'');\n    return `<div class=\"tot\">\n      <div class=\"lbl\">${label}</div>\n      <div class=\"val\">${total}</div>\n      <div class=\"meta\">\n        <span class=\"pill\">${n} ${n===1?'líder':'líderes'}</span>\n        ${caption?`<span>${caption}</span>`:''}\n      </div>\n    </div>`;\n  }\n};"}},"label":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"label"}}}},"total":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"total"}}}},"leaderCount":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"leaderCount"}}}},"caption":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"caption"}}}}}}}}}},{"_id":"6a47f23823ea82ec61fb80f0","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotRoleControls","package":"natura-x-piloto","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 T = {\n  ink: '#101828', muted: '#757575', line: 'rgba(16,24,40,0.12)',\n  surface: '#FFFFFF', blue: '#0078DC',\n  font: \"'Inter', -apple-system, system-ui, sans-serif\"\n};\nconst PERFIS = [ ['lider','Líder'], ['gn','GN'], ['gv','GV'] ];\nexport default {\n  css: `\n    .ctl{box-sizing:border-box;width:100%;display:flex;flex-wrap:wrap;align-items:flex-end;gap:16px;\n      padding:16px 20px;background:${T.surface};border:1px solid ${T.line};border-radius:14px;font-family:${T.font}}\n    .fld{display:flex;flex-direction:column;gap:5px}\n    .fld .cap{font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:${T.muted}}\n    .seg{display:inline-flex;background:#EEF1F5;border-radius:10px;padding:3px;gap:2px}\n    .seg button{border:0;background:transparent;font-family:${T.font};font-size:13px;font-weight:700;\n      color:${T.muted};padding:7px 16px;border-radius:8px;cursor:pointer;transition:all .12s ease}\n    .seg button[data-on]{background:${T.blue};color:#fff;box-shadow:0 1px 4px rgba(0,120,220,0.35)}\n    .ctl input{font-family:${T.font};font-size:14px;font-weight:600;color:${T.ink};background:#F7F9FB;\n      border:1px solid ${T.line};border-radius:9px;padding:8px 12px;width:120px;box-sizing:border-box}\n    .ctl input:focus{outline:none;border-color:${T.blue};background:#fff}\n    .ctl .grow{flex:1 1 auto}\n  `,\n  render(d2){\n    const s = d2.store(d2.params.store);\n    const perfil = s.get('data.perfil','gn');\n    const structureCode = s.get('data.structureCode','');\n    const cycle = s.get('data.cycle','');\n    return `<div class=\"ctl\">\n      <div class=\"fld\">\n        <span class=\"cap\">Perfil</span>\n        <div class=\"seg\">${PERFIS.map(([v,l])=>\n          `<button data-perfil=\"${v}\" ${perfil===v?'data-on':''}>${l}</button>`).join('')}</div>\n      </div>\n      <div class=\"fld\">\n        <span class=\"cap\">Setor / Estrutura</span>\n        <input class=\"in-structure\" value=\"${structureCode??''}\" placeholder=\"3253\" ${perfil==='gv'?'disabled':''}/>\n      </div>\n      <div class=\"fld\">\n        <span class=\"cap\">Ciclo</span>\n        <input class=\"in-cycle\" value=\"${cycle??''}\" placeholder=\"202516\"/>\n      </div>\n      <div class=\"grow\"></div>\n    </div>`;\n  },\n  mounted(d2){\n    const s = () => d2.store(d2.params.store);\n    d2.on('.seg button','click',(e,el)=>{ s().set('data.perfil', el.dataset.perfil); d2.emit('onChange', el.dataset.perfil); });\n    d2.on('.in-structure','change',(e,el)=>{ s().set('data.structureCode', el.value.trim()); d2.emit('onChange', el.value.trim()); });\n    d2.on('.in-cycle','change',(e,el)=>{ s().set('data.cycle', el.value.trim()); d2.emit('onChange', el.value.trim()); });\n  }\n};"}},"store":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"store"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}}}}}}}},{"_id":"6a47f300ea22d868558c5e44","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotDashboard","package":"natura-x-piloto","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 T = {\n  ink: '#101828', muted: '#757575', line: 'rgba(16,24,40,0.08)',\n  ground: '#F4F6F9', blue: '#0078DC', green: '#29AC56', orange: '#EC6718',\n  font: \"'Inter', -apple-system, system-ui, sans-serif\"\n};\nconst ACCENTS = [T.blue, T.green, T.orange, '#7A5AF8', '#0BA5A5'];\n\nfunction doFetch(d2){\n  const s = d2.store(d2.params.store);\n  const perfil = s.get('data.perfil','gn');\n  const structureCode = s.get('data.structureCode','3253');\n  const cycle = s.get('data.cycle','202516');\n  s.set('data.loading', true);\n  Promise.resolve(d2.rush(d2.params.api).invoke({ perfil, structureCode, cycle }, { method:'POST' }))\n    .then((res)=>{\n      const env = (res && res.data) ? res.data : res;\n      const payload = (env && env.payload) ? env.payload : null;\n      s.set('data.data', payload);\n    })\n    .catch((e)=>{ d2.log('pilotDashboard fetch failed', e); s.set('data.data', { __error: String((e && e.message) || e) }); })\n    .then(()=>{ s.set('data.loading', false); });\n}\n\nfunction renderGn(d2, data){\n  const tz = data.totalizador || {};\n  const leaders = Array.isArray(data.leaders) ? data.leaders : [];\n  const kpis = Array.isArray(data.kpiPanel) ? data.kpiPanel : [];\n  const tot = d2.render(d2.param('totalizador'), {\n    label: 'Total do Setor ' + (data.structureCode||''),\n    total: tz.remuneracao || 0,\n    leaderCount: tz.leaderCount || leaders.length,\n    caption: 'ciclo ' + (data.cycle||'')\n  }, { key:'tot', style:'height:100%' });\n\n  const leaderRows = leaders.map((l)=>\n    d2.render(d2.param('leaderRow'), {\n      name: 'Grupo ' + l.structureCode, nivel: l.nivel,\n      remuneracao: l.remuneracao || 0, code: String(l.structureCode)\n    }, { key: String(l.structureCode), style:'height:72px', onClick:(code)=>{ d2.log('leader click', code); } })\n  ).join('');\n\n  const kpiCards = kpis.map((k,i)=>\n    d2.render(d2.param('kpiCard'), {\n      label: k.kpi, value: k.value,\n      sub: k.grain === 'sector' ? 'setor' : (k.aggregation==='sum'?'soma dos grupos':''),\n      accent: ACCENTS[i % ACCENTS.length],\n      kind: (k.code === 'REMUN') ? 'currency' : 'number'\n    }, { key: String(k.code), style:'height:100%' })\n  ).join('');\n\n  return `\n    <div class=\"hero\">\n      <div style=\"min-height:150px\">${tot}</div>\n      <div class=\"heroSide\">\n        <div class=\"sec\">Líderes do setor</div>\n        <div class=\"leaders\">${leaderRows}</div>\n      </div>\n    </div>\n    <div class=\"sec\">Indicadores do setor</div>\n    <div class=\"kpis\">${kpiCards}</div>`;\n}\n\nfunction renderLider(d2, data){\n  const rem = data.remuneracao || 0;\n  const bd = data.breakdown || {};\n  const at = bd.atingimentos || {};\n  const comp = bd.components || {};\n  const single = d2.render(d2.param('totalizador'), {\n    label: 'Grupo ' + (data.structureCode||'') + ' · ' + (data.nivel||''),\n    total: rem, leaderCount: 1, caption: 'ciclo ' + (data.cycle||'')\n  }, { key:'single', style:'height:100%' });\n  const cards = [\n    { label:'Atingimento Natura', value: Math.round(at.natura||0), kind:'number', sub:'% da meta', accent:T.blue },\n    { label:'Atingimento Avon', value: Math.round(at.avon||0), kind:'number', sub:'% da meta', accent:T.orange },\n    { label:'Componente Natura', value: comp.natura||0, kind:'currency', sub:'', accent:T.green },\n    { label:'Componente Avon', value: comp.avon||0, kind:'currency', sub:'', accent:T.green }\n  ].map((c,i)=> d2.render(d2.param('kpiCard'), c, { key:'l'+i, style:'height:100%' })).join('');\n  return `<div class=\"hero\"><div style=\"min-height:150px\">${single}</div><div></div></div>\n    <div class=\"sec\">Composição da remuneração</div>\n    <div class=\"kpis\">${cards}</div>`;\n}\n\nfunction renderGv(d2, data){\n  const sectors = Array.isArray(data.sectors) ? data.sectors : [];\n  const tot = d2.render(d2.param('totalizador'), {\n    label:'Total da Organização', total: data.orgTotal||0,\n    leaderCount: data.sectorCount||sectors.length, caption:'ciclo '+(data.cycle||'')\n  }, { key:'org', style:'height:100%' });\n  const rows = sectors.map((sct)=>\n    d2.render(d2.param('leaderRow'), {\n      name:'Setor '+sct.sector, nivel:'', remuneracao:sct.remuneracao||0, code:String(sct.sector)\n    }, { key:String(sct.sector), style:'height:72px' })).join('');\n  return `<div class=\"hero\"><div style=\"min-height:150px\">${tot}</div>\n    <div class=\"heroSide\"><div class=\"sec\">Setores</div><div class=\"leaders\">${rows}</div></div></div>`;\n}\n\nexport default {\n  css: `\n    .dash{box-sizing:border-box;width:100%;height:100%;overflow:auto;background:${T.ground};\n      font-family:${T.font};display:flex;flex-direction:column;gap:20px;padding:24px 28px}\n    .dash .ctlrow{width:100%}\n    .dash .hero{display:grid;grid-template-columns:minmax(280px,360px) 1fr;gap:20px;align-items:stretch}\n    .dash.narrow .hero{grid-template-columns:1fr}\n    .dash.narrow{padding:16px 14px}\n    .dash.narrow .kpis{grid-template-columns:1fr 1fr}\n    .dash .heroSide{display:flex;flex-direction:column;gap:12px}\n    .dash .sec{font-size:13px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:${T.muted};margin:2px 2px 0}\n    .dash .leaders{display:flex;flex-direction:column;gap:10px}\n    .dash .kpis{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));grid-auto-rows:132px;gap:14px}\n    .dash .empty{padding:40px;text-align:center;color:${T.muted};background:#fff;border:1px solid ${T.line};\n      border-radius:14px;font-weight:600}\n    .dash .loading{padding:40px;text-align:center;color:${T.blue};font-weight:700}\n    .dash .toterr{padding:20px;background:#FEF3F2;border:1px solid #FDA29B;border-radius:12px;color:#B42318;font-weight:600}\n  `,\n  mounted(d2){\n    doFetch(d2);\n  },\n  updated(d2, root){\n    const el = root.querySelector('.dash');\n    if (!el) return;\n    const w = el.clientWidth || (root.getBoundingClientRect && root.getBoundingClientRect().width) || 9999;\n    const narrow = w > 0 && w < 760;\n    if (narrow && !el.classList.contains('narrow')) el.classList.add('narrow');\n    else if (!narrow && el.classList.contains('narrow')) el.classList.remove('narrow');\n  },\n  render(d2){\n    const s = d2.store(d2.params.store);\n    const perfil = s.get('data.perfil','gn');\n    const loading = s.get('data.loading', false);\n    const data = s.get('data.data', null);\n\n    const controls = d2.render(d2.param('controls'), { store: d2.params.store },\n      { key:'controls', onChange: ()=>{ doFetch(d2); } });\n\n    let body;\n    if (loading && !data) body = `<div class=\"loading\">Carregando painel…</div>`;\n    else if (!data) body = `<div class=\"empty\">Sem dados. Ajuste os filtros acima.</div>`;\n    else if (data.__error) body = `<div class=\"toterr\">Erro ao carregar: ${data.__error}</div>`;\n    else if (perfil === 'gn') body = renderGn(d2, data);\n    else if (perfil === 'lider') body = renderLider(d2, data);\n    else if (perfil === 'gv') body = renderGv(d2, data);\n    else body = `<div class=\"empty\">Perfil desconhecido.</div>`;\n\n    return `<div class=\"dash\">\n      <div class=\"ctlrow\">${controls}</div>\n      ${body}\n    </div>`;\n  }\n};"}},"store":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"store"}}}},"api":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"api"}}}},"controls":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"controls"}}}},"totalizador":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"totalizador"}}}},"leaderRow":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"leaderRow"}}}},"kpiCard":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"kpiCard"}}}}}}}}}},{"_id":"6a47f625e3014dd5bb6e76d8","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotLeaderRowV2","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"code"}}}},"name":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"name"}}}},"nivel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"nivel"}}}},"remuneracao":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"remuneracao"}}}},"onClick":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onClick"}}}}}}}}}},{"_id":"6a47f63dea22d868558c6a24","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotLeaderRowV3","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"code"}}}},"name":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"name"}}}},"nivel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"nivel"}}}},"remuneracao":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"remuneracao"}}}}}}}}}},{"_id":"6a47f65c1ecc4fa972d7e077","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotGroupRow","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"code"}}}},"name":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"name"}}}},"nivel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"nivel"}}}},"remuneracao":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"remuneracao"}}}}}}}}}},{"_id":"6a47f66a1d5442d873f765b3","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotRowMin","package":"natura-x-piloto","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 T = {\n  ink: '#101828', muted: '#757575', line: 'rgba(16,24,40,0.08)',\n  surface: '#FFFFFF', blue: '#0078DC', font: \"'Inter', -apple-system, system-ui, sans-serif\"\n};\nconst BADGE = {\n  diamante: { bg: 'rgba(0,120,220,0.12)', fg: '#0078DC' },\n  ouro:     { bg: 'rgba(250,160,0,0.16)', fg: '#B26A00' },\n  prata:    { bg: 'rgba(117,117,117,0.14)', fg: '#5B5B5B' }\n};\nconst brl = (n)=> 'R$ ' + (Number(n)||0).toLocaleString('pt-BR', {maximumFractionDigits:0});\nexport default {\n  css: `\n    .row{box-sizing:border-box;height:100%;width:100%;display:flex;align-items:center;gap:14px;\n      padding:14px 18px;background:${T.surface};border:1px solid ${T.line};border-radius:12px;\n      font-family:${T.font};cursor:pointer;transition:box-shadow .15s ease,transform .15s ease}\n    .row:hover{box-shadow:0 4px 14px rgba(16,24,40,0.10);transform:translateY(-1px)}\n    .row .dot{width:44px;height:44px;border-radius:10px;flex:0 0 auto;display:flex;align-items:center;\n      justify-content:center;font-weight:800;font-size:13px;letter-spacing:.02em}\n    .row .mid{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:3px}\n    .row .nm{font-size:15px;font-weight:700;color:${T.ink};white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n    .row .badge{align-self:flex-start;font-size:11px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;\n      padding:2px 8px;border-radius:999px}\n    .row .rem{flex:0 0 auto;text-align:right}\n    .row .rem .v{font-size:18px;font-weight:800;color:${T.ink};font-variant-numeric:tabular-nums}\n    .row .rem .k{font-size:11px;font-weight:600;color:${T.muted};text-transform:uppercase;letter-spacing:.04em}\n  `,\n  render(d2){\n    const name = String(d2.param('name','') || '—');\n    const nivel = String(d2.param('nivel','') || '').toLowerCase();\n    const badge = BADGE[nivel] || { bg: 'rgba(117,117,117,0.14)', fg: T.muted };\n    const rem = brl(d2.param('remuneracao',0));\n    const numMatch = name.match(/\\d{3,}/);\n    const initials = numMatch ? numMatch[0].slice(-3) : 'GR';\n    return `<div class=\"row\" data-key=\"${d2.param('code','')||name}\">\n      <div class=\"dot\" style=\"background:${badge.bg};color:${badge.fg}\">${initials}</div>\n      <div class=\"mid\">\n        <div class=\"nm\">${name}</div>\n        <div class=\"badge\" style=\"background:${badge.bg};color:${badge.fg}\">${nivel||'—'}</div>\n      </div>\n      <div class=\"rem\"><div class=\"v\">${rem}</div><div class=\"k\">Remuneração</div></div>\n    </div>`;\n  },\n  mounted(d2){\n    d2.on('.row','click',()=> d2.emit('onClick', d2.param('code','')));\n  }\n};"}},"name":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"name"}}}},"remuneracao":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"remuneracao"}}}}}}}}}},{"_id":"6a47fb98daa5100667881244","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotPersistProbe","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default { css: `.p{color:red}`, render(d2){ return `<div class=\"p\">PERSIST_PROBE_MARKER_12345</div>` } }"}}}}}}}},{"_id":"6a47fbafe3014dd5bb6e8f4f","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotPersistProbe2","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `.row{display:flex;justify-content:space-between;padding:12px;border-radius:8px;background:${'#fff'}}\n        .name{font-weight:600}\n        .badge{padding:2px 8px;border-radius:999px;background:#eee}\n        .val{font-variant-numeric:tabular-nums}`,\n  render(d2) {\n    const p = d2.params || {}\n    const name = p.name || '—'\n    const nivel = p.nivel || '—'\n    const remun = p.remuneracao || 0\n    const brl = new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL', maximumFractionDigits: 0 }).format(remun)\n    return `<div class=\"row\" data-key=\"${p.code || name}\">\n      <span class=\"name\">${name}</span>\n      <span class=\"badge\">${nivel}</span>\n      <span class=\"val\">${brl}</span>\n    </div>`\n  },\n  mounted(d2, root) { /* MARKER_PROBE2_67890 */ }\n}"}}}}}}}},{"_id":"6a47fbd0ea22d868558c8336","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotPersistProbe3","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  render(d2) {\n    const p = d2.params || {}\n    return `<div data-key=\"${p.name}\" onclick=\"__press\">${p.name} · ${p.nivel} · ${p.remuneracao} MARKER_PROBE3_ABCDE</div>`\n  },\n  mounted(d2, root) {\n    root.querySelector('[data-key]')?.addEventListener('click', () => d2.emit('onPress', { name: d2.params.name }))\n  }\n}"}},"name":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"name"}}}},"nivel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"nivel"}}}},"remuneracao":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"remuneracao"}}}},"onPress":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onPress"}}}}}}}}}},{"_id":"6a47fc4adaa51006678815a6","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotPersistProbeBig","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `.big{padding:8px}`,\n  render(d2) {\n    const line0 = d2.params.v0 || \"row 0 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line1 = d2.params.v1 || \"row 1 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line2 = d2.params.v2 || \"row 2 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line3 = d2.params.v3 || \"row 3 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line4 = d2.params.v4 || \"row 4 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line5 = d2.params.v5 || \"row 5 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line6 = d2.params.v6 || \"row 6 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line7 = d2.params.v7 || \"row 7 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line8 = d2.params.v8 || \"row 8 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line9 = d2.params.v9 || \"row 9 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line10 = d2.params.v10 || \"row 10 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line11 = d2.params.v11 || \"row 11 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line12 = d2.params.v12 || \"row 12 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line13 = d2.params.v13 || \"row 13 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line14 = d2.params.v14 || \"row 14 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line15 = d2.params.v15 || \"row 15 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line16 = d2.params.v16 || \"row 16 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line17 = d2.params.v17 || \"row 17 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line18 = d2.params.v18 || \"row 18 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line19 = d2.params.v19 || \"row 19 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line20 = d2.params.v20 || \"row 20 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line21 = d2.params.v21 || \"row 21 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line22 = d2.params.v22 || \"row 22 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line23 = d2.params.v23 || \"row 23 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line24 = d2.params.v24 || \"row 24 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line25 = d2.params.v25 || \"row 25 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line26 = d2.params.v26 || \"row 26 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line27 = d2.params.v27 || \"row 27 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line28 = d2.params.v28 || \"row 28 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line29 = d2.params.v29 || \"row 29 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line30 = d2.params.v30 || \"row 30 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line31 = d2.params.v31 || \"row 31 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line32 = d2.params.v32 || \"row 32 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line33 = d2.params.v33 || \"row 33 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line34 = d2.params.v34 || \"row 34 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line35 = d2.params.v35 || \"row 35 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line36 = d2.params.v36 || \"row 36 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line37 = d2.params.v37 || \"row 37 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line38 = d2.params.v38 || \"row 38 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line39 = d2.params.v39 || \"row 39 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line40 = d2.params.v40 || \"row 40 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line41 = d2.params.v41 || \"row 41 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line42 = d2.params.v42 || \"row 42 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line43 = d2.params.v43 || \"row 43 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line44 = d2.params.v44 || \"row 44 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line45 = d2.params.v45 || \"row 45 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line46 = d2.params.v46 || \"row 46 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line47 = d2.params.v47 || \"row 47 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line48 = d2.params.v48 || \"row 48 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line49 = d2.params.v49 || \"row 49 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line50 = d2.params.v50 || \"row 50 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line51 = d2.params.v51 || \"row 51 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line52 = d2.params.v52 || \"row 52 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line53 = d2.params.v53 || \"row 53 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line54 = d2.params.v54 || \"row 54 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line55 = d2.params.v55 || \"row 55 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line56 = d2.params.v56 || \"row 56 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line57 = d2.params.v57 || \"row 57 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line58 = d2.params.v58 || \"row 58 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line59 = d2.params.v59 || \"row 59 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line60 = d2.params.v60 || \"row 60 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line61 = d2.params.v61 || \"row 61 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line62 = d2.params.v62 || \"row 62 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line63 = d2.params.v63 || \"row 63 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line64 = d2.params.v64 || \"row 64 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line65 = d2.params.v65 || \"row 65 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line66 = d2.params.v66 || \"row 66 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line67 = d2.params.v67 || \"row 67 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line68 = d2.params.v68 || \"row 68 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line69 = d2.params.v69 || \"row 69 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line70 = d2.params.v70 || \"row 70 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line71 = d2.params.v71 || \"row 71 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line72 = d2.params.v72 || \"row 72 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line73 = d2.params.v73 || \"row 73 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line74 = d2.params.v74 || \"row 74 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line75 = d2.params.v75 || \"row 75 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line76 = d2.params.v76 || \"row 76 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line77 = d2.params.v77 || \"row 77 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line78 = d2.params.v78 || \"row 78 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line79 = d2.params.v79 || \"row 79 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line80 = d2.params.v80 || \"row 80 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line81 = d2.params.v81 || \"row 81 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line82 = d2.params.v82 || \"row 82 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line83 = d2.params.v83 || \"row 83 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line84 = d2.params.v84 || \"row 84 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line85 = d2.params.v85 || \"row 85 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line86 = d2.params.v86 || \"row 86 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line87 = d2.params.v87 || \"row 87 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line88 = d2.params.v88 || \"row 88 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line89 = d2.params.v89 || \"row 89 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line90 = d2.params.v90 || \"row 90 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line91 = d2.params.v91 || \"row 91 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line92 = d2.params.v92 || \"row 92 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line93 = d2.params.v93 || \"row 93 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line94 = d2.params.v94 || \"row 94 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line95 = d2.params.v95 || \"row 95 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line96 = d2.params.v96 || \"row 96 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line97 = d2.params.v97 || \"row 97 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line98 = d2.params.v98 || \"row 98 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line99 = d2.params.v99 || \"row 99 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line100 = d2.params.v100 || \"row 100 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line101 = d2.params.v101 || \"row 101 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line102 = d2.params.v102 || \"row 102 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line103 = d2.params.v103 || \"row 103 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line104 = d2.params.v104 || \"row 104 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line105 = d2.params.v105 || \"row 105 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line106 = d2.params.v106 || \"row 106 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line107 = d2.params.v107 || \"row 107 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line108 = d2.params.v108 || \"row 108 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line109 = d2.params.v109 || \"row 109 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line110 = d2.params.v110 || \"row 110 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line111 = d2.params.v111 || \"row 111 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line112 = d2.params.v112 || \"row 112 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line113 = d2.params.v113 || \"row 113 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line114 = d2.params.v114 || \"row 114 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line115 = d2.params.v115 || \"row 115 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line116 = d2.params.v116 || \"row 116 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line117 = d2.params.v117 || \"row 117 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line118 = d2.params.v118 || \"row 118 padding xxxxxxxxxxxxxxxxxxxx\"\n    const line119 = d2.params.v119 || \"row 119 padding xxxxxxxxxxxxxxxxxxxx\"\n    return `<div class=\"big\">BIG_START_MARKER ${d2.params.name||\"\"} ... BIG_END_MARKER_ZZZ9</div>`\n  }\n}"}}}}}}}},{"_id":"6a4806abea22d868558cb41a","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMBrandChip","package":"natura-x-piloto","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 MTOK = {\n  primary: '#0078DC', onPrimary: '#FFFFFF', primaryContainer: '#D6E9FF', onPrimaryContainer: '#001C3B',\n  avon: '#B0006E', avonContainer: '#FFD9E7', onAvonContainer: '#3B0021',\n  ink: '#1A1C1E', muted: '#43474E'\n};\nfunction brandCfg(brand) {\n  const b = String(brand || '').toLowerCase();\n  if (b === 'avon') return { label: 'Avon', bg: MTOK.avonContainer, fg: MTOK.onAvonContainer, dot: MTOK.avon };\n  return { label: 'Natura', bg: MTOK.primaryContainer, fg: MTOK.onPrimaryContainer, dot: MTOK.primary };\n}\nexport default {\n  css: `\n  .chip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 12px;border-radius:8px;\n    font:500 12px/1 Roboto,system-ui,sans-serif;letter-spacing:.2px;white-space:nowrap;\n    transition:transform .15s cubic-bezier(0.2,0,0,1),box-shadow .15s cubic-bezier(0.2,0,0,1)}\n  .chip:hover{transform:translateY(-1px);box-shadow:0 1px 3px rgba(0,0,0,.12)}\n  .chip.sm{height:22px;padding:0 9px;font-size:11px}\n  .dot{width:8px;height:8px;border-radius:50%}\n  @media (prefers-reduced-motion: reduce){.chip{transition:none}.chip:hover{transform:none}}\n  `,\n  render(d2) {\n    const c = brandCfg(d2.param('brand', 'natura'));\n    const sm = d2.param('size', '') === 'sm' ? ' sm' : '';\n    return `<span class=\"chip${sm}\" style=\"background:${c.bg};color:${c.fg}\"><span class=\"dot\" style=\"background:${c.dot}\"></span>${c.label}</span>`;\n  }\n};"}},"brand":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"brand"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}}}}}}}},{"_id":"6a4806bcbf38d3828155eb7a","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMTypeBadge","package":"natura-x-piloto","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 TIERS = {\n  diamante: { label: 'Diamante', bg: '#FCE1EA', fg: '#B0003B', glyph: '◆' },\n  ouro:     { label: 'Ouro',     bg: '#FDF3D6', fg: '#8A6A00', glyph: '★' },\n  prata:    { label: 'Prata',    bg: '#ECEFF3', fg: '#4A5560', glyph: '●' },\n  bronze:   { label: 'Bronze',   bg: '#F3E4D6', fg: '#7A4A1F', glyph: '●' }\n};\nfunction tierCfg(nivel) {\n  const n = String(nivel || '').toLowerCase();\n  return TIERS[n] || { label: (nivel ? String(nivel) : 'Nível'), bg: '#ECEFF3', fg: '#4A5560', glyph: '●' };\n}\nfunction redeLabel(rede) {\n  const r = String(rede || '').toLowerCase();\n  if (r === 'rede1') return 'Rede 1';\n  if (r === 'rede2') return 'Rede 2';\n  return rede ? String(rede) : '';\n}\nexport default {\n  css: `\n  .wrap{display:inline-flex;align-items:center;gap:6px}\n  .badge{display:inline-flex;align-items:center;gap:5px;height:26px;padding:0 11px;border-radius:8px;\n    font:600 12px/1 Roboto,system-ui,sans-serif;white-space:nowrap;\n    transition:transform .15s cubic-bezier(0.2,0,0,1)}\n  .badge:hover{transform:translateY(-1px)}\n  .badge.sm{height:22px;padding:0 8px;font-size:11px}\n  .g{font-size:11px;line-height:1}\n  .rede{display:inline-flex;align-items:center;height:26px;padding:0 10px;border-radius:8px;\n    background:#F3F4F6;color:#6B7280;font:500 12px/1 Roboto,system-ui,sans-serif;white-space:nowrap}\n  .rede.sm{height:22px;padding:0 8px;font-size:11px}\n  @media (prefers-reduced-motion: reduce){.badge{transition:none}.badge:hover{transform:none}}\n  `,\n  render(d2) {\n    const t = tierCfg(d2.param('nivel'));\n    const sm = d2.param('size', '') === 'sm' ? ' sm' : '';\n    const rede = redeLabel(d2.param('rede'));\n    const redeHtml = rede ? `<span class=\"rede${sm}\">${rede}</span>` : '';\n    return `<span class=\"wrap\"><span class=\"badge${sm}\" style=\"background:${t.bg};color:${t.fg}\"><span class=\"g\">${t.glyph}</span>${t.label}</span>${redeHtml}</span>`;\n  }\n};"}},"nivel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"nivel"}}}},"rede":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rede"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}}}}}}}},{"_id":"6a4806d123ea82ec61fbda92","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMTopBar","package":"natura-x-piloto","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 FALLBACK = { color:{ surface:'#FFFFFF', ink:'#1A1C1E', muted:'#6B7280', hairline:'rgba(16,24,40,0.08)', naturaMagenta:'#E5004B', naturaOrange:'#EB6619', brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)' }, media:{ lockup:'https://natura-x-piloto.data2.media/file/H0P_N-7AQzQOg_VJMBWzV' } };\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction initials(name){\n  const parts = String(name||'').trim().split(/\\s+/).filter(Boolean);\n  if(!parts.length) return '·';\n  if(parts.length===1) return parts[0].slice(0,2).toUpperCase();\n  return (parts[0][0]+parts[parts.length-1][0]).toUpperCase();\n}\nexport default {\n  css: `\n  :host{display:block}\n  .bar{display:flex;align-items:center;gap:14px;height:64px;padding:0 20px;box-sizing:border-box;\n    background:#FFFFFF;color:#1A1C1E;border-bottom:1px solid rgba(16,24,40,0.08);\n    font-family:Roboto,system-ui,sans-serif}\n  .lock{height:30px;display:flex;align-items:center}\n  .lock img{height:100%;width:auto;display:block}\n  .ttl{font-size:16px;font-weight:600;letter-spacing:.15px;color:#1A1C1E;padding-left:14px;margin-left:2px;border-left:1px solid rgba(16,24,40,0.10)}\n  .iconbtn{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;\n    cursor:pointer;border:none;background:transparent;color:#6B7280;font-size:22px;\n    transition:background .15s ease-out,transform .15s ease-out;position:relative;overflow:hidden}\n  .iconbtn:hover{background:rgba(229,0,75,.08);color:#E5004B}\n  .iconbtn:active{transform:scale(.94)}\n  .spacer{flex:1 1 auto}\n  .avatar{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;\n    background:linear-gradient(135deg,#E5004B 0%,#EB6619 100%);color:#fff;font-weight:700;font-size:14px;cursor:default}\n  .ripple{position:absolute;border-radius:50%;background:rgba(229,0,75,.25);transform:scale(0);\n    animation:rip .5s ease-out;pointer-events:none}\n  @keyframes rip{to{transform:scale(2.4);opacity:0}}\n  @media (max-width:640px){\n    .bar{height:56px;padding:0 10px;gap:8px}\n    .lock{height:22px;flex:none}\n    .ttl{flex:1 1 auto;min-width:0;font-size:13px;padding-left:10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n    .spacer,.more{display:none}\n    .iconbtn{width:36px;height:36px;font-size:20px;flex:none}\n    .avatar{width:34px;height:34px;font-size:12px;flex:none}\n  }\n  @media (prefers-reduced-motion: reduce){.iconbtn,.iconbtn:active{transition:none;transform:none}.ripple{display:none}}\n  `,\n  render(d2){\n    const t = tok(d2);\n    const title = d2.param('title','Painel de Ganhos');\n    const user = d2.param('userName','');\n    return `<div class=\"bar\">\n      <span class=\"lock\"><img src=\"${t.media.lockup}\" alt=\"Natura & Avon consultoria de beleza\"/></span>\n      <span class=\"ttl\">${title}</span>\n      <span class=\"spacer\"></span>\n      <button class=\"iconbtn more\" aria-label=\"more\">⋮</button>\n      <span class=\"avatar\" title=\"${user}\">${initials(user)}</span>\n    </div>`;\n  },\n  mounted(d2){\n    d2.on('.iconbtn','click',(e,el)=>{\n      const r=document.createElement('span');r.className='ripple';\n      const b=el.getBoundingClientRect();const s=Math.max(b.width,b.height);\n      r.style.width=r.style.height=s+'px';\n      r.style.left=(e.clientX-b.left-s/2)+'px';r.style.top=(e.clientY-b.top-s/2)+'px';\n      el.appendChild(r);setTimeout(()=>r.remove(),500);\n    });\n  }\n};"}},"title":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"title"}}}},"userName":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"userName"}}}},"onMenu":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onMenu"}}}}}}}}}},{"_id":"6a4806ebbf38d3828155ec43","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMUserHeader","package":"natura-x-piloto","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 FALLBACK = { color:{ surface:'#FFFFFF', ground:'#FAFAFB', ink:'#1A1C1E', muted:'#6B7280', hairline:'rgba(16,24,40,0.08)', naturaMagenta:'#E5004B', naturaOrange:'#EB6619', brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)', gold:'#F7BE00', money:'#29AC56' } };\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction initials(name){\n  const parts=String(name||'').trim().split(/\\s+/).filter(Boolean);\n  if(!parts.length) return '·';\n  if(parts.length===1) return parts[0].slice(0,2).toUpperCase();\n  return (parts[0][0]+parts[parts.length-1][0]).toUpperCase();\n}\nfunction perfilLabel(p){\n  const m={gn:'Gerente de Negócios',lider:'Líder de Grupo',gv:'Gerente de Vendas'};\n  return m[String(p||'').toLowerCase()]||String(p||'');\n}\nfunction brl(d2, v){ try{ return Number(v||0).toLocaleString('pt-BR',{style:'currency',currency:'BRL'}); }catch(e){ return 'R$ '+Number(v||0).toLocaleString('pt-BR',{minimumFractionDigits:2,maximumFractionDigits:2}); } }\nexport default {\n  css:`\n  :host{display:block}\n  .hdr{display:flex;gap:20px;align-items:stretch;background:#FFFFFF;border:1px solid rgba(16,24,40,0.08);\n    border-radius:16px;padding:20px;box-sizing:border-box;box-shadow:0 1px 3px rgba(16,24,40,.08);\n    font-family:Roboto,system-ui,sans-serif;\n    opacity:0;transform:translateY(12px);animation:enter .4s cubic-bezier(0.4,0,0.2,1) forwards}\n  @keyframes enter{to{opacity:1;transform:none}}\n  .left{display:flex;gap:16px;align-items:center;flex:1 1 auto;min-width:0}\n  .av{flex:0 0 auto;width:64px;height:64px;border-radius:50%;\n    background:linear-gradient(135deg,#E5004B 0%,#EB6619 100%);color:#fff;\n    display:flex;align-items:center;justify-content:center;font-weight:700;font-size:24px}\n  .who{min-width:0}\n  .nm{font-size:22px;font-weight:600;color:#1A1C1E;line-height:1.2}\n  .role{font-size:13px;color:#6B7280;margin-top:2px}\n  .chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px;align-items:center}\n  .meta{font-size:12px;color:#6B7280}\n  .hero{flex:0 0 auto;min-width:230px;border-radius:14px;padding:16px 20px;display:flex;flex-direction:column;justify-content:center;\n    background:linear-gradient(135deg,#FFF7DE 0%,#FFEFC2 100%);border:1px solid rgba(247,190,0,.35)}\n  .hlabel{font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase;color:#8A6A00}\n  .hval{font-size:34px;font-weight:700;line-height:1.1;margin-top:4px;letter-spacing:-.5px;color:#29AC56}\n  .hcycle{font-size:12px;margin-top:6px;color:#8A6A00}\n  @media (max-width:640px){.hdr{flex-direction:column}.hero{min-width:0}}\n  @media (prefers-reduced-motion: reduce){.hdr{animation:none;opacity:1;transform:none}}\n  `,\n  render(d2){\n    const t = tok(d2);\n    const name=d2.param('name','');\n    const perfil=d2.param('perfil','');\n    const nivel=d2.param('nivel','');\n    const rede=d2.param('rede','');\n    const sectorCode=d2.param('sectorCode','');\n    const cycle=d2.param('cycle','');\n    const grupo=d2.param('grupo','');\n    const gvName=d2.param('gvName','');\n    const redeNum = String(rede||'').replace('rede','');\n    const isLider = String(perfil||'').toLowerCase()==='lider';\n    const isGv = String(perfil||'').toLowerCase()==='gv';\n    const sectorCount=d2.param('sectorCount', null);\n    const roleParts = [perfilLabel(perfil)];\n    if(isGv){\n      if(sectorCount!=null) roleParts.push(sectorCount+' setores');\n    } else if(String(perfil||'').toLowerCase()==='gn'){\n      if(sectorCode) roleParts.push('Setor '+sectorCode);\n      if(redeNum) roleParts.push('Rede '+redeNum);\n    } else if(isLider){\n      if(redeNum) roleParts.push('Rede '+redeNum);\n      if(nivel) roleParts.push('Líder '+String(nivel).charAt(0).toUpperCase()+String(nivel).slice(1));\n    }\n    const roleLine = roleParts.filter(Boolean).join(' · ');\n    const remun=d2.param('remuneracao',0);\n    const leaderCount=d2.param('leaderCount', null);\n    const badgeRef=d2.param('typeBadge','');\n    const badgeSlot = (badgeRef && nivel) ? d2.render(badgeRef,{nivel:nivel,rede:rede,size:''},{key:'ub',style:'display:inline-flex'}) : '';\n    const lc = (!isLider && leaderCount!=null) ? `<span class=\"meta\">· ${leaderCount} grupos</span>` : '';\n    const grupoMeta = (isLider && grupo) ? `<span class=\"meta\">Grupo ${grupo}</span>` : '';\n    const gvMeta = (isLider && gvName) ? `<span class=\"meta\">· GV ${gvName}</span>` : '';\n    const chips = (badgeSlot || lc || grupoMeta || gvMeta) ? `<div class=\"chips\">${badgeSlot}${lc}${grupoMeta}${gvMeta}</div>` : '';\n    return `<div class=\"hdr\">\n      <div class=\"left\">\n        <div class=\"av\">${initials(name)}</div>\n        <div class=\"who\">\n          <div class=\"nm\">${name||'—'}</div>\n          <div class=\"role\">${roleLine}</div>\n          ${chips}\n        </div>\n      </div>\n      <div class=\"hero\">\n        <div class=\"hlabel\">${isGv ? 'Total da Rede' : 'Remuneração do ciclo'}</div>\n        <div class=\"hval\">${brl(d2, remun)}</div>\n        <div class=\"hcycle\">Ciclo ${cycle||'—'}</div>\n      </div>\n    </div>`;\n  }\n};"}},"name":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"name"}}}},"perfil":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"perfil"}}}},"nivel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"nivel"}}}},"rede":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rede"}}}},"sectorCode":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"sectorCode"}}}},"cycle":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cycle"}}}},"remuneracao":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"remuneracao"}}}},"leaderCount":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"leaderCount"}}}},"typeBadge":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"typeBadge"}}}}}}}}}},{"_id":"6a480707b0a857d0aa63bd1c","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMStatCard","package":"natura-x-piloto","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 MTOK = {\n  primary:'#0078DC', surface:'#FFFFFF', ink:'#1A1C1E', muted:'#43474E',\n  container:'#EEF1F8', positive:'#2E7D32', warning:'#ED6C02', danger:'#C62828'\n};\nfunction brl(v){\n  const n=Number(v||0);\n  return 'R$ '+n.toLocaleString('pt-BR',{minimumFractionDigits:0,maximumFractionDigits:0});\n}\nfunction attColor(pct){\n  const p=Number(pct||0);\n  if(p>=100) return MTOK.positive;\n  if(p>=60) return MTOK.warning;\n  return MTOK.danger;\n}\nexport default {\n  css:`\n  :host{display:block}\n  .card{background:${MTOK.surface};border-radius:16px;padding:16px;box-sizing:border-box;font-family:Roboto,system-ui,sans-serif;\n    box-shadow:0 1px 3px rgba(0,0,0,.12);transition:box-shadow .15s cubic-bezier(0.2,0,0,1),transform .15s cubic-bezier(0.2,0,0,1)}\n  .card:hover{box-shadow:0 3px 8px rgba(0,0,0,.14);transform:translateY(-2px)}\n  .top{display:flex;justify-content:space-between;align-items:flex-start;gap:12px}\n  .ttl{font-size:16px;font-weight:600;color:${MTOK.ink};line-height:1.25}\n  .val{font-size:28px;font-weight:700;color:${MTOK.ink};letter-spacing:-.5px;white-space:nowrap}\n  .chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}\n  .metrics{display:flex;gap:18px;margin-top:14px;flex-wrap:wrap}\n  .metric{display:flex;flex-direction:column}\n  .mlab{font-size:11px;font-weight:500;color:${MTOK.muted};text-transform:uppercase;letter-spacing:.3px}\n  .mval{font-size:16px;font-weight:600;color:${MTOK.ink};margin-top:2px}\n  .prog{margin-top:14px}\n  .pbar{height:8px;border-radius:999px;background:${MTOK.container};overflow:hidden}\n  .pfill{height:100%;border-radius:999px;transition:width .5s cubic-bezier(0.2,0,0,1)}\n  .plab{display:flex;justify-content:space-between;font-size:11px;color:${MTOK.muted};margin-top:6px}\n  @media (prefers-reduced-motion: reduce){.card,.card:hover{transition:none;transform:none}.pfill{transition:none}}\n  `,\n  render(d2){\n    const title=d2.param('title','');\n    const val=d2.param('value',0);\n    const nivel=d2.param('nivel','');\n    const rede=d2.param('rede','');\n    const brands=d2.param('brands',[])||[];\n    const metrics=d2.param('metrics',[])||[];\n    const att=Number(d2.param('attainment',0));\n    const brandChip=d2.param('brandChip','');\n    const typeBadge=d2.param('typeBadge','');\n    let chips='';\n    if(typeBadge && nivel) chips += d2.render(typeBadge,{nivel:nivel,rede:rede,size:'sm'},{key:'tb',style:'display:inline-flex'});\n    if(brandChip){ brands.forEach((b,i)=>{ chips += d2.render(brandChip,{brand:b,size:'sm'},{key:'br'+i,style:'display:inline-flex'}); }); }\n    const metricsHtml = metrics.map(m=>`<div class=\"metric\"><span class=\"mlab\">${m.label}</span><span class=\"mval\">${m.value}</span></div>`).join('');\n    const clamped=Math.max(0,Math.min(100,att));\n    const progHtml = att>0 ? `<div class=\"prog\"><div class=\"pbar\"><div class=\"pfill\" style=\"width:${clamped}%;background:${attColor(att)}\"></div></div><div class=\"plab\"><span>Atingimento</span><span>${Math.round(att)}%</span></div></div>` : '';\n    return `<div class=\"card\">\n      <div class=\"top\">\n        <div class=\"ttl\">${title}</div>\n        <div class=\"val\">${brl(val)}</div>\n      </div>\n      <div class=\"chips\">${chips}</div>\n      <div class=\"metrics\">${metricsHtml}</div>\n      ${progHtml}\n    </div>`;\n  }\n};"}},"title":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"title"}}}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"nivel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"nivel"}}}},"rede":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rede"}}}},"brands":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"brands"}}}},"metrics":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"metrics"}}}},"attainment":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"attainment"}}}},"brandChip":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"brandChip"}}}},"typeBadge":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"typeBadge"}}}}}}}}}},{"_id":"6a48072d23ea82ec61fbdc50","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMDetailAccordion","package":"natura-x-piloto","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 MTOK = {\n  primary:'#0078DC', surface:'#FFFFFF', ink:'#1A1C1E', muted:'#43474E',\n  container:'#EEF1F8', containerHigh:'#E7EAF2', outline:'#C3C7CF',\n  positive:'#2E7D32', warning:'#ED6C02', danger:'#C62828'\n};\nfunction brl(v){ const n=Number(v||0); return 'R$ '+n.toLocaleString('pt-BR',{minimumFractionDigits:0,maximumFractionDigits:0}); }\nfunction attColor(pct){ const p=Number(pct||0); if(p>=100) return MTOK.positive; if(p>=60) return MTOK.warning; return MTOK.danger; }\nexport default {\n  css:`\n  :host{display:block}\n  .acc{background:${MTOK.surface};border-radius:16px;box-sizing:border-box;font-family:Roboto,system-ui,sans-serif;\n    box-shadow:0 1px 3px rgba(0,0,0,.12);overflow:hidden;\n    transition:box-shadow .15s cubic-bezier(0.2,0,0,1)}\n  .acc[data-open]{box-shadow:0 3px 8px rgba(0,0,0,.14)}\n  .head{display:flex;align-items:center;gap:14px;padding:16px;cursor:pointer;position:relative;overflow:hidden;\n    transition:background .15s cubic-bezier(0.2,0,0,1)}\n  .head:hover{background:${MTOK.container}}\n  .hmain{flex:1 1 auto;min-width:0}\n  .ttl{font-size:16px;font-weight:600;color:${MTOK.ink};line-height:1.25}\n  .chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}\n  .hright{display:flex;align-items:center;gap:14px;flex:0 0 auto}\n  .val{font-size:22px;font-weight:700;color:${MTOK.ink};letter-spacing:-.3px;white-space:nowrap}\n  .caret{width:28px;height:28px;display:flex;align-items:center;justify-content:center;color:${MTOK.muted};font-size:18px;\n    transition:transform .28s cubic-bezier(0.2,0,0,1)}\n  .acc[data-open] .caret{transform:rotate(180deg)}\n  .body{max-height:0;opacity:0;overflow:hidden;\n    transition:max-height .28s cubic-bezier(0.2,0,0,1),opacity .28s cubic-bezier(0.2,0,0,1)}\n  .acc[data-open] .body{max-height:600px;opacity:1}\n  .bodyin{padding:0 16px 16px 16px;border-top:1px solid ${MTOK.outline}}\n  .att{margin:14px 0}\n  .pbar{height:8px;border-radius:999px;background:${MTOK.container};overflow:hidden}\n  .pfill{height:100%;border-radius:999px;transition:width .5s cubic-bezier(0.2,0,0,1)}\n  .plab{display:flex;justify-content:space-between;font-size:11px;color:${MTOK.muted};margin-top:6px}\n  .kgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(130px,1fr));gap:10px;margin-top:12px}\n  .kpi{background:${MTOK.container};border-radius:12px;padding:12px}\n  .klab{font-size:11px;font-weight:500;color:${MTOK.muted};text-transform:uppercase;letter-spacing:.3px;line-height:1.3}\n  .kval{font-size:20px;font-weight:700;color:${MTOK.ink};margin-top:4px}\n  .ripple{position:absolute;border-radius:50%;background:rgba(0,120,220,.16);transform:scale(0);\n    animation:rip .5s cubic-bezier(0.2,0,0,1);pointer-events:none}\n  @keyframes rip{to{transform:scale(2.4);opacity:0}}\n  @media (prefers-reduced-motion: reduce){\n    .head,.caret,.body,.pfill,.acc{transition:none}.ripple{display:none}\n    .acc[data-open] .body{max-height:none}\n  }\n  `,\n  render(d2){\n    const title=d2.param('title','');\n    const val=d2.param('value',0);\n    const nivel=d2.param('nivel','');\n    const rede=d2.param('rede','');\n    const brands=d2.param('brands',[])||[];\n    const att=Number(d2.param('attainment',0));\n    const kpis=d2.param('kpis',[])||[];\n    const brandChip=d2.param('brandChip','');\n    const typeBadge=d2.param('typeBadge','');\n    if(d2.state.open===undefined) d2.state.open = !!d2.param('startExpanded',false);\n    const open=d2.state.open;\n    let chips='';\n    if(typeBadge && nivel) chips += d2.render(typeBadge,{nivel:nivel,rede:rede,size:'sm'},{key:'tb',style:'display:inline-flex'});\n    if(brandChip){ brands.forEach((b,i)=>{ chips += d2.render(brandChip,{brand:b,size:'sm'},{key:'br'+i,style:'display:inline-flex'}); }); }\n    const clamped=Math.max(0,Math.min(100,att));\n    const attHtml = att>0 ? `<div class=\"att\"><div class=\"pbar\"><div class=\"pfill\" style=\"width:${open?clamped:0}%;background:${attColor(att)}\"></div></div><div class=\"plab\"><span>Atingimento do grupo</span><span>${Math.round(att)}%</span></div></div>` : '';\n    const kpiHtml = kpis.map(k=>`<div class=\"kpi\"><div class=\"klab\">${k.label}</div><div class=\"kval\">${k.value}</div></div>`).join('');\n    return `<div class=\"acc\" ${open?'data-open':''}>\n      <div class=\"head\">\n        <div class=\"hmain\">\n          <div class=\"ttl\">${title}</div>\n          <div class=\"chips\">${chips}</div>\n        </div>\n        <div class=\"hright\">\n          <div class=\"val\">${brl(val)}</div>\n          <div class=\"caret\">⌄</div>\n        </div>\n      </div>\n      <div class=\"body\"><div class=\"bodyin\">\n        ${attHtml}\n        <div class=\"kgrid\">${kpiHtml}</div>\n      </div></div>\n    </div>`;\n  },\n  mounted(d2){\n    d2.on('.head','click',(e,el)=>{\n      const r=document.createElement('span');r.className='ripple';\n      const b=el.getBoundingClientRect();const s=Math.max(b.width,b.height);\n      r.style.width=r.style.height=s+'px';\n      r.style.left=(e.clientX-b.left-s/2)+'px';r.style.top=(e.clientY-b.top-s/2)+'px';\n      el.appendChild(r);setTimeout(()=>r.remove(),500);\n      d2.state.open=!d2.state.open;\n      d2.emit('onToggle', d2.state.open);\n    });\n  }\n};"}},"title":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"title"}}}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"nivel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"nivel"}}}},"rede":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rede"}}}},"brands":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"brands"}}}},"metrics":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"metrics"}}}},"attainment":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"attainment"}}}},"kpis":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"kpis"}}}},"startExpanded":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"startExpanded"}}}},"brandChip":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"brandChip"}}}},"typeBadge":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"typeBadge"}}}}}}}}}},{"_id":"6a480769ea22d868558cb7c7","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMDashboard","package":"natura-x-piloto","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 MTOK = {\n  ground:'#FDFBFF', primary:'#0078DC', ink:'#1A1C1E', muted:'#43474E',\n  container:'#EEF1F8', containerHigh:'#E7EAF2', surface:'#FFFFFF', outline:'#C3C7CF',\n  primaryContainer:'#D6E9FF', onPrimaryContainer:'#001C3B'\n};\nfunction num(v){ return Number(v||0); }\nfunction avg2(a,b){ const x=num(a),y=num(b); return (x+y)/2; }\nfunction round(n){ return Math.round(num(n)); }\nfunction leaderToCard(l){\n  const bd = l.breakdown || {};\n  const kp = bd.kpis || {};\n  const at = bd.atingimentos || {};\n  const attainment = avg2(at.natura, at.avon);\n  const metrics = [\n    { label:'Ativas Nat', value: (kp.naturaExclusiva!=null?kp.naturaExclusiva:'—') },\n    { label:'Ativas Avon', value: (kp.avonExclusiva!=null?kp.avonExclusiva:'—') },\n    { label:'Saldo', value: (kp.saldo!=null?kp.saldo:'—') }\n  ];\n  const kpis = [\n    { label:'Ativas Natura Excl.', value: kp.naturaExclusiva!=null?kp.naturaExclusiva:'—' },\n    { label:'Ativas Avon Excl.', value: kp.avonExclusiva!=null?kp.avonExclusiva:'—' },\n    { label:'Saldo Cadastro', value: kp.saldo!=null?kp.saldo:'—' },\n    { label:'Ating. Natura', value: at.natura!=null?round(at.natura)+'%':'—' },\n    { label:'Ating. Avon', value: at.avon!=null?round(at.avon)+'%':'—' }\n  ];\n  return { code:l.structureCode, nivel:l.nivel, rede:l.rede, remuneracao:l.remuneracao, attainment, metrics, kpis };\n}\nasync function fetchData(d2){\n  const store = d2.store(d2.params.store);\n  const perfil = store.get('data.perfil', store.get('perfil','gn')) || store.get('perfil','gn');\n  const p = store.get('perfil','gn');\n  const structureCode = store.get('structureCode','3253');\n  const cycle = store.get('cycle','202516');\n  d2.state.loading = true; d2.state.error='';\n  try {\n    const res = await d2.rush(d2.params.api).invoke({ perfil:p, structureCode, cycle });\n    const payload = (res && res.payload) ? res.payload : res;\n    store.set('data', payload);\n  } catch(err){\n    d2.state.error = String(err && err.message ? err.message : err);\n  } finally {\n    d2.state.loading = false;\n  }\n}\nexport default {\n  css:`\n  :host{display:block}\n  .shell{background:${MTOK.ground};min-height:100%;font-family:Roboto,system-ui,sans-serif;display:flex;flex-direction:column}\n  .page{padding:24px;max-width:1200px;width:100%;margin:0 auto;box-sizing:border-box;display:flex;flex-direction:column;gap:20px}\n  .controls{display:flex;gap:10px;flex-wrap:wrap;align-items:center}\n  .seg{display:inline-flex;background:${MTOK.container};border-radius:999px;padding:4px}\n  .segbtn{border:none;background:transparent;color:${MTOK.muted};font:600 13px Roboto,sans-serif;padding:7px 16px;border-radius:999px;cursor:pointer;\n    transition:background .2s cubic-bezier(0.2,0,0,1),color .2s cubic-bezier(0.2,0,0,1)}\n  .segbtn[data-active]{background:${MTOK.primary};color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.2)}\n  .fld{display:inline-flex;align-items:center;gap:6px;background:${MTOK.surface};border:1px solid ${MTOK.outline};border-radius:10px;padding:6px 10px}\n  .fld label{font:500 11px Roboto;color:${MTOK.muted};text-transform:uppercase;letter-spacing:.3px}\n  .fld input{border:none;outline:none;font:600 13px Roboto;color:${MTOK.ink};width:74px;background:transparent}\n  .sectionlab{font-size:13px;font-weight:600;color:${MTOK.muted};text-transform:uppercase;letter-spacing:.4px;margin-top:4px}\n  .totrow{display:grid;grid-template-columns:1fr;gap:16px}\n  .grid{display:grid;grid-template-columns:1fr;gap:14px}\n  .accgrid{display:flex;flex-direction:column;gap:12px}\n  .kpistrip{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:12px}\n  .kcard{background:${MTOK.surface};border-radius:16px;padding:16px;box-shadow:0 1px 3px rgba(0,0,0,.12);\n    opacity:0;transform:translateY(12px);animation:enter .3s cubic-bezier(0.2,0,0,1) forwards}\n  .kcard .kl{font-size:12px;font-weight:500;color:${MTOK.muted};line-height:1.3}\n  .kcard .kv{font-size:26px;font-weight:700;color:${MTOK.ink};margin-top:6px}\n  .stagger>*{opacity:0;transform:translateY(12px);animation:enter .3s cubic-bezier(0.2,0,0,1) forwards}\n  @keyframes enter{to{opacity:1;transform:none}}\n  .empty{padding:40px;text-align:center;color:${MTOK.muted};font-size:14px}\n  .err{background:#FDECEA;color:#C62828;border-radius:12px;padding:14px;font-size:13px}\n  .loading{display:flex;align-items:center;gap:10px;color:${MTOK.muted};font-size:14px;padding:20px}\n  .spin{width:18px;height:18px;border:3px solid ${MTOK.container};border-top-color:${MTOK.primary};border-radius:50%;animation:sp .8s linear infinite}\n  @keyframes sp{to{transform:rotate(360deg)}}\n  @media (prefers-reduced-motion: reduce){.stagger>*,.kcard{animation:none;opacity:1;transform:none}.spin{animation:none}}\n  `,\n  render(d2){\n    const store=d2.store(d2.params.store);\n    const perfil=store.get('perfil','gn');\n    const cycle=store.get('cycle','202516');\n    const structureCode=store.get('structureCode','3253');\n    const data=store.get('data',null);\n    const topBar=d2.param('topBar','');\n    const userHeader=d2.param('userHeader','');\n    const statCard=d2.param('statCard','');\n    const accordion=d2.param('accordion','');\n    const brandChip=d2.param('brandChip','');\n    const typeBadge=d2.param('typeBadge','');\n\n    const topSlot = topBar ? d2.render(topBar,{title:'Painel de Ganhos',userName: perfil==='gn'?'Gerência Nacional':(perfil==='gv'?'Gerência de Vendas':'Líder')},{key:'top',style:'display:block'}) : '';\n\n    const seg = (id,lab)=>`<button class=\"segbtn\" data-perfil=\"${id}\" ${perfil===id?'data-active':''}>${lab}</button>`;\n    const controls = `<div class=\"controls\">\n      <div class=\"seg\">${seg('gn','GN')}${seg('lider','Líder')}${seg('gv','GV')}</div>\n      <div class=\"fld\"><label>Setor</label><input class=\"in-structure\" value=\"${structureCode}\"/></div>\n      <div class=\"fld\"><label>Ciclo</label><input class=\"in-cycle\" value=\"${cycle}\"/></div>\n    </div>`;\n\n    let bodyHtml='';\n    if(d2.state.loading){\n      bodyHtml = `<div class=\"loading\"><span class=\"spin\"></span>Carregando painel…</div>`;\n    } else if(d2.state.error){\n      bodyHtml = `<div class=\"err\">Erro ao carregar: ${d2.state.error}</div>`;\n    } else if(!data){\n      bodyHtml = `<div class=\"empty\">Sem dados. Ajuste os controles.</div>`;\n    } else if(perfil==='gv'){\n      const orgTotal=data.orgTotal||0;\n      const sectors=data.sectors||[];\n      let tot='';\n      if(statCard) tot=d2.render(statCard,{title:'Organização — Total',value:orgTotal,metrics:[{label:'Setores',value:String(data.sectorCount||sectors.length)}],brandChip:brandChip,typeBadge:typeBadge},{key:'org',style:'display:block'});\n      const cards=sectors.map((s,i)=> statCard?d2.render(statCard,{title:'Setor '+s.sector,value:s.remuneracao,metrics:[{label:'Líderes',value:String(s.leaderCount)}],brandChip:brandChip,typeBadge:typeBadge},{key:'s'+s.sector,style:'display:block'}):'').join('');\n      bodyHtml = `<div class=\"totrow\">${tot}</div><div class=\"sectionlab\">Setores</div><div class=\"stagger grid\">${cards}</div>`;\n    } else if(perfil==='lider'){\n      const t=data.totalizador||{};\n      const l=data.leaders&&data.leaders[0]?data.leaders[0]:data;\n      const c=leaderToCard(l);\n      let card='';\n      if(statCard) card=d2.render(statCard,{title:'Grupo '+(c.code||structureCode),value:c.remuneracao||t.remuneracao||0,nivel:c.nivel,rede:c.rede,brands:['natura','avon'],metrics:c.metrics,attainment:c.attainment,brandChip:brandChip,typeBadge:typeBadge},{key:'lcard',style:'display:block'});\n      const kcards=(c.kpis||[]).map((k,i)=>`<div class=\"kcard\" style=\"animation-delay:${i*60}ms\"><div class=\"kl\">${k.label}</div><div class=\"kv\">${k.value}</div></div>`).join('');\n      bodyHtml = `<div class=\"totrow\">${card}</div><div class=\"sectionlab\">Indicadores do grupo</div><div class=\"kpistrip\">${kcards}</div>`;\n    } else {\n      const t=data.totalizador||{};\n      const leaders=data.leaders||[];\n      const kpiPanel=data.kpiPanel||[];\n      let tot='';\n      if(statCard) tot=d2.render(statCard,{title:'Setor '+(data.structureCode||structureCode)+' — Total',value:t.remuneracao||0,metrics:[{label:'Grupos',value:String(t.leaderCount||leaders.length)}],brandChip:brandChip,typeBadge:typeBadge},{key:'tot',style:'display:block'});\n      const kstrip = kpiPanel.filter(k=>k.grain==='sector').map((k,i)=>`<div class=\"kcard\" style=\"animation-delay:${i*60}ms\"><div class=\"kl\">${k.kpi}</div><div class=\"kv\">${k.value!=null?Number(k.value).toLocaleString('pt-BR'):'—'}</div></div>`).join('');\n      const accs = leaders.map((l,i)=>{\n        const c=leaderToCard(l);\n        return accordion?d2.render(accordion,{title:'Grupo '+c.code,value:c.remuneracao,nivel:c.nivel,rede:c.rede,brands:['natura','avon'],attainment:c.attainment,metrics:c.metrics,kpis:c.kpis,startExpanded:i===0,brandChip:brandChip,typeBadge:typeBadge},{key:'g'+c.code,style:'display:block'}):'';\n      }).join('');\n      bodyHtml = `<div class=\"totrow\">${tot}</div>\n        <div class=\"sectionlab\">Indicadores do setor</div><div class=\"kpistrip\">${kstrip}</div>\n        <div class=\"sectionlab\">Grupos do setor</div><div class=\"accgrid\">${accs}</div>`;\n    }\n\n    return `<div class=\"shell\">\n      ${topSlot}\n      <div class=\"page\">\n        ${controls}\n        ${bodyHtml}\n      </div>\n    </div>`;\n  },\n  mounted(d2){\n    const store=d2.store(d2.params.store);\n    if(!store.get('data',null) && !d2.state.loading){ fetchData(d2); }\n    d2.on('.segbtn','click',(e,el)=>{ store.set('perfil', el.dataset.perfil); store.set('data', null); fetchData(d2); });\n    d2.on('.in-structure','change',(e,el)=>{ store.set('structureCode', el.value.trim()); store.set('data', null); fetchData(d2); });\n    d2.on('.in-cycle','change',(e,el)=>{ store.set('cycle', el.value.trim()); store.set('data', null); fetchData(d2); });\n  }\n};"}},"store":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"store"}}}},"api":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"api"}}}},"topBar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"topBar"}}}},"userHeader":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"userHeader"}}}},"statCard":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"statCard"}}}},"accordion":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"accordion"}}}},"brandChip":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"brandChip"}}}},"typeBadge":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"typeBadge"}}}}}}}}}},{"_id":"6a4849719c748d97fd57acea","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"component":"pilotMTokens","package":"natura-x-piloto","definition":{"component":"data2-code-components@CodeFn","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default () => ({\n  color: {\n    surface: '#FFFFFF',\n    ground: '#FAFAFB',\n    ink: '#1A1C1E',\n    muted: '#6B7280',\n    hairline: 'rgba(16,24,40,0.08)',\n    naturaMagenta: '#E5004B',\n    naturaOrange: '#EB6619',\n    avonMagenta: '#E5014B',\n    brandGradient: 'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',\n    rampRed: '#FF1418',\n    rampAmber: '#FAA000',\n    rampGreen: '#29AC56',\n    gold: '#F7BE00',\n    goldIap: '#FFCF30',\n    money: '#29AC56'\n  },\n  radius: { sm: 8, md: 12, lg: 16, pill: 999 },\n  type: {\n    family: \"'Roboto',system-ui,-apple-system,sans-serif\",\n    h1: '28px', h2: '20px', title: '15px', body: '13px', caption: '11px'\n  },\n  shadow: {\n    card: '0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',\n    raised: '0 4px 12px rgba(16,24,40,0.10)'\n  },\n  motion: {\n    hover: '150ms ease-out',\n    mount: '400ms cubic-bezier(0.4,0,0.2,1)',\n    fade: '200ms ease-out'\n  },\n  media: {\n    natura: 'https://natura-x-piloto.data2.media/file/UrhVLdPDEZCXToLgJDPW8',\n    avon: 'https://natura-x-piloto.data2.media/file/HqLhKqINaRUI9OSBjYGFh',\n    lockup: 'https://natura-x-piloto.data2.media/file/H0P_N-7AQzQOg_VJMBWzV'\n  }\n});"}}}}}},{"_id":"6a48497f6102ce7182b78e1e","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMBrandMark","package":"natura-x-piloto","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 FALLBACK = { media: {\n  natura: 'https://natura-x-piloto.data2.media/file/UrhVLdPDEZCXToLgJDPW8',\n  avon: 'https://natura-x-piloto.data2.media/file/HqLhKqINaRUI9OSBjYGFh',\n  lockup: 'https://natura-x-piloto.data2.media/file/H0P_N-7AQzQOg_VJMBWzV'\n}};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.media) TOK = FALLBACK; } return TOK; }\nfunction markSrc(t, brand){\n  const b = String(brand || 'natura').toLowerCase();\n  return b === 'avon' ? t.media.avon : t.media.natura;\n}\nexport default {\n  css: `\n  .bm{display:inline-flex;align-items:center;justify-content:center;line-height:0}\n  .bm img{display:block;height:100%;width:auto;object-fit:contain}\n  `,\n  render(d2){\n    const t = tok(d2);\n    const brand = d2.param('brand','natura');\n    const size = Number(d2.param('glyphSize', 20)) || 20;\n    const src = markSrc(t, brand);\n    const label = String(brand||'natura').toLowerCase()==='avon' ? 'Avon' : 'Natura';\n    return `<span class=\"bm\" style=\"height:${size}px\" title=\"${label}\"><img src=\"${src}\" alt=\"${label}\"/></span>`;\n  }\n};"}},"brand":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"brand"}}}},"glyphSize":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"glyphSize"}}}}}}}}}},{"_id":"6a4849886102ce7182b78e3e","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMProgressBar","package":"natura-x-piloto","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 FALLBACK = { color: { rampRed:'#FF1418', rampAmber:'#FAA000', rampGreen:'#29AC56' } };\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction rampColor(t, pct){\n  if (pct < 30) return t.color.rampRed;\n  if (pct < 60) return t.color.rampAmber;\n  return t.color.rampGreen;\n}\nexport default {\n  css: `\n  .pbwrap{display:flex;flex-direction:column;gap:4px;width:100%}\n  .pbtrack{height:7px;border-radius:999px;background:rgba(16,24,40,0.07);overflow:hidden}\n  .pbfill{height:100%;border-radius:999px;width:0;transition:width 400ms cubic-bezier(0.4,0,0.2,1)}\n  .pbcap{font:600 11px/1 'Roboto',system-ui,sans-serif;letter-spacing:.4px;text-transform:uppercase}\n  @media (prefers-reduced-motion: reduce){.pbfill{transition:none}}\n  `,\n  render(d2){\n    const t = tok(d2);\n    const value = Number(d2.param('value', 0)) || 0;\n    const goal = Number(d2.param('goal', 0)) || 0;\n    const pct = goal > 0 ? (value / goal) * 100 : 0;\n    const clamped = Math.max(0, Math.min(100, pct));\n    const col = rampColor(t, pct);\n    const showCap = d2.param('showCaption', true);\n    const cap = showCap ? `<div class=\"pbcap\" style=\"color:${col}\">ATINGIMENTO: ${pct.toFixed(2)}%</div>` : '';\n    return `<div class=\"pbwrap\">\n      <div class=\"pbtrack\"><div class=\"pbfill\" data-fill style=\"background:${col};width:0\"></div></div>\n      ${cap}\n    </div>`;\n  },\n  mounted(d2, root){\n    const value = Number(d2.param('value', 0)) || 0;\n    const goal = Number(d2.param('goal', 0)) || 0;\n    const pct = goal > 0 ? (value / goal) * 100 : 0;\n    const clamped = Math.max(0, Math.min(100, pct));\n    const fill = root.querySelector('[data-fill]');\n    if (fill) requestAnimationFrame(() => { fill.style.width = clamped + '%'; });\n  }\n};"}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"goal":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"goal"}}}},"showCaption":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"showCaption"}}}}}}}}}},{"_id":"6a4849d6e3014dd5bb6fd09a","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMKpiCard","package":"natura-x-piloto","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 FALLBACK = { color:{ surface:'#FFFFFF', ink:'#1A1C1E', muted:'#6B7280', hairline:'rgba(16,24,40,0.08)', goldIap:'#FFCF30', naturaMagenta:'#E5004B' }, radius:{ md:12 }, shadow:{ card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)' } };\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction fmtNum(d2, n){ try{ return d2.fmt.number(n); }catch(e){ return String(n); } }\nexport default {\n  css: `\n  .kc{position:relative;background:#FFFFFF;border:1px solid rgba(16,24,40,0.08);border-radius:12px;\n    padding:14px 16px;display:flex;flex-direction:column;gap:10px;box-sizing:border-box;height:100%;\n    box-shadow:0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08);transition:box-shadow 150ms ease-out,transform 150ms ease-out}\n  .kc:hover{box-shadow:0 4px 12px rgba(16,24,40,0.10);transform:translateY(-1px)}\n  .kc-top{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}\n  .kc-title{font:500 13px/1.3 'Roboto',system-ui,sans-serif;color:#6B7280;flex:1}\n  .kc-info{width:18px;height:18px;flex:none;border-radius:50%;border:1px solid rgba(16,24,40,0.16);\n    background:#fff;color:#6B7280;font:600 11px/16px 'Roboto',sans-serif;text-align:center;cursor:help;position:relative}\n  .kc-val{font:700 26px/1 'Roboto',system-ui,sans-serif;color:#1A1C1E;letter-spacing:-.3px}\n  .kc-val .goal{font-size:15px;font-weight:500;color:#6B7280}\n  .kc-iap{align-self:flex-start;display:inline-flex;align-items:center;gap:4px;height:20px;padding:0 9px;\n    border-radius:999px;background:#FFCF30;color:#5A4600;font:700 10px/1 'Roboto',sans-serif;letter-spacing:.5px}\n  .kc-tip{position:absolute;top:24px;right:0;z-index:20;width:200px;background:#1A1C1E;color:#fff;\n    padding:9px 11px;border-radius:8px;font:400 12px/1.45 'Roboto',sans-serif;\n    opacity:0;transform:translateY(2px);pointer-events:none;transition:opacity 200ms ease-out,transform 200ms ease-out;\n    box-shadow:0 6px 20px rgba(0,0,0,.25)}\n  .kc-info:hover .kc-tip{opacity:1;transform:translateY(0)}\n  @media (prefers-reduced-motion: reduce){.kc,.kc-tip{transition:none}.kc:hover{transform:none}}\n  `,\n  render(d2){\n    const t = tok(d2);\n    const title = d2.param('cardTitle','');\n    const value = d2.param('value', null);\n    const goal = Number(d2.param('goal', 0)) || 0;\n    const desc = d2.param('description','');\n    const iap = d2.param('iap', false);\n    const bar = d2.param('progressBar','natura-x-piloto@pilotMProgressBar');\n    const valTxt = (value === null || value === undefined || value === '') ? '—' : fmtNum(d2, value);\n    const goalHtml = goal > 0 ? `<span class=\"goal\"> / ${fmtNum(d2, goal)}</span>` : '';\n    const infoHtml = desc ? `<span class=\"kc-info\">i<span class=\"kc-tip\">${desc}</span></span>` : '';\n    const iapHtml = iap ? `<span class=\"kc-iap\">IAP</span>` : '';\n    const barHtml = (goal > 0 && value !== null && value !== undefined)\n      ? d2.render(bar, { value: Number(value)||0, goal: goal, showCaption: true }, { key: 'bar', style:'display:block' })\n      : '';\n    return `<div class=\"kc\">\n      <div class=\"kc-top\"><div class=\"kc-title\">${title}</div>${infoHtml}</div>\n      <div class=\"kc-val\">${valTxt}${goalHtml}</div>\n      ${barHtml}\n      ${iapHtml}\n    </div>`;\n  }\n};"}},"cardTitle":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cardTitle"}}}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"goal":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"goal"}}}},"description":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"description"}}}},"iap":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"iap"}}}},"progressBar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"progressBar"}}}}}}}}}},{"_id":"6a4849f7bf38d3828157022f","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMGroupCard","package":"natura-x-piloto","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 FALLBACK = { color:{ surface:'#FFFFFF', ink:'#1A1C1E', muted:'#6B7280', hairline:'rgba(16,24,40,0.08)', money:'#29AC56', gold:'#F7BE00', naturaMagenta:'#E5004B', naturaOrange:'#EB6619', rampRed:'#FF1418', rampAmber:'#FAA000', rampGreen:'#29AC56', totalTint:'#EAF7EE', totalBorder:'rgba(41,172,86,0.30)', brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)' } };\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction statusColor(t, status){\n  if(status==='green') return t.color.rampGreen;\n  if(status==='amber') return t.color.rampAmber;\n  if(status==='red') return t.color.rampRed;\n  return null;\n}\nfunction money(d2, n){ try{ return Number(n||0).toLocaleString('pt-BR',{style:'currency',currency:'BRL'}); }catch(e){ return 'R$ '+n; } }\nfunction num(d2, n){\n  if(n===null||n===undefined) return '—';\n  try{ return Number(n).toLocaleString('pt-BR',{maximumFractionDigits:0}); }catch(e){ return String(n); }\n}\nfunction initials(d2, name){ try{ return d2.fmt.initials(name,2); }catch(e){ return String(name||'?').slice(0,2).toUpperCase(); } }\nfunction redeLabel(rede){\n  const r = String(rede||'').toLowerCase();\n  if(r==='rede1') return 'REDE 1';\n  if(r==='rede2') return 'REDE 2';\n  return rede ? String(rede).toUpperCase() : '';\n}\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); }\nfunction svgIcon(iconId, color){\n  const c = color || '#6B7280';\n  const w = 'width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"'+c+'\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"';\n  const P = {\n    'people': '<circle cx=\"9\" cy=\"7\" r=\"3\"/><path d=\"M2 21v-2a5 5 0 0 1 5-5h4a5 5 0 0 1 5 5v2\"/><path d=\"M17 7a3 3 0 0 1 0 6\"/><path d=\"M22 21v-2a5 5 0 0 0-3-4.5\"/>',\n    'user': '<circle cx=\"12\" cy=\"8\" r=\"3.5\"/><path d=\"M4 21v-2a5 5 0 0 1 5-5h6a5 5 0 0 1 5 5v2\"/>',\n    'target': '<circle cx=\"12\" cy=\"12\" r=\"9\"/><circle cx=\"12\" cy=\"12\" r=\"5\"/><circle cx=\"12\" cy=\"12\" r=\"1.5\" fill=\"'+c+'\"/>',\n    'crown': '<path d=\"M3 8l4 4 5-6 5 6 4-4v9H3z\"/><path d=\"M3 20h18\"/>',\n    'swap': '<path d=\"M12 4v16\"/><path d=\"M7 8l-4 4 4 4\"/><path d=\"M17 8l4 4-4 4\"/>',\n    'user-add': '<circle cx=\"9\" cy=\"8\" r=\"3.5\"/><path d=\"M2 20v-1.5a5 5 0 0 1 5-5h4\"/><path d=\"M18 12v6\"/><path d=\"M15 15h6\"/>',\n    'coins': '<circle cx=\"8\" cy=\"8\" r=\"6\"/><path d=\"M18.09 10.37A6 6 0 1 1 10.34 18\"/><path d=\"M7 6h1v4\"/><path d=\"M16.71 13.88l.7.71-2.82 2.82\"/>'\n  };\n  const path = P[iconId] || '<circle cx=\"12\" cy=\"12\" r=\"3\" fill=\"'+c+'\" stroke=\"none\"/>';\n  return '<svg '+w+'>'+path+'</svg>';\n}\n// Friendly label for a gainByRef entry (rede1 ativas OR rede2 pontos, plus fallbacks).\nfunction gainLabel(ref){\n  const r = String(ref||'');\n  if(r.indexOf('pontos')>=0 || r.indexOf('volume')>=0) return 'Volume de pontos por marca';\n  if(r.indexOf('ativas')>=0) return 'Ativas por marca';\n  if(r.indexOf('ambas')>=0) return 'Ambas as marcas';\n  if(r.indexOf('migrad')>=0) return 'Migradas';\n  if(!r) return 'Acelerador';\n  return r.replace(/^lider-/,'').replace(/-/g,' ').replace(/\\b\\w/g, m => m.toUpperCase());\n}\n// Compact \"how the remuneração was built\" footer. Works for GN, leader and\n// totalizador cards; rede1 ativas AND rede2 pontos (same components shape).\n// comp = breakdown.components; gainByRef = array [{ref,amount,natura,avon}].\nfunction renderComposition(d2, markRef, comp, gainByRef, rem){\n  if(!comp) return '';\n  const brl = (n) => money(d2, n);\n  const natura = Number(comp.natura || 0);\n  const avon = Number(comp.avon || 0);\n  const remunBase = Number(comp.remunBase || (natura + avon) || 0);\n  const bonusAmbas = Number(comp.bonusAmbasMarcas || 0);\n  const bonusTotal = Number(comp.bonusTotal || 0);\n  const otherBonus = Math.max(0, bonusTotal - bonusAmbas);\n  const gains = Array.isArray(gainByRef) ? gainByRef : [];\n  const hasAny = (natura>0 || avon>0 || remunBase>0 || bonusTotal>0 || gains.length>0);\n  if(!hasAny) return '';\n\n  const brandRow = (brand, val) => {\n    if(!(Number(val) > 0)) return '';\n    const mark = d2.render(markRef, { brand: brand, glyphSize: 15 }, { key:'cmp-'+brand, style:'display:inline-flex' });\n    const nm = brand==='natura' ? 'Natura' : 'Avon';\n    return `<div class=\"gc-cline\"><span class=\"gc-cmark\">${mark}</span><span class=\"gc-clbl\">${nm}</span><span class=\"gc-cval\">${brl(val)}</span></div>`;\n  };\n  const plusRow = (label, val) => (Number(val) > 0)\n    ? `<div class=\"gc-cline\"><span class=\"gc-cbullet\">+</span><span class=\"gc-clbl\">${esc(label)}</span><span class=\"gc-cval\">+${brl(val)}</span></div>`\n    : '';\n\n  // Accelerator gains (rede1 ativas / rede2 pontos). Shows the primary gain(s).\n  const accRows = gains.filter(g => Number(g.amount||0) !== 0).map((g, i) => {\n    const amt = Number(g.amount || 0);\n    return `<div class=\"gc-cline gc-cacc\"><span class=\"gc-cbullet up\">↑</span><span class=\"gc-clbl\">${esc(gainLabel(g.ref))}</span><span class=\"gc-cval money\">+${brl(amt)}</span></div>`;\n  }).join('');\n\n  const brandRows = brandRow('natura', natura) + brandRow('avon', avon);\n  const bonusRows = plusRow('Bônus ambas as marcas', bonusAmbas) + plusRow('Bônus', otherBonus);\n  const ajuste = Number(comp.ajuste || 0);\n  const ajusteRow = ajuste !== 0\n    ? `<div class=\"gc-cline\"><span class=\"gc-cbullet\">${ajuste > 0 ? '+' : '−'}</span><span class=\"gc-clbl\">Ajuste do fechamento</span><span class=\"gc-cval\">${ajuste > 0 ? '+' : '−'}${brl(Math.abs(ajuste))}</span></div>`\n    : '';\n  const inner = brandRows + bonusRows + accRows + ajusteRow;\n  if(!inner) return '';\n\n  return `<details class=\"gc-comp\">\n    <summary class=\"gc-comp-sum\">\n      <span class=\"gc-comp-t\">Como sua remuneração foi construída</span>\n      <span class=\"gc-comp-caret\">⌄</span>\n    </summary>\n    <div class=\"gc-comp-body\">\n      ${inner}\n      <div class=\"gc-cline gc-ctotal\"><span class=\"gc-cbullet\">=</span><span class=\"gc-clbl\">Total</span><span class=\"gc-cval money\">${brl(rem)}</span></div>\n    </div>\n  </details>`;\n}\nexport default {\n  css: `\n  :host{overflow:visible!important;display:block}\n  .gc{background:transparent;border:0;padding:6px;box-sizing:border-box;height:100%;display:flex;min-width:0}\n  .gc-inner{background:#FFFFFF;border:1px solid rgba(16,24,40,0.08);border-radius:16px;padding:16px;\n    display:flex;flex-direction:column;gap:12px;box-sizing:border-box;width:100%;height:100%;\n    box-shadow:0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08);transition:box-shadow 150ms ease-out,transform 150ms ease-out}\n  .gc-inner:hover{box-shadow:0 4px 12px rgba(16,24,40,0.10);transform:translateY(-1px)}\n  .gc.clickable .gc-inner{cursor:pointer}\n  .gc.clickable:hover .gc-inner{box-shadow:0 6px 18px rgba(229,0,75,0.14);border-color:rgba(229,0,75,0.28);transform:translateY(-2px)}\n  .gc.clickable:active .gc-inner{transform:translateY(0)}\n  .gc.total .gc-inner{background:#EAF7EE;border-color:rgba(41,172,86,0.30)}\n  .gc-head{display:flex;align-items:flex-start;gap:12px}\n  .gc-av{width:44px;height:44px;flex:none;border-radius:50%;display:flex;align-items:center;justify-content:center;\n    color:#fff;font:700 15px/1 'Roboto',sans-serif;background:linear-gradient(135deg,#E5004B 0%,#EB6619 100%)}\n  .gc.total .gc-av{background:#29AC56}\n  .gc-id{flex:1;min-width:0}\n  .gc-name{font:600 15px/1.2 'Roboto',sans-serif;color:#1A1C1E;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .gc-sub{font:400 12px/1.3 'Roboto',sans-serif;color:#6B7280;margin-top:3px}\n  .gc-grp{font:500 11px/1.3 'Roboto',sans-serif;color:#6B7280;margin-top:1px}\n  .gc-badge{flex:none;display:flex;align-items:center}\n  .gc-redechip{display:inline-flex;align-items:center;height:22px;padding:0 9px;border-radius:999px;\n    background:#F3F4F6;color:#4A5560;font:700 10px/1 'Roboto',sans-serif;letter-spacing:.5px;white-space:nowrap}\n  .gc.total .gc-redechip{background:rgba(41,172,86,0.14);color:#1E7D3E}\n  .gc-stats{display:flex;flex-direction:column;gap:2px;border-top:1px solid rgba(16,24,40,0.07);padding-top:8px}\n  .gc.total .gc-stats{border-top-color:rgba(41,172,86,0.20)}\n  .gc-srow{display:flex;align-items:center;gap:10px;padding:5px 0}\n  .gc-ic{width:22px;flex:none;display:flex;align-items:center;justify-content:center}\n  .gc-dot-n{width:8px;height:8px;border-radius:50%;background:rgba(16,24,40,0.18)}\n  .gc-lbl{flex:1;min-width:0;font:500 12.5px/1.25 'Roboto',sans-serif;color:#3A3F45;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .gc-vals{flex:none;display:flex;align-items:baseline;gap:6px;text-align:right;font-variant-numeric:tabular-nums}\n  .gc-v{font:700 13px/1 'Roboto',sans-serif;color:#1A1C1E}\n  .gc-g{font:400 11px/1 'Roboto',sans-serif;color:#9AA1A9}\n  .gc-pct{font:700 12px/1 'Roboto',sans-serif;min-width:44px;text-align:right}\n  .gc-sdot{width:9px;height:9px;flex:none;border-radius:50%;box-shadow:0 0 0 3px rgba(0,0,0,0.02)}\n  .gc-sdot.none{background:transparent;box-shadow:none}\n  .gc-bonuschip{flex:none;display:inline-flex;align-items:center;gap:5px;height:22px;padding:0 10px;border-radius:999px;\n    font:700 10.5px/1 'Roboto',sans-serif;letter-spacing:.3px;white-space:nowrap}\n  .gc-bonuschip.yes{background:rgba(41,172,86,0.14);color:#1E7D3E}\n  .gc-bonuschip.no{background:#F1F2F4;color:#8A929B}\n  .gc-bonuschip svg{width:13px;height:13px}\n  .gc-ambas{display:flex;flex-direction:column;gap:4px;padding:5px 0}\n  .gc-ambas-h{display:flex;align-items:center;gap:10px}\n  .gc-ambas-m{display:flex;flex-wrap:wrap;gap:6px 14px;padding-left:32px}\n  .gc-am{display:inline-flex;align-items:center;gap:5px;font:600 12px/1 'Roboto',sans-serif;font-variant-numeric:tabular-nums}\n  .gc-am.ok{color:#1E7D3E}\n  .gc-am.no{color:#C2410C}\n  .gc-foot{display:flex;align-items:center;justify-content:space-between;border-top:1px solid rgba(16,24,40,0.07);padding-top:10px;margin-top:2px}\n  .gc.total .gc-foot{border-top-color:rgba(41,172,86,0.20)}\n  .gc-foot-l{font:500 10px/1 'Roboto',sans-serif;color:#6B7280;text-transform:uppercase;letter-spacing:.5px}\n  .gc-foot-v{font:700 17px/1 'Roboto',sans-serif;color:#29AC56}\n  /* composition footer (expandable) */\n  .gc-comp{border-top:1px solid rgba(16,24,40,0.07);margin-top:2px}\n  .gc.total .gc-comp{border-top-color:rgba(41,172,86,0.20)}\n  .gc-comp-sum{list-style:none;display:flex;align-items:center;gap:8px;cursor:pointer;padding:9px 0 2px;user-select:none}\n  .gc-comp-sum::-webkit-details-marker{display:none}\n  .gc-comp-t{flex:1;font:600 10.5px/1 'Roboto',sans-serif;color:#6B7280;text-transform:uppercase;letter-spacing:.5px}\n  .gc-comp-caret{color:#9AA1A9;font-size:14px;transition:transform 200ms ease-out}\n  .gc-comp[open] .gc-comp-caret{transform:rotate(180deg)}\n  .gc-comp-body{display:flex;flex-direction:column;gap:3px;padding:6px 0 2px}\n  .gc-cline{display:flex;align-items:center;gap:8px;font-variant-numeric:tabular-nums}\n  .gc-cmark{width:18px;flex:none;display:flex;align-items:center;justify-content:center}\n  .gc-cbullet{width:18px;flex:none;text-align:center;font:700 12px/1 'Roboto',sans-serif;color:#9AA1A9}\n  .gc-cbullet.up{color:#1E7D3E}\n  .gc-clbl{flex:1;min-width:0;font:500 12px/1.3 'Roboto',sans-serif;color:#3A3F45;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .gc-cval{flex:none;font:700 12.5px/1 'Roboto',sans-serif;color:#1A1C1E}\n  .gc-cval.money{color:#1E7D3E}\n  .gc-cacc .gc-clbl{color:#1E7D3E}\n  .gc-ctotal{border-top:1px dashed rgba(16,24,40,0.12);margin-top:4px;padding-top:6px}\n  .gc-ctotal .gc-clbl{font-weight:700;color:#1A1C1E}\n  .gc-ctotal .gc-cval{font-size:13.5px}\n  .dv-sec{font:600 10px/1 'Roboto',sans-serif;color:#6B7280;text-transform:uppercase;letter-spacing:.5px;margin:6px 0 2px}\n  .dv-sec:first-child{margin-top:0}\n  .dv-eff{flex:none;min-width:70px;text-align:right;font:700 12.5px/1 'Roboto',sans-serif;color:#1A1C1E;font-variant-numeric:tabular-nums}\n  .dv-lbl{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}\n  .dv-sub{font:400 11px/1.25 'Roboto',sans-serif;color:#6B7280;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .dv-ptitle{display:flex;align-items:center;gap:6px;font:700 11.5px/1 'Roboto',sans-serif;color:#3A3F45;margin-top:4px}\n  .dv-psub{margin-left:auto;font:700 12px/1 'Roboto',sans-serif;color:#1E7D3E;font-variant-numeric:tabular-nums}\n  .dv-subtot{display:flex;justify-content:flex-end;font:700 12px/1 'Roboto',sans-serif;color:#1E7D3E;padding:2px 0 4px;font-variant-numeric:tabular-nums}\n  .dv-formula{border-top:1px dashed rgba(16,24,40,0.12);margin-top:6px;padding-top:7px;text-align:right;font:500 11.5px/1.3 'Roboto',sans-serif;color:#4A5560;font-variant-numeric:tabular-nums}\n  @media (max-width:640px){.dv-eff{min-width:62px}.dv-sub{white-space:normal}}\n  @media (max-width:640px){.gc{padding:4px}.gc-inner{padding:14px;gap:10px}.gc-srow{gap:8px}.gc-pct{min-width:36px}}\n  @media (prefers-reduced-motion: reduce){.gc{transition:none}.gc:hover{transform:none}.gc-comp-caret{transition:none}}\n  `,\n  render(d2){\n    const t = tok(d2);\n    const name = d2.param('name','');\n    const nivel = d2.param('nivel','');\n    const rede = d2.param('rede','');\n    const rem = d2.param('remuneracao', 0);\n    const grupo = d2.param('codigoGrupo', d2.param('grupo',''));\n    const stats = d2.param('stats', d2.param('brandStats', [])) || [];\n    const variant = d2.param('variant','');\n    const isTotal = variant === 'totalizador';\n    const markRef = d2.param('brandMark','natura-x-piloto@pilotMBrandMark');\n    const badgeRef = d2.param('typeBadge','natura-x-piloto@pilotMTypeBadge');\n    const isGn = String(nivel).toLowerCase()==='gn';\n    const av = isTotal ? 'Σ' : initials(d2, name);\n    const roleWord = (String(nivel).toLowerCase()==='setor') ? 'Setor' : ('Líder ' + esc(nivel));\n    const redeNum = String(rede).replace('rede','');\n    const sub = isTotal ? ('Rede ' + redeNum) : (isGn ? ('Rede ' + redeNum + ' · GN') : ('Rede ' + redeNum + ' · ' + roleWord));\n    const grpLine = grupo ? `<div class=\"gc-grp\">${isGn ? 'Setor' : 'Grupo'} — ${esc(grupo)}</div>` : '';\n    const redeChip = `<span class=\"gc-redechip\">${redeLabel(rede)}</span>`;\n    const badgeHtml = (!isTotal && nivel && !isGn) ? d2.render(badgeRef, { nivel: nivel, rede: '', size: 'sm' }, { key:'badge', style:'display:inline-flex' }) : '';\n\n    const rows = stats.map((s, i) => {\n      const st = s.status || 'none';\n      const col = statusColor(t, st);\n      const hasBrand = s.brand === 'natura' || s.brand === 'avon';\n      const iconId = s.icon || '';\n      const isBonus = !!s.isBonus;\n      const iconTint = (iconId === 'crown') ? t.color.gold : (col || t.color.muted || '#6B7280');\n      const icon = hasBrand\n        ? d2.render(markRef, { brand: s.brand, glyphSize: 16 }, { key:'m'+i, style:'display:inline-flex' })\n        : svgIcon(iconId, iconTint);\n\n      if (Array.isArray(s.marcas)){\n        const recebe = s.recebe === true;\n        const chip = `<span class=\"gc-bonuschip ${recebe ? 'yes' : 'no'}\">${recebe ? '+' : ''}${money(d2, s.bonusValor)}</span>`;\n        const marcas = s.marcas.map((m, j) => {\n          const mk = (m.brand === 'natura' || m.brand === 'avon')\n            ? d2.render(markRef, { brand: m.brand, glyphSize: 14 }, { key:'am'+i+'-'+j, style:'display:inline-flex' })\n            : '';\n          const nm = m.brand === 'avon' ? 'Avon' : (m.brand === 'natura' ? 'Natura' : '');\n          return `<span class=\"gc-am ${m.ok ? 'ok' : 'no'}\">${mk}${nm} ${Number(m.value || 0).toFixed(0)}% ${m.ok ? '✓' : '✗'}</span>`;\n        }).join('');\n        return `<div class=\"gc-ambas\" data-key=\"srow-${i}\">\n          <div class=\"gc-ambas-h\">\n            <span class=\"gc-ic\">${icon}</span>\n            <span class=\"gc-lbl\" title=\"${esc(s.label)}\">Ambas as marcas 100%</span>\n            ${chip}\n          </div>\n          <div class=\"gc-ambas-m\">${marcas}</div>\n        </div>`;\n      }\n\n      if (isBonus){\n        const will = s.willReceive === true;\n        const chkSvg = '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>';\n        const dashSvg = '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linecap=\"round\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"/></svg>';\n        const chip = will\n          ? `<span class=\"gc-bonuschip yes\">${chkSvg} Vai receber</span>`\n          : `<span class=\"gc-bonuschip no\">${dashSvg} Não atingido</span>`;\n        return `<div class=\"gc-srow\" data-key=\"srow-${i}\">\n          <span class=\"gc-ic\">${icon}</span>\n          <span class=\"gc-lbl\" title=\"${esc(s.label)}\">${esc(s.label)}</span>\n          ${chip}\n        </div>`;\n      }\n\n      const hasGoal = s.goal !== null && s.goal !== undefined;\n      const goalHtml = hasGoal ? `<span class=\"gc-g\">/ ${num(d2, s.goal)}</span>` : '';\n      const at = s.atingimento;\n      const pctHtml = (at !== null && at !== undefined)\n        ? `<span class=\"gc-pct\" style=\"color:${col||'#6B7280'}\">${Number(at).toFixed(0)}%</span>`\n        : `<span class=\"gc-pct\" style=\"color:transparent\">·</span>`;\n      const dotHtml = (st === 'none')\n        ? `<span class=\"gc-sdot none\"></span>`\n        : `<span class=\"gc-sdot\" style=\"background:${col}\"></span>`;\n      return `<div class=\"gc-srow\" data-key=\"srow-${i}\">\n        <span class=\"gc-ic\">${icon}</span>\n        <span class=\"gc-lbl\" title=\"${esc(s.label)}\">${esc(s.label)}</span>\n        <span class=\"gc-vals\"><span class=\"gc-v\">${num(d2, s.value)}</span>${goalHtml}</span>\n        ${pctHtml}\n        ${dotHtml}\n      </div>`;\n    }).join('');\n\n    const drillEvent = d2.param('drillEvent','filter:group');\n    const drillCode = d2.param('drillCode', grupo);\n    const drillable = !isTotal && drillCode != null && String(drillCode) !== '';\n    const clickCls = drillable ? ' clickable' : '';\n    const groupAttr = drillable ? ` data-group=\"${esc(drillCode)}\" data-drill-event=\"${esc(drillEvent)}\"` : '';\n    return `<div class=\"gc${isTotal?' total':''}${clickCls}\"${groupAttr}>\n      <div class=\"gc-inner\">\n        <div class=\"gc-head\">\n          <span class=\"gc-av\">${av}</span>\n          <span class=\"gc-id\">\n            <div class=\"gc-name\">${isTotal ? esc(d2.param('totalLabel','0 - Totalizador Setor')) : esc(name)}</div>\n            <div class=\"gc-sub\">${sub}</div>\n            ${grpLine}\n            ${badgeHtml ? `<div style=\"margin-top:6px\">${badgeHtml}</div>` : ''}\n          </span>\n          <span class=\"gc-badge\">${redeChip}</span>\n        </div>\n        <div class=\"gc-stats\">${rows}</div>\n        <div class=\"gc-foot\">\n          <span class=\"gc-foot-l\">Remuneração</span>\n          <span class=\"gc-foot-v\">${money(d2, rem)}</span>\n        </div>\n      </div>\n    </div>`;\n  },\n  mounted(d2){\n    d2.on('.gc.clickable','click',(e,el)=>{\n      const code = el && el.getAttribute('data-group');\n      if(!code) return;\n      const evt = (el && el.getAttribute('data-drill-event')) || 'filter:group';\n      d2.bus.emit(evt, String(code));\n    });\n  }\n};"}},"name":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"name"}}}},"codigoGrupo":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"codigoGrupo"}}}},"nivel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"nivel"}}}},"rede":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rede"}}}},"remuneracao":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"remuneracao"}}}},"stats":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"stats"}}}},"variant":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"variant"}}}},"grupo":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"grupo"}}}},"brandStats":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"brandStats"}}}},"brandMark":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"brandMark"}}}},"typeBadge":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"typeBadge"}}}},"drillEvent":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"drillEvent"}}}},"drillCode":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"drillCode"}}}},"totalLabel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"totalLabel"}}}},"composition":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"composition"}}}},"gainByRef":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"gainByRef"}}}},"drivers":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"drivers"}}}}}}}}}},{"_id":"6a484a06c4ffc320c8fe8c1c","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMKpiGrid","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .kg{display:flex;flex-direction:column;gap:12px;overflow:visible}\n  .kg-h{font:600 15px/1 'Roboto',system-ui,sans-serif;color:#1A1C1E;display:flex;align-items:center;gap:8px}\n  .kg-h::before{content:'';width:4px;height:16px;border-radius:2px;background:linear-gradient(135deg,#E5004B 0%,#EB6619 100%)}\n  /* gutter so hover shadows are not cropped by the grid box */\n  .kg-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:14px;align-items:stretch;overflow:visible;padding:8px 6px 16px;margin:-8px -6px -16px}\n  .kg-cell{min-height:130px;overflow:visible}\n  `,\n  render(d2){\n    const kpis = d2.param('kpis', []) || [];\n    const card = d2.param('kpiCard','natura-x-piloto@pilotMKpiCard');\n    const title = d2.param('sectionTitle','Indicadores do Setor');\n    const cells = kpis.map((k, i) => {\n      const host = d2.render(card, {\n        cardTitle: k.title, value: k.value, goal: k.goal || 0,\n        description: k.description || '', iap: k.iap || false\n      }, { key: 'kpi-'+(k.code!=null?k.code:i), style:'display:block;height:100%' });\n      return `<div class=\"kg-cell\" data-key=\"kc-${i}\">${host}</div>`;\n    }).join('');\n    return `<div class=\"kg\">\n      <div class=\"kg-h\">${title}</div>\n      <div class=\"kg-grid\">${cells}</div>\n    </div>`;\n  }\n};"}},"kpis":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"kpis"}}}},"kpiCard":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"kpiCard"}}}},"sectionTitle":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"sectionTitle"}}}}}}}}}},{"_id":"6a484a0ebf38d38281570241","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMGroupGrid","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"function renderCard(d2, card, g, key, variant){\n  return d2.render(card, {\n    name: g.name,\n    codigoGrupo: (g.codigoGrupo != null ? g.codigoGrupo : g.grupo),\n    nivel: g.nivel,\n    rede: g.rede,\n    remuneracao: g.remuneracao,\n    stats: g.stats || [],\n    variant: variant || '',\n    composition: g.composition || null,\n    gainByRef: g.gainByRef || [],\n    drivers: g.drivers || null\n  }, { key: key, style:'display:block;height:100%;overflow:visible' });\n}\nexport default {\n  css: `\n  .gg{display:flex;flex-direction:column;gap:12px;overflow:visible}\n  .gg-h{font:600 15px/1 'Roboto',system-ui,sans-serif;color:#1A1C1E;display:flex;align-items:center;gap:8px}\n  .gg-h::before{content:'';width:4px;height:16px;border-radius:2px;background:linear-gradient(135deg,#E5004B 0%,#EB6619 100%)}\n  /* Shadow fix: symmetric padding gutter (NO negative margin) so a hover-lifted card's\n     shadow (blur 12 + translateY -1) breathes on every side and is never cropped.\n     The prior negative margins re-pulled cards flush to the clip edge — removed. */\n  .gg-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,360px),1fr));gap:12px;align-items:stretch;overflow:visible;padding:12px 10px 16px}\n  @media (max-width:640px){.gg-grid{gap:10px;padding:8px 0 12px}}\n  .gg-cell{min-height:1px;overflow:visible}\n  `,\n  render(d2){\n    const groups = d2.param('groups', []) || [];\n    const tot = d2.param('totalizador', null);\n    const card = d2.param('groupCard','natura-x-piloto@pilotMGroupCard');\n    const title = d2.param('sectionTitle','Ranking de Líderes');\n\n    let cells = '';\n    if (tot && (tot.stats || []).length){\n      const host = renderCard(d2, card, tot, 'tot-' + (tot.remuneracao || 0), 'totalizador');\n      cells += `<div class=\"gg-cell\" data-key=\"cell-tot\">${host}</div>`;\n    }\n    cells += groups.map((g, i) => {\n      const code = (g.codigoGrupo != null ? g.codigoGrupo : (g.grupo != null ? g.grupo : i));\n      const key = 'grp-' + code + '-' + (g.remuneracao || 0);\n      const host = renderCard(d2, card, g, key, '');\n      return `<div class=\"gg-cell\" data-key=\"cell-${i}\">${host}</div>`;\n    }).join('');\n\n    return `<div class=\"gg\">\n      <div class=\"gg-h\">${title}</div>\n      <div class=\"gg-grid\">${cells}</div>\n    </div>`;\n  }\n};"}},"groups":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"groups"}}}},"totalizador":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"totalizador"}}}},"groupCard":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"groupCard"}}}},"sectionTitle":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"sectionTitle"}}}}}}}}}},{"_id":"6a484a63242d6fc94ef5dd3a","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMDashboardShell","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"async function loadData(d2){\n  const store = d2.store('pilotDashboardStore');\n  if(!store) return;\n  try{\n    d2.state.loaderDone = false;\n    store.set('loading', true);\n    d2.refresh();\n    const perfil = store.get('perfil','gn');\n    const structureCode = store.get('structureCode','3253');\n    const rede = store.get('rede','rede1');\n    const gvName = store.get('gvName','PAINEIRA-ROSA');\n    // ── PART A — resolve the display cycle per group/sector. Default = the CURRENT\n    // calendar cycle; the header selector (cycleOptions) lets the user switch to a\n    // previous one, and that pick (cycleUserSel) survives drills while still valid.\n    // GV spans sectors: resolve on the GV's own gvName scope key; if that has no\n    // calendar rows the resolver 404s and we keep the store cycle. A manual ?cycle=\n    // override (bootstrapped into the store) still wins so a tester can pin a cycle.\n    let cycle = store.get('cycle', '');\n    const cycleForced = !!store.get('cycleForced', false);\n    if(!cycleForced){\n      const resolveKey = (perfil === 'gv') ? (gvName || structureCode) : structureCode;\n      try{\n        const rc = await d2.rush('pilotResolveDisplayCycle').invoke({ structureCode: resolveKey, perfil });\n        const rb = (rc && rc.data && rc.data.cycle) ? rc.data : (rc && rc.cycle ? rc : (rc && rc.data ? rc.data : null));\n        if(rb && (rb.calendarCycle || rb.cycle)){\n          const opts = Array.isArray(rb.availableCycles) ? rb.availableCycles : [];\n          store.set('cycleOptions', opts);\n          store.set('calendarCycle', rb.calendarCycle || '');\n          const picked = !!store.get('cycleUserSel', false) && opts.some(o=>String(o.cycle)===String(cycle));\n          if(!picked){ cycle = String(rb.calendarCycle || rb.cycle); store.set('cycle', cycle); store.set('cycleUserSel', false); }\n        } else if(!cycle){\n          cycle = '202610'; store.set('cycle', cycle);\n        }\n      }catch(e){ d2.log('resolveDisplayCycle error', e); if(!cycle){ cycle = '202610'; store.set('cycle', cycle); } }\n    }\n    if(!cycle){ cycle = '202610'; store.set('cycle', cycle); }\n    const res = await d2.rush('api').invoke({ perfil, structureCode, cycle, rede, gvName });\n    const payload = (res && (res.payload || (res.data && res.data.payload))) || (res && res.data) || res;\n    if(payload && payload.perfil){ store.set('data', payload); }\n    store.set('loading', false);\n    d2.refresh();\n  }catch(e){\n    d2.log('shell load error', e);\n    store.set('loading', false);\n    d2.refresh();\n  }\n}\n// Drill GN sector → LIDER group (remembers the sector to return to)\nfunction drillToLider(d2, groupCode, groupSectorCode){\n  const store = d2.store('pilotDashboardStore');\n  if(!store || !groupCode) return;\n  // STEP 3 clamp: a Líder cannot drill anywhere; a GN can only drill into its own sector.\n  if(scopeLockedToGroup(d2)) return;\n  if(!groupAllowed(d2, groupCode, groupSectorCode)) { d2.log('drillToLider blocked (out of scope)', groupCode); return; }\n  const curPerfil = store.get('perfil','gn');\n  if(curPerfil !== 'lider'){\n    // remember where we came from so \"Voltar\" restores it\n    d2.shared.set('pilotReturnPerfil', curPerfil, { global:true });\n    d2.shared.set('pilotReturnStructure', store.get('structureCode',''), { global:true });\n  }\n  store.set('perfil','lider');\n  store.set('structureCode', String(groupCode));\n  store.set('data', null);\n  pilotTrackView(d2, 'dashboard:lider', 'lider');\n  loadData(d2);\n}\n// Drill GV rede → GN sector (remembers the GV rede to return to)\nfunction drillToGn(d2, sectorCode){\n  const store = d2.store('pilotDashboardStore');\n  if(!store || !sectorCode) return;\n  // STEP 3 clamp: only a GV may switch to an arbitrary sector. A GN/Líder is pinned.\n  if(!sectorAllowed(d2, sectorCode)) { d2.log('drillToGn blocked (out of scope)', sectorCode); return; }\n  const curPerfil = store.get('perfil','gn');\n  if(curPerfil === 'gv'){\n    // Mark that this GN view was entered from a GV grid (survives a GN→LIDER→GN round-trip)\n    d2.shared.set('pilotGvRede', store.get('rede','rede1'), { global:true });\n  }\n  store.set('perfil','gn');\n  store.set('structureCode', String(sectorCode));\n  store.set('data', null);\n  d2.state.selGroup = '';\n  d2.shared.set('pilotSelectedGroup', '', { global:true });\n  pilotTrackView(d2, 'dashboard:gn', 'gn');\n  loadData(d2);\n}\n// Back GN → GV (rede) — pops one level up to the GV grid we came from\nfunction backToGv(d2){\n  const store = d2.store('pilotDashboardStore');\n  if(!store) return;\n  // STEP 3 clamp: a GN/Líder can NEVER go up to the GV view.\n  if(scopeLockedToSector(d2) || scopeLockedToGroup(d2)) { d2.log('backToGv blocked (out of scope)'); return; }\n  const retRede = d2.shared.get('pilotGvRede', 'rede1', { global:true }) || 'rede1';\n  store.set('perfil','gv');\n  store.set('rede', retRede);\n  store.set('data', null);\n  d2.state.selGroup = '';\n  d2.shared.set('pilotSelectedGroup', '', { global:true });\n  d2.shared.set('pilotGvRede', '', { global:true });\n  pilotTrackView(d2, 'dashboard:gv', 'gv');\n  loadData(d2);\n}\n// Back LIDER → GN sector (only valid when the effective identity is a GV or GN who\n// drilled DOWN to a leader; an effective LÍDER identity is locked to its group and\n// has no sector to return to — STEP 3).\nfunction backToSector(d2){\n  const store = d2.store('pilotDashboardStore');\n  if(!store) return;\n  if(scopeLockedToGroup(d2)) { d2.log('backToSector blocked — effective identity is a locked Líder'); return; }\n  let retPerfil = d2.shared.get('pilotReturnPerfil', 'gn', { global:true }) || 'gn';\n  const retStruct = d2.shared.get('pilotReturnStructure', '', { global:true });\n  // A GN drilling back always lands on its OWN sector, never a GV view.\n  if(scopeLockedToSector(d2)){\n    const eff = resolveEffectiveIdentity(d2);\n    retPerfil = 'gn';\n    if(eff) store.set('structureCode', String(eff.structureCode || eff.sectorCode || ''));\n  }\n  store.set('perfil', retPerfil);\n  if(retStruct && !scopeLockedToSector(d2)) store.set('structureCode', String(retStruct));\n  store.set('data', null);\n  d2.state.selGroup = '';\n  d2.shared.set('pilotSelectedGroup', '', { global:true });\n  pilotTrackView(d2, 'dashboard:sector', 'gn');\n  loadData(d2);\n}\n// ─────────────────────────────────────────────────────────────────────────────\n// STEP 2 — IDENTITY RESOLVER SEAM (prod-compliant abstraction)\n// Everything downstream consumes ONLY resolveActingIdentity / resolveEffectiveIdentity.\n// PILOT source of the acting identity = d2.shared 'pilotActingUserId' (set by the\n// switcher) or the ?actingUser= query param, defaulting to the seeded GV.\n// PROD source (documented, not wired): the acting identity would come from the\n// session token instead of d2.shared — see readActingUserId() below.\n// The resolver output SHAPE is identical in both worlds, so prod swaps only the\n// source (readActingUserId) + the lookup transport (pilotResolveIdentity → the\n// prod user/structure service). Nothing else in this shell changes.\n// ─────────────────────────────────────────────────────────────────────────────\n\n// ── STEP 2 — TWO identity SOURCES, ONE downstream shape ──────────────────────\n// PROD is two apps sharing this scope logic:\n//   • App B (token): identity from an auth TOKEN in the URL → scoped end-user, no\n//     impersonation UI. Checked FIRST (below).\n//   • App A (gv-admin): identity from the login session → full dashboard +\n//     impersonation. The PILOT stand-in for the login is the user-switcher, which\n//     writes d2.shared 'pilotActingUserId'.\n// readActingIdentitySource(d2) returns { userId, mode } where mode drives whether\n// the impersonation/switcher UI is shown. PROD swaps only the two source branches.\nfunction readActingIdentitySource(d2){\n  // App B / TOKEN mode — check FIRST. A token/user in the URL means the scoped\n  // end-user app; identity is that user and there is NO impersonation UI.\n  try{\n    const q = new URLSearchParams((typeof location!=='undefined' && location.search) || '');\n    // App B / TOKEN — prod reads the auth token from the URL as\n    // ?authorization (the OAM cookie) || ?token || ?c. We read all three, in\n    // that prod precedence, then keep ?actingUser as a DEV-only fallback so a\n    // tester can still open a pilot-user directly by id without a real token.\n    // V1-style session: the router stores the token in localStorage (_d2_natura_session) and\n    // strips it from the URL, so fall back to the stored token when the URL has none.\n    let urlToken = q.get('authorization') || q.get('token') || q.get('c');\n    if(!urlToken){ try{ const ns = JSON.parse(window.localStorage.getItem('_d2_natura_session') || 'null'); if(ns && ns.token) urlToken = ns.token; }catch(e){} }\n    const actingUser = q.get('actingUser');\n    if(urlToken || actingUser){\n      // The token itself is the source of truth in App B. resolveIdentityAndSeed\n      // resolves it via d2.rush('pilotResolveSession') → identity (PILOT synthetic\n      // users) — the ?actingUser fallback resolves through pilotResolveIdentity.\n      d2.shared.set('pilotMode', 'token', { global:true });\n      // token mode can never be impersonating - clear any stale target\n      d2.shared.set('pilotImpersonateUserId', '', { global:true });\n      if(urlToken){\n        d2.shared.set('pilotUrlToken', urlToken, { global:true });\n        // acting user id is unknown until pilotResolveSession returns it\n        return { userId: '', mode: 'token', token: urlToken };\n      }\n      // DEV fallback: ?actingUser=<pilot-user id> stands in for the decoded subject\n      d2.shared.set('pilotActingUserId', actingUser, { global:true });\n      return { userId: actingUser, mode: 'token' };\n    }\n    d2.shared.set('pilotUrlToken', '', { global:true });\n  }catch(e){}\n  // App A / GV-ADMIN mode (fallback). PROD App A: identity from login session.\n  // PROD: const claim = d2.session && d2.session.userId; if(claim) return { userId: claim, mode:'gv-admin' };\n  d2.shared.set('pilotMode', 'gv-admin', { global:true });\n  const uid = d2.shared.get('pilotActingUserId', '', { global:true }) || '';\n  return { userId: uid, mode: 'gv-admin' };\n}\nfunction readActingUserId(d2){ return readActingIdentitySource(d2).userId; }\n// The mode the shell resolved on mount (cached into the store). 'token' hides all\n// role-switching UI; 'gv-admin' shows the switcher + Impersonar.\nfunction resolveMode(d2){\n  const store = d2.store('pilotDashboardStore');\n  return (store && store.get('pilotMode', 'gv-admin')) || 'gv-admin';\n}\nfunction readImpersonateUserId(d2){\n  return d2.shared.get('pilotImpersonateUserId', '', { global:true }) || '';\n}\n// Resolve acting + effective identities via the server-side seam (pilotResolveIdentity).\n// Returns { acting, effective, impersonating }. Both identities share one shape:\n// { userId, name, perfil, structureCode, sectorCode, rede, nivel, gvName, scope }\n// where scope = { kind:'gv'|'sector'|'group', gvName?, sectorCode?, groupCode? }.\nasync function resolveIdentities(d2){\n  const actingUserId = readActingUserId(d2);\n  const impersonateUserId = readImpersonateUserId(d2);\n  try{\n    const res = await d2.rush('pilotResolveIdentity').invoke({ actingUserId, impersonateUserId });\n    const body = (res && res.data && res.data.data) ? res.data.data : (res && res.data ? res.data : res);\n    if(body && (body.acting || body.effective)) return body;\n  }catch(e){ d2.log('resolveIdentities error', e); }\n  return { acting:null, effective:null, impersonating:false };\n}\n// STEP 2 — the two named seams the briefing calls for. They read the identities the\n// shell cached into the store on mount (populated by resolveIdentities above). Kept\n// synchronous so render()/scope logic can consume them without awaiting.\nfunction resolveActingIdentity(d2){\n  const store = d2.store('pilotDashboardStore');\n  return (store && store.get('pilotActingIdentity', null)) || null;\n}\nfunction resolveEffectiveIdentity(d2){\n  const store = d2.store('pilotDashboardStore');\n  return (store && store.get('pilotEffectiveIdentity', null))\n    || (store && store.get('pilotActingIdentity', null)) || null;\n}\nfunction isImpersonating(d2){\n  const store = d2.store('pilotDashboardStore');\n  return !!(store && store.get('pilotImpersonating', false));\n}\n// ── STEP 2/3 — mount-time identity resolution ────────────────────────────────\n// Resolve acting + effective identities via the server seam, cache them into the\n// store (so the sync resolveActingIdentity/resolveEffectiveIdentity see them), then\n// clamp the store to the effective scope. Applied identically in token + gv-admin\n// mode, so an App-B GN and an impersonated GN are locked the same way.\nasync function resolveIdentityAndSeed(d2){\n  const store = d2.store('pilotDashboardStore');\n  if(!store) return;\n  const src = readActingIdentitySource(d2);        // establishes pilotMode + acting id\n  store.set('pilotMode', src.mode);\n  store.set('pilotTokenInvalid', false);\n  store.set('pilotTokenInvalidReason', '');\n  d2.shared.set('pilotTokenInvalid', false, { global:true }); // launchers (Histórico/Simulador) hide on an invalid session\n  // ── App B / TOKEN INGRESS — resolve the URL token via the pilotResolveSession\n  // Rush endpoint (STEP 3/4). This is the prod-faithful path: the token in the\n  // URL is exchanged for a scoped identity server-side. For PILOT synthetic users\n  // the endpoint maps demoToken/cdPessoa/_id → seeded pilot-user; in PROD the\n  // SAME endpoint runs pilotCheckToken→cd_pessoa→pilotGetToken→structure (its\n  // disabled `usePilotNatura` branch), so the shell never changes on the flip.\n  if(src.mode === 'token' && src.token){\n    // Session persistence: a resolved token-session survives SPA navigation via\n    // the pilot store (reused as the session store — key 'pilotTokenSession').\n    const cached = store.get('pilotTokenSession', null);\n    let identity = (cached && cached.token === src.token && cached.identity) ? cached.identity : null;\n    if(!identity){\n      try{\n        const res = await d2.rush('pilotResolveSession').invoke({ token: src.token });\n        const b = (res && res.data && res.data.data) ? res.data.data : (res && res.data ? res.data : res);\n        if(b && b.valid && b.userId){\n          identity = b;\n          store.set('pilotTokenSession', { token: src.token, identity: identity });\n        } else if(b && b.reason){\n          store.set('pilotTokenInvalidReason', String(b.reason));\n        }\n      }catch(e){ d2.log('pilotResolveSession error', e); }\n    }\n    if(identity){\n      // Token identity has no impersonation. acting == effective == the scoped user.\n      d2.shared.set('pilotActingUserId', identity.userId, { global:true });\n      store.set('pilotActingIdentity', identity);\n      store.set('pilotEffectiveIdentity', identity);\n      store.set('pilotImpersonating', false);\n      seedStoreFromEffective(d2);\n      return; // token mode: no switcher, no pilotResolveIdentity round-trip\n    }\n    // Invalid/expired token → clear the \"sessão inválida\" state (rendered below).\n    // PROD: location.href = 'https://consultoria.natura.com.br/...login' to bounce\n    // the consultant back to the Natura Consultoria login. In the pilot we show a\n    // clear invalid-session screen instead of a silent full-GV fallback.\n    store.set('pilotTokenInvalid', true);\n    d2.shared.set('pilotTokenInvalid', true, { global:true });\n    store.set('pilotTokenSession', null);\n    return;\n  }\n  const body = await resolveIdentities(d2);         // { acting, effective, impersonating }\n  if(body){\n    if(body.acting) store.set('pilotActingIdentity', body.acting);\n    if(body.effective) store.set('pilotEffectiveIdentity', body.effective);\n    store.set('pilotImpersonating', !!body.impersonating);\n  }\n  // Clamp the dashboard store to the effective identity (STEP 3). This runs AFTER\n  // the URL bootstrap, so a GN/Líder cannot land on another sector via a query param.\n  seedStoreFromEffective(d2);\n  // Populate the pilot user-switcher (gv-admin only). Token mode has no switcher.\n  if(src.mode !== 'token') ensureSwitcherUsers(d2);\n}\n// Load the full pilot-user roster once for the switcher dropdown (gv-admin\n// stand-in for the App-A login — NOT scope-limited; it lists everyone you can act\n// as). Distinct from pilotAllowedTargets (which IS scope-limited, for the picker).\nasync function ensureSwitcherUsers(d2){\n  if(Array.isArray(d2.state.switcherUsers) && d2.state.switcherUsers.length) return;\n  try{\n    const res = await d2.rush('pilotUsers').invoke({});\n    const b = (res && res.data && res.data.data) ? res.data.data : (res && res.data ? res.data : res);\n    d2.state.switcherUsers = (b && Array.isArray(b.users)) ? b.users : [];\n    d2.refresh();\n  }catch(e){ d2.log('switcherUsers error', e); }\n}\n// PILOT switcher (App-A stand-in for login). Sets the acting user + reloads as them.\nfunction onSwitchActingUser(d2, uid){\n  if(!uid) return;\n  d2.shared.set('pilotActingUserId', uid, { global:true });\n  d2.shared.set('pilotImpersonateUserId', '', { global:true }); // switching identity ends any impersonation\n  reloadAsIdentity(d2);\n}\n// Fetch the allowed impersonation targets for the current acting user (rules + scope).\nasync function ensureAllowedTargets(d2){\n  const store = d2.store('pilotDashboardStore');\n  const acting = resolveActingIdentity(d2);\n  const actorUserId = (acting && acting.userId) || d2.shared.get('pilotActingUserId','', { global:true });\n  if(!actorUserId){ d2.state.allowedTargets = []; d2.refresh(); return; }\n  if(d2.state.allowedTargetsFor === actorUserId && Array.isArray(d2.state.allowedTargets)) return;\n  d2.state.allowedTargetsLoading = true; d2.refresh();\n  try{\n    const res = await d2.rush('pilotAllowedTargets').invoke({ actorUserId });\n    const b = (res && res.data && res.data.data) ? res.data.data : (res && res.data ? res.data : res);\n    d2.state.allowedTargets = (b && Array.isArray(b.targets)) ? b.targets : [];\n    d2.state.allowedTargetsFor = actorUserId;\n  }catch(e){ d2.log('allowedTargets error', e); d2.state.allowedTargets = []; }\n  finally{ d2.state.allowedTargetsLoading = false; d2.refresh(); }\n}\n// Pick a target -> validate via pilotImpersonate (403 if denied) -> apply effective identity + reload.\nasync function onPickImpersonationTarget(d2, targetUserId){\n  if(!targetUserId) return;\n  const store = d2.store('pilotDashboardStore');\n  const acting = resolveActingIdentity(d2);\n  const actorUserId = (acting && acting.userId) || d2.shared.get('pilotActingUserId','', { global:true });\n  const cycle = store ? store.get('cycle','202610') : '202610';\n  try{\n    const res = await d2.rush('pilotImpersonate').invoke({ actorUserId, targetUserId, cycle });\n    const b = (res && res.data && res.data.data) ? res.data.data : (res && res.data ? res.data : res);\n    if(!b || b.code === 403 || b.allowed === false){\n      d2.state.impError = (b && b.message) || 'Impersonação não permitida.';\n      d2.refresh();\n      return;\n    }\n    d2.shared.set('pilotImpersonateUserId', targetUserId, { global:true });\n    d2.state.impPickerOpen = false; d2.state.impError = null;\n    pilotTrackView(d2, 'impersonation:start', (b && b.perfil) || 'impersonation', 'impersonation');\n    reloadAsIdentity(d2);\n  }catch(e){\n    d2.state.impError = 'Falha ao impersonar: ' + (e && e.message ? e.message : String(e));\n    d2.refresh();\n  }\n}\n// Sair da impersonação -> log end + restore actor + full scope.\nasync function onExitImpersonation(d2){\n  const store = d2.store('pilotDashboardStore');\n  const acting = resolveActingIdentity(d2);\n  const actorUserId = (acting && acting.userId) || d2.shared.get('pilotActingUserId','', { global:true });\n  const targetUserId = d2.shared.get('pilotImpersonateUserId','', { global:true });\n  const cycle = store ? store.get('cycle','202610') : '202610';\n  try{ await d2.rush('pilotEndImpersonation').invoke({ actorUserId, targetUserId, cycle }); }\n  catch(e){ d2.log('endImpersonation error', e); }\n  d2.shared.set('pilotImpersonateUserId', '', { global:true });\n  pilotTrackView(d2, 'impersonation:end', 'gv');\n  reloadAsIdentity(d2);\n}\n// Re-resolve identity, clear any drill breadcrumbs, seed scope and refetch the dashboard.\nasync function reloadAsIdentity(d2){\n  const store = d2.store('pilotDashboardStore');\n  if(store){\n    store.set('data', null);\n    d2.shared.set('pilotGvRede','', { global:true });\n    d2.shared.set('pilotReturnPerfil','', { global:true });\n    d2.shared.set('pilotReturnStructure','', { global:true });\n    d2.shared.set('pilotSelectedGroup','', { global:true });\n    d2.state.selGroup = '';\n  }\n  await resolveIdentityAndSeed(d2);\n  await loadData(d2);\n}\n// The effective perfil drives ALL scope locks. When a GV impersonates a GN/Líder,\n// the effective perfil becomes gn/lider so the SAME locks apply.\nfunction effectivePerfil(d2){\n  const eff = resolveEffectiveIdentity(d2);\n  return (eff && eff.perfil) || 'gv';\n}\n// ─────────────────────────────────────────────────────────────────────────────\n// STEP 3 — SCOPE ENFORCEMENT. Seed + clamp the dashboard store to the effective\n// identity so a GN/Líder can NEVER reach another sector/group by any control or a\n// stale query param. Seeding runs on mount; clamping runs on every drill/back/toggle.\n// ─────────────────────────────────────────────────────────────────────────────\nfunction seedStoreFromEffective(d2){\n  const store = d2.store('pilotDashboardStore');\n  const eff = resolveEffectiveIdentity(d2);\n  if(!store || !eff) return;\n  const perfil = eff.perfil || 'gv';\n  store.set('perfil', perfil);\n  store.set('gvName', eff.gvName || 'PAINEIRA-ROSA');\n  if(perfil === 'gn'){\n    store.set('structureCode', String(eff.structureCode || eff.sectorCode || ''));\n    if(eff.rede) store.set('rede', eff.rede);\n  } else if(perfil === 'lider'){\n    store.set('structureCode', String(eff.structureCode || ''));\n    if(eff.rede) store.set('rede', eff.rede);\n  } else {\n    // GV — keep full navigation; only default the structure if empty.\n    if(eff.rede) store.set('rede', eff.rede);\n  }\n}\n// True when the effective identity may NOT navigate above `level`.\n// gv → no locks; gn → locked to own sector (may drill down to a leader read-only);\n// lider → locked to own group (no drill/back at all).\nfunction scopeLockedToSector(d2){ return effectivePerfil(d2) === 'gn'; }\nfunction scopeLockedToGroup(d2){ return effectivePerfil(d2) === 'lider'; }\n// Clamp any attempt to move to a sector the effective GN doesn't own.\nfunction sectorAllowed(d2, sectorCode){\n  const eff = resolveEffectiveIdentity(d2);\n  if(!eff) return true;\n  if(eff.perfil === 'gv') return true;\n  if(eff.perfil === 'gn') return String(sectorCode) === String(eff.structureCode || eff.sectorCode || '');\n  if(eff.perfil === 'lider') return String(sectorCode) === String(eff.sectorCode || '');\n  return true;\n}\n// Clamp any attempt to drill into a group outside the effective identity's scope.\nfunction groupAllowed(d2, groupCode, groupSectorCode){\n  const eff = resolveEffectiveIdentity(d2);\n  if(!eff) return true;\n  if(eff.perfil === 'gv') return true;\n  if(eff.perfil === 'gn'){\n    // A GN may drill into leaders within its OWN sector only. When a group's parent\n    // sector is known, enforce it; otherwise fall back to allowing (data-driven grid\n    // already only shows this sector's leaders).\n    if(groupSectorCode != null) return String(groupSectorCode) === String(eff.structureCode || eff.sectorCode || '');\n    return true;\n  }\n  if(eff.perfil === 'lider') return String(groupCode) === String(eff.structureCode || '');\n  return true;\n}\nfunction escH(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n// PART A — cycle selector (current cycle + previous ones) shown at the top of every\n// branch; when the selected cycle is still open, a chip warns the values are partial.\nfunction fechamentoChip(d2){\n  const store = d2.store('pilotDashboardStore');\n  if(!store) return '';\n  const opts = store.get('cycleOptions', []) || [];\n  if(!opts.length) return '';\n  const cur = String(store.get('cycle', '') || '');\n  const sel = opts.find(o=>String(o.cycle)===cur);\n  const options = opts.map(o=>`<option value=\"${escH(o.cycle)}\" ${String(o.cycle)===cur?'selected':''}>Ciclo ${escH(o.cycle)}${o.isCurrent?' · atual':''}${o.closed?'':' · em andamento'}</option>`).join('');\n  const partial = (sel && !sel.closed) ? `<div class=\"pil-fechamento\" title=\"Valores parciais até o fechamento estatístico do ciclo\">\n    <svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M12 7v5l3 2\"/></svg>\n    <span class=\"pil-fech-txt\">Ciclo ${escH(cur)} em andamento — valores parciais, sujeitos ao fechamento</span>\n  </div>` : '';\n  return `<div class=\"pil-cycle-bar\">\n    <label class=\"pil-cycle-lbl\">Ciclo</label>\n    <select class=\"pil-cycle-sel\" aria-label=\"Selecionar ciclo\">${options}</select>\n    ${partial}\n  </div>`;\n}\nconst PERFIL_LABEL = { gv:'GV', gn:'GN', lider:'Líder' };\nfunction perfilLabel(p){ return PERFIL_LABEL[p] || String(p||''); }\n// ── STEP 5 — impersonation bar: switcher + Impersonar + banner + Sair ────────\n// gv-admin mode only. In token mode (App B) this renders NOTHING — the scoped\n// end-user app has no role-switching. All controls signal the shell's own mount\n// handlers (delegated d2.on); child picker rows use data-uid.\n// End-user (token) session? Not only the store's pilotMode — the global store handle can come back\n// empty on some loads — but also the shared flag, a token in the URL, or the locally stored token.\nfunction isTokenMode(d2){\n  if(resolveMode(d2) === 'token') return true;\n  try{ if(d2.shared.get('pilotMode', '', { global:true }) === 'token') return true; }catch(e){}\n  try{ const q = new URLSearchParams((typeof location!=='undefined' && location.search) || ''); if(q.get('authorization') || q.get('token') || q.get('c')) return true; }catch(e){}\n  try{ const ns = JSON.parse(window.localStorage.getItem('_d2_natura_session') || 'null'); if(ns && ns.token) return true; }catch(e){}\n  return false;\n}\nfunction impBar(d2){\n  const store = d2.store('pilotDashboardStore');\n  if(isTokenMode(d2)) return ''; // App B — hide PILOTO bar, switcher AND Impersonar entirely\n  const acting = resolveActingIdentity(d2);\n  const eff = resolveEffectiveIdentity(d2);\n  const impersonating = isImpersonating(d2);\n\n  // Banner (persistent, sticky, distinct colour) while impersonating.\n  let banner = '';\n  if(impersonating && eff && acting){\n    const scopeTxt = eff.perfil==='gn' ? (' · Setor '+(eff.structureCode||eff.sectorCode||''))\n      : eff.perfil==='lider' ? (' · Grupo '+(eff.structureCode||'')) : '';\n    banner = `<div class=\"pil-banner\">\n      <span class=\"pil-eye\" aria-hidden=\"true\">\n        <svg viewBox=\"0 0 24 24\" width=\"17\" height=\"17\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg>\n      </span>\n      <span class=\"pil-btxt\">Visualizando como <strong>${escH(eff.name)}</strong> (${escH(perfilLabel(eff.perfil))})${escH(scopeTxt)} · impersonado por <strong>${escH(acting.name)}</strong></span>\n      <span class=\"pil-spacer\"></span>\n      <button class=\"pil-imp-exit\" type=\"button\">Sair da impersonação</button>\n    </div>`;\n  }\n\n  // Switcher (pilot stand-in for the App-A login) + Impersonar button.\n  const switcherUsers = (d2.state.switcherUsers && Array.isArray(d2.state.switcherUsers)) ? d2.state.switcherUsers : [];\n  const curActingId = (acting && acting.userId) || '';\n  const opts = switcherUsers.map(u=>`<option value=\"${escH(u.userId)}\" ${String(u.userId)===String(curActingId)?'selected':''}>${escH(u.name)} · ${escH(perfilLabel(u.perfil))}${u.structureCode?(' '+escH(u.structureCode)):''}</option>`).join('');\n  const switcher = `<label class=\"pil-switch-wrap\" title=\"Trocar de usuário (piloto — stand-in do login App A)\">\n      <span class=\"pil-swlabel\">Usuário (piloto)</span>\n      <select class=\"pil-switch\">${opts||`<option>${escH((acting&&acting.name)||'—')}</option>`}</select>\n    </label>`;\n  const impBtn = impersonating ? '' : `<button class=\"pil-imp-open\" type=\"button\">\n      <svg viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><path d=\"M22 11l-3 3-2-2\"/></svg>\n      Impersonar</button>`;\n\n  // Picker overlay listing ONLY allowed targets.\n  let picker = '';\n  if(d2.state.impPickerOpen){\n    const q = String(d2.state.impQuery||'').trim().toLowerCase();\n    const all = Array.isArray(d2.state.allowedTargets) ? d2.state.allowedTargets : [];\n    const list = q ? all.filter(t=>{\n      const hay = `${t.name||''} ${perfilLabel(t.perfil)} ${t.structureCode||''} ${t.sectorCode||''}`.toLowerCase();\n      return hay.indexOf(q)>=0;\n    }) : all;\n    const rows = list.map(t=>`<button class=\"pil-imp-pick\" type=\"button\" data-uid=\"${escH(t.userId)}\" data-key=\"pk-${escH(t.userId)}\">\n        <span class=\"pil-pk-name\">${escH(t.name)}</span>\n        <span class=\"pil-pk-meta\"><span class=\"pil-pk-badge ${escH(t.perfil)}\">${escH(perfilLabel(t.perfil))}</span>${t.perfil==='gn'?('Setor '+escH(t.structureCode||'')):('Grupo '+escH(t.structureCode||'')+' · Setor '+escH(t.sectorCode||''))}</span>\n      </button>`).join('');\n    const bodyHtml = d2.state.allowedTargetsLoading\n      ? `<div class=\"pil-pk-empty\">Carregando alvos permitidos…</div>`\n      : (rows || `<div class=\"pil-pk-empty\">Nenhum alvo de impersonação permitido para este usuário.</div>`);\n    picker = `<div class=\"pil-modal\" data-key=\"pil-modal\">\n      <div class=\"pil-modal-card\">\n        <div class=\"pil-modal-head\">\n          <span class=\"pil-modal-title\">Impersonar usuário</span>\n          <button class=\"pil-imp-close\" type=\"button\" aria-label=\"Fechar\">✕</button>\n        </div>\n        <div class=\"pil-modal-sub\">Somente os usuários que você tem permissão de impersonar (regras + escopo).</div>\n        <input class=\"pil-imp-search\" type=\"text\" placeholder=\"Buscar por nome, perfil, setor ou grupo…\" value=\"${escH(d2.state.impQuery||'')}\"/>\n        ${d2.state.impError?`<div class=\"pil-pk-err\">${escH(d2.state.impError)}</div>`:''}\n        <div class=\"pil-pk-list\">${bodyHtml}</div>\n      </div>\n    </div>`;\n  }\n\n  const toolbar = `<div class=\"pil-toolbar\">\n      <span class=\"pil-tag\">PILOTO</span>\n      ${switcher}\n      <span class=\"pil-spacer\"></span>\n      ${impBtn}\n    </div>`;\n  return `<div class=\"pil-wrap\">${banner}${toolbar}${picker}</div>`;\n}\n// ─────────────────────────────────────────────────────────────────────────────\n// ACCESS TRACKING (additive) — sessions + section-view events via pilotTrackAccess.\n// One session per BROWSER session (sessionStorage), reused across SPA reloads.\n// IP is captured server-side; userAgent/referrer/entryMode/cycle client-side.\n// All calls are best-effort and never block or throw into the identity/scope path.\n// ─────────────────────────────────────────────────────────────────────────────\nconst PILOT_SID_KEY = 'pilotAccessSessionId';\nlet _pilotViewInFlight = null; // dedupe: last section we emitted a view for\nfunction pilotSidStore(){\n  try{ return (typeof window!=='undefined' && window.sessionStorage) ? window.sessionStorage : null; }catch(e){ return null; }\n}\nfunction pilotGetSid(d2){\n  const ss = pilotSidStore();\n  let sid = '';\n  try{ if(ss) sid = ss.getItem(PILOT_SID_KEY) || ''; }catch(e){}\n  if(!sid){\n    const store = d2.store('pilotDashboardStore');\n    if(store) sid = store.get('pilotAccessSid','') || '';\n  }\n  return sid;\n}\nfunction pilotSetSid(d2, sid){\n  if(!sid) return;\n  const ss = pilotSidStore();\n  try{ if(ss) ss.setItem(PILOT_SID_KEY, sid); }catch(e){}\n  const store = d2.store('pilotDashboardStore');\n  if(store) store.set('pilotAccessSid', sid);\n}\nfunction pilotMakeSid(){\n  try{ if(typeof crypto!=='undefined' && crypto.randomUUID) return 's-'+crypto.randomUUID(); }catch(e){}\n  return 's-'+Date.now()+'-'+Math.floor(Math.random()*1e9);\n}\n// effective identity + current store scope, flattened into the tracker payload shape.\nfunction pilotIdentityPayload(d2){\n  const store = d2.store('pilotDashboardStore');\n  const eff = (typeof resolveEffectiveIdentity==='function' ? resolveEffectiveIdentity(d2) : null) || {};\n  const impersonating = (typeof isImpersonating==='function') ? isImpersonating(d2) : false;\n  const rawMode = store ? store.get('pilotMode','gv-admin') : 'gv-admin';\n  // entryMode = the identity mode; a login while impersonating carries mode 'impersonation'.\n  const mode = impersonating ? 'impersonation' : (rawMode === 'gv-admin' ? 'session' : rawMode);\n  let ua = ''; let ref = '';\n  try{ ua = (typeof navigator!=='undefined' && navigator.userAgent) || ''; }catch(e){}\n  try{ ref = (typeof document!=='undefined' && document.referrer) || ''; }catch(e){}\n  return {\n    userId: eff.userId || (store && store.get('pilotActingUserId','')) || '',\n    name: eff.name || '',\n    perfil: eff.perfil || (store && store.get('perfil','')) || '',\n    mode: mode,\n    entryMode: mode,\n    structureCode: eff.structureCode || (store && store.get('structureCode','')) || '',\n    sectorCode: eff.sectorCode || '',\n    rede: eff.rede || (store && store.get('rede','')) || '',\n    gvName: eff.gvName || (store && store.get('gvName','')) || '',\n    cycle: (store && store.get('cycle','')) || '',\n    userAgent: ua,\n    referrer: ref\n  };\n}\n// On mount, AFTER identity resolves: reuse a stored sessionId (heartbeat) or FRESH login.\nasync function pilotTrackMount(d2){\n  try{\n    const store = d2.store('pilotDashboardStore');\n    // Do not track the invalid-session screen (no identity resolved).\n    if(store && store.get('pilotTokenInvalid', false)) return;\n    const existing = pilotGetSid(d2);\n    if(existing){\n      d2.rush('pilotTrackAccess').invoke({ action:'heartbeat', sessionId: existing }).catch(()=>{});\n      return;\n    }\n    const sid = pilotMakeSid();\n    const payload = pilotIdentityPayload(d2);\n    payload.action = 'login';\n    payload.sessionId = sid;\n    // Optimistically store first so a fast reload reuses it even if the call is in flight.\n    pilotSetSid(d2, sid);\n    const res = await d2.rush('pilotTrackAccess').invoke(payload);\n    const b = (res && res.data) ? res.data : res;\n    if(b && b.sessionId) pilotSetSid(d2, b.sessionId);\n  }catch(e){ d2.log('pilotTrackMount error', e); }\n}\n// Section navigation → one view event per logical navigation (deduped by section+level).\nfunction pilotTrackView(d2, section, drillLevel, modeOverride){\n  try{\n    if(!section) return;\n    const sid = pilotGetSid(d2);\n    if(!sid) return;\n    const key = section + '|' + (drillLevel||'') + '|' + (modeOverride||'');\n    if(_pilotViewInFlight === key) return; // collapse repeated same-target navigations\n    _pilotViewInFlight = key;\n    const payload = { action:'view', sessionId: sid, section: section, drillLevel: drillLevel||'' };\n    if(modeOverride) payload.mode = modeOverride; // event-level mode (e.g. 'impersonation')\n    d2.rush('pilotTrackAccess').invoke(payload)\n      .catch(()=>{})\n      .then(()=>{ if(_pilotViewInFlight===key) _pilotViewInFlight = null; });\n  }catch(e){ d2.log('pilotTrackView error', e); }\n}\n// Exit / logout / token-invalid → best-effort session-end (does not block).\nfunction pilotTrackEnd(d2){\n  try{\n    const sid = pilotGetSid(d2);\n    if(!sid) return;\n    d2.rush('pilotTrackAccess').invoke({ action:'session-end', sessionId: sid }).catch(()=>{});\n    const ss = pilotSidStore();\n    try{ if(ss) ss.removeItem(PILOT_SID_KEY); }catch(e){}\n    const store = d2.store('pilotDashboardStore');\n    if(store) store.set('pilotAccessSid','');\n  }catch(e){ d2.log('pilotTrackEnd error', e); }\n}\nfunction mapLeaders(leaders){\n  return (leaders || []).map(l => {\n    const comp = (l.breakdown && l.breakdown.components) || l.components || null;\n    const gainByRef = (comp && Array.isArray(comp.gainByRef)) ? comp.gainByRef : [];\n    return {\n      name: l.name || ('Grupo ' + l.structureCode),\n      codigoGrupo: l.codigoGrupo != null ? l.codigoGrupo : l.structureCode,\n      nivel: l.nivel,\n      rede: l.rede,\n      remuneracao: l.remuneracao,\n      stats: l.stats || [],\n      composition: comp,\n      gainByRef: gainByRef,\n      drivers: l.drivers || null\n    };\n  });\n}\n// Extract {composition, gainByRef} from a node carrying breakdown.components or components.\nfunction compOf(node){\n  if(!node) return { composition:null, gainByRef:[] };\n  const comp = (node.breakdown && node.breakdown.components) || node.components || null;\n  const gainByRef = (comp && Array.isArray(comp.gainByRef)) ? comp.gainByRef : [];\n  return { composition: comp, gainByRef: gainByRef };\n}\nexport default {\n  css: `\n  :host{display:block}\n  .shell{display:flex;flex-direction:column;min-height:100%;height:auto;background:#FAFAFB;font-family:Roboto,system-ui,sans-serif;overflow-x:visible}\n  /* Shadow fix: symmetric >=32px gutters on the scroll container's content so a hover-lifted\n     card's box-shadow (blur 12 + translateY -1) never reaches a clip edge on any side. */\n  .shell-body{display:flex;flex-direction:column;gap:24px;padding:32px 36px 64px;box-sizing:border-box;max-width:1264px;width:100%;margin:0 auto;overflow:visible}\n  .shell-load{padding:60px 20px;text-align:center;color:#6B7280;font-size:14px}\n  .topbar-host{position:sticky;top:0;z-index:10}\n  .lider-nav{display:flex}\n  .lider-back,.gn-back{display:inline-flex;align-items:center;gap:7px;height:38px;padding:0 16px 0 12px;border-radius:999px;\n    border:1px solid rgba(16,24,40,0.14);background:#FFFFFF;color:#3A3F45;font:600 13px/1 'Roboto',system-ui,sans-serif;\n    cursor:pointer;box-shadow:0 1px 2px rgba(16,24,40,0.05);transition:background 150ms ease-out,box-shadow 150ms ease-out,transform 150ms ease-out}\n  .lider-back:hover,.gn-back:hover{background:#F7F8FA;box-shadow:0 4px 12px rgba(16,24,40,0.10);transform:translateY(-1px)}\n  .lider-back svg,.gn-back svg{width:17px;height:17px}\n  .rede-toggle{display:inline-flex;gap:4px;padding:4px;background:#FFFFFF;border:1px solid rgba(16,24,40,0.10);\n    border-radius:999px;box-shadow:0 1px 2px rgba(16,24,40,0.05);width:max-content}\n  .rede-seg{appearance:none;border:0;background:transparent;cursor:pointer;height:34px;padding:0 20px;border-radius:999px;\n    font:700 12px/1 'Roboto',system-ui,sans-serif;letter-spacing:.5px;color:#6B7280;transition:background 150ms ease-out,color 150ms ease-out}\n  .rede-seg:hover{color:#3A3F45}\n  .rede-seg.on{background:linear-gradient(135deg,#E5004B 0%,#EB6619 100%);color:#FFFFFF;box-shadow:0 2px 8px rgba(229,0,75,0.28)}\n  .pil-fechamento{display:inline-flex;align-items:center;gap:7px;align-self:flex-start;padding:7px 13px;border-radius:999px;\n    background:rgba(250,160,0,0.12);border:1px solid rgba(250,160,0,0.35);color:#8A5B00;\n    font:700 12px/1.2 'Roboto',system-ui,sans-serif;letter-spacing:.1px}\n  .pil-fechamento svg{flex:none;color:#C77700}\n  .pil-fech-txt{white-space:normal}\n  .pil-cycle-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;align-self:flex-start}\n  .pil-cycle-lbl{font:700 11px/1 'Roboto',system-ui,sans-serif;letter-spacing:.06em;text-transform:uppercase;color:#6B7280}\n  .pil-cycle-sel{height:36px;padding:0 12px;border:1.5px solid rgba(16,24,40,0.12);border-radius:10px;background:#FFFFFF;\n    font:700 13px/1 'Roboto',system-ui,sans-serif;color:#1A1C1E;cursor:pointer;outline:none}\n  .pil-cycle-sel:focus{border-color:#E5004B}\n  .gv-h{font:600 15px/1 'Roboto',system-ui,sans-serif;color:#1A1C1E;display:flex;align-items:center;gap:8px}\n  .gv-h::before{content:'';width:4px;height:16px;border-radius:2px;background:linear-gradient(135deg,#E5004B 0%,#EB6619 100%)}\n  .gv-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,360px),1fr));gap:12px;align-items:stretch;overflow:visible;padding:12px 10px 16px}\n  @media (max-width:640px){.shell-body{padding:20px 12px 96px;gap:18px}.gv-grid{gap:10px;padding:8px 0 12px}\n    .pil-wrap{top:56px}.pil-toolbar{padding:8px 12px;gap:8px}.pil-swlabel{display:none}\n    .pil-switch-wrap{flex:1 1 auto;min-width:0}.pil-switch{max-width:none;width:100%;min-width:0}.pil-spacer{display:none}\n    .pil-imp-open{height:34px;padding:0 12px;flex:none}.pil-banner{padding:9px 12px;font-size:12px}}\n  .gv-cell{min-height:1px;overflow:visible}\n  /* ── STEP 5 impersonation bar ── */\n  .pil-wrap{position:sticky;top:64px;z-index:9;display:flex;flex-direction:column}\n  .pil-banner{display:flex;align-items:center;gap:10px;padding:10px 18px;background:linear-gradient(135deg,#6D28D9 0%,#9333EA 100%);color:#fff;font:600 13px/1.35 'Roboto',system-ui,sans-serif;box-shadow:0 2px 8px rgba(109,40,217,.28)}\n  .pil-banner strong{font-weight:800}\n  .pil-eye{display:inline-flex;align-items:center;opacity:.92}\n  .pil-btxt{min-width:0}\n  .pil-spacer{flex:1 1 auto}\n  .pil-imp-exit{appearance:none;border:1px solid rgba(255,255,255,.55);background:rgba(255,255,255,.14);color:#fff;font:700 12px/1 'Roboto',sans-serif;padding:8px 14px;border-radius:999px;cursor:pointer;white-space:nowrap;transition:background 150ms ease-out}\n  .pil-imp-exit:hover{background:rgba(255,255,255,.26)}\n  .pil-toolbar{display:flex;align-items:center;gap:12px;padding:8px 18px;background:#FFF7FB;border-bottom:1px solid rgba(229,0,75,.14)}\n  .pil-tag{font:800 9px/1 'Roboto',sans-serif;letter-spacing:.08em;color:#E5004B;background:rgba(229,0,75,.12);padding:5px 8px;border-radius:999px}\n  .pil-switch-wrap{display:inline-flex;align-items:center;gap:8px}\n  .pil-swlabel{font:700 10px/1 'Roboto',sans-serif;letter-spacing:.04em;text-transform:uppercase;color:#8A6D7A}\n  .pil-switch{appearance:none;height:34px;padding:0 30px 0 12px;border:1px solid rgba(16,24,40,.16);border-radius:9px;background:#fff;color:#1A1C1E;font:600 12px/1 'Roboto',sans-serif;cursor:pointer;max-width:340px;\n    background-image:url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236B7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>\");background-repeat:no-repeat;background-position:right 9px center}\n  .pil-switch:focus{outline:none;border-color:#E5004B;box-shadow:0 0 0 3px rgba(229,0,75,.12)}\n  .pil-imp-open{display:inline-flex;align-items:center;gap:7px;height:36px;padding:0 16px;border:none;border-radius:999px;cursor:pointer;color:#fff;\n    background:linear-gradient(135deg,#E5004B 0%,#EB6619 100%);font:700 12.5px/1 'Roboto',sans-serif;box-shadow:0 2px 8px rgba(229,0,75,.26);transition:transform 150ms ease-out,box-shadow 150ms ease-out}\n  .pil-imp-open:hover{transform:translateY(-1px);box-shadow:0 5px 14px rgba(229,0,75,.32)}\n  .pil-modal{position:fixed;inset:0;z-index:60;display:flex;align-items:flex-start;justify-content:center;padding:80px 16px 16px;background:rgba(16,24,40,.42);backdrop-filter:blur(2px)}\n  .pil-modal-card{width:100%;max-width:520px;background:#fff;border-radius:16px;box-shadow:0 24px 64px rgba(16,24,40,.30);padding:20px;box-sizing:border-box;max-height:70vh;display:flex;flex-direction:column}\n  .pil-modal-head{display:flex;align-items:center;gap:10px}\n  .pil-modal-title{font:800 17px/1.1 'Roboto',sans-serif;color:#1A1C1E;flex:1 1 auto}\n  .pil-imp-close{appearance:none;border:none;background:transparent;font-size:16px;color:#6B7280;cursor:pointer;width:30px;height:30px;border-radius:8px}\n  .pil-imp-close:hover{background:#F1F3F6;color:#1A1C1E}\n  .pil-modal-sub{margin:6px 0 12px;font:400 12.5px/1.4 'Roboto',sans-serif;color:#6B7280}\n  .pil-imp-search{width:100%;box-sizing:border-box;height:40px;padding:0 12px;border:1px solid rgba(16,24,40,.16);border-radius:10px;font:500 14px/1 'Roboto',sans-serif;color:#1A1C1E;margin-bottom:12px}\n  .pil-imp-search:focus{outline:none;border-color:#E5004B;box-shadow:0 0 0 3px rgba(229,0,75,.12)}\n  .pil-pk-err{background:#FFF1F1;border:1px solid #FFD2D2;color:#C4001D;border-radius:9px;padding:8px 11px;font:600 12px/1.4 'Roboto',sans-serif;margin-bottom:10px}\n  .pil-pk-list{overflow-y:auto;display:flex;flex-direction:column;gap:6px}\n  .pil-imp-pick{display:flex;flex-direction:column;gap:4px;text-align:left;padding:11px 13px;border:1px solid rgba(16,24,40,.10);border-radius:11px;background:#fff;cursor:pointer;transition:border-color 150ms,background 150ms}\n  .pil-imp-pick:hover{border-color:rgba(229,0,75,.4);background:#FFF7FB}\n  .pil-pk-name{font:700 13.5px/1.2 'Roboto',sans-serif;color:#1A1C1E}\n  .pil-pk-meta{display:flex;align-items:center;gap:8px;font:500 11.5px/1 'Roboto',sans-serif;color:#6B7280}\n  .pil-pk-badge{font:800 9.5px/1 'Roboto',sans-serif;letter-spacing:.04em;padding:4px 7px;border-radius:999px}\n  .pil-pk-badge.gn{background:rgba(59,130,246,.14);color:#1d5fd1}\n  .pil-pk-badge.lider{background:rgba(139,92,246,.16);color:#6d34d6}\n  .pil-pk-badge.gv{background:rgba(229,0,75,.12);color:#E5004B}\n  .pil-pk-empty{padding:26px 10px;text-align:center;color:#9AA1AC;font:500 13px/1.4 'Roboto',sans-serif}\n  @media (prefers-reduced-motion: reduce){.pil-imp-open,.pil-imp-exit,.pil-imp-pick{transition:none}.pil-imp-open:hover{transform:none}}\n  /* ── App B invalid-session screen ── */\n  .pil-invalid{display:flex;align-items:center;justify-content:center;min-height:100vh;padding:40px 20px;box-sizing:border-box}\n  .pil-invalid-card{max-width:420px;width:100%;background:#fff;border:1px solid rgba(16,24,40,.08);border-radius:18px;box-shadow:0 12px 40px rgba(16,24,40,.10);padding:36px 32px;text-align:center}\n  .pil-invalid-ic{width:64px;height:64px;margin:0 auto 18px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#E5004B;background:rgba(229,0,75,.10)}\n  .pil-invalid-tt{font:800 20px/1.2 'Roboto',system-ui,sans-serif;color:#1A1C1E;margin-bottom:10px}\n  .pil-invalid-sub{font:400 14px/1.5 'Roboto',system-ui,sans-serif;color:#6B7280}\n  `,\n  render(d2){\n    const store = d2.store('pilotDashboardStore');\n    const _tick = d2.state.filterTick;\n    const data = store ? store.get('data', {}) : {};\n    const loading = store ? store.get('loading', false) : false;\n    const perfil = (store ? store.get('perfil','gn') : 'gn');\n    const selectedGroup = (d2.state.selGroup != null) ? d2.state.selGroup : d2.shared.get('pilotSelectedGroup', '', { global:true });\n\n    // ── App B / TOKEN — invalid/expired session screen ────────────────────────\n    // Shown when a token param was present in the URL but pilotResolveSession\n    // returned {valid:false}. Never a silent full-GV fallback (that would be a\n    // scope-leak). In PROD this screen would be a redirect to the Natura\n    // Consultoria login (see resolveIdentityAndSeed).\n    if (store && store.get('pilotTokenInvalid', false)){\n      return `<div class=\"shell\"><div class=\"pil-invalid\">\n        <div class=\"pil-invalid-card\">\n          <div class=\"pil-invalid-ic\" aria-hidden=\"true\">\n            <svg viewBox=\"0 0 24 24\" width=\"30\" height=\"30\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/></svg>\n          </div>\n          ${store.get('pilotTokenInvalidReason', '') === 'sector-not-in-pilot'\n            ? `<div class=\"pil-invalid-tt\">Painel exclusivo do piloto</div>\n          <div class=\"pil-invalid-sub\">Este painel está disponível apenas para os setores que participam do piloto de remuneração. Em caso de dúvida, procure sua liderança.</div>`\n            : `<div class=\"pil-invalid-tt\">Sessão inválida</div>\n          <div class=\"pil-invalid-sub\">Não foi possível validar seu acesso. Faça login novamente pela Consultoria Natura para continuar.</div>`}\n        </div>\n      </div>`;\n    }\n\n    const topBar = d2.param('topBar','natura-x-piloto@pilotMTopBar');\n    const userHeader = d2.param('userHeader','natura-x-piloto@pilotMUserHeader');\n    const controls = d2.param('controls','natura-x-piloto@pilotMControls');\n    const groupGrid = d2.param('groupGrid','natura-x-piloto@pilotMGroupGrid');\n    const kpiGrid = d2.param('kpiGrid','natura-x-piloto@pilotMKpiGrid');\n    const typeBadge = d2.param('typeBadge','natura-x-piloto@pilotMTypeBadge');\n\n    // ── LIDER branch — own-performance drill view (no group grid) ──────────────\n    if (!loading && data && data.perfil === 'lider'){\n      const accL = d2.param('sectorAccordion','natura-x-piloto@pilotMSectorAccordion');\n      const lh = (data.header) || {};\n      const barL = d2.render(topBar, { title: 'Meu Desempenho', userName: (lh.leaderName || lh.name || '') }, { key:'barL', style:'display:block' });\n      // STEP 3: a locked Líder (effective perfil = lider) has NO sector to return to,\n      // so the back affordance is omitted entirely. Only a GV/GN who DRILLED down to a\n      // leader sees \"Voltar ao Setor\".\n      const backBtn = scopeLockedToGroup(d2) ? '' : `<button class=\"lider-back\" data-back=\"1\">\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M15 18l-6-6 6-6\"/></svg>\n        Voltar ao Setor</button>`;\n      const headerHostL = d2.render(userHeader, {\n        name: (lh.leaderName || lh.name || ''),\n        perfil: 'lider',\n        nivel: (lh.nivel || data.nivel || ''),\n        rede: (lh.rede || data.rede || ''),\n        grupo: (lh.grupo || data.structureCode || ''),\n        gvName: (lh.gvName || ''),\n        cycle: (lh.cycle || data.cycle || ''),\n        remuneracao: (data.remuneracao || 0),\n        typeBadge: typeBadge\n      }, { key:'hdrL-'+(data.structureCode||''), style:'display:block' });\n\n      const aceleradores = (data.aceleradores) || [];\n      const indicadores = (data.indicadores) || [];\n      const acSection = aceleradores.length ? d2.render(accL, {\n        items: aceleradores,\n        sectionTitle: 'Aceleradores de Ganhos',\n        startExpandedRef: (aceleradores[0] && aceleradores[0].ref) || ''\n      }, { key:'acel-'+(data.structureCode||'')+'-'+aceleradores.length, style:'display:block' }) : '';\n      const inSection = indicadores.length ? d2.render(accL, {\n        items: indicadores,\n        sectionTitle: 'Indicadores de Performance'\n      }, { key:'indic-'+(data.structureCode||'')+'-'+indicadores.length, style:'display:block' }) : '';\n\n      return `<div class=\"shell\">\n        <div class=\"topbar-host\">${barL}</div>\n        ${impBar(d2)}\n        <div class=\"shell-body\">\n          ${fechamentoChip(d2)}\n          <div class=\"lider-nav\">${backBtn}</div>\n          ${headerHostL}\n          ${acSection}\n          ${inSection}\n        </div>\n      </div>`;\n    }\n\n    // ── GV branch — GN-card grid + REDE toggle + Totalizador Rede ──────────────\n    if (!loading && data && data.perfil === 'gv'){\n      const gh = (data.header) || {};\n      const rede = data.rede || (store ? store.get('rede','rede1') : 'rede1');\n      const groupCard = d2.param('groupCard','natura-x-piloto@pilotMGroupCard');\n      const totRede = (data.totalizadorRede) || {};\n      const gns = (data.gns) || [];\n\n      const barGv = d2.render(topBar, { title: 'Gerentes de Negócio', userName: (gh.gvName || '') }, { key:'barGv', style:'display:block' });\n      const headerHostGv = d2.render(userHeader, {\n        name: (gh.gvName || ''),\n        perfil: 'gv',\n        cycle: (gh.cycle || data.cycle || ''),\n        sectorCount: (gh.sectorCount != null ? gh.sectorCount : gns.length),\n        remuneracao: (totRede.remuneracao || 0)\n      }, { key:'hdrGv-'+rede, style:'display:block' });\n\n      const seg = (r, lbl) => `<button class=\"rede-seg${r===rede?' on':''}\" data-rede=\"${r}\">${lbl}</button>`;\n      const toggle = `<div class=\"rede-toggle\" role=\"tablist\">${seg('rede1','REDE 1')}${seg('rede2','REDE 2')}</div>`;\n\n      const totRedeComp = compOf(totRede);\n      const totCard = (totRede.stats && totRede.stats.length) ? d2.render(groupCard, {\n        variant: 'totalizador',\n        totalLabel: (totRede.label || ('Totalizador Rede ' + String(rede).replace('rede',''))),\n        rede: rede,\n        stats: totRede.stats,\n        remuneracao: (totRede.remuneracao || 0),\n        composition: totRedeComp.composition,\n        gainByRef: totRedeComp.gainByRef\n      }, { key:'totrede-'+rede+'-'+(totRede.remuneracao||0), style:'display:block;height:100%;overflow:visible' }) : '';\n\n      const gnCards = gns.map((g, i) => {\n        const gnNatura = Number(g.compNatura || 0);\n        const gnAvon = Number(g.compAvon || 0);\n        const gnBonusAmbas = Number(g.compBonusAmbas || 0);\n        const gnComp = { natura: gnNatura, avon: gnAvon, remunBase: (gnNatura + gnAvon), bonusAmbasMarcas: gnBonusAmbas, bonusTotal: gnBonusAmbas };\n        const gnGain = (gnNatura + gnAvon) > 0 ? [{ ref: (g.rede==='rede2'?'lider-volume-pontos-marca':'lider-ativas-por-marca'), amount: (gnNatura + gnAvon), natura: gnNatura, avon: gnAvon }] : [];\n        const host = d2.render(groupCard, {\n          name: g.gnName,\n          nivel: 'gn',\n          rede: g.rede,\n          remuneracao: g.remuneracao,\n          codigoGrupo: g.sectorCode,\n          drillCode: g.sectorCode,\n          drillEvent: 'drill:gn',\n          stats: g.stats || [],\n          composition: gnComp,\n          gainByRef: gnGain,\n          drivers: g.drivers || null\n        }, { key:'gn-'+g.sectorCode+'-'+(g.remuneracao||0), style:'display:block;height:100%;overflow:visible' });\n        return `<div class=\"gv-cell\" data-key=\"gvcell-${g.sectorCode}\">${host}</div>`;\n      }).join('');\n\n      const totCell = totCard ? `<div class=\"gv-cell\" data-key=\"gvcell-tot-${rede}\">${totCard}</div>` : '';\n\n      return `<div class=\"shell\">\n        <div class=\"topbar-host\">${barGv}</div>\n        ${impBar(d2)}\n        <div class=\"shell-body\">\n          ${fechamentoChip(d2)}\n          ${headerHostGv}\n          ${toggle}\n          <div class=\"gv-h\">Gerentes de Negócio · Rede ${String(rede).replace('rede','')}</div>\n          <div class=\"gv-grid\">${totCell}${gnCards}</div>\n        </div>\n      </div>`;\n    }\n\n    const header = (data && data.header) || {};\n    const tot = (data && data.totalizador) || {};\n    const leaders = (data && data.leaders) || [];\n    const sectorCode = header.sectorCode || (data && data.structureCode) || (store ? store.get('structureCode','') : '');\n    const gnName = header.gnName || '';\n    const sectorName = header.sectorName || ('Setor ' + sectorCode);\n    const cycle = header.cycle || (data && data.cycle) || (store ? store.get('cycle','') : '');\n    const rede = header.rede || tot.rede || '';\n\n    const bar = d2.render(topBar, { title: 'Ranking de Líderes', userName: (gnName || sectorName) }, { key:'bar', style:'display:block' });\n\n    const dataReady = !loading && !!data && !!data.perfil;\n    if (!dataReady && !d2.state.loaderDone){\n      const loadingCmp = d2.param('loading','natura-x-piloto@pilotMLoading');\n      const loadDetail = (d2.state.loadDetail != null) ? d2.state.loadDetail : '';\n      const loadingHost = d2.render(loadingCmp, {\n        label: 'Carregando painel',\n        detail: loadDetail,\n        estimateMs: 18000,\n        cardCount: 6,\n        done: dataReady\n      }, { key:'loader', style:'display:block', onDone: ()=>{ d2.state.loaderDone = true; d2.refresh(); } });\n      return `<div class=\"shell\">\n        <div class=\"topbar-host\">${bar}</div>\n        ${impBar(d2)}\n        ${loadingHost}\n      </div>`;\n    }\n\n    const headerHost = d2.render(userHeader, {\n      name: (gnName || sectorName),\n      perfil: perfil,\n      rede: rede,\n      sectorCode: sectorCode,\n      cycle: cycle,\n      remuneracao: tot.remuneracao || 0,\n      leaderCount: (data.leaderCount != null ? data.leaderCount : leaders.length)\n    }, { key:'hdr-'+sectorCode, style:'display:block' });\n\n    const allGroups = mapLeaders(leaders);\n    const cycles = [{ code: cycle }];\n    const controlsHost = d2.render(controls, {\n      groups: allGroups,\n      cycles: cycles\n    }, { key:'ctl', style:'display:block', onChange: (payload)=>{ d2.state.filterTick = Date.now(); } });\n\n    const filtered = selectedGroup\n      ? allGroups.filter(g => String(g.codigoGrupo) === String(selectedGroup))\n      : allGroups;\n    const totComp = compOf(tot);\n    const showTot = !selectedGroup ? Object.assign({}, tot, { composition: totComp.composition, gainByRef: totComp.gainByRef }) : null;\n    const titleSuffix = selectedGroup ? (' · Grupo ' + selectedGroup) : (gnName ? (' · ' + gnName) : '');\n    const groupSection = d2.render(groupGrid, {\n      groups: filtered,\n      totalizador: showTot,\n      sectionTitle: 'Ranking de Líderes' + titleSuffix\n    }, { key:'groups-' + (selectedGroup || 'all'), style:'display:block' });\n\n    const sectorItems = (data && data.sectorItems) || [];\n    const sectorKpis = (data && data.sectorKpis) || [];\n    const sectorAccordion = d2.param('sectorAccordion','natura-x-piloto@pilotMSectorAccordion');\n    let sectorSection = '';\n    if (!selectedGroup && sectorItems.length){\n      sectorSection = d2.render(sectorAccordion, {\n        items: sectorItems,\n        sectionTitle: 'Indicadores do Setor',\n        startExpandedRef: (sectorItems[0] && sectorItems[0].ref) || ''\n      }, { key:'sectoritems-' + sectorCode + '-' + sectorItems.length, style:'display:block' });\n    } else if (!selectedGroup && sectorKpis.length){\n      sectorSection = d2.render(kpiGrid, {\n        kpis: sectorKpis,\n        sectionTitle: 'Indicadores do Setor'\n      }, { key:'sectorkpis-' + sectorCode + '-' + sectorKpis.length, style:'display:block' });\n    }\n\n    const cameFromGv = !!(d2.shared.get('pilotGvRede','', { global:true }));\n    const gnBack = cameFromGv ? `<div class=\"lider-nav\"><button class=\"gn-back\" data-gnback=\"1\">\n      <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M15 18l-6-6 6-6\"/></svg>\n      Voltar aos Setores</button></div>` : '';\n\n    return `<div class=\"shell\">\n      <div class=\"topbar-host\">${bar}</div>\n      ${impBar(d2)}\n      <div class=\"shell-body\">\n        ${fechamentoChip(d2)}\n        ${gnBack}\n        ${headerHost}\n        ${controlsHost}\n        ${groupSection}\n        ${sectorSection}\n      </div>\n    </div>`;\n  },\n  async mounted(d2){\n    // Bootstrap overrides from URL query (?perfil=gv&rede=rede1&structureCode=3253&gvName=...)\n    // Lets a GV/GN/LIDER view be opened directly for verification without a role-switch UI.\n    try{\n      const store = d2.store('pilotDashboardStore');\n      const q = new URLSearchParams((typeof location!=='undefined' && location.search) || '');\n      if(store){\n        if(q.get('perfil')) store.set('perfil', q.get('perfil'));\n        if(q.get('rede')) store.set('rede', q.get('rede'));\n        if(q.get('structureCode')) store.set('structureCode', q.get('structureCode'));\n        if(q.get('gvName')) store.set('gvName', q.get('gvName'));\n        if(q.get('cycle')){ store.set('cycle', q.get('cycle')); store.set('cycleForced', true); }\n      }\n    }catch(e){ d2.log('bootstrap query error', e); }\n    // ── STEP 2/3 — resolve identity (token vs gv-admin) then seed + clamp scope ──\n    // Runs AFTER the raw ?perfil=/?structureCode= bootstrap so the effective\n    // identity's scope OVERRIDES any stale/hostile query param for a GN/Líder.\n    await resolveIdentityAndSeed(d2);\n    // ── ACCESS TRACKING (additive) — runs AFTER identity resolves so the session\n    // carries the effective identity/scope. Reuses a stored sessionId (heartbeat)\n    // or mints one (login). Never blocks the dashboard load below.\n    await pilotTrackMount(d2);\n    // Impersonation-bar UI events (gv-admin mode only; the render hides them in token mode).\n    d2.on('.pil-switch','change',(e,el)=>{ onSwitchActingUser(d2, el && el.value); });\n    d2.on('.pil-imp-open','click',()=>{ d2.state.impPickerOpen = true; d2.state.impQuery=''; ensureAllowedTargets(d2); d2.refresh(); });\n    d2.on('.pil-imp-close','click',()=>{ d2.state.impPickerOpen = false; d2.refresh(); });\n    d2.on('.pil-imp-search','input',(e,el)=>{ d2.state.impQuery = el ? el.value : ''; d2.refresh(); });\n    d2.on('.pil-imp-pick','click',(e,el)=>{ onPickImpersonationTarget(d2, el && el.getAttribute('data-uid')); });\n    d2.on('.pil-imp-exit','click',()=>{ onExitImpersonation(d2); });\n    // Group selector: non-empty -> drill into that group's LIDER view; empty -> back to sector.\n    d2.bus.on('filter:group', (v)=>{\n      const store = d2.store('pilotDashboardStore');\n      const code = (v || '');\n      if(code){\n        drillToLider(d2, code);\n      } else if(store && store.get('perfil','gn') === 'lider'){\n        backToSector(d2);\n      } else {\n        d2.state.selGroup = '';\n        d2.refresh();\n      }\n    });\n    // GV → GN drill: clicking a GN card emits 'drill:gn' with the sector code.\n    d2.bus.on('drill:gn', (v)=>{ drillToGn(d2, (v || '')); });\n    // Explicit back signal (from another component if needed)\n    d2.bus.on('pilot:back', ()=>{ backToSector(d2); });\n    // Back button inside this shell's LIDER header\n    d2.on('.lider-back','click',()=>{ backToSector(d2); });\n    // REDE 1 / REDE 2 toggle in the GV branch → switch rede param and refetch.\n    d2.on('.rede-seg','click',(e,el)=>{\n      const store = d2.store('pilotDashboardStore');\n      const r = el && el.getAttribute('data-rede');\n      if(!store || !r || store.get('rede','rede1') === r) return;\n      pilotTrackView(d2, 'dashboard:gv:'+r, 'gv');\n      store.set('rede', r);\n      store.set('data', null);\n      loadData(d2);\n    });\n    // GN → GV back button (only present when we drilled from a GV grid)\n    d2.on('.gn-back','click',()=>{ backToGv(d2); });\n    // Cycle selector → refetch the current view for the chosen cycle.\n    d2.on('.pil-cycle-sel','change',(e,el)=>{\n      const store = d2.store('pilotDashboardStore');\n      const v = el && el.value;\n      if(!store || !v || String(store.get('cycle','')) === String(v)) return;\n      store.set('cycle', String(v));\n      store.set('cycleUserSel', true);\n      store.set('data', null);\n      pilotTrackView(d2, 'dashboard:cycle:'+v, store.get('perfil','gn'));\n      loadData(d2);\n    });\n    // App B: an invalid token shows the \"sessão inválida\" screen — do NOT fetch\n    // default dashboard data (that would render a silent full-GV view = scope leak).\n    const storeM = d2.store('pilotDashboardStore');\n    if(storeM && storeM.get('pilotTokenInvalid', false)){\n      pilotTrackEnd(d2); // token invalid → end any session from this browser session\n      d2.state.loaderDone = true; d2.refresh(); return;\n    }\n    await loadData(d2);\n    // Initial section view for the entry screen (after data resolves so perfil is known).\n    try{\n      const p = storeM ? storeM.get('perfil','gn') : 'gn';\n      pilotTrackView(d2, 'dashboard:'+p, p);\n    }catch(e){}\n    // NOTE: intentionally NO 'pagehide'/'beforeunload' session-end — those fire on a\n    // plain RELOAD too, which would end the session and break the one-session-per-browser\n    // guarantee (a reload must REUSE the stored sessionId). Abandoned sessions are derived\n    // as expired in the stats screen via the 30-min lastSeenAt TTL; explicit session-end is\n    // reserved for logout / token-invalid (handled above and on the invalid-token branch).\n  }\n};"}},"store":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"store"}}}},"api":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"api"}}}},"topBar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"topBar"}}}},"userHeader":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"userHeader"}}}},"controls":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"controls"}}}},"kpiGrid":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"kpiGrid"}}}},"groupGrid":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"groupGrid"}}}}}}}}}},{"_id":"6a484afcb0a857d0aa64c9f0","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMTokenProbe","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  render(d2){\n    return `<pre class=\"probe\">pending…</pre>`;\n  },\n  async mounted(d2, root){\n    const show = (msg)=>{ const p=root.querySelector('.probe'); if(p) p.textContent=msg; };\n    let out = [];\n    // 1) d2.exec of the headless CD\n    try {\n      const r = await d2.exec({ component:'natura-x-piloto@pilotMTokens', params:{} });\n      out.push('exec='+(r&&r.color?('OK '+r.color.naturaMagenta):(typeof r)));\n    } catch(e){ out.push('exec THREW '+String(e).slice(0,60)); }\n    // 2) d2.process\n    try {\n      const pr = d2.process ? d2.process('pilotMTokens') : null;\n      const keys = pr ? Object.keys(pr).slice(0,8).join(',') : '';\n      let val;\n      try { val = pr && pr.invoke ? await pr.invoke({}) : undefined; } catch(e2){ val = 'invErr:'+String(e2).slice(0,40); }\n      const shape = (val&&val.color)?('OK '+val.color.naturaMagenta):(typeof val==='string'?val:typeof val);\n      out.push('invoke='+shape);\n    } catch(e){ out.push('process THREW '+String(e).slice(0,40)); }\n    show(out.join(' | '));\n  }\n};"}}}}}}}},{"_id":"6a490aa7e3014dd5bb70bd32","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMControls","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"function esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nexport default {\n  css: `\n  :host{display:block}\n  .ctl{display:flex;flex-wrap:wrap;gap:12px;align-items:flex-end;background:#FFFFFF;border:1px solid rgba(16,24,40,0.08);\n    border-radius:14px;padding:14px 16px;box-sizing:border-box;box-shadow:0 1px 3px rgba(16,24,40,.06);\n    font-family:Roboto,system-ui,sans-serif}\n  .fld{display:flex;flex-direction:column;gap:5px;min-width:0}\n  .fld.grow{flex:1 1 260px}\n  .lbl{font:600 10px/1 'Roboto',sans-serif;letter-spacing:.6px;text-transform:uppercase;color:#6B7280}\n  .sel{appearance:none;-webkit-appearance:none;width:100%;box-sizing:border-box;height:40px;padding:0 34px 0 12px;\n    border:1px solid rgba(16,24,40,0.14);border-radius:10px;background:#FFFFFF;color:#1A1C1E;font:500 13px/1 'Roboto',sans-serif;\n    cursor:pointer;transition:border-color 150ms ease-out,box-shadow 150ms ease-out;\n    background-image:url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236B7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>\");\n    background-repeat:no-repeat;background-position:right 10px center}\n  .sel:focus{outline:none;border-color:#E5004B;box-shadow:0 0 0 3px rgba(229,0,75,.12)}\n  .sel.cycle{min-width:150px}\n  .clr{height:40px;padding:0 14px;border:1px solid rgba(16,24,40,0.14);border-radius:10px;background:#F7F8FA;color:#4A5560;\n    font:600 12px/1 'Roboto',sans-serif;cursor:pointer;transition:background 150ms ease-out}\n  .clr:hover{background:#EEF0F3}\n  .clr[disabled]{opacity:.45;cursor:default}\n  @media (max-width:640px){.ctl{flex-direction:column;align-items:stretch}.fld.grow{flex:1 1 auto}}\n  `,\n  render(d2){\n    const store = d2.store('pilotDashboardStore');\n    const groups = d2.param('groups', []) || [];\n    const cycles = d2.param('cycles', []) || [];\n    const selGroup = d2.shared.get('pilotSelectedGroup', '', { global:true });\n    const selCycle = store ? (store.get('cycle','') || '') : '';\n\n    const grpOpts = ['<option value=\"\">Todos os grupos</option>'].concat(\n      groups.map(g => {\n        const code = (g.codigoGrupo != null ? g.codigoGrupo : g.grupo);\n        const nm = g.name || g.leaderName || '';\n        const txt = code + (nm ? (' — ' + nm) : '');\n        const sel = (String(code) === String(selGroup)) ? ' selected' : '';\n        return `<option value=\"${esc(code)}\"${sel}>${esc(txt)}</option>`;\n      })\n    ).join('');\n\n    const cycOpts = (cycles.length ? cycles : [selCycle]).map(c => {\n      const code = (c && c.code != null) ? c.code : c;\n      const sel = (String(code) === String(selCycle)) ? ' selected' : '';\n      return `<option value=\"${esc(code)}\"${sel}>Ciclo ${esc(code)}</option>`;\n    }).join('');\n\n    return `<div class=\"ctl\">\n      <div class=\"fld grow\">\n        <span class=\"lbl\">Grupo</span>\n        <select class=\"sel group\">${grpOpts}</select>\n      </div>\n      <div class=\"fld\">\n        <span class=\"lbl\">Ciclo</span>\n        <select class=\"sel cycle\">${cycOpts}</select>\n      </div>\n      <button class=\"clr\" ${selGroup ? '' : 'disabled'}>Limpar</button>\n    </div>`;\n  },\n  mounted(d2){\n    d2.on('.group','change',(e,el)=>{\n      const store = d2.store('pilotDashboardStore');\n      if(store) store.set('selectedGroup', el.value || '');\n      d2.shared.set('pilotSelectedGroup', el.value || '', { global:true });\n      d2.bus.emit('filter:group', el.value || '');\n      d2.emit('onChange', { type:'group', value: el.value || '' });\n    });\n    d2.on('.cycle','change',(e,el)=>{\n      const store = d2.store('pilotDashboardStore');\n      if(store){ store.set('cycle', el.value || ''); store.set('data', null); store.set('loading', false); }\n      d2.emit('onChange', { type:'cycle', value: el.value || '' });\n    });\n    d2.on('.clr','click',()=>{\n      const store = d2.store('pilotDashboardStore');\n      if(store) store.set('selectedGroup', '');\n      d2.shared.set('pilotSelectedGroup', '', { global:true });\n      d2.bus.emit('filter:group', '');\n      d2.emit('onChange', { type:'group', value:'' });\n    });\n  }\n};"}},"store":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"store"}}}},"groups":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"groups"}}}},"cycles":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cycles"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}}}}}}}},{"_id":"6a4bbd245059efc0d0a5247e","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMSectorAccordion","package":"natura-x-piloto","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 FALLBACK = { color:{ surface:'#FFFFFF', ink:'#1A1C1E', muted:'#6B7280', hairline:'rgba(16,24,40,0.08)', rampRed:'#FF1418', rampAmber:'#FAA000', rampGreen:'#29AC56', goldIap:'#FFCF30', naturaMagenta:'#E5004B', naturaOrange:'#EB6619', money:'#29AC56' } };\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction statusColor(t, status){\n  if(status==='green') return t.color.rampGreen;\n  if(status==='amber') return t.color.rampAmber;\n  if(status==='red') return t.color.rampRed;\n  return t.color.muted;\n}\nfunction attColor(t, pct){ const p=Number(pct||0); if(p>=100) return t.color.rampGreen; if(p>=60) return t.color.rampAmber; return t.color.rampRed; }\nfunction num(n){ if(n===null||n===undefined) return '—'; try{ return Number(n).toLocaleString('pt-BR',{maximumFractionDigits:0}); }catch(e){ return String(n); } }\nfunction brl(n){ try{ return Number(n||0).toLocaleString('pt-BR',{style:'currency',currency:'BRL'}); }catch(e){ return 'R$ '+Number(n||0).toLocaleString('pt-BR',{minimumFractionDigits:2,maximumFractionDigits:2}); } }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); }\nfunction svgIcon(iconId, color){\n  const c = color || '#6B7280';\n  const w = 'width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"'+c+'\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"';\n  const P = {\n    'people': '<circle cx=\"9\" cy=\"7\" r=\"3\"/><path d=\"M2 21v-2a5 5 0 0 1 5-5h4a5 5 0 0 1 5 5v2\"/><path d=\"M17 7a3 3 0 0 1 0 6\"/><path d=\"M22 21v-2a5 5 0 0 0-3-4.5\"/>',\n    'user': '<circle cx=\"12\" cy=\"8\" r=\"3.5\"/><path d=\"M4 21v-2a5 5 0 0 1 5-5h6a5 5 0 0 1 5 5v2\"/>',\n    'target': '<circle cx=\"12\" cy=\"12\" r=\"9\"/><circle cx=\"12\" cy=\"12\" r=\"5\"/><circle cx=\"12\" cy=\"12\" r=\"1.5\" fill=\"'+c+'\"/>',\n    'crown': '<path d=\"M3 8l4 4 5-6 5 6 4-4v9H3z\"/><path d=\"M3 20h18\"/>',\n    'swap': '<path d=\"M12 4v16\"/><path d=\"M7 8l-4 4 4 4\"/><path d=\"M17 8l4 4-4 4\"/>',\n    'user-add': '<circle cx=\"9\" cy=\"8\" r=\"3.5\"/><path d=\"M2 20v-1.5a5 5 0 0 1 5-5h4\"/><path d=\"M18 12v6\"/><path d=\"M15 15h6\"/>',\n    'coins': '<circle cx=\"8\" cy=\"8\" r=\"6\"/><path d=\"M18.09 10.37A6 6 0 1 1 10.34 18\"/><path d=\"M7 6h1v4\"/><path d=\"M16.71 13.88l.7.71-2.82 2.82\"/>',\n    'brand-natura': '<path d=\"M12 3c4 3 6 6 6 9a6 6 0 0 1-12 0c0-3 2-6 6-9z\"/>',\n    'brand-avon': '<circle cx=\"12\" cy=\"12\" r=\"8\"/><path d=\"M8 14l4-7 4 7\"/>'\n  };\n  const path = P[iconId] || '<circle cx=\"12\" cy=\"12\" r=\"3\" fill=\"'+c+'\" stroke=\"none\"/>';\n  return '<svg '+w+'>'+path+'</svg>';\n}\nexport default {\n  css: `\n  :host{display:block;overflow:visible!important}\n  /* Shadow fix: the accordion's own code-component host clips at its edge; pad the shadow-root\n     content 18px on the sides + bottom so each hover-lifted line's box-shadow stays within the host. */\n  .sa{display:flex;flex-direction:column;gap:12px;padding:2px 18px 18px;box-sizing:border-box}\n  .sa-h{font:600 15px/1 'Roboto',system-ui,sans-serif;color:#1A1C1E;display:flex;align-items:center;gap:8px}\n  .sa-h::before{content:'';width:4px;height:16px;border-radius:2px;background:linear-gradient(135deg,#E5004B 0%,#EB6619 100%)}\n  .sa-list{display:flex;flex-direction:column;gap:12px}\n  .it{background:#FFFFFF;border:1px solid rgba(16,24,40,0.08);border-radius:16px;box-sizing:border-box;overflow:visible;\n    box-shadow:0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08);\n    transition:box-shadow 150ms ease-out,transform 150ms ease-out}\n  .it:hover{box-shadow:0 4px 12px rgba(16,24,40,0.10);transform:translateY(-1px)}\n  .it[data-open]{box-shadow:0 6px 18px rgba(16,24,40,0.12)}\n  .it-head{display:flex;align-items:center;gap:14px;padding:16px;cursor:pointer;position:relative;border-radius:16px;\n    transition:background 150ms ease-out}\n  .it-head:hover{background:#F7F8FA}\n  .it-ic{width:40px;height:40px;flex:none;border-radius:12px;display:flex;align-items:center;justify-content:center;\n    background:#F3F4F6}\n  .it[data-iap] .it-ic{background:rgba(255,207,48,0.22)}\n  .it-mid{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:7px}\n  .it-toprow{display:flex;align-items:flex-start;gap:8px}\n  .it-lbl{font:600 15px/1.25 'Roboto',sans-serif;color:#1A1C1E;white-space:normal;overflow-wrap:anywhere;min-width:0}\n  .it-iapchip{flex:none;display:inline-flex;align-items:center;height:19px;padding:0 8px;border-radius:999px;\n    background:#FFCF30;color:#5A4600;font:700 9.5px/1 'Roboto',sans-serif;letter-spacing:.5px}\n  .it-bonuschip{flex:none;display:inline-flex;align-items:center;gap:4px;height:20px;padding:0 10px;border-radius:999px;\n    font:700 10px/1 'Roboto',sans-serif;letter-spacing:.3px}\n  .it-bonuschip.yes{background:rgba(41,172,86,0.14);color:#1E7D3E}\n  .it-bonuschip.no{background:#F1F2F4;color:#8A929B}\n  .it-bonuschip svg{width:12px;height:12px}\n  .it-gain{flex:none;display:inline-flex;align-items:center;gap:4px;height:24px;padding:0 11px;border-radius:999px;\n    background:rgba(41,172,86,0.12);color:#1E7D3E;font:700 13px/1 'Roboto',sans-serif;letter-spacing:.2px;white-space:nowrap;\n    font-variant-numeric:tabular-nums}\n  .it-gain.zero{background:#F1F2F4;color:#8A929B}\n  .it-gain svg{width:13px;height:13px}\n  .it-right{flex:none;display:flex;align-items:center;gap:10px}\n  .it-bar{display:flex;align-items:center;gap:10px}\n  .it-track{flex:1 1 auto;height:6px;border-radius:999px;background:rgba(16,24,40,0.07);overflow:hidden}\n  .it-fill{height:100%;border-radius:999px;width:0;transition:width 500ms cubic-bezier(0.4,0,0.2,1)}\n  .it-vals{flex:none;display:flex;align-items:baseline;gap:5px;font-variant-numeric:tabular-nums}\n  .it-v{font:700 15px/1 'Roboto',sans-serif;color:#1A1C1E}\n  .it-g{font:400 12px/1 'Roboto',sans-serif;color:#9AA1A9}\n  .it-pct{flex:none;font:700 13px/1 'Roboto',sans-serif;min-width:42px;text-align:right}\n  .it-caret{width:26px;height:26px;flex:none;display:flex;align-items:center;justify-content:center;color:#6B7280;font-size:16px;\n    transition:transform 280ms cubic-bezier(0.2,0,0,1)}\n  .it[data-open] .it-caret{transform:rotate(180deg)}\n  .it-body{max-height:0;opacity:0;overflow:hidden;\n    transition:max-height 280ms cubic-bezier(0.2,0,0,1),opacity 280ms cubic-bezier(0.2,0,0,1)}\n  .it[data-open] .it-body{max-height:900px;opacity:1}\n  .it-bodyin{padding:2px 16px 16px 16px}\n  .it-dettitle{font:700 10.5px/1 'Roboto',sans-serif;color:#6B7280;letter-spacing:.6px;text-transform:uppercase;margin:6px 0 12px}\n  .it-kgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:12px}\n  @media (max-width:640px){\n    .it-head{flex-wrap:wrap;gap:10px 12px;padding:14px}\n    .it-mid{flex:1 1 calc(100% - 92px)}\n    .it-caret{order:2}\n    .it-right{order:3;flex:1 1 100%;justify-content:flex-start;flex-wrap:wrap;padding-left:52px}\n  }\n  @media (prefers-reduced-motion: reduce){.it,.it-caret,.it-body,.it-fill{transition:none}.it:hover{transform:none}\n    .it[data-open] .it-body{max-height:none}}\n  `,\n  render(d2){\n    const t = tok(d2);\n    const items = d2.param('items', []) || [];\n    const title = d2.param('sectionTitle','Indicadores do Setor');\n    const kpiCard = d2.param('kpiCard','natura-x-piloto@pilotMKpiCard');\n    const brandMark = d2.param('brandMark','natura-x-piloto@pilotMBrandMark');\n    if(!d2.state.open){\n      const initial = {};\n      const startRef = d2.param('startExpandedRef','');\n      if(startRef) initial[startRef] = true;\n      d2.state.open = initial;\n    }\n    const openMap = d2.state.open || {};\n\n    const lines = items.map((it, idx) => {\n      const ref = it.ref || ('item-'+idx);\n      const open = !!openMap[ref];\n      const main = it.main || {};\n      const isIap = it.agrupamento === 'indicador-iap';\n      const isBonus = !!it.isBonus;\n      const status = main.status || 'none';\n      const sCol = statusColor(t, status);\n      const at = main.atingimento;\n      const hasGoal = main.goal !== null && main.goal !== undefined && Number(main.goal) > 0;\n      const clamped = (at !== null && at !== undefined) ? Math.max(0, Math.min(100, Number(at))) : 0;\n\n      const iconTint = isIap ? '#8A6D00' : (sCol || t.color.muted);\n      const iconHtml = svgIcon(it.icon || main.icon || '', iconTint);\n      const iapChip = isIap ? `<span class=\"it-iapchip\">IAP</span>` : '';\n\n      // right-side: bonus → chip; else value/goal + pct\n      let rightHtml;\n      if(isBonus){\n        const will = it.willReceive === true;\n        const chk = '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>';\n        const dash = '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linecap=\"round\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"/></svg>';\n        rightHtml = will\n          ? `<span class=\"it-bonuschip yes\">${chk} Vai receber</span>`\n          : `<span class=\"it-bonuschip no\">${dash} Não atingido</span>`;\n      } else {\n        const goalHtml = hasGoal ? `<span class=\"it-g\">/ ${num(main.goal)}</span>` : '';\n        rightHtml = `<span class=\"it-vals\"><span class=\"it-v\">${num(main.value)}</span>${goalHtml}</span>`;\n      }\n\n      // R$ projected gain badge — LIDER accelerators only (indicadores carry no projectedGain)\n      const hasGain = Object.prototype.hasOwnProperty.call(it, 'projectedGain') && it.projectedGain !== null && it.projectedGain !== undefined;\n      let gainHtml = '';\n      if(hasGain){\n        const g = Number(it.projectedGain || 0);\n        if(isBonus){\n          // bonus: R$ only when it will be received, else the chip already says \"Não atingido\"\n          gainHtml = (it.willReceive === true && g > 0)\n            ? `<span class=\"it-gain\">+${brl(g)}</span>` : '';\n        } else {\n          const upSvg = '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"18 15 12 9 6 15\"/></svg>';\n          gainHtml = (g > 0)\n            ? `<span class=\"it-gain\">${upSvg} +${brl(g)}</span>`\n            : `<span class=\"it-gain zero\">R$ 0</span>`;\n        }\n      }\n      const rightGroup = `<span class=\"it-right\">${rightHtml}${gainHtml}</span>`;\n\n      // slim progress bar in collapsed line (only when the main KPI has a goal)\n      const barHtml = (hasGoal)\n        ? `<div class=\"it-bar\">\n             <div class=\"it-track\"><div class=\"it-fill\" data-fill=\"${esc(ref)}\" style=\"background:${attColor(t,at)};width:${open?clamped:clamped}%\"></div></div>\n             <span class=\"it-pct\" style=\"color:${attColor(t,at)}\">${(at!==null&&at!==undefined)?Number(at).toFixed(0)+'%':''}</span>\n           </div>`\n        : (isBonus ? '' : `<div class=\"it-bar\"><span class=\"it-pct\" style=\"color:${t.color.muted};min-width:auto\">Sem meta</span></div>`);\n\n      // DETALHES sub-cards — related KPIs, else the main itself as a single detail card\n      const detailSource = (it.related && it.related.length) ? it.related : [{\n        code: main.code, label: main.label, value: main.value, goal: main.goal, description: it.detailNote || main.label\n      }];\n      const subCards = detailSource.map((k, ki) => {\n        return d2.render(kpiCard, {\n          cardTitle: k.label,\n          value: k.value,\n          goal: k.goal,\n          description: k.description || '',\n          iap: false\n        }, { key: 'kc-'+ref+'-'+(k.code||ki)+'-'+(open?'o':'c'), style:'display:block;height:100%' });\n      }).join('');\n\n      const bodyHtml = `<div class=\"it-body\"><div class=\"it-bodyin\">\n        <div class=\"it-dettitle\">Detalhes${(it.related&&it.related.length)?'':' do indicador'}</div>\n        <div class=\"it-kgrid\">${subCards}</div>\n      </div></div>`;\n\n      return `<div class=\"it${open?' data-open':''}\" ${open?'data-open':''} ${isIap?'data-iap':''} data-key=\"line-${esc(ref)}\" data-ref=\"${esc(ref)}\">\n        <div class=\"it-head\" data-toggle=\"${esc(ref)}\">\n          <span class=\"it-ic\">${iconHtml}</span>\n          <span class=\"it-mid\">\n            <span class=\"it-toprow\"><span class=\"it-lbl\" title=\"${esc(it.label)}\">${esc(it.label)}</span>${iapChip}</span>\n            ${barHtml}\n          </span>\n          ${rightGroup}\n          <span class=\"it-caret\">⌄</span>\n        </div>\n        ${bodyHtml}\n      </div>`;\n    }).join('');\n\n    return `<div class=\"sa\">\n      <div class=\"sa-h\">${esc(title)}</div>\n      <div class=\"sa-list\">${lines}</div>\n    </div>`;\n  },\n  mounted(d2){\n    d2.on('.it-head','click',(e, el)=>{\n      const ref = el.getAttribute('data-toggle');\n      if(!ref) return;\n      const cur = Object.assign({}, d2.state.open || {});\n      cur[ref] = !cur[ref];\n      d2.state.open = cur;\n    });\n  }\n};"}},"items":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"items"}}}},"sectionTitle":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"sectionTitle"}}}},"kpiCard":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"kpiCard"}}}},"progressBar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"progressBar"}}}},"brandMark":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"brandMark"}}}},"startExpandedRef":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"startExpandedRef"}}}}}}}}}},{"_id":"6a4bfe5288f318116b8513e4","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotMLoading","package":"natura-x-piloto","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 FALLBACK = {\n  color: {\n    surface:'#FFFFFF', ground:'#FAFAFB', ink:'#1A1C1E', muted:'#6B7280',\n    hairline:'rgba(16,24,40,0.08)', naturaMagenta:'#E5004B', naturaOrange:'#EB6619',\n    brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)'\n  },\n  radius:{ sm:8, md:12, lg:16, pill:999 },\n  type:{ family:\"'Roboto',system-ui,-apple-system,sans-serif\", h2:'20px', title:'15px', body:'13px', caption:'11px' },\n  shadow:{ card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)' }\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\n// ease-out (fast start, slowing) mapping normalized time [0..1] -> progress fraction toward the 0.9 ceiling\nfunction eased(frac){ const e = 1 - Math.pow(1 - Math.min(1, Math.max(0, frac)), 3); return e * 0.9; }\n// Asymptotic micro-creep past the 90% cap: given seconds spent past the cap, inch 90 -> ~97 (never reaching it).\n// 1 - e^(-t/tau) approaches 1 slowly; scaled into the 90..97 band. At t=6s ~ +4.3, t=15s ~ +6.2, never hits 97.\nfunction creep(secPastCap){ const CAP = 90, CEIL = 97, tau = 8; return CAP + (CEIL - CAP) * (1 - Math.exp(-Math.max(0, secPastCap) / tau)); }\nexport default {\n  css: `\n  :host{display:block}\n  .ld{display:flex;flex-direction:column;min-height:100%;height:auto;background:var(--ground,#FAFAFB);font-family:'Roboto',system-ui,sans-serif;opacity:1;transition:opacity 360ms ease-out}\n  .ld[data-fading]{opacity:0}\n  .ld-body{display:flex;flex-direction:column;gap:24px;padding:24px 20px 48px;box-sizing:border-box;max-width:1264px;width:100%;margin:0 auto}\n  /* progress banner */\n  .pgwrap{display:flex;flex-direction:column;gap:10px;background:var(--surface,#FFF);border:1px solid var(--hair,rgba(16,24,40,0.08));border-radius:16px;padding:18px 18px 20px;box-shadow:0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)}\n  .pgtop{display:flex;align-items:baseline;justify-content:space-between;gap:12px}\n  .pglabel{font:700 15px/1.2 'Roboto',system-ui,sans-serif;color:var(--ink,#1A1C1E)}\n  .pgpct{font:800 15px/1 'Roboto',system-ui,sans-serif;color:var(--mag,#E5004B);font-variant-numeric:tabular-nums;letter-spacing:.3px}\n  .pgtrack{height:9px;border-radius:999px;background:rgba(16,24,40,0.07);overflow:hidden;position:relative}\n  .pgfill{height:100%;border-radius:999px;width:0%;background:var(--grad,linear-gradient(135deg,#E5004B 0%,#EB6619 100%));box-shadow:0 1px 4px rgba(229,0,75,0.35);position:relative;overflow:hidden;transition:width 120ms linear}\n  .pgfill::after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,0.45) 50%,transparent 100%);transform:translateX(-100%);animation:pgsheen 1400ms ease-in-out infinite}\n  /* indeterminate travelling stripe over the fill — kept alive while we sit near the cap so the bar never reads as frozen */\n  .pgfill[data-cap]::before{content:'';position:absolute;top:0;bottom:0;width:38%;left:0;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,0.55) 50%,transparent 100%);transform:translateX(-120%);animation:pgindet 1150ms cubic-bezier(.4,0,.2,1) infinite;pointer-events:none}\n  /* while finishing (visible fill-to-100), speed the width tween up a touch for a satisfying snap-to-complete */\n  .pgfill[data-finish]{transition:width 350ms cubic-bezier(.22,.61,.36,1)}\n  .pgdetail{font:600 11px/1.3 'Roboto',system-ui,sans-serif;letter-spacing:.4px;text-transform:uppercase;color:var(--muted,#6B7280);min-height:14px}\n  /* reassuring secondary line that appears after a few seconds of waiting */\n  .pgsub{font:500 11px/1.3 'Roboto',system-ui,sans-serif;color:var(--muted,#6B7280);opacity:0;transform:translateY(-2px);transition:opacity 320ms ease-out,transform 320ms ease-out;min-height:0;overflow:hidden}\n  .pgsub[data-on]{opacity:.85;transform:translateY(0)}\n  /* skeleton */\n  .skhead{display:flex;flex-direction:column;gap:12px;background:var(--surface,#FFF);border:1px solid var(--hair,rgba(16,24,40,0.08));border-radius:16px;padding:18px;box-shadow:0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)}\n  .skhead-top{display:flex;align-items:center;gap:14px}\n  .skgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:18px}\n  .skcard{background:var(--surface,#FFF);border:1px solid var(--hair,rgba(16,24,40,0.08));border-radius:16px;padding:18px;box-shadow:0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08);display:flex;flex-direction:column;gap:14px;min-height:150px}\n  .skcard-top{display:flex;align-items:center;gap:12px}\n  .sk{position:relative;overflow:hidden;background:#EDEFF3;border-radius:8px}\n  .sk::after{content:'';position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,0.65) 50%,transparent 100%);animation:skshimmer 1500ms ease-in-out infinite}\n  .sk-circle{border-radius:999px}\n  @keyframes skshimmer{100%{transform:translateX(100%)}}\n  @keyframes pgsheen{100%{transform:translateX(100%)}}\n  @keyframes pgindet{0%{transform:translateX(-120%)}100%{transform:translateX(360%)}}\n  @media (prefers-reduced-motion: reduce){\n    .sk::after,.pgfill::after,.pgfill[data-cap]::before{animation:none;display:none}\n    .pgfill,.pgfill[data-finish],.pgsub{transition:none}\n    .ld{transition:none}\n  }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const label = d2.param('label','Carregando painel');\n    const detail = d2.param('detail','');\n    const n = Math.max(3, Math.min(8, Number(d2.param('cardCount', 6)) || 6));\n    const vars = `--ground:${t.color.ground};--surface:${t.color.surface};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient}`;\n    const cards = [];\n    for(let i=0;i<n;i++){\n      cards.push(`<div class=\"skcard\" data-key=\"skc-${i}\">\n        <div class=\"skcard-top\">\n          <div class=\"sk sk-circle\" style=\"width:34px;height:34px\"></div>\n          <div style=\"display:flex;flex-direction:column;gap:7px;flex:1\">\n            <div class=\"sk\" style=\"height:12px;width:58%\"></div>\n            <div class=\"sk\" style=\"height:9px;width:34%\"></div>\n          </div>\n        </div>\n        <div class=\"sk\" style=\"height:9px;width:100%\"></div>\n        <div class=\"sk\" style=\"height:9px;width:82%\"></div>\n        <div class=\"sk\" style=\"height:9px;width:66%\"></div>\n        <div class=\"sk\" style=\"height:7px;width:100%;border-radius:999px;margin-top:auto\"></div>\n      </div>`);\n    }\n    return `<div class=\"ld\" data-root style=\"${vars}\">\n      <div class=\"ld-body\">\n        <div class=\"pgwrap\">\n          <div class=\"pgtop\">\n            <span class=\"pglabel\">${String(label).replace(/</g,'&lt;')}…</span>\n            <span class=\"pgpct\" data-pct>0%</span>\n          </div>\n          <div class=\"pgtrack\"><div class=\"pgfill\" data-fill style=\"width:0%\"></div></div>\n          <div class=\"pgdetail\" data-detail>${String(detail).replace(/</g,'&lt;')}</div>\n          <div class=\"pgsub\" data-sub></div>\n        </div>\n        <div class=\"skhead\">\n          <div class=\"skhead-top\">\n            <div class=\"sk sk-circle\" style=\"width:48px;height:48px\"></div>\n            <div style=\"display:flex;flex-direction:column;gap:9px;flex:1\">\n              <div class=\"sk\" style=\"height:15px;width:42%\"></div>\n              <div class=\"sk\" style=\"height:11px;width:26%\"></div>\n            </div>\n            <div class=\"sk\" style=\"height:34px;width:120px;border-radius:999px\"></div>\n          </div>\n        </div>\n        <div class=\"skgrid\" data-key=\"skgrid\">${cards.join('')}</div>\n      </div>\n    </div>`;\n  },\n  mounted(d2, root){\n    const start = (typeof performance!=='undefined' ? performance.now() : Date.now());\n    const estimate = Math.max(3000, Number(d2.param('estimateMs', 18000)) || 18000);\n    const fillEl = root.querySelector('[data-fill]');\n    const pctEl = root.querySelector('[data-pct]');\n    const detEl = root.querySelector('[data-detail]');\n    const subEl = root.querySelector('[data-sub]');\n    const rootEl = root.querySelector('[data-root]');\n    const reduce = (typeof window!=='undefined' && window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches);\n    let shown = 0;        // 0..100, monotonic\n    let fading = false;\n    let finishing = false;\n    let capActive = false;   // whether the indeterminate stripe / creep phase is engaged\n    let subLevel = 0;        // 0 none, 1 \"consolidando\", 2 \"quase lá\"\n    const paint = (p) => {\n      const v = Math.max(0, Math.min(100, p));\n      if(v > shown) shown = v;             // never go backwards\n      if(fillEl) fillEl.style.width = shown.toFixed(1) + '%';\n      if(pctEl) pctEl.textContent = Math.round(shown) + '%';\n    };\n    // Engage the \"alive at the cap\" treatment: travelling indeterminate stripe (skipped under reduced motion).\n    const setCap = (on) => {\n      if(on === capActive) return;\n      capActive = on;\n      if(fillEl){ if(on && !reduce) fillEl.setAttribute('data-cap',''); else fillEl.removeAttribute('data-cap'); }\n    };\n    // Reassuring secondary line — appears after a few seconds, escalates once more further in.\n    const setSub = (level) => {\n      if(level === subLevel || !subEl) return;\n      subLevel = level;\n      if(level === 0){ subEl.removeAttribute('data-on'); return; }\n      subEl.textContent = level >= 2 ? 'Quase lá…' : 'Consolidando dados do setor…';\n      subEl.setAttribute('data-on','');\n    };\n    const done = () => {\n      const p = d2.param('progress', null);\n      return d2.param('done', false) === true || (typeof p === 'number' && p >= 1);\n    };\n    // Real-progress override (stretch): if a numeric `progress` (0..1) is supplied,\n    // follow it instead of the eased estimate. Never regresses (paint clamps).\n    d2.raf(() => {\n      // refresh detail text live (real \"X de N\" if the shell supplies it)\n      if(detEl){ const d = d2.param('detail',''); if(d !== detEl.textContent) detEl.textContent = String(d); }\n      if(done()){\n        if(!finishing){\n          finishing = true;\n          setCap(false);                              // drop the indeterminate stripe; this is a determinate finish now\n          if(reduce){\n            // reduced motion: jump straight to 100 and skip the fade entirely\n            paint(100);\n            d2.emit('onDone');\n          } else {\n            // VISIBLE completion: tween current -> 100 over ~350ms, hold ~150ms, then fade ~300ms.\n            if(fillEl) fillEl.setAttribute('data-finish','');   // engages the 350ms width transition\n            shown = 100;\n            if(fillEl) fillEl.style.width = '100%';\n            if(pctEl) pctEl.textContent = '100%';\n            setSub(0);\n            fading = true;\n            setTimeout(() => { if(rootEl) rootEl.setAttribute('data-fading',''); }, 500);   // 350 fill + 150 hold\n            setTimeout(() => { d2.emit('onDone'); }, 800);                                   // + ~300ms fade\n          }\n        }\n        return false;    // stop the loop once completion has been kicked off\n      }\n      const now = (typeof performance!=='undefined' ? performance.now() : Date.now());\n      const elapsed = now - start;\n      const pOverride = d2.param('progress', null);\n      let target;\n      if(typeof pOverride === 'number'){\n        target = Math.min(90, pOverride * 100);       // hold below the cap until `done`\n      } else {\n        target = eased(elapsed / estimate) * 100;\n      }\n      // Once the eased fill has reached the ~90% ceiling and we're still waiting, keep the bar alive:\n      //  - engage the travelling indeterminate stripe, and\n      //  - apply a slow asymptotic micro-creep 90 -> ~97 so the numbers keep inching (never hits 100).\n      if(target >= 89.5){\n        setCap(true);\n        const secPastCap = Math.max(0, (elapsed - estimate) / 1000);\n        target = Math.max(target, creep(secPastCap));\n      }\n      paint(target);\n      // reassuring sub-label: appears after ~7s still loading, escalates after ~14s\n      if(elapsed >= 14000) setSub(2);\n      else if(elapsed >= 7000) setSub(1);\n    });\n  }\n};"}},"done":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"done"}}}},"estimateMs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"estimateMs"}}}},"label":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"label"}}}},"detail":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"detail"}}}},"progress":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"progress"}}}},"cardCount":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cardCount"}}}}}}}}}},{"_id":"6a4c0ae108850cd753f0647a","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotAdmCard","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',gold:'#F7BE00',money:'#29AC56'},\n  radius:{sm:8,md:12,lg:16,pill:999},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\",h2:'20px',title:'15px',body:'13px',caption:'11px'},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\n\n// Lucide (ISC) — paths inline, sem lib\nconst LUCIDE = {\n  'brand-natura':'<path d=\"M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 4.18 2 8 0 5.5-4.78 10-10 10Z\"/><path d=\"M2 21c0-3 1.85-5.36 5.08-6C9.5 14.52 12 13 13 12\"/>',\n  'brand-avon':'<path d=\"M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5C6 11.1 5 13 5 15a7 7 0 0 0 7 7z\"/>',\n  'people':'<path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><path d=\"M22 21v-2a4 4 0 0 0-3-3.87\"/><path d=\"M16 3.13a4 4 0 0 1 0 7.75\"/>',\n  'target':'<circle cx=\"12\" cy=\"12\" r=\"10\"/><circle cx=\"12\" cy=\"12\" r=\"6\"/><circle cx=\"12\" cy=\"12\" r=\"2\"/>',\n  'crown':'<path d=\"M11.562 3.266a.5.5 0 0 1 .876 0L15.39 8.87a1 1 0 0 0 1.516.294L21.183 5.5a.5.5 0 0 1 .798.519l-2.834 10.246a1 1 0 0 1-.956.734H5.81a1 1 0 0 1-.957-.734L2.02 6.02a.5.5 0 0 1 .798-.519l4.276 3.664a1 1 0 0 0 1.516-.294z\"/><path d=\"M5 21h14\"/>',\n  'swap':'<path d=\"M8 3 4 7l4 4\"/><path d=\"M4 7h16\"/><path d=\"m16 21 4-4-4-4\"/><path d=\"M20 17H4\"/>',\n  'user-add':'<path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><line x1=\"19\" x2=\"19\" y1=\"8\" y2=\"14\"/><line x1=\"22\" x2=\"16\" y1=\"11\" y2=\"11\"/>',\n  'coins':'<circle cx=\"8\" cy=\"8\" r=\"6\"/><path d=\"M18.09 10.37A6 6 0 1 1 10.34 18\"/><path d=\"M7 6h1v4\"/><path d=\"m16.71 13.88.7.71-2.82 2.82\"/>',\n  'user':'<path d=\"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\"/><circle cx=\"12\" cy=\"7\" r=\"4\"/>',\n  'chart':'<path d=\"M3 3v18h18\"/><path d=\"M18 17V9\"/><path d=\"M13 17V5\"/><path d=\"M8 17v-3\"/>'\n};\nfunction lucide(name){ return `<svg class=\"lu\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${LUCIDE[name]||LUCIDE.chart}</svg>`; }\nconst ICON = (()=>{\n  const S = (p)=>`<svg class=\"ic-svg\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${p}</svg>`;\n  return {\n    edit:S('<path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/>'),\n    dup:S('<rect x=\"9\" y=\"9\" width=\"11\" height=\"11\" rx=\"2\"/><path d=\"M5 15V5a2 2 0 0 1 2-2h8\"/>'),\n    del:S('<path d=\"M3 6h18\"/><path d=\"M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/>'),\n    grip:S('<circle cx=\"9\" cy=\"6\" r=\"1.3\"/><circle cx=\"15\" cy=\"6\" r=\"1.3\"/><circle cx=\"9\" cy=\"12\" r=\"1.3\"/><circle cx=\"15\" cy=\"12\" r=\"1.3\"/><circle cx=\"9\" cy=\"18\" r=\"1.3\"/><circle cx=\"15\" cy=\"18\" r=\"1.3\"/>')\n  };\n})();\nconst AGRUP_LABEL = { 'ranking-stat':'Ranking', 'acelerador':'Acelerador', 'indicador-iap':'IAP' };\nconst PERFIL_LABEL = { gn:'GN', lider:'Líder', gv:'GV', all:'Todos' };\nconst REDE_LABEL = { rede1:'Rede 1', rede2:'Rede 2', both:'Ambas' };\nfunction sectionLabel(s){\n  const m = {'leader-card':'Cartão Líder','sector':'Setor','sector-kpi':'KPI Setor','leader':'Líder','kpis':'KPIs','totalizador':'Totalizador'};\n  return m[s] || (s||'—');\n}\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n  :host{display:block}\n  .pad{padding:9px;box-sizing:border-box;height:100%}\n  .card{position:relative;background:var(--surface);border:1px solid var(--hair);border-radius:var(--rlg);\n        padding:14px 16px;box-sizing:border-box;box-shadow:var(--sh);display:flex;gap:12px;align-items:flex-start;\n        transition:box-shadow .15s ease-out, transform .15s ease-out;overflow:hidden}\n  .card:hover{box-shadow:var(--shr);transform:translateY(-1px)}\n  .card.drag{box-shadow:var(--shr);transform:scale(1.015)}\n  .card.off{opacity:.55}\n  .card::before{content:'';position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--accent);border-radius:4px 0 0 4px}\n  .handle{flex:0 0 auto;display:flex;align-items:center;justify-content:center;width:26px;height:34px;margin-top:2px;\n          color:var(--muted);cursor:grab;border-radius:8px;font-size:16px;line-height:1;user-select:none;touch-action:none;\n          transition:background .15s}\n  .handle:hover{background:var(--ground);color:var(--ink)}\n  .glyph{flex:0 0 auto;width:40px;height:40px;border-radius:12px;display:flex;align-items:center;justify-content:center;\n         background:var(--ground);color:var(--accent)}\n  .glyph .lu{width:20px;height:20px;display:block}\n  .body{flex:1 1 auto;min-width:0}\n  .top{display:flex;align-items:center;gap:8px}\n  .label{font:600 15px/1.25 var(--fam);color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .order{flex:0 0 auto;font:700 11px/1 var(--fam);color:var(--muted);background:var(--ground);border-radius:999px;padding:4px 8px}\n  .chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}\n  .chip{font:600 11px/1 var(--fam);padding:5px 9px;border-radius:999px;background:var(--ground);color:var(--muted);white-space:nowrap}\n  .chip.p{background:rgba(229,0,75,.10);color:var(--mag)}\n  .kpi{margin-top:9px;font:500 12px/1.3 var(--fam);color:var(--muted)}\n  .kpi b{color:var(--ink);font-weight:600}\n  .tag{display:inline-flex;align-items:center;gap:4px;margin-top:9px;font:700 10px/1 var(--fam);letter-spacing:.04em;\n       text-transform:uppercase;padding:5px 8px;border-radius:999px}\n  .tag.iap{background:rgba(247,190,0,.16);color:#9a7400}\n  .actions{flex:0 0 auto;display:flex;align-items:center;gap:4px;opacity:0;transition:opacity .15s}\n  .card:hover .actions{opacity:1}\n  .act{width:30px;height:30px;border:none;border-radius:9px;background:var(--ground);color:var(--muted);cursor:pointer;\n       font-size:13px;display:flex;align-items:center;justify-content:center;transition:background .15s,color .15s}\n  .act:hover{background:rgba(229,0,75,.10);color:var(--mag)}\n  .ic-svg{display:block;flex:0 0 auto}\n  .handle .ic-svg{width:18px;height:18px}\n  .act .ic-svg{width:16px;height:16px}\n  .act.del:hover{background:rgba(229,0,75,.14);color:var(--mag)}\n  .act.del.confirm{width:auto;padding:0 10px;background:var(--mag);color:#fff;font:700 11px/1 var(--fam);animation:cfpop .18s ease-out}\n  @keyframes cfpop{from{transform:scale(.8);opacity:.5}to{transform:scale(1);opacity:1}}\n  .toggle{flex:0 0 auto;width:38px;height:22px;border-radius:999px;background:#D1D5DB;position:relative;cursor:pointer;\n          transition:background .18s;border:none;padding:0}\n  .toggle.on{background:var(--green)}\n  .toggle i{position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:#fff;transition:transform .18s;\n            box-shadow:0 1px 2px rgba(0,0,0,.2)}\n  .toggle.on i{transform:translateX(16px)}\n  @media (prefers-reduced-motion: reduce){\n    .card,.card:hover,.act,.toggle,.toggle i,.handle,.actions{transition:none!important}\n    .card:hover{transform:none}\n  }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const it = d2.param('item', {}) || {};\n    const dragging = !!d2.param('dragging', false);\n    const kpiName = d2.param('kpiName','');\n    const accent = it.isBonus ? t.color.gold : t.color.naturaMagenta;\n    const glyph = lucide(it.icon);\n    const visible = it.visible !== false;\n    const mainLine = it.mainKpiCode ? `KPI principal · <b>${esc(kpiName || it.mainKpiCode)}</b>` : 'Sem KPI principal';\n    const rel = Array.isArray(it.relatedKpiCodes) ? it.relatedKpiCodes.length : 0;\n    return `\n    <div class=\"pad\" style=\"\n      --surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};\n      --hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--green:${t.color.money||'#29AC56'};\n      --rlg:${t.radius.lg}px;--fam:${t.type.family};--sh:${t.shadow.card};--shr:${t.shadow.raised||t.shadow.card};\n      --accent:${accent}\">\n      <div class=\"card ${dragging?'drag':''} ${visible?'':'off'}\" data-card-body>\n        <div class=\"handle\" data-handle title=\"Arraste para reordenar\">${ICON.grip}</div>\n        <div class=\"glyph\">${glyph}</div>\n        <div class=\"body\">\n          <div class=\"top\">\n            <span class=\"label\" title=\"${esc(it.label)}\">${esc(it.label||'(sem título)')}</span>\n            <span class=\"order\">#${esc(it.displayOrder!=null?it.displayOrder:'—')}</span>\n          </div>\n          <div class=\"chips\">\n            <span class=\"chip p\">${esc(PERFIL_LABEL[it.perfil]||it.perfil||'—')}</span>\n            <span class=\"chip\">${esc(REDE_LABEL[it.rede]||it.rede||'—')}</span>\n            <span class=\"chip\">${esc(sectionLabel(it.section))}</span>\n            <span class=\"chip\">${esc(AGRUP_LABEL[it.agrupamento]||it.agrupamento||'—')}</span>\n          </div>\n          <div class=\"kpi\">${mainLine}${rel?` · <b>${rel}</b> relacionado${rel>1?'s':''}`:''}</div>\n          ${it.isBonus?`<span class=\"tag iap\">★ IAP / Bônus</span>`:''}\n        </div>\n        <div class=\"actions\">\n          <button class=\"act\" data-edit title=\"Editar\">${ICON.edit}</button>\n          <button class=\"act\" data-dup title=\"Duplicar\">${ICON.dup}</button>\n          ${d2.state.confirmDel\n            ? `<button class=\"act del confirm\" data-delyes title=\"Confirmar exclusão\">Excluir?</button>`\n            : `<button class=\"act del\" data-del title=\"Excluir\">${ICON.del}</button>`}\n        </div>\n        <button class=\"toggle ${visible?'on':''}\" data-toggle title=\"${visible?'Visível':'Oculto'}\" aria-label=\"visível\"><i></i></button>\n      </div>\n    </div>`;\n  },\n  mounted(d2){\n    // Child→parent via the app-scoped bus (opts/param callbacks proved unreliable\n    // across the nested shadow roots here). The card carries its own item.\n    const it = ()=> d2.param('item', {}) || {};\n    d2.on('[data-edit]','click',(e)=>{ e.stopPropagation(); d2.bus.emit('adm:edit', it()); });\n    d2.on('[data-dup]','click',(e)=>{ e.stopPropagation(); d2.bus.emit('adm:dup', it()); });\n    d2.on('[data-del]','click',(e)=>{ e.stopPropagation(); d2.setState({ confirmDel:true }); });\n    d2.on('[data-delyes]','click',(e)=>{ e.stopPropagation(); d2.setState({ confirmDel:false }); d2.bus.emit('adm:del', it()); });\n    d2.on('[data-toggle]','click',(e)=>{ e.stopPropagation(); d2.bus.emit('adm:toggle', it()); });\n    // reset the inline confirm when the pointer leaves the card\n    d2.on(d2.root,'mouseleave',()=>{ if(d2.state.confirmDel) d2.setState({ confirmDel:false }); });\n  }\n};\n"}},"item":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"item"}}}},"kpiName":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"kpiName"}}}},"dragging":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"dragging"}}}}}}}}}},{"_id":"6a4c0b3ccafa01f91f62aa68","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotAdmForm","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',gold:'#F7BE00',money:'#29AC56'},\n  radius:{sm:8,md:12,lg:16,pill:999},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\",h2:'20px',title:'15px',body:'13px',caption:'11px'},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\n\nconst ENUMS = {\n  agrupamento:[['ranking-stat','Ranking'],['acelerador','Acelerador'],['indicador-iap','Indicador IAP']],\n  section:[['leader-card','Cartão Líder'],['sector','Setor'],['sector-kpi','KPI de Setor']],\n  rede:[['rede1','Rede 1'],['rede2','Rede 2'],['both','Ambas']],\n  perfil:[['gn','GN'],['lider','Líder'],['gv','GV'],['all','Todos']],\n  icon:[['brand-natura','Natura'],['brand-avon','Avon'],['people','Pessoas'],['target','Alvo'],['crown','Coroa'],['swap','Troca'],['user-add','Novo'],['coins','Moedas'],['user','Usuário']]\n};\n// Lucide (ISC) — paths inline, sem lib\nconst LUCIDE = {\n  'brand-natura':'<path d=\"M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 4.18 2 8 0 5.5-4.78 10-10 10Z\"/><path d=\"M2 21c0-3 1.85-5.36 5.08-6C9.5 14.52 12 13 13 12\"/>',\n  'brand-avon':'<path d=\"M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5C6 11.1 5 13 5 15a7 7 0 0 0 7 7z\"/>',\n  'people':'<path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><path d=\"M22 21v-2a4 4 0 0 0-3-3.87\"/><path d=\"M16 3.13a4 4 0 0 1 0 7.75\"/>',\n  'target':'<circle cx=\"12\" cy=\"12\" r=\"10\"/><circle cx=\"12\" cy=\"12\" r=\"6\"/><circle cx=\"12\" cy=\"12\" r=\"2\"/>',\n  'crown':'<path d=\"M11.562 3.266a.5.5 0 0 1 .876 0L15.39 8.87a1 1 0 0 0 1.516.294L21.183 5.5a.5.5 0 0 1 .798.519l-2.834 10.246a1 1 0 0 1-.956.734H5.81a1 1 0 0 1-.957-.734L2.02 6.02a.5.5 0 0 1 .798-.519l4.276 3.664a1 1 0 0 0 1.516-.294z\"/><path d=\"M5 21h14\"/>',\n  'swap':'<path d=\"M8 3 4 7l4 4\"/><path d=\"M4 7h16\"/><path d=\"m16 21 4-4-4-4\"/><path d=\"M20 17H4\"/>',\n  'user-add':'<path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><line x1=\"19\" x2=\"19\" y1=\"8\" y2=\"14\"/><line x1=\"22\" x2=\"16\" y1=\"11\" y2=\"11\"/>',\n  'coins':'<circle cx=\"8\" cy=\"8\" r=\"6\"/><path d=\"M18.09 10.37A6 6 0 1 1 10.34 18\"/><path d=\"M7 6h1v4\"/><path d=\"m16.71 13.88.7.71-2.82 2.82\"/>',\n  'user':'<path d=\"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\"/><circle cx=\"12\" cy=\"7\" r=\"4\"/>',\n  'plus':'<path d=\"M5 12h14\"/><path d=\"M12 5v14\"/>',\n  'pencil':'<path d=\"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\"/><path d=\"m15 5 4 4\"/>'\n};\nfunction lucide(name){ return LUCIDE[name] ? `<svg class=\"lu\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${LUCIDE[name]}</svg>` : ''; }\nfunction enumLabel(field,val){ const e=(ENUMS[field]||[]).find(x=>x[0]===val); return e?e[1]:(val||'Selecione…'); }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nfunction emptyItem(){\n  return { ref:'', label:'', icon:'people', agrupamento:'ranking-stat', section:'sector', perfil:'gn', rede:'rede1',\n           mainKpiCode:'', relatedKpiCodes:[], isBonus:false, visible:true, displayOrder:1 };\n}\nfunction kpiName(list,code){ const k=(list||[]).find(x=>String(x.code)===String(code)); return k?k.name:code; }\n\nexport default {\n  css: `\n  :host{display:block}\n  .scrim{position:fixed;inset:0;z-index:9000;display:flex;align-items:flex-start;justify-content:center;\n         background:rgba(16,24,40,.44);backdrop-filter:blur(2px);opacity:0;transition:opacity .22s ease-out;\n         overflow-y:auto;padding:40px 16px}\n  .scrim.in{opacity:1}\n  .modal{width:100%;max-width:560px;background:var(--surface);border-radius:20px;box-shadow:0 24px 64px rgba(16,24,40,.28);\n         transform:scale(.94) translateY(8px);opacity:0;transition:transform .24s cubic-bezier(.2,0,0,1),opacity .24s ease-out;\n         overflow:hidden;margin:auto 0}\n  .scrim.in .modal{transform:scale(1) translateY(0);opacity:1}\n  .head{padding:20px 22px 14px;display:flex;align-items:center;gap:12px;border-bottom:1px solid var(--hair)}\n  .head .hg{width:40px;height:40px;border-radius:12px;background:var(--grad);display:flex;align-items:center;justify-content:center;font-size:20px}\n  .head h3{margin:0;font:700 20px/1.1 var(--fam);color:var(--ink)}\n  .head p{margin:2px 0 0;font:400 12px/1.2 var(--fam);color:var(--muted)}\n  .x{margin-left:auto;width:34px;height:34px;border:none;border-radius:10px;background:var(--ground);color:var(--muted);\n     font-size:16px;cursor:pointer;transition:background .15s}\n  .x:hover{background:rgba(229,0,75,.10);color:var(--mag)}\n  .form{padding:18px 22px 8px;max-height:60vh;overflow-y:auto}\n  .row{display:flex;gap:12px}\n  .row>.field{flex:1 1 0;min-width:0}\n  .field{margin-bottom:15px}\n  label{display:block;font:600 12px/1 var(--fam);color:var(--ink);margin-bottom:7px}\n  input[type=text],input[type=number]{width:100%;box-sizing:border-box;padding:11px 12px;border:1.5px solid var(--hair);\n    border-radius:11px;font:400 14px/1.2 var(--fam);color:var(--ink);background:var(--surface);outline:none;transition:border-color .15s}\n  input:focus{border-color:var(--mag)}\n  .sel{position:relative}\n  .sel .trigger{width:100%;box-sizing:border-box;padding:11px 12px;border:1.5px solid var(--hair);border-radius:11px;\n    font:500 14px/1.2 var(--fam);color:var(--ink);background:var(--surface);cursor:pointer;display:flex;align-items:center;\n    justify-content:space-between;gap:8px;text-align:left}\n  .sel .trigger:hover{border-color:var(--muted)}\n  .sel .trigger .cv{color:var(--muted);transition:transform .18s}\n  .sel.open .trigger{border-color:var(--mag)}\n  .sel.open .trigger .cv{transform:rotate(180deg)}\n  .menu{position:absolute;left:0;right:0;top:calc(100% + 6px);z-index:20;background:var(--surface);border:1px solid var(--hair);\n    border-radius:12px;box-shadow:0 12px 32px rgba(16,24,40,.16);padding:5px;max-height:230px;overflow-y:auto;\n    transform-origin:top;transform:scaleY(.6);opacity:0;pointer-events:none;transition:transform .16s cubic-bezier(.2,0,0,1),opacity .16s}\n  .sel.open .menu{transform:scaleY(1);opacity:1;pointer-events:auto}\n  .opt{padding:9px 11px;border-radius:8px;font:500 13px/1.2 var(--fam);color:var(--ink);cursor:pointer;transition:background .12s}\n  .opt:hover{background:var(--ground)}\n  .opt,.lbl{display:flex;align-items:center;gap:8px}\n  .opt .lu,.lbl .lu{width:16px;height:16px;flex:0 0 auto;color:var(--mag)}\n  .head .hg{color:#fff}\n  .head .hg .lu{width:20px;height:20px}\n  .opt.on{background:rgba(229,0,75,.10);color:var(--mag);font-weight:600}\n  .search{width:100%;box-sizing:border-box;padding:8px 10px;border:1px solid var(--hair);border-radius:8px;margin-bottom:5px;\n    font:400 13px/1.2 var(--fam);outline:none}\n  .search:focus{border-color:var(--mag)}\n  .chips{display:flex;flex-wrap:wrap;gap:7px;padding:10px;border:1.5px dashed var(--hair);border-radius:11px;min-height:20px}\n  .chip{display:inline-flex;align-items:center;gap:6px;font:600 12px/1 var(--fam);padding:6px 8px 6px 10px;border-radius:999px;\n    background:rgba(229,0,75,.10);color:var(--mag);animation:pop .2s cubic-bezier(.2,0,0,1)}\n  .chip button{border:none;background:none;color:var(--mag);cursor:pointer;font-size:13px;line-height:1;padding:0;opacity:.7}\n  .chip button:hover{opacity:1}\n  .chip.empty{background:none;color:var(--muted);font-weight:400;animation:none}\n  @keyframes pop{from{transform:scale(.6);opacity:0}to{transform:scale(1);opacity:1}}\n  .toggles{display:flex;gap:22px;margin-bottom:8px}\n  .tg{display:flex;align-items:center;gap:9px;cursor:pointer}\n  .tg .sw{width:40px;height:23px;border-radius:999px;background:#D1D5DB;position:relative;transition:background .18s;flex:0 0 auto}\n  .tg .sw.on{background:var(--green)}\n  .tg .sw i{position:absolute;top:2px;left:2px;width:19px;height:19px;border-radius:50%;background:#fff;transition:transform .18s;box-shadow:0 1px 2px rgba(0,0,0,.2)}\n  .tg .sw.on i{transform:translateX(17px)}\n  .tg span{font:600 13px/1 var(--fam);color:var(--ink)}\n  .foot{padding:14px 22px 20px;display:flex;gap:10px;justify-content:flex-end;border-top:1px solid var(--hair)}\n  .btn{padding:11px 20px;border-radius:11px;font:600 14px/1 var(--fam);cursor:pointer;border:none;transition:filter .15s,background .15s}\n  .btn.ghost{background:var(--ground);color:var(--ink)}\n  .btn.ghost:hover{background:var(--hair)}\n  .btn.primary{background:var(--grad);color:#fff;box-shadow:0 6px 16px rgba(229,0,75,.30)}\n  .btn.primary:hover{filter:brightness(1.05)}\n  .btn.primary:disabled{opacity:.5;cursor:not-allowed;box-shadow:none;filter:none}\n  @media (prefers-reduced-motion: reduce){\n    .scrim,.modal,.menu,.sel .trigger .cv,.chip,.tg .sw,.tg .sw i{transition:none!important;animation:none!important}\n    .modal{transform:none}\n  }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const list = d2.param('kpiList', []) || [];\n    const dr = d2.state.draft || {};\n    const isNew = !dr._id;\n    const open = d2.state.openSel || null;\n    const kq = (d2.state.kpiQuery||'').toLowerCase();\n    const rel = Array.isArray(dr.relatedKpiCodes) ? dr.relatedKpiCodes : [];\n    const canSave = !!(dr.label && dr.label.trim());\n    // dedupe kpi list by code for pickers\n    const seen = {}; const kpis = [];\n    for(const k of list){ if(!seen[k.code]){ seen[k.code]=1; kpis.push(k); } }\n    const filtered = kq ? kpis.filter(k=>String(k.name).toLowerCase().includes(kq)||String(k.code).includes(kq)) : kpis;\n\n    const selField = (field,current)=>`\n      <div class=\"sel ${open===field?'open':''}\" data-sel=\"${field}\">\n        <button type=\"button\" class=\"trigger\" data-trigger=\"${field}\">\n          <span class=\"lbl\">${field==='icon'?lucide(current):''}${esc(enumLabel(field,current))}</span><span class=\"cv\">▾</span>\n        </button>\n        <div class=\"menu\">\n          ${(ENUMS[field]||[]).map(([v,l])=>`<div class=\"opt ${v===current?'on':''}\" data-pick=\"${field}\" data-val=\"${esc(v)}\">${field==='icon'?lucide(v):''}${esc(l)}</div>`).join('')}\n        </div>\n      </div>`;\n\n    const mainPicker = `\n      <div class=\"sel ${open==='mainKpi'?'open':''}\" data-sel=\"mainKpi\">\n        <button type=\"button\" class=\"trigger\" data-trigger=\"mainKpi\">\n          <span>${dr.mainKpiCode?esc(kpiName(kpis,dr.mainKpiCode)+' ('+dr.mainKpiCode+')'):'Selecione o KPI principal…'}</span><span class=\"cv\">▾</span>\n        </button>\n        <div class=\"menu\">\n          <input class=\"search\" data-kpisearch placeholder=\"Buscar KPI…\" value=\"${esc(d2.state.kpiQuery||'')}\"/>\n          ${filtered.map(k=>`<div class=\"opt ${String(k.code)===String(dr.mainKpiCode)?'on':''}\" data-mainkpi=\"${esc(k.code)}\">${esc(k.name)} <span style=\"color:${t.color.muted}\">· ${esc(k.code)}</span></div>`).join('')||'<div class=\"opt\" style=\"color:'+t.color.muted+'\">Nenhum KPI</div>'}\n        </div>\n      </div>`;\n\n    const relPicker = `\n      <div class=\"sel ${open==='relKpi'?'open':''}\" data-sel=\"relKpi\">\n        <button type=\"button\" class=\"trigger\" data-trigger=\"relKpi\">\n          <span>Adicionar KPI relacionado…</span><span class=\"cv\">▾</span>\n        </button>\n        <div class=\"menu\">\n          <input class=\"search\" data-relsearch placeholder=\"Buscar KPI…\" value=\"${esc(d2.state.relQuery||'')}\"/>\n          ${(()=>{ const rq=(d2.state.relQuery||'').toLowerCase();\n            const f = rq?kpis.filter(k=>String(k.name).toLowerCase().includes(rq)||String(k.code).includes(rq)):kpis;\n            return f.map(k=>`<div class=\"opt ${rel.includes(String(k.code))?'on':''}\" data-relkpi=\"${esc(k.code)}\">${rel.includes(String(k.code))?'✓ ':''}${esc(k.name)} <span style=\"color:${t.color.muted}\">· ${esc(k.code)}</span></div>`).join('')||'<div class=\"opt\" style=\"color:'+t.color.muted+'\">Nenhum KPI</div>';\n          })()}\n        </div>\n      </div>`;\n\n    return `\n    <div class=\"scrim ${d2.state.shown?'in':''}\" data-scrim style=\"\n      --surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};\n      --hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--green:${t.color.money||'#29AC56'};\n      --grad:${t.color.brandGradient};--fam:${t.type.family}\">\n      <div class=\"modal\" data-modal>\n        <div class=\"head\">\n          <div class=\"hg\">${lucide(isNew?'plus':'pencil')}</div>\n          <div>\n            <h3>${isNew?'Novo indicador':'Editar indicador'}</h3>\n            <p>${isNew?'Adicione um indicador ao dashboard':esc(dr.ref||'')}</p>\n          </div>\n          <button class=\"x\" data-close title=\"Fechar\">✕</button>\n        </div>\n        <div class=\"form\">\n          <div class=\"field\">\n            <label>Título</label>\n            <input type=\"text\" data-f=\"label\" value=\"${esc(dr.label||'')}\" placeholder=\"Ex.: Ativas por Marca\"/>\n          </div>\n          <div class=\"row\">\n            <div class=\"field\"><label>Perfil</label>${selField('perfil',dr.perfil)}</div>\n            <div class=\"field\"><label>Rede</label>${selField('rede',dr.rede)}</div>\n          </div>\n          <div class=\"row\">\n            <div class=\"field\"><label>Seção</label>${selField('section',dr.section)}</div>\n            <div class=\"field\"><label>Agrupamento</label>${selField('agrupamento',dr.agrupamento)}</div>\n          </div>\n          <div class=\"field\"><label>Ícone</label>${selField('icon',dr.icon)}</div>\n          <div class=\"field\"><label>KPI principal</label>${mainPicker}</div>\n          <div class=\"field\">\n            <label>KPIs relacionados</label>\n            ${relPicker}\n            <div class=\"chips\" style=\"margin-top:9px\" data-chips>\n              ${rel.length?rel.map(c=>`<span class=\"chip\" data-key=\"${esc(c)}\">${esc(kpiName(kpis,c))}<button data-relremove=\"${esc(c)}\" title=\"remover\">✕</button></span>`).join(''):'<span class=\"chip empty\">Nenhum KPI relacionado</span>'}\n            </div>\n          </div>\n          <div class=\"row\">\n            <div class=\"field\" style=\"flex:0 0 140px\">\n              <label>Ordem</label>\n              <input type=\"number\" data-f=\"displayOrder\" value=\"${esc(dr.displayOrder!=null?dr.displayOrder:1)}\" min=\"1\"/>\n            </div>\n            <div class=\"field\" style=\"display:flex;align-items:flex-end\">\n              <div class=\"toggles\">\n                <div class=\"tg\" data-tg=\"isBonus\"><div class=\"sw ${dr.isBonus?'on':''}\"><i></i></div><span>Bônus / IAP</span></div>\n                <div class=\"tg\" data-tg=\"visible\"><div class=\"sw ${dr.visible!==false?'on':''}\"><i></i></div><span>Visível</span></div>\n              </div>\n            </div>\n          </div>\n        </div>\n        <div class=\"foot\">\n          <button class=\"btn ghost\" data-close>Cancelar</button>\n          <button class=\"btn primary\" data-save ${canSave?'':'disabled'}>${isNew?'Criar indicador':'Salvar alterações'}</button>\n        </div>\n      </div>\n    </div>`;\n  },\n  mounted(d2){\n    // Initialize draft from item param whenever openKey changes.\n    const syncDraft = ()=>{\n      const it = d2.param('item', null);\n      const base = it && (it.ref!=null||it._id!=null||it.label!=null) ? JSON.parse(JSON.stringify(it)) : emptyItem();\n      if(!Array.isArray(base.relatedKpiCodes)) base.relatedKpiCodes = [];\n      d2.state.draft = base;\n      d2.state.openSel = null;\n      d2.state.kpiQuery = '';\n      d2.state.relQuery = '';\n      d2.state.shown = false;\n      // next frame → play the enter transition\n      d2.raf(()=>{ d2.setState({ shown:true }); return false; });\n    };\n    d2._lastOpen = d2.param('openKey', 0);\n    syncDraft();\n\n    // text/number fields\n    d2.on('[data-f]','input',(e,el)=>{\n      const f = el.dataset.f;\n      const v = f==='displayOrder' ? (parseInt(el.value,10)||1) : el.value;\n      d2.state.draft = { ...d2.state.draft, [f]:v };\n      // canSave gate lives in render → nudge\n      d2.refresh();\n    });\n\n    // enum dropdown open/close\n    d2.on('[data-trigger]','click',(e,el)=>{\n      e.stopPropagation();\n      const f = el.dataset.trigger;\n      d2.setState({ openSel: d2.state.openSel===f?null:f });\n    });\n    d2.on('[data-pick]','click',(e,el)=>{\n      e.stopPropagation();\n      const f = el.dataset.pick;\n      d2.state.draft = { ...d2.state.draft, [f]: el.dataset.val };\n      d2.setState({ openSel:null });\n    });\n    // main KPI pick\n    d2.on('[data-mainkpi]','click',(e,el)=>{\n      e.stopPropagation();\n      d2.state.draft = { ...d2.state.draft, mainKpiCode: el.dataset.mainkpi };\n      d2.setState({ openSel:null, kpiQuery:'' });\n    });\n    d2.on('[data-kpisearch]','input',(e,el)=>{ d2.state.kpiQuery = el.value; d2.refresh(); });\n    // related KPI multi-select\n    d2.on('[data-relkpi]','click',(e,el)=>{\n      e.stopPropagation();\n      const c = String(el.dataset.relkpi);\n      const cur = Array.isArray(d2.state.draft.relatedKpiCodes)?d2.state.draft.relatedKpiCodes.slice():[];\n      const i = cur.indexOf(c);\n      if(i>=0) cur.splice(i,1); else cur.push(c);\n      d2.state.draft = { ...d2.state.draft, relatedKpiCodes: cur };\n      d2.refresh();\n    });\n    d2.on('[data-relsearch]','input',(e,el)=>{ d2.state.relQuery = el.value; d2.refresh(); });\n    d2.on('[data-relremove]','click',(e,el)=>{\n      e.stopPropagation();\n      const c = String(el.dataset.relremove);\n      const cur = (d2.state.draft.relatedKpiCodes||[]).filter(x=>x!==c);\n      d2.state.draft = { ...d2.state.draft, relatedKpiCodes: cur };\n      d2.refresh();\n    });\n    // toggles\n    d2.on('[data-tg]','click',(e,el)=>{\n      e.stopPropagation();\n      const f = el.dataset.tg;\n      const cur = f==='visible' ? (d2.state.draft.visible!==false) : !!d2.state.draft.isBonus;\n      d2.state.draft = { ...d2.state.draft, [f]: !cur };\n      d2.refresh();\n    });\n    // close menus when clicking elsewhere in the modal\n    d2.on('[data-modal]','click',(e)=>{ if(d2.state.openSel) d2.setState({ openSel:null }); });\n    // close on scrim / buttons\n    const close = ()=>{ d2.setState({ shown:false }); d2.raf(()=>{ setTimeout(()=>d2.bus.emit('adm:formClose'),200); return false; }); };\n    d2.on('[data-close]','click',(e)=>{ e.stopPropagation(); close(); });\n    d2.on('[data-scrim]','click',(e)=>{ if(e.target && e.target.hasAttribute && e.target.hasAttribute('data-scrim')) close(); });\n    // save\n    d2.on('[data-save]','click',(e)=>{\n      e.stopPropagation();\n      const dr = d2.state.draft || {};\n      if(!dr.label || !dr.label.trim()) return;\n      d2.bus.emit('adm:formSave', JSON.parse(JSON.stringify(dr)));\n    });\n    // esc key\n    d2.on(document,'keydown',(e)=>{ if(e.key==='Escape') close(); });\n  },\n  updated(d2){\n    // re-sync when parent bumps openKey (new modal open with a different item)\n    const ok = d2.param('openKey', 0);\n    if(ok !== d2._lastOpen){\n      d2._lastOpen = ok;\n      const it = d2.param('item', null);\n      const base = it && (it.ref!=null||it._id!=null||it.label!=null) ? JSON.parse(JSON.stringify(it)) : emptyItem();\n      if(!Array.isArray(base.relatedKpiCodes)) base.relatedKpiCodes = [];\n      d2.state.draft = base;\n      d2.state.openSel=null; d2.state.kpiQuery=''; d2.state.relQuery=''; d2.state.shown=false;\n      d2.raf(()=>{ d2.setState({ shown:true }); return false; });\n    }\n  }\n};\n"}},"item":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"item"}}}},"kpiList":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"kpiList"}}}},"openKey":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"openKey"}}}}}}}}}},{"_id":"6a4c0b7ebe5b19656f2619ba","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotAdmList","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',gold:'#F7BE00',money:'#29AC56'},\n  radius:{sm:8,md:12,lg:16,pill:999},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\",title:'15px',body:'13px',caption:'11px'},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction kpiName(list,code){ const k=(list||[]).find(x=>String(x.code)===String(code)); return k?k.name:code; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction reduced(){ try{ return window.matchMedia('(prefers-reduced-motion: reduce)').matches; }catch(e){ return false; } }\n// elementFromPoint doesn't pierce shadow DOM — walk into shadow roots at the point.\nfunction rowAtPoint(root, x, y){\n  let el = (root && root.elementFromPoint) ? root.elementFromPoint(x,y) : document.elementFromPoint(x,y);\n  let guard = 0;\n  while(el && el.shadowRoot && guard++ < 8){\n    const inner = el.shadowRoot.elementFromPoint(x,y);\n    if(!inner || inner===el) break;\n    el = inner;\n  }\n  return el && el.closest ? el.closest('[data-card]') : null;\n}\n\nexport default {\n  css: `\n  :host{display:block}\n  .wrap{padding:2px;box-sizing:border-box}\n  .list{display:flex;flex-direction:column;gap:10px;position:relative}\n  .row{position:relative;border-radius:16px;will-change:transform;animation:rowIn .34s cubic-bezier(.2,0,0,1) both}\n  .row.dragging{opacity:.28}\n  .row.leaving{animation:rowOut .28s cubic-bezier(.4,0,1,1) forwards;overflow:hidden}\n  @keyframes rowIn{from{opacity:0;transform:translateY(10px) scale(.98)}to{opacity:1;transform:none}}\n  @keyframes rowOut{from{opacity:1;max-height:200px;transform:none}to{opacity:0;max-height:0;transform:translateX(-24px);margin-top:-10px}}\n  .grip{position:absolute;left:0;top:0;bottom:0;width:44px;z-index:5;cursor:grab;touch-action:none;border-radius:16px 0 0 16px}\n  .grip:active{cursor:grabbing}\n  .host{position:relative}\n  .indicator{height:3px;border-radius:3px;background:linear-gradient(90deg,#E5004B,#EB6619);margin:0 8px;\n             box-shadow:0 0 8px rgba(229,0,75,.5);animation:pulse 1.2s ease-in-out infinite}\n  @keyframes pulse{0%,100%{opacity:.7}50%{opacity:1}}\n  .empty{padding:48px 20px;text-align:center;color:var(--muted);font:400 14px/1.4 var(--fam)}\n  .empty .big{font-size:34px;margin-bottom:10px}\n  .savebar{position:sticky;bottom:0;display:flex;align-items:center;gap:10px;justify-content:flex-end;padding:10px 4px 2px}\n  @media (prefers-reduced-motion: reduce){\n    .indicator{animation:none}\n    .row{transition:none!important;animation:none!important}\n    .row.leaving{animation:none!important}\n  }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const list = d2.param('items', []) || [];\n    const kpiList = d2.param('kpiList', []) || [];\n    const card = d2.param('card','natura-x-piloto@pilotAdmCard');\n    // local working order (array of items) so reorder is instant; seeded from param\n    let order = d2.state.order;\n    const version = d2.param('orderVersion', 0);\n    if(!order || d2.state._seededV !== version){\n      order = list.slice().sort((a,b)=>(a.displayOrder||0)-(b.displayOrder||0));\n      d2.state.order = order;\n      d2.state._seededV = version;\n    }\n    const dragId = d2.state.dragId;\n    const dropBefore = d2.state.dropBefore;\n    const dropAfter = d2.state.dropAfter;\n\n    if(!order.length){\n      return `<div class=\"wrap\" style=\"--muted:${t.color.muted};--fam:${t.type.family}\">\n        <div class=\"empty\"><div class=\"big\">📋</div>Nenhum indicador neste filtro.<br/>Use “+ Novo indicador” para começar.</div></div>`;\n    }\n\n    const rows = order.map(it=>{\n      const id = it.ref || it._id;\n      const ind = dropBefore===id ? `<div class=\"indicator\" data-d2-static></div>` : '';\n      const indA = dropAfter===id ? `<div class=\"indicator\" data-d2-static></div>` : '';\n      return `${ind}<div class=\"row ${dragId===id?'dragging':''}\" data-key=\"${esc(id)}\" data-card=\"${esc(id)}\">\n        <div class=\"grip\" data-grip=\"${esc(id)}\" title=\"Arraste para reordenar\"></div>\n        <div class=\"host\">${d2.render(card,{ item:it, kpiName:kpiName(kpiList,it.mainKpiCode), dragging:dragId===id },{ key:id })}</div>\n      </div>${indA}`;\n    }).join('');\n\n    return `<div class=\"wrap\" style=\"--muted:${t.color.muted};--fam:${t.type.family}\">\n      <div class=\"list\" data-list>${rows}</div>\n    </div>`;\n  },\n  mounted(d2){\n    let start = null;      // {x,y,id,startIndex} — closure, non-reactive\n    let lastY = 0;\n\n    const idsInOrder = ()=> (d2.state.order||[]).map(it=>it.ref||it._id);\n\n    d2.on('[data-grip]','pointerdown',(e,el)=>{\n      e.preventDefault();\n      const id = el.dataset.grip;\n      try{ el.setPointerCapture(e.pointerId); }catch(_){}\n      const idx = idsInOrder().indexOf(id);\n      const rowEl = el.closest('[data-card]');\n      const label = (()=>{ const it=(d2.state.order||[]).find(x=>(x.ref||x._id)===id); return it?it.label:''; })();\n      start = { x:e.clientX, y:e.clientY, id, startIndex:idx, w: rowEl?rowEl.getBoundingClientRect().width:320 };\n      lastY = e.clientY;\n      d2.setState({ dragId:id, ghost:{ x:e.clientX, y:e.clientY, label } });\n    });\n\n    d2.on(window,'pointermove',(e)=>{\n      if(!start) return;\n      lastY = e.clientY;\n      const overRow = rowAtPoint(d2.root.getRootNode(), e.clientX, e.clientY);\n      let nb=null, na=null;\n      if(overRow){\n        const oid = overRow.dataset.card;\n        if(oid !== start.id){\n          const box = overRow.getBoundingClientRect();\n          const before = e.clientY < box.top + box.height/2;\n          if(before) nb = oid; else na = oid;\n        }\n      }\n      d2.setState({ dropBefore:nb, dropAfter:na, ghost:{ ...(d2.state.ghost||{}), x:e.clientX, y:e.clientY } });\n    });\n\n    d2.on(window,'pointerup',(e)=>{\n      if(!start) return;\n      const s = start; start = null;\n      const nb = d2.state.dropBefore, na = d2.state.dropAfter;\n      const order = (d2.state.order||[]).slice();\n      const from = order.findIndex(it=>(it.ref||it._id)===s.id);\n      if(from<0){ d2.setState({ dragId:null, ghost:null, dropBefore:null, dropAfter:null }); return; }\n\n      // compute target index\n      let targetId = nb || na;\n      let moved = false;\n      if(targetId && targetId!==s.id){\n        const [rec] = order.splice(from,1);\n        let ti = order.findIndex(it=>(it.ref||it._id)===targetId);\n        if(na) ti = ti+1;\n        order.splice(ti,0,rec);\n        moved = true;\n      }\n\n      // FLIP: capture first rects BEFORE the reorder paints\n      const first = {};\n      d2.$$('[data-card]').forEach(el=>{ first[el.dataset.card] = el.getBoundingClientRect().top; });\n\n      // renumber displayOrder 1..N and commit to state → morph reorders keyed rows\n      order.forEach((it,i)=>{ it.displayOrder = i+1; });\n      d2.setState({ order, dragId:null, ghost:null, dropBefore:null, dropAfter:null });\n\n      if(moved){\n        // play FLIP after DOM settles\n        d2.raf(()=>{\n          if(reduced()){ return false; }\n          d2.$$('[data-card]').forEach(el=>{\n            const id = el.dataset.card;\n            const prev = first[id];\n            if(prev==null) return;\n            const now = el.getBoundingClientRect().top;\n            const dy = prev - now;\n            if(dy){\n              el.style.transition='none';\n              el.style.transform=`translateY(${dy}px)`;\n              // force reflow then animate to 0\n              void el.offsetHeight;\n              el.style.transition='transform .26s cubic-bezier(.2,0,0,1)';\n              el.style.transform='';\n              setTimeout(()=>{ el.style.transition=''; }, 300);\n            }\n          });\n          return false;\n        });\n        // persist the new order — screen listens on the bus and invokes the listener\n        d2.bus.emit('adm:reorder', order.map(it=>({ ref:it.ref, _id:it._id, displayOrder:it.displayOrder })));\n      }\n    });\n\n    // exit animation: screen fires this right before it deletes a row\n    d2.bus.on('adm:leaving',(id)=>{\n      const rows = Array.prototype.slice.call(d2.$('[data-card]')||[]);\n      const row = rows.filter(el=>el.dataset.card===id)[0];\n      if(row && !reduced()) row.classList.add('leaving');\n    });\n\n    // ghost portal\n    d2.onUnmount(()=>{ if(d2._ghostEl){ d2._ghostEl.remove(); d2._ghostEl=null; } });\n  },\n  updated(d2){\n    // body-portaled drag ghost\n    const g0 = d2._ghostEl;\n    if(!d2.state.ghost){ if(g0){ g0.remove(); d2._ghostEl=null; } return; }\n    let g = d2._ghostEl;\n    if(!g){\n      g = document.createElement('div');\n      Object.assign(g.style,{position:'fixed',left:'0',top:'0',pointerEvents:'none',zIndex:9999,\n        padding:'12px 16px',borderRadius:'14px',background:'#fff',color:'#1A1C1E',font:\"600 14px/1 'Roboto',sans-serif\",\n        boxShadow:'0 16px 40px rgba(16,24,40,.28)',border:'1px solid rgba(16,24,40,.08)',\n        display:'flex',alignItems:'center',gap:'8px'});\n      document.body.appendChild(g); d2._ghostEl=g;\n    }\n    g.innerHTML = `<span style=\"opacity:.5\">⠿</span><span>${esc(d2.state.ghost.label||'')}</span>`;\n    g.style.transform = `translate3d(${d2.state.ghost.x+14}px,${d2.state.ghost.y-6}px,0)`;\n  }\n};\n"}},"items":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"items"}}}},"kpiList":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"kpiList"}}}},"card":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"card"}}}},"orderVersion":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"orderVersion"}}}},"busy":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"busy"}}}}}}}}}},{"_id":"6a4c0c5afe6887479ea7e300","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotAdmScreen","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',gold:'#F7BE00',money:'#29AC56'},\n  radius:{sm:8,md:12,lg:16,pill:999},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\",h1:'28px',h2:'20px',title:'15px',body:'13px',caption:'11px'},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nconst ICON = (()=>{\n  const S = (p)=>`<svg class=\"ic-svg\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${p}</svg>`;\n  return {\n    plus:S('<path d=\"M12 5v14M5 12h14\"/>'),\n    search:S('<circle cx=\"11\" cy=\"11\" r=\"7\"/><path d=\"m21 21-4.3-4.3\"/>')\n  };\n})();\nconst PERFIL_SEG = [['all','Todos'],['gn','GN'],['lider','Líder'],['gv','GV']];\nconst REDE_SEG = [['all','Todas'],['rede1','Rede 1'],['rede2','Rede 2'],['both','Ambas']];\nconst SECTION_SEG = [['all','Todas'],['leader-card','Cartão Líder'],['leader','Líder'],['sector','Setor'],['sector-kpi','KPI Setor']];\n\nfunction matchFilter(it,f){\n  if(!it.ref) return false; // only briefing-shape items\n  if(f.perfil!=='all' && it.perfil!==f.perfil) return false;\n  if(f.rede!=='all' && it.rede!==f.rede) return false;\n  if(f.section!=='all' && it.section!==f.section) return false;\n  if(f.q){ const q=f.q.toLowerCase(); if(!String(it.label||'').toLowerCase().includes(q) && !String(it.ref||'').toLowerCase().includes(q)) return false; }\n  return true;\n}\n\nexport default {\n  css: `\n  :host{display:block}\n  .screen{min-height:100%;height:auto;display:flex;flex-direction:column;background:var(--ground);font-family:var(--fam);box-sizing:border-box}\n  .header{padding:26px 30px 18px;background:var(--surface);border-bottom:1px solid var(--hair)}\n  .htop{display:flex;align-items:flex-start;gap:16px}\n  .htitle h1{margin:0;font:800 28px/1.1 var(--fam);color:var(--ink);letter-spacing:-.5px}\n  .htitle p{margin:5px 0 0;font:400 13px/1.3 var(--fam);color:var(--muted)}\n  .htitle .badge{display:inline-block;margin-left:10px;font:700 10px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;\n    color:var(--mag);background:rgba(229,0,75,.10);padding:5px 9px;border-radius:999px;vertical-align:middle}\n  .new{margin-left:auto;display:inline-flex;align-items:center;gap:8px;padding:12px 20px;border:none;border-radius:12px;\n    background:var(--grad);color:#fff;font:700 14px/1 var(--fam);cursor:pointer;box-shadow:0 6px 16px rgba(229,0,75,.30);\n    transition:filter .15s,transform .15s}\n  .new:hover{filter:brightness(1.06);transform:translateY(-1px)}\n  .filters{display:flex;flex-wrap:wrap;gap:18px;margin-top:20px;align-items:center}\n  .fg{display:flex;align-items:center;gap:8px}\n  .fg>.lb{font:600 11px/1 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.05em}\n  .seg{display:inline-flex;background:var(--ground);border-radius:10px;padding:3px;gap:2px}\n  .seg button{border:none;background:none;padding:7px 12px;border-radius:8px;font:600 12px/1 var(--fam);color:var(--muted);\n    cursor:pointer;transition:background .15s,color .15s}\n  .seg button.on{background:var(--surface);color:var(--ink);box-shadow:0 1px 2px rgba(16,24,40,.10)}\n  .search{margin-left:auto;position:relative}\n  .search input{padding:9px 12px 9px 32px;border:1.5px solid var(--hair);border-radius:10px;font:400 13px/1 var(--fam);\n    width:190px;outline:none;transition:border-color .15s}\n  .search input:focus{border-color:var(--mag)}\n  .search .ic{position:absolute;left:10px;top:50%;transform:translateY(-50%);color:var(--muted);font-size:13px;display:inline-flex}\n  .ic-svg{display:block;flex:0 0 auto}\n  .new .ic-svg{width:17px;height:17px}\n  .search .ic .ic-svg{width:15px;height:15px}\n  .meta{display:flex;align-items:center;gap:12px;padding:14px 30px 0;font:500 12px/1 var(--fam);color:var(--muted)}\n  .meta .count{color:var(--ink);font-weight:700}\n  .meta .saving{display:inline-flex;align-items:center;gap:6px;color:var(--mag)}\n  .spin{width:12px;height:12px;border:2px solid rgba(229,0,75,.25);border-top-color:var(--mag);border-radius:50%;animation:sp .7s linear infinite}\n  @keyframes sp{to{transform:rotate(360deg)}}\n  .body{flex:1 1 auto;overflow:visible;padding:14px 30px 64px}\n  .toast{position:fixed;left:50%;bottom:26px;transform:translate(-50%,20px);background:var(--ink);color:#fff;\n    padding:12px 20px;border-radius:12px;font:600 13px/1 var(--fam);box-shadow:0 10px 30px rgba(0,0,0,.3);z-index:9500;\n    opacity:0;transition:opacity .2s,transform .2s;pointer-events:none}\n  .toast.in{opacity:1;transform:translate(-50%,0)}\n  @media (prefers-reduced-motion: reduce){\n    .new,.seg button,.search input,.toast{transition:none!important}\n    .new:hover{transform:none}\n    .spin{animation:none}\n  }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const ds = d2.data('items');\n    const kds = d2.data('kpis');\n    const loading = ds && ds.loading;\n    const all = ds ? ds.records() : [];\n    const kpiList = kds ? kds.records() : [];\n    const f = d2.state.filter || { perfil:'all', rede:'all', section:'all', q:'' };\n    const filtered = all.filter(it=>matchFilter(it,f));\n    const version = d2.state.orderVersion || 1;\n    const seg = (name,opts,cur)=>`<div class=\"seg\">${opts.map(([v,l])=>`<button data-seg=\"${name}\" data-val=\"${v}\" class=\"${cur===v?'on':''}\">${esc(l)}</button>`).join('')}</div>`;\n\n    const listHost = loading\n      ? `<div style=\"padding:60px;text-align:center;color:${t.color.muted}\">Carregando indicadores…</div>`\n      : d2.render(d2.param('list','natura-x-piloto@pilotAdmList'), {\n          items: filtered, kpiList: kpiList, card:'natura-x-piloto@pilotAdmCard', orderVersion: version\n        }, {\n          key:'admlist-'+(kpiList.length>0?'k1':'k0')+'-'+f.perfil+'-'+f.rede+'-'+f.section+'-'+(f.q||'').length\n        });\n\n    const formHost = d2.state.formOpen\n      ? d2.render(d2.param('form','natura-x-piloto@pilotAdmForm'), {\n          item: d2.state.formItem || null, kpiList: kpiList, openKey: d2.state.formKey || 1\n        }, {\n          key:'admform-'+(d2.state.formKey||1)\n        })\n      : '';\n\n    return `<div class=\"screen\" style=\"\n      --surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};\n      --hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient};--fam:${t.type.family}\">\n      <div class=\"header\">\n        <div class=\"htop\">\n          <div class=\"htitle\">\n            <h1>Administração · Indicadores <span class=\"badge\">Code · DnD</span></h1>\n            <p>Arraste pelos punhos para reordenar · edite, duplique ou oculte cada indicador do dashboard.</p>\n          </div>\n          <button class=\"new\" data-new>${ICON.plus} Novo indicador</button>\n        </div>\n        <div class=\"filters\">\n          <div class=\"fg\"><span class=\"lb\">Perfil</span>${seg('perfil',PERFIL_SEG,f.perfil)}</div>\n          <div class=\"fg\"><span class=\"lb\">Rede</span>${seg('rede',REDE_SEG,f.rede)}</div>\n          <div class=\"fg\"><span class=\"lb\">Seção</span>${seg('section',SECTION_SEG,f.section)}</div>\n          <div class=\"search\"><span class=\"ic\">${ICON.search}</span><input data-search placeholder=\"Buscar…\" value=\"${esc(f.q||'')}\"/></div>\n        </div>\n      </div>\n      <div class=\"meta\">\n        <span><span class=\"count\">${filtered.length}</span> indicador${filtered.length===1?'':'es'}</span>\n        ${d2.state.saving?`<span class=\"saving\"><span class=\"spin\"></span>Salvando…</span>`:''}\n      </div>\n      <div class=\"body\">${listHost}</div>\n      ${formHost}\n      <div class=\"toast ${d2.state.toast?'in':''}\" data-toast>${esc(d2.state.toast||'')}</div>\n    </div>`;\n  },\n  mounted(d2){\n    d2.state.filter = d2.state.filter || { perfil:'all', rede:'all', section:'all', q:'' };\n    d2.state.orderVersion = d2.state.orderVersion || 1;\n\n    d2.on('[data-seg]','click',(e,el)=>{\n      const f = { ...(d2.state.filter||{}) };\n      f[el.dataset.seg] = el.dataset.val;\n      d2.setState({ filter:f, orderVersion:(d2.state.orderVersion||1)+1 });\n    });\n    d2.on('[data-search]','input',(e,el)=>{\n      const f = { ...(d2.state.filter||{}), q: el.value };\n      d2.state.filter = f; d2.refresh();\n    });\n    d2.on('[data-new]','click',()=>openForm(d2,null));\n\n    // child→parent signals over the app bus (auto-unsubscribed on unmount)\n    d2.bus.on('adm:edit',    (it)=>openForm(d2,it));\n    d2.bus.on('adm:dup',     (it)=>handleDup(d2,it));\n    d2.bus.on('adm:del',     (it)=>handleDel(d2,it));\n    d2.bus.on('adm:toggle',  (it)=>handleToggle(d2,it));\n    d2.bus.on('adm:reorder', (payload)=>handleReorder(d2,payload));\n    d2.bus.on('adm:formSave',(draft)=>handleSave(d2,draft));\n    d2.bus.on('adm:formClose',()=>d2.setState({ formOpen:false }));\n  }\n};\n\n// ---- module-level handlers (this is unbound; pass d2) ----\nfunction openForm(d2,item){\n  d2.setState({ formOpen:true, formItem:item, formKey:(d2.state.formKey||0)+1 });\n}\nfunction toast(d2,msg){\n  d2.setState({ toast:msg });\n  setTimeout(()=>d2.setState({ toast:null }), 2200);\n}\nfunction refreshItems(d2){\n  const ds = d2.data('items');\n  if(ds && ds.refresh) ds.refresh();\n  d2.setState({ orderVersion:(d2.state.orderVersion||1)+1 });\n}\nasync function invoke(d2,payload){\n  const w = d2.rush('writer');\n  return await w.invoke(payload);\n}\nasync function handleSave(d2,draft){\n  d2.setState({ saving:true, formOpen:false });\n  try{\n    await invoke(d2,{ op:'update', actorEmail:'gabriel.cardoso@data2.app', item:draft });\n    toast(d2, draft._id ? 'Indicador atualizado' : 'Indicador criado');\n  }catch(e){ toast(d2,'Erro ao salvar'); }\n  refreshItems(d2);\n  d2.setState({ saving:false });\n}\nasync function handleDel(d2,it){\n  // confirmation is an inline two-click guard on the card; here we animate + persist.\n  d2.bus.emit('adm:leaving', it.ref || it._id);\n  await new Promise(r=>setTimeout(r, 260));\n  d2.setState({ saving:true });\n  try{\n    await invoke(d2,{ op:'delete', actorEmail:'gabriel.cardoso@data2.app', item:{ _id:it._id, ref:it.ref, perfil:it.perfil } });\n    toast(d2,'Indicador excluído');\n  }catch(e){ toast(d2,'Erro ao excluir'); }\n  refreshItems(d2);\n  d2.setState({ saving:false });\n}\nasync function handleToggle(d2,it){\n  d2.setState({ saving:true });\n  const next = { ...it, visible: it.visible===false };\n  try{\n    await invoke(d2,{ op:'update', actorEmail:'gabriel.cardoso@data2.app', item:next, before:it });\n    toast(d2, next.visible ? 'Indicador visível' : 'Indicador oculto');\n  }catch(e){ toast(d2,'Erro'); }\n  refreshItems(d2);\n  d2.setState({ saving:false });\n}\nasync function handleDup(d2,it){\n  d2.setState({ saving:true });\n  const copy = { ...it }; delete copy._id; copy.ref=''; copy.label = (it.label||'')+' (cópia)';\n  try{\n    await invoke(d2,{ op:'update', actorEmail:'gabriel.cardoso@data2.app', item:copy });\n    toast(d2,'Indicador duplicado');\n  }catch(e){ toast(d2,'Erro ao duplicar'); }\n  refreshItems(d2);\n  d2.setState({ saving:false });\n}\nasync function handleReorder(d2,payload){\n  // payload: [{ref,_id,displayOrder}]\n  d2.setState({ saving:true });\n  const perfil = (d2.state.filter && d2.state.filter.perfil!=='all') ? d2.state.filter.perfil : 'gn';\n  try{\n    const withId = payload.filter(p=>p._id);\n    await invoke(d2,{ op:'reorder', perfil, actorEmail:'gabriel.cardoso@data2.app', items:withId });\n    toast(d2,'Nova ordem salva');\n  }catch(e){ toast(d2,'Erro ao salvar ordem'); }\n  // silent refresh (don't bump orderVersion → keep the animated local order; refresh underlying data)\n  const ds = d2.data('items');\n  if(ds && ds.refresh) ds.refresh();\n  d2.setState({ saving:false });\n}\n"}},"items":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"items"}}}},"kpis":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"kpis"}}}},"writer":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"writer"}}}},"list":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"list"}}}},"form":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"form"}}}}}}}}}},{"_id":"6a4c144ff667a03103c91994","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotRuleBandGrid","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',avonMagenta:'#E5014B',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',gold:'#F7BE00',money:'#29AC56'},\n  radius:{sm:8,md:12,lg:16,pill:999},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\",h1:'28px',h2:'20px',title:'15px',body:'13px',caption:'11px'},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction nf(n){ try{ return Number(n).toLocaleString('pt-BR'); }catch(e){ return String(n); } }\nfunction money(n){ try{ return Number(n).toLocaleString('pt-BR',{style:'currency',currency:'BRL',minimumFractionDigits:0,maximumFractionDigits:0}); }catch(e){ return 'R$'+n; } }\n\nconst ICON = (()=>{\n  const S = (p)=>`<svg class=\"ic-svg\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${p}</svg>`;\n  return {\n    edit:S('<path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/>'),\n    del:S('<path d=\"M3 6h18\"/><path d=\"M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/>'),\n    ok:S('<path d=\"M20 6 9 17l-5-5\"/>'),\n    plus:S('<path d=\"M12 5v14M5 12h14\"/>'),\n    gear:S('<circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z\"/>')\n  };\n})();\nconst TABLE_LABEL = {\n  'ativas-total':'Ativas Totais','atingimento':'Atingimento','pontos':'Pontos',\n  'saldo-positivo':'Saldo Positivo','saldo-negativo':'Saldo Negativo',\n  'multiplicador':'Multiplicador','atingimento-faturamento':'Atingimento Faturamento'\n};\nconst TABLE_ORDER = ['ativas-total','atingimento','pontos','atingimento-faturamento','saldo-positivo','saldo-negativo','multiplicador'];\nconst VT_LABEL = { fixed:'R$ fixo', multiplier:'% multiplicador' };\nconst REDE_LABEL = { rede1:'Rede 1', rede2:'Rede 2' };\nconst PERFIL_LABEL = { lider:'Líder', gn:'GN' };\n// Brand grouping order within each bandTable category: natura → avon → total('') → none.\nconst BRAND_ORDER = { 'natura':0, 'avon':1, '':2 };\nfunction brandRank(b){ const k=(b&&b.brand)||''; return (k in BRAND_ORDER) ? BRAND_ORDER[k] : 3; }\n// Nivel order (within a brand): diamante → ouro → prata → none.\nconst NIVEL_ORDER = { 'diamante':0, 'ouro':1, 'prata':2, '':3 };\nfunction nivelRank(b){ const k=(b&&b.nivel)||''; return (k in NIVEL_ORDER) ? NIVEL_ORDER[k] : 4; }\n// Sort a bandTable group: brand, then nivel, then minPct.\nfunction sortBandGroup(rows){\n  return rows.slice().sort((a,b)=>{\n    const br = brandRank(a)-brandRank(b); if(br!==0) return br;\n    const nr = nivelRank(a)-nivelRank(b); if(nr!==0) return nr;\n    return (Number(a.minPct)||0)-(Number(b.minPct)||0);\n  });\n}\nfunction refOf(b){ return b.bandTableRef || b.bandTable; }\nfunction btMap(bandTables){ const m={}; (bandTables||[]).forEach(t=>{ m[t.ref]=t; }); return m; }\n\nfunction matchFilter(b,f){\n  if(f.rede && f.rede!=='all' && b.rede!==f.rede) return false;\n  if(f.bandTable!=='all' && b.bandTable!==f.bandTable) return false;\n  if(f.nivel!=='all' && (b.nivel||'')!==f.nivel) return false;\n  if(f.brand!=='all' && (b.brand||'')!==f.brand) return false;\n  return true;\n}\n\nexport default {\n  css: `\n  :host{display:block}\n  .wrap{display:flex;flex-direction:column;gap:18px}\n  .grp{background:var(--surface);border:1px solid var(--hair);border-radius:16px;overflow:hidden;box-shadow:var(--shadowcard)}\n  .grphead{display:flex;align-items:center;gap:12px;padding:14px 18px;background:linear-gradient(180deg,rgba(229,0,75,.04),transparent);border-bottom:1px solid var(--hair)}\n  .grphead .dot{width:8px;height:8px;border-radius:50%;background:var(--grad);flex:none}\n  .grphead .htext{display:flex;flex-direction:column;gap:3px;min-width:0}\n  .grphead h3{margin:0;font:800 15px/1 var(--fam);color:var(--ink);letter-spacing:-.2px}\n  .grphead .sub{display:flex;align-items:center;gap:8px;flex-wrap:wrap}\n  .grphead .kpi{font:600 11px/1 var(--fam);color:var(--muted)}\n  .grphead .kpi b{color:var(--ink);font-weight:700}\n  .vtchip{font:700 10px/1 var(--fam);letter-spacing:.02em;padding:4px 8px;border-radius:999px}\n  .vtchip.fixed{background:rgba(41,172,86,.14);color:var(--money)}\n  .vtchip.multiplier{background:rgba(72,152,255,.16);color:#1462c7}\n  .scopechip{font:700 10px/1 var(--fam);letter-spacing:.02em;padding:4px 8px;border-radius:999px;background:var(--ground);color:var(--muted)}\n  .grphead .cnt{margin-left:auto;font:700 11px/1 var(--fam);color:var(--muted);background:var(--ground);padding:4px 8px;border-radius:999px}\n  .grphead .ictable{width:30px;height:30px;border:none;border-radius:9px;background:var(--ground);color:var(--muted);cursor:pointer;font-size:13px;\n    display:inline-flex;align-items:center;justify-content:center;transition:background .15s,color .15s}\n  .grphead .ictable:hover{background:rgba(229,0,75,.10);color:var(--mag)}\n  .rows{display:flex;flex-direction:column}\n  .row{display:grid;grid-template-columns:120px 88px 1fr 130px 88px;gap:12px;align-items:center;padding:11px 18px;border-top:1px solid var(--hair);\n    transition:background .15s;cursor:default}\n  .row:first-child{border-top:none}\n  .row:hover{background:var(--ground)}\n  .row.flash{animation:flash .8s ease-out}\n  @keyframes flash{0%{background:rgba(41,172,86,.22)}100%{background:transparent}}\n  .tag{display:inline-flex;align-items:center;gap:6px}\n  .chip{font:700 10px/1 var(--fam);letter-spacing:.03em;padding:5px 8px;border-radius:999px;text-transform:capitalize}\n  .chip.nivel{background:rgba(247,190,0,.16);color:#8a6d00}\n  .chip.nivel.diamante{background:rgba(72,152,255,.16);color:#1462c7}\n  .chip.nivel.ouro{background:rgba(247,190,0,.20);color:#8a6d00}\n  .chip.nivel.prata{background:rgba(120,130,145,.18);color:#4a5464}\n  .chip.brand{background:rgba(229,0,75,.10);color:var(--mag)}\n  .chip.brand.avon{background:rgba(160,32,120,.12);color:#a02078}\n  .rng{font:600 13px/1.3 var(--fam);color:var(--ink)}\n  .rng small{color:var(--muted);font-weight:500}\n  .track{position:relative;height:8px;border-radius:999px;background:var(--ground);overflow:hidden}\n  .track .fill{position:absolute;top:0;bottom:0;border-radius:999px;background:var(--grad);transition:left .4s cubic-bezier(.4,0,.2,1),right .4s cubic-bezier(.4,0,.2,1)}\n  .val{text-align:right;font:800 15px/1 var(--fam);color:var(--money)}\n  .val.pct{color:#1462c7}\n  .val.pct::after{content:'%';font-size:11px;color:var(--muted);margin-left:1px}\n  .acts{display:flex;gap:6px;justify-content:flex-end}\n  .ic{width:32px;height:32px;border:none;border-radius:9px;background:var(--ground);color:var(--muted);cursor:pointer;font-size:14px;\n    display:inline-flex;align-items:center;justify-content:center;transition:background .15s,color .15s,transform .1s}\n  .ic:hover{background:rgba(229,0,75,.10);color:var(--mag)}\n  .ic:active{transform:scale(.92)}\n  .ic.del:hover{background:rgba(255,20,24,.12);color:#d61419}\n  .ic.del.armed{background:#d61419;color:#fff}\n  .ic-svg{display:block;flex:0 0 auto}\n  .ic .ic-svg{width:17px;height:17px}\n  .ictable .ic-svg{width:16px;height:16px}\n  .addbtn .ic-svg{width:15px;height:15px}\n  .addrow{display:flex;justify-content:center;padding:10px}\n  .addbtn{display:inline-flex;align-items:center;gap:7px;padding:9px 16px;border:1.5px dashed var(--hair);border-radius:10px;background:transparent;\n    color:var(--mag);font:700 12px/1 var(--fam);cursor:pointer;transition:background .15s,border-color .15s}\n  .addbtn:hover{background:rgba(229,0,75,.06);border-color:var(--mag)}\n  .grpempty{padding:20px 18px;text-align:center;color:var(--muted);font:500 12px/1.4 var(--fam)}\n  .empty{padding:50px;text-align:center;color:var(--muted);font:500 13px/1.4 var(--fam)}\n  @media (prefers-reduced-motion: reduce){\n    .row,.ic,.track .fill,.addbtn{transition:none!important}\n    .row.flash{animation:none!important}\n  }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const bands = d2.param('bands',[]) || [];\n    const f = d2.param('filter',{rede:'all',bandTable:'all',nivel:'all',brand:'all'});\n    const flashId = d2.param('flashId','');\n    const bandTables = d2.param('bandTables',[]) || [];\n    const byRef = btMap(bandTables);\n    const filtered = bands.filter(b=>matchFilter(b,f));\n\n    // Build the ordered list of band-tables to show: every band-table in scope,\n    // plus any bandTable slug present in the bands that has no band-table row yet.\n    const groups = {};\n    filtered.forEach(b=>{ const k=refOf(b); (groups[k]=groups[k]||[]).push(b); });\n    const refsFromTables = bandTables.map(bt=>bt.ref);\n    const refsFromBands = Object.keys(groups);\n    const allRefs = [];\n    const seen={};\n    refsFromTables.concat(refsFromBands).forEach(r=>{ if(!seen[r]){ seen[r]=1; allRefs.push(r); } });\n    allRefs.sort((a,b)=>{\n      const oa = byRef[a]&&byRef[a].displayOrder!=null?byRef[a].displayOrder:null;\n      const ob = byRef[b]&&byRef[b].displayOrder!=null?byRef[b].displayOrder:null;\n      if(oa!=null&&ob!=null&&oa!==ob) return oa-ob;\n      const ia=TABLE_ORDER.indexOf(a), ib=TABLE_ORDER.indexOf(b);\n      return (ia<0?99:ia)-(ib<0?99:ib);\n    });\n\n    if(allRefs.length===0){\n      return `<div class=\"wrap\" style=\"${cssVars(t)}\"><div class=\"grp\"><div class=\"empty\">Nenhuma faixa ou tabela para este filtro.<br/>Ajuste os filtros, crie uma tabela ou adicione uma faixa.</div></div></div>`;\n    }\n\n    const rowHtml = (b, vt)=>{\n      const isPct = (vt==='multiplier');\n      const lo = Number(b.minPct)||0, hi = Number(b.maxPct)||0;\n      const capHi = Math.min(hi, isPct?200:9999);\n      const scale = isPct?150:Math.max(200,capHi||200);\n      const left = Math.max(0,Math.min(100, lo/scale*100));\n      const right = Math.max(0,Math.min(100, 100 - capHi/scale*100));\n      const armed = (d2.state.armDel === b._id);\n      return `<div class=\"row ${flashId===b._id?'flash':''}\" data-key=\"${esc(b._id)}\" data-id=\"${esc(b._id)}\">\n        <div class=\"tag\">\n          ${b.nivel?`<span class=\"chip nivel ${esc(b.nivel)}\">${esc(b.nivel)}</span>`:'<span style=\"color:var(--muted);font:600 11px/1 var(--fam)\">—</span>'}\n        </div>\n        <div class=\"tag\">${b.brand?`<span class=\"chip brand ${esc(b.brand)}\">${esc(b.brand)}</span>`:'<span style=\"color:var(--muted);font:600 11px/1 var(--fam)\">total</span>'}</div>\n        <div>\n          <div class=\"rng\">${nf(lo)} <small>a</small> ${hi>=9999?'∞':nf(hi)} <small>${isPct?'% de atingimento':''}</small></div>\n          <div class=\"track\" style=\"margin-top:6px\"><span class=\"fill\" style=\"left:${left}%;right:${right}%\"></span></div>\n        </div>\n        <div class=\"val ${isPct?'pct':''}\">${isPct?nf(b.value):money(b.value)}</div>\n        <div class=\"acts\">\n          <button class=\"ic edit\" data-edit=\"${esc(b._id)}\" title=\"Editar\">${ICON.edit}</button>\n          <button class=\"ic del ${armed?'armed':''}\" data-del=\"${esc(b._id)}\" title=\"${armed?'Confirmar exclusão':'Excluir'}\">${armed?ICON.ok:ICON.del}</button>\n        </div>\n      </div>`;\n    };\n\n    const groupHtml = allRefs.map(ref=>{\n      const bt = byRef[ref];\n      const label = bt ? bt.label : (TABLE_LABEL[ref]||ref);\n      const vt = bt && bt.valueType ? bt.valueType : (ref==='atingimento'?'multiplier':'fixed');\n      const rows = sortBandGroup(groups[ref]||[]);\n      const kpiTxt = bt && bt.kpiName ? `KPI <b>${esc(bt.kpiName)}</b>` : (bt&&bt.kpiCode?`KPI <b>${esc(bt.kpiCode)}</b>`:'sem KPI');\n      const scopeTxt = bt ? `${esc(REDE_LABEL[bt.rede]||bt.rede||'')} · ${esc(PERFIL_LABEL[bt.perfil]||bt.perfil||'')}` : '';\n      const editBtn = bt ? `<button class=\"ictable\" data-edittable=\"${esc(ref)}\" title=\"Editar tabela\">${ICON.gear}</button>` : '';\n      const inner = rows.length\n        ? `<div class=\"rows\">${rows.map(b=>rowHtml(b,vt)).join('')}</div>`\n        : `<div class=\"grpempty\">Nenhuma faixa nesta tabela ainda.</div>`;\n      return `<div class=\"grp\">\n        <div class=\"grphead\">\n          <span class=\"dot\"></span>\n          <div class=\"htext\">\n            <h3>${esc(label)}</h3>\n            <div class=\"sub\">\n              <span class=\"kpi\">${kpiTxt}</span>\n              <span class=\"vtchip ${vt}\">${esc(VT_LABEL[vt]||vt)}</span>\n              ${scopeTxt?`<span class=\"scopechip\">${scopeTxt}</span>`:''}\n            </div>\n          </div>\n          <span class=\"cnt\">${rows.length}</span>\n          ${editBtn}\n        </div>\n        ${inner}\n        <div class=\"addrow\"><button class=\"addbtn\" data-add=\"${esc(ref)}\">${ICON.plus} Adicionar faixa em ${esc(label)}</button></div>\n      </div>`;\n    }).join('');\n\n    return `<div class=\"wrap\" style=\"${cssVars(t)}\">${groupHtml}</div>`;\n  },\n  mounted(d2){\n    d2.on('[data-edit]','click',(e,el)=>{ d2.state.armDel=null; d2.bus.emit('rule:band:edit', findBand(d2, el.dataset.edit)); });\n    d2.on('[data-add]','click',(e,el)=>{ d2.state.armDel=null; d2.bus.emit('rule:band:add', el.dataset.add); });\n    d2.on('[data-edittable]','click',(e,el)=>{ d2.state.armDel=null; d2.bus.emit('rule:table:edit', findTable(d2, el.dataset.edittable)); });\n    d2.on('[data-del]','click',(e,el)=>{\n      const id = el.dataset.del;\n      if(d2.state.armDel === id){ d2.state.armDel=null; d2.bus.emit('rule:band:del', findBand(d2,id)); }\n      else { d2.state.armDel = id; d2.refresh(); setTimeout(()=>{ if(d2.state.armDel===id){ d2.state.armDel=null; d2.refresh(); } }, 3000); }\n    });\n  }\n};\nfunction cssVars(t){\n  return `--surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient};--money:${t.color.money};--fam:${t.type.family};--shadowcard:${t.shadow.card}`;\n}\nfunction findBand(d2,id){ return (d2.param('bands',[])||[]).find(b=>b._id===id) || null; }\nfunction findTable(d2,ref){\n  const bt = (d2.param('bandTables',[])||[]).find(x=>x.ref===ref) || null;\n  if(!bt) return null;\n  // Emit a plain band-table row shape the parent modal expects (strip derived kpiName).\n  return { _id:bt._id, ref:bt.ref, label:bt.label, kpiCode:bt.kpiCode, rede:bt.rede, perfil:bt.perfil, valueType:bt.valueType, displayOrder:bt.displayOrder, active:bt.active };\n}"}},"bands":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bands"}}}},"filter":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"filter"}}}},"flashId":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"flashId"}}}},"bandTables":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bandTables"}}}}}}}}}},{"_id":"6a4c1473be5b19656f26461f","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotRuleBonusEditor","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',avonMagenta:'#E5014B',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',gold:'#F7BE00',money:'#29AC56'},\n  radius:{sm:8,md:12,lg:16,pill:999},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\",h1:'28px',h2:'20px',title:'15px',body:'13px',caption:'11px'},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction money(n){ try{ return Number(n||0).toLocaleString('pt-BR',{style:'currency',currency:'BRL',minimumFractionDigits:0,maximumFractionDigits:2}); }catch(e){ return 'R$'+n; } }\n\nconst ICON = (()=>{\n  const S = (p)=>`<svg class=\"ic-svg\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${p}</svg>`;\n  return {\n    edit:S('<path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/>'),\n    dup:S('<rect x=\"9\" y=\"9\" width=\"11\" height=\"11\" rx=\"2\"/><path d=\"M5 15V5a2 2 0 0 1 2-2h8\"/>'),\n    del:S('<path d=\"M3 6h18\"/><path d=\"M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/>'),\n    x:S('<path d=\"M18 6 6 18M6 6l12 12\"/>'),\n    plus:S('<path d=\"M12 5v14M5 12h14\"/>')\n  };\n})();\nconst KPIS = [\n  {code:'545',label:'Ativas Natura'},\n  {code:'546',label:'Ativas Avon'},\n  {code:'28',label:'Ativas Totais'},\n  {code:'9001',label:'Atingimento 100% ambas marcas'},\n  {code:'9002',label:'Migradas Ouro +'},\n  {code:'481',label:'Faturamento Natura'},\n  {code:'486',label:'Faturamento Avon'},\n  {code:'469',label:'Volume de Pontos Natura'},\n  {code:'472',label:'Volume de Pontos Avon'},\n  {code:'379',label:'Inícios'},\n  {code:'32',label:'Quantidade de Cadastros'},\n  {code:'392',label:'Saldo'}\n];\nfunction kpiLabel(code){ const k=KPIS.find(x=>String(x.code)===String(code)); return k?k.label:(code||'—'); }\nconst OP_LABEL = { gte:'≥', gt:'>', eq:'=' };\nconst PERFIL_LABEL = { lider:'Líder', gn:'GN' };\nconst REDE_LABEL = { rede1:'Rede 1', rede2:'Rede 2' };\n\nfunction summarize(b){\n  const conds=(b.conditions||[]);\n  const type=b.payoutType||b.basis||'flat';\n  const val=(b.payoutValue!=null?b.payoutValue:b.amount)||0;\n  if(type==='per-unit'){\n    return `${money(val)} por unidade de ${esc(kpiLabel(b.perUnitKpiCode))}`;\n  }\n  if(conds.length===0) return `${money(val)} (sem condições)`;\n  const parts=conds.map(c=>`${esc(kpiLabel(c.kpiCode))} ${OP_LABEL[c.op]||c.op} ${esc(c.threshold)}${c.metric==='value'?'':'%'}`);\n  return `Se ${parts.join(' E ')} → ${money(val)}`;\n}\n\nexport default {\n  css: `\n  :host{display:block}\n  .wrap{display:flex;flex-direction:column;gap:16px}\n  .toolbar{display:flex;justify-content:flex-end}\n  .add-btn{padding:10px 18px;border:none;border-radius:11px;background:var(--grad);color:#fff;font:700 13px/1 var(--fam);cursor:pointer;\n    box-shadow:0 4px 12px rgba(229,0,75,.25);transition:filter .15s,transform .1s;display:inline-flex;align-items:center;gap:7px}\n  .add-btn:hover{filter:brightness(1.06)} .add-btn:active{transform:scale(.97)}\n  .ic-svg{display:block;flex:0 0 auto}\n  .add-btn .ic-svg{width:15px;height:15px}\n  .act .ic-svg{width:15px;height:15px}\n  .addc .ic-svg{width:13px;height:13px;display:inline-block;vertical-align:-2px}\n  .cond .rm .ic-svg{width:16px;height:16px}\n  .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:16px}\n  .card{background:var(--surface);border:1px solid var(--hair);border-radius:16px;padding:18px;box-shadow:var(--shadowcard);\n    display:flex;flex-direction:column;gap:12px;transition:box-shadow .18s,transform .18s;position:relative}\n  .card:hover{box-shadow:var(--shadowraised);transform:translateY(-2px)}\n  .card.flash{animation:flash .8s ease-out}\n  @keyframes flash{0%{box-shadow:0 0 0 3px rgba(41,172,86,.5)}100%{box-shadow:var(--shadowcard)}}\n  .top{display:flex;align-items:flex-start;gap:10px}\n  .badge{font:800 15px/1.2 var(--fam);color:var(--ink)}\n  .ptag{margin-left:auto;font:800 12px/1 var(--fam);padding:6px 10px;border-radius:999px;white-space:nowrap}\n  .ptag.flat{background:rgba(41,172,86,.12);color:var(--money)}\n  .ptag.unit{background:rgba(247,190,0,.16);color:#9a7500}\n  .subs{display:flex;gap:6px;flex-wrap:wrap}\n  .chip{font:700 10px/1 var(--fam);padding:5px 8px;border-radius:999px}\n  .chip.perfil{background:rgba(229,0,75,.10);color:var(--mag)}\n  .chip.rede{background:var(--ground);color:var(--muted)}\n  .summary{font:500 13px/1.5 var(--fam);color:var(--ink);background:var(--ground);border-radius:10px;padding:11px 13px}\n  .summary b{color:var(--money);font-weight:800}\n  .acts{display:flex;gap:8px;margin-top:2px}\n  .act{flex:0 0 auto;padding:8px 12px;border:1px solid var(--hair);border-radius:9px;background:var(--surface);color:var(--muted);\n    font:700 12px/1 var(--fam);cursor:pointer;transition:background .15s,color .15s,border-color .15s;display:inline-flex;align-items:center;gap:5px}\n  .act:hover{background:var(--ground);color:var(--ink)}\n  .act.edit:hover{color:var(--mag);border-color:var(--mag)}\n  .act.del{margin-left:auto}\n  .act.del:hover{color:#d92d20;border-color:#d92d20}\n  .act.del.confirm{background:#d92d20;color:#fff;border-color:#d92d20}\n  .empty{padding:40px;text-align:center;color:var(--muted);font:500 13px/1.4 var(--fam);grid-column:1/-1}\n\n  .modal-bg{position:fixed;inset:0;background:rgba(16,24,40,.42);z-index:9200;display:flex;align-items:center;justify-content:center;\n    opacity:0;transition:opacity .2s;padding:24px}\n  .modal-bg.in{opacity:1}\n  .modal{background:var(--surface);border-radius:20px;box-shadow:var(--shadowraised);width:min(560px,100%);max-height:88vh;overflow:auto;padding:24px 26px;\n    transform:translateY(14px) scale(.98);transition:transform .24s cubic-bezier(.34,1.4,.64,1)}\n  .modal-bg.in .modal{transform:none}\n  .modal h2{margin:0 0 4px;font:800 20px/1.1 var(--fam);color:var(--ink)}\n  .modal .msub{margin:0 0 18px;font:500 12px/1.4 var(--fam);color:var(--muted)}\n  .field{display:flex;flex-direction:column;gap:6px;margin-bottom:14px}\n  .field>label{font:600 11px/1 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.05em}\n  .field input,.field select{width:100%;max-width:100%;box-sizing:border-box;padding:10px 12px;border:1.5px solid var(--hair);border-radius:10px;font:600 14px/1 var(--fam);color:var(--ink);outline:none;background:var(--surface);transition:border-color .15s}\n  .field input:focus,.field select:focus{border-color:var(--mag)}\n  .frow{display:flex;gap:12px;flex-wrap:wrap}\n  .frow .field{flex:1 1 0;min-width:0}\n  .sect{border:1px solid var(--hair);border-radius:14px;padding:14px;margin-bottom:14px;background:var(--ground)}\n  .sect>.st{display:flex;align-items:center;margin-bottom:10px}\n  .sect .st b{font:800 12px/1 var(--fam);color:var(--ink);text-transform:uppercase;letter-spacing:.05em}\n  .sect .st .addc{margin-left:auto;border:1px dashed var(--mag);color:var(--mag);background:none;border-radius:9px;padding:6px 10px;font:700 11px/1 var(--fam);cursor:pointer}\n  .cond{display:flex;flex-wrap:wrap;gap:8px;align-items:flex-end;background:var(--surface);border:1px solid var(--hair);border-radius:11px;padding:10px;margin-bottom:8px;box-sizing:border-box}\n  .cond .field{margin:0;min-width:0}\n  .cond .kpi{flex:2 1 120px;min-width:0}.cond .met{flex:1.2 1 100px;min-width:0}.cond .op{flex:.7 1 64px;min-width:0}.cond .th{flex:.9 1 80px;min-width:0}\n  .cond .rm{flex:0 0 auto;align-self:flex-end;border:none;background:none;color:var(--muted);cursor:pointer;font:800 16px/1 var(--fam);padding:8px 4px}\n  .cond .rm:hover{color:#d92d20}\n  .noconds{font:500 12px/1.4 var(--fam);color:var(--muted);text-align:center;padding:8px}\n  .toggle{display:inline-flex;background:var(--surface);border:1px solid var(--hair);border-radius:10px;padding:3px;gap:2px}\n  .toggle button{border:none;background:none;padding:9px 14px;border-radius:8px;font:700 12px/1 var(--fam);color:var(--muted);cursor:pointer;transition:background .15s,color .15s}\n  .toggle button.on{background:var(--grad);color:#fff}\n  .preview{border:1.5px dashed var(--mag);border-radius:12px;padding:13px 15px;margin-bottom:6px;background:rgba(229,0,75,.04)}\n  .preview .pl{font:700 10px/1 var(--fam);color:var(--mag);text-transform:uppercase;letter-spacing:.06em;margin-bottom:6px}\n  .preview .pv{font:600 14px/1.5 var(--fam);color:var(--ink)}\n  .mfoot{display:flex;gap:10px;justify-content:flex-end;margin-top:20px}\n  .btn{padding:11px 20px;border-radius:11px;font:700 13px/1 var(--fam);cursor:pointer;border:none;transition:filter .15s,transform .1s,background .15s}\n  .btn.ghost{background:var(--ground);color:var(--muted)} .btn.ghost:hover{background:var(--hair)}\n  .btn.prim{background:var(--grad);color:#fff;box-shadow:0 4px 12px rgba(229,0,75,.28)} .btn.prim:hover{filter:brightness(1.06)} .btn.prim:active{transform:scale(.97)}\n  @media (prefers-reduced-motion: reduce){ .card,.add-btn,.act,.toggle button,.btn,.modal-bg,.modal,.field input,.field select{transition:none!important} .card:hover{transform:none} .card.flash{animation:none!important} }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const bonuses = d2.param('bonuses',[]) || [];\n    const flashId = d2.param('flashId','');\n    const confirmDel = d2.state.confirmDel || '';\n    const vars = cssVars(t);\n\n    const toolbar = `<div class=\"toolbar\"><button class=\"add-btn\" data-new>${ICON.plus} Nova regra de bônus</button></div>`;\n\n    let cards;\n    if(bonuses.length===0){\n      cards = `<div class=\"empty\">Nenhuma regra de bônus neste perfil. Crie a primeira com “Nova regra de bônus”.</div>`;\n    } else {\n      cards = bonuses.map(b=>{\n        const isUnit=(b.payoutType||b.basis)==='per-unit';\n        const val=(b.payoutValue!=null?b.payoutValue:b.amount)||0;\n        const summ=summarize(b).replace(money(val), '<b>'+money(val)+'</b>');\n        const confirming = confirmDel===b._id;\n        return `<div class=\"card ${flashId===b._id?'flash':''}\" data-key=\"${esc(b._id)}\" data-id=\"${esc(b._id)}\">\n          <div class=\"top\">\n            <div class=\"badge\">${esc(b.label||b.bonusType||'Bônus')}</div>\n            <span class=\"ptag ${isUnit?'unit':'flat'}\">${isUnit?'Por unidade':'Total fixo'}</span>\n          </div>\n          <div class=\"subs\">\n            <span class=\"chip perfil\">${esc(PERFIL_LABEL[b.perfil]||b.perfil||'')}</span>\n            <span class=\"chip rede\">${esc(REDE_LABEL[b.rede]||b.rede||'')}</span>\n          </div>\n          <div class=\"summary\">${summ}</div>\n          <div class=\"acts\">\n            <button class=\"act edit\" data-edit=\"${esc(b._id)}\">${ICON.edit} Editar</button>\n            <button class=\"act dup\" data-dup=\"${esc(b._id)}\">${ICON.dup} Duplicar</button>\n            <button class=\"act del ${confirming?'confirm':''}\" data-del=\"${esc(b._id)}\">${confirming?'Confirmar?':ICON.del+' Excluir'}</button>\n          </div>\n        </div>`;\n      }).join('');\n    }\n\n    return `<div class=\"wrap\" style=\"${vars}\">\n      ${toolbar}\n      <div class=\"grid\">${cards}</div>\n      ${renderModal(d2,t)}\n    </div>`;\n  },\n  mounted(d2){\n    d2.on('[data-new]','click',()=>openModal(d2,blank(d2)));\n    d2.on('[data-edit]','click',(e,el)=>{ const b=findBonus(d2,el.dataset.edit); if(b) openModal(d2,toDraft(b)); });\n    d2.on('[data-dup]','click',(e,el)=>{ const b=findBonus(d2,el.dataset.dup); if(!b) return; const dr=toDraft(b); delete dr._id; dr.label=(dr.label||'Bônus')+' (cópia)'; openModal(d2,dr); });\n    d2.on('[data-del]','click',(e,el)=>{\n      const id=el.dataset.del;\n      if(d2.state.confirmDel===id){\n        const b=findBonus(d2,id);\n        d2.setState({confirmDel:''});\n        if(b) d2.bus.emit('rule:bonus:del', b);\n      } else {\n        d2.setState({confirmDel:id});\n        setTimeout(()=>{ if(d2.state.confirmDel===id) d2.setState({confirmDel:''}); }, 3200);\n      }\n    });\n\n    d2.on('[data-mf]','input',(e,el)=>{ const m={...(d2.state.modal||{})}; m[el.dataset.mf]=el.value; d2.state.modal=m; d2.refresh(); });\n    d2.on('[data-mf]','change',(e,el)=>{ const m={...(d2.state.modal||{})}; m[el.dataset.mf]=el.value; d2.state.modal=m; d2.refresh(); });\n    d2.on('[data-ptype]','click',(e,el)=>{ const m={...(d2.state.modal||{})}; m.payoutType=el.dataset.ptype; d2.state.modal=m; d2.refresh(); });\n\n    d2.on('[data-addcond]','click',()=>{ const m={...(d2.state.modal||{})}; const cs=(m.conditions||[]).slice(); cs.push({kpiCode:'545',metric:'atingimento',op:'gte',threshold:100}); m.conditions=cs; d2.state.modal=m; d2.refresh(); });\n    d2.on('[data-rmcond]','click',(e,el)=>{ const i=Number(el.dataset.rmcond); const m={...(d2.state.modal||{})}; const cs=(m.conditions||[]).slice(); cs.splice(i,1); m.conditions=cs; d2.state.modal=m; d2.refresh(); });\n    d2.on('[data-cf]','input',(e,el)=>updCond(d2,el));\n    d2.on('[data-cf]','change',(e,el)=>updCond(d2,el));\n\n    d2.on('[data-mclose]','click',()=>d2.setState({modalOpen:false}));\n    d2.on('[data-mbg]','click',(e,el)=>{ if(e.target===el) d2.setState({modalOpen:false}); });\n    d2.on('[data-msave]','click',()=>saveModal(d2));\n  }\n};\n\nfunction cssVars(t){\n  return `--surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient};--money:${t.color.money};--fam:${t.type.family};--shadowcard:${t.shadow.card};--shadowraised:${t.shadow.raised}`;\n}\nfunction findBonus(d2,id){ return (d2.param('bonuses',[])||[]).find(x=>x._id===id); }\nfunction blank(d2){ return { label:'', perfil:(d2.param('perfilHint','')||'lider'), rede:'rede1', bonusType:'', conditions:[], payoutType:'flat', payoutValue:1000, perUnitKpiCode:'9002', rulesetVersion:1 }; }\nfunction toDraft(b){ return {\n  _id:b._id, label:b.label||'', perfil:b.perfil||'lider', rede:b.rede||'rede1', bonusType:b.bonusType||'',\n  conditions:(b.conditions||[]).map(c=>({kpiCode:String(c.kpiCode),metric:c.metric||'atingimento',op:c.op||'gte',threshold:c.threshold})),\n  payoutType:b.payoutType||b.basis||'flat', payoutValue:(b.payoutValue!=null?b.payoutValue:b.amount)||0, perUnitKpiCode:b.perUnitKpiCode||'9002',\n  rulesetVersion:b.rulesetVersion||1\n}; }\nfunction openModal(d2,draft){ d2.setState({modalOpen:true, modal:draft, confirmDel:''}); }\nfunction updCond(d2,el){\n  const i=Number(el.dataset.i); const key=el.dataset.cf;\n  const m={...(d2.state.modal||{})}; const cs=(m.conditions||[]).slice();\n  const c={...(cs[i]||{})}; c[key]=el.value; cs[i]=c; m.conditions=cs; d2.state.modal=m; d2.refresh();\n}\nfunction normalize(m){\n  const isUnit=m.payoutType==='per-unit';\n  const conds=(m.conditions||[]).map(c=>({kpiCode:String(c.kpiCode),metric:c.metric||'atingimento',op:c.op||'gte',threshold:Number(c.threshold)||0}));\n  const val=Number(m.payoutValue)||0;\n  const row={\n    rulesetVersion:Number(m.rulesetVersion)||1, perfil:m.perfil||'lider', rede:m.rede||'rede1',\n    bonusType:m.bonusType|| (isUnit?'per-unit-bonus':'condition-bonus'),\n    label:m.label||'Bônus', conditions:isUnit?[]:conds,\n    payoutType:isUnit?'per-unit':'flat', payoutValue:val, perUnitKpiCode:isUnit?String(m.perUnitKpiCode||''):'',\n    amount:val, basis:isUnit?'per-unit':'flat'\n  };\n  if(m._id) row._id=m._id;\n  return row;\n}\nfunction saveModal(d2){\n  const row=normalize(d2.state.modal||{});\n  d2.setState({modalOpen:false});\n  d2.bus.emit('rule:bonus:save', row);\n}\nfunction opt(v,l,cur){ return `<option value=\"${esc(v)}\" ${String(cur)===String(v)?'selected':''}>${esc(l)}</option>`; }\nfunction kpiOpts(cur){ return KPIS.map(k=>opt(k.code,k.label,cur)).join(''); }\nfunction renderModal(d2,t){\n  if(!d2.state.modalOpen) return '';\n  const m=d2.state.modal||{};\n  const isNew=!m._id;\n  const isUnit=m.payoutType==='per-unit';\n  const conds=m.conditions||[];\n  const condRows = conds.length? conds.map((c,i)=>`\n    <div class=\"cond\" data-key=\"cond-${i}\">\n      <div class=\"field kpi\"><label>Indicador</label><select data-cf=\"kpiCode\" data-i=\"${i}\">${kpiOpts(c.kpiCode)}</select></div>\n      <div class=\"field met\"><label>Métrica</label><select data-cf=\"metric\" data-i=\"${i}\">${opt('atingimento','Atingimento %',c.metric)}${opt('value','Valor',c.metric)}</select></div>\n      <div class=\"field op\"><label>Op.</label><select data-cf=\"op\" data-i=\"${i}\">${opt('gte','≥',c.op)}${opt('gt','>',c.op)}${opt('eq','=',c.op)}</select></div>\n      <div class=\"field th\"><label>Limite</label><input type=\"number\" step=\"0.01\" data-cf=\"threshold\" data-i=\"${i}\" value=\"${esc(c.threshold)}\"/></div>\n      <button class=\"rm\" data-rmcond=\"${i}\" title=\"Remover\">${ICON.x}</button>\n    </div>`).join('') : `<div class=\"noconds\">Nenhuma condição — o bônus é pago sempre (útil para aceleradores por unidade).</div>`;\n\n  return `<div class=\"modal-bg in\" data-mbg>\n    <div class=\"modal\">\n      <h2>${isNew?'Nova regra de bônus':'Editar regra de bônus'}</h2>\n      <p class=\"msub\">Defina condições sobre indicadores e o pagamento. Nomes amigáveis dos indicadores.</p>\n\n      <div class=\"field\"><label>Nome da regra</label><input type=\"text\" data-mf=\"label\" value=\"${esc(m.label||'')}\" placeholder=\"Ex.: Ambas as marcas 100%\"/></div>\n\n      <div class=\"frow\">\n        <div class=\"field\"><label>Perfil</label><select data-mf=\"perfil\">${opt('lider','Líder',m.perfil)}${opt('gn','GN',m.perfil)}</select></div>\n        <div class=\"field\"><label>Rede</label><select data-mf=\"rede\">${opt('rede1','Rede 1',m.rede)}${opt('rede2','Rede 2',m.rede)}</select></div>\n      </div>\n\n      <div class=\"sect\">\n        <div class=\"st\"><b>Condições${isUnit?' (ignoradas em Por unidade)':''}</b><button class=\"addc\" data-addcond>${ICON.plus} Condição</button></div>\n        ${condRows}\n      </div>\n\n      <div class=\"sect\">\n        <div class=\"st\"><b>Pagamento</b></div>\n        <div class=\"field\"><label>Tipo</label>\n          <div class=\"toggle\">\n            <button data-ptype=\"flat\" class=\"${!isUnit?'on':''}\">Total fixo</button>\n            <button data-ptype=\"per-unit\" class=\"${isUnit?'on':''}\">Por unidade</button>\n          </div>\n        </div>\n        <div class=\"frow\">\n          <div class=\"field\"><label>${isUnit?'Valor por unidade (R$)':'Valor total (R$)'}</label><input type=\"number\" step=\"0.01\" data-mf=\"payoutValue\" value=\"${esc(m.payoutValue)}\"/></div>\n          ${isUnit?`<div class=\"field\"><label>Indicador (contagem)</label><select data-mf=\"perUnitKpiCode\">${kpiOpts(m.perUnitKpiCode)}</select></div>`:''}\n        </div>\n      </div>\n\n      <div class=\"preview\">\n        <div class=\"pl\">Pré-visualização</div>\n        <div class=\"pv\">${summarize(normalize(m)).replace(money(Number(m.payoutValue)||0),'<b>'+money(Number(m.payoutValue)||0)+'</b>')}</div>\n      </div>\n\n      <div class=\"mfoot\">\n        <button class=\"btn ghost\" data-mclose>Cancelar</button>\n        <button class=\"btn prim\" data-msave>${isNew?'Criar bônus':'Salvar'}</button>\n      </div>\n    </div>\n  </div>`;\n}"}},"bonuses":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bonuses"}}}},"flashId":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"flashId"}}}},"perfilHint":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"perfilHint"}}}}}}}}}},{"_id":"6a4c1498dc1636e8597b46b5","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotRuleFormulaEditor","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',avonMagenta:'#E5014B',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',gold:'#F7BE00',money:'#29AC56'},\n  radius:{sm:8,md:12,lg:16,pill:999},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\",h1:'28px',h2:'20px',title:'15px',body:'13px',caption:'11px'},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nconst ICON = (()=>{\n  const S = (p)=>`<svg class=\"ic-svg\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${p}</svg>`;\n  return {\n    x:S('<path d=\"M18 6 6 18M6 6l12 12\"/>'),\n    plus:S('<path d=\"M12 5v14M5 12h14\"/>'),\n    up:S('<path d=\"m6 15 6-6 6 6\"/>'),\n    down:S('<path d=\"m6 9 6 6 6-6\"/>'),\n    left:S('<path d=\"m15 18-6-6 6-6\"/>'),\n    right:S('<path d=\"m9 18 6-6-6-6\"/>')\n  };\n})();\nconst PERFIL_LABEL = { 'lider':'Líder','gn':'GN' };\nconst BRAND_LABEL = { 'natura':'Natura','avon':'Avon','':'Total' };\n// sample group per rede for the live R$ result\nconst SAMPLE = { rede1: { code:'20200', cycle:'202516' }, rede2: { code:'20202', cycle:'202516' } };\n\nfunction clone(o){ return JSON.parse(JSON.stringify(o||{})); }\nfunction emptyStructure(){ return { parcelas: [] }; }\n// Friendly label for a factor.\nfunction factorLabel(f, bandTables){\n  if(!f) return '';\n  if(f.kind==='const') return String(f.n==null?1:f.n);\n  if(f.kind==='kpi'){ return f.label || ('KPI '+(f.kpiCode||'')); }\n  // band-table\n  const bt = (bandTables||[]).find(t=>t.ref===f.ref);\n  const base = f.label || (bt ? bt.label : (f.ref||'faixa'));\n  return base + (f.brand ? (' · '+(BRAND_LABEL[f.brand]||f.brand)) : '');\n}\nfunction factorKindTag(f){\n  if(!f) return '';\n  if(f.kind==='const') return 'const';\n  if(f.kind==='kpi') return 'KPI';\n  return 'faixa';\n}\n// Human-readable expression line for a structure.\nfunction humanLine(structure, bandTables){\n  const parcelas = (structure&&structure.parcelas)||[];\n  if(!parcelas.length) return '—';\n  const parts = parcelas.map(p=>{\n    const facs = (p.factors||[]);\n    if(!facs.length) return '( )';\n    const inner = facs.map((f,i)=>{\n      const op = i===0 ? '' : (f.op==='div'?' ÷ ':' × ');\n      return op + factorLabel(f, bandTables);\n    }).join('');\n    return '('+inner.trim()+')';\n  });\n  return parts.join(' + ') + ' + bônus';\n}\n\nexport default {\n  css: `\n  :host{display:block}\n  .banner{display:flex;gap:12px;align-items:flex-start;background:rgba(41,172,86,.10);border:1px solid rgba(41,172,86,.32);\n    border-radius:14px;padding:14px 16px;margin-bottom:18px}\n  .banner .ic{font-size:18px;line-height:1.2}\n  .banner .txt{font:500 12.5px/1.5 var(--fam);color:#1c7a43}\n  .banner .txt b{font-weight:800;color:#14663a}\n  .banner .tag{display:inline-block;font:800 9px/1 var(--fam);letter-spacing:.08em;text-transform:uppercase;color:#14663a;\n    background:rgba(41,172,86,.20);padding:4px 7px;border-radius:6px;margin-left:6px;vertical-align:middle}\n  .grid{display:flex;flex-direction:column;gap:16px}\n  .card{background:var(--surface);border:1px solid var(--hair);border-radius:16px;padding:18px;box-shadow:var(--shadowcard);display:flex;flex-direction:column;gap:14px;position:relative}\n  .card.flash{animation:flash .8s ease-out}\n  @keyframes flash{0%{box-shadow:0 0 0 3px rgba(41,172,86,.5)}100%{box-shadow:var(--shadowcard)}}\n  .head{display:flex;align-items:center;gap:8px}\n  .chip{font:700 10px/1 var(--fam);padding:5px 8px;border-radius:999px;text-transform:capitalize}\n  .chip.perfil{background:rgba(229,0,75,.10);color:var(--mag)}\n  .chip.rede{background:var(--ground);color:var(--muted)}\n  .badge-live{margin-left:auto;font:800 9px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;color:#14663a;background:rgba(41,172,86,.16);padding:5px 9px;border-radius:999px}\n  .preview{font:600 13px/1.6 'SF Mono',ui-monospace,Menlo,monospace;color:var(--ink);background:var(--ground);border-radius:10px;padding:12px 14px;word-break:break-word}\n  .preview .b{color:var(--mag);font-weight:700}\n  .resline{display:flex;align-items:center;gap:10px;flex-wrap:wrap}\n  .resbox{display:flex;align-items:baseline;gap:8px;background:linear-gradient(135deg,rgba(41,172,86,.10),rgba(41,172,86,.03));border:1px solid rgba(41,172,86,.28);border-radius:12px;padding:10px 16px}\n  .resbox .lbl{font:600 10px/1 var(--fam);text-transform:uppercase;letter-spacing:.05em;color:#1c7a43}\n  .resbox .val{font:800 22px/1 var(--fam);color:#14663a;letter-spacing:-.5px}\n  .resbox.dirty .val{color:var(--naturaOrange,#EB6619)}\n  .resbox .spin{width:13px;height:13px;border:2px solid rgba(41,172,86,.25);border-top-color:#29AC56;border-radius:50%;animation:sp .7s linear infinite;align-self:center}\n  @keyframes sp{to{transform:rotate(360deg)}}\n  .samplenote{font:500 11px/1.3 var(--fam);color:var(--muted)}\n  .parcelas{display:flex;flex-direction:column;gap:10px}\n  .parcela{border:1.5px dashed var(--hair);border-radius:14px;padding:12px 12px 12px 14px;background:var(--ground);position:relative}\n  .parcela .ptop{display:flex;align-items:center;gap:8px;margin-bottom:10px}\n  .parcela .pname{font:700 12px/1 var(--fam);color:var(--ink)}\n  .parcela .pval{font:700 11px/1 var(--fam);color:#1c7a43;background:rgba(41,172,86,.12);padding:4px 8px;border-radius:999px}\n  .parcela .pctl{margin-left:auto;display:flex;gap:4px}\n  .iconbtn{border:none;background:var(--surface);border:1px solid var(--hair);width:26px;height:26px;border-radius:8px;cursor:pointer;font:700 12px/1 var(--fam);color:var(--muted);display:inline-flex;align-items:center;justify-content:center;transition:background .12s,color .12s,transform .1s}\n  .iconbtn:hover{background:var(--hair);color:var(--ink)} .iconbtn:active{transform:scale(.92)}\n  .iconbtn.del:hover{background:rgba(214,20,25,.12);color:#d61419;border-color:rgba(214,20,25,.3)}\n  .iconbtn[disabled]{opacity:.3;cursor:default}\n  .ic-svg{display:block;flex:0 0 auto}\n  .iconbtn .ic-svg{width:15px;height:15px}\n  .mini .ic-svg{width:13px;height:13px}\n  .addfac .ic-svg,.addparc .ic-svg{width:14px;height:14px;display:inline-block;vertical-align:-2px}\n  .plus .ic-svg{width:18px;height:18px}\n  .chain{display:flex;align-items:center;gap:6px;flex-wrap:wrap}\n  .fchip{display:inline-flex;align-items:center;gap:7px;background:var(--surface);border:1.5px solid var(--hair);border-radius:999px;padding:7px 10px 7px 12px;transition:border-color .12s,box-shadow .12s}\n  .fchip:hover{border-color:var(--mag);box-shadow:0 2px 8px rgba(229,0,75,.12)}\n  .fchip .knd{font:800 8px/1 var(--fam);letter-spacing:.05em;text-transform:uppercase;padding:3px 5px;border-radius:5px}\n  .fchip .knd.faixa{background:rgba(72,152,255,.16);color:#1462c7}\n  .fchip .knd.KPI{background:rgba(229,0,75,.12);color:var(--mag)}\n  .fchip .knd.const{background:rgba(41,172,86,.14);color:var(--money)}\n  .fchip .lab{font:600 12px/1 var(--fam);color:var(--ink)}\n  .fchip .fctl{display:inline-flex;gap:2px;margin-left:2px}\n  .fchip .mini{border:none;background:none;cursor:pointer;color:var(--muted);font:700 11px/1 var(--fam);padding:2px 3px;border-radius:5px;transition:background .12s,color .12s}\n  .fchip .mini:hover{background:var(--hair);color:var(--ink)}\n  .fchip .mini.x:hover{background:rgba(214,20,25,.14);color:#d61419}\n  .fchip .mini[disabled]{opacity:.25;cursor:default}\n  .oppill{border:1.5px solid var(--hair);background:var(--surface);width:30px;height:30px;border-radius:999px;cursor:pointer;font:800 15px/1 var(--fam);color:var(--mag);display:inline-flex;align-items:center;justify-content:center;transition:background .12s,transform .1s}\n  .oppill:hover{background:rgba(229,0,75,.08)} .oppill:active{transform:scale(.9)}\n  .addfac{border:1.5px dashed var(--hair);background:none;border-radius:999px;padding:7px 12px;cursor:pointer;font:700 11px/1 var(--fam);color:var(--muted);transition:border-color .12s,color .12s}\n  .addfac:hover{border-color:var(--mag);color:var(--mag)}\n  .plus{display:flex;align-items:center;justify-content:center;font:800 20px/1 var(--fam);color:var(--mag);opacity:.8;padding:2px 0}\n  .addparc{align-self:flex-start;border:1.5px dashed var(--mag);background:rgba(229,0,75,.05);border-radius:12px;padding:9px 16px;cursor:pointer;font:700 12px/1 var(--fam);color:var(--mag);transition:background .12s}\n  .addparc:hover{background:rgba(229,0,75,.10)}\n  .actions{display:flex;align-items:center;gap:10px;border-top:1px solid var(--hair);padding-top:14px}\n  .save{margin-left:auto;padding:10px 20px;border:none;border-radius:10px;background:var(--grad);color:#fff;font:700 13px/1 var(--fam);cursor:pointer;\n    box-shadow:0 4px 12px rgba(229,0,75,.25);transition:filter .15s,transform .1s,opacity .15s}\n  .save:hover{filter:brightness(1.06)} .save:active{transform:scale(.97)}\n  .save[disabled]{opacity:.4;cursor:default;box-shadow:none}\n  .reset{padding:10px 14px;border:1px solid var(--hair);border-radius:10px;background:var(--surface);color:var(--muted);font:700 12px/1 var(--fam);cursor:pointer}\n  .reset[disabled]{opacity:.3;cursor:default}\n  .empty{padding:40px;text-align:center;color:var(--muted);font:500 13px/1.4 var(--fam)}\n  /* picker popover */\n  .pk-bg{position:fixed;inset:0;background:rgba(16,24,40,.42);z-index:9000;display:flex;align-items:center;justify-content:center;padding:24px}\n  .pk{background:var(--surface);border-radius:18px;box-shadow:var(--shadowraised);width:min(440px,100%);max-height:80vh;overflow:auto;padding:22px 24px}\n  .pk h3{margin:0 0 4px;font:800 18px/1.1 var(--fam);color:var(--ink)}\n  .pk .sub{margin:0 0 16px;font:500 12px/1.4 var(--fam);color:var(--muted)}\n  .pk .seg{display:inline-flex;background:var(--ground);border-radius:10px;padding:3px;gap:2px;margin-bottom:14px}\n  .pk .seg button{border:none;background:none;padding:7px 13px;border-radius:8px;font:700 12px/1 var(--fam);color:var(--muted);cursor:pointer}\n  .pk .seg button.on{background:var(--surface);color:var(--ink);box-shadow:0 1px 2px rgba(16,24,40,.1)}\n  .pk .opt{display:flex;align-items:center;gap:10px;padding:11px 12px;border:1px solid var(--hair);border-radius:11px;margin-bottom:8px;cursor:pointer;transition:border-color .12s,background .12s}\n  .pk .opt:hover{border-color:var(--mag);background:rgba(229,0,75,.04)}\n  .pk .opt .nm{font:700 13px/1.2 var(--fam);color:var(--ink)}\n  .pk .opt .mt{font:500 11px/1.2 var(--fam);color:var(--muted);margin-top:2px}\n  .pk .brandrow{display:flex;gap:8px;margin:6px 0 14px}\n  .pk .brandrow button{flex:1;border:1.5px solid var(--hair);background:var(--surface);border-radius:10px;padding:9px;font:700 12px/1 var(--fam);color:var(--muted);cursor:pointer;transition:border-color .12s,color .12s}\n  .pk .brandrow button.on{border-color:var(--mag);color:var(--mag);background:rgba(229,0,75,.06)}\n  .pk .constrow{display:flex;gap:10px;align-items:center;margin-bottom:14px}\n  .pk .constrow input{flex:1;padding:11px 13px;border:1.5px solid var(--hair);border-radius:10px;font:600 15px/1 var(--fam);color:var(--ink);outline:none}\n  .pk .constrow input:focus{border-color:var(--mag)}\n  .pk .pkfoot{display:flex;gap:10px;justify-content:flex-end;margin-top:8px}\n  .pk .btn{padding:10px 18px;border-radius:10px;font:700 13px/1 var(--fam);cursor:pointer;border:none}\n  .pk .btn.ghost{background:var(--ground);color:var(--muted)}\n  .pk .btn.prim{background:var(--grad);color:#fff}\n  @media (prefers-reduced-motion: reduce){ .save,.iconbtn,.oppill,.addparc,.fchip{transition:none!important} .card.flash{animation:none!important} .spin{animation:none} }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const formulas = d2.param('formulas',[]) || [];\n    const bandTables = d2.param('bandTables',[]) || [];\n    const flashId = d2.param('flashId','');\n    const drafts = d2.state.drafts || {};\n    const previews = d2.state.previews || {};\n    const vars = cssVars(t);\n    const banner = `<div class=\"banner\">\n      <span class=\"ic\">✅</span>\n      <div class=\"txt\"><b>Fórmulas estruturadas são interpretadas ao vivo pelo cálculo.</b>\n      Monte a remuneração com blocos amigáveis — cada edição salva altera o ganho real (sem string <code>Formula()</code>).\n      <span class=\"tag\">Afeta o cálculo ao vivo</span></div>\n    </div>`;\n    if(formulas.length===0){\n      return `<div style=\"${vars}\">${banner}<div class=\"grid\"><div class=\"card\"><div class=\"empty\">Nenhuma fórmula neste perfil.</div></div></div></div>`;\n    }\n    const cards = formulas.map(fm=>{\n      const draft = drafts[fm._id];\n      const structure = draft!=null ? draft : (fm.structure || emptyStructure());\n      const savedStr = JSON.stringify(fm.structure || emptyStructure());\n      const dirty = JSON.stringify(structure) !== savedStr;\n      const pv = previews[fm._id] || {};\n      return renderCard(d2, t, fm, structure, dirty, pv, bandTables, flashId);\n    }).join('');\n    return `<div style=\"${vars}\">${banner}<div class=\"grid\">${cards}</div>${renderPicker(d2,t,bandTables)}</div>`;\n  },\n  mounted(d2){\n    d2.state.drafts = d2.state.drafts || {};\n    d2.state.previews = d2.state.previews || {};\n    // kick an initial preview for each formula (saved structure)\n    (d2.param('formulas',[])||[]).forEach(fm=>{ recompute(d2, fm._id); });\n\n    d2.on('[data-optoggle]','click',(e,el)=>{\n      const {fm,p,f}=parseTriple(el.dataset.optoggle);\n      mutate(d2,fm,st=>{ const fac=st.parcelas[p].factors[f]; fac.op = (fac.op==='div')?'mul':'div'; });\n    });\n    d2.on('[data-fdel]','click',(e,el)=>{\n      const {fm,p,f}=parseTriple(el.dataset.fdel);\n      mutate(d2,fm,st=>{ st.parcelas[p].factors.splice(f,1); });\n    });\n    d2.on('[data-fleft]','click',(e,el)=>{\n      const {fm,p,f}=parseTriple(el.dataset.fleft);\n      mutate(d2,fm,st=>{ const arr=st.parcelas[p].factors; if(f>0){ const x=arr[f]; arr[f]=arr[f-1]; arr[f-1]=x; } });\n    });\n    d2.on('[data-fright]','click',(e,el)=>{\n      const {fm,p,f}=parseTriple(el.dataset.fright);\n      mutate(d2,fm,st=>{ const arr=st.parcelas[p].factors; if(f<arr.length-1){ const x=arr[f]; arr[f]=arr[f+1]; arr[f+1]=x; } });\n    });\n    d2.on('[data-pup]','click',(e,el)=>{\n      const {fm,p}=parseDouble(el.dataset.pup);\n      mutate(d2,fm,st=>{ if(p>0){ const x=st.parcelas[p]; st.parcelas[p]=st.parcelas[p-1]; st.parcelas[p-1]=x; } });\n    });\n    d2.on('[data-pdown]','click',(e,el)=>{\n      const {fm,p}=parseDouble(el.dataset.pdown);\n      mutate(d2,fm,st=>{ if(p<st.parcelas.length-1){ const x=st.parcelas[p]; st.parcelas[p]=st.parcelas[p+1]; st.parcelas[p+1]=x; } });\n    });\n    d2.on('[data-pdel]','click',(e,el)=>{\n      const {fm,p}=parseDouble(el.dataset.pdel);\n      mutate(d2,fm,st=>{ st.parcelas.splice(p,1); });\n    });\n    d2.on('[data-addparc]','click',(e,el)=>{\n      const fm=el.dataset.addparc;\n      mutate(d2,fm,st=>{ st.parcelas.push({ label:'Parcela '+(st.parcelas.length+1), factors:[] }); });\n    });\n    d2.on('[data-addfac]','click',(e,el)=>{\n      const {fm,p}=parseDouble(el.dataset.addfac);\n      d2.setState({ picker:{ fm, p, tab:'band', brand:'natura', constVal:'1' } });\n    });\n    // picker\n    d2.on('[data-pktab]','click',(e,el)=>{ const pk={...(d2.state.picker||{})}; pk.tab=el.dataset.pktab; d2.setState({picker:pk}); });\n    d2.on('[data-pkbrand]','click',(e,el)=>{ const pk={...(d2.state.picker||{})}; pk.brand=el.dataset.pkbrand; d2.setState({picker:pk}); });\n    d2.on('[data-pkconst]','input',(e,el)=>{ const pk={...(d2.state.picker||{})}; pk.constVal=el.value; d2.state.picker=pk; });\n    d2.on('[data-pkclose]','click',()=>d2.setState({picker:null}));\n    d2.on('[data-pkbg]','click',(e,el)=>{ if(e.target===el) d2.setState({picker:null}); });\n    d2.on('[data-pkpick-band]','click',(e,el)=>{\n      const pk=d2.state.picker||{}; const ref=el.dataset.pkpickBand;\n      const bts=d2.param('bandTables',[])||[]; const bt=bts.find(x=>x.ref===ref)||{};\n      const brand = pk.brand||'natura';\n      const fac={ kind:'band-table', ref, brand, label:(bt.label||ref), op:'mul' };\n      addFactor(d2, pk.fm, pk.p, fac);\n    });\n    d2.on('[data-pkpick-kpi]','click',(e,el)=>{\n      const pk=d2.state.picker||{}; const code=el.dataset.pkpickKpi;\n      const kpis=d2.param('kpis',[])||[]; const k=kpis.find(x=>String(x.code)===String(code))||{};\n      const fac={ kind:'kpi', kpiCode:String(code), label:(k.label||k.name||('KPI '+code)), op:'mul' };\n      addFactor(d2, pk.fm, pk.p, fac);\n    });\n    d2.on('[data-pkpick-const]','click',()=>{\n      const pk=d2.state.picker||{}; const n=Number(pk.constVal); const val=isNaN(n)?1:n;\n      addFactor(d2, pk.fm, pk.p, { kind:'const', n:val, label:String(val), op:'mul' });\n    });\n    d2.on('[data-reset]','click',(e,el)=>{\n      const fm=el.dataset.reset; const d=d2.state.drafts||{}; delete d[fm]; d2.state.drafts=d; d2.refresh(); recompute(d2,fm);\n    });\n    d2.on('[data-save]','click',(e,el)=>{\n      const id=el.dataset.save;\n      const base=(d2.param('formulas',[])||[]).find(x=>x._id===id); if(!base) return;\n      const structure=(d2.state.drafts||{})[id]; if(structure==null) return;\n      const next={ ...base, structure };\n      const d=d2.state.drafts||{}; delete d[id]; d2.state.drafts=d;\n      d2.bus.emit('rule:formula:save', next);\n    });\n  }\n};\n\nfunction parseTriple(s){ const [fm,p,f]=String(s).split('|'); return { fm, p:Number(p), f:Number(f) }; }\nfunction parseDouble(s){ const [fm,p]=String(s).split('|'); return { fm, p:Number(p) }; }\n\nfunction currentStructure(d2, fmId){\n  const drafts = d2.state.drafts||{};\n  if(drafts[fmId]!=null) return clone(drafts[fmId]);\n  const base=(d2.param('formulas',[])||[]).find(x=>x._id===fmId);\n  return clone((base&&base.structure) || emptyStructure());\n}\nfunction mutate(d2, fmId, fn){\n  const st = currentStructure(d2, fmId);\n  fn(st);\n  const d = d2.state.drafts||{}; d[fmId]=st; d2.state.drafts=d;\n  d2.refresh();\n  recompute(d2, fmId);\n}\nfunction addFactor(d2, fmId, p, fac){\n  mutate(d2, fmId, st=>{ if(st.parcelas[p]){ st.parcelas[p].factors.push(fac); } });\n  d2.setState({ picker:null });\n}\nasync function recompute(d2, fmId){\n  const base=(d2.param('formulas',[])||[]).find(x=>x._id===fmId);\n  if(!base) return;\n  const st = currentStructure(d2, fmId);\n  const sample = SAMPLE[base.rede] || SAMPLE.rede1;\n  const pv = {...(d2.state.previews||{})}; pv[fmId]={...(pv[fmId]||{}), loading:true}; d2.setState({previews:pv});\n  try{\n    const r = await d2.rush('pilotGetGroupEarnings').invoke({ structureCode:sample.code, cycle:sample.cycle, structureOverride:st });\n    const data = (r && r.data) || r || {};\n    const val = data.remuneracao;\n    const base2 = data.breakdown && data.breakdown.components ? data.breakdown.components.structuredBase : null;\n    const pv2 = {...(d2.state.previews||{})};\n    pv2[fmId]={ loading:false, value:val, structuredBase:base2, sample:sample.code };\n    d2.setState({previews:pv2});\n  }catch(e){\n    const pv2={...(d2.state.previews||{})}; pv2[fmId]={ loading:false, error:true }; d2.setState({previews:pv2});\n  }\n}\n\nfunction renderCard(d2, t, fm, structure, dirty, pv, bandTables, flashId){\n  const parcelas = structure.parcelas||[];\n  const parcHtml = parcelas.map((p,pi)=>renderParcela(d2,t,fm._id,p,pi,parcelas.length,bandTables)).join(`<div class=\"plus\">${ICON.plus}</div>`);\n  const line = humanLine(structure, bandTables);\n  const resVal = pv.loading ? '' : (pv.error ? 'erro' : (pv.value!=null ? Number(pv.value).toLocaleString('pt-BR',{style:'currency',currency:'BRL'}) : '—'));\n  const sampleCode = pv.sample || (SAMPLE[fm.rede]||SAMPLE.rede1).code;\n  return `<div class=\"card ${flashId===fm._id?'flash':''}\" data-key=\"${esc(fm._id)}\">\n    <div class=\"head\">\n      <span class=\"chip perfil\">${esc(PERFIL_LABEL[fm.perfil]||fm.perfil)}</span>\n      <span class=\"chip rede\">${esc(fm.rede)}</span>\n      <span class=\"badge-live\">Estruturada · ao vivo</span>\n    </div>\n    <div class=\"preview\">${humanHtml(line)}</div>\n    <div class=\"resline\">\n      <div class=\"resbox ${dirty?'dirty':''}\">\n        <span class=\"lbl\">Ganho — grupo ${esc(sampleCode)}${dirty?' (rascunho)':''}</span>\n        ${pv.loading?`<span class=\"spin\"></span>`:`<span class=\"val\">${esc(resVal)}</span>`}\n      </div>\n      <span class=\"samplenote\">Cálculo ao vivo via motor de ganhos (mesmo avaliador do dashboard).</span>\n    </div>\n    <div class=\"parcelas\">\n      ${parcHtml || `<div class=\"samplenote\" style=\"padding:8px 2px\">Nenhuma parcela — adicione a primeira abaixo.</div>`}\n    </div>\n    <button class=\"addparc\" data-addparc=\"${esc(fm._id)}\">${ICON.plus} Parcela (nova soma)</button>\n    <div class=\"actions\">\n      <button class=\"reset\" data-reset=\"${esc(fm._id)}\" ${dirty?'':'disabled'}>Descartar</button>\n      <button class=\"save\" data-save=\"${esc(fm._id)}\" ${dirty?'':'disabled'}>Salvar fórmula</button>\n    </div>\n  </div>`;\n}\n\nfunction renderParcela(d2,t,fmId,p,pi,total,bandTables){\n  const facs = p.factors||[];\n  const key = fmId+'|'+pi;\n  let chain='';\n  facs.forEach((f,fi)=>{\n    if(fi>0){\n      const isDiv = f.op==='div';\n      chain += `<button class=\"oppill\" data-optoggle=\"${esc(fmId+'|'+pi+'|'+fi)}\" title=\"Alternar × / ÷\">${isDiv?'÷':'×'}</button>`;\n    }\n    const tag=factorKindTag(f);\n    chain += `<span class=\"fchip\">\n      <span class=\"knd ${tag}\">${esc(tag)}</span>\n      <span class=\"lab\">${esc(factorLabel(f,bandTables))}</span>\n      <span class=\"fctl\">\n        <button class=\"mini\" data-fleft=\"${esc(fmId+'|'+pi+'|'+fi)}\" ${fi===0?'disabled':''} title=\"Mover para esquerda\">${ICON.left}</button>\n        <button class=\"mini\" data-fright=\"${esc(fmId+'|'+pi+'|'+fi)}\" ${fi===facs.length-1?'disabled':''} title=\"Mover para direita\">${ICON.right}</button>\n        <button class=\"mini x\" data-fdel=\"${esc(fmId+'|'+pi+'|'+fi)}\" title=\"Remover\">${ICON.x}</button>\n      </span>\n    </span>`;\n  });\n  return `<div class=\"parcela\" data-key=\"parc-${esc(key)}\">\n    <div class=\"ptop\">\n      <span class=\"pname\">${esc(p.label||('Parcela '+(pi+1)))}</span>\n      <div class=\"pctl\">\n        <button class=\"iconbtn\" data-pup=\"${esc(key)}\" ${pi===0?'disabled':''} title=\"Subir\">${ICON.up}</button>\n        <button class=\"iconbtn\" data-pdown=\"${esc(key)}\" ${pi===total-1?'disabled':''} title=\"Descer\">${ICON.down}</button>\n        <button class=\"iconbtn del\" data-pdel=\"${esc(key)}\" title=\"Remover parcela\">${ICON.x}</button>\n      </div>\n    </div>\n    <div class=\"chain\">\n      ${chain}\n      <button class=\"addfac\" data-addfac=\"${esc(key)}\">${ICON.plus} fator</button>\n    </div>\n  </div>`;\n}\n\nfunction humanHtml(line){\n  // bold the numeric/label operators lightly\n  return esc(line).replace(/×/g,'<span class=\"b\">×</span>').replace(/÷/g,'<span class=\"b\">÷</span>').replace(/\\+/g,'<span class=\"b\">+</span>');\n}\n\nfunction renderPicker(d2,t,bandTables){\n  const pk = d2.state.picker;\n  if(!pk) return '';\n  const tab = pk.tab||'band';\n  const kpis = d2.param('kpis',[])||[];\n  // dedupe kpis by code\n  const seen={}; const kpiList=[];\n  (kpis||[]).slice().sort((a,b)=>(a.displayOrder||0)-(b.displayOrder||0)).forEach(k=>{ const c=String(k.code); if(!seen[c]){ seen[c]=1; kpiList.push({code:c,name:(k.label||k.name||c)}); } });\n  const bts = (bandTables||[]).filter(b=>b && b.ref);\n  const seg = `<div class=\"seg\">\n    <button data-pktab=\"band\" class=\"${tab==='band'?'on':''}\">Tabela de faixas</button>\n    <button data-pktab=\"kpi\" class=\"${tab==='kpi'?'on':''}\">Indicador (KPI)</button>\n    <button data-pktab=\"const\" class=\"${tab==='const'?'on':''}\">Constante</button>\n  </div>`;\n  let body='';\n  if(tab==='band'){\n    const brand=pk.brand||'natura';\n    const brow=`<div class=\"brandrow\">\n      ${[['natura','Natura'],['avon','Avon'],['','Total']].map(([v,l])=>`<button data-pkbrand=\"${v}\" class=\"${brand===v?'on':''}\">${esc(l)}</button>`).join('')}\n    </div>`;\n    const opts = bts.map(b=>`<div class=\"opt\" data-pkpick-band=\"${esc(b.ref)}\">\n      <div><div class=\"nm\">${esc(b.label||b.ref)}</div><div class=\"mt\">${esc(b.valueType==='multiplier'?'% multiplicador':'R$ fixo')} · KPI ${esc(b.kpiCode||'—')}</div></div>\n    </div>`).join('') || `<div class=\"mt\" style=\"color:${t.color.muted}\">Nenhuma tabela de faixas.</div>`;\n    body = `<p class=\"sub\">Escolha a marca e a tabela. O valor da faixa correspondente ao grupo entra no produto (multiplicador vira % automaticamente).</p>${brow}${opts}`;\n  } else if(tab==='kpi'){\n    const opts = kpiList.map(k=>`<div class=\"opt\" data-pkpick-kpi=\"${esc(k.code)}\">\n      <div><div class=\"nm\">${esc(k.name)}</div><div class=\"mt\">Valor realizado do indicador · código ${esc(k.code)}</div></div>\n    </div>`).join('') || `<div class=\"mt\">Nenhum indicador.</div>`;\n    body = `<p class=\"sub\">O valor realizado do indicador (ex.: pontos, ativas) entra direto como fator.</p>${opts}`;\n  } else {\n    body = `<p class=\"sub\">Um número fixo (ex.: 1.1 para +10%, 100 como base).</p>\n      <div class=\"constrow\"><input type=\"number\" step=\"0.01\" data-pkconst value=\"${esc(pk.constVal!=null?pk.constVal:'1')}\" placeholder=\"Ex.: 1.1\"/></div>\n      <div class=\"pkfoot\"><button class=\"btn ghost\" data-pkclose>Cancelar</button><button class=\"btn prim\" data-pkpick-const>Adicionar constante</button></div>`;\n  }\n  const foot = tab==='const' ? '' : `<div class=\"pkfoot\"><button class=\"btn ghost\" data-pkclose>Cancelar</button></div>`;\n  return `<div class=\"pk-bg\" data-pkbg><div class=\"pk\">\n    <h3>Adicionar fator</h3>\n    ${seg}\n    ${body}\n    ${foot}\n  </div></div>`;\n}\n\nfunction cssVars(t){\n  return `--surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient};--money:${t.color.money};--naturaOrange:${t.color.naturaOrange};--fam:${t.type.family};--shadowcard:${t.shadow.card};--shadowraised:${t.shadow.raised}`;\n}"}},"formulas":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"formulas"}}}},"bandTables":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bandTables"}}}},"kpis":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"kpis"}}}},"flashId":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"flashId"}}}}}}}}}},{"_id":"6a4c151011352c87ee6f2452","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotRuleAdmScreen","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',avonMagenta:'#E5014B',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',gold:'#F7BE00',money:'#29AC56'},\n  radius:{sm:8,md:12,lg:16,pill:999},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\",h1:'28px',h2:'20px',title:'15px',body:'13px',caption:'11px'},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nconst ACTOR='gabriel.cardoso@data2.app';\n\n// Perfil × Rede are INDEPENDENT dimensions for the whole rules editor. GV is NOT calculated here → excluded.\nconst PERFIL_SEG = [['lider','Líder'],['gn','GN']];\nconst PERFIL_REDE_SEG = [['rede1','Rede 1'],['rede2','Rede 2']];\nconst PERFIL_LABEL = { lider:'Líder', gn:'GN' };\nconst REDE_LABEL = { rede1:'Rede 1', rede2:'Rede 2' };\nconst TAB_SEG = [['bands','Faixas'],['bonus','Bônus'],['formula','Fórmulas']];\nconst NIVEL_SEG = [['all','Todos'],['diamante','Diamante'],['ouro','Ouro'],['prata','Prata']];\nconst BRAND_SEG = [['all','Todas'],['natura','Natura'],['avon','Avon'],['','Total']];\nconst STATUS_SEG = [['draft','Rascunho'],['active','Ativo'],['archived','Arquivado']];\nconst STATUS_LABEL = { draft:'Rascunho', active:'Ativo', archived:'Arquivado' };\nconst VALUETYPE_SEG = [['fixed','R$ fixo'],['multiplier','% multiplicador']];\nconst VT_LABEL = { fixed:'R$ fixo', multiplier:'% multiplicador' };\n// Faixas — layout do admin da V1 (Tabelas Remuneração)\nconst NIVEL_LABEL = { diamante:'Diamante', ouro:'Ouro', prata:'Prata' };\nconst NIVEL_ORDER = { diamante:0, ouro:1, prata:2, '':3 };\nconst MARCA_LABEL = { natura:'Natura', avon:'Avon', '':'Total' };\nconst VT_CHIP = { fixed:'R$ fixo', multiplier:'% multiplicador' };\nconst BRAND_ORDER = { natura:0, avon:1, '':2 };\nconst ICON = (()=>{\n  const S = (p)=>`<svg class=\"ic-svg\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${p}</svg>`;\n  return {\n    del:S('<path d=\"M3 6h18\"/><path d=\"M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/>'),\n    ok:S('<path d=\"M20 6 9 17l-5-5\"/>'),\n    plus:S('<path d=\"M12 5v14M5 12h14\"/>'),\n    gear:S('<circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z\"/>')\n  };\n})();\n\nfunction kpiName(kpis, code){ if(!code) return ''; const hit=(kpis||[]).find(k=>String(k.code)===String(code)); return hit ? (hit.label||hit.name||code) : code; }\n\n// Bands: d2.data().records() only holds the first page (~1000). The active ruleset's bands sit past it,\n// so the screen keeps its own full copy loaded with loadAll().\nfunction allBands(d2){\n  if(Array.isArray(d2.state.allBands)) return d2.state.allBands;\n  const ds = d2.data('bands');\n  return ds ? ds.records() : [];\n}\n// loadAll() no-ops while another fetch is in flight (e.g. the first page on mount), so retry until\n// the copy holds pageInfo().total rows.\nasync function reloadBands(d2, attempt){\n  const ds = d2.data('bands');\n  if(!ds) return;\n  const n = attempt || 0;\n  try{\n    const arr = await ds.loadAll();\n    const recs = ds.records();\n    const rows = (Array.isArray(arr) && arr.length >= recs.length) ? arr : recs;\n    const info = ds.pageInfo ? ds.pageInfo() : null;\n    const total = info && Number(info.total);\n    const incomplete = !rows.length || (total && rows.length < total);\n    if(incomplete && n < 10){\n      setTimeout(()=>reloadBands(d2, n+1), 400 + n*300);\n      return;\n    }\n    d2.setState({ allBands: rows.slice() });\n  }catch(e){\n    d2.log('loadAll faixas falhou', e);\n    if(n < 8) setTimeout(()=>reloadBands(d2, n+1), 600);\n  }\n}\nfunction cycleRows(d2){ const ds=d2.data('cycles'); return ds ? ds.records() : []; }\nfunction currentCycle(d2){\n  const cs = cycleRows(d2);\n  return cs.find(c=>c.isCurrent===true) || null;\n}\n// Accepts \"202615\", \"202612,202613\" (first code wins) or padded input — V1 broke on comma-joined vigência.\nfunction normCycle(raw){\n  const m = String(raw==null?'':raw).match(/\\d{6}/);\n  return m ? m[0] : '';\n}\n\nexport default {\n  css: `\n  :host{display:block}\n  .screen{min-height:100%;height:auto;display:flex;flex-direction:column;background:var(--ground);font-family:var(--fam);box-sizing:border-box}\n  .header{padding:26px 30px 0;background:var(--surface);border-bottom:1px solid var(--hair)}\n  .htop{display:flex;align-items:flex-start;gap:16px}\n  .htitle h1{margin:0;font:800 28px/1.1 var(--fam);color:var(--ink);letter-spacing:-.5px}\n  .htitle p{margin:6px 0 0;font:400 13px/1.4 var(--fam);color:var(--muted);max-width:720px}\n  .hacts{margin-left:auto;display:flex;align-items:center;gap:8px;flex:0 0 auto}\n  .toolbar{display:flex;align-items:center;gap:12px;margin-top:16px;flex-wrap:wrap}\n  .tfield{display:flex;align-items:center;gap:8px;background:var(--ground);border:1.5px solid var(--hair);border-radius:11px;padding:0 13px;height:40px;box-sizing:border-box;transition:border-color .15s}\n  .tfield:focus-within{border-color:var(--mag)}\n  .tfield .tl{font:600 11px/1 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.05em;white-space:nowrap}\n  .tfield input,.tfield select{border:none;background:none;outline:none;font:600 14px/1 var(--fam);color:var(--ink);min-width:0}\n  .tfield input{width:84px}\n  .tfield select{cursor:pointer;max-width:420px}\n  .tfield.grow{flex:1 1 260px;min-width:0}\n  .tfield.grow select{flex:1 1 auto;width:100%}\n  .tfield.err{border-color:rgba(214,20,25,.45)}\n  .count{font:600 12px/1 var(--fam);color:var(--muted);white-space:nowrap}\n  .count.err{color:#d61419}\n  .stchip{font:700 10px/1 var(--fam);letter-spacing:.05em;text-transform:uppercase;padding:5px 9px;border-radius:999px;white-space:nowrap}\n  .stchip.st-active{background:rgba(41,172,86,.14);color:var(--money)}\n  .stchip.st-draft{background:rgba(107,114,128,.16);color:var(--muted)}\n  .stchip.st-archived{background:rgba(138,92,255,.16);color:#6a3ee0}\n  .htitle .badge{display:inline-block;margin-left:10px;font:700 10px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;\n    color:var(--mag);background:rgba(229,0,75,.10);padding:5px 9px;border-radius:999px;vertical-align:middle}\n  .rsstatus{display:inline-flex;background:var(--ground);border-radius:10px;padding:3px;gap:2px}\n  .rsstatus button{border:none;background:none;padding:7px 11px;border-radius:8px;font:600 12px/1 var(--fam);color:var(--muted);cursor:pointer;transition:background .15s,color .15s}\n  .rsstatus button.on{background:var(--surface);box-shadow:0 1px 2px rgba(16,24,40,.10)}\n  .rsstatus button.on[data-val=\"active\"]{color:var(--money)}\n  .rsstatus button.on[data-val=\"draft\"]{color:var(--ink)}\n  .rsstatus button.on[data-val=\"archived\"]{color:#6a3ee0}\n  .tabs{display:flex;gap:4px;margin-top:20px}\n  .tabs button{border:none;background:none;padding:12px 18px;font:700 14px/1 var(--fam);color:var(--muted);cursor:pointer;position:relative;transition:color .15s}\n  .tabs button.on{color:var(--mag)}\n  .tabs button.on::after{content:'';position:absolute;left:12px;right:12px;bottom:-1px;height:3px;border-radius:3px 3px 0 0;background:var(--grad)}\n  .filters{display:flex;flex-wrap:wrap;gap:16px;align-items:center;padding:16px 30px;background:var(--surface);border-bottom:1px solid var(--hair)}\n  .filters .spacer{margin-left:auto}\n  .fg{display:flex;align-items:center;gap:8px}\n  .fg>.lb{font:600 11px/1 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.05em}\n  .seg{display:inline-flex;background:var(--ground);border-radius:10px;padding:3px;gap:2px}\n  .seg button{border:none;background:none;padding:7px 11px;border-radius:8px;font:600 12px/1 var(--fam);color:var(--muted);cursor:pointer;transition:background .15s,color .15s}\n  .seg button.on{background:var(--surface);color:var(--ink);box-shadow:0 1px 2px rgba(16,24,40,.10)}\n  .newbtn{display:inline-flex;align-items:center;gap:7px;padding:11px 18px;border:none;border-radius:11px;background:var(--grad);\n    color:#fff;font:700 13px/1 var(--fam);cursor:pointer;box-shadow:0 4px 12px rgba(229,0,75,.28);transition:filter .15s,transform .1s;white-space:nowrap}\n  .newbtn .ic-svg{width:15px;height:15px}\n  .newbtn:hover{filter:brightness(1.06)} .newbtn:active{transform:scale(.97)}\n  .newbtn[disabled]{opacity:.45;cursor:default;box-shadow:none}\n  .ghostbtn{display:inline-flex;align-items:center;padding:11px 16px;border-radius:11px;border:1px solid var(--hair);background:var(--ground);color:var(--muted);font:700 13px/1 var(--fam);cursor:pointer;white-space:nowrap;transition:background .15s,color .15s}\n  .ghostbtn:hover{background:var(--hair);color:var(--ink)}\n  .meta{display:flex;align-items:center;gap:12px;padding:18px 30px 0;font:500 12px/1 var(--fam);color:var(--muted)}\n  .meta .count{color:var(--ink);font-weight:700}\n  .meta .saving{display:inline-flex;align-items:center;gap:6px;color:var(--mag)}\n  .meta .hint{margin-left:auto;font:500 11px/1.3 var(--fam);color:var(--muted);opacity:.85;max-width:560px;text-align:right}\n  .spin{width:12px;height:12px;border:2px solid rgba(229,0,75,.25);border-top-color:var(--mag);border-radius:50%;animation:sp .7s linear infinite}\n  @keyframes sp{to{transform:rotate(360deg)}}\n  .body{flex:1 1 auto;overflow:visible;padding:14px 30px 72px}\n  .toast{position:fixed;left:50%;bottom:26px;transform:translate(-50%,20px);background:var(--ink);color:#fff;padding:12px 20px;border-radius:12px;\n    font:600 13px/1.3 var(--fam);box-shadow:0 10px 30px rgba(0,0,0,.3);z-index:9500;opacity:0;transition:opacity .2s,transform .2s;pointer-events:none;max-width:80vw;text-align:center}\n  .toast.in{opacity:1;transform:translate(-50%,0)}\n  /* ---- Faixas (cards modernos) ---- */\n  .wrap{display:flex;flex-direction:column;gap:18px}\n  .grp{background:var(--surface);border:1px solid var(--hair);border-radius:16px;overflow:hidden;box-shadow:var(--shadowcard);transition:box-shadow .18s}\n  .grp:hover{box-shadow:var(--shadowraised)}\n  .grphead{display:flex;align-items:center;gap:12px;padding:14px 18px;background:linear-gradient(180deg,rgba(229,0,75,.04),transparent);border-bottom:1px solid var(--hair)}\n  .grphead .dot{width:8px;height:8px;border-radius:50%;background:var(--grad);flex:none}\n  .grphead .htext{display:flex;flex-direction:column;gap:3px;min-width:0}\n  .grphead h3{margin:0;font:800 15px/1 var(--fam);color:var(--ink);letter-spacing:-.2px}\n  .grphead .sub{display:flex;align-items:center;gap:8px;flex-wrap:wrap}\n  .grphead .kpi{font:600 11px/1 var(--fam);color:var(--muted)}\n  .grphead .kpi b{color:var(--ink);font-weight:700}\n  .vtchip{font:700 10px/1 var(--fam);letter-spacing:.02em;padding:4px 8px;border-radius:999px}\n  .vtchip.fixed{background:rgba(41,172,86,.14);color:var(--money)}\n  .vtchip.multiplier{background:rgba(72,152,255,.16);color:#1462c7}\n  .scopechip{font:700 10px/1 var(--fam);letter-spacing:.02em;padding:4px 8px;border-radius:999px;background:var(--ground);color:var(--muted)}\n  .pendchip{font:700 10px/1 var(--fam);padding:4px 8px;border-radius:999px;background:rgba(229,0,75,.10);color:var(--mag)}\n  .grphead .cnt{margin-left:auto;font:700 11px/1 var(--fam);color:var(--muted);background:var(--ground);padding:4px 8px;border-radius:999px}\n  .grphead .ictable{width:30px;height:30px;border:none;border-radius:9px;background:var(--ground);color:var(--muted);cursor:pointer;\n    display:inline-flex;align-items:center;justify-content:center;transition:background .15s,color .15s}\n  .grphead .ictable:hover{background:rgba(229,0,75,.10);color:var(--mag)}\n  .rows{display:flex;flex-direction:column}\n  .row{display:grid;grid-template-columns:110px 80px 1fr 150px 44px;gap:12px;align-items:center;padding:11px 18px;border-top:1px solid var(--hair);transition:background .15s}\n  .row:first-child{border-top:none}\n  .row:hover{background:var(--ground)}\n  .row.dirtyrow{background:rgba(229,0,75,.04)}\n  .tag{display:inline-flex;align-items:center;gap:6px}\n  .chip{font:700 10px/1 var(--fam);letter-spacing:.03em;padding:5px 8px;border-radius:999px;text-transform:capitalize}\n  .chip.nivel{background:rgba(247,190,0,.16);color:#8a6d00}\n  .chip.nivel.diamante{background:rgba(72,152,255,.16);color:#1462c7}\n  .chip.nivel.ouro{background:rgba(247,190,0,.20);color:#8a6d00}\n  .chip.nivel.prata{background:rgba(120,130,145,.18);color:#4a5464}\n  .chip.brand{background:rgba(229,0,75,.10);color:var(--mag)}\n  .chip.brand.avon{background:rgba(160,32,120,.12);color:#a02078}\n  .none{color:var(--muted);font:600 11px/1 var(--fam)}\n  .rng{display:flex;align-items:center;gap:6px;font:600 13px/1.3 var(--fam);color:var(--ink)}\n  .rng small{color:var(--muted);font-weight:500}\n  .ni{width:86px;box-sizing:border-box;padding:6px 8px;border:1.5px solid var(--hair);border-radius:8px;background:var(--surface);font:600 13px/1 var(--fam);color:var(--ink);outline:none;transition:border-color .15s,background .15s}\n  .ni:focus{border-color:var(--mag)}\n  .ni.dirty{border-color:var(--mag);background:rgba(229,0,75,.06)}\n  .track{position:relative;height:8px;border-radius:999px;background:var(--ground);overflow:hidden;margin-top:6px}\n  .track .fill{position:absolute;top:0;bottom:0;border-radius:999px;background:var(--grad);transition:left .4s cubic-bezier(.4,0,.2,1),right .4s cubic-bezier(.4,0,.2,1)}\n  .valcell{display:flex;align-items:center;justify-content:flex-end;gap:5px}\n  .valcell .u{font:700 11px/1 var(--fam);color:var(--muted)}\n  .valcell .ni{width:110px;text-align:right;font:800 15px/1 var(--fam);color:var(--money)}\n  .valcell.pct .ni{color:#1462c7}\n  .acts{display:flex;justify-content:flex-end}\n  .ic{width:32px;height:32px;border:none;border-radius:9px;background:var(--ground);color:var(--muted);cursor:pointer;\n    display:inline-flex;align-items:center;justify-content:center;transition:background .15s,color .15s,transform .1s}\n  .ic:active{transform:scale(.92)}\n  .ic.del:hover{background:rgba(255,20,24,.12);color:#d61419}\n  .ic.del.armed{background:#d61419;color:#fff}\n  .ic-svg{display:block;flex:0 0 auto}\n  .ic .ic-svg{width:17px;height:17px}\n  .ictable .ic-svg{width:16px;height:16px}\n  .addbtn .ic-svg{width:15px;height:15px}\n  .addrow{display:flex;justify-content:center;padding:10px}\n  .addbtn{display:inline-flex;align-items:center;gap:7px;padding:9px 16px;border:1.5px dashed var(--hair);border-radius:10px;background:transparent;\n    color:var(--mag);font:700 12px/1 var(--fam);cursor:pointer;transition:background .15s,border-color .15s}\n  .addbtn:hover{background:rgba(229,0,75,.06);border-color:var(--mag)}\n  .grpempty{padding:20px 18px;text-align:center;color:var(--muted);font:500 12px/1.4 var(--fam)}\n  .empty{padding:50px;text-align:center;color:var(--muted);font:500 13px/1.4 var(--fam)}\n  /* ---- modals ---- */\n  .modal-bg{position:fixed;inset:0;background:rgba(16,24,40,.42);z-index:9000;display:flex;align-items:center;justify-content:center;\n    opacity:0;transition:opacity .2s;padding:24px}\n  .modal-bg.in{opacity:1}\n  .modal{background:var(--surface);border-radius:20px;box-shadow:var(--shadowraised);width:min(460px,100%);max-width:100%;box-sizing:border-box;max-height:88vh;overflow:auto;padding:24px 26px;\n    transform:translateY(14px) scale(.98);transition:transform .24s cubic-bezier(.34,1.4,.64,1)}\n  .modal-bg.in .modal{transform:none}\n  .modal h2{margin:0 0 4px;font:800 20px/1.1 var(--fam);color:var(--ink)}\n  .modal .msub{margin:0 0 18px;font:500 12px/1.4 var(--fam);color:var(--muted)}\n  .frow{display:flex;gap:12px;margin-bottom:14px;flex-wrap:wrap}\n  .field{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:6px}\n  .field label{font:600 11px/1 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.05em}\n  .field input,.field select{width:100%;max-width:100%;box-sizing:border-box;padding:10px 12px;border:1.5px solid var(--hair);border-radius:10px;font:600 14px/1 var(--fam);color:var(--ink);outline:none;background:var(--surface);transition:border-color .15s}\n  .field input:focus,.field select:focus{border-color:var(--mag)}\n  .valwrap{position:relative;display:flex;align-items:center;width:100%;min-width:0}\n  .valwrap input{flex:1 1 0;min-width:0;width:100%;box-sizing:border-box;padding-right:64px}\n  .valwrap .vtbadge{position:absolute;right:8px;font:700 10px/1 var(--fam);letter-spacing:.02em;padding:5px 8px;border-radius:999px;pointer-events:none}\n  .vtbadge.fixed{background:rgba(41,172,86,.14);color:var(--money)}\n  .vtbadge.multiplier{background:rgba(72,152,255,.16);color:#1462c7}\n  .vtnote{margin:-6px 0 14px;font:500 11px/1.3 var(--fam);color:var(--muted)}\n  .inertnote{margin:2px 0 16px;padding:10px 12px;border-radius:10px;background:rgba(247,190,0,.12);border:1px solid rgba(247,190,0,.35);\n    font:600 11px/1.4 var(--fam);color:#8a6d00}\n  .mfoot{display:flex;gap:10px;justify-content:flex-end;margin-top:22px;align-items:center}\n  .btn{padding:11px 20px;border-radius:11px;font:700 13px/1 var(--fam);cursor:pointer;border:none;transition:filter .15s,transform .1s,background .15s}\n  .btn.ghost{background:var(--ground);color:var(--muted)} .btn.ghost:hover{background:var(--hair)}\n  .btn.prim{background:var(--grad);color:#fff;box-shadow:0 4px 12px rgba(229,0,75,.28)} .btn.prim:hover{filter:brightness(1.06)} .btn.prim:active{transform:scale(.97)}\n  .btn.danger{background:rgba(214,20,25,.10);color:#d61419} .btn.danger:hover{background:rgba(214,20,25,.18)}\n  .btn.danger.armed{background:#d61419;color:#fff}\n  @media (prefers-reduced-motion: reduce){ .tabs button,.seg button,.rsstatus button,.toast,.modal-bg,.modal,.btn,.newbtn{transition:none!important} .spin{animation:none} }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const bandsDs = d2.data('bands');\n    const bands = allBands(d2);\n    const bonusDs = d2.data('bonuses');\n    const bonuses = bonusDs ? bonusDs.records() : [];\n    const formulaDs = d2.data('formulas');\n    const formulas = formulaDs ? formulaDs.records() : [];\n    const rulesetDs = d2.data('rulesets');\n    const rulesets = rulesetDs ? rulesetDs.records() : [];\n    const btDs = d2.data('bandTables');\n    const bandTables = btDs ? btDs.records() : [];\n    const kpiDs = d2.data('kpis');\n    const kpis = kpiDs ? kpiDs.records() : [];\n    const loading = (bandsDs && bandsDs.loading) || ((d2.state.tab||'bands')==='bands' && d2.state.allBands==null);\n    const tab = d2.state.tab || 'bands';\n    const perfil = d2.state.perfil || 'lider';\n    const rede = d2.state.rede || 'rede1';\n    const f = { bandTable:'all', nivel:'all', brand:'all', ...(d2.state.filter||{}) };\n    const rsSorted = rulesets.slice().sort((a,b)=>(Number(a.version)||0)-(Number(b.version)||0));\n    const selVer = selectedVersion(d2);\n    const selectedRs = rsSorted.find(r=>Number(r.version)===selVer) || {version:selVer,label:'—',status:'draft'};\n    const isDraft = selectedRs.status==='draft';\n    const perfilTables = bandTables.filter(bt=>bt.perfil===perfil && bt.rede===rede);\n    const scopeRefs = {};\n    perfilTables.forEach(bt=>{ scopeRefs[bt.ref]=1; });\n    const perfilBands = bands.filter(b=>Number(b.rulesetVersion)===selVer && b.rede===rede && scopeRefs[b.bandTableRef||b.bandTable]);\n    const perfilBonuses = bonuses.filter(b=>Number(b.rulesetVersion)===selVer && b.perfil===perfil && b.rede===rede);\n    const perfilFormulas = formulas.filter(fm=>Number(fm.rulesetVersion)===selVer && fm.perfil===perfil && fm.rede===rede);\n    const vars = cssVars(t);\n    const pending = d2.state.pending || {};\n    const pendingCount = Object.keys(pending).length;\n\n    const seg = (name,opts,cur)=>`<div class=\"seg\">${opts.map(([v,l])=>`<button data-seg=\"${name}\" data-val=\"${v}\" class=\"${cur===v?'on':''}\">${esc(l)}</button>`).join('')}</div>`;\n    const tabs = `<div class=\"tabs\">${TAB_SEG.map(([v,l])=>`<button data-tab=\"${v}\" class=\"${tab===v?'on':''}\">${esc(l)}</button>`).join('')}</div>`;\n    const rsstatus = `<div class=\"rsstatus\">${STATUS_SEG.map(([v,l])=>`<button data-status=\"${v}\" data-val=\"${v}\" class=\"${selectedRs.status===v?'on':''}\">${esc(l)}</button>`).join('')}</div>`;\n    const perfilSeg = `<div class=\"fg\"><span class=\"lb\">Perfil</span><div class=\"seg\">${PERFIL_SEG.map(([v,l])=>`<button data-perfil=\"${v}\" class=\"${perfil===v?'on':''}\">${esc(l)}</button>`).join('')}</div></div>`;\n    const redeSeg = `<div class=\"fg\"><span class=\"lb\">Rede</span><div class=\"seg\">${PERFIL_REDE_SEG.map(([v,l])=>`<button data-rede=\"${v}\" class=\"${rede===v?'on':''}\">${esc(l)}</button>`).join('')}</div></div>`;\n\n    // Ciclo (V1): typing a cycle selects the ruleset pinned to it in pilot-cycle.\n    const cyCode = d2.state.cycleCode!=null ? d2.state.cycleCode : ((currentCycle(d2)||{}).code || '');\n    const cyErr = d2.state.cycleErr || '';\n    const cyInfo = cyErr ? `<span class=\"count err\">${esc(cyErr)}</span>` : (cyCode ? `<span class=\"count\">Ciclo ${esc(cyCode)} usa v${esc(selVer)}</span>` : '');\n    const cyclePick = `<label class=\"tfield ${cyErr?'err':''}\"><span class=\"tl\">Ciclo</span><input data-cycle inputmode=\"numeric\" placeholder=\"202615\" value=\"${esc(cyCode)}\"/></label>`;\n\n    let filterBar = '';\n    if(tab==='bands'){\n      const tableSeg = [['all','Todas']].concat(perfilTables.slice().sort((a,b)=>(Number(a.displayOrder)||0)-(Number(b.displayOrder)||0)).map(bt=>[bt.ref, bt.label||bt.ref]));\n      if(f.bandTable!=='all' && !perfilTables.some(bt=>bt.ref===f.bandTable)) f.bandTable='all';\n      filterBar = `<div class=\"fg\"><span class=\"lb\">Tabela</span>${seg('bandTable',tableSeg,f.bandTable)}</div>\n        <div class=\"fg\"><span class=\"lb\">Nível</span>${seg('nivel',NIVEL_SEG,f.nivel)}</div>\n        <div class=\"fg\"><span class=\"lb\">Marca</span>${seg('brand',BRAND_SEG,f.brand)}</div>`;\n    }\n\n    let bodyHost = '';\n    let count = 0;\n    if(loading){\n      bodyHost = `<div style=\"padding:60px;text-align:center;color:${t.color.muted}\">Carregando regras…</div>`;\n    } else if(tab==='bands'){\n      const vis = perfilBands.filter(b=>((f.bandTable||'all')==='all'||(b.bandTableRef||b.bandTable)===f.bandTable)&&(f.nivel==='all'||(b.nivel||'')===f.nivel)&&(f.brand==='all'||(b.brand||'')===f.brand));\n      count = vis.length;\n      bodyHost = renderBandCards(d2, vis, perfilTables, kpis, pending, f);\n    } else if(tab==='bonus'){\n      count = perfilBonuses.length;\n      bodyHost = d2.render('natura-x-piloto@pilotRuleBonusEditor', { bonuses:perfilBonuses, flashId:d2.state.flashId||'', perfilHint:perfil }, { key:'bn-v'+selVer+'-'+perfil+'-'+rede+'-'+perfilBonuses.length+'-'+(d2.state.flashId||'') });\n    } else {\n      count = perfilFormulas.length;\n      const btForFormula = perfilTables.map(bt=>({ _id:bt._id, ref:bt.ref, label:bt.label, valueType:bt.valueType, rede:bt.rede, perfil:bt.perfil, kpiCode:bt.kpiCode }));\n      bodyHost = d2.render('natura-x-piloto@pilotRuleFormulaEditor', { formulas:perfilFormulas, bandTables:btForFormula, kpis:kpis, flashId:d2.state.flashId||'' }, { key:'fm-v'+selVer+'-'+perfil+'-'+rede+'-'+perfilFormulas.length+'-'+perfilTables.length+'-'+(d2.state.flashId||'') });\n    }\n\n    const scopeLabel = `${PERFIL_LABEL[perfil]||perfil} · ${REDE_LABEL[rede]||rede}`;\n    const countLabel = tab==='bands' ? `${count} faixa${count===1?'':'s'} · ${perfilTables.length} tabela${perfilTables.length===1?'':'s'}` : tab==='bonus' ? `${count} regra${count===1?'':'s'} de bônus` : `${count} fórmula${count===1?'':'s'}`;\n    const metaLabel = `${scopeLabel} — ${countLabel}`;\n    const draftHint = isDraft\n      ? `Editando rascunho v${esc(selectedRs.version)} — não afeta ciclos usando outra versão.`\n      : (tab==='bands' ? `Ruleset ${STATUS_LABEL[selectedRs.status]||selectedRs.status} v${esc(selectedRs.version)}: \"Enviar Alterações\" cria um rascunho novo com as mudanças; ele só vale depois de ativado.` : '');\n    const metaHint = draftHint;\n\n    return `<div class=\"screen\" style=\"${vars}\">\n      <div class=\"header\">\n        <div class=\"htop\">\n          <div class=\"htitle\">\n            <h1>Administração · Regras <span class=\"badge\">Code · Remuneração</span></h1>\n            <p>Ajuste faixas, tabelas, bônus e fórmulas que compõem o cálculo de ganhos. Digite o ciclo para abrir o ruleset que ele usa; mudanças num ruleset ativo viram um rascunho novo, que só vale depois de ativado em Rulesets.</p>\n          </div>\n          <div class=\"hacts\">${tab==='bands'\n            ? (pendingCount\n              ? `<button class=\"ghostbtn\" data-discard>Descartar</button><button class=\"newbtn\" data-submit ${d2.state.saving?'disabled':''}>${ICON.ok} Enviar alterações (${pendingCount})</button>`\n              : `<button class=\"newbtn\" data-newtable>${ICON.plus} Nova tabela de faixas</button>`)\n            : ''}</div>\n        </div>\n        <div class=\"toolbar\">\n          ${cyclePick}\n          <label class=\"tfield grow\"><span class=\"tl\">Ruleset</span><select data-rsver>${rsSorted.map(r=>`<option value=\"${esc(r.version)}\" ${Number(r.version)===selVer?'selected':''}>v${esc(r.version)} · ${esc(r.label)} — ${esc(STATUS_LABEL[r.status]||r.status)}</option>`).join('')}</select></label>\n          <span class=\"stchip st-${esc(selectedRs.status)}\">${esc(STATUS_LABEL[selectedRs.status]||selectedRs.status)}</span>\n          ${rsstatus}\n          ${cyInfo}\n        </div>\n        ${tabs}\n      </div>\n      <div class=\"filters\">${perfilSeg}${redeSeg}${filterBar}</div>\n      <div class=\"meta\"><span><span class=\"count\">${metaLabel}</span></span>${d2.state.saving?`<span class=\"saving\"><span class=\"spin\"></span>Salvando…</span>`:''}${metaHint?`<span class=\"hint\">${esc(metaHint)}</span>`:''}</div>\n      <div class=\"body\">${bodyHost}</div>\n      ${renderModal(d2,t)}\n      ${renderTableModal(d2,t,kpis)}\n      <div class=\"toast ${d2.state.toast?'in':''}\" data-toast>${esc(d2.state.toast||'')}</div>\n    </div>`;\n  },\n  mounted(d2){\n    d2.state.filter = d2.state.filter || {bandTable:'all',nivel:'all',brand:'all'};\n    d2.state.tab = d2.state.tab || 'bands';\n    d2.state.perfil = d2.state.perfil || 'lider';\n    d2.state.rede = d2.state.rede || 'rede1';\n    d2.state.pending = d2.state.pending || {};\n    d2.state.open = d2.state.open || {};\n    reloadBands(d2);\n\n    d2.on('[data-tab]','click',(e,el)=>{ d2.setState({ tab: el.dataset.tab }); });\n    d2.on('[data-perfil]','click',(e,el)=>{ d2.setState({ perfil: el.dataset.perfil }); });\n    d2.on('[data-rede]','click',(e,el)=>{ d2.setState({ rede: el.dataset.rede }); });\n    d2.on('[data-rsver]','change',(e,el)=>{\n      if(Object.keys(d2.state.pending||{}).length && !confirmDiscard()) { el.value = String(selectedVersion(d2)); return; }\n      d2.setState({ rulesetVersion: Number(el.value), pending:{}, cycleErr:'' });\n    });\n    d2.on('[data-cycle]','change',(e,el)=>applyCycle(d2, el.value));\n    d2.on('[data-cycle]','keydown',(e,el)=>{ if(e.key==='Enter'){ e.preventDefault(); el.blur(); } });\n    d2.on('[data-seg]','click',(e,el)=>{ const f={...(d2.state.filter||{})}; f[el.dataset.seg]=el.dataset.val; d2.setState({ filter:f }); });\n    d2.on('[data-status]','click',(e,el)=>{ handleRulesetStatus(d2, el.dataset.val); });\n    d2.on('[data-newtable]','click',()=>openTableModal(d2,null));\n\n    // Faixas (V1): collapsible cards, inline edits kept pending until \"Enviar Alterações\".\n    d2.on('[data-edittable]','click',(e,el)=>{ const bt=(d2.data('bandTables')?d2.data('bandTables').records():[]).find(x=>x.ref===el.dataset.edittable); if(bt) openTableModal(d2,{ _id:bt._id, ref:bt.ref, label:bt.label, kpiCode:bt.kpiCode, rede:bt.rede, perfil:bt.perfil, valueType:bt.valueType, displayOrder:bt.displayOrder, active:bt.active }); });\n    d2.on('[data-bf]','change',(e,el)=>onBandField(d2, el));\n    d2.on('[data-discard]','click',()=>d2.setState({ pending:{} }));\n    d2.on('[data-submit]','click',()=>submitPending(d2));\n    d2.on('[data-vadd]','click',(e,el)=>addBand(d2, el.dataset.vadd, el.dataset.nivel||''));\n    d2.on('[data-vdel]','click',(e,el)=>{\n      const id = el.dataset.vdel;\n      if(d2.state.armDel===id){ d2.setState({ armDel:'' }); const b=allBands(d2).find(x=>x._id===id); handleDelBand(d2,b); }\n      else { d2.setState({ armDel:id }); setTimeout(()=>{ if(d2.state.armDel===id) d2.setState({ armDel:'' }); },3000); }\n    });\n\n    // faixa modal fields (nova faixa)\n    d2.on('[data-mfield]','input',(e,el)=>{ const m={...(d2.state.modal||{})}; m[el.dataset.mfield]=el.value; d2.state.modal=m; });\n    d2.on('[data-mfield]','change',(e,el)=>{ const m={...(d2.state.modal||{})}; m[el.dataset.mfield]=el.value; d2.state.modal=m; });\n    d2.on('[data-mclose]','click',()=>d2.setState({ modalOpen:false }));\n    d2.on('[data-msave]','click',()=>saveModal(d2));\n    d2.on('[data-mbg]','click',(e,el)=>{ if(e.target===el) d2.setState({ modalOpen:false }); });\n\n    // band-table modal fields\n    d2.on('[data-tfield]','input',(e,el)=>{ const m={...(d2.state.tableModal||{})}; m[el.dataset.tfield]=el.value; d2.state.tableModal=m; });\n    d2.on('[data-tfield]','change',(e,el)=>{ const m={...(d2.state.tableModal||{})}; m[el.dataset.tfield]=el.value; d2.state.tableModal=m; });\n    d2.on('[data-tclose]','click',()=>d2.setState({ tableModalOpen:false, tArmDel:false }));\n    d2.on('[data-tsave]','click',()=>saveTableModal(d2));\n    d2.on('[data-tdel]','click',()=>{ if(d2.state.tArmDel){ handleDelTable(d2); } else { d2.setState({ tArmDel:true }); setTimeout(()=>{ if(d2.state.tArmDel) d2.setState({ tArmDel:false }); },3000); } });\n    d2.on('[data-tbg]','click',(e,el)=>{ if(e.target===el) d2.setState({ tableModalOpen:false, tArmDel:false }); });\n\n    // child → parent (bônus / fórmulas)\n    d2.bus.on('rule:table:edit', (bt)=>openTableModal(d2,bt));\n    d2.bus.on('rule:bonus:save', (row)=>handleSave(d2,'bonus',row,row._id?'Bônus atualizado':'Bônus criado'));\n    d2.bus.on('rule:bonus:del', (b)=>handleDelBonus(d2,b));\n    d2.bus.on('rule:formula:save', (row)=>handleSave(d2,'formula',row,'Fórmula salva'));\n  }\n};\n\nfunction confirmDiscard(){\n  try{ return window.confirm('Há alterações não enviadas. Descartar?'); }catch(e){ return true; }\n}\n\nfunction nf(n){ try{ return Number(n).toLocaleString('pt-BR'); }catch(e){ return String(n); } }\n// Min/max are shown as \"% de atingimento\" only for atingimento tables; value is % for multiplier tables, R$ for fixed.\nfunction isAtingTable(bt){ const s=(String(bt.ref||'')+' '+String(bt.label||'')).toLowerCase(); return s.includes('tingimento'); }\nfunction shown(v){ return (v===undefined||v===null||v==='') ? '' : String(v); }\n\nfunction renderBandCards(d2, vis, perfilTables, kpis, pending, f){\n  if(!perfilTables.length) return `<div class=\"wrap\"><div class=\"grp\"><div class=\"empty\">Nenhuma tabela de faixas para este perfil e rede.<br/>Crie uma tabela para começar.</div></div></div>`;\n  const tables = perfilTables\n    .filter(bt=>f.bandTable==='all' || bt.ref===f.bandTable)\n    .slice().sort((a,b)=>{\n      const oa=a.displayOrder!=null?Number(a.displayOrder):99, ob=b.displayOrder!=null?Number(b.displayOrder):99;\n      return (oa-ob) || String(a.label||a.ref).localeCompare(String(b.label||b.ref),'pt-BR');\n    });\n  const groups = {};\n  vis.forEach(b=>{ const k=b.bandTableRef||b.bandTable; (groups[k]=groups[k]||[]).push(b); });\n  const filtering = f.nivel!=='all' || f.brand!=='all';\n  const shownTables = filtering ? tables.filter(bt=>(groups[bt.ref]||[]).length) : tables;\n  if(!shownTables.length) return `<div class=\"wrap\"><div class=\"grp\"><div class=\"empty\">Nenhuma faixa para este filtro.<br/>Ajuste os filtros, crie uma tabela ou adicione uma faixa.</div></div></div>`;\n\n  const rowHtml = (b, bt)=>{\n    const vt = bt.valueType==='multiplier' ? 'multiplier' : 'fixed';\n    const isPct = vt==='multiplier';\n    const p = pending[b._id] || {};\n    const val = (fld)=> p[fld]!==undefined ? p[fld] : shown(b[fld]);\n    const dirty = (fld)=> p[fld]!==undefined ? ' dirty' : '';\n    const lo = Number(val('minPct'))||0, hi = Number(val('maxPct'))||0;\n    const capHi = Math.min(hi, isPct?200:9999);\n    const scale = isPct?150:Math.max(200,capHi||200);\n    const left = Math.max(0,Math.min(100, lo/scale*100));\n    const right = Math.max(0,Math.min(100, 100 - capHi/scale*100));\n    const armed = d2.state.armDel===b._id;\n    const nv = b.nivel||'', br = b.brand||'';\n    return `<div class=\"row${pending[b._id]?' dirtyrow':''}\" data-key=\"${esc(b._id)}\">\n      <div class=\"tag\">${nv?`<span class=\"chip nivel ${esc(nv)}\">${esc(NIVEL_LABEL[nv]||nv)}</span>`:'<span class=\"none\">—</span>'}</div>\n      <div class=\"tag\">${br?`<span class=\"chip brand ${esc(br)}\">${esc(MARCA_LABEL[br]||br)}</span>`:'<span class=\"none\">total</span>'}</div>\n      <div>\n        <div class=\"rng\">\n          <input class=\"ni${dirty('minPct')}\" type=\"number\" step=\"any\" data-bf=\"minPct\" data-id=\"${esc(b._id)}\" value=\"${esc(val('minPct'))}\" aria-label=\"Mínimo\"/>\n          <small>a</small>\n          <input class=\"ni${dirty('maxPct')}\" type=\"number\" step=\"any\" data-bf=\"maxPct\" data-id=\"${esc(b._id)}\" value=\"${esc(val('maxPct'))}\" aria-label=\"Máximo\" title=\"${hi>=9999?'9999 = sem limite (∞)':''}\"/>\n          <small>${isAtingTable(bt)?'% de atingimento':(hi>=9999?'(∞)':'')}</small>\n        </div>\n        <div class=\"track\"><span class=\"fill\" style=\"left:${left}%;right:${right}%\"></span></div>\n      </div>\n      <div class=\"valcell ${isPct?'pct':''}\">${isPct?'':'<span class=\"u\">R$</span>'}<input class=\"ni${dirty('value')}\" type=\"number\" step=\"any\" data-bf=\"value\" data-id=\"${esc(b._id)}\" value=\"${esc(val('value'))}\" aria-label=\"Valor\"/>${isPct?'<span class=\"u\">%</span>':''}</div>\n      <div class=\"acts\"><button class=\"ic del ${armed?'armed':''}\" data-vdel=\"${esc(b._id)}\" title=\"${armed?'Confirmar exclusão':'Excluir'}\">${armed?ICON.ok:ICON.del}</button></div>\n    </div>`;\n  };\n\n  const cards = shownTables.map(bt=>{\n    const vt = bt.valueType==='multiplier' ? 'multiplier' : 'fixed';\n    const rows = (groups[bt.ref]||[]).slice().sort((a,b)=>\n      ((BRAND_ORDER[a.brand||'']??3)-(BRAND_ORDER[b.brand||'']??3)) ||\n      ((NIVEL_ORDER[a.nivel||'']??4)-(NIVEL_ORDER[b.nivel||'']??4)) ||\n      ((Number(a.minPct)||0)-(Number(b.minPct)||0)));\n    const kn = kpiName(kpis, bt.kpiCode);\n    const kpiTxt = kn ? `KPI <b>${esc(kn)}</b>` : 'sem KPI';\n    const scopeTxt = `${esc(REDE_LABEL[bt.rede]||bt.rede||'')} · ${esc(PERFIL_LABEL[bt.perfil]||bt.perfil||'')}`;\n    const pend = rows.filter(b=>pending[b._id]).length;\n    const inner = rows.length\n      ? `<div class=\"rows\">${rows.map(b=>rowHtml(b,bt)).join('')}</div>`\n      : `<div class=\"grpempty\">Nenhuma faixa nesta tabela nesta versão.</div>`;\n    return `<div class=\"grp\" data-key=\"${esc(bt.ref)}\">\n      <div class=\"grphead\">\n        <span class=\"dot\"></span>\n        <div class=\"htext\">\n          <h3>${esc(bt.label||bt.ref)}</h3>\n          <div class=\"sub\">\n            <span class=\"kpi\">${kpiTxt}</span>\n            <span class=\"vtchip ${vt}\">${esc(VT_CHIP[vt])}</span>\n            <span class=\"scopechip\">${scopeTxt}</span>\n            ${pend?`<span class=\"pendchip\">${pend} alterada${pend===1?'':'s'}</span>`:''}\n          </div>\n        </div>\n        <span class=\"cnt\">${rows.length}</span>\n        <button class=\"ictable\" data-edittable=\"${esc(bt.ref)}\" title=\"Editar tabela\">${ICON.gear}</button>\n      </div>\n      ${inner}\n      <div class=\"addrow\"><button class=\"addbtn\" data-vadd=\"${esc(bt.ref)}\" data-nivel=\"\">${ICON.plus} Adicionar faixa em ${esc(bt.label||bt.ref)}</button></div>\n    </div>`;\n  });\n  return `<div class=\"wrap\">${cards.join('')}</div>`;\n}\n\nfunction onBandField(d2, el){\n  const id = el.dataset.id, fld = el.dataset.bf;\n  const b = allBands(d2).find(x=>x._id===id); if(!b) return;\n  const pending = { ...(d2.state.pending||{}) };\n  const p = { ...(pending[id]||{}) };\n  const raw = String(el.value).trim();\n  const orig = shown(b[fld]);\n  if(raw==='' || Number(raw)===Number(orig)) delete p[fld]; else p[fld] = raw;\n  if(Object.keys(p).length) pending[id] = p; else delete pending[id];\n  d2.setState({ pending });\n}\n\nfunction applyCycle(d2, raw){\n  const code = normCycle(raw);\n  if(!code){ d2.setState({ cycleCode:String(raw||''), cycleErr:'Ciclo inválido (ex.: 202615)' }); return; }\n  const cyc = cycleRows(d2).find(c=>String(c.code)===code);\n  if(!cyc){ d2.setState({ cycleCode:code, cycleErr:`Ciclo ${code} não cadastrado` }); return; }\n  const v = Number(cyc.rulesetVersion)||0;\n  if(Object.keys(d2.state.pending||{}).length && v!==selectedVersion(d2) && !confirmDiscard()) return;\n  d2.setState({ cycleCode:code, cycleErr:'', rulesetVersion: v || null, pending: v!==selectedVersion(d2) ? {} : d2.state.pending });\n}\n\nasync function submitPending(d2){\n  const pending = d2.state.pending || {};\n  const ids = Object.keys(pending);\n  if(!ids.length || d2.state.saving) return;\n  const bands = allBands(d2);\n  for(const id of ids){\n    const p = pending[id];\n    for(const k of Object.keys(p)){ if(!isFinite(Number(p[k]))){ toast(d2,'Valor inválido em uma das faixas'); return; } }\n    const b = bands.find(x=>x._id===id);\n    const mn = Number(p.minPct!==undefined?p.minPct:b&&b.minPct), mx = Number(p.maxPct!==undefined?p.maxPct:b&&b.maxPct);\n    if(b && mx < mn){ toast(d2,'Há faixa com máximo menor que o mínimo'); return; }\n  }\n  const ver = selectedVersion(d2);\n  const rsDs = d2.data('rulesets'); const rs = rsDs ? rsDs.records() : [];\n  const cur = rs.find(r=>Number(r.version)===ver);\n  d2.setState({ saving:true });\n  try{\n    let targetVer = ver;\n    let idMap = null;\n    if(!cur || cur.status!=='draft'){\n      // Locked ruleset → duplicate into a new draft and apply the edits there (server guard stays intact).\n      targetVer = rs.reduce((m,r)=>Math.max(m,Number(r.version)||0),0) + 1;\n      const today = new Date().toISOString().slice(0,10);\n      const dup = await invoke(d2,{ entity:'ruleset', op:'duplicate', actorEmail:ACTOR, row:{ version:targetVer, sourceVersion:ver, label:`Rascunho de v${ver} — ajuste de faixas (${today})` }, before:{} });\n      const dd = dup && dup.data;\n      if(!dd || dd.ok!==true) throw new Error('duplicate: '+JSON.stringify(dd||dup));\n      await reloadBands(d2);\n      const fresh = allBands(d2).filter(x=>Number(x.rulesetVersion)===targetVer);\n      idMap = {};\n      for(const id of ids){\n        const b = bands.find(x=>x._id===id); if(!b) continue;\n        const twin = fresh.find(x=>(x.bandTableRef||x.bandTable)===(b.bandTableRef||b.bandTable) && x.rede===b.rede && (x.nivel||'')===(b.nivel||'') && (x.brand||'')===(b.brand||'') && Number(x.minPct)===Number(b.minPct) && Number(x.maxPct)===Number(b.maxPct) && Number(x.value)===Number(b.value) && !Object.values(idMap).includes(x._id));\n        if(!twin) throw new Error('faixa copiada não encontrada para '+id);\n        idMap[id] = twin._id;\n      }\n    }\n    let fails = 0;\n    for(const id of ids){\n      const b = bands.find(x=>x._id===id); if(!b) { fails++; continue; }\n      const p = pending[id];\n      const row = {\n        _id: idMap ? idMap[id] : id, rulesetVersion: targetVer, bandTable: b.bandTable, bandTableRef: b.bandTableRef||b.bandTable, rede: b.rede,\n        nivel: b.nivel||'', brand: b.brand||'',\n        minPct: Number(p.minPct!==undefined?p.minPct:b.minPct)||0,\n        maxPct: Number(p.maxPct!==undefined?p.maxPct:b.maxPct)||0,\n        value: Number(p.value!==undefined?p.value:b.value)||0\n      };\n      const r = await invoke(d2,{ entity:'band', op:'upsert', actorEmail:ACTOR, row, before:{ minPct:b.minPct, maxPct:b.maxPct, value:b.value, sourceVersion:ver } });\n      if(!(r && r.data && r.data.ok===true)) fails++;\n    }\n    refreshAll(d2);\n    await reloadBands(d2);\n    if(targetVer!==ver){\n      d2.setState({ pending:{}, rulesetVersion:targetVer, cycleErr:'' });\n      toast(d2, fails ? `Rascunho v${targetVer} criado, mas ${fails} faixa(s) falharam` : `Rascunho v${targetVer} criado com ${ids.length} alteração(ões). Ative-o em Rulesets para aplicar.`);\n    } else {\n      d2.setState({ pending: fails ? d2.state.pending : {} });\n      toast(d2, fails ? `${fails} faixa(s) não foram salvas` : `${ids.length} faixa(s) atualizada(s)`);\n    }\n  }catch(e){\n    d2.log('Enviar Alterações falhou', e);\n    toast(d2,'Erro ao enviar alterações');\n  }\n  d2.setState({ saving:false });\n}\n\nfunction addBand(d2, ref, nivel){\n  const ver = selectedVersion(d2);\n  const rsDs = d2.data('rulesets'); const rs = rsDs ? rsDs.records() : [];\n  const cur = rs.find(r=>Number(r.version)===ver);\n  if(!cur || cur.status!=='draft'){ toast(d2,'Para adicionar faixas, selecione um ruleset em rascunho (ou envie uma alteração para criar um).'); return; }\n  openBandModal(d2,{ bandTable:ref, bandTableRef:ref, rulesetVersion:ver, rede:d2.state.rede||'rede1', nivel:nivel||'', brand:'', minPct:0, maxPct:100, value:0 });\n}\n\nfunction valueTypeOf(d2, m){\n  const ref = m.bandTableRef || m.bandTable;\n  const btDs = d2.data('bandTables');\n  const bts = btDs ? btDs.records() : [];\n  const bt = bts.find(x=>x.ref===ref);\n  if(bt && bt.valueType) return bt.valueType;\n  return 'fixed';\n}\nfunction tableLabelOf(d2, ref){\n  const btDs = d2.data('bandTables');\n  const bt = (btDs ? btDs.records() : []).find(x=>x.ref===ref);\n  return bt ? (bt.label||ref) : (ref||'');\n}\n\nfunction renderModal(d2,t){\n  if(!d2.state.modalOpen) return '';\n  const m = d2.state.modal || {};\n  const vt = valueTypeOf(d2, m);\n  const vtLabel = VT_LABEL[vt] || vt;\n  const isPct = vt==='multiplier';\n  const valNote = isPct\n    ? 'Multiplicador: o valor é aplicado como % sobre a base (ex.: 85 = 85%).'\n    : 'Valor fixo em R$: entra direto no cálculo do ganho.';\n  return `<div class=\"modal-bg in\" data-mbg>\n    <div class=\"modal\">\n      <h2>Nova faixa</h2>\n      <p class=\"msub\">${esc(tableLabelOf(d2, m.bandTableRef||m.bandTable))} · ${esc(REDE_LABEL[m.rede]||m.rede||'')} · <span class=\"vtbadge ${vt}\" style=\"position:static;padding:3px 7px\">${esc(vtLabel)}</span></p>\n      <div class=\"frow\">\n        <div class=\"field\"><label>Nível</label>\n          <select data-mfield=\"nivel\">${['diamante','ouro','prata',''].map(v=>`<option value=\"${v}\" ${((m.nivel||'')===v)?'selected':''}>${v?NIVEL_LABEL[v]:'—'}</option>`).join('')}</select>\n        </div>\n        <div class=\"field\"><label>Marca</label>\n          <select data-mfield=\"brand\">${['natura','avon',''].map(v=>`<option value=\"${v}\" ${((m.brand||'')===v)?'selected':''}>${MARCA_LABEL[v]}</option>`).join('')}</select>\n        </div>\n      </div>\n      <div class=\"frow\">\n        <div class=\"field\"><label>Mínimo</label><input type=\"number\" step=\"any\" data-mfield=\"minPct\" value=\"${esc(m.minPct)}\"/></div>\n        <div class=\"field\"><label>Máximo</label><input type=\"number\" step=\"any\" data-mfield=\"maxPct\" value=\"${esc(m.maxPct)}\"/></div>\n        <div class=\"field\"><label>Valor</label>\n          <div class=\"valwrap\"><input type=\"number\" step=\"any\" data-mfield=\"value\" value=\"${esc(m.value)}\"/><span class=\"vtbadge ${vt}\">${isPct?'%':'R$'}</span></div>\n        </div>\n      </div>\n      <p class=\"vtnote\">${esc(valNote)}</p>\n      <div class=\"mfoot\">\n        <button class=\"btn ghost\" data-mclose>Cancelar</button>\n        <button class=\"btn prim\" data-msave>Criar faixa</button>\n      </div>\n    </div>\n  </div>`;\n}\n\nfunction renderTableModal(d2,t,kpis){\n  if(!d2.state.tableModalOpen) return '';\n  const m = d2.state.tableModal || {};\n  const isNew = !m._id;\n  const kpiOpts = (kpis||[]).slice().sort((a,b)=>(a.displayOrder||0)-(b.displayOrder||0));\n  const seen = {};\n  const kpiList = [];\n  kpiOpts.forEach(k=>{ const c=String(k.code); if(!seen[c]){ seen[c]=1; kpiList.push({code:c,name:(k.label||k.name||c)}); } });\n  const cur = m.kpiCode!=null?String(m.kpiCode):'';\n  return `<div class=\"modal-bg in\" data-tbg>\n    <div class=\"modal\">\n      <h2>${isNew?'Nova tabela de faixas':'Editar tabela de faixas'}</h2>\n      <p class=\"msub\">Uma tabela agrupa faixas por KPI. ${isNew?'Ela fica inerte até ser referenciada por uma fórmula.':esc('Slug: '+(m.ref||''))}</p>\n      <div class=\"frow\">\n        <div class=\"field\"><label>Nome da tabela</label><input type=\"text\" data-tfield=\"label\" value=\"${esc(m.label||'')}\" placeholder=\"Ex.: Volume de Pontos\"/></div>\n      </div>\n      <div class=\"frow\">\n        <div class=\"field\"><label>KPI vinculado</label>\n          <select data-tfield=\"kpiCode\"><option value=\"\">—</option>${kpiList.map(k=>`<option value=\"${esc(k.code)}\" ${cur===k.code?'selected':''}>${esc(k.name)} (${esc(k.code)})</option>`).join('')}</select>\n        </div>\n      </div>\n      <div class=\"frow\">\n        <div class=\"field\"><label>Rede</label>\n          <select data-tfield=\"rede\">${['rede1','rede2'].map(v=>`<option value=\"${v}\" ${((m.rede||'rede1')===v)?'selected':''}>${v==='rede1'?'Rede 1':'Rede 2'}</option>`).join('')}</select>\n        </div>\n        <div class=\"field\"><label>Perfil</label>\n          <select data-tfield=\"perfil\">${[['lider','Líder'],['gn','GN']].map(([v,l])=>`<option value=\"${v}\" ${((m.perfil||'lider')===v)?'selected':''}>${l}</option>`).join('')}</select>\n        </div>\n        <div class=\"field\"><label>Tipo de valor</label>\n          <select data-tfield=\"valueType\">${VALUETYPE_SEG.map(([v,l])=>`<option value=\"${v}\" ${((m.valueType||'multiplier')===v)?'selected':''}>${l}</option>`).join('')}</select>\n        </div>\n      </div>\n      ${isNew?`<div class=\"inertnote\">Tabela nova: as faixas dela ainda NÃO afetam o cálculo. Só passam a valer quando uma fórmula referenciar esta tabela.</div>`:''}\n      <div class=\"mfoot\">\n        ${!isNew?`<button class=\"btn danger ${d2.state.tArmDel?'armed':''}\" data-tdel>${d2.state.tArmDel?'Confirmar exclusão':'Excluir tabela'}</button>`:''}\n        <button class=\"btn ghost\" data-tclose>Cancelar</button>\n        <button class=\"btn prim\" data-tsave>${isNew?'Criar tabela':'Salvar'}</button>\n      </div>\n    </div>\n  </div>`;\n}\n\nfunction cssVars(t){\n  return `--surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient};--money:${t.color.money};--fam:${t.type.family};--shadowcard:${t.shadow.card};--shadowraised:${t.shadow.raised}`;\n}\nfunction openBandModal(d2,b){ d2.setState({ modalOpen:true, modal:{ ...b } }); }\nfunction openTableModal(d2,bt){\n  const defPerfil = d2.state.perfil||'lider';\n  const defRede = d2.state.rede||'rede1';\n  const base = bt ? { ...bt } : { label:'', kpiCode:'', rede:defRede, perfil:defPerfil, valueType:'multiplier', displayOrder:0, active:true };\n  d2.setState({ tableModalOpen:true, tableModal:base, tArmDel:false });\n}\nfunction toast(d2,msg){ d2.setState({ toast:msg }); setTimeout(()=>d2.setState({ toast:null }), 3200); }\nfunction flash(d2,id){ d2.setState({ flashId:id }); setTimeout(()=>{ if(d2.state.flashId===id) d2.setState({ flashId:'' }); }, 900); }\nfunction refreshAll(d2){\n  ['bonuses','formulas','rulesets','bandTables','kpis','cycles'].forEach(n=>{ const ds=d2.data(n); if(ds&&ds.refresh) ds.refresh(); });\n  reloadBands(d2);\n}\nasync function invoke(d2,payload){ return await d2.rush('writer').invoke(payload); }\nfunction okOrMsg(r, fallback){\n  const d = r && r.data;\n  if(d && d.ok===true) return null;\n  if(d && d.code===409) return 'Bloqueado: o ruleset não está em rascunho';\n  return (d && d.message) || fallback;\n}\n// Selected ruleset: explicit pick → else the ruleset pinned to the current cycle → else active → first.\nfunction selectedVersion(d2){\n  const ds = d2.data('rulesets');\n  const rs = ds ? ds.records() : [];\n  const sorted = rs.slice().sort((a,b)=>(Number(a.version)||0)-(Number(b.version)||0));\n  const has = (v)=>sorted.some(r=>Number(r.version)===v);\n  if(d2.state.rulesetVersion!=null){ const v=Number(d2.state.rulesetVersion); if(has(v)) return v; }\n  const cc = currentCycle(d2);\n  if(cc && has(Number(cc.rulesetVersion))) return Number(cc.rulesetVersion);\n  const def = sorted.find(r=>r.status==='active') || sorted[0];\n  return def ? (Number(def.version)||1) : 1;\n}\n\nasync function saveModal(d2){\n  const m = d2.state.modal || {};\n  const row = {\n    rulesetVersion: (m.rulesetVersion!=null?Number(m.rulesetVersion):selectedVersion(d2)), bandTable: m.bandTable, bandTableRef: m.bandTableRef||m.bandTable, rede: m.rede,\n    nivel: m.nivel||'', brand: m.brand||'', minPct: Number(m.minPct)||0, maxPct: Number(m.maxPct)||0, value: Number(m.value)||0\n  };\n  if(row.maxPct < row.minPct){ toast(d2,'Máximo menor que o mínimo'); return; }\n  d2.setState({ saving:true, modalOpen:false });\n  let savedId=null;\n  try{\n    const r = await invoke(d2,{ entity:'band', op:'upsert', actorEmail:ACTOR, row, before:{} });\n    const err = okOrMsg(r,'Erro ao criar faixa');\n    if(err){ toast(d2, (r&&r.data&&r.data.guards&&r.data.guards.bandOverlap)?'Faixa sobrepõe outra existente':err); }\n    else { savedId = r.data.id; toast(d2,'Faixa criada'); }\n  }catch(e){ toast(d2,'Erro ao salvar faixa'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\n  if(savedId) flash(d2,savedId);\n}\nasync function saveTableModal(d2){\n  const m = d2.state.tableModal || {};\n  if(!m.label || !String(m.label).trim()){ toast(d2,'Informe o nome da tabela'); return; }\n  const rede = m.rede||'rede1';\n  const perfil = m.perfil||'lider';\n  const vt = m.valueType||'multiplier';\n  let ref = m.ref;\n  if(!ref){\n    ref = String(m.label).toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g,'').replace(/[^a-z0-9]+/g,'-').replace(/^-+|-+$/g,'').slice(0,40) || ('tabela-'+Date.now());\n  }\n  const row = {\n    _id: m._id, ref, label:String(m.label).trim(), kpiCode: m.kpiCode!=null?String(m.kpiCode):'',\n    rede, perfil, valueType:vt, displayOrder:Number(m.displayOrder)||0, active:true\n  };\n  if(!row._id) delete row._id;\n  d2.setState({ saving:true, tableModalOpen:false, tArmDel:false });\n  try{\n    const r = await invoke(d2,{ entity:'band-table', op:'upsert', actorEmail:ACTOR, row, before: m._id?{ label:m.label, valueType:m.valueType }:{} });\n    const err = okOrMsg(r,'Erro ao salvar tabela');\n    toast(d2, err || (m._id?'Tabela atualizada':'Tabela criada (inerte até uma fórmula referenciá-la)'));\n  }catch(e){ toast(d2,'Erro ao salvar tabela'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\n}\nasync function handleDelTable(d2){\n  const m = d2.state.tableModal || {};\n  if(!m._id){ d2.setState({ tableModalOpen:false, tArmDel:false }); return; }\n  d2.setState({ saving:true, tableModalOpen:false, tArmDel:false });\n  try{\n    const r = await invoke(d2,{ entity:'band-table', op:'delete', actorEmail:ACTOR, row:{ _id:m._id }, before:m });\n    toast(d2, okOrMsg(r,'Erro ao excluir tabela') || 'Tabela excluída');\n  }catch(e){ toast(d2,'Erro ao excluir tabela'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\n}\nasync function handleDelBand(d2,b){\n  if(!b || !b._id) return;\n  const rsDs = d2.data('rulesets'); const rs = rsDs ? rsDs.records() : [];\n  const cur = rs.find(r=>Number(r.version)===Number(b.rulesetVersion));\n  if(!cur || cur.status!=='draft'){ toast(d2,'Para excluir faixas, selecione um ruleset em rascunho (ou envie uma alteração para criar um).'); return; }\n  d2.setState({ saving:true });\n  try{\n    const r = await invoke(d2,{ entity:'band', op:'delete', actorEmail:ACTOR, row:{ _id:b._id, rulesetVersion:b.rulesetVersion }, before:b });\n    toast(d2, okOrMsg(r,'Erro ao excluir') || 'Faixa excluída');\n  }catch(e){ toast(d2,'Erro ao excluir'); }\n  const pending = { ...(d2.state.pending||{}) }; delete pending[b._id];\n  d2.setState({ pending });\n  refreshAll(d2);\n  d2.setState({ saving:false });\n}\nasync function handleDelBonus(d2,b){\n  if(!b || !b._id) return;\n  d2.setState({ saving:true });\n  try{\n    const r = await invoke(d2,{ entity:'bonus', op:'delete', actorEmail:ACTOR, row:{ _id:b._id, rulesetVersion:b.rulesetVersion }, before:b });\n    toast(d2, okOrMsg(r,'Erro ao excluir bônus') || 'Bônus excluído');\n  }catch(e){ toast(d2,'Erro ao excluir bônus'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\n}\nasync function handleSave(d2,entity,row,msg){\n  d2.setState({ saving:true });\n  let savedId=null;\n  const rowV = { ...row, rulesetVersion: (row && row.rulesetVersion!=null ? Number(row.rulesetVersion) : selectedVersion(d2)) };\n  try{\n    const r = await invoke(d2,{ entity, op:'upsert', actorEmail:ACTOR, row:rowV, before:{} });\n    const err = okOrMsg(r,'Erro ao salvar');\n    if(err) toast(d2, err); else { savedId = r.data.id; toast(d2,msg); }\n  }catch(e){ toast(d2,'Erro ao salvar'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\n  if(savedId) flash(d2,savedId);\n}\nasync function handleRulesetStatus(d2,status){\n  const ds=d2.data('rulesets'); const rs=ds?ds.records():[];\n  const v=selectedVersion(d2);\n  const active=rs.find(r=>Number(r.version)===v) || rs[0]; if(!active) return;\n  if(active.status===status) return;\n  d2.setState({ saving:true });\n  try{\n    const r = await invoke(d2,{ entity:'ruleset', op:'upsert', actorEmail:ACTOR, row:{ _id:active._id, version:active.version, label:active.label, status }, before:{ status:active.status } });\n    toast(d2, okOrMsg(r,'Erro') || ('Status do ruleset: '+(STATUS_LABEL[status]||status)));\n  }catch(e){ toast(d2,'Erro'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\n}\n"}},"bands":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bands"}}}},"bonuses":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bonuses"}}}},"formulas":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"formulas"}}}},"rulesets":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rulesets"}}}},"bandTables":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bandTables"}}}},"kpis":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"kpis"}}}},"cycles":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cycles"}}}},"writer":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"writer"}}}}}}}}}},{"_id":"6a4c1a542daf06e6ec4c2c43","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotAdminNav","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)'},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\"}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nconst ROUTER = 'pilotAdminRouter';\nconst LINKS = [\n  { href:'/indicadores', label:'Indicadores', glyph:'📊' },\n  { href:'/kpis',        label:'KPIs',        glyph:'🧮' },\n  { href:'/regras',      label:'Regras',      glyph:'⚖️' },\n  { href:'/rulesets',    label:'Rulesets',    glyph:'🗂️' },\n  { href:'/ciclos',      label:'Ciclos',      glyph:'🗓️' },\n  { href:'/auditoria',   label:'Auditoria',   glyph:'🕵️' }\n];\nfunction isActive(here, href){ return here===href || here.indexOf(href+'/')===0; }\nexport default {\n  css: `\n  :host{display:block}\n  .bar{display:flex;align-items:center;gap:8px;height:100%;box-sizing:border-box;padding:0 22px;background:var(--surface);border-bottom:1px solid var(--hair);font-family:var(--fam)}\n  .brand{display:flex;align-items:center;gap:10px;cursor:pointer;padding:6px 6px 6px 0;margin-right:8px;border-radius:10px}\n  .brand .logo{width:26px;height:26px;border-radius:8px;background:var(--grad);display:inline-flex;align-items:center;justify-content:center;color:#fff;font:800 14px/1 var(--fam)}\n  .brand .name{font:800 15px/1 var(--fam);color:var(--ink);letter-spacing:-.2px}\n  .brand .name small{display:block;font:600 10px/1.3 var(--fam);color:var(--muted);letter-spacing:.04em;text-transform:uppercase;margin-top:3px}\n  .links{display:flex;gap:4px;margin-left:6px}\n  .item{display:inline-flex;align-items:center;gap:7px;padding:9px 15px;border-radius:10px;cursor:pointer;font:700 13px/1 var(--fam);color:var(--muted);\n    background:none;border:none;transition:background .15s,color .15s}\n  .item:hover{background:var(--ground);color:var(--ink)}\n  .item[data-active]{color:var(--mag);background:rgba(229,0,75,.10)}\n  .item .g{font-size:14px;line-height:1}\n  .spacer{margin-left:auto}\n  .home{display:inline-flex;align-items:center;gap:6px;padding:8px 13px;border-radius:10px;cursor:pointer;font:700 12px/1 var(--fam);color:var(--muted);\n    background:none;border:1px solid var(--hair);transition:background .15s,color .15s}\n  .home:hover{background:var(--ground);color:var(--ink)}\n  @media (prefers-reduced-motion: reduce){ .item,.home{transition:none!important} }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const here = d2.router(ROUTER).path || '/';\n    const vars = `--surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient};--fam:${t.type.family}`;\n    const links = LINKS.map(l=>`<button class=\"item\" data-href=\"${l.href}\" ${isActive(here,l.href)?'data-active':''}><span class=\"g\">${l.glyph}</span>${esc(l.label)}</button>`).join('');\n    return `<div class=\"bar\" style=\"${vars}\">\n      <div class=\"brand\" data-home>\n        <span class=\"logo\">A</span>\n        <span class=\"name\">Administração<small>Painel de Remuneração</small></span>\n      </div>\n      <div class=\"links\">${links}</div>\n      <span class=\"spacer\"></span>\n      <button class=\"home\" data-home>⌂ Início</button>\n    </div>`;\n  },\n  mounted(d2){\n    d2.on('[data-href]','click',(e,el)=>{ d2.router(ROUTER).goTo(el.dataset.href); });\n    d2.on('[data-home]','click',()=>{ d2.router(ROUTER).goTo('/'); });\n  }\n};"}}}}}}}},{"_id":"6a4c1a6c53bf708a566f210c","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotAdminHome","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)'},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\"},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nconst ROUTER = 'pilotAdminRouter';\nconst CARDS = [\n  { href:'/indicadores', glyph:'📊', title:'Indicadores', desc:'Reordene, edite, duplique ou oculte os indicadores exibidos no dashboard. Arraste pelos punhos para reorganizar.', tag:'Code · DnD' },\n  { href:'/kpis',        glyph:'🧮', title:'KPIs',        desc:'Gerencie as definições dos indicadores (KPIs) que o painel referencia. Edite nome, meta, marca e IAP, ou crie um novo mapeando um código de índice da Performance API.', tag:'Code · Definições' },\n  { href:'/regras',      glyph:'⚖️', title:'Regras',      desc:'Ajuste faixas, bônus e fórmulas por perfil (Líder / GN) que compõem o cálculo de ganhos.', tag:'Code · Remuneração' },\n  { href:'/rulesets',    glyph:'🗂️', title:'Rulesets',    desc:'Versione as regras de remuneração. Duplique um ruleset ativo para preparar o próximo ciclo sem tocar no conjunto em produção.', tag:'Code · Versionamento' },\n  { href:'/ciclos',      glyph:'🗓️', title:'Ciclos',      desc:'Vincule cada ciclo a um ruleset e controle status/ciclo atual. Trocar o ruleset de um ciclo muda o cálculo daquele ciclo.', tag:'Code · Vínculo' },\n  { href:'/auditoria',   glyph:'🕵️', title:'Auditoria',   desc:'Histórico somente-leitura de \"quem alterou o quê e quando\": KPIs, faixas, bônus, fórmulas, rulesets e ciclos. Filtre por entidade, ação, autor e período; expanda para ver o diff completo.', tag:'Code · Somente leitura' }\n];\nexport default {\n  css: `\n  :host{display:block}\n  .home{min-height:100%;height:auto;box-sizing:border-box;background:var(--ground);font-family:var(--fam);padding:40px 44px 64px}\n  .inner{max-width:1000px;margin:0 auto}\n  .hero h1{margin:0;font:800 34px/1.1 var(--fam);color:var(--ink);letter-spacing:-.6px}\n  .hero p{margin:8px 0 0;font:400 15px/1.5 var(--fam);color:var(--muted);max-width:640px}\n  .grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:22px;margin-top:34px}\n  .card{position:relative;background:var(--surface);border:1px solid var(--hair);border-radius:20px;padding:26px;cursor:pointer;\n    box-shadow:var(--shadowcard);transition:box-shadow .2s,transform .2s;overflow:hidden}\n  .card:hover{box-shadow:var(--shadowraised);transform:translateY(-3px)}\n  .card::after{content:'';position:absolute;left:0;top:0;bottom:0;width:5px;background:var(--grad);opacity:0;transition:opacity .2s}\n  .card:hover::after{opacity:1}\n  .card .ico{width:52px;height:52px;border-radius:14px;background:rgba(229,0,75,.10);display:inline-flex;align-items:center;justify-content:center;font-size:26px}\n  .card h2{margin:16px 0 0;font:800 21px/1.15 var(--fam);color:var(--ink);letter-spacing:-.3px}\n  .card .tag{display:inline-block;margin-top:8px;font:700 10px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;\n    color:var(--mag);background:rgba(229,0,75,.10);padding:5px 9px;border-radius:999px}\n  .card p{margin:14px 0 0;font:400 13.5px/1.55 var(--fam);color:var(--muted)}\n  .card .go{margin-top:18px;display:inline-flex;align-items:center;gap:6px;font:700 13px/1 var(--fam);color:var(--mag)}\n  @media (prefers-reduced-motion: reduce){ .card{transition:none!important} .card:hover{transform:none} }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const vars = `--surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient};--fam:${t.type.family};--shadowcard:${t.shadow.card};--shadowraised:${t.shadow.raised}`;\n    const cards = CARDS.map(c=>`<div class=\"card\" data-href=\"${c.href}\">\n      <span class=\"ico\">${c.glyph}</span>\n      <h2>${esc(c.title)} <span class=\"tag\">${esc(c.tag)}</span></h2>\n      <p>${esc(c.desc)}</p>\n      <span class=\"go\">Abrir →</span>\n    </div>`).join('');\n    return `<div class=\"home\" style=\"${vars}\"><div class=\"inner\">\n      <div class=\"hero\">\n        <h1>Administração do Painel</h1>\n        <p>Central de configuração do piloto Natura. Gerencie os indicadores do dashboard e as regras de remuneração a partir de um só lugar.</p>\n      </div>\n      <div class=\"grid\">${cards}</div>\n    </div></div>`;\n  },\n  mounted(d2){\n    d2.on('[data-href]','click',(e,el)=>{ d2.router(ROUTER).goTo(el.dataset.href); });\n  }\n};"}}}}}}}},{"_id":"6a4c507c103d5c4b54fba096","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotRulesetAdmScreen","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',money:'#29AC56'},\n  radius:{sm:8,md:12,lg:16,pill:999},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\"},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nconst ACTOR='gabriel.cardoso@data2.app';\nconst STATUS_LABEL = { draft:'Rascunho', active:'Ativo', archived:'Arquivado' };\nconst ICON = (()=>{\n  const S = (p)=>`<svg class=\"ic-svg\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${p}</svg>`;\n  return {\n    edit:S('<path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/>'),\n    dup:S('<rect x=\"9\" y=\"9\" width=\"11\" height=\"11\" rx=\"2\"/><path d=\"M5 15V5a2 2 0 0 1 2-2h8\"/>'),\n    plus:S('<path d=\"M12 5v14M5 12h14\"/>'),\n    power:S('<path d=\"M18.36 6.64a9 9 0 1 1-12.73 0\"/><path d=\"M12 2v10\"/>'),\n    archive:S('<rect x=\"3\" y=\"4\" width=\"18\" height=\"4\" rx=\"1\"/><path d=\"M5 8v11a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V8\"/><path d=\"M10 12h4\"/>')\n  };\n})();\nconst STATUS_ORDER = ['active','draft','archived'];\n\nfunction cssVars(t){\n  return `--surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient};--money:${t.color.money};--fam:${t.type.family};--shadowcard:${t.shadow.card};--shadowraised:${t.shadow.raised}`;\n}\nfunction countBy(rows, v){ let n=0; for(const r of (rows||[])) if(Number(r.rulesetVersion)===Number(v)) n++; return n; }\nfunction boundCycles(cycles, v){ return (cycles||[]).filter(c=>Number(c.rulesetVersion)===Number(v)); }\nfunction nextVersion(rulesets){ let mx=0; (rulesets||[]).forEach(r=>{ if(Number(r.version)>mx) mx=Number(r.version); }); return mx+1; }\n\nasync function invoke(d2,payload){ return await d2.rush('writer').invoke(payload); }\nfunction refreshAll(d2){ ['rulesets','bands','formulas','bonuses','cycles'].forEach(n=>{ const ds=d2.data(n); if(ds&&ds.refresh) ds.refresh(); }); }\nfunction toast(d2,msg){ d2.setState({ toast:msg }); setTimeout(()=>d2.setState({ toast:null }), 2600); }\n\nfunction statusChip(status){\n  const s = status||'draft';\n  return `<span class=\"chip st-${esc(s)}\">${esc(STATUS_LABEL[s]||s)}</span>`;\n}\n\nfunction renderCard(d2, rs, bands, formulas, bonuses, cycles){\n  const v = rs.version;\n  const nb = countBy(bands,v), nf = countBy(formulas,v), nbo = countBy(bonuses,v);\n  const bc = boundCycles(cycles,v);\n  const bcLabel = bc.length ? bc.map(c=>esc(c.code)).join(', ') : 'nenhum ciclo';\n  return `<div class=\"rcard\" data-key=\"rs-${esc(v)}\">\n    <div class=\"rc-top\">\n      <div class=\"rc-id\">\n        <div class=\"rc-ver\">v${esc(v)}</div>\n        ${statusChip(rs.status)}\n      </div>\n      <div class=\"rc-actions\">\n        <button class=\"mini\" data-edit=\"${esc(v)}\" title=\"Editar rótulo / status\">${ICON.edit} Editar</button>\n        <button class=\"mini\" data-dup=\"${esc(v)}\" title=\"Duplicar para nova versão\">${ICON.dup} Duplicar</button>\n      </div>\n    </div>\n    <div class=\"rc-label\">${esc(rs.label||'—')}</div>\n    <div class=\"rc-counts\">\n      <span class=\"ct\"><b>${nb}</b> faixas</span>\n      <span class=\"ct\"><b>${nf}</b> fórmulas</span>\n      <span class=\"ct\"><b>${nbo}</b> bônus</span>\n    </div>\n    <div class=\"rc-cycles\">Ciclos vinculados: <b>${bcLabel}</b></div>\n    <div class=\"rc-foot\">\n      ${rs.status!=='active'?`<button class=\"mini go\" data-activate=\"${esc(v)}\">${ICON.power} Ativar</button>`:''}\n      ${rs.status!=='archived'?`<button class=\"mini\" data-archive=\"${esc(v)}\">${ICON.archive} Arquivar</button>`:''}\n    </div>\n  </div>`;\n}\n\nfunction renderEditModal(d2){\n  if(!d2.state.editOpen) return '';\n  const m = d2.state.edit || {};\n  const isDup = m._mode==='dup';\n  const isNew = m._mode==='new';\n  const title = isDup ? `Duplicar ruleset v${esc(m.sourceVersion)}` : isNew ? 'Novo ruleset (em branco)' : `Editar ruleset v${esc(m.version)}`;\n  const sub = isDup ? `Clona TODAS as faixas, fórmulas e bônus da v${esc(m.sourceVersion)} para uma nova versão em rascunho.` : isNew ? 'Cria um ruleset vazio (sem faixas). Duplique de um existente para partir de uma base.' : 'Ajuste o rótulo e o status desta versão.';\n  const canDelete = !isNew && !isDup && m._canDelete;\n  return `<div class=\"modal-bg in\" data-mbg>\n    <div class=\"modal\">\n      <h2>${esc(title)}</h2>\n      <p class=\"msub\">${esc(sub)}</p>\n      <div class=\"frow\">\n        <div class=\"field\"><label>Versão</label><input type=\"number\" data-mfield=\"version\" value=\"${esc(m.version)}\" ${(!isNew&&!isDup)?'disabled':''}/></div>\n      </div>\n      <div class=\"frow\">\n        <div class=\"field\"><label>Rótulo</label><input type=\"text\" data-mfield=\"label\" value=\"${esc(m.label||'')}\" placeholder=\"Ex.: Ruleset ciclo 2026 Q3\"/></div>\n      </div>\n      ${(!isNew&&!isDup)?`<div class=\"frow\"><div class=\"field\"><label>Status</label>\n        <select data-mfield=\"status\">${STATUS_ORDER.map(s=>`<option value=\"${s}\" ${((m.status||'draft')===s)?'selected':''}>${STATUS_LABEL[s]}</option>`).join('')}</select>\n      </div></div>`:''}\n      ${canDelete?'':(!isNew&&!isDup?`<div class=\"inertnote\">Só é possível excluir um rascunho sem ciclos vinculados. Esta versão está protegida.</div>`:'')}\n      <div class=\"mfoot\">\n        ${canDelete?`<button class=\"btn danger ${d2.state.armDel?'armed':''}\" data-mdel>${d2.state.armDel?'Confirmar exclusão':'Excluir ruleset'}</button>`:''}\n        <button class=\"btn ghost\" data-mclose>Cancelar</button>\n        <button class=\"btn prim\" data-msave>${isDup?'Duplicar':isNew?'Criar':'Salvar'}</button>\n      </div>\n    </div>\n  </div>`;\n}\n\nexport default {\n  css: `\n  :host{display:block}\n  .screen{min-height:100%;height:auto;display:flex;flex-direction:column;background:var(--ground);font-family:var(--fam);box-sizing:border-box}\n  .header{padding:26px 30px 22px;background:var(--surface);border-bottom:1px solid var(--hair)}\n  .htop{display:flex;align-items:flex-start;gap:16px}\n  .htitle h1{margin:0;font:800 28px/1.1 var(--fam);color:var(--ink);letter-spacing:-.5px}\n  .htitle .badge{display:inline-block;margin-left:10px;font:700 10px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;color:var(--mag);background:rgba(229,0,75,.10);padding:5px 9px;border-radius:999px;vertical-align:middle}\n  .htitle p{margin:6px 0 0;font:400 13px/1.4 var(--fam);color:var(--muted);max-width:640px}\n  .newbtn{margin-left:auto;display:inline-flex;align-items:center;gap:7px;padding:11px 18px;border:none;border-radius:11px;background:var(--grad);color:#fff;font:700 13px/1 var(--fam);cursor:pointer;box-shadow:0 4px 12px rgba(229,0,75,.28);transition:filter .15s,transform .1s}\n  .newbtn:hover{filter:brightness(1.06)} .newbtn:active{transform:scale(.97)}\n  .body{flex:1 1 auto;padding:24px 30px 64px}\n  .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:20px}\n  .rcard{background:var(--surface);border:1px solid var(--hair);border-radius:18px;padding:20px;box-shadow:var(--shadowcard);display:flex;flex-direction:column;gap:12px;transition:box-shadow .18s,transform .18s}\n  .rcard:hover{box-shadow:var(--shadowraised);transform:translateY(-2px)}\n  .rc-top{display:flex;align-items:center;gap:10px}\n  .rc-id{display:flex;align-items:center;gap:10px}\n  .rc-ver{font:800 22px/1 var(--fam);color:var(--ink);letter-spacing:-.4px}\n  .rc-actions{margin-left:auto;display:flex;gap:6px}\n  .chip{font:700 10px/1 var(--fam);letter-spacing:.05em;text-transform:uppercase;padding:5px 9px;border-radius:999px}\n  .chip.st-active{background:rgba(41,172,86,.14);color:var(--money)}\n  .chip.st-draft{background:rgba(107,114,128,.16);color:var(--muted)}\n  .chip.st-archived{background:rgba(138,92,255,.16);color:#6a3ee0}\n  .rc-label{font:600 14px/1.35 var(--fam);color:var(--ink)}\n  .rc-counts{display:flex;gap:14px;flex-wrap:wrap}\n  .rc-counts .ct{font:500 12px/1 var(--fam);color:var(--muted)}\n  .rc-counts .ct b{color:var(--ink);font-weight:800}\n  .rc-cycles{font:500 12px/1.3 var(--fam);color:var(--muted);padding-top:8px;border-top:1px dashed var(--hair)}\n  .rc-cycles b{color:var(--ink)}\n  .rc-foot{display:flex;gap:8px;margin-top:2px}\n  .mini{border:1px solid var(--hair);background:var(--ground);color:var(--muted);padding:7px 11px;border-radius:9px;font:700 11px/1 var(--fam);cursor:pointer;transition:background .15s,color .15s}\n  .mini:hover{background:var(--hair);color:var(--ink)}\n  .mini.go{color:var(--money);border-color:rgba(41,172,86,.3)}\n  .mini.go:hover{background:rgba(41,172,86,.12);color:var(--money)}\n  .ic-svg{display:inline-block;vertical-align:-2px;flex:0 0 auto}\n  .mini .ic-svg{width:13px;height:13px}\n  .newbtn .ic-svg{width:15px;height:15px;vertical-align:middle}\n  .toast{position:fixed;left:50%;bottom:26px;transform:translate(-50%,20px);background:var(--ink);color:#fff;padding:12px 20px;border-radius:12px;font:600 13px/1 var(--fam);box-shadow:0 10px 30px rgba(0,0,0,.3);z-index:9500;opacity:0;transition:opacity .2s,transform .2s;pointer-events:none}\n  .toast.in{opacity:1;transform:translate(-50%,0)}\n  .modal-bg{position:fixed;inset:0;background:rgba(16,24,40,.42);z-index:9000;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s;padding:24px}\n  .modal-bg.in{opacity:1}\n  .modal{background:var(--surface);border-radius:20px;box-shadow:var(--shadowraised);width:min(460px,100%);max-width:100%;box-sizing:border-box;max-height:88vh;overflow:auto;padding:24px 26px;transform:translateY(14px) scale(.98);transition:transform .24s cubic-bezier(.34,1.4,.64,1)}\n  .modal-bg.in .modal{transform:none}\n  .modal h2{margin:0 0 4px;font:800 20px/1.1 var(--fam);color:var(--ink)}\n  .modal .msub{margin:0 0 18px;font:500 12px/1.4 var(--fam);color:var(--muted)}\n  .frow{display:flex;gap:12px;margin-bottom:14px;flex-wrap:wrap}\n  .field{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:6px}\n  .field label{font:600 11px/1 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.05em}\n  .field input,.field select{width:100%;max-width:100%;box-sizing:border-box;padding:10px 12px;border:1.5px solid var(--hair);border-radius:10px;font:600 14px/1 var(--fam);color:var(--ink);outline:none;background:var(--surface);transition:border-color .15s}\n  .field input:disabled{background:var(--ground);color:var(--muted)}\n  .field input:focus,.field select:focus{border-color:var(--mag)}\n  .inertnote{margin:2px 0 16px;padding:10px 12px;border-radius:10px;background:rgba(247,190,0,.12);border:1px solid rgba(247,190,0,.35);font:600 11px/1.4 var(--fam);color:#8a6d00}\n  .mfoot{display:flex;gap:10px;justify-content:flex-end;margin-top:22px;align-items:center}\n  .btn{padding:11px 20px;border-radius:11px;font:700 13px/1 var(--fam);cursor:pointer;border:none;transition:filter .15s,transform .1s,background .15s}\n  .btn.ghost{background:var(--ground);color:var(--muted)} .btn.ghost:hover{background:var(--hair)}\n  .btn.prim{background:var(--grad);color:#fff;box-shadow:0 4px 12px rgba(229,0,75,.28)} .btn.prim:hover{filter:brightness(1.06)} .btn.prim:active{transform:scale(.97)}\n  .btn.danger{background:rgba(214,20,25,.10);color:#d61419;margin-right:auto} .btn.danger:hover{background:rgba(214,20,25,.18)}\n  .btn.danger.armed{background:#d61419;color:#fff}\n  .saving{display:inline-flex;align-items:center;gap:6px;color:var(--mag);font:700 12px/1 var(--fam);margin-left:6px}\n  .spin{width:12px;height:12px;border:2px solid rgba(229,0,75,.25);border-top-color:var(--mag);border-radius:50%;animation:sp .7s linear infinite}\n  @keyframes sp{to{transform:rotate(360deg)}}\n  @media (prefers-reduced-motion: reduce){ .rcard,.mini,.btn,.newbtn,.toast,.modal-bg,.modal{transition:none!important} .rcard:hover{transform:none} .spin{animation:none} }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const rsDs = d2.data('rulesets'); const rulesets = rsDs ? rsDs.records() : [];\n    const bands = (d2.data('bands')||{records:()=>[]}).records ? (d2.data('bands')?d2.data('bands').records():[]) : [];\n    const formulas = d2.data('formulas') ? d2.data('formulas').records() : [];\n    const bonuses = d2.data('bonuses') ? d2.data('bonuses').records() : [];\n    const cycles = d2.data('cycles') ? d2.data('cycles').records() : [];\n    const loading = rsDs && rsDs.loading;\n    const vars = cssVars(t);\n    const sorted = rulesets.slice().sort((a,b)=>Number(a.version)-Number(b.version));\n    const cards = sorted.map(rs=>renderCard(d2,rs,bands,formulas,bonuses,cycles)).join('');\n    return `<div class=\"screen\" style=\"${vars}\">\n      <div class=\"header\">\n        <div class=\"htop\">\n          <div class=\"htitle\">\n            <h1>Rulesets <span class=\"badge\">Code · Versionamento</span></h1>\n            <p>Cada ruleset é uma versão completa das regras de remuneração (faixas, fórmulas e bônus). Duplique um ruleset ativo para preparar as regras do próximo ciclo sem tocar no conjunto em produção.</p>\n          </div>\n          <button class=\"newbtn\" data-new>${ICON.plus} Novo ruleset</button>\n        </div>\n        ${d2.state.saving?`<span class=\"saving\"><span class=\"spin\"></span>Processando…</span>`:''}\n      </div>\n      <div class=\"body\">\n        ${loading?`<div style=\"padding:60px;text-align:center;color:${t.color.muted}\">Carregando rulesets…</div>`:`<div class=\"grid\">${cards}</div>`}\n      </div>\n      ${renderEditModal(d2)}\n      <div class=\"toast ${d2.state.toast?'in':''}\">${esc(d2.state.toast||'')}</div>\n    </div>`;\n  },\n  mounted(d2){\n    d2.on('[data-new]','click',()=>{ const rs=d2.data('rulesets')?d2.data('rulesets').records():[]; d2.setState({ editOpen:true, armDel:false, edit:{ _mode:'new', version:nextVersion(rs), label:'', status:'draft' } }); });\n    d2.on('[data-dup]','click',(e,el)=>{ const v=Number(el.dataset.dup); const rs=d2.data('rulesets')?d2.data('rulesets').records():[]; const src=rs.find(r=>Number(r.version)===v)||{}; d2.setState({ editOpen:true, armDel:false, edit:{ _mode:'dup', sourceVersion:v, version:nextVersion(rs), label:`${src.label||('Ruleset v'+v)} (cópia)` } }); });\n    d2.on('[data-edit]','click',(e,el)=>{ const v=Number(el.dataset.edit); openEdit(d2,v); });\n    d2.on('[data-activate]','click',(e,el)=>{ setStatus(d2, Number(el.dataset.activate), 'active'); });\n    d2.on('[data-archive]','click',(e,el)=>{ setStatus(d2, Number(el.dataset.archive), 'archived'); });\n\n    d2.on('[data-mfield]','input',(e,el)=>{ const m={...(d2.state.edit||{})}; m[el.dataset.mfield]=el.value; d2.state.edit=m; });\n    d2.on('[data-mfield]','change',(e,el)=>{ const m={...(d2.state.edit||{})}; m[el.dataset.mfield]=el.value; d2.state.edit=m; });\n    d2.on('[data-mclose]','click',()=>d2.setState({ editOpen:false, armDel:false }));\n    d2.on('[data-mbg]','click',(e,el)=>{ if(e.target===el) d2.setState({ editOpen:false, armDel:false }); });\n    d2.on('[data-msave]','click',()=>saveEdit(d2));\n    d2.on('[data-mdel]','click',()=>{ if(d2.state.armDel){ delRuleset(d2); } else { d2.setState({ armDel:true }); setTimeout(()=>{ if(d2.state.armDel) d2.setState({ armDel:false }); },3000); } });\n  }\n};\n\nfunction openEdit(d2, v){\n  const rs = d2.data('rulesets')?d2.data('rulesets').records():[];\n  const cycles = d2.data('cycles')?d2.data('cycles').records():[];\n  const bands = d2.data('bands')?d2.data('bands').records():[];\n  const cur = rs.find(r=>Number(r.version)===v); if(!cur) return;\n  const bc = boundCycles(cycles,v);\n  const nb = countBy(bands,v);\n  const canDelete = (cur.status==='draft') && bc.length===0 && rs.length>1;\n  d2.setState({ editOpen:true, armDel:false, edit:{ _mode:'edit', _id:cur._id, _canDelete:canDelete, version:cur.version, label:cur.label||'', status:cur.status||'draft' } });\n}\n\nasync function saveEdit(d2){\n  const m = d2.state.edit || {};\n  d2.setState({ saving:true, editOpen:false, armDel:false });\n  try{\n    if(m._mode==='dup'){\n      const r = await invoke(d2,{ entity:'ruleset', op:'duplicate', actorEmail:ACTOR, row:{ sourceVersion:Number(m.sourceVersion), version:Number(m.version), label:String(m.label||('Ruleset v'+m.version)) }, before:{} });\n      const c = r && r.data && r.data.cloned || {};\n      toast(d2, `Ruleset v${m.version} criado — ${c.bands||0} faixas, ${c.formulas||0} fórmulas, ${c.bonuses||0} bônus clonados`);\n    } else if(m._mode==='new'){\n      await invoke(d2,{ entity:'ruleset', op:'upsert', actorEmail:ACTOR, row:{ version:Number(m.version), label:String(m.label||('Ruleset v'+m.version)), status:'draft' }, before:{} });\n      toast(d2, `Ruleset v${m.version} criado (em branco)`);\n    } else {\n      await invoke(d2,{ entity:'ruleset', op:'upsert', actorEmail:ACTOR, row:{ _id:m._id, version:Number(m.version), label:String(m.label||''), status:m.status||'draft' }, before:{ label:m.label, status:m.status } });\n      toast(d2, `Ruleset v${m.version} atualizado`);\n    }\n  }catch(e){ toast(d2,'Erro ao salvar ruleset'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\n}\n\nasync function setStatus(d2, v, status){\n  const rs = d2.data('rulesets')?d2.data('rulesets').records():[];\n  const cur = rs.find(r=>Number(r.version)===v); if(!cur||cur.status===status) return;\n  d2.setState({ saving:true });\n  try{\n    // Activate: demote any other active ruleset to archived first (single-active invariant).\n    if(status==='active'){\n      const others = rs.filter(r=>r.status==='active' && Number(r.version)!==v);\n      for(const o of others){\n        await invoke(d2,{ entity:'ruleset', op:'upsert', actorEmail:ACTOR, row:{ _id:o._id, version:o.version, label:o.label, status:'archived' }, before:{ status:'active' } });\n      }\n    }\n    await invoke(d2,{ entity:'ruleset', op:'upsert', actorEmail:ACTOR, row:{ _id:cur._id, version:cur.version, label:cur.label, status }, before:{ status:cur.status } });\n    toast(d2, `Ruleset v${v}: ${STATUS_LABEL[status]}`);\n  }catch(e){ toast(d2,'Erro ao alterar status'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\n}\n\nasync function delRuleset(d2){\n  const m = d2.state.edit || {};\n  d2.setState({ saving:true, editOpen:false, armDel:false });\n  try{\n    await invoke(d2,{ entity:'ruleset', op:'delete', actorEmail:ACTOR, row:{ _id:m._id }, before:{ version:m.version, label:m.label } });\n    toast(d2, `Ruleset v${m.version} excluído`);\n  }catch(e){ toast(d2,'Erro ao excluir'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\n}\n"}},"rulesets":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rulesets"}}}},"bands":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bands"}}}},"formulas":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"formulas"}}}},"bonuses":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bonuses"}}}},"cycles":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cycles"}}}},"writer":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"writer"}}}}}}}}}},{"_id":"6a4c50d2cafa01f91f642faa","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotCycleAdmScreen","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',money:'#29AC56'},\n  radius:{sm:8,md:12,lg:16,pill:999},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\"},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nconst ACTOR='gabriel.cardoso@data2.app';\nconst STATUS_LABEL = { scheduled:'Agendado', open:'Aberto', closed:'Fechado' };\nconst STATUS_KEYS = ['scheduled','open','closed'];\nconst RS_STATUS_LABEL = { draft:'Rascunho', active:'Ativo', archived:'Arquivado' };\nconst ICON = (()=>{\n  const S = (p)=>`<svg class=\"ic-svg\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${p}</svg>`;\n  return { plus:S('<path d=\"M12 5v14M5 12h14\"/>') };\n})();\n\nfunction cssVars(t){\n  return `--surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient};--money:${t.color.money};--fam:${t.type.family};--shadowcard:${t.shadow.card};--shadowraised:${t.shadow.raised}`;\n}\nfunction rsLabel(rulesets, v){ const r=(rulesets||[]).find(x=>Number(x.version)===Number(v)); return r ? `v${r.version} · ${r.label||''}` : (v!=null?`v${v}`:'—'); }\n\nasync function invoke(d2,payload){ return await d2.rush('writer').invoke(payload); }\nfunction refreshAll(d2){ ['cycles','rulesets'].forEach(n=>{ const ds=d2.data(n); if(ds&&ds.refresh) ds.refresh(); }); }\nfunction toast(d2,msg){ d2.setState({ toast:msg }); setTimeout(()=>d2.setState({ toast:null }), 2600); }\n\nfunction rsOptions(rulesets, cur){\n  const sorted = (rulesets||[]).slice().sort((a,b)=>Number(a.version)-Number(b.version));\n  return sorted.map(r=>`<option value=\"${esc(r.version)}\" ${Number(cur)===Number(r.version)?'selected':''}>v${esc(r.version)} — ${esc(r.label||'')} [${esc(RS_STATUS_LABEL[r.status]||r.status||'')}]</option>`).join('');\n}\n\nfunction renderRow(d2, c, rulesets){\n  // controls show the pending draft (d2.state.draft[code]) over the stored record, so edits stick across re-renders\n  const st = curVal(d2, c.code, 'status') || 'open';\n  const rsv = curVal(d2, c.code, 'rulesetVersion');\n  const isCur = !!curVal(d2, c.code, 'isCurrent');\n  const lbl = curVal(d2, c.code, 'label');\n  const dirty = !!(d2.state.draft||{})[c.code];\n  return `<div class=\"crow\" data-key=\"cy-${esc(c.code)}\">\n    <div class=\"cy-id\">\n      <div class=\"cy-code\">${esc(c.code)}</div>\n      <div class=\"cy-label\">${esc(c.label||'—')}</div>\n    </div>\n    <div class=\"cy-badges\">\n      <span class=\"chip st-${esc(st)}\">${esc(STATUS_LABEL[st]||st)}</span>\n      ${c.isCurrent?`<span class=\"chip cur\">● Atual</span>`:''}\n      <span class=\"chip rs\">${esc(rsLabel(rulesets,c.rulesetVersion))}</span>\n    </div>\n    <div class=\"cy-ctl\">\n      <div class=\"field\">\n        <label>Rótulo</label>\n        <input type=\"text\" data-lb=\"${esc(c.code)}\" value=\"${esc(lbl||'')}\" placeholder=\"Ciclo ${esc(c.code)}\"/>\n      </div>\n      <div class=\"field\">\n        <label>Ruleset vinculado</label>\n        <select data-rs=\"${esc(c.code)}\">${rsOptions(rulesets, rsv)}</select>\n      </div>\n      <div class=\"field\">\n        <label>Status</label>\n        <select data-st=\"${esc(c.code)}\">${STATUS_KEYS.map(s=>`<option value=\"${s}\" ${st===s?'selected':''}>${STATUS_LABEL[s]}</option>`).join('')}</select>\n      </div>\n      <div class=\"field toggle\">\n        <label>Ciclo atual</label>\n        <button class=\"tog ${isCur?'on':''}\" data-cur=\"${esc(c.code)}\"><span class=\"knob\"></span></button>\n      </div>\n      <button class=\"btn prim save\" data-save=\"${esc(c.code)}\">${dirty?'Salvar •':'Salvar'}</button>\n    </div>\n  </div>`;\n}\n\nexport default {\n  css: `\n  :host{display:block}\n  .screen{min-height:100%;height:auto;display:flex;flex-direction:column;background:var(--ground);font-family:var(--fam);box-sizing:border-box}\n  .header{padding:26px 30px 22px;background:var(--surface);border-bottom:1px solid var(--hair)}\n  .htop{display:flex;align-items:flex-start;gap:16px}\n  .htitle h1{margin:0;font:800 28px/1.1 var(--fam);color:var(--ink);letter-spacing:-.5px}\n  .htitle .badge{display:inline-block;margin-left:10px;font:700 10px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;color:var(--mag);background:rgba(229,0,75,.10);padding:5px 9px;border-radius:999px;vertical-align:middle}\n  .htitle p{margin:6px 0 0;font:400 13px/1.4 var(--fam);color:var(--muted);max-width:680px}\n  .newbtn{margin-left:auto;display:inline-flex;align-items:center;gap:7px;padding:11px 18px;border:none;border-radius:11px;background:var(--grad);color:#fff;font:700 13px/1 var(--fam);cursor:pointer;box-shadow:0 4px 12px rgba(229,0,75,.28);transition:filter .15s,transform .1s}\n  .newbtn:hover{filter:brightness(1.06)} .newbtn:active{transform:scale(.97)}\n  .ic-svg{display:block;flex:0 0 auto}\n  .newbtn .ic-svg{width:15px;height:15px}\n  .body{flex:1 1 auto;padding:24px 30px 64px;display:flex;flex-direction:column;gap:16px}\n  .crow{background:var(--surface);border:1px solid var(--hair);border-radius:16px;padding:18px 20px;box-shadow:var(--shadowcard);display:flex;flex-wrap:wrap;align-items:center;gap:18px}\n  .cy-id{min-width:220px}\n  .cy-code{font:800 20px/1 var(--fam);color:var(--ink);letter-spacing:-.3px}\n  .cy-label{font:500 12px/1.3 var(--fam);color:var(--muted);margin-top:4px}\n  .cy-badges{display:flex;gap:6px;flex-wrap:wrap;align-items:center}\n  .chip{font:700 10px/1 var(--fam);letter-spacing:.04em;text-transform:uppercase;padding:5px 9px;border-radius:999px}\n  .chip.st-open{background:rgba(41,172,86,.14);color:var(--money)}\n  .chip.st-scheduled{background:rgba(72,152,255,.16);color:#1462c7}\n  .chip.st-closed{background:rgba(107,114,128,.16);color:var(--muted)}\n  .chip.cur{background:rgba(229,0,75,.12);color:var(--mag)}\n  .chip.rs{background:rgba(72,152,255,.16);color:#1462c7;text-transform:none;letter-spacing:0}\n  .cy-ctl{margin-left:auto;display:flex;align-items:flex-end;gap:14px;flex-wrap:wrap}\n  .field{display:flex;flex-direction:column;gap:6px;min-width:0}\n  .field label{font:600 10px/1 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.05em}\n  .field input{width:180px;box-sizing:border-box;padding:9px 11px;border:1.5px solid var(--hair);border-radius:10px;font:600 13px/1 var(--fam);color:var(--ink);outline:none;background:var(--surface)}\n  .field input:focus{border-color:var(--mag)}\n  .field select{min-width:220px;max-width:340px;box-sizing:border-box;padding:9px 11px;border:1.5px solid var(--hair);border-radius:10px;font:600 13px/1 var(--fam);color:var(--ink);outline:none;background:var(--surface);transition:border-color .15s}\n  .field select:focus{border-color:var(--mag)}\n  .field.toggle{align-items:flex-start}\n  .tog{width:44px;height:26px;border-radius:999px;border:none;background:var(--hair);position:relative;cursor:pointer;transition:background .18s}\n  .tog.on{background:var(--money)}\n  .tog .knob{position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.25);transition:transform .18s}\n  .tog.on .knob{transform:translateX(18px)}\n  .btn{padding:10px 18px;border-radius:10px;font:700 13px/1 var(--fam);cursor:pointer;border:none;transition:filter .15s,transform .1s}\n  .btn.prim{background:var(--grad);color:#fff;box-shadow:0 4px 12px rgba(229,0,75,.28)} .btn.prim:hover{filter:brightness(1.06)} .btn.prim:active{transform:scale(.97)}\n  .toast{position:fixed;left:50%;bottom:26px;transform:translate(-50%,20px);background:var(--ink);color:#fff;padding:12px 20px;border-radius:12px;font:600 13px/1 var(--fam);box-shadow:0 10px 30px rgba(0,0,0,.3);z-index:9500;opacity:0;transition:opacity .2s,transform .2s;pointer-events:none}\n  .toast.in{opacity:1;transform:translate(-50%,0)}\n  .modal-bg{position:fixed;inset:0;background:rgba(16,24,40,.42);z-index:9000;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s;padding:24px}\n  .modal-bg.in{opacity:1}\n  .modal{background:var(--surface);border-radius:20px;box-shadow:var(--shadowraised);width:min(440px,100%);max-width:100%;box-sizing:border-box;padding:24px 26px;transform:translateY(14px) scale(.98);transition:transform .24s cubic-bezier(.34,1.4,.64,1)}\n  .modal-bg.in .modal{transform:none}\n  .modal h2{margin:0 0 4px;font:800 20px/1.1 var(--fam);color:var(--ink)}\n  .modal .msub{margin:0 0 18px;font:500 12px/1.4 var(--fam);color:var(--muted)}\n  .frow{display:flex;gap:12px;margin-bottom:14px;flex-wrap:wrap}\n  .mfield{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:6px}\n  .mfield label{font:600 11px/1 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.05em}\n  .mfield input,.mfield select{width:100%;max-width:100%;box-sizing:border-box;padding:10px 12px;border:1.5px solid var(--hair);border-radius:10px;font:600 14px/1 var(--fam);color:var(--ink);outline:none;background:var(--surface)}\n  .mfield input:focus,.mfield select:focus{border-color:var(--mag)}\n  .mfoot{display:flex;gap:10px;justify-content:flex-end;margin-top:22px}\n  .btn.ghost{background:var(--ground);color:var(--muted)} .btn.ghost:hover{background:var(--hair)}\n  .saving{display:inline-flex;align-items:center;gap:6px;color:var(--mag);font:700 12px/1 var(--fam);margin-left:6px}\n  .spin{width:12px;height:12px;border:2px solid rgba(229,0,75,.25);border-top-color:var(--mag);border-radius:50%;animation:sp .7s linear infinite}\n  @keyframes sp{to{transform:rotate(360deg)}}\n  @media (prefers-reduced-motion: reduce){ .crow,.tog,.tog .knob,.btn,.newbtn,.toast,.modal-bg,.modal{transition:none!important} .spin{animation:none} }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const cyDs = d2.data('cycles'); const cycles = cyDs ? cyDs.records() : [];\n    const rulesets = d2.data('rulesets') ? d2.data('rulesets').records() : [];\n    const loading = cyDs && cyDs.loading;\n    const vars = cssVars(t);\n    const sorted = cycles.slice().sort((a,b)=>String(b.code).localeCompare(String(a.code)));\n    const rows = sorted.map(c=>renderRow(d2,c,rulesets)).join('');\n    return `<div class=\"screen\" style=\"${vars}\">\n      <div class=\"header\">\n        <div class=\"htop\">\n          <div class=\"htitle\">\n            <h1>Ciclos <span class=\"badge\">Code · Vínculo de regras</span></h1>\n            <p>Cada ciclo aponta para um ruleset. Ao trocar o ruleset de um ciclo, o cálculo de remuneração daquele ciclo passa a usar as faixas/fórmulas/bônus da versão escolhida — imediatamente. Também controle status (aberto/fechado) e o ciclo atual.</p>\n          </div>\n          <button class=\"newbtn\" data-newcy>${ICON.plus} Novo ciclo</button>\n        </div>\n        ${d2.state.saving?`<span class=\"saving\"><span class=\"spin\"></span>Salvando…</span>`:''}\n      </div>\n      <div class=\"body\">\n        ${loading?`<div style=\"padding:60px;text-align:center;color:${t.color.muted}\">Carregando ciclos…</div>`:rows}\n      </div>\n      ${renderNewModal(d2,rulesets)}\n      <div class=\"toast ${d2.state.toast?'in':''}\">${esc(d2.state.toast||'')}</div>\n    </div>`;\n  },\n  mounted(d2){\n    d2.state.draft = d2.state.draft || {};\n    // per-row pending edits (rs/status/isCurrent) live in d2.state.draft[code]\n    d2.on('[data-rs]','change',(e,el)=>{ setDraft(d2, el.dataset.rs, 'rulesetVersion', Number(el.value)); });\n    d2.on('[data-st]','change',(e,el)=>{ setDraft(d2, el.dataset.st, 'status', el.value); });\n    // label: write the draft on every keystroke WITHOUT re-rendering (keeps focus); commit/re-render on change\n    d2.on('[data-lb]','input',(e,el)=>{ const all={...(d2.state.draft||{})}; all[el.dataset.lb]={...(all[el.dataset.lb]||{}), label:el.value}; d2.state.draft=all; });\n    d2.on('[data-lb]','change',(e,el)=>{ setDraft(d2, el.dataset.lb, 'label', el.value); });\n    d2.on('[data-cur]','click',(e,el)=>{ const code=el.dataset.cur; const cur=curVal(d2,code,'isCurrent'); setDraft(d2, code, 'isCurrent', !cur); });\n    d2.on('[data-save]','click',(e,el)=>saveCycle(d2, el.dataset.save));\n\n    d2.on('[data-newcy]','click',()=>{ const rs=d2.data('rulesets')?d2.data('rulesets').records():[]; const activeRs=rs.find(r=>r.status==='active')||rs[0]||{version:1}; d2.setState({ newOpen:true, newCy:{ code:'', label:'', status:'open', rulesetVersion:activeRs.version, isCurrent:false } }); });\n    d2.on('[data-nfield]','input',(e,el)=>{ const m={...(d2.state.newCy||{})}; m[el.dataset.nfield]=el.value; d2.state.newCy=m; });\n    d2.on('[data-nfield]','change',(e,el)=>{ const m={...(d2.state.newCy||{})}; m[el.dataset.nfield]=el.value; d2.state.newCy=m; });\n    d2.on('[data-nclose]','click',()=>d2.setState({ newOpen:false }));\n    d2.on('[data-nbg]','click',(e,el)=>{ if(e.target===el) d2.setState({ newOpen:false }); });\n    d2.on('[data-nsave]','click',()=>saveNewCycle(d2));\n  }\n};\n\nfunction curVal(d2, code, key){\n  const draft = (d2.state.draft||{})[code]||{};\n  if(key in draft) return draft[key];\n  const cy = (d2.data('cycles')?d2.data('cycles').records():[]).find(c=>String(c.code)===String(code))||{};\n  return cy[key];\n}\nfunction setDraft(d2, code, key, val){\n  const all = {...(d2.state.draft||{})};\n  const row = {...(all[code]||{})};\n  row[key] = val;\n  all[code] = row;\n  d2.setState({ draft: all });\n}\n\nasync function saveCycle(d2, code){\n  const cy = (d2.data('cycles')?d2.data('cycles').records():[]).find(c=>String(c.code)===String(code));\n  if(!cy) return;\n  const draft = (d2.state.draft||{})[code]||{};\n  const row = {\n    _id: cy._id,\n    code: cy.code,\n    label: ('label' in draft)?String(draft.label||'').trim():(cy.label||''),\n    status: ('status' in draft)?draft.status:(cy.status||'open'),\n    isCurrent: ('isCurrent' in draft)?!!draft.isCurrent:!!cy.isCurrent,\n    rulesetVersion: ('rulesetVersion' in draft)?Number(draft.rulesetVersion):Number(cy.rulesetVersion||1),\n    dashboardConfigVersion: Number(cy.dashboardConfigVersion||1)\n  };\n  const before = { label: cy.label, rulesetVersion: cy.rulesetVersion, status: cy.status, isCurrent: cy.isCurrent };\n  d2.setState({ saving:true });\n  try{\n    await invoke(d2,{ entity:'cycle', op:'upsert', actorEmail:ACTOR, row, before });\n    // clear this row's draft\n    const all = {...(d2.state.draft||{})}; delete all[code]; d2.setState({ draft: all });\n    toast(d2, `Ciclo ${code} salvo — ruleset v${row.rulesetVersion}`);\n  }catch(e){ toast(d2,'Erro ao salvar ciclo'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\n}\n\nfunction renderNewModal(d2, rulesets){\n  if(!d2.state.newOpen) return '';\n  const m = d2.state.newCy || {};\n  const sorted = (rulesets||[]).slice().sort((a,b)=>Number(a.version)-Number(b.version));\n  return `<div class=\"modal-bg in\" data-nbg>\n    <div class=\"modal\">\n      <h2>Novo ciclo</h2>\n      <p class=\"msub\">Cadastre um ciclo e vincule-o a um ruleset. O código é a chave (ex.: 202611).</p>\n      <div class=\"frow\">\n        <div class=\"mfield\"><label>Código</label><input type=\"text\" data-nfield=\"code\" value=\"${esc(m.code||'')}\" placeholder=\"202611\"/></div>\n        <div class=\"mfield\"><label>Status</label><select data-nfield=\"status\">${STATUS_KEYS.map(s=>`<option value=\"${s}\" ${((m.status||'open')===s)?'selected':''}>${STATUS_LABEL[s]}</option>`).join('')}</select></div>\n      </div>\n      <div class=\"frow\">\n        <div class=\"mfield\"><label>Rótulo</label><input type=\"text\" data-nfield=\"label\" value=\"${esc(m.label||'')}\" placeholder=\"Ciclo 202611\"/></div>\n      </div>\n      <div class=\"frow\">\n        <div class=\"mfield\"><label>Ruleset vinculado</label><select data-nfield=\"rulesetVersion\">${sorted.map(r=>`<option value=\"${esc(r.version)}\" ${Number(m.rulesetVersion)===Number(r.version)?'selected':''}>v${esc(r.version)} — ${esc(r.label||'')}</option>`).join('')}</select></div>\n      </div>\n      <div class=\"mfoot\">\n        <button class=\"btn ghost\" data-nclose>Cancelar</button>\n        <button class=\"btn prim\" data-nsave>Criar ciclo</button>\n      </div>\n    </div>\n  </div>`;\n}\n\nasync function saveNewCycle(d2){\n  const m = d2.state.newCy || {};\n  if(!m.code || !String(m.code).trim()){ toast(d2,'Informe o código do ciclo'); return; }\n  const row = {\n    code: String(m.code).trim(),\n    label: String(m.label||('Ciclo '+m.code)).trim(),\n    status: m.status||'open',\n    isCurrent: !!m.isCurrent,\n    rulesetVersion: Number(m.rulesetVersion)||1,\n    dashboardConfigVersion: 1\n  };\n  d2.setState({ saving:true, newOpen:false });\n  try{\n    await invoke(d2,{ entity:'cycle', op:'upsert', actorEmail:ACTOR, row, before:{} });\n    toast(d2, `Ciclo ${row.code} criado — ruleset v${row.rulesetVersion}`);\n  }catch(e){ toast(d2,'Erro ao criar ciclo'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\n}\n"}},"cycles":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cycles"}}}},"rulesets":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rulesets"}}}},"writer":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"writer"}}}}}}}}}},{"_id":"6a4c54c0d2eba06a60ceff9a","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotKpiAdmScreen","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',money:'#29AC56',gold:'#F7BE00'},\n  radius:{sm:8,md:12,lg:16,pill:999},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\"},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nconst BRAND_LABEL = { natura:'Natura', avon:'Avon', total:'Total' };\nconst SOURCE_LABEL = { 'performance-api':'Performance API', 'databricks-query':'Databricks query' };\nconst ICONS = ['brand-natura','brand-avon','people','target','crown','swap','user-add','coins','user'];\nconst ICON_LABEL = { 'brand-natura':'Natura (folha)','brand-avon':'Avon (gota)','people':'Pessoas','target':'Alvo','crown':'Coroa','swap':'Troca','user-add':'Adicionar pessoa','coins':'Moedas','user':'Pessoa' };\n// Lucide (ISC) — paths inline, sem lib\nconst LUCIDE = {\n  'brand-natura':'<path d=\"M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 4.18 2 8 0 5.5-4.78 10-10 10Z\"/><path d=\"M2 21c0-3 1.85-5.36 5.08-6C9.5 14.52 12 13 13 12\"/>',\n  'brand-avon':'<path d=\"M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5C6 11.1 5 13 5 15a7 7 0 0 0 7 7z\"/>',\n  'people':'<path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><path d=\"M22 21v-2a4 4 0 0 0-3-3.87\"/><path d=\"M16 3.13a4 4 0 0 1 0 7.75\"/>',\n  'target':'<circle cx=\"12\" cy=\"12\" r=\"10\"/><circle cx=\"12\" cy=\"12\" r=\"6\"/><circle cx=\"12\" cy=\"12\" r=\"2\"/>',\n  'crown':'<path d=\"M11.562 3.266a.5.5 0 0 1 .876 0L15.39 8.87a1 1 0 0 0 1.516.294L21.183 5.5a.5.5 0 0 1 .798.519l-2.834 10.246a1 1 0 0 1-.956.734H5.81a1 1 0 0 1-.957-.734L2.02 6.02a.5.5 0 0 1 .798-.519l4.276 3.664a1 1 0 0 0 1.516-.294z\"/><path d=\"M5 21h14\"/>',\n  'swap':'<path d=\"M8 3 4 7l4 4\"/><path d=\"M4 7h16\"/><path d=\"m16 21 4-4-4-4\"/><path d=\"M20 17H4\"/>',\n  'user-add':'<path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><line x1=\"19\" x2=\"19\" y1=\"8\" y2=\"14\"/><line x1=\"22\" x2=\"16\" y1=\"11\" y2=\"11\"/>',\n  'coins':'<circle cx=\"8\" cy=\"8\" r=\"6\"/><path d=\"M18.09 10.37A6 6 0 1 1 10.34 18\"/><path d=\"M7 6h1v4\"/><path d=\"m16.71 13.88.7.71-2.82 2.82\"/>',\n  'user':'<path d=\"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\"/><circle cx=\"12\" cy=\"7\" r=\"4\"/>',\n  'chart':'<path d=\"M3 3v18h18\"/><path d=\"M18 17V9\"/><path d=\"M13 17V5\"/><path d=\"M8 17v-3\"/>'\n};\nfunction lucide(name){ return `<svg class=\"lu\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${LUCIDE[name]||LUCIDE.chart}</svg>`; }\nconst ICON = (()=>{\n  const S = (p)=>`<svg class=\"ic-svg\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${p}</svg>`;\n  return {\n    edit:S('<path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/>'),\n    dup:S('<rect x=\"9\" y=\"9\" width=\"11\" height=\"11\" rx=\"2\"/><path d=\"M5 15V5a2 2 0 0 1 2-2h8\"/>'),\n    del:S('<path d=\"M3 6h18\"/><path d=\"M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/>'),\n    ok:S('<path d=\"M20 6 9 17l-5-5\"/>'),\n    x:S('<path d=\"M18 6 6 18M6 6l12 12\"/>'),\n    plus:S('<path d=\"M12 5v14M5 12h14\"/>'),\n    search:S('<circle cx=\"11\" cy=\"11\" r=\"7\"/><path d=\"m21 21-4.3-4.3\"/>')\n  };\n})();\n\nfunction cssVars(t){\n  return `--surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient};--money:${t.color.money};--gold:${t.color.gold||'#F7BE00'};--fam:${t.type.family};--shadowcard:${t.shadow.card};--shadowraised:${t.shadow.raised}`;\n}\n\nasync function invoke(d2,payload){ return await d2.rush('writer').invoke(payload); }\nfunction refreshAll(d2){ const ds=d2.data('kpis'); if(ds&&ds.refresh) ds.refresh(); }\nfunction toast(d2,msg){ d2.setState({ toast:msg }); setTimeout(()=>d2.setState({ toast:null }), 2600); }\n\nfunction refCount(kpis, row){\n  const code = String(row.code||'');\n  if(!code) return 0;\n  return (kpis||[]).filter(k=>k._id!==row._id && String(k.code)===code).length;\n}\n\n// Uma linha por posição de card (código × perfil × rede × seção). Linhas do líder vieram só com label e goalKey.\nfunction norm(k){ return { ...k, name: k.name || k.label || '', hasGoal: !!(k.hasGoal || k.goalKey) }; }\nconst PERFIL_LABEL = { gn:'GN', lider:'Líder', gv:'GV', all:'Todos' };\nconst REDE_LABEL = { rede1:'Rede 1', rede2:'Rede 2', both:'Ambas' };\nconst SECTION_LABEL = { 'leader-card':'Cartão', 'sector-kpi':'KPI do setor', 'sector':'Setor' };\nfunction placeChip(k){\n  const parts = [PERFIL_LABEL[k.perfil], REDE_LABEL[k.rede], SECTION_LABEL[k.section]].filter(Boolean);\n  return parts.length ? `<span class=\"chip place\">${esc(parts.join(' · '))}</span>` : '';\n}\nfunction brandChip(brand){\n  const b = brand||'total';\n  return `<span class=\"chip brand br-${esc(b)}\">${esc(BRAND_LABEL[b]||b)}</span>`;\n}\nfunction iconGlyph(icon){ return lucide(icon||'target'); }\n\nfunction renderCard(d2, k, kpis){\n  const refs = refCount(kpis, k);\n  const src = k.source||'performance-api';\n  const armed = d2.state.confirmDel===k._id;\n  return `<div class=\"krow\" data-key=\"kpi-${esc(k._id)}\">\n    <div class=\"kicon\">${iconGlyph(k.icon)}</div>\n    <div class=\"kmain\">\n      <div class=\"ktop\">\n        <span class=\"kname\">${esc(k.name||'(sem nome)')}</span>\n        <span class=\"kcode\">#${esc(k.code||'—')}</span>\n      </div>\n      <div class=\"kbadges\">\n        ${brandChip(k.brand)}\n        ${placeChip(k)}\n        <span class=\"chip src\">${esc(SOURCE_LABEL[src]||src)}</span>\n        ${k.hasGoal?`<span class=\"chip goal\">Com meta</span>`:`<span class=\"chip nogoal\">Sem meta</span>`}\n        ${k.iap?`<span class=\"chip iap\">IAP</span>`:''}\n        ${refs>0?`<span class=\"chip reflink\" title=\"${refs} outro(s) uso(s) do código ${esc(k.code)}\">${refs}× uso</span>`:''}\n      </div>\n      ${k.hasGoal&&k.goalKey?`<div class=\"kmeta\">meta: <code>${esc(k.goalKey)}</code></div>`:''}\n      ${k.description?`<div class=\"kdesc\">${esc(String(k.description).slice(0,140))}${String(k.description).length>140?'…':''}</div>`:''}\n    </div>\n    <div class=\"kctl\">\n      <button class=\"kic edit\" data-edit=\"${esc(k._id)}\" title=\"Editar\">${ICON.edit}</button>\n      <button class=\"kic dup\" data-dup=\"${esc(k._id)}\" title=\"Duplicar\">${ICON.dup}</button>\n      ${armed\n        ? `<button class=\"kic del armed\" data-del=\"${esc(k._id)}\" title=\"Confirmar exclusão\">${ICON.ok}</button><button class=\"kic\" data-delcancel title=\"Cancelar\">${ICON.x}</button>`\n        : `<button class=\"kic del\" data-delask=\"${esc(k._id)}\" title=\"Excluir\">${ICON.del}</button>`}\n    </div>\n  </div>`;\n}\n\nfunction iconOptions(cur){\n  return ICONS.map(i=>`<option value=\"${i}\" ${cur===i?'selected':''}>${ICON_LABEL[i]||i}</option>`).join('');\n}\nfunction brandOptions(cur){\n  return ['natura','avon','total'].map(b=>`<option value=\"${b}\" ${((cur||'total')===b)?'selected':''}>${BRAND_LABEL[b]}</option>`).join('');\n}\n\nfunction fieldsMarkup(d2, m, isNew){\n  const src = m.source||'performance-api';\n  const isBricks = src==='databricks-query';\n  return `\n    <div class=\"frow\">\n      <div class=\"mfield grow\"><label>Nome do indicador</label><input type=\"text\" data-mfield=\"name\" value=\"${esc(m.name||'')}\" placeholder=\"Ex.: Ativas Natura\"/></div>\n      <div class=\"mfield\"><label>Marca</label><select data-mfield=\"brand\">${brandOptions(m.brand)}</select></div>\n    </div>\n    <div class=\"frow\">\n      <div class=\"mfield grow\"><label>Descrição</label><textarea data-mfield=\"description\" rows=\"2\" placeholder=\"O que este indicador mede e como é usado.\">${esc(m.description||'')}</textarea></div>\n    </div>\n    ${isNew?`\n    <div class=\"frow\">\n      <div class=\"mfield grow\"><label>Origem do dado</label>\n        <select data-mfield=\"source\">\n          <option value=\"performance-api\" ${!isBricks?'selected':''}>Performance API</option>\n          <option value=\"databricks-query\" disabled>Databricks query — em breve</option>\n        </select>\n        <div class=\"hint\">Mapeie um indicador da Performance API pelo código de índice. A origem por consulta Databricks chega em breve.</div>\n      </div>\n    </div>\n    <div class=\"frow\">\n      <div class=\"mfield\"><label>Código do índice (Performance API)</label><input type=\"text\" data-mfield=\"apiIndexCode\" value=\"${esc(m.apiIndexCode||'')}\" placeholder=\"Ex.: 545\" ${isBricks?'disabled':''}/></div>\n      <div class=\"mfield\"><label>Ícone</label><select data-mfield=\"icon\">${iconOptions(m.icon||'target')}</select></div>\n    </div>`:`\n    <div class=\"frow\">\n      <div class=\"mfield\"><label>Ícone</label><select data-mfield=\"icon\">${iconOptions(m.icon||'target')}</select></div>\n      <div class=\"mfield\"><label>Origem</label><input type=\"text\" value=\"${esc(SOURCE_LABEL[src]||src)}\" disabled/></div>\n    </div>`}\n    <div class=\"frow toggles\">\n      <div class=\"mfield tog\">\n        <label>Possui meta</label>\n        <button type=\"button\" class=\"tog ${m.hasGoal?'on':''}\" data-mtog=\"hasGoal\"><span class=\"knob\"></span></button>\n      </div>\n      <div class=\"mfield tog\">\n        <label>Indicador de acompanhamento (IAP)</label>\n        <button type=\"button\" class=\"tog ${m.iap?'on':''}\" data-mtog=\"iap\"><span class=\"knob\"></span></button>\n      </div>\n    </div>\n    ${m.hasGoal?`<div class=\"frow\">\n      <div class=\"mfield grow\"><label>Chave da meta (goalKey)</label><input type=\"text\" data-mfield=\"goalKey\" value=\"${esc(m.goalKey||'')}\" placeholder=\"Ex.: goalActivesNaturaExclusive\"/>\n      <div class=\"hint\">Chave usada na resposta de metas da API. Deixe em branco para indicador sem alvo.</div></div>\n    </div>`:''}`;\n}\n\nfunction renderEditModal(d2, kpis){\n  if(!d2.state.editOpen) return '';\n  const m = d2.state.edit || {};\n  const refs = refCount(kpis, m);\n  return `<div class=\"modal-bg in\" data-mbg>\n    <div class=\"modal\">\n      <h2>Editar indicador</h2>\n      <p class=\"msub\">Código <code>#${esc(m.code||'—')}</code> · propriedades intrínsecas do KPI. A exibição no dashboard (agrupamento, seção, ordem) fica no editor de Indicadores.</p>\n      ${refs>0?`<div class=\"warnbox\">⚠️ Este código é usado por ${refs} outro registro. Alterações no significado do indicador podem afetar itens do dashboard, tabelas de faixas e bônus que apontam para <code>#${esc(m.code)}</code>.</div>`:''}\n      ${fieldsMarkup(d2, m, false)}\n      <div class=\"mfoot\">\n        <button class=\"btn ghost\" data-mclose>Cancelar</button>\n        <button class=\"btn prim\" data-msave>Salvar alterações</button>\n      </div>\n    </div>\n  </div>`;\n}\n\nfunction renderNewModal(d2){\n  if(!d2.state.newOpen) return '';\n  const m = d2.state.newKpi || {};\n  return `<div class=\"modal-bg in\" data-nbg>\n    <div class=\"modal\">\n      <h2>Novo indicador</h2>\n      <p class=\"msub\">Mapeie uma métrica de negócio a partir do código de índice da Performance API. O código do índice vira o código (chave) do KPI — pronto para ser escolhido nos itens do dashboard, tabelas de faixas e bônus.</p>\n      ${fieldsMarkup(d2, m, true)}\n      <div class=\"mfoot\">\n        <button class=\"btn ghost\" data-nclose>Cancelar</button>\n        <button class=\"btn prim\" data-nsave>Criar indicador</button>\n      </div>\n    </div>\n  </div>`;\n}\n\nexport default {\n  css: `\n  :host{display:block}\n  .screen{min-height:100%;height:auto;display:flex;flex-direction:column;background:var(--ground);font-family:var(--fam);box-sizing:border-box}\n  .header{padding:26px 30px 20px;background:var(--surface);border-bottom:1px solid var(--hair)}\n  .htop{display:flex;align-items:flex-start;gap:16px}\n  .htitle h1{margin:0;font:800 28px/1.1 var(--fam);color:var(--ink);letter-spacing:-.5px}\n  .htitle .badge{display:inline-block;margin-left:10px;font:700 10px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;color:var(--mag);background:rgba(229,0,75,.10);padding:5px 9px;border-radius:999px;vertical-align:middle}\n  .htitle p{margin:6px 0 0;font:400 13px/1.4 var(--fam);color:var(--muted);max-width:720px}\n  .newbtn{margin-left:auto;display:inline-flex;align-items:center;gap:7px;padding:11px 18px;border:none;border-radius:11px;background:var(--grad);color:#fff;font:700 13px/1 var(--fam);cursor:pointer;box-shadow:0 4px 12px rgba(229,0,75,.28);transition:filter .15s,transform .1s;white-space:nowrap}\n  .newbtn:hover{filter:brightness(1.06)} .newbtn:active{transform:scale(.97)}\n  .toolbar{display:flex;align-items:center;gap:12px;margin-top:16px;flex-wrap:wrap}\n  .search{flex:1 1 260px;min-width:0;display:flex;align-items:center;gap:8px;background:var(--ground);border:1.5px solid var(--hair);border-radius:11px;padding:9px 13px}\n  .search input{flex:1;min-width:0;border:none;background:none;outline:none;font:500 14px/1 var(--fam);color:var(--ink)}\n  .search .si{color:var(--muted)}\n  .count{font:600 12px/1 var(--fam);color:var(--muted);white-space:nowrap}\n  .body{flex:1 1 auto;padding:22px 30px 72px;display:flex;flex-direction:column;gap:14px}\n  .krow{background:var(--surface);border:1px solid var(--hair);border-radius:16px;padding:16px 18px;box-shadow:var(--shadowcard);display:flex;align-items:flex-start;gap:16px}\n  .kicon{width:44px;height:44px;flex:0 0 auto;border-radius:12px;background:rgba(229,0,75,.08);display:flex;align-items:center;justify-content:center;color:var(--mag)}\n  .kicon .lu{width:22px;height:22px;display:block}\n  .kmain{flex:1 1 auto;min-width:0}\n  .ktop{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}\n  .kname{font:800 17px/1.2 var(--fam);color:var(--ink);letter-spacing:-.2px}\n  .kcode{font:700 12px/1 var(--fam);color:var(--muted)}\n  .kbadges{display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin-top:8px}\n  .chip{font:700 10px/1 var(--fam);letter-spacing:.03em;padding:5px 9px;border-radius:999px;white-space:nowrap}\n  .chip.brand{text-transform:uppercase}\n  .chip.br-natura{background:rgba(229,0,75,.12);color:var(--mag)}\n  .chip.br-avon{background:rgba(229,1,75,.10);color:#b8003c}\n  .chip.br-total{background:rgba(107,114,128,.14);color:var(--muted)}\n  .chip.src{background:rgba(72,152,255,.16);color:#1462c7}\n  .chip.place{background:rgba(26,28,30,.06);color:var(--ink)}\n  .chip.goal{background:rgba(41,172,86,.14);color:var(--money)}\n  .chip.nogoal{background:rgba(107,114,128,.12);color:var(--muted)}\n  .chip.iap{background:rgba(247,190,0,.20);color:#8a6d00}\n  .chip.reflink{background:rgba(72,152,255,.10);color:#1462c7;text-transform:none}\n  .kmeta{margin-top:8px;font:500 11.5px/1.3 var(--fam);color:var(--muted)}\n  .kmeta code,.msub code,.warnbox code{font:700 11px/1 'SF Mono',ui-monospace,Menlo,monospace;background:var(--ground);padding:2px 5px;border-radius:5px;color:var(--ink)}\n  .kdesc{margin-top:8px;font:400 12.5px/1.45 var(--fam);color:var(--muted)}\n  .kctl{margin-left:auto;display:flex;align-items:center;gap:6px;flex-wrap:wrap;justify-content:flex-end}\n  .btn{padding:9px 15px;border-radius:10px;font:700 12.5px/1 var(--fam);cursor:pointer;border:none;transition:filter .15s,transform .1s,background .15s;white-space:nowrap}\n  .btn.prim{background:var(--grad);color:#fff;box-shadow:0 4px 12px rgba(229,0,75,.28)} .btn.prim:hover{filter:brightness(1.06)} .btn.prim:active{transform:scale(.97)}\n  .btn.ghost{background:var(--ground);color:var(--muted);border:1px solid var(--hair)} .btn.ghost:hover{background:var(--hair);color:var(--ink)}\n  .btn.ghosticon{background:var(--ground);color:var(--muted);border:1px solid var(--hair);padding:9px 11px;font-size:14px} .btn.ghosticon.del:hover{background:rgba(214,20,25,.12);color:#d61419;border-color:rgba(214,20,25,.3)}\n  .kic{width:32px;height:32px;flex:0 0 auto;border:none;border-radius:9px;background:var(--ground);color:var(--muted);cursor:pointer;font-size:14px;display:inline-flex;align-items:center;justify-content:center;transition:background .15s,color .15s,transform .1s}\n  .kic:hover{background:rgba(229,0,75,.10);color:var(--mag)}\n  .kic:active{transform:scale(.92)}\n  .kic.del:hover{background:rgba(214,20,25,.12);color:#d61419}\n  .kic.del.armed{background:#d61419;color:#fff}\n  .ic-svg{display:block;flex:0 0 auto}\n  .kic .ic-svg{width:17px;height:17px}\n  .newbtn .ic-svg{width:15px;height:15px}\n  .search .si{display:inline-flex}\n  .search .si .ic-svg{width:16px;height:16px}\n  .btn.danger{background:#d61419;color:#fff} .btn.danger:hover{filter:brightness(1.06)}\n  .empty{padding:60px;text-align:center;color:var(--muted);font:500 14px/1.5 var(--fam)}\n  .toast{position:fixed;left:50%;bottom:26px;transform:translate(-50%,20px);background:var(--ink);color:#fff;padding:12px 20px;border-radius:12px;font:600 13px/1 var(--fam);box-shadow:0 10px 30px rgba(0,0,0,.3);z-index:9500;opacity:0;transition:opacity .2s,transform .2s;pointer-events:none}\n  .toast.in{opacity:1;transform:translate(-50%,0)}\n  .saving{display:inline-flex;align-items:center;gap:6px;color:var(--mag);font:700 12px/1 var(--fam);margin-top:10px}\n  .spin{width:12px;height:12px;border:2px solid rgba(229,0,75,.25);border-top-color:var(--mag);border-radius:50%;animation:sp .7s linear infinite}\n  @keyframes sp{to{transform:rotate(360deg)}}\n  .modal-bg{position:fixed;inset:0;background:rgba(16,24,40,.42);z-index:9000;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s;padding:24px}\n  .modal-bg.in{opacity:1}\n  .modal{background:var(--surface);border-radius:20px;box-shadow:var(--shadowraised);width:min(520px,100%);max-width:100%;max-height:88vh;overflow:auto;box-sizing:border-box;padding:24px 26px;transform:translateY(14px) scale(.98);transition:transform .24s cubic-bezier(.34,1.4,.64,1)}\n  .modal-bg.in .modal{transform:none}\n  .modal h2{margin:0 0 4px;font:800 20px/1.1 var(--fam);color:var(--ink)}\n  .modal .msub{margin:0 0 16px;font:500 12px/1.5 var(--fam);color:var(--muted)}\n  .warnbox{background:rgba(247,190,0,.12);border:1px solid rgba(247,190,0,.4);border-radius:12px;padding:11px 13px;margin-bottom:16px;font:500 12px/1.5 var(--fam);color:#8a6d00}\n  .frow{display:flex;gap:12px;margin-bottom:14px;flex-wrap:wrap}\n  .frow.toggles{gap:12px}\n  .mfield{flex:1 1 160px;min-width:0;display:flex;flex-direction:column;gap:6px}\n  .mfield.grow{flex:1 1 100%}\n  .mfield label{font:600 11px/1 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.05em}\n  .mfield input,.mfield select,.mfield textarea{width:100%;max-width:100%;min-width:0;box-sizing:border-box;padding:10px 12px;border:1.5px solid var(--hair);border-radius:10px;font:600 14px/1.3 var(--fam);color:var(--ink);outline:none;background:var(--surface);font-family:var(--fam)}\n  .mfield textarea{resize:vertical}\n  .mfield input:focus,.mfield select:focus,.mfield textarea:focus{border-color:var(--mag)}\n  .mfield input:disabled,.mfield select:disabled{background:var(--ground);color:var(--muted);cursor:not-allowed}\n  .mfield .hint{font:500 11px/1.4 var(--fam);color:var(--muted);text-transform:none;letter-spacing:0}\n  .mfield.tog{flex:1 1 160px;flex-direction:row;align-items:center;justify-content:space-between;gap:10px;background:var(--ground);border:1px solid var(--hair);border-radius:11px;padding:10px 12px}\n  .mfield.tog label{text-transform:none;letter-spacing:0;font:600 12.5px/1.3 var(--fam);color:var(--ink)}\n  .tog{width:44px;height:26px;flex:0 0 auto;border-radius:999px;border:none;background:var(--hair);position:relative;cursor:pointer;transition:background .18s}\n  .tog.on{background:var(--money)}\n  .tog .knob{position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.25);transition:transform .18s}\n  .tog.on .knob{transform:translateX(18px)}\n  .mfoot{display:flex;gap:10px;justify-content:flex-end;margin-top:20px}\n  @media (prefers-reduced-motion: reduce){ .krow,.tog,.tog .knob,.btn,.kic,.newbtn,.toast,.modal-bg,.modal,.card{transition:none!important} .spin{animation:none} }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const ds = d2.data('kpis');\n    const kpis = (ds ? ds.records() : []).map(norm);\n    const loading = ds && ds.loading;\n    const vars = cssVars(t);\n    const q = String(d2.state.q||'').trim().toLowerCase();\n    const filtered = !q ? kpis : kpis.filter(k=>{\n      const hay = `${k.name||''} ${k.code||''} ${k.brand||''} ${SOURCE_LABEL[k.source||'performance-api']||''} ${k.goalKey||''}`.toLowerCase();\n      return hay.indexOf(q)>=0;\n    });\n    const sorted = filtered.slice().sort((a,b)=>String(a.name||'').localeCompare(String(b.name||''),'pt-BR'));\n    const rows = sorted.map(k=>renderCard(d2,k,kpis)).join('');\n    return `<div class=\"screen\" style=\"${vars}\">\n      <div class=\"header\">\n        <div class=\"htop\">\n          <div class=\"htitle\">\n            <h1>Indicadores (KPIs) <span class=\"badge\">Code · Definições de KPI</span></h1>\n            <p>Gerencie as definições dos indicadores que o painel inteiro referencia. Cada KPI mapeia uma métrica da Performance API por um código de índice. Aqui você edita o significado do indicador (nome, meta, marca, IAP) e cria novos — a exibição no dashboard é configurada no editor de Indicadores.</p>\n          </div>\n          <button class=\"newbtn\" data-new>${ICON.plus} Novo indicador</button>\n        </div>\n        <div class=\"toolbar\">\n          <div class=\"search\"><span class=\"si\">${ICON.search}</span><input type=\"text\" data-q placeholder=\"Buscar por nome, código, marca ou origem…\" value=\"${esc(d2.state.q||'')}\"/></div>\n          <span class=\"count\">${sorted.length} de ${kpis.length} indicadores</span>\n        </div>\n        ${d2.state.saving?`<div class=\"saving\"><span class=\"spin\"></span>Salvando…</div>`:''}\n      </div>\n      <div class=\"body\">\n        ${loading?`<div class=\"empty\">Carregando indicadores…</div>`:(rows||`<div class=\"empty\">Nenhum indicador encontrado${q?` para “${esc(d2.state.q)}”`:''}.</div>`)}\n      </div>\n      ${renderEditModal(d2,kpis)}\n      ${renderNewModal(d2)}\n      <div class=\"toast ${d2.state.toast?'in':''}\">${esc(d2.state.toast||'')}</div>\n    </div>`;\n  },\n  mounted(d2){\n    d2.on('[data-q]','input',(e,el)=>{ d2.state.q = el.value; d2.refresh(); });\n\n    d2.on('[data-edit]','click',(e,el)=>openEdit(d2, el.dataset.edit));\n    d2.on('[data-dup]','click',(e,el)=>duplicateKpi(d2, el.dataset.dup));\n    d2.on('[data-delask]','click',(e,el)=>d2.setState({ confirmDel: el.dataset.delask }));\n    d2.on('[data-delcancel]','click',()=>d2.setState({ confirmDel:null }));\n    d2.on('[data-del]','click',(e,el)=>deleteKpi(d2, el.dataset.del));\n\n    const activeKey=()=> d2.state.newOpen ? 'newKpi' : 'edit';\n    d2.on('[data-mfield]','input',(e,el)=>{ const key=activeKey(); const m={...(d2.state[key]||{})}; m[el.dataset.mfield]=el.value; d2.state[key]=m; });\n    d2.on('[data-mfield]','change',(e,el)=>{ const key=activeKey(); const m={...(d2.state[key]||{})}; m[el.dataset.mfield]=el.value; d2.state[key]=m; d2.refresh(); });\n    d2.on('[data-mtog]','click',(e,el)=>{ const key=activeKey(); const k=el.dataset.mtog; const m={...(d2.state[key]||{})}; m[k]=!m[k]; d2.state[key]=m; d2.refresh(); });\n    d2.on('[data-mclose]','click',()=>d2.setState({ editOpen:false }));\n    d2.on('[data-mbg]','click',(e,el)=>{ if(e.target===el) d2.setState({ editOpen:false }); });\n    d2.on('[data-msave]','click',()=>saveEdit(d2));\n\n    d2.on('[data-new]','click',()=>d2.setState({ newOpen:true, newKpi:{ name:'', brand:'natura', source:'performance-api', apiIndexCode:'', icon:'target', hasGoal:false, goalKey:'', iap:false, description:'' } }));\n    d2.on('[data-nclose]','click',()=>d2.setState({ newOpen:false }));\n    d2.on('[data-nbg]','click',(e,el)=>{ if(e.target===el) d2.setState({ newOpen:false }); });\n    d2.on('[data-nsave]','click',()=>saveNew(d2));\n  }\n};\n\nfunction findById(d2, id){\n  const ds=d2.data('kpis'); const recs = (ds?ds.records():[]).map(norm);\n  return recs.find(k=>String(k._id)===String(id));\n}\n\nfunction openEdit(d2, id){\n  const k = findById(d2, id);\n  if(!k) return;\n  d2.setState({ editOpen:true, confirmDel:null, edit:{ ...k } });\n}\n\nasync function saveEdit(d2){\n  const m = d2.state.edit || {};\n  if(!m.name || !String(m.name).trim()){ toast(d2,'Informe o nome do indicador'); return; }\n  const before = { name:m.name, hasGoal:m.hasGoal, description:m.description, iap:m.iap };\n  const row = { ...m,\n    name: String(m.name).trim(),\n    description: String(m.description||'').trim(),\n    hasGoal: !!m.hasGoal,\n    iap: !!m.iap,\n    goalKey: m.hasGoal ? String(m.goalKey||'').trim() : '',\n    brand: m.brand||'total',\n    icon: m.icon||'target'\n  };\n  d2.setState({ saving:true, editOpen:false });\n  try{\n    await invoke(d2,{ entity:'kpi', op:'upsert', row, before });\n    toast(d2, `Indicador “${row.name}” salvo`);\n  }catch(e){ toast(d2,'Erro ao salvar indicador'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\n}\n\nasync function duplicateKpi(d2, id){\n  const k = findById(d2, id);\n  if(!k) return;\n  const copy = { ...k };\n  delete copy._id;\n  copy.name = `${k.name||'Indicador'} (cópia)`;\n  d2.setState({ saving:true });\n  try{\n    await invoke(d2,{ entity:'kpi', op:'upsert', row:copy, before:{} });\n    toast(d2, `Indicador duplicado — ajuste o código de índice`);\n  }catch(e){ toast(d2,'Erro ao duplicar'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\n}\n\nasync function deleteKpi(d2, id){\n  const k = findById(d2, id);\n  if(!k) return;\n  d2.setState({ saving:true, confirmDel:null });\n  try{\n    await invoke(d2,{ entity:'kpi', op:'delete', row:{ _id:k._id }, before:{ code:k.code, name:k.name } });\n    toast(d2, `Indicador “${k.name||k.code}” excluído`);\n  }catch(e){ toast(d2,'Erro ao excluir'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\n}\n\nasync function saveNew(d2){\n  const m = d2.state.newKpi || {};\n  if(m.source==='databricks-query'){ toast(d2,'Origem Databricks ainda não disponível'); return; }\n  if(!m.name || !String(m.name).trim()){ toast(d2,'Informe o nome do indicador'); return; }\n  const code = String(m.apiIndexCode||'').trim();\n  if(!code){ toast(d2,'Informe o código do índice da Performance API'); return; }\n  const row = {\n    code,\n    apiIndexCode: code,\n    valueKey: code,\n    name: String(m.name).trim(),\n    label: String(m.name).trim(),\n    description: String(m.description||'').trim(),\n    brand: m.brand||'total',\n    source: 'performance-api',\n    icon: m.icon||'target',\n    hasGoal: !!m.hasGoal,\n    goalKey: m.hasGoal ? String(m.goalKey||'').trim() : '',\n    iap: !!m.iap,\n    visible: true\n  };\n  d2.setState({ saving:true, newOpen:false });\n  try{\n    await invoke(d2,{ entity:'kpi', op:'upsert', row, before:{} });\n    toast(d2, `Indicador “${row.name}” criado — código #${code}`);\n  }catch(e){ toast(d2,'Erro ao criar indicador'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\n}"}},"kpis":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"kpis"}}}},"writer":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"writer"}}}}}}}}}},{"_id":"6a4c585de4871a9f8062de5a","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotAuditAdmScreen","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',money:'#29AC56',rampGreen:'#29AC56',rampRed:'#FF1418',rampAmber:'#FAA000',gold:'#F7BE00'},\n  radius:{sm:8,md:12,lg:16,pill:999},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\"},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'},\n  motion:{hover:'150ms ease-out',mount:'400ms cubic-bezier(0.4,0,0.2,1)',fade:'200ms ease-out'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nconst ENTITY_LABEL = {\n  'dashboard-item':'Item do painel', 'band':'Faixa', 'bonus':'Bônus', 'formula':'Fórmula',\n  'ruleset':'Ruleset', 'cycle':'Ciclo', 'band-table':'Tabela de faixas', 'kpi':'KPI'\n};\nconst ENTITY_GLYPH = {\n  'dashboard-item':'📊', 'band':'📶', 'bonus':'🎁', 'formula':'🧮',\n  'ruleset':'🗂️', 'cycle':'🗓️', 'band-table':'📋', 'kpi':'🎯'\n};\nconst ICON = (()=>{\n  const S = (p)=>`<svg class=\"ic-svg\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${p}</svg>`;\n  return {\n    down:S('<path d=\"m6 9 6 6 6-6\"/>'),\n    right:S('<path d=\"m9 18 6-6-6-6\"/>'),\n    search:S('<circle cx=\"11\" cy=\"11\" r=\"7\"/><path d=\"m21 21-4.3-4.3\"/>')\n  };\n})();\nconst ACTION_META = {\n  create:   { label:'Criou',     cls:'create'    },\n  update:   { label:'Editou',    cls:'update'    },\n  delete:   { label:'Excluiu',   cls:'delete'    },\n  reorder:  { label:'Reordenou', cls:'reorder'   },\n  duplicate:{ label:'Duplicou',  cls:'duplicate' }\n};\n\nfunction effectiveAction(rec){\n  const a = String(rec.action||'').toLowerCase();\n  if(a==='upsert'){\n    const before = (rec.changes && rec.changes.before) || {};\n    const hasBefore = before && typeof before==='object' && Object.keys(before).length>0;\n    return hasBefore ? 'update' : 'create';\n  }\n  if(ACTION_META[a]) return a;\n  return a || 'update';\n}\n\nfunction actorInitials(email){\n  const s = String(email||'').split('@')[0] || '?';\n  const parts = s.split(/[.\\-_]/).filter(Boolean);\n  const a = (parts[0]||s)[0]||'?';\n  const b = parts[1]?parts[1][0]:'';\n  return (a+b).toUpperCase();\n}\n\nfunction relTime(d2, iso){\n  const t = new Date(iso).getTime();\n  if(!isFinite(t)) return '';\n  const diff = Date.now()-t;\n  const s = Math.round(diff/1000);\n  if(s<60) return 'agora mesmo';\n  const m = Math.round(s/60);\n  if(m<60) return `há ${m} min`;\n  const h = Math.round(m/60);\n  if(h<24) return `há ${h} h`;\n  const dd = Math.round(h/24);\n  if(dd<30) return `há ${dd} d`;\n  try{ return new Date(iso).toLocaleDateString('pt-BR',{day:'2-digit',month:'short'}); }catch(e){ return ''; }\n}\nfunction absTime(iso){\n  try{ return new Date(iso).toLocaleString('pt-BR',{day:'2-digit',month:'2-digit',year:'numeric',hour:'2-digit',minute:'2-digit'}); }\n  catch(e){ return String(iso||''); }\n}\n\nfunction friendlyLabel(rec){\n  const c = rec.changes||{};\n  const row = c.row || {};\n  const before = c.before || {};\n  const cand = row.label || row.name || before.label || before.name\n    || row.code || before.code || (row.ref) || (before.ref);\n  return cand ? String(cand) : '';\n}\n\nfunction fmtVal(v){\n  if(v===null||v===undefined) return '∅';\n  if(typeof v==='boolean') return v?'sim':'não';\n  if(typeof v==='number'){ try{ return v.toLocaleString('pt-BR'); }catch(e){ return String(v); } }\n  if(typeof v==='object'){\n    try{ const j=JSON.stringify(v); return j.length>60?j.slice(0,60)+'…':j; }catch(e){ return '{…}'; }\n  }\n  const s = String(v);\n  return s.length>60 ? s.slice(0,60)+'…' : s;\n}\n\nfunction buildDiff(rec){\n  const c = rec.changes||{};\n  const before = (c.before && typeof c.before==='object') ? c.before : {};\n  const row = (c.row && typeof c.row==='object') ? c.row : {};\n  const out = [];\n  const keys = Object.keys(before);\n  for(const k of keys){\n    if(k==='_id') continue;\n    const b = before[k];\n    const a = Object.prototype.hasOwnProperty.call(row,k) ? row[k] : undefined;\n    out.push({ key:k, before:b, after:a, hasAfter: Object.prototype.hasOwnProperty.call(row,k) });\n  }\n  return out;\n}\n\nfunction keyFields(rec){\n  const c = rec.changes||{};\n  const src = (c.op==='delete') ? (c.before||c.row||{}) : (c.row||{});\n  const PICK = ['label','name','code','ref','value','amount','perfil','rede','brand','status','version','minPct','maxPct'];\n  const out = [];\n  for(const k of PICK){\n    if(src && Object.prototype.hasOwnProperty.call(src,k) && src[k]!=='' && src[k]!=null){\n      out.push({ key:k, val:src[k] });\n      if(out.length>=5) break;\n    }\n  }\n  return out;\n}\n\nfunction summaryMarkup(rec){\n  const act = effectiveAction(rec);\n  const c = rec.changes||{};\n  if(act==='duplicate'){\n    const dc = c.dupCounts||{};\n    const parts = [];\n    if(dc.bands) parts.push(`${dc.bands} faixas`);\n    if(dc.formulas) parts.push(`${dc.formulas} fórmulas`);\n    if(dc.bonuses) parts.push(`${dc.bonuses} bônus`);\n    const row = c.row||{};\n    const lbl = row.label ? `→ ${esc(row.label)}` : '';\n    return `<div class=\"sumline\"><span class=\"dtag copy\">cópia</span> ${lbl} ${parts.length?`<span class=\"dcount\">${esc(parts.join(' · '))} copiados</span>`:''}</div>`;\n  }\n  if(act==='update'){\n    const diff = buildDiff(rec).filter(d=>d.hasAfter && JSON.stringify(d.before)!==JSON.stringify(d.after));\n    const annotations = buildDiff(rec).filter(d=>!d.hasAfter);\n    if(diff.length===0 && annotations.length>0){\n      return annotations.map(d=>`<div class=\"sumline\"><code>${esc(d.key)}</code>: <span class=\"note\">${esc(fmtVal(d.before))}</span></div>`).join('');\n    }\n    if(diff.length===0){\n      return `<div class=\"sumline note\">Sem alterações de campo detectadas.</div>`;\n    }\n    return diff.slice(0,6).map(d=>\n      `<div class=\"sumline\"><code>${esc(d.key)}</code>: <span class=\"was\">${esc(fmtVal(d.before))}</span> <span class=\"arr\">→</span> <span class=\"now\">${esc(fmtVal(d.after))}</span></div>`\n    ).join('') + (diff.length>6?`<div class=\"sumline more\">+${diff.length-6} outro(s) campo(s)</div>`:'');\n  }\n  const kf = keyFields(rec);\n  if(kf.length===0) return `<div class=\"sumline note\">${act==='delete'?'Registro removido.':'Registro criado.'}</div>`;\n  return `<div class=\"sumline kf\">${kf.map(f=>`<span class=\"kfpair\"><code>${esc(f.key)}</code> ${esc(fmtVal(f.val))}</span>`).join('')}</div>`;\n}\n\nfunction rowMarkup(d2, rec){\n  const act = effectiveAction(rec);\n  const meta = ACTION_META[act] || {label:act,cls:'update'};\n  const et = String(rec.entityType||'');\n  const etLabel = ENTITY_LABEL[et]||et||'—';\n  const etGlyph = ENTITY_GLYPH[et]||'•';\n  const lbl = friendlyLabel(rec);\n  const id = String(rec._id||'');\n  const expanded = d2.state.expanded===id;\n  let fullJson = '';\n  try{ fullJson = JSON.stringify(rec.changes||{}, null, 2); }catch(e){ fullJson='{}'; }\n  return `<div class=\"row\" data-key=\"au-${esc(id)}\">\n    <div class=\"railcol\">\n      <span class=\"dot ${meta.cls}\"></span>\n      <span class=\"rail\"></span>\n    </div>\n    <div class=\"card\">\n      <div class=\"rtop\">\n        <span class=\"avatar\" title=\"${esc(rec.actorEmail||'')}\">${esc(actorInitials(rec.actorEmail))}</span>\n        <span class=\"actor\">${esc(rec.actorEmail||'—')}</span>\n        <span class=\"achip ${meta.cls}\">${esc(meta.label)}</span>\n        <span class=\"etchip\"><span class=\"etg\">${etGlyph}</span>${esc(etLabel)}</span>\n        <span class=\"spacer\"></span>\n        <span class=\"time\" title=\"${esc(absTime(rec.at))}\">${esc(relTime(d2, rec.at))}</span>\n      </div>\n      <div class=\"rmid\">\n        ${lbl?`<span class=\"ename\">${esc(lbl)}</span>`:''}\n        <span class=\"eid\" title=\"entityId\">#${esc(rec.entityId||'—')}</span>\n      </div>\n      <div class=\"summary\">${summaryMarkup(rec)}</div>\n      <div class=\"rfoot\">\n        <button class=\"expand\" data-expand=\"${esc(id)}\">${expanded?ICON.down+' Ocultar JSON':ICON.right+' Ver alteração completa (JSON)'}</button>\n        <span class=\"abs\">${esc(absTime(rec.at))}</span>\n      </div>\n      ${expanded?`<pre class=\"json\">${esc(fullJson)}</pre>`:''}\n    </div>\n  </div>`;\n}\n\nconst ACTION_FILTERS = [\n  { key:'', label:'Todas' },\n  { key:'create', label:'Criou' },\n  { key:'update', label:'Editou' },\n  { key:'delete', label:'Excluiu' },\n  { key:'duplicate', label:'Duplicou' },\n  { key:'reorder', label:'Reordenou' }\n];\nconst DATE_PRESETS = [\n  { key:'today', label:'Hoje' },\n  { key:'7d', label:'7 dias' },\n  { key:'all', label:'Tudo' }\n];\n\nfunction withinDate(iso, preset){\n  if(preset==='all'||!preset) return true;\n  const t = new Date(iso).getTime();\n  if(!isFinite(t)) return false;\n  const now = Date.now();\n  if(preset==='today'){\n    const d = new Date(); d.setHours(0,0,0,0);\n    return t>=d.getTime();\n  }\n  if(preset==='7d') return t >= now - 7*24*3600*1000;\n  return true;\n}\n\nexport default {\n  css: `\n  :host{display:block}\n  .screen{min-height:100%;height:auto;display:flex;flex-direction:column;background:var(--ground);font-family:var(--fam);box-sizing:border-box}\n  .header{padding:26px 30px 18px;background:var(--surface);border-bottom:1px solid var(--hair)}\n  .htop{display:flex;align-items:flex-start;gap:16px}\n  .htitle h1{margin:0;font:800 28px/1.1 var(--fam);color:var(--ink);letter-spacing:-.5px}\n  .htitle .badge{display:inline-block;margin-left:10px;font:700 10px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;color:var(--mag);background:rgba(229,0,75,.10);padding:5px 9px;border-radius:999px;vertical-align:middle}\n  .htitle p{margin:6px 0 0;font:400 13px/1.4 var(--fam);color:var(--muted);max-width:720px}\n  .toolbar{display:flex;align-items:center;gap:12px;margin-top:16px;flex-wrap:wrap}\n  .search{flex:1 1 240px;min-width:0;display:flex;align-items:center;gap:8px;background:var(--ground);border:1.5px solid var(--hair);border-radius:11px;padding:9px 13px}\n  .search input{flex:1;min-width:0;border:none;background:none;outline:none;font:500 14px/1 var(--fam);color:var(--ink)}\n  .search .si{color:var(--muted)}\n  .count{font:600 12px/1 var(--fam);color:var(--muted);white-space:nowrap}\n  .filters{display:flex;align-items:center;gap:10px;margin-top:12px;flex-wrap:wrap}\n  .fgroup{display:flex;align-items:center;gap:6px;flex-wrap:wrap}\n  .flabel{font:700 10px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin-right:2px}\n  .fchip{padding:7px 12px;border-radius:999px;border:1px solid var(--hair);background:var(--surface);color:var(--muted);font:700 12px/1 var(--fam);cursor:pointer;transition:background .15s,color .15s,border-color .15s;white-space:nowrap}\n  .fchip:hover{background:var(--ground);color:var(--ink)}\n  .fchip[data-on]{background:var(--mag);color:#fff;border-color:var(--mag)}\n  .fsel{padding:7px 12px;border-radius:999px;border:1px solid var(--hair);background:var(--surface);color:var(--ink);font:600 12px/1 var(--fam);cursor:pointer;outline:none;font-family:var(--fam)}\n  .fsel:focus{border-color:var(--mag)}\n  .body{flex:1 1 auto;padding:22px 30px 90px}\n  .tl{position:relative;max-width:920px;margin:0 auto;display:flex;flex-direction:column;gap:2px}\n  .row{display:flex;gap:14px;align-items:stretch}\n  .railcol{position:relative;flex:0 0 auto;width:20px;display:flex;flex-direction:column;align-items:center}\n  .dot{width:14px;height:14px;border-radius:50%;margin-top:20px;flex:0 0 auto;box-shadow:0 0 0 3px var(--ground);z-index:1}\n  .dot.create{background:var(--green)} .dot.update{background:#3b82f6} .dot.delete{background:var(--red)}\n  .dot.duplicate{background:#8b5cf6} .dot.reorder{background:var(--muted)}\n  .rail{flex:1 1 auto;width:2px;background:var(--hair)}\n  .row:last-child .rail{display:none}\n  .card{flex:1 1 auto;min-width:0;background:var(--surface);border:1px solid var(--hair);border-radius:14px;padding:14px 16px;box-shadow:var(--shadowcard);margin-bottom:12px;animation:rise var(--mount)}\n  .rtop{display:flex;align-items:center;gap:9px;flex-wrap:wrap}\n  .avatar{width:26px;height:26px;flex:0 0 auto;border-radius:50%;background:var(--grad);color:#fff;font:800 10px/1 var(--fam);display:inline-flex;align-items:center;justify-content:center;letter-spacing:.02em}\n  .actor{font:700 13px/1.2 var(--fam);color:var(--ink)}\n  .achip{font:800 10px/1 var(--fam);letter-spacing:.03em;text-transform:uppercase;padding:5px 9px;border-radius:999px;white-space:nowrap}\n  .achip.create{background:rgba(41,172,86,.15);color:#1a7d3c}\n  .achip.update{background:rgba(59,130,246,.15);color:#1d5fd1}\n  .achip.delete{background:rgba(255,20,24,.13);color:#c00d11}\n  .achip.duplicate{background:rgba(139,92,246,.15);color:#6d34d6}\n  .achip.reorder{background:rgba(107,114,128,.15);color:var(--muted)}\n  .etchip{display:inline-flex;align-items:center;gap:5px;font:700 11px/1 var(--fam);padding:5px 9px;border-radius:999px;background:var(--ground);border:1px solid var(--hair);color:var(--ink);white-space:nowrap}\n  .etchip .etg{font-size:12px}\n  .spacer{margin-left:auto}\n  .time{font:600 11px/1 var(--fam);color:var(--muted);white-space:nowrap}\n  .rmid{display:flex;align-items:baseline;gap:9px;margin-top:9px;flex-wrap:wrap}\n  .ename{font:800 14px/1.2 var(--fam);color:var(--ink);letter-spacing:-.2px}\n  .eid{font:700 11px/1 'SF Mono',ui-monospace,Menlo,monospace;color:var(--muted)}\n  .summary{margin-top:9px;display:flex;flex-direction:column;gap:4px}\n  .sumline{font:500 12.5px/1.5 var(--fam);color:var(--ink)}\n  .sumline code{font:700 11px/1 'SF Mono',ui-monospace,Menlo,monospace;background:var(--ground);padding:2px 6px;border-radius:5px;color:var(--ink)}\n  .sumline .was{color:var(--muted);text-decoration:line-through;text-decoration-color:rgba(107,114,128,.5)}\n  .sumline .arr{color:var(--muted);margin:0 2px}\n  .sumline .now{color:#1a7d3c;font-weight:700}\n  .sumline.note,.sumline .note{color:var(--muted);font-style:italic}\n  .sumline.more,.sumline .more{color:var(--muted);font-size:11.5px}\n  .sumline.kf{display:flex;flex-wrap:wrap;gap:8px}\n  .kfpair{display:inline-flex;align-items:center;gap:5px;font:600 12px/1.4 var(--fam);color:var(--ink)}\n  .dtag{font:800 10px/1 var(--fam);text-transform:uppercase;padding:4px 8px;border-radius:999px;background:rgba(139,92,246,.15);color:#6d34d6}\n  .dcount{color:var(--muted);font:600 12px/1.4 var(--fam)}\n  .rfoot{display:flex;align-items:center;gap:12px;margin-top:11px;padding-top:10px;border-top:1px dashed var(--hair)}\n  .expand{background:none;border:none;padding:0;cursor:pointer;font:700 11.5px/1 var(--fam);color:var(--mag)}\n  .expand:hover{text-decoration:underline}\n  .expand{display:inline-flex;align-items:center;gap:5px}\n  .ic-svg{flex:0 0 auto}\n  .expand .ic-svg{width:14px;height:14px}\n  .search .si{display:inline-flex}\n  .search .si .ic-svg{width:16px;height:16px}\n  .abs{margin-left:auto;font:500 10.5px/1 var(--fam);color:var(--muted)}\n  .json{margin:11px 0 2px;background:#0f172a;color:#e2e8f0;border-radius:10px;padding:13px 14px;font:500 11px/1.5 'SF Mono',ui-monospace,Menlo,monospace;overflow:auto;max-height:340px;white-space:pre;box-sizing:border-box}\n  .empty{padding:60px;text-align:center;color:var(--muted);font:500 14px/1.5 var(--fam)}\n  @keyframes rise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}\n  @media (prefers-reduced-motion: reduce){ .card{animation:none} .fchip{transition:none!important} }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const green = t.color.rampGreen||t.color.money||'#29AC56';\n    const red = t.color.rampRed||'#FF1418';\n    const vars = `--surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient};--green:${green};--red:${red};--fam:${t.type.family};--shadowcard:${t.shadow.card};--mount:${(t.motion&&t.motion.mount)||'400ms cubic-bezier(0.4,0,0.2,1)'}`;\n\n    const ds = d2.data('audit');\n    const all = ds ? ds.records() : [];\n    const loading = ds && ds.loading;\n\n    const sorted = all.slice().sort((a,b)=> new Date(b.at||0)-new Date(a.at||0));\n\n    const fEntity = d2.state.fEntity||'';\n    const fAction = d2.state.fAction||'';\n    const fActor  = d2.state.fActor||'';\n    const fDate   = d2.state.fDate||'all';\n    const q = String(d2.state.q||'').trim().toLowerCase();\n\n    const actors = Array.from(new Set(sorted.map(r=>r.actorEmail).filter(Boolean))).sort();\n\n    const filtered = sorted.filter(r=>{\n      if(fEntity && String(r.entityType)!==fEntity) return false;\n      if(fAction && effectiveAction(r)!==fAction) return false;\n      if(fActor && String(r.actorEmail)!==fActor) return false;\n      if(!withinDate(r.at, fDate)) return false;\n      if(q){\n        const lbl = friendlyLabel(r);\n        const hay = `${r.actorEmail||''} ${r.entityId||''} ${r.entityType||''} ${lbl}`.toLowerCase();\n        if(hay.indexOf(q)<0) return false;\n      }\n      return true;\n    });\n\n    const rows = filtered.map(r=>rowMarkup(d2,r)).join('');\n\n    const entityChips = [{key:'',label:'Todos'}].concat(\n      Object.keys(ENTITY_LABEL).map(k=>({key:k,label:ENTITY_LABEL[k]}))\n    ).map(c=>`<button class=\"fchip\" data-fentity=\"${esc(c.key)}\" ${fEntity===c.key?'data-on':''}>${esc(c.label)}</button>`).join('');\n    const actionChips = ACTION_FILTERS.map(c=>`<button class=\"fchip\" data-faction=\"${esc(c.key)}\" ${fAction===c.key?'data-on':''}>${esc(c.label)}</button>`).join('');\n    const dateChips = DATE_PRESETS.map(c=>`<button class=\"fchip\" data-fdate=\"${esc(c.key)}\" ${fDate===c.key?'data-on':''}>${esc(c.label)}</button>`).join('');\n    const actorOpts = ['<option value=\"\">Todos os autores</option>'].concat(\n      actors.map(a=>`<option value=\"${esc(a)}\" ${fActor===a?'selected':''}>${esc(a)}</option>`)\n    ).join('');\n\n    return `<div class=\"screen\" style=\"${vars}\">\n      <div class=\"header\">\n        <div class=\"htop\">\n          <div class=\"htitle\">\n            <h1>Auditoria · Histórico de alterações <span class=\"badge\">Code · Somente leitura</span></h1>\n            <p>Registro de \"quem alterou o quê e quando\" no painel de remuneração. Cada entrada mostra o autor, a ação, a entidade afetada e um resumo legível da alteração. Expanda uma linha para ver o JSON completo da mudança.</p>\n          </div>\n        </div>\n        <div class=\"toolbar\">\n          <div class=\"search\"><span class=\"si\">${ICON.search}</span><input type=\"text\" data-q placeholder=\"Buscar por autor, ID, entidade ou rótulo…\" value=\"${esc(d2.state.q||'')}\"/></div>\n          <span class=\"count\">${filtered.length} de ${sorted.length} eventos</span>\n        </div>\n        <div class=\"filters\">\n          <div class=\"fgroup\"><span class=\"flabel\">Entidade</span>${entityChips}</div>\n        </div>\n        <div class=\"filters\">\n          <div class=\"fgroup\"><span class=\"flabel\">Ação</span>${actionChips}</div>\n          <div class=\"fgroup\"><span class=\"flabel\">Período</span>${dateChips}</div>\n          <div class=\"fgroup\"><span class=\"flabel\">Autor</span><select class=\"fsel\" data-factor>${actorOpts}</select></div>\n        </div>\n      </div>\n      <div class=\"body\">\n        ${loading\n          ? `<div class=\"empty\">Carregando histórico…</div>`\n          : (rows ? `<div class=\"tl\">${rows}</div>` : `<div class=\"empty\">Nenhum evento de auditoria encontrado com os filtros atuais.</div>`)}\n      </div>\n    </div>`;\n  },\n  mounted(d2){\n    const ds = d2.data('audit');\n    if(ds && ds.loadAll){ ds.loadAll().catch(()=>{}); }\n\n    d2.on('[data-q]','input',(e,el)=>{ d2.state.q = el.value; d2.refresh(); });\n    d2.on('[data-fentity]','click',(e,el)=>{ d2.setState({ fEntity: el.dataset.fentity }); });\n    d2.on('[data-faction]','click',(e,el)=>{ d2.setState({ fAction: el.dataset.faction }); });\n    d2.on('[data-fdate]','click',(e,el)=>{ d2.setState({ fDate: el.dataset.fdate }); });\n    d2.on('[data-factor]','change',(e,el)=>{ d2.setState({ fActor: el.value }); });\n    d2.on('[data-expand]','click',(e,el)=>{\n      const id = el.dataset.expand;\n      d2.setState({ expanded: d2.state.expanded===id ? null : id });\n    });\n  }\n};"}},"audit":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"audit"}}}}}}}}}},{"_id":"6a4ce62c28bee8a92628670a","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotAdminApp","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)'},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\"},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\n// ---- inline stroke SVG glyphs (uniform 24x24 viewBox, currentColor) ----\nconst SVG = {\n  home:'<path d=\"M4 10.5 12 4l8 6.5\"/><path d=\"M6 9.5V19h12V9.5\"/><path d=\"M10 19v-5h4v5\"/>',\n  indicadores:'<path d=\"M4 19V5\"/><path d=\"M4 19h16\"/><rect x=\"7\" y=\"11\" width=\"2.6\" height=\"5\"/><rect x=\"11\" y=\"8\" width=\"2.6\" height=\"8\"/><rect x=\"15\" y=\"6\" width=\"2.6\" height=\"10\"/>',\n  kpis:'<circle cx=\"12\" cy=\"12\" r=\"8\"/><circle cx=\"12\" cy=\"12\" r=\"4\"/><circle cx=\"12\" cy=\"12\" r=\"1\"/>',\n  regras:'<line x1=\"4\" y1=\"7\" x2=\"20\" y2=\"7\"/><circle cx=\"9\" cy=\"7\" r=\"2.4\"/><line x1=\"4\" y1=\"14\" x2=\"20\" y2=\"14\"/><circle cx=\"15\" cy=\"14\" r=\"2.4\"/>',\n  rulesets:'<path d=\"M12 3 3 8l9 5 9-5-9-5Z\"/><path d=\"M3 12l9 5 9-5\"/><path d=\"M3 16l9 5 9-5\"/>',\n  ciclos:'<rect x=\"4\" y=\"5\" width=\"16\" height=\"15\" rx=\"2\"/><line x1=\"4\" y1=\"9\" x2=\"20\" y2=\"9\"/><line x1=\"8\" y1=\"3\" x2=\"8\" y2=\"6\"/><line x1=\"16\" y1=\"3\" x2=\"16\" y2=\"6\"/>',\n  auditoria:'<path d=\"M20 12a8 8 0 1 1-2.6-5.9\"/><polyline points=\"20 3 20 7 16 7\"/><polyline points=\"12 8 12 12 15 14\"/>',\n  acesso:'<path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>',\n  estatisticas:'<path d=\"M4 19V5\"/><path d=\"M4 19h16\"/><path d=\"M7 15l3-3 3 2 4-6\"/>',\n  consultas:'<path d=\"M4 6h13\"/><path d=\"M4 11h13\"/><path d=\"M4 16h8\"/><circle cx=\"18.5\" cy=\"17\" r=\"2.6\"/><line x1=\"20.4\" y1=\"18.9\" x2=\"22\" y2=\"20.5\"/>',\n  rightArrow:'<line x1=\"4\" y1=\"12\" x2=\"19\" y2=\"12\"/><polyline points=\"13 6 19 12 13 18\"/>',\n  logout:'<path d=\"M15 4h3a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-3\"/><polyline points=\"10 17 15 12 10 7\"/><line x1=\"15\" y1=\"12\" x2=\"3\" y2=\"12\"/>'\n};\nfunction icon(name,cls){ return `<svg class=\"${cls||'g'}\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${SVG[name]||''}</svg>`; }\n\nconst SECTIONS = [\n  { id:'indicadores', label:'Indicadores', icon:'indicadores', tag:'Code · DnD',            desc:'Reordene, edite, duplique ou oculte os indicadores exibidos no dashboard. Arraste pelos punhos para reorganizar.' },\n  { id:'kpis',        label:'KPIs',        icon:'kpis',        tag:'Code · Definições',      desc:'Gerencie as definições dos indicadores (KPIs) que o painel referencia. Edite nome, meta, marca e IAP, ou crie um novo mapeando um código de índice da Performance API.' },\n  { id:'regras',      label:'Regras',      icon:'regras',      tag:'Code · Remuneração',     desc:'Ajuste faixas, bônus e fórmulas por perfil (Líder / GN) que compõem o cálculo de ganhos.' },\n  { id:'rulesets',    label:'Rulesets',    icon:'rulesets',    tag:'Code · Versionamento',   desc:'Versione as regras de remuneração. Duplique um ruleset ativo para preparar o próximo ciclo sem tocar no conjunto em produção.' },\n  { id:'ciclos',      label:'Ciclos',      icon:'ciclos',      tag:'Code · Vínculo',         desc:'Vincule cada ciclo a um ruleset e controle status/ciclo atual. Trocar o ruleset de um ciclo muda o cálculo daquele ciclo.' },\n  { id:'consultas',   label:'Consultas',   icon:'consultas',   tag:'Code · Databricks',      desc:'Biblioteca de consultas SQL parametrizadas ({{param}}) executadas ao vivo no Databricks. Crie, edite, teste consultas e consulte o calendário de ciclos por grupo.' },\n  { id:'auditoria',   label:'Auditoria',   icon:'auditoria',   tag:'Code · Somente leitura', desc:'Histórico somente-leitura de \"quem alterou o quê e quando\": KPIs, faixas, bônus, fórmulas, rulesets e ciclos. Filtre por entidade, ação, autor e período; expanda para ver o diff completo.' },\n  { id:'acesso',      label:'Acessos',     icon:'acesso',      tag:'Code · Somente leitura', desc:'Registro de impersonações e acessos ao painel: quem visualizou como quem, quando, com qual escopo e ciclo. Estatísticas de uso e tabela do mais recente ao mais antigo.' },\n  { id:'estatisticas',label:'Estatísticas', icon:'estatisticas', tag:'Code · Somente leitura', desc:'Painel de uso: sessões ativas agora, logins ao longo do tempo, distribuição por perfil / modo / rede, usuários mais ativos, seções mais acessadas e mix de dispositivo/entrada.' }\n];\n\n// section typeId + which shell params each one needs, mapped to the child's expected param names.\nfunction sectionCfg(d2){\n  return {\n    indicadores: { type:'natura-x-piloto@pilotAdmScreen', params:{\n      items:d2.params.items, kpis:d2.params.kpis, writer:d2.params.itemWriter,\n      list:'natura-x-piloto@pilotAdmList', form:'natura-x-piloto@pilotAdmForm' } },\n    kpis: { type:'natura-x-piloto@pilotKpiAdmScreen', params:{\n      kpis:d2.params.kpis, writer:d2.params.ruleWriter } },\n    regras: { type:'natura-x-piloto@pilotRuleAdmScreen', params:{\n      bands:d2.params.bands, bonuses:d2.params.bonuses, formulas:d2.params.formulas,\n      rulesets:d2.params.rulesets, bandTables:d2.params.bandTables, kpis:d2.params.kpis,\n      cycles:d2.params.cycles, writer:d2.params.ruleWriter } },\n    rulesets: { type:'natura-x-piloto@pilotRulesetAdmScreen', params:{\n      rulesets:d2.params.rulesets, bands:d2.params.bands, formulas:d2.params.formulas,\n      bonuses:d2.params.bonuses, cycles:d2.params.cycles, writer:d2.params.ruleWriter } },\n    ciclos: { type:'natura-x-piloto@pilotCycleAdmScreen', params:{\n      cycles:d2.params.cycles, rulesets:d2.params.rulesets, writer:d2.params.ruleWriter } },\n    consultas: { type:'natura-x-piloto@pilotQueryLibAdmScreen', params:{\n      queryLib:d2.params.queryLib, queryCalendar:d2.params.queryCalendar,\n      queryWriter:d2.params.queryWriter, runner:d2.params.runner } },\n    auditoria: { type:'natura-x-piloto@pilotAuditAdmScreen', params:{\n      audit:d2.params.audit } },\n    acesso: { type:'natura-x-piloto@pilotAccessLogAdmScreen', params:{\n      accessLog:d2.params.accessLog } },\n    estatisticas: { type:'natura-x-piloto@pilotAccessStatsAdmScreen', params:{\n      sessions:d2.params.sessions, accessLog:d2.params.accessLog } }\n  };\n}\n\nfunction syncLinksEdge(el){ if(!el) return; el.classList.toggle('atend', el.scrollLeft + el.clientWidth >= el.scrollWidth - 4); }\nfunction revealActiveTab(d2){\n  const l = d2.$('.links'); const a = d2.$('.item[data-active]');\n  if(l && a){\n    const lr = l.getBoundingClientRect(), ar = a.getBoundingClientRect();\n    if(ar.left < lr.left || ar.right > lr.right) l.scrollLeft += (ar.left - lr.left) - (lr.width - ar.width)/2;\n  }\n  syncLinksEdge(l);\n}\n\nexport default {\n  css: `\n  :host{display:block}\n  .app{min-height:100%;height:auto;display:flex;flex-direction:column;background:var(--ground);font-family:var(--fam)}\n  .bar{position:sticky;top:0;z-index:40;display:flex;align-items:center;gap:8px;min-height:62px;box-sizing:border-box;padding:0 22px;background:var(--surface);border-bottom:1px solid var(--hair)}\n  .brand{display:flex;align-items:center;gap:10px;cursor:pointer;padding:6px 6px 6px 0;margin-right:8px;border-radius:10px}\n  .brand .logo{width:26px;height:26px;border-radius:8px;background:var(--grad);display:inline-flex;align-items:center;justify-content:center;color:#fff;font:800 14px/1 var(--fam)}\n  .brand .name{font:800 15px/1 var(--fam);color:var(--ink);letter-spacing:-.2px}\n  .brand .name small{display:block;font:600 10px/1.3 var(--fam);color:var(--muted);letter-spacing:.04em;text-transform:uppercase;margin-top:3px}\n  .links{display:flex;gap:4px;margin-left:6px;flex-wrap:nowrap;flex:1 1 auto;min-width:0;overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none;-webkit-overflow-scrolling:touch;\n    -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 24px),transparent);mask-image:linear-gradient(90deg,#000 calc(100% - 24px),transparent)}\n  .links::-webkit-scrollbar{display:none}\n  .links.atend{-webkit-mask-image:none;mask-image:none}\n  .item{display:inline-flex;align-items:center;gap:7px;padding:9px 14px;border-radius:10px;cursor:pointer;font:700 13px/1 var(--fam);color:var(--muted);\n    background:none;border:none;transition:background .15s,color .15s;white-space:nowrap;flex:0 0 auto}\n  .item:hover{background:var(--ground);color:var(--ink)}\n  .item[data-active]{color:var(--mag);background:rgba(229,0,75,.10)}\n  .g{width:17px;height:17px;flex:none}\n  .spacer{margin-left:auto}\n  .bar .spacer{flex:0 0 auto;margin-left:0}\n  .home-btn,.brand{flex:0 0 auto;white-space:nowrap}\n  @media (max-width:900px){\n    .bar{flex-wrap:wrap;padding:8px 14px 0;gap:6px 8px;align-items:center}\n    .brand{order:1;margin-right:auto;padding:4px 0}\n    .brand .name small{display:none}\n    .bar>.spacer{display:none}\n    .home-btn{order:2;padding:8px 10px}\n    .home-btn .lbl{display:none}\n    .who{display:none}\n    .links{order:3;flex:1 0 100%;margin:0 -14px;padding:2px 14px 8px;gap:2px}\n    .item{padding:9px 12px}\n  }\n  @media (max-width:900px) and (prefers-reduced-motion: no-preference){ .links{scroll-behavior:smooth} }\n  .home-btn{display:inline-flex;align-items:center;gap:7px;padding:8px 13px;border-radius:10px;cursor:pointer;font:700 12px/1 var(--fam);color:var(--muted);\n    background:none;border:1px solid var(--hair);transition:background .15s,color .15s}\n  .home-btn:hover{background:var(--ground);color:var(--ink)}\n  .home-btn[data-active]{color:var(--mag);border-color:rgba(229,0,75,.30);background:rgba(229,0,75,.06)}\n  .home-btn .g{width:16px;height:16px}\n  .home-btn[disabled]{opacity:.6;cursor:default}\n  .who{font:600 12px/1 var(--fam);color:var(--muted);max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n  .slot{flex:1 1 auto;min-height:600px}\n  .sechost{display:block;width:100%}\n  .home{min-height:100%;height:auto;box-sizing:border-box;background:var(--ground);font-family:var(--fam);padding:40px 44px 64px}\n  .inner{max-width:1000px;margin:0 auto}\n  .hero h1{margin:0;font:800 34px/1.1 var(--fam);color:var(--ink);letter-spacing:-.6px}\n  .hero p{margin:8px 0 0;font:400 15px/1.5 var(--fam);color:var(--muted);max-width:640px}\n  .grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:22px;margin-top:34px}\n  .card{position:relative;background:var(--surface);border:1px solid var(--hair);border-radius:20px;padding:26px;cursor:pointer;\n    box-shadow:var(--shadowcard);transition:box-shadow .2s,transform .2s;overflow:hidden}\n  .card:hover{box-shadow:var(--shadowraised);transform:translateY(-3px)}\n  .card::after{content:'';position:absolute;left:0;top:0;bottom:0;width:5px;background:var(--grad);opacity:0;transition:opacity .2s}\n  .card:hover::after{opacity:1}\n  .card .ico{width:52px;height:52px;border-radius:14px;background:rgba(229,0,75,.10);display:inline-flex;align-items:center;justify-content:center;color:var(--mag)}\n  .card .ico svg{width:26px;height:26px}\n  .card h2{margin:16px 0 0;font:800 21px/1.15 var(--fam);color:var(--ink);letter-spacing:-.3px}\n  .card .tag{display:inline-block;margin-top:8px;font:700 10px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;\n    color:var(--mag);background:rgba(229,0,75,.10);padding:5px 9px;border-radius:999px}\n  .card p{margin:14px 0 0;font:400 13.5px/1.55 var(--fam);color:var(--muted)}\n  .card .go{margin-top:18px;display:inline-flex;align-items:center;gap:6px;font:700 13px/1 var(--fam);color:var(--mag)}\n  .card .go svg{width:15px;height:15px}\n  @media (prefers-reduced-motion: reduce){ .item,.home-btn,.card{transition:none!important} .card:hover{transform:none} }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const section = d2.state.section || 'home';\n    const vars = `--surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient};--fam:${t.type.family};--shadowcard:${(t.shadow&&t.shadow.card)||FALLBACK.shadow.card};--shadowraised:${(t.shadow&&t.shadow.raised)||FALLBACK.shadow.raised}`;\n\n    let who = '';\n    try { const a = d2.auth('pilotAdminAuth'); who = (a && a.user && a.user.email) || ''; } catch(e) {}\n    const links = SECTIONS.map(s=>`<button class=\"item\" data-sec=\"${s.id}\" ${section===s.id?'data-active':''}>${icon(s.icon)}${esc(s.label)}</button>`).join('');\n    const nav = `<div class=\"bar\">\n      <div class=\"brand\" data-sec=\"home\">\n        <span class=\"logo\">A</span>\n        <span class=\"name\">Administração<small>Painel de Remuneração</small></span>\n      </div>\n      <div class=\"links\">${links}</div>\n      <span class=\"spacer\"></span>\n      <button class=\"home-btn\" data-sec=\"home\" ${section==='home'?'data-active':''} aria-label=\"Início\">${icon('home')}<span class=\"lbl\">Início</span></button>\n      ${who?`<span class=\"who\" title=\"${esc(who)}\">${esc(who)}</span>`:''}\n      <button class=\"home-btn\" data-logout ${d2.state.loggingOut?'disabled':''} aria-label=\"Sair\">${icon('logout')}<span class=\"lbl\">${d2.state.loggingOut?'Saindo…':'Sair'}</span></button>\n    </div>`;\n\n    let slot;\n    if(section==='home'){\n      const cards = SECTIONS.map(s=>`<div class=\"card\" data-sec=\"${s.id}\">\n        <span class=\"ico\">${icon(s.icon)}</span>\n        <h2>${esc(s.label)} <span class=\"tag\">${esc(s.tag)}</span></h2>\n        <p>${esc(s.desc)}</p>\n        <span class=\"go\">Abrir ${icon('rightArrow')}</span>\n      </div>`).join('');\n      slot = `<div class=\"slot\"><div class=\"home\"><div class=\"inner\">\n        <div class=\"hero\">\n          <h1>Administração do Painel</h1>\n          <p>Central de configuração do piloto Natura. Gerencie os indicadores do dashboard e as regras de remuneração a partir de um só lugar.</p>\n        </div>\n        <div class=\"grid\">${cards}</div>\n      </div></div></div>`;\n    } else {\n      const cfg = sectionCfg(d2)[section];\n      const inner = cfg\n        ? d2.render(cfg.type, cfg.params, { key:'sec-'+section, class:'sechost' })\n        : `<div style=\"padding:60px;text-align:center;color:${t.color.muted}\">Seção desconhecida</div>`;\n      slot = `<div class=\"slot\">${inner}</div>`;\n    }\n\n    return `<div class=\"app\" style=\"${vars}\">${nav}${slot}</div>`;\n  },\n  updated(d2){ const l=d2.$('.links'); if(l) syncLinksEdge(l); },\n  mounted(d2){\n    if(!d2.state.section) d2.state.section = 'home';\n    d2.on('[data-logout]','click',async()=>{\n      if(d2.state.loggingOut) return;\n      d2.state.loggingOut = true;\n      try { await d2.auth('pilotAdminAuth').logout(); } catch(e) { d2.log('logout falhou', e); }\n      window.location.assign('/');\n    });\n    d2.on('[data-sec]','click',(e,el)=>{\n      const next = el.dataset.sec;\n      if(next && next!==d2.state.section){ d2.state.section = next; if(d2.root && d2.root.scrollTo) d2.root.scrollTo(0,0); }\n      setTimeout(()=>revealActiveTab(d2), 60);\n    });\n    // Mobile: keep the active tab inside the scrollable tab strip, and drop the fade once scrolled to the end.\n    d2.on('.links','scroll',(e,el)=>syncLinksEdge(el));\n    setTimeout(()=>{ revealActiveTab(d2); const l=d2.$('.links'); if(l) syncLinksEdge(l); }, 120);\n  }\n};"}},"items":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"items"}}}},"kpis":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"kpis"}}}},"itemWriter":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"itemWriter"}}}},"bands":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bands"}}}},"bonuses":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bonuses"}}}},"formulas":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"formulas"}}}},"rulesets":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rulesets"}}}},"bandTables":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bandTables"}}}},"cycles":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cycles"}}}},"ruleWriter":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"ruleWriter"}}}},"audit":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"audit"}}}},"accessLog":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"accessLog"}}}},"sessions":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"sessions"}}}},"queryLib":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"queryLib"}}}},"queryCalendar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"queryCalendar"}}}},"queryWriter":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"queryWriter"}}}},"runner":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"runner"}}}}}}}}}},{"_id":"6a4ce9aed961b870ddee86db","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotSimulador","package":"natura-x-piloto","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 FALLBACK_TOK = {\n  color:{ surface:'#FFFFFF', ground:'#FAFAFB', ink:'#1A1C1E', muted:'#6B7280', hairline:'rgba(16,24,40,0.08)',\n    naturaMagenta:'#E5004B', naturaOrange:'#EB6619', brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',\n    rampRed:'#FF1418', rampAmber:'#FAA000', rampGreen:'#29AC56', gold:'#F7BE00', money:'#29AC56' },\n  radius:{ sm:8, md:12, lg:16, pill:999 },\n  type:{ family:\"'Roboto',system-ui,-apple-system,sans-serif\" },\n  shadow:{ card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)', raised:'0 4px 12px rgba(16,24,40,0.10)' },\n  media:{ natura:'https://natura-x-piloto.data2.media/file/UrhVLdPDEZCXToLgJDPW8',\n    avon:'https://natura-x-piloto.data2.media/file/HqLhKqINaRUI9OSBjYGFh',\n    lockup:'https://natura-x-piloto.data2.media/file/H0P_N-7AQzQOg_VJMBWzV' }\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK_TOK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction brl(n){ const v = Number(n)||0; return v.toLocaleString('pt-BR',{ style:'currency', currency:'BRL' }); }\nfunction num(n){ const v = Number(n); return isFinite(v) ? v.toLocaleString('pt-BR',{ maximumFractionDigits:0 }) : '—'; }\nfunction pct(n){ if(n==null||!isFinite(Number(n))) return '—'; return (Number(n)).toLocaleString('pt-BR',{ maximumFractionDigits:1 })+'%'; }\nfunction pctClass(a){ if(a==null||!isFinite(Number(a))) return 'n'; const v=Number(a); if(v>=100) return 'g'; if(v>=80) return 'a'; return 'r'; }\n\nfunction icon(name, color, size){\n  const s = size||18; const c = color||'#6B7280';\n  const A = `xmlns=\"http://www.w3.org/2000/svg\" width=\"${s}\" height=\"${s}\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"${c}\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"`;\n  const P = {\n    people:`<path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><path d=\"M23 21v-2a4 4 0 0 0-3-3.87\"/><path d=\"M16 3.13a4 4 0 0 1 0 7.75\"/>`,\n    target:`<circle cx=\"12\" cy=\"12\" r=\"9\"/><circle cx=\"12\" cy=\"12\" r=\"5\"/><circle cx=\"12\" cy=\"12\" r=\"1.4\"/>`,\n    crown:`<path d=\"M3 8l4 5 5-8 5 8 4-5-2 11H5L3 8z\"/>`,\n    swap:`<polyline points=\"17 2 21 6 17 10\"/><path d=\"M3 6h18\"/><polyline points=\"7 22 3 18 7 14\"/><path d=\"M21 18H3\"/>`,\n    userAdd:`<path d=\"M15 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\"/><circle cx=\"8\" cy=\"7\" r=\"4\"/><line x1=\"19\" y1=\"8\" x2=\"19\" y2=\"14\"/><line x1=\"22\" y1=\"11\" x2=\"16\" y2=\"11\"/>`,\n    coins:`<circle cx=\"8\" cy=\"8\" r=\"6\"/><path d=\"M18.09 10.37A6 6 0 1 1 10.34 18\"/><path d=\"M7 6h1v4\"/><path d=\"M16.71 13.88l.7.71-2.82 2.82\"/>`,\n    receipt:`<path d=\"M5 3v18l2-1.5L9 21l2-1.5L13 21l2-1.5L17 21l2-1.5V3l-2 1.5L15 3l-2 1.5L11 3 9 4.5 7 3 5 4.5z\"/><line x1=\"8\" y1=\"8\" x2=\"16\" y2=\"8\"/><line x1=\"8\" y1=\"12\" x2=\"16\" y2=\"12\"/>`,\n    flag:`<path d=\"M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z\"/><line x1=\"4\" y1=\"22\" x2=\"4\" y2=\"15\"/>`,\n    calc:`<rect x=\"4\" y=\"2\" width=\"16\" height=\"20\" rx=\"2\"/><line x1=\"8\" y1=\"6\" x2=\"16\" y2=\"6\"/><line x1=\"8\" y1=\"11\" x2=\"8\" y2=\"11\"/><line x1=\"12\" y1=\"11\" x2=\"12\" y2=\"11\"/><line x1=\"16\" y1=\"11\" x2=\"16\" y2=\"11\"/><line x1=\"8\" y1=\"15\" x2=\"8\" y2=\"15\"/><line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"15\"/><line x1=\"16\" y1=\"15\" x2=\"16\" y2=\"18\"/>`,\n    check:`<polyline points=\"20 6 9 17 4 12\"/>`,\n    layers:`<polygon points=\"12 2 2 7 12 12 22 7 12 2\"/><polyline points=\"2 17 12 22 22 17\"/><polyline points=\"2 12 12 17 22 12\"/>`,\n    gift:`<polyline points=\"20 12 20 22 4 22 4 12\"/><rect x=\"2\" y=\"7\" width=\"20\" height=\"5\"/><line x1=\"12\" y1=\"22\" x2=\"12\" y2=\"7\"/><path d=\"M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z\"/><path d=\"M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z\"/>`,\n    money:`<line x1=\"12\" y1=\"1\" x2=\"12\" y2=\"23\"/><path d=\"M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6\"/>`,\n    sliders:`<line x1=\"4\" y1=\"21\" x2=\"4\" y2=\"14\"/><line x1=\"4\" y1=\"10\" x2=\"4\" y2=\"3\"/><line x1=\"12\" y1=\"21\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"3\"/><line x1=\"20\" y1=\"21\" x2=\"20\" y2=\"16\"/><line x1=\"20\" y1=\"12\" x2=\"20\" y2=\"3\"/><line x1=\"1\" y1=\"14\" x2=\"7\" y2=\"14\"/><line x1=\"9\" y1=\"8\" x2=\"15\" y2=\"8\"/><line x1=\"17\" y1=\"16\" x2=\"23\" y2=\"16\"/>`,\n    back:`<polyline points=\"15 18 9 12 15 6\"/>`\n  };\n  return `<svg ${A}>${P[name]||''}</svg>`;\n}\nfunction dashIcon(iconId, color){\n  const c = color || '#6B7280';\n  const w = `width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"${c}\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"`;\n  const P = {\n    'people':`<circle cx=\"9\" cy=\"7\" r=\"3\"/><path d=\"M2 21v-2a5 5 0 0 1 5-5h4a5 5 0 0 1 5 5v2\"/><path d=\"M17 7a3 3 0 0 1 0 6\"/><path d=\"M22 21v-2a5 5 0 0 0-3-4.5\"/>`,\n    'user':`<circle cx=\"12\" cy=\"8\" r=\"3.5\"/><path d=\"M4 21v-2a5 5 0 0 1 5-5h6a5 5 0 0 1 5 5v2\"/>`,\n    'target':`<circle cx=\"12\" cy=\"12\" r=\"9\"/><circle cx=\"12\" cy=\"12\" r=\"5\"/><circle cx=\"12\" cy=\"12\" r=\"1.5\" fill=\"${c}\"/>`,\n    'crown':`<path d=\"M3 8l4 4 5-6 5 6 4-4v9H3z\"/><path d=\"M3 20h18\"/>`,\n    'swap':`<path d=\"M12 4v16\"/><path d=\"M7 8l-4 4 4 4\"/><path d=\"M17 8l4 4-4 4\"/>`,\n    'user-add':`<circle cx=\"9\" cy=\"8\" r=\"3.5\"/><path d=\"M2 20v-1.5a5 5 0 0 1 5-5h4\"/><path d=\"M18 12v6\"/><path d=\"M15 15h6\"/>`,\n    'coins':`<circle cx=\"8\" cy=\"8\" r=\"6\"/><path d=\"M18.09 10.37A6 6 0 1 1 10.34 18\"/><path d=\"M7 6h1v4\"/><path d=\"M16.71 13.88l.7.71-2.82 2.82\"/>`\n  };\n  const path = P[iconId] || `<circle cx=\"12\" cy=\"12\" r=\"3\" fill=\"${c}\" stroke=\"none\"/>`;\n  return `<svg ${w}>${path}</svg>`;\n}\nfunction brandMark(t, brand, size){\n  const s = size||18;\n  const src = String(brand).toLowerCase()==='avon' ? t.media.avon : t.media.natura;\n  const label = String(brand).toLowerCase()==='avon' ? 'Avon' : 'Natura';\n  return `<span class=\"bmk\" style=\"height:${s}px\"><img src=\"${esc(src)}\" alt=\"${label}\"/></span>`;\n}\nfunction fieldIcon(t, f){\n  if(f.brand) return brandMark(t, f.brand, 20);\n  return dashIcon(f.ic||'target', t.color.muted);\n}\nfunction statIcon(t, s){\n  const hasBrand = s.brand === 'natura' || s.brand === 'avon';\n  if(hasBrand) return brandMark(t, s.brand, 16);\n  const col = s.status==='green'?t.color.rampGreen:(s.status==='amber'?t.color.rampAmber:(s.status==='red'?t.color.rampRed:null));\n  const iconId = s.icon || 'target';\n  const tint = (iconId==='crown') ? t.color.gold : (col || t.color.muted || '#6B7280');\n  return dashIcon(iconId, tint);\n}\nfunction fields(perfil, rede){\n  const isGn = (perfil==='gn');\n  if(rede==='rede2'){\n    if(isGn){\n      // GN rede2 — GN-level faturamento (the atingimento-faturamento inputs)\n      return [\n        { code:'481', label:'Faturamento GN Natura', brand:'natura', goalKey:'goalBillingNatura' },\n        { code:'486', label:'Faturamento GN Avon', brand:'avon', goalKey:'goalBillingAvon' }\n      ];\n    }\n    return [\n      { code:'481', label:'Faturamento Natura', brand:'natura', goalKey:'goalBillingNatura' },\n      { code:'486', label:'Faturamento Avon', brand:'avon', goalKey:'goalBillingAvon' },\n      { code:'469', label:'Volume de Pontos Natura', brand:'natura', goalKey:'goalsPointsNatura' },\n      { code:'472', label:'Volume de Pontos Avon', brand:'avon', goalKey:'goalsPointsAvon' },\n      { code:'32', label:'Quantidade de Cadastros', ic:'user-add' }\n    ];\n  }\n  if(isGn){\n    // GN rede1 — GN-level ativas (the ativas-gn inputs)\n    return [\n      { code:'545', label:'Ativas GN Natura', brand:'natura', goalKey:'goalActivesNaturaExclusive' },\n      { code:'546', label:'Ativas GN Avon', brand:'avon', goalKey:'goalActivesAvonExclusive' },\n      { code:'28', label:'Ativas GN Totais', ic:'people', goalKey:'goalActive' }\n    ];\n  }\n  return [\n    { code:'545', label:'Ativas Natura', brand:'natura', goalKey:'goalActivesNaturaExclusive' },\n    { code:'546', label:'Ativas Avon', brand:'avon', goalKey:'goalActivesAvonExclusive' },\n    { code:'28', label:'Ativas Totais', ic:'people', goalKey:'goalActive' },\n    { code:'registerSilverPlus', label:'Migradas Ouro +', ic:'crown' },\n    { code:'392', label:'Saldo', ic:'swap' },\n    { code:'379', label:'Inícios', ic:'user-add' }\n  ];\n}\n// Read the current-view context handed over by the launcher (query first, then shared UIState).\nfunction readSimContext(d2){\n  const out = { perfil:'', structureCode:'', rede:'', cycle:'', gvName:'' };\n  try{\n    const qs = (typeof location!=='undefined' && location.search) ? location.search : '';\n    if(qs){\n      const p = new URLSearchParams(qs);\n      out.perfil = p.get('perfil') || '';\n      out.structureCode = p.get('structureCode') || '';\n      out.rede = p.get('rede') || '';\n      out.cycle = p.get('cycle') || '';\n      out.gvName = p.get('gvName') || '';\n    }\n  }catch(e){}\n  try{\n    const sh = d2.shared.get('pilotSimContext', null, {global:true});\n    if(sh){\n      if(!out.perfil) out.perfil = sh.perfil || '';\n      if(!out.structureCode) out.structureCode = String(sh.structureCode||'');\n      if(!out.rede) out.rede = sh.rede || '';\n      if(!out.cycle) out.cycle = String(sh.cycle||'');\n      if(!out.gvName) out.gvName = sh.gvName || '';\n    }\n  }catch(e){}\n  return out;\n}\nfunction sliderMax(f){\n  const v = Number(f.value)||0;\n  const g = Number(f.goal)||0;\n  const b = Number(f.baseline)||0;\n  const floor = f.brand ? 200 : 50;\n  return Math.max(g*1.6, v*1.4, b*1.4, floor, 10);\n}\n// ---- Remuneration ladder (rede-aware) helpers ----\n// Index value the engine uses to locate the active faixa, per (table ref, brand).\nfunction bandIndex(tableRef, brand, bd, stats, kpiCode){\n  const B = bd || {};\n  if(tableRef==='ativas-total'){ const k=B.kpis||{}; return brand==='avon'? k.avonExclusiva : k.naturaExclusiva; }\n  if(tableRef==='atingimento'){ const a=B.atingimentos||{}; return brand==='avon'? a.avon : a.natura; }\n  if(tableRef==='pontos'){ const p=B.pontos||{}; return brand==='avon'? p.atingAvon : p.atingNatura; }\n  // any other table: atingimento of that kpiCode from stats\n  const arr = (stats||[]).filter(s=>String(s.indexCode)===String(kpiCode)).slice(0,1);\n  return arr.length ? arr[0].atingimento : null;\n}\n// Volume applied by the rede2 multiplier, per brand (pontos volume for lider rede2).\nfunction bandVolume(tableRef, brand, bd){\n  const B = bd || {};\n  if(tableRef==='pontos'){ const p=B.pontos||{}; return brand==='avon'? p.avonRealized : p.naturaRealized; }\n  return null;\n}\nfunction activeRow(rows, idx){\n  if(idx==null || !isFinite(Number(idx))) return -1;\n  const v = Number(idx);\n  for(let i=0;i<rows.length;i++){ const r=rows[i]; if(v>=Number(r.minPct) && v<=Number(r.maxPct)) return i; }\n  return -1;\n}\n// Faixa label: '%' suffix for multiplier / atingimento-style tables, plain range for fixed (ativas-total).\nfunction faixaLabel(r, valueType, kpiCode){\n  const suffix = (valueType==='multiplier') ? '%' : '';\n  const lo = num(r.minPct);\n  const hi = (Number(r.maxPct)>=9999) ? '+' : num(r.maxPct);\n  if(Number(r.maxPct)>=9999) return `${lo}${suffix}+`;\n  return `${lo}${suffix}–${hi}${suffix}`;\n}\n// Valor cell: multiplier → 'N%' (or ×N%); fixed → R$.\nfunction valorCell(r, valueType){\n  if(valueType==='multiplier') return `${num(r.value)}%`;\n  return brl(r.value);\n}\nfunction topbar(t){\n  return `<div class=\"topbar\">\n    <button class=\"backbtn\" title=\"Voltar ao Painel\">${icon('back','#E5004B',20)}<span>Voltar ao Painel</span></button>\n    <span class=\"lock\"><img src=\"${esc(t.media.lockup)}\" alt=\"Natura &amp; Avon\"/></span>\n    <span class=\"tbttl\">Simulador de Ganhos</span>\n    <span class=\"tbspacer\"></span>\n  </div>`;\n}\n\nexport default {\n  css: `\n  :host{ display:block; min-height:100%; height:auto; background:#FAFAFB; font-family:'Roboto',system-ui,-apple-system,sans-serif; color:#1A1C1E; }\n  .page{ min-height:100%; background:#FAFAFB; }\n  *{ box-sizing:border-box; }\n  .topbar{ position:sticky; top:0; z-index:50; display:flex; align-items:center; gap:14px; height:60px; padding:0 18px;\n    background:#FFFFFF; border-bottom:1px solid rgba(16,24,40,0.08); box-shadow:0 1px 3px rgba(16,24,40,0.05); }\n  .backbtn{ display:inline-flex; align-items:center; gap:7px; height:38px; padding:0 14px 0 10px; border:1px solid rgba(229,0,75,.24);\n    border-radius:999px; background:#fff; color:#E5004B; font:700 13px/1 'Roboto',sans-serif; cursor:pointer;\n    transition:background 150ms ease-out,border-color 150ms ease-out,transform 150ms ease-out; }\n  .backbtn:hover{ background:rgba(229,0,75,.06); border-color:rgba(229,0,75,.4); transform:translateX(-1px); }\n  .backbtn:active{ transform:translateX(0); }\n  .lock{ height:28px; display:flex; align-items:center; margin-left:2px; padding-left:14px; border-left:1px solid rgba(16,24,40,0.10); }\n  .lock img{ height:100%; width:auto; display:block; }\n  .tbttl{ font:600 15px/1 'Roboto',sans-serif; color:#1A1C1E; letter-spacing:.1px; }\n  .tbspacer{ flex:1 1 auto; }\n  .wrap{ max-width:960px; margin:0 auto; padding:20px 16px 56px; }\n  .head{ display:flex; align-items:center; gap:12px; margin:0 0 18px; }\n  .head .mk{ width:40px; height:40px; border-radius:12px; display:flex; align-items:center; justify-content:center;\n    background:linear-gradient(135deg,#E5004B 0%,#EB6619 100%); box-shadow:0 4px 12px rgba(229,0,75,.28); flex:0 0 40px; }\n  .head h1{ font:700 22px/1.1 'Roboto',sans-serif; margin:0; letter-spacing:-.2px; }\n  .head p{ margin:2px 0 0; font:400 12px/1.3 'Roboto',sans-serif; color:#6B7280; }\n  .card{ background:#FFFFFF; border:1px solid rgba(16,24,40,0.08); border-radius:16px;\n    box-shadow:0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08); padding:18px; margin-bottom:16px; }\n  .card > .ct{ display:flex; align-items:center; gap:8px; font:700 11px/1 'Roboto',sans-serif; letter-spacing:.6px;\n    text-transform:uppercase; color:#6B7280; margin:0 0 14px; }\n  .ct .spacer{ flex:1 1 auto; }\n  .ctl{ display:flex; flex-wrap:wrap; gap:12px; }\n  .fld{ display:flex; flex-direction:column; gap:5px; min-width:0; flex:1 1 150px; }\n  .fld.wide{ flex:1 1 260px; }\n  .lbl{ font:600 10px/1 'Roboto',sans-serif; letter-spacing:.5px; text-transform:uppercase; color:#6B7280; }\n  .sel{ appearance:none; -webkit-appearance:none; width:100%; min-width:0; height:40px; padding:0 34px 0 12px;\n    border:1px solid rgba(16,24,40,0.14); border-radius:10px; background:#FFFFFF; color:#1A1C1E;\n    font:500 13px/1 'Roboto',sans-serif; cursor:pointer; transition:border-color 150ms ease-out,box-shadow 150ms ease-out;\n    background-image:url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236B7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>\");\n    background-repeat:no-repeat; background-position:right 10px center; }\n  .sel:focus{ outline:none; border-color:#E5004B; box-shadow:0 0 0 3px rgba(229,0,75,.12); }\n  .grid{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:16px 18px; }\n  .kpi{ display:flex; flex-direction:column; gap:9px; min-width:0; padding:12px; border:1px solid rgba(16,24,40,0.07);\n    border-radius:13px; background:#FCFCFD; }\n  .kpi .krow{ display:flex; align-items:center; gap:10px; min-width:0; }\n  .kicon{ width:32px; height:32px; flex:0 0 32px; border-radius:9px; background:#FFFFFF; border:1px solid rgba(16,24,40,0.08);\n    display:flex; align-items:center; justify-content:center; }\n  .bmk{ display:inline-flex; align-items:center; justify-content:center; line-height:0; }\n  .bmk img{ display:block; height:100%; width:auto; object-fit:contain; }\n  .knm{ flex:1 1 auto; min-width:0; font:600 13px/1.2 'Roboto',sans-serif; color:#1A1C1E; }\n  .atchip{ flex:0 0 auto; display:inline-flex; align-items:center; padding:3px 9px; border-radius:999px; font:700 11px/1 'Roboto',sans-serif; }\n  .atchip.g{ background:rgba(41,172,86,.12); color:#1F8A45; } .atchip.a{ background:rgba(250,160,0,.14); color:#B57200; }\n  .atchip.r{ background:rgba(255,20,24,.10); color:#D01418; } .atchip.n{ background:#F1F3F6; color:#6B7280; }\n  .inps{ display:flex; gap:8px; min-width:0; }\n  .inbox{ flex:1 1 0; min-width:0; display:flex; flex-direction:column; gap:3px; }\n  .inbox .t{ font:500 9px/1 'Roboto',sans-serif; letter-spacing:.4px; text-transform:uppercase; color:#9AA1AC; }\n  .num{ width:100%; min-width:0; height:36px; padding:0 10px; border:1px solid rgba(16,24,40,0.14); border-radius:9px;\n    background:#FFFFFF; color:#1A1C1E; font:600 14px/1 'Roboto',sans-serif; transition:border-color 150ms ease-out,box-shadow 150ms ease-out; }\n  .num:focus{ outline:none; border-color:#E5004B; box-shadow:0 0 0 3px rgba(229,0,75,.12); }\n  .num.goal{ font-weight:500; color:#4A5560; }\n  .slwrap{ position:relative; padding:14px 2px 20px; --r:9px; }\n  .track{ position:relative; height:6px; border-radius:999px; background:#EAECEF; }\n  .fill{ position:absolute; left:0; top:0; height:6px; border-radius:999px; background:linear-gradient(90deg,#E5004B,#EB6619); }\n  .rng{ position:absolute; left:0; top:8px; width:100%; height:22px; margin:0; -webkit-appearance:none; appearance:none;\n    background:transparent; cursor:pointer; z-index:3; }\n  .rng::-webkit-slider-runnable-track{ height:22px; background:transparent; }\n  .rng::-moz-range-track{ height:22px; background:transparent; }\n  .rng::-webkit-slider-thumb{ -webkit-appearance:none; appearance:none; width:18px; height:18px; border-radius:50%; margin-top:2px;\n    background:#fff; border:3px solid #E5004B; box-shadow:0 2px 5px rgba(16,24,40,.22); cursor:grab; }\n  .rng:active::-webkit-slider-thumb{ cursor:grabbing; }\n  .rng::-moz-range-thumb{ width:18px; height:18px; border-radius:50%; background:#fff; border:3px solid #E5004B; box-shadow:0 2px 5px rgba(16,24,40,.22); cursor:grab; }\n  .mk{ position:absolute; top:-3px; width:2px; height:12px; border-radius:2px; z-index:2; transform:translateX(-50%); }\n  .mk.meta{ background:#1A1C1E; }\n  .mk.prod{ background:#8B5CF6; }\n  .mklab{ position:absolute; bottom:0; transform:translateX(-50%); font:600 8.5px/1 'Roboto',sans-serif; letter-spacing:.2px;\n    white-space:nowrap; padding:1px 4px; border-radius:4px; }\n  .mklab.meta{ color:#1A1C1E; background:#EEF0F3; }\n  .mklab.prod{ color:#6D28D9; background:#F1EBFF; }\n  .actions{ display:flex; gap:12px; align-items:center; margin-top:4px; flex-wrap:wrap; }\n  .btn{ height:46px; padding:0 22px; border:none; border-radius:12px; cursor:pointer; color:#fff;\n    background:linear-gradient(135deg,#E5004B 0%,#EB6619 100%); font:700 14px/1 'Roboto',sans-serif;\n    display:inline-flex; align-items:center; gap:9px; box-shadow:0 4px 12px rgba(229,0,75,.24);\n    transition:transform 150ms ease-out,box-shadow 150ms ease-out; }\n  .btn:hover{ transform:translateY(-1px); box-shadow:0 6px 16px rgba(229,0,75,.30); }\n  .btn[disabled]{ opacity:.6; cursor:default; transform:none; box-shadow:none; }\n  .btn.ghost{ background:#fff; color:#4A5560; border:1px solid rgba(16,24,40,0.14); box-shadow:none; }\n  .btn.ghost:hover{ background:#FAFAFB; border-color:rgba(16,24,40,0.24); }\n  .hint{ font:400 12px/1.4 'Roboto',sans-serif; color:#9AA1AC; }\n  .autotag{ display:inline-flex; align-items:center; gap:6px; font:600 11px/1 'Roboto',sans-serif; color:#6B7280; }\n  .autotag .spin{ width:14px; height:14px; border:2px solid rgba(229,0,75,.2); border-top-color:#E5004B; border-radius:50%;\n    display:inline-block; animation:spin 700ms linear infinite; }\n  .err{ background:#FFF1F1; border:1px solid #FFD2D2; color:#C4001D; border-radius:10px; padding:10px 12px;\n    font:500 12px/1.4 'Roboto',sans-serif; margin-top:12px; }\n  .res .big{ display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; }\n  .res .rlbl{ font:600 11px/1 'Roboto',sans-serif; letter-spacing:.6px; text-transform:uppercase; color:#6B7280; }\n  .res .money{ font:800 40px/1 'Roboto',sans-serif; letter-spacing:-1px; color:#29AC56; transition:color 150ms ease-out; }\n  .res .delta{ font:700 13px/1 'Roboto',sans-serif; padding:3px 9px; border-radius:999px; }\n  .res .delta.up{ background:rgba(41,172,86,.12); color:#1F8A45; } .res .delta.down{ background:rgba(255,20,24,.10); color:#D01418; }\n  .res .delta.flat{ background:#F1F3F6; color:#6B7280; }\n  .res .subline{ margin-top:6px; font:400 12px/1.4 'Roboto',sans-serif; color:#6B7280; }\n  .pill{ display:inline-flex; align-items:center; gap:5px; padding:3px 9px; border-radius:999px; font:600 11px/1 'Roboto',sans-serif; }\n  .pill.g{ background:rgba(41,172,86,.12); color:#1F8A45; } .pill.a{ background:rgba(250,160,0,.14); color:#B57200; }\n  .pill.r{ background:rgba(255,20,24,.10); color:#D01418; } .pill.n{ background:#F1F3F6; color:#6B7280; }\n  .bd{ margin-top:16px; }\n  .bd .sub{ display:flex; align-items:center; gap:8px; font:700 11px/1 'Roboto',sans-serif; letter-spacing:.5px;\n    text-transform:uppercase; color:#6B7280; margin:16px 0 10px; }\n  table.kp{ width:100%; border-collapse:collapse; }\n  table.kp th{ text-align:right; font:600 10px/1 'Roboto',sans-serif; letter-spacing:.4px; text-transform:uppercase;\n    color:#9AA1AC; padding:6px 8px; border-bottom:1px solid rgba(16,24,40,0.08); }\n  table.kp th:first-child{ text-align:left; }\n  table.kp td{ padding:9px 8px; border-bottom:1px solid rgba(16,24,40,0.05); font:500 13px/1.2 'Roboto',sans-serif; text-align:right; }\n  table.kp td:first-child{ text-align:left; }\n  table.kp td.nm{ display:flex; align-items:center; gap:8px; }\n  table.kp td.nm .bmk, table.kp td.nm svg{ flex:0 0 auto; }\n  table.kp td.sim{ font-weight:700; color:#1A1C1E; }\n  .comp{ display:flex; flex-wrap:wrap; gap:10px; }\n  .compc{ flex:1 1 160px; background:#FAFAFB; border:1px solid rgba(16,24,40,0.06); border-radius:12px; padding:12px 14px; }\n  .compc .cl{ font:600 10px/1 'Roboto',sans-serif; letter-spacing:.4px; text-transform:uppercase; color:#9AA1AC; }\n  .compc .cv{ font:700 18px/1.1 'Roboto',sans-serif; margin-top:5px; color:#1A1C1E; }\n  .bon{ display:flex; flex-direction:column; gap:8px; }\n  .bonr{ display:flex; align-items:center; justify-content:space-between; gap:12px; padding:11px 13px;\n    border:1px solid rgba(16,24,40,0.08); border-radius:12px; background:#fff; }\n  .bonr .bl{ display:flex; align-items:center; gap:9px; min-width:0; }\n  .bonr .bnm{ font:600 13px/1.2 'Roboto',sans-serif; color:#1A1C1E; }\n  .bonr .bva{ font:700 14px/1 'Roboto',sans-serif; }\n  .rt{ display:flex; flex-direction:column; gap:8px; }\n  .rt .cap{ font:500 12px/1.4 'Roboto',sans-serif; color:#6B7280; margin:-4px 0 6px; }\n  .rt .tgrp{ border:1px solid rgba(16,24,40,0.08); border-radius:13px; overflow:hidden; margin-bottom:12px; }\n  .rt .tgh{ display:flex; align-items:center; gap:9px; padding:11px 13px; background:#FAFAFB; border-bottom:1px solid rgba(16,24,40,0.07); }\n  .rt .tgh .tnm{ font:700 13px/1.2 'Roboto',sans-serif; color:#1A1C1E; }\n  .rt .tgh .tbadge{ font:600 10px/1 'Roboto',sans-serif; letter-spacing:.4px; text-transform:uppercase; color:#9AA1AC;\n    padding:3px 8px; border-radius:999px; background:#F1F3F6; }\n  .rt .tgh .spacer{ flex:1 1 auto; }\n  .rt .tgh .idxv{ font:700 11px/1 'Roboto',sans-serif; color:#6D28D9; background:#F1EBFF; padding:4px 9px; border-radius:999px; }\n  table.faixa{ width:100%; border-collapse:collapse; }\n  table.faixa th{ text-align:left; font:600 9.5px/1 'Roboto',sans-serif; letter-spacing:.4px; text-transform:uppercase;\n    color:#9AA1AC; padding:7px 13px; border-bottom:1px solid rgba(16,24,40,0.06); background:#fff; }\n  table.faixa th:last-child{ text-align:right; }\n  table.faixa td{ padding:9px 13px; border-bottom:1px solid rgba(16,24,40,0.04); font:500 13px/1.2 'Roboto',sans-serif; color:#1A1C1E; }\n  table.faixa td:last-child{ text-align:right; font-weight:700; }\n  table.faixa tr:last-child td{ border-bottom:none; }\n  table.faixa tr.hot td{ background:rgba(229,0,75,.07); }\n  table.faixa tr.hot td:first-child{ box-shadow:inset 3px 0 0 #E5004B; font-weight:700; }\n  .youmark{ display:inline-flex; align-items:center; gap:5px; margin-left:8px; font:700 10px/1 'Roboto',sans-serif;\n    color:#E5004B; background:#FFE9F0; padding:3px 8px; border-radius:999px; vertical-align:middle; white-space:nowrap; }\n  .parcela{ display:flex; flex-wrap:wrap; gap:8px; margin-top:4px; }\n  .parcela .pc{ flex:1 1 200px; background:#F7F3FF; border:1px solid rgba(109,40,217,.16); border-radius:12px; padding:11px 13px; }\n  .parcela .pc .pcl{ font:600 10px/1 'Roboto',sans-serif; letter-spacing:.4px; text-transform:uppercase; color:#8B5CF6; }\n  .parcela .pc .pcv{ font:700 15px/1.2 'Roboto',sans-serif; color:#1A1C1E; margin-top:5px; }\n  .parcela .pc .pcf{ font:500 11px/1.4 'Roboto',sans-serif; color:#6B7280; margin-top:3px; }\n  .empty{ text-align:center; padding:34px 10px; color:#9AA1AC; }\n  .loadrow{ display:flex; align-items:center; gap:10px; padding:16px 4px; color:#6B7280; font:500 13px/1 'Roboto',sans-serif; }\n  .spin{ width:20px; height:20px; border:2.5px solid rgba(229,0,75,.18); border-top-color:#E5004B; border-radius:50%;\n    display:inline-block; animation:spin 700ms linear infinite; vertical-align:middle; }\n  @keyframes spin{ to{ transform:rotate(360deg); } }\n  @media (max-width:640px){ .grid{ grid-template-columns:1fr; } .res .money{ font-size:32px; } .tbttl{ display:none; } }\n  @media (prefers-reduced-motion:reduce){ .btn,.num,.sel,.rng,.backbtn,.res .money{ transition:none; } .btn:hover{ transform:none; } .spin,.autotag .spin{ animation:none; } }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const st = d2.state;\n    if(st.rede==null){\n      // Initialize from the CURRENT view context (launcher → query/shared) — no more 20200/lider pin.\n      const ctx = readSimContext(d2);\n      const ctxPerfil = ctx.perfil || '';\n      // Engine only simulates lider|gn. A GV (or unknown) context keeps its structure selected\n      // but defaults perfil to lider and does NOT auto-load (the selector drives — no 20200 pin).\n      const knownPerfil = (ctxPerfil==='lider' || ctxPerfil==='gn');\n      st.perfil = knownPerfil ? ctxPerfil : 'lider';\n      st.autoLoadOnMount = knownPerfil;\n      st.rede = ctx.rede || 'rede1';\n      st.nivel = 'diamante';\n      // Cycle: context → resolved display cycle (202610) fallback.\n      st.cycle = ctx.cycle || (d2.param('defaultCycle','') || '202610') || '202610';\n      // Group/structure: context → (only if absent) the instance default. GV opens with its default sector.\n      st.group = ctx.structureCode || String(d2.param('defaultGroup','') || '');\n      st.gvName = ctx.gvName || '';\n      st.inputs={}; st.goals={}; st.baseline={}; st.baselineGoal={};\n      st.result=null; st.baseRemuneracao=null; st.loading=false; st.error=null;\n      st.autoLoading=false; st.loadError=null; st.groupLoaded=false;\n      st.cycleList=null;\n    }\n    const rede = st.rede, fl = fields(st.perfil, rede);\n    // Cycle selector options: real seeded cycles (loaded in mounted) → fall back to param/context cycle.\n    const cycles = (Array.isArray(st.cycleList) && st.cycleList.length)\n      ? st.cycleList\n      : (d2.param('cycles', null) || [st.cycle || '202610']);\n    const groups = d2.param('groups', []) || [];\n\n    const opt = (v,cur,txt)=>`<option value=\"${esc(v)}\"${String(v)===String(cur)?' selected':''}>${esc(txt)}</option>`;\n    // End user (token session): only their own structure is offered — the server enforces the same scope.\n    let tokenUser = false; try{ const ns = JSON.parse(window.localStorage.getItem('_d2_natura_session') || 'null'); tokenUser = !!(ns && ns.token); }catch(e){}\n    const groupList = tokenUser ? [] : (Array.isArray(groups)?groups:[]).slice();\n    // Ensure the current context structure is a selectable option even if it isn't in the static list.\n    if(st.group && !groupList.some(g=>String((g&&g.code!=null)?g.code:g)===String(st.group))){\n      const lbl = (st.perfil==='gn' ? 'Setor ' : 'Grupo ') + st.group + (st.gvName?(' · '+st.gvName):'');\n      groupList.unshift({ code: st.group, name: lbl });\n    }\n    const groupOpts = `${opt('', st.group, '— Manual (sem grupo) —')}` + groupList.map(g=>{\n      const code=(g&&g.code!=null)?g.code:g; const nm=(g&&g.name)?g.name:('Grupo '+code); return opt(code, st.group, nm);\n    }).join('');\n    const groupSel = `<select class=\"sel\" data-k=\"group\">${groupOpts}</select>`;\n    const perfilSel = `<select class=\"sel\" data-k=\"perfil\">${opt('lider',st.perfil,'Líder')}${opt('gn',st.perfil,'GN')}</select>`;\n    const redeSel = `<select class=\"sel\" data-k=\"rede\">${opt('rede1',st.rede,'Rede 1')}${opt('rede2',st.rede,'Rede 2')}</select>`;\n    const nivelSel = `<select class=\"sel\" data-k=\"nivel\">${opt('prata',st.nivel,'Prata')}${opt('ouro',st.nivel,'Ouro')}${opt('diamante',st.nivel,'Diamante')}</select>`;\n    const cycOpts = (Array.isArray(cycles)?cycles:[cycles]).map(c=>{ const code=(c&&c.code!=null)?c.code:c; return opt(code,st.cycle,'Ciclo '+code); }).join('');\n    const cycleSel = `<select class=\"sel\" data-k=\"cycle\">${cycOpts}</select>`;\n\n    const inpVal = (k)=>{ const v = st.inputs[k]; return (v==null?'':v); };\n    const goalVal = (k)=>{ const v = st.goals[k]; return (v==null?'':v); };\n\n    const kpiCards = fl.map(f=>{\n      const code = f.code;\n      const val = st.inputs[code];\n      const goal = f.goalKey ? st.goals[f.goalKey] : null;\n      const baseline = st.baseline[code];\n      const fx = { value: val, goal: goal, baseline: baseline, brand: f.brand };\n      const max = sliderMax(fx);\n      const v = Number(val)||0;\n      const g = (goal!=null && isFinite(Number(goal))) ? Number(goal) : null;\n      const at = (g && g>0) ? (v/g*100) : null;\n      const atCls = pctClass(at);\n      const fillPct = Math.max(0, Math.min(100, (v/max)*100));\n      const metaPct = (g!=null) ? Math.max(0, Math.min(100,(g/max)*100)) : null;\n      const prodPct = (baseline!=null) ? Math.max(0, Math.min(100,(Number(baseline)/max)*100)) : null;\n      const goalCell = f.goalKey ? `<div class=\"inbox\"><span class=\"t\">Meta</span>\n        <input class=\"num goal\" type=\"number\" inputmode=\"numeric\" data-goal=\"${esc(f.goalKey)}\" value=\"${esc(goalVal(f.goalKey))}\" placeholder=\"0\"/></div>` : '';\n      const realLbl = f.goalKey ? 'Realizado (simulado)' : 'Valor (simulado)';\n      const mkLeft = (p)=>`calc(var(--r) + (${p}/100)*(100% - 2*var(--r)))`;\n      const markers = `\n        ${metaPct!=null?`<div class=\"mk meta\" style=\"left:${mkLeft(metaPct)}\"></div><div class=\"mklab meta\" style=\"left:${mkLeft(metaPct)}\">Meta ${num(g)}</div>`:''}\n        ${prodPct!=null?`<div class=\"mk prod\" style=\"left:${mkLeft(prodPct)}\"></div><div class=\"mklab prod\" style=\"left:${mkLeft(prodPct)}\">Realizado ${num(baseline)}</div>`:''}`;\n      const atChip = (at!=null) ? `<span class=\"atchip ${atCls}\" data-atchip=\"${esc(code)}\">${pct(at)}</span>` : `<span class=\"atchip n\" data-atchip=\"${esc(code)}\">—</span>`;\n      return `<div class=\"kpi\" data-key=\"k-${esc(code)}\">\n        <div class=\"krow\">\n          <div class=\"kicon\">${fieldIcon(t,f)}</div>\n          <span class=\"knm\">${esc(f.label)}</span>\n          ${atChip}\n        </div>\n        <div class=\"inps\">\n          <div class=\"inbox\"><span class=\"t\">${realLbl}</span>\n            <input class=\"num real\" type=\"number\" inputmode=\"numeric\" data-code=\"${esc(code)}\" data-max=\"${max}\" value=\"${esc(inpVal(code))}\" placeholder=\"0\"/></div>\n          ${goalCell}\n        </div>\n        <div class=\"slwrap\" data-slwrap=\"${esc(code)}\">\n          <div class=\"track\"><div class=\"fill\" data-fill=\"${esc(code)}\" style=\"width:${fillPct}%\"></div></div>\n          <input class=\"rng\" type=\"range\" min=\"0\" max=\"${max}\" step=\"${f.brand&&rede==='rede2'?'100':'1'}\" value=\"${v}\" data-rng=\"${esc(code)}\" data-max=\"${max}\"/>\n          ${markers}\n        </div>\n      </div>`;\n    }).join('');\n\n    const indRows = fl.map(f=>{\n      const code=f.code;\n      const sim = st.inputs[code];\n      const goal = f.goalKey ? st.goals[f.goalKey] : null;\n      const baseline = st.baseline[code];\n      const simN = Number(sim)||0;\n      const gN = (goal!=null&&isFinite(Number(goal)))?Number(goal):null;\n      const at = (gN&&gN>0)?(simN/gN*100):null;\n      const atCls = pctClass(at);\n      const pseudoStat = { brand:f.brand, icon:(f.brand?('brand-'+f.brand):(f.ic||'target')), status:(at!=null?(at>=100?'green':(at>=80?'amber':'red')):'none') };\n      const ico = statIcon(t, pseudoStat);\n      const atv = (at!=null)?`<span class=\"pill ${atCls}\">${pct(at)}</span>`:'—';\n      return `<tr data-key=\"ind-${esc(code)}\"><td class=\"nm\">${ico}${esc(f.label)}</td>\n        <td>${baseline!=null?num(baseline):'—'}</td>\n        <td>${gN!=null?num(gN):'—'}</td>\n        <td class=\"sim\" data-simcell=\"${esc(code)}\">${num(sim)}</td>\n        <td data-atcell=\"${esc(code)}\">${atv}</td></tr>`;\n    }).join('');\n    const indicatorTable = `<div class=\"card\">\n      <div class=\"ct\">${icon('sliders', t.color.muted, 15)} Indicadores — Realizado · Meta · Simulado<span class=\"spacer\"></span>\n        ${st.autoLoading?'<span class=\"autotag\"><span class=\"spin\"></span> Carregando grupo…</span>':''}</div>\n      ${st.loadError?`<div class=\"err\">${esc(st.loadError)}</div>`:''}\n      <table class=\"kp\"><thead><tr><th>Indicador</th><th>Realizado</th><th>Meta</th><th>Simulado</th><th>Atingimento</th></tr></thead>\n      <tbody>${indRows}</tbody></table></div>`;\n\n    let resultHtml = '';\n    if(st.error){ resultHtml = `<div class=\"card\"><div class=\"err\">${esc(st.error)}</div></div>`; }\n    else if(st.result){\n      const r = st.result; const bd = r.breakdown||{}; const comp = bd.components||{};\n      const stats = (r.stats||[]);\n      const base = st.baseRemuneracao;\n      let deltaHtml = '';\n      if(base!=null){\n        const d = (Number(r.remuneracao)||0) - (Number(base)||0);\n        if(d>0.5) deltaHtml = `<span class=\"delta up\">+${brl(d)} vs. grupo</span>`;\n        else if(d<-0.5) deltaHtml = `<span class=\"delta down\">${brl(d)} vs. grupo</span>`;\n        else deltaHtml = `<span class=\"delta flat\">= remuneração do grupo</span>`;\n      }\n      const kpTable = stats.filter(s=>!s.isBonus).map(s=>{\n        const cls = s.status==='green'?'g':(s.status==='amber'?'a':(s.status==='red'?'r':'n'));\n        const atv = (s.atingimento==null)?'—':`<span class=\"pill ${cls}\">${pct(s.atingimento)}</span>`;\n        const brandIco = statIcon(t, s);\n        return `<tr data-key=\"rst-${esc(s.indexCode)}\"><td class=\"nm\">${brandIco}${esc(s.label)}</td>\n          <td>${num(s.value)}</td><td>${s.goal!=null?num(s.goal):'—'}</td><td>${atv}</td></tr>`;\n      }).join('');\n      const compCards = `\n        <div class=\"compc\"><div class=\"cl\">Componente Natura</div><div class=\"cv\">${brl(comp.natura)}</div></div>\n        <div class=\"compc\"><div class=\"cl\">Componente Avon</div><div class=\"cv\">${brl(comp.avon)}</div></div>\n        <div class=\"compc\"><div class=\"cl\">Base de remuneração</div><div class=\"cv\">${brl(comp.remunBase)}</div></div>\n        <div class=\"compc\"><div class=\"cl\">Total bônus</div><div class=\"cv\">${brl(comp.bonusTotal)}</div></div>`;\n      const bonuses = (r.bonuses||[]);\n      const bonHtml = bonuses.length ? bonuses.map(b=>{\n        const wr = !!b.willReceive;\n        return `<div class=\"bonr\" data-key=\"bn-${esc(b._id||b.bonusType)}\">\n          <div class=\"bl\">${icon('gift', wr?t.color.money:t.color.muted, 18)}\n            <span class=\"bnm\">${esc(b.label||b.bonusType)}</span>\n            <span class=\"pill ${wr?'g':'n'}\">${wr?'Recebe':'Não recebe'}</span></div>\n          <span class=\"bva\" style=\"color:${wr?'#29AC56':'#9AA1AC'}\">${brl(b.amount)}</span>\n        </div>`;\n      }).join('') : `<div class=\"hint\">Nenhum bônus configurado para este perfil/rede.</div>`;\n\n      resultHtml = `<div class=\"card res\">\n        <div class=\"ct\">${icon('money', t.color.money, 15)} Resultado da simulação\n          <span class=\"spacer\"></span>${st.loading?'<span class=\"autotag\"><span class=\"spin\"></span> Recalculando…</span>':''}</div>\n        <div class=\"big\">\n          <span class=\"rlbl\">Remuneração estimada</span>\n          <span class=\"money\" data-money=\"1\">${brl(r.remuneracao)}</span>\n          ${deltaHtml}\n        </div>\n        <div class=\"subline\">${esc(r.rede==='rede2'?'Rede 2':'Rede 1')} · nível ${esc(r.nivel||'')} · ciclo ${esc(r.cycle||'')} · ${comp.structured?'fórmula estruturada':'cálculo nativo'} · ruleset v${esc(r.rulesetVersion||'')}</div>\n        <div class=\"bd\">\n          <div class=\"sub\">${icon('target', t.color.muted, 15)} Atingimento por indicador (motor)</div>\n          <table class=\"kp\"><thead><tr><th>Indicador</th><th>Realizado</th><th>Meta</th><th>Atingimento</th></tr></thead>\n          <tbody>${kpTable}</tbody></table>\n          <div class=\"sub\">${icon('layers', t.color.muted, 15)} Componentes da remuneração</div>\n          <div class=\"comp\">${compCards}</div>\n          <div class=\"sub\">${icon('gift', t.color.muted, 15)} Bônus &amp; aceleradores</div>\n          <div class=\"bon\">${bonHtml}</div>\n        </div>\n      </div>`;\n    } else {\n      resultHtml = `<div class=\"card\"><div class=\"empty\">${icon('calc', '#C7CCD3', 30)}<div style=\"margin-top:8px;font:500 13px/1.4 Roboto\">Escolha um grupo (ou preencha manualmente) e ajuste os controles — a remuneração recalcula automaticamente.</div></div></div>`;\n    }\n\n    const groupTitle = st.groupLoaded && st.groupInfo ? `${esc(st.groupInfo.leaderName||('Grupo '+st.group))} · ${esc(rede==='rede2'?'Rede 2':'Rede 1')} · nível ${esc(st.nivel)}` : 'Escolha um grupo para carregar produção e metas reais.';\n\n    // ---- FIX 4b: Tabela de Remuneração (rede-aware, live highlight) ----\n    let remunTableHtml = '';\n    {\n      const bt = st.bandTables;\n      const isRede2 = (rede==='rede2');\n      const modelCaption = isRede2 ? 'Multiplicador × volume' : 'Soma de parcelas';\n      if(st.bandTablesLoading && !bt){\n        remunTableHtml = `<div class=\"card\"><div class=\"ct\">${icon('layers', t.color.muted, 15)} Tabela de Remuneração</div>\n          <div class=\"loadrow\"><span class=\"spin\"></span> Carregando faixas…</div></div>`;\n      } else if(bt && Array.isArray(bt.tables) && bt.tables.length){\n        const bd = (st.result && st.result.breakdown) ? st.result.breakdown : {};\n        const stats = (st.result && st.result.stats) ? st.result.stats : [];\n        const parcelaAcc = [];\n        const groups = bt.tables.map(tbl=>{\n          const brandsHtml = (tbl.brands||[]).map(bg=>{\n            const brand = bg.brand;\n            const rows = bg.rows||[];\n            const idx = bandIndex(tbl.ref, brand, bd, stats, tbl.kpiCode);\n            const hot = activeRow(rows, idx);\n            const rowsHtml = rows.map((r,i)=>{\n              const you = (i===hot) ? `<span class=\"youmark\">${icon('flag','#E5004B',11)} você está aqui</span>` : '';\n              return `<tr class=\"${i===hot?'hot':''}\" data-key=\"fx-${esc(tbl.ref)}-${esc(brand)}-${i}\">\n                <td>${faixaLabel(r, tbl.valueType, tbl.kpiCode)}${you}</td>\n                <td>${valorCell(r, tbl.valueType)}</td></tr>`;\n            }).join('');\n            const idxDisp = (idx!=null && isFinite(Number(idx)))\n              ? ((tbl.valueType==='multiplier') ? pct(idx) : num(idx)) : '—';\n            // accumulate parcela / component for the summary strip\n            if(hot>=0){\n              const bandVal = Number(rows[hot].value)||0;\n              if(!isRede2 && tbl.ref==='ativas-total'){ parcelaAcc.push({brand, ativas:bandVal}); }\n              if(!isRede2 && tbl.ref==='atingimento'){ const p=parcelaAcc.find(x=>x.brand===brand); if(p){ p.mult=bandVal; } }\n              if(isRede2 && tbl.ref==='pontos'){ const vol=Number(bandVolume(tbl.ref,brand,bd))||0; parcelaAcc.push({brand, mult:bandVal, vol, comp:(bandVal/100)*vol}); }\n            }\n            return `<div class=\"tgrp\">\n              <div class=\"tgh\">${brandMark(t, brand, 18)}<span class=\"tnm\">${esc(tbl.label)}</span>\n                <span class=\"tbadge\">${brand==='avon'?'Avon':'Natura'}</span><span class=\"spacer\"></span>\n                <span class=\"idxv\">${tbl.valueType==='multiplier'?'Atingimento':'Realizado'}: ${idxDisp}</span></div>\n              <table class=\"faixa\"><thead><tr><th>Faixa</th><th>Valor</th></tr></thead><tbody>${rowsHtml}</tbody></table>\n            </div>`;\n          }).join('');\n          return brandsHtml;\n        }).join('');\n\n        // Parcela / component summary strip\n        let strip = '';\n        if(!isRede2){\n          const parts = parcelaAcc.filter(p=>p.ativas!=null).map(p=>{\n            const mult = (p.mult!=null?p.mult:0);\n            const parcela = (Number(p.ativas)||0) * (mult/100);\n            return `<div class=\"pc\"><div class=\"pcl\">Parcela ${p.brand==='avon'?'Avon':'Natura'}</div>\n              <div class=\"pcv\">${brl(parcela)}</div>\n              <div class=\"pcf\">${brl(p.ativas)} × ${num(mult)}% = ${brl(parcela)}</div></div>`;\n          }).join('');\n          if(parts) strip = `<div class=\"parcela\">${parts}</div>`;\n        } else {\n          const parts = parcelaAcc.filter(p=>p.comp!=null).map(p=>{\n            return `<div class=\"pc\"><div class=\"pcl\">Componente ${p.brand==='avon'?'Avon':'Natura'}</div>\n              <div class=\"pcv\">${brl(p.comp)}</div>\n              <div class=\"pcf\">${num(p.mult)}% × ${num(p.vol)} pontos = ${brl(p.comp)}</div></div>`;\n          }).join('');\n          if(parts) strip = `<div class=\"parcela\">${parts}</div>`;\n        }\n\n        remunTableHtml = `<div class=\"card\">\n          <div class=\"ct\">${icon('layers', t.color.muted, 15)} Tabela de Remuneração<span class=\"spacer\"></span>\n            <span class=\"tbadge\">${esc(rede==='rede2'?'Rede 2':'Rede 1')}</span></div>\n          <div class=\"cap\">${esc(modelCaption)} — a faixa destacada é onde a simulação atual se encontra.</div>\n          <div class=\"rt\">${groups}</div>\n          ${strip}\n        </div>`;\n      } else if(st.result){\n        remunTableHtml = `<div class=\"card\"><div class=\"ct\">${icon('layers', t.color.muted, 15)} Tabela de Remuneração</div>\n          <div class=\"hint\">Sem faixas configuradas para este perfil/rede/nível.</div></div>`;\n      }\n    }\n\n    return `<div class=\"page\">${topbar(t)}\n    <div class=\"wrap\">\n      <div class=\"head\">\n        <div class=\"mk\">${icon('calc', '#FFFFFF', 22)}</div>\n        <div><h1>Simulador de Ganhos</h1><p>${tokenUser ? 'Arraste os indicadores e veja como fica a sua remuneração, pelo mesmo motor do painel.' : 'Carregue um grupo real, arraste os indicadores e veja a remuneração pelo mesmo motor do painel.'}</p></div>\n      </div>\n      ${tokenUser ? '' : `<div class=\"card\">\n        <div class=\"ct\">${icon('people', t.color.muted, 15)} Grupo / usuário a simular\n          <span class=\"spacer\"></span>${st.autoLoading?'<span class=\"autotag\"><span class=\"spin\"></span> Carregando…</span>':''}</div>\n        <div class=\"ctl\">\n          <div class=\"fld wide\"><span class=\"lbl\">Grupo</span>${groupSel}</div>\n          <div class=\"fld\"><span class=\"lbl\">Perfil</span>${perfilSel}</div>\n          <div class=\"fld\"><span class=\"lbl\">Rede</span>${redeSel}</div>\n          <div class=\"fld\"><span class=\"lbl\">Nível</span>${nivelSel}</div>\n          <div class=\"fld\"><span class=\"lbl\">Ciclo</span>${cycleSel}</div>\n        </div>\n        <div class=\"hint\" style=\"margin-top:10px\">${groupTitle}</div>\n      </div>`}\n      ${indicatorTable}\n      <div class=\"card\">\n        <div class=\"ct\">${icon('receipt', t.color.muted, 15)} Ajuste os indicadores — ${esc(rede==='rede2'?'Rede 2':'Rede 1')}</div>\n        <div class=\"grid\">${kpiCards}</div>\n        <div class=\"actions\">\n          <button class=\"btn sim\" ${st.loading?'disabled':''}>${icon('check','#fff',18)}<span>${st.loading?'Simulando…':'Simular agora'}</span></button>\n          <button class=\"btn ghost reset\">Restaurar realizado</button>\n          <span class=\"hint\">Recalcula automaticamente (~500ms) pelo endpoint pilotSimulate, sem cache.</span>\n        </div>\n      </div>\n      ${resultHtml}\n      ${remunTableHtml}\n    </div></div>`;\n  },\n  mounted(d2){\n    const st = d2.state;\n    let debTimer = null;\n    let simSeq = 0;\n\n    function goBack(){\n      const ref = d2.param('backRef','T1Koa6_rMuQPmA9nSCIk1');\n      const inPreview = /\\/preview\\//.test((typeof location!=='undefined' && location.pathname) || '');\n      try{\n        if(inPreview && typeof location!=='undefined'){ location.href='/preview/'+ref; return; }\n        // back to the dashboard URL the launcher saved; history + popstate drive the router\n        let back = ''; try{ back = window.sessionStorage.getItem('pilotReturnUrl') || ''; }catch(e){}\n        history.pushState({}, '', back || '/'); window.dispatchEvent(new PopStateEvent('popstate')); return;\n        if(typeof location!=='undefined'){ location.href='/preview/'+ref; }\n      }catch(err){ d2.log('back nav error', err); if(typeof location!=='undefined'){ location.href='/preview/'+ref; } }\n    }\n    d2.on('.backbtn','click', goBack);\n\n    function buildPayload(){\n      const fl = fields(st.perfil, st.rede);\n      const inputs = {}; const goals = {};\n      fl.forEach(f=>{\n        const v = st.inputs[f.code];\n        if(v!=null && v!=='' && isFinite(Number(v))) inputs[f.code] = Number(v);\n        if(f.goalKey){ const gv = st.goals[f.goalKey]; if(gv!=null && gv!=='' && isFinite(Number(gv))) goals[f.goalKey] = Number(gv); }\n      });\n      inputs.goals = goals;\n      return { perfil: st.perfil, rede: st.rede, nivel: st.nivel, cycle: st.cycle, inputs: inputs };\n    }\n\n    async function runSimulate(){\n      const seq = ++simSeq;\n      st.loading = true; st.error = null; d2.refresh();\n      try{\n        const res = await d2.rush('pilotSimulate').invoke(buildPayload());\n        if(seq !== simSeq) return;\n        const body = (res && res.data && res.data.data) ? res.data.data : (res && res.data ? res.data : res);\n        if(!body || body.remuneracao==null){ st.error = 'Resposta inesperada do simulador.'; }\n        else { st.result = body; loadBandTables(body); }\n      }catch(err){\n        if(seq !== simSeq) return;\n        st.error = 'Falha ao simular: ' + (err && err.message ? err.message : String(err));\n      }finally{\n        if(seq === simSeq){ st.loading = false; d2.refresh(); }\n      }\n    }\n    function scheduleSimulate(){ if(debTimer) clearTimeout(debTimer); debTimer = setTimeout(runSimulate, 500); }\n\n    async function loadBandTables(body){\n      const rv = (body && body.rulesetVersion!=null) ? body.rulesetVersion : 1;\n      const rede = (body && body.rede) ? body.rede : st.rede;\n      const nivel = (body && body.nivel) ? body.nivel : st.nivel;\n      const perfil = (body && body.perfil) ? body.perfil : st.perfil;\n      const sig = `${rv}|${rede}|${nivel}|${perfil}`;\n      if(st.bandTables && st.bandTablesSig===sig) return; // static per ruleset — no re-fetch needed\n      st.bandTablesLoading = true; d2.refresh();\n      try{\n        const res = await d2.rush('pilotBandTables').invoke({ rulesetVersion: rv, rede: rede, nivel: nivel, perfil: perfil });\n        const bt = (res && res.data && res.data.data) ? res.data.data : (res && res.data ? res.data : res);\n        if(bt && Array.isArray(bt.tables)){ st.bandTables = bt; st.bandTablesSig = sig; }\n      }catch(err){ d2.log('bandTables load error', err); }\n      finally{ st.bandTablesLoading = false; d2.refresh(); }\n    }\n\n    async function loadGroup(){\n      const code = st.group;\n      if(!code){ st.groupLoaded=false; st.groupInfo=null; st.baseRemuneracao=null; d2.refresh(); return; }\n      st.autoLoading = true; st.loadError = null; d2.refresh();\n      try{\n        const res = await d2.rush('pilotGetGroupEarnings').invoke({ structureCode: code, cycle: st.cycle, perfil: st.perfil, rede: st.rede });\n        const body = (res && res.data && res.data.data) ? res.data.data : (res && res.data ? res.data : res);\n        if(!body || body.remuneracao==null){ st.loadError = 'Resposta inesperada ao carregar o grupo.'; return; }\n        if(body.perfil) st.perfil = body.perfil;\n        if(body.rede) st.rede = body.rede;\n        if(body.nivel) st.nivel = body.nivel;\n        st.groupInfo = { leaderName: body.leaderName || body.name };\n        st.baseRemuneracao = Number(body.remuneracao)||0;\n        const goalKeyByCode = (st.rede==='rede2') ?\n          {'481':'goalBillingNatura','486':'goalBillingAvon','469':'goalsPointsNatura','472':'goalsPointsAvon'} :\n          {'545':'goalActivesNaturaExclusive','546':'goalActivesAvonExclusive','28':'goalActive'};\n        const inputs = {}; const goals = {}; const baseline = {}; const baselineGoal = {};\n        (body.stats||[]).forEach(s=>{\n          if(s.isBonus) return;\n          const c = s.indexCode;\n          if(s.value!=null){ inputs[c] = Number(s.value); baseline[c] = Number(s.value); }\n          const gk = goalKeyByCode[c];\n          if(gk && s.goal!=null){ goals[gk] = Number(s.goal); baselineGoal[gk] = Number(s.goal); }\n        });\n        st.inputs = inputs; st.goals = goals; st.baseline = baseline; st.baselineGoal = baselineGoal;\n        st.groupLoaded = true;\n      }catch(err){\n        st.loadError = 'Falha ao carregar grupo: ' + (err && err.message ? err.message : String(err));\n      }finally{\n        st.autoLoading = false; d2.refresh();\n        if(st.groupLoaded) runSimulate();\n      }\n    }\n\n    function syncLive(code, val){\n      const v = Number(val)||0;\n      const numEl = d2.$(`.num.real[data-code=\"${code}\"]`);\n      if(numEl && document.activeElement!==numEl) numEl.value = String(v);\n      const rng = d2.$(`.rng[data-rng=\"${code}\"]`);\n      const max = rng ? Number(rng.getAttribute('data-max'))||1 : 1;\n      const fill = d2.$(`.fill[data-fill=\"${code}\"]`);\n      if(fill) fill.style.width = Math.max(0,Math.min(100,(v/max)*100))+'%';\n      const goalKeyByCode = (st.rede==='rede2') ?\n        {'481':'goalBillingNatura','486':'goalBillingAvon','469':'goalsPointsNatura','472':'goalsPointsAvon'} :\n        {'545':'goalActivesNaturaExclusive','546':'goalActivesAvonExclusive','28':'goalActive'};\n      const gk = goalKeyByCode[code];\n      const g = gk ? Number(st.goals[gk]) : null;\n      const at = (g && g>0) ? (v/g*100) : null;\n      const chip = d2.$(`[data-atchip=\"${code}\"]`);\n      if(chip){ chip.className = 'atchip ' + pctClass(at); chip.textContent = at!=null ? pct(at) : '—'; }\n      const simCell = d2.$(`[data-simcell=\"${code}\"]`);\n      if(simCell) simCell.textContent = num(v);\n      const atCell = d2.$(`[data-atcell=\"${code}\"]`);\n      if(atCell) atCell.innerHTML = at!=null ? `<span class=\"pill ${pctClass(at)}\">${pct(at)}</span>` : '—';\n    }\n\n    d2.on('.sel','change',(e,el)=>{\n      const k = el.getAttribute('data-k'); if(!k) return;\n      st[k] = el.value;\n      if(k==='group'){ loadGroup(); return; }\n      if(k==='rede' || k==='perfil'){\n        // perfil/rede switch changes the whole indicator set — reset and reload.\n        st.inputs={}; st.goals={}; st.baseline={}; st.baselineGoal={}; st.result=null; st.error=null;\n        st.groupLoaded=false; st.baseRemuneracao=null; st.bandTables=null; st.bandTablesSig=null;\n        if(st.group){ loadGroup(); return; }\n        d2.refresh(); return;\n      }\n      if(k==='cycle'){ if(st.group){ loadGroup(); return; } }\n      d2.refresh();\n      scheduleSimulate();\n    });\n\n    d2.on('.rng','input',(e,el)=>{\n      const code = el.getAttribute('data-rng'); if(!code) return;\n      const v = Number(el.value);\n      if(!st.inputs) st.inputs={};\n      st.inputs[code] = v;\n      syncLive(code, v);\n      scheduleSimulate();\n    });\n\n    d2.on('.num','input',(e,el)=>{\n      const code = el.getAttribute('data-code');\n      const goal = el.getAttribute('data-goal');\n      const v = el.value===''? null : Number(el.value);\n      if(!st.inputs) st.inputs={}; if(!st.goals) st.goals={};\n      if(code!=null){\n        st.inputs[code]=v;\n        const rng = d2.$(`.rng[data-rng=\"${code}\"]`);\n        if(rng){ const max=Number(rng.getAttribute('data-max'))||1; rng.value = String(Math.max(0,Math.min(max, Number(v)||0))); }\n        syncLive(code, v||0);\n        scheduleSimulate();\n      } else if(goal!=null){\n        st.goals[goal]=v;\n        scheduleSimulate();\n      }\n    });\n\n    d2.on('.sim','click', ()=>{ if(debTimer) clearTimeout(debTimer); runSimulate(); });\n    d2.on('.reset','click', ()=>{\n      if(st.groupLoaded){\n        st.inputs = {...st.baseline}; st.goals = {...st.baselineGoal}; d2.refresh(); scheduleSimulate();\n      } else {\n        st.inputs = {}; st.goals = {}; st.result=null; d2.refresh();\n      }\n    });\n\n    async function loadCycleList(){\n      try{\n        const ds = d2.data('pilot-cycleDataSet');\n        if(!ds) return;\n        let rows = ds.records();\n        if(!rows || !rows.length){ rows = await ds.loadAll(); }\n        if(Array.isArray(rows) && rows.length){\n          st.cycleList = rows.map(r=>({ code:String(r.code), name:('Ciclo '+r.code) }))\n            .sort((a,b)=> a.code<b.code?-1:(a.code>b.code?1:0));\n          d2.refresh();\n        }\n      }catch(err){ d2.log('cycle list load error', err); }\n    }\n    loadCycleList();\n\n    if(st.group && st.autoLoadOnMount!==false) loadGroup(); else d2.refresh();\n  }\n};"}},"cycles":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cycles"}}}},"defaultCycle":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"defaultCycle"}}}},"groups":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"groups"}}}},"defaultGroup":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"defaultGroup"}}}},"backRef":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"backRef"}}}}}}}}}},{"_id":"6a4ceaa06c020b3085c1e987","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotSimuladorLauncher","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"function icon(name, color, size){\n  const s = size||20; const c = color||'#FFFFFF';\n  const A = `xmlns=\"http://www.w3.org/2000/svg\" width=\"${s}\" height=\"${s}\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"${c}\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\"`;\n  const P = {\n    calc:`<rect x=\"4\" y=\"2\" width=\"16\" height=\"20\" rx=\"2\"/><line x1=\"8\" y1=\"6\" x2=\"16\" y2=\"6\"/><line x1=\"8\" y1=\"11\" x2=\"8\" y2=\"11\"/><line x1=\"12\" y1=\"11\" x2=\"12\" y2=\"11\"/><line x1=\"16\" y1=\"11\" x2=\"16\" y2=\"11\"/><line x1=\"8\" y1=\"15\" x2=\"8\" y2=\"15\"/><line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"15\"/><line x1=\"16\" y1=\"15\" x2=\"16\" y2=\"18\"/>`\n  };\n  return `<svg ${A}>${P[name]||''}</svg>`;\n}\nconst FAB_CSS = `\n  :host{ display:block; }\n  .fab{ position:fixed; right:24px; bottom:24px; z-index:9999; height:52px; padding:0 20px 0 18px;\n    display:inline-flex; align-items:center; gap:10px; border:none; border-radius:999px; cursor:pointer;\n    color:#fff; background:linear-gradient(135deg,#E5004B 0%,#EB6619 100%); font:700 14px/1 'Roboto',system-ui,sans-serif;\n    box-shadow:0 6px 18px rgba(229,0,75,.34); transition:transform 150ms ease-out,box-shadow 150ms ease-out; }\n  .fab:hover{ transform:translateY(-2px); box-shadow:0 10px 24px rgba(229,0,75,.40); }\n  @media (prefers-reduced-motion:reduce){ .fab{ transition:none; } .fab:hover{ transform:none; } }\n  @media (max-width:640px){ .fab{ right:16px; bottom:16px; height:46px; padding:0 16px 0 14px; font-size:13px; } }\n  `;\n// position:fixed breaks under a transformed ancestor (the player wraps artboards), so the\n// button lives in a <body> portal with its own shadow root; removed on unmount.\nfunction fabPortal(d2, kind, html, onClick){\n  if(typeof document === 'undefined') return;\n  const old = document.querySelector('[data-pilot-fab=\"'+kind+'\"]');\n  if(old) old.remove();\n  const host = document.createElement('div');\n  host.setAttribute('data-pilot-fab', kind);\n  const sh = host.attachShadow({ mode:'open' });\n  sh.innerHTML = '<style>'+FAB_CSS+'</style>' + html;\n  document.body.appendChild(host);\n  const b = sh.querySelector('.fab');\n  if(b) b.addEventListener('click', onClick);\n  d2.onUnmount(()=>{ host.remove(); });\n}\nexport default {\n  css: `:host{ display:none; }`,\n  render(d2){\n    return `<span class=\"fab-anchor\"></span>`;\n  },\n  mounted(d2){\n    const label = d2.param('label','Simulador');\n    const html = `<button class=\"fab\" title=\"Abrir Simulador de Ganhos\">${icon('calc','#fff',20)}<span>${label}</span></button>`;\n    const go = ()=>{\n      const ref = d2.param('artboardRef','');\n      if(!ref) return;\n      // ACCESS TRACKING (additive) — record a Simulador section view before navigating away.\n      try{\n        const sid = (typeof window!=='undefined' && window.sessionStorage) ? window.sessionStorage.getItem('pilotAccessSessionId') : '';\n        if(sid) d2.rush('pilotTrackAccess').invoke({ action:'view', sessionId: sid, section:'simulador', drillLevel:'launcher' }).catch(()=>{});\n      }catch(e){}\n      // CURRENT-CONTEXT PASS — read the live dashboard view and hand it to the Simulador screen.\n      // perfil gv → simulate the GV's default sector context; leader/gn → that entity.\n      let ctx = null;\n      try{\n        const store = d2.store('pilotDashboardStore');\n        if(store){\n          ctx = {\n            perfil: store.get('perfil',''),\n            structureCode: String(store.get('selectedGroup','') || store.get('structureCode','') || ''),\n            rede: store.get('rede',''),\n            cycle: String(store.get('cycle','') || ''),\n            gvName: store.get('gvName','')\n          };\n          d2.shared.set('pilotSimContext', ctx, {global:true});\n        }\n      }catch(e){ d2.log('sim context read error', e); }\n      // Encode context into the URL so it survives a full-page nav to the screen artboard.\n      let qs = '';\n      try{\n        if(ctx){\n          const p = [];\n          if(ctx.perfil) p.push('perfil='+encodeURIComponent(ctx.perfil));\n          if(ctx.structureCode) p.push('structureCode='+encodeURIComponent(ctx.structureCode));\n          if(ctx.rede) p.push('rede='+encodeURIComponent(ctx.rede));\n          if(ctx.cycle) p.push('cycle='+encodeURIComponent(ctx.cycle));\n          if(ctx.gvName) p.push('gvName='+encodeURIComponent(ctx.gvName));\n          if(p.length) qs = '?'+p.join('&');\n        }\n      }catch(e){}\n      const path = (typeof location!=='undefined' && location.pathname) || '';\n      const inPreview = /\\/preview\\//.test(path);\n      try{\n        if(inPreview && typeof location!=='undefined'){\n          // Isolated preview host renders ONE artboard by ref — hop to the sibling preview route.\n          location.href = '/preview/'+ref+qs; return;\n        }\n        // d2.router().goTo() does not navigate from this component in the player — drive the\n        // browser router via history + popstate, remembering the dashboard URL (keeps ?token).\n        try{ window.sessionStorage.setItem('pilotReturnUrl', location.pathname + location.search); }catch(e){}\n        history.pushState({}, '', '/'+ref+qs); window.dispatchEvent(new PopStateEvent('popstate')); return;\n        if(typeof location!=='undefined'){ location.href = '/preview/'+ref+qs; }\n      }catch(err){ d2.log('launcher nav error', err); if(typeof location!=='undefined'){ location.href = '/preview/'+ref+qs; } }\n    };\n    fabPortal(d2, 'simulador', html, go);\n    // Hide the button while the dashboard shows \"Sessão inválida\" — the shell sets the flag asynchronously.\n    const syncVis = ()=>{ try{ const h = document.querySelector('[data-pilot-fab=\"simulador\"]'); if(h) h.style.display = d2.shared.get('pilotTokenInvalid', false, { global:true }) ? 'none' : ''; }catch(e){} };\n    syncVis(); const visTimer = setInterval(syncVis, 400); d2.onUnmount(()=>clearInterval(visTimer));\n  }\n};"}},"artboardRef":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"artboardRef"}}}},"label":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"label"}}}}}}}}}},{"_id":"6a4cedd991afdd4d5cd38fac","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotHistoricoScreen","package":"natura-x-piloto","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 FALLBACK_TOK = {\n  color:{ surface:'#FFFFFF', ground:'#FAFAFB', ink:'#1A1C1E', muted:'#6B7280', hairline:'rgba(16,24,40,0.08)',\n    naturaMagenta:'#E5004B', naturaOrange:'#EB6619', brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',\n    rampRed:'#FF1418', rampAmber:'#FAA000', rampGreen:'#29AC56', gold:'#F7BE00', money:'#29AC56' },\n  radius:{ sm:8, md:12, lg:16, pill:999 },\n  type:{ family:\"'Roboto',system-ui,-apple-system,sans-serif\" },\n  shadow:{ card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)', raised:'0 4px 12px rgba(16,24,40,0.10)' },\n  media:{ natura:'https://natura-x-piloto.data2.media/file/UrhVLdPDEZCXToLgJDPW8',\n    avon:'https://natura-x-piloto.data2.media/file/HqLhKqINaRUI9OSBjYGFh',\n    lockup:'https://natura-x-piloto.data2.media/file/H0P_N-7AQzQOg_VJMBWzV' }\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK_TOK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction brl(n){ const v = Number(n)||0; return v.toLocaleString('pt-BR',{ style:'currency', currency:'BRL' }); }\nfunction num(n){ const v = Number(n); return isFinite(v) ? v.toLocaleString('pt-BR',{ maximumFractionDigits:0 }) : '—'; }\nfunction pct(n){ if(n==null||!isFinite(Number(n))) return '—'; return (Number(n)).toLocaleString('pt-BR',{ maximumFractionDigits:1 })+'%'; }\n\n// Inline SVG icon set — uniform stroke style, token-colored. No emoji.\nfunction icon(name, color, size){\n  const s = size||18; const c = color||'#6B7280';\n  const A = `xmlns=\"http://www.w3.org/2000/svg\" width=\"${s}\" height=\"${s}\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"${c}\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"`;\n  const P = {\n    history:`<path d=\"M3 3v5h5\"/><path d=\"M3.05 13A9 9 0 1 0 6 5.3L3 8\"/><path d=\"M12 7v5l3 2\"/>`,\n    clock:`<circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M12 7v5l3 2\"/>`,\n    people:`<path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><path d=\"M23 21v-2a4 4 0 0 0-3-3.87\"/><path d=\"M16 3.13a4 4 0 0 1 0 7.75\"/>`,\n    target:`<circle cx=\"12\" cy=\"12\" r=\"9\"/><circle cx=\"12\" cy=\"12\" r=\"5\"/><circle cx=\"12\" cy=\"12\" r=\"1.4\"/>`,\n    crown:`<path d=\"M3 8l4 5 5-8 5 8 4-5-2 11H5L3 8z\"/>`,\n    swap:`<polyline points=\"17 2 21 6 17 10\"/><path d=\"M3 6h18\"/><polyline points=\"7 22 3 18 7 14\"/><path d=\"M21 18H3\"/>`,\n    userAdd:`<path d=\"M15 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\"/><circle cx=\"8\" cy=\"7\" r=\"4\"/><line x1=\"19\" y1=\"8\" x2=\"19\" y2=\"14\"/><line x1=\"22\" y1=\"11\" x2=\"16\" y2=\"11\"/>`,\n    receipt:`<path d=\"M5 3v18l2-1.5L9 21l2-1.5L13 21l2-1.5L17 21l2-1.5V3l-2 1.5L15 3l-2 1.5L11 3 9 4.5 7 3 5 4.5z\"/><line x1=\"8\" y1=\"8\" x2=\"16\" y2=\"8\"/><line x1=\"8\" y1=\"12\" x2=\"16\" y2=\"12\"/>`,\n    layers:`<polygon points=\"12 2 2 7 12 12 22 7 12 2\"/><polyline points=\"2 17 12 22 22 17\"/><polyline points=\"2 12 12 17 22 12\"/>`,\n    gift:`<polyline points=\"20 12 20 22 4 22 4 12\"/><rect x=\"2\" y=\"7\" width=\"20\" height=\"5\"/><line x1=\"12\" y1=\"22\" x2=\"12\" y2=\"7\"/><path d=\"M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z\"/><path d=\"M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z\"/>`,\n    money:`<line x1=\"12\" y1=\"1\" x2=\"12\" y2=\"23\"/><path d=\"M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6\"/>`,\n    trendUp:`<polyline points=\"23 6 13.5 15.5 8.5 10.5 1 18\"/><polyline points=\"17 6 23 6 23 12\"/>`,\n    trendDown:`<polyline points=\"23 18 13.5 8.5 8.5 13.5 1 6\"/><polyline points=\"17 18 23 18 23 12\"/>`,\n    dash:`<line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"/>`,\n    chevron:`<polyline points=\"9 18 15 12 9 6\"/>`,\n    back:`<polyline points=\"15 18 9 12 15 6\"/>`\n  };\n  return `<svg ${A}>${P[name]||''}</svg>`;\n}\nfunction brandMark(t, brand, size){\n  const s = size||18;\n  const src = String(brand).toLowerCase()==='avon' ? t.media.avon : t.media.natura;\n  const label = String(brand).toLowerCase()==='avon' ? 'Avon' : 'Natura';\n  return `<span class=\"bmk\" style=\"height:${s}px\"><img src=\"${esc(src)}\" alt=\"${label}\"/></span>`;\n}\n// EXACT dashboard mapping (pilotMGroupCard.svgIcon) — 16px stroke-2 glyphs.\nfunction dashIcon(iconId, color){\n  const c = color || '#6B7280';\n  const w = `width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"${c}\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"`;\n  const P = {\n    'people':`<circle cx=\"9\" cy=\"7\" r=\"3\"/><path d=\"M2 21v-2a5 5 0 0 1 5-5h4a5 5 0 0 1 5 5v2\"/><path d=\"M17 7a3 3 0 0 1 0 6\"/><path d=\"M22 21v-2a5 5 0 0 0-3-4.5\"/>`,\n    'user':`<circle cx=\"12\" cy=\"8\" r=\"3.5\"/><path d=\"M4 21v-2a5 5 0 0 1 5-5h6a5 5 0 0 1 5 5v2\"/>`,\n    'target':`<circle cx=\"12\" cy=\"12\" r=\"9\"/><circle cx=\"12\" cy=\"12\" r=\"5\"/><circle cx=\"12\" cy=\"12\" r=\"1.5\" fill=\"${c}\"/>`,\n    'crown':`<path d=\"M3 8l4 4 5-6 5 6 4-4v9H3z\"/><path d=\"M3 20h18\"/>`,\n    'swap':`<path d=\"M12 4v16\"/><path d=\"M7 8l-4 4 4 4\"/><path d=\"M17 8l4 4-4 4\"/>`,\n    'user-add':`<circle cx=\"9\" cy=\"8\" r=\"3.5\"/><path d=\"M2 20v-1.5a5 5 0 0 1 5-5h4\"/><path d=\"M18 12v6\"/><path d=\"M15 15h6\"/>`,\n    'coins':`<circle cx=\"8\" cy=\"8\" r=\"6\"/><path d=\"M18.09 10.37A6 6 0 1 1 10.34 18\"/><path d=\"M7 6h1v4\"/><path d=\"M16.71 13.88l.7.71-2.82 2.82\"/>`\n  };\n  const path = P[iconId] || `<circle cx=\"12\" cy=\"12\" r=\"3\" fill=\"${c}\" stroke=\"none\"/>`;\n  return `<svg ${w}>${path}</svg>`;\n}\n// Dashboard-parity stat icon: brand → brandMark; else the SAME svgIcon map the dashboard uses,\n// crown→gold, else status color / muted. Drives off stats[].icon and stats[].brand exactly like pilotMGroupCard.\nfunction statIcon(t, s){\n  const hasBrand = s.brand === 'natura' || s.brand === 'avon';\n  if(hasBrand) return brandMark(t, s.brand, 16);\n  const col = s.status==='green'?t.color.rampGreen:(s.status==='amber'?t.color.rampAmber:(s.status==='red'?t.color.rampRed:null));\n  const iconId = s.icon || 'target';\n  const tint = (iconId==='crown') ? t.color.gold : (col || t.color.muted || '#6B7280');\n  return dashIcon(iconId, tint);\n}\n// Sticky nav topbar + back-to-dashboard. Matches dashboard chrome (lockup + title + brand-accent back).\nfunction topbar(t){\n  return `<div class=\"topbar\">\n    <button class=\"backbtn\" title=\"Voltar ao Painel\">${icon('back','#E5004B',20)}<span>Voltar ao Painel</span></button>\n    <span class=\"lock\"><img src=\"${esc(t.media.lockup)}\" alt=\"Natura &amp; Avon\"/></span>\n    <span class=\"tbttl\">Histórico de Ganhos</span>\n    <span class=\"tbspacer\"></span>\n  </div>`;\n}\nfunction statusChip(status){\n  const s = String(status||'').toLowerCase();\n  if(s==='closed') return `<span class=\"pill n\">Fechado</span>`;\n  if(s==='open' || s==='current') return `<span class=\"pill g\">Aberto</span>`;\n  return `<span class=\"pill n\">${esc(status||'—')}</span>`;\n}\n// Inline SVG sparkline of a numeric series. Clean vector, no emoji.\nfunction sparkline(values, w, h, color){\n  const arr = (values||[]).map(v=>Number(v)||0);\n  if(arr.length < 2) return `<svg width=\"${w}\" height=\"${h}\" viewBox=\"0 0 ${w} ${h}\"></svg>`;\n  const min = Math.min.apply(null, arr), max = Math.max.apply(null, arr);\n  const span = (max - min) || 1;\n  const pad = 3;\n  const step = (w - pad*2) / (arr.length - 1);\n  const pts = arr.map((v,i)=>{\n    const x = pad + i*step;\n    const y = pad + (h - pad*2) * (1 - (v - min)/span);\n    return [x, y];\n  });\n  const d = pts.map((p,i)=> (i===0?'M':'L') + p[0].toFixed(1) + ' ' + p[1].toFixed(1)).join(' ');\n  const dots = pts.map((p,i)=>`<circle cx=\"${p[0].toFixed(1)}\" cy=\"${p[1].toFixed(1)}\" r=\"${i===pts.length-1?2.6:1.8}\" fill=\"${color}\"/>`).join('');\n  return `<svg width=\"${w}\" height=\"${h}\" viewBox=\"0 0 ${w} ${h}\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n    <path d=\"${d}\" stroke=\"${color}\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>${dots}</svg>`;\n}\n\nfunction redeLabel(r){ return r==='rede2' ? 'Rede 2' : 'Rede 1'; }\n// Read the current-view context handed over by the launcher (query first, then shared UIState).\nfunction readHistContext(d2){\n  const out = { perfil:'', structureCode:'', rede:'', cycle:'', gvName:'' };\n  try{\n    const qs = (typeof location!=='undefined' && location.search) ? location.search : '';\n    if(qs){\n      const p = new URLSearchParams(qs);\n      out.perfil = p.get('perfil') || '';\n      out.structureCode = p.get('structureCode') || '';\n      out.rede = p.get('rede') || '';\n      out.cycle = p.get('cycle') || '';\n      out.gvName = p.get('gvName') || '';\n    }\n  }catch(e){}\n  try{\n    const sh = d2.shared.get('pilotSimContext', null, {global:true});\n    if(sh){\n      if(!out.perfil) out.perfil = sh.perfil || '';\n      if(!out.structureCode) out.structureCode = String(sh.structureCode||'');\n      if(!out.rede) out.rede = sh.rede || '';\n      if(!out.cycle) out.cycle = String(sh.cycle||'');\n      if(!out.gvName) out.gvName = sh.gvName || '';\n    }\n  }catch(e){}\n  return out;\n}\n\nexport default {\n  css: `\n  :host{ display:block; min-height:100%; height:auto; background:#FAFAFB; font-family:'Roboto',system-ui,-apple-system,sans-serif; color:#1A1C1E; }\n  .page{ min-height:100%; background:#FAFAFB; }\n  *{ box-sizing:border-box; }\n  .topbar{ position:sticky; top:0; z-index:50; display:flex; align-items:center; gap:14px; height:60px; padding:0 18px;\n    background:#FFFFFF; border-bottom:1px solid rgba(16,24,40,0.08); box-shadow:0 1px 3px rgba(16,24,40,0.05); }\n  .backbtn{ display:inline-flex; align-items:center; gap:7px; height:38px; padding:0 14px 0 10px; border:1px solid rgba(229,0,75,.24);\n    border-radius:999px; background:#fff; color:#E5004B; font:700 13px/1 'Roboto',sans-serif; cursor:pointer;\n    transition:background 150ms ease-out,border-color 150ms ease-out,transform 150ms ease-out; }\n  .backbtn:hover{ background:rgba(229,0,75,.06); border-color:rgba(229,0,75,.4); transform:translateX(-1px); }\n  .backbtn:active{ transform:translateX(0); }\n  .lock{ height:28px; display:flex; align-items:center; margin-left:2px; padding-left:14px; border-left:1px solid rgba(16,24,40,0.10); }\n  .lock img{ height:100%; width:auto; display:block; }\n  .tbttl{ font:600 15px/1 'Roboto',sans-serif; color:#1A1C1E; letter-spacing:.1px; }\n  .tbspacer{ flex:1 1 auto; }\n  .wrap{ max-width:960px; margin:0 auto; padding:20px 16px 48px; }\n  .head{ display:flex; align-items:center; gap:12px; margin:0 0 18px; flex-wrap:wrap; }\n  .head .mk{ width:40px; height:40px; border-radius:12px; display:flex; align-items:center; justify-content:center;\n    background:linear-gradient(135deg,#E5004B 0%,#EB6619 100%); box-shadow:0 4px 12px rgba(229,0,75,.28); flex:0 0 40px; }\n  .head .htxt{ flex:1 1 auto; min-width:0; }\n  .head h1{ font:700 22px/1.1 'Roboto',sans-serif; margin:0; letter-spacing:-.2px; }\n  .head p{ margin:2px 0 0; font:400 12px/1.3 'Roboto',sans-serif; color:#6B7280; }\n  .card{ background:#FFFFFF; border:1px solid rgba(16,24,40,0.08); border-radius:16px;\n    box-shadow:0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08); padding:18px; margin-bottom:16px; }\n  .card > .ct{ display:flex; align-items:center; gap:8px; font:700 11px/1 'Roboto',sans-serif; letter-spacing:.6px;\n    text-transform:uppercase; color:#6B7280; margin:0 0 14px; }\n  .idrow{ display:flex; align-items:center; gap:14px; flex-wrap:wrap; }\n  .idrow .who{ flex:1 1 220px; min-width:0; }\n  .idrow .who .nm{ font:700 17px/1.2 'Roboto',sans-serif; color:#1A1C1E; letter-spacing:-.2px; }\n  .idrow .who .meta{ margin-top:3px; font:500 12px/1.3 'Roboto',sans-serif; color:#6B7280; }\n  .fld{ display:flex; flex-direction:column; gap:5px; min-width:0; flex:0 0 200px; }\n  .lbl{ font:600 10px/1 'Roboto',sans-serif; letter-spacing:.5px; text-transform:uppercase; color:#6B7280; }\n  .sel{ appearance:none; -webkit-appearance:none; width:100%; min-width:0; height:40px; padding:0 34px 0 12px;\n    border:1px solid rgba(16,24,40,0.14); border-radius:10px; background:#FFFFFF; color:#1A1C1E;\n    font:500 13px/1 'Roboto',sans-serif; cursor:pointer; transition:border-color 150ms ease-out,box-shadow 150ms ease-out;\n    background-image:url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236B7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>\");\n    background-repeat:no-repeat; background-position:right 10px center; }\n  .sel:focus{ outline:none; border-color:#E5004B; box-shadow:0 0 0 3px rgba(229,0,75,.12); }\n  .pill{ display:inline-flex; align-items:center; gap:5px; padding:3px 9px; border-radius:999px; font:600 11px/1 'Roboto',sans-serif; }\n  .pill.g{ background:rgba(41,172,86,.12); color:#1F8A45; } .pill.a{ background:rgba(250,160,0,.14); color:#B57200; }\n  .pill.r{ background:rgba(255,20,24,.10); color:#D01418; } .pill.n{ background:#F1F3F6; color:#6B7280; }\n  .trend{ display:inline-flex; align-items:center; gap:4px; font:700 12px/1 'Roboto',sans-serif; }\n  .trend.up{ color:#1F8A45; } .trend.down{ color:#D01418; } .trend.flat{ color:#9AA1AC; }\n  .sparkwrap{ display:flex; align-items:center; justify-content:flex-end; }\n  .tl{ display:flex; flex-direction:column; }\n  .cyc{ position:relative; display:flex; align-items:center; gap:14px; padding:14px 8px 14px 4px; cursor:pointer;\n    border-bottom:1px solid rgba(16,24,40,0.06); transition:background 120ms ease-out; border-radius:10px; }\n  .cyc:last-child{ border-bottom:none; }\n  .cyc:hover{ background:#FAFAFB; }\n  .cyc.sel{ background:rgba(229,0,75,.045); }\n  .cyc .dot{ flex:0 0 34px; width:34px; height:34px; border-radius:50%; display:flex; align-items:center; justify-content:center;\n    background:#FAFAFB; border:1px solid rgba(16,24,40,0.10); }\n  .cyc.sel .dot{ background:linear-gradient(135deg,#E5004B 0%,#EB6619 100%); border-color:transparent; }\n  .cyc .cinfo{ flex:1 1 auto; min-width:0; }\n  .cyc .cnm{ font:700 14px/1.2 'Roboto',sans-serif; color:#1A1C1E; display:flex; align-items:center; gap:8px; flex-wrap:wrap; }\n  .cyc .csub{ margin-top:3px; font:400 11px/1.3 'Roboto',sans-serif; color:#9AA1AC; }\n  .cyc .cmoney{ flex:0 0 auto; text-align:right; }\n  .cyc .cmoney .m{ font:800 18px/1 'Roboto',sans-serif; color:#29AC56; letter-spacing:-.4px; }\n  .cyc .cmoney .tr{ margin-top:5px; display:flex; align-items:center; justify-content:flex-end; gap:6px; }\n  .cyc .chev{ flex:0 0 auto; display:flex; align-items:center; color:#C7CCD3; transition:transform 150ms ease-out; }\n  .cyc.sel .chev{ transform:rotate(90deg); color:#E5004B; }\n  .ex{ overflow:hidden; }\n  .ex .exhead{ display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; margin-bottom:4px; }\n  .ex .rlbl{ font:600 11px/1 'Roboto',sans-serif; letter-spacing:.6px; text-transform:uppercase; color:#6B7280; }\n  .ex .money{ font:800 34px/1 'Roboto',sans-serif; letter-spacing:-1px; color:#29AC56; }\n  .ex .subline{ margin-top:6px; font:400 12px/1.4 'Roboto',sans-serif; color:#6B7280; }\n  .sub{ display:flex; align-items:center; gap:8px; font:700 11px/1 'Roboto',sans-serif; letter-spacing:.5px;\n    text-transform:uppercase; color:#6B7280; margin:18px 0 10px; }\n  table.kp{ width:100%; border-collapse:collapse; }\n  table.kp th{ text-align:right; font:600 10px/1 'Roboto',sans-serif; letter-spacing:.4px; text-transform:uppercase;\n    color:#9AA1AC; padding:6px 8px; border-bottom:1px solid rgba(16,24,40,0.08); }\n  table.kp th:first-child{ text-align:left; }\n  table.kp td{ padding:9px 8px; border-bottom:1px solid rgba(16,24,40,0.05); font:500 13px/1.2 'Roboto',sans-serif; text-align:right; }\n  table.kp td:first-child{ text-align:left; }\n  table.kp td.nm{ display:flex; align-items:center; gap:8px; }\n  table.kp td.nm .bmk, table.kp td.nm svg{ flex:0 0 auto; }\n  .comp{ display:flex; flex-wrap:wrap; gap:10px; }\n  .compc{ flex:1 1 150px; background:#FAFAFB; border:1px solid rgba(16,24,40,0.06); border-radius:12px; padding:12px 14px; }\n  .compc .cl{ font:600 10px/1 'Roboto',sans-serif; letter-spacing:.4px; text-transform:uppercase; color:#9AA1AC; }\n  .compc .cv{ font:700 18px/1.1 'Roboto',sans-serif; margin-top:5px; color:#1A1C1E; }\n  .bon{ display:flex; flex-direction:column; gap:8px; }\n  .bonr{ display:flex; align-items:center; justify-content:space-between; gap:12px; padding:11px 13px;\n    border:1px solid rgba(16,24,40,0.08); border-radius:12px; background:#fff; }\n  .bonr .bl{ display:flex; align-items:center; gap:9px; min-width:0; }\n  .bonr .bnm{ font:600 13px/1.2 'Roboto',sans-serif; color:#1A1C1E; }\n  .bonr .bva{ font:700 14px/1 'Roboto',sans-serif; }\n  .bmk{ display:inline-flex; align-items:center; justify-content:center; line-height:0; }\n  .bmk img{ display:block; height:100%; width:auto; object-fit:contain; }\n  .empty{ text-align:center; padding:30px 10px; color:#9AA1AC; }\n  .hint{ font:400 12px/1.4 'Roboto',sans-serif; color:#9AA1AC; }\n  .err{ background:#FFF1F1; border:1px solid #FFD2D2; color:#C4001D; border-radius:10px; padding:10px 12px;\n    font:500 12px/1.4 'Roboto',sans-serif; margin-top:12px; }\n  .spin{ width:20px; height:20px; border:2.5px solid rgba(229,0,75,.18); border-top-color:#E5004B; border-radius:50%;\n    display:inline-block; animation:spin 700ms linear infinite; vertical-align:middle; }\n  .loadrow{ display:flex; align-items:center; gap:10px; padding:24px 8px; color:#6B7280; font:500 13px/1 'Roboto',sans-serif; }\n  @keyframes spin{ to{ transform:rotate(360deg); } }\n  @media (max-width:640px){ .fld{ flex:1 1 100%; } .ex .money{ font-size:28px; } .tbttl{ display:none; } }\n  @media (prefers-reduced-motion:reduce){ .sel,.cyc,.chev,.backbtn{ transition:none; } .spin{ animation:none; } }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const st = d2.state;\n    if(st.init==null){\n      const groups = d2.param('groups', []) || [];\n      // Initialize from CURRENT view context (launcher → query/shared) — no 20200/lider pin.\n      const ctx = readHistContext(d2);\n      const dg = String(ctx.structureCode || d2.param('defaultGroup','') || (groups[0] && (groups[0].code!=null?groups[0].code:groups[0])) || '');\n      st.init = true;\n      st.perfil = ctx.perfil || 'lider';\n      st.gvName = ctx.gvName || '';\n      st.structureCode = dg;\n      st.history = null;\n      st.histLoading = false;\n      st.histError = null;\n      st.selectedCycle = null;\n      st.extrato = null;\n      st.exLoading = false;\n      st.exError = null;\n    }\n    const groups = d2.param('groups', []) || [];\n\n    const opt = (v,cur,txt)=>`<option value=\"${esc(v)}\"${String(v)===String(cur)?' selected':''}>${esc(txt)}</option>`;\n    const isGn = (st.perfil==='gn');\n    // End user (token session): only their own structure is offered — the server enforces the same scope.\n    let tokenUser = false; try{ const ns = JSON.parse(window.localStorage.getItem('_d2_natura_session') || 'null'); tokenUser = !!(ns && ns.token); }catch(e){}\n    const groupList = tokenUser ? [] : (Array.isArray(groups)?groups:[]).slice();\n    if(st.structureCode && !groupList.some(g=>String((g&&g.code!=null)?g.code:g)===String(st.structureCode))){\n      const lbl = (isGn?'Setor ':'Grupo ') + st.structureCode + (st.gvName?(' · '+st.gvName):'');\n      groupList.unshift({ code: st.structureCode, name: lbl });\n    }\n    const groupOpts = groupList.map(g=>{\n      const code = (g && g.code!=null) ? g.code : g;\n      const nm = (g && g.name) ? g.name : ('Grupo '+code);\n      return opt(code, st.structureCode, nm);\n    }).join('');\n    const groupSel = `<select class=\"sel\" data-k=\"group\">${groupOpts}</select>`;\n\n    const H = st.history;\n    const entityWord = isGn ? 'Setor' : 'Grupo';\n    const perfilLabel = isGn ? 'GN' : 'Líder';\n    const identity = H ? `\n      <div class=\"who\">\n        <div class=\"nm\">${esc(H.leaderName||(entityWord+' '+st.structureCode))}</div>\n        <div class=\"meta\">${esc(perfilLabel)} · ${esc(entityWord)} ${esc(st.structureCode)} · ${esc(redeLabel(H.rede))}${H.nivel?(' · nível '+esc(H.nivel)):''}</div>\n      </div>` : `\n      <div class=\"who\">\n        <div class=\"nm\">${esc(entityWord)} ${esc(st.structureCode||'—')}</div>\n        <div class=\"meta\">Selecione um ${esc(entityWord.toLowerCase())} para ver o histórico</div>\n      </div>`;\n\n    let listHtml = '';\n    if(st.histLoading){\n      listHtml = `<div class=\"loadrow\"><span class=\"spin\"></span> Carregando histórico do grupo…</div>`;\n    } else if(st.histError){\n      listHtml = `<div class=\"err\">${esc(st.histError)}</div>`;\n    } else if(H && Array.isArray(H.history) && H.history.length){\n      const series = H.history.map(h=>Number(h.remuneracao)||0);\n      const rows = H.history.map((h,i)=>{\n        const prev = i>0 ? (Number(H.history[i-1].remuneracao)||0) : null;\n        const cur = Number(h.remuneracao)||0;\n        let trendHtml = `<span class=\"trend flat\">${icon('dash', t.color.muted, 14)}</span>`;\n        if(prev!=null){\n          if(cur > prev){ trendHtml = `<span class=\"trend up\">${icon('trendUp','#1F8A45',15)} ${pct(((cur-prev)/(prev||1))*100)}</span>`; }\n          else if(cur < prev){ trendHtml = `<span class=\"trend down\">${icon('trendDown','#D01418',15)} ${pct(((cur-prev)/(prev||1))*100)}</span>`; }\n          else { trendHtml = `<span class=\"trend flat\">${icon('dash', t.color.muted, 14)} 0%</span>`; }\n        }\n        const selCls = String(st.selectedCycle)===String(h.cycle) ? ' sel' : '';\n        const dotColor = selCls ? '#FFFFFF' : t.color.muted;\n        return `<div class=\"cyc${selCls}\" data-key=\"cyc-${esc(h.cycle)}\" data-cycle=\"${esc(h.cycle)}\">\n          <div class=\"dot\">${icon('clock', dotColor, 17)}</div>\n          <div class=\"cinfo\">\n            <div class=\"cnm\">Ciclo ${esc(h.cycle)} ${statusChip(h.status)}${h.isCurrent?'<span class=\"pill g\">Atual</span>':''}</div>\n            <div class=\"csub\">${esc(h.label||'')}</div>\n          </div>\n          <div class=\"cmoney\">\n            <div class=\"m\">${brl(h.remuneracao)}</div>\n            <div class=\"tr\">${trendHtml}</div>\n          </div>\n          <div class=\"chev\">${icon('chevron', selCls?'#E5004B':'#C7CCD3', 18)}</div>\n        </div>`;\n      }).reverse().join(''); // most recent cycle first; trend still compares each cycle with the previous one in time\n      const sparkColor = (series[series.length-1] >= series[0]) ? t.color.money : t.color.rampRed;\n      listHtml = `\n        <div class=\"sparkwrap\" style=\"margin:-6px 0 8px\">${sparkline(series, 220, 44, sparkColor)}</div>\n        <div class=\"tl\">${rows}</div>`;\n    } else if(H) {\n      listHtml = `<div class=\"empty\">${icon('history','#C7CCD3',30)}<div style=\"margin-top:8px;font:500 13px/1.4 Roboto\">Nenhum ciclo disponível para este grupo.</div></div>`;\n    } else {\n      listHtml = `<div class=\"loadrow\"><span class=\"spin\"></span> Carregando…</div>`;\n    }\n\n    let exHtml = '';\n    if(st.selectedCycle!=null){\n      if(st.exLoading){\n        exHtml = `<div class=\"card ex\"><div class=\"loadrow\"><span class=\"spin\"></span> Carregando extrato do ciclo ${esc(st.selectedCycle)}…</div></div>`;\n      } else if(st.exError){\n        exHtml = `<div class=\"card ex\"><div class=\"err\">${esc(st.exError)}</div></div>`;\n      } else if(st.extrato){\n        const r = st.extrato; const bd = r.breakdown||{}; const comp = bd.components||{};\n        const stats = (r.stats||[]);\n        const kpTable = stats.filter(s=>!s.isBonus).map(s=>{\n          const cls = s.status==='green'?'g':(s.status==='amber'?'a':(s.status==='red'?'r':'n'));\n          const atv = (s.atingimento==null)?'—':`<span class=\"pill ${cls}\">${pct(s.atingimento)}</span>`;\n          const brandIco = statIcon(t, s);\n          return `<tr data-key=\"st-${esc(s.indexCode)}\"><td class=\"nm\">${brandIco}${esc(s.label)}</td>\n            <td>${num(s.value)}</td><td>${s.goal!=null?num(s.goal):'—'}</td><td>${atv}</td></tr>`;\n        }).join('');\n        const compCards = `\n          <div class=\"compc\"><div class=\"cl\">Componente Natura</div><div class=\"cv\">${brl(comp.natura)}</div></div>\n          <div class=\"compc\"><div class=\"cl\">Componente Avon</div><div class=\"cv\">${brl(comp.avon)}</div></div>\n          <div class=\"compc\"><div class=\"cl\">Base de remuneração</div><div class=\"cv\">${brl(comp.remunBase)}</div></div>\n          <div class=\"compc\"><div class=\"cl\">Total bônus</div><div class=\"cv\">${brl(comp.bonusTotal)}</div></div>`;\n        const bonuses = (r.bonuses||[]);\n        const bonHtml = bonuses.length ? bonuses.map(b=>{\n          const wr = !!b.willReceive;\n          return `<div class=\"bonr\" data-key=\"bn-${esc(b._id||b.bonusType)}\">\n            <div class=\"bl\">${icon('gift', wr?t.color.money:t.color.muted, 18)}\n              <span class=\"bnm\">${esc(b.label||b.bonusType)}</span>\n              <span class=\"pill ${wr?'g':'n'}\">${wr?'Recebe':'Não recebe'}</span></div>\n            <span class=\"bva\" style=\"color:${wr?'#29AC56':'#9AA1AC'}\">${brl(b.amount)}</span>\n          </div>`;\n        }).join('') : `<div class=\"hint\">Nenhum bônus configurado para este perfil/rede.</div>`;\n\n        exHtml = `<div class=\"card ex\">\n          <div class=\"ct\">${icon('receipt', t.color.muted, 15)} Extrato — Ciclo ${esc(r.cycle)}</div>\n          <div class=\"exhead\">\n            <span class=\"rlbl\">Remuneração do ciclo</span>\n            <span class=\"money\">${brl(r.remuneracao)}</span>\n          </div>\n          <div class=\"subline\">${esc(H?H.leaderName:'')} · ${esc(redeLabel(r.rede))} · nível ${esc(r.nivel||'')} · ${comp.structured?'fórmula estruturada':'cálculo nativo'} · ruleset v${esc(r.rulesetVersion||'')}</div>\n          <div class=\"sub\">${icon('target', t.color.muted, 15)} Indicadores &amp; atingimentos</div>\n          <table class=\"kp\"><thead><tr><th>Indicador</th><th>Realizado</th><th>Meta</th><th>Atingimento</th></tr></thead>\n          <tbody>${kpTable}</tbody></table>\n          <div class=\"sub\">${icon('layers', t.color.muted, 15)} Componentes da remuneração</div>\n          <div class=\"comp\">${compCards}</div>\n          <div class=\"sub\">${icon('gift', t.color.muted, 15)} Bônus &amp; aceleradores</div>\n          <div class=\"bon\">${bonHtml}</div>\n        </div>`;\n      }\n    }\n\n    return `<div class=\"page\">${topbar(t)}\n    <div class=\"wrap\">\n      <div class=\"head\">\n        <div class=\"mk\">${icon('history', '#FFFFFF', 22)}</div>\n        <div class=\"htxt\"><h1>Histórico de Ganhos</h1><p>Remuneração do grupo ao longo dos ciclos — clique em um ciclo para ver o extrato completo.</p></div>\n      </div>\n      <div class=\"card\">\n        <div class=\"ct\">${icon('people', t.color.muted, 15)} Grupo</div>\n        <div class=\"idrow\">\n          ${identity}\n          <div class=\"fld\"><span class=\"lbl\">Selecionar grupo</span>${groupSel}</div>\n        </div>\n      </div>\n      <div class=\"card\">\n        <div class=\"ct\">${icon('history', t.color.muted, 15)} Linha do tempo de remuneração</div>\n        ${listHtml}\n      </div>\n      ${exHtml}\n    </div></div>`;\n  },\n  mounted(d2){\n    const st = d2.state;\n\n    function goBack(){\n      const ref = d2.param('backRef','T1Koa6_rMuQPmA9nSCIk1');\n      const inPreview = /\\/preview\\//.test((typeof location!=='undefined' && location.pathname) || '');\n      try{\n        if(inPreview && typeof location!=='undefined'){ location.href='/preview/'+ref; return; }\n        // back to the dashboard URL the launcher saved (keeps ?token); history + popstate drive the router\n        let back = ''; try{ back = window.sessionStorage.getItem('pilotReturnUrl') || ''; }catch(e){}\n        history.pushState({}, '', back || '/'); window.dispatchEvent(new PopStateEvent('popstate')); return;\n        if(typeof location!=='undefined'){ location.href='/preview/'+ref; }\n      }catch(err){ d2.log('back nav error', err); if(typeof location!=='undefined'){ location.href='/preview/'+ref; } }\n    }\n    d2.on('.backbtn','click', goBack);\n\n    async function loadHistory(){\n      const code = st.structureCode;\n      if(!code){ return; }\n      st.histLoading = true; st.histError = null; st.history = null;\n      st.selectedCycle = null; st.extrato = null; st.exError = null;\n      d2.refresh();\n      try{\n        const res = await d2.rush('pilotHistorico').invoke({ structureCode: code, perfil: (st.perfil||'lider') });\n        const body = (res && res.data && res.data.data) ? res.data.data : (res && res.data ? res.data : res);\n        if(!body || !Array.isArray(body.history)){\n          st.histError = 'Resposta inesperada do histórico.';\n        } else {\n          st.history = body;\n        }\n      }catch(err){\n        st.histError = 'Falha ao carregar histórico: ' + (err && err.message ? err.message : String(err));\n      }finally{\n        st.histLoading = false; d2.refresh();\n      }\n    }\n\n    async function loadExtrato(cycle){\n      const code = st.structureCode;\n      if(!code || cycle==null) return;\n      st.selectedCycle = cycle; st.extrato = null; st.exError = null; st.exLoading = true;\n      d2.refresh();\n      try{\n        const res = await d2.rush('pilotGetGroupEarnings').invoke({ structureCode: code, cycle: cycle, perfil: (st.perfil||'lider') });\n        const body = (res && res.data && res.data.data) ? res.data.data : (res && res.data ? res.data : res);\n        if(!body || body.remuneracao==null){\n          st.exError = 'Resposta inesperada do extrato.';\n        } else {\n          st.extrato = body;\n        }\n      }catch(err){\n        st.exError = 'Falha ao carregar extrato: ' + (err && err.message ? err.message : String(err));\n      }finally{\n        st.exLoading = false; d2.refresh();\n      }\n    }\n\n    d2.on('.sel','change',(e,el)=>{\n      const k = el.getAttribute('data-k');\n      if(k==='group'){\n        st.structureCode = el.value;\n        loadHistory();\n      }\n    });\n\n    d2.on('.cyc','click',(e,el)=>{\n      const cycle = el.getAttribute('data-cycle');\n      if(cycle==null) return;\n      if(String(st.selectedCycle)===String(cycle)){\n        st.selectedCycle = null; st.extrato = null; st.exError = null; st.exLoading = false;\n        d2.refresh();\n        return;\n      }\n      loadExtrato(cycle);\n    });\n\n    loadHistory();\n  }\n};\n"}},"groups":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"groups"}}}},"defaultGroup":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"defaultGroup"}}}},"cycles":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cycles"}}}}}}}}}},{"_id":"6a4cee975192fc0b86101d9f","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotHistoricoLauncher","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"function icon(name, color, size){\n  const s = size||20; const c = color||'#FFFFFF';\n  const A = `xmlns=\"http://www.w3.org/2000/svg\" width=\"${s}\" height=\"${s}\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"${c}\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\"`;\n  const P = {\n    history:`<path d=\"M3 3v5h5\"/><path d=\"M3.05 13A9 9 0 1 0 6 5.3L3 8\"/><path d=\"M12 7v5l3 2\"/>`\n  };\n  return `<svg ${A}>${P[name]||''}</svg>`;\n}\nconst FAB_CSS = `\n  :host{ display:block; }\n  .fab{ position:fixed; right:24px; bottom:96px; z-index:9998; height:52px; padding:0 20px 0 18px;\n    display:inline-flex; align-items:center; gap:10px; border:none; border-radius:999px; cursor:pointer;\n    color:#fff; background:linear-gradient(135deg,#E5004B 0%,#EB6619 100%); font:700 14px/1 'Roboto',system-ui,sans-serif;\n    box-shadow:0 6px 18px rgba(229,0,75,.34); transition:transform 150ms ease-out,box-shadow 150ms ease-out; }\n  .fab:hover{ transform:translateY(-2px); box-shadow:0 10px 24px rgba(229,0,75,.40); }\n  @media (prefers-reduced-motion:reduce){ .fab{ transition:none; } .fab:hover{ transform:none; } }\n  @media (max-width:640px){ .fab{ right:16px; bottom:74px; height:46px; padding:0 16px 0 14px; font-size:13px; } }\n  `;\n// position:fixed breaks under a transformed ancestor (the player wraps artboards), so the\n// button lives in a <body> portal with its own shadow root; removed on unmount.\nfunction fabPortal(d2, kind, html, onClick){\n  if(typeof document === 'undefined') return;\n  const old = document.querySelector('[data-pilot-fab=\"'+kind+'\"]');\n  if(old) old.remove();\n  const host = document.createElement('div');\n  host.setAttribute('data-pilot-fab', kind);\n  const sh = host.attachShadow({ mode:'open' });\n  sh.innerHTML = '<style>'+FAB_CSS+'</style>' + html;\n  document.body.appendChild(host);\n  const b = sh.querySelector('.fab');\n  if(b) b.addEventListener('click', onClick);\n  d2.onUnmount(()=>{ host.remove(); });\n}\nexport default {\n  css: `:host{ display:none; }`,\n  render(d2){\n    return `<span class=\"fab-anchor\"></span>`;\n  },\n  mounted(d2){\n    const label = d2.param('label','Histórico');\n    const html = `<button class=\"fab\" title=\"Abrir Histórico de Ganhos\">${icon('history','#fff',20)}<span>${label}</span></button>`;\n    const go = ()=>{\n      const ref = d2.param('artboardRef','');\n      if(!ref) return;\n      // ACCESS TRACKING (additive) — record a Histórico section view before navigating away.\n      try{\n        const sid = (typeof window!=='undefined' && window.sessionStorage) ? window.sessionStorage.getItem('pilotAccessSessionId') : '';\n        if(sid) d2.rush('pilotTrackAccess').invoke({ action:'view', sessionId: sid, section:'historico', drillLevel:'launcher' }).catch(()=>{});\n      }catch(e){}\n      // CURRENT-CONTEXT PASS — hand the live dashboard view to the Histórico screen.\n      let ctx = null;\n      try{\n        const store = d2.store('pilotDashboardStore');\n        if(store){\n          ctx = {\n            perfil: store.get('perfil',''),\n            structureCode: String(store.get('selectedGroup','') || store.get('structureCode','') || ''),\n            rede: store.get('rede',''),\n            cycle: String(store.get('cycle','') || ''),\n            gvName: store.get('gvName','')\n          };\n          d2.shared.set('pilotSimContext', ctx, {global:true});\n        }\n      }catch(e){ d2.log('hist context read error', e); }\n      let qs = '';\n      try{\n        if(ctx){\n          const p = [];\n          if(ctx.perfil) p.push('perfil='+encodeURIComponent(ctx.perfil));\n          if(ctx.structureCode) p.push('structureCode='+encodeURIComponent(ctx.structureCode));\n          if(ctx.rede) p.push('rede='+encodeURIComponent(ctx.rede));\n          if(ctx.cycle) p.push('cycle='+encodeURIComponent(ctx.cycle));\n          if(ctx.gvName) p.push('gvName='+encodeURIComponent(ctx.gvName));\n          if(p.length) qs = '?'+p.join('&');\n        }\n      }catch(e){}\n      const path = (typeof location!=='undefined' && location.pathname) || '';\n      const inPreview = /\\/preview\\//.test(path);\n      try{\n        if(inPreview && typeof location!=='undefined'){\n          location.href = '/preview/'+ref+qs; return;\n        }\n        // d2.router().goTo() does not navigate from this component in the player — drive the\n        // browser router via history + popstate, remembering the dashboard URL (keeps ?token).\n        try{ window.sessionStorage.setItem('pilotReturnUrl', location.pathname + location.search); }catch(e){}\n        history.pushState({}, '', '/'+ref+qs); window.dispatchEvent(new PopStateEvent('popstate')); return;\n        if(typeof location!=='undefined'){ location.href = '/preview/'+ref+qs; }\n      }catch(err){ d2.log('launcher nav error', err); if(typeof location!=='undefined'){ location.href = '/preview/'+ref+qs; } }\n    };\n    fabPortal(d2, 'historico', html, go);\n    // Hide the button while the dashboard shows \"Sessão inválida\" — the shell sets the flag asynchronously.\n    const syncVis = ()=>{ try{ const h = document.querySelector('[data-pilot-fab=\"historico\"]'); if(h) h.style.display = d2.shared.get('pilotTokenInvalid', false, { global:true }) ? 'none' : ''; }catch(e){} };\n    syncVis(); const visTimer = setInterval(syncVis, 400); d2.onUnmount(()=>clearInterval(visTimer));\n  }\n};\n"}},"artboardRef":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"artboardRef"}}}},"label":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"label"}}}}}}}}}},{"_id":"6a4d0ea891afdd4d5cd4381b","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotAccessLogAdmScreen","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',money:'#29AC56',rampGreen:'#29AC56',rampRed:'#FF1418',rampAmber:'#FAA000',gold:'#F7BE00'},\n  radius:{sm:8,md:12,lg:16,pill:999},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\"},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'},\n  motion:{hover:'150ms ease-out',mount:'400ms cubic-bezier(0.4,0,0.2,1)',fade:'200ms ease-out'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nconst PERFIL_LABEL = { gv:'GV', gn:'GN', lider:'Líder' };\nfunction perfilLabel(p){ return PERFIL_LABEL[p] || String(p||'—'); }\nconst ACTION_META = {\n  'impersonate-start':{ label:'Início impersonação', cls:'start' },\n  'impersonate-end':{ label:'Fim impersonação', cls:'end' },\n  'view':{ label:'Visualização', cls:'view' },\n  'simulate':{ label:'Simulação', cls:'sim' },\n  'export':{ label:'Exportação', cls:'exp' },\n  'login':{ label:'Login', cls:'start' },\n  'session-end':{ label:'Fim de sessão', cls:'end' }\n};\nfunction actionMeta(a){ return ACTION_META[String(a||'')] || { label:String(a||'—'), cls:'view' }; }\n\nconst ICON = (()=>{\n  const S = (p)=>`<svg class=\"ic-svg\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${p}</svg>`;\n  return {\n    search:S('<circle cx=\"11\" cy=\"11\" r=\"7\"/><path d=\"m21 21-4.3-4.3\"/>'),\n    arrow:S('<line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"/><polyline points=\"12 5 19 12 12 19\"/>'),\n    users:S('<path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><path d=\"M23 21v-2a4 4 0 0 0-3-3.87\"/><path d=\"M16 3.13a4 4 0 0 1 0 7.75\"/>'),\n    eye:S('<path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>'),\n    target:S('<circle cx=\"12\" cy=\"12\" r=\"9\"/><circle cx=\"12\" cy=\"12\" r=\"5\"/><circle cx=\"12\" cy=\"12\" r=\"1.4\"/>')\n  };\n})();\n\nfunction actorInitials(name){\n  const parts = String(name||'').trim().split(/\\s+/).filter(Boolean);\n  if(!parts.length) return '?';\n  if(parts.length===1) return parts[0].slice(0,2).toUpperCase();\n  return (parts[0][0]+parts[parts.length-1][0]).toUpperCase();\n}\nfunction relTime(iso){\n  const t = new Date(iso).getTime();\n  if(!isFinite(t)) return '';\n  const diff = Date.now()-t;\n  const s = Math.round(diff/1000);\n  if(s<60) return 'agora mesmo';\n  const m = Math.round(s/60); if(m<60) return `há ${m} min`;\n  const h = Math.round(m/60); if(h<24) return `há ${h} h`;\n  const dd = Math.round(h/24); if(dd<30) return `há ${dd} d`;\n  try{ return new Date(iso).toLocaleDateString('pt-BR',{day:'2-digit',month:'short'}); }catch(e){ return ''; }\n}\nfunction absTime(iso){\n  try{ return new Date(iso).toLocaleString('pt-BR',{day:'2-digit',month:'2-digit',year:'numeric',hour:'2-digit',minute:'2-digit'}); }\n  catch(e){ return String(iso||''); }\n}\n\nfunction computeStats(rows){\n  const starts = rows.filter(r=>String(r.action)==='impersonate-start');\n  const actors = {};\n  const targets = {};\n  starts.forEach(r=>{\n    const a = r.actorName || r.actorEmail || r.actorUserId;\n    if(a) actors[a] = (actors[a]||0)+1;\n    const t = r.targetName || r.targetUserId;\n    if(t) targets[t] = (targets[t]||0)+1;\n  });\n  const distinctActors = Object.keys(actors).length;\n  let topTarget = '—'; let topN = 0;\n  Object.keys(targets).forEach(k=>{ if(targets[k]>topN){ topN=targets[k]; topTarget=k; } });\n  return { totalImpersonations: starts.length, distinctActors, topTarget, topTargetCount: topN };\n}\n\nconst ACTION_FILTERS = [\n  { key:'', label:'Todas' },\n  { key:'impersonate-start', label:'Início' },\n  { key:'impersonate-end', label:'Fim' },\n  { key:'login', label:'Login' },\n  { key:'view', label:'Visualização' }\n];\n\nfunction rowMarkup(rec){\n  const m = actionMeta(rec.action);\n  const id = String(rec._id||'');\n  // Two record shapes share pilot-access-log: impersonation events (actor*/target*/scope)\n  // and pilotTrackAccess session events (name/userId/perfil/section/mode).\n  const actor = rec.actorName || rec.actorEmail || rec.name || (rec.perfil==='gv' ? rec.gvName : '') || rec.userId || '—';\n  const actorPerfil = rec.actorPerfil || rec.actualPerfil || rec.perfil;\n  const target = rec.targetName || (rec.action==='impersonate-end' ? '(fim)' : (rec.section || '—'));\n  const targetPerfil = rec.targetPerfil || rec.effectivePerfil || rec.perfil || '';\n  const scope = rec.scope && rec.scope!=='n/a' ? rec.scope : (rec.mode || '—');\n  return `<tr data-key=\"al-${esc(id)}\">\n    <td class=\"c-when\"><span class=\"rel\" title=\"${esc(absTime(rec.at))}\">${esc(relTime(rec.at))}</span><span class=\"abs\">${esc(absTime(rec.at))}</span></td>\n    <td class=\"c-actor\"><span class=\"avatar\" title=\"${esc(rec.actorEmail||'')}\">${esc(actorInitials(actor))}</span><span class=\"an\"><span class=\"anm\">${esc(actor)}</span><span class=\"ap\">${esc(perfilLabel(actorPerfil))}</span></span></td>\n    <td class=\"c-arrow\">${ICON.arrow}</td>\n    <td class=\"c-target\"><span class=\"tn\">${esc(target)}</span>${rec.impersonatedCode||rec.structureCode?`<span class=\"tc\">${esc(rec.impersonatedCode||rec.structureCode)}</span>`:''}</td>\n    <td class=\"c-perfil\"><span class=\"pchip ${esc(targetPerfil)}\">${esc(perfilLabel(targetPerfil))}</span></td>\n    <td class=\"c-action\"><span class=\"achip ${esc(m.cls)}\">${esc(m.label)}</span></td>\n    <td class=\"c-scope\">${esc(scope)}</td>\n    <td class=\"c-cycle\">${esc(rec.cycle||'—')}</td>\n  </tr>`;\n}\n\nexport default {\n  css: `\n  :host{display:block}\n  .screen{min-height:100%;height:auto;display:flex;flex-direction:column;background:var(--ground);font-family:var(--fam);box-sizing:border-box}\n  .header{padding:26px 30px 18px;background:var(--surface);border-bottom:1px solid var(--hair)}\n  .htitle h1{margin:0;font:800 28px/1.1 var(--fam);color:var(--ink);letter-spacing:-.5px}\n  .htitle .badge{display:inline-block;margin-left:10px;font:700 10px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;color:var(--mag);background:rgba(229,0,75,.10);padding:5px 9px;border-radius:999px;vertical-align:middle}\n  .htitle p{margin:6px 0 0;font:400 13px/1.4 var(--fam);color:var(--muted);max-width:720px}\n  .toolbar{display:flex;align-items:center;gap:12px;margin-top:16px;flex-wrap:wrap}\n  .search{flex:1 1 240px;min-width:0;display:flex;align-items:center;gap:8px;background:var(--ground);border:1.5px solid var(--hair);border-radius:11px;padding:9px 13px}\n  .search input{flex:1;min-width:0;border:none;background:none;outline:none;font:500 14px/1 var(--fam);color:var(--ink)}\n  .search .si{color:var(--muted);display:inline-flex}\n  .search .si .ic-svg{width:16px;height:16px}\n  .count{font:600 12px/1 var(--fam);color:var(--muted);white-space:nowrap}\n  .filters{display:flex;align-items:center;gap:8px;margin-top:12px;flex-wrap:wrap}\n  .flabel{font:700 10px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin-right:2px}\n  .fchip{padding:7px 12px;border-radius:999px;border:1px solid var(--hair);background:var(--surface);color:var(--muted);font:700 12px/1 var(--fam);cursor:pointer;transition:background .15s,color .15s,border-color .15s;white-space:nowrap}\n  .fchip:hover{background:var(--ground);color:var(--ink)}\n  .fchip[data-on]{background:var(--mag);color:#fff;border-color:var(--mag)}\n  .stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px;padding:22px 30px 4px}\n  .stat{background:var(--surface);border:1px solid var(--hair);border-radius:16px;padding:18px 20px;box-shadow:var(--shadowcard);display:flex;align-items:center;gap:14px}\n  .stat .ico{width:44px;height:44px;flex:none;border-radius:12px;background:rgba(229,0,75,.10);display:inline-flex;align-items:center;justify-content:center;color:var(--mag)}\n  .stat .ico .ic-svg{width:22px;height:22px}\n  .stat .sv{font:800 26px/1 var(--fam);color:var(--ink);letter-spacing:-.5px}\n  .stat .sl{font:600 11px/1.3 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.04em;margin-top:4px}\n  .stat .st{font:600 12px/1.3 var(--fam);color:var(--ink);margin-top:3px;max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n  .body{flex:1 1 auto;padding:18px 30px 90px}\n  .tablecard{max-width:1080px;margin:0 auto;background:var(--surface);border:1px solid var(--hair);border-radius:16px;box-shadow:var(--shadowcard);overflow:hidden}\n  table.log{width:100%;border-collapse:collapse}\n  table.log thead th{text-align:left;font:700 10px/1 var(--fam);letter-spacing:.05em;text-transform:uppercase;color:var(--muted);padding:13px 14px;border-bottom:1px solid var(--hair);background:var(--ground);white-space:nowrap}\n  table.log td{padding:12px 14px;border-bottom:1px solid rgba(16,24,40,0.05);font:500 13px/1.3 var(--fam);color:var(--ink);vertical-align:middle}\n  table.log tbody tr:last-child td{border-bottom:none}\n  table.log tbody tr:hover{background:var(--ground)}\n  .c-when .rel{display:block;font-weight:700;color:var(--ink)}\n  .c-when .abs{display:block;font:500 10.5px/1.2 var(--fam);color:var(--muted);margin-top:2px}\n  .c-actor{display:flex;align-items:center;gap:9px}\n  .avatar{width:28px;height:28px;flex:none;border-radius:50%;background:var(--grad);color:#fff;font:800 10px/1 var(--fam);display:inline-flex;align-items:center;justify-content:center}\n  .an{display:flex;flex-direction:column;min-width:0}\n  .anm{font:700 12.5px/1.2 var(--fam);color:var(--ink);max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n  .ap{font:600 10.5px/1 var(--fam);color:var(--muted);margin-top:2px}\n  .c-arrow{color:var(--muted);width:26px;text-align:center}\n  .c-arrow .ic-svg{width:16px;height:16px}\n  .tn{font:700 12.5px/1.2 var(--fam);color:var(--ink)}\n  .tc{display:inline-block;margin-left:6px;font:700 10px/1 'SF Mono',ui-monospace,Menlo,monospace;color:var(--muted);background:var(--ground);padding:2px 6px;border-radius:5px}\n  .pchip{font:800 10px/1 var(--fam);letter-spacing:.03em;padding:5px 9px;border-radius:999px;white-space:nowrap}\n  .pchip.gn{background:rgba(59,130,246,.14);color:#1d5fd1}\n  .pchip.lider{background:rgba(139,92,246,.16);color:#6d34d6}\n  .pchip.gv{background:rgba(229,0,75,.12);color:var(--mag)}\n  .achip{font:800 10px/1 var(--fam);letter-spacing:.03em;padding:5px 9px;border-radius:999px;white-space:nowrap}\n  .achip.start{background:rgba(41,172,86,.15);color:#1a7d3c}\n  .achip.end{background:rgba(107,114,128,.16);color:var(--muted)}\n  .achip.view{background:rgba(59,130,246,.14);color:#1d5fd1}\n  .achip.sim{background:rgba(250,160,0,.16);color:#b57200}\n  .achip.exp{background:rgba(139,92,246,.14);color:#6d34d6}\n  .c-scope,.c-cycle{color:var(--muted);font-weight:600;white-space:nowrap}\n  .empty{padding:60px;text-align:center;color:var(--muted);font:500 14px/1.5 var(--fam)}\n  @media (prefers-reduced-motion: reduce){ .fchip{transition:none!important} }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const green = t.color.rampGreen||t.color.money||'#29AC56';\n    const vars = `--surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient};--green:${green};--fam:${t.type.family};--shadowcard:${t.shadow.card}`;\n\n    const ds = d2.data('accessLog');\n    const all = ds ? ds.records() : [];\n    const loading = ds && ds.loading;\n    const sorted = all.slice().sort((a,b)=> new Date(b.at||0)-new Date(a.at||0));\n\n    const fAction = d2.state.fAction||'';\n    const q = String(d2.state.q||'').trim().toLowerCase();\n    const filtered = sorted.filter(r=>{\n      if(fAction && String(r.action)!==fAction) return false;\n      if(q){\n        const hay = `${r.actorName||''} ${r.actorEmail||''} ${r.targetName||''} ${r.name||''} ${r.userId||''} ${r.gvName||''} ${r.section||''} ${r.mode||''} ${r.action||''} ${r.impersonatedCode||''} ${r.structureCode||''} ${r.cycle||''}`.toLowerCase();\n        if(hay.indexOf(q)<0) return false;\n      }\n      return true;\n    });\n\n    const st = computeStats(sorted);\n    const statCards = `\n      <div class=\"stat\"><span class=\"ico\">${ICON.eye}</span><div><div class=\"sv\">${st.totalImpersonations}</div><div class=\"sl\">Impersonações (início)</div></div></div>\n      <div class=\"stat\"><span class=\"ico\">${ICON.users}</span><div><div class=\"sv\">${st.distinctActors}</div><div class=\"sl\">Atores distintos</div></div></div>\n      <div class=\"stat\"><span class=\"ico\">${ICON.target}</span><div><div class=\"sv\">${st.topTargetCount||0}×</div><div class=\"sl\">Alvo mais impersonado</div><div class=\"st\" title=\"${esc(st.topTarget)}\">${esc(st.topTarget)}</div></div></div>`;\n\n    const rows = filtered.map(r=>rowMarkup(r)).join('');\n    const actionChips = ACTION_FILTERS.map(c=>`<button class=\"fchip\" data-faction=\"${esc(c.key)}\" ${fAction===c.key?'data-on':''}>${esc(c.label)}</button>`).join('');\n\n    const tableBody = loading\n      ? `<div class=\"empty\">Carregando registros de acesso…</div>`\n      : (rows\n        ? `<div class=\"tablecard\"><table class=\"log\">\n            <thead><tr><th>Quando</th><th>Ator</th><th></th><th>Alvo</th><th>Perfil</th><th>Ação</th><th>Escopo</th><th>Ciclo</th></tr></thead>\n            <tbody>${rows}</tbody></table></div>`\n        : `<div class=\"empty\">Nenhum registro de acesso encontrado com os filtros atuais.</div>`);\n\n    return `<div class=\"screen\" style=\"${vars}\">\n      <div class=\"header\">\n        <div class=\"htitle\">\n          <h1>Registro de Acessos <span class=\"badge\">Code · Somente leitura</span></h1>\n          <p>Histórico de impersonações e acessos ao painel: quem visualizou como quem, quando, com qual escopo e ciclo. Ordenado do mais recente para o mais antigo.</p>\n        </div>\n        <div class=\"toolbar\">\n          <div class=\"search\"><span class=\"si\">${ICON.search}</span><input type=\"text\" data-q placeholder=\"Buscar por ator, alvo, ação, código ou ciclo…\" value=\"${esc(d2.state.q||'')}\"/></div>\n          <span class=\"count\">${filtered.length} de ${sorted.length} eventos</span>\n        </div>\n        <div class=\"filters\"><span class=\"flabel\">Ação</span>${actionChips}</div>\n      </div>\n      <div class=\"stats\">${statCards}</div>\n      <div class=\"body\">${tableBody}</div>\n    </div>`;\n  },\n  mounted(d2){\n    const ds = d2.data('accessLog');\n    if(ds && ds.loadAll){ ds.loadAll().catch(()=>{}); }\n    d2.on('[data-q]','input',(e,el)=>{ d2.state.q = el.value; d2.refresh(); });\n    d2.on('[data-faction]','click',(e,el)=>{ d2.setState({ fAction: el.dataset.faction }); });\n  }\n};"}},"accessLog":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"accessLog"}}}}}}}}}},{"_id":"6a4d4ccc30d16699f7f94d0a","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotAccessStatsAdmScreen","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',money:'#29AC56',rampGreen:'#29AC56',rampRed:'#FF1418',rampAmber:'#FAA000',gold:'#F7BE00'},\n  radius:{sm:8,md:12,lg:16,pill:999},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\"},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'},\n  motion:{hover:'150ms ease-out',mount:'400ms cubic-bezier(0.4,0,0.2,1)',fade:'200ms ease-out'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nconst TTL_MS = 30*60*1000; // active-now window\n\nconst PERFIL_LABEL = { gv:'GV', gn:'GN', lider:'Líder', admin:'Admin' };\nfunction perfilLabel(p){ return PERFIL_LABEL[p] || String(p||'—'); }\nconst MODE_LABEL = { session:'Sessão (App A)', 'gv-admin':'Sessão (App A)', idp:'IdP / SSO', token:'Token (App B)', impersonation:'Impersonação' };\nfunction modeLabel(m){ return MODE_LABEL[m] || String(m||'—'); }\nconst REDE_LABEL = { rede1:'Rede 1', rede2:'Rede 2' };\nfunction redeLabel(r){ return REDE_LABEL[r] || String(r||'—'); }\nconst SECTION_LABEL = {\n  'dashboard:gv':'Painel · GV', 'dashboard:gn':'Painel · GN', 'dashboard:lider':'Painel · Líder',\n  'dashboard:sector':'Painel · Setor', 'dashboard:admin':'Admin', 'simulador':'Simulador',\n  'historico':'Histórico', 'impersonation:start':'Impersonação (início)', 'impersonation:end':'Impersonação (fim)'\n};\nfunction sectionLabel(s){\n  const raw = String(s||'—');\n  if(SECTION_LABEL[raw]) return SECTION_LABEL[raw];\n  if(raw.indexOf('dashboard:gv:')===0) return 'Painel · GV · '+raw.split(':').pop().toUpperCase();\n  return raw;\n}\n\nconst ICON = (()=>{\n  const S = (p)=>`<svg class=\"ic-svg\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${p}</svg>`;\n  return {\n    live:S('<circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M5 12a7 7 0 0 1 14 0\"/><path d=\"M2 12a10 10 0 0 1 20 0\"/>'),\n    login:S('<path d=\"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4\"/><polyline points=\"10 17 15 12 10 7\"/><line x1=\"15\" y1=\"12\" x2=\"3\" y2=\"12\"/>'),\n    cycle:S('<path d=\"M21 12a9 9 0 1 1-3-6.7\"/><polyline points=\"21 3 21 8 16 8\"/>'),\n    users:S('<path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><path d=\"M23 21v-2a4 4 0 0 0-3-3.87\"/><path d=\"M16 3.13a4 4 0 0 1 0 7.75\"/>'),\n    clock:S('<circle cx=\"12\" cy=\"12\" r=\"9\"/><polyline points=\"12 7 12 12 15 14\"/>'),\n    eye:S('<path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>'),\n    device:S('<rect x=\"2\" y=\"4\" width=\"20\" height=\"12\" rx=\"2\"/><line x1=\"8\" y1=\"20\" x2=\"16\" y2=\"20\"/><line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"20\"/>'),\n    bars:S('<path d=\"M4 19V5\"/><path d=\"M4 19h16\"/><rect x=\"7\" y=\"11\" width=\"2.6\" height=\"5\"/><rect x=\"11\" y=\"8\" width=\"2.6\" height=\"8\"/><rect x=\"15\" y=\"6\" width=\"2.6\" height=\"10\"/>')\n  };\n})();\n\nfunction num(n){ try{ return Number(n||0).toLocaleString('pt-BR'); }catch(e){ return String(n||0); } }\nfunction absTime(iso){\n  if(!iso) return '—';\n  try{ return new Date(iso).toLocaleString('pt-BR',{day:'2-digit',month:'2-digit',year:'numeric',hour:'2-digit',minute:'2-digit'}); }\n  catch(e){ return String(iso||''); }\n}\nfunction relTime(iso){\n  const t = new Date(iso).getTime();\n  if(!isFinite(t)) return '—';\n  const diff = Date.now()-t;\n  const s = Math.round(diff/1000);\n  if(s<60) return 'agora mesmo';\n  const m = Math.round(s/60); if(m<60) return `há ${m} min`;\n  const h = Math.round(m/60); if(h<24) return `há ${h} h`;\n  const dd = Math.round(h/24); if(dd<30) return `há ${dd} d`;\n  try{ return new Date(iso).toLocaleDateString('pt-BR',{day:'2-digit',month:'short'}); }catch(e){ return '—'; }\n}\nfunction dayKey(iso){\n  const d = new Date(iso);\n  if(!isFinite(d.getTime())) return '';\n  return d.toISOString().slice(0,10);\n}\nfunction dayLabel(key){\n  try{ const d = new Date(key+'T00:00:00'); return d.toLocaleDateString('pt-BR',{day:'2-digit',month:'2-digit'}); }catch(e){ return key; }\n}\nfunction fmtDuration(ms){\n  if(!isFinite(ms) || ms<=0) return '—';\n  const totalMin = Math.round(ms/60000);\n  if(totalMin < 60) return totalMin+' min';\n  const h = Math.floor(totalMin/60); const m = totalMin%60;\n  return m ? `${h}h ${m}min` : `${h}h`;\n}\n\n// coarse userAgent → { browser, os } bucket\nfunction parseUA(ua){\n  const s = String(ua||'');\n  let browser = 'Outro';\n  if(/Edg\\//i.test(s)) browser='Edge';\n  else if(/OPR\\/|Opera/i.test(s)) browser='Opera';\n  else if(/Chrome\\//i.test(s) && !/Chromium/i.test(s)) browser='Chrome';\n  else if(/Firefox\\//i.test(s)) browser='Firefox';\n  else if(/Safari\\//i.test(s) && /Version\\//i.test(s)) browser='Safari';\n  else if(!s) browser='Desconhecido';\n  let os = 'Outro';\n  if(/iPhone|iPad|iPod/i.test(s)) os='iOS';\n  else if(/Android/i.test(s)) os='Android';\n  else if(/Windows/i.test(s)) os='Windows';\n  else if(/Mac OS X|Macintosh/i.test(s)) os='macOS';\n  else if(/Linux/i.test(s)) os='Linux';\n  else if(!s) os='Desconhecido';\n  const mobile = /Mobi|iPhone|iPad|iPod|Android/i.test(s);\n  return { browser, os, kind: mobile?'Mobile':(s?'Desktop':'Desconhecido') };\n}\n\n// horizontal breakdown bars from a {label,count} array\nfunction breakdownBars(items, colorVar){\n  if(!items.length) return `<div class=\"bd-empty\">Sem dados.</div>`;\n  const max = Math.max.apply(null, items.map(i=>i.count).concat([1]));\n  return items.map(i=>{\n    const pct = Math.round((i.count/max)*100);\n    return `<div class=\"bd-row\">\n      <span class=\"bd-label\" title=\"${esc(i.label)}\">${esc(i.label)}</span>\n      <span class=\"bd-track\"><span class=\"bd-fill\" style=\"width:${pct}%;background:${colorVar}\"></span></span>\n      <span class=\"bd-val\">${num(i.count)}</span>\n    </div>`;\n  }).join('');\n}\n\n// inline-SVG login-over-time bar chart (last N days)\nfunction loginsChart(days){\n  if(!days.length) return `<div class=\"bd-empty\">Sem logins no período.</div>`;\n  const W = 720, H = 140, pad = 24, n = days.length;\n  const max = Math.max.apply(null, days.map(d=>d.count).concat([1]));\n  const bw = (W - pad*2) / n;\n  const barW = Math.max(6, Math.min(38, bw*0.6));\n  let bars = '';\n  let labels = '';\n  days.forEach((d,i)=>{\n    const x = pad + i*bw + (bw-barW)/2;\n    const h = Math.round((d.count/max)*(H-pad*2));\n    const y = H - pad - h;\n    bars += `<rect x=\"${x.toFixed(1)}\" y=\"${y.toFixed(1)}\" width=\"${barW.toFixed(1)}\" height=\"${Math.max(0,h)}\" rx=\"3\" fill=\"url(#lg)\"><title>${esc(dayLabel(d.key))}: ${num(d.count)} login(s)</title></rect>`;\n    bars += `<text x=\"${(x+barW/2).toFixed(1)}\" y=\"${(y-5).toFixed(1)}\" text-anchor=\"middle\" class=\"ch-num\">${d.count?num(d.count):''}</text>`;\n    if(n<=14 || i%2===0){\n      labels += `<text x=\"${(x+barW/2).toFixed(1)}\" y=\"${H-6}\" text-anchor=\"middle\" class=\"ch-lbl\">${esc(dayLabel(d.key))}</text>`;\n    }\n  });\n  return `<svg class=\"chart\" viewBox=\"0 0 ${W} ${H}\" preserveAspectRatio=\"xMidYMid meet\" role=\"img\" aria-label=\"Logins ao longo do tempo\">\n    <defs><linearGradient id=\"lg\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\"><stop offset=\"0%\" stop-color=\"var(--mag)\"/><stop offset=\"100%\" stop-color=\"var(--orange)\"/></linearGradient></defs>\n    <line x1=\"${pad}\" y1=\"${H-pad}\" x2=\"${W-pad}\" y2=\"${H-pad}\" stroke=\"var(--hair)\" stroke-width=\"1\"/>\n    ${bars}${labels}\n  </svg>`;\n}\n\nfunction tally(arr, keyFn, labelFn){\n  const m = {};\n  arr.forEach(r=>{ const k = keyFn(r); if(k==null||k==='') return; m[k]=(m[k]||0)+1; });\n  return Object.keys(m).map(k=>({ key:k, label: labelFn?labelFn(k):k, count:m[k] })).sort((a,b)=>b.count-a.count);\n}\n\nexport default {\n  css: `\n  :host{display:block}\n  .screen{min-height:100%;height:auto;display:flex;flex-direction:column;background:var(--ground);font-family:var(--fam);box-sizing:border-box}\n  .header{padding:26px 30px 18px;background:var(--surface);border-bottom:1px solid var(--hair)}\n  .htitle h1{margin:0;font:800 28px/1.1 var(--fam);color:var(--ink);letter-spacing:-.5px}\n  .htitle .badge{display:inline-block;margin-left:10px;font:700 10px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;color:var(--mag);background:rgba(229,0,75,.10);padding:5px 9px;border-radius:999px;vertical-align:middle}\n  .htitle p{margin:6px 0 0;font:400 13px/1.4 var(--fam);color:var(--muted);max-width:760px}\n  .toolbar{display:flex;align-items:center;gap:10px;margin-top:16px;flex-wrap:wrap}\n  .flabel{font:700 10px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin-right:2px}\n  .fchip{padding:7px 12px;border-radius:999px;border:1px solid var(--hair);background:var(--surface);color:var(--muted);font:700 12px/1 var(--fam);cursor:pointer;transition:background .15s,color .15s,border-color .15s;white-space:nowrap}\n  .fchip:hover{background:var(--ground);color:var(--ink)}\n  .fchip[data-on]{background:var(--mag);color:#fff;border-color:var(--mag)}\n  .count{font:600 12px/1 var(--fam);color:var(--muted);white-space:nowrap;margin-left:auto}\n  .body{flex:1 1 auto;padding:22px 30px 90px;max-width:1120px;margin:0 auto;width:100%;box-sizing:border-box}\n  .kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:16px}\n  .kpi{background:var(--surface);border:1px solid var(--hair);border-radius:16px;padding:16px 18px;box-shadow:var(--shadowcard);display:flex;align-items:center;gap:13px}\n  .kpi .ico{width:42px;height:42px;flex:none;border-radius:12px;background:rgba(229,0,75,.10);display:inline-flex;align-items:center;justify-content:center;color:var(--mag)}\n  .kpi .ico.live{background:rgba(41,172,86,.14);color:var(--green)}\n  .kpi .ico .ic-svg{width:21px;height:21px}\n  .kpi .sv{font:800 25px/1 var(--fam);color:var(--ink);letter-spacing:-.5px}\n  .kpi .sl{font:600 10.5px/1.3 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.04em;margin-top:4px}\n  .kpi .live-dot{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--green);margin-right:5px;vertical-align:middle;box-shadow:0 0 0 3px rgba(41,172,86,.18)}\n  .grid2{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-top:20px}\n  .grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:18px}\n  @media (max-width:860px){ .grid2,.grid3{grid-template-columns:1fr} }\n  .panel{background:var(--surface);border:1px solid var(--hair);border-radius:16px;box-shadow:var(--shadowcard);padding:18px 20px}\n  .panel.wide{grid-column:1 / -1}\n  .ptitle{display:flex;align-items:center;gap:8px;font:800 14px/1 var(--fam);color:var(--ink);margin:0 0 14px}\n  .ptitle .pico{color:var(--mag);display:inline-flex}\n  .ptitle .pico .ic-svg{width:17px;height:17px}\n  .ptitle .psub{font:600 11px/1 var(--fam);color:var(--muted);margin-left:auto;text-transform:none;letter-spacing:0}\n  .chart{width:100%;height:auto;display:block}\n  .ch-num{font:700 10px/1 var(--fam);fill:var(--muted)}\n  .ch-lbl{font:600 10px/1 var(--fam);fill:var(--muted)}\n  .bd-row{display:flex;align-items:center;gap:10px;margin:0 0 9px}\n  .bd-label{flex:0 0 120px;font:700 12px/1.2 var(--fam);color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .bd-track{flex:1 1 auto;height:10px;background:var(--ground);border-radius:999px;overflow:hidden;min-width:40px}\n  .bd-fill{display:block;height:100%;border-radius:999px;transition:width .3s ease-out}\n  .bd-val{flex:0 0 auto;font:800 12px/1 var(--fam);color:var(--ink);min-width:34px;text-align:right}\n  .bd-empty{padding:16px 4px;color:var(--muted);font:500 12.5px/1.4 var(--fam);font-style:italic}\n  table.tbl{width:100%;border-collapse:collapse}\n  table.tbl thead th{text-align:left;font:700 10px/1 var(--fam);letter-spacing:.05em;text-transform:uppercase;color:var(--muted);padding:10px 12px;border-bottom:1px solid var(--hair);white-space:nowrap}\n  table.tbl td{padding:11px 12px;border-bottom:1px solid rgba(16,24,40,0.05);font:500 13px/1.3 var(--fam);color:var(--ink);vertical-align:middle}\n  table.tbl tbody tr:last-child td{border-bottom:none}\n  table.tbl tbody tr:hover{background:var(--ground)}\n  .u-name{display:flex;align-items:center;gap:9px}\n  .avatar{width:26px;height:26px;flex:none;border-radius:50%;background:var(--grad);color:#fff;font:800 10px/1 var(--fam);display:inline-flex;align-items:center;justify-content:center}\n  .pchip{font:800 9.5px/1 var(--fam);letter-spacing:.03em;padding:4px 8px;border-radius:999px;white-space:nowrap}\n  .pchip.gn{background:rgba(59,130,246,.14);color:#1d5fd1}\n  .pchip.lider{background:rgba(139,92,246,.16);color:#6d34d6}\n  .pchip.gv{background:rgba(229,0,75,.12);color:var(--mag)}\n  .pchip.admin{background:rgba(107,114,128,.16);color:var(--muted)}\n  .tnum{font:800 13px/1 var(--fam);color:var(--ink)}\n  .tmut{color:var(--muted);font-weight:600;white-space:nowrap}\n  .sec-name{font:700 12.5px/1.2 var(--fam);color:var(--ink)}\n  .empty{padding:60px;text-align:center;color:var(--muted);font:500 14px/1.5 var(--fam)}\n  @media (prefers-reduced-motion: reduce){ .fchip{transition:none!important} .bd-fill{transition:none} }\n  `,\n  render(d2){\n    const t = tok(d2);\n    const green = t.color.rampGreen||t.color.money||'#29AC56';\n    const blue = '#3b82f6';\n    const purple = '#8b5cf6';\n    const vars = `--surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--orange:${t.color.naturaOrange};--grad:${t.color.brandGradient};--green:${green};--fam:${t.type.family};--shadowcard:${t.shadow.card}`;\n\n    // Prefer the declared params; fall back to the global DataSet processes so the\n    // screen works even if a host forgot to bind them.\n    const sDs = d2.data('sessions') || d2.data('pilot-sessionDataSet');\n    const eDs = d2.data('accessLog') || d2.data('pilot-access-logDataSet');\n    const sessions = sDs ? sDs.records() : [];\n    const events = eDs ? eDs.records() : [];\n    const loading = (sDs && sDs.loading) || (eDs && eDs.loading);\n\n    const now = Date.now();\n    const range = d2.state.range || '7d';\n    const rangeMs = range==='today' ? null : (range==='30d' ? 30*24*3600*1000 : (range==='all' ? null : 7*24*3600*1000));\n    function inRange(iso){\n      const ts = new Date(iso).getTime();\n      if(!isFinite(ts)) return false;\n      if(range==='today'){ const d=new Date(); d.setHours(0,0,0,0); return ts>=d.getTime(); }\n      if(range==='all') return true;\n      return ts >= now - rangeMs;\n    }\n\n    // ── sessions in range (by startedAt) ─────────────────────────────────────\n    const sessInRange = sessions.filter(s=>inRange(s.startedAt));\n    // active-now: lastSeenAt within TTL AND not ended\n    const activeNow = sessions.filter(s=>{\n      if(String(s.status)==='ended') return false;\n      const ls = new Date(s.lastSeenAt||s.startedAt).getTime();\n      return isFinite(ls) && (now - ls) <= TTL_MS;\n    });\n\n    // login events (from the event stream) — the canonical \"logins\" metric\n    const loginEvents = events.filter(e=>String(e.action)==='login');\n    const viewEvents = events.filter(e=>String(e.action)==='view');\n    const loginsInRange = loginEvents.filter(e=>inRange(e.at));\n\n    // logins today / cycle\n    const startToday = (()=>{ const d=new Date(); d.setHours(0,0,0,0); return d.getTime(); })();\n    const loginsToday = loginEvents.filter(e=>{ const ts=new Date(e.at).getTime(); return isFinite(ts) && ts>=startToday; }).length;\n    // cycle = the most common cycle in login events (pilot has one active cycle)\n    const cycleTally = tally(loginEvents, e=>e.cycle);\n    const topCycle = cycleTally.length ? cycleTally[0].key : '';\n    const loginsCycle = topCycle ? loginEvents.filter(e=>String(e.cycle)===String(topCycle)).length : loginEvents.length;\n\n    // distinct users (in range) — by userId, fallback name\n    const userKeys = {};\n    loginsInRange.forEach(e=>{ const k=e.userId||e.name; if(k) userKeys[k]=1; });\n    const distinctUsers = Object.keys(userKeys).length;\n\n    // avg session duration for ended sessions in range\n    const ended = sessInRange.filter(s=>String(s.status)==='ended' && s.endedAt && s.startedAt);\n    let avgDur = 0;\n    if(ended.length){\n      const totalMs = ended.reduce((acc,s)=>{\n        const d = new Date(s.endedAt).getTime() - new Date(s.startedAt).getTime();\n        return acc + (isFinite(d) && d>0 ? d : 0);\n      }, 0);\n      avgDur = totalMs / ended.length;\n    }\n\n    // logins over time (by day) — from login events in range\n    const dayMap = {};\n    loginsInRange.forEach(e=>{ const k=dayKey(e.at); if(!k) return; dayMap[k]=(dayMap[k]||0)+1; });\n    // build a contiguous day series for the last N days when a windowed range is used\n    let daySeries = [];\n    if(range==='today'){\n      daySeries = Object.keys(dayMap).sort().map(k=>({key:k,count:dayMap[k]}));\n      if(!daySeries.length) daySeries = [{ key: dayKey(new Date().toISOString()), count: 0 }];\n    } else if(range==='all'){\n      daySeries = Object.keys(dayMap).sort().map(k=>({key:k,count:dayMap[k]}));\n    } else {\n      const nDays = range==='30d' ? 30 : 7;\n      for(let i=nDays-1;i>=0;i--){\n        const d = new Date(now - i*24*3600*1000);\n        const k = d.toISOString().slice(0,10);\n        daySeries.push({ key:k, count: dayMap[k]||0 });\n      }\n    }\n\n    // breakdowns (from login events in range)\n    const byPerfil = tally(loginsInRange, e=>e.perfil, perfilLabel);\n    const byMode = tally(loginsInRange, e=>e.mode, modeLabel);\n    const byRede = tally(loginsInRange.filter(e=>e.rede), e=>e.rede, redeLabel);\n\n    // most-active users — sessions count + last-seen + total views, in range\n    const uMap = {};\n    loginsInRange.forEach(e=>{\n      const k = e.userId || e.name || '?';\n      if(!uMap[k]) uMap[k] = { key:k, name:e.name||e.userId||'—', perfil:e.perfil, sessions:0, views:0, lastSeen:0 };\n      uMap[k].sessions += 1;\n    });\n    // fold last-seen from the session rows + views from view events\n    sessInRange.forEach(s=>{\n      const k = s.userId || s.name; if(!k || !uMap[k]) return;\n      const ls = new Date(s.lastSeenAt||s.startedAt).getTime();\n      if(isFinite(ls) && ls>uMap[k].lastSeen) uMap[k].lastSeen = ls;\n      uMap[k].views += Number(s.viewCount||0);\n    });\n    const activeUsers = Object.keys(uMap).map(k=>uMap[k]).sort((a,b)=> b.sessions-a.sessions || b.views-a.views).slice(0,10);\n\n    // most-viewed sections — from view events in range\n    const bySection = tally(viewEvents.filter(e=>inRange(e.at)), e=>e.section, sectionLabel).slice(0,10);\n\n    // device / entry mix (from sessions in range — coarse UA + entryMode)\n    const uaParsed = sessInRange.map(s=>parseUA(s.userAgent));\n    const byKind = tally(uaParsed, r=>r.kind, x=>x);\n    const byBrowser = tally(uaParsed, r=>r.browser, x=>x);\n    const byEntry = tally(sessInRange, s=>s.entryMode||s.mode, modeLabel);\n\n    if(loading){\n      return `<div class=\"screen\" style=\"${vars}\">\n        <div class=\"header\"><div class=\"htitle\"><h1>Estatísticas de Acesso <span class=\"badge\">Code · Somente leitura</span></h1></div></div>\n        <div class=\"body\"><div class=\"empty\">Carregando estatísticas de uso…</div></div>\n      </div>`;\n    }\n\n    const RANGES = [{key:'today',label:'Hoje'},{key:'7d',label:'7 dias'},{key:'30d',label:'30 dias'},{key:'all',label:'Tudo'}];\n    const rangeChips = RANGES.map(c=>`<button class=\"fchip\" data-range=\"${esc(c.key)}\" ${range===c.key?'data-on':''}>${esc(c.label)}</button>`).join('');\n\n    const kpis = `\n      <div class=\"kpi\"><span class=\"ico live\">${ICON.live}</span><div><div class=\"sv\"><span class=\"live-dot\"></span>${num(activeNow.length)}</div><div class=\"sl\">Sessões ativas agora</div></div></div>\n      <div class=\"kpi\"><span class=\"ico\">${ICON.login}</span><div><div class=\"sv\">${num(loginsToday)}</div><div class=\"sl\">Logins hoje</div></div></div>\n      <div class=\"kpi\"><span class=\"ico\">${ICON.cycle}</span><div><div class=\"sv\">${num(loginsCycle)}</div><div class=\"sl\">Logins no ciclo ${topCycle?esc(topCycle):''}</div></div></div>\n      <div class=\"kpi\"><span class=\"ico\">${ICON.users}</span><div><div class=\"sv\">${num(distinctUsers)}</div><div class=\"sl\">Usuários distintos</div></div></div>\n      <div class=\"kpi\"><span class=\"ico\">${ICON.clock}</span><div><div class=\"sv\">${fmtDuration(avgDur)}</div><div class=\"sl\">Duração média</div></div></div>`;\n\n    const userRows = activeUsers.length ? activeUsers.map(u=>`<tr data-key=\"au-${esc(u.key)}\">\n      <td><span class=\"u-name\"><span class=\"avatar\">${esc((String(u.name||'?').trim()[0]||'?').toUpperCase())}</span>${esc(u.name)}</span></td>\n      <td><span class=\"pchip ${esc(u.perfil||'')}\">${esc(perfilLabel(u.perfil))}</span></td>\n      <td class=\"tnum\">${num(u.sessions)}</td>\n      <td class=\"tnum\">${num(u.views)}</td>\n      <td class=\"tmut\" title=\"${esc(u.lastSeen?absTime(new Date(u.lastSeen).toISOString()):'')}\">${u.lastSeen?esc(relTime(new Date(u.lastSeen).toISOString())):'—'}</td>\n    </tr>`).join('') : '';\n\n    const secRows = bySection.length ? bySection.map(s=>`<tr data-key=\"sec-${esc(s.key)}\">\n      <td><span class=\"sec-name\">${esc(s.label)}</span></td>\n      <td class=\"tnum\">${num(s.count)}</td>\n    </tr>`).join('') : '';\n\n    return `<div class=\"screen\" style=\"${vars}\">\n      <div class=\"header\">\n        <div class=\"htitle\">\n          <h1>Estatísticas de Acesso <span class=\"badge\">Code · Somente leitura</span></h1>\n          <p>Uso do painel de remuneração: sessões ativas, logins ao longo do tempo, distribuição por perfil, modo de entrada e rede, usuários mais ativos, seções mais acessadas e mix de dispositivo. Somente leitura — nenhuma escrita a partir desta tela.</p>\n        </div>\n        <div class=\"toolbar\">\n          <span class=\"flabel\">Período</span>${rangeChips}\n          <span class=\"count\">${num(sessInRange.length)} sessões · ${num(loginsInRange.length)} logins · ${num(viewEvents.filter(e=>inRange(e.at)).length)} views</span>\n        </div>\n      </div>\n      <div class=\"body\">\n        <div class=\"kpis\">${kpis}</div>\n\n        <div class=\"grid2\">\n          <div class=\"panel wide\">\n            <div class=\"ptitle\"><span class=\"pico\">${ICON.bars}</span>Logins ao longo do tempo <span class=\"psub\">${range==='today'?'hoje':(range==='all'?'todo o histórico':(range==='30d'?'últimos 30 dias':'últimos 7 dias'))}</span></div>\n            ${loginsChart(daySeries)}\n          </div>\n        </div>\n\n        <div class=\"grid3\">\n          <div class=\"panel\">\n            <div class=\"ptitle\"><span class=\"pico\">${ICON.users}</span>Por perfil</div>\n            ${breakdownBars(byPerfil, 'var(--mag)')}\n          </div>\n          <div class=\"panel\">\n            <div class=\"ptitle\"><span class=\"pico\">${ICON.login}</span>Por modo de entrada</div>\n            ${breakdownBars(byMode, blue)}\n          </div>\n          <div class=\"panel\">\n            <div class=\"ptitle\"><span class=\"pico\">${ICON.bars}</span>Por rede</div>\n            ${breakdownBars(byRede, green)}\n          </div>\n        </div>\n\n        <div class=\"grid2\">\n          <div class=\"panel\">\n            <div class=\"ptitle\"><span class=\"pico\">${ICON.users}</span>Usuários mais ativos <span class=\"psub\">top 10</span></div>\n            ${userRows ? `<table class=\"tbl\"><thead><tr><th>Usuário</th><th>Perfil</th><th>Sessões</th><th>Views</th><th>Último acesso</th></tr></thead><tbody>${userRows}</tbody></table>` : `<div class=\"bd-empty\">Nenhum acesso no período.</div>`}\n          </div>\n          <div class=\"panel\">\n            <div class=\"ptitle\"><span class=\"pico\">${ICON.eye}</span>Seções mais acessadas <span class=\"psub\">top 10</span></div>\n            ${secRows ? `<table class=\"tbl\"><thead><tr><th>Seção</th><th>Views</th></tr></thead><tbody>${secRows}</tbody></table>` : `<div class=\"bd-empty\">Nenhuma visualização no período.</div>`}\n          </div>\n        </div>\n\n        <div class=\"grid3\">\n          <div class=\"panel\">\n            <div class=\"ptitle\"><span class=\"pico\">${ICON.device}</span>Tipo de dispositivo</div>\n            ${breakdownBars(byKind, purple)}\n          </div>\n          <div class=\"panel\">\n            <div class=\"ptitle\"><span class=\"pico\">${ICON.device}</span>Navegador</div>\n            ${breakdownBars(byBrowser, 'var(--orange)')}\n          </div>\n          <div class=\"panel\">\n            <div class=\"ptitle\"><span class=\"pico\">${ICON.login}</span>Modo de entrada (sessões)</div>\n            ${breakdownBars(byEntry, 'var(--mag)')}\n          </div>\n        </div>\n      </div>\n    </div>`;\n  },\n  mounted(d2){\n    const sDs = d2.data('sessions') || d2.data('pilot-sessionDataSet');\n    if(sDs && sDs.loadAll){ sDs.loadAll().catch(()=>{}); }\n    const eDs = d2.data('accessLog') || d2.data('pilot-access-logDataSet');\n    if(eDs && eDs.loadAll){ eDs.loadAll().catch(()=>{}); }\n    d2.on('[data-range]','click',(e,el)=>{ d2.setState({ range: el.dataset.range }); });\n  }\n};"}},"sessions":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"sessions"}}}},"accessLog":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"accessLog"}}}}}}}}}},{"_id":"6a4d688cf59849fa5edc1cad","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotQueryLibAdmScreen","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',naturaOrange:'#EB6619',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',money:'#29AC56',gold:'#F7BE00'},\n  radius:{sm:8,md:12,lg:16,pill:999},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\"},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 8px 24px rgba(16,24,40,0.18)'}\n};\nlet TOK;\nfunction tok(d2){ if(!TOK){ try{ TOK = d2.call('natura-x-piloto@pilotMTokens'); }catch(e){} if(!TOK||!TOK.color) TOK = FALLBACK; } return TOK; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nconst ICON = (()=>{\n  const S = (p)=>`<svg class=\"ic-svg\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${p}</svg>`;\n  return {\n    edit:S('<path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/>'),\n    del:S('<path d=\"M3 6h18\"/><path d=\"M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/>'),\n    ok:S('<path d=\"M20 6 9 17l-5-5\"/>'),\n    x:S('<path d=\"M18 6 6 18M6 6l12 12\"/>'),\n    plus:S('<path d=\"M12 5v14M5 12h14\"/>'),\n    run:S('<polygon points=\"6 4 20 12 6 20 6 4\"/>'),\n    search:S('<circle cx=\"11\" cy=\"11\" r=\"7\"/><path d=\"m21 21-4.3-4.3\"/>')\n  };\n})();\n\nfunction cssVars(t){\n  return `--surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient};--money:${t.color.money};--fam:${t.type.family};--shadowcard:${t.shadow.card};--shadowraised:${t.shadow.raised}`;\n}\n\n// ---- data access ----\nfunction queries(d2){ const ds=d2.data('queryLib'); const rows=(ds&&ds.records&&ds.records())||[]; return rows; }\nfunction calendar(d2){ const ds=d2.data('queryCalendar'); const rows=(ds&&ds.records&&ds.records())||[]; return rows; }\nfunction refresh(d2){ const ds=d2.data('queryLib'); if(ds&&ds.refresh) ds.refresh(); }\nfunction toast(d2,msg){ d2.setState({ toast:msg }); setTimeout(()=>d2.setState({ toast:null }), 2600); }\nasync function write(d2,payload){ return await d2.rush('queryWriter').invoke(payload); }\nasync function runner(d2,payload){ return await d2.rush('runner').invoke(payload); }\n\nfunction parseVars(str){\n  return String(str||'').split(',').map(s=>s.trim()).filter(Boolean);\n}\nfunction varsArray(row){\n  const v = row && row.variables;\n  if(Array.isArray(v)) return v;\n  if(typeof v==='string') return parseVars(v);\n  return [];\n}\n\nfunction rowCard(d2, q){\n  const armed = d2.state.confirmDel===q._id;\n  const vars = varsArray(q);\n  const sqlPreview = String(q.sql||'').replace(/\\s+/g,' ').trim().slice(0,120);\n  return `<div class=\"qrow\" data-key=\"ql-${esc(q._id)}\">\n    <div class=\"qmain\">\n      <div class=\"qtop\">\n        <span class=\"qname\">${esc(q.name||'(sem nome)')}</span>\n        ${q.active===false?`<span class=\"chip off\">inativa</span>`:`<span class=\"chip on\">ativa</span>`}\n        ${vars.length?`<span class=\"chip vars\">${vars.length} var${vars.length>1?'s':''}</span>`:''}\n        ${q.strategy?`<span class=\"chip calc\" title=\"Roda no scheduler e alimenta o cálculo do painel (remuneração e totalizadores)\">usada no cálculo</span><span class=\"chip sched\">scheduler · ${esc(q.strategy)}</span>`:''}\n        ${q.lastExecutedAt?`<span class=\"chip off\">última ${esc(String(q.lastExecutedAt).replace('T',' ').slice(0,16))}</span>`:''}\n      </div>\n      ${q.description?`<div class=\"qdesc\">${esc(q.description)}</div>`:''}\n      <div class=\"qsql\"><code>${esc(sqlPreview)}${String(q.sql||'').length>120?'…':''}</code></div>\n      ${vars.length?`<div class=\"qvars\">${vars.map(v=>`<span class=\"vtag\">{{${esc(v)}}}</span>`).join('')}</div>`:''}\n    </div>\n    <div class=\"qctl\">\n      <button class=\"qic run\" data-run=\"${esc(q._id)}\" title=\"Executar\">${ICON.run}</button>\n      <button class=\"qic edit\" data-edit=\"${esc(q._id)}\" title=\"Editar\">${ICON.edit}</button>\n      ${armed\n        ? `<button class=\"qic del armed\" data-del=\"${esc(q._id)}\" title=\"Confirmar exclusão\">${ICON.ok}</button><button class=\"qic\" data-delcancel title=\"Cancelar\">${ICON.x}</button>`\n        : `<button class=\"qic del\" data-delask=\"${esc(q._id)}\" title=\"Excluir\">${ICON.del}</button>`}\n    </div>\n  </div>`;\n}\n\nfunction editModal(d2){\n  if(!d2.state.editOpen) return '';\n  const m = d2.state.edit || {};\n  const isNew = !m._id;\n  const varsStr = Array.isArray(m.variables) ? m.variables.join(', ') : (m.variables||'');\n  return `<div class=\"modal-bg in\" data-mbg>\n    <div class=\"modal\">\n      <h2>${isNew?'Nova consulta':'Editar consulta'}</h2>\n      <p class=\"msub\">Consultas com <code>{{param}}</code> são substituídas pelo runner antes de irem ao Databricks.</p>\n      ${m.strategy?`<div class=\"warnbox\"><b>Consulta usada no cálculo do painel.</b> O scheduler roda esta consulta toda hora e o resultado vira o realizado e as metas da remuneração e dos totalizadores. Uma alteração vale na próxima execução: se a consulta passar a devolver linhas erradas, o painel mostra números errados. Mantenha as colunas (<code>structure_code</code>, <code>index_code</code>, valor) e teste com ▶ Executar antes de salvar.</div>`:''}\n      <div class=\"frow\">\n        <div class=\"mfield grow\"><label>Nome (chave)</label><input type=\"text\" data-mfield=\"name\" value=\"${esc(m.name||'')}\" placeholder=\"Ex.: cycle-calendar\"/></div>\n        <div class=\"mfield tog\"><label>Ativa</label><button type=\"button\" class=\"tog ${m.active===false?'':'on'}\" data-mtog=\"active\"><span class=\"knob\"></span></button></div>\n        <div class=\"mfield\"><label>Scheduler</label><select data-mfield=\"strategy\">\n          <option value=\"\" ${!m.strategy?'selected':''}>não roda</option>\n          <option value=\"cache\" ${m.strategy==='cache'?'selected':''}>cache (toda hora, por ciclo aberto)</option>\n          <option value=\"oneTimeCycle\" ${m.strategy==='oneTimeCycle'?'selected':''}>oneTimeCycle (uma vez por ciclo)</option>\n        </select><div class=\"hint\">Precisa de <code>{{cycle}}</code> no SQL.</div></div>\n      </div>\n      <div class=\"frow\"><div class=\"mfield grow\"><label>Descrição</label><textarea data-mfield=\"description\" rows=\"2\" placeholder=\"O que a consulta retorna.\">${esc(m.description||'')}</textarea></div></div>\n      <div class=\"frow\"><div class=\"mfield grow\"><label>SQL</label><textarea class=\"mono\" data-mfield=\"sql\" rows=\"8\" placeholder=\"SELECT ... WHERE cd = {{param}}\">${esc(m.sql||'')}</textarea></div></div>\n      <div class=\"frow\"><div class=\"mfield grow\"><label>Variáveis (separadas por vírgula)</label><input type=\"text\" data-mfield=\"variables\" value=\"${esc(varsStr)}\" placeholder=\"Ex.: gerencia\"/>\n        <div class=\"hint\">Nomes dos <code>{{param}}</code> usados no SQL.</div></div></div>\n      <div class=\"mfoot\">\n        <button class=\"btn ghost\" data-mclose>Cancelar</button>\n        <button class=\"btn prim\" data-msave>${isNew?'Criar':'Salvar'}</button>\n      </div>\n    </div>\n  </div>`;\n}\n\nfunction paramInputs(d2, q){\n  const vars = varsArray(q);\n  const rp = d2.state.runParams || {};\n  if(!vars.length) return `<div class=\"hint\">Esta consulta não tem parâmetros.</div>`;\n  return `<div class=\"prow\">${vars.map(v=>`<div class=\"pfield\"><label>{{${esc(v)}}}</label><input type=\"text\" data-pfield=\"${esc(v)}\" value=\"${esc(rp[v]==null?'':rp[v])}\" placeholder=\"valor\"/></div>`).join('')}</div>`;\n}\n\nfunction resultTable(res){\n  if(!res) return '';\n  if(res.error) return `<div class=\"rerr\">${esc(res.error)}</div>`;\n  const rows = res.rows||[];\n  if(!rows.length) return `<div class=\"hint\">0 linhas.</div>`;\n  const cols = Object.keys(rows[0]);\n  const head = cols.map(c=>`<th>${esc(c)}</th>`).join('');\n  const body = rows.slice(0,50).map(r=>`<tr>${cols.map(c=>`<td>${esc(r[c])}</td>`).join('')}</tr>`).join('');\n  return `<div class=\"rmeta\">${rows.length} linha(s)${rows.length>50?' (mostrando 50)':''}</div>\n    <div class=\"rsqlbox\"><code>${esc(res.sql||'')}</code></div>\n    <div class=\"rtblwrap\"><table class=\"rtbl\"><thead><tr>${head}</tr></thead><tbody>${body}</tbody></table></div>`;\n}\n\nfunction runModal(d2){\n  if(!d2.state.runOpen) return '';\n  const id = d2.state.runId;\n  const q = queries(d2).find(x=>x._id===id) || {};\n  const running = d2.state.running;\n  const res = d2.state.runResult;\n  return `<div class=\"modal-bg in\" data-rbg>\n    <div class=\"modal wide\">\n      <h2>Executar · ${esc(q.name||'')}</h2>\n      <p class=\"msub\">Preencha os parâmetros e execute. As linhas voltam do Databricks ao vivo.</p>\n      ${paramInputs(d2, q)}\n      <div class=\"mfoot\">\n        <button class=\"btn ghost\" data-rclose>Fechar</button>\n        <button class=\"btn prim ${running?'busy':''}\" data-rgo>${running?'<span class=\"spin\"></span> Executando…':ICON.run+' Executar'}</button>\n      </div>\n      <div class=\"rout\">${res?resultTable(res):(running?'<div class=\"hint\">Consultando Databricks…</div>':'<div class=\"hint\">Sem resultado ainda.</div>')}</div>\n    </div>\n  </div>`;\n}\n\nfunction calendarPanel(d2){\n  const rows = calendar(d2);\n  if(!d2.state.calOpen){\n    return `<div class=\"calbar\"><button class=\"btn ghost\" data-caltoggle>Ver calendário de ciclos por grupo (${rows.length})</button></div>`;\n  }\n  const filter = String(d2.state.calFilter||'').trim();\n  let list = rows.slice();\n  if(filter) list = list.filter(r=>String(r.groupCode||'').includes(filter)||String(r.sectorCode||'').includes(filter)||String(r.cycle||'').includes(filter));\n  list = list.slice().sort((a,b)=> (String(a.groupCode)+a.cycle).localeCompare(String(b.groupCode)+b.cycle));\n  const head = `<tr><th>Ciclo</th><th>Setor</th><th>Grupo</th><th>Início</th><th>Fim</th><th>Origem</th></tr>`;\n  const body = list.slice(0,200).map(r=>`<tr><td>${esc(r.cycle)}</td><td>${esc(r.sectorCode)}</td><td>${esc(r.groupCode)}</td><td>${esc(r.startDate)}</td><td>${esc(r.endDate)}</td><td><span class=\"chip ${r.source==='live'?'on':'off'}\">${esc(r.source||'—')}</span></td></tr>`).join('');\n  return `<div class=\"calpanel\">\n    <div class=\"calhead\">\n      <span class=\"caltitle\">Calendário de ciclos por grupo <span class=\"chip vars\">${rows.length} linhas</span></span>\n      <div class=\"search\"><span class=\"si\">${ICON.search}</span><input type=\"text\" data-calfilter value=\"${esc(filter)}\" placeholder=\"filtrar por grupo, setor ou ciclo\"/></div>\n      <button class=\"btn ghost\" data-caltoggle>Ocultar</button>\n    </div>\n    <div class=\"rtblwrap\"><table class=\"rtbl\"><thead>${head}</thead><tbody>${body}</tbody></table></div>\n    ${list.length>200?`<div class=\"hint\">Mostrando 200 de ${list.length}.</div>`:''}\n  </div>`;\n}\n\nexport default {\n  css: `\n  :host{display:block}\n  .screen{min-height:100%;height:auto;display:flex;flex-direction:column;background:var(--ground);font-family:var(--fam);box-sizing:border-box}\n  .header{padding:26px 30px 20px;background:var(--surface);border-bottom:1px solid var(--hair)}\n  .htop{display:flex;align-items:flex-start;gap:16px}\n  .htitle h1{margin:0;font:800 28px/1.1 var(--fam);color:var(--ink);letter-spacing:-.5px}\n  .htitle .badge{display:inline-block;margin-left:10px;font:700 10px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;color:var(--mag);background:rgba(229,0,75,.10);padding:5px 9px;border-radius:999px;vertical-align:middle}\n  .htitle p{margin:6px 0 0;font:400 13px/1.4 var(--fam);color:var(--muted);max-width:720px}\n  .newbtn{margin-left:auto;display:inline-flex;align-items:center;gap:7px;padding:11px 18px;border:none;border-radius:11px;background:var(--grad);color:#fff;font:700 13px/1 var(--fam);cursor:pointer;box-shadow:0 4px 12px rgba(229,0,75,.28);transition:filter .15s,transform .1s;white-space:nowrap}\n  .newbtn:hover{filter:brightness(1.06)} .newbtn:active{transform:scale(.97)}\n  .newbtn .ic-svg{width:15px;height:15px}\n  .toolbar{display:flex;align-items:center;gap:12px;margin-top:16px;flex-wrap:wrap}\n  .search{flex:1 1 240px;min-width:0;display:flex;align-items:center;gap:8px;background:var(--ground);border:1.5px solid var(--hair);border-radius:11px;padding:9px 13px}\n  .search input{flex:1;min-width:0;border:none;background:none;outline:none;font:500 14px/1 var(--fam);color:var(--ink)}\n  .search .si{color:var(--muted);display:inline-flex} .search .si .ic-svg{width:16px;height:16px}\n  .count{font:600 12px/1 var(--fam);color:var(--muted);white-space:nowrap}\n  .body{flex:1 1 auto;padding:22px 30px 72px;display:flex;flex-direction:column;gap:14px}\n  .qrow{background:var(--surface);border:1px solid var(--hair);border-radius:16px;padding:16px 18px;box-shadow:var(--shadowcard);display:flex;align-items:flex-start;gap:16px}\n  .qmain{flex:1 1 auto;min-width:0}\n  .qtop{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}\n  .qname{font:800 17px/1.2 var(--fam);color:var(--ink);letter-spacing:-.2px}\n  .chip{font:700 10px/1 var(--fam);letter-spacing:.03em;padding:5px 9px;border-radius:999px;white-space:nowrap}\n  .chip.on{background:rgba(41,172,86,.14);color:var(--money)}\n  .chip.off{background:rgba(107,114,128,.14);color:var(--muted)}\n  .chip.vars{background:rgba(72,152,255,.14);color:#1462c7}\n  .chip.sched{background:rgba(247,190,0,.18);color:#8a6a00}\n  .chip.calc{background:rgba(229,0,75,.12);color:var(--mag)}\n  .warnbox{background:rgba(247,190,0,.12);border:1px solid rgba(247,190,0,.45);border-radius:12px;padding:11px 13px;margin:0 0 16px;font:500 12px/1.5 var(--fam);color:#7a5c00}\n  .warnbox code{font:700 11px/1 'SF Mono',ui-monospace,Menlo,monospace;background:rgba(255,255,255,.6);padding:2px 5px;border-radius:5px}\n  .mfield select{border:1.5px solid var(--hair);border-radius:10px;padding:10px 12px;font:500 13px/1.4 var(--fam);color:var(--ink);background:var(--surface);outline:none;box-sizing:border-box;width:100%}\n  .qdesc{margin-top:8px;font:400 12.5px/1.45 var(--fam);color:var(--muted)}\n  .qsql{margin-top:8px}\n  .qsql code,.rsqlbox code{font:600 11.5px/1.4 'SF Mono',ui-monospace,Menlo,monospace;background:var(--ground);padding:6px 9px;border-radius:8px;color:var(--ink);display:block;white-space:pre-wrap;word-break:break-word}\n  .qvars{margin-top:8px;display:flex;gap:6px;flex-wrap:wrap}\n  .vtag{font:700 10.5px/1 'SF Mono',ui-monospace,Menlo,monospace;background:rgba(229,0,75,.08);color:var(--mag);padding:5px 8px;border-radius:7px}\n  .qctl{margin-left:auto;display:flex;align-items:center;gap:6px;flex-wrap:wrap;justify-content:flex-end}\n  .qic{width:32px;height:32px;flex:0 0 auto;border:none;border-radius:9px;background:var(--ground);color:var(--muted);cursor:pointer;font-size:14px;display:inline-flex;align-items:center;justify-content:center;transition:background .15s,color .15s,transform .1s}\n  .qic:hover{background:rgba(229,0,75,.10);color:var(--mag)} .qic:active{transform:scale(.92)}\n  .qic.run:hover{background:rgba(41,172,86,.14);color:var(--money)}\n  .qic.del:hover{background:rgba(214,20,25,.12);color:#d61419}\n  .qic.del.armed{background:#d61419;color:#fff}\n  .ic-svg{display:block;flex:0 0 auto} .qic .ic-svg{width:17px;height:17px}\n  .btn{padding:9px 15px;border-radius:10px;font:700 12.5px/1 var(--fam);cursor:pointer;border:none;transition:filter .15s,transform .1s,background .15s;white-space:nowrap;display:inline-flex;align-items:center;gap:7px}\n  .btn .ic-svg{width:15px;height:15px}\n  .btn.prim{background:var(--grad);color:#fff;box-shadow:0 4px 12px rgba(229,0,75,.28)} .btn.prim:hover{filter:brightness(1.06)} .btn.prim:active{transform:scale(.97)}\n  .btn.prim.busy{opacity:.7;pointer-events:none}\n  .btn.ghost{background:var(--ground);color:var(--muted);border:1px solid var(--hair)} .btn.ghost:hover{background:var(--hair);color:var(--ink)}\n  .empty{padding:60px;text-align:center;color:var(--muted);font:500 14px/1.5 var(--fam)}\n  .calbar{margin-top:6px}\n  .calpanel{background:var(--surface);border:1px solid var(--hair);border-radius:16px;padding:16px 18px;box-shadow:var(--shadowcard);margin-top:6px}\n  .calhead{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:12px}\n  .caltitle{font:800 15px/1.2 var(--fam);color:var(--ink);display:flex;align-items:center;gap:8px}\n  .rtblwrap{overflow-x:auto;border:1px solid var(--hair);border-radius:12px}\n  .rtbl{border-collapse:collapse;width:100%;font:500 12px/1.4 var(--fam);color:var(--ink)}\n  .rtbl th{text-align:left;font:700 11px/1 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.04em;padding:10px 12px;background:var(--ground);border-bottom:1px solid var(--hair);white-space:nowrap}\n  .rtbl td{padding:9px 12px;border-bottom:1px solid var(--hair);white-space:nowrap}\n  .rtbl tr:last-child td{border-bottom:none}\n  .hint{margin-top:8px;font:500 11.5px/1.4 var(--fam);color:var(--muted)}\n  .hint code,.msub code{font:700 11px/1 'SF Mono',ui-monospace,Menlo,monospace;background:var(--ground);padding:2px 5px;border-radius:5px;color:var(--ink)}\n  .toast{position:fixed;left:50%;bottom:26px;transform:translate(-50%,20px);background:var(--ink);color:#fff;padding:12px 20px;border-radius:12px;font:600 13px/1 var(--fam);box-shadow:0 10px 30px rgba(0,0,0,.3);z-index:9500;opacity:0;transition:opacity .2s,transform .2s;pointer-events:none}\n  .toast.in{opacity:1;transform:translate(-50%,0)}\n  .modal-bg{position:fixed;inset:0;background:rgba(16,24,40,.42);z-index:9000;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s;padding:24px}\n  .modal-bg.in{opacity:1}\n  .modal{background:var(--surface);border-radius:20px;box-shadow:var(--shadowraised);width:min(560px,100%);max-width:100%;max-height:90vh;overflow:auto;box-sizing:border-box;padding:24px 26px}\n  .modal.wide{width:min(820px,100%)}\n  .modal h2{margin:0 0 4px;font:800 20px/1.1 var(--fam);color:var(--ink)}\n  .modal .msub{margin:0 0 16px;font:500 12px/1.5 var(--fam);color:var(--muted)}\n  .frow{display:flex;gap:12px;margin-bottom:14px;flex-wrap:wrap}\n  .mfield{flex:1 1 160px;min-width:0;display:flex;flex-direction:column;gap:6px}\n  .mfield.grow{flex:1 1 100%}\n  .mfield.tog{flex:0 0 auto;align-items:flex-start}\n  .mfield label{font:700 11px/1 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.04em}\n  .mfield input,.mfield textarea{border:1.5px solid var(--hair);border-radius:10px;padding:10px 12px;font:500 13px/1.4 var(--fam);color:var(--ink);background:var(--surface);outline:none;box-sizing:border-box;width:100%}\n  .mfield textarea.mono{font:500 12px/1.5 'SF Mono',ui-monospace,Menlo,monospace}\n  .mfield input:focus,.mfield textarea:focus{border-color:var(--mag)}\n  .tog{width:44px;height:26px;border-radius:999px;border:none;background:var(--hair);position:relative;cursor:pointer;transition:background .15s;padding:0}\n  .tog.on{background:var(--money)}\n  .tog .knob{position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.3);transition:left .15s}\n  .tog.on .knob{left:21px}\n  .mfoot{display:flex;justify-content:flex-end;gap:10px;margin-top:8px}\n  .prow{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:14px}\n  .pfield{flex:1 1 160px;display:flex;flex-direction:column;gap:6px}\n  .pfield label{font:700 11px/1 'SF Mono',ui-monospace,Menlo,monospace;color:var(--mag)}\n  .pfield input{border:1.5px solid var(--hair);border-radius:10px;padding:9px 12px;font:500 13px/1.4 var(--fam);color:var(--ink);outline:none}\n  .pfield input:focus{border-color:var(--mag)}\n  .rout{margin-top:6px}\n  .rmeta{font:700 12px/1 var(--fam);color:var(--money);margin-bottom:8px}\n  .rsqlbox{margin-bottom:10px}\n  .rerr{background:rgba(214,20,25,.10);color:#c00d11;padding:12px 14px;border-radius:10px;font:600 12.5px/1.5 var(--fam)}\n  .spin{width:12px;height:12px;border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;animation:sp .7s linear infinite;display:inline-block}\n  @keyframes sp{to{transform:rotate(360deg)}}\n  `,\n  render(d2){\n    const t = tok(d2);\n    const all = queries(d2);\n    const q = String(d2.state.q||'').trim().toLowerCase();\n    let list = all.slice();\n    if(q) list = list.filter(r=>String(r.name||'').toLowerCase().includes(q)||String(r.description||'').toLowerCase().includes(q)||String(r.sql||'').toLowerCase().includes(q));\n    list = list.slice().sort((a,b)=>String(a.name||'').localeCompare(String(b.name||'')));\n    const cards = list.length\n      ? list.map(x=>rowCard(d2,x)).join('')\n      : `<div class=\"empty\">Nenhuma consulta ainda. Crie a primeira.</div>`;\n    const toastEl = d2.state.toast?`<div class=\"toast in\">${esc(d2.state.toast)}</div>`:'';\n    return `<div class=\"screen\" style=\"${cssVars(t)}\">\n      <div class=\"header\">\n        <div class=\"htop\">\n          <div class=\"htitle\">\n            <h1>Consultas <span class=\"badge\">Query Library</span></h1>\n            <p>Biblioteca de consultas SQL parametrizadas (<code>{{param}}</code>) executadas ao vivo no Databricks pelo runner <code>pilotRunQuery</code>. Crie, edite e teste consultas; veja o calendário de ciclos por grupo abaixo.</p>\n          </div>\n          <button class=\"newbtn\" data-new>${ICON.plus} Nova consulta</button>\n        </div>\n        <div class=\"toolbar\">\n          <div class=\"search\"><span class=\"si\">${ICON.search}</span><input type=\"text\" data-q value=\"${esc(d2.state.q||'')}\" placeholder=\"buscar por nome, descrição ou SQL\"/></div>\n          <span class=\"count\">${list.length} de ${all.length}</span>\n        </div>\n      </div>\n      <div class=\"body\">\n        ${cards}\n        ${calendarPanel(d2)}\n      </div>\n      ${editModal(d2)}\n      ${runModal(d2)}\n      ${toastEl}\n    </div>`;\n  },\n  mounted(d2){\n    if(!d2.state.runParams) d2.state.runParams = {};\n    const openEdit = (row)=>{ d2.setState({ editOpen:true, edit: row?JSON.parse(JSON.stringify(row)):{ active:true, variables:[] } }); };\n    const closeEdit = ()=> d2.setState({ editOpen:false, edit:null });\n\n    d2.on('[data-new]','click',()=> openEdit(null));\n    d2.on('[data-edit]','click',(e,el)=>{ const id=el.dataset.edit; const row=queries(d2).find(x=>x._id===id); openEdit(row); });\n    d2.on('[data-mclose]','click',()=> closeEdit());\n    d2.on('[data-mbg]','click',(e,el)=>{ if(e.target===el) closeEdit(); });\n\n    d2.on('[data-mfield]','input',(e,el)=>{ const k=el.dataset.mfield; const m=Object.assign({}, d2.state.edit); m[k]=el.value; d2.state.edit=m; });\n    d2.on('[data-mtog]','click',(e,el)=>{ const k=el.dataset.mtog; const cur=d2.state.edit||{}; const m=Object.assign({}, cur); m[k]=(cur[k]===false)?true:false; if(k==='active') m.active=(cur.active===false); d2.setState({ edit:m }); });\n\n    d2.on('[data-msave]','click',async()=>{\n      const m = Object.assign({}, d2.state.edit||{});\n      if(!String(m.name||'').trim()){ toast(d2,'Nome é obrigatório'); return; }\n      m.variables = Array.isArray(m.variables)?m.variables:parseVars(m.variables);\n      const before = m._id ? (queries(d2).find(x=>x._id===m._id)||{}) : {};\n      try{\n        const r = await write(d2,{ op:'upsert', row:m, before });\n        const ok = r && (r.ok || (r.data&&r.data.ok));\n        if(ok){ closeEdit(); refresh(d2); toast(d2,'Consulta salva'); }\n        else toast(d2,'Falha ao salvar');\n      }catch(err){ toast(d2,'Erro: '+String(err&&err.message||err)); }\n    });\n\n    d2.on('[data-delask]','click',(e,el)=> d2.setState({ confirmDel: el.dataset.delask }));\n    d2.on('[data-delcancel]','click',()=> d2.setState({ confirmDel:null }));\n    d2.on('[data-del]','click',async(e,el)=>{\n      const id = el.dataset.del; const row = queries(d2).find(x=>x._id===id)||{ _id:id };\n      try{\n        const r = await write(d2,{ op:'delete', row:{ _id:id }, before:row });\n        const ok = r && (r.ok || (r.data&&r.data.ok));\n        d2.setState({ confirmDel:null });\n        if(ok){ refresh(d2); toast(d2,'Consulta excluída'); } else toast(d2,'Falha ao excluir');\n      }catch(err){ d2.setState({ confirmDel:null }); toast(d2,'Erro: '+String(err&&err.message||err)); }\n    });\n\n    // ---- runner ----\n    d2.on('[data-run]','click',(e,el)=>{ d2.setState({ runOpen:true, runId:el.dataset.run, runParams:{}, runResult:null, running:false }); });\n    d2.on('[data-rclose]','click',()=> d2.setState({ runOpen:false, runResult:null, running:false }));\n    d2.on('[data-rbg]','click',(e,el)=>{ if(e.target===el) d2.setState({ runOpen:false, runResult:null, running:false }); });\n    d2.on('[data-pfield]','input',(e,el)=>{ const k=el.dataset.pfield; const rp=Object.assign({}, d2.state.runParams); rp[k]=el.value; d2.state.runParams=rp; });\n    d2.on('[data-rgo]','click',async()=>{\n      const id = d2.state.runId; const q = queries(d2).find(x=>x._id===id); if(!q) return;\n      d2.setState({ running:true, runResult:null });\n      try{\n        const r = await runner(d2,{ name:q.name, params:(d2.state.runParams||{}) });\n        const payload = (r&&r.data)?r.data:r;\n        d2.setState({ running:false, runResult: payload });\n      }catch(err){ d2.setState({ running:false, runResult:{ error:String(err&&err.message||err) } }); }\n    });\n\n    // ---- calendar ----\n    d2.on('[data-caltoggle]','click',()=> d2.setState({ calOpen: !d2.state.calOpen }));\n    d2.on('[data-calfilter]','input',(e,el)=>{ d2.state.calFilter = el.value; });\n\n    d2.on('[data-q]','input',(e,el)=>{ d2.state.q = el.value; });\n  }\n};"}},"queryLib":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"queryLib"}}}},"queryCalendar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"queryCalendar"}}}},"queryWriter":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"queryWriter"}}}},"runner":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"runner"}}}}}}}}}},{"_id":"6a7cc8df7c3ad3f0fdbceac8","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotDocV1V2","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n.doc{height:100%;overflow-y:auto;background:#eef1f5;color:#1c2230;font:15px/1.65 -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif}\n.doc *{box-sizing:border-box}\n.wrap{max-width:1020px;margin:0 auto;padding:0 24px 96px}\n.hero{margin:0 0 8px;padding:56px 28px 40px;background:linear-gradient(135deg,#ff6a3d,#e5197b 58%,#7b2ff7);color:#fff}\n.hero h1{margin:0 0 10px;font-size:34px;font-weight:800;letter-spacing:-.02em}\n.hero p{margin:0;font-size:17px;line-height:1.5;opacity:.96;max-width:74ch}\n.pills{margin-top:22px;display:flex;flex-wrap:wrap;gap:8px}\n.pill{background:rgba(255,255,255,.16);border:1px solid rgba(255,255,255,.30);padding:5px 11px;border-radius:999px;font-size:12.5px;font-weight:600}\nh2{margin:46px 0 14px;font-size:22px;font-weight:800;letter-spacing:-.01em;padding-left:12px;border-left:4px solid #e5197b}\nh3{margin:24px 0 10px;font-size:16px;font-weight:700;color:#2a3040}\nh4{margin:0 0 8px;font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:.04em;color:#c01362}\np{margin:0 0 12px}\n.lead{font-size:16px;color:#3a4256}\nul{margin:0 0 14px;padding-left:20px}li{margin:5px 0}\ncode{background:#dde3ec;padding:1px 6px;border-radius:5px;font:12.5px/1.4 'SF Mono',ui-monospace,Menlo,Consolas,monospace;color:#0b3a6b;white-space:nowrap}\n.grid2{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin:16px 0}\n@media(max-width:760px){.grid2{grid-template-columns:1fr}}\n.card{background:#fff;border:1px solid #d7dde6;border-radius:14px;padding:16px 18px 8px;box-shadow:0 1px 3px rgba(20,30,50,.05)}\n.card.v1{border-top:4px solid #8a94a6}\n.card.v2{border-top:4px solid #16a34a}\n.card h3{margin-top:2px}\n.badge{display:inline-block;font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;padding:3px 8px;border-radius:6px;margin-bottom:8px}\n.badge.b1{background:#eceff3;color:#5a6474}\n.badge.b2{background:#dcfce7;color:#15803d}\n.tw{overflow-x:auto;margin:12px 0 20px;border:1px solid #d7dde6;border-radius:12px}\ntable{width:100%;border-collapse:collapse;font-size:13px;background:#fff;min-width:600px}\nth,td{text-align:left;padding:9px 12px;border-bottom:1px solid #e6eaf0;vertical-align:top}\nth{background:#f5f7fa;font-weight:700;color:#3a4256}\ntr:last-child td{border-bottom:0}\ntd code{font-size:11.5px;background:#eef2f7;white-space:normal}\n.cat td{background:#f0f3f8;font-weight:800;color:#2a3040;font-size:11.5px;text-transform:uppercase;letter-spacing:.04em}\n.callout{background:#fff;border:1px solid #d7dde6;border-left:4px solid #e5197b;border-radius:10px;padding:14px 16px;margin:12px 0}\n.callout h3{margin:0 0 6px;color:#c01362}\n.callout.ok{border-left-color:#16a34a}.callout.ok h3{color:#15803d}\n.callout.warn{border-left-color:#d97706}.callout.warn h3{color:#b45309}\n.muted{color:#6a7383;font-size:13px}\n.foot{margin-top:52px;padding-top:16px;border-top:1px solid #d7dde6;color:#6a7383;font-size:13px}\n.phases{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0 16px}\n.phase{background:#fff;border:1px solid #d7dde6;border-radius:8px;padding:6px 10px;font-size:12.5px;font-weight:600;color:#2a3040}\n.phase b{color:#e5197b}\n.svgwrap{background:#fff;border:1px solid #d7dde6;border-radius:12px;padding:16px;margin:14px 0;overflow-x:auto}\n.emap{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:8px 0 18px}\n@media(max-width:760px){.emap{grid-template-columns:1fr}}\n.ec{background:#fff;border:1px solid #d7dde6;border-radius:12px;padding:14px 16px}\n.ec.g h4{color:#15803d}\n.edge{font-size:13px;margin:5px 0;color:#2a3040}\n.edge b{color:#0b3a6b;font-weight:700}\n.ar{color:#e5197b;font-weight:800;padding:0 5px}\n.fc{background:#fff;border:1px solid #d7dde6;border-radius:12px;padding:14px 16px;margin:12px 0}\n.fc h3{margin:0 0 2px;color:#2a3040}\n.fc p{margin:4px 0 8px;font-size:14px;color:#3a4256}\n.flow{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:8px 0 2px}\n.step{background:#eef2ff;border:1px solid #c7d2fe;color:#3730a3;border-radius:8px;padding:5px 9px;font-size:12px;font-weight:600;font-family:'SF Mono',ui-monospace,Menlo,monospace}\n.sep{color:#94a3b8;font-weight:800;font-size:14px}\n`,\n  render(){\n    return `<div class=\"doc\"><div class=\"wrap\">\n<div class=\"hero\">\n  <h1>natura-x-piloto — V1 × V2</h1>\n  <p>Dashboard de remuneração variável da consultora Natura. Esta é a doc do rebuild net-new no Data2 (V2), feito como stress test de um build <b>spec-driven</b> — \"The Data2 Way\". A V1 é o piloto em produção; a V2 atingiu paridade funcional sem tocar em prod.</p>\n  <div class=\"pills\">\n    <span class=\"pill\">systemId 688179c2a93dd170ce61e598</span>\n    <span class=\"pill\">as-of 2026-08-12</span>\n    <span class=\"pill\">42 tabelas · 19 PILOT ·</span>\n    <span class=\"pill\">37 listeners</span>\n    <span class=\"pill\">âncora: grupo 20200 rede1 diamante = R$ 680,00</span>\n  </div>\n</div>\n\n<h2>1 · TL;DR</h2>\n<ul class=\"lead\">\n  <li><b>O que é:</b> painel de remuneração variável com drill GV → GN → Líder; cada perfil enxerga a própria estrutura para baixo.</li>\n  <li><b>O que faz:</b> calcula o ganho variável de cada consultora por ciclo, a partir de KPIs da API de performance da Natura + Databricks, aplicando um <b>rules-engine versionado</b>, e entrega num dashboard escopado por perfil — com admin pra editar as regras, simulador e histórico.</li>\n  <li><b>O que foi a V2:</b> reconstrução limpa do piloto direto no Data2, via o MCP <code>data2-builder</code>, seguindo uma metodologia spec-driven de 12 fases (dado primeiro, contratos, comportamento, UI por último). Rodou num workspace isolado (<code>🧪 rebuild-pilot</code>).</li>\n  <li><b>Veredito do experimento:</b> metodologia <b>8.5/10</b>, ergonomia da plataforma <b>6/10</b>, loop dispatch/verify/memory <b>9/10</b>. Nada foi publicado em prod — a V2 fica atrás de <code>resolveActingIdentity()</code>; o cutover troca só a fonte, não o formato.</li>\n</ul>\n\n<h2>2 · Escopo &amp; features (o que a spec entregou)</h2>\n<p class=\"lead\">A spec começou como \"vertical slice do dashboard principal\" e foi além, até um <b>substituto funcional</b> do piloto. O que entrou:</p>\n<ul>\n  <li><b>Dashboard 3 perfis</b> — GV→GN→Líder com drill real + agregação grupo/setor, sobre dados live da API. <span class=\"muted\">(live-real)</span></li>\n  <li><b>Engine de ganhos config-driven</b> — band tables (fixo &amp; multiplicador) + fórmula estruturada (rede1 soma-de-parcelas, rede2 multiplicador×volume) + regras de bônus; versionado ruleset→cycle, editável por GUI.</li>\n  <li><b>Admin completo</b> — indicadores, regras (bands/bônus/construtor de fórmula), rulesets, binding de ciclo, gerenciador de KPI, viewers de audit-log + access-log.</li>\n  <li><b>Simulador</b> — auto-carrega a produção real de uma consultora; sliders por KPI (meta/realizado); re-simulação ao vivo; escada de remuneração com faixa ativa destacada. <b>+ Histórico</b>.</li>\n  <li><b>Impersonation formal</b> + modelo two-app prod-compliant, seam <code>resolveActingIdentity</code>, scope locks por identidade efetiva.</li>\n</ul>\n<div class=\"callout\">\n  <h3>Proveniência dos dados</h3>\n  <p><b>Live-real:</b> KPIs, metas e remuneração vêm da API/Databricks de verdade. <b>Seeded mirror:</b> identidade + hierarquia (setor/grupo/usuário) são espelhos semeados atrás do resolver — o cutover de prod troca a <i>fonte</i>, não o shape.</p>\n</div>\n<div class=\"callout warn\">\n  <h3>Fora de escopo / pendente</h3>\n  <p>Nada publicado em prod. O <b>IR/compiler</b> (v2 do produto app-builder) não foi exercido. O <b>cutover de prod</b> — plugar a fonte real de identidade no seam — fica pendente, junto do <b>natura-piloto-hardening</b> (fechar as leituras abertas).</p>\n</div>\n\n<h2>3 · O produto</h2>\n<p>Remuneração por duas redes com regra dependente de ciclo, mais bônus por cima:</p>\n<ul>\n  <li><b>rede1</b> = soma de parcelas · <b>rede2</b> = multiplicador × volume.</li>\n  <li>Perfis / grãos: <b>GV → GN → Líder</b> (hierarquia de drill; cada um vê para baixo).</li>\n  <li>Fontes de dado: uma API principal da Natura (performance) + Databricks (espalhado). Na V1 há ainda Tableau.</li>\n</ul>\n\n<h2>4 · V1 × V2 — visão geral</h2>\n<div class=\"grid2\">\n  <div class=\"card v1\">\n    <span class=\"badge b1\">V1 · prod original</span>\n    <h3>Modelo ad-hoc, dados espalhados</h3>\n    <ul>\n      <li>KPIs num <b>tabelão denormalizado</b> (display + cálculo + validade-por-ciclo + prompt no mesmo registro).</li>\n      <li>Faixas e fórmulas espalhadas em várias tabelas + view client-side; regra é dado cravado.</li>\n      <li><b>Caches manuais</b> (painelCache, getGnGoalsCache, getLeaderGoalsCache).</li>\n      <li>Identidade simples: <code>email / name / password</code>.</li>\n      <li>Fluxos: listeners <code>getKPIsGN/Leader</code>, <code>getSimulationLider</code>, <code>goals-por-grupo</code>, <code>getPoints</code>, schedulers de fechamento.</li>\n    </ul>\n  </div>\n  <div class=\"card v2\">\n    <span class=\"badge b2\">V2 · rebuild Data2</span>\n    <h3>Engine config-driven, modelo normalizado</h3>\n    <ul>\n      <li><b>Regras vivem em tabelas versionadas</b> (ruleset ↔ cycle). \"Mudar regra\" = editar linha, não código.</li>\n      <li>Modelo normalizado com FKs e enums explícitos; admin GUI = CRUD sobre as tabelas de config.</li>\n      <li><b>Simulador reusa o mesmo engine</b> via <code>inputsOverride</code>.</li>\n      <li>Identidade one-seam (4 modos) + <b>impersonation formal</b> com scope efetivo.</li>\n      <li>UI também é config-driven (dashboard-config → dashboard-item); listeners <code>PILOT ·</code> por recurso.</li>\n    </ul>\n  </div>\n</div>\n\n<h2>5 · Metodologia — dois eixos de \"v1/v2\"</h2>\n<p>Cuidado com a ambiguidade: existem <b>dois</b> eixos v1/v2 no projeto.</p>\n<div class=\"grid2\">\n  <div class=\"card\">\n    <h3>Eixo A — o app</h3>\n    <p class=\"muted\"><b>V1</b> = o piloto rodando em produção (API Natura + Databricks + Tableau).<br><b>V2</b> = o rebuild net-new dentro do Data2 seguindo The Data2 Way.</p>\n  </div>\n  <div class=\"card\">\n    <h3>Eixo B — o produto (app-builder)</h3>\n    <p class=\"muted\"><b>v1</b> = \"agent path\" — sub-agentes briefados + MCP cru + KB de footguns + verify em <code>.data2.qa</code> + loop findings→memory. <b>Provado.</b><br><b>v2</b> = IR/compiler determinístico (idempotência, drift, diff/apply). Aposta de escala; <b>não</b> pode travar o v1.</p>\n  </div>\n</div>\n<h3>The Data2 Way — 12 fases (gate por fase)</h3>\n<div class=\"phases\">\n  <span class=\"phase\"><b>0</b> Foundation</span>\n  <span class=\"phase\"><b>1</b> Data models</span>\n  <span class=\"phase\"><b>2</b> Schemas</span>\n  <span class=\"phase\"><b>3</b> Identity &amp; access</span>\n  <span class=\"phase\"><b>4</b> Client state</span>\n  <span class=\"phase\"><b>5</b> Integrations</span>\n  <span class=\"phase\"><b>6</b> Endpoints &amp; flows</span>\n  <span class=\"phase\"><b>7</b> Design system</span>\n  <span class=\"phase\"><b>8</b> Reusable UI</span>\n  <span class=\"phase\"><b>9</b> Screens</span>\n  <span class=\"phase\"><b>10</b> Navigation</span>\n  <span class=\"phase\"><b>11</b> Verify &amp; publish</span>\n</div>\n<p class=\"muted\">Doutrina: <b>dado primeiro, contratos, comportamento, UI por último</b>. Tela é projeção de dado + endpoint; construí-la cedo é retrabalho. Não se começa a fase N+1 sem o gate de N passar.</p>\n\n<h2>6 · Decisões load-bearing</h2>\n<div class=\"callout\">\n  <h3>Two-app identity + um único seam</h3>\n  <p>Prod são <b>dois apps</b> com uma só lógica de escopo. <b>App A (GV/Admin):</b> login full-dashboard; impersonation mora aqui. <b>App B (token-in-URL):</b> identidade chega como token na URL, escopada (GN → só seu setor; Líder → só seu grupo). Regra de conformidade: impersonar GN X no App A tem que dar <b>exatamente</b> o que GN X vê no App B. Tudo passa por <code>resolveActingIdentity()</code>; o cutover de prod troca só a fonte, não o shape.</p>\n</div>\n<div class=\"callout ok\">\n  <h3>Config-driven rules engine</h3>\n  <p>O engine de ganhos lê as regras de tabelas (<code>kpi-definition</code> · <code>band-table</code> · <code>earning-band</code> · <code>earning-formula.structure</code> · <code>bonus-rule</code>, versionadas por <code>ruleset</code> → <code>cycle</code>). Consequência: o admin GUI <i>cai fora</i> do modelo de dados (é só CRUD), e o Simulador reusa a mesma computação de produção.</p>\n</div>\n<div class=\"callout ok\">\n  <h3>Avaliação nativa estruturada, não Formula() string</h3>\n  <p>rede1 = soma-de-produtos, rede2 = multiplicador × volume, avaliados <b>nativamente</b> no handler a partir do campo <code>structure</code> — não uma string <code>Formula()</code>. Isso rebaixou \"expor Formula no parser\" de blocker para nice-to-have.</p>\n</div>\n<div class=\"callout\">\n  <h3>Seeded-vs-live por camada</h3>\n  <p>KPIs/metas/remuneração rodaram <b>live-real</b>; identidade + hierarquia foram <b>seeded mirrors</b> atrás do resolver. Toda camada declara se é live ou espelho, para o cutover trocar fonte e não formato.</p>\n</div>\n<div class=\"callout\">\n  <h3>Identity seam = 4 modos</h3>\n  <p><code>session</code> (email/senha) · <code>idp</code> (OAuth/OIDC/SAML — SSO Natura/Maia) · <code>token-url</code> (app escopado) · <code>impersonation</code> (efetivo ≠ acting). Todos resolvem para um shape único <code>{userId, perfil, structureCode, scope}</code>; scope e impersonation vivem downstream, provider-agnósticos.</p>\n</div>\n\n<h2>7 · Modelos de dados — real × KB</h2>\n<p>São 42 tabelas no sistema: as legadas (V1) convivem com as <code>PILOT ·</code> (V2). Abaixo os <b>schemas reais puxados do syste</b>, confrontados com o que a KB (context-pack) descrevia.</p>\n\n<h3>V1 — legado (schemas reais)</h3>\n<div class=\"tw\"><table>\n  <tr><th>Tabela</th><th>Campos reais</th><th>Papel</th></tr>\n  <tr><td><code>Kpis/remuneraçao</code></td><td>titulo, agrupamento, rede, color, perfil, index, index_grid, tipo_kpi, icon, marca, acoes, quem_sao (obj), descricao, calculo_do_kpi, indicadores (lookup), prompt, afetado_por_nivel, has_table, table (lookup), ganho, iap, hide, aceleradores_validados_ciclos, ciclos_validado… <b>(28 campos)</b></td><td>KPIs num tabelão: display + cálculo + validade-por-ciclo + prompt tudo junto</td></tr>\n  <tr><td><code>tabelas-remuneração</code></td><td>nome</td><td>stub/ponteiro — praticamente vazio</td></tr>\n  <tr><td><code>lideres_e_niveis</code></td><td>lider, nome, nivel, effective_from, effective_to</td><td>líder → nível, temporal por strings</td></tr>\n  <tr><td><code>GV/Admin users</code></td><td>email, name, password</td><td>identidade de login (herdada; a V2 mantém)</td></tr>\n  <tr><td><code>parametros-faixas-remuneracao (OLD)</code>, <code>formulas-ganhos</code>, <code>🕘parametros-faixas-*</code></td><td>—</td><td>faixas e fórmulas espalhadas + view join client-side</td></tr>\n  <tr><td><code>painelCache</code>, <code>getGnGoalsCache</code>, <code>getLeaderGoalsCache</code></td><td>—</td><td>caches manuais</td></tr>\n  <tr><td><code>🌐 Queries Databricks</code>, <code>query_library</code></td><td>—</td><td>SQL Databricks avulso</td></tr>\n</table></div>\n\n<h3>V2 — PILOT · (schemas reais)</h3>\n<div class=\"tw\"><table>\n  <tr><th>Tabela</th><th>Campos reais (FK → destino)</th><th>Papel</th></tr>\n  <tr class=\"cat\"><td colspan=\"3\">Config / rules engine</td></tr>\n  <tr><td><code>pilot-ruleset</code></td><td>version*, label, status (draft/active/archived)</td><td>versão do conjunto de regras</td></tr>\n  <tr><td><code>pilot-cycle</code></td><td>code* (202605), label, status (open/closed), isCurrent, rulesetVersion → ruleset, dashboardConfigVersion → dashboard-config, startsAt, endsAt</td><td>ciclo amarra ruleset + dashboard</td></tr>\n  <tr><td><code>pilot-kpi-definition</code></td><td>code*, name*, brand (natura/avon/total), hasGoal, sourceGrain (sector/group), aggregation (sum/avg/none), goalKey, valueKey, rede, perfil, source (performance-api/databricks-query), apiIndexCode… <b>(23 campos)</b></td><td>definição declarativa de KPI</td></tr>\n  <tr><td><code>pilot-band-table</code></td><td>ref*, label*, kpiCode → kpi-definition, rede, perfil, valueType (fixed/multiplier), active</td><td>catálogo de faixas</td></tr>\n  <tr><td><code>pilot-earning-band</code></td><td>rulesetVersion → ruleset, bandTable (atingimento/pontos/…/multiplicador), rede, nivel (prata/ouro/diamante), brand, minPct, maxPct, value, bandTableRef → band-table</td><td>linhas de faixa (fixo/multiplicador)</td></tr>\n  <tr><td><code>pilot-earning-formula</code></td><td>rulesetVersion → ruleset, perfil, rede, template ({{}}), <b>structure (object — soma-de-produtos)</b></td><td>fórmula estruturada, avaliada nativa</td></tr>\n  <tr><td><code>pilot-bonus-rule</code></td><td>rulesetVersion → ruleset, perfil, rede, bonusType, conditions[], payoutType (flat/per-unit), payoutValue, perUnitKpiCode → kpi-definition</td><td>regras de bônus</td></tr>\n  <tr class=\"cat\"><td colspan=\"3\">Estrutura (temporal por ciclo)</td></tr>\n  <tr><td><code>pilot-sector</code></td><td>code*, name, gnCode, gnName, rede, effectiveFromCycle, effectiveToCycle, gvName</td><td>setor</td></tr>\n  <tr><td><code>pilot-group</code></td><td>code*, name, sectorCode → sector, leaderCode, leaderName, nivel, rede, effectiveFrom/ToCycle</td><td>grupo → setor</td></tr>\n  <tr class=\"cat\"><td colspan=\"3\">Identidade &amp; acesso</td></tr>\n  <tr><td><code>pilot-user</code></td><td>email*, name, perfil (lider/gn/gv/admin), structureCode, sectorCode, scopeStructureCode, rede, nivel, gvName, <b>naturaId (SSO Natura/Maia)</b></td><td>identidade + escopo efetivo</td></tr>\n  <tr><td><code>pilot-impersonation-rule</code></td><td>actorPerfil (gv/gn), targetPerfil (gn/lider), scope (any/within-sector)</td><td>política de impersonation</td></tr>\n  <tr><td><code>pilot-session</code>, <code>pilot-access-log</code>, <code>pilot-audit-log</code></td><td>—</td><td>sessão + logs de acesso/auditoria</td></tr>\n  <tr class=\"cat\"><td colspan=\"3\">Dashboard (UI config-driven)</td></tr>\n  <tr><td><code>pilot-dashboard-config</code></td><td>version*, label, status</td><td>versão do layout</td></tr>\n  <tr><td><code>pilot-dashboard-item</code></td><td>dashboardConfigVersion → config, perfil, rede, kpiCode → kpi-definition, mainKpiCode, relatedKpiCodes[], section, displayOrder, isBonus…</td><td>card/item declarativo do dashboard</td></tr>\n  <tr><td><code>pilot-dashboard-cache</code>, <code>pilot-query-library</code>, <code>pilot-cycle-calendar</code></td><td>—</td><td>cache de render + biblioteca de queries + calendário de ciclos</td></tr>\n</table></div>\n\n<div class=\"callout warn\">\n  <h3>Real × KB — onde diverge</h3>\n  <p>A KB descrevia o engine como <code>kpi-definition / band-table / earning-formula.structure / bonus-rule / ruleset↔cycle</code>. O syste real <b>confirma todos</b> e vai além: (1) <code>pilot-earning-band</code> guarda as linhas de faixa de fato; (2) <code>sector → group</code> são temporais por ciclo; (3) existe uma camada <code>dashboard-config → dashboard-item</code> que a KB não citava — <b>a UI também é config-driven</b>, não só o cálculo; (4) identidade ganhou tabela própria (<code>user</code> + <code>impersonation-rule</code> + <code>session</code> + access/audit-log), casando com o seam de 4 modos; (5) <code>naturaId</code> no <code>pilot-user</code> é o gancho concreto do SSO Natura (Maia) que a KB só previa como modo genérico <code>token-url/idp</code>.</p>\n</div>\n\n<h2>8 · Mapa de entidades (V2)</h2>\n<p>O eixo do modelo é o <b>versionamento</b>: cada <code>cycle</code> amarra uma <code>ruleset</code> (as regras) e uma <code>dashboard-config</code> (o layout). Trocar de ciclo = apontar para outras versions. Tudo no rules-engine aponta para <code>ruleset</code>; <code>kpi-definition</code> é o hub referenciado por todo lado.</p>\n<div class=\"svgwrap\"><svg viewBox=\"0 0 760 120\" width=\"100%\" style=\"max-width:760px;display:block\">\n  <defs><marker id=\"ah\" markerWidth=\"9\" markerHeight=\"9\" refX=\"7\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L7,3 L0,6 Z\" fill=\"#e5197b\"/></marker></defs>\n  <rect x=\"20\" y=\"40\" width=\"190\" height=\"52\" rx=\"9\" fill=\"#fff\" stroke=\"#8a94a6\" stroke-width=\"1.5\"/>\n  <text x=\"115\" y=\"63\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" fill=\"#1c2230\">pilot-ruleset</text>\n  <text x=\"115\" y=\"80\" text-anchor=\"middle\" font-size=\"11\" fill=\"#6a7383\">version · status</text>\n  <rect x=\"285\" y=\"40\" width=\"190\" height=\"52\" rx=\"9\" fill=\"#fff5fa\" stroke=\"#e5197b\" stroke-width=\"1.8\"/>\n  <text x=\"380\" y=\"63\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"800\" fill=\"#c01362\">pilot-cycle</text>\n  <text x=\"380\" y=\"80\" text-anchor=\"middle\" font-size=\"11\" fill=\"#6a7383\">code · isCurrent</text>\n  <rect x=\"545\" y=\"40\" width=\"195\" height=\"52\" rx=\"9\" fill=\"#fff\" stroke=\"#16a34a\" stroke-width=\"1.5\"/>\n  <text x=\"642\" y=\"63\" text-anchor=\"middle\" font-size=\"12.5\" font-weight=\"700\" fill=\"#15803d\">pilot-dashboard-config</text>\n  <text x=\"642\" y=\"80\" text-anchor=\"middle\" font-size=\"11\" fill=\"#6a7383\">version · status</text>\n  <line x1=\"285\" y1=\"66\" x2=\"216\" y2=\"66\" stroke=\"#e5197b\" stroke-width=\"1.6\" marker-end=\"url(#ah)\"/>\n  <text x=\"250\" y=\"32\" text-anchor=\"middle\" font-size=\"10.5\" fill=\"#c01362\">rulesetVersion</text>\n  <line x1=\"475\" y1=\"66\" x2=\"539\" y2=\"66\" stroke=\"#e5197b\" stroke-width=\"1.6\" marker-end=\"url(#ah)\"/>\n  <text x=\"512\" y=\"32\" text-anchor=\"middle\" font-size=\"10.5\" fill=\"#c01362\">dashboardConfigVersion</text>\n</svg></div>\n<div class=\"emap\">\n  <div class=\"ec\">\n    <h4>Rules engine → ruleset</h4>\n    <div class=\"edge\"><b>earning-band</b><span class=\"ar\">→</span>ruleset · band-table <span class=\"muted\">(rulesetVersion, bandTableRef)</span></div>\n    <div class=\"edge\"><b>earning-formula</b><span class=\"ar\">→</span>ruleset <span class=\"muted\">(rulesetVersion)</span></div>\n    <div class=\"edge\"><b>bonus-rule</b><span class=\"ar\">→</span>ruleset · kpi-definition <span class=\"muted\">(perUnitKpiCode)</span></div>\n    <div class=\"edge\"><b>band-table</b><span class=\"ar\">→</span>kpi-definition <span class=\"muted\">(kpiCode)</span></div>\n  </div>\n  <div class=\"ec\">\n    <h4>Hub: kpi-definition</h4>\n    <div class=\"edge\">Referenciado por <b>band-table</b>, <b>bonus-rule</b>, <b>dashboard-item</b> (kpiCode / mainKpiCode / relatedKpiCodes[]).</div>\n    <div class=\"edge muted\">A definição declarativa de cada indicador — de onde vem o valor (performance-api/databricks), grão, agregação, marca, perfil.</div>\n  </div>\n  <div class=\"ec g\">\n    <h4>Dashboard (config-driven)</h4>\n    <div class=\"edge\"><b>dashboard-item</b><span class=\"ar\">→</span>dashboard-config <span class=\"muted\">(dashboardConfigVersion)</span></div>\n    <div class=\"edge\"><b>dashboard-item</b><span class=\"ar\">→</span>kpi-definition <span class=\"muted\">(kpiCode/main/related)</span></div>\n    <div class=\"edge muted\">O que aparece em tela é linha de tabela, não código.</div>\n  </div>\n  <div class=\"ec\">\n    <h4>Estrutura + Identidade</h4>\n    <div class=\"edge\"><b>group</b><span class=\"ar\">→</span>sector <span class=\"muted\">(sectorCode)</span></div>\n    <div class=\"edge\"><b>user</b><span class=\"ar\">→</span>sector <span class=\"muted\">(sectorCode) · naturaId → SSO</span></div>\n    <div class=\"edge\"><b>impersonation-rule</b> <span class=\"muted\">actorPerfil → targetPerfil + scope</span></div>\n    <div class=\"edge muted\">sector e group são temporais (effectiveFrom/ToCycle). session + access-log + audit-log são satélites.</div>\n  </div>\n</div>\n\n<h2>9 · O que o sistema faz — fluxos</h2>\n<p class=\"lead\">Sete fluxos cobrem o sistema. Cada passo abaixo é um <b>listener real</b> (<code>PILOT ·</code>) do sistema.</p>\n\n<div class=\"fc\">\n  <h3>1 · Identidade (entrada)</h3>\n  <p>Dois caminhos, um só seam. App A resolve login; App B resolve o token da URL (clone fiel do SSO Natura, pronto pra switch).</p>\n  <div class=\"flow\"><span class=\"step\">login (piloto-admin-auth)</span><span class=\"sep\">→</span><span class=\"step\">pilotResolveIdentity</span><span class=\"sep\">→</span><span class=\"step\">pilotUsers (switcher)</span></div>\n  <div class=\"flow\"><span class=\"step\">token na URL</span><span class=\"sep\">→</span><span class=\"step\">pilotResolveSession</span><span class=\"sep\">/</span><span class=\"step\">pilotResolveNaturaSession</span><span class=\"sep\">→</span><span class=\"step\">pilotResolveDisplayCycle</span></div>\n</div>\n\n<div class=\"fc\">\n  <h3>2 · Dashboard (o coração)</h3>\n  <p>Resolve identidade e ciclo, computa os ganhos pelo rules-engine, faz o rollup grupo→setor e monta os cards a partir da config.</p>\n  <div class=\"flow\"><span class=\"step\">pilotResolveIdentity</span><span class=\"sep\">→</span><span class=\"step\">pilotResolveDisplayCycle</span><span class=\"sep\">→</span><span class=\"step\">pilotGetDashboardData</span><span class=\"sep\">→</span><span class=\"step\">pilotGetGroupEarnings</span><span class=\"sep\">→</span><span class=\"step\">pilotGetSectorRollup</span><span class=\"sep\">→</span><span class=\"step\">pilotTrackAccess</span></div>\n  <p class=\"muted\"><code>pilotGetGroupEarnings</code> aplica ruleset/cycle → earning-band + earning-formula + bonus-rule. <code>pilotGetSectorRollup</code> agrega group→sector (sum/avg por KPI). <code>pilotBandTables</code> alimenta as faixas exibidas. Render config-driven via dashboard-config → dashboard-item.</p>\n</div>\n\n<div class=\"fc\">\n  <h3>3 · Impersonation (GV/GN vê para baixo)</h3>\n  <p>A identidade <i>efetiva</i> passa a ser a do alvo; o dashboard re-renderiza no escopo dele — idêntico ao que o alvo veria sozinho.</p>\n  <div class=\"flow\"><span class=\"step\">pilotAllowedTargets</span><span class=\"sep\">→</span><span class=\"step\">pilotImpersonate (start)</span><span class=\"sep\">→</span><span class=\"step\">dashboard no escopo do alvo</span><span class=\"sep\">→</span><span class=\"step\">pilotEndImpersonation</span></div>\n</div>\n\n<div class=\"fc\">\n  <h3>4 · Simulador</h3>\n  <p>Carrega a produção real da consultora, deixa mexer nos KPIs e re-simula reusando o <b>mesmo</b> engine.</p>\n  <div class=\"flow\"><span class=\"step\">carrega produção real</span><span class=\"sep\">→</span><span class=\"step\">sliders por KPI (meta/realizado)</span><span class=\"sep\">→</span><span class=\"step\">pilotSimulate (inputsOverride)</span><span class=\"sep\">→</span><span class=\"step\">escada de remuneração</span></div>\n</div>\n\n<div class=\"fc\">\n  <h3>5 · Histórico</h3>\n  <div class=\"flow\"><span class=\"step\">pilotHistorico</span><span class=\"sep\">→</span><span class=\"step\">ganhos por ciclos anteriores</span></div>\n</div>\n\n<div class=\"fc\">\n  <h3>6 · Admin (config-as-data)</h3>\n  <p>Gated por <code>piloto-admin-auth</code>. Editar regra = editar tabela e subir uma nova <b>version</b> de ruleset/dashboard-config, que o <code>cycle</code> passa a apontar.</p>\n  <div class=\"flow\"><span class=\"step\">pilotAdminRuleWrite</span><span class=\"sep\">·</span><span class=\"step\">pilotAdminItemWrite</span><span class=\"sep\">·</span><span class=\"step\">pilotQueryLibWrite</span><span class=\"sep\">→</span><span class=\"step\">nova version</span><span class=\"sep\">→</span><span class=\"step\">bind no cycle</span></div>\n  <p class=\"muted\">Telas: PILOT · Admin — Home / KPIs / Regras / Rulesets / Ciclos / Indicadores / Auditoria.</p>\n</div>\n\n<div class=\"fc\">\n  <h3>7 · Dados externos / fechamento</h3>\n  <p>Schedulers puxam Databricks e geram fechamentos por ciclo; queries parametrizadas rodam da query-library.</p>\n  <div class=\"flow\"><span class=\"step\">🌐 Bricks Scheduler</span><span class=\"sep\">·</span><span class=\"step\">Gera fechamentos (líderes/gerentes)</span><span class=\"sep\">·</span><span class=\"step\">pilotRunQuery</span><span class=\"sep\">→</span><span class=\"step\">Databricks / performance-api</span></div>\n</div>\n\n<div class=\"callout warn\">\n  <h3>Postura de acesso (gates reais)</h3>\n  <p>As <b>leituras do piloto</b> (dashboard, earnings, simulate, histórico) estão <code>Policy(empty=open)</code> — abertas, herança do modo piloto. As <b>escritas de admin e o impersonation</b> são gated por <code>piloto-admin-auth</code>. <code>resolveIdentity/session/users/trackAccess</code> estão <b>UNGATED</b>. Fechar as leituras é item do <b>natura-piloto-hardening</b>.</p>\n</div>\n\n<h2>10 · O que quebrou — lições</h2>\n<ul>\n  <li><b>Fail-silent code-component authoring</b> (maior time-sink): corpo não persiste em silêncio, <code>this</code> solto, preview renderiza frame preto → stub-then-patch e verificar só em <code>.data2.qa</code>.</li>\n  <li><b>Descoberta lida como impossibilidade:</b> agente concluiu 2× que algo buildável era impossível (Schema sem <code>create_schema</code>; parser rejeita <code>Formula()</code>). Ambos buildáveis.</li>\n  <li><b>Write-but-don't-wire:</b> o resolver de impersonation foi autorado mas nunca wired no mount — parecia pronto, estava inerte. Daí o gate <b>\"wire-it-and-prove-it\"</b>.</li>\n  <li><b>Config mal-taggeada</b> vira bug de <i>dado</i> silencioso (band table rede2 marcada <code>perfil:gn</code> escondeu a tabela do líder) → <code>oneOf</code> + lint.</li>\n  <li><b>Stale-published-app:</b> \"está quebrado\" era o owner vendo o app publicado enquanto o fix vivia no draft → explicar draft × published no kickoff.</li>\n</ul>\n\n<h2>11 · Estado &amp; fontes</h2>\n<ul>\n  <li><b>sistema:</b> <code>natura-x-piloto</code> (688179c2a93dd170ce61e598). Apps: <code>PILOT · Admin App</code> (pilot-admin), <code>piloto-dashboard-view</code> (novo-piloto). Workspace de build: <code>🧪 rebuild-pilot</code>.</li>\n  <li><b>Auth strategies:</b> piloto-admin-auth · admin-view-auth · <code>PILOT · Maia Auth</code> (consultora SSO).</li>\n  <li><b>Context pack completo:</b> repo <code>natura-x-piloto-context</code> (CONTEXT.md + memory/ com 45+ notas de gotcha do Data2).</li>\n  <li><b>Vault:</b> <code>Projects/natura-x-piloto</code> + <code>Resources/clients/natura/piloto</code>.</li>\n  <li><b>Âncora de regressão (nunca quebra):</b> grupo 20200 rede1 diamante = <b>R$ 680,00</b>.</li>\n</ul>\n\n<div class=\"foot\">Gerado 2026-08-12 a partir dos schemas + listeners reais do sistema + context-pack da V2. Nada publicado em prod.</div>\n</div></div>`\n  }\n}"}}}}}}}},{"_id":"6aa82ceaf4b70a9a69324073","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotQtShell","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"// PILOT · QT Shell — o Query Tester inteiro em UM code component.\n//\n// Monolítico de propósito. A versão anterior quebrava a tela em 8 componentes\n// (sidebar/card/sqlView/result/detail/editModal/runModal) e esbarrava nos limites\n// de composição do CodeHost deste build: callback de opts não atravessa o shadow\n// boundary, filho já montado não re-renderiza quando o param muda, e clique dentro\n// de filho renderizado em loop não chega aos handlers dele. Um shadow root só, um\n// delegador de eventos só, um estado só — nenhum desses limites se aplica aqui.\n//\n// Estado: tudo em d2.state. Não há d2.bus nem d2.shared porque não há mais irmãos.\n// Formulários: o DOM é a fonte da verdade enquanto o modal está aberto; sincronizo\n// para o state antes de qualquer setState que provoque re-render, para nunca\n// perder o que foi digitado.\n\nconst T = {\n  surface:'#FFFFFF', ground:'#FAFAFB', ink:'#1A1C1E', muted:'#6B7280',\n  hair:'rgba(16,24,40,0.08)', mag:'#E5004B', orange:'#EB6619',\n  grad:'linear-gradient(135deg,#E5004B 0%,#EB6619 55%,#F7BE00 100%)',\n  money:'#29AC56', red:'#FF1418',\n  fam:\"'Roboto',system-ui,-apple-system,sans-serif\",\n  mono:\"'SF Mono',ui-monospace,Menlo,Consolas,monospace\",\n  shadowcard:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',\n  shadowraised:'0 18px 48px rgba(16,24,40,0.22)'\n};\nfunction cssVars(){\n  return `--surface:${T.surface};--ground:${T.ground};--ink:${T.ink};--muted:${T.muted};`\n    + `--hair:${T.hair};--mag:${T.mag};--orange:${T.orange};--grad:${T.grad};`\n    + `--money:${T.money};--red:${T.red};--fam:${T.fam};--mono:${T.mono};`\n    + `--shadowcard:${T.shadowcard};--shadowraised:${T.shadowraised}`;\n}\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction errMsg(err){ return String((err && err.message) || err); }\n\nconst S = (p)=>`<svg class=\"ic-svg\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${p}</svg>`;\nconst ICON = {\n  plus:   S('<path d=\"M12 5v14M5 12h14\"/>'),\n  search: S('<circle cx=\"11\" cy=\"11\" r=\"7\"/><path d=\"m21 21-4.3-4.3\"/>'),\n  del:    S('<path d=\"M3 6h18\"/><path d=\"M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/>'),\n  ok:     S('<path d=\"M20 6 9 17l-5-5\"/>'),\n  x:      S('<path d=\"M18 6 6 18M6 6l12 12\"/>'),\n  run:    S('<polygon points=\"6 4 20 12 6 20 6 4\"/>'),\n  power:  S('<path d=\"M12 2v10\"/><path d=\"M18.4 6.6a9 9 0 1 1-12.8 0\"/>'),\n  edit:   S('<path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/>'),\n  copy:   S('<rect x=\"9\" y=\"9\" width=\"12\" height=\"12\" rx=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/>'),\n  chev:   S('<path d=\"m9 18 6-6-6-6\"/>')\n};\n\n// ---- SQL highlight: o MutationObserver do highlight.js do app não alcança um\n// shadow root, então o tokenizador mora aqui. ----\nconst KW = 'SELECT|FROM|WHERE|JOIN|LEFT|RIGHT|INNER|FULL|OUTER|CROSS|ON|GROUP|ORDER|BY|HAVING|LIMIT|OFFSET|WITH|AS|AND|OR|NOT|IN|IS|NULL|CASE|WHEN|THEN|ELSE|END|DISTINCT|OVER|PARTITION|UNION|ALL|INSERT|INTO|UPDATE|DELETE|VALUES|SET|DESC|ASC|BETWEEN|LIKE|EXISTS|CREATE|TABLE|VIEW|TEMP|IF';\nconst FN = 'COUNT|SUM|AVG|MIN|MAX|ROW_NUMBER|RANK|DENSE_RANK|LAG|LEAD|COALESCE|NVL|CAST|CONCAT|SUBSTR|SUBSTRING|TRIM|UPPER|LOWER|ROUND|ABS|DATE|DATEDIFF|DATE_ADD|NOW|CURRENT_DATE';\nfunction hl(sql){\n  const src = esc(sql);\n  const re = new RegExp(\n    '(--[^\\\\n]*|\\\\/\\\\*[\\\\s\\\\S]*?\\\\*\\\\/)' +\n    '|(\\\\{\\\\{[^}]*\\\\}\\\\})' +\n    \"|('(?:[^']|'')*')\" +\n    '|\\\\b(' + FN + ')(?=\\\\s*\\\\()' +\n    '|\\\\b(' + KW + ')\\\\b' +\n    '|\\\\b(\\\\d+(?:\\\\.\\\\d+)?)\\\\b', 'gi');\n  return src.replace(re,(m,com,vr,str,fn,kw,num)=>{\n    if(com) return '<span class=\"t-com\">'+com+'</span>';\n    if(vr)  return '<span class=\"t-var\">'+vr+'</span>';\n    if(str) return '<span class=\"t-str\">'+str+'</span>';\n    if(fn)  return '<span class=\"t-fn\">'+fn+'</span>';\n    if(kw)  return '<span class=\"t-kw\">'+kw+'</span>';\n    if(num) return '<span class=\"t-num\">'+num+'</span>';\n    return m;\n  });\n}\n\nfunction varsOf(row){\n  const out=[], seen={};\n  const push=(v)=>{ v=String(v==null?'':v).trim(); if(v && !seen[v]){ seen[v]=1; out.push(v); } };\n  (String((row&&row.sql)||'').match(/\\{\\{([^}]*)\\}\\}/g)||[]).forEach(x=>push(x.replace(/^\\{\\{|\\}\\}$/g,'')));\n  const st = row && row.variables;\n  if(Array.isArray(st)) st.forEach(push);\n  else if(typeof st === 'string') st.split(',').forEach(push);\n  return out;\n}\n\n// ---- dados ----\nfunction dsOf(d2){ return d2.data('queryLib'); }\nfunction sortedRows(d2){\n  const ds = dsOf(d2);\n  const all = (ds && ds.records && ds.records()) || [];\n  return all.slice().sort((a,b)=>String(a.name||'').localeCompare(String(b.name||'')));\n}\nfunction visibleRows(d2){\n  const all = sortedRows(d2);\n  const term = String(d2.state.q||'').trim().toLowerCase();\n  const filt = d2.state.filt || 'all';\n  let list = all;\n  if(filt==='on')  list = list.filter(r=>r.active!==false);\n  if(filt==='off') list = list.filter(r=>r.active===false);\n  if(term) list = list.filter(r=>\n    String(r.name||'').toLowerCase().includes(term) ||\n    String(r.description||'').toLowerCase().includes(term) ||\n    String(r.sql||'').toLowerCase().includes(term));\n  return { all, list };\n}\nfunction curRow(d2){\n  const all = sortedRows(d2);\n  const id = d2.state.selId;\n  return all.find(r=>r._id===id) || all[0] || null;\n}\n\n// ---- ações ----\nfunction toast(d2,msg,kind){\n  d2.setState({ toast:msg, toastKind:kind||'ok', toastKey:(d2.state.toastKey||0)+1 });\n  setTimeout(()=>d2.setState({ toast:null }), 2800);\n}\nfunction actor(d2){ return String(d2.param('actorEmail','') || '').trim() || 'query-tester@pilot'; }\nfunction ok(r){ return !!(r && (r.ok || (r.data && r.data.ok))); }\nfunction refresh(d2){ const ds=dsOf(d2); if(ds && ds.refresh) ds.refresh(); }\nasync function write(d2,payload){ return await d2.rush('queryWriter').invoke(payload); }\n\nasync function doDelete(d2, before){\n  const id = before && before._id;\n  if(!id) return;\n  try{\n    const r = await write(d2,{ op:'delete', actorEmail:actor(d2), row:{ _id:id }, before });\n    d2.setState({ armed:null });\n    if(ok(r)){\n      refresh(d2);\n      if(d2.state.selId===id) d2.setState({ selId:null });\n      toast(d2,'Consulta excluída');\n    } else toast(d2,'Falha ao excluir','err');\n  }catch(err){ d2.setState({ armed:null }); toast(d2,'Erro: '+errMsg(err),'err'); }\n}\nasync function doSave(d2, m){\n  const before = d2.state.editBefore || {};\n  try{\n    const r = await write(d2,{ op:'upsert', actorEmail:actor(d2), row:m, before });\n    if(ok(r)){\n      const newId = (r.id || (r.data && r.data.id)) || m._id;\n      d2.setState({ editOpen:false, editDraft:null, editBefore:null, editErr:null });\n      refresh(d2);\n      if(newId) d2.setState({ selId:newId });\n      toast(d2,'Consulta salva');\n    } else toast(d2,'Falha ao salvar','err');\n  }catch(err){ toast(d2,'Erro: '+errMsg(err),'err'); }\n}\nasync function doToggle(d2, row){\n  if(!row) return;\n  const next = Object.assign({}, row, { active: row.active===false });\n  try{\n    const r = await write(d2,{ op:'upsert', actorEmail:actor(d2), row:next, before:row });\n    if(ok(r)){ refresh(d2); toast(d2, next.active ? 'Consulta ativada' : 'Consulta desativada'); }\n    else toast(d2,'Falha ao alterar estado','err');\n  }catch(err){ toast(d2,'Erro: '+errMsg(err),'err'); }\n}\nasync function doCopy(d2, sql){\n  try{ await navigator.clipboard.writeText(String(sql||'')); toast(d2,'SQL copiado'); }\n  catch(err){ toast(d2,'Não foi possível copiar','err'); }\n}\nasync function doRun(d2, params){\n  const q = d2.state.runRow;\n  if(!q || !q._id) return;\n  const id = q._id;\n  d2.setState({ running:true });\n  const t0 = Date.now();\n  try{\n    const r = await d2.rush('runner').invoke({ name:q.name, params: params||{} });\n    const p = (r && r.data) ? r.data : r;\n    const ms = Date.now() - t0;\n    const lr = Object.assign({}, d2.state.lastRun);\n    lr[id] = (p && p.error)\n      ? { error:String(p.error), ms, raw:p }\n      : { rows:(p && p.rows) || [], sql:(p && p.sql) || '', count:(p && p.count), ms, raw:p };\n    d2.setState({ running:false, runOpen:false, runRow:null, lastRun:lr, selId:id });\n    const n = (lr[id].rows||[]).length;\n    toast(d2,\n      lr[id].error ? 'Erro na consulta' : (n ? n+' linha(s) em '+ms+'ms' : 'O runner respondeu sem linhas'),\n      (lr[id].error || !n) ? 'err' : 'ok');\n  }catch(err){\n    const ms = Date.now() - t0;\n    const lr = Object.assign({}, d2.state.lastRun);\n    lr[id] = { error:errMsg(err), ms, raw:null };\n    d2.setState({ running:false, runOpen:false, runRow:null, lastRun:lr, selId:id });\n    toast(d2,'Erro na consulta','err');\n  }\n}\n\n// ---- sincronização DOM -> state (o modal é a fonte da verdade enquanto aberto) ----\nfunction syncEdit(d2){\n  const m = Object.assign({}, d2.state.editDraft||{});\n  (d2.$$('[data-f]')||[]).forEach(el=>{ m[el.dataset.f] = el.value; });\n  d2.state.editDraft = m;\n  return m;\n}\nfunction syncRun(d2){\n  const v = {};\n  (d2.$$('[data-p]')||[]).forEach(el=>{ v[el.dataset.p] = el.value; });\n  return v;\n}\nfunction varsFromSql(sql){\n  const out=[], seen={};\n  (String(sql||'').match(/\\{\\{([^}]*)\\}\\}/g)||[]).forEach(x=>{\n    const v = x.replace(/^\\{\\{|\\}\\}$/g,'').trim();\n    if(v && !seen[v]){ seen[v]=1; out.push(v); }\n  });\n  return out;\n}\n\n// ---- pedaços de UI ----\nfunction cardHtml(d2, q, sel){\n  const vars = varsOf(q);\n  const armed = d2.state.armed === q._id;\n  return `<div class=\"cardslot${sel?' sel':''}\" data-key=\"${esc(q._id||'')}\" data-pick=\"${esc(q._id||'')}\">\n    <div class=\"acts\">${armed\n      ? `<button class=\"mic ok\" data-del=\"${esc(q._id)}\" title=\"Confirmar exclusão\">${ICON.ok}</button><button class=\"mic\" data-delcancel title=\"Cancelar\">${ICON.x}</button>`\n      : `<button class=\"mic del\" data-delask=\"${esc(q._id)}\" title=\"Excluir\">${ICON.del}</button>`}</div>\n    <div class=\"qcard\">\n      <span class=\"qname\">${esc(q.name||'(sem nome)')}</span>\n      <div class=\"qchips\">\n        <span class=\"chip ${q.active===false?'off':'on'}\">${q.active===false?'inativa':'ativa'}</span>\n        ${vars.length?`<span class=\"chip info\">${vars.length} var${vars.length>1?'s':''}</span>`:''}\n        ${q.dataset?`<span class=\"chip ds\">${esc(q.dataset)}</span>`:''}\n      </div>\n      ${q.description?`<div class=\"qdesc\">${esc(q.description)}</div>`:''}\n    </div>\n  </div>`;\n}\nfunction sideHtml(d2){\n  const { all, list } = visibleRows(d2);\n  const selId = (curRow(d2)||{})._id;\n  const filt = d2.state.filt || 'all';\n  const tab = (k,l)=>`<button class=\"tag${filt===k?' on':''}\" data-filt=\"${k}\">${l}</button>`;\n  const slots = list.length\n    ? list.map(r=>cardHtml(d2, r, r._id===selId)).join('')\n    : `<div class=\"empty-s\">Nenhuma consulta encontrada.</div>`;\n  return `<aside class=\"side\">\n    <div class=\"side-h\">\n      <span class=\"side-t\">Query Library</span>\n      <button class=\"newbtn\" data-new title=\"Nova consulta\">${ICON.plus}</button>\n    </div>\n    <div class=\"side-tools\">\n      <div class=\"search\"><span class=\"si\">${ICON.search}</span><input type=\"text\" data-q value=\"${esc(d2.state.q||'')}\" placeholder=\"buscar\"/></div>\n      <div class=\"tags\">${tab('all','Todas')}${tab('on','Ativas')}${tab('off','Inativas')}</div>\n    </div>\n    <div class=\"count\">${list.length} de ${all.length}</div>\n    <div class=\"side-list\">${slots}</div>\n  </aside>`;\n}\nfunction resultHtml(lr){\n  if(!lr) return '';\n  if(lr.error) return `<div class=\"panel rise\"><div class=\"rerr\">${esc(lr.error)}</div></div>`;\n  const rs = lr.rows || [];\n  if(!rs.length) return `<div class=\"panel rise\">\n    <div class=\"phead\"><span class=\"ptitle\">Preview</span><span class=\"rmeta warn\">sem linhas · ${esc(lr.ms)}ms</span></div>\n    <div class=\"hint\">O runner respondeu sem <code>rows</code>. Payload bruto de <code>pilotRunQuery</code> — use isto para saber se o problema é a query ou o bridge Databricks:</div>\n    <pre class=\"rawbox\"><code>${esc(JSON.stringify(lr.raw||{}, null, 2)).slice(0,4000)}</code></pre>\n  </div>`;\n  const cols = Object.keys(rs[0]);\n  const head = cols.map(c=>`<th>${esc(c)}</th>`).join('');\n  const body = rs.slice(0,100).map((r,i)=>`<tr data-key=\"rr-${i}\">${cols.map(c=>`<td>${esc(r[c])}</td>`).join('')}</tr>`).join('');\n  return `<div class=\"panel rise\">\n    <div class=\"phead\"><span class=\"ptitle\">Preview</span><span class=\"rmeta\">${rs.length} linha(s)${rs.length>100?' · mostrando 100':''} · ${esc(lr.ms)}ms</span></div>\n    <div class=\"tblwrap\"><table class=\"rtbl\"><thead><tr>${head}</tr></thead><tbody>${body}</tbody></table></div>\n  </div>`;\n}\nfunction detailHtml(d2){\n  const ds = dsOf(d2);\n  const q = curRow(d2);\n  if(!q){\n    const msg = !ds ? 'Sem handle de dados: o param <code>queryLib</code> não resolveu nenhum módulo.'\n      : (ds.loading ? 'Carregando consultas…' : 'Crie a primeira consulta para começar a testar.');\n    return `<section class=\"main\"><div class=\"empty\">${msg}</div></section>`;\n  }\n  const lr = (d2.state.lastRun || {})[q._id];\n  const sql = String(q.sql||'');\n  const vars = varsOf(q);\n  const off = q.active===false;\n  const n = lr && lr.rows ? lr.rows.length : 0;\n  const runTxt = !lr ? '—' : (lr.error ? 'erro' : (n ? n+' linha(s) · '+lr.ms+'ms' : 'sem linhas · '+lr.ms+'ms'));\n  const runCls = lr && (lr.error || !n) ? ' warn' : '';\n  return `<section class=\"main\">\n    <div class=\"crumb\"><span>Query Library</span>${ICON.chev}<span class=\"cur\">${esc(q.name||'')}</span></div>\n    <div class=\"dhead\">\n      <div class=\"dtitle\">\n        <h1>${esc(q.name||'')}</h1>\n        ${q.description?`<p>${esc(q.description)}</p>`:''}\n      </div>\n      <div class=\"dacts\">\n        <button class=\"btn ghost ic-power\" data-toggle>${ICON.power} ${off?'Ativar':'Desativar'}</button>\n        <button class=\"btn prim ic-run\" data-run>${ICON.run} Executar</button>\n      </div>\n    </div>\n    <div class=\"meta\">\n      <span class=\"dot\"></span><span class=\"mk\">Databricks</span>\n      <span class=\"sep\">·</span><span>Estado:</span><span class=\"mv ${off?'muted':'good'}\">${off?'inativa':'ativa'}</span>\n      <span class=\"sep\">·</span><span>SQL:</span><span class=\"mv\">${sql.length} car.</span>\n      <span class=\"sep\">·</span><span>Última execução:</span><span class=\"mv${runCls}\">${esc(runTxt)}</span>\n    </div>\n    <div class=\"varsrow\">\n      <span class=\"vlabel\">Variables</span>\n      ${vars.length?vars.map(v=>`<span class=\"vtag\">{{${esc(v)}}}</span>`).join(''):'<span class=\"nohint\">sem parâmetros</span>'}\n    </div>\n    <div class=\"panel\">\n      <div class=\"phead\">\n        <span class=\"ptitle mono\">Databricks SQL</span>\n        <span class=\"pacts\">\n          <button class=\"btn mini ic-edit\" data-edit>${ICON.edit} Editar</button>\n          <button class=\"btn mini ic-copy\" data-copy>${ICON.copy} Copiar</button>\n        </span>\n      </div>\n      <pre class=\"sqlbox\"><code>${sql?hl(sql):'<span class=\"t-com\">-- sem SQL</span>'}</code></pre>\n    </div>\n    ${resultHtml(lr)}\n  </section>`;\n}\nfunction editHtml(d2){\n  if(!d2.state.editOpen) return '';\n  const m = d2.state.editDraft || {};\n  const isNew = !m._id;\n  const varsStr = Array.isArray(m.variables) ? m.variables.join(', ') : (m.variables||'');\n  return `<div class=\"modal-bg\" data-editbg>\n    <div class=\"modal\">\n      <div class=\"mgrad\"></div>\n      <h2>${isNew?'Nova consulta':'Editar consulta'}</h2>\n      <p class=\"msub\">Placeholders <code>{{param}}</code> são substituídos por <code>pilotRunQuery</code> antes de ir ao Databricks.</p>\n      <div class=\"frow\">\n        <div class=\"mfield grow\"><label>Nome (chave)</label><input type=\"text\" data-f=\"name\" value=\"${esc(m.name||'')}\" placeholder=\"ex.: cycle-calendar\"/>${d2.state.editErr?`<div class=\"err\">${esc(d2.state.editErr)}</div>`:''}</div>\n        <div class=\"mfield tg\"><label>Ativa</label><button type=\"button\" class=\"tog${m.active===false?'':' on'}\" data-tog><span class=\"knob\"></span></button></div>\n      </div>\n      <div class=\"frow\"><div class=\"mfield grow\"><label>Descrição</label><textarea data-f=\"description\" rows=\"2\" placeholder=\"O que a consulta retorna.\">${esc(m.description||'')}</textarea></div></div>\n      <div class=\"frow\"><div class=\"mfield grow\"><label>SQL</label><textarea class=\"mono\" data-f=\"sql\" rows=\"10\" placeholder=\"SELECT ... WHERE cd = {{param}}\">${esc(m.sql||'')}</textarea></div></div>\n      <div class=\"frow\">\n        <div class=\"mfield grow\"><label>Variáveis (separadas por vírgula)</label><input type=\"text\" data-f=\"variables\" value=\"${esc(varsStr)}\" placeholder=\"ex.: gerencia, ciclo\"/>\n          <div class=\"hint\">Deixe vazio para derivar dos <code>{{…}}</code> do SQL ao salvar.</div></div>\n        <div class=\"mfield\"><label>Dataset</label><input type=\"text\" data-f=\"dataset\" value=\"${esc(m.dataset||'')}\" placeholder=\"opcional\"/></div>\n      </div>\n      <div class=\"mfoot\">\n        <button class=\"btn ghost\" data-editclose>Cancelar</button>\n        <button class=\"btn prim\" data-save>${isNew?'Criar':'Salvar'}</button>\n      </div>\n    </div>\n  </div>`;\n}\nfunction runHtml(d2){\n  if(!d2.state.runOpen) return '';\n  const q = d2.state.runRow || {};\n  const vars = varsOf(q);\n  const running = !!d2.state.running;\n  const fields = vars.length\n    ? `<div class=\"prow\">${vars.map(v=>`<div class=\"pfield\"><label>{{${esc(v)}}}</label><input type=\"text\" data-p=\"${esc(v)}\" placeholder=\"valor\"/></div>`).join('')}</div>`\n    : `<div class=\"hint pad\">Esta consulta não tem parâmetros.</div>`;\n  return `<div class=\"modal-bg\" data-runbg>\n    <div class=\"modal narrow\">\n      <div class=\"mgrad\"></div>\n      <h2>Executar · ${esc(q.name||'')}</h2>\n      <p class=\"msub\">As linhas voltam do Databricks ao vivo e aparecem no Preview.</p>\n      ${fields}\n      <div class=\"mfoot\">\n        <button class=\"btn ghost\" data-runclose>Cancelar</button>\n        <button class=\"btn prim ic-run${running?' busy':''}\" data-go>${running?'<span class=\"spin\"></span> Executando…':ICON.run+' Executar'}</button>\n      </div>\n    </div>\n  </div>`;\n}\n\nexport default {\n  css: `\n  :host{display:block;height:100%}\n  *{box-sizing:border-box}\n  .wrap{position:relative;display:flex;height:100%;min-height:100%;background:var(--ground);font-family:var(--fam);color:var(--ink)}\n\n  /* ---------- animações ---------- */\n  @keyframes qt-fade{from{opacity:0}to{opacity:1}}\n  @keyframes qt-pop{from{opacity:0;transform:translateY(14px) scale(.965)}to{opacity:1;transform:none}}\n  @keyframes qt-toast{from{opacity:0;transform:translate(-50%,16px) scale(.96)}to{opacity:1;transform:translate(-50%,0) scale(1)}}\n  @keyframes qt-rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}\n  @keyframes qt-spin{to{transform:rotate(360deg)}}\n  @keyframes qt-sheen{from{transform:translateX(-130%) skewX(-18deg)}to{transform:translateX(320%) skewX(-18deg)}}\n  @keyframes qt-shake{10%,90%{transform:translateX(-1px)}30%,70%{transform:translateX(2px)}50%{transform:translateX(-2px)}}\n  @keyframes qt-slide{from{background-position:0% 50%}to{background-position:100% 50%}}\n\n  /* ---------- botões: degradê + microanimação ---------- */\n  .btn{position:relative;overflow:hidden;padding:10px 16px;border-radius:10px;font:700 12.5px/1 var(--fam);cursor:pointer;border:none;white-space:nowrap;display:inline-flex;align-items:center;gap:7px;\n       transition:transform .16s cubic-bezier(.2,.8,.3,1),box-shadow .22s ease,filter .2s ease,background .2s ease,color .2s ease,border-color .2s ease}\n  .btn .ic-svg{width:14px;height:14px;display:block;transition:transform .22s cubic-bezier(.2,.8,.3,1)}\n  .btn.prim{background:var(--grad);background-size:200% 200%;color:#fff;box-shadow:0 4px 14px rgba(229,0,75,.30)}\n  .btn.prim:hover{transform:translateY(-1px);box-shadow:0 10px 24px rgba(229,0,75,.36);animation:qt-slide .6s ease forwards}\n  .btn.prim:active{transform:translateY(0) scale(.97)}\n  .btn.prim::after{content:'';position:absolute;top:-20%;bottom:-20%;left:0;width:34%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.5),transparent);transform:translateX(-130%) skewX(-18deg);pointer-events:none}\n  .btn.prim:hover::after{animation:qt-sheen .8s ease}\n  .btn.prim.busy{pointer-events:none;opacity:.78}\n  .btn.ghost{background:var(--surface);color:var(--muted);border:1px solid var(--hair)}\n  .btn.ghost:hover{background:var(--ground);color:var(--ink);border-color:rgba(16,24,40,.16);transform:translateY(-1px)}\n  .btn.ghost:active{transform:translateY(0) scale(.98)}\n  .btn.mini{padding:7px 11px;border-radius:8px;font-size:11.5px;background:var(--surface);color:var(--muted);border:1px solid var(--hair)}\n  .btn.mini:hover{color:var(--mag);border-color:rgba(229,0,75,.35);background:rgba(229,0,75,.05)}\n  .btn.ic-run:hover .ic-svg{transform:translateX(2px) scale(1.12)}\n  .btn.ic-power:hover .ic-svg{transform:rotate(180deg)}\n  .btn.ic-edit:hover .ic-svg{transform:translate(1px,-1px) rotate(-8deg)}\n  .btn.ic-copy:hover .ic-svg{transform:translateY(-2px)}\n  .spin{width:12px;height:12px;border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;animation:qt-spin .7s linear infinite;display:inline-block}\n\n  /* ---------- sidebar ---------- */\n  .side{flex:0 0 302px;width:302px;display:flex;flex-direction:column;height:100%;min-height:0;background:var(--surface);border-right:1px solid var(--hair)}\n  .side-h{display:flex;align-items:center;gap:10px;padding:20px 18px 14px}\n  .side-t{font:800 19px/1.1 var(--fam);letter-spacing:-.3px;background:var(--grad);background-size:200% 200%;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}\n  .newbtn{margin-left:auto;width:32px;height:32px;flex:0 0 auto;border:none;border-radius:10px;background:var(--grad);background-size:200% 200%;color:#fff;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;box-shadow:0 4px 12px rgba(229,0,75,.28);\n          transition:transform .18s cubic-bezier(.2,.8,.3,1),box-shadow .22s,filter .2s}\n  .newbtn:hover{transform:translateY(-1px) scale(1.06);box-shadow:0 8px 20px rgba(229,0,75,.38);animation:qt-slide .6s ease forwards}\n  .newbtn:active{transform:scale(.92)}\n  .newbtn .ic-svg{width:16px;height:16px;display:block;transition:transform .25s cubic-bezier(.2,.8,.3,1)}\n  .newbtn:hover .ic-svg{transform:rotate(90deg)}\n  .side-tools{padding:0 18px 12px;display:flex;flex-direction:column;gap:10px}\n  .search{display:flex;align-items:center;gap:8px;background:var(--ground);border:1.5px solid var(--hair);border-radius:10px;padding:8px 11px;transition:border-color .2s,box-shadow .2s}\n  .search:focus-within{border-color:var(--mag);box-shadow:0 0 0 3px rgba(229,0,75,.10)}\n  .search input{flex:1;min-width:0;border:none;background:none;outline:none;font:500 13px/1 var(--fam);color:var(--ink)}\n  .search .si{color:var(--muted);display:inline-flex;transition:color .2s,transform .2s}\n  .search:focus-within .si{color:var(--mag);transform:scale(1.1)}\n  .search .si .ic-svg{width:15px;height:15px;display:block}\n  .tags{display:flex;gap:6px}\n  .tag{border:1px solid var(--hair);background:var(--ground);color:var(--muted);border-radius:999px;padding:5px 11px;font:700 11px/1 var(--fam);cursor:pointer;transition:background .2s,color .2s,border-color .2s,transform .15s}\n  .tag:hover{color:var(--ink);transform:translateY(-1px)}\n  .tag.on{background:var(--grad);background-size:200% 200%;border-color:transparent;color:#fff;box-shadow:0 3px 10px rgba(229,0,75,.26)}\n  .count{padding:0 18px 8px;font:600 11px/1 var(--fam);color:var(--muted)}\n  .side-list{flex:1 1 auto;min-height:0;overflow-y:auto;padding:4px 14px 20px;display:flex;flex-direction:column;gap:9px}\n\n  .cardslot{position:relative;cursor:pointer;animation:qt-rise .26s ease both}\n  .cardslot .acts{position:absolute;top:10px;right:11px;z-index:2;display:flex;gap:4px;opacity:0;transition:opacity .18s ease}\n  .cardslot:hover .acts,.cardslot.sel .acts{opacity:1}\n  .mic{width:24px;height:24px;flex:0 0 auto;border:none;border-radius:7px;background:transparent;color:var(--muted);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:background .18s,color .18s,transform .15s}\n  .mic .ic-svg{width:14px;height:14px;display:block}\n  .mic:hover{background:var(--ground);color:var(--ink);transform:scale(1.1)}\n  .mic.del:hover{background:rgba(255,20,24,.10);color:var(--red)}\n  .mic.del:hover .ic-svg{animation:qt-shake .45s ease}\n  .mic.ok{background:var(--red);color:#fff;box-shadow:0 3px 10px rgba(255,20,24,.35)}\n  .qcard{position:relative;overflow:hidden;background:var(--surface);border:1px solid var(--hair);border-radius:14px;padding:12px 44px 12px 14px;color:var(--ink);\n         transition:border-color .2s,box-shadow .22s,background .2s,transform .18s cubic-bezier(.2,.8,.3,1)}\n  .cardslot:hover .qcard{transform:translateY(-1px);box-shadow:0 6px 18px rgba(16,24,40,.09);border-color:rgba(16,24,40,.14)}\n  .qcard::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--grad);opacity:0;transform:scaleY(.3);transform-origin:center;transition:opacity .22s ease,transform .28s cubic-bezier(.2,.8,.3,1)}\n  .cardslot.sel .qcard{border-color:rgba(229,0,75,.45);background:rgba(229,0,75,.04)}\n  .cardslot.sel .qcard::before{opacity:1;transform:scaleY(1)}\n  .qname{font:700 14px/1.25 var(--fam);letter-spacing:-.1px;word-break:break-word;display:block}\n  .qchips{display:flex;gap:5px;flex-wrap:wrap;margin-top:8px}\n  .chip{font:700 10px/1 var(--fam);letter-spacing:.03em;padding:4px 8px;border-radius:999px;white-space:nowrap}\n  .chip.on{background:rgba(41,172,86,.14);color:var(--money)}\n  .chip.off{background:rgba(107,114,128,.14);color:var(--muted)}\n  .chip.info{background:rgba(72,152,255,.14);color:#1462c7}\n  .chip.ds{background:rgba(247,190,0,.18);color:#8a6a00}\n  .qdesc{margin-top:8px;font:400 11.5px/1.45 var(--fam);color:var(--muted);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}\n  .empty-s{padding:28px 6px;text-align:center;color:var(--muted);font:500 12.5px/1.5 var(--fam)}\n\n  /* ---------- detalhe ---------- */\n  .main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:14px;height:100%;padding:20px 26px 40px;overflow-y:auto}\n  .empty{margin:auto;padding:60px;text-align:center;color:var(--muted);font:500 14px/1.5 var(--fam)}\n  .empty code{font:700 12px/1 var(--mono);background:var(--ground);padding:2px 6px;border-radius:5px;color:var(--ink)}\n  .crumb{display:flex;align-items:center;gap:4px;font:600 12px/1 var(--fam);color:var(--muted)}\n  .crumb .ic-svg{width:13px;height:13px;opacity:.6;display:block}\n  .crumb .cur{color:var(--mag);font-weight:800}\n  .dhead{display:flex;align-items:flex-start;gap:16px;flex-wrap:wrap}\n  .dtitle{flex:1 1 320px;min-width:0}\n  .dtitle h1{margin:0;font:800 26px/1.15 var(--fam);letter-spacing:-.5px;word-break:break-word}\n  .dtitle p{margin:7px 0 0;font:400 13px/1.45 var(--fam);color:var(--muted);max-width:760px}\n  .dacts{display:flex;gap:9px;flex:0 0 auto;flex-wrap:wrap}\n  .meta{display:flex;align-items:center;gap:7px;flex-wrap:wrap;font:500 12px/1 var(--fam);color:var(--muted)}\n  .meta .dot{width:7px;height:7px;border-radius:50%;background:var(--grad);flex:0 0 auto}\n  .meta .mk,.meta .mv{font-weight:700;color:var(--ink)}\n  .meta .sep{opacity:.45}\n  .meta .mv.good{color:var(--money)}\n  .meta .mv.warn{color:var(--orange)}\n  .meta .mv.muted{color:var(--muted)}\n  .varsrow{display:flex;align-items:center;gap:7px;flex-wrap:wrap}\n  .vlabel{font:700 11px/1 var(--fam);text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin-right:2px}\n  .vtag{font:700 10.5px/1 var(--mono);background:rgba(229,0,75,.08);color:var(--mag);padding:5px 8px;border-radius:7px;transition:background .2s,transform .15s}\n  .vtag:hover{background:rgba(229,0,75,.16);transform:translateY(-1px)}\n  .nohint{font:500 11.5px/1.45 var(--fam);color:var(--muted)}\n\n  .panel{background:var(--surface);border:1px solid var(--hair);border-radius:16px;box-shadow:var(--shadowcard);overflow:hidden}\n  .panel.rise{animation:qt-rise .3s cubic-bezier(.2,.8,.3,1) both}\n  .phead{display:flex;align-items:center;gap:10px;padding:10px 14px;background:var(--ground);border-bottom:1px solid var(--hair)}\n  .ptitle{font:800 12px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}\n  .ptitle.mono{font-family:var(--mono);letter-spacing:.1em}\n  .pacts{margin-left:auto;display:flex;gap:7px}\n  .sqlbox{margin:0;padding:16px 18px;max-height:360px;overflow:auto;background:var(--surface)}\n  .sqlbox code{font:500 11.5px/1.65 var(--mono);white-space:pre;color:var(--ink);display:block}\n  .t-kw{color:var(--mag);font-weight:700}\n  .t-fn{color:#1462c7;font-weight:700}\n  .t-str{color:var(--money)}\n  .t-num{color:var(--orange)}\n  .t-com{color:var(--muted);font-style:italic}\n  .t-var{color:#8a6a00;font-weight:700;background:rgba(247,190,0,.18);border-radius:3px;padding:0 2px}\n  .rmeta{margin-left:auto;font:700 11.5px/1 var(--fam);color:var(--money)}\n  .rmeta.warn{color:var(--orange)}\n  .tblwrap{overflow:auto;max-height:340px}\n  .rtbl{border-collapse:collapse;width:100%;font:500 12px/1.4 var(--fam);color:var(--ink)}\n  .rtbl th{position:sticky;top:0;text-align:left;font:700 10.5px/1 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.04em;padding:9px 12px;background:var(--ground);border-bottom:1px solid var(--hair);white-space:nowrap}\n  .rtbl td{padding:8px 12px;border-bottom:1px solid var(--hair);white-space:nowrap}\n  .rtbl tbody tr{transition:background .15s}\n  .rtbl tbody tr:hover{background:rgba(229,0,75,.04)}\n  .rtbl tr:last-child td{border-bottom:none}\n  .rerr{padding:14px 16px;background:rgba(255,20,24,.08);color:#c00d11;font:600 12.5px/1.5 var(--fam)}\n  .hint{font:500 11.5px/1.45 var(--fam);color:var(--muted)}\n  .hint.pad{padding:12px 0 2px}\n  .panel .hint{padding:12px 14px}\n  .hint code,.msub code{font:700 11px/1 var(--mono);background:var(--ground);padding:2px 5px;border-radius:5px;color:var(--ink)}\n  .rawbox{margin:0;padding:14px 18px;max-height:260px;overflow:auto;background:var(--surface);border-top:1px solid var(--hair)}\n  .rawbox code{font:500 11px/1.6 var(--mono);white-space:pre-wrap;word-break:break-word;color:var(--muted);display:block}\n\n  /* ---------- diálogos ---------- */\n  .modal-bg{position:fixed;inset:0;background:rgba(16,24,40,.44);backdrop-filter:blur(3px);z-index:9000;display:flex;align-items:center;justify-content:center;padding:24px;animation:qt-fade .2s ease both}\n  .modal{position:relative;overflow:hidden auto;background:var(--surface);border-radius:20px;box-shadow:var(--shadowraised);width:min(620px,100%);max-height:90vh;padding:26px 26px 22px;color:var(--ink);\n         animation:qt-pop .3s cubic-bezier(.2,.9,.3,1.08) both}\n  .modal.narrow{width:min(520px,100%)}\n  .mgrad{position:absolute;left:0;right:0;top:0;height:4px;background:var(--grad);background-size:200% 200%;animation:qt-slide 3.5s ease-in-out infinite alternate}\n  .modal h2{margin:0 0 4px;font:800 20px/1.15 var(--fam)}\n  .msub{margin:0 0 16px;font:500 12px/1.5 var(--fam);color:var(--muted)}\n  .frow,.prow{display:flex;gap:12px;margin-bottom:14px;flex-wrap:wrap}\n  .mfield,.pfield{flex:1 1 160px;min-width:0;display:flex;flex-direction:column;gap:6px}\n  .mfield.grow{flex:1 1 100%}\n  .mfield.tg{flex:0 0 auto}\n  .pfield{flex:1 1 170px}\n  .mfield label{font:700 11px/1 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.04em}\n  .pfield label{font:700 11px/1 var(--mono);color:var(--mag)}\n  .mfield input,.mfield textarea,.pfield input{border:1.5px solid var(--hair);border-radius:10px;padding:10px 12px;font:500 13px/1.45 var(--fam);color:var(--ink);background:var(--surface);outline:none;width:100%;transition:border-color .2s,box-shadow .2s}\n  .mfield textarea.mono{font:500 12px/1.6 var(--mono)}\n  .mfield input:focus,.mfield textarea:focus,.pfield input:focus{border-color:var(--mag);box-shadow:0 0 0 3px rgba(229,0,75,.12)}\n  .tog{width:44px;height:26px;border-radius:999px;border:none;background:var(--hair);position:relative;cursor:pointer;transition:background .25s ease;padding:0}\n  .tog.on{background:linear-gradient(135deg,#29AC56,#7ED957)}\n  .tog .knob{position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.3);transition:left .25s cubic-bezier(.2,.8,.3,1.4)}\n  .tog.on .knob{left:21px}\n  .mfoot{display:flex;justify-content:flex-end;gap:10px;margin-top:8px}\n  .err{color:#c00d11;font:600 11.5px/1.4 var(--fam);margin-top:4px}\n\n  /* ---------- toast ---------- */\n  .toast{position:fixed;left:50%;bottom:26px;background:var(--ink);color:#fff;padding:12px 20px;border-radius:12px;font:600 13px/1 var(--fam);box-shadow:0 12px 34px rgba(0,0,0,.34);z-index:9500;animation:qt-toast .28s cubic-bezier(.2,.9,.3,1.1) both}\n  .toast.err{background:linear-gradient(135deg,#c00d11,#FF1418)}\n  .toast.ok{background:linear-gradient(135deg,#1A1C1E,#3a2230)}\n\n  @media (prefers-reduced-motion: reduce){\n    *{animation-duration:.01ms !important;animation-iteration-count:1 !important;transition-duration:.01ms !important}\n  }\n  `,\n  render(d2){\n    const toastEl = d2.state.toast\n      ? `<div class=\"toast ${d2.state.toastKind==='err'?'err':'ok'}\" data-key=\"toast-${d2.state.toastKey||0}\">${esc(d2.state.toast)}</div>`\n      : '';\n    return `<div class=\"wrap\" style=\"${cssVars()}\">\n      ${sideHtml(d2)}\n      ${detailHtml(d2)}\n      ${editHtml(d2)}${runHtml(d2)}${toastEl}\n    </div>`;\n  },\n  mounted(d2){\n    if(!d2.state.lastRun) d2.state.lastRun = {};\n\n    // --- lista ---\n    d2.on('[data-new]','click',()=> d2.setState({ editOpen:true, editDraft:{ active:true, variables:[] }, editBefore:{}, editErr:null }));\n    d2.on('[data-q]','input',(e,el)=>{ d2.setState({ q: el.value }); });\n    d2.on('[data-filt]','click',(e,el)=> d2.setState({ filt: el.dataset.filt }));\n    d2.on('[data-pick]','click',(e,el)=>{\n      if(e.target && e.target.closest && e.target.closest('.acts')) return;\n      d2.setState({ selId: el.dataset.pick, armed:null });\n    });\n    d2.on('[data-delask]','click',(e,el)=> d2.setState({ armed: el.dataset.delask }));\n    d2.on('[data-delcancel]','click',()=> d2.setState({ armed:null }));\n    d2.on('[data-del]','click',(e,el)=>{\n      const id = el.dataset.del;\n      const row = sortedRows(d2).find(r=>r._id===id) || { _id:id };\n      doDelete(d2, row);\n    });\n\n    // --- detalhe ---\n    d2.on('[data-run]','click',()=>{ const q=curRow(d2); if(q) d2.setState({ runOpen:true, runRow:q, running:false }); });\n    d2.on('[data-toggle]','click',()=>{ const q=curRow(d2); if(q) doToggle(d2, q); });\n    d2.on('[data-edit]','click',()=>{ const q=curRow(d2); if(q) d2.setState({ editOpen:true, editDraft:JSON.parse(JSON.stringify(q)), editBefore:q, editErr:null }); });\n    d2.on('[data-copy]','click',()=>{ const q=curRow(d2); doCopy(d2, q && q.sql); });\n\n    // --- modal de edição ---\n    d2.on('[data-tog]','click',()=>{\n      const m = syncEdit(d2);\n      d2.setState({ editDraft: Object.assign({}, m, { active: m.active===false }) });\n    });\n    d2.on('[data-editclose]','click',()=> d2.setState({ editOpen:false, editDraft:null, editBefore:null, editErr:null }));\n    d2.on('[data-editbg]','click',(e,el)=>{ if(e.target===el) d2.setState({ editOpen:false, editDraft:null, editBefore:null, editErr:null }); });\n    d2.on('[data-save]','click',()=>{\n      const m = Object.assign({}, syncEdit(d2));\n      if(!String(m.name||'').trim()){ d2.setState({ editErr:'Nome é obrigatório' }); return; }\n      const typed = Array.isArray(m.variables)\n        ? m.variables\n        : String(m.variables||'').split(',').map(s=>s.trim()).filter(Boolean);\n      m.variables = typed.length ? typed : varsFromSql(m.sql);\n      doSave(d2, m);\n    });\n\n    // --- modal de execução ---\n    d2.on('[data-runclose]','click',()=> d2.setState({ runOpen:false, runRow:null, running:false }));\n    d2.on('[data-runbg]','click',(e,el)=>{ if(e.target===el) d2.setState({ runOpen:false, runRow:null, running:false }); });\n    d2.on('[data-go]','click',()=> doRun(d2, syncRun(d2)));\n\n    d2.on(document,'keydown',(e)=>{\n      if(e.key!=='Escape') return;\n      if(d2.state.runOpen)  d2.setState({ runOpen:false, runRow:null, running:false });\n      else if(d2.state.editOpen) d2.setState({ editOpen:false, editDraft:null, editBefore:null, editErr:null });\n      else if(d2.state.armed) d2.setState({ armed:null });\n    });\n  },\n  updated(d2){\n    // Semeia a seleção assim que os records chegam, para a lista e o painel\n    // concordarem no primeiro load. Roda pós-render, nunca dentro de render().\n    if(d2.state.selId) return;\n    const first = sortedRows(d2)[0];\n    if(first && first._id) d2.state.selId = first._id;\n  }\n};"}},"queryLib":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"queryLib"}}}},"queryWriter":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"queryWriter"}}}},"runner":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"runner"}}}},"actorEmail":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"actorEmail"}}}}}}}}}},{"_id":"6ad7dacc41232854da246f48","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotSimPicker","package":"natura-x-piloto","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 esc = (s) => String(s == null ? '' : s).replace(/[&<>\"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' }[c]));\n\nfunction readUrl() {\n  let q;\n  try { q = new URLSearchParams(location.search); } catch (e) { q = { get: () => null }; }\n  return {\n    perfil: q.get('perfil') || '',\n    structureCode: q.get('structureCode') || '',\n    cycle: q.get('cycle') || ''\n  };\n}\n\nexport default {\n  css: `\n    :host { display:block; }\n    .bar { box-sizing:border-box; height:100%; display:flex; align-items:center; gap:12px; flex-wrap:nowrap;\n      padding:8px 16px; background:#4a1d96; color:#fff; font:500 13px/1.3 system-ui, sans-serif;\n      overflow-x:auto; scrollbar-width:none; -webkit-overflow-scrolling:touch; }\n    .bar::-webkit-scrollbar { display:none; }\n    .bar > * { flex:0 0 auto; white-space:nowrap; }\n    form { flex-wrap:nowrap !important; }\n    @media (max-width:700px) { .bar { gap:8px; padding:8px 12px; } .muted { display:none; } .tag { padding:3px 6px; } }\n    .tag { background:#fbbf24; color:#1f1300; font-weight:700; padding:3px 8px; border-radius:999px; letter-spacing:.04em; }\n    .who { font-weight:600; }\n    .muted { opacity:.8; }\n    form { display:flex; gap:8px; align-items:center; margin-left:auto; flex-wrap:wrap; }\n    select, input { font:inherit; padding:5px 8px; border-radius:6px; border:1px solid #a78bfa; background:#fff; color:#111; }\n    input.code { width:110px; }\n    input.cyc { width:90px; }\n    button { font:inherit; font-weight:600; padding:6px 12px; border-radius:6px; border:0; background:#fbbf24; color:#1f1300; cursor:pointer; }\n    button.ghost { background:transparent; color:#fff; border:1px solid #c4b5fd; }\n    .err { color:#fecaca; }\n  `,\n  render(d2) {\n    const cur = readUrl();\n    const active = !!(cur.perfil && cur.structureCode);\n    const label = cur.perfil === 'gn' ? 'GN do setor' : 'Líder do grupo';\n    const err = d2.state.err || '';\n    return `\n      <div class=\"bar\">\n        <span class=\"tag\">MODO SIMULAÇÃO</span>\n        ${active\n          ? `<span class=\"who\">Vendo como ${esc(label)} ${esc(cur.structureCode)}</span>${cur.cycle ? `<span class=\"muted\">· ciclo ${esc(cur.cycle)}</span>` : ''}`\n          : `<span class=\"muted\">Escolha um perfil e o código da estrutura para simular.</span>`}\n        <form class=\"f\">\n          <select name=\"perfil\">\n            <option value=\"lider\" ${cur.perfil !== 'gn' ? 'selected' : ''}>Líder (código do grupo)</option>\n            <option value=\"gn\" ${cur.perfil === 'gn' ? 'selected' : ''}>GN (código do setor)</option>\n          </select>\n          <input class=\"code\" name=\"structureCode\" placeholder=\"ex.: 22001\" inputmode=\"numeric\" value=\"${esc(cur.structureCode)}\">\n          <input class=\"cyc\" name=\"cycle\" placeholder=\"ciclo (opcional)\" inputmode=\"numeric\" value=\"${esc(cur.cycle)}\">\n          <button type=\"submit\">Simular</button>\n          ${active ? `<button type=\"button\" class=\"ghost clear\">Limpar</button>` : ''}\n        </form>\n        ${err ? `<span class=\"err\">${esc(err)}</span>` : ''}\n      </div>`;\n  },\n  mounted(d2, root) {\n    d2.on('.f', 'submit', (ev) => {\n      ev.preventDefault();\n      const f = ev.target;\n      const perfil = f.perfil.value === 'gn' ? 'gn' : 'lider';\n      const code = String(f.structureCode.value || '').trim();\n      const cycle = String(f.cycle.value || '').trim();\n      if (!/^\\d{1,10}$/.test(code)) { d2.state.err = 'Código da estrutura inválido.'; return; }\n      if (cycle && !/^\\d{6}$/.test(cycle)) { d2.state.err = 'Ciclo deve ter 6 dígitos (ex.: 202615).'; return; }\n      const q = new URLSearchParams();\n      q.set('perfil', perfil);\n      q.set('structureCode', code);\n      if (cycle) q.set('cycle', cycle);\n      location.search = q.toString();\n    });\n    d2.on('.clear', 'click', () => { location.search = ''; });\n  }\n};"}}}}}}}},{"_id":"6ad953d8c520b0805dcbdd8d","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotDeckV1V2","package":"natura-x-piloto","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 ul = (items) => `<ul>${items.map((i) => `<li>${i}</li>`).join('')}</ul>`\n\nconst problem = (tag, title, items, note) => `\n  <div class=\"kicker\">Problemas da v1 · ${tag}</div>\n  <h2>${title}</h2>\n  ${ul(items)}\n  ${note ? `<div class=\"note\">${note}</div>` : ''}`\n\nconst map = (title, rows) => `\n  <div class=\"kicker\">O que a v2 resolve</div>\n  <h2>${title}</h2>\n  <div class=\"map\">${rows.map(([a, b]) => `\n    <div class=\"row\"><div class=\"v1\"><span class=\"tag t1\">v1</span>${a}</div><div class=\"arrow\">→</div><div class=\"v2\"><span class=\"tag t2\">v2</span>${b}</div></div>`).join('')}\n  </div>`\n\nconst SLIDES = [\n  `<div class=\"cover\">\n    <div class=\"kicker light\">Data2 × Natura · 22/10/2026</div>\n    <h1>Painel de Ganhos</h1>\n    <p class=\"sub\">O que aprendemos com a v1 e como a v2 resolve</p>\n  </div>`,\n\n  `<div class=\"kicker\">Contexto</div>\n  <h2>A v1 cresceu por camadas</h2>\n  <p class=\"lead\">A v1 está no ar desde 2025 e atende GV, GN e Líder de Negócio nas Redes 1 e 2: aceleradores, ranking de líderes e remuneração prévia do ciclo.</p>\n  <p class=\"lead\">Cada ciclo trouxe uma regra nova, uma base nova e um ajuste de urgência. A v2 é a reconstrução com o que aprendemos.</p>\n  <div class=\"chips\"><span>Dados mantidos à mão</span><span>Lentidão e cache</span><span>Virada de ciclo manual</span><span>Acesso e sessão</span><span>Dependência da Data2</span></div>`,\n\n  problem('dados', 'Dados mantidos à mão', [\n    'O nível da líder vem de uma tabela atualizada a partir do CSV de líderes. Existem duas cópias dessa tabela, e elas divergem.',\n    'O CSV traz a data de entrada da líder no cargo, não o ciclo em que o nível mudou.',\n    'Grupo × setor, setor × rede e setor × GN também são planilhas copiadas pro sistema. A atualização de 28/08 foram 109 alterações manuais.',\n    'Líder nova só aparece depois de entrar em duas listas fixas e de uma publicação.',\n  ], '<b>21/10:</b> um GN viu no ranking níveis do ciclo anterior. O DW da Natura registra a mudança no 202614; a tabela montada pelo CSV, no 202615.'),\n\n  problem('performance', 'Lentidão e cache', [\n    'Consulta de uma líder na API: <b>30 a 50 s</b> sem cache. Ranking de um setor: <b>24 s</b>.',\n    'O cache depende de três rotinas de aquecimento a cada 6 h.',\n    'Quando uma rodada falha, a tela da líder mostra meta sem realizado ou número em branco (23/09 e 14/10).',\n    'Ciclo fechado continua lento no primeiro acesso.',\n  ], 'Em setembro o ranking caiu de 24 s pra 2,7 s com cache quente. Isso melhorou a tela, mas o problema de origem continuou.'),\n\n  problem('ciclo', 'Virada de ciclo manual', [\n    'Abrir um ciclo exige três passos: cadastrar o ciclo, validar os aceleradores nos 18 cards e atualizar o ciclo padrão do app, com publicação.',\n    'Rede 1 e Rede 2 viram em dias diferentes. Em 25/09 a Rede 2 chegou ao 202615 antes da Rede 1, e cada acesso levava de 8 a 26 s.',\n    'A regra de remuneração muda por ciclo escrito no código (202604, 202612).',\n    'Regras herdadas com erro: faixa faltando que vira valor vazio e faturamento Avon do GN Rede 2 comparando indicadores diferentes.',\n  ], '<b>21/10:</b> os aceleradores do 202616 só apareceram depois da virada manual.'),\n\n  problem('acesso', 'Acesso e sessão', [\n    'A sessão se acumulava a cada ciclo até travar o painel (22/09). A correção limitou a sessão a 6 h; quem já estava travado precisou limpar o navegador.',\n    'O controle de acesso por perfil entrou com o produto já no ar, em agosto, fechando acesso tela por tela.',\n  ]),\n\n  problem('operação', 'Dependência da Data2 pra operar', [\n    'Mudar indicador, faixa ou bônus é mudança de código.',\n    'Virar ciclo, cadastrar líder e trocar GN de setor passam pela Data2.',\n    'Quando um número sai estranho, nenhuma tela mostra de onde ele veio.',\n  ]),\n\n  map('Dados e performance', [\n    ['Nível da líder em planilha manual', 'Nível por ciclo lido do DW da Natura (plano Líder de Negócio, com vigência). Bateu com o fechamento nos casos testados'],\n    ['Estrutura copiada de CSV', 'Calendário e ciclos já vêm do Databricks de hora em hora. Estrutura (setor, GN, grupo) passa a sincronizar do Databricks no mesmo job: em implementação, antes do paralelo de 05/11'],\n    ['Tela esperando a API', 'Indicadores e metas atualizados de hora em hora num snapshot. Medido em 19/10: grupo 15 s → 4,6 s, setor 17 s → 5,8 s'],\n    ['Virada de ciclo em 3 passos', 'Ciclo abre e fecha pelo calendário da Natura, por grupo. Rede 1 e Rede 2 viram cada uma no seu dia'],\n  ]),\n\n  map('Regras, acesso e operação', [\n    ['Regra de remuneração no código', 'Cada ciclo aponta pra um conjunto de regras versionado: faixas, fórmula e bônus. As 6 configurações da v1 foram migradas'],\n    ['Acesso remendado', 'Um ponto único de identidade: GV vê tudo, GN o setor, líder o grupo. Admin com login próprio e registro de acesso'],\n    ['Tudo passa pela Data2', 'Admin com indicadores, faixas, bônus, fórmula, regras por ciclo e consultas. Toda alteração fica no log de auditoria'],\n    ['Sem visibilidade do cálculo', 'Simulador com meta e realizado por indicador e a faixa ativa destacada, mais histórico por ciclo'],\n  ]),\n\n  `<div class=\"kicker\">v1 × v2 · mesma tela, mesmo setor</div>\n  <h2>Ranking de Líderes, setor 3531, ciclo 202615</h2>\n  <div class=\"shots\">\n    <a class=\"shot\" href=\"https://natura-x-piloto.data2.media/file/T8g4_jo0Yvtv9R_DsFvj0\" target=\"_blank\" rel=\"noopener\"><span class=\"tag t1\">v1</span><img src=\"https://natura-x-piloto.data2.media/file/bFkBIYc7o5dC1fyrYgDzf\" alt=\"Ranking de Líderes na v1\"></a>\n    <a class=\"shot\" href=\"https://natura-x-piloto.data2.media/file/ELFZsTxJBFWylmAraGL1O\" target=\"_blank\" rel=\"noopener\"><span class=\"tag t2\">v2</span><img src=\"https://natura-x-piloto.data2.media/file/kAne0Jy-ZXdNfuRQXiKHR\" alt=\"Ranking de Líderes na v2\"></a>\n  </div>\n  <div class=\"facts\">\n    <div><b>Mesma base.</b> Faturamento Natura 2.307.185, mesmo volume de pontos e 1.494 cadastros nas duas.</div>\n    <div><b>Nível da líder.</b> A v1 mostra Erica Ouro, Camila Diamante e Acalicia sem nível. A v2 lê do DW: Prata, Prata e Diamante.</div>\n    <div><b>Remuneração por líder.</b> A v2 mostra o valor prévio de cada líder no próprio card.</div>\n  </div>`,\n\n  `<div class=\"kicker\">Validação</div>\n  <h2>Mesmo cálculo da v1</h2>\n  <table>\n    <thead><tr><th>Caso</th><th>v1 / fechamento</th><th>v2</th></tr></thead>\n    <tbody>\n      <tr><td>Líder Rede 1, 202615</td><td>956,25</td><td class=\"ok\">956,25</td></tr>\n      <tr><td>Líder Rede 2, 202613</td><td>5.417,52</td><td class=\"ok\">5.417,52</td></tr>\n      <tr><td>Líder Rede 1, 202601 (fechamento pago)</td><td>1.725,00</td><td class=\"ok\">1.725,00</td></tr>\n      <tr><td>GN Rede 1, 202516</td><td>5.700,00</td><td class=\"ok\">5.700,00</td></tr>\n    </tbody>\n  </table>\n  <div class=\"note\">As 6 configurações de remuneração da v1 foram migradas e conferidas caso a caso contra a v1 e contra o fechamento pago.</div>`,\n\n  `<div class=\"kicker\">Veja a v2</div>\n  <h2>Onde abrir</h2>\n  <div class=\"links\">\n    <div class=\"link main\"><div class=\"lk-t\">Validação da v2</div><a href=\"https://pilot-validacao.natura-x-piloto.next.data2.app/\" target=\"_blank\" rel=\"noopener\">pilot-validacao.natura-x-piloto.next.data2.app</a><div class=\"lk-d\">Login \"Validação\" com usuário e senha que a Data2 envia. Uma tela só: escolha qualquer líder ou GN e veja o painel da v2.</div></div>\n    <div class=\"link\"><div class=\"lk-t\">Admin da v2</div><a href=\"https://pilot-admin.natura-x-piloto.next.data2.app/\" target=\"_blank\" rel=\"noopener\">pilot-admin.natura-x-piloto.next.data2.app</a><div class=\"lk-d\">Indicadores, regras e ciclos. Login de administrador do piloto, criado pela Data2.</div></div>\n  </div>`,\n\n  `<div class=\"kicker\">Go-live</div>\n  <h2>v2 oficial em 12/11</h2>\n  <div class=\"tl\">\n    <div class=\"st\"><div class=\"dt\">28/10</div><div class=\"sd\">Fechamento estatístico do 202615 em todos os setores</div></div>\n    <div class=\"st\"><div class=\"dt\">até 04/11</div><div class=\"sd\">Natura valida a v2 contra o fechamento. Setores 3515 e 3531 podem começar antes</div></div>\n    <div class=\"st\"><div class=\"dt\">05/11</div><div class=\"sd\">v2 no ar em paralelo com a v1, mesmos usuários, comparação lado a lado</div></div>\n    <div class=\"st hl\"><div class=\"dt\">12/11</div><div class=\"sd\">Go-live final: a v2 vira a oficial</div></div>\n  </div>\n  <div class=\"note\">Em andamento, antes de 05/11: acesso de líderes e GNs pelo SSO da Natura na v2 e sincronização da estrutura (setor, GN, grupo) com o Databricks. Pendente da Natura: fonte oficial do nível da líder (DW ou CSV de líderes).</div>`,\n]\n\nfunction go(d2, delta) {\n  const i = Math.min(SLIDES.length - 1, Math.max(0, (d2.state.i || 0) + delta))\n  if (i !== (d2.state.i || 0)) d2.state.i = i\n}\n\nexport default {\n  css: `\n:host{--brand:#F26B21;--brand2:#E5197B;--ink:#1c2230;--muted:#5a6474;--line:#e3e7ee;--ok:#15803d;--warn:#b45309}\n.deck{position:relative;height:100%;min-height:100%;display:flex;flex-direction:column;background:#f6f4f1;color:var(--ink);font:18px/1.55 -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;overflow:hidden}\n.deck *{box-sizing:border-box}\n.deck:focus{outline:none}\n.bar{height:5px;background:var(--line)}\n.bar i{display:block;height:100%;background:linear-gradient(90deg,var(--brand),var(--brand2));transition:width .3s ease}\n.stage{flex:1;min-height:0;display:flex;padding:32px 48px;overflow:auto}\n.slide{margin:auto;width:100%;max-width:1080px;background:#fff;border:1px solid var(--line);border-radius:18px;padding:52px 60px;box-shadow:0 2px 10px rgba(20,30,50,.06)}\n.slide.c{background:linear-gradient(135deg,var(--brand),var(--brand2));border:0;color:#fff;min-height:440px;display:flex;align-items:center}\n.kicker{font-size:13px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--brand2);margin-bottom:10px}\n.kicker.light{color:rgba(255,255,255,.85)}\nh1{margin:0 0 12px;font-size:56px;font-weight:800;letter-spacing:-.02em;line-height:1.05}\nh2{margin:0 0 22px;font-size:34px;font-weight:800;letter-spacing:-.01em;line-height:1.15}\n.sub{margin:0;font-size:24px;opacity:.95}\n.lead{font-size:20px;color:#2a3040;margin:0 0 14px;max-width:62ch}\nul,ol{margin:0;padding-left:24px}\nli{margin:10px 0}\nli::marker{color:var(--brand)}\n.note{margin-top:22px;padding:14px 18px;border-left:4px solid var(--brand);background:#fff6ef;border-radius:10px;font-size:16px;color:#3a2a1c}\n.chips{display:flex;flex-wrap:wrap;gap:10px;margin-top:26px}\n.chips span{background:#fff1e8;color:#a3420c;border:1px solid #ffd7bf;border-radius:999px;padding:7px 14px;font-size:15px;font-weight:600}\n.map{display:flex;flex-direction:column;gap:12px}\n.row{display:grid;grid-template-columns:1fr 32px 1.6fr;align-items:center;gap:8px}\n.v1,.v2{border-radius:12px;padding:12px 16px;font-size:16px;line-height:1.45}\n.v1{background:#f1f3f6;color:#3a4256}\n.v2{background:#ecfdf3;color:#14532d;border:1px solid #bbf7d0}\n.arrow{text-align:center;color:var(--brand);font-weight:800;font-size:22px}\n.tag{display:inline-block;font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;border-radius:5px;padding:2px 6px;margin-right:8px;vertical-align:1px}\n.t1{background:#dde2ea;color:#4a5466}.t2{background:#bbf7d0;color:#15803d}\ntable{width:100%;border-collapse:collapse;font-size:17px}\nth,td{text-align:left;padding:12px 14px;border-bottom:1px solid var(--line)}\nth{font-size:13px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}\ntd.ok{color:var(--ok);font-weight:700}td.diff{color:var(--warn);font-weight:700}\n.steps li{padding-left:6px;font-size:19px}\n.shots{display:grid;grid-template-columns:1fr 1fr;gap:16px}\n.shot{position:relative;display:block;border:1px solid var(--line);border-radius:12px;overflow:hidden;background:#f5f5f5;height:420px}\n.shot img{width:100%;height:100%;object-fit:contain;object-position:top center;display:block}\n.shot .tag{position:absolute;top:10px;left:10px;margin:0;z-index:1}\n.facts{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:16px;font-size:14.5px;line-height:1.45}\n.facts div{background:#fff6ef;border-radius:10px;padding:10px 14px}\n.links{display:flex;flex-direction:column;gap:14px}\n.link{border:1px solid var(--line);border-radius:12px;padding:16px 20px}\n.lk-t{font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin-bottom:4px}\n.link a{font-size:20px;font-weight:700;color:var(--brand2);word-break:break-all}\n.lk-d{font-size:16px;color:#3a4256;margin-top:6px}\n.link.main{border:2px solid var(--brand);background:#fff6ef;padding:22px 24px}\n.link.main a{font-size:24px}\n.link:not(.main) a{font-size:16px}\n.tl{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}\n.st{border-top:4px solid var(--line);padding:12px 4px 0}\n.st.hl{border-top-color:var(--brand)}\n.dt{font-size:24px;font-weight:800;color:var(--ink)}\n.st.hl .dt{color:var(--brand2)}\n.sd{font-size:15.5px;color:#3a4256;margin-top:4px;line-height:1.45}\n.nav{display:flex;align-items:center;justify-content:space-between;padding:12px 48px 18px;color:var(--muted);font-size:14px}\n.nav button{border:1px solid var(--line);background:#fff;border-radius:10px;padding:8px 16px;font-weight:600;font-size:14px;font-family:inherit;color:var(--ink);cursor:pointer}\n.nav button:disabled{opacity:.35;cursor:default}\n.hint{opacity:.7}\n@media(max-width:760px){.stage{padding:16px}.slide{padding:28px 22px}h1{font-size:38px}h2{font-size:26px}.row{grid-template-columns:1fr}.arrow{display:none}.shots,.facts,.tl{grid-template-columns:1fr}.shot{height:260px}table{font-size:14px}th,td{padding:8px 6px}th{font-size:11px}.nav{padding:10px 16px}.hint{display:none}}\n`,\n  render(d2) {\n    const i = d2.state.i || 0\n    const n = SLIDES.length\n    return `<div class=\"deck\" tabindex=\"-1\">\n  <div class=\"bar\"><i style=\"width:${((i + 1) / n) * 100}%\"></i></div>\n  <div class=\"stage\"><div class=\"slide${i === 0 ? ' c' : ''}\" data-key=\"s${i}\">${SLIDES[i]}</div></div>\n  <div class=\"nav\">\n    <button class=\"prev\" ${i === 0 ? 'disabled' : ''}>← Anterior</button>\n    <span>${i + 1} / ${n} <span class=\"hint\">· setas ← → pra navegar</span></span>\n    <button class=\"next\" ${i === n - 1 ? 'disabled' : ''}>Próximo →</button>\n  </div>\n</div>`\n  },\n  updated(d2) {\n    d2.$('.deck')?.focus({ preventScroll: true })\n  },\n  mounted(d2) {\n    d2.$('.deck')?.focus({ preventScroll: true })\n    d2.on('.prev', 'click', () => go(d2, -1))\n    d2.on('.next', 'click', () => go(d2, 1))\n    d2.on(window, 'keydown', (e) => {\n      if (['ArrowRight', 'PageDown', ' '].includes(e.key)) { e.preventDefault(); go(d2, 1) }\n      if (['ArrowLeft', 'PageUp'].includes(e.key)) { e.preventDefault(); go(d2, -1) }\n      if (e.key === 'Home') d2.state.i = 0\n      if (e.key === 'End') d2.state.i = SLIDES.length - 1\n    })\n  },\n}"}}}}}}}},{"_id":"6ae33be0da4cc3f9fdbea5da","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotTestRunner","package":"natura-x-piloto","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 FALLBACK = {\n  color:{surface:'#FFFFFF',ground:'#FAFAFB',ink:'#1A1C1E',muted:'#6B7280',hairline:'rgba(16,24,40,0.08)',naturaMagenta:'#E5004B',brandGradient:'linear-gradient(135deg,#E5004B 0%,#EB6619 100%)',money:'#29AC56'},\n  type:{family:\"'Roboto',system-ui,-apple-system,sans-serif\"},\n  shadow:{card:'0 1px 2px rgba(16,24,40,0.04),0 1px 3px rgba(16,24,40,0.08)',raised:'0 4px 12px rgba(16,24,40,0.10)'}\n};\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction fmtDate(v){ try{ const d=new Date(v); if(isNaN(d)) return ''; return d.toLocaleString('pt-BR',{day:'2-digit',month:'2-digit',year:'numeric',hour:'2-digit',minute:'2-digit'}); }catch(e){ return ''; } }\nfunction fmtVal(v){ if(v===null||v===undefined) return '—'; if(typeof v==='number') return v.toLocaleString('pt-BR',{maximumFractionDigits:2}); return String(v); }\nfunction allRuns(d2){ const ds=d2.data('runs'); const rs=ds?ds.records():[]; return rs.slice().sort((a,b)=>String(b.startedAt||b.createdAt||'').localeCompare(String(a.startedAt||a.createdAt||''))); }\nfunction allReqs(d2){ const ds=d2.data('reqs'); const rs=ds?ds.records():[]; return rs.slice().sort((a,b)=>((Number(a.order)||999)-(Number(b.order)||999))||String(a.code||'').localeCompare(String(b.code||''))); }\nfunction lastResults(d2){ const r=d2.state.lastRun||allRuns(d2)[0]; const m={}; ((r&&r.results)||[]).forEach(x=>{ m[x.id]=!!x.ok; }); return m; }\nfunction covOf(r,res){ const ts=Array.isArray(r.tests)?r.tests:[]; if(!ts.length) return 'none'; if(ts.some(t=>res[t]===false)) return 'fail'; if(ts.some(t=>res[t]===true)) return 'auto'; return 'manual'; }\nconst COV = { auto:['Suíte automática','ok'], fail:['Falhando','bad'], manual:['Só manual','neutral'], none:['Sem teste','warn'] };\nasync function reloadReqs(d2){ const ds=d2.data('reqs'); if(ds && ds.refresh){ try{ await ds.refresh(); }catch(e){} } }\nconst ICON = {\n  play:'<svg viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M7 4.5v15l12-7.5z\"/></svg>',\n  ok:'<svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M20 6 9 17l-5-5\"/></svg>',\n  x:'<svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\" aria-hidden=\"true\"><path d=\"M18 6 6 18M6 6l12 12\"/></svg>'\n};\n\nexport default {\n  css: `\n  :host{display:block}\n  .screen{min-height:100%;display:flex;flex-direction:column;background:var(--ground);font-family:var(--fam);box-sizing:border-box}\n  .header{padding:26px 30px 22px;background:var(--surface);border-bottom:1px solid var(--hair)}\n  .htop{display:flex;align-items:flex-start;gap:16px}\n  .htitle h1{margin:0;font:800 28px/1.1 var(--fam);color:var(--ink);letter-spacing:-.5px}\n  .htitle .badge{display:inline-block;margin-left:10px;font:700 10px/1 var(--fam);letter-spacing:.06em;text-transform:uppercase;color:var(--mag);background:rgba(229,0,75,.10);padding:5px 9px;border-radius:999px;vertical-align:middle}\n  .htitle p{margin:6px 0 0;font:400 13px/1.4 var(--fam);color:var(--muted);max-width:720px}\n  .newbtn{margin-left:auto;display:inline-flex;align-items:center;gap:7px;padding:11px 18px;border:none;border-radius:11px;background:var(--grad);color:#fff;font:700 13px/1 var(--fam);cursor:pointer;box-shadow:0 4px 12px rgba(229,0,75,.28);white-space:nowrap;flex:0 0 auto}\n  .newbtn[disabled]{opacity:.55;cursor:default}\n  .summary{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:16px}\n  .pill{font:700 11px/1 var(--fam);padding:6px 10px;border-radius:999px;white-space:nowrap}\n  .pill.ok{background:rgba(41,172,86,.14);color:var(--money)}\n  .pill.bad{background:rgba(214,20,25,.10);color:#d61419}\n  .pill.neutral{background:var(--ground);color:var(--muted);border:1px solid var(--hair)}\n  .meta{font:500 12px/1.3 var(--fam);color:var(--muted)}\n  .body{padding:22px 30px 72px;display:flex;flex-direction:column;gap:18px}\n  .card{background:var(--surface);border:1px solid var(--hair);border-radius:16px;box-shadow:var(--shadowcard);overflow:hidden}\n  .card h2{margin:0;padding:14px 18px;font:800 15px/1.2 var(--fam);color:var(--ink);border-bottom:1px solid var(--hair)}\n  .row{display:grid;grid-template-columns:34px 96px minmax(0,1fr) minmax(0,0.9fr) minmax(0,0.9fr) 64px;gap:12px;align-items:start;padding:12px 18px;border-top:1px solid var(--hair)}\n  .row:first-of-type{border-top:none}\n  .row.head{background:var(--ground);font:700 10.5px/1 var(--fam);letter-spacing:.05em;text-transform:uppercase;color:var(--muted);padding:9px 18px}\n  .row.fail{background:rgba(214,20,25,.04)}\n  .st{width:24px;height:24px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center}\n  .st.ok{background:rgba(41,172,86,.16);color:var(--money)}\n  .st.bad{background:#d61419;color:#fff}\n  .cid{font:700 12px/1.3 var(--fam);color:var(--ink)}\n  .cname{font:500 13px/1.35 var(--fam);color:var(--ink);overflow-wrap:anywhere}\n  .val{font:500 12px/1.35 'SF Mono',ui-monospace,Menlo,monospace;color:var(--muted);overflow-wrap:anywhere}\n  .val.got.bad{color:#d61419;font-weight:700}\n  .ms{font:500 12px/1.3 var(--fam);color:var(--muted);text-align:right}\n  .lbl{display:none}\n  .hist{display:flex;flex-direction:column}\n  .hrow{display:flex;align-items:center;gap:12px;padding:11px 18px;border-top:1px solid var(--hair);cursor:pointer;background:none;border-left:none;border-right:none;border-bottom:none;text-align:left;font:inherit;width:100%}\n  .hrow:first-child{border-top:none}\n  .hrow:hover{background:var(--ground)}\n  .hrow.on{background:rgba(229,0,75,.05)}\n  .hrow .when{font:600 13px/1 var(--fam);color:var(--ink);min-width:150px}\n  .empty{padding:48px 18px;text-align:center;color:var(--muted);font:500 14px/1.5 var(--fam)}\n  .err{margin-top:12px;padding:10px 12px;border-radius:10px;background:rgba(214,20,25,.08);color:#a10f13;font:600 12px/1.4 var(--fam)}\n  .spin{width:13px;height:13px;border:2px solid rgba(255,255,255,.45);border-top-color:#fff;border-radius:50%;animation:sp .7s linear infinite}\n  @keyframes sp{to{transform:rotate(360deg)}}\n  .tabs{display:flex;gap:4px;margin:18px 0 -22px;overflow-x:auto}\n  .tab{appearance:none;border:none;background:none;padding:11px 14px;font:700 13px/1 var(--fam);color:var(--muted);cursor:pointer;border-bottom:2px solid transparent;white-space:nowrap}\n  .tab.on{color:var(--mag);border-bottom-color:var(--mag)}\n  .tab .n{font-weight:600;color:var(--muted);margin-left:5px}\n  .rtools{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:12px 18px;border-bottom:1px solid var(--hair)}\n  .rsearch{flex:1 1 220px;min-width:0;height:36px;padding:0 12px;border:1px solid var(--hair);border-radius:10px;font:500 13px/1 var(--fam);color:var(--ink);background:#fff;box-sizing:border-box}\n  .rsearch:focus,.fgrid input:focus,.fgrid textarea:focus,.fgrid select:focus{outline:none;border-color:var(--mag);box-shadow:0 0 0 3px rgba(229,0,75,.10)}\n  .fchip{appearance:none;border:1px solid var(--hair);background:#fff;border-radius:999px;padding:7px 11px;font:600 12px/1 var(--fam);color:var(--muted);cursor:pointer;white-space:nowrap}\n  .fchip.on{background:rgba(229,0,75,.08);border-color:rgba(229,0,75,.35);color:var(--mag)}\n  .ghost{appearance:none;border:1px solid var(--hair);background:#fff;border-radius:10px;padding:8px 13px;font:700 12px/1 var(--fam);color:var(--ink);cursor:pointer;white-space:nowrap}\n  .ghost:hover{background:var(--ground)}\n  .ghost.danger{color:#d61419;border-color:rgba(214,20,25,.3)}\n  .primary{appearance:none;border:none;border-radius:10px;padding:9px 15px;background:var(--grad);color:#fff;font:700 12px/1 var(--fam);cursor:pointer;white-space:nowrap}\n  .primary[disabled]{opacity:.55;cursor:default}\n  .hbtns{margin-left:auto;display:flex;align-items:center;gap:10px;flex:0 0 auto}\n  .hbtns .newbtn{margin-left:0}\n  .helpbtn{appearance:none;display:inline-flex;align-items:center;gap:7px;padding:10px 15px;border:1.5px solid rgba(229,0,75,.35);border-radius:11px;background:rgba(229,0,75,.06);color:var(--mag);font:700 13px/1 var(--fam);cursor:pointer;white-space:nowrap}\n  .helpbtn:hover,.helpbtn:focus-visible{background:rgba(229,0,75,.12);outline:none}\n  .helpbtn .q{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;background:var(--mag);color:#fff;font:800 11px/1 var(--fam)}\n  .helpbtn.sm{padding:7px 11px;font-size:12px;margin-left:10px;vertical-align:middle}\n  .linkbtn{appearance:none;border:none;background:none;padding:0;margin-left:4px;color:var(--mag);font:700 12px/1.45 var(--fam);text-decoration:underline;cursor:pointer}\n  .idlg{width:min(640px,100%) !important}\n  .steps{margin:0;padding:0;list-style:none;counter-reset:st}\n  .steps li{position:relative;padding:0 0 14px 38px;counter-increment:st}\n  .steps li::before{content:counter(st);position:absolute;left:0;top:0;width:26px;height:26px;border-radius:50%;background:var(--grad);color:#fff;font:800 12px/26px var(--fam);text-align:center}\n  .steps b{display:block;font:700 13px/1.3 var(--fam);color:var(--ink);margin-bottom:3px}\n  .steps span{font:400 13px/1.5 var(--fam);color:var(--muted)}\n  .isub{margin:0 0 10px;font:800 12px/1.2 var(--fam);letter-spacing:.06em;text-transform:uppercase;color:var(--mag)}\n  .iok{margin-top:6px;display:flex;justify-content:flex-end}\n  @media (max-width:760px){ .hbtns{width:100%;margin-left:0} .hbtns .newbtn,.hbtns .helpbtn{flex:1 1 0;justify-content:center} .helpbtn.sm{margin:8px 0 0 0} }\n  .ibtn{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-left:6px;padding:0;border:1px solid var(--hair);border-radius:50%;background:#fff;color:var(--muted);font:700 11px/1 Georgia,serif;font-style:italic;cursor:pointer;vertical-align:middle}\n  .ibtn:hover,.ibtn:focus-visible{color:var(--mag);border-color:rgba(229,0,75,.4);outline:none}\n  .ibk{position:fixed;inset:0;z-index:50;background:rgba(16,24,40,.42);display:flex;align-items:center;justify-content:center;padding:16px}\n  .idlg{background:var(--surface);border-radius:16px;box-shadow:0 12px 32px rgba(16,24,40,.22);width:min(520px,100%);max-height:calc(100vh - 32px);overflow:auto;padding:20px 22px;box-sizing:border-box}\n  .idlg .ihd{display:flex;align-items:center;gap:10px;margin-bottom:12px}\n  .idlg h3{margin:0;font:800 16px/1.2 var(--fam);color:var(--ink)}\n  .idlg .ix{margin-left:auto;appearance:none;border:none;background:none;font:400 22px/1 var(--fam);color:var(--muted);cursor:pointer;padding:2px 6px}\n  .idlg dl{margin:0}\n  .idlg dt{margin-top:12px;font:700 13px/1.3 var(--fam);color:var(--ink)}\n  .idlg dt:first-child{margin-top:0}\n  .idlg dd{margin:4px 0 0;font:400 13px/1.5 var(--fam);color:var(--muted)}\n  .idlg .isec{margin-top:16px;padding-top:14px;border-top:1px solid var(--hair)}\n  .legend{padding:10px 18px;font:500 12px/1.45 var(--fam);color:var(--muted);border-bottom:1px solid var(--hair);background:var(--ground)}\n  .req{padding:14px 18px;border-top:1px solid var(--hair)}\n  .req:first-child{border-top:none}\n  .rhead{display:flex;align-items:flex-start;gap:12px}\n  .rcode{font:800 12px/1.35 var(--fam);color:var(--ink);min-width:62px}\n  .rmain{flex:1 1 auto;min-width:0}\n  .rtitle{font:600 14px/1.35 var(--fam);color:var(--ink);overflow-wrap:anywhere}\n  .rsec{font:500 11.5px/1.3 var(--fam);color:var(--muted);margin-top:3px}\n  .rcrit{font:400 12.5px/1.45 var(--fam);color:#3A3F45;margin-top:6px;overflow-wrap:anywhere}\n  .rdec{font:500 12px/1.45 var(--fam);color:#8A5B00;background:rgba(250,160,0,.10);border-radius:8px;padding:6px 9px;margin-top:8px;overflow-wrap:anywhere}\n  .tchips{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px}\n  .tchip{font:700 10.5px/1 'SF Mono',ui-monospace,Menlo,monospace;padding:4px 7px;border-radius:6px;background:var(--ground);color:var(--muted);border:1px solid var(--hair)}\n  .tchip.ok{background:rgba(41,172,86,.12);color:var(--money);border-color:rgba(41,172,86,.3)}\n  .tchip.bad{background:rgba(214,20,25,.08);color:#d61419;border-color:rgba(214,20,25,.3)}\n  .rside{display:flex;flex-direction:column;align-items:flex-end;gap:8px;flex:0 0 auto}\n  .pill.warn{background:rgba(250,160,0,.14);color:#8A5B00}\n  .rmeta{font:500 11px/1.3 var(--fam);color:var(--muted);margin-top:8px}\n  .rform{padding:16px 18px;background:#FFFBFD;border-top:1px solid var(--hair)}\n  .fgrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}\n  .fgrid label{display:flex;flex-direction:column;gap:5px;font:700 10.5px/1 var(--fam);letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}\n  .fgrid label.wide{grid-column:1 / -1}\n  .fgrid input,.fgrid select,.fgrid textarea{font:500 13px/1.4 var(--fam);color:var(--ink);border:1px solid var(--hair);border-radius:9px;padding:8px 10px;background:#fff;text-transform:none;letter-spacing:0;box-sizing:border-box;width:100%}\n  .fgrid textarea{resize:vertical}\n  .factions{display:flex;gap:8px;align-items:center;margin-top:14px;flex-wrap:wrap}\n  .factions .sp{flex:1 1 auto}\n  .ferr{color:#a10f13;font:600 12px/1.4 var(--fam)}\n  @media (max-width:760px){\n    .tabs{margin:14px 0 -18px}\n    .rtools{padding:12px 14px}.req,.rform{padding:14px}\n    .rhead{flex-wrap:wrap}.rside{flex-direction:row;align-items:center;width:100%;justify-content:space-between}\n    .fgrid{grid-template-columns:minmax(0,1fr)}\n  }\n  @media (max-width:760px){\n    .header{padding:20px 16px 18px}.body{padding:16px 12px 64px}\n    .htop{flex-wrap:wrap}.newbtn{margin-left:0;width:100%;justify-content:center}\n    .row.head{display:none}\n    .row{grid-template-columns:30px minmax(0,1fr) 56px;row-gap:6px;padding:12px 14px}\n    .row .cname{grid-column:2 / 4}\n    .row .val{grid-column:2 / 4}\n    .row .cid{grid-column:2}\n    .row .ms{grid-column:3;grid-row:1}\n    .lbl{display:inline;font:700 10.5px/1 var(--fam);letter-spacing:.04em;text-transform:uppercase;color:var(--muted);margin-right:6px}\n    .hrow{flex-wrap:wrap;gap:8px}\n  }\n  @media (prefers-reduced-motion: reduce){.spin{animation:none}}\n  `,\n  render(d2){\n    const t = FALLBACK;\n    const vars = `--surface:${t.color.surface};--ground:${t.color.ground};--ink:${t.color.ink};--muted:${t.color.muted};--hair:${t.color.hairline};--mag:${t.color.naturaMagenta};--grad:${t.color.brandGradient};--money:${t.color.money};--fam:${t.type.family};--shadowcard:${t.shadow.card}`;\n    const runs = allRuns(d2);\n    const live = d2.state.lastRun || null;\n    const selId = d2.state.selId || '';\n    const sel = (selId && runs.find(r=>r._id===selId)) || live || runs[0] || null;\n    const running = !!d2.state.running;\n    const results = sel && Array.isArray(sel.results) ? sel.results.slice().sort((a,b)=>(a.ok===b.ok)?0:(a.ok?1:-1)) : [];\n    const summary = sel ? `<div class=\"summary\">\n        <span class=\"pill ${sel.failed>0?'bad':'ok'}\">${sel.failed>0?`${sel.failed} reprovado${sel.failed===1?'':'s'}`:'Tudo aprovado'}</span>\n        <span class=\"pill neutral\">${esc(sel.passed)} de ${esc(sel.total)} casos</span>\n        <span class=\"meta\">${esc(fmtDate(sel.startedAt||sel.createdAt))}${sel.actor?` · ${esc(sel.actor)}`:''}${sel.durationMs!=null?` · ${(Number(sel.durationMs)/1000).toLocaleString('pt-BR',{maximumFractionDigits:1})} s`:''}</span>\n      </div>` : `<div class=\"summary\"><span class=\"meta\">Nenhuma execução ainda.</span></div>`;\n    const rows = results.map(r=>`<div class=\"row ${r.ok?'':'fail'}\" data-key=\"${esc(r.id)}\">\n        <span class=\"st ${r.ok?'ok':'bad'}\" title=\"${r.ok?'Aprovado':'Reprovado'}\">${r.ok?ICON.ok:ICON.x}</span>\n        <span class=\"cid\">${esc(r.id)}</span>\n        <span class=\"cname\">${esc(r.name)}</span>\n        <span class=\"val\"><span class=\"lbl\">Esperado</span>${esc(fmtVal(r.expected))}</span>\n        <span class=\"val got ${r.ok?'':'bad'}\"><span class=\"lbl\">Obtido</span>${esc(fmtVal(r.got))}</span>\n        <span class=\"ms\">${esc(fmtVal(r.ms))} ms</span>\n      </div>`).join('');\n    const casesCard = sel ? `<div class=\"card\"><h2>Casos da execução</h2>\n        <div class=\"row head\"><span></span><span>Caso</span><span>O que verifica</span><span>Esperado</span><span>Obtido</span><span style=\"text-align:right\">Tempo</span></div>\n        ${rows || '<div class=\"empty\">Execução sem casos.</div>'}</div>`\n      : `<div class=\"card\"><div class=\"empty\">Rode a suíte para ver o resultado de cada caso.</div></div>`;\n    const hist = runs.slice(0,15).map(r=>`<button class=\"hrow ${sel&&sel._id===r._id?'on':''}\" data-run=\"${esc(r._id)}\" data-key=\"h-${esc(r._id)}\">\n        <span class=\"when\">${esc(fmtDate(r.startedAt||r.createdAt))}</span>\n        <span class=\"pill ${r.failed>0?'bad':'ok'}\">${esc(r.passed)}/${esc(r.total)}</span>\n        <span class=\"meta\">${esc(r.actor||'')}${r.cardId?` · card ${esc(String(r.cardId).slice(-6))}`:''}</span>\n      </button>`).join('');\n    const histCard = runs.length ? `<div class=\"card\"><h2>Histórico</h2><div class=\"hist\">${hist}</div></div>` : '';\n    const tab = d2.state.tab || 'runs';\n    const reqsAll = allReqs(d2);\n    let reqCard = '';\n    if(tab === 'reqs'){\n      const res = lastResults(d2);\n      const q = String(d2.state.rq||'').trim().toLowerCase();\n      const rk = d2.state.rk || 'all';\n      const rc = d2.state.rc || 'all';\n      const counts = { auto:0, fail:0, manual:0, none:0 };\n      reqsAll.forEach(r=>{ counts[covOf(r,res)]++; });\n      const list = reqsAll.filter(r=>{\n        if(rk!=='all' && r.kind!==rk) return false;\n        if(rc!=='all' && covOf(r,res)!==rc) return false;\n        if(!q) return true;\n        const hay = `${r.code||''} ${r.title||''} ${r.section||''} ${r.criteria||''} ${r.decision||''} ${(r.tests||[]).join(' ')}`.toLowerCase();\n        return hay.indexOf(q) >= 0;\n      });\n      const editId = d2.state.editId || '';\n      const f = d2.state.form || {};\n      const saving = !!d2.state.saving;\n      const opt = (v,cur)=>`<option value=\"${esc(v)}\" ${String(cur||'')===v?'selected':''}>${esc(v)}</option>`;\n      const form = (isNew)=>`<div class=\"rform\" data-key=\"rform-${esc(editId)}\">\n          <div class=\"fgrid\">\n            <label>ID<input data-f=\"code\" value=\"${esc(f.code||'')}\" placeholder=\"RF-31\"></label>\n            <label>Tipo<select data-f=\"kind\">${opt('funcional',f.kind)}${opt('não funcional',f.kind)}</select></label>\n            <label>Seção / categoria<input data-f=\"section\" value=\"${esc(f.section||'')}\"></label>\n            <label>Status<select data-f=\"status\">${opt('vigente',f.status)}${opt('em aberto',f.status)}${opt('descontinuado',f.status)}</select></label>\n            <label class=\"wide\">Requisito<textarea data-f=\"title\" rows=\"2\">${esc(f.title||'')}</textarea></label>\n            <label class=\"wide\">Critério de aceite<textarea data-f=\"criteria\" rows=\"3\">${esc(f.criteria||'')}</textarea></label>\n            <label class=\"wide\">Casos de teste (separados por vírgula)<input data-f=\"tests\" value=\"${esc(f.tests||'')}\" placeholder=\"UNIT-S01, ACC-02, E2E-L1\"></label>\n            <label class=\"wide\">Decisão / observação<textarea data-f=\"decision\" rows=\"2\">${esc(f.decision||'')}</textarea></label>\n            <label>Ordem<input type=\"number\" data-f=\"order\" value=\"${esc(f.order==null?'':f.order)}\"></label>\n          </div>\n          <div class=\"factions\">\n            ${d2.state.formErr?`<span class=\"ferr\">${esc(d2.state.formErr)}</span>`:''}\n            <span class=\"sp\"></span>\n            ${isNew?'':`<button class=\"ghost danger\" data-rdel>${d2.state.confirmDel?'Confirmar exclusão':'Excluir'}</button>`}\n            <button class=\"ghost\" data-rcancel>Cancelar</button>\n            <button class=\"primary\" data-rsave ${saving?'disabled':''}>${saving?'Salvando…':'Salvar'}</button>\n          </div>\n        </div>`;\n      const items = list.map(r=>{\n        const c = covOf(r,res);\n        const tests = (Array.isArray(r.tests)?r.tests:[]).map(t=>`<span class=\"tchip ${res[t]===true?'ok':(res[t]===false?'bad':'')}\" title=\"${res[t]===true?'Passou na última execução':(res[t]===false?'Falhou na última execução':'Manual ou fora da suíte automática')}\">${esc(t)}</span>`).join('');\n        const st = (r.status && r.status!=='vigente') ? `<span class=\"pill ${r.status==='em aberto'?'warn':'neutral'}\">${esc(r.status)}</span>` : '';\n        const editing = editId === r._id;\n        return `<div class=\"req\" data-key=\"rq-${esc(r._id)}\">\n          <div class=\"rhead\">\n            <span class=\"rcode\">${esc(r.code)}</span>\n            <div class=\"rmain\">\n              <div class=\"rtitle\">${esc(r.title)}</div>\n              <div class=\"rsec\">${esc(r.kind||'')}${r.section?` · ${esc(r.section)}`:''}</div>\n              ${r.criteria?`<div class=\"rcrit\">${esc(r.criteria)}</div>`:''}\n              ${r.decision?`<div class=\"rdec\">${esc(r.decision)}</div>`:''}\n              ${tests?`<div class=\"tchips\">${tests}</div>`:''}\n              <div class=\"rmeta\">${r.updatedBy?`Alterado por ${esc(r.updatedBy)}`:''}${r.updatedAt?` · ${esc(fmtDate(r.updatedAt))}`:''}</div>\n            </div>\n            <div class=\"rside\">\n              <span class=\"pill ${COV[c][1]}\">${COV[c][0]}</span>${st}\n              ${editing?'':`<button class=\"ghost\" data-redit=\"${esc(r._id)}\">Editar</button>`}\n            </div>\n          </div>\n        </div>${editing?form(false):''}`;\n      }).join('');\n      const chip = (attr,val,cur,label)=>`<button class=\"fchip ${cur===val?'on':''}\" ${attr}=\"${esc(val)}\">${label}</button>`;\n      reqCard = `<div class=\"card\">\n        <h2>Requisitos da V2 <span class=\"meta\" style=\"font-weight:500\">· base dos testes</span><button class=\"helpbtn sm\" data-info><span class=\"q\">?</span>O que é RF e RNF?</button></h2>\n        <div class=\"rtools\">\n          <input class=\"rsearch\" data-rq data-key=\"rsearch\" type=\"search\" placeholder=\"Buscar por ID, texto ou caso de teste…\" value=\"${esc(d2.state.rq||'')}\">\n          <button class=\"primary\" data-rnew ${editId?'disabled':''}>Novo requisito</button>\n        </div>\n        <div class=\"rtools\">\n          ${chip('data-rk','all',rk,'Todos')}${chip('data-rk','funcional',rk,'Funcionais')}${chip('data-rk','não funcional',rk,'Não funcionais')}\n          <span style=\"width:8px\"></span>\n          ${chip('data-rc','all',rc,'Qualquer cobertura')}${chip('data-rc','auto',rc,`Suíte automática (${counts.auto})`)}${chip('data-rc','fail',rc,`Falhando (${counts.fail})`)}${chip('data-rc','manual',rc,`Só manual (${counts.manual})`)}${chip('data-rc','none',rc,`Sem teste (${counts.none})`)}\n        </div>\n        <div class=\"legend\">Os casos ficam verdes ou vermelhos conforme a última execução da suíte; cinza é teste manual (E2E, SEG, VIS, REG, SCAN) ou ainda não automatizado.<button class=\"linkbtn\" data-info>Entenda a cobertura</button></div>\n        ${editId==='__new'?form(true):''}\n        ${items || '<div class=\"empty\">Nenhum requisito com esses filtros.</div>'}\n      </div>`;\n    }\n    const helpModal = d2.state.infoOpen ? `<div class=\"ibk\" data-infobk>\n        <div class=\"idlg\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Como usar a tela de testes\">\n          <div class=\"ihd\"><h3>Como usar a tela de testes</h3><button class=\"ix\" data-infox aria-label=\"Fechar\">×</button></div>\n          <p class=\"isub\">Passo a passo</p>\n          <ol class=\"steps\">\n            <li><b>Rode a suíte</b><span>Clique em <strong>Rodar suíte</strong>. Ela verifica sessão, ciclo, cálculo, acesso e a saúde dos dados direto no servidor, em cerca de 1 minuto. Só lê dados; a única gravação é o registro da própria execução.</span></li>\n            <li><b>Leia o resultado</b><span>O selo mostra \"Tudo aprovado\" ou quantos casos reprovaram. Na aba <strong>Execuções</strong> os reprovados vêm primeiro, com o valor esperado e o obtido lado a lado.</span></li>\n            <li><b>Use o histórico como evidência</b><span>Cada execução fica guardada com data, autor e duração. Clique numa execução antiga para revê-la e cite-a na nota do card antes de pedir review.</span></li>\n            <li><b>Confira o que cada teste cobre</b><span>Na aba <strong>Requisitos</strong> está a lista do que a V2 precisa fazer, com os casos ligados a cada item: verde passou, vermelho falhou, cinza é verificação manual. Os filtros mostram o que está falhando ou sem teste.</span></li>\n            <li><b>Mantenha os requisitos em dia</b><span>Use <strong>Novo requisito</strong> ou <strong>Editar</strong>. Em \"Casos de teste\", separe os IDs por vírgula. Excluir pede uma segunda confirmação.</span></li>\n          </ol>\n          <div class=\"isec\"><p class=\"isub\">Tipos de requisito</p><dl>\n            <dt>RF · requisito funcional</dt>\n            <dd>O que o painel faz para quem usa: uma tela, uma regra de cálculo, uma ação. Ex.: RF-13, calcular a remuneração pela fórmula do ciclo.</dd>\n            <dt>RNF · requisito não funcional</dt>\n            <dd>Como o sistema precisa se comportar, seja qual for a função: segurança, privacidade, desempenho, integridade, responsividade, rastreabilidade. Ex.: RNF-03, token Natura nunca fica gravado.</dd>\n          </dl></div>\n          <div class=\"isec\"><p class=\"isub\">Casos e cobertura</p><dl>\n            <dt>Casos de teste</dt>\n            <dd>UNIT, INT, ACC, SYNC, CACHE, EST, KPI e PERF rodam na suíte automática. E2E, SEG, VIS e REG são verificações manuais feitas no painel; SCAN é a varredura de segurança feita no builder.</dd>\n            <dt>Cobertura</dt>\n            <dd>Suíte automática: algum caso passou na última execução. Falhando: algum caso falhou. Só manual: só há casos manuais. Sem teste: nenhum caso ligado.</dd>\n          </dl></div>\n          <div class=\"iok\"><button class=\"primary\" data-infox>Entendi</button></div>\n        </div>\n      </div>` : '';\n    return `<div class=\"screen\" style=\"${vars}\">\n      <div class=\"header\">\n        <div class=\"htop\">\n          <div class=\"htitle\">\n            <h1>Testes V2 <span class=\"badge\">Suíte essencial</span></h1>\n            <p>Roda no servidor os casos unitários não destrutivos do processo de testes (sessão, ciclo, cálculo e integridade de dados) e guarda cada execução como evidência para o card.</p>\n          </div>\n          <div class=\"hbtns\">\n            <button class=\"helpbtn\" data-info><span class=\"q\">?</span>Como usar esta tela</button>\n            <button class=\"newbtn\" data-runall ${running?'disabled':''}>${running?'<span class=\"spin\"></span> Rodando…':`${ICON.play} Rodar suíte`}</button>\n          </div>\n        </div>\n        ${summary}\n        ${d2.state.err?`<div class=\"err\">${esc(d2.state.err)}</div>`:''}\n        <div class=\"tabs\" role=\"tablist\">\n          <button class=\"tab ${tab==='runs'?'on':''}\" data-tab=\"runs\" role=\"tab\">Execuções<span class=\"n\">${runs.length}</span></button>\n          <button class=\"tab ${tab==='reqs'?'on':''}\" data-tab=\"reqs\" role=\"tab\">Requisitos<span class=\"n\">${reqsAll.length}</span></button>\n        </div>\n      </div>\n      <div class=\"body\">${tab==='reqs' ? reqCard : casesCard + histCard}</div>\n      ${helpModal}\n    </div>`;\n  },\n  mounted(d2){\n    d2.on('[data-runall]','click', async ()=>{\n      if(d2.state.running) return;\n      d2.setState({ running:true, err:'' });\n      try{\n        const r = await d2.rush('runner').invoke({});\n        const out = (r && r.data) || r;\n        if(!out || !Array.isArray(out.results)) throw new Error('Resposta inesperada do autoteste');\n        d2.setState({ lastRun:{ _id:out.runId||'live', startedAt:new Date().toISOString(), total:out.total, passed:out.passed, failed:out.failed, durationMs:out.durationMs, results:out.results }, selId:'' });\n        const ds = d2.data('runs'); if(ds && ds.refresh) ds.refresh();\n      }catch(e){\n        d2.setState({ err:'Não foi possível rodar a suíte: '+((e && e.message) || e) });\n      }\n      d2.setState({ running:false });\n    });\n    d2.on('[data-run]','click',(e,el)=>{ d2.setState({ selId: el.dataset.run, lastRun:null }); });\n    try{ const saved = window.localStorage.getItem('pilotTestRunnerTab'); if(saved === 'reqs' || saved === 'runs') d2.setState({ tab: saved }); }catch(e){}\n    try{ if(!window.localStorage.getItem('pilotTestRunnerHelpSeen')){ window.localStorage.setItem('pilotTestRunnerHelpSeen','1'); d2.setState({ infoOpen:true }); } }catch(e){}\n    try{ if(new URLSearchParams(location.search).get('ajuda') === '1') d2.setState({ infoOpen:true }); }catch(e){}\n    try{ const qt = new URLSearchParams(location.search).get('tab'); if(qt === 'reqs' || qt === 'runs') d2.setState({ tab: qt }); }catch(e){}\n    d2.on('[data-tab]','click',(e,el)=>{ d2.setState({ tab: el.dataset.tab }); try{ window.localStorage.setItem('pilotTestRunnerTab', el.dataset.tab); }catch(err){} });\n    d2.on('[data-rq]','input',(e,el)=>{ d2.setState({ rq: el.value }); });\n    d2.on('[data-info]','click',()=>{ d2.setState({ infoOpen:true }); });\n    d2.on('[data-infox]','click',()=>{ d2.setState({ infoOpen:false }); });\n    d2.on('[data-infobk]','click',(e,el)=>{ if(e.target===el) d2.setState({ infoOpen:false }); });\n    d2.on('[data-rk]','click',(e,el)=>{ d2.setState({ rk: el.dataset.rk }); });\n    d2.on('[data-rc]','click',(e,el)=>{ d2.setState({ rc: el.dataset.rc }); });\n    const setField = (e,el)=>{ const f = Object.assign({}, d2.state.form||{}); f[el.dataset.f] = el.value; d2.state.form = f; };\n    d2.on('[data-f]','input', setField);\n    d2.on('[data-f]','change', setField);\n    d2.on('[data-rnew]','click',()=>{\n      const reqs = allReqs(d2);\n      const maxOrder = reqs.reduce((m,r)=>Math.max(m, Number(r.order)||0), 0);\n      d2.setState({ editId:'__new', form:{ kind:'funcional', status:'vigente', order: maxOrder ? maxOrder+1 : '' }, formErr:'', confirmDel:false });\n    });\n    d2.on('[data-redit]','click',(e,el)=>{\n      const r = allReqs(d2).find(x=>x._id===el.dataset.redit);\n      if(!r) return;\n      d2.setState({ editId:r._id, form:{ code:r.code, kind:r.kind||'funcional', section:r.section||'', status:r.status||'vigente', title:r.title||'', criteria:r.criteria||'', tests:(Array.isArray(r.tests)?r.tests:[]).join(', '), decision:r.decision||'', order:r.order }, formErr:'', confirmDel:false });\n    });\n    d2.on('[data-rcancel]','click',()=>{ d2.setState({ editId:'', form:null, formErr:'', confirmDel:false }); });\n    d2.on('[data-rsave]','click', async ()=>{\n      if(d2.state.saving) return;\n      const f = d2.state.form || {};\n      const tests = String(f.tests||'').split(/[,;\\s]+/).map(s=>s.trim()).filter(Boolean);\n      const record = { code:f.code, kind:f.kind, section:f.section, status:f.status, title:f.title, criteria:f.criteria, decision:f.decision, tests };\n      if(f.order !== '' && f.order != null && !isNaN(Number(f.order))) record.order = Number(f.order);\n      if(d2.state.editId && d2.state.editId !== '__new') record._id = d2.state.editId;\n      d2.setState({ saving:true, formErr:'' });\n      try{\n        const r = await d2.rush('reqWriter').invoke({ op:'upsert', record });\n        const out = (r && r.data) || r;\n        if(!out || !out.ok) throw new Error((out && out.message) || 'Não foi possível salvar');\n        await reloadReqs(d2);\n        d2.setState({ editId:'', form:null, saving:false });\n      }catch(err){ d2.setState({ saving:false, formErr:(err && err.message) || String(err) }); }\n    });\n    d2.on('[data-rdel]','click', async ()=>{\n      if(!d2.state.confirmDel){ d2.setState({ confirmDel:true }); return; }\n      const id = d2.state.editId;\n      if(!id || id === '__new') return;\n      d2.setState({ saving:true, formErr:'' });\n      try{\n        const r = await d2.rush('reqWriter').invoke({ op:'remove', record:{ _id:id } });\n        const out = (r && r.data) || r;\n        if(!out || !out.ok) throw new Error((out && out.message) || 'Não foi possível excluir');\n        await reloadReqs(d2);\n        d2.setState({ editId:'', form:null, saving:false, confirmDel:false });\n      }catch(err){ d2.setState({ saving:false, formErr:(err && err.message) || String(err) }); }\n    });\n  }\n};"}},"runner":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"runner"}}}},"runs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"runs"}}}},"reqs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"reqs"}}}},"reqWriter":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"reqWriter"}}}}}}}}}},{"_id":"6ae9ee6b1fe415b1acbbc64e","component":"data2-core-types@Component","system":"688179c2a93dd170ce61e598","params":{"extends":"data2-core-primitives@Block","component":"pilotRedesignPainel","package":"natura-x-piloto","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"// REDESIGN · Painel (GV / GN / Líder). The logic below is a copy of pilotMDashboardShell\n// (identity + token session, scope locks, impersonation, access tracking, cycle resolution,\n// loadData through the `api` param). Only two things change: the store comes from the declared\n// `store` param, and drills/back navigate between the three panel artboards through the router.\n// The `view` param says which panel this artboard shows: gv | gn | lider.\nconst ROUTER_REF = 'pilotRedesignRouter';\nasync function loadData(d2){\n  const store = d2.store('store');\n  if(!store) return;\n  const seq = (d2.state.loadSeq = (d2.state.loadSeq || 0) + 1);\n  try{\n    d2.state.loaderDone = false;\n    d2.state.loadError = '';\n    store.set('loading', true);\n    d2.refresh();\n    const perfil = store.get('perfil','gn');\n    const structureCode = store.get('structureCode','3253');\n    const rede = store.get('rede','rede1');\n    const gvName = store.get('gvName','PAINEIRA-ROSA');\n    // ── PART A — resolve the display cycle per group/sector. Default = the CURRENT\n    // calendar cycle; the header selector (cycleOptions) lets the user switch to a\n    // previous one, and that pick (cycleUserSel) survives drills while still valid.\n    // GV spans sectors: resolve on the GV's own gvName scope key; if that has no\n    // calendar rows the resolver 404s and we keep the store cycle. A manual ?cycle=\n    // override (bootstrapped into the store) still wins so a tester can pin a cycle.\n    let cycle = store.get('cycle', '');\n    const cycleForced = !!store.get('cycleForced', false);\n    if(!cycleForced){\n      const resolveKey = (perfil === 'gv') ? (gvName || structureCode) : structureCode;\n      try{\n        const rc = await d2.rush('pilotResolveDisplayCycle').invoke({ structureCode: resolveKey, perfil });\n        const rb = (rc && rc.data && rc.data.cycle) ? rc.data : (rc && rc.cycle ? rc : (rc && rc.data ? rc.data : null));\n        if(rb && (rb.calendarCycle || rb.cycle)){\n          const opts = Array.isArray(rb.availableCycles) ? rb.availableCycles : [];\n          store.set('cycleOptions', opts);\n          store.set('calendarCycle', rb.calendarCycle || '');\n          const picked = !!store.get('cycleUserSel', false) && opts.some(o=>String(o.cycle)===String(cycle));\n          if(!picked){ cycle = String(rb.calendarCycle || rb.cycle); store.set('cycle', cycle); store.set('cycleUserSel', false); }\n        } else if(!cycle){\n          cycle = '202610'; store.set('cycle', cycle);\n        }\n      }catch(e){ d2.log('resolveDisplayCycle error', e); if(!cycle){ cycle = '202610'; store.set('cycle', cycle); } }\n    }\n    if(!cycle){ cycle = '202610'; store.set('cycle', cycle); }\n    const res = await d2.rush('api').invoke({ perfil, structureCode, cycle, rede, gvName });\n    if(seq !== d2.state.loadSeq) return; // a newer load (rede/cycle switch) already took over\n    const payload = (res && (res.payload || (res.data && res.data.payload))) || (res && res.data) || res;\n    if(payload && payload.perfil){ store.set('data', payload); }\n    else { d2.state.loadError = 'O servidor respondeu sem os dados do painel.'; }\n    store.set('loading', false);\n    d2.refresh();\n  }catch(e){\n    d2.log('shell load error', e);\n    if(seq !== d2.state.loadSeq) return;\n    d2.state.loadError = (e && e.message) ? String(e.message) : String(e);\n    store.set('loading', false);\n    d2.refresh();\n  }\n}\n// ── Panel routing (new): each panel is its own artboard behind pilotRedesignRouter ──\nfunction curView(d2){\n  const v = String(d2.param('view','gv') || 'gv');\n  return (v === 'gn' || v === 'lider') ? v : 'gv';\n}\nfunction queryParam(name){\n  try{ return new URLSearchParams((typeof location!=='undefined' && location.search) || '').get(name) || ''; }catch(e){ return ''; }\n}\nfunction routerGo(d2, path){\n  try{ d2.router(ROUTER_REF).goTo(path); }catch(e){ d2.log('router goTo error', path, e); }\n}\n// Same artboard → re-run this panel in place (the router keeps it mounted); other → navigate.\nfunction goView(d2, view, query){\n  const path = '/' + view + (query ? ('?' + query) : '');\n  routerGo(d2, path);\n  if(view === curView(d2)) bootView(d2);\n}\n// Builder canvas only: the GN/Líder artboards have no ?setor/?grupo there, so show a real sample\n// (sector 3253 = the old shell's default, and its first leader) instead of bouncing to the GV panel.\nfunction inBuilder(d2){\n  try{ if(d2.context && d2.context.isBuilder) return true; }catch(e){}\n  try{ const c = window.D2Env && window.D2Env.context; if(c && (c.builder || c.artboardPreview)) return true; }catch(e){}\n  try{ return /\\/preview\\//.test(String(location.pathname || '')); }catch(e){ return false; }\n}\nasync function builderSample(d2){\n  if(!inBuilder(d2) || curView(d2) !== 'lider' || queryParam('grupo') || d2.state.builderGroup) return;\n  const store = d2.store('store');\n  try{\n    const res = await d2.rush('api').invoke({ perfil:'gn', structureCode: (store && store.get('structureCode','')) || '3253', cycle: (store && store.get('cycle','')) || '', rede: (store && store.get('rede','rede1')) || 'rede1', gvName: (store && store.get('gvName','')) || '' });\n    const p = (res && (res.payload || (res.data && res.data.payload))) || (res && res.data) || res;\n    const l = p && Array.isArray(p.leaders) ? p.leaders[0] : null;\n    if(l) d2.state.builderGroup = String(l.codigoGrupo != null ? l.codigoGrupo : l.structureCode);\n  }catch(e){ d2.log('builderSample error', e); }\n}\nfunction homeView(d2){\n  const p = effectivePerfil(d2);\n  return p === 'gn' ? 'gn' : (p === 'lider' ? 'lider' : 'gv');\n}\n// Point the store at what THIS artboard shows, inside the effective identity's scope.\n// Returns false when the panel is out of scope and we navigated away instead.\nfunction applyView(d2){\n  const store = d2.store('store');\n  if(!store) return false;\n  const view = curView(d2);\n  const eff = resolveEffectiveIdentity(d2) || {};\n  const effP = eff.perfil || 'gv';\n  const own = String(eff.structureCode || eff.sectorCode || '');\n  if(view === 'gv'){\n    if(effP !== 'gv'){ routerGo(d2, '/' + homeView(d2)); return false; }\n    store.set('perfil','gv');\n    return true;\n  }\n  if(view === 'gn'){\n    if(effP === 'lider'){ routerGo(d2, '/lider'); return false; }\n    if(effP === 'gn'){ store.set('perfil','gn'); store.set('structureCode', own); return true; }\n    const setor = queryParam('setor') || (inBuilder(d2) ? String(store.get('structureCode','') || '3253') : '');\n    if(!setor || !sectorAllowed(d2, setor)){ routerGo(d2, '/gv'); return false; }\n    if(!d2.shared.get('pilotGvRede','', { global:true })) d2.shared.set('pilotGvRede', store.get('rede','rede1'), { global:true });\n    store.set('perfil','gn');\n    store.set('structureCode', String(setor));\n    return true;\n  }\n  if(effP === 'lider'){\n    store.set('perfil','lider');\n    store.set('structureCode', String(eff.structureCode || ''));\n    store.set('pilotLiderSetor', String(eff.sectorCode || ''));\n    return true;\n  }\n  const grupo = queryParam('grupo') || (inBuilder(d2) ? (d2.state.builderGroup || '') : '');\n  const setor = queryParam('setor') || ((inBuilder(d2) && !queryParam('grupo')) ? String(store.get('structureCode','') || '3253') : '');\n  // A GN reaches a leader only from her own grid (the drill marks the group); a typed URL is refused.\n  const drilled = String(d2.shared.get('pilotDrillGroup','', { global:true }) || '');\n  const okGn = effP !== 'gn' || inBuilder(d2) || (!!grupo && drilled === String(grupo));\n  if(!grupo || !okGn || !groupAllowed(d2, grupo, setor || null)){ routerGo(d2, '/' + homeView(d2)); return false; }\n  store.set('perfil','lider');\n  store.set('structureCode', String(grupo));\n  store.set('pilotLiderSetor', String(setor || (effP === 'gn' ? own : '')));\n  return true;\n}\n// Mount flow of the old shell (identity → tracking → invalid check → load → view event),\n// plus applyView in between. Also re-run in place after a switch/impersonation.\nasync function bootView(d2){\n  const seq = (d2.state.bootSeq = (d2.state.bootSeq || 0) + 1);\n  d2.state.viewReady = false;\n  d2.state.loadError = '';\n  d2.state.modal = null;\n  d2.state.page = 1;\n  await resolveIdentityAndSeed(d2);\n  if(seq !== d2.state.bootSeq) return;\n  await pilotTrackMount(d2);\n  const store = d2.store('store');\n  // App B: an invalid token shows the \"sessão inválida\" screen — do NOT fetch\n  // default dashboard data (that would render a silent full-GV view = scope leak).\n  if(store && store.get('pilotTokenInvalid', false)){\n    pilotTrackEnd(d2);\n    d2.state.loaderDone = true; d2.state.viewReady = true; d2.refresh(); return;\n  }\n  await builderSample(d2);\n  if(!applyView(d2)) return;\n  if(store) store.set('data', null);\n  d2.state.viewReady = true;\n  await loadData(d2);\n  if(seq !== d2.state.bootSeq) return;\n  try{\n    const p = store ? store.get('perfil','gn') : 'gn';\n    pilotTrackView(d2, 'dashboard:'+p, p);\n  }catch(e){}\n}\n// Sair = logout on pilotMaiaAuth + forget the stored token, then back to \"/\".\nasync function onLogout(d2){\n  pilotTrackEnd(d2);\n  try{ await d2.auth('auth').logout(); }catch(e){ d2.log('logout error', e); }\n  try{ window.localStorage.removeItem('_d2_natura_session'); }catch(e){}\n  const store = d2.store('store');\n  if(store){\n    store.set('pilotTokenSession', null);\n    store.set('pilotActingIdentity', null);\n    store.set('pilotEffectiveIdentity', null);\n    store.set('pilotImpersonating', false);\n    store.set('data', null);\n  }\n  ['pilotUrlToken','pilotActingUserId','pilotImpersonateUserId','pilotGvRede','pilotReturnPerfil','pilotReturnStructure','pilotSelectedGroup','pilotDrillGroup']\n    .forEach(k=>{ try{ d2.shared.set(k, '', { global:true }); }catch(e){} });\n  d2.state.selGroup = '';\n  goView(d2, 'gv');\n}\n// Drill GN sector → LIDER group (remembers the sector to return to)\nfunction drillToLider(d2, groupCode, groupSectorCode){\n  const store = d2.store('store');\n  if(!store || !groupCode) return;\n  // STEP 3 clamp: a Líder cannot drill anywhere; a GN can only drill into its own sector.\n  if(scopeLockedToGroup(d2)) return;\n  if(!groupAllowed(d2, groupCode, groupSectorCode)) { d2.log('drillToLider blocked (out of scope)', groupCode); return; }\n  const curPerfil = store.get('perfil','gn');\n  const sector = String(groupSectorCode || store.get('structureCode','') || '');\n  if(curPerfil !== 'lider'){\n    // remember where we came from so \"Voltar\" restores it\n    d2.shared.set('pilotReturnPerfil', curPerfil, { global:true });\n    d2.shared.set('pilotReturnStructure', store.get('structureCode',''), { global:true });\n  }\n  d2.shared.set('pilotDrillGroup', String(groupCode), { global:true });\n  pilotTrackView(d2, 'dashboard:lider', 'lider');\n  goView(d2, 'lider', 'grupo=' + encodeURIComponent(groupCode) + (sector ? ('&setor=' + encodeURIComponent(sector)) : ''));\n}\n// Drill GV rede → GN sector (remembers the GV rede to return to)\nfunction drillToGn(d2, sectorCode){\n  const store = d2.store('store');\n  if(!store || !sectorCode) return;\n  // STEP 3 clamp: only a GV may switch to an arbitrary sector. A GN/Líder is pinned.\n  if(!sectorAllowed(d2, sectorCode)) { d2.log('drillToGn blocked (out of scope)', sectorCode); return; }\n  const curPerfil = store.get('perfil','gn');\n  if(curPerfil === 'gv'){\n    // Mark that this GN view was entered from a GV grid (survives a GN→LIDER→GN round-trip)\n    d2.shared.set('pilotGvRede', store.get('rede','rede1'), { global:true });\n  }\n  d2.state.selGroup = '';\n  d2.shared.set('pilotSelectedGroup', '', { global:true });\n  pilotTrackView(d2, 'dashboard:gn', 'gn');\n  goView(d2, 'gn', 'setor=' + encodeURIComponent(sectorCode));\n}\n// Back GN → GV (rede) — pops one level up to the GV grid we came from\nfunction backToGv(d2){\n  const store = d2.store('store');\n  if(!store) return;\n  // STEP 3 clamp: a GN/Líder can NEVER go up to the GV view.\n  if(scopeLockedToSector(d2) || scopeLockedToGroup(d2)) { d2.log('backToGv blocked (out of scope)'); return; }\n  const retRede = d2.shared.get('pilotGvRede', 'rede1', { global:true }) || 'rede1';\n  store.set('rede', retRede);\n  d2.state.selGroup = '';\n  d2.shared.set('pilotSelectedGroup', '', { global:true });\n  d2.shared.set('pilotGvRede', '', { global:true });\n  pilotTrackView(d2, 'dashboard:gv', 'gv');\n  goView(d2, 'gv');\n}\n// Back LIDER → GN sector (only valid when the effective identity is a GV or GN who\n// drilled DOWN to a leader; an effective LÍDER identity is locked to its group and\n// has no sector to return to — STEP 3).\nfunction backToSector(d2){\n  const store = d2.store('store');\n  if(!store) return;\n  if(scopeLockedToGroup(d2)) { d2.log('backToSector blocked — effective identity is a locked Líder'); return; }\n  let retStruct = d2.shared.get('pilotReturnStructure', '', { global:true }) || store.get('pilotLiderSetor','');\n  // A GN drilling back always lands on its OWN sector, never a GV view.\n  if(scopeLockedToSector(d2)){\n    const eff = resolveEffectiveIdentity(d2);\n    if(eff) retStruct = String(eff.structureCode || eff.sectorCode || '');\n  }\n  d2.state.selGroup = '';\n  d2.shared.set('pilotSelectedGroup', '', { global:true });\n  pilotTrackView(d2, 'dashboard:sector', 'gn');\n  goView(d2, 'gn', retStruct ? ('setor=' + encodeURIComponent(retStruct)) : '');\n}\n// ─────────────────────────────────────────────────────────────────────────────\n// STEP 2 — IDENTITY RESOLVER SEAM (prod-compliant abstraction)\n// Everything downstream consumes ONLY resolveActingIdentity / resolveEffectiveIdentity.\n// PILOT source of the acting identity = d2.shared 'pilotActingUserId' (set by the\n// switcher) or the ?actingUser= query param, defaulting to the seeded GV.\n// PROD source (documented, not wired): the acting identity would come from the\n// session token instead of d2.shared — see readActingUserId() below.\n// ─────────────────────────────────────────────────────────────────────────────\nfunction readActingIdentitySource(d2){\n  // App B / TOKEN mode — check FIRST. A token/user in the URL means the scoped\n  // end-user app; identity is that user and there is NO impersonation UI.\n  try{\n    const q = new URLSearchParams((typeof location!=='undefined' && location.search) || '');\n    // App B / TOKEN — prod reads the auth token from the URL as\n    // ?authorization (the OAM cookie) || ?token || ?c. We read all three, in\n    // that prod precedence, then keep ?actingUser as a DEV-only fallback so a\n    // tester can still open a pilot-user directly by id without a real token.\n    // V1-style session: the router stores the token in localStorage (_d2_natura_session) and\n    // strips it from the URL, so fall back to the stored token when the URL has none.\n    let urlToken = q.get('authorization') || q.get('token') || q.get('c');\n    if(!urlToken){ try{ const ns = JSON.parse(window.localStorage.getItem('_d2_natura_session') || 'null'); if(ns && ns.token) urlToken = ns.token; }catch(e){} }\n    const actingUser = q.get('actingUser');\n    if(urlToken || actingUser){\n      d2.shared.set('pilotMode', 'token', { global:true });\n      // token mode can never be impersonating - clear any stale target\n      d2.shared.set('pilotImpersonateUserId', '', { global:true });\n      if(urlToken){\n        d2.shared.set('pilotUrlToken', urlToken, { global:true });\n        // acting user id is unknown until pilotResolveSession returns it\n        return { userId: '', mode: 'token', token: urlToken };\n      }\n      // DEV fallback: ?actingUser=<pilot-user id> stands in for the decoded subject\n      d2.shared.set('pilotActingUserId', actingUser, { global:true });\n      return { userId: actingUser, mode: 'token' };\n    }\n    d2.shared.set('pilotUrlToken', '', { global:true });\n  }catch(e){}\n  // App A / GV-ADMIN mode (fallback). PROD App A: identity from login session.\n  d2.shared.set('pilotMode', 'gv-admin', { global:true });\n  const uid = d2.shared.get('pilotActingUserId', '', { global:true }) || '';\n  return { userId: uid, mode: 'gv-admin' };\n}\nfunction readActingUserId(d2){ return readActingIdentitySource(d2).userId; }\n// The mode the shell resolved on mount (cached into the store). 'token' hides all\n// role-switching UI; 'gv-admin' shows the switcher + Ver como.\nfunction resolveMode(d2){\n  const store = d2.store('store');\n  return (store && store.get('pilotMode', 'gv-admin')) || 'gv-admin';\n}\nfunction readImpersonateUserId(d2){\n  return d2.shared.get('pilotImpersonateUserId', '', { global:true }) || '';\n}\n// Resolve acting + effective identities via the server-side seam (pilotResolveIdentity).\nasync function resolveIdentities(d2){\n  const actingUserId = readActingUserId(d2);\n  const impersonateUserId = readImpersonateUserId(d2);\n  try{\n    const res = await d2.rush('pilotResolveIdentity').invoke({ actingUserId, impersonateUserId });\n    const body = (res && res.data && res.data.data) ? res.data.data : (res && res.data ? res.data : res);\n    if(body && (body.acting || body.effective)) return body;\n  }catch(e){ d2.log('resolveIdentities error', e); }\n  return { acting:null, effective:null, impersonating:false };\n}\nfunction resolveActingIdentity(d2){\n  const store = d2.store('store');\n  return (store && store.get('pilotActingIdentity', null)) || null;\n}\nfunction resolveEffectiveIdentity(d2){\n  const store = d2.store('store');\n  return (store && store.get('pilotEffectiveIdentity', null))\n    || (store && store.get('pilotActingIdentity', null)) || null;\n}\nfunction isImpersonating(d2){\n  const store = d2.store('store');\n  return !!(store && store.get('pilotImpersonating', false));\n}\n// ── STEP 2/3 — mount-time identity resolution ────────────────────────────────\nasync function resolveIdentityAndSeed(d2){\n  const store = d2.store('store');\n  if(!store) return;\n  const src = readActingIdentitySource(d2);        // establishes pilotMode + acting id\n  store.set('pilotMode', src.mode);\n  store.set('pilotTokenInvalid', false);\n  store.set('pilotTokenInvalidReason', '');\n  d2.shared.set('pilotTokenInvalid', false, { global:true }); // launchers (Histórico/Simulador) hide on an invalid session\n  // ── App B / TOKEN INGRESS — resolve the URL token via the pilotResolveSession\n  // Rush endpoint. The token in the URL is exchanged for a scoped identity server-side.\n  if(src.mode === 'token' && src.token){\n    // Session persistence: a resolved token-session survives SPA navigation via\n    // the pilot store (reused as the session store — key 'pilotTokenSession').\n    const cached = store.get('pilotTokenSession', null);\n    let identity = (cached && cached.token === src.token && cached.identity) ? cached.identity : null;\n    if(!identity){\n      try{\n        const res = await d2.rush('pilotResolveSession').invoke({ token: src.token });\n        const b = (res && res.data && res.data.data) ? res.data.data : (res && res.data ? res.data : res);\n        if(b && b.valid && b.userId){\n          identity = b;\n          store.set('pilotTokenSession', { token: src.token, identity: identity });\n        } else if(b && b.reason){\n          store.set('pilotTokenInvalidReason', String(b.reason));\n        }\n      }catch(e){ d2.log('pilotResolveSession error', e); }\n    }\n    if(identity){\n      // Token identity has no impersonation. acting == effective == the scoped user.\n      d2.shared.set('pilotActingUserId', identity.userId, { global:true });\n      store.set('pilotActingIdentity', identity);\n      store.set('pilotEffectiveIdentity', identity);\n      store.set('pilotImpersonating', false);\n      seedStoreFromEffective(d2);\n      return; // token mode: no switcher, no pilotResolveIdentity round-trip\n    }\n    // Invalid/expired token → \"sessão inválida\" state (rendered by the panel).\n    store.set('pilotTokenInvalid', true);\n    d2.shared.set('pilotTokenInvalid', true, { global:true });\n    store.set('pilotTokenSession', null);\n    return;\n  }\n  const body = await resolveIdentities(d2);         // { acting, effective, impersonating }\n  if(body){\n    if(body.acting) store.set('pilotActingIdentity', body.acting);\n    if(body.effective) store.set('pilotEffectiveIdentity', body.effective);\n    store.set('pilotImpersonating', !!body.impersonating);\n  }\n  // Clamp the dashboard store to the effective identity (STEP 3).\n  seedStoreFromEffective(d2);\n  // Populate the pilot user-switcher (gv-admin only). Token mode has no switcher.\n  if(src.mode !== 'token') ensureSwitcherUsers(d2);\n}\n// Load the full pilot-user roster once for the switcher dropdown (gv-admin\n// stand-in for the App-A login). Distinct from pilotAllowedTargets (scope-limited).\nasync function ensureSwitcherUsers(d2){\n  if(Array.isArray(d2.state.switcherUsers) && d2.state.switcherUsers.length) return;\n  try{\n    const res = await d2.rush('pilotUsers').invoke({});\n    const b = (res && res.data && res.data.data) ? res.data.data : (res && res.data ? res.data : res);\n    d2.state.switcherUsers = (b && Array.isArray(b.users)) ? b.users : [];\n    d2.refresh();\n  }catch(e){ d2.log('switcherUsers error', e); }\n}\n// PILOT switcher (App-A stand-in for login). Sets the acting user + reloads as them.\nfunction onSwitchActingUser(d2, uid){\n  if(!uid) return;\n  d2.shared.set('pilotActingUserId', uid, { global:true });\n  d2.shared.set('pilotImpersonateUserId', '', { global:true }); // switching identity ends any impersonation\n  reloadAsIdentity(d2);\n}\n// Fetch the allowed impersonation targets for the current acting user (rules + scope).\nasync function ensureAllowedTargets(d2){\n  const acting = resolveActingIdentity(d2);\n  const actorUserId = (acting && acting.userId) || d2.shared.get('pilotActingUserId','', { global:true });\n  if(!actorUserId){ d2.state.allowedTargets = []; d2.refresh(); return; }\n  if(d2.state.allowedTargetsFor === actorUserId && Array.isArray(d2.state.allowedTargets)) return;\n  d2.state.allowedTargetsLoading = true; d2.refresh();\n  try{\n    const res = await d2.rush('pilotAllowedTargets').invoke({ actorUserId });\n    const b = (res && res.data && res.data.data) ? res.data.data : (res && res.data ? res.data : res);\n    d2.state.allowedTargets = (b && Array.isArray(b.targets)) ? b.targets : [];\n    d2.state.allowedTargetsFor = actorUserId;\n  }catch(e){ d2.log('allowedTargets error', e); d2.state.allowedTargets = []; }\n  finally{ d2.state.allowedTargetsLoading = false; d2.refresh(); }\n}\n// Pick a target -> validate via pilotImpersonate (403 if denied) -> apply effective identity + reload.\nasync function onPickImpersonationTarget(d2, targetUserId){\n  if(!targetUserId) return;\n  const store = d2.store('store');\n  const acting = resolveActingIdentity(d2);\n  const actorUserId = (acting && acting.userId) || d2.shared.get('pilotActingUserId','', { global:true });\n  const cycle = store ? store.get('cycle','202610') : '202610';\n  try{\n    const res = await d2.rush('pilotImpersonate').invoke({ actorUserId, targetUserId, cycle });\n    const b = (res && res.data && res.data.data) ? res.data.data : (res && res.data ? res.data : res);\n    if(!b || b.code === 403 || b.allowed === false){\n      d2.state.impError = (b && b.message) || 'Você não tem permissão para ver como essa pessoa.';\n      d2.refresh();\n      return;\n    }\n    d2.shared.set('pilotImpersonateUserId', targetUserId, { global:true });\n    d2.state.impPickerOpen = false; d2.state.impError = null;\n    pilotTrackView(d2, 'impersonation:start', (b && b.perfil) || 'impersonation', 'impersonation');\n    reloadAsIdentity(d2);\n  }catch(e){\n    d2.state.impError = 'Não foi possível abrir a visualização: ' + (e && e.message ? e.message : String(e));\n    d2.refresh();\n  }\n}\n// Sair da impersonação -> log end + restore actor + full scope.\nasync function onExitImpersonation(d2){\n  const store = d2.store('store');\n  const acting = resolveActingIdentity(d2);\n  const actorUserId = (acting && acting.userId) || d2.shared.get('pilotActingUserId','', { global:true });\n  const targetUserId = d2.shared.get('pilotImpersonateUserId','', { global:true });\n  const cycle = store ? store.get('cycle','202610') : '202610';\n  try{ await d2.rush('pilotEndImpersonation').invoke({ actorUserId, targetUserId, cycle }); }\n  catch(e){ d2.log('endImpersonation error', e); }\n  d2.shared.set('pilotImpersonateUserId', '', { global:true });\n  pilotTrackView(d2, 'impersonation:end', 'gv');\n  reloadAsIdentity(d2);\n}\n// Re-resolve identity, clear any drill breadcrumbs, then boot the panel again — which\n// moves to the panel of the new effective identity when it is not this one.\nasync function reloadAsIdentity(d2){\n  const store = d2.store('store');\n  if(store){\n    store.set('data', null);\n    d2.shared.set('pilotGvRede','', { global:true });\n    d2.shared.set('pilotReturnPerfil','', { global:true });\n    d2.shared.set('pilotReturnStructure','', { global:true });\n    d2.shared.set('pilotSelectedGroup','', { global:true });\n    d2.shared.set('pilotDrillGroup','', { global:true });\n    d2.state.selGroup = '';\n  }\n  await bootView(d2);\n}\n// The effective perfil drives ALL scope locks. When a GV impersonates a GN/Líder,\n// the effective perfil becomes gn/lider so the SAME locks apply.\nfunction effectivePerfil(d2){\n  const eff = resolveEffectiveIdentity(d2);\n  return (eff && eff.perfil) || 'gv';\n}\n// STEP 3 — SCOPE ENFORCEMENT. Seed + clamp the dashboard store to the effective identity.\nfunction seedStoreFromEffective(d2){\n  const store = d2.store('store');\n  const eff = resolveEffectiveIdentity(d2);\n  if(!store || !eff) return;\n  const perfil = eff.perfil || 'gv';\n  store.set('perfil', perfil);\n  store.set('gvName', eff.gvName || 'PAINEIRA-ROSA');\n  if(perfil === 'gn'){\n    store.set('structureCode', String(eff.structureCode || eff.sectorCode || ''));\n    if(eff.rede) store.set('rede', eff.rede);\n  } else if(perfil === 'lider'){\n    store.set('structureCode', String(eff.structureCode || ''));\n    if(eff.rede) store.set('rede', eff.rede);\n  } else {\n    // GV — keep full navigation; only default the structure if empty.\n    if(eff.rede) store.set('rede', eff.rede);\n  }\n}\n// gv → no locks; gn → locked to own sector (may drill down to a leader read-only);\n// lider → locked to own group (no drill/back at all).\nfunction scopeLockedToSector(d2){ return effectivePerfil(d2) === 'gn'; }\nfunction scopeLockedToGroup(d2){ return effectivePerfil(d2) === 'lider'; }\n// Clamp any attempt to move to a sector the effective GN doesn't own.\nfunction sectorAllowed(d2, sectorCode){\n  const eff = resolveEffectiveIdentity(d2);\n  if(!eff) return true;\n  if(eff.perfil === 'gv') return true;\n  if(eff.perfil === 'gn') return String(sectorCode) === String(eff.structureCode || eff.sectorCode || '');\n  if(eff.perfil === 'lider') return String(sectorCode) === String(eff.sectorCode || '');\n  return true;\n}\n// Clamp any attempt to drill into a group outside the effective identity's scope.\nfunction groupAllowed(d2, groupCode, groupSectorCode){\n  const eff = resolveEffectiveIdentity(d2);\n  if(!eff) return true;\n  if(eff.perfil === 'gv') return true;\n  if(eff.perfil === 'gn'){\n    if(groupSectorCode != null) return String(groupSectorCode) === String(eff.structureCode || eff.sectorCode || '');\n    return true;\n  }\n  if(eff.perfil === 'lider') return String(groupCode) === String(eff.structureCode || '');\n  return true;\n}\nfunction escH(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nconst PERFIL_LABEL = { gv:'GV', gn:'GN', lider:'Líder' };\nfunction perfilLabel(p){ return PERFIL_LABEL[p] || String(p||''); }\n// End-user (token) session? Not only the store's pilotMode — the global store handle can come back\n// empty on some loads — but also the shared flag, a token in the URL, or the locally stored token.\nfunction isTokenMode(d2){\n  if(resolveMode(d2) === 'token') return true;\n  try{ if(d2.shared.get('pilotMode', '', { global:true }) === 'token') return true; }catch(e){}\n  try{ const q = new URLSearchParams((typeof location!=='undefined' && location.search) || ''); if(q.get('authorization') || q.get('token') || q.get('c')) return true; }catch(e){}\n  try{ const ns = JSON.parse(window.localStorage.getItem('_d2_natura_session') || 'null'); if(ns && ns.token) return true; }catch(e){}\n  return false;\n}\n// ─────────────────────────────────────────────────────────────────────────────\n// ACCESS TRACKING (additive) — sessions + section-view events via pilotTrackAccess.\n// One session per BROWSER session (sessionStorage), reused across SPA reloads.\n// ─────────────────────────────────────────────────────────────────────────────\nconst PILOT_SID_KEY = 'pilotAccessSessionId';\nlet _pilotViewInFlight = null; // dedupe: last section we emitted a view for\nfunction pilotSidStore(){\n  try{ return (typeof window!=='undefined' && window.sessionStorage) ? window.sessionStorage : null; }catch(e){ return null; }\n}\nfunction pilotGetSid(d2){\n  const ss = pilotSidStore();\n  let sid = '';\n  try{ if(ss) sid = ss.getItem(PILOT_SID_KEY) || ''; }catch(e){}\n  if(!sid){\n    const store = d2.store('store');\n    if(store) sid = store.get('pilotAccessSid','') || '';\n  }\n  return sid;\n}\nfunction pilotSetSid(d2, sid){\n  if(!sid) return;\n  const ss = pilotSidStore();\n  try{ if(ss) ss.setItem(PILOT_SID_KEY, sid); }catch(e){}\n  const store = d2.store('store');\n  if(store) store.set('pilotAccessSid', sid);\n}\nfunction pilotMakeSid(){\n  try{ if(typeof crypto!=='undefined' && crypto.randomUUID) return 's-'+crypto.randomUUID(); }catch(e){}\n  return 's-'+Date.now()+'-'+Math.floor(Math.random()*1e9);\n}\n// effective identity + current store scope, flattened into the tracker payload shape.\nfunction pilotIdentityPayload(d2){\n  const store = d2.store('store');\n  const eff = (typeof resolveEffectiveIdentity==='function' ? resolveEffectiveIdentity(d2) : null) || {};\n  const impersonating = (typeof isImpersonating==='function') ? isImpersonating(d2) : false;\n  const rawMode = store ? store.get('pilotMode','gv-admin') : 'gv-admin';\n  // entryMode = the identity mode; a login while impersonating carries mode 'impersonation'.\n  const mode = impersonating ? 'impersonation' : (rawMode === 'gv-admin' ? 'session' : rawMode);\n  let ua = ''; let ref = '';\n  try{ ua = (typeof navigator!=='undefined' && navigator.userAgent) || ''; }catch(e){}\n  try{ ref = (typeof document!=='undefined' && document.referrer) || ''; }catch(e){}\n  return {\n    userId: eff.userId || (store && store.get('pilotActingUserId','')) || '',\n    name: eff.name || '',\n    perfil: eff.perfil || (store && store.get('perfil','')) || '',\n    mode: mode,\n    entryMode: mode,\n    structureCode: eff.structureCode || (store && store.get('structureCode','')) || '',\n    sectorCode: eff.sectorCode || '',\n    rede: eff.rede || (store && store.get('rede','')) || '',\n    gvName: eff.gvName || (store && store.get('gvName','')) || '',\n    cycle: (store && store.get('cycle','')) || '',\n    userAgent: ua,\n    referrer: ref\n  };\n}\n// On mount, AFTER identity resolves: reuse a stored sessionId (heartbeat) or FRESH login.\nasync function pilotTrackMount(d2){\n  try{\n    const store = d2.store('store');\n    // Do not track the invalid-session screen (no identity resolved).\n    if(store && store.get('pilotTokenInvalid', false)) return;\n    const existing = pilotGetSid(d2);\n    if(existing){\n      d2.rush('pilotTrackAccess').invoke({ action:'heartbeat', sessionId: existing }).catch(()=>{});\n      return;\n    }\n    const sid = pilotMakeSid();\n    const payload = pilotIdentityPayload(d2);\n    payload.action = 'login';\n    payload.sessionId = sid;\n    // Optimistically store first so a fast reload reuses it even if the call is in flight.\n    pilotSetSid(d2, sid);\n    const res = await d2.rush('pilotTrackAccess').invoke(payload);\n    const b = (res && res.data) ? res.data : res;\n    if(b && b.sessionId) pilotSetSid(d2, b.sessionId);\n  }catch(e){ d2.log('pilotTrackMount error', e); }\n}\n// Section navigation → one view event per logical navigation (deduped by section+level).\nfunction pilotTrackView(d2, section, drillLevel, modeOverride){\n  try{\n    if(!section) return;\n    const sid = pilotGetSid(d2);\n    if(!sid) return;\n    const key = section + '|' + (drillLevel||'') + '|' + (modeOverride||'');\n    if(_pilotViewInFlight === key) return; // collapse repeated same-target navigations\n    _pilotViewInFlight = key;\n    const payload = { action:'view', sessionId: sid, section: section, drillLevel: drillLevel||'' };\n    if(modeOverride) payload.mode = modeOverride; // event-level mode (e.g. 'impersonation')\n    d2.rush('pilotTrackAccess').invoke(payload)\n      .catch(()=>{})\n      .then(()=>{ if(_pilotViewInFlight===key) _pilotViewInFlight = null; });\n  }catch(e){ d2.log('pilotTrackView error', e); }\n}\n// Exit / logout / token-invalid → best-effort session-end (does not block).\nfunction pilotTrackEnd(d2){\n  try{\n    const sid = pilotGetSid(d2);\n    if(!sid) return;\n    d2.rush('pilotTrackAccess').invoke({ action:'session-end', sessionId: sid }).catch(()=>{});\n    const ss = pilotSidStore();\n    try{ if(ss) ss.removeItem(PILOT_SID_KEY); }catch(e){}\n    const store = d2.store('store');\n    if(store) store.set('pilotAccessSid','');\n  }catch(e){ d2.log('pilotTrackEnd error', e); }\n}\nfunction mapLeaders(leaders){\n  return (leaders || []).map(l => {\n    const comp = (l.breakdown && l.breakdown.components) || l.components || null;\n    const gainByRef = (comp && Array.isArray(comp.gainByRef)) ? comp.gainByRef : [];\n    return {\n      name: l.name || ('Grupo ' + l.structureCode),\n      codigoGrupo: l.codigoGrupo != null ? l.codigoGrupo : l.structureCode,\n      nivel: l.nivel,\n      rede: l.rede,\n      remuneracao: l.remuneracao,\n      stats: l.stats || [],\n      composition: comp,\n      gainByRef: gainByRef,\n      drivers: l.drivers || null\n    };\n  });\n}\n// Extract {composition, gainByRef} from a node carrying breakdown.components or components.\nfunction compOf(node){\n  if(!node) return { composition:null, gainByRef:[] };\n  const comp = (node.breakdown && node.breakdown.components) || node.components || null;\n  const gainByRef = (comp && Array.isArray(comp.gainByRef)) ? comp.gainByRef : [];\n  return { composition: comp, gainByRef: gainByRef };\n}\n// ─────────────────────────────────────────────────────────────────────────────\n// NEW LAYOUT — the prototype \"Painel\" boards (GV / GN / Líder), responsive.\n// ─────────────────────────────────────────────────────────────────────────────\nconst ASSET = 'https://natura-x-piloto.data2.media/file/';\nconst IMG = {\n  logo: ASSET + 'H0P_N-7AQzQOg_VJMBWzV',\n  logoW: ASSET + 'l8OGBbGu-q9PqWy_enKhS',\n  natura: ASSET + 'UrhVLdPDEZCXToLgJDPW8',\n  avon: ASSET + 'HqLhKqINaRUI9OSBjYGFh'\n};\nconst MEDAL = { prata:'XaupHTnpmugw-UyhnYvo2', ouro:'9hek6z8USd_zqLqsBAr3x', diamante:'L2wHYI7sUGWajYkS6vOG8', bronze:'3E3WozfBJQ-U3TeDeBPgN', cristal:'Yqrae4YObN99lRdeZ-lgz', 'diamante+':'okKvTBHVWJcsMxxoqZ7_3' };\nconst COL = { green:'#1B9A55', amber:'#E8590C', red:'#E5231B', none:'#C9BDB5' };\nconst TIP = { green:'Meta batida (100% ou mais)', amber:'Entre 60% e 99% da meta', red:'Abaixo de 60% da meta', none:'' };\nconst TINT = { green:'#E8F5EE', amber:'#FDF0E7', red:'#FDECEC', none:'#F5EEE9' };\nconst ICO = {\n  people: 'M6 7a3 3 0 1 0 6 0a3 3 0 1 0-6 0M2 21v-2a5 5 0 0 1 5-5h4a5 5 0 0 1 5 5v2M17 7a3 3 0 0 1 0 6M22 21v-2a5 5 0 0 0-3-4.5',\n  user: 'M8.5 8a3.5 3.5 0 1 0 7 0a3.5 3.5 0 1 0-7 0M4 21v-2a5 5 0 0 1 5-5h6a5 5 0 0 1 5 5v2',\n  crown: 'M3 8l4 4 5-6 5 6 4-4v9H3zM3 20h18',\n  swap: 'M12 4v16M7 8l-4 4 4 4M17 8l4 4-4 4',\n  add: 'M5.5 8a3.5 3.5 0 1 0 7 0a3.5 3.5 0 1 0-7 0M2 20v-1.5a5 5 0 0 1 5-5h4M18 12v6M15 15h6',\n  target: 'M3 12a9 9 0 1 0 18 0a9 9 0 1 0-18 0M7 12a5 5 0 1 0 10 0a5 5 0 1 0-10 0M10.5 12a1.5 1.5 0 1 0 3 0a1.5 1.5 0 1 0-3 0',\n  painel: 'M3 3h7v9H3zM14 3h7v5h-7zM14 12h7v9h-7zM3 16h7v5H3z',\n  vercomo: 'M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12zM9 12a3 3 0 1 0 6 0a3 3 0 1 0-6 0',\n  simulador: 'M6 2h12a2 2 0 0 1 2 2v16a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2zM8 6h8M8 10h.01M12 10h.01M16 10h.01M8 14h.01M12 14h.01M16 14h.01M8 18h8',\n  historico: 'M3 12a9 9 0 1 0 3-6.7L3 8M3 3v5h5M12 7v5l3 2'\n};\nconst OUT_D = 'M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9';\nconst MEDAL_D = 'M12 15a6 6 0 1 0 0-12 6 6 0 0 0 0 12zM8.2 13.9 7 22l5-3 5 3-1.2-8.1';\nconst ROLE = { gv:'Gerente de vendas', gn:'Gerente de negócio', lider:'Líder' };\nconst BADGE = { gv:'linear-gradient(135deg,#AE0025,#590013)', gn:'linear-gradient(135deg,#F69C00,#AE0025)', lider:'linear-gradient(135deg,#FF809B,#AE0025)' };\nconst PAGE_SIZE = 10;\nconst LOWER = ['de','da','do','dos','das','e'];\nconst LEGEND = '<span class=\"legend\" aria-label=\"Legenda das cores\"><span><i style=\"background:#1B9A55\"></i>Meta batida</span><span><i style=\"background:#E8590C\"></i>60% a 99% da meta</span><span><i style=\"background:#E5231B\"></i>Abaixo de 60%</span></span>';\nconst SIDE_DECO = '<svg class=\"side-deco\" aria-hidden=\"true\" viewBox=\"0 0 224 170\" preserveAspectRatio=\"none\"><defs><linearGradient id=\"sideFitaA\" x1=\"0\" y1=\"1\" x2=\"1\" y2=\"0\"><stop offset=\"0\" stop-color=\"#FFB27A\"></stop><stop offset=\"1\" stop-color=\"#FFD080\"></stop></linearGradient><linearGradient id=\"sideFitaB\" x1=\"0\" y1=\"1\" x2=\"1\" y2=\"0\"><stop offset=\"0\" stop-color=\"#FF809B\"></stop><stop offset=\"1\" stop-color=\"#FFB3C3\"></stop></linearGradient></defs><path d=\"M0 170 L 0 146 C 64 128, 140 112, 224 66 L 224 170 Z\" fill=\"url(#sideFitaA)\"></path><path d=\"M62 170 C 118 150, 176 112, 224 36 L 224 170 Z\" fill=\"url(#sideFitaB)\"></path><path d=\"M140 170 C 176 150, 204 118, 224 88 L 224 170 Z\" fill=\"#FFCCD7\"></path></svg>';\nconst HERO_DECO = {\n  gv: '<svg class=\"hero-deco\" aria-hidden=\"true\" viewBox=\"0 0 1200 380\" preserveAspectRatio=\"xMaxYMid slice\"><defs><linearGradient id=\"gvFitaA\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\"><stop offset=\"0\" stop-color=\"#E6005C\"></stop><stop offset=\"1\" stop-color=\"#AE0025\"></stop></linearGradient><linearGradient id=\"gvFitaB\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"0\"><stop offset=\"0\" stop-color=\"#E6005C\" stop-opacity=\"0\"></stop><stop offset=\"0.45\" stop-color=\"#FF809B\"></stop><stop offset=\"1\" stop-color=\"#FFCCD7\"></stop></linearGradient><pattern id=\"gvPontos\" width=\"11\" height=\"11\" patternUnits=\"userSpaceOnUse\"><circle cx=\"2\" cy=\"2\" r=\"1.7\" fill=\"#FF809B\" fill-opacity=\"0.6\"></circle></pattern></defs><path d=\"M420 0 C 600 150, 880 30, 1200 210 L 1200 120 C 920 -10, 680 100, 520 0 Z\" fill=\"url(#gvPontos)\"></path><path d=\"M840 380 C 960 260, 1060 280, 1200 140 L 1200 380 Z\" fill=\"url(#gvFitaA)\" fill-opacity=\"0.95\"></path><path d=\"M640 380 C 800 290, 960 370, 1200 240 L 1200 310 C 980 410, 820 350, 700 380 Z\" fill=\"url(#gvFitaB)\"></path><path d=\"M980 0 C 1060 90, 1140 70, 1200 110 L 1200 0 Z\" fill=\"#E6005C\" fill-opacity=\"0.5\"></path></svg>',\n  gn: '<svg class=\"hero-deco\" aria-hidden=\"true\" viewBox=\"0 0 1440 400\" preserveAspectRatio=\"xMaxYMid slice\"><defs><linearGradient id=\"gnFitaA\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\"><stop offset=\"0\" stop-color=\"#FFD080\"></stop><stop offset=\"1\" stop-color=\"#F69C00\"></stop></linearGradient><linearGradient id=\"gnFitaB\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"0\"><stop offset=\"0\" stop-color=\"#F69C00\" stop-opacity=\"0\"></stop><stop offset=\"0.45\" stop-color=\"#F26B1D\"></stop><stop offset=\"1\" stop-color=\"#FFD080\"></stop></linearGradient><pattern id=\"gnPontos\" width=\"11\" height=\"11\" patternUnits=\"userSpaceOnUse\"><circle cx=\"2\" cy=\"2\" r=\"1.7\" fill=\"#FFD080\" fill-opacity=\"0.55\"></circle></pattern></defs><path d=\"M560 0 C 760 150, 1060 30, 1440 210 L 1440 120 C 1120 -10, 840 100, 660 0 Z\" fill=\"url(#gnPontos)\"></path><path d=\"M1040 400 C 1160 280, 1260 300, 1440 150 L 1440 400 Z\" fill=\"url(#gnFitaA)\" fill-opacity=\"0.95\"></path><path d=\"M820 400 C 1000 300, 1170 390, 1440 250 L 1440 320 C 1190 430, 1020 370, 880 400 Z\" fill=\"url(#gnFitaB)\"></path><path d=\"M1180 0 C 1260 90, 1360 70, 1440 120 L 1440 0 Z\" fill=\"#F26B1D\" fill-opacity=\"0.4\"></path></svg>',\n  lider: '<svg class=\"hero-deco\" aria-hidden=\"true\" viewBox=\"0 0 1440 460\" preserveAspectRatio=\"xMaxYMid slice\"><defs><linearGradient id=\"ldFitaA\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\"><stop offset=\"0\" stop-color=\"#FF809B\"></stop><stop offset=\"1\" stop-color=\"#AE0025\"></stop></linearGradient><linearGradient id=\"ldFitaB\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"0\"><stop offset=\"0\" stop-color=\"#AE0025\" stop-opacity=\"0\"></stop><stop offset=\"0.45\" stop-color=\"#E6005C\"></stop><stop offset=\"1\" stop-color=\"#FF809B\"></stop></linearGradient><pattern id=\"ldPontos\" width=\"11\" height=\"11\" patternUnits=\"userSpaceOnUse\"><circle cx=\"2\" cy=\"2\" r=\"1.7\" fill=\"#AE0025\" fill-opacity=\"0.3\"></circle></pattern></defs><path d=\"M560 0 C 760 170, 1060 40, 1440 240 L 1440 140 C 1120 0, 840 110, 660 0 Z\" fill=\"url(#ldPontos)\"></path><path d=\"M1100 460 C 1200 340, 1290 350, 1440 200 L 1440 460 Z\" fill=\"url(#ldFitaA)\" fill-opacity=\"0.9\"></path><path d=\"M900 460 C 1060 360, 1200 450, 1440 300 L 1440 370 C 1220 490, 1080 430, 960 460 Z\" fill=\"url(#ldFitaB)\"></path><path d=\"M1220 0 C 1290 90, 1370 80, 1440 120 L 1440 0 Z\" fill=\"#FF809B\" fill-opacity=\"0.7\"></path></svg>'\n};\nfunction svgP(d, size, stroke, sw){ return '<svg aria-hidden=\"true\" width=\"' + size + '\" height=\"' + size + '\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"' + stroke + '\" stroke-width=\"' + (sw || 2) + '\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"' + d + '\"></path></svg>'; }\nfunction caret(open){ return '<svg aria-hidden=\"true\" class=\"caret' + (open ? ' up' : '') + '\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#AE0025\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m6 9 6 6 6-6\"></path></svg>'; }\nfunction chev(){ return svgP('m9 6 6 6-6 6', 18, '#AE0025', 2.2); }\nfunction check(){ return svgP('M20 6 9 17l-5-5', 16, '#AE0025', 2.6); }\nfunction xIcon(){ return svgP('M6 6l12 12M18 6 6 18', 18, '#1A1A1A', 2); }\nfunction crumbSep(){ return '<span class=\"crumb-sep\">' + svgP('m9 6 6 6-6 6', 14, 'currentColor', 2) + '</span>'; }\nfunction lockChip(text){ return '<span class=\"lock\">' + svgP('M5 11h14v10H5zM8 11V7a4 4 0 0 1 8 0v4', 12, 'currentColor', 2.5) + escH(text) + '</span>'; }\nfunction partialChip(){ return '<span class=\"chip-part\" title=\"Valores parciais até o fechamento estatístico do ciclo\">' + svgP('M12 3a9 9 0 1 0 0 18a9 9 0 1 0 0-18M12 7v5l3 2', 14, 'currentColor', 2) + 'Ciclo em andamento · valores parciais, sujeitos ao fechamento</span>'; }\n// ── formatting ──\nfunction brl(v){ return 'R$ ' + Number(v || 0).toLocaleString('pt-BR', { minimumFractionDigits:2, maximumFractionDigits:2 }); }\nfunction brl0(v){ return 'R$ ' + Number(v || 0).toLocaleString('pt-BR', { maximumFractionDigits:2 }); }\nfunction n0(v){ return Math.round(Number(v) || 0).toLocaleString('pt-BR'); }\nfunction compact(v){\n  v = Number(v) || 0;\n  if(Math.abs(v) >= 1e6) return 'R$ ' + (v / 1e6).toLocaleString('pt-BR', { maximumFractionDigits:1 }) + ' mi';\n  if(Math.abs(v) >= 1e3) return 'R$ ' + Math.round(v / 1e3).toLocaleString('pt-BR') + ' mil';\n  return brl(v);\n}\nfunction pctNum(m){ return (Number(m || 0) * 100).toLocaleString('pt-BR', { maximumFractionDigits:1 }) + '%'; }\nfunction faixaPct(f){ f = Number(f || 0); return f > 1.5 ? f.toLocaleString('pt-BR', { maximumFractionDigits:1 }) + '%' : pctNum(f); }\nfunction nome(s){\n  return String(s || '').toLowerCase().split(/\\s+/).filter(Boolean)\n    .map(w => LOWER.indexOf(w) >= 0 ? w : w.split('-').map(p => p.charAt(0).toUpperCase() + p.slice(1)).join('-')).join(' ');\n}\nfunction nameParts(s){ return nome(s).split(' ').filter(w => w && LOWER.indexOf(w) < 0); }\nfunction initials(s){ const p = nameParts(s); if(!p.length) return ''; return ((p[0][0] || '') + (p.length > 1 ? p[p.length - 1][0] : '')).toUpperCase(); }\nfunction shortName(s){ const p = nameParts(s); return p.length > 1 ? p[0] + ' ' + p[p.length - 1] : (p[0] || ''); }\nfunction redeTxt(r){ return 'rede ' + String(r || '').replace('rede', ''); }\nfunction joinE(a){ return a.length <= 1 ? (a[0] || '') : a.slice(0, -1).join(', ') + ' e ' + a[a.length - 1]; }\n// ── stats (value / goal / atingimento / status come from the backend as-is) ──\nfunction isMoney(s){ return /fatur/i.test(String((s && s.label) || '')); }\nfunction hasGoal(s){ return !!s && s.goal != null && Number(s.goal) > 0 && s.atingimento != null; }\nfunction kindOf(s){\n  const st = String((s && s.status) || '').toLowerCase();\n  if(st === 'green') return 'green';\n  if(st === 'amber' || st === 'yellow' || st === 'orange') return 'amber';\n  if(st === 'red') return 'red';\n  if(!hasGoal(s)) return 'none';\n  const a = Number(s.atingimento);\n  return a >= 100 ? 'green' : (a >= 60 ? 'amber' : 'red');\n}\nfunction sv(s){\n  s = s || {};\n  const fmt = isMoney(s) ? compact : n0;\n  const g = hasGoal(s);\n  const k = g ? kindOf(s) : 'none';\n  return {\n    label: s.label || '', k: k,\n    pct: g ? Math.round(Number(s.atingimento)) + '%' : fmt(s.value),\n    vg: g ? fmt(s.value) + ' de ' + fmt(s.goal) : '',\n    dot: g ? COL[k] : '', tip: g ? TIP[k] : '',\n    faltam: g ? (Number(s.value) < Number(s.goal) ? 'Faltam ' + fmt(Number(s.goal) - Number(s.value)) : 'Meta batida') : 'Sem meta'\n  };\n}\nfunction dotHtml(x){ return '<span class=\"dot\"' + (x.dot ? ' style=\"background:' + x.dot + '\" title=\"' + escH(x.tip) + '\"' : '') + '></span>'; }\nfunction iconId(icon, label){\n  const i = String(icon || '').toLowerCase(); const l = String(label || '').toLowerCase();\n  if(i === 'people' || l.indexOf('totais') >= 0) return 'people';\n  if(i === 'crown' || l.indexOf('migradas') >= 0) return 'crown';\n  if(i === 'swap' || l.indexOf('saldo') >= 0) return 'swap';\n  if(i === 'user-add' || l.indexOf('início') >= 0 || l.indexOf('inicio') >= 0) return 'add';\n  if(i === 'target' || l.indexOf('ambas') >= 0) return 'target';\n  return 'user';\n}\nfunction brandOf(s){\n  const b = String((s && s.brand) || '').toLowerCase(); const l = String((s && s.label) || '').toLowerCase();\n  if(b === 'natura' || (!b && l.indexOf('natura') >= 0)) return 'natura';\n  if(b === 'avon' || (!b && l.indexOf('avon') >= 0)) return 'avon';\n  return '';\n}\nfunction brandWord(s){ const b = brandOf(s); return b === 'natura' ? 'Natura' : (b === 'avon' ? 'Avon' : ((s && s.label) || '')); }\nfunction icoHtml(s, size){\n  const b = brandOf(s);\n  if(b) return '<img class=\"brand\" src=\"' + IMG[b] + '\" alt=\"\" width=\"' + size + '\" height=\"' + size + '\">';\n  const id = iconId(s && s.icon, s && s.label); const k = kindOf(s);\n  return svgP(ICO[id], size, id === 'crown' ? '#F69C00' : (k === 'none' ? '#757575' : COL[k]), 2);\n}\nfunction medalKey(n){\n  const s = String(n || '').toLowerCase().trim();\n  if(s.indexOf('diamante') >= 0 && (s.indexOf('+') >= 0 || s.indexOf('plus') >= 0)) return 'diamante+';\n  return MEDAL[s] ? s : '';\n}\nfunction medalHtml(n, size){\n  const k = medalKey(n);\n  return k ? '<img class=\"medal\" src=\"' + ASSET + MEDAL[k] + '\" alt=\"Nível ' + escH(k) + '\" title=\"Nível ' + escH(k) + '\" width=\"' + size + '\" height=\"' + size + '\">'\n    : '<span class=\"medal medal-off\" style=\"width:' + size + 'px;height:' + size + 'px\"></span>';\n}\n// ── \"Como foi calculado\": built only from what the backend returned (drivers / components) ──\nfunction bonusShort(l){ const s = String(l || '').replace(/^Bônus (de )?atingimento /i, '').replace(/\\s*100%.*$/, '').trim(); return /^ambas/i.test(s) ? s.toLowerCase() : s; }\nfunction compFromDrivers(dr){\n  const rows = [];\n  (dr.fatores || []).forEach(f => {\n    const isVal = String(f.faixaTipo || '') === 'valor';\n    const at = (!isVal && f.atingimento != null) ? ' (' + Math.round(Number(f.atingimento)) + '%)' : '';\n    rows.push({ label: (f.label || f.kpi || '') + (isVal ? ' (faixa)' : at), value: isVal ? brl(f.faixa) : '× ' + faixaPct(f.faixa) });\n  });\n  const m = dr.multiplicador;\n  if(m && m.multiplicador != null) rows.push({ label: (m.label || 'Multiplicador de saldo') + (m.value != null ? ' (saldo ' + n0(m.value) + ')' : ''), value: '× ' + pctNum(m.multiplicador) });\n  const bon = Array.isArray(dr.bonus) ? dr.bonus : [];\n  bon.filter(b => b.willReceive && Number(b.amount) > 0).forEach(b => rows.push({ label: b.label, value: brl(b.amount) }));\n  const miss = bon.filter(b => !(b.willReceive && Number(b.amount) > 0)).map(b => bonusShort(b.label));\n  if(miss.length) rows.push({ label: 'Bônus ' + joinE(miss), value: miss.length > 1 ? 'Não atingidos' : 'Não atingido' });\n  return rows;\n}\nfunction compFromComponents(c, total, diffLabel){\n  if(!c) return [];\n  const rows = [{ label: 'Componente Natura', value: brl(c.natura) }];\n  if(c.avon != null) rows.push({ label: 'Componente Avon', value: brl(c.avon) });\n  if(c.multiplicador != null && c.saldo != null){\n    rows.push({ label: 'Multiplicador de saldo (saldo ' + n0(c.saldo) + ')', value: '× ' + pctNum(c.multiplicador) });\n  } else {\n    const diff = Number(c.remunBase || 0) + Number(c.bonusTotal || 0) - Number(total || 0);\n    if(diff > 0.005) rows.push({ label: diffLabel || 'Multiplicador de saldo', value: '− ' + brl(diff) });\n  }\n  rows.push({ label: 'Bônus', value: brl(c.bonusTotal || 0) });\n  return rows;\n}\nfunction ambasRow(dr){\n  const b = (dr && Array.isArray(dr.bonus)) ? dr.bonus.find(x => x.bonusType === 'ambas-marcas') : null;\n  if(!b) return null;\n  const parts = (b.conditions || []).map(c => (/natura/i.test(c.kpi || '') ? 'Natura' : (/avon/i.test(c.kpi || '') ? 'Avon' : (c.kpi || ''))) + ' ' + Math.round(Number(c.atingimento || 0)) + '%');\n  const ok = !!b.willReceive;\n  return { __x: { label: 'Atingimento 100% ambas marcas', vg: parts.join(' · '), pct: ok ? 'Atingido' : 'Não atingido', dot: '', tip: '', color: ok ? '#1B7A45' : '#5C5C5C' }, __ico: svgP(ICO.target, 20, '#757575', 2) };\n}\nfunction withAmbas(stats, dr){ const list = (stats || []).slice(); const a = ambasRow(dr); if(a) list.splice(Math.min(3, list.length), 0, a); return list; }\n// ── building blocks ──\nfunction cycleInfo(d2){\n  const store = d2.store('store');\n  const opts = (store && store.get('cycleOptions', [])) || [];\n  const cur = String((store && store.get('cycle', '')) || '');\n  const sel = opts.find(o => String(o.cycle) === cur);\n  return { opts: opts, cur: cur, sel: sel, partial: !!(sel && !sel.closed) };\n}\nfunction cycleDd(d2){\n  const ci = cycleInfo(d2);\n  const open = !!d2.state.cycleOpen && ci.opts.length > 0;\n  const lbl = ci.cur + (ci.sel && ci.sel.isCurrent ? ' · atual' : '');\n  const list = open ? '<button class=\"dd-ovl js-close-lists\" aria-label=\"Fechar lista\" tabindex=\"-1\"></button><div class=\"dd-list\" role=\"listbox\" aria-label=\"Ciclo\">' + ci.opts.map(o => {\n    const on = String(o.cycle) === ci.cur;\n    return '<button class=\"dd-opt js-cycle-opt' + (on ? ' on' : '') + '\" role=\"option\" aria-selected=\"' + on + '\" data-cycle=\"' + escH(o.cycle) + '\"><span class=\"flex1\">' + escH(o.cycle) + '</span>' + (o.isCurrent ? '<span class=\"tag-atual\">Atual</span>' : '') + '<span class=\"dd-sub\">' + (o.closed ? 'Fechado' : 'Em andamento') + '</span><span class=\"dd-chk\">' + (on ? check() : '') + '</span></button>';\n  }).join('') + '</div>' : '';\n  return '<div class=\"dd\"><button class=\"dd-btn js-cycle-toggle\" aria-haspopup=\"listbox\" aria-expanded=\"' + open + '\"><span class=\"muted\">Ciclo</span><b>' + escH(lbl) + '</b>' + caret(open) + '</button>' + list + '</div>';\n}\nfunction navItems(d2){\n  const items = [{ go:'painel', label:'Painel', short:'Painel', d: ICO.painel, on: true }];\n  if(!isTokenMode(d2) && !isImpersonating(d2)) items.push({ vercomo: true, label:'Ver como outra pessoa', short:'Ver como', d: ICO.vercomo });\n  items.push({ go:'simulador', label:'Simulador', short:'Simulador', d: ICO.simulador });\n  items.push({ go:'historico', label:'Histórico', short:'Histórico', d: ICO.historico });\n  return items;\n}\nfunction navAttrs(n){ return (n.vercomo ? 'js-vercomo' : 'js-nav') + (n.on ? ' on' : '') + '\"' + (n.go ? ' data-go=\"' + n.go + '\"' : '') + (n.on ? ' aria-current=\"page\"' : ''); }\nfunction sideNavHtml(items){ return items.map(n => '<a href=\"#\" class=\"nav-it ' + navAttrs(n) + ' title=\"' + n.label + '\">' + svgP(n.d, 20, 'currentColor', 1.8) + '<span class=\"long\">' + n.label + '</span><span class=\"short\">' + n.short + '</span></a>').join(''); }\nfunction tabsHtml(items){ return '<nav class=\"mtabs\" aria-label=\"Menu\">' + items.map(n => '<a href=\"#\" class=\"mt ' + navAttrs(n) + '><span class=\"mt-pill\">' + svgP(n.d, 20, 'currentColor', 1.8) + '</span><span>' + n.short + '</span></a>').join('') + '</nav>'; }\nfunction userCard(d2){\n  const a = resolveActingIdentity(d2) || resolveEffectiveIdentity(d2) || {};\n  const nm = shortName(a.name || '') || (isTokenMode(d2) ? '' : 'Usuário de teste');\n  return '<div class=\"user\"><span class=\"user-av\">' + svgP('M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2M8 7a4 4 0 1 0 8 0a4 4 0 1 0-8 0', 15, '#FFFFFF', 1.8) + '</span><span class=\"user-txt\"><span class=\"user-n\">' + escH(nm) + '</span><span class=\"user-r\">' + escH(ROLE[a.perfil] || (isTokenMode(d2) ? '' : 'Modo piloto')) + '</span></span><button class=\"user-out js-logout\" aria-label=\"Sair\" title=\"Sair\">' + svgP(OUT_D, 14, 'currentColor', 2) + '</button></div>';\n}\nfunction pilotBar(d2){\n  if(isTokenMode(d2)) return '';\n  const acting = resolveActingIdentity(d2);\n  const users = Array.isArray(d2.state.switcherUsers) ? d2.state.switcherUsers : [];\n  const cur = (acting && acting.userId) || '';\n  const opts = users.map(u => '<option value=\"' + escH(u.userId) + '\"' + (String(u.userId) === String(cur) ? ' selected' : '') + '>' + escH(nome(u.name)) + ' · ' + escH(perfilLabel(u.perfil)) + (u.structureCode ? ' ' + escH(u.structureCode) : '') + '</option>').join('');\n  return '<div class=\"pbar\" role=\"region\" aria-label=\"Modo piloto\"><span class=\"ptag\">PILOTO</span><span class=\"ptxt\">Modo de teste: troque de usuário para ver o painel de cada perfil. Some quando o login definitivo entrar.</span><span class=\"flex1\"></span><label class=\"psw\"><span class=\"psw-l\">Usuário de teste</span><select class=\"pil-switch\" aria-label=\"Usuário de teste\">' + (opts || '<option>' + escH(nome((acting && acting.name) || '—')) + '</option>') + '</select></label></div>';\n}\nfunction viewBanner(d2){\n  if(!isImpersonating(d2)) return '';\n  const eff = resolveEffectiveIdentity(d2); const acting = resolveActingIdentity(d2);\n  if(!eff || !acting) return '';\n  const scope = eff.perfil === 'gn' ? ' · setor ' + (eff.structureCode || eff.sectorCode || '') : (eff.perfil === 'lider' ? ' · grupo ' + (eff.structureCode || '') : '');\n  return '<div class=\"vbar\"><div class=\"vbar-in\">' + svgP(ICO.vercomo, 18, 'currentColor', 2) + '<span>Você está vendo como <b>' + escH(nome(eff.name)) + '</b> (' + escH(perfilLabel(eff.perfil) + scope) + ') · acesso de <b>' + escH(nome(acting.name)) + '</b> (' + escH(perfilLabel(acting.perfil)) + ')</span><span class=\"flex1\"></span><button class=\"vbar-out pil-imp-exit\">Sair da visualização</button></div></div>';\n}\nfunction heroWrap(view, inner){\n  const logo = view === 'lider' ? IMG.logo : IMG.logoW;\n  return '<div class=\"hero hero-' + view + '\">' + HERO_DECO[view] + '<div class=\"hero-in\"><div class=\"band-top\"><a href=\"#\" class=\"band-logo js-nav\" data-go=\"painel\" aria-label=\"Consultoria de Beleza · ir para o painel\"><img src=\"' + logo + '\" alt=\"\" width=\"120\" height=\"30\"></a><button class=\"m-out js-logout\" aria-label=\"Sair\" title=\"Sair\">' + svgP(OUT_D, 16, 'currentColor', 2) + '</button></div>' + inner + '</div></div>';\n}\n// Modals go INSIDE the single root: the morph-patcher only updates the first root element.\nfunction shellHtml(d2, view, hero, body, overlays){\n  const items = navItems(d2);\n  return '<div class=\"app v-' + view + '\">' + pilotBar(d2) + viewBanner(d2) + '<div class=\"frame\"><aside class=\"aside\"><div class=\"side\"><div class=\"side-logo\"><a href=\"#\" class=\"js-nav\" data-go=\"painel\" aria-label=\"Consultoria de Beleza · ir para o painel\"><img src=\"' + IMG.logo + '\" alt=\"\" width=\"160\" height=\"40\"></a></div>' + SIDE_DECO + '<nav class=\"side-nav\" aria-label=\"Menu\">' + sideNavHtml(items) + '</nav><span class=\"flex1\"></span>' + userCard(d2) + '</div></aside><div class=\"col\">' + hero + '<main class=\"main\">' + body + '</main></div></div>' + tabsHtml(items) + (overlays || '') + '</div>';\n}\nfunction paginate(list, page){\n  const pages = Math.max(1, Math.ceil(list.length / PAGE_SIZE));\n  const p = Math.min(Math.max(1, Number(page) || 1), pages);\n  const from = (p - 1) * PAGE_SIZE;\n  return { p: p, pages: pages, from: from, items: list.slice(from, from + PAGE_SIZE), total: list.length };\n}\nfunction pagerHtml(pg){\n  if(pg.pages <= 1) return '';\n  let btns = '';\n  for(let i = 1; i <= pg.pages; i++) btns += '<button class=\"pg js-page' + (i === pg.p ? ' on' : '') + '\" data-page=\"' + i + '\" aria-label=\"Página ' + i + '\"' + (i === pg.p ? ' aria-current=\"page\"' : '') + '>' + i + '</button>';\n  return '<nav class=\"pager\" aria-label=\"Paginação\"><span class=\"pg-info\">Mostrando ' + (pg.total ? pg.from + 1 : 0) + '–' + Math.min(pg.from + PAGE_SIZE, pg.total) + ' de ' + pg.total + '</span><button class=\"pg pg-arw js-page\" data-page=\"' + (pg.p - 1) + '\" aria-label=\"Página anterior\"' + (pg.p <= 1 ? ' disabled' : '') + '>' + svgP('m15 18-6-6 6-6', 16, 'currentColor', 2.2) + '</button>' + btns + '<button class=\"pg pg-arw js-page\" data-page=\"' + (pg.p + 1) + '\" aria-label=\"Próxima página\"' + (pg.p >= pg.pages ? ' disabled' : '') + '>' + svgP('m9 6 6 6-6 6', 16, 'currentColor', 2.2) + '</button></nav>';\n}\nfunction shortLabel(l){ return String(l || '').replace(/^Faturamento/i, 'Fatur.').replace(/^Volume de Pontos/i, 'Pontos').replace(/^Quantidade de /i, ''); }\nfunction tableHead(first, stats3){ return '<div class=\"t-row t-head\"><span class=\"t-name\">' + first + '</span>' + stats3.map(s => '<span class=\"t-kpi\">' + escH(shortLabel(s.label)) + '</span>').join('') + '<span class=\"t-rem\">Remuneração</span><span class=\"t-act\"></span></div>'; }\nfunction cellHtml(s){ const x = sv(s); return '<span class=\"t-kpi\" title=\"' + escH(x.label + ': ' + (x.vg || x.pct)) + '\">' + dotHtml(x) + '<span class=\"t-pct\">' + escH(x.pct) + '</span></span>'; }\nfunction remCard(view, label, value, subHtml){\n  return '<div class=\"card card-rem\"><span class=\"badge\" style=\"background:' + BADGE[view] + '\">' + svgP('M3 17l6-6 4 4 8-8M15 7h6v6', 20, '#FFFFFF', 1.8) + '</span><span class=\"c-lbl\">' + label + '</span><span class=\"c-big\">' + value + '</span><span class=\"c-sub\">' + subHtml + '</span><button class=\"btn-ghost js-modal\" data-kind=\"tot\" data-i=\"0\">Como foi calculado</button></div>';\n}\nfunction totCard(view, label, stats, iapCodes){\n  return '<div class=\"card card-tot\"><span class=\"badge\" style=\"background:' + BADGE[view] + '\">' + svgP('M3 3v18h18M7 15l4-4 3 3 5-6', 20, '#FFFFFF', 1.8) + '</span><span class=\"c-lbl\">' + label + '</span><div class=\"tot-grid\">' + (stats || []).map(s => {\n    const x = sv(s);\n    const iap = (iapCodes && iapCodes[s.indexCode]) ? '<span class=\"iap\">IAP</span>' : '';\n    return '<div class=\"tot-row\" title=\"' + escH(x.label + ': ' + (x.vg || x.pct)) + '\"><span class=\"tr-l\">' + escH(x.label) + iap + '</span><span class=\"tr-vg\">' + escH(x.vg) + '</span><span class=\"tr-p\">' + escH(x.pct) + '</span>' + dotHtml(x) + '</div>';\n  }).join('') + '</div></div>';\n}\nfunction relHtml(r){ const x = sv(r); return '<div class=\"rel\"><span class=\"rel-l\">' + escH(x.label) + '</span><span class=\"rel-v\">' + (x.dot ? dotHtml(x) : '') + escH(x.pct) + '<span class=\"muted\">' + escH(x.vg) + '</span></span><span class=\"rel-f\">' + escH(x.faltam) + '</span></div>'; }\n// One indicator row (sectorItems / aceleradores / indicadores), expandable when it has related KPIs.\nfunction itemHtml(d2, it, kpiByCode){\n  const main = Object.assign({}, it.main || {});\n  if(!hasGoal(main) && kpiByCode && main.code != null && kpiByCode[main.code]){\n    const k = kpiByCode[main.code];\n    if(k.goal != null && Number(k.goal) > 0){\n      if(main.value == null) main.value = k.value;\n      main.goal = k.goal;\n      main.atingimento = (k.atingimento != null) ? k.atingimento : (Number(main.value || 0) / Number(k.goal)) * 100;\n    }\n  }\n  main.label = main.label || it.label;\n  const x = sv(main);\n  const g = hasGoal(main);\n  const fmt = isMoney(main) ? compact : n0;\n  const related = Array.isArray(it.related) ? it.related : [];\n  const ref = String(it.ref || it.label || '');\n  const open = !!(d2.state.openItems || {})[ref];\n  const canOpen = related.length > 0;\n  const id = iconId(it.icon || main.icon, it.label);\n  const icoCor = id === 'crown' ? '#F69C00' : (x.k === 'none' ? '#757575' : COL[x.k]);\n  const icoBg = id === 'crown' ? '#FFF4DD' : TINT[x.k];\n  const iap = String(it.agrupamento || '') === 'indicador-iap' ? '<span class=\"iap\">IAP</span>' : '';\n  const isAmbas = /ambas/i.test(ref) || /ambas/i.test(it.label || '');\n  let sub = '';\n  if(!g && isAmbas && related.length) sub = related.map(r => brandWord(r) + ' ' + sv(r).pct).join(' · ') + ' · precisa de 100% nas duas';\n  else if(!g) sub = 'Sem meta';\n  const gain = Number(it.projectedGain || 0);\n  let chip = '';\n  if(it.isBonus) chip = (it.willReceive && gain > 0) ? '<span class=\"chip chip-yes\">Vai receber ' + escH(brl(gain)) + '</span>' : '<span class=\"chip chip-no\">Não atingido</span>';\n  else if(gain > 0) chip = '<span class=\"chip chip-gain\">' + svgP('m6 15 6-6 6 6', 16, 'currentColor', 2.6) + '+' + escH(brl(gain)) + '</span>';\n  const valBlock = (isAmbas && !g && related.length) ? '' : '<span class=\"it-val\"><b>' + escH(g ? fmt(main.value) : x.pct) + '</b>' + (g ? '<span class=\"muted\"> / ' + escH(fmt(main.goal)) + '</span>' : '') + '</span>';\n  const bar = g ? '<span class=\"bar\"><span style=\"width:' + Math.max(0, Math.min(100, Number(main.atingimento) || 0)) + '%;background:' + x.dot + '\"></span></span>' : '';\n  const head = '<span class=\"it-ico\" style=\"background:' + icoBg + '\">' + svgP(ICO[id], 24, icoCor, 2) + '</span>'\n    + '<span class=\"it-main\"><span class=\"it-l\">' + escH(it.label || main.label) + iap + '</span>' + bar + (sub ? '<span class=\"it-sub\">' + escH(sub) + '</span>' : '') + '</span>'\n    + (g ? '<span class=\"it-pct\" style=\"color:' + x.dot + '\" title=\"' + escH(x.tip) + '\">' + escH(x.pct) + '</span>' : '')\n    + valBlock + '<span class=\"it-chip\">' + chip + '</span>'\n    + (canOpen ? '<span class=\"it-caret\">' + caret(open) + '</span>' : '');\n  const h = canOpen ? '<button class=\"it-h js-item\" data-ref=\"' + escH(ref) + '\" aria-expanded=\"' + open + '\">' + head + '</button>' : '<div class=\"it-h\">' + head + '</div>';\n  return '<div class=\"it\" data-key=\"it-' + escH(ref) + '\">' + h + (open ? '<div class=\"it-rel\">' + related.map(relHtml).join('') + '</div>' : '') + '</div>';\n}\nfunction mStatRow(s){\n  const x = s.__x || sv(s);\n  const ico = s.__ico != null ? s.__ico : icoHtml(s, 20);\n  return '<div class=\"m-row\"><span class=\"m-ico\">' + ico + '</span><span class=\"flex1\">' + escH(x.label) + '</span><span class=\"muted\">' + escH(x.vg) + '</span><span class=\"m-pct\"' + (x.color ? ' style=\"color:' + x.color + '\"' : '') + '>' + escH(x.pct) + '</span>' + dotHtml(x) + '</div>';\n}\nfunction modalHtml(o){\n  const stats = (o.stats && o.stats.length) ? '<div class=\"m-sec\"><span class=\"eyebrow\">indicadores</span>' + o.stats.map(mStatRow).join('') + '</div>' : '';\n  const rows = (o.comp || []).map(c => '<div class=\"comp-r\"><span class=\"flex1\">' + escH(c.label) + '</span><span>' + escH(c.value) + '</span></div>').join('');\n  const comp = '<div class=\"comp\"><span class=\"eyebrow\">como a remuneração foi construída</span>' + (rows || '<div class=\"comp-r muted\">Sem detalhamento para este ciclo.</div>') + '<div class=\"comp-tot\"><span class=\"flex1\">Total</span><span>' + escH(o.total) + '</span></div></div>';\n  const link = o.link ? '<button class=\"btn-pri ' + o.link.cls + '\" data-code=\"' + escH(o.link.code) + '\"' + (o.link.setor ? ' data-setor=\"' + escH(o.link.setor) + '\"' : '') + '>' + escH(o.link.label) + '</button>' : '';\n  return '<div class=\"mwrap\"><button class=\"ovl js-modal-close\" aria-label=\"Fechar\" tabindex=\"-1\"></button><div class=\"dlg\" role=\"dialog\" aria-modal=\"true\" aria-label=\"' + escH(o.title) + '\"><div class=\"dlg-h\"><div class=\"dlg-ht\"><span class=\"dlg-t\">' + escH(o.title) + '</span><span class=\"dlg-s\">' + escH(o.sub) + '</span></div><button class=\"x js-modal-close\" aria-label=\"Fechar\">' + xIcon() + '</button></div>' + stats + comp + '<div class=\"dlg-f\"><button class=\"btn-out js-modal-close\">Fechar</button>' + link + '</div></div></div>';\n}\nfunction verComoHtml(d2){\n  if(!d2.state.impPickerOpen) return '';\n  const q = String(d2.state.impQuery || '').trim().toLowerCase();\n  const all = Array.isArray(d2.state.allowedTargets) ? d2.state.allowedTargets : [];\n  const list = q ? all.filter(t => ((t.name || '') + ' ' + perfilLabel(t.perfil) + ' ' + (t.perfil === 'gn' ? 'gerente de negócio' : 'líder lider') + ' ' + (t.structureCode || '') + ' ' + (t.sectorCode || '')).toLowerCase().indexOf(q) >= 0) : all;\n  const rows = list.map(t => '<button class=\"pk pil-imp-pick\" type=\"button\" data-uid=\"' + escH(t.userId) + '\" data-key=\"pk-' + escH(t.userId) + '\"><span class=\"av\">' + escH(initials(t.name)) + '</span><span class=\"pk-t\"><span class=\"pk-n\">' + escH(nome(t.name)) + '<span class=\"pk-b ' + (t.perfil === 'gn' ? 'gn' : 'li') + '\">' + escH(perfilLabel(t.perfil)) + '</span></span><span class=\"pk-m\">' + (t.perfil === 'gn' ? 'Setor ' + escH(t.structureCode || '') : 'Grupo ' + escH(t.structureCode || '') + ' · setor ' + escH(t.sectorCode || '')) + '</span></span>' + chev() + '</button>').join('');\n  const body = d2.state.allowedTargetsLoading ? '<div class=\"pk-empty\">Carregando as pessoas que você pode ver…</div>'\n    : (rows || '<div class=\"pk-empty\">' + (q ? 'Ninguém encontrado com essa busca.' : 'Não há pessoas que você tenha permissão de ver.') + '</div>');\n  return '<div class=\"mwrap\"><button class=\"ovl pil-imp-close\" aria-label=\"Fechar\" tabindex=\"-1\"></button><div class=\"dlg dlg-sm\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Ver como outra pessoa\"><div class=\"dlg-h\"><div class=\"dlg-ht\"><span class=\"dlg-t\">Ver como outra pessoa</span><span class=\"dlg-s\">Somente as pessoas que você tem permissão de ver (regras e escopo).</span></div><button class=\"x pil-imp-close\" aria-label=\"Fechar\">' + xIcon() + '</button></div><label class=\"search\">' + svgP('M11 4a7 7 0 1 0 0 14a7 7 0 1 0 0-14M20 20l-3.5-3.5', 18, '#757575', 2) + '<input class=\"pil-imp-search\" type=\"search\" value=\"' + escH(d2.state.impQuery || '') + '\" placeholder=\"Buscar por nome, perfil, setor ou grupo\" aria-label=\"Buscar pessoa\"></label>' + (d2.state.impError ? '<div class=\"err\">' + escH(d2.state.impError) + '</div>' : '') + '<div class=\"pk-list\">' + body + '</div></div></div>';\n}\n// ── the three panels ──\nfunction gvView(d2, data){\n  const store = d2.store('store');\n  const gh = data.header || {};\n  const rede = data.rede || (store ? store.get('rede','rede1') : 'rede1');\n  const tot = data.totalizadorRede || {};\n  const gns = data.gns || [];\n  const ci = cycleInfo(d2);\n  const cyc = gh.cycle || data.cycle || ci.cur;\n  const seg = (r, l) => '<button class=\"seg-b js-rede' + (r === rede ? ' on' : '') + '\" role=\"tab\" aria-selected=\"' + (r === rede) + '\" data-rede=\"' + r + '\">' + l + '</button>';\n  const hero = heroWrap('gv', '<div class=\"row\"><h1 class=\"h1\">Gerente de vendas <b>' + escH(nome(gh.gvName || '')) + '</b></h1><span class=\"flex1\"></span>' + cycleDd(d2) + '</div><div class=\"row\"><div class=\"seg\" role=\"tablist\" aria-label=\"Rede\">' + seg('rede1', 'Rede 1') + seg('rede2', 'Rede 2') + '</div>' + (ci.partial ? partialChip() : '') + '</div>');\n  const pg = paginate(gns, d2.state.page);\n  const head3 = ((gns[0] && gns[0].stats) || tot.stats || []).slice(0, 3);\n  const rows = pg.items.map((g, j) => {\n    const i = pg.from + j;\n    const code = escH(g.sectorCode);\n    return '<div class=\"t-row\" data-key=\"gn-' + code + '\"><span class=\"t-name\"><span class=\"av\">' + escH(initials(g.gnName)) + '</span><span class=\"t-nm\"><a href=\"#\" class=\"t-link js-drill-gn\" data-code=\"' + code + '\">' + escH(nome(g.gnName)) + '</a><span class=\"t-sub\">Setor ' + code + (g.leaderCount != null ? ' · ' + escH(g.leaderCount) + ' grupos' : '') + '</span></span></span>'\n      + (g.stats || []).slice(0, 3).map(cellHtml).join('')\n      + '<span class=\"t-rem\">' + escH(brl(g.remuneracao)) + '</span><span class=\"t-act\"><button class=\"btn-sm js-modal\" data-kind=\"gn\" data-i=\"' + i + '\">Detalhes</button><a href=\"#\" class=\"t-go js-drill-gn\" data-code=\"' + code + '\" aria-label=\"Abrir setor\">' + chev() + '</a></span></div>';\n  }).join('');\n  const body = '<section class=\"sum\" aria-label=\"Resumo da rede\">'\n    + remCard('gv', 'Total da ' + redeTxt(rede), escH(brl(tot.remuneracao)), '<b>Ciclo ' + escH(cyc) + '</b> · soma das ' + gns.length + ' gerentes de negócio')\n    + totCard('gv', 'Totalizador da ' + redeTxt(rede), tot.stats)\n    + '</section><section class=\"sec\"><div class=\"sec-h\"><div class=\"sec-ht\"><h2 class=\"h2\">Suas <b>gerentes de negócio</b></h2><span class=\"count count-gv\">' + gns.length + '</span><span class=\"flex1\"></span>' + LEGEND + '</div></div><div class=\"tbl\">'\n    + tableHead('Gerente de negócio', head3) + (rows || '<div class=\"t-empty\">Nenhuma gerente de negócio nesta rede.</div>') + pagerHtml(pg) + '</div></section>';\n  let modal = '';\n  const md = d2.state.modal;\n  if(md && md.kind === 'tot'){\n    modal = modalHtml({ title: 'Total da ' + redeTxt(rede), sub: 'Soma da remuneração das ' + gns.length + ' gerentes de negócio', comp: compFromComponents(compOf(tot).composition, tot.remuneracao, 'Multiplicador de saldo de cada GN'), total: brl(tot.remuneracao) });\n  } else if(md && md.kind === 'gn' && gns[md.i]){\n    const g = gns[md.i];\n    modal = modalHtml({ title: nome(g.gnName), sub: 'Gerente de negócio · setor ' + g.sectorCode + (g.leaderCount != null ? ' · ' + g.leaderCount + ' grupos' : '') + ' · ' + redeTxt(g.rede || rede), stats: withAmbas(g.stats, g.drivers), comp: g.drivers ? compFromDrivers(g.drivers) : [], total: brl(g.remuneracao), link: { cls: 'js-drill-gn', code: g.sectorCode, label: 'Abrir setor' } });\n  }\n  return { hero: hero, body: body, modal: modal };\n}\nfunction gnView(d2, data){\n  const store = d2.store('store');\n  const header = data.header || {};\n  const tot = data.totalizador || {};\n  const leaders = data.leaders || [];\n  const sectorCode = header.sectorCode || data.structureCode || (store ? store.get('structureCode','') : '');\n  const gnName = header.gnName || '';\n  const rede = header.rede || tot.rede || '';\n  const ci = cycleInfo(d2);\n  const cyc = header.cycle || data.cycle || ci.cur;\n  const effP = effectivePerfil(d2);\n  const eff = resolveEffectiveIdentity(d2) || {};\n  const gvName = eff.gvName || (store ? store.get('gvName','') : '');\n  const crumbs = (effP === 'gv' ? '<a href=\"#\" class=\"crumb js-crumb\" data-go=\"gv\">Gerência ' + escH(nome(gvName)) + '</a>' + crumbSep() : '')\n    + '<span class=\"crumb-cur\" aria-current=\"page\">Setor ' + escH(sectorCode) + ' · ' + escH(redeTxt(rede)) + '</span>'\n    + (effP === 'gn' ? lockChip('Você vê só o seu setor') : '');\n  const hero = heroWrap('gn', '<div class=\"row\"><nav class=\"crumbs\" aria-label=\"Você está em\">' + crumbs + '</nav>' + cycleDd(d2) + '</div><h1 class=\"h1\">Gerente de negócio <b>' + escH(nome(gnName)) + '</b></h1>' + (ci.partial ? partialChip() : ''));\n  // Sector indicators: sectorItems (or sectorKpis when the payload has no items), goals from sectorKpis.\n  const sectorKpis = data.sectorKpis || [];\n  const kpiByCode = {};\n  sectorKpis.forEach(k => { kpiByCode[k.code] = k; });\n  let items = data.sectorItems || [];\n  if(!items.length && sectorKpis.length) items = sectorKpis.map(k => ({ ref: 'kpi-' + k.code, label: k.title, icon: k.icon, agrupamento: k.agrupamento, main: { code: k.code, label: k.title, brand: k.brand === 'total' ? null : k.brand, value: k.value, goal: k.goal, atingimento: k.atingimento }, related: [] }));\n  const iapCodes = {};\n  items.forEach(it => { if(String(it.agrupamento || '') === 'indicador-iap' && it.main && it.main.code != null) iapCodes[it.main.code] = true; });\n  // Leaders: the group picker only filters this list; the row opens the leader.\n  const allGroups = mapLeaders(leaders);\n  const selectedGroup = (d2.state.selGroup != null) ? d2.state.selGroup : d2.shared.get('pilotSelectedGroup', '', { global:true });\n  const filtered = selectedGroup ? allGroups.filter(g => String(g.codigoGrupo) === String(selectedGroup)) : allGroups;\n  const pg = paginate(filtered, d2.state.page);\n  const head3 = ((allGroups[0] && allGroups[0].stats) || tot.stats || []).slice(0, 3);\n  const rows = pg.items.map(l => {\n    const i = allGroups.indexOf(l);\n    const code = escH(l.codigoGrupo);\n    const drill = 'data-code=\"' + code + '\" data-setor=\"' + escH(sectorCode) + '\"';\n    return '<div class=\"t-row\" data-key=\"ld-' + code + '\"><span class=\"t-name\"><span class=\"t-medal\">' + medalHtml(l.nivel, 40) + '</span><span class=\"t-nm\"><a href=\"#\" class=\"t-link js-drill-lider\" ' + drill + '>' + escH(nome(l.name)) + '</a><span class=\"t-sub\">Grupo ' + code + (l.nivel ? ' · ' + escH(String(l.nivel).toLowerCase()) : '') + '</span></span></span>'\n      + (l.stats || []).slice(0, 3).map(cellHtml).join('')\n      + '<span class=\"t-rem\">' + escH(brl(l.remuneracao)) + '</span><span class=\"t-act\"><button class=\"btn-sm js-modal\" data-kind=\"lider\" data-i=\"' + i + '\">Detalhes</button><a href=\"#\" class=\"t-go js-drill-lider\" ' + drill + ' aria-label=\"Abrir grupo\">' + chev() + '</a></span></div>';\n  }).join('');\n  const gList = [{ code: '', label: 'Todos os grupos', sub: '' }].concat(allGroups.map(g => ({ code: String(g.codigoGrupo), label: g.codigoGrupo + ' · ' + nome(g.name), sub: String(g.nivel || '').toLowerCase() })));\n  const gSel = gList.find(g => g.code === String(selectedGroup || '')) || gList[0];\n  const gOpen = !!d2.state.groupOpen;\n  const groupDd = '<div class=\"dd\"><button class=\"dd-btn dd-light js-group-toggle\" aria-haspopup=\"listbox\" aria-expanded=\"' + gOpen + '\"><span class=\"muted\">Grupo</span><b>' + escH(gSel.label) + '</b>' + caret(gOpen) + '</button>'\n    + (gOpen ? '<button class=\"dd-ovl js-close-lists\" aria-label=\"Fechar lista\" tabindex=\"-1\"></button><div class=\"dd-list dd-wide\" role=\"listbox\" aria-label=\"Grupo\">' + gList.map(g => {\n      const on = g.code === gSel.code;\n      return '<button class=\"dd-opt js-group-opt' + (on ? ' on' : '') + '\" role=\"option\" aria-selected=\"' + on + '\" data-code=\"' + escH(g.code) + '\"><span class=\"flex1\">' + escH(g.label) + '</span><span class=\"dd-sub\">' + escH(g.sub) + '</span><span class=\"dd-chk\">' + (on ? check() : '') + '</span></button>';\n    }).join('') + '</div>' : '') + '</div>';\n  const leadersSum = (tot.leadersRemunSum != null) ? tot.leadersRemunSum : data.leadersRemunSum;\n  const remTot = (tot.remuneracao != null) ? tot.remuneracao : data.remuneracao;\n  const body = '<section class=\"sum\" aria-label=\"Resumo do setor\">'\n    + remCard('gn', 'Remuneração do ciclo', escH(brl(remTot)), '<b>Ciclo ' + escH(cyc) + '</b>' + (leadersSum != null ? ' · as líderes do setor somam ' + escH(brl(leadersSum)) : ''))\n    + totCard('gn', 'Totalizador do setor', tot.stats, iapCodes) + '</section>'\n    + (items.length ? '<section class=\"sec\"><h2 class=\"h2\">Indicadores do <b>setor</b></h2><div class=\"list\">' + items.map(it => itemHtml(d2, it, kpiByCode)).join('') + '</div></section>' : '')\n    + '<section class=\"sec\"><div class=\"sec-h\"><div class=\"sec-ht\"><h2 class=\"h2\">Líderes do <b>setor</b></h2><span class=\"count count-gn\">' + allGroups.length + '</span><span class=\"flex1\"></span>' + LEGEND + '</div>' + groupDd + '</div><div class=\"tbl\">'\n    + tableHead('Líder', head3) + (rows || '<div class=\"t-empty\">Nenhuma líder encontrada.</div>') + pagerHtml(pg) + '</div></section>';\n  let modal = '';\n  const md = d2.state.modal;\n  if(md && md.kind === 'tot'){\n    modal = modalHtml({ title: 'Remuneração do ciclo', sub: nome(gnName) + ' · setor ' + sectorCode, comp: tot.drivers ? compFromDrivers(tot.drivers) : compFromComponents(compOf(tot).composition, remTot), total: brl(remTot) });\n  } else if(md && md.kind === 'lider' && allGroups[md.i]){\n    const l = allGroups[md.i];\n    modal = modalHtml({ title: nome(l.name), sub: 'Líder' + (l.nivel ? ' ' + String(l.nivel).toLowerCase() : '') + ' · grupo ' + l.codigoGrupo + ' · ' + redeTxt(l.rede || rede), stats: withAmbas(l.stats, l.drivers), comp: l.drivers ? compFromDrivers(l.drivers) : compFromComponents(l.composition, l.remuneracao), total: brl(l.remuneracao), link: { cls: 'js-drill-lider', code: l.codigoGrupo, setor: sectorCode, label: 'Abrir grupo' } });\n  }\n  return { hero: hero, body: body, modal: modal };\n}\nfunction bonusRow(label, rule, status, ok){ return '<div class=\"b-row\"><span class=\"b-t\"><span class=\"b-l\">' + escH(label) + '</span>' + (rule ? '<span class=\"b-s\">' + escH(rule) + '</span>' : '') + '</span><span class=\"chip ' + (ok ? 'chip-yes' : 'chip-no') + '\">' + escH(status) + '</span></div>'; }\n// Bônus do ciclo: payout rules when the payload brings drivers; otherwise the bonus accelerators.\nfunction liderBonusRows(data){\n  const dr = data.drivers;\n  if(dr && Array.isArray(dr.bonus) && dr.bonus.length){\n    return dr.bonus.map(b => {\n      const ok = b.willReceive && Number(b.amount) > 0;\n      const rule = b.payoutType === 'per-unit' ? brl0(b.payoutValue) + (/migrad/i.test(b.label || '') ? ' por migrada' : ' por unidade')\n        : brl0(b.payoutValue) + ((b.conditions || []).length ? ' · ' + b.conditions.map(c => c.kpi + ' em ' + c.threshold + '%').join(' e ') : '');\n      return bonusRow(b.label, rule, ok ? 'Vai receber ' + brl(b.amount) : 'Não atingido', ok);\n    }).join('');\n  }\n  return (data.aceleradores || []).filter(a => a.isBonus).map(a => {\n    const gain = Number(a.projectedGain || 0);\n    const ok = a.willReceive && gain > 0;\n    const rel = (a.related || []).filter(hasGoal);\n    const rule = rel.length ? rel.map(r => brandWord(r) + ' ' + sv(r).pct).join(' · ') : '';\n    return bonusRow(a.label, rule, ok ? 'Vai receber ' + brl(gain) : 'Não atingido', ok);\n  }).join('');\n}\nfunction liderView(d2, data){\n  const store = d2.store('store');\n  const lh = data.header || {};\n  const ci = cycleInfo(d2);\n  const cyc = lh.cycle || data.cycle || ci.cur;\n  const grupo = lh.grupo || data.structureCode || '';\n  const rede = lh.rede || data.rede || '';\n  const nivel = lh.nivel || data.nivel || '';\n  const effP = effectivePerfil(d2);\n  const eff = resolveEffectiveIdentity(d2) || {};\n  const gvName = eff.gvName || (store ? store.get('gvName','') : '');\n  const setor = (store && store.get('pilotLiderSetor', '')) || '';\n  const crumbs = (effP === 'gv' ? '<a href=\"#\" class=\"crumb js-crumb\" data-go=\"gv\">Gerência ' + escH(nome(gvName)) + '</a>' + crumbSep() : '')\n    + ((effP !== 'lider' && setor) ? '<a href=\"#\" class=\"crumb js-crumb\" data-go=\"gn\">Setor ' + escH(setor) + '</a>' + crumbSep() : '')\n    + '<span class=\"crumb-cur\" aria-current=\"page\">Grupo ' + escH(grupo) + ' · ' + escH(redeTxt(rede)) + '</span>'\n    + (effP === 'lider' ? lockChip('Você vê só o seu grupo') : '');\n  const hero = heroWrap('lider', '<div class=\"row\"><nav class=\"crumbs\" aria-label=\"Você está em\">' + crumbs + '</nav>' + cycleDd(d2) + '</div><div class=\"row\">' + medalHtml(nivel, 56) + '<h1 class=\"h1\">Líder <b>' + escH(nome(lh.leaderName || lh.name || '')) + '</b></h1></div>' + (ci.partial ? partialChip() : ''));\n  const acel = data.aceleradores || [];\n  const indic = data.indicadores || [];\n  const bonusRows = liderBonusRows(data);\n  const body = '<section class=\"sum\" aria-label=\"Resumo do grupo\">'\n    + remCard('lider', 'Remuneração do ciclo', escH(brl(data.remuneracao)), '<b>Ciclo ' + escH(cyc) + '</b> · grupo ' + escH(grupo))\n    + (bonusRows ? '<div class=\"card card-bonus\"><span class=\"badge\" style=\"background:' + BADGE.lider + '\">' + svgP(MEDAL_D, 20, '#FFFFFF', 1.8) + '</span><span class=\"c-lbl\">Bônus do ciclo</span>' + bonusRows + '</div>' : '')\n    + '</section>'\n    + (acel.length ? '<section class=\"sec\"><div class=\"sec-h\"><div class=\"sec-ht\"><h2 class=\"h2\">Aceleradores de <b>ganhos</b></h2><span class=\"flex1\"></span>' + LEGEND + '</div></div><div class=\"list\">' + acel.map(it => itemHtml(d2, it)).join('') + '</div></section>' : '')\n    + (indic.length ? '<section class=\"sec\"><h2 class=\"h2 h2-sm\">Indicadores de <b>performance</b></h2><div class=\"list\">' + indic.map(it => itemHtml(d2, it)).join('') + '</div></section>' : '');\n  let modal = '';\n  const md = d2.state.modal;\n  if(md && md.kind === 'tot'){\n    modal = modalHtml({ title: 'Remuneração do ciclo', sub: 'Líder' + (nivel ? ' ' + String(nivel).toLowerCase() : '') + ' · grupo ' + grupo + ' · ' + redeTxt(rede), comp: data.drivers ? compFromDrivers(data.drivers) : compFromComponents(compOf(data).composition, data.remuneracao), total: brl(data.remuneracao) });\n  }\n  return { hero: hero, body: body, modal: modal };\n}\n// ── loading / error / invalid session ──\nfunction skeletonHero(view){\n  return heroWrap(view, '<div class=\"row\"><span class=\"skb sk-h1\"></span><span class=\"flex1\"></span><span class=\"skb sk-pill\"></span></div><span class=\"loading-txt\"><svg class=\"spin\" aria-hidden=\"true\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\"><path d=\"M21 12a9 9 0 1 1-6.2-8.56\"></path></svg>Carregando os ganhos do ciclo…</span>');\n}\nfunction skeletonBody(){\n  const line = '<div class=\"sk-row\"><span class=\"skl sk-av\"></span><span class=\"skl sk-w40\"></span><span class=\"flex1\"></span><span class=\"skl sk-w12\"></span><span class=\"skl sk-w12\"></span><span class=\"skl sk-w12\"></span></div>';\n  return '<section class=\"sum\"><div class=\"card card-rem\"><span class=\"skl sk-w40\"></span><span class=\"skl sk-big\"></span><span class=\"skl sk-w70\"></span></div><div class=\"card card-tot\">' + '<span class=\"skl sk-line\"></span>'.repeat(5) + '</div></section><div class=\"tbl sk-tbl\">' + line.repeat(5) + '</div>';\n}\nfunction errorHero(d2, view){\n  const eff = resolveEffectiveIdentity(d2) || {};\n  const own = effectivePerfil(d2) === view;\n  const name = own ? (view === 'gv' ? (eff.gvName || eff.name) : eff.name) : '';\n  return heroWrap(view, '<div class=\"row\"><h1 class=\"h1\">' + ROLE[view] + (name ? ' <b>' + escH(nome(name)) + '</b>' : '') + '</h1><span class=\"flex1\"></span>' + cycleDd(d2) + '</div>');\n}\nfunction errorBody(d2){\n  return '<div class=\"err-card\" role=\"alert\"><span class=\"err-ic\">' + svgP('M2 2l20 20M5.8 5.8A7 7 0 0 0 6.5 19.5H17M20.6 15.6A4.5 4.5 0 0 0 17.5 9h-1.3A7 7 0 0 0 9.2 4.6', 30, '#E5231B', 1.8) + '</span><span class=\"err-t\">Não foi possível carregar o painel</span><span class=\"err-s\">Pode ser uma instabilidade de conexão. Seus dados não foram alterados — tente de novo em instantes.</span><button class=\"btn-pri js-retry\">' + svgP('M21 12a9 9 0 1 1-3-6.7L21 8M21 3v5h-5', 16, 'currentColor', 2.2) + 'Tentar de novo</button>' + (d2.state.loadError ? '<span class=\"err-d\">Detalhe: ' + escH(d2.state.loadError) + '</span>' : '') + '</div>';\n}\nfunction invalidHtml(reason){\n  const pilot = reason === 'sector-not-in-pilot';\n  return '<div class=\"inv\">' + HERO_DECO.gv + '<img class=\"inv-logo\" src=\"' + IMG.logoW + '\" alt=\"natura · AVON · consultoria de beleza\" width=\"168\" height=\"42\"><div class=\"inv-wrap\"><div class=\"inv-card\" role=\"alert\"><span class=\"inv-ic\">'\n    + svgP(pilot ? 'M12 3a9 9 0 1 0 0 18a9 9 0 1 0 0-18M12 8v5M12 16h.01' : 'M5 11h14v10H5zM8 11V7a4 4 0 0 1 8 0v4', 28, '#AE0025', 2) + '</span>'\n    + (pilot ? '<h1 class=\"inv-t\">Painel <b>exclusivo do piloto</b></h1><p class=\"inv-p\">Este painel está disponível apenas para os setores que participam do piloto de remuneração.</p><span class=\"inv-s\">Em caso de dúvida, procure sua liderança.</span>'\n      : '<h1 class=\"inv-t\">Não conseguimos <b>validar seu acesso</b></h1><p class=\"inv-p\">O link de acesso pode ter expirado. Entre de novo pela Consultoria Natura para ver seus ganhos.</p><span class=\"inv-s\">Se continuar acontecendo, fale com sua liderança.</span>')\n    + '</div></div></div>';\n}\nfunction setUi(d2, patch){ Object.keys(patch).forEach(k=>{ d2.state[k] = patch[k]; }); d2.refresh(); }\nexport default {\n  css: `\n  :host{display:block;height:100%}\n  *{box-sizing:border-box}\n  .app{height:100%;min-height:0;display:flex;flex-direction:column;background:#F7F1EC;font-family:Roboto,system-ui,sans-serif;color:#1A1A1A;-webkit-font-smoothing:antialiased}\n  .frame{flex:1 1 auto;display:flex;min-height:0}\n  .flex1{flex:1 1 auto}\n  .muted{color:#757575}\n  a{color:inherit}\n  button{font-family:inherit}\n  /* sidebar */\n  .aside{flex:0 0 224px;width:224px;overflow:hidden;background:#F1E5DC;border-right:1px solid #E6D8CE}\n  .side{position:relative;height:100%;overflow:hidden;padding:16px 12px 12px;display:flex;flex-direction:column;gap:24px}\n  .side-logo{position:relative;padding:8px 12px 20px;border-bottom:1px solid #E0D0C5}\n  .side-logo a{display:block;width:max-content;max-width:100%}\n  .side-logo img{display:block;max-width:100%;height:auto}\n  .side-deco{position:absolute;left:0;bottom:0;width:100%;height:170px;pointer-events:none;opacity:.55}\n  .side-nav{position:relative;display:flex;flex-direction:column;gap:4px}\n  .nav-it{display:flex;align-items:center;gap:12px;height:40px;padding:0 12px;border-radius:12px;text-decoration:none;font-size:14px;color:#1A1A1A;cursor:pointer}\n  .nav-it:hover{background:#E8D9CE}\n  .nav-it.on{font-weight:500;background:#AE0025;color:#FFFFFF}\n  .nav-it .short{display:none}\n  .user{position:relative;display:flex;align-items:center;gap:8px;padding:6px 6px 6px 8px;border-radius:12px;background:#730018;color:#FFFFFF}\n  .user-av{width:26px;height:26px;flex:0 0 26px;border-radius:999px;background:linear-gradient(135deg,#FDB33F,#F57A5B);display:flex;align-items:center;justify-content:center}\n  .user-txt{flex:1;min-width:0;display:flex;flex-direction:column;line-height:15px}\n  .user-n{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .user-r{font-size:11px;color:#FFCCD7;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .user-out{width:28px;height:28px;flex:0 0 28px;border-radius:999px;border:1px solid rgba(255,255,255,.45);background:transparent;color:#FFFFFF;display:flex;align-items:center;justify-content:center;cursor:pointer}\n  .user-out:hover{background:rgba(255,255,255,.14)}\n  /* hero band */\n  .col{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;overflow-y:auto;overscroll-behavior:contain}\n  .col > *{flex-shrink:0}\n  .hero{position:relative;padding-bottom:80px;color:#FFFFFF}\n  .hero-gv{background:linear-gradient(120deg,#590013 0%,#730018 55%,#AE0025 100%)}\n  .hero-gn{background:linear-gradient(120deg,#730018 0%,#AE0025 55%,#AE0025 100%)}\n  .hero-lider{background:linear-gradient(120deg,#FFCCD7 0%,#FFE3E9 55%,#FFCCD7 100%);color:#590013}\n  .hero-deco{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}\n  .hero-in{position:relative;max-width:1104px;margin:0 auto;padding:32px 32px 0;display:flex;flex-direction:column;gap:10px}\n  .hero-gn .hero-in,.hero-lider .hero-in{padding-top:16px;gap:8px}\n  .band-top{display:none;align-items:center;justify-content:space-between}\n  .band-logo{display:block}\n  .band-logo img{display:block}\n  .m-out{display:none;width:36px;height:36px;border-radius:999px;border:1px solid rgba(255,255,255,.55);background:transparent;color:inherit;align-items:center;justify-content:center;cursor:pointer}\n  .hero-lider .m-out{border-color:rgba(89,0,19,.35)}\n  .row{display:flex;flex-wrap:wrap;align-items:center;gap:12px 16px}\n  .h1{margin:0;font-size:32px;line-height:38px;font-weight:300}\n  .h1 b{font-weight:700}\n  .crumbs{flex:1 1 320px;display:flex;flex-wrap:wrap;align-items:center;gap:8px;font-size:14px}\n  .crumb{color:#FFD9E0;text-decoration:none;cursor:pointer}\n  .crumb:hover{text-decoration:underline}\n  .crumb-cur{font-weight:500}\n  .crumb-sep{display:inline-flex;color:#FFD9E0}\n  .hero-lider .crumb,.hero-lider .crumb-sep{color:#730018}\n  .lock{margin-left:8px;display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 12px;border-radius:999px;background:#590013;font-size:12px;color:#FFFFFF}\n  .chip-part{align-self:flex-start;display:inline-flex;align-items:center;gap:8px;height:30px;padding:0 12px;border-radius:999px;background:rgba(255,255,255,.16);font-size:13px}\n  .hero-lider .chip-part{background:#FFFFFF;color:#730018}\n  .seg{display:inline-flex;padding:3px;gap:4px;border-radius:999px;background:rgba(255,255,255,.14)}\n  .seg-b{height:30px;padding:0 18px;border:0;border-radius:999px;background:transparent;color:#FFFFFF;font-size:14px;cursor:pointer}\n  .seg-b.on{background:#FFFFFF;color:#AE0025;font-weight:500}\n  .loading-txt{display:inline-flex;align-items:center;gap:8px;font-size:13px;color:#FFD9E0}\n  .hero-lider .loading-txt{color:#730018}\n  /* dropdowns */\n  .dd{position:relative}\n  .dd-btn{height:36px;max-width:340px;padding:0 12px 0 16px;border:0;border-radius:999px;background:#FFFFFF;color:#1A1A1A;font-size:14px;display:inline-flex;align-items:center;gap:8px;cursor:pointer}\n  .dd-btn b{font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .dd-light{border:1px solid #E2D6CE}\n  .caret{display:block;flex:0 0 18px;transition:transform 150ms ease}\n  .caret.up{transform:rotate(180deg)}\n  .dd-ovl{position:fixed;inset:0;z-index:55;border:0;background:transparent;cursor:default}\n  .dd-list{position:absolute;top:44px;right:0;z-index:60;width:300px;max-height:360px;overflow-y:auto;padding:6px;border-radius:16px;background:#FFFFFF;box-shadow:0 12px 32px rgba(89,0,19,.22);display:flex;flex-direction:column;gap:2px}\n  .dd-wide{width:340px}\n  .dd-opt{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;padding:0 12px;border:0;border-radius:10px;font-size:14px;text-align:left;background:#FFFFFF;color:#1A1A1A;cursor:pointer}\n  .dd-opt:hover{filter:brightness(.97)}\n  .dd-opt.on{background:#FFF0F3;color:#AE0025;font-weight:500}\n  .dd-sub{font-size:12px;font-weight:400;color:#757575}\n  .dd-chk{width:18px;height:18px;flex:0 0 18px;display:inline-flex;align-items:center;justify-content:center}\n  .tag-atual{height:22px;padding:0 8px;border-radius:999px;background:#FFE0E7;color:#AE0025;font-size:11px;font-weight:500;display:inline-flex;align-items:center}\n  /* content */\n  .main{position:relative;width:100%;max-width:1104px;margin:-64px auto 0;padding:0 32px 64px;display:flex;flex-direction:column;gap:32px}\n  .sum{display:flex;flex-wrap:wrap;gap:20px;padding-top:20px}\n  .card{position:relative;background:#FFFFFF;border-radius:20px;box-shadow:0 8px 24px rgba(89,0,19,.14);padding:30px 24px 18px;display:flex;flex-direction:column;gap:4px}\n  .card-rem{flex:1 1 260px}\n  .v-lider .card-rem{flex:1 1 300px}\n  .card-tot{flex:2 1 520px;padding-bottom:10px;gap:2px}\n  .card-bonus{flex:1 1 300px;padding-bottom:8px;gap:2px}\n  .badge{position:absolute;top:-20px;left:24px;width:40px;height:40px;border-radius:999px;display:flex;align-items:center;justify-content:center}\n  .c-lbl{font-size:14px;color:#5C5C5C}\n  .c-big{font-size:30px;line-height:36px;font-weight:500}\n  .c-sub{font-size:13px;color:#5C5C5C}\n  .c-sub b{font-weight:500;color:#1A1A1A}\n  .btn-ghost{align-self:flex-start;margin-top:auto;height:34px;padding:0 16px;border-radius:999px;border:1px solid #AE0025;background:transparent;color:#AE0025;font-size:13px;font-weight:500;cursor:pointer}\n  .card-rem .btn-ghost{margin-top:12px}\n  .btn-ghost:hover{background:#FFF0F3}\n  .tot-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));column-gap:32px}\n  .tot-row{display:flex;align-items:center;gap:10px;min-height:38px;border-bottom:1px solid #F1E8E2}\n  .tr-l{flex:1;display:flex;align-items:center;gap:6px;font-size:14px}\n  .tr-vg{font-size:13px;color:#757575}\n  .tr-p{min-width:44px;white-space:nowrap;text-align:right;font-size:15px;font-weight:500}\n  .dot{display:inline-block;width:9px;height:9px;flex:0 0 9px;border-radius:999px;background:transparent;cursor:help}\n  .iap{height:18px;padding:0 6px;border-radius:999px;background:#FFECCC;color:#734900;font-size:10px;font-weight:500;display:inline-flex;align-items:center}\n  .b-row{display:flex;align-items:center;gap:12px;min-height:46px;border-bottom:1px solid #F1E8E2}\n  .b-row:last-child{border-bottom:0}\n  .b-t{flex:1;display:flex;flex-direction:column}\n  .b-l{font-size:15px}\n  .b-s{font-size:12px;color:#757575}\n  .chip{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 14px;border-radius:999px;font-size:13px;font-weight:500;white-space:nowrap}\n  .chip-yes{background:#E8F5EE;color:#1B7A45}\n  .chip-no{background:#F1EDEA;color:#5C5C5C}\n  .chip-gain{height:36px;background:#E8F5EE;color:#1B7A45;font-size:16px;font-weight:700}\n  .b-row .chip{height:28px;padding:0 12px;font-size:12px}\n  .sec{display:flex;flex-direction:column;gap:16px}\n  .sec-h{display:flex;flex-wrap:wrap;align-items:center;gap:12px 16px}\n  .sec-ht{flex:1 1 280px;display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px}\n  .h2{margin:0;font-size:24px;line-height:30px;font-weight:300}\n  .h2 b{font-weight:700}\n  .h2-sm{font-size:22px}\n  .count{min-width:28px;height:24px;padding:0 8px;border-radius:999px;font-size:13px;font-weight:500;display:inline-flex;align-items:center;justify-content:center}\n  .count-gv{background:#FFCCD7;color:#590013}\n  .count-gn{background:#FFE3B3;color:#734900}\n  .legend{display:inline-flex;flex-wrap:wrap;align-items:center;gap:4px 12px;font-size:12px;color:#757575}\n  .legend span{display:inline-flex;align-items:center;gap:6px}\n  .legend i{display:inline-block;width:8px;height:8px;border-radius:999px}\n  /* tables */\n  .tbl,.list{background:#FFFFFF;border-radius:20px;box-shadow:0 1px 2px rgba(89,0,19,.08);overflow:hidden}\n  .t-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px;min-height:64px;padding:10px 24px;border-top:1px solid #F1E8E2}\n  .t-head{min-height:0;padding:12px 24px;border-top:0;background:#FBF6F2;font-size:12px;color:#757575}\n  .t-name{flex:1 1 240px;min-width:0;display:flex;align-items:center;gap:12px}\n  .t-kpi{flex:0 0 96px;display:flex;align-items:center;gap:8px}\n  .t-head .t-kpi{display:block}\n  .t-pct{font-size:15px;font-weight:500}\n  .t-rem{flex:0 0 104px;text-align:right;font-size:16px;font-weight:500}\n  .t-head .t-rem{font-size:12px;font-weight:400}\n  .t-act{flex:0 0 148px;display:flex;justify-content:flex-end;gap:8px}\n  .t-nm{min-width:0;display:flex;flex-direction:column}\n  .t-link{font-size:15px;font-weight:500;color:#1A1A1A;text-decoration:none;cursor:pointer}\n  .t-link:hover{color:#AE0025}\n  .t-sub{font-size:13px;color:#5C5C5C}\n  .av{width:40px;height:40px;flex:0 0 40px;border-radius:999px;background:linear-gradient(135deg,#FDB33F,#F57A5B);text-shadow:0 1px 2px rgba(115,0,24,.35);color:#FFFFFF;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:500}\n  .t-medal{width:40px;height:40px;flex:0 0 40px;display:flex;align-items:center;justify-content:center}\n  .medal{display:block;flex:0 0 auto;border-radius:999px}\n  .medal-off{background:#F1E8E2}\n  .btn-sm{height:36px;padding:0 14px;border-radius:999px;border:1px solid #E2D6CE;background:#FFFFFF;color:#1A1A1A;font-size:13px;cursor:pointer}\n  .btn-sm:hover{background:#FBF6F2}\n  .t-go{width:36px;height:36px;border-radius:999px;background:#FFF0F3;display:flex;align-items:center;justify-content:center;cursor:pointer}\n  .t-go:hover{background:#FFE0E7}\n  .t-empty{padding:24px;border-top:1px solid #F1E8E2;text-align:center;color:#757575;font-size:14px}\n  .pager{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:12px 24px;border-top:1px solid #F1E8E2;background:#FBF6F2}\n  .pg-info{flex:1;font-size:13px;color:#5C5C5C}\n  .pg{min-width:36px;height:36px;padding:0 10px;border-radius:999px;border:1px solid #E2D6CE;background:#FFFFFF;color:#1A1A1A;font-size:14px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer}\n  .pg.on{border:0;background:#AE0025;color:#FFFFFF;font-weight:500}\n  .pg-arw{color:#AE0025}\n  .pg:disabled{cursor:default;color:#C9BDB5}\n  /* indicator rows */\n  .it{border-bottom:1px solid #F1E8E2}\n  .it:last-child{border-bottom:0}\n  .it-h{width:100%;display:flex;flex-wrap:wrap;align-items:center;gap:12px 20px;min-height:80px;padding:16px 24px;border:0;background:transparent;text-align:left;color:#1A1A1A;font-size:inherit}\n  button.it-h{cursor:pointer}\n  button.it-h:hover{background:#FDFAF8}\n  .it-ico{width:48px;height:48px;flex:0 0 48px;border-radius:14px;display:flex;align-items:center;justify-content:center}\n  .it-main{flex:1 1 260px;min-width:0;display:flex;flex-direction:column;gap:10px}\n  .it-l{display:flex;align-items:center;gap:8px;font-size:17px;font-weight:700}\n  .it-l .iap{height:20px;padding:0 8px;font-size:11px}\n  .bar{display:block;height:10px;border-radius:999px;background:#F1E8E2;overflow:hidden}\n  .bar span{display:block;height:10px;border-radius:999px}\n  .it-sub{font-size:13px;color:#757575}\n  .it-pct{min-width:48px;text-align:right;font-size:18px;font-weight:700}\n  .it-val{min-width:88px;text-align:right;white-space:nowrap}\n  .it-val b{font-size:20px}\n  .it-val .muted{font-size:14px;color:#9A9A9A}\n  .it-chip{flex:0 0 170px;display:flex;justify-content:flex-end}\n  .it-caret{flex:0 0 18px;display:flex}\n  .it-rel{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;padding:0 24px 16px}\n  .rel{padding:14px 16px;border-radius:16px;background:#FBF6F2;display:flex;flex-direction:column;gap:4px}\n  .rel-l{font-size:13px;color:#5C5C5C}\n  .rel-v{display:flex;align-items:center;gap:8px;font-size:18px;font-weight:500}\n  .rel-v .muted{font-size:13px;font-weight:400}\n  .rel-f{font-size:12px;color:#757575}\n  /* modals: fixed in the viewport, centered, the dialog scrolls (never the page behind) */\n  .mwrap{position:fixed;inset:0;z-index:70;display:flex;align-items:center;justify-content:center;padding:24px}\n  .ovl{position:absolute;inset:0;border:0;background:rgba(40,0,10,.45);cursor:default}\n  .dlg{position:relative;width:100%;max-width:620px;max-height:calc(100vh - 48px);overflow-y:auto;overscroll-behavior:contain;background:#FFFFFF;border-radius:24px;box-shadow:0 24px 64px rgba(40,0,10,.3);padding:28px;display:flex;flex-direction:column;gap:20px}\n  .dlg-sm{max-width:560px;gap:16px}\n  .dlg-h{display:flex;align-items:flex-start;gap:14px}\n  .dlg-ht{flex:1;display:flex;flex-direction:column;gap:4px}\n  .dlg-t{font-size:24px;line-height:30px;font-weight:500}\n  .dlg-s{font-size:14px;color:#5C5C5C}\n  .x{width:40px;height:40px;flex:0 0 40px;border-radius:999px;border:1px solid #E2D6CE;background:#FFFFFF;display:flex;align-items:center;justify-content:center;cursor:pointer}\n  .eyebrow{padding-bottom:6px;font-size:12px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:#757575}\n  .m-sec{display:flex;flex-direction:column}\n  .m-row{display:flex;align-items:center;gap:12px;min-height:44px;border-bottom:1px solid #F1E8E2;font-size:15px}\n  .m-row .muted{font-size:14px;color:#5C5C5C}\n  .m-ico{width:22px;height:22px;flex:0 0 22px;display:flex;align-items:center;justify-content:center}\n  .brand{display:block}\n  .m-pct{min-width:48px;white-space:nowrap;text-align:right;font-weight:500}\n  .comp{display:flex;flex-direction:column;padding:16px 20px;border-radius:16px;background:#FBF6F2}\n  .comp-r{display:flex;align-items:center;gap:12px;min-height:36px;font-size:15px}\n  .comp-tot{display:flex;align-items:center;gap:12px;min-height:40px;margin-top:4px;border-top:1px solid #E6D8CE;font-size:16px;font-weight:500}\n  .dlg-f{display:flex;justify-content:flex-end;gap:8px}\n  .btn-out{height:44px;padding:0 20px;border-radius:999px;border:1px solid #1A1A1A;background:#FFFFFF;color:#1A1A1A;font-size:14px;font-weight:500;cursor:pointer}\n  .btn-pri{height:44px;padding:0 20px;border-radius:999px;border:0;background:#AE0025;color:#FFFFFF;font-size:14px;font-weight:500;display:inline-flex;align-items:center;gap:8px;cursor:pointer}\n  .btn-pri:hover{background:#730018}\n  .search{display:flex;align-items:center;gap:10px;height:48px;padding:0 18px;border:1px solid #E2D6CE;border-radius:999px}\n  .search input{flex:1;min-width:0;height:44px;border:0;outline:none;background:transparent;font-family:inherit;font-size:15px;color:#1A1A1A}\n  .err{padding:10px 14px;border-radius:12px;background:#FDECEC;color:#B3261E;font-size:13px}\n  .pk-list{max-height:420px;overflow-y:auto;display:flex;flex-direction:column;gap:4px}\n  .pk{display:flex;align-items:center;gap:12px;min-height:60px;padding:8px 12px;border:0;border-radius:14px;background:#FFFFFF;color:#1A1A1A;text-align:left;cursor:pointer}\n  .pk:hover{background:#FBF6F2}\n  .pk-t{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}\n  .pk-n{display:flex;align-items:center;gap:8px;font-size:15px;font-weight:500}\n  .pk-m{font-size:13px;color:#5C5C5C}\n  .pk-b{height:22px;padding:0 8px;border-radius:999px;font-size:11px;font-weight:500;display:inline-flex;align-items:center}\n  .pk-b.gn{background:#FFE3B3;color:#734900}\n  .pk-b.li{background:#FFE0E7;color:#AE0025}\n  .pk-empty{padding:28px 12px;text-align:center;color:#757575;font-size:14px}\n  /* pilot bar (test mode) + \"vendo como\" banner */\n  .pbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;min-height:52px;padding:8px 24px;background:#2B0009;color:#FFFFFF;font-size:13px}\n  .ptag{height:24px;padding:0 10px;border-radius:999px;background:#F69C00;color:#2B0009;font-size:11px;font-weight:700;letter-spacing:.06em;display:inline-flex;align-items:center}\n  .ptxt{color:#FFCCD7}\n  .psw{display:inline-flex;align-items:center;gap:8px;height:36px;padding:0 8px 0 14px;border-radius:999px;background:#FFFFFF;color:#1A1A1A}\n  .psw-l{color:#757575;font-size:14px;white-space:nowrap}\n  .pil-switch{height:32px;max-width:260px;border:0;background:transparent;font-family:inherit;font-size:14px;font-weight:500;color:#1A1A1A;outline:none;cursor:pointer}\n  .vbar{background:#590013;color:#FFFFFF}\n  .vbar-in{max-width:1200px;margin:0 auto;padding:10px 24px;display:flex;flex-wrap:wrap;align-items:center;gap:10px;font-size:14px}\n  .vbar-in b{font-weight:500}\n  .vbar-out{height:32px;padding:0 14px;border-radius:999px;border:1px solid rgba(255,255,255,.6);background:transparent;color:#FFFFFF;font-size:13px;font-weight:500;cursor:pointer}\n  /* loading */\n  .skb{display:block;position:relative;overflow:hidden;border-radius:999px;background:rgba(255,255,255,.18)}\n  .hero-lider .skb{background:rgba(89,0,19,.10)}\n  .sk-h1{width:360px;max-width:70%;height:36px}\n  .sk-pill{width:150px;height:36px}\n  .skl{display:block;position:relative;overflow:hidden;height:14px;border-radius:8px;background:#F1E8E2}\n  .skb::after,.skl::after{content:'';position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(90deg,transparent,rgba(255,255,255,.45),transparent);animation:skm 1.4s infinite}\n  @keyframes skm{100%{transform:translateX(100%)}}\n  .sk-w40{width:40%}\n  .sk-w70{width:70%}\n  .sk-w12{width:72px}\n  .sk-big{width:55%;height:30px;margin:6px 0}\n  .sk-line{width:100%;margin:12px 0}\n  .sk-av{width:40px;height:40px;border-radius:999px}\n  .sk-row{display:flex;align-items:center;gap:16px;min-height:64px;padding:10px 24px;border-top:1px solid #F1E8E2}\n  .sk-row:first-child{border-top:0}\n  .spin{animation:spin 800ms linear infinite}\n  @keyframes spin{to{transform:rotate(360deg)}}\n  /* error */\n  .err-card{position:relative;margin-top:20px;padding:48px 32px 40px;border-radius:24px;background:#FFFFFF;box-shadow:0 8px 24px rgba(89,0,19,.14);display:flex;flex-direction:column;align-items:center;gap:12px;text-align:center}\n  .err-ic{width:64px;height:64px;border-radius:999px;background:#FDECEC;display:flex;align-items:center;justify-content:center}\n  .err-t{font-size:22px;line-height:28px;font-weight:500}\n  .err-s{max-width:460px;font-size:15px;line-height:22px;color:#5C5C5C}\n  .err-card .btn-pri{margin-top:8px}\n  .err-d{font-size:12px;color:#9A9A9A}\n  /* invalid session / outside the pilot */\n  .inv{position:relative;min-height:100vh;overflow:hidden;background:linear-gradient(120deg,#590013 0%,#730018 55%,#AE0025 100%);font-family:Roboto,system-ui,sans-serif;color:#1A1A1A}\n  .inv .hero-deco{position:absolute}\n  .inv-logo{position:absolute;top:32px;left:40px;display:block}\n  .inv-wrap{position:relative;min-height:100vh;display:flex;align-items:center;justify-content:center;padding:40px}\n  .inv-card{width:100%;max-width:480px;padding:40px 40px 32px;border-radius:24px;background:#FFFFFF;box-shadow:0 24px 64px rgba(40,0,10,.35);display:flex;flex-direction:column;align-items:center;gap:14px;text-align:center}\n  .inv-ic{width:64px;height:64px;border-radius:999px;background:#FFE0E7;display:flex;align-items:center;justify-content:center}\n  .inv-t{margin:4px 0 0;font-size:24px;line-height:30px;font-weight:300}\n  .inv-t b{font-weight:700}\n  .inv-p{margin:0;font-size:15px;line-height:22px;color:#5C5C5C}\n  .inv-s{font-size:13px;color:#757575}\n  .mtabs{display:none}\n  @media (prefers-reduced-motion: reduce){.spin,.skb::after,.skl::after{animation:none}.caret{transition:none}}\n  /* tablet: compact menu */\n  @media (max-width:1100px){\n    .aside{flex:0 0 88px;width:88px}\n    .side{padding:12px 8px;gap:16px}\n    .side-logo{display:none}\n    .nav-it{flex-direction:column;justify-content:center;height:auto;min-height:60px;padding:8px 4px;gap:4px;font-size:11px;line-height:13px;text-align:center}\n    .nav-it .long{display:none}\n    .nav-it .short{display:inline}\n    .user{flex-direction:column;padding:8px 4px;gap:8px}\n    .user-txt{display:none}\n    .band-top{display:flex;margin-bottom:8px}\n    .hero-in{padding-left:24px;padding-right:24px}\n    .main{padding-left:24px;padding-right:24px}\n    .t-row{padding-left:16px;padding-right:16px;column-gap:12px}\n    .t-name{flex-basis:180px}\n    .t-kpi{flex-basis:72px}\n    .t-rem{flex-basis:96px}\n    .t-act{flex-basis:auto}\n    .t-go{display:none}\n  }\n  /* phone: no sidebar, bottom tabs */\n  @media (max-width:700px){\n    .aside{display:none}\n    .m-out{display:inline-flex}\n    .hero{padding-bottom:72px}\n    .hero-in{padding:16px 16px 0}\n    .h1{font-size:24px;line-height:30px}\n    .main{padding:0 16px 104px;gap:24px}\n    .card-rem,.card-tot,.card-bonus{flex-basis:100%}\n    .c-big{font-size:26px;line-height:32px}\n    .tot-grid{grid-template-columns:1fr}\n    .t-head{display:none}\n    .t-row{padding:12px 16px;gap:8px 12px}\n    .t-name{flex:1 1 100%}\n    .t-kpi{flex:1 1 0}\n    .t-rem{flex:1 1 auto;text-align:left}\n    .it-h{padding:14px 16px;gap:10px 14px}\n    .it-main{flex-basis:100%}\n    .it-chip{flex:1 1 auto;justify-content:flex-start}\n    .it-rel{padding:0 16px 14px}\n    .dd-list{right:auto;left:0;width:min(300px,calc(100vw - 32px))}\n    .ptxt{display:none}\n    .pbar{padding:8px 16px}\n    .mwrap{padding:12px}\n    .dlg{padding:20px;border-radius:20px}\n    .mtabs{display:flex;justify-content:space-around;position:fixed;left:0;right:0;bottom:0;z-index:40;padding:6px 8px calc(6px + env(safe-area-inset-bottom));background:#FFFFFF;box-shadow:0 -4px 16px rgba(89,0,19,.10)}\n    .mt{flex:1;display:flex;flex-direction:column;align-items:center;gap:4px;text-decoration:none;font-size:12px;color:#5C5C5C}\n    .mt-pill{width:56px;height:30px;border-radius:999px;display:flex;align-items:center;justify-content:center}\n    .mt.on{color:#AE0025;font-weight:500}\n    .mt.on .mt-pill{background:#FFE0E7}\n    .inv-logo{top:24px;left:24px}\n    .inv-wrap{padding:96px 16px 24px}\n    .inv-card{padding:32px 24px 28px}\n  }\n  `,\n  render(d2){\n    const store = d2.store('store');\n    const view = curView(d2);\n    // App B / TOKEN — invalid/expired session or sector outside the pilot. Never a silent\n    // full-GV fallback (that would be a scope leak).\n    if(store && store.get('pilotTokenInvalid', false)) return invalidHtml(store.get('pilotTokenInvalidReason', ''));\n    const data = store ? store.get('data', null) : null;\n    const loading = store ? store.get('loading', false) : false;\n    let v;\n    if(d2.state.viewReady && !loading && data && data.perfil === view){\n      v = view === 'gv' ? gvView(d2, data) : (view === 'gn' ? gnView(d2, data) : liderView(d2, data));\n    } else if(d2.state.viewReady && !loading && d2.state.loadError){\n      v = { hero: errorHero(d2, view), body: errorBody(d2), modal: '' };\n    } else {\n      v = { hero: skeletonHero(view), body: skeletonBody(), modal: '' };\n    }\n    return shellHtml(d2, view, v.hero, v.body, (v.modal || '') + verComoHtml(d2));\n  },\n  async mounted(d2){\n    // Bootstrap overrides from URL query (?perfil=gv&rede=rede1&structureCode=3253&gvName=...)\n    try{\n      const store = d2.store('store');\n      const q = new URLSearchParams((typeof location!=='undefined' && location.search) || '');\n      if(store){\n        if(q.get('perfil')) store.set('perfil', q.get('perfil'));\n        if(q.get('rede')) store.set('rede', q.get('rede'));\n        if(q.get('structureCode')) store.set('structureCode', q.get('structureCode'));\n        if(q.get('gvName')) store.set('gvName', q.get('gvName'));\n        if(q.get('cycle')){ store.set('cycle', q.get('cycle')); store.set('cycleForced', true); }\n      }\n    }catch(e){ d2.log('bootstrap query error', e); }\n    // Pilot bar + Ver como (gv-admin mode only; the render hides them in token mode).\n    d2.on('.pil-switch','change',(e,el)=>{ onSwitchActingUser(d2, el && el.value); });\n    d2.on('.js-vercomo','click',(e)=>{ if(e && e.preventDefault) e.preventDefault(); setUi(d2, { impPickerOpen:true, impQuery:'', impError:null }); ensureAllowedTargets(d2); });\n    d2.on('.pil-imp-close','click',()=>{ setUi(d2, { impPickerOpen:false }); });\n    d2.on('.pil-imp-search','input',(e,el)=>{ setUi(d2, { impQuery: el ? el.value : '' }); });\n    d2.on('.pil-imp-pick','click',(e,el)=>{ onPickImpersonationTarget(d2, el && el.getAttribute('data-uid')); });\n    d2.on('.pil-imp-exit','click',()=>{ onExitImpersonation(d2); });\n    // Menu (sidebar + phone tabs) and Sair.\n    d2.on('.js-nav','click',(e,el)=>{\n      if(e && e.preventDefault) e.preventDefault();\n      const go = el && el.getAttribute('data-go');\n      if(go === 'painel'){ const h = homeView(d2); if(h !== curView(d2)) goView(d2, h); return; }\n      if(go) routerGo(d2, '/' + go);\n    });\n    d2.on('.js-logout','click',()=>{ onLogout(d2); });\n    d2.on('.js-retry','click',()=>{ loadData(d2); });\n    // Breadcrumb back links.\n    d2.on('.js-crumb','click',(e,el)=>{\n      if(e && e.preventDefault) e.preventDefault();\n      const go = el && el.getAttribute('data-go');\n      if(go === 'gv') backToGv(d2); else if(go === 'gn') backToSector(d2);\n    });\n    // Cycle selector → refetch the current view for the chosen cycle.\n    d2.on('.js-cycle-toggle','click',()=>{ setUi(d2, { cycleOpen: !d2.state.cycleOpen, groupOpen:false }); });\n    d2.on('.js-close-lists','click',()=>{ setUi(d2, { cycleOpen:false, groupOpen:false }); });\n    d2.on('.js-cycle-opt','click',(e,el)=>{\n      setUi(d2, { cycleOpen:false });\n      const store = d2.store('store');\n      const v = el && el.getAttribute('data-cycle');\n      if(!store || !v || String(store.get('cycle','')) === String(v)) return;\n      store.set('cycle', String(v));\n      store.set('cycleUserSel', true);\n      store.set('data', null);\n      pilotTrackView(d2, 'dashboard:cycle:'+v, store.get('perfil','gn'));\n      loadData(d2);\n    });\n    // REDE 1 / REDE 2 toggle in the GV panel → switch rede param and refetch.\n    d2.on('.js-rede','click',(e,el)=>{\n      const store = d2.store('store');\n      const r = el && el.getAttribute('data-rede');\n      if(!store || !r || store.get('rede','rede1') === r) return;\n      pilotTrackView(d2, 'dashboard:gv:'+r, 'gv');\n      setUi(d2, { page:1, modal:null });\n      store.set('rede', r);\n      store.set('data', null);\n      loadData(d2);\n    });\n    // Group picker on the GN panel: only filters the list (the row opens the leader).\n    d2.on('.js-group-toggle','click',()=>{ setUi(d2, { groupOpen: !d2.state.groupOpen, cycleOpen:false }); });\n    d2.on('.js-group-opt','click',(e,el)=>{\n      const code = (el && el.getAttribute('data-code')) || '';\n      d2.shared.set('pilotSelectedGroup', code, { global:true });\n      setUi(d2, { groupOpen:false, selGroup: code, page:1 });\n    });\n    // Drills: GV → GN sector, GN → leader.\n    d2.on('.js-drill-gn','click',(e,el)=>{ if(e && e.preventDefault) e.preventDefault(); setUi(d2, { modal:null }); drillToGn(d2, el && el.getAttribute('data-code')); });\n    d2.on('.js-drill-lider','click',(e,el)=>{ if(e && e.preventDefault) e.preventDefault(); setUi(d2, { modal:null }); drillToLider(d2, el && el.getAttribute('data-code'), (el && el.getAttribute('data-setor')) || null); });\n    // Detalhes / Como foi calculado, pagination, expandable indicator rows.\n    d2.on('.js-modal','click',(e,el)=>{ setUi(d2, { modal: { kind: el.getAttribute('data-kind'), i: Number(el.getAttribute('data-i') || 0) } }); });\n    d2.on('.js-modal-close','click',()=>{ setUi(d2, { modal:null }); });\n    d2.on('.js-page','click',(e,el)=>{ const p = Number(el && el.getAttribute('data-page')); if(p) setUi(d2, { page:p }); });\n    d2.on('.js-item','click',(e,el)=>{\n      const ref = el && el.getAttribute('data-ref');\n      if(!ref) return;\n      const o = Object.assign({}, d2.state.openItems || {});\n      o[ref] = !o[ref];\n      setUi(d2, { openItems:o });\n    });\n    d2.on(document,'keydown',(e)=>{\n      if(e && e.key === 'Escape') setUi(d2, { modal:null, impPickerOpen:false, cycleOpen:false, groupOpen:false });\n    });\n    await bootView(d2);\n  }\n};\n"}},"store":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"store"}}}},"api":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"api"}}}},"auth":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"auth"}}}},"view":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"view"}}}}}}}}}},{"_id":"5ed9bed7b9e0891ce913e884","component":"data2-core-types@Component","params":{"package":"data2-core","component":"DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}},{"_id":"5f472ae463c680de4ff296e9","component":"data2-core-types@Component","params":{"package":"data2-core","component":"Data2TableDataSource","extends":"data2-core@DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}},{"_id":"5ecd05ded68ce41360f74b43","component":"data2-core-types@Component","params":{"extendable":{"placeholder":"children"},"component":"Block","package":"data2-core-primitives"}},{"_id":"5f494791a575399a45020f87","component":"data2-core-types@Component","params":{"definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"html@input","params":{"style":{"width":"100%","height":"100%","boxSizing":"border-box","background":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparision-operators@Identical","params":{"subject":{"params":{"reference":"type","source":"VIRTUAL_COMPONENT_PARAMS"},"component":"data2-core-types@Reference"},"comparisonSubject":"checkbox"}}],"then":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparision-operators@Identical","params":{"subject":{"component":"data2-core-types@DataLinkGetter","params":{"dataset":{"component":"data2-core-types@Reference","params":{"reference":"dataset","source":"VIRTUAL_COMPONENT_PARAMS"}},"field":{"component":"data2-core-types@Reference","params":{"reference":"field","source":"VIRTUAL_COMPONENT_PARAMS"}},"record":{"component":"data2-core-types@Reference","params":{"reference":"record","source":"VIRTUAL_COMPONENT_PARAMS"}}}},"comparisonSubject":true}}],"then":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"checkboxFill"}}}},"rgba(0,118,255,1)"]},"component":"data2-core-logical-operators@Or"},"else":{"params":{"content":"none"},"component":"data2-core-primitives@String"}}},"else":{"params":{"content":"none"},"component":"data2-core-primitives@String"}}},"color":{"params":{"reference":"super.textColor"},"component":"data2-core-types@Reference"},"border":"none","outline":"none","appearance":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparision-operators@Identical","params":{"subject":{"params":{"reference":"orient","source":"VIRTUAL_COMPONENT_PARAMS"},"component":"data2-core-types@Reference"},"comparisonSubject":"vertical"}}],"then":"slider-vertical","else":"none"}},"cursor":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"super.cursor"}}}},{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparision-operators@Identical","params":{"subject":{"params":{"reference":"disabled","source":"VIRTUAL_COMPONENT_PARAMS"},"component":"data2-core-types@Reference"},"comparisonSubject":true}}],"then":{"component":"data2-core-primitives@String","params":{"content":"not-allowed"}},"else":{"component":"data2-core-primitives@String","params":{"content":"auto"}}}}]},"component":"data2-core-logical-operators@Or"},"fontWeight":{"component":"data2-core-primitives@String","params":{"content":"inherit"}},"paddingLeft":{"component":"data2-core-flow@If","params":{"compare":[{"params":{"comparisonSubject":{"params":{},"component":"data2-core-primitives@Undefined"},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"padding.left"}}}}},"component":"data2-core-comparison-operators@Different"}],"then":{"params":{"portions":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"padding.left"}}}},{"component":"data2-core-primitives@String","params":{"content":"px"}}]},"component":"data2-core-functions@StringConcat"}}},"paddingRight":{"component":"data2-core-flow@If","params":{"compare":[{"params":{"comparisonSubject":{"params":{},"component":"data2-core-primitives@Undefined"},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"padding.right"}}}}},"component":"data2-core-comparison-operators@Different"}],"then":{"params":{"portions":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"padding.right"}}}},{"component":"data2-core-primitives@String","params":{"content":"px"}}]},"component":"data2-core-functions@StringConcat"}}},"caretColor":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"caretColor"}}}},"textAlign":{"params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"super.textFormat.textAlign"}}},"component":"data2-core-types@Reference"}},"tabIndex":{"component":"data2-core-types@Reference","params":{"reference":"tabIndex","source":"VIRTUAL_COMPONENT_PARAMS"}},"step":{"component":"data2-core-types@Reference","params":{"reference":"step","source":"VIRTUAL_COMPONENT_PARAMS"}},"min":{"component":"data2-core-types@Reference","params":{"reference":"min","source":"VIRTUAL_COMPONENT_PARAMS"}},"max":{"component":"data2-core-types@Reference","params":{"reference":"max","source":"VIRTUAL_COMPONENT_PARAMS"}},"maxLength":{"params":{"then":{"params":{},"component":"data2-core-primitives@Undefined"},"compare":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":"maxLength","source":"VIRTUAL_COMPONENT_PARAMS"}},"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":""}}},"component":"data2-core-comparison-operators@Equal"}],"else":{"component":"data2-core-types@Reference","params":{"reference":"maxLength","source":"VIRTUAL_COMPONENT_PARAMS"}}},"component":"data2-core-flow@If"},"orient":{"component":"data2-core-types@Reference","params":{"reference":"orient","source":"VIRTUAL_COMPONENT_PARAMS"}},"type":{"component":"data2-core-types@Reference","params":{"reference":"type","source":"VIRTUAL_COMPONENT_PARAMS"}},"placeholder":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":"placeholder","source":"VIRTUAL_COMPONENT_PARAMS"}},{"component":"data2-core-types@Reference","params":{"reference":"field","source":"VIRTUAL_COMPONENT_PARAMS"}}]}},"value":{"params":{"expression":{"params":{"content":true},"component":"data2-core-primitives@Boolean"},"defaultCase":{"component":"data2-core-types@DataLinkGetter","params":{"dataset":{"component":"data2-core-types@Reference","params":{"reference":"dataset","source":"VIRTUAL_COMPONENT_PARAMS"}},"field":{"component":"data2-core-types@Reference","params":{"reference":"field","source":"VIRTUAL_COMPONENT_PARAMS"}},"record":{"component":"data2-core-types@Reference","params":{"reference":"record","source":"VIRTUAL_COMPONENT_PARAMS"}},"mask":{"component":"data2-core-types@Reference","params":{"reference":"mask","source":"VIRTUAL_COMPONENT_PARAMS"}}}},"cases":[{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-comparision-operators@Identical","params":{"subject":{"params":{"reference":"type","source":"VIRTUAL_COMPONENT_PARAMS"},"component":"data2-core-types@Reference"},"comparisonSubject":"date"}},"value":{"component":"data2-core-functions@DateFormat","params":{"date":{"component":"data2-core-types@DataLinkGetter","params":{"dataset":{"component":"data2-core-types@Reference","params":{"reference":"dataset","source":"VIRTUAL_COMPONENT_PARAMS"}},"field":{"component":"data2-core-types@Reference","params":{"reference":"field","source":"VIRTUAL_COMPONENT_PARAMS"}},"record":{"component":"data2-core-types@Reference","params":{"reference":"record","source":"VIRTUAL_COMPONENT_PARAMS"}}}},"format":"YYYY-MM-DD"}}}},{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-comparision-operators@Identical","params":{"subject":{"params":{"reference":"type","source":"VIRTUAL_COMPONENT_PARAMS"},"component":"data2-core-types@Reference"},"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"month"}}}},"value":{"component":"data2-core-functions@DateFormat","params":{"date":{"component":"data2-core-types@DataLinkGetter","params":{"dataset":{"component":"data2-core-types@Reference","params":{"reference":"dataset","source":"VIRTUAL_COMPONENT_PARAMS"}},"field":{"component":"data2-core-types@Reference","params":{"reference":"field","source":"VIRTUAL_COMPONENT_PARAMS"}},"record":{"component":"data2-core-types@Reference","params":{"reference":"record","source":"VIRTUAL_COMPONENT_PARAMS"}}}},"format":{"component":"data2-core-primitives@String","params":{"content":"YYYY-MM"}}}}}},{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-comparision-operators@Identical","params":{"subject":{"params":{"reference":"type","source":"VIRTUAL_COMPONENT_PARAMS"},"component":"data2-core-types@Reference"},"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"datetime-local"}}}},"value":{"component":"data2-core-functions@DateFormat","params":{"date":{"component":"data2-core-types@DataLinkGetter","params":{"dataset":{"component":"data2-core-types@Reference","params":{"reference":"dataset","source":"VIRTUAL_COMPONENT_PARAMS"}},"field":{"component":"data2-core-types@Reference","params":{"reference":"field","source":"VIRTUAL_COMPONENT_PARAMS"}},"record":{"component":"data2-core-types@Reference","params":{"reference":"record","source":"VIRTUAL_COMPONENT_PARAMS"}}}},"format":{"component":"data2-core-primitives@String","params":{"content":"YYYY-MM-DDTHH:mm"}}}}}}]},"component":"data2-core-flow@Switch"},"onChange":{"component":"data2-core-types@DataLinkSetter","params":{"dataset":{"component":"data2-core-types@Reference","params":{"reference":"dataset","source":"VIRTUAL_COMPONENT_PARAMS"}},"field":{"component":"data2-core-types@Reference","params":{"reference":"field","source":"VIRTUAL_COMPONENT_PARAMS"}},"record":{"component":"data2-core-types@Reference","params":{"reference":"record","source":"VIRTUAL_COMPONENT_PARAMS"}},"recordUpsert":{"component":"data2-core-types@Reference","params":{"reference":"recordUpsert","source":"VIRTUAL_COMPONENT_PARAMS"}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":"onChange","source":"VIRTUAL_COMPONENT_PARAMS"}},"mask":{"component":"data2-core-types@Reference","params":{"reference":"mask","source":"VIRTUAL_COMPONENT_PARAMS"}}}},"defaultChecked":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparision-operators@Identical","params":{"subject":{"params":{"reference":"type","source":"VIRTUAL_COMPONENT_PARAMS"},"component":"data2-core-types@Reference"},"comparisonSubject":"checkbox"}}],"then":{"component":"data2-core-types@DataLinkGetter","params":{"dataset":{"component":"data2-core-types@Reference","params":{"reference":"dataset","source":"VIRTUAL_COMPONENT_PARAMS"}},"field":{"component":"data2-core-types@Reference","params":{"reference":"field","source":"VIRTUAL_COMPONENT_PARAMS"}},"record":{"component":"data2-core-types@Reference","params":{"reference":"record","source":"VIRTUAL_COMPONENT_PARAMS"}}}},"else":""}},"field":{"component":"data2-core-types@Reference","params":{"reference":"field"}},"opacity":{"component":"data2-core-flow@If","params":{"compare":[{"params":{"reference":"disabled","source":"VIRTUAL_COMPONENT_PARAMS"},"component":"data2-core-types@Reference"}],"then":0.38,"else":1}},"disabled":{"params":{"reference":"disabled","source":"VIRTUAL_COMPONENT_PARAMS"},"component":"data2-core-types@Reference"},"autoComplete":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparision-operators@Equal","params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":"builder"}},"comparisonSubject":true}}],"then":"new-password","else":{"params":{"compare":{"params":{"comparisonSubject":{"params":{"content":true},"component":"data2-core-primitives@Boolean"},"subject":{"params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"autoComplete"}}},"component":"data2-core-types@Reference"}},"component":"data2-core-comparison-operators@Identical"},"else":{"params":{"components":[{"params":{"reference":"autoComplete","source":"VIRTUAL_COMPONENT_PARAMS"},"component":"data2-core-types@Reference"},{"component":"data2-core-primitives@String","params":{"content":"off"}}]},"component":"data2-core-logical-operators@Or"}},"component":"data2-core-flow@If"}}},"data-lpignore":{"component":"data2-core-flow@If","params":{"compare":[{"params":{"reference":"autoComplete","source":"VIRTUAL_COMPONENT_PARAMS"},"component":"data2-core-types@Reference"}],"then":"","else":"true"}},"onFocus":{"component":"data2-core-types@Reference","params":{"reference":"onFocus","source":"VIRTUAL_COMPONENT_PARAMS"}},"onBlur":{"component":"data2-core-types@Reference","params":{"reference":"onBlur","source":"VIRTUAL_COMPONENT_PARAMS"}},"onKeyPress":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onKeyPress"}}}},"autoCapitalize":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"autoCapitalize"}}}},"spellCheck":{"params":{"expression":{"params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"spellCheck"}}},"component":"data2-core-types@Reference"},"cases":[{"component":"data2-core-flow@Case","params":{"expression":{"params":{"content":true},"component":"data2-core-primitives@Boolean"},"value":{"component":"data2-core-primitives@String","params":{"content":"true"}}}},{"component":"data2-core-flow@Case","params":{"expression":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"value":{"component":"data2-core-primitives@String","params":{"content":"false"}}}}]},"component":"data2-core-flow@Switch"}}}}},"component":"DataFieldBlock","package":"data2-blocks","extends":"data2-core-primitives@Block"}}]}},{"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":{"component":"data2-core-types@Getter","displayName":"isData2User","params":{"module":{"component":"data2-core-functions@Match","params":{"pattern":{"component":"data2-core-types@Regex","params":{"pattern":"@data2\\.app$","flags":"i"}},"text":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.email"}}}}}},"prop":{"component":"data2-core-primitives@String","params":{"content":"0"}}}},"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":{"component":"data2-core-flow@If","displayName":"management exception never picks the system","params":{"compare":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}}},{"component":"data2-core-logical-operators@Not","params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}}}}}]}},"then":{"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"else":{"d2_app":"management"}}},"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-10-29T19:05:43.007Z","updateMetadata":{"updatedBy":{"user":"5f1609be1ca96def427e1559"}}},{"_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"},{"component":"data2-core@DataSet","reference":"SessionsDataSet","params":{"requiresConfirmation":false,"pk":"key","datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"data2sessionsdatasource"}}}},{"component":"data2-core@ServerSessionsDataSource","reference":"data2sessionsdatasource","params":{}},{"reference":"UsersTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"_id":"5f1600b70528b92601890f75","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ServiceComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ServiceComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:20.208Z","createdAt":"2020-07-20T20:38:15.436Z"},{"_id":"5f1602190528b92601890f7d","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":40000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentInstancesTableDataSource"}},"sort":{"_id":1},"pk":"_id","autoEdit":true,"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:07.089Z","createdAt":"2020-07-20T20:44:09.350Z"},{"_id":"5f16017f0528b92601890f7a","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"clientApplicationDomain"}}},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"FileComponentInstancesDataSet","updatedAt":"2023-08-03T16:08:18.193Z","createdAt":"2020-07-20T20:41:35.797Z"},{"_id":"5f1601990528b92601890f7b","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ApplicationsTableDataSource"}},"pk":"_id","autoEdit":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"params":{"column":"_id"},"component":"data2-core-types@DataSetColumnReference"}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"ApplicationsDataSet","updatedAt":"2022-12-13T21:51:13.995Z","createdAt":"2020-07-20T20:42:01.657Z"},{"_id":"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":[{"_id":"6a4e34932daf06e6ec513738","component":"data2-rush@HTTPListener","reference":"pilotResolveDisplayCycle","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a4d0b6abeefcfaef4a8e2c3","component":"data2-rush@HTTPListener","reference":"pilotResolveIdentity","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a4d22a588e6a7e5f175fa2d","component":"data2-rush@HTTPListener","reference":"pilotResolveSession","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a4d0e0de68b299a00e0a5e3","component":"data2-rush@HTTPListener","reference":"pilotUsers","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a4d0d7691afdd4d5cd432f1","component":"data2-rush@HTTPListener","reference":"pilotAllowedTargets","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a4d0b111f90fca2e26ec5cc","component":"data2-rush@HTTPListener","reference":"pilotImpersonate","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a4d0b1e5352e22ca383eaa3","component":"data2-rush@HTTPListener","reference":"pilotEndImpersonation","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a4d4a1376e1040b314ea1d0","component":"data2-rush@HTTPListener","reference":"pilotTrackAccess","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a47e3e59c748d97fd55feb8","component":"data2-rush@HTTPListener","reference":"pilotGetGroupEarnings","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a4ce85aec1515c9a0beddb2","component":"data2-rush@HTTPListener","reference":"pilotSimulate","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a4d041e946749d49a751006","component":"data2-rush@HTTPListener","reference":"pilotBandTables","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a4cec6c1f90fca2e26e26b6","component":"data2-rush@HTTPListener","reference":"pilotHistorico","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a47e4aad135f62a64eed8d8","component":"data2-rush@HTTPListener","reference":"pilotGetDashboardData","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a4d65dd2daf06e6ec50270a","component":"data2-rush@HTTPListener","reference":"pilotRunQuery","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a4d6772a473ec02c4b08492","component":"data2-rush@HTTPListener","reference":"pilotQueryLibWrite","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a4c13a0cafa01f91f62d5f8","component":"data2-rush@HTTPListener","reference":"pilotAdminRuleWrite","system":"688179c2a93dd170ce61e598","params":{}},{"_id":"6a4c017138d004bafdea4b25","component":"data2-rush@HTTPListener","reference":"pilotAdminItemWrite","system":"688179c2a93dd170ce61e598","params":{}}]}},{"reference":"ComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6ad65bfb2ac18dc3fcbcf40e","component":"data2-core-primitives@Router","system":"688179c2a93dd170ce61e598","displayName":"PILOT · Admin Router","params":{"routerType":{"component":"data2-core-primitives@String","params":{"content":"browser"}},"routes":[{"component":"data2-core-primitives@Route","params":{"path":"","name":"Administração do Painel","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"JecI-Fl9ecOnfdjb4gaI5"}},"policies":[{"component":"data2-core-auth@Policy","params":{"authenticationStrategy":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotAdminAuth"}}}}]}},{"component":"data2-core-primitives@Route","params":{"path":"/simular","name":"Simular usuário","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"6D4KMO_WM699IGwgZocts"}},"policies":[{"component":"data2-core-auth@Policy","params":{"authenticationStrategy":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotAdminAuth"}}}}]}}],"login":{"component":"data2-core-types@ArtboardReference","params":{"reference":"cjloJx4TuhpyVmpq1WZzR"}}},"reference":"pilotAdminRouter"},{"_id":"6a480778e3014dd5bb6ec589","component":"data2-core-primitives@Artboard","system":"688179c2a93dd170ce61e598","displayName":"PILOT · Dashboard M","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"PILOT · Dashboard M"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"alternativeArtboards":{"component":"data2-core-types@ResponsiveArtboards","params":{"mobile":{"component":"data2-core-types@ArtboardReference","params":{"reference":"h9CDEJeATP5mABV7X-Ute"}}}}},"reference":"T1Koa6_rMuQPmA9nSCIk1"},{"_id":"6ae9e6e7da75201f6b34ca1a","component":"data2-core-primitives@Router","system":"688179c2a93dd170ce61e598","displayName":"REDESIGN · Router","params":{"routerType":{"component":"data2-core-primitives@String","params":{"content":"browser"}},"routes":[{"component":"data2-core-primitives@Route","params":{"path":"/","name":"Painel","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"vC0Wc2AL0qIdO9XXjIIEO"}},"onEnter":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-functions@JSONParse","params":{"text":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"localStorage.getItem","args":["_d2_natura_session"]}}}},"resultName":"natura_session"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.authorization"}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.token"}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.c"}}]}},"resultName":"urlToken"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@And","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":"natura_session.token"}},{"component":"data2-core-types@Reference","params":{"reference":"natura_session.createdAt"}},{"component":"data2-core-comparison-operators@LesserThan","params":{"subject":{"component":"data2-core-functions@DateDiff","params":{"left":{"component":"data2-core-functions@DateNow","params":{}},"right":{"component":"data2-core-functions@DateParse","params":{"date":{"component":"data2-core-types@Reference","params":{"reference":"natura_session.createdAt"}}}},"period":"hours"}},"comparisonSubject":2}}]}},"resultName":"storedOk"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":"urlToken"}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"storedOk"}},"then":{"component":"data2-core-types@Reference","params":{"reference":"natura_session.token"}}}}]}},"resultName":"cookie"}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"cookie"}},"then":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotMaiaAuth"}},"prop":"logout","args":[]}},{"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotMaiaAuth"}},"prop":"loginIdentityProvider","args":[{"component":"data2-core-types@IdentityProviderReference","params":{"reference":"NlrnS53tjBMzSo2rIsfG6"}},{"component":"data2-core-types@Reference","params":{"reference":"cookie"}}]}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"localStorage.setItem","args":["_d2_natura_session",{"component":"data2-core-functions@JSONStringify","params":{"value":{"token":{"component":"data2-core-types@Reference","params":{"reference":"cookie"}},"createdAt":{"component":"data2-core-functions@DateFormat","params":{"date":{"component":"data2-core-functions@DateNow","params":{}}}}}}}]}}]}}}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"urlToken"}},"then":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"history.replaceState","args":[{},"",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"location.pathname"}}]}}}}]}}}},{"component":"data2-core-primitives@Route","params":{"path":"/gv","name":"Painel GV","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"vC0Wc2AL0qIdO9XXjIIEO"}},"onEnter":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-functions@JSONParse","params":{"text":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"localStorage.getItem","args":["_d2_natura_session"]}}}},"resultName":"natura_session"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.authorization"}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.token"}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.c"}}]}},"resultName":"urlToken"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@And","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":"natura_session.token"}},{"component":"data2-core-types@Reference","params":{"reference":"natura_session.createdAt"}},{"component":"data2-core-comparison-operators@LesserThan","params":{"subject":{"component":"data2-core-functions@DateDiff","params":{"left":{"component":"data2-core-functions@DateNow","params":{}},"right":{"component":"data2-core-functions@DateParse","params":{"date":{"component":"data2-core-types@Reference","params":{"reference":"natura_session.createdAt"}}}},"period":"hours"}},"comparisonSubject":2}}]}},"resultName":"storedOk"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":"urlToken"}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"storedOk"}},"then":{"component":"data2-core-types@Reference","params":{"reference":"natura_session.token"}}}}]}},"resultName":"cookie"}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"cookie"}},"then":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotMaiaAuth"}},"prop":"logout","args":[]}},{"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotMaiaAuth"}},"prop":"loginIdentityProvider","args":[{"component":"data2-core-types@IdentityProviderReference","params":{"reference":"NlrnS53tjBMzSo2rIsfG6"}},{"component":"data2-core-types@Reference","params":{"reference":"cookie"}}]}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"localStorage.setItem","args":["_d2_natura_session",{"component":"data2-core-functions@JSONStringify","params":{"value":{"token":{"component":"data2-core-types@Reference","params":{"reference":"cookie"}},"createdAt":{"component":"data2-core-functions@DateFormat","params":{"date":{"component":"data2-core-functions@DateNow","params":{}}}}}}}]}}]}}}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"urlToken"}},"then":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"history.replaceState","args":[{},"",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"location.pathname"}}]}}}}]}}}},{"component":"data2-core-primitives@Route","params":{"path":"/gn","name":"Painel GN","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"ddQOH1XSfT4e1JwYn43J1"}},"onEnter":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-functions@JSONParse","params":{"text":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"localStorage.getItem","args":["_d2_natura_session"]}}}},"resultName":"natura_session"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.authorization"}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.token"}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.c"}}]}},"resultName":"urlToken"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@And","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":"natura_session.token"}},{"component":"data2-core-types@Reference","params":{"reference":"natura_session.createdAt"}},{"component":"data2-core-comparison-operators@LesserThan","params":{"subject":{"component":"data2-core-functions@DateDiff","params":{"left":{"component":"data2-core-functions@DateNow","params":{}},"right":{"component":"data2-core-functions@DateParse","params":{"date":{"component":"data2-core-types@Reference","params":{"reference":"natura_session.createdAt"}}}},"period":"hours"}},"comparisonSubject":2}}]}},"resultName":"storedOk"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":"urlToken"}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"storedOk"}},"then":{"component":"data2-core-types@Reference","params":{"reference":"natura_session.token"}}}}]}},"resultName":"cookie"}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"cookie"}},"then":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotMaiaAuth"}},"prop":"logout","args":[]}},{"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotMaiaAuth"}},"prop":"loginIdentityProvider","args":[{"component":"data2-core-types@IdentityProviderReference","params":{"reference":"NlrnS53tjBMzSo2rIsfG6"}},{"component":"data2-core-types@Reference","params":{"reference":"cookie"}}]}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"localStorage.setItem","args":["_d2_natura_session",{"component":"data2-core-functions@JSONStringify","params":{"value":{"token":{"component":"data2-core-types@Reference","params":{"reference":"cookie"}},"createdAt":{"component":"data2-core-functions@DateFormat","params":{"date":{"component":"data2-core-functions@DateNow","params":{}}}}}}}]}}]}}}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"urlToken"}},"then":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"history.replaceState","args":[{},"",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"location.pathname"}}]}}}}]}}}},{"component":"data2-core-primitives@Route","params":{"path":"/lider","name":"Painel Líder","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"0C6IxJ3IbamCK9_yFOCJf"}},"onEnter":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-functions@JSONParse","params":{"text":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"localStorage.getItem","args":["_d2_natura_session"]}}}},"resultName":"natura_session"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.authorization"}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.token"}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.c"}}]}},"resultName":"urlToken"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@And","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":"natura_session.token"}},{"component":"data2-core-types@Reference","params":{"reference":"natura_session.createdAt"}},{"component":"data2-core-comparison-operators@LesserThan","params":{"subject":{"component":"data2-core-functions@DateDiff","params":{"left":{"component":"data2-core-functions@DateNow","params":{}},"right":{"component":"data2-core-functions@DateParse","params":{"date":{"component":"data2-core-types@Reference","params":{"reference":"natura_session.createdAt"}}}},"period":"hours"}},"comparisonSubject":2}}]}},"resultName":"storedOk"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":"urlToken"}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"storedOk"}},"then":{"component":"data2-core-types@Reference","params":{"reference":"natura_session.token"}}}}]}},"resultName":"cookie"}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"cookie"}},"then":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotMaiaAuth"}},"prop":"logout","args":[]}},{"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotMaiaAuth"}},"prop":"loginIdentityProvider","args":[{"component":"data2-core-types@IdentityProviderReference","params":{"reference":"NlrnS53tjBMzSo2rIsfG6"}},{"component":"data2-core-types@Reference","params":{"reference":"cookie"}}]}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"localStorage.setItem","args":["_d2_natura_session",{"component":"data2-core-functions@JSONStringify","params":{"value":{"token":{"component":"data2-core-types@Reference","params":{"reference":"cookie"}},"createdAt":{"component":"data2-core-functions@DateFormat","params":{"date":{"component":"data2-core-functions@DateNow","params":{}}}}}}}]}}]}}}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"urlToken"}},"then":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"history.replaceState","args":[{},"",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"location.pathname"}}]}}}}]}}}},{"component":"data2-core-primitives@Route","params":{"path":"/simulador","name":"Simulador","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"4evX6hSMzy2KBB9RI6E60"}},"onEnter":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-functions@JSONParse","params":{"text":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"localStorage.getItem","args":["_d2_natura_session"]}}}},"resultName":"natura_session"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.authorization"}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.token"}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.c"}}]}},"resultName":"urlToken"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@And","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":"natura_session.token"}},{"component":"data2-core-types@Reference","params":{"reference":"natura_session.createdAt"}},{"component":"data2-core-comparison-operators@LesserThan","params":{"subject":{"component":"data2-core-functions@DateDiff","params":{"left":{"component":"data2-core-functions@DateNow","params":{}},"right":{"component":"data2-core-functions@DateParse","params":{"date":{"component":"data2-core-types@Reference","params":{"reference":"natura_session.createdAt"}}}},"period":"hours"}},"comparisonSubject":2}}]}},"resultName":"storedOk"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":"urlToken"}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"storedOk"}},"then":{"component":"data2-core-types@Reference","params":{"reference":"natura_session.token"}}}}]}},"resultName":"cookie"}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"cookie"}},"then":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotMaiaAuth"}},"prop":"logout","args":[]}},{"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotMaiaAuth"}},"prop":"loginIdentityProvider","args":[{"component":"data2-core-types@IdentityProviderReference","params":{"reference":"NlrnS53tjBMzSo2rIsfG6"}},{"component":"data2-core-types@Reference","params":{"reference":"cookie"}}]}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"localStorage.setItem","args":["_d2_natura_session",{"component":"data2-core-functions@JSONStringify","params":{"value":{"token":{"component":"data2-core-types@Reference","params":{"reference":"cookie"}},"createdAt":{"component":"data2-core-functions@DateFormat","params":{"date":{"component":"data2-core-functions@DateNow","params":{}}}}}}}]}}]}}}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"urlToken"}},"then":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"history.replaceState","args":[{},"",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"location.pathname"}}]}}}}]}}}},{"component":"data2-core-primitives@Route","params":{"path":"/historico","name":"Histórico","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"JXv5aElG_lM1EUbOvn1Ny"}},"onEnter":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-functions@JSONParse","params":{"text":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"localStorage.getItem","args":["_d2_natura_session"]}}}},"resultName":"natura_session"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.authorization"}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.token"}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRedesignRouterInterface"}},"prop":"routeParams.query.c"}}]}},"resultName":"urlToken"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@And","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":"natura_session.token"}},{"component":"data2-core-types@Reference","params":{"reference":"natura_session.createdAt"}},{"component":"data2-core-comparison-operators@LesserThan","params":{"subject":{"component":"data2-core-functions@DateDiff","params":{"left":{"component":"data2-core-functions@DateNow","params":{}},"right":{"component":"data2-core-functions@DateParse","params":{"date":{"component":"data2-core-types@Reference","params":{"reference":"natura_session.createdAt"}}}},"period":"hours"}},"comparisonSubject":2}}]}},"resultName":"storedOk"}},{"component":"data2-core-flow@Step","params":{"action":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":"urlToken"}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"storedOk"}},"then":{"component":"data2-core-types@Reference","params":{"reference":"natura_session.token"}}}}]}},"resultName":"cookie"}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"cookie"}},"then":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotMaiaAuth"}},"prop":"logout","args":[]}},{"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotMaiaAuth"}},"prop":"loginIdentityProvider","args":[{"component":"data2-core-types@IdentityProviderReference","params":{"reference":"NlrnS53tjBMzSo2rIsfG6"}},{"component":"data2-core-types@Reference","params":{"reference":"cookie"}}]}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"localStorage.setItem","args":["_d2_natura_session",{"component":"data2-core-functions@JSONStringify","params":{"value":{"token":{"component":"data2-core-types@Reference","params":{"reference":"cookie"}},"createdAt":{"component":"data2-core-functions@DateFormat","params":{"date":{"component":"data2-core-functions@DateNow","params":{}}}}}}}]}}]}}}},{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-types@Reference","params":{"reference":"urlToken"}},"then":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"history.replaceState","args":[{},"",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"location.pathname"}}]}}}}]}}}}],"notFound":{"component":"data2-core-types@ArtboardReference","params":{"reference":"vC0Wc2AL0qIdO9XXjIIEO"}}},"reference":"pilotRedesignRouter"},{"_id":"6a98745d784e6873cdee5f22","component":"data2-core-primitives@Artboard","system":"688179c2a93dd170ce61e598","displayName":"PILOT · Login","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"PILOT · Login"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}}},"reference":"cjloJx4TuhpyVmpq1WZzR"},{"_id":"6ad7dadd5b1be212dfbd8856","component":"data2-core-primitives@Artboard","system":"688179c2a93dd170ce61e598","displayName":"PILOT · Admin — Simular usuário","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"PILOT · Admin — Simular usuário"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":1788,"y":1100,"exactX":1788,"exactY":1100}}},"reference":"6D4KMO_WM699IGwgZocts"},{"_id":"6a4ce5a6beefcfaef4a82a0e","component":"data2-core-primitives@Artboard","system":"688179c2a93dd170ce61e598","displayName":"PILOT · Admin App (Code)","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"PILOT · Admin App (Code)"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":1100}}},"reference":"JecI-Fl9ecOnfdjb4gaI5"},{"_id":"85cfb3bf49cea0a7edb24347","parent":"6a480778e3014dd5bb6ec589","component":"natura-x-piloto@pilotSimuladorLauncher","system":"688179c2a93dd170ce61e598","displayName":"Simulador Launcher FAB","params":{"artboardRef":"bqF-UV_wLQvduQnBbVxlg","label":"Simulador","super":{"position":{"component":"data2-core-types@Position","params":{"x":1200,"y":820,"freeTransform":true,"left":false,"right":true,"top":false,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":200,"height":60}}}},"reference":"bUsRjvvJwohc6T-idNH-j"},{"_id":"9db24b9975a5bbe1a802e290","parent":"6a480778e3014dd5bb6ec589","component":"natura-x-piloto@pilotMDashboardShell","system":"688179c2a93dd170ce61e598","displayName":"M Dashboard Shell root","params":{"store":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotDashboardStore"}},"api":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotGetDashboardData"}},"topBar":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMTopBar"}},"userHeader":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMUserHeader"}},"kpiGrid":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMKpiGrid"}},"groupGrid":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMGroupGrid"}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"scroll":{"component":"data2-core-types@Scroll","params":{"y":true}}},"controls":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMControls"}}},"reference":"_8yXXGpnIjH1m5ogZS54N"},{"_id":"c8e8f4899c67c2a10c665cf0","parent":"6a480778e3014dd5bb6ec589","component":"natura-x-piloto@pilotHistoricoLauncher","system":"688179c2a93dd170ce61e598","displayName":"Histórico Launcher FAB","params":{"artboardRef":"2nDUSVL8m6TyPw1itylqZ","label":"Histórico","super":{"position":{"component":"data2-core-types@Position","params":{"x":1200,"y":748,"freeTransform":true,"left":false,"right":true,"top":false,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":200,"height":60}}}},"reference":"sA_kLXTvUdNAIsGIDwACn"},{"_id":"6a480816c03bd927a9d7a871","component":"data2-core-primitives@Artboard","system":"688179c2a93dd170ce61e598","displayName":"PILOT · Dashboard M Mobile","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"PILOT · Dashboard M Mobile"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":430,"height":932}}},"reference":"h9CDEJeATP5mABV7X-Ute"},{"_id":"6ae9e6d6734c65cf08668abd","component":"data2-core-primitives@Artboard","system":"688179c2a93dd170ce61e598","displayName":"REDESIGN · Painel GV","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"REDESIGN · Painel GV"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"vC0Wc2AL0qIdO9XXjIIEO"},{"_id":"6ae9e6dc2cab8ab5e41f6a5d","component":"data2-core-primitives@Artboard","system":"688179c2a93dd170ce61e598","displayName":"REDESIGN · Histórico","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"REDESIGN · Histórico"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"JXv5aElG_lM1EUbOvn1Ny"},{"_id":"6ae9e6da911c2172260aee32","component":"data2-core-primitives@Artboard","system":"688179c2a93dd170ce61e598","displayName":"REDESIGN · Simulador","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"REDESIGN · Simulador"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"4evX6hSMzy2KBB9RI6E60"},{"_id":"6ae9e6d916cfee0d9cc15d59","component":"data2-core-primitives@Artboard","system":"688179c2a93dd170ce61e598","displayName":"REDESIGN · Painel Líder","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"REDESIGN · Painel Líder"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"0C6IxJ3IbamCK9_yFOCJf"},{"_id":"6ae9e6d8c2e24d420cf9a408","component":"data2-core-primitives@Artboard","system":"688179c2a93dd170ce61e598","displayName":"REDESIGN · Painel GN","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"REDESIGN · Painel GN"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"ddQOH1XSfT4e1JwYn43J1"},{"_id":"54aad7e7c607cb1e9caf4a85","parent":"6a98745d784e6873cdee5f22","component":"data2-core-primitives@Block","system":"688179c2a93dd170ce61e598","displayName":"Page","params":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"#FAFAFB"}}}}]}},"font":{"component":"data2-core-web@GoogleFont","params":{"family":"Roboto","weight":"400"}}},"index":0,"reference":"XkHSBrRsXy9gg2NHshVYz"},{"_id":"e7620603c659d4a0faef729c","parent":"6ad7dadd5b1be212dfbd8856","component":"natura-x-piloto@pilotMDashboardShell","system":"688179c2a93dd170ce61e598","displayName":"Sim · M Dashboard Shell","params":{"store":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotDashboardStore"}},"api":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotGetDashboardData"}},"topBar":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMTopBar"}},"userHeader":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMUserHeader"}},"kpiGrid":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMKpiGrid"}},"groupGrid":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMGroupGrid"}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":56,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":844}},"scroll":{"component":"data2-core-types@Scroll","params":{"y":true}}},"controls":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMControls"}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":56,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":844}}},"index":0,"reference":"2qRhmSvZ3AZubfVAm_YGG"},{"_id":"83931f3b2416f48fab003dbe","parent":"6ad7dadd5b1be212dfbd8856","component":"natura-x-piloto@pilotSimPicker","system":"688179c2a93dd170ce61e598","displayName":"Sim · Picker bar","params":{"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":56}}}},"reference":"dQVMrhYqy9XvImQZWRukh"},{"_id":"1d0b3dff49daf84589c8f817","parent":"6a4ce5a6beefcfaef4a82a0e","component":"natura-x-piloto@pilotAdminApp","system":"688179c2a93dd170ce61e598","displayName":"Admin App Shell root","params":{"items":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilot-dashboard-itemDataSet"}},"kpis":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilot-kpi-definitionDataSet"}},"itemWriter":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotAdminItemWrite"}},"bands":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilot-earning-bandDataSet"}},"bonuses":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilot-bonus-ruleDataSet"}},"formulas":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilot-earning-formulaDataSet"}},"rulesets":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilot-rulesetDataSet"}},"bandTables":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilot-band-tableDataSet"}},"cycles":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilot-cycleDataSet"}},"ruleWriter":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotAdminRuleWrite"}},"audit":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilot-audit-logDataSet"}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true,"exactX":false,"exactY":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":1100}},"scroll":{"component":"data2-core-types@Scroll","params":{"y":true}}},"accessLog":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilot-access-logDataSet"}},"sessions":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilot-sessionDataSet"}},"queryLib":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilot-query-libraryDataSet"}},"queryCalendar":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilot-cycle-calendarDataSet"}},"queryWriter":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotQueryLibWrite"}},"runner":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotRunQuery"}}},"reference":"EyV14I26Wcmf8zae-EaVU"},{"_id":"97b28b16eb1c8b2aa1b67050","parent":"6a480816c03bd927a9d7a871","component":"natura-x-piloto@pilotSimuladorLauncher","system":"688179c2a93dd170ce61e598","displayName":"Simulador Launcher FAB (mobile)","params":{"artboardRef":"bqF-UV_wLQvduQnBbVxlg","label":"Simulador","super":{"position":{"component":"data2-core-types@Position","params":{"x":222,"y":860,"freeTransform":true,"left":true,"top":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":200,"height":60}}}},"index":1,"reference":"u98XJy8zO2RzH90O-VLDS"},{"_id":"9d5d543488dff6bd327c2ee7","parent":"6a480816c03bd927a9d7a871","component":"natura-x-piloto@pilotHistoricoLauncher","system":"688179c2a93dd170ce61e598","displayName":"Histórico Launcher FAB (mobile)","params":{"artboardRef":"2nDUSVL8m6TyPw1itylqZ","label":"Histórico","super":{"position":{"component":"data2-core-types@Position","params":{"x":222,"y":788,"freeTransform":true,"left":true,"top":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":200,"height":60}}}},"index":2,"reference":"dNG2DCgqhZFv-wVATkJKY"},{"_id":"3b174bf0967d6be7d80b0f10","parent":"6a480816c03bd927a9d7a871","component":"natura-x-piloto@pilotMDashboardShell","system":"688179c2a93dd170ce61e598","displayName":"M Dashboard Shell root (mobile)","params":{"store":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotDashboardStore"}},"api":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotGetDashboardData"}},"topBar":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMTopBar"}},"userHeader":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMUserHeader"}},"kpiGrid":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMKpiGrid"}},"groupGrid":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMGroupGrid"}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":430,"height":932}},"scroll":{"component":"data2-core-types@Scroll","params":{"y":true}}},"controls":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMControls"}}},"reference":"X0emPPYsyUymMU5lH50HO"},{"_id":"121e4517b6a27b8381c50e7a","parent":"6ae9e6d6734c65cf08668abd","component":"natura-x-piloto@pilotRedesignPainel","system":"688179c2a93dd170ce61e598","displayName":"Painel GV","params":{"store":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotDashboardStore"}},"api":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotGetDashboardData"}},"auth":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotMaiaAuth"}},"view":"gv","super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"scroll":{"component":"data2-core-types@Scroll","params":{"y":true}}}},"reference":"Y-XX1pu0RlmKdiN_vX6-j"},{"_id":"7521558c5f9be834afe0a831","parent":"6ae9e6d916cfee0d9cc15d59","component":"natura-x-piloto@pilotRedesignPainel","system":"688179c2a93dd170ce61e598","displayName":"Painel Líder","params":{"store":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotDashboardStore"}},"api":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotGetDashboardData"}},"auth":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotMaiaAuth"}},"view":"lider","super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"scroll":{"component":"data2-core-types@Scroll","params":{"y":true}}}},"reference":"noWPGbiUAJfhx8bgOkpSl"},{"_id":"26cf3dd9b70f335dda99456b","parent":"6ae9e6d8c2e24d420cf9a408","component":"natura-x-piloto@pilotRedesignPainel","system":"688179c2a93dd170ce61e598","displayName":"Painel GN","params":{"store":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotDashboardStore"}},"api":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotGetDashboardData"}},"auth":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotMaiaAuth"}},"view":"gn","super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"scroll":{"component":"data2-core-types@Scroll","params":{"y":true}}}},"reference":"W-OrMhjQmsDf3h6jIAaGN"},{"_id":"85385505adb5f61d36d0abdf","parent":"54aad7e7c607cb1e9caf4a85","component":"data2-core-primitives@Block","system":"688179c2a93dd170ce61e598","displayName":"Card","params":{"position":{"component":"data2-core-types@Position","params":{"x":530,"y":190,"freeTransform":true,"left":false,"right":false,"top":false,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":380,"height":520}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"#FFFFFF"}}}}]}},"border":{"component":"data2-core-types@Border","params":{"radius":{"leftTop":"16","rightTop":"16","rightBottom":"16","leftBottom":"16"},"width":{"left":"1","top":"1","right":"1","bottom":"1"},"color":"rgba(16,24,40,0.08)"}},"shadow":{"component":"data2-core-types@Shadow","params":{"x":0,"y":2,"blur":12,"spread":0,"inset":false,"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(16,24,40,0.10)"}}}}},"index":0,"reference":"-amntgH6yHtFZzH8tXqsD"},{"_id":"e5b90c9d4481f8b68533794d","parent":"85385505adb5f61d36d0abdf","component":"data2-core-primitives@Block","system":"688179c2a93dd170ce61e598","displayName":"LogoMark","params":{"position":{"component":"data2-core-types@Position","params":{"x":36,"y":36,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":34,"height":34}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"disabled":true,"component":"data2-core-types@Color","params":{"rgba":"rgba(0,0,0,1)"}},"gradient":{"disabled":false,"component":"data2-core-types@ColorGradient","params":{"type":"linear","angle":135,"colors":[{"component":"data2-core-types@ColorGradientStop","params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"#E5004B"}},"offset":"0%"}},{"component":"data2-core-types@ColorGradientStop","params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"#EB6619"}},"offset":"100%"}}]}}}}]}},"border":{"component":"data2-core-types@Border","params":{"radius":{"leftTop":"10","rightTop":"10","rightBottom":"10","leftBottom":"10"},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"text":"A","textColor":{"component":"data2-core-types@Color","params":{"rgba":"#FFFFFF"}},"textSize":16,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":"800","horizontalAlignment":"center","verticalAlignment":"middle"}}},"index":0,"reference":"L5LlKkyQoHRZDbN9bR_is"},{"_id":"15cab3e1cb682a38167adb34","parent":"85385505adb5f61d36d0abdf","component":"data2-core-primitives@Block","system":"688179c2a93dd170ce61e598","displayName":"BrandName","params":{"position":{"component":"data2-core-types@Position","params":{"x":82,"y":38,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":226,"height":18}},"text":"Administração","textColor":{"component":"data2-core-types@Color","params":{"rgba":"#1A1C1E"}},"textSize":15,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":"800","verticalAlignment":"middle"}}},"index":1,"reference":"T_OK_GjBm-Kg9mRyqjbny"},{"_id":"371c246ee2ebcb3f1c0cf952","parent":"85385505adb5f61d36d0abdf","component":"data2-core-primitives@Block","system":"688179c2a93dd170ce61e598","displayName":"BrandSub","params":{"position":{"component":"data2-core-types@Position","params":{"x":82,"y":57,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":226,"height":14}},"text":"PAINEL DE REMUNERAÇÃO","textColor":{"component":"data2-core-types@Color","params":{"rgba":"#6B7280"}},"textSize":10,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":"600","verticalAlignment":"middle"}}},"index":2,"reference":"j7ANU8qQH9rGl7QU0fu0R"},{"_id":"bf6e04f6775a400fd49b2e8c","parent":"85385505adb5f61d36d0abdf","component":"data2-core-primitives@Block","system":"688179c2a93dd170ce61e598","displayName":"Title","params":{"position":{"component":"data2-core-types@Position","params":{"x":36,"y":110,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":308,"height":36}},"text":"Entrar","textColor":{"component":"data2-core-types@Color","params":{"rgba":"#1A1C1E"}},"textSize":28,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":"800","verticalAlignment":"middle"}}},"index":3,"reference":"ldyjAfqM_gNuyGMJjKE8Q"},{"_id":"1516d66201348eeeef0c76f7","parent":"85385505adb5f61d36d0abdf","component":"data2-core-primitives@Block","system":"688179c2a93dd170ce61e598","displayName":"Subtitle","params":{"position":{"component":"data2-core-types@Position","params":{"x":36,"y":150,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":308,"height":34,"growHeightWithContent":false}},"text":"Use suas credenciais de administrador do piloto.","textColor":{"component":"data2-core-types@Color","params":{"rgba":"#6B7280"}},"textSize":13,"wordWrap":true},"index":4,"reference":"rEBs2LdG3i7OdKhotlujG"},{"_id":"898fee214f5d571f77f4ba5a","parent":"85385505adb5f61d36d0abdf","component":"data2-core-primitives@Block","system":"688179c2a93dd170ce61e598","displayName":"LabelEmail","params":{"position":{"component":"data2-core-types@Position","params":{"x":36,"y":202,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":308,"height":14}},"text":"E-MAIL","textColor":{"component":"data2-core-types@Color","params":{"rgba":"#6B7280"}},"textSize":10,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":"700","verticalAlignment":"middle"}}},"index":5,"reference":"uguC-PusS_Gc8NR5z-oFN"},{"_id":"e9291ef4e5d44bf24136f44d","parent":"85385505adb5f61d36d0abdf","component":"data2-blocks@DataFieldBlock","system":"688179c2a93dd170ce61e598","displayName":"EmailField","params":{"padding":{"left":14,"right":14},"placeholder":"seu.email@natura.com.br","type":"email","autoComplete":"username","dataset":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotAdminAuth"}},"field":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"credentials.email"}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":36,"y":220,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":308,"height":44}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"#FFFFFF"}}}}]}},"border":{"component":"data2-core-types@Border","params":{"radius":{"leftTop":"10","rightTop":"10","rightBottom":"10","leftBottom":"10"},"width":{"left":"1","top":"1","right":"1","bottom":"1"},"color":"rgba(16,24,40,0.16)"}},"textColor":{"component":"data2-core-types@Color","params":{"rgba":"#1A1C1E"}},"textSize":14}},"index":6,"reference":"pPhPZwHc-6zVZla1wRg5d"},{"_id":"127131131e9c5e4b4a2d2cb6","parent":"85385505adb5f61d36d0abdf","component":"data2-core-primitives@Block","system":"688179c2a93dd170ce61e598","displayName":"LabelPassword","params":{"position":{"component":"data2-core-types@Position","params":{"x":36,"y":282,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":308,"height":14}},"text":"SENHA","textColor":{"component":"data2-core-types@Color","params":{"rgba":"#6B7280"}},"textSize":10,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":"700","verticalAlignment":"middle"}}},"index":7,"reference":"uCmDzlHCJvsNRfXro28hp"},{"_id":"eb3717b56a5ee9483db4aa9a","parent":"85385505adb5f61d36d0abdf","component":"data2-blocks@DataFieldBlock","system":"688179c2a93dd170ce61e598","displayName":"PasswordField","params":{"padding":{"left":14,"right":14},"placeholder":"••••••••","type":"password","autoComplete":"current-password","dataset":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotAdminAuth"}},"onEnter":{"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotAdminAuth"}},"prop":"login","args":{}}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":36,"y":300,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":308,"height":44}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"#FFFFFF"}}}}]}},"border":{"component":"data2-core-types@Border","params":{"radius":{"leftTop":"10","rightTop":"10","rightBottom":"10","leftBottom":"10"},"width":{"left":"1","top":"1","right":"1","bottom":"1"},"color":"rgba(16,24,40,0.16)"}},"textColor":{"component":"data2-core-types@Color","params":{"rgba":"#1A1C1E"}},"textSize":14},"field":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"credentials.password"}}},"index":8,"reference":"IxPHVSog1TvhQbxhcF3xe"},{"_id":"ca7ba2b63fba353bf5c53a7b","parent":"85385505adb5f61d36d0abdf","component":"data2-core-primitives@Block","system":"688179c2a93dd170ce61e598","displayName":"SubmitButton","params":{"position":{"component":"data2-core-types@Position","params":{"x":36,"y":368,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":308,"height":48}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"disabled":true,"component":"data2-core-types@Color","params":{"rgba":"rgba(0,0,0,1)"}},"gradient":{"disabled":false,"component":"data2-core-types@ColorGradient","params":{"type":"linear","angle":135,"colors":[{"component":"data2-core-types@ColorGradientStop","params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"#E5004B"}},"offset":"0%"}},{"component":"data2-core-types@ColorGradientStop","params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"#EB6619"}},"offset":"100%"}}]}}}}]}},"border":{"component":"data2-core-types@Border","params":{"radius":{"leftTop":"12","rightTop":"12","rightBottom":"12","leftBottom":"12"},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"text":"Entrar","textColor":{"component":"data2-core-types@Color","params":{"rgba":"#FFFFFF"}},"textSize":15,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":"700","horizontalAlignment":"center","verticalAlignment":"middle"}},"cursor":"pointer","preventUserSelection":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"accessibilityRole":"button","accessibilityLabel":"Entrar na administração do painel","onClick":{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotAdminAuth"}},"prop":"login"},"component":"data2-core-types@Interaction"}},"index":9,"reference":"E76GYWzchxjBcyaIGywWf"},{"_id":"be3a748b4f58a10d1ec21f4a","parent":"85385505adb5f61d36d0abdf","component":"data2-core-primitives@Block","system":"688179c2a93dd170ce61e598","displayName":"ErrorText","params":{"position":{"component":"data2-core-types@Position","params":{"x":36,"y":428,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":308,"height":32}},"text":"E-mail ou senha inválidos.","textColor":{"component":"data2-core-types@Color","params":{"rgba":"#FF1418"}},"textSize":12,"textFormat":{"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","verticalAlignment":"middle"}},"accessibilityRole":"alert","hide":{"component":"data2-core-logical-operators@Not","params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"SessionsDataSet"}},"prop":"interactionError"}}}}},"index":10,"reference":"SvD-iHGP6r0WbrnoCzjlE"},{"_id":"91fd3bda96510a2dd6661f27","parent":"85385505adb5f61d36d0abdf","component":"data2-core-primitives@Block","system":"688179c2a93dd170ce61e598","displayName":"Footnote","params":{"position":{"component":"data2-core-types@Position","params":{"x":36,"y":470,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":308,"height":16}},"text":"Acesso restrito · piloto Natura","textColor":{"component":"data2-core-types@Color","params":{"rgba":"#6B7280"}},"textSize":11,"textFormat":{"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","verticalAlignment":"middle"}}},"index":11,"reference":"pw_n8vzN2eT2SbQ77AIvQ"}]}},{"_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":"6ae9e73bd79019a0ae2240ab","displayName":"REDESIGN · Painel do piloto","reference":"HYdD8TCQ52KcgAOdPFRwM","params":{"domain":{"component":"data2-core-primitives@String","params":{"content":"piloto-redesign"}},"entryPoint":{"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Router","reference":"pilotRedesignRouter"}},"onBeforeSessions":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-logical-operators@And","params":{"components":[{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-functions@Includes","params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"location.search"}},"pattern":"authorization="}},{"component":"data2-core-functions@Includes","params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"location.search"}},"pattern":"token="}},{"component":"data2-core-functions@Includes","params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"location.search"}},"pattern":"?c="}},{"component":"data2-core-functions@Includes","params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"location.search"}},"pattern":"&c="}}]}},{"component":"data2-core-comparison-operators@GreaterThan","params":{"subject":{"component":"data2-core-numerical-operators@Subtract","params":{"components":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"Date.now","args":[]}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"sessionStorage.getItem","args":["_d2_reset_at"]}}]}},"comparisonSubject":60000}}]}},"then":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"sessionStorage.setItem","args":["_d2_reset_at",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"Date.now","args":[]}}]}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"localStorage.removeItem","args":["__data2-session-natura-x-piloto"]}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"localStorage.removeItem","args":["_d2_natura_session"]}},{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-web@Window","params":{}},"prop":"location.reload","args":[]}}]}}}}]}}},"system":"688179c2a93dd170ce61e598","component":"data2-core-primitives@Application"}]}},{"reference":"DataComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a47f2d8daa510066787ecf9","component":"data2-core@Store","system":"688179c2a93dd170ce61e598","params":{"initialData":{"perfil":"gv","gvName":"PAINEIRA-ROSA","rede":"rede1","structureCode":"3253","cycle":"202610","loading":false,"data":null,"selectedGroup":""}},"reference":"pilotDashboardStore"},{"_id":"6a9872577a1e0417d6475674","component":"data2-core@AuthenticationStrategy","system":"688179c2a93dd170ce61e598","params":{"credentials":[{"component":"data2-core-types@FieldReference","params":{"key":"email"}},{"component":"data2-core-types@FieldReference","params":{"key":"password"}}],"verifier":{"component":"data2-core-types@DataSetReference","params":{"reference":"pilot-admin-userDataSet"}},"email":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},"password":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}}},"reference":"pilotAdminAuth"},{"_id":"6a47dcfba3e194e598412562","component":"data2-core@DataSet","system":"688179c2a93dd170ce61e598","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"pilot-cycle"}}},"reference":"pilot-cycleDataSet"},{"_id":"6a4d49c22daf06e6ec4fea6c","component":"data2-core@DataSet","system":"688179c2a93dd170ce61e598","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"pilot-session"}}},"reference":"pilot-sessionDataSet"},{"_id":"6a47dd2a1ecc4fa972d77a94","component":"data2-core@DataSet","system":"688179c2a93dd170ce61e598","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"pilot-access-log"}}},"reference":"pilot-access-logDataSet"},{"_id":"6a987243ef8f14e4f9d65a3e","component":"data2-core@DataSet","system":"688179c2a93dd170ce61e598","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"pilot-admin-user"}}},"reference":"pilot-admin-userDataSet"},{"_id":"6a47dcfa1ecc4fa972d779c8","component":"data2-core@Data2TableDataSource","system":"688179c2a93dd170ce61e598","params":{"table":"pilot-cycle","schema":[{"component":"data2-core-types@Field","params":{"key":"code","title":"code (required, e.g. 202605)","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"label","title":"label","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"status","title":"status (enum: open,closed)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"isCurrent","title":"isCurrent","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"rulesetVersion","title":"rulesetVersion (FK -> pilot-ruleset.version)","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"dashboardConfigVersion","title":"dashboardConfigVersion (FK -> pilot-dashboard-config.version)","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"startsAt","title":"startsAt","component":"data2-core-primitives@Date"}},{"component":"data2-core-types@Field","params":{"key":"endsAt","title":"endsAt","component":"data2-core-primitives@Date"}},{"component":"data2-core-types@Field","params":{"key":"redeSnapshot","title":"Rede por setor no fechamento","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"key":"frozenAt","title":"Congelado em","component":"data2-core-primitives@Number"}}]},"reference":"pilot-cycle"},{"_id":"6a4d49c2a0b8f894aacff333","component":"data2-core@Data2TableDataSource","system":"688179c2a93dd170ce61e598","params":{"table":"pilot-session","schema":[{"component":"data2-core-types@Field","params":{"key":"sessionId","title":"sessionId","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"userId","title":"userId","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"name","title":"name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"perfil","title":"perfil (lider/gn/gv/admin)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"mode","title":"mode (session/idp/token/impersonation)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"structureCode","title":"structureCode","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"sectorCode","title":"sectorCode","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"rede","title":"rede","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"gvName","title":"gvName","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"cycle","title":"cycle","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"entryMode","title":"entryMode (identity mode at login)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"referrer","title":"referrer","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"userAgent","title":"userAgent","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"ip","title":"ip (captured server-side)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"startedAt","title":"startedAt","component":"data2-core-primitives@Date"}},{"component":"data2-core-types@Field","params":{"key":"lastSeenAt","title":"lastSeenAt","component":"data2-core-primitives@Date"}},{"component":"data2-core-types@Field","params":{"key":"endedAt","title":"endedAt","component":"data2-core-primitives@Date"}},{"component":"data2-core-types@Field","params":{"key":"status","title":"status (active/ended)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"viewCount","title":"viewCount","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"lastSection","title":"lastSection","component":"data2-core-primitives@String"}}]},"reference":"pilot-session"},{"_id":"6a47dd2aa3e194e59841261f","component":"data2-core@Data2TableDataSource","system":"688179c2a93dd170ce61e598","params":{"table":"pilot-access-log","schema":[{"component":"data2-core-types@Field","params":{"key":"actorEmail","title":"actorEmail","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"actualPerfil","title":"actualPerfil","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"effectivePerfil","title":"effectivePerfil","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"impersonatedCode","title":"impersonatedCode (optional)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"action","title":"action (enum: view,simulate,impersonate-start,export)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"structureCode","title":"structureCode","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"cycle","title":"cycle (cycle code)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"at","title":"at","component":"data2-core-primitives@Date"}},{"component":"data2-core-types@Field","params":{"key":"actorUserId","title":"actorUserId","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"actorName","title":"actorName","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"actorPerfil","title":"actorPerfil","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"targetUserId","title":"targetUserId","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"targetName","title":"targetName","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"targetPerfil","title":"targetPerfil","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"scope","title":"scope (any/within-sector)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"sessionId","title":"sessionId","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"mode","title":"mode (session/idp/token/impersonation)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"userId","title":"userId","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"name","title":"name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"perfil","title":"perfil","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"sectorCode","title":"sectorCode","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"rede","title":"rede","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"gvName","title":"gvName","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"section","title":"section (view target)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"drillLevel","title":"drillLevel","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"userAgent","title":"userAgent","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"ip","title":"ip (server-side)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"referrer","title":"referrer","component":"data2-core-primitives@String"}}]},"reference":"pilot-access-log"},{"_id":"68a700f20fd5d1c3c270b0e7","component":"data2-core-id@IdentityProvider","system":"688179c2a93dd170ce61e598","params":{},"reference":"NlrnS53tjBMzSo2rIsfG6"},{"_id":"6a64256e665f2da2cacda356","component":"data2-core@AuthenticationStrategy","system":"688179c2a93dd170ce61e598","params":{"credentials":[{"key":"email"},{"key":"password"}],"verifier":{"component":"data2-core-types@DataSetReference","params":{"reference":"pilot-userDataSet"}},"email":"email","password":"password","identityProviders":[{"component":"data2-core-id@ProviderAuthenticationSettings","params":{"identityProvider":{"disabled":false,"component":"data2-core-types@IdentityProviderReference","params":{"reference":"NlrnS53tjBMzSo2rIsfG6"}},"providerField":{"disabled":false,"component":"data2-core-types@FieldReference","params":{"key":"cookie"},"break":true},"allowSignup":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"omitSessionToken":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"shouldForwardErrors":{"component":"data2-core-primitives@Boolean","params":{"content":true}}}}],"sessionExpiresIn":21600},"reference":"pilotMaiaAuth"},{"_id":"6a9872438afd1f89835cf2e1","component":"data2-core@Data2TableDataSource","system":"688179c2a93dd170ce61e598","params":{"table":"pilot-admin-user","schema":[{"component":"data2-core-types@Field","params":{"key":"email","title":"email (required) — identificador de login","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"password","title":"password","component":"data2-core-types@Password"}},{"component":"data2-core-types@Field","params":{"key":"name","title":"name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"pilotUserEmail","title":"pilotUserEmail (vínculo com PILOT · user; vazio = usa o próprio email)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"active","title":"active","component":"data2-core-primitives@Boolean"}}]},"reference":"pilot-admin-user"},{"_id":"6a47dd1cea22d868558c0688","component":"data2-core@DataSet","system":"688179c2a93dd170ce61e598","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"pilot-user"}}},"reference":"pilot-userDataSet"},{"_id":"6a4d664aef24ea5fd74aad96","component":"data2-core@DataSet","system":"688179c2a93dd170ce61e598","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"pilot-cycle-calendar"}}},"reference":"pilot-cycle-calendarDataSet"},{"_id":"6a4d65bc72e86abc5f0fc47b","component":"data2-core@DataSet","system":"688179c2a93dd170ce61e598","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"pilot-query-library"}}},"reference":"pilot-query-libraryDataSet"},{"_id":"6a47dd2a9c748d97fd55eb88","component":"data2-core@DataSet","system":"688179c2a93dd170ce61e598","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"pilot-audit-log"}}},"reference":"pilot-audit-logDataSet"},{"_id":"6a4c3f906c020b3085c07187","component":"data2-core@DataSet","system":"688179c2a93dd170ce61e598","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"pilot-band-table"}}},"reference":"pilot-band-tableDataSet"},{"_id":"6a47dcf123ea82ec61fb2c2a","component":"data2-core@DataSet","system":"688179c2a93dd170ce61e598","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"pilot-ruleset"}}},"reference":"pilot-rulesetDataSet"},{"_id":"6a47dd0de3014dd5bb6e1214","component":"data2-core@DataSet","system":"688179c2a93dd170ce61e598","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"pilot-earning-formula"}}},"reference":"pilot-earning-formulaDataSet"},{"_id":"6a47dd0fb0a857d0aa630a99","component":"data2-core@DataSet","system":"688179c2a93dd170ce61e598","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"pilot-bonus-rule"}}},"reference":"pilot-bonus-ruleDataSet"},{"_id":"6a47dd0a1d5442d873f6fbf0","component":"data2-core@DataSet","system":"688179c2a93dd170ce61e598","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"pilot-earning-band"}}},"reference":"pilot-earning-bandDataSet"},{"_id":"6a47dd06bf38d38281553462","component":"data2-core@DataSet","system":"688179c2a93dd170ce61e598","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"pilot-kpi-definition"}}},"reference":"pilot-kpi-definitionDataSet"},{"_id":"6a47dd17a3e194e5984125b6","component":"data2-core@DataSet","system":"688179c2a93dd170ce61e598","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"pilot-dashboard-item"}}},"reference":"pilot-dashboard-itemDataSet"},{"_id":"6a47dd1c23ea82ec61fb2cec","component":"data2-core@Data2TableDataSource","system":"688179c2a93dd170ce61e598","params":{"table":"pilot-user","schema":[{"component":"data2-core-types@Field","params":{"key":"email","title":"email (required)","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"name","title":"name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"perfil","title":"perfil (enum: lider,gn,gv,admin)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"scopeStructureCode","title":"scopeStructureCode","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"active","title":"active","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"structureCode","title":"structureCode (GV code / GN sectorCode / Líder groupCode)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"sectorCode","title":"sectorCode (parent sector for scope)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"rede","title":"rede (rede1/rede2)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"nivel","title":"nivel (leader nivel)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"gvName","title":"gvName (GV grouping)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"naturaId","title":"naturaId (person id do SSO Natura — casa com getProviderId data.me._id do IdP maia)","component":"data2-core-primitives@String"}}]},"reference":"pilot-user"},{"_id":"6a4d664aab36156bc1fecb3c","component":"data2-core@Data2TableDataSource","system":"688179c2a93dd170ce61e598","params":{"table":"pilot-cycle-calendar","schema":[{"component":"data2-core-types@Field","params":{"key":"cycle","title":"cycle (=nm_ciclo_operacional)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"sectorCode","title":"sectorCode (=cd_setor)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"groupCode","title":"groupCode (=cd_grupo)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"startDate","title":"startDate (=dt_inicio_ciclo)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"endDate","title":"endDate (=dt_termino_ciclo)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"gerencia","title":"gerencia (cd_gerencia_venda source)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"source","title":"source (live|seeded-fallback)","component":"data2-core-primitives@String"}}]},"reference":"pilot-cycle-calendar"},{"_id":"6a4d65bc937c6c0b63b2d991","component":"data2-core@Data2TableDataSource","system":"688179c2a93dd170ce61e598","params":{"table":"pilot-query-library","schema":[{"component":"data2-core-types@Field","params":{"key":"name","title":"name","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"description","title":"description","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"sql","title":"sql (with {{param}})","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"variables","title":"variables (array of names)","component":"data2-core-primitives@Array"}},{"component":"data2-core-types@Field","params":{"key":"active","title":"active","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"dataset","title":"dataset","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"strategy","title":"strategy (cache | oneTimeCycle; vazio = não roda no scheduler)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"lastExecutedAt","title":"lastExecutedAt","component":"data2-core-primitives@Date"}}]},"reference":"pilot-query-library"},{"_id":"6a47dd2a1ecc4fa972d77a99","component":"data2-core@Data2TableDataSource","system":"688179c2a93dd170ce61e598","params":{"table":"pilot-audit-log","schema":[{"component":"data2-core-types@Field","params":{"key":"actorEmail","title":"actorEmail","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"actorPerfil","title":"actorPerfil","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"action","title":"action (enum: create,update,delete)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"entityType","title":"entityType","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"entityId","title":"entityId","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"changes","title":"changes","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"key":"at","title":"at","component":"data2-core-primitives@Date"}}]},"reference":"pilot-audit-log"},{"_id":"6a4c3f8f53a8d089aac600b8","component":"data2-core@Data2TableDataSource","system":"688179c2a93dd170ce61e598","params":{"table":"pilot-band-table","schema":[{"component":"data2-core-types@Field","params":{"key":"ref","title":"ref (bandTable slug, unique key)","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"label","title":"label (human display name)","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"kpiCode","title":"kpiCode (FK -> pilot-kpi-definition.code)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"rede","title":"rede (enum: rede1,rede2)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"perfil","title":"perfil (enum: lider,gn)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"valueType","title":"valueType (enum: fixed,multiplier)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"displayOrder","title":"displayOrder (number)","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"active","title":"active (bool)","component":"data2-core-primitives@Boolean"}}]},"reference":"pilot-band-table"},{"_id":"6a47dcf1b0a857d0aa6309e9","component":"data2-core@Data2TableDataSource","system":"688179c2a93dd170ce61e598","params":{"table":"pilot-ruleset","schema":[{"component":"data2-core-types@Field","params":{"key":"version","title":"version (required)","component":"data2-core-primitives@Number","required":true}},{"component":"data2-core-types@Field","params":{"key":"label","title":"label","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"status","title":"status (enum: draft,active,archived)","component":"data2-core-primitives@String"}}]},"reference":"pilot-ruleset"},{"_id":"6a47dd0c9c748d97fd55eaec","component":"data2-core@Data2TableDataSource","system":"688179c2a93dd170ce61e598","params":{"table":"pilot-earning-formula","schema":[{"component":"data2-core-types@Field","params":{"key":"rulesetVersion","title":"rulesetVersion (FK -> pilot-ruleset.version)","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"perfil","title":"perfil (enum: lider,gn)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"rede","title":"rede (enum: rede1,rede2)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"template","title":"template ({{placeholder}} expression)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"structure","title":"structure (sum-of-products chip formula)","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"key":"structureV2","title":"structureV2 (schema 2: parcelas[] {id,label,factors[{kind:band|metric|const, table, input, metric, n, op}], gate{all[]}, clamp{min,max}}, rounding)","component":"data2-core-primitives@Object"}}]},"reference":"pilot-earning-formula"},{"_id":"6a47dd0fe3014dd5bb6e1224","component":"data2-core@Data2TableDataSource","system":"688179c2a93dd170ce61e598","params":{"table":"pilot-bonus-rule","schema":[{"component":"data2-core-types@Field","params":{"key":"rulesetVersion","title":"rulesetVersion (FK -> pilot-ruleset.version)","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"perfil","title":"perfil (enum: lider,gn)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"rede","title":"rede (enum: rede1,rede2)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"bonusType","title":"bonusType (enum: migradas-ouro,ambas-marcas)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"amount","title":"amount","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"basis","title":"basis (enum: per-unit,flat)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"label","title":"label (human name)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"conditions","title":"conditions [{kpiCode, metric, op, threshold}]","component":"data2-core-primitives@Array"}},{"component":"data2-core-types@Field","params":{"key":"payoutType","title":"payoutType (enum: flat,per-unit)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"payoutValue","title":"payoutValue (flat total OR per-unit rate)","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"perUnitKpiCode","title":"perUnitKpiCode (KPI whose count multiplies rate)","component":"data2-core-primitives@String"}}]},"reference":"pilot-bonus-rule"},{"_id":"6a47dd0ad135f62a64eec215","component":"data2-core@Data2TableDataSource","system":"688179c2a93dd170ce61e598","params":{"table":"pilot-earning-band","schema":[{"component":"data2-core-types@Field","params":{"key":"rulesetVersion","title":"rulesetVersion (FK -> pilot-ruleset.version)","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"bandTable","title":"bandTable (enum: atingimento,ativas-total,pontos,saldo-positivo,saldo-negativo,multiplicador)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"rede","title":"rede (enum: rede1,rede2)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"nivel","title":"nivel (enum: prata,ouro,diamante, optional)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"brand","title":"brand (enum: natura,avon,total)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"minPct","title":"minPct","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"maxPct","title":"maxPct","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"value","title":"value","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"bandTableRef","title":"bandTableRef (FK -> pilot-band-table.ref, backfilled)","component":"data2-core-primitives@String"}}]},"reference":"pilot-earning-band"},{"_id":"6a47dd06b0a857d0aa630a6b","component":"data2-core@Data2TableDataSource","system":"688179c2a93dd170ce61e598","params":{"table":"pilot-kpi-definition","schema":[{"component":"data2-core-types@Field","params":{"key":"code","title":"code (required, external index code)","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"name","title":"name (required)","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"brand","title":"brand (enum: natura,avon,total)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"hasGoal","title":"hasGoal","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"sourceGrain","title":"sourceGrain (enum: sector,group — where the API serves this KPI)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"aggregation","title":"aggregation (enum: sum,avg,none — group->sector rollup)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"label","title":"label (display label on card)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"icon","title":"icon (icon id: brand-natura,brand-avon,people,target,crown,swap,user-add,coins,user)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"goalKey","title":"goalKey (goals-response key, null=value-only)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"valueKey","title":"valueKey (kpis-response indexCode key)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"agrupamento","title":"agrupamento (ranking-stat,acelerador,indicador-iap)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"isBonus","title":"isBonus (yes/no willReceive indicator)","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"section","title":"section (leader-card,sector-kpi)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"rede","title":"rede (rede1,rede2,both)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"perfil","title":"perfil (gn,lider,gv,all)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"displayOrder","title":"displayOrder (number)","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"visible","title":"visible (bool)","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"description","title":"description (long human-friendly explanation)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"iap","title":"iap (indicador de acompanhamento de performance flag)","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"source","title":"source (enum: performance-api,databricks-query — default performance-api)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"apiIndexCode","title":"apiIndexCode (Performance API index code the KPI maps to; backfill=code)","component":"data2-core-primitives@String"}}]},"reference":"pilot-kpi-definition"},{"_id":"6a47dd17daa5100667879477","component":"data2-core@Data2TableDataSource","system":"688179c2a93dd170ce61e598","params":{"table":"pilot-dashboard-item","schema":[{"component":"data2-core-types@Field","params":{"key":"dashboardConfigVersion","title":"dashboardConfigVersion (FK -> pilot-dashboard-config.version)","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"perfil","title":"perfil (enum: lider,gn,gv)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"rede","title":"rede (enum: rede1,rede2)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"kpiCode","title":"kpiCode (FK -> pilot-kpi-definition.code)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"title","title":"title","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"section","title":"section","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"displayOrder","title":"displayOrder","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"icon","title":"icon","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"color","title":"color","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"showsGain","title":"showsGain","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"visible","title":"visible","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"ref","title":"ref (stable item id, e.g. sector-ativas-por-marca)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"label","title":"label (accordion line label)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"agrupamento","title":"agrupamento (acelerador|indicador-iap|ranking-stat)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"mainKpiCode","title":"mainKpiCode (FK -> pilot-kpi-definition.code — the collapsed MAIN kpi)","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"relatedKpiCodes","title":"relatedKpiCodes (array of FK codes — the expanded DETALHES sub-cards)","component":"data2-core-primitives@Array"}},{"component":"data2-core-types@Field","params":{"key":"isBonus","title":"isBonus (bool — bonus item shows Vai receber/Nao atingido chip, no R$)","component":"data2-core-primitives@Boolean"}}]},"reference":"pilot-dashboard-item"}]}},{"reference":"BundlesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}}],"processesParams":{}}}}