{"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 (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      <button class=\"iconbtn menu\" aria-label=\"menu\">☰</button>\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    d2.on('.menu','click',()=>d2.emit('onMenu'));\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 inner = brandRows + bonusRows + accRows;\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:18px;box-sizing:border-box;height:100%;display:flex}\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-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  @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 (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"}}}}}}}}}},{"_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  }, { 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(340px,1fr));gap:20px;align-items:stretch;overflow:visible;padding:16px 16px 20px}\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, with closed-cycle\n    // fallback. The calendar cycle containing \"today\" may be OPEN (in fechamento /\n    // no live data) → we fall back to the latest CLOSED cycle and surface a note.\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.cycle){\n          cycle = String(rb.cycle);\n          store.set('cycle', cycle);\n          store.set('displayCycleNote', rb.isFallback ? (rb.note || '') : '');\n          store.set('displayCycleFallback', !!rb.isFallback);\n          store.set('calendarCycle', rb.calendarCycle || '');\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    const urlToken = q.get('authorization') || q.get('token') || q.get('c');\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  // ── 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        }\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    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 — small \"ciclo em fechamento\" chip shown in the header when the current\n// calendar cycle is still open and we're displaying the latest closed cycle.\nfunction fechamentoChip(d2){\n  const store = d2.store('pilotDashboardStore');\n  if(!store || !store.get('displayCycleFallback', false)) return '';\n  const note = store.get('displayCycleNote', '') || 'Ciclo em fechamento';\n  return `<div class=\"pil-fechamento\" title=\"${escH(note)}\">\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\">${escH(note)}</span>\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.\nfunction impBar(d2){\n  const store = d2.store('pilotDashboardStore');\n  const mode = resolveMode(d2);\n  if(mode === 'token') return ''; // App B — hide 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    };\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  .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(340px,1fr));gap:20px;align-items:stretch;overflow:visible;padding:16px 16px 20px}\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          <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        }, { 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    // 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:center;gap:8px}\n  .it-lbl{font:600 15px/1.2 'Roboto',sans-serif;color:#1A1C1E;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\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 (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\nconst GLYPH = {\n  'brand-natura':'🌸','brand-avon':'💧','people':'👥','target':'🎯','crown':'👑',\n  'swap':'🔁','user-add':'➕','coins':'🪙','user':'👤'\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    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         font-size:20px;background:var(--ground)}\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 = GLYPH[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};\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.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>${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)}\">${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\">${isNew?'✨':'✎'}</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.\n// Both Líder and GN exist in BOTH redes (rede1 and rede2) with different calcs; the previous\n// forced perfil→rede mapping was wrong and hid valid combinations (e.g. GN·Rede1, Líder·Rede2).\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']];\n// Secondary bands filter no longer carries a Rede axis — Rede is now a primary independent dimension.\nconst REDE_SEG = [['all','Todas'],['rede1','Rede 1'],['rede2','Rede 2']];\nconst NIVEL_SEG = [['all','Todos'],['diamante','Diamante'],['ouro','Ouro'],['prata','Prata']];\nconst BRAND_SEG = [['all','Todas'],['natura','Natura'],['avon','Avon'],['','Total']];\nconst TABLE_SEG = [['all','Todas'],['ativas-total','Ativas'],['atingimento','Ating.'],['pontos','Pontos'],['atingimento-faturamento','Fat.']];\nconst STATUS_SEG = [['draft','Rascunho'],['active','Ativo'],['archived','Arquivado']];\nconst STATUS_LABEL = { draft:'Rascunho', active:'Ativo', archived:'Arquivado' };\nconst TABLE_LABEL = {'ativas-total':'Ativas Totais','atingimento':'Atingimento','pontos':'Pontos','saldo-positivo':'Saldo Positivo','saldo-negativo':'Saldo Negativo','multiplicador':'Multiplicador','atingimento-faturamento':'Atingimento Faturamento'};\nconst VALUETYPE_SEG = [['fixed','R$ fixo'],['multiplier','% multiplicador']];\nconst VT_LABEL = { fixed:'R$ fixo', multiplier:'% multiplicador' };\n\nfunction btByRef(bandTables){ const m={}; (bandTables||[]).forEach(t=>{ m[t.ref]=t; }); return m; }\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\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: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  .rsbar{margin-left:auto;display:flex;align-items:center;gap:12px;background:var(--ground);border:1px solid var(--hair);border-radius:14px;padding:10px 14px}\n  .rsbar .v{font:800 15px/1 var(--fam);color:var(--ink)}\n  .rsbar .lbl{font:500 12px/1.2 var(--fam);color:var(--muted);max-width:240px}\n  .rspick{display:flex;flex-direction:column;gap:4px}\n  .rspick .rslbl{font:600 10px/1 var(--fam);color:var(--muted);text-transform:uppercase;letter-spacing:.06em}\n  .rspick select{border:1.5px solid var(--hair);border-radius:9px;background:var(--surface);color:var(--ink);font:700 13px/1 var(--fam);padding:8px 10px;outline:none;cursor:pointer;max-width:320px;transition:border-color .15s}\n  .rspick select:focus{border-color:var(--mag)}\n  .rschip{font:700 10px/1 var(--fam);letter-spacing:.04em;text-transform:uppercase;padding:5px 9px;border-radius:999px;color:#fff}\n  .rschip.active{background:var(--money)}\n  .rschip.draft{background:var(--muted)}\n  .rschip.archived{background:#8a5cff}\n  .rsstatus{display:inline-flex;background:var(--surface);border-radius:9px;padding:3px;gap:2px;border:1px solid var(--hair)}\n  .rsstatus button{border:none;background:none;padding:6px 10px;border-radius:7px;font:700 11px/1 var(--fam);color:var(--muted);cursor:pointer;transition:background .15s,color .15s}\n  .rsstatus button.on{color:#fff}\n  .rsstatus button.on[data-val=\"active\"]{background:var(--money)}\n  .rsstatus button.on[data-val=\"draft\"]{background:var(--muted)}\n  .rsstatus button.on[data-val=\"archived\"]{background:#8a5cff}\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:9px 16px;border:none;border-radius:10px;background:var(--grad);\n    color:#fff;font:700 12px/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  .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  .meta .hint{margin-left:auto;font:500 11px/1.3 var(--fam);color:var(--muted);opacity:.85;max-width:520px;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:16px 30px 64px}\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 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;\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  .mfoot .delside{margin-right:auto}\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 = bandsDs ? bandsDs.records() : [];\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;\n    const tab = d2.state.tab || 'bands';\n    const perfil = d2.state.perfil || 'lider';\n    const rede = d2.state.rede || 'rede1';\n    const f = d2.state.filter || {bandTable:'all',nivel:'all',brand:'all'};\n    const rsSorted = rulesets.slice().sort((a,b)=>(Number(a.version)||0)-(Number(b.version)||0));\n    const defaultRs = rsSorted.find(r=>r.status==='active') || rsSorted[0] || {version:1,label:'—',status:'draft'};\n    let selVer = (d2.state.rulesetVersion==null) ? (Number(defaultRs.version)||1) : Number(d2.state.rulesetVersion);\n    let selectedRs = rsSorted.find(r=>Number(r.version)===selVer);\n    if(!selectedRs){ selectedRs = defaultRs; selVer = Number(defaultRs.version)||1; }\n    const isDraft = selectedRs.status!=='active';\n    // Scope every section to the SELECTED perfil AND rede — the two are independent.\n    // Band-tables carry both perfil and rede → scope directly. Bands carry rede + a bandTable ref\n    // (no perfil field) → scope to the in-scope band-tables' refs AND the selected rede.\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 active = selectedRs;\n    const vars = cssVars(t);\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=\"${active.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    let filterBar = '';\n    if(tab==='bands'){\n      filterBar = `<div class=\"filters\">\n        <div class=\"fg\"><span class=\"lb\">Tabela</span>${seg('bandTable',TABLE_SEG,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        <button class=\"newbtn spacer\" data-newtable>＋ Nova tabela de faixas</button>\n      </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'||b.bandTable===f.bandTable)&&(f.nivel==='all'||(b.nivel||'')===f.nivel)&&(f.brand==='all'||(b.brand||'')===f.brand));\n      count = vis.length;\n      // Pass band-tables (with valueType + kpi friendly names) so the grid groups by band-table and shows headers.\n      const btForGrid = perfilTables.map(bt=>({ _id:bt._id, ref:bt.ref, label:bt.label, valueType:bt.valueType, rede:bt.rede, perfil:bt.perfil, kpiCode:bt.kpiCode, displayOrder:bt.displayOrder, active:bt.active, kpiName:kpiName(kpis,bt.kpiCode) }));\n      bodyHost = d2.render('natura-x-piloto@pilotRuleBandGrid', { bands:perfilBands, filter:f, flashId:d2.state.flashId||'', bandTables:btForGrid }, { key:'bg-v'+selVer+'-'+perfil+'-'+rede+'-'+f.bandTable+'-'+f.nivel+'-'+f.brand+'-'+perfilBands.length+'-'+perfilTables.length+'-'+(d2.state.flashId||'') });\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 ? `Editando rascunho v${esc(selectedRs.version)} — não afeta ciclos usando outra versão.` : '';\n    const baseHint = tab==='bands' ? `Faixas de tabelas já referenciadas pelo cálculo impactam ganhos ao vivo. Uma tabela nova só afeta o cálculo após ser referenciada por uma fórmula (construtor de fórmulas — próxima etapa).` : '';\n    const metaHint = [draftHint, baseHint].filter(Boolean).join(' ');\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. Faixas e bônus impactam o cálculo ao vivo.</p>\n          </div>\n          <div class=\"rsbar\">\n            <div class=\"rspick\">\n              <label class=\"rslbl\">Ruleset</label>\n              <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>\n            </div>\n            <span class=\"rschip ${esc(selectedRs.status)}\">${esc(STATUS_LABEL[selectedRs.status]||selectedRs.status)}</span>\n            ${rsstatus}\n          </div>\n        </div>\n        ${tabs}\n      </div>\n      <div class=\"filters\">${perfilSeg}${redeSeg}</div>\n      ${filterBar}\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\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)=>{ d2.setState({ rulesetVersion: Number(el.value) }); });\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    // faixa modal fields\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\n    d2.bus.on('rule:band:edit', (b)=>openBandModal(d2,b));\n    d2.bus.on('rule:band:add', (tbl)=>{ const defRede=d2.state.rede||'rede1'; openBandModal(d2,{ bandTable:tbl, bandTableRef:tbl, rulesetVersion:selectedVersion(d2), rede:defRede, nivel:'diamante', brand:'natura', minPct:0, maxPct:100, value:0 }); });\n    d2.bus.on('rule:band:del', (b)=>handleDelBand(d2,b));\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 — cálculo atualizado ao vivo'));\n  }\n};\n\nfunction valueTypeOf(d2, m){\n  // Resolve valueType from the band's band-table (via bandTableRef/bandTable), fallback to legacy heuristic.\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 (m.bandTable==='atingimento') ? 'multiplier' : 'fixed';\n}\n\nfunction renderModal(d2,t){\n  if(!d2.state.modalOpen) return '';\n  const m = d2.state.modal || {};\n  const isNew = !m._id;\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>${isNew?'Nova faixa':'Editar faixa'}</h2>\n      <p class=\"msub\">${esc(TABLE_LABEL[m.bandTable]||m.bandTable||'')} · ${esc(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||'—'}</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':''}>${v||'total'}</option>`).join('')}</select>\n        </div>\n      </div>\n      <div class=\"frow\">\n        <div class=\"field\"><label>Mín %</label><input type=\"number\" step=\"0.01\" data-mfield=\"minPct\" value=\"${esc(m.minPct)}\"/></div>\n        <div class=\"field\"><label>Máx %</label><input type=\"number\" step=\"0.01\" data-mfield=\"maxPct\" value=\"${esc(m.maxPct)}\"/></div>\n        <div class=\"field\"><label>Valor (resultado)</label>\n          <div class=\"valwrap\"><input type=\"number\" step=\"0.01\" 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>${isNew?'Criar faixa':'Salvar'}</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  // dedupe kpi codes for the picker (friendly names)\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 (construtor de fórmulas — próxima etapa).</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 }), 2400); }\nfunction flash(d2,id){ d2.setState({ flashId:id }); setTimeout(()=>{ if(d2.state.flashId===id) d2.setState({ flashId:'' }); }, 900); }\nfunction refreshAll(d2){\n  ['bands','bonuses','formulas','rulesets','bandTables','kpis'].forEach(n=>{ const ds=d2.data(n); if(ds&&ds.refresh) ds.refresh(); });\n}\nasync function invoke(d2,payload){ return await d2.rush('writer').invoke(payload); }\n// Resolve the currently SELECTED ruleset version from state, falling back to the ACTIVE ruleset\n// (then first, then 1). Mirrors the render() derivation so saves land on the selected version.\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 def = sorted.find(r=>r.status==='active') || sorted[0];\n  if(d2.state.rulesetVersion==null) return def ? (Number(def.version)||1) : 1;\n  const v = Number(d2.state.rulesetVersion);\n  return sorted.some(r=>Number(r.version)===v) ? v : (def ? (Number(def.version)||1) : 1);\n}\n\nasync function saveModal(d2){\n  const m = d2.state.modal || {};\n  const row = {\n    _id: m._id, 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._id) delete row._id;\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: m._id?{ value:m.value }:{} });\n    savedId = r && r.data && r.data.id;\n    toast(d2, m._id?'Faixa atualizada':'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  // Derive a stable slug for new tables from the label (letters/digits, hyphenated).\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  let savedId=null;\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    savedId = r && r.data && r.data.id;\n    toast(d2, 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    await invoke(d2,{ entity:'band-table', op:'delete', actorEmail:ACTOR, row:{ _id:m._id }, before:m });\n    toast(d2,'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  d2.setState({ saving:true });\n  try{\n    await invoke(d2,{ entity:'band', op:'delete', actorEmail:ACTOR, row:{ _id:b._id }, before:b });\n    toast(d2,'Faixa excluída');\n  }catch(e){ toast(d2,'Erro ao excluir'); }\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    await invoke(d2,{ entity:'bonus', op:'delete', actorEmail:ACTOR, row:{ _id:b._id }, before:b });\n    toast(d2,'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  // Carry the SELECTED ruleset version into bonus/formula saves (preserve an existing row's version).\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    savedId = r && r.data && r.data.id;\n    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    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,'Status do ruleset: '+status);\n  }catch(e){ toast(d2,'Erro'); }\n  refreshAll(d2);\n  d2.setState({ saving:false });\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"}}}},"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 = { open:'Aberto', closed:'Fechado' };\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  const st = c.status||'open';\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>Ruleset vinculado</label>\n        <select data-rs=\"${esc(c.code)}\">${rsOptions(rulesets, c.rulesetVersion)}</select>\n      </div>\n      <div class=\"field\">\n        <label>Status</label>\n        <select data-st=\"${esc(c.code)}\">${['open','closed'].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 ${c.isCurrent?'on':''}\" data-cur=\"${esc(c.code)}\"><span class=\"knob\"></span></button>\n      </div>\n      <button class=\"btn prim save\" data-save=\"${esc(c.code)}\">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-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 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    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: 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 = { 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\">${['open','closed'].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 ACTOR='gabriel.cardoso@data2.app';\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_GLYPH = { 'brand-natura':'🌿','brand-avon':'💗','people':'👥','target':'🎯','crown':'👑','swap':'🔁','user-add':'➕','coins':'🪙','user':'🙂' };\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\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 ICON_GLYPH[icon]||'🎯'; }\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        <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':''}>${iconGlyph(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;font-size:22px}\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.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() : [];\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():[];\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', actorEmail:ACTOR, 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', actorEmail:ACTOR, 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', actorEmail:ACTOR, 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', actorEmail:ACTOR, 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};\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      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\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;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:wrap}\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}\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  .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  .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    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':''}>${icon('home')}Início</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  mounted(d2){\n    if(!d2.state.section) d2.state.section = 'home';\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    });\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    const groupList = (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>Carregue um grupo real, arraste os indicadores e veja a remuneração pelo mesmo motor do painel.</p></div>\n      </div>\n      <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        const r = d2.router(); if(r){ r.goTo('/'+ref); 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}\nexport default {\n  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  `,\n  render(d2){\n    const label = d2.param('label','Simulador');\n    return `<button class=\"fab\" title=\"Abrir Simulador de Ganhos\">${icon('calc','#fff',20)}<span>${label}</span></button>`;\n  },\n  mounted(d2){\n    d2.on('.fab','click',()=>{\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        const r = d2.router();\n        if(r){ r.goTo('/'+ref+qs); 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  }\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    const groupList = (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      }).join('');\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        const r = d2.router(); if(r){ r.goTo('/'+ref); 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}\nexport default {\n  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  `,\n  render(d2){\n    const label = d2.param('label','Histórico');\n    return `<button class=\"fab\" title=\"Abrir Histórico de Ganhos\">${icon('history','#fff',20)}<span>${label}</span></button>`;\n  },\n  mounted(d2){\n    d2.on('.fab','click',()=>{\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        const r = d2.router();\n        if(r){ r.goTo('/'+ref+qs); 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  }\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};\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];\n\nfunction rowMarkup(rec){\n  const m = actionMeta(rec.action);\n  const id = String(rec._id||'');\n  const actor = rec.actorName || rec.actorEmail || '—';\n  const target = rec.targetName || (rec.action==='impersonate-end' ? '(fim)' : '—');\n  const scope = rec.scope && rec.scope!=='n/a' ? rec.scope : '—';\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(rec.actorPerfil||rec.actualPerfil))}</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(rec.targetPerfil||rec.effectivePerfil||'')}\">${esc(perfilLabel(rec.targetPerfil||rec.effectivePerfil))}</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.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;'); }\nconst ACTOR='gabriel.cardoso@data2.app';\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      </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      <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>\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  .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', actorEmail:ACTOR, 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', actorEmail:ACTOR, 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":"5ed9bed7b9e0891ce913e884","component":"data2-core-types@Component","params":{"package":"data2-core","component":"DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}},{"_id":"5f472ae463c680de4ff296e9","component":"data2-core-types@Component","params":{"package":"data2-core","component":"Data2TableDataSource","extends":"data2-core@DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}}]}},{"reference":"ExternalComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"_id":"5f060d9b1ca96def42f3c40a","displayName":"Builder AuthStrategy","component":"data2-core@AuthenticationStrategy","system":"5e3b796d6228227ca637d0f4","params":{"credentials":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"verifier":{"component":"data2-core-types@DataSetReference","params":{"reference":"UsersDataSet"}},"sessionShared":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"password":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},"email":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},"resetPassword":{"resetEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"nR6Q9d7qdaPtZhJ28Q8Dy"},"component":"data2-core-types@ArtboardReference"}},"resetSuccessEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"yPCJBTKo8q1Mw0B_3Kpwl"},"component":"data2-core-types@ArtboardReference"}}},"session":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"name"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"sessionMetadata":{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},{"params":{"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"active"}},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.status"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is active user"}]},"component":"data2-core-logical-operators@And","displayName":"is active and has _id"}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $user"},{"params":{"action":{"params":{"pattern":{"component":"data2-core-primitives@String","params":{"content":"@data2.app"}},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.email"}}}}},"component":"data2-core-functions@Includes","displayName":"isData2User"},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}},"component":"data2-core-flow@Step"},{"params":{"action":{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.d2_app"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"management"}}]},"component":"data2-core-functions@Includes","displayName":"isData2App Exception"},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}},"component":"data2-core-flow@Step"},{"params":{"resultName":{"component":"data2-core-primitives@String","params":{"content":"has_access"}},"action":{"params":{"compare":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}}},{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}}}]},"component":"data2-core-logical-operators@Or"},"else":{"params":{"actions":[{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $metadata.system"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":"filter","args":[{"_id":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records.length"}}}}},"component":"data2-core-logical-operators@Not","displayName":"systems not found"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check system found"},{"params":{"actions":[{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"organization":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"cursor.current.organization._id"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"}]},"component":"data2-core-flow@Parallel"}]},"component":"data2-core-flow@Series","displayName":"common setup"},{"params":{"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"},"else":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"compare":{"params":{"components":{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"mapper":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"system"}}],"body":{"params":{"expression":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.visibility"}}}},"defaultCase":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"cases":[{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"public"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"billing-owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}},{"component":"data2-core-primitives@String","params":{"content":"member"}}]},"component":"data2-core-functions@Includes","displayName":"has role with access"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"collaborator"}}},"component":"data2-core-comparison-operators@Equal","displayName":"is collaborator"}]},"component":"data2-core-logical-operators@And","displayName":"is org member and collaborator"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is collaborator"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is collaborator and has system access"}]},"component":"data2-core-logical-operators@Or"}}},{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"private"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}}]},"component":"data2-core-functions@Includes","displayName":"is owner/admin"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is owner/admin"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is member and has system access"}]},"component":"data2-core-logical-operators@Or","displayName":"is owner/admin or has system access"}}}]},"component":"data2-core-flow@Switch"}}}},"component":"data2-core-functions@ArrayMap"}},"component":"data2-core-logical-operators@And","displayName":"has org member for all systems in request"}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"}},"component":"data2-core-flow@If"}},"component":"data2-core-flow@Step"},{"params":{"then":{"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"else":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"},"compare":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"has_access"}}}}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"sessionExpiresIn":{"component":"data2-core-primitives@Number","params":{"content":604800}},"sessionRenewal":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"identityProviders":[{"provider":{"component":"data2-core-primitives@String","params":{"content":"GOOGLE"}},"clientId":{"component":"data2-core-primitives@String","params":{"content":"55470861603-22pvfc1t49lp8cjnbfk71s5ct9hp1q1v.apps.googleusercontent.com"}}}]},"reference":"Data2BuilderAuthentication","updatedAt":"2026-08-06T19:31:23.557Z"},{"_id":"5f060ee51ca96def42f3fbd1","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"UsersTableDataSource"}},"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}}},"reference":"UsersDataSet","updatedAt":"2026-03-04T21:16:40.291Z"},{"_id":"68f938cf5fb002e33752a43d","displayName":"InternalApplicationsAuthenticationStrategy","component":"data2-core@AuthenticationStrategy","system":"5e3b796d6228227ca637d0f4","params":{"resetPassword":{"resetEmail":{"artboard":{"params":{"preventEvaluation":true},"component":"data2-core-types@ArtboardReference"}},"resetSuccessEmail":{"artboard":{"params":{"preventEvaluation":true},"component":"data2-core-types@ArtboardReference"}}},"verifier":{"disabled":false,"component":"data2-core-types@DataSetReference","params":{"reference":"InternalApplicationsVerifierDataSet"}},"password":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"secret"}},"credentials":[{"component":"data2-core-types@FieldReference","params":{"key":"application"}},{"component":"data2-core-types@FieldReference","params":{"key":"secret"}},{"component":"data2-core-types@FieldReference","params":{"key":"status"}}],"session":[{"component":"data2-core-types@FieldReference","params":{"key":"application"}},{"component":"data2-core-types@FieldReference","params":{"key":"secret"}},{"component":"data2-core-types@FieldReference","params":{"key":"status"}}]},"reference":"InternalApplicationsAuthenticationStrategy","updatedAt":"2025-10-22T20:08:54.442Z","createdAt":"2025-10-22T20:04:31.198Z"},{"component":"data2-core@DataSet","reference":"SessionsDataSet","params":{"requiresConfirmation":false,"pk":"key","datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"data2sessionsdatasource"}}}},{"reference":"UsersTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@ServerSessionsDataSource","reference":"data2sessionsdatasource","params":{}},{"_id":"5f1600b70528b92601890f75","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ServiceComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ServiceComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:20.208Z","createdAt":"2020-07-20T20:38:15.436Z"},{"_id":"5f1602190528b92601890f7d","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":40000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentInstancesTableDataSource"}},"sort":{"_id":1},"pk":"_id","autoEdit":true,"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:07.089Z","createdAt":"2020-07-20T20:44:09.350Z"},{"_id":"5f16017f0528b92601890f7a","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"clientApplicationDomain"}}},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"FileComponentInstancesDataSet","updatedAt":"2023-08-03T16:08:18.193Z","createdAt":"2020-07-20T20:41:35.797Z"},{"_id":"5f1601990528b92601890f7b","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ApplicationsTableDataSource"}},"pk":"_id","autoEdit":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"params":{"column":"_id"},"component":"data2-core-types@DataSetColumnReference"}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"ApplicationsDataSet","updatedAt":"2022-12-13T21:51:13.995Z","createdAt":"2020-07-20T20:42:01.657Z"},{"_id":"5f16172a0528b92601890f85","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":10000}}},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"DataComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"DataComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:12.831Z","createdAt":"2020-07-20T22:14:02.097Z"},{"_id":"60ddc1bbda3861ca65407c5a","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"clientApplicationDomain"}}},"pagination":{"size":1},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"}},"reference":"OneFileComponentInstancesDataSet","updatedAt":"2022-02-09T19:44:38.036Z","createdAt":"2020-07-20T20:41:35.797Z"},{"_id":"63ee3d38b8c9838c62fb05fb","displayName":"DriveFileComponentInstancesDataSet","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core@Drive"}}},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"DriveFileComponentInstancesDataSet","updatedAt":"2025-12-04T21:58:32.367Z","createdAt":"2023-02-16T14:27:07.797Z"},{"reference":"ServiceComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_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":{}}]}},{"reference":"ComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_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":"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":"9dd19eb8fb2bde13372df178","parent":"6a480778e3014dd5bb6ec589","component":"natura-x-piloto@pilotMDashboard","system":"688179c2a93dd170ce61e598","displayName":"[DELETE] old M Dashboard monolith","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"}},"statCard":"natura-x-piloto@pilotMStatCard","accordion":"natura-x-piloto@pilotMDetailAccordion","brandChip":"natura-x-piloto@pilotMBrandChip","typeBadge":"natura-x-piloto@pilotMTypeBadge","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}},"hide":true},"kpiGrid":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMKpiGrid"}},"groupGrid":{"component":"data2-core-primitives@String","params":{"content":"natura-x-piloto@pilotMGroupGrid"}},"freeTransform":true},"reference":"GnvP_uK3AS8qc6rZg75lE"},{"_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":"f49efd89698d205979197e8a","parent":"6a480778e3014dd5bb6ec589","component":"natura-x-piloto@pilotMTokenProbe","system":"688179c2a93dd170ce61e598","displayName":"[DELETE] token probe","params":{"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":860,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":700,"height":30}},"hide":true}},"reference":"IdFRr2Lh_rS1NGGk8zCaZ"},{"_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":"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":"6f2ae19de0565f1c28854671","parent":"6a480816c03bd927a9d7a871","component":"natura-x-piloto@pilotMDashboard","system":"688179c2a93dd170ce61e598","displayName":"[DELETE] old M Dashboard monolith (mobile)","params":{"store":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotDashboardStore"}},"api":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"pilotGetDashboardData"}},"topBar":"natura-x-piloto@pilotMTopBar","userHeader":"natura-x-piloto@pilotMUserHeader","statCard":"natura-x-piloto@pilotMStatCard","accordion":"natura-x-piloto@pilotMDetailAccordion","brandChip":"natura-x-piloto@pilotMBrandChip","typeBadge":"natura-x-piloto@pilotMTypeBadge","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}},"hide":true},"freeTransform":true},"reference":"Uqer9iGJWErp-iIrMgJI4"}]}},{"_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":"6a4c1b0f76e88709ac217d93","displayName":"PILOT · Admin App","reference":"Hu4m9tqGXMr2wct2jsjHm","params":{"domain":{"component":"data2-core-primitives@String","params":{"content":"pilot-admin"}},"entryPoint":{"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Router","reference":"pilotAdminRouter"}}},"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":"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":"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"}}]},"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"}]}},{"reference":"BundlesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}}],"processesParams":{}}}}