{"context":{"domain":"massayuki-playground"},"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":"686bd24b4fcbdb97284775e3","name":"Massayuki Honda","domain":"massayuki-playground","visibility":"public","settings":{"defaultAccessPolicy":"private"},"updatedAt":"2026-08-14T19:26:29.927Z","createdAt":"2025-07-07T12:56:41.025Z"}]}},{"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":"6ac563db06e81c2076f3bcec","component":"data2-core-types@Component","system":"686bd24b4fcbdb97284775e3","params":{"extends":"data2-core-primitives@Block","component":"Invest_Manager","package":"massayuki-playground","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 BRL = new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' })\nconst NUM = new Intl.NumberFormat('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 })\nconst money = (v) => BRL.format(Number(v) || 0)\nconst esc = (v) => String(v == null ? '' : v).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;')\nconst norm = (t) => String(t || '').toUpperCase().replace(/[^A-Z0-9]/g, '')\nconst parse = (v) => {\n  if (typeof v === 'number') return v\n  let s = String(v == null ? '' : v).replace(/[^0-9,.-]/g, '')\n  if (s.includes(',')) s = s.replace(/\\./g, '').replace(',', '.')\n  const n = parseFloat(s)\n  return isNaN(n) ? 0 : n\n}\nconst CATS = [\n  { key: 'acoes', label: 'Ações' },\n  { key: 'fiis', label: 'FIIs' },\n  { key: 'rendafixa', label: 'Renda fixa', free: true },\n  { key: 'etfs', label: 'ETFs' },\n]\nconst CAT_KEYS = CATS.map((c) => c.key)\nconst catOf = (r) => (r && CAT_KEYS.includes(r.categoria) ? r.categoria : (r && r.valorDireto ? 'rendafixa' : 'etfs'))\nconst RF_PADRAO = ['IPCA+2032', 'RENDA+2065', 'TESOURO SELIC', 'CAIXINHA']\nconst layout = (h) => `${h.acoes}${h.fiis}<div class=\"stack\" data-key=\"stack\">${h.rendafixa}${h.etfs}</div>`\nconst realUnit = (it) => {\n  const q = Number(it.quantidade) || 0\n  if (it.valorDireto || it.totalReal == null || !(q > 0)) return null\n  return Math.ceil(Math.round((Number(it.totalReal) || 0) * 100) / q - 1e-6) / 100\n}\nconst itemVal = (it) => (it.totalReal != null ? Number(it.totalReal) || 0 : Number(it.total) || 0)\nconst sumItens = (h) => Math.round((Array.isArray(h.itens) ? h.itens : []).reduce((s, x) => s + itemVal(x), 0) * 100) / 100\n// Caixinha: valor pago editável no histórico mesmo sem planejado (aportes ao longo do mês)\nconst isCx = (it) => norm(it && it.ticker) === 'CAIXINHA'\nconst ativoH = (it) => (Number(it.total) || 0) > 0 || isCx(it)\nconst visivelH = (it) => (Number(it.total) || 0) > 0.005 || isCx(it)\nconst compraH = (x) => (Number(x.total) || 0) > 0.005 || (isCx(x) && (Number(x.totalReal) || 0) > 0.005)\n// rentabilidade do aporte: ações + FIIs comprados, valor pago (real, ou planejado) × quantidade a preço de hoje\nconst rentab = (itens, now) => {\n  let inv = 0, cur = 0\n  itens.forEach((it) => {\n    const c = catOf(it)\n    if ((c !== 'acoes' && c !== 'fiis') || it.valorDireto || !it.comprado) return\n    const q = Number(it.quantidade) || 0\n    const n = now[norm(it.ticker)]\n    if (!(q > 0) || !(n > 0)) return\n    const pago = it.totalReal != null ? Number(it.totalReal) || 0 : Number(it.total) || 0\n    if (!(pago > 0)) return\n    inv += pago\n    cur += n * q\n  })\n  if (!(inv > 0)) return ''\n  const d = Math.round((cur - inv) * 100) / 100\n  const pc = (cur / inv - 1) * 100\n  const up = d >= 0\n  return `<div class=\"rent ${up ? 'u' : 'n'}\" title=\"Ações + FIIs · hoje ${money(cur)} − aportado ${money(inv)}\"><span class=\"rl\">Rentabilidade</span><b>${up ? '+' : '−'}${Math.abs(pc).toFixed(2).replace('.', ',')}%</b><span class=\"rv\">${up ? '+' : '−'}${money(Math.abs(d))}</span></div>`\n}\nconst GRIP = '<svg viewBox=\"0 0 8 14\" width=\"8\" height=\"14\" fill=\"currentColor\"><circle cx=\"2\" cy=\"2\" r=\"1.3\"/><circle cx=\"6\" cy=\"2\" r=\"1.3\"/><circle cx=\"2\" cy=\"7\" r=\"1.3\"/><circle cx=\"6\" cy=\"7\" r=\"1.3\"/><circle cx=\"2\" cy=\"12\" r=\"1.3\"/><circle cx=\"6\" cy=\"12\" r=\"1.3\"/></svg>'\n\nfunction shrink(file) {\n  return new Promise((resolve, reject) => {\n    const img = new Image()\n    const url = URL.createObjectURL(file)\n    img.onload = () => {\n      const max = 1800\n      const k = Math.min(1, max / Math.max(img.width, img.height))\n      const cv = document.createElement('canvas')\n      cv.width = Math.round(img.width * k)\n      cv.height = Math.round(img.height * k)\n      cv.getContext('2d').drawImage(img, 0, 0, cv.width, cv.height)\n      URL.revokeObjectURL(url)\n      resolve(cv.toDataURL('image/jpeg', 0.9))\n    }\n    img.onerror = () => { URL.revokeObjectURL(url); reject(new Error('imagem inválida')) }\n    img.src = url\n  })\n}\n\nfunction readAnswer(res, depth) {\n  depth = depth || 0\n  if (depth > 5 || res == null) return []\n  let out = res\n  if (typeof out === 'string') {\n    const s = out.replace(/```json|```/g, '').trim()\n    const m = s.match(/[\\[{][\\s\\S]*[\\]}]/)\n    try { out = JSON.parse(m ? m[0] : s) } catch (e) { return [] }\n  }\n  if (Array.isArray(out)) {\n    if (out.some((x) => x && typeof x === 'object' && ('ticker' in x || 'preco' in x))) return out\n    for (const x of out) { const r = readAnswer(x, depth + 1); if (r.length) return r }\n    return []\n  }\n  if (typeof out === 'object') {\n    for (const k of ['ativos', 'assets', 'data', 'answer', 'content', 'text', 'result']) {\n      if (out[k] != null) { const r = readAnswer(out[k], depth + 1); if (r.length) return r }\n    }\n    for (const v of Object.values(out)) { if (v && typeof v !== 'number') { const r = readAnswer(v, depth + 1); if (r.length) return r } }\n  }\n  return []\n}\n\nasync function importFile(d2, file) {\n  const S = d2.state\n  if (!file || !String(file.type || '').startsWith('image/')) {\n    S.msg = { type: 'err', text: 'Envie uma imagem (PNG ou JPG).' }\n    return\n  }\n  if (S.importing) return\n  S.view = 'main'\n  S.armed = false\n  S.importing = true\n  S.msg = null\n  try {\n    let url = await shrink(file)\n    file = null\n    const a = d2.assistant(d2.params.extrator)\n    const res = await a.ask('Extraia o ticker e o preço atual de cada ativo visível nesta imagem.', { images: [url], json: true })\n    url = null\n    let items = readAnswer(res)\n    if (!items.length) items = readAnswer(a.answer)\n    if (res && res.isData2Error) throw new Error(res.code === 401 ? 'sem permissão para usar o extrator' : (res.message || 'erro no extrator'))\n    const ds = d2.data('ativos')\n    const map = {}\n    ;(ds.records() || []).forEach((r) => { map[norm(r.ticker)] = r })\n    const now = new Date().toISOString()\n    const updated = {}\n    const missing = []\n    const jobs = []\n    items.forEach((it) => {\n      const t = norm(it.ticker)\n      const p = parse(it.preco != null ? it.preco : it.price)\n      if (!t || !(p > 0)) return\n      const r = map[t]\n      if (r && r._id) {\n        const old = Number(r.preco) || 0\n        updated[t] = { de: old, para: p }\n        const patch = { ...r, preco: p, atualizadoEm: now }\n        if (old > 0 && Math.abs(old - p) > 0.0001) patch.precoAnterior = old\n        jobs.push(ds.update(patch))\n      } else if (!missing.find((m) => m.ticker === t)) {\n        missing.push({ ticker: t, preco: p })\n      }\n    })\n    await Promise.all(jobs)\n    const n = Object.keys(updated).length\n    S.updated = updated\n    S.missing = missing\n    if (!items.length) S.msg = { type: 'err', text: 'Não encontrei ativos nessa imagem.' }\n    else S.msg = { type: 'ok', text: `${n} ${n === 1 ? 'cotação atualizada' : 'cotações atualizadas'}` + (missing.length ? ` · ${missing.length} fora da sua lista` : '') }\n  } catch (err) {\n    S.msg = { type: 'err', text: 'Não consegui ler a imagem: ' + (err && err.message ? err.message : err) }\n  } finally {\n    S.importing = false\n  }\n}\n\nconst LOGO = {}\nconst logoUrl = (t) => `https://icons.brapi.dev/icons/${t}.svg`\nfunction logo(d2, ticker, plain) {\n  const t = norm(ticker)\n  d2.state.logoTick\n  let s = 'fail'\n  if (!plain && t && typeof Image !== 'undefined') {\n    s = LOGO[t]\n    if (!s) {\n      LOGO[t] = s = 'loading'\n      const img = new Image()\n      img.onload = () => { LOGO[t] = img.naturalWidth > 1 ? 'ok' : 'fail'; d2.state.logoTick = (d2.state.logoTick || 0) + 1 }\n      img.onerror = () => { LOGO[t] = 'fail'; d2.state.logoTick = (d2.state.logoTick || 0) + 1 }\n      img.src = logoUrl(t)\n    }\n  }\n  return s === 'ok'\n    ? `<img class=\"lg\" src=\"${logoUrl(t)}\" alt=\"\" loading=\"lazy\">`\n    : `<span class=\"lg ini\">${esc(t.slice(0, 2))}</span>`\n}\n\nfunction userOf(a) {\n  if (!a) return null\n  const u = a.user\n  if (u && u.email) return u\n  const c = a.raw && a.raw.cursor && a.raw.cursor.current\n  if (c && c.credentials && c.credentials.email) return c.credentials\n  let g = null\n  try { g = a.raw && a.raw.getSelectedSession && a.raw.getSelectedSession() } catch (e) {}\n  if (g && g.authStrategy === 'invest-auth' && g.credentials && g.credentials.email) return g.credentials\n  return null\n}\n\nfunction renderLogin(d2, aviso) {\n  const L = d2.state.lg || {}\n  const cad = L.modo === 'cad'\n  const err = aviso || L.err\n  return `<div class=\"app\"><div class=\"lgw\"><div class=\"lgc\">\n    <div class=\"logo lgl\">IM</div>\n    <h1 class=\"lgt\">Invest manager</h1>\n    <p class=\"lgs\">${cad ? 'Crie seu acesso. Só funciona uma vez e só pela rede de casa.' : 'Entre para continuar.'}</p>\n    <label class=\"lgla\" for=\"lg-email\">E-mail</label>\n    <input class=\"lgi\" id=\"lg-email\" type=\"email\" autocomplete=\"username\" data-lgin value=\"${esc(L.email || '')}\">\n    <label class=\"lgla\" for=\"lg-senha\">Senha</label>\n    <input class=\"lgi\" id=\"lg-senha\" type=\"password\" autocomplete=\"${cad ? 'new-password' : 'current-password'}\" data-lgin>\n    ${cad ? `<label class=\"lgla\" for=\"lg-senha2\">Repita a senha</label><input class=\"lgi\" id=\"lg-senha2\" type=\"password\" autocomplete=\"new-password\" data-lgin>` : ''}\n    ${err ? `<div class=\"lge\">${esc(err)}</div>` : ''}\n    <button class=\"btn pri lgb\" data-auth=\"${cad ? 'criar' : 'entrar'}\" ${L.busy ? 'disabled' : ''}>${L.busy ? 'Aguarde…' : (cad ? 'Criar acesso' : 'Entrar')}</button>\n    ${aviso ? '<button class=\"link lgm\" data-auth=\"sair\">Sair</button>' : `<button class=\"link lgm\" data-auth=\"modo\">${cad ? 'Já tenho acesso' : 'Primeiro acesso'}</button>`}\n  </div></div></div>`\n}\n\nfunction renderChart(d2, ticker) {\n  const hs = d2.data('aportes')\n  const list = ((hs && hs.records()) || []).slice().sort((a, b) => String(a.data || '').localeCompare(String(b.data || '')))\n  const pts = []\n  list.forEach((h) => {\n    const it = (Array.isArray(h.itens) ? h.itens : []).find((i) => norm(i.ticker) === ticker)\n    if (it && Number(it.preco) > 0) { const ru = realUnit(it); pts.push({ d: h.data, p: ru != null ? ru : Number(it.preco), q: Number(it.quantidade) || 0, tot: itemVal(it) }) }\n  })\n  let body\n  if (!pts.length) {\n    body = `<p class=\"free\" style=\"font-size:13px;padding:12px 0\">Esse ativo ainda não aparece em nenhum aporte salvo. O gráfico usa só os preços dos aportes que você salvar.</p>`\n  } else {\n    const W = 640, H = 220, pl = 58, pr = 18, pt = 16, pb = 34\n    const ps = pts.map((x) => x.p)\n    let mn = Math.min(...ps), mx = Math.max(...ps)\n    if (mx - mn < 1e-9) { mn = mn * 0.95; mx = mx * 1.05 } else { const pad = (mx - mn) * 0.12; mn -= pad; mx += pad }\n    const X = (i) => (pts.length === 1 ? pl + (W - pl - pr) / 2 : pl + (i * (W - pl - pr)) / (pts.length - 1))\n    const Y = (p) => pt + (1 - (p - mn) / (mx - mn)) * (H - pt - pb)\n    const line = pts.map((x, i) => `${i ? 'L' : 'M'}${X(i).toFixed(1)},${Y(x.p).toFixed(1)}`).join(' ')\n    const grid = [0, 0.5, 1].map((f) => {\n      const v = mn + (mx - mn) * (1 - f)\n      const y = pt + f * (H - pt - pb)\n      return `<line x1=\"${pl}\" x2=\"${W - pr}\" y1=\"${y}\" y2=\"${y}\" class=\"gl\"/><text x=\"${pl - 8}\" y=\"${y + 4}\" class=\"ax\" text-anchor=\"end\">${NUM.format(v)}</text>`\n    }).join('')\n    const step = Math.max(1, Math.ceil(pts.length / 6))\n    const xl = pts.map((x, i) => (i % step === 0 || i === pts.length - 1)\n      ? `<text x=\"${X(i)}\" y=\"${H - 10}\" class=\"ax\" text-anchor=\"middle\">${new Date(x.d).toLocaleDateString('pt-BR', { day: '2-digit', month: '2-digit', year: '2-digit' })}</text>` : '').join('')\n    const dots = pts.map((x, i) => `<circle cx=\"${X(i)}\" cy=\"${Y(x.p)}\" r=\"${x.q > 0 ? 5 : 3.5}\" class=\"${x.q > 0 ? 'pb' : 'pn'}\"><title>${fmtDT(x.d)} · ${money(x.p)}${x.q > 0 ? ` · comprou ${x.q}` : ''}</title></circle>`).join('')\n    const chg = pts.length > 1 ? (pts[pts.length - 1].p / pts[0].p - 1) * 100 : 0\n    body = `<div class=\"cst\"><span>${pts.length} aporte(s) · ponto cheio = aporte em que você comprou</span>${pts.length > 1 ? `<span class=\"var ${chg >= 0 ? 'u' : 'n'}\">${chg >= 0 ? '+' : ''}${chg.toFixed(1).replace('.', ',')}% desde o primeiro</span>` : ''}</div>\n      <svg viewBox=\"0 0 ${W} ${H}\" class=\"chart\">${grid}<path d=\"${line}\" class=\"ln\"/>${dots}${xl}</svg>\n      <table class=\"ctab\"><thead><tr><th>Data do aporte</th><th>Preço</th><th style=\"text-align:center\">Qtd</th><th>Total</th></tr></thead>\n      <tbody>${pts.slice().reverse().map((x, i) => `<tr data-key=\"cp-${i}\"><td>${esc(fmtDT(x.d))}</td><td>${money(x.p)}</td><td style=\"text-align:center\">${x.q || '-'}</td><td>${money(x.tot)}</td></tr>`).join('')}</tbody></table>`\n  }\n  return `<div class=\"ovl\"><div class=\"ovp\"><div class=\"ovh\"><span class=\"tk\">${logo(d2, ticker)}<b>${esc(ticker)}</b><span class=\"free\" style=\"margin-left:8px\">preço nos aportes salvos</span></span><button class=\"btn closechart\">Fechar</button></div>${body}</div></div>`\n}\n\nfunction fmtDT(x) {\n  const d = new Date(x)\n  if (isNaN(d.getTime())) return '-'\n  return d.toLocaleDateString('pt-BR') + ' às ' + d.toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })\n}\n\nfunction snapshot(d2) {\n  const draft = d2.state.draft || {}\n  const recs = (d2.data('ativos').records() || []).slice().sort((a, b) => (Number(a.ordem) || 0) - (Number(b.ordem) || 0))\n  const v = (r, k) => {\n    const key = (r._id || '') + ':' + k\n    return draft[key] != null ? parse(draft[key]) : Number(r[k]) || 0\n  }\n  return recs.map((r) => {\n    const preco = v(r, 'preco')\n    const quantidade = v(r, 'quantidade')\n    const valor = v(r, 'valor')\n    return {\n      ticker: String(r.ticker || '').toUpperCase(),\n      categoria: catOf(r),\n      preco: preco,\n      precoAnterior: Number(r.precoAnterior) || 0,\n      quantidade: r.valorDireto ? 0 : quantidade,\n      valorDireto: !!r.valorDireto,\n      valor: r.valorDireto ? valor : 0,\n      total: Math.round((r.valorDireto ? valor : preco * quantidade) * 100) / 100,\n    }\n  })\n}\n\nfunction renderHist(d2, current) {\n  const S = d2.state\n  const hs = d2.data('aportes')\n  if (!hs) return `<div class=\"wrap\"><p class=\"empty\">Tabela de aportes não vinculada.</p></div>`\n  if (hs.loading) return `<div class=\"wrap\"><p class=\"empty\">Carregando histórico…</p></div>`\n  const list = (hs.records() || []).slice().sort((a, b) => String(b.data || '').localeCompare(String(a.data || '')))\n  if (!list.length) {\n    return `<div class=\"wrap\"><div class=\"hempty\"><b>Nenhum aporte salvo ainda</b><span>Use \"Salvar aporte\" para registrar os preços e as quantidades do dia.</span><button class=\"btn back\">Voltar</button></div></div>`\n  }\n  const sel = list.find((x) => x._id && x._id === S.histSel) || list[0]\n  const now = {}\n  current.forEach((r) => { now[norm(r.ticker)] = Number(r.preco) || 0 })\n  const itens = Array.isArray(sel.itens) ? sel.itens : []\n  const sums = {}\n  CATS.forEach((c) => { sums[c.key] = 0 })\n  itens.forEach((i) => { sums[catOf(i)] += itemVal(i) })\n\n  const side = list.map((h, i) => `<div class=\"hi ${h === sel ? 'on' : ''}\" data-key=\"${esc(h._id || 'p' + i)}\" data-id=\"${esc(h._id || '')}\">\n      <button class=\"hdel\" data-id=\"${esc(h._id || '')}\" title=\"Excluir aporte\">×</button>\n      <span>${esc(fmtDT(h.data))}</span>\n      <div class=\"hv\">${money(sumItens(h))}</div>\n      ${(() => { const b = (Array.isArray(h.itens) ? h.itens : []).filter(compraH); const dn = b.filter((x) => x.comprado).length; return b.length ? `<span class=\"hx ${dn === b.length ? 'all' : ''}\">${dn === b.length ? '✓ tudo comprado' : `${dn} de ${b.length} comprados`}</span>` : '' })()}\n      ${h.nota ? `<span>${esc(h.nota)}</span>` : ''}\n    </div>`).join('')\n\n  const row = (it, i) => {\n    const t = norm(it.ticker)\n    const p = Number(it.preco) || 0\n    const n = now[t]\n    const q = Number(it.quantidade) || 0\n    const tot = Number(it.total) || 0\n    const idx = itens.indexOf(it)\n    const ru = realUnit(it)\n    const hasReal = it.totalReal != null\n    const pago = hasReal ? Number(it.totalReal) || 0 : tot\n    let v = '<span class=\"free\">-</span>'\n    if (!it.valorDireto && p > 0 && n > 0) {\n      const pc = hasReal && q > 0 && pago > 0 ? ((n * q) / pago - 1) * 100 : (n / p - 1) * 100\n      v = `<span class=\"var ${pc >= 0 ? 'u' : 'n'}\" title=\"hoje ${money(n)}\">${pc >= 0 ? '+' : ''}${pc.toFixed(1).replace('.', ',')}%</span>`\n      if (S.histOnly && q > 0) {\n        const sd = Math.round((n * q - pago) * 100) / 100\n        v += `<span class=\"saldo ${sd >= 0 ? 'u' : 'n'}\" title=\"hoje ${money(n * q)} (${q} × ${money(n)}) − pago ${money(pago)}\">${sd >= 0 ? '+' : '−'}${money(Math.abs(sd))}</span>`\n      }\n    }\n    const dk = (sel._id || '') + ':' + idx\n    const hd = S.hdraft || {}\n    const priceCell = it.valorDireto ? '<span class=\"free\">valor livre</span>' : (ru != null ? `<b class=\"rp\">${money(ru)}</b><span class=\"pl\">planejado ${money(p)}</span>` : money(p))\n    const at = ativoH(it)\n    const totCell = at\n      ? `<input class=\"rin\" data-h=\"${esc(sel._id || '')}\" data-i=\"${idx}\" value=\"${esc(hd[dk] != null ? hd[dk] : (hasReal ? NUM.format(Number(it.totalReal) || 0) : ''))}\" placeholder=\"${NUM.format(tot)}\" title=\"Valor real pago na corretora\">${tot > 0 ? `<span class=\"pl\">planejado ${money(tot)}</span>` : ''}`\n      : money(tot)\n    return `<tr data-key=\"h-${esc(t)}-${i}\" class=\"${at ? 'has' : 'zero'}${it.comprado && at ? ' done' : ''}\">\n      <td><span class=\"tk\">${at ? `<input type=\"checkbox\" class=\"exec\" data-h=\"${esc(sel._id || '')}\" data-i=\"${itens.indexOf(it)}\" ${it.comprado ? 'checked' : ''} title=\"Já comprei\">` : '<span class=\"exsp\"></span>'}${logo(d2, it.ticker, it.valorDireto)}<span class=\"tkn\" data-t=\"${esc(t)}\" title=\"Ver preço nos aportes\">${esc(it.ticker)}</span></span></td>\n      <td>${priceCell}</td>\n      <td style=\"text-align:center\">${it.valorDireto ? '' : (q || '-')}</td>\n      <td class=\"tot\">${totCell}</td>\n      <td>${v}</td>\n    </tr>`\n  }\n\n  const cards = {}\n  CATS.forEach((c) => {\n    const l = itens.filter((i) => catOf(i) === c.key)\n    const lv = S.histOnly ? l.filter(visivelH) : l\n    cards[c.key] = `<section class=\"card\" data-key=\"hc-${c.key}\">\n      <div class=\"ch\"><div class=\"row1\"><h2>${c.label}<em>${S.histOnly ? `${lv.length} de ${l.length}` : l.length}</em></h2><span class=\"sub\">${money(sums[c.key])}</span></div></div>\n      <table><thead><tr><th>Ativo</th><th>Preço</th><th style=\"text-align:center\">Qtd</th><th>Total real</th><th>Até hoje</th></tr></thead>\n      <tbody>${lv.length ? lv.map(row).join('') : `<tr data-key=\"hempty-${c.key}\"><td colspan=\"5\" class=\"emptyrow\">Nada comprado nesta categoria</td></tr>`}</tbody></table>\n    </section>`\n  })\n\n  const buys = itens.filter(compraH)\n  const doneN = buys.filter((x) => x.comprado).length\n  return `<div class=\"hwrap\">\n    <aside class=\"hl\"><div class=\"hlt\">Aportes salvos (${list.length})</div>${side}</aside>\n    <div>\n      <div class=\"hh\"><div><div class=\"hrow\"><h2>Aporte de ${esc(fmtDT(sel.data))}</h2>${rentab(itens, now)}</div>${sel.nota ? `<span class=\"free\">${esc(sel.nota)}</span>` : ''}${buys.length ? `<div class=\"exprog ${doneN === buys.length ? 'all' : ''}\">${doneN === buys.length ? '✓ Tudo comprado' : `Comprado ${doneN} de ${buys.length} · informe o valor real pago em cada compra`}</div>` : ''}</div><span class=\"big\">${money(sumItens(sel))}</span></div>\n      <div class=\"cols hc\">${layout(cards)}</div>\n    </div>\n  </div>`\n}\n\nfunction renderHistMob(d2, current) {\n  const S = d2.state\n  const hs = d2.data('aportes')\n  if (!hs) return '<p class=\"empty\">Tabela de aportes não vinculada.</p>'\n  if (hs.loading) return '<p class=\"empty\">Carregando histórico…</p>'\n  const list = (hs.records() || []).slice().sort((a, b) => String(b.data || '').localeCompare(String(a.data || '')))\n  if (!list.length) return '<div class=\"mbh-empty\"><b>Nenhum aporte salvo ainda</b><span>Use “Salvar aporte” para registrar os preços e as quantidades do dia.</span></div>'\n  const sel = list.find((x) => x._id && x._id === S.histSel) || list[0]\n  const now = {}\n  current.forEach((r) => { now[norm(r.ticker)] = Number(r.preco) || 0 })\n  const hd = S.hdraft || {}\n  return list.map((h, hi) => {\n    const id = esc(h._id || '')\n    const itens = Array.isArray(h.itens) ? h.itens : []\n    const buys = itens.filter(compraH)\n    const dn = buys.filter((x) => x.comprado).length\n    const prog = buys.length ? (dn === buys.length ? '✓ tudo comprado' : `${dn} de ${buys.length} comprados`) : 'sem compras'\n    const head = `<div class=\"mbh-h\"><div><b>${esc(fmtDT(h.data))}</b><span>${prog}${h.nota ? ' · ' + esc(h.nota) : ''}</span></div><b class=\"mbh-v\">${money(sumItens(h))}</b></div>`\n    if (h !== sel) return `<button class=\"mbh hi\" data-key=\"mh-${id || hi}\" data-id=\"${id}\">${head}</button>`\n    const item = (it) => {\n      const idx = itens.indexOf(it)\n      const t = norm(it.ticker)\n      const p = Number(it.preco) || 0\n      const n = now[t]\n      const q = Number(it.quantidade) || 0\n      const tot = Number(it.total) || 0\n      const ru = realUnit(it)\n      const hasReal = it.totalReal != null\n      const pago = hasReal ? Number(it.totalReal) || 0 : tot\n      let ate = ''\n      if (!it.valorDireto && p > 0 && n > 0) {\n        const pc = hasReal && q > 0 && pago > 0 ? ((n * q) / pago - 1) * 100 : (n / p - 1) * 100\n        ate = `<span class=\"var ${pc >= 0 ? 'u' : 'n'}\">${pc >= 0 ? '+' : ''}${pc.toFixed(1).replace('.', ',')}%</span>`\n        if (S.histOnly && q > 0) {\n          const sd = Math.round((n * q - pago) * 100) / 100\n          ate += `<span class=\"saldo ${sd >= 0 ? 'u' : 'n'}\">${sd >= 0 ? '+' : '−'}${money(Math.abs(sd))}</span>`\n        }\n      }\n      const dk = (h._id || '') + ':' + idx\n      const at = ativoH(it)\n      const line2 = at\n        ? `<div class=\"mbi2\"><span class=\"pl\">${tot > 0 ? 'Planejado ' + money(tot) : 'Sem planejado'}${ru != null ? ` · ${money(ru)} por cota` : ''}</span><label>Pago <input class=\"rin\" inputmode=\"decimal\" data-h=\"${id}\" data-i=\"${idx}\" value=\"${esc(hd[dk] != null ? hd[dk] : (hasReal ? NUM.format(Number(it.totalReal) || 0) : ''))}\" placeholder=\"${NUM.format(tot)}\"></label></div>`\n        : (it.valorDireto ? '' : `<div class=\"mbi2\"><span class=\"pl\">Preço ${money(p)}</span></div>`)\n      return `<div class=\"mbi ${at ? 'has' : 'zero'}${it.comprado && at ? ' done' : ''}\" data-key=\"mi-${esc(t)}-${idx}\">\n        <div class=\"mbi1\">${at ? `<input type=\"checkbox\" class=\"exec\" data-h=\"${id}\" data-i=\"${idx}\" ${it.comprado ? 'checked' : ''} aria-label=\"Já comprei\">` : ''}${logo(d2, it.ticker, it.valorDireto)}<span class=\"tkn\" data-t=\"${esc(t)}\">${esc(it.ticker)}</span>${!it.valorDireto && q ? `<em>${q} cotas</em>` : ''}<span class=\"sp\"></span>${ate}</div>\n        ${line2}\n      </div>`\n    }\n    const groups = CATS.map((c) => {\n      const l = itens.filter((i) => catOf(i) === c.key)\n      const lv = S.histOnly ? l.filter(visivelH) : l\n      return lv.length ? `<div class=\"mbg\" data-key=\"mg-${c.key}\">${c.label}</div>${lv.map(item).join('')}` : ''\n    }).join('')\n    return `<section class=\"mbh on\" data-key=\"mh-${id || hi}\">${head}${(() => { const r = rentab(itens, now); return r ? `<div class=\"mrent\">${r}</div>` : '' })()}${groups || '<div class=\"memp\">Nada comprado neste aporte</div>'}<div class=\"mbh-f\"><button class=\"link mhdel\" data-id=\"${id}\">Excluir aporte</button></div></section>`\n  }).join('')\n}\n\n// celular: a página fica 1 px rolada (como no app Moti), assim o pull-to-refresh do APK nunca dispara\nconst NP_CSS = `html.inv-np,html.inv-np body{height:auto!important;min-height:100%;overscroll-behavior-y:none;background:#16181d}\nhtml.inv-np #app{position:static!important;height:auto!important}\nhtml.inv-np #app .data2-artboard{height:auto!important;min-height:calc(100vh + 2px)!important;overflow:visible!important}\nhtml.inv-np #app .data2-player-block{position:relative!important;height:auto!important;min-height:100vh;overflow:visible!important}`\nconst npSync = (S) => {\n  if (typeof document === 'undefined' || typeof window === 'undefined') return\n  const h = document.documentElement\n  if (!h || !h.classList) return\n  const on = !!S.npOn && !!S.mob\n  h.classList.toggle('inv-np', on)\n  if (on && (window.scrollY || 0) < 1) window.scrollTo(0, 1)\n}\n\nexport default {\n  css: `\n:host{--bg:#16181d;--sf:#1f2229;--ln:#2c3038;--tx:#e8eaed;--mu:#8a8f98;--ac:#2ecc71;--ac2:#1e8f4e;--in:#2a2e36;--dn:#ff6b6b}\n*{box-sizing:border-box}\n.app{height:100%;overflow:auto;background:var(--bg);color:var(--tx);font:14px/1.4 Inter,\"Segoe UI\",system-ui,sans-serif}\n.empty{padding:40px;color:var(--mu)}\n.lgw{width:100%;min-height:100vh;background:var(--bg);display:flex;align-items:center;justify-content:center;padding:32px 24px}\n.lgc{width:100%;max-width:360px;display:flex;flex-direction:column}\n.lgl{width:52px;height:52px;border-radius:14px;font-size:20px;align-self:center;margin-bottom:12px}\n.lgt{margin:0;text-align:center;font-size:20px;font-weight:600}\n.lgs{margin:6px 0 22px;text-align:center;color:var(--mu);font-size:13px}\n.lgla{font-size:12px;color:var(--mu);margin:0 0 6px}\n.lgi{background:var(--in);border:1px solid var(--ln);color:var(--tx);border-radius:10px;font:inherit;font-size:16px;height:48px;padding:0 14px;margin-bottom:14px;width:100%}\n.lgi:focus{outline:none;border-color:var(--ac)}\n.lge{color:var(--dn);font-size:13px;margin:-4px 0 12px}\n.lgb{height:48px;font-size:15px;font-weight:700;width:100%}\n.lgm{margin-top:14px;align-self:center;padding:10px}\n.top{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:18px 28px;border-bottom:1px solid var(--ln);position:sticky;top:0;background:var(--bg);z-index:2}\n.brand{display:flex;align-items:center;gap:10px}\n.logo{width:34px;height:34px;border-radius:9px;background:var(--ac);display:flex;align-items:center;justify-content:center;color:var(--bg);font-weight:700;font-size:15px}\n.brand h1{margin:0;font-size:17px;font-weight:600}\n.brand small{display:block;color:var(--mu);font-size:12px}\n.brand small.uso{font-size:11px;margin-top:1px;cursor:help}\n.brand small.uso.warn{color:#f5b041}\n.brand small.uso.crit{color:var(--dn)}\n.kpis{display:flex;align-items:center;gap:22px}\n.kpi{text-align:right}\n.kpi span{display:block;color:var(--mu);font-size:11px}\n.kpi b{font-size:14px;font-weight:600}\n.kpi.main b{font-size:22px;color:var(--ac)}\n.btn{background:transparent;border:1px solid var(--ln);color:var(--tx);border-radius:8px;padding:8px 12px;font:inherit;font-size:12px;cursor:pointer}\n.btn:hover{border-color:var(--mu)}\n.btn[disabled]{opacity:.6;cursor:progress}\n.wrap{padding:18px 28px 28px}\n.drop{display:flex;align-items:center;gap:14px;border:1.5px dashed var(--ln);border-radius:12px;padding:14px 16px;cursor:pointer;transition:border-color .15s,background .15s}\n.drop:hover,.drop.over{border-color:var(--ac);background:rgba(46,204,113,.06)}\n.drop:focus{outline:0}\n.drop.armed{border-style:solid;border-color:var(--ac);background:rgba(46,204,113,.10)}\n.drop.armed .ic{background:var(--ac);color:var(--bg)}\n.drop .ic{width:40px;height:40px;border-radius:10px;background:var(--in);display:flex;align-items:center;justify-content:center;color:var(--ac);flex:none}\n.drop .ic svg{width:20px;height:20px}\n.drop .t{flex:1;min-width:0}\n.drop .t b{display:block;font-weight:600}\n.drop .t span{color:var(--mu);font-size:12px}\n.kbd{font-size:11px;border:1px solid var(--ln);border-radius:5px;padding:1px 6px;color:var(--mu)}\n.spin{width:18px;height:18px;border:2px solid var(--ln);border-top-color:var(--ac);border-radius:50%;animation:sp .8s linear infinite}\n@keyframes sp{to{transform:rotate(360deg)}}\n.msg{margin-top:10px;font-size:13px;display:flex;flex-wrap:wrap;align-items:center;gap:8px}\n.msg.ok{color:var(--ac)} .msg.err{color:var(--dn)}\n.miss{margin-top:10px;display:flex;flex-wrap:wrap;gap:8px;align-items:center}\n.miss .lb{color:var(--mu);font-size:12px}\n.chip{display:flex;align-items:center;gap:6px;background:var(--sf);border:1px solid var(--ln);border-radius:8px;padding:4px 6px 4px 10px;font-size:12px}\n.chip em{font-style:normal;color:var(--mu)}\n.chip button{background:var(--in);border:0;color:var(--tx);border-radius:6px;padding:3px 7px;font:inherit;font-size:11px;cursor:pointer}\n.chip button:hover{background:var(--ac2)}\n.link{background:none;border:0;color:var(--mu);font:inherit;font-size:12px;cursor:pointer;text-decoration:underline}\n.cols{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;margin-top:18px;align-items:start;min-width:1080px}\n.stack{display:flex;flex-direction:column;gap:12px;min-width:0}\n.card{background:var(--sf);border:1px solid var(--ln);border-radius:12px;overflow:hidden}\n.ch{padding:14px 16px 10px}\n.ch .row1{display:flex;justify-content:space-between;align-items:baseline}\n.ch h2{margin:0;font-size:15px;font-weight:600}\n.ch h2 em{font-style:normal;color:var(--mu);font-weight:400;font-size:12px;margin-left:6px}\n.ch .sub{color:var(--ac);font-weight:600;font-size:16px}\n.bar{height:4px;background:var(--in);border-radius:4px;margin-top:10px;overflow:hidden}\n.bar i{display:block;height:100%;background:var(--ac);border-radius:4px}\n.pct{color:var(--mu);font-size:11px;margin-top:4px}\ntable{width:100%;border-collapse:collapse;font-size:13px}\nth{color:var(--mu);font-weight:400;font-size:11px;text-align:right;padding:6px 8px;border-top:1px solid var(--ln);white-space:nowrap}\nth:first-child{text-align:left;padding-left:16px}\ntd{padding:5px 8px;border-top:1px solid var(--ln);text-align:right;white-space:nowrap}\ntd:first-child{text-align:left;padding-left:16px;font-weight:500}\ntr.has td.tot{color:var(--tx)}\ntd.tot{color:var(--mu)}\n.dot{display:inline-block;width:6px;height:6px;border-radius:50%;margin-right:7px;background:transparent;vertical-align:middle}\ntr.up .dot{background:var(--ac)}\n.in{width:64px;background:var(--in);border:1px solid transparent;color:var(--tx);border-radius:6px;padding:4px 6px;font:inherit;font-size:13px;text-align:right;outline:0}\n.in:focus{border-color:var(--ac)}\n.in.q{width:46px;text-align:center}\n.in.v{width:90px}\n.in.p{background:transparent}\n.in.p:hover,.in.p:focus{background:var(--in)}\n.d{display:inline-block;width:12px;font-size:10px;margin-left:3px;text-align:left}\n.d.u{color:var(--ac)} .d.n{color:var(--dn)}\n.free{color:var(--mu);font-size:11px}\n.del{background:none;border:0;color:var(--mu);cursor:pointer;font-size:14px;opacity:0;padding:0 8px 0 0}\ntr:hover .del{opacity:1}\n.del:hover{color:var(--dn)}\n.cf{padding:10px 16px;border-top:1px solid var(--ln)}\n.add{background:none;border:0;color:var(--mu);font:inherit;font-size:12px;cursor:pointer;padding:0}\n.add:hover{color:var(--ac)}\n.btn.pri{background:var(--ac);color:var(--bg);border-color:var(--ac);font-weight:600}\n.btn.pri:hover{background:#3ddc80}\n.hwrap{display:grid;grid-template-columns:250px minmax(0,1fr);gap:16px;padding:18px 28px 28px;align-items:start}\n.hl{display:flex;flex-direction:column;gap:8px;position:sticky;top:90px}\n.hlt{color:var(--mu);font-size:12px;margin-bottom:2px}\n.hi{background:var(--sf);border:1px solid var(--ln);border-radius:10px;padding:10px 12px;cursor:pointer;position:relative}\n.hi:hover{border-color:var(--mu)}\n.hi.on{border-color:var(--ac)}\n.hi span{display:block;color:var(--mu);font-size:12px;padding-right:16px}\n.hi .hv{color:var(--tx);font-weight:600;font-size:15px;margin:2px 0}\n.hi.on .hv{color:var(--ac)}\n.hdel{position:absolute;top:6px;right:6px;background:none;border:0;color:var(--mu);cursor:pointer;font-size:14px;opacity:0}\n.hi:hover .hdel{opacity:1}\n.hdel:hover{color:var(--dn)}\n.hh{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:14px}\n.hh h2{margin:0;font-size:17px;font-weight:600}\n.hh .big{color:var(--ac);font-size:20px;font-weight:600}\n.hc{margin-top:0}\ntr.zero td{color:var(--mu)}\n.var{font-size:12px}\n.var.u{color:var(--ac)} .var.n{color:var(--dn)}\n.hempty{display:flex;flex-direction:column;align-items:flex-start;gap:8px;background:var(--sf);border:1px solid var(--ln);border-radius:12px;padding:24px}\n.hempty span{color:var(--mu);font-size:13px}\n.tkn{cursor:pointer}\n.tkn:hover{color:var(--ac);text-decoration:underline}\n.in.m{width:78px}\ntd.tot.ok,tr.has td.tot.ok{color:var(--ac)}\ntd.tot.under,tr.has td.tot.under{color:#f5b041}\ntd.tot.over,tr.has td.tot.over{color:var(--dn)}\n.orc{display:flex;flex-direction:column;align-items:flex-end}\n.orcin{width:120px;background:var(--in);border:1px solid transparent;color:var(--tx);border-radius:6px;padding:4px 8px;font:inherit;font-size:14px;font-weight:600;text-align:right;outline:0}\n.orcin:focus{border-color:var(--ac)}\n.kpi b.ovr{color:var(--dn)}\n.os{display:block;font-size:11px;color:var(--mu);margin-top:2px}\n.os.ok{color:var(--ac)} .os.under{color:#f5b041} .os.over{color:var(--dn)}\n.ovl{position:fixed;inset:0;background:rgba(0,0,0,.55);display:flex;align-items:center;justify-content:center;z-index:20;padding:24px}\n.ovp{width:min(720px,100%);max-height:90vh;overflow:auto;background:var(--sf);border:1px solid var(--ln);border-radius:14px;padding:18px 20px}\n.ovh{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}\n.cst{display:flex;justify-content:space-between;gap:12px;color:var(--mu);font-size:12px;margin-bottom:6px}\n.chart{width:100%;height:auto;display:block}\n.chart .gl{stroke:var(--ln);stroke-width:1}\n.chart .ax{fill:var(--mu);font-size:11px}\n.chart .ln{fill:none;stroke:var(--ac);stroke-width:2.5}\n.chart .pb{fill:var(--ac);stroke:var(--sf);stroke-width:2}\n.chart .pn{fill:var(--sf);stroke:var(--ac);stroke-width:2}\n.ctab{margin-top:10px}\n.grip{cursor:grab;color:var(--mu);opacity:.35;display:inline-flex;align-items:center;margin:0 8px 0 -8px;padding:4px 3px;user-select:none;border-radius:4px}\n.grip:hover{background:var(--in)}\n.grip svg{pointer-events:none}\n.grip.off{visibility:hidden;pointer-events:none}\n.sth{cursor:pointer;user-select:none}\n.sth:hover{color:var(--tx)}\n.sth.on{color:var(--ac)}\n.tools b{color:var(--tx);font-weight:500}\n.tools .link{font-size:12px}\n.tools{display:flex;align-items:center;justify-content:flex-end;gap:12px;margin-top:16px;font-size:12px;color:var(--mu)}\n.sortsel{background:var(--in);color:var(--tx);border:1px solid transparent;border-radius:6px;padding:5px 8px;font:inherit;font-size:12px;margin-left:6px;outline:0;cursor:pointer}\n.sortsel:focus{border-color:var(--ac)}\n.exec{accent-color:var(--ac);width:15px;height:15px;margin:0 9px 0 0;cursor:pointer;flex:none}\n.exsp{display:inline-block;width:24px;flex:none}\ntr.done .tkn{color:var(--ac)}\n.exprog{font-size:12px;color:#f5b041;margin-top:4px}\n.exprog.all{color:var(--ac)}\n.hi .hx{color:#f5b041}\n.hi .hx.all{color:var(--ac)}\n.grip{touch-action:none}\n.app.dragmode{user-select:none;cursor:grabbing}\n.app.dragmode *{cursor:grabbing !important}\n.btn.histonly.on{border-color:var(--ac);color:var(--ac)}\ntr:hover .grip{opacity:1}\n.grip:active{cursor:grabbing}\ntr.dragging{opacity:.4}\ntr.dropb td{box-shadow:inset 0 2px 0 var(--ac)}\ntr.dropa td{box-shadow:inset 0 -2px 0 var(--ac)}\n.btn.onlybtn.on{border-color:var(--ac);color:var(--ac)}\ntd.emptyrow{color:var(--mu);font-weight:400;text-align:center;padding:16px}\n.mrow{display:flex;align-items:center;gap:8px;margin-top:10px;font-size:12px;color:var(--mu)}\n.metain{width:120px;background:var(--in);border:1px solid transparent;color:var(--tx);border-radius:6px;padding:4px 8px;font:inherit;font-size:13px;font-weight:600;text-align:right;outline:0}\n.metain:focus{border-color:var(--ac)}\n.mrow .os{display:inline;margin:0 0 0 4px}\n.bar i.over{background:var(--dn)}\ntd.lp{color:var(--mu)}\n.tk{display:inline-flex;align-items:center}\n.lg{width:24px;height:24px;border-radius:7px;margin-right:10px;object-fit:cover;flex:none;display:inline-block;background:#fff}\n.lg.ini{background:var(--in);color:var(--mu);font-size:10px;font-weight:600;line-height:24px;text-align:center;letter-spacing:.02em}\n.chip .lg{width:18px;height:18px;line-height:18px;border-radius:5px;margin-right:2px;font-size:8px}\n.savebar{display:flex;align-items:center;gap:10px;background:var(--sf);border:1px solid var(--ac2);border-radius:12px;padding:12px 14px;margin-bottom:14px}\n.savebar .st{flex:1;min-width:0}\n.savebar .st b{display:block;font-weight:600}\n.savebar .st span{color:var(--mu);font-size:12px}\n.note{width:240px;background:var(--in);border:1px solid transparent;color:var(--tx);border-radius:8px;padding:8px 10px;font:inherit;font-size:13px;outline:0}\n.note:focus{border-color:var(--ac)}\n.hwrap{min-width:1400px}\n.rin{width:92px;background:var(--in);border:1px solid transparent;color:var(--tx);border-radius:6px;padding:4px 6px;font:inherit;font-size:13px;text-align:right;outline:0}\n.rin:focus{border-color:var(--ac)}\n.rin::placeholder{color:var(--mu)}\n.pl{display:block;font-size:11px;color:var(--mu);font-weight:400;margin-top:2px}\nb.rp{font-weight:600}\n.saldo{display:block;font-size:11px;margin-top:2px}\n.saldo.u{color:var(--ac)} .saldo.n{color:var(--dn)}\n.hrow{display:flex;align-items:center;gap:28px;flex-wrap:wrap}\n.rent{display:inline-flex;align-items:baseline;gap:8px;padding:5px 12px;border:1px solid var(--ln);border-radius:8px;font-size:13px}\n.rent .rl{color:var(--mu);font-size:12px}\n.rent b{font-weight:600;font-size:15px}\n.rent.u b,.rent.u .rv{color:var(--ac)} .rent.n b,.rent.n .rv{color:var(--dn)}\n.mrent{padding:10px 14px;border-bottom:1px solid var(--ln)}\n.mrent .rent{border:0;padding:0}\n.rfn{font-weight:500}\n.app.mb{height:100vh;height:100dvh;overflow:hidden;display:flex;flex-direction:column;position:relative}\n.mtop{flex:none;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 16px;padding-top:calc(10px + env(safe-area-inset-top,0px));border-bottom:1px solid var(--ln)}\n.mbr{display:flex;align-items:center;gap:10px;min-width:0}\n.mbr .logo{width:32px;height:32px;font-size:14px;flex:none}\n.mbr b{display:block;font-size:16px;font-weight:600}\n.mbr small{display:block;font-size:12px;color:var(--mu)}\n.mib{width:44px;height:44px;border-radius:10px;border:1px solid var(--ln);background:transparent;color:var(--tx);display:flex;align-items:center;justify-content:center;padding:0;flex:none;cursor:pointer}\n.mmw{position:absolute;top:64px;right:12px;z-index:20;background:var(--sf);border:1px solid var(--ln);border-radius:12px;padding:6px;width:240px;display:flex;flex-direction:column;box-shadow:0 12px 32px rgba(0,0,0,.5)}\n.mmi{background:transparent;border:0;color:var(--tx);font:inherit;text-align:left;padding:12px;border-radius:8px;cursor:pointer}\n.mmi:active{background:var(--in)}\n.mmu{padding:8px 12px 10px;font-size:12px;color:var(--mu);border-top:1px solid var(--ln);margin-top:4px}\n.mbody{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior-y:contain}\n.mtr{display:flex;align-items:center;gap:8px;flex:none}\n.mrl{height:44px;border-radius:10px;border:1px solid var(--ln);background:transparent;color:var(--tx);display:flex;align-items:center;gap:6px;padding:0 12px;font:inherit;font-size:13px;cursor:pointer}\n.mrl svg{width:16px;height:16px;flex:none}\n.mrl.on svg{animation:sp .8s linear infinite}\n.mrl[disabled]{opacity:.7}\n.mend{height:12px}\n.mres{padding:14px 16px 12px;display:flex;flex-direction:column;gap:8px}\n.mres .bar{margin-top:0;height:6px}\n.mres1{display:flex;justify-content:space-between;align-items:flex-end;gap:12px}\n.mlab{display:block;font-size:12px;color:var(--mu)}\n.mgr{display:block;font-size:26px;font-weight:700;color:var(--ac);line-height:1.15}\n.morc{text-align:right}\n.mb input.orcin,.mb input.metain{background:var(--in);border:1px solid var(--ln);color:var(--tx);border-radius:8px;font:inherit;font-size:16px;height:40px;padding:0 10px;width:124px;text-align:right;outline:0}\n.mb input.metain{height:36px;width:110px}\n.mb input.orcin:focus,.mb input.metain:focus{border-color:var(--ac)}\n.mres2{display:flex;flex-wrap:wrap;gap:4px 12px;font-size:12px;color:var(--mu)}\n.mpw{padding:0 16px 12px;display:flex;gap:8px;align-items:stretch}\n.mpaste{flex:1;min-width:0;min-height:52px;display:flex;align-items:center;gap:12px;background:var(--sf);border:1px dashed #3a3f48;border-radius:12px;color:var(--tx);font:inherit;padding:8px 12px;text-align:left;cursor:pointer}\n.mpi{width:36px;height:36px;border-radius:10px;background:var(--in);color:var(--ac);display:flex;align-items:center;justify-content:center;flex:none}\n.mpi svg{width:18px;height:18px}\n.mpt{flex:1;min-width:0}\n.mpt b{display:block;font-weight:600}\n.mpt span{display:block;font-size:12px;color:var(--mu)}\n.mgal,.mbtn{display:inline-flex;align-items:center;justify-content:center;min-height:44px;padding:0 14px;border-radius:12px;border:1px solid var(--ln);background:transparent;color:var(--tx);font:inherit;font-size:13px;font-weight:600;position:relative;overflow:hidden;cursor:pointer}\n.mfile{position:absolute;left:0;top:0;width:1px;height:1px;opacity:0;pointer-events:none}\n.mmsg{margin:0 16px 12px}\n.mtabs{position:sticky;top:0;z-index:3;background:var(--bg);padding:8px 16px 10px;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;border-bottom:1px solid var(--ln)}\n.mtab{min-height:52px;display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:2px;padding:6px 10px;border-radius:10px;font:inherit;color:var(--tx);text-align:left;background:transparent;border:1px solid var(--ln);cursor:pointer;min-width:0}\n.mtab.on{background:var(--sf);border-color:var(--ac)}\n.mtl{display:flex;align-items:center;gap:6px;font-size:13px;font-weight:600;white-space:nowrap}\n.mtv{font-size:12px;color:var(--mu);white-space:nowrap}\n.mdot{width:8px;height:8px;border-radius:50%;background:var(--ln);flex:none}\n.mdot.ok{background:var(--ac)}\n.mdot.under{background:#f5b041}\n.mdot.over{background:var(--dn)}\n.mtool{display:flex;justify-content:flex-end;padding:10px 16px 0}\n.mchip{min-height:36px;padding:0 12px;border-radius:18px;font:inherit;font-size:12px;background:transparent;border:1px solid var(--ln);color:#c9ced6;cursor:pointer}\n.mchip.on{background:var(--ac2);border-color:var(--ac);color:#fff}\n.mcard{margin:10px 16px 14px;background:var(--sf);border:1px solid var(--ln);border-radius:12px;overflow:hidden}\n.mch{padding:12px 14px 10px;border-bottom:1px solid var(--ln)}\n.mch1{display:flex;justify-content:space-between;align-items:baseline;gap:8px}\n.mch1 b{font-size:15px;font-weight:600}\n.mch1 em{font-style:normal;font-weight:400;font-size:12px;color:var(--mu)}\n.msum{color:var(--ac);font-weight:600;font-size:16px}\n.mmeta{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin-top:8px;font-size:12px;color:var(--mu)}\n.mr{padding:10px 14px;border-bottom:1px solid #262a31;display:flex;flex-direction:column;gap:8px}\n.mr1,.mr2{display:flex;align-items:center;gap:8px;min-width:0}\n.mr2{padding-left:22px}\n.sp{flex:1}\n.mtk{font-weight:600;font-size:14px;color:var(--mu);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.mr.has .mtk{color:var(--tx)}\n.mtot{font-weight:600;font-size:15px;color:#6b7079;white-space:nowrap}\n.mr.has .mtot{color:var(--ac)}\n.mb .lg{margin-right:0}\n.mb .grip.mgrip{color:#6b7079;padding:8px 4px;margin:-8px 0;touch-action:none;cursor:grab;opacity:1;visibility:visible;display:inline-flex}\n.mdel{width:32px;height:32px;border:0;background:transparent;color:var(--mu);font-size:18px;border-radius:8px;flex:none;cursor:pointer}\n.mb .in{background:var(--in);border:1px solid var(--ln);color:var(--tx);border-radius:8px;font:inherit;font-size:16px;height:40px;padding:0 10px;outline:0}\n.mb .in:focus{border-color:var(--ac)}\n.mb .in.p{width:96px}\n.mb .in.q{width:56px;text-align:center;padding:0 4px}\n.mb .in.v{width:124px;text-align:right}\n.mlp{font-size:12px;color:var(--mu);white-space:nowrap}\n.mstp{width:40px;height:40px;border-radius:10px;border:1px solid var(--ln);background:var(--in);color:var(--tx);font:inherit;font-size:20px;line-height:1;padding:0;flex:none;cursor:pointer}\n.memp{padding:14px;color:var(--mu);font-size:13px}\n.mcf{padding:2px 14px 6px}\n.mcf .add{min-height:44px}\n.mb .dropb{box-shadow:inset 0 2px 0 var(--ac)}\n.mb .dropa{box-shadow:inset 0 -2px 0 var(--ac)}\n.mb .dragging{opacity:.45}\n.mfoot{flex:none;border-top:1px solid var(--ln);background:var(--bg);padding:10px 16px calc(6px + env(safe-area-inset-bottom,0px))}\n.msave{width:100%;height:48px;border:0;border-radius:12px;background:var(--ac);color:#10130f;font:inherit;font-size:15px;font-weight:700;margin-bottom:6px;cursor:pointer}\n.mnav{display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}\n.mnb{display:flex;flex-direction:column;align-items:center;gap:2px;padding:6px;background:transparent;border:0;color:var(--mu);font:inherit;font-size:12px;min-height:44px;cursor:pointer}\n.mnb.on{color:var(--ac);font-weight:600}\n.mnb svg{width:20px;height:20px}\n.msh-ov{position:absolute;inset:0;z-index:30;background:rgba(8,9,12,.72);display:flex;align-items:flex-end}\n.msh{width:100%;max-height:85%;overflow-y:auto;background:var(--sf);border-top:1px solid var(--ln);border-radius:20px 20px 0 0;padding:16px 16px calc(16px + env(safe-area-inset-bottom,0px));display:flex;flex-direction:column;gap:14px}\n.msh-hd b{display:block;font-size:16px;font-weight:600}\n.msh-hd span{display:block;font-size:12px;color:var(--mu);margin-top:2px}\n.msh-l{background:var(--bg);border:1px solid var(--ln);border-radius:12px;overflow:hidden}\n.msh-r{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));padding:9px 12px;border-bottom:1px solid #262a31}\n.msh-r span{text-align:right;color:var(--mu)}\n.msh-r span.u{color:var(--ac)}\n.msh-r span.n{color:var(--dn)}\n.msh-th{font-size:12px;color:var(--mu)}\n.msh-th span:first-child{text-align:left}\n.msh-m{display:flex;align-items:center;flex-wrap:wrap;gap:8px;background:var(--bg);border:1px solid var(--ln);border-radius:10px;padding:8px 10px}\n.msh-m span{color:var(--mu)}\n.msh-m .addm{min-height:36px}\n.msh-b{display:flex;gap:10px}\n.msh-b>*{flex:1}\n.mbtn.pri{background:var(--ac);border:0;color:#10130f;font-weight:700}\n.mb .note.mnote{width:100%;height:44px;font-size:16px}\n.mbh{display:block;width:calc(100% - 32px);margin:10px 16px;text-align:left;background:var(--sf);border:1px solid var(--ln);border-radius:12px;color:var(--tx);font:inherit;padding:0;overflow:hidden;cursor:pointer}\n.mbh.on{cursor:default}\n.mbh-h{display:flex;justify-content:space-between;align-items:baseline;gap:12px;padding:12px 14px}\n.mbh.on .mbh-h{border-bottom:1px solid var(--ln)}\n.mbh-h b{display:block;font-weight:600;font-size:15px}\n.mbh-h span{display:block;font-size:12px;color:var(--mu)}\n.mbh.on .mbh-v{color:var(--ac)}\n.mbg{padding:10px 14px 2px;font-size:11px;letter-spacing:.04em;text-transform:uppercase;color:var(--mu)}\n.mbi{padding:10px 14px;border-bottom:1px solid #262a31;display:flex;flex-direction:column;gap:6px}\n.mbi1,.mbi2{display:flex;align-items:center;gap:8px;min-width:0}\n.mbi1 em{font-style:normal;font-size:12px;color:var(--mu)}\n.mbi1 .tkn{font-weight:600}\n.mbi.zero .tkn{color:var(--mu)}\n.mbi2 .pl{flex:1;margin:0;font-size:12px}\n.mbi2 label{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--mu)}\n.mb .rin{width:112px;height:40px;font-size:16px;border:1px solid var(--ln)}\n.mb .exec{width:20px;height:20px;accent-color:var(--ac);flex:none}\n.mbi .var{font-size:12px}\n.mbi .saldo{display:inline;margin:0 0 0 6px}\n.mbh-f{padding:6px 14px 10px;text-align:right}\n.mbh-f .mhdel{color:var(--dn);padding:10px 0}\n.mbh-empty{margin:24px 16px;display:flex;flex-direction:column;gap:6px;color:var(--mu)}\n.mbh-empty b{color:var(--tx)}\n.mb .ovl{padding:12px;align-items:flex-start}\n.mb .ovp{width:100%;max-width:100%;max-height:calc(100dvh - 24px);overflow:auto}\n.mb .chart{width:100%;height:auto}\n.mb .ctab{font-size:12px}\n`,\n\n  render(d2) {\n    const au = d2.auth('auth')\n    if (!au) return `<div class=\"app\"><p class=\"empty\">Conectando…</p></div>`\n    const me = userOf(au)\n    if (!me || !me.email) return renderLogin(d2)\n    if (me.role !== 'admin') return renderLogin(d2, 'Este acesso não tem permissão para usar o app.')\n    const ds = d2.data('ativos')\n    if (!ds) return `<div class=\"app\"><p class=\"empty\">Tabela de ativos não vinculada.</p></div>`\n    if (ds.loading) return `<div class=\"app\"><p class=\"empty\">Carregando ativos…</p></div>`\n    const S = d2.state\n    const draft = S.draft || {}\n    const upd = S.updated || {}\n    const recs = (ds.records() || []).slice().sort((a, b) => (Number(a.ordem) || 0) - (Number(b.ordem) || 0))\n\n    const val = (r, k) => {\n      const key = (r._id || '') + ':' + k\n      return draft[key] != null ? parse(draft[key]) : Number(r[k]) || 0\n    }\n    const shown = (r, k, dec) => {\n      const key = (r._id || '') + ':' + k\n      if (draft[key] != null) return draft[key]\n      const n = Number(r[k]) || 0\n      if (!dec) return n ? String(n) : ''\n      return n ? NUM.format(n) : ''\n    }\n    const total = (r) => (r.valorDireto ? val(r, 'valor') : val(r, 'preco') * val(r, 'quantidade'))\n\n    const sums = {}\n    CATS.forEach((c) => { sums[c.key] = 0 })\n    recs.forEach((r) => { sums[catOf(r)] += total(r) })\n    const grand = Object.values(sums).reduce((a, b) => a + b, 0)\n    const msums = {}\n    CATS.forEach((c) => { msums[c.key] = 0 })\n    const metas = S.metas || {}\n    CATS.forEach((c) => { msums[c.key] = parse(metas[c.key] != null ? metas[c.key] : '') })\n    const mgrand = Object.values(msums).reduce((a, b) => a + b, 0)\n    const orc = parse(S.orcamento != null ? S.orcamento : '')\n    let orcStatus = ''\n    if (orc > 0) {\n      const df = orc - grand\n      orcStatus = df > 0.005 ? `<small class=\"os under\">faltam ${money(df)}</small>` : df < -0.005 ? `<small class=\"os over\">passou ${money(-df)}</small>` : '<small class=\"os ok\">no orçamento</small>'\n    }\n    const last = recs.reduce((m, r) => (r.atualizadoEm && r.atualizadoEm > m ? r.atualizadoEm : m), '')\n    const lastTxt = last ? new Date(last).toLocaleString('pt-BR', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' }) : 'nunca'\n\n    const row = (r, i) => {\n      const id = esc(r._id || '')\n      const t = norm(r.ticker)\n      const u = upd[t]\n      const tot = total(r)\n      const cur = Number(r.preco) || 0\n      const prev = Number(r.precoAnterior) || 0\n      let delta = '<span class=\"d\"></span>'\n      if (!r.valorDireto && cur > 0 && prev > 0 && Math.abs(cur - prev) > 0.0001) {\n        const pc = (cur / prev - 1) * 100\n        const tip = `last price ${money(prev)} (${pc >= 0 ? '+' : ''}${pc.toFixed(2).replace('.', ',')}%)`\n        delta = cur > prev ? `<span class=\"d u\" title=\"${tip}\">▲</span>` : `<span class=\"d n\" title=\"${tip}\">▼</span>`\n      }\n      const lastCell = r.valorDireto ? '' : (prev > 0 ? NUM.format(prev) : '<span class=\"free\">-</span>')\n\n      const priceCell = r.valorDireto\n        ? `<span class=\"free\">valor livre</span>`\n        : `<input class=\"in p\" data-id=\"${id}\" data-k=\"preco\" value=\"${esc(shown(r, 'preco', true))}\" placeholder=\"0,00\">${delta}`\n      const qtyCell = r.valorDireto ? '' : `<input class=\"in q\" data-id=\"${id}\" data-k=\"quantidade\" value=\"${esc(shown(r, 'quantidade', false))}\" placeholder=\"0\">`\n      const totCell = r.valorDireto\n        ? `<input class=\"in v\" data-id=\"${id}\" data-k=\"valor\" value=\"${esc(shown(r, 'valor', true))}\" placeholder=\"R$ 0,00\">`\n        : money(tot)\n      if (catOf(r) === 'rendafixa') {\n        return `<tr data-key=\"${esc(r._id || 'pending-' + i)}\" data-rid=\"${id}\" data-cat=\"rendafixa\" class=\"${tot > 0 ? 'has' : ''}\">\n        <td><span class=\"tk\"><span class=\"grip ${sortBy !== 'manual' ? 'off' : ''}\" data-id=\"${id}\" title=\"Arraste para reordenar\">${GRIP}</span>${logo(d2, r.ticker, true)}<span class=\"rfn\">${esc(String(r.ticker || '').toUpperCase())}</span></span></td>\n        <td class=\"tot\">${totCell}</td>\n        <td style=\"padding:0\"><button class=\"del\" data-id=\"${id}\" data-t=\"${esc(r.ticker)}\" title=\"Remover\">×</button></td>\n      </tr>`\n      }\n      return `<tr data-key=\"${esc(r._id || 'pending-' + i)}\" data-rid=\"${id}\" data-cat=\"${esc(catOf(r))}\" class=\"${u ? 'up' : ''} ${tot > 0 ? 'has' : ''}\">\n        <td><span class=\"tk\"><span class=\"grip ${sortBy !== 'manual' ? 'off' : ''}\" data-id=\"${id}\" title=\"Arraste para reordenar\"><svg viewBox=\"0 0 8 14\" width=\"8\" height=\"14\" fill=\"currentColor\"><circle cx=\"2\" cy=\"2\" r=\"1.3\"/><circle cx=\"6\" cy=\"2\" r=\"1.3\"/><circle cx=\"2\" cy=\"7\" r=\"1.3\"/><circle cx=\"6\" cy=\"7\" r=\"1.3\"/><circle cx=\"2\" cy=\"12\" r=\"1.3\"/><circle cx=\"6\" cy=\"12\" r=\"1.3\"/></svg></span><span class=\"dot\"></span>${logo(d2, r.ticker, r.valorDireto)}<span class=\"tkn\" data-t=\"${esc(t)}\" title=\"Ver preço nos aportes\">${esc(String(r.ticker || '').toUpperCase())}</span></span></td>\n        <td class=\"lp\">${lastCell}</td>\n        <td>${priceCell}</td>\n        <td>${qtyCell}</td>\n        <td class=\"tot\">${totCell}</td>\n        <td style=\"padding:0\"><button class=\"del\" data-id=\"${id}\" data-t=\"${esc(r.ticker)}\" title=\"Remover\">×</button></td>\n      </tr>`\n    }\n\n    const sk = ''\n    const sd = S.sortDir === 'desc' ? -1 : 1\n    const sortBy = sk ? 'custom' : 'manual'\n    const SK_LABEL = { ticker: 'Ativo', precoAnterior: 'Last price', preco: 'Preço', quantidade: 'Qtd', total: 'Total' }\n    const sortRows = (arr) => {\n      const a = arr.slice()\n      if (!sk) return a\n      const kv = (r) => {\n        if (sk === 'ticker') return String(r.ticker || '')\n        if (sk === 'total') return total(r)\n        if (r.valorDireto) return null\n        return Number(r[sk]) || 0\n      }\n      a.sort((x, y) => {\n        const vx = kv(x), vy = kv(y)\n        if (vx === null && vy === null) return 0\n        if (vx === null) return 1\n        if (vy === null) return -1\n        if (typeof vx === 'string') return vx.localeCompare(vy) * sd\n        return (vx - vy) * sd\n      })\n      return a\n    }\n    const th = (k, label, al) => `<th class=\"sth ${sk === k ? 'on' : ''}\" data-sk=\"${k}\"${al ? ` style=\"text-align:${al}\"` : ''} title=\"Ordenar por ${label}\">${label}${sk === k ? (sd > 0 ? ' ▲' : ' ▼') : ''}</th>`\n\n    const cards = {}\n    CATS.forEach((c) => {\n      const list = recs.filter((r) => catOf(r) === c.key)\n      const vis = S.onlyBuy ? list.filter((r) => total(r) > 0.005) : list\n      const pct = grand > 0 ? (sums[c.key] / grand) * 100 : 0\n      const mt = msums[c.key]\n      let mst = ''\n      let mcls = ''\n      if (mt > 0) {\n        const TOL = 100\n        const df = mt - sums[c.key]\n        if (df < -TOL) { mcls = 'over'; mst = `<small class=\"os over\">passou ${money(-df)}</small>` }\n        else if (df > TOL) { mcls = 'under'; mst = `<small class=\"os under\">faltam ${money(df)}</small>` }\n        else {\n          mcls = 'ok'\n          const det = Math.abs(df) < 0.005 ? '' : df > 0 ? ` · faltam ${money(df)}` : ` · passou ${money(-df)}`\n          mst = `<small class=\"os ok\">na meta${det}</small>`\n        }\n      }\n      const barW = mt > 0 ? Math.min(100, (sums[c.key] / mt) * 100) : pct\n      cards[c.key] = `<section class=\"card\" data-key=\"col-${c.key}\">\n        <div class=\"ch\">\n          <div class=\"row1\"><h2>${c.label}<em>${S.onlyBuy ? `${vis.length} de ${list.length}` : list.length}</em></h2><span class=\"sub\">${money(sums[c.key])}</span></div>\n          <div class=\"mrow\"><span>Meta</span><input class=\"metain\" data-cat=\"${c.key}\" value=\"${esc(metas[c.key] != null ? metas[c.key] : '')}\" placeholder=\"R$ 0,00\">${mst}</div>\n          <div class=\"bar\"><i class=\"${mcls}\" style=\"width:${barW.toFixed(1)}%\"></i></div>\n          <div class=\"pct\">${pct.toFixed(1).replace('.', ',')}% do aporte${mt > 0 ? ` · ${Math.round((sums[c.key] / mt) * 100)}% da meta` : ''}</div>\n        </div>\n        <table>\n          <thead><tr>${c.free ? `${th('ticker', 'Título')}${th('total', 'Valor')}` : `${th('ticker', 'Ativo')}${th('precoAnterior', 'Last price')}${th('preco', 'Preço')}${th('quantidade', 'Qtd', 'center')}${th('total', 'Total')}`}<th></th></tr></thead>\n          <tbody>${vis.length ? sortRows(vis).map(row).join('') : `<tr data-key=\"empty-${c.key}\"><td colspan=\"${c.free ? 3 : 6}\" class=\"emptyrow\">Nada para comprar nesta categoria</td></tr>`}</tbody>\n        </table>\n        <div class=\"cf\"><button class=\"add\" data-cat=\"${c.key}\">${c.free ? '+ Adicionar título' : '+ Adicionar ativo'}</button></div>\n      </section>`\n    })\n\n    const miss = (S.missing || []).length\n      ? `<div class=\"miss\"><span class=\"lb\">Fora da sua lista:</span>${S.missing.map((m) =>\n        `<span class=\"chip\" data-key=\"m-${esc(m.ticker)}\">${logo(d2, m.ticker)}<b>${esc(m.ticker)}</b><em>${money(m.preco)}</em>\n          ${CATS.filter((c) => !c.free).map((c) => `<button class=\"addm\" data-t=\"${esc(m.ticker)}\" data-p=\"${m.preco}\" data-cat=\"${c.key}\">+ ${c.label}</button>`).join('')}\n        </span>`).join('')}<button class=\"link dismiss\">ignorar</button></div>`\n      : ''\n\n    const dropInner = S.importing\n      ? `<div class=\"ic\"><div class=\"spin\"></div></div><div class=\"t\"><b>Lendo a print…</b><span>Extraindo tickers e preço atual. A imagem não é salva.</span></div>`\n      : `<div class=\"ic\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M15 8h.01\"/><path d=\"M12 21H6a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v6\"/><path d=\"m3 16 5-5c.93-.9 2.07-.9 3 0l4 4\"/><path d=\"M19 22v-6\"/><path d=\"m22 19-3-3-3 3\"/></svg></div>\n         <div class=\"t\"><b>${S.armed ? 'Pronto, cole a print agora (Ctrl+V)' : 'Atualizar cotações pela print'}</b><span>${S.armed ? 'A área está ativa. ' : 'Clique aqui e cole com <span class=\"kbd\">Ctrl+V</span> (também funciona arrastando a imagem). '}Só o ticker e o preço atual são usados; a imagem é descartada.</span></div>`\n\n    const mob = S.mob != null ? S.mob : (typeof window !== 'undefined' && window.matchMedia ? window.matchMedia('(max-width: 767px)').matches : false)\n    if (mob) {\n      const stOf = (k) => {\n        const mt = msums[k]\n        if (!(mt > 0)) return { c: '', t: '' }\n        const df = mt - sums[k]\n        if (df < -100) return { c: 'over', t: `passou ${money(-df)}` }\n        if (df > 100) return { c: 'under', t: `faltam ${money(df)}` }\n        return { c: 'ok', t: Math.abs(df) < 0.005 ? 'na meta' : `na meta · ${df > 0 ? 'faltam' : 'passou'} ${money(Math.abs(df))}` }\n      }\n      const worst = (ks) => { const cs = ks.map((k) => stOf(k).c); return cs.includes('over') ? 'over' : cs.includes('under') ? 'under' : cs.includes('ok') ? 'ok' : '' }\n      const tab = S.mtab || 'acoes'\n      const TABS = [['acoes', 'Ações', ['acoes']], ['fiis', 'FIIs', ['fiis']], ['rfetf', 'RF + ETFs', ['rendafixa', 'etfs']]]\n      const tabsH = TABS.map((tb) => `<button class=\"mtab ${tab === tb[0] ? 'on' : ''}\" data-tab=\"${tb[0]}\"><span class=\"mtl\"><i class=\"mdot ${worst(tb[2])}\"></i>${tb[1]}</span><span class=\"mtv\">${money(tb[2].reduce((s, k) => s + sums[k], 0))}</span></button>`).join('')\n      const mrow = (r, i) => {\n        const id = esc(r._id || '')\n        const t = norm(r.ticker)\n        const tot = total(r)\n        const nm = esc(String(r.ticker || '').toUpperCase())\n        const grip = `<span class=\"grip mgrip\" data-id=\"${id}\" aria-hidden=\"true\">${GRIP}</span>`\n        const del = `<button class=\"mdel\" data-id=\"${id}\" data-t=\"${esc(r.ticker)}\" aria-label=\"Remover ${nm}\">×</button>`\n        const base = `data-key=\"${esc(r._id || 'pm-' + i)}\" data-rid=\"${id}\" data-cat=\"${esc(catOf(r))}\"`\n        if (r.valorDireto) {\n          return `<div class=\"mr ${tot > 0 ? 'has' : ''}\" ${base}><div class=\"mr1\">${grip}${logo(d2, r.ticker, true)}<span class=\"mtk\">${nm}</span><span class=\"sp\"></span><input class=\"in v\" data-id=\"${id}\" data-k=\"valor\" inputmode=\"decimal\" aria-label=\"Valor de ${nm}\" value=\"${esc(shown(r, 'valor', true))}\" placeholder=\"R$ 0,00\">${del}</div></div>`\n        }\n        const cur = Number(r.preco) || 0\n        const prev = Number(r.precoAnterior) || 0\n        let delta = ''\n        if (cur > 0 && prev > 0 && Math.abs(cur - prev) > 0.0001) delta = cur > prev ? '<span class=\"d u\">▲</span>' : '<span class=\"d n\">▼</span>'\n        return `<div class=\"mr ${tot > 0 ? 'has' : ''} ${upd[t] ? 'up' : ''}\" ${base}>\n          <div class=\"mr1\">${grip}${logo(d2, r.ticker)}<span class=\"tkn mtk\" data-t=\"${esc(t)}\">${nm}</span>${delta}<span class=\"sp\"></span><span class=\"mtot\">${money(tot)}</span>${del}</div>\n          <div class=\"mr2\"><input class=\"in p\" data-id=\"${id}\" data-k=\"preco\" inputmode=\"decimal\" aria-label=\"Preço de ${nm}\" value=\"${esc(shown(r, 'preco', true))}\" placeholder=\"0,00\"><span class=\"mlp\">${prev > 0 ? 'antes ' + NUM.format(prev) : ''}</span><span class=\"sp\"></span><button class=\"mstp\" data-id=\"${id}\" data-d=\"-1\" aria-label=\"Diminuir\">−</button><input class=\"in q\" data-id=\"${id}\" data-k=\"quantidade\" inputmode=\"numeric\" aria-label=\"Quantidade de ${nm}\" value=\"${esc(shown(r, 'quantidade', false))}\" placeholder=\"0\"><button class=\"mstp\" data-id=\"${id}\" data-d=\"1\" aria-label=\"Aumentar\">+</button></div>\n        </div>`\n      }\n      const msec = (c) => {\n        const list = recs.filter((r) => catOf(r) === c.key)\n        const vis = S.onlyBuy ? list.filter((r) => total(r) > 0.005) : list\n        const st = stOf(c.key)\n        const mt = msums[c.key]\n        const barW = mt > 0 ? Math.min(100, (sums[c.key] / mt) * 100) : 0\n        return `<section class=\"mcard\" data-key=\"mc-${c.key}\">\n          <div class=\"mch\"><div class=\"mch1\"><b>${c.label} <em>${S.onlyBuy ? `${vis.length} de ${list.length}` : list.length}</em></b><span class=\"msum\">${money(sums[c.key])}</span></div>\n          <div class=\"mmeta\"><span>Meta</span><input class=\"metain\" data-cat=\"${c.key}\" inputmode=\"decimal\" aria-label=\"Meta de ${c.label}\" value=\"${esc(metas[c.key] != null ? metas[c.key] : '')}\" placeholder=\"R$ 0,00\">${st.t ? `<small class=\"os ${st.c}\">${st.t}</small>` : ''}</div>\n          <div class=\"bar\"><i class=\"${st.c}\" style=\"width:${barW.toFixed(1)}%\"></i></div></div>\n          ${vis.length ? vis.map(mrow).join('') : '<div class=\"memp\">Nada para comprar nesta categoria</div>'}\n          <div class=\"mcf\"><button class=\"add\" data-cat=\"${c.key}\">${c.free ? '+ Adicionar título' : '+ Adicionar ativo'}</button></div>\n        </section>`\n      }\n      const keys = tab === 'rfetf' ? ['rendafixa', 'etfs'] : [tab]\n      const secs = CATS.filter((c) => keys.includes(c.key)).map(msec).join('')\n      const oc = orc > 0 ? (orc - grand > 0.005 ? 'under' : orc - grand < -0.005 ? 'over' : 'ok') : ''\n      const ot = oc === 'under' ? `faltam ${money(orc - grand)}` : oc === 'over' ? `passou ${money(grand - orc)}` : oc === 'ok' ? 'no orçamento' : ''\n      const usoTxt = S.uso && S.uso.limite ? `brapi: ${Math.max(0, S.uso.limite - S.uso.restantes).toLocaleString('pt-BR')}/${S.uso.limite.toLocaleString('pt-BR')} req. (30 dias)` : ''\n      const ICO_CLIP = '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"8\" y=\"2\" width=\"8\" height=\"4\" rx=\"1\"/><path d=\"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2\"/></svg>'\n      const hist = S.view === 'hist'\n      const bodyMain = `\n        <section class=\"mres\">\n          <div class=\"mres1\"><div><span class=\"mlab\">Total a investir</span><b class=\"mgr\">${money(grand)}</b></div><label class=\"morc\"><span class=\"mlab\">Orçamento</span><input class=\"orcin\" inputmode=\"decimal\" value=\"${esc(S.orcamento != null ? S.orcamento : '')}\" placeholder=\"R$ 0,00\"></label></div>\n          ${orc > 0 ? `<div class=\"bar\"><i class=\"${oc}\" style=\"width:${Math.min(100, (grand / orc) * 100).toFixed(1)}%\"></i></div>` : ''}\n          ${ot || mgrand > 0 ? `<div class=\"mres2\">${ot ? `<small class=\"os ${oc}\">${ot}</small>` : ''}${mgrand > 0 ? `<span>soma das metas ${money(mgrand)}</span>` : ''}</div>` : ''}\n        </section>\n        <section class=\"mpw\">\n          <button class=\"mpaste\" ${S.importing ? 'disabled' : ''}><span class=\"mpi\">${S.importing ? '<span class=\"spin\"></span>' : ICO_CLIP}</span><span class=\"mpt\"><b>${S.importing ? 'Lendo a print…' : 'Colar print da corretora'}</b><span>${S.importing ? 'A imagem não é salva.' : 'Copie a print e toque aqui'}</span></span></button>\n          <label class=\"mgal\">Galeria<input type=\"file\" accept=\"image/*\" class=\"mfile\"></label>\n        </section>\n        ${S.msg && !S.msheet ? `<div class=\"msg ${S.msg.type} mmsg\">${esc(S.msg.text)}</div>` : ''}\n        <nav class=\"mtabs\">${tabsH}</nav>\n        <div class=\"mtool\"><button class=\"mchip onlybtn ${S.onlyBuy ? 'on' : ''}\">Só o que vou comprar</button></div>\n        ${secs}`\n      const bodyHist = `<div class=\"mtool\"><button class=\"mchip histonly ${S.histOnly ? 'on' : ''}\">Só o que comprei</button></div>${renderHistMob(d2, recs)}`\n      const updL = Object.keys(S.updated || {}).map((k) => [k, S.updated[k]])\n      const sheetPrint = S.msheet && !S.importing ? `<div class=\"msh-ov\"><div class=\"msh\">\n          <div class=\"msh-hd\"><b>${esc(S.msg ? S.msg.text : 'Print lida')}</b><span>Só ticker e preço atual foram usados. A imagem foi descartada.</span></div>\n          ${updL.length ? `<div class=\"msh-l\"><div class=\"msh-r msh-th\"><span>Ativo</span><span>Antes</span><span>Agora</span></div>${updL.map((u) => `<div class=\"msh-r\" data-key=\"u-${esc(u[0])}\"><b>${esc(u[0])}</b><span>${u[1].de > 0 ? NUM.format(u[1].de) : '-'}</span><span class=\"${u[1].para >= u[1].de ? 'u' : 'n'}\">${NUM.format(u[1].para)}</span></div>`).join('')}</div>` : ''}\n          ${(S.missing || []).length ? `<span class=\"mlab\">Fora da sua lista</span>${S.missing.map((m) => `<div class=\"msh-m\" data-key=\"mm-${esc(m.ticker)}\"><b>${esc(m.ticker)}</b><span>${money(m.preco)}</span><span class=\"sp\"></span>${CATS.filter((c) => !c.free).map((c) => `<button class=\"addm\" data-t=\"${esc(m.ticker)}\" data-p=\"${m.preco}\" data-cat=\"${c.key}\">+ ${c.label}</button>`).join('')}</div>`).join('')}` : ''}\n          <div class=\"msh-b\"><label class=\"mbtn\">Escolher da galeria<input type=\"file\" accept=\"image/*\" class=\"mfile\"></label><button class=\"mbtn pri msheetok\">Pronto</button></div>\n        </div></div>` : ''\n      const sheetSave = S.confirmSave ? `<div class=\"msh-ov\"><div class=\"msh\">\n          <div class=\"msh-hd\"><b>Salvar aporte de hoje · ${money(grand)}</b><span>Guarda a data, o preço de todos os ativos (inclusive os sem compra) e as quantidades escolhidas.</span></div>\n          <input class=\"note mnote\" placeholder=\"Observação (opcional)\" maxlength=\"120\">\n          <div class=\"msh-b\"><button class=\"mbtn cancelsave\">Cancelar</button><button class=\"mbtn pri dosave\">${S.saving ? 'Salvando…' : 'Confirmar'}</button></div>\n        </div></div>` : ''\n      return `<div class=\"app mb\">\n        <header class=\"mtop\"><div class=\"mbr\"><div class=\"logo\">IM</div><div><b>Invest manager</b><small>Cotações de ${esc(lastTxt)}</small></div></div><div class=\"mtr\"><button class=\"mrl ${S.reloading ? 'on' : ''}\" ${S.reloading ? 'disabled' : ''}><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4\"/><path d=\"M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4\"/></svg>${S.reloading ? 'Atualizando…' : 'Atualizar'}</button><button class=\"mib mmenu\" aria-label=\"Mais ações\"><svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><circle cx=\"5\" cy=\"12\" r=\"2\"/><circle cx=\"12\" cy=\"12\" r=\"2\"/><circle cx=\"19\" cy=\"12\" r=\"2\"/></svg></button></div></header>\n        ${S.mmenu ? `<div class=\"mmw\"><button class=\"mmi refresh\" ${S.refreshing ? 'disabled' : ''}>${S.refreshing ? 'Atualizando…' : 'Atualizar preços (brapi)'}</button><button class=\"mmi zero\">Zerar quantidades</button><button class=\"mmi\" data-auth=\"sair\">Sair</button>${usoTxt ? `<div class=\"mmu\">${usoTxt}</div>` : ''}</div>` : ''}\n        <div class=\"mbody\">${hist ? bodyHist : bodyMain}<div class=\"mend\"></div></div>\n        <footer class=\"mfoot\">\n          ${hist ? '' : `<button class=\"msave save\" ${S.saving ? 'disabled' : ''}>Salvar aporte · ${money(grand)}</button>`}\n          <nav class=\"mnav\"><button class=\"mnb back ${hist ? '' : 'on'}\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M12 5v14\"/><path d=\"M5 12h14\"/></svg>Aporte</button><button class=\"mnb histbtn ${hist ? 'on' : ''}\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M3 12a9 9 0 1 0 3-6.7L3 8\"/><path d=\"M3 3v5h5\"/><path d=\"M12 7v5l4 2\"/></svg>Histórico</button></nav>\n        </footer>\n        ${sheetSave}${sheetPrint}\n        ${S.chart ? renderChart(d2, S.chart) : ''}\n      </div>`\n    }\n\n    return `<div class=\"app\">\n      <header class=\"top\">\n        <div class=\"brand\"><div class=\"logo\">IM</div><div><h1>Invest manager</h1><small>Cotações atualizadas em ${esc(lastTxt)} · <button class=\"link sairlk\" data-auth=\"sair\">sair</button></small>${S.uso && S.uso.limite ? (() => { const used = Math.max(0, S.uso.limite - S.uso.restantes); const pc = used / S.uso.limite; return `<small class=\"uso ${pc >= 0.9 ? 'crit' : pc >= 0.7 ? 'warn' : ''}\" title=\"Requisições usadas na brapi na janela móvel de 30 dias. Registrado em ${esc(fmtDT(S.uso.em))}\">brapi: ${used.toLocaleString('pt-BR')}/${S.uso.limite.toLocaleString('pt-BR')} req. (30 dias)</small>` })() : ''}</div></div>\n        <div class=\"kpis\">\n          <div class=\"kpi orc\"><span>Orçamento do aporte</span><input class=\"orcin\" value=\"${esc(S.orcamento != null ? S.orcamento : '')}\" placeholder=\"R$ 0,00\"></div>\n          ${mgrand > 0 ? `<div class=\"kpi\"><span>Soma das metas</span><b class=\"${orc > 0 && mgrand > orc + 0.005 ? 'ovr' : ''}\">${money(mgrand)}</b></div>` : ''}\n          <div class=\"kpi main\"><span>Total a investir</span><b>${money(grand)}</b>${orcStatus}</div>\n          ${S.view === 'hist' ? `<button class=\"btn histonly ${S.histOnly ? 'on' : ''}\">${S.histOnly ? 'Mostrar tudo' : 'Mostrar só o que comprei'}</button>` : `<button class=\"btn onlybtn ${S.onlyBuy ? 'on' : ''}\">${S.onlyBuy ? 'Mostrar tudo' : 'Mostrar só o que vou comprar'}</button>`}\n          <button class=\"btn zero\">Zerar quantidades</button>\n          <button class=\"btn refresh\" ${S.refreshing ? 'disabled' : ''}>${S.refreshing ? 'Atualizando…' : 'Atualizar preços'}</button>\n          ${S.view === 'hist' ? '<button class=\"btn back\">Voltar</button>' : '<button class=\"btn histbtn\">Histórico</button>'}\n          <button class=\"btn pri save\">${S.saving ? 'Salvando…' : 'Salvar aporte'}</button>\n        </div>\n      </header>\n      ${S.view === 'hist' ? renderHist(d2, recs) : `<div class=\"wrap\">\n        ${S.confirmSave ? `<div class=\"savebar\"><div class=\"st\"><b>Salvar aporte de hoje · ${money(grand)}</b><span>Guarda a data, o preço de todos os ativos (inclusive os sem compra) e as quantidades escolhidas.</span></div><input class=\"note\" placeholder=\"Observação (opcional)\" maxlength=\"120\"><button class=\"btn cancelsave\">Cancelar</button><button class=\"btn pri dosave\">${S.saving ? 'Salvando…' : 'Confirmar'}</button></div>` : ''}\n        <div class=\"drop ${S.over ? 'over' : ''} ${S.armed ? 'armed' : ''}\" tabindex=\"0\">${dropInner}</div>\n        ${S.msg ? `<div class=\"msg ${S.msg.type}\">${esc(S.msg.text)}</div>` : ''}\n        ${miss}\n        ${sk ? `<div class=\"tools\"><span>Ordenado por <b>${SK_LABEL[sk] || sk}</b> ${sd > 0 ? '(crescente)' : '(decrescente)'} · para arrastar e reordenar, <button class=\"link clrsort\">volte para a sua ordem</button></span></div>` : ''}\n        <div class=\"cols\">${layout(cards)}</div>\n      </div>`}\n      ${S.chart ? renderChart(d2, S.chart) : ''}\n    </div>`\n  },\n\n  updated(d2) { npSync(d2.state) },\n\n  mounted(d2) {\n    const S = d2.state\n    const mq = typeof window !== 'undefined' && window.matchMedia ? window.matchMedia('(max-width: 767px)') : null\n    const setMob = () => { const m = !!(mq && mq.matches); if (S.mob !== m) S.mob = m }\n    setMob()\n    d2.on(window, 'resize', setMob)\n    try {\n      if (!(d2.context && d2.context.isBuilder && !d2.context.isPlaying) && typeof document !== 'undefined' && document.head) {\n        if (!document.getElementById('invest-np-css')) { const st = document.createElement('style'); st.id = 'invest-np-css'; st.textContent = NP_CSS; document.head.appendChild(st) }\n        S.npOn = true\n        npSync(S)\n        d2.on(window, 'resize', () => npSync(S))\n        d2.on(window, 'scroll', () => npSync(S))\n        if (d2.onUnmount) d2.onUnmount(() => document.documentElement.classList.remove('inv-np'))\n      }\n    } catch (err) {}\n    const ds0 = d2.data('ativos')\n    if (ds0 && ds0.loadAll) {\n      Promise.resolve(ds0.loadAll()).then(async () => {\n        if (S.migrated) return\n        const ds = d2.data('ativos')\n        if (!ds || ds.loading) return\n        const recs = (ds.records() || []).filter((r) => r._id)\n        if (!recs.length) return\n        S.migrated = true\n        const jobs = []\n        const pos = (r) => RF_PADRAO.findIndex((nm) => norm(nm) === norm(r.ticker))\n        let etf = recs.filter((r) => r.categoria === 'etfs').reduce((mx, r) => Math.max(mx, Number(r.ordem) || 0), 0)\n        let extra = 10\n        recs.filter((r) => !CAT_KEYS.includes(r.categoria)).forEach((r) => {\n          const k = catOf(r)\n          if (k === 'rendafixa') { const p = pos(r); jobs.push(ds.update({ ...r, categoria: k, valorDireto: true, ordem: p >= 0 ? p + 1 : extra++ })) }\n          else { etf += 1; jobs.push(ds.update({ ...r, categoria: k, ordem: etf })) }\n        })\n        const have = recs.map((r) => norm(r.ticker))\n        RF_PADRAO.forEach((nm, p) => { if (!have.includes(norm(nm))) jobs.push(ds.create({ ticker: nm, categoria: 'rendafixa', valorDireto: true, valor: 0, preco: 0, quantidade: 0, ordem: p + 1 })) })\n        if (jobs.length) await Promise.all(jobs)\n      }).catch(() => {})\n    }\n    const hs0 = d2.data('aportes')\n    if (hs0 && hs0.loadAll) hs0.loadAll()\n    let cfgT = null\n    const saveCfg = () => {\n      clearTimeout(cfgT)\n      cfgT = setTimeout(async () => {\n        const cd = d2.data('config')\n        if (!cd) return\n        const rec = (cd.records() || []).find((r) => r.chave === 'geral')\n        const valor = { metas: S.metas || {}, orcamento: S.orcamento != null ? S.orcamento : '' }\n        try { if (rec && rec._id) await cd.update({ ...rec, valor }); else await cd.create({ chave: 'geral', valor }) } catch (err) {}\n      }, 600)\n    }\n    const syncCfg = async () => {\n      const cd = d2.data('config')\n      if (!cd || !cd.loadAll) return\n      try { await cd.loadAll() } catch (err) { return }\n      const rec = (cd.records() || []).find((r) => r.chave === 'geral')\n      if (rec && rec.valor) {\n        if (rec.valor.metas) S.metas = rec.valor.metas\n        if (rec.valor.orcamento != null) S.orcamento = rec.valor.orcamento\n        return\n      }\n      let lm = null, lo = null\n      try { lm = JSON.parse(window.localStorage.getItem('invest-metas') || 'null'); lo = window.localStorage.getItem('invest-orcamento') } catch (err) {}\n      if (lm) S.metas = lm\n      if (lo != null) S.orcamento = lo\n      if (lm || lo != null) saveCfg()\n    }\n    syncCfg()\n    d2.on('.orcin', 'input', (e, el) => { S.orcamento = el.value; saveCfg() })\n    d2.on('.orcin', 'keydown', (e, el) => { if (e.key === 'Enter') el.blur() })\n    d2.on('.metain', 'input', (e, el) => {\n      S.metas = { ...(S.metas || {}), [el.dataset.cat]: el.value }\n      saveCfg()\n    })\n    d2.on('.metain', 'keydown', (e, el) => { if (e.key === 'Enter') el.blur() })\n    d2.on('.tkn', 'click', (e, el) => { if (el.dataset.t) S.chart = el.dataset.t })\n    d2.on('.closechart', 'click', () => { S.chart = null })\n    d2.on('.ovl', 'click', (e, el) => { if (e.target === el) S.chart = null })\n    d2.on(window, 'keydown', (e) => { if (e.key === 'Escape' && S.chart) S.chart = null })\n\n\n    const findRec = (id) => (d2.data('ativos').records() || []).find((r) => r._id === id)\n    const nextOrder = (cat) => (d2.data('ativos').records() || []).filter((r) => r.categoria === cat).reduce((m, r) => Math.max(m, Number(r.ordem) || 0), 0) + 1\n\n    d2.on('.in', 'input', (e, el) => {\n      S.draft = { ...(S.draft || {}), [el.dataset.id + ':' + el.dataset.k]: el.value }\n    })\n    d2.on('.in', 'keydown', (e, el) => {\n      if (e.key === 'Enter') { el.blur(); return }\n      if (e.key === 'Tab' && (el.classList.contains('q') || el.classList.contains('v'))) {\n        const all = d2.$('.in.q, .in.v')\n        const nx = all[all.indexOf(el) + (e.shiftKey ? -1 : 1)]\n        if (nx) { e.preventDefault(); nx.focus(); try { nx.select() } catch (err) {} }\n      }\n    })\n    d2.on('.in', 'focus', (e, el) => { if (el.classList.contains('q') || el.classList.contains('v')) { try { el.select() } catch (err) {} } })\n    const loadUso = async () => {\n      try {\n        const j = await d2.rush(d2.param('rushUso')).invoke({})\n        const u = j && j.data && j.data.limite != null ? j.data : j\n        if (u && u.limite) S.uso = { limite: Number(u.limite), restantes: Number(u.restantes), em: u.em }\n      } catch (err) {}\n    }\n    loadUso()\n\n    // ---------- login / primeiro acesso / sair ----------\n    const lgVal = (id) => { const el = d2.$('#' + id); return el ? String(el.value || '').trim() : '' }\n    const recarregar = () => {\n      const a = d2.data('ativos'); if (a && a.loadAll) a.loadAll()\n      const h = d2.data('aportes'); if (h && h.loadAll) h.loadAll()\n      loadUso()\n      syncCfg()\n    }\n    d2.on('[data-lgin]', 'keydown', (e) => { if (e.key === 'Enter') { const b = d2.$('[data-auth=\"entrar\"],[data-auth=\"criar\"]'); if (b) b.click() } })\n    d2.on('[data-auth]', 'click', async (e, el) => {\n      const a = el.dataset.auth, au = d2.auth('auth')\n      if (!au) return\n      if (a === 'modo') { S.lg = { modo: (S.lg && S.lg.modo === 'cad') ? 'login' : 'cad', email: lgVal('lg-email') }; return }\n      if (a === 'sair') { try { await au.logout() } catch (err) {} try { const i0 = au.raw; if (i0 && i0.cursor) i0.cursor.current = null } catch (err) {} S.lg = {}; S.view = 'main'; S.chart = null; return }\n      const email = lgVal('lg-email').toLowerCase(), password = lgVal('lg-senha')\n      const modo = a === 'criar' ? 'cad' : 'login'\n      if (!email || !password) { S.lg = { modo, email, err: 'Preencha e-mail e senha.' }; return }\n      if (modo === 'cad' && password !== lgVal('lg-senha2')) { S.lg = { modo, email, err: 'As senhas não conferem.' }; return }\n      S.lg = { modo, email, busy: true }\n      let falhou = false\n      try {\n        if (modo === 'cad') {\n          let res = null\n          try { res = await d2.rush(d2.param('rushCriar')).invoke({ email, password }) } catch (err) { S.lg = { modo, email, err: 'Não foi possível criar. Esse passo só funciona pela rede de casa.' }; return }\n          const r = (res && res.data && typeof res.data === 'object') ? res.data : (res || {})\n          if (!r.ok) { S.lg = { modo, email, err: r.error || 'Não foi possível criar o acesso.' }; return }\n        }\n        const inst = au.raw\n        if (inst && inst.cursor) { if (!inst.cursor.current) inst.cursor.current = {}; inst.cursor.current.credentials = { email, password } }\n        if (inst && typeof inst.login === 'function') await inst.login({ credentials: { email, password } })\n        else await au.login({ credentials: { email, password } })\n      } catch (err) {\n        falhou = true\n        try { const i2 = au.raw; if (i2 && i2.cursor) i2.cursor.current = null } catch (e2) {}\n      }\n      const u = userOf(au)\n      if (!falhou && u && u.email) { S.lg = {}; recarregar() }\n      else S.lg = { modo: 'login', email, err: 'E-mail ou senha incorretos.' }\n    })\n\n    d2.on('.onlybtn', 'click', () => { S.onlyBuy = !S.onlyBuy })\n    d2.on('.refresh', 'click', async () => {\n      if (S.refreshing) return\n      S.refreshing = true\n      S.view = 'main'\n      S.msg = { type: 'ok', text: 'Buscando preços na brapi… isso leva alguns segundos.' }\n      const ds = d2.data('ativos')\n      const antes = {}\n      ;(ds.records() || []).forEach((r) => { antes[norm(r.ticker)] = Number(r.preco) || 0 })\n      try {\n        let out = null\n        try { out = await d2.rush(d2.param('rushPrecos')).invoke({}) } catch (err) { const st = err && err.response && err.response.status; throw new Error(st === 401 || st === 403 ? 'sem permissão (faça login de novo)' : (err && err.message) || 'erro ao atualizar') }\n        const r = (out && out.data && out.data.ok != null) ? out.data : out\n        if (ds.loadAll) await ds.loadAll()\n        else if (ds.refresh) await ds.refresh()\n        const upd = {}\n        ;(ds.records() || []).forEach((x) => {\n          const t = norm(x.ticker)\n          if (!x.valorDireto && antes[t] != null && Math.abs((Number(x.preco) || 0) - antes[t]) > 0.0001) upd[t] = { de: antes[t], para: Number(x.preco) || 0 }\n        })\n        S.updated = upd\n        const n = r && r.atualizados != null ? r.atualizados : Object.keys(upd).length\n        const mud = r && Array.isArray(r.mudaram) ? r.mudaram.length : Object.keys(upd).length\n        const sem = r && Array.isArray(r.semCotacao) && r.semCotacao.length ? ` · sem cotação: ${r.semCotacao.join(', ')}` : ''\n        S.msg = { type: 'ok', text: `Preços atualizados pela brapi: ${n} ativo(s) consultado(s), ${mud} com preço diferente${sem}.` }\n        if (r && r.uso && Number(r.uso.limite) > 0 && Number(r.uso.restantes) >= 0) S.uso = { limite: Number(r.uso.limite), restantes: Number(r.uso.restantes), em: new Date().toISOString() }\n        else loadUso()\n      } catch (err) {\n        S.msg = { type: 'err', text: 'Não consegui atualizar os preços: ' + (err && err.message ? err.message : err) }\n      } finally {\n        S.refreshing = false\n      }\n    })\n    try { window.localStorage.removeItem('invest-sort2') } catch (err) {}\n    const saveSort = () => { try { window.localStorage.setItem('invest-sort2', JSON.stringify({ k: S.sortKey || '', d: S.sortDir || 'asc' })) } catch (err) {} }\n    d2.on('.sth', 'click', async (e, el) => {\n      const k = el.dataset.sk\n      const sec = el.closest('section')\n      const cat = sec && sec.dataset.key ? sec.dataset.key.replace(/^col-/, '') : ''\n      if (!k || !CAT_KEYS.includes(cat)) return\n      const desc = S.sortKey === k + ':' + cat && S.sortDir !== 'desc'\n      S.sortKey = k + ':' + cat\n      S.sortDir = desc ? 'desc' : 'asc'\n      const sd = desc ? -1 : 1\n      const kv = (r) => {\n        if (k === 'ticker') return String(r.ticker || '')\n        if (k === 'total') return r.valorDireto ? Number(r.valor) || 0 : (Number(r.preco) || 0) * (Number(r.quantidade) || 0)\n        if (r.valorDireto) return null\n        return Number(r[k]) || 0\n      }\n      const ds = d2.data('ativos')\n      const list = (ds.records() || []).filter((r) => r._id && catOf(r) === cat).sort((a, b) => (Number(a.ordem) || 0) - (Number(b.ordem) || 0))\n      list.sort((x, y) => {\n        const vx = kv(x), vy = kv(y)\n        if (vx === null && vy === null) return 0\n        if (vx === null) return 1\n        if (vy === null) return -1\n        if (typeof vx === 'string') return vx.localeCompare(vy) * sd\n        return (vx - vy) * sd\n      })\n      await Promise.all(list.map((r, i) => (Number(r.ordem) !== i + 1 ? ds.update({ ...r, ordem: i + 1 }) : null)).filter(Boolean))\n    })\n    d2.on('.clrsort', 'click', () => { S.sortKey = ''; S.sortDir = 'asc'; saveSort() })\n    d2.on('.exec', 'change', async (e, el) => {\n      const hs = d2.data('aportes')\n      const rec = (hs.records() || []).find((h) => h._id === el.dataset.h)\n      if (!rec) return\n      const idx = Number(el.dataset.i)\n      const itens = (Array.isArray(rec.itens) ? rec.itens : []).map((it, i) => (i === idx ? { ...it, comprado: el.checked } : it))\n      await hs.update({ ...rec, itens: itens })\n    })\n    d2.on('.histonly', 'click', () => { S.histOnly = !S.histOnly })\n    d2.on('.rin', 'input', (e, el) => { S.hdraft = { ...(S.hdraft || {}), [el.dataset.h + ':' + el.dataset.i]: el.value } })\n    d2.on('.rin', 'keydown', (e, el) => { if (e.key === 'Enter') el.blur() })\n    d2.on('.rin', 'change', async (e, el) => {\n      const key = el.dataset.h + ':' + el.dataset.i\n      const hs = d2.data('aportes')\n      const rec = (hs.records() || []).find((h) => h._id === el.dataset.h)\n      const v = parse(el.value)\n      const ok = String(el.value || '').trim() !== '' && v > 0\n      if (rec) {\n        const idx = Number(el.dataset.i)\n        const itens = (Array.isArray(rec.itens) ? rec.itens : []).map((it, i) => (i === idx ? { ...it, totalReal: ok ? Math.round(v * 100) / 100 : null, comprado: ok } : it))\n        await hs.update({ ...rec, itens: itens })\n      }\n      const dr = { ...(S.hdraft || {}) }\n      delete dr[key]\n      S.hdraft = dr\n    })\n    d2.on('.in', 'change', async (e, el) => {\n      const key = el.dataset.id + ':' + el.dataset.k\n      const rec = findRec(el.dataset.id)\n      if (rec) {\n        const patch = { ...rec, [el.dataset.k]: parse(el.value) }\n        if (el.dataset.k === 'preco') {\n          patch.atualizadoEm = new Date().toISOString()\n          const old = Number(rec.preco) || 0\n          if (old > 0 && Math.abs(old - patch.preco) > 0.0001) patch.precoAnterior = old\n        }\n        await d2.data('ativos').update(patch)\n      }\n      const dr = { ...(S.draft || {}) }\n      delete dr[key]\n      S.draft = dr\n    })\n\n    d2.on('.drop', 'click', (e, el) => { if (!S.importing) { S.armed = true; try { el.focus({ preventScroll: true }) } catch (err) {} } })\n    d2.on(document, 'pointerdown', (e) => {\n      if (!S.armed) return\n      const path = (e.composedPath && e.composedPath()) || []\n      if (!path.some((n) => n && n.classList && n.classList.contains('drop'))) S.armed = false\n    })\n    d2.on(document, 'paste', (e) => {\n      const items = Array.from((e.clipboardData && e.clipboardData.items) || [])\n      const it = items.find((i) => String(i.type).startsWith('image/'))\n      if (it) { e.preventDefault(); importFile(d2, it.getAsFile()) }\n    })\n    const isFileDrag = (e) => !!(e.dataTransfer && Array.from(e.dataTransfer.types || []).includes('Files'))\n    d2.on('.app', 'dragover', (e) => { if (!isFileDrag(e)) return; e.preventDefault(); if (!S.over) S.over = true })\n    d2.on('.app', 'dragleave', (e) => { if (!e.relatedTarget && S.over) S.over = false })\n    d2.on('.app', 'drop', (e) => {\n      if (!isFileDrag(e)) return\n      e.preventDefault()\n      S.over = false\n      const f = e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files[0]\n      importFile(d2, f)\n    })\n\n    let drag = null\n    const clearMarks = () => d2.$$('.dropb, .dropa').forEach((n) => n.classList.remove('dropb', 'dropa'))\n    const endDrag = () => {\n      clearMarks()\n      d2.$$('.dragging').forEach((n) => n.classList.remove('dragging'))\n      const ap = d2.$('.app')\n      if (ap) ap.classList.remove('dragmode')\n    }\n    d2.on('.grip', 'pointerdown', (e, el) => {\n      if (e.button != null && e.button !== 0) return\n      e.preventDefault()\n      const tr = el.closest('[data-rid]')\n      if (!tr || !el.dataset.id) return\n      drag = { id: el.dataset.id, cat: tr.dataset.cat, target: null, after: false }\n      tr.classList.add('dragging')\n      const ap = d2.$('.app')\n      if (ap) ap.classList.add('dragmode')\n    })\n    d2.on(window, 'pointermove', (e) => {\n      if (!drag) return\n      const sr = d2.root && d2.root.getRootNode ? d2.root.getRootNode() : document\n      const hit = sr.elementFromPoint ? sr.elementFromPoint(e.clientX, e.clientY) : document.elementFromPoint(e.clientX, e.clientY)\n      const row = hit && hit.closest ? hit.closest('[data-rid]') : null\n      clearMarks()\n      if (!row || row.dataset.cat !== drag.cat || row.dataset.rid === drag.id) { drag.target = null; return }\n      const rc = row.getBoundingClientRect()\n      drag.after = e.clientY > rc.top + rc.height / 2\n      drag.target = row.dataset.rid\n      row.classList.add(drag.after ? 'dropa' : 'dropb')\n    })\n    d2.on(window, 'pointercancel', () => { drag = null; endDrag() })\n    d2.on(window, 'pointerup', async () => {\n      if (!drag) return\n      const d = drag\n      drag = null\n      endDrag()\n      if (!d.target || d.target === d.id) return\n      const ds = d2.data('ativos')\n      const list = (ds.records() || []).filter((r) => r._id && catOf(r) === d.cat).sort((a, b) => (Number(a.ordem) || 0) - (Number(b.ordem) || 0))\n      const from = list.findIndex((r) => r._id === d.id)\n      if (from < 0) return\n      const mv = list.splice(from, 1)[0]\n      let to = list.findIndex((r) => r._id === d.target)\n      if (to < 0) return\n      if (d.after) to += 1\n      list.splice(to, 0, mv)\n      await Promise.all(list.map((r, i) => (Number(r.ordem) !== i + 1 ? ds.update({ ...r, ordem: i + 1 }) : null)).filter(Boolean))\n    })\n\n    d2.on('.addm', 'click', async (e, el) => {\n      const t = el.dataset.t\n      const p = Number(el.dataset.p) || 0\n      const cat = el.dataset.cat\n      S.missing = (S.missing || []).filter((m) => m.ticker !== t)\n      S.updated = { ...(S.updated || {}), [t]: { de: 0, para: p } }\n      await d2.data('ativos').create({ ticker: t, categoria: cat, preco: p, quantidade: 0, ordem: nextOrder(cat), atualizadoEm: new Date().toISOString() })\n    })\n    d2.on('.dismiss', 'click', () => { S.missing = [] })\n\n    // ---------- mobile ----------\n    d2.on('.mtab', 'click', (e, el) => { if (el.dataset.tab) S.mtab = el.dataset.tab })\n    d2.on('.mmenu', 'click', () => { S.mmenu = !S.mmenu })\n    d2.on('.mmi', 'click', () => { S.mmenu = false })\n    d2.on('.mnb', 'click', () => { S.mmenu = false })\n    d2.on(document, 'pointerdown', (e) => {\n      if (!S.mmenu) return\n      const path = (e.composedPath && e.composedPath()) || []\n      if (!path.some((n) => n && n.classList && (n.classList.contains('mmw') || n.classList.contains('mmenu')))) S.mmenu = false\n    })\n    d2.on('.mstp', 'click', async (e, el) => {\n      const rec = findRec(el.dataset.id)\n      if (!rec) return\n      const key = el.dataset.id + ':quantidade'\n      const dr = S.draft || {}\n      const cur = dr[key] != null ? parse(dr[key]) : Number(rec.quantidade) || 0\n      const nv = Math.max(0, Math.round(cur + Number(el.dataset.d || 0)))\n      S.draft = { ...dr, [key]: String(nv) }\n      try { await d2.data('ativos').update({ ...(findRec(el.dataset.id) || rec), quantidade: nv }) } catch (err) {}\n      const d3 = { ...(S.draft || {}) }\n      if (d3[key] === String(nv)) { delete d3[key]; S.draft = d3 }\n    })\n    d2.on('.mdel', 'click', async (e, el) => {\n      if (!el.dataset.id) return\n      const ok = await d2.dialog.confirm(`Remover ${el.dataset.t} da lista?`)\n      if (ok) await d2.data('ativos').remove(el.dataset.id)\n    })\n    d2.on('.mhdel', 'click', async (e, el) => {\n      if (!el.dataset.id) return\n      const ok = await d2.dialog.confirm('Excluir este aporte do histórico?')\n      if (ok) {\n        await d2.data('aportes').remove(el.dataset.id)\n        if (S.histSel === el.dataset.id) S.histSel = null\n      }\n    })\n    d2.on('.mpaste', 'click', async () => {\n      if (S.importing) return\n      let blob = null\n      try {\n        if (navigator.clipboard && navigator.clipboard.read) {\n          const items = await navigator.clipboard.read()\n          for (const it of items) {\n            const t = (it.types || []).find((x) => String(x).startsWith('image/'))\n            if (t) { blob = await it.getType(t); break }\n          }\n        }\n      } catch (err) {}\n      if (blob) { await importFile(d2, blob); S.msheet = true; return }\n      const f = d2.$('.mfile')\n      if (f && f.click) { S.msg = { type: 'err', text: 'Não achei imagem copiada. Escolha a print na galeria.' }; f.click() }\n    })\n    d2.on('.mfile', 'change', async (e, el) => {\n      const f = el.files && el.files[0]\n      el.value = ''\n      if (f) { await importFile(d2, f); S.msheet = true }\n    })\n    d2.on('.msheetok', 'click', () => { S.msheet = false })\n    d2.on('.mrl', 'click', () => {\n      if (S.reloading) return\n      S.reloading = true\n      S.mmenu = false\n      setTimeout(() => { try { window.location.reload() } catch (err) { S.reloading = false } }, 50)\n    })\n\n    d2.on('.add', 'click', async (e, el) => {\n      const cat = el.dataset.cat\n      const rf = cat === 'rendafixa'\n      const raw = await d2.dialog.prompt(rf ? 'Nome do título (ex: IPCA+2035)' : 'Ticker do novo ativo (ex: VALE3)')\n      const t = norm(raw)\n      if (!t) return\n      const nome = rf ? String(raw).trim().toUpperCase() : t\n      if ((d2.data('ativos').records() || []).some((r) => norm(r.ticker) === t)) {\n        S.msg = { type: 'err', text: `${nome} já está na lista.` }\n        return\n      }\n      await d2.data('ativos').create(rf\n        ? { ticker: nome, categoria: cat, valorDireto: true, valor: 0, preco: 0, quantidade: 0, ordem: nextOrder(cat) }\n        : { ticker: t, categoria: cat, preco: 0, quantidade: 0, ordem: nextOrder(cat) })\n    })\n\n    d2.on('.del', 'click', async (e, el) => {\n      if (!el.dataset.id) return\n      const ok = await d2.dialog.confirm(`Remover ${el.dataset.t} da lista?`)\n      if (ok) await d2.data('ativos').remove(el.dataset.id)\n    })\n\n    d2.on('.histbtn', 'click', () => {\n      const h = d2.data('aportes')\n      if (h && h.refresh) h.refresh()\n      S.histSel = null\n      S.histOnly = true\n      S.view = 'hist'\n    })\n    d2.on('.back', 'click', () => { S.view = 'main' })\n    d2.on('.hi', 'click', (e, el) => {\n      if (e.target && e.target.closest && e.target.closest('.hdel')) return\n      if (el.dataset.id) S.histSel = el.dataset.id\n    })\n    d2.on('.hdel', 'click', async (e, el) => {\n      if (!el.dataset.id) return\n      const ok = await d2.dialog.confirm('Excluir este aporte do histórico?')\n      if (ok) {\n        await d2.data('aportes').remove(el.dataset.id)\n        if (S.histSel === el.dataset.id) S.histSel = null\n      }\n    })\n    d2.on('.save', 'click', () => {\n      if (S.saving) return\n      S.view = 'main'\n      S.confirmSave = true\n    })\n    d2.on('.cancelsave', 'click', () => { S.confirmSave = false })\n    d2.on('.note', 'keydown', (e) => { if (e.key === 'Enter') { const b = d2.$('.dosave'); if (b) b.click() } })\n    d2.on('.dosave', 'click', async () => {\n      if (S.saving) return\n      const ne = d2.$('.note')\n      const note = ne ? ne.value : ''\n      S.saving = true\n      try {\n        const itens = snapshot(d2)\n        const total = Math.round(itens.reduce((s, i) => s + (Number(i.total) || 0), 0) * 100) / 100\n        const when = new Date().toISOString()\n        await d2.data('aportes').create({ data: when, total: total, itens: itens, nota: String(note || '').trim() })\n        S.confirmSave = false\n        S.msg = { type: 'ok', text: `Aporte de ${money(total)} salvo em ${fmtDT(when)}. Marque o que for comprando no Histórico.` }\n      } catch (err) {\n        S.msg = { type: 'err', text: 'Não consegui salvar o aporte: ' + (err && err.message ? err.message : err) }\n      } finally {\n        S.saving = false\n      }\n    })\n\n    d2.on('.zero', 'click', async () => {\n      const ok = await d2.dialog.confirm('Zerar todas as quantidades e valores?')\n      if (!ok) return\n      const ds = d2.data('ativos')\n      const jobs = (ds.records() || []).filter((r) => r._id && ((Number(r.quantidade) || 0) !== 0 || (Number(r.valor) || 0) !== 0))\n        .map((r) => ds.update({ ...r, quantidade: 0, valor: 0 }))\n      await Promise.all(jobs)\n      S.draft = {}\n    })\n  },\n}"}},"aportes":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"aportes"}}}},"ativos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"ativos"}}}},"extrator":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"extrator"}}}},"auth":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"auth"}}}},"rushCriar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushCriar"}}}},"rushPrecos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushPrecos"}}}},"rushUso":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushUso"}}}},"config":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"config"}}}}}}}}}},{"_id":"6ac6ab5c5da28ca8d58c2780","component":"data2-core-types@Component","system":"686bd24b4fcbdb97284775e3","params":{"extends":"data2-core-primitives@Block","component":"GI_App_Principal","package":"massayuki-playground","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 EL = { Pyro: '#e04a45', Hydro: '#3fb0dc', Anemo: '#3fc3ad', Electro: '#9a7ae8', Dendro: '#8fcc3d', Cryo: '#9cc4f0', Geo: '#f0b866' };\n\nconst esc = (s) => String(s == null ? '' : s).replace(/[&<>\"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' }[c]));\nconst fmt = (n) => Math.round(n || 0).toLocaleString('pt-BR');\nconst signed = (p) => (p >= 0 ? '+' : '') + p.toFixed(1).replace('.', ',') + '%';\nconst buildStr = (c, r) => (c > 0 ? 'C' + c : '') + (r > 0 ? 'R' + r : '');\nconst mean = (xs) => (xs.length ? xs.reduce((a, b) => a + b, 0) / xs.length : 0);\nconst sleep = (ms) => new Promise((res) => setTimeout(res, ms));\nconst parseNum = (t) => { const n = parseFloat(String(t || '').replace(/\\./g, '').replace(',', '.')); return isNaN(n) || n <= 0 ? null : n; };\nconst keyOfBuilds = (builds) => builds.map((b) => b.characterId + ':C' + (b.constellation || 0) + 'R' + (b.refinement || 0)).sort().join('|');\nconst groupOf = (ids) => ids.slice().sort().join('|');\nconst dateBR = (d) => { if (!d) return ''; const x = new Date(d); return isNaN(x) ? '' : x.toLocaleDateString('pt-BR'); };\n\nconst ACTIONS = { rushDados: 'dados', rushRunAdd: 'runAdd', rushRunNote: 'runNote', rushRunDelete: 'runDelete', rushVersionDelete: 'versionDelete', rushTeamDelete: 'teamDelete', rushTeamRename: 'teamRename', rushTeamCreate: 'teamCreate', rushRoster: 'rosterSave', rushCatalog: 'catalogSave', rushEnka: 'enkaFetch', rushOnboard: 'onboardDone', rushRosto: 'rosto', rushPrint: 'lerPrint', rushAdminList: 'adminList', rushAdminAdd: 'adminAdd', rushAdminUpdate: 'adminUpdate', rushGerarCodigo: 'gerarCodigo', rushApelido: 'apelidoSave' };\n\nasync function callRush(d2, param, body) {\n  const res = await d2.rush(d2.param('rushDados')).invoke(Object.assign({}, body || {}, { action: ACTIONS[param] || param }));\n  const r = res && res.data && typeof res.data === 'object' && !Array.isArray(res.data) ? res.data : res;\n  return r || {};\n}\n\nasync function loadAllData(d2) {\n  for (let i = 0; i < 60 && d2.state.dataLoading; i++) await sleep(300);\n  d2.setState({ dataLoading: true });\n  let ok = false;\n  try {\n    const timeout = new Promise((res) => setTimeout(() => res({ ok: false, timeout: true }), 15000));\n    const r = await Promise.race([callRush(d2, 'rushDados', {}), timeout]);\n    if (r && r.ok) { d2.state.db = r; ok = true; }\n  } catch (e) {\n    ok = false;\n  }\n  d2.setState({ dataLoading: false, dataLoaded: true, loading: false, authed: ok });\n  return ok;\n}\n\nasync function loadAdmin(d2) {\n  try {\n    const r = await callRush(d2, 'rushAdminList', {});\n    d2.setState({ adm: r && r.ok ? r : { acessos: [], users: [] }, admErr: r && r.ok ? '' : 'Não foi possível carregar os acessos.' });\n  } catch (e) {\n    d2.setState({ adm: { acessos: [], users: [] }, admErr: 'Não foi possível carregar os acessos.' });\n  }\n}\n\nfunction adminPage(d2, M) {\n  const s = d2.state;\n  const A = s.adm;\n  const role = s.admRole || 'player';\n  const acessos = A ? A.acessos.slice().sort((a, b) => String(a.email).localeCompare(String(b.email))) : [];\n  const users = A ? A.users : [];\n  const activeAdmins = acessos.filter((x) => x.active && x.role === 'admin').length;\n  const rows = acessos.map((x) => {\n    const u = users.find((y) => String(y.email || '').toLowerCase() === String(x.email || '').toLowerCase());\n    const conta = u && !u.semSenha ? 'Conta criada' : 'Ainda não criou conta';\n    const locked = x.active && x.role === 'admin' && activeAdmins <= 1;\n    const isAdmin = x.role === 'admin';\n    return `<tr style=\"opacity:${x.active ? 1 : 0.55}\">\n      <td style=\"padding:12px 10px\"><b>${esc(x.email)}</b></td>\n      <td><span class=\"tag\" style=\"margin:0;background:${isAdmin ? '#b3121f' : '#3a2a2a'}\">${isAdmin ? 'Admin' : 'Jogador'}</span></td>\n      <td>${x.active ? 'Ativo' : 'Bloqueado'}</td>\n      <td class=\"muted\">${conta}</td>\n      <td><div class=\"row\" style=\"justify-content:flex-end;gap:8px\">\n        <button class=\"btn sm\" data-act=\"admUpd\" data-id=\"${x._id}\" data-role=\"${isAdmin ? 'player' : 'admin'}\" data-active=\"${x.active ? 1 : 0}\" ${locked || s.busy ? 'disabled title=\"Único admin ativo\"' : ''}>${isAdmin ? 'Tornar jogador' : 'Tornar admin'}</button>\n        <button class=\"btn sm\" style=\"color:#e8a3a3\" data-act=\"admUpd\" data-id=\"${x._id}\" data-role=\"${x.role}\" data-active=\"${x.active ? 0 : 1}\" ${locked || s.busy ? 'disabled title=\"Único admin ativo\"' : ''}>${x.active ? 'Bloquear' : 'Reativar'}</button>\n        <button class=\"btn sm\" data-act=\"admCode\" data-email=\"${esc(x.email)}\" ${u && !u.semSenha && !s.busy ? '' : 'disabled title=\"A pessoa ainda não criou a conta\"'}>Código de senha</button>\n      </div></td></tr>`;\n  }).join('');\n  const codeModal = s.admCode ? `<div class=\"overlay\"><div class=\"modal\"><h2 style=\"font-size:22px\">Código de redefinição</h2>\n    <div class=\"note\">Passe este código para <b>${esc(s.admCode.email)}</b>. Ele vale por 24 horas e só pode ser usado uma vez, na tela \"Esqueci a senha\".</div>\n    <div style=\"font-size:40px;font-weight:800;letter-spacing:.2em;text-align:center\">${esc(s.admCode.code)}</div>\n    <button class=\"btn primary\" data-act=\"admCloseCode\">Fechar</button></div></div>` : '';\n  return `<div class=\"app\"><div class=\"wrap\">\n    <div class=\"row between\">\n      <div><div class=\"kicker\">Genshin · DPS</div><div class=\"row\" style=\"gap:10px\"><h1>Acessos</h1><span class=\"tag\" style=\"background:#b3121f;margin:0\">ADMIN</span></div></div>\n      <button class=\"btn\" data-act=\"closeAdmin\">Voltar ao app</button>\n    </div>\n    <div class=\"panel\" style=\"gap:14px\">\n      <h2>Liberar novo acesso</h2>\n      <div class=\"row\" style=\"align-items:flex-end\">\n        <div style=\"flex:1 1 320px;display:flex;flex-direction:column;gap:6px\"><label class=\"f\" for=\"adm-email\">E-mail</label><input id=\"adm-email\" class=\"input dark\" placeholder=\"nome@gmail.com\" value=\"${esc(s.admEmail || '')}\" data-in=\"admEmail\" data-key-enter=\"admAdd\"></div>\n        <div style=\"display:flex;flex-direction:column;gap:6px\"><span class=\"f\">Papel</span><div class=\"seg\"><button class=\"${role === 'player' ? 'on' : ''}\" data-act=\"admRole\" data-v=\"player\">Jogador</button><button class=\"${role === 'admin' ? 'on' : ''}\" data-act=\"admRole\" data-v=\"admin\">Admin</button></div></div>\n        <button class=\"btn primary\" data-act=\"admAdd\" ${s.busy ? 'disabled' : ''}>Liberar acesso</button>\n      </div>\n      ${s.admMsg ? `<div class=\"muted\"><b>${esc(s.admMsg)}</b></div>` : ''}\n      <div class=\"muted\">A pessoa usa \"Criar conta\" com esse e-mail. Bloquear não apaga os dados dela.</div>\n    </div>\n    <div class=\"panel\" style=\"gap:14px\">\n      <div class=\"row between\"><h2>Pessoas com acesso</h2><span class=\"muted\">${acessos.filter((x) => x.active).length} ativos · ${activeAdmins} admin(s)</span></div>\n      ${s.admErr ? `<div class=\"warn\">${esc(s.admErr)}</div>` : ''}\n      ${A ? `<div style=\"overflow-x:auto\"><table><thead><tr><th>E-mail</th><th>Papel</th><th>Situação</th><th>Conta</th><th></th></tr></thead><tbody>${rows || '<tr><td colspan=\"5\" class=\"muted\">Ninguém liberado ainda.</td></tr>'}</tbody></table></div>` : '<div class=\"muted\">Carregando…</div>'}\n      <div class=\"muted\">O último admin ativo não pode ser bloqueado nem virar jogador. Mudanças de papel valem a partir do próximo login da pessoa.</div>\n    </div>\n  </div>${codeModal}</div>`;\n}\n\nconst norm = (t) => String(t || '').normalize('NFD').replace(/[\\u0300-\\u036f]/g, '').toLowerCase().replace(/[^a-z0-9 ]/g, ' ').replace(/\\s+/g, ' ').trim();\n\nfunction findChar(M, raw) {\n  const n = norm(raw);\n  if (!n) return { unknown: true };\n  if (/^(viajante|traveler|traveller)$/.test(n)) return { traveler: true };\n  const hit = M.chars.find((c) => [c.namePt, c.nameEn].concat(c.aliases || []).some((x) => norm(x) === n));\n  return hit ? { charId: hit._id } : { unknown: true };\n}\n\nasync function imageToDataUrl(file) {\n  const url = URL.createObjectURL(file);\n  try {\n    const img = await new Promise((res, rej) => { const i = new Image(); i.onload = () => res(i); i.onerror = rej; i.src = url; });\n    const max = 1400;\n    const scale = Math.min(1, max / Math.max(img.width, img.height));\n    const c = document.createElement('canvas');\n    c.width = Math.round(img.width * scale); c.height = Math.round(img.height * scale);\n    c.getContext('2d').drawImage(img, 0, 0, c.width, c.height);\n    return c.toDataURL('image/jpeg', 0.85);\n  } finally { URL.revokeObjectURL(url); }\n}\n\nasync function handlePrintFile(d2, file) {\n  if (!file || !/^image\\//.test(file.type || '')) { d2.setState({ pr: { stage: 'error', title: 'Arquivo não é uma imagem', msg: 'Envie a captura de tela do resultado de dano.' } }); return; }\n  if (d2.state.pr && (d2.state.pr.stage === 'reading' || d2.state.pr.stage === 'saving')) return;\n  d2.setState({ pr: { stage: 'reading' }, prToast: null });\n  let res = null;\n  try {\n    const image = await imageToDataUrl(file);\n    const r = await callRush(d2, 'rushPrint', { image });\n    res = r && r.result ? r.result : null;\n    if (typeof res === 'string') { try { res = JSON.parse(res); } catch (e) { res = null; } }\n  } catch (e) { d2.log(e); res = null; }\n  if (!res || res.ok === false || !Array.isArray(res.members) || !res.members.length || !res.dps) {\n    d2.setState({ pr: { stage: 'error', title: 'Não foi possível ler a imagem', msg: 'Nada foi registrado. Confira se a imagem é a tela de resultado de dano completa e envie de novo.' } });\n    return;\n  }\n  const M = model(d2);\n  const members = res.members.map((m) => Object.assign({ raw: m.name, damage: Math.round(+m.damage || 0), pct: m.pct }, findChar(M, m.name)));\n  const unknown = members.filter((m) => m.unknown);\n  if (unknown.length) { d2.setState({ pr: { stage: 'error', title: 'Personagem fora do catálogo', msg: unknown.map((m) => '\"' + m.raw + '\"').join(', ') + ' ainda não está cadastrado no app. Fale com o administrador pra incluir e envie a print de novo.' } }); return; }\n  const pr = { stage: 'review', dps: Math.round(+res.dps), total: Math.round(+res.totalDamage || 0), members, builds: {} };\n  d2.setState({ pr });\n}\n\nfunction printIssues(d2) {\n  const s = d2.state; const pr = s.pr; const M = model(d2);\n  const sum = pr.members.reduce((a, m) => a + (+m.damage || 0), 0);\n  const sumOk = !pr.total || Math.abs(sum - pr.total) <= Math.max(2, pr.total * 0.002);\n  const traveler = pr.members.some((m) => m.traveler && !m.charId);\n  const fewer = pr.members.length < 4;\n  const ids = pr.members.map((m) => m.charId).filter(Boolean);\n  const dupChar = ids.some((x, i) => ids.indexOf(x) !== i);\n  const missing = ids.filter((id) => !M.rosterBy[id] || M.rosterBy[id].owned === false);\n  return { sum, sumOk, traveler, fewer, dupChar, missing, needsInput: !sumOk || traveler || fewer || dupChar || missing.length > 0 };\n}\n\nasync function savePrint(d2) {\n  const pr = d2.state.pr;\n  const M0 = model(d2);\n  const dup = M0.runs.find((r) => Math.round(+r.dps) === Math.round(+pr.dps) && Math.round(+(r.totalDamage || 0)) === Math.round(+pr.total || 0));\n  if (dup) {\n    const dv = M0.versions.find((v) => v._id === dup.versionId);\n    const dt = M0.teams.find((t) => t._id === (dup.teamId || (dv && dv.teamId)));\n    d2.setState({ pr: { stage: 'error', title: 'Esse dano já foi registrado', msg: 'O DPS e o dano total são idênticos a um teste que você já tem' + (dt ? ' em ' + dt.label : '') + '. Como dois testes nunca dão exatamente o mesmo dano, nada foi registrado.' } });\n    return;\n  }\n  d2.setState({ pr: Object.assign({}, pr, { stage: 'saving' }) });\n  try {\n    let M = model(d2);\n    const ids = pr.members.map((m) => m.charId);\n    for (const id of ids) {\n      if (!M.rosterBy[id] || M.rosterBy[id].owned === false) {\n        const b = pr.builds[id] || { c: 0, r: 0 };\n        const r = await mustOk(d2, 'rushRoster', { characterId: id, constellation: +b.c || 0, refinement: +b.r || 0, owned: true });\n        applyData(d2, r);\n      }\n    }\n    M = model(d2);\n    const gk = groupOf(ids);\n    let team = M.teams.find((t) => groupOf(t.memberOrder || []) === gk);\n    let created = false;\n    if (!team) {\n      const label = (M.charById[ids[0]] || {}).namePt || 'Novo time';\n      const r = await mustOk(d2, 'rushTeamCreate', { groupKey: gk, label, memberOrder: ids, firstCharacterId: ids[0] });\n      applyData(d2, r);\n      M = model(d2);\n      team = M.teams.find((t) => t._id === r.teamId) || M.teams.find((t) => groupOf(t.memberOrder || []) === gk);\n      created = true;\n    }\n    const builds = M.currentBuilds(team.memberOrder || ids);\n    const breakdown = {};\n    pr.members.forEach((m) => { breakdown[m.charId] = Math.round(+m.damage || 0); });\n    const r = await mustOk(d2, 'rushRunAdd', { teamId: team._id, compositionKey: keyOfBuilds(builds), builds, dps: pr.dps, totalDamage: pr.total, breakdown, source: 'print' });\n    applyData(d2, r);\n    d2.setState({ pr: null, sel: team._id, selVersion: r.versionId, q: '', prToast: { text: (created ? 'Time novo criado e dano registrado: ' : 'Dano registrado em ') + team.label + ' · ' + fmt(pr.dps) } });\n  } catch (e) {\n    d2.log(e);\n    d2.setState({ pr: Object.assign({}, pr, { stage: 'review', err: 'Não foi possível registrar: ' + (e && e.message ? e.message : e) }) });\n  }\n}\n\nfunction renderPrint(d2) {\n  const s = d2.state; const pr = s.pr;\n  if (!pr) return '';\n  if (pr.stage === 'reading' || pr.stage === 'saving') return `<div class=\"overlay\"><div class=\"modal\" style=\"align-items:center\"><div class=\"loading\" style=\"height:auto\">${pr.stage === 'reading' ? 'Lendo a print…' : 'Registrando…'}</div></div></div>`;\n  if (pr.stage === 'error') return `<div class=\"overlay\"><div class=\"modal\"><div class=\"kicker\">Leitura da print</div><h2 style=\"font-size:22px\">${esc(pr.title)}</h2><div class=\"note\">${esc(pr.msg)}</div><button class=\"btn primary\" data-act=\"prDiscard\">Entendi</button></div></div>`;\n  const M = model(d2);\n  const I = printIssues(d2);\n  const travelers = M.chars.filter((c) => /^Viajante /.test(c.namePt));\n  const owned = Object.keys(M.rosterBy).filter((id) => M.rosterBy[id].owned !== false && M.charById[id]).sort((a, b) => M.charById[a].namePt.localeCompare(M.charById[b].namePt));\n  const rows = pr.members.map((m, i) => {\n    let who;\n    if (m.traveler) who = `<select data-pr=\"trav:${i}\"><option value=\"\">Qual elemento?</option>${travelers.map((c) => `<option value=\"${c._id}\" ${c._id === m.charId ? 'selected' : ''}>${esc(c.namePt)}</option>`).join('')}</select>`;\n    else if (m.added) who = `<select data-pr=\"slot:${i}\"><option value=\"\">Escolha</option>${owned.map((id) => `<option value=\"${id}\" ${id === m.charId ? 'selected' : ''}>${esc(M.charById[id].namePt)}</option>`).join('')}</select>`;\n    else { const c = M.charById[m.charId]; who = `<div class=\"row\" style=\"gap:10px\">${avatar(c, null, 36)}<b>${esc(c ? c.namePt : '?')}</b></div>`; }\n    return `<tr><td class=\"muted\">${esc(m.raw || '—')}</td><td>${who}</td><td class=\"r\"><input class=\"input dark\" style=\"height:34px;width:130px;text-align:right\" value=\"${esc(String(m.damage))}\" data-pr=\"dmg:${i}\"></td></tr>`;\n  }).join('');\n  const missing = I.missing.map((id) => {\n    const c = M.charById[id] || {}; const b = pr.builds[id] || { c: 0, r: 0 };\n    return `<div class=\"row\" style=\"gap:10px\"><b style=\"min-width:150px\">${esc(c.namePt || '?')}</b>\n      <select data-pr=\"c:${id}\" style=\"width:auto\">${[0, 1, 2, 3, 4, 5, 6].map((n) => `<option value=\"${n}\" ${+b.c === n ? 'selected' : ''}>C${n}</option>`).join('')}</select>\n      <select data-pr=\"r:${id}\" style=\"width:auto\">${[0, 1, 2, 3, 4, 5].map((n) => `<option value=\"${n}\" ${+b.r === n ? 'selected' : ''}>${n ? 'R' + n : 'Sem signature'}</option>`).join('')}</select></div>`;\n  }).join('');\n  const msgs = [];\n  if (!I.sumOk) msgs.push(`A soma dos personagens (${fmt(I.sum)}) não bate com o dano total. Confira os números lidos.`);\n  if (I.traveler) msgs.push('A print mostra só \"Viajante\". Escolha qual elemento foi usado.');\n  if (I.fewer) msgs.push('A print tem menos de 4 personagens. Escolha quem completa o time ou descarte.');\n  if (I.dupChar) msgs.push('Um personagem aparece duas vezes.');\n  const canSave = I.sumOk && !pr.members.some((m) => !m.charId) && !I.dupChar && pr.members.length === 4;\n  const dIds = pr.members.map((m) => m.charId);\n  let dest = '';\n  if (dIds.length === 4 && dIds.every(Boolean) && !I.dupChar) {\n    const dT = M.teams.find((t) => groupOf(t.memberOrder || []) === groupOf(dIds));\n    dest = dT ? `Vai registrar no time <b>${esc(dT.label)}</b>.` : `Nenhum time seu tem esses 4 personagens: vai criar o time <b>${esc((M.charById[dIds[0]] || {}).namePt || 'Novo time')}</b>.`;\n  }\n  return `<div class=\"overlay\"><div class=\"modal\" style=\"max-width:720px;max-height:90vh;overflow:auto\">\n    <div class=\"kicker\">Leitura da print</div><h2 style=\"font-size:22px\">Confira antes de registrar</h2>\n    ${msgs.map((t) => `<div class=\"warn\">${esc(t)}</div>`).join('')}\n    ${pr.err ? `<div class=\"warn\">${esc(pr.err)}</div>` : ''}\n    <div class=\"grid4\" style=\"grid-template-columns:repeat(2,minmax(0,1fr))\">\n      <div style=\"display:flex;flex-direction:column;gap:6px\"><label class=\"f\">DPS</label><input class=\"input dark\" value=\"${esc(String(pr.dps))}\" data-pr=\"dps\"></div>\n      <div style=\"display:flex;flex-direction:column;gap:6px\"><label class=\"f\">Dano total</label><input class=\"input dark\" value=\"${esc(String(pr.total))}\" data-pr=\"total\"></div>\n    </div>\n    <div style=\"overflow-x:auto\"><table><thead><tr><th>Na print</th><th>Personagem no app</th><th class=\"r\">Dano</th></tr></thead><tbody>${rows}</tbody></table></div>\n    ${I.fewer ? `<button class=\"btn sm\" data-act=\"prAddSlot\" style=\"align-self:flex-start\">+ Adicionar personagem</button>` : ''}\n    ${missing ? `<div class=\"note\" style=\"display:flex;flex-direction:column;gap:10px\"><b>Personagens que não estavam na sua conta. Qual constelação e arma?</b>${missing}</div>` : ''}\n    ${dest ? `<div class=\"note\">${dest}</div>` : ''}\n    <div class=\"row\"><button class=\"btn primary\" data-act=\"prSave\" ${canSave ? '' : 'disabled'}>Confirmar e registrar</button><button class=\"btn\" data-act=\"prDiscard\">Descartar</button></div>\n  </div></div>`;\n}\n\nfunction prInput(d2, el) {\n  if (!el || !d2.state.pr) return;\n  const pr = d2.state.pr;\n  const k = el.getAttribute('data-pr');\n  const v = el.value;\n  const parts = k.split(':'); const t = parts[0]; const x = parts[1];\n  const num = (q) => Math.round(+String(q).replace(/\\./g, '').replace(',', '.')) || 0;\n  if (t === 'dps') pr.dps = num(v);\n  else if (t === 'total') pr.total = num(v);\n  else if (t === 'dmg') pr.members[+x].damage = num(v);\n  else if (t === 'trav' || t === 'slot') pr.members[+x].charId = v || null;\n  else if (t === 'c' || t === 'r') { pr.builds[x] = Object.assign({ c: 0, r: 0 }, pr.builds[x]); pr.builds[x][t] = +v; }\n  d2.setState({ pr: Object.assign({}, pr, { members: pr.members.slice(), builds: Object.assign({}, pr.builds) }) });\n  d2.refresh();\n}\n\nconst EL_ORDER = ['Pyro', 'Hydro', 'Anemo', 'Electro', 'Dendro', 'Cryo', 'Geo'];\n\nfunction charsPage(d2, M) {\n  const s = d2.state;\n  const isAdmin = M.me.role === 'admin';\n  const q = norm(s.chQ || '');\n  const sortBy = s.chSort || 'name';\n  const own = (id) => M.rosterBy[id] && M.rosterBy[id].owned !== false;\n  const ownF = s.chOwnF || 'all';\n  const elF = sortBy === 'element' ? (s.chElF || null) : null;\n  const list = M.chars.filter((c) => !q || [c.namePt, c.nameEn].concat(c.aliases || []).some((x) => norm(x).includes(q)))\n    .filter((c) => ownF === 'all' || (ownF === 'have' ? own(c._id) : !own(c._id)))\n    .filter((c) => !elF || c.element === elF)\n    .sort((a, b) => a.namePt.localeCompare(b.namePt));\n  const cell = (c) => {\n    const r = M.rosterBy[c._id];\n    const b = own(c._id) ? { constellation: r.constellation || 0, refinement: r.refinement || 0 } : null;\n    return `<button class=\"chcell ${s.chSel === c._id ? 'on' : ''}\" style=\"opacity:${own(c._id) ? 1 : 0.4}\" data-act=\"chSel\" data-id=\"${c._id}\" data-key=\"ch-${c._id}\" title=\"${esc(c.namePt)}\">${avatar(c, b, 56)}<span class=\"n\">${esc(c.namePt)}</span></button>`;\n  };\n  let grid;\n  if (sortBy === 'element') {\n    grid = EL_ORDER.concat(['']).map((el) => {\n      const its = list.filter((c) => (c.element || '') === el);\n      if (!its.length) return '';\n      return `<div class=\"row\" style=\"gap:8px;padding:6px 0;border-bottom:1px solid #211a1a\"><span style=\"width:12px;height:12px;border-radius:50%;background:${EL[el] || '#6b5a5a'}\"></span><b style=\"font-size:13px\">${el || 'Sem elemento'}</b><span class=\"muted\">${its.length}</span></div><div class=\"chgrid\">${its.map(cell).join('')}</div>`;\n    }).join('');\n  } else grid = `<div class=\"chgrid\">${list.map(cell).join('')}</div>`;\n  if (!list.length) grid = `<div class=\"note\">Nenhum personagem com esses filtros.</div>`;\n  const ownLabel = { all: 'Mostrando: todos', have: 'Só os que tenho', missing: 'Só os que não tenho' }[ownF];\n  const dots = sortBy === 'element' ? `<div class=\"row\" style=\"gap:6px\">${EL_ORDER.map((el) => `<button class=\"eldot ${elF === el ? 'on' : ''}\" title=\"${el}\" data-act=\"chElF\" data-v=\"${el}\" style=\"background:${EL[el]}\"></button>`).join('')}</div>` : '';\n  const ownedCount = M.chars.filter((c) => own(c._id)).length;\n\n  const c = M.charById[s.chSel] || null;\n  let panel = `<div class=\"panel\"><div class=\"note\">Escolha um personagem na grade pra ver e ajustar o build da sua conta.</div></div>`;\n  if (c) {\n    const r = M.rosterBy[c._id] || {};\n    const owned = own(c._id);\n    const cc = owned ? (r.constellation || 0) : 0;\n    const rr = owned ? (r.refinement || 0) : 0;\n    const usage = M.teamInfo.filter((x) => (x.t.memberOrder || []).indexOf(c._id) >= 0);\n    const seg = (vals, cur, act, label) => `<div class=\"seg\" style=\"flex-wrap:wrap\">${vals.map((v) => `<button class=\"${cur === v ? 'on' : ''}\" data-act=\"${act}\" data-v=\"${v}\" ${owned && !s.busy ? '' : 'disabled'}>${label(v)}</button>`).join('')}</div>`;\n    const usageRows = usage.map((x) => {\n      const show = x.best;\n      const b = show ? show.v.builds.find((y) => y.characterId === c._id) : null;\n      const snap = b ? (buildStr(b.constellation, b.refinement) || 'C0') : '—';\n      const outdated = b && (b.constellation !== cc || (b.refinement || 0) !== rr);\n      return `<div class=\"row between note\" style=\"border:1px solid ${outdated ? '#b3121f' : 'transparent'}\"><span><b>${esc(x.t.label)}</b> <span class=\"muted\">· testado com ${snap}</span></span>${outdated ? '<span class=\"tag\" style=\"background:#b3121f;margin:0\">build anterior</span>' : ''}</div>`;\n    }).join('');\n    const adminBox = isAdmin ? `<div class=\"note\" style=\"display:flex;flex-direction:column;gap:10px\"><b>Catálogo (admin) · vale pra todos os jogadores</b>\n        <div class=\"row\"><label class=\"btn sm\" for=\"phfile\" style=\"display:inline-flex;align-items:center\">${String(c.iconUrl || '').trim() ? 'Trocar foto' : 'Adicionar foto'}</label><input id=\"phfile\" type=\"file\" accept=\"image/*\" data-phfile style=\"display:none\">${String(c.iconUrl || '').trim() ? '<button class=\"btn sm\" data-act=\"phRemove\" style=\"color:#e8a3a3\">Tirar foto</button>' : ''}<span class=\"muted\">Pode ser qualquer imagem do personagem: o app acha o rosto e recorta.</span></div>\n        <div class=\"seg\" style=\"flex-wrap:wrap\">${EL_ORDER.map((el) => `<button class=\"${c.element === el ? 'on' : ''}\" data-act=\"chEl\" data-v=\"${el}\" ${s.busy ? 'disabled' : ''}>${el}</button>`).join('')}</div>\n        <label class=\"f\" for=\"ch-alias\">Aliases (separados por vírgula)</label>\n        <div class=\"row\"><input id=\"ch-alias\" class=\"input dark\" style=\"flex:1 1 240px\" value=\"${esc(s.chAliasDraft !== undefined && s.chAliasFor === c._id ? s.chAliasDraft : (c.aliases || []).join(', '))}\" data-in=\"chAliasDraft\" data-key-enter=\"chAliasSave\"><button class=\"btn sm\" data-act=\"chAliasSave\">Salvar aliases</button></div>\n        <div class=\"muted\">Nome em inglês: ${esc(c.nameEn || '—')} · ID Enka: ${esc((c.enkaIds || []).join(', ') || '—')}</div>\n      </div>` : '';\n    const confirm = s.chConfirmRemove === c._id ? `<div class=\"warn row between\"><span style=\"flex:1 1 260px\">${esc(c.namePt)} está em ${usage.length} ${usage.length > 1 ? 'times seus' : 'time seu'}. Os times e testes continuam, mas ele deixa de aparecer na hora de montar times novos.</span><span class=\"row\" style=\"gap:8px\"><button class=\"btn sm primary\" data-act=\"chOwnConfirm\">Remover mesmo assim</button><button class=\"btn sm\" data-act=\"chOwnCancel\">Cancelar</button></span></div>` : '';\n    panel = `<div class=\"panel\">\n      <div class=\"row\" style=\"gap:20px;align-items:center\">${avatar(c, owned ? { constellation: cc, refinement: rr } : null, 120)}\n        <div style=\"display:flex;flex-direction:column;gap:6px\"><div style=\"font-size:26px;font-weight:800\">${esc(c.namePt)}</div>\n          <div class=\"row\" style=\"gap:8px\"><span style=\"width:12px;height:12px;border-radius:50%;background:${EL[c.element] || '#6b5a5a'}\"></span><b>${esc(c.element || 'Elemento não definido')}</b><span class=\"muted\">· ${c.rarity || '?'}★</span></div></div></div>\n      <div class=\"row between note\"><div><b>${owned ? 'Você tem este personagem' : 'Você não tem este personagem'}</b><div class=\"muted\">${owned ? 'Constelação e arma valem só pra sua conta.' : 'Só personagens que você tem aparecem na hora de montar times.'}</div></div>\n        <button class=\"btn sm ${owned ? '' : 'primary'}\" data-act=\"chOwn\" ${s.busy ? 'disabled' : ''}>${owned ? 'Remover da conta' : 'Adicionar à conta'}</button></div>\n      ${confirm}\n      <div style=\"display:flex;flex-direction:column;gap:8px;opacity:${owned ? 1 : 0.4}\"><span class=\"f\">Constelação</span>${seg([0, 1, 2, 3, 4, 5, 6], cc, 'chC', (v) => 'C' + v)}</div>\n      <div style=\"display:flex;flex-direction:column;gap:8px;opacity:${owned ? 1 : 0.4}\"><span class=\"f\">Arma signature · clique de novo no R pra tirar</span>${seg([0, 1, 2, 3, 4, 5], rr, 'chR', (v) => (v ? 'R' + v : 'Sem signature'))}</div>\n      ${adminBox}\n      <div style=\"display:flex;flex-direction:column;gap:8px\"><h3>Usado em ${usage.length} ${usage.length === 1 ? 'time' : 'times'}</h3>${usageRows || '<div class=\"muted\">Ainda não está em nenhum time.</div>'}</div>\n    </div>`;\n  }\n  return `<div class=\"app\"><div class=\"wrap\">\n    <div class=\"row between\">\n      <div><div class=\"kicker\">Genshin · DPS</div><h1>Personagens</h1><div class=\"muted\">${ownedCount} de ${M.chars.length} na sua conta</div></div>\n      <div class=\"row\"><input class=\"input dark\" style=\"width:170px\" inputmode=\"numeric\" placeholder=\"UID\" value=\"${esc(s.uidDraft !== undefined ? s.uidDraft : (M.me.uid || ''))}\" data-in=\"uidDraft\" data-key-enter=\"chSync\"><button class=\"btn sm primary\" data-act=\"chSync\" ${s.syncBusy ? 'disabled' : ''}>${s.syncBusy ? 'Sincronizando…' : 'Sincronizar pela vitrine'}</button><button class=\"btn\" data-act=\"closeChars\">Voltar ao app</button></div>\n    </div>\n    <div class=\"muted\">A sincronização só adiciona e atualiza: quem sair da vitrine continua na sua conta.${M.me.nickname ? ' · Jogador: ' + esc(M.me.nickname) : ''}</div>\n    ${s.syncMsg ? `<div class=\"${s.syncMsg.err ? 'warn' : 'toast'}\">${esc(s.syncMsg.text)}</div>` : ''}\n    <div class=\"cols\">\n      <div class=\"panel\" style=\"gap:12px\">\n        <div class=\"row between\"><div class=\"row\" style=\"gap:10px\"><div class=\"seg\"><button class=\"${sortBy === 'name' ? 'on' : ''}\" data-act=\"chSort\" data-v=\"name\">Nome</button><button class=\"${sortBy === 'element' ? 'on' : ''}\" data-act=\"chSort\" data-v=\"element\">Elemento</button></div>${dots}<button class=\"btn sm\" data-act=\"chOwnF\">${ownLabel}</button></div>\n          <input class=\"input dark\" style=\"width:220px\" placeholder=\"Buscar\" value=\"${esc(s.chQ || '')}\" data-in=\"chQ\"></div>\n        ${grid}\n      </div>\n      ${panel}\n    </div>\n  </div>${renderSyncConf(d2)}${renderPhoto(d2, M)}</div>`;\n}\n\nasync function saveRoster(d2, id, patch) {\n  const M = model(d2);\n  const r = M.rosterBy[id] || {};\n  const cur = { constellation: r.constellation || 0, refinement: r.refinement || 0, owned: r.owned !== false && !!M.rosterBy[id] };\n  const next = Object.assign(cur, patch);\n  const res = await mustOk(d2, 'rushRoster', { characterId: id, constellation: next.constellation, refinement: next.refinement, owned: next.owned });\n  applyData(d2, res);\n}\n\nasync function syncFromEnka(d2, gameUid) {\n  const uidTxt = String(gameUid || '').trim();\n  if (!/^\\d{9,10}$/.test(uidTxt)) { d2.setState({ syncMsg: { err: true, text: 'Digite um UID válido (9 ou 10 números).' } }); return; }\n  d2.setState({ syncBusy: true, syncMsg: null });\n  try {\n    const r = await callRush(d2, 'rushEnka', { gameUid: uidTxt });\n    if (!r.ok) { d2.setState({ syncBusy: false, syncMsg: { err: true, text: r.error || 'Não foi possível consultar o Enka.' } }); return; }\n    d2.state.db.me = Object.assign({}, d2.state.db.me, { uid: uidTxt, nickname: r.nickname });\n    if (!Array.isArray(r.avatars) || !r.avatars.length) {\n      d2.setState({ syncBusy: false, syncMsg: { err: true, text: 'O UID existe, mas a vitrine está oculta ou vazia. No jogo, abra o Perfil, entre em Vitrine de Personagens, ative a exibição de detalhes dos personagens e tente de novo em alguns minutos.' } });\n      return;\n    }\n    const M = model(d2);\n    const byEnka = {};\n    M.chars.forEach((c) => (c.enkaIds || []).forEach((k) => { byEnka[String(k)] = c; }));\n    const auto = []; const conflicts = []; const unknown = [];\n    r.avatars.forEach((a) => {\n      const c = byEnka[String(a.avatarId) + '-' + String(a.skillDepotId)] || byEnka[String(a.avatarId)];\n      if (!c) { unknown.push(a.avatarId); return; }\n      const vc = (a.talentIdList || []).length;\n      const w = (a.equipList || []).find((e) => e.flat && e.flat.itemType === 'ITEM_WEAPON');\n      const vref = w && w.weapon && w.weapon.affixMap ? (+Object.values(w.weapon.affixMap)[0] || 0) + 1 : 0;\n      const isSig = !!(w && c.signatureWeaponId && String(w.itemId) === String(c.signatureWeaponId));\n      const cur = M.rosterBy[c._id];\n      const owned = cur && cur.owned !== false;\n      const cc = owned ? (cur.constellation || 0) : 0;\n      const cr = owned ? (cur.refinement || 0) : 0;\n      const nextC = owned ? Math.max(cc, vc) : vc;\n      const nextR = isSig ? vref : cr;\n      const item = { id: c._id, name: c.namePt, cc, cr, vc, vref, isSig, nextC, nextR, owned };\n      const lowerC = owned && vc < cc;\n      const lostSig = owned && cr > 0 && !!c.signatureWeaponId && !isSig;\n      if (lowerC || lostSig) { item.lowerC = lowerC; item.lostSig = lostSig; item.choiceC = 'keep'; item.choiceR = 'keep'; conflicts.push(item); }\n      else if (!owned || nextC !== cc || nextR !== cr) auto.push(item);\n    });\n    for (const it of auto) await saveRoster(d2, it.id, { owned: true, constellation: it.nextC, refinement: it.nextR });\n    const summary = { synced: auto.length, same: r.avatars.length - auto.length - conflicts.length - unknown.length, unknown: unknown.length, nickname: r.nickname };\n    if (conflicts.length) d2.setState({ syncBusy: false, syncConf: { items: conflicts, summary } });\n    else d2.setState({ syncBusy: false, syncMsg: { text: syncText(summary) } });\n  } catch (e) {\n    d2.log(e);\n    d2.setState({ syncBusy: false, syncMsg: { err: true, text: 'Não foi possível sincronizar agora. Tente de novo em instantes.' } });\n  }\n}\n\nfunction syncText(sm) {\n  const parts = [(sm.nickname ? sm.nickname + ': ' : '') + sm.synced + (sm.synced === 1 ? ' personagem atualizado' : ' personagens atualizados')];\n  if (sm.same) parts.push(sm.same + ' já estavam iguais');\n  if (sm.resolved) parts.push(sm.resolved + ' com divergência resolvida');\n  if (sm.unknown) parts.push(sm.unknown + ' fora do catálogo (fale com o administrador)');\n  return parts.join(' · ') + '. A sincronização nunca remove ninguém da sua conta.';\n}\n\nfunction renderSyncConf(d2) {\n  const sc = d2.state.syncConf;\n  if (!sc) return '';\n  const rows = sc.items.map((it, i) => {\n    const opts = [];\n    if (it.lowerC) opts.push(`<div class=\"row\" style=\"gap:8px\"><span class=\"muted\" style=\"min-width:120px\">Constelação</span><div class=\"seg\"><button class=\"${it.choiceC === 'keep' ? 'on' : ''}\" data-act=\"scPick\" data-i=\"${i}\" data-k=\"C\" data-v=\"keep\">Manter C${it.cc}</button><button class=\"${it.choiceC === 'change' ? 'on' : ''}\" data-act=\"scPick\" data-i=\"${i}\" data-k=\"C\" data-v=\"change\">Mudar para C${it.vc}</button></div></div>`);\n    if (it.lostSig) opts.push(`<div class=\"row\" style=\"gap:8px\"><span class=\"muted\" style=\"min-width:120px\">Arma</span><div class=\"seg\"><button class=\"${it.choiceR === 'keep' ? 'on' : ''}\" data-act=\"scPick\" data-i=\"${i}\" data-k=\"R\" data-v=\"keep\">Manter signature R${it.cr}</button><button class=\"${it.choiceR === 'change' ? 'on' : ''}\" data-act=\"scPick\" data-i=\"${i}\" data-k=\"R\" data-v=\"change\">Tirar a signature</button></div></div>`);\n    return `<div class=\"note\" style=\"display:flex;flex-direction:column;gap:10px\"><b>${esc(it.name)}</b><div class=\"muted\">No app: C${it.cc}${it.cr ? ' · signature R' + it.cr : ''} · Na vitrine: C${it.vc}${it.lostSig ? ' · outra arma equipada' : ''}</div>${opts.join('')}</div>`;\n  }).join('');\n  return `<div class=\"overlay\"><div class=\"modal\" style=\"max-height:90vh;overflow:auto\"><div class=\"kicker\">Sincronizar pela vitrine</div><h2 style=\"font-size:22px\">${sc.items.length} ${sc.items.length > 1 ? 'personagens precisam' : 'personagem precisa'} da sua decisão</h2>\n    <div class=\"muted\">${sc.summary.synced} atualizados automaticamente. Nestes, o que está no app é diferente do que está no jogo agora.</div>${rows}\n    <div class=\"row\"><button class=\"btn primary\" data-act=\"scApply\" ${d2.state.busy ? 'disabled' : ''}>Aplicar escolhas</button><button class=\"btn\" data-act=\"scKeepAll\">Manter tudo como está</button></div></div></div>`;\n}\n\nfunction welcomePage(d2, M) {\n  const s = d2.state;\n  const msg = s.syncMsg ? `<div class=\"${s.syncMsg.err ? 'warn' : 'note'}\">${esc(s.syncMsg.text)}</div>` : '';\n  return `<div class=\"app\"><div class=\"wrap\" style=\"max-width:760px\">\n    <div><div class=\"kicker\">Genshin · DPS · primeiro acesso</div><h1>Vamos trazer seus personagens</h1>\n    <p style=\"font-size:15px;line-height:1.5\">Digite seu UID e o app importa os personagens da sua Vitrine de Personagens, com a constelação de cada um. Os demais você marca na tela de Personagens.</p></div>\n    <div class=\"panel\" style=\"gap:12px\">\n      <label class=\"f\" for=\"wuid\">UID do Genshin</label>\n      <div class=\"row\"><input id=\"wuid\" class=\"input dark\" style=\"flex:1 1 260px;height:52px;font-size:20px;font-weight:700\" inputmode=\"numeric\" placeholder=\"Ex.: 618285856\" value=\"${esc(s.uidDraft || '')}\" data-in=\"uidDraft\" data-key-enter=\"wImport\"><button class=\"btn primary\" style=\"height:52px\" data-act=\"wImport\" ${s.syncBusy ? 'disabled' : ''}>${s.syncBusy ? 'Importando…' : 'Importar da vitrine'}</button></div>\n      ${msg}\n    </div>\n    <div class=\"row\"><button class=\"btn\" data-act=\"wDone\">${(M.roster || []).length || Object.keys(M.rosterBy).length ? 'Continuar para o app' : 'Pular e cadastrar depois'}</button></div>\n  </div>${renderSyncConf(d2)}</div>`;\n}\n\nasync function fileToDataUrl(file, max) {\n  const url = URL.createObjectURL(file);\n  try {\n    const img = await new Promise((res, rej) => { const i = new Image(); i.onload = () => res(i); i.onerror = rej; i.src = url; });\n    const scale = Math.min(1, max / Math.max(img.width, img.height));\n    const c = document.createElement('canvas');\n    c.width = Math.round(img.width * scale); c.height = Math.round(img.height * scale);\n    c.getContext('2d').drawImage(img, 0, 0, c.width, c.height);\n    return { src: c.toDataURL('image/jpeg', 0.9), w: c.width, h: c.height };\n  } finally { URL.revokeObjectURL(url); }\n}\n\nasync function handlePhotoFile(d2, file) {\n  if (!file || !/^image\\//.test(file.type || '')) { d2.setState({ ph: { err: 'Envie uma imagem (PNG, JPG ou WEBP).' } }); return; }\n  const id = d2.state.chSel;\n  d2.setState({ ph: { stage: 'reading', id } });\n  try {\n    const im = await fileToDataUrl(file, 1200);\n    let cx = im.w / 2; let cy = im.h / 3; let size = Math.min(im.w, im.h) * 0.6; let found = false;\n    try {\n      const gImg = await new Promise((res, rej) => { const i = new Image(); i.onload = () => res(i); i.onerror = rej; i.src = im.src; });\n      const gc = document.createElement('canvas'); gc.width = im.w; gc.height = im.h;\n      const g = gc.getContext('2d'); g.drawImage(gImg, 0, 0);\n      g.lineWidth = Math.max(1, im.w / 600); g.strokeStyle = 'rgba(255,0,0,0.75)';\n      const fs = Math.max(12, Math.round(Math.min(im.w, im.h) / 28)); g.font = 'bold ' + fs + 'px sans-serif';\n      for (let i = 0; i <= 10; i++) { const x = i * im.w / 10; const y = i * im.h / 10; g.beginPath(); g.moveTo(x, 0); g.lineTo(x, im.h); g.stroke(); g.beginPath(); g.moveTo(0, y); g.lineTo(im.w, y); g.stroke(); }\n      for (let i = 0; i < 10; i++) {\n        const lx = (i + 0.5) * im.w / 10; const ly = (i + 0.5) * im.h / 10;\n        g.fillStyle = 'rgba(0,0,0,0.7)'; g.fillRect(lx - fs * 0.6, 2, fs * 1.2, fs * 1.1); g.fillRect(2, ly - fs * 0.6, fs * 1.4, fs * 1.1);\n        g.fillStyle = '#ffff00'; g.fillText('ABCDEFGHIJ'[i], lx - fs * 0.35, fs * 0.95); g.fillText(String(i + 1), 4, ly + fs * 0.35);\n      }\n      const r = await callRush(d2, 'rushRosto', { image: gc.toDataURL('image/jpeg', 0.85) });\n      let b = r && r.box;\n      if (typeof b === 'string') { try { b = JSON.parse(b); } catch (e) { b = null; } }\n      const col = b && typeof b.col === 'string' ? 'ABCDEFGHIJ'.indexOf(b.col.trim().toUpperCase().charAt(0)) : -1;\n      const row = b ? +b.row : 0;\n      if (b && b.ok !== false && col >= 0 && row >= 1 && row <= 10) {\n        cx = (col + 0.5) * im.w / 10; cy = (row - 0.5) * im.h / 10;\n        const cells = Math.max(0.5, Math.min(6, +b.cells || 1.5));\n        size = cells * (im.h / 10) * 1.7; found = true;\n      }\n    } catch (e) { d2.log(e); }\n    size = Math.max(40, Math.min(size, Math.min(im.w, im.h)));\n    d2.setState({ ph: clampPh({ stage: 'adjust', id, src: im.src, w: im.w, h: im.h, cx, cy, size, found }) });\n  } catch (e) {\n    d2.log(e);\n    d2.setState({ ph: { stage: 'adjust', id, err: 'Não foi possível abrir a imagem.' } });\n  }\n}\n\nfunction clampPh(ph) {\n  const half = ph.size / 2;\n  ph.cx = Math.min(Math.max(ph.cx, half), ph.w - half);\n  ph.cy = Math.min(Math.max(ph.cy, half), ph.h - half);\n  return ph;\n}\n\nasync function cropPhoto(ph) {\n  const img = await new Promise((res, rej) => { const i = new Image(); i.onload = () => res(i); i.onerror = rej; i.src = ph.src; });\n  const out = 192;\n  const c = document.createElement('canvas'); c.width = out; c.height = out;\n  c.getContext('2d').drawImage(img, ph.cx - ph.size / 2, ph.cy - ph.size / 2, ph.size, ph.size, 0, 0, out, out);\n  return c.toDataURL('image/jpeg', 0.85);\n}\n\nfunction renderPhoto(d2, M) {\n  const ph = d2.state.ph;\n  if (!ph) return '';\n  const c = M.charById[ph.id] || {};\n  if (ph.stage === 'reading') return `<div class=\"overlay\"><div class=\"modal\" style=\"align-items:center\"><div class=\"loading\" style=\"height:auto\">Procurando o rosto na imagem…</div></div></div>`;\n  if (ph.err && !ph.src) return `<div class=\"overlay\"><div class=\"modal\"><h2 style=\"font-size:22px\">Foto</h2><div class=\"warn\">${esc(ph.err)}</div><button class=\"btn\" data-act=\"phCancel\">Fechar</button></div></div>`;\n  const view = 220;\n  const imgStyle = (V) => { const k = V / ph.size; return `position:absolute;max-width:none;width:${(ph.w * k).toFixed(1)}px;height:${(ph.h * k).toFixed(1)}px;left:${(-(ph.cx - ph.size / 2) * k).toFixed(1)}px;top:${(-(ph.cy - ph.size / 2) * k).toFixed(1)}px`; };\n  const color = EL[c.element] || '#3a2a2a';\n  const maxSize = Math.min(ph.w, ph.h);\n  const zoom = Math.round((1 - (ph.size - 40) / Math.max(1, maxSize - 40)) * 100);\n  return `<div class=\"overlay\"><div class=\"modal\" style=\"max-width:560px\">\n    <div class=\"kicker\">Foto do personagem</div><h2 style=\"font-size:22px\">${esc(c.namePt || '')}</h2>\n    <div class=\"muted\">${ph.found ? 'O rosto foi localizado automaticamente. Ajuste se precisar.' : 'Não achei o rosto sozinho. Ajuste o enquadramento abaixo.'}</div>\n    <div class=\"row\" style=\"justify-content:center;gap:28px\">\n      <div style=\"width:${view}px;height:${view}px;border-radius:50%;overflow:hidden;position:relative;border:4px solid ${color};box-shadow:0 0 18px ${color}88;background:#0b0909\"><img src=\"${ph.src}\" alt=\"\" data-phimg=\"${view - 8}\" style=\"${imgStyle(view - 8)}\"></div>\n      <div style=\"width:64px;height:64px;border-radius:50%;overflow:hidden;position:relative;border:3px solid ${color};background:#0b0909\"><img src=\"${ph.src}\" alt=\"\" data-phimg=\"58\" style=\"${imgStyle(58)}\"></div>\n    </div>\n    <label class=\"f\">Zoom</label><input type=\"range\" min=\"0\" max=\"100\" value=\"${zoom}\" data-ph=\"zoom\">\n    <label class=\"f\">Horizontal</label><input type=\"range\" min=\"0\" max=\"1000\" value=\"${Math.round(ph.cx / ph.w * 1000)}\" data-ph=\"x\">\n    <label class=\"f\">Vertical</label><input type=\"range\" min=\"0\" max=\"1000\" value=\"${Math.round(ph.cy / ph.h * 1000)}\" data-ph=\"y\">\n    ${ph.err ? `<div class=\"warn\">${esc(ph.err)}</div>` : ''}\n    <div class=\"row\"><button class=\"btn primary\" data-act=\"phSave\" ${d2.state.busy ? 'disabled' : ''}>Salvar foto</button><button class=\"btn\" data-act=\"phCancel\">Cancelar</button></div>\n  </div></div>`;\n}\n\nfunction phInput(d2, el) {\n  const ph = d2.state.ph; if (!ph || !el || !ph.src) return;\n  const k = el.getAttribute('data-ph'); const v = +el.value;\n  const maxSize = Math.min(ph.w, ph.h);\n  if (k === 'zoom') ph.size = maxSize - (v / 100) * (maxSize - 40);\n  if (k === 'x') ph.cx = (v / 1000) * ph.w;\n  if (k === 'y') ph.cy = (v / 1000) * ph.h;\n  clampPh(ph);\n  const imgs = d2.root && d2.root.querySelectorAll ? Array.from(d2.root.querySelectorAll('img[data-phimg]')) : [];\n  imgs.forEach((im) => {\n    const V = +im.getAttribute('data-phimg'); const kk = V / ph.size;\n    im.style.width = (ph.w * kk).toFixed(1) + 'px'; im.style.height = (ph.h * kk).toFixed(1) + 'px';\n    im.style.left = (-(ph.cx - ph.size / 2) * kk).toFixed(1) + 'px'; im.style.top = (-(ph.cy - ph.size / 2) * kk).toFixed(1) + 'px';\n  });\n}\n\nfunction authScreen(d2) {\n  const s = d2.state;\n  const v = s.view || 'login';\n  const msg = s.authMsg ? `<div class=\"note\">${esc(s.authMsg)}</div>` : '';\n  const err = s.authErr ? `<div class=\"warn\">${esc(s.authErr)}</div>` : '';\n  const field = (id, label, type, key, ph, enter) => `<label class=\"f\" for=\"${id}\">${label}</label><input id=\"${id}\" class=\"input dark\" type=\"${type}\" placeholder=\"${ph}\" value=\"${esc(s[key] || '')}\" data-in=\"${key}\" ${enter ? `data-key-enter=\"${enter}\"` : ''}>`;\n  let body = '';\n  if (v === 'login') {\n    body = `<h1>Entrar</h1>${msg}${err}\n      ${field('au-email', 'E-mail', 'email', 'auEmail', 'voce@email.com', 'doLogin')}\n      ${field('au-pass', 'Senha', 'password', 'auPass', '', 'doLogin')}\n      <button class=\"btn primary\" data-act=\"doLogin\" ${s.busy ? 'disabled' : ''}>Entrar</button>\n      <div class=\"row between\"><button class=\"more\" data-act=\"goView\" data-v=\"signup\">Criar conta</button><button class=\"more\" data-act=\"goView\" data-v=\"reset\">Esqueci a senha</button></div>`;\n  } else if (v === 'signup') {\n    body = `<h1>Criar conta</h1>\n      <div class=\"note\">Use o e-mail que o administrador liberou para você.</div>${err}\n      ${field('su-email', 'E-mail', 'email', 'auEmail', 'voce@email.com')}\n      ${field('su-pass', 'Senha (mínimo 6 caracteres)', 'password', 'auPass', '')}\n      ${field('su-pass2', 'Confirmar senha', 'password', 'auPass2', '', 'doSignup')}\n      <button class=\"btn primary\" data-act=\"doSignup\" ${s.busy ? 'disabled' : ''}>Criar conta</button>\n      <button class=\"more\" data-act=\"goView\" data-v=\"login\">Já tenho conta</button>`;\n  } else {\n    body = `<h1>Redefinir senha</h1>\n      <div class=\"note\">Peça ao administrador do app um código de redefinição e preencha abaixo.</div>${err}\n      ${field('rs-email', 'E-mail', 'email', 'auEmail', 'voce@email.com')}\n      ${field('rs-code', 'Código', 'text', 'auCode', 'Ex.: 482913')}\n      ${field('rs-pass', 'Nova senha (mínimo 6 caracteres)', 'password', 'auPass', '')}\n      ${field('rs-pass2', 'Confirmar nova senha', 'password', 'auPass2', '', 'doReset')}\n      <button class=\"btn primary\" data-act=\"doReset\" ${s.busy ? 'disabled' : ''}>Redefinir senha</button>\n      <button class=\"more\" data-act=\"goView\" data-v=\"login\">Voltar para entrar</button>`;\n  }\n  return `<div class=\"app\"><div class=\"authwrap\"><div class=\"authcard\"><div class=\"kicker\">Genshin · DPS</div>${body}</div></div></div>`;\n}\n\nfunction model(d2) {\n  const db = d2.state.db || {};\n  const rec = (n) => db[n] || [];\n  const me = db.me || null;\n  const uid = me ? me._id : null;\n  const chars = rec('chars');\n  const charById = {};\n  chars.forEach((c) => { charById[c._id] = c; });\n  const roster = rec('roster').filter((r) => r.ownerId === uid);\n  const rosterBy = {};\n  roster.forEach((r) => { rosterBy[r.characterId] = r; });\n  const teams = rec('teams').filter((t) => t.ownerId === uid);\n  const versions = rec('versions').filter((v) => v.ownerId === uid);\n  const runs = rec('runs').filter((r) => r.ownerId === uid);\n  const runsByVersion = {};\n  runs.forEach((r) => { (runsByVersion[r.versionId] = runsByVersion[r.versionId] || []).push(r); });\n  const currentBuilds = (ids) => ids.map((id) => ({ characterId: id, constellation: (rosterBy[id] && rosterBy[id].constellation) || 0, refinement: (rosterBy[id] && rosterBy[id].refinement) || 0 }));\n  const teamInfo = teams.map((t) => {\n    const vs = versions.filter((v) => v.teamId === t._id).map((v) => {\n      const rs = runsByVersion[v._id] || [];\n      const vals = rs.map((r) => r.dps);\n      return { v, runs: rs, avg: mean(vals), count: vals.length };\n    });\n    const curKey = keyOfBuilds(currentBuilds(t.memberOrder || []));\n    vs.forEach((x) => { x.isCurrent = x.v.compositionKey === curKey; });\n    const withRuns = vs.filter((x) => x.count > 0);\n    const best = withRuns.slice().sort((a, b) => b.avg - a.avg)[0] || null;\n    return { t, versions: vs, best, curKey, current: vs.find((x) => x.isCurrent) || null };\n  });\n  return { me, uid, chars, charById, rosterBy, teams, teamInfo, versions, runs, currentBuilds };\n}\n\nfunction avatar(c, build, size, opts) {\n  opts = opts || {};\n  const color = c && EL[c.element];\n  const bw = size >= 70 ? 4 : 3;\n  const ring = color\n    ? `background:linear-gradient(#1e1717,#1e1717) padding-box,conic-gradient(from 210deg,${color},#ffffff 18%,${color} 36%,${color}55 62%,${color}) border-box;box-shadow:inset 0 0 0 2px #0b0909,0 0 14px ${color}66;`\n    : 'background:linear-gradient(#1e1717,#1e1717) padding-box,linear-gradient(#3a2a2a,#3a2a2a) border-box;';\n  const name = c ? c.namePt : '?';\n  const short = c && /\\s/.test(name) && !/^Viajante /.test(name) && c.aliases && c.aliases.length ? c.aliases.slice().sort((a, b) => a.length - b.length)[0] : name;\n  const inner = c && c.iconUrl && String(c.iconUrl).trim()\n    ? `<img src=\"${esc(c.iconUrl)}\" alt=\"\" style=\"width:100%;height:100%;border-radius:50%;object-fit:cover;display:block\">`\n    : `<span style=\"font-size:${Math.round(size * 0.3)}px\">${esc(short.replace(/^Viajante /, 'V').slice(0, 2))}</span>`;\n  const b = build ? buildStr(build.constellation, build.refinement) : '';\n  const badge = b && opts.badge !== false ? `<span class=\"badge\" style=\"font-size:${size >= 70 ? 11 : 9}px\">${b}</span>` : '';\n  return `<span class=\"avw\" style=\"width:${size}px;height:${size}px\" title=\"${esc(name + (b ? ' ' + b : ''))}\"><span class=\"av\" style=\"width:${size}px;height:${size}px;border:${bw}px solid transparent;${ring}\">${inner}</span>${badge}</span>`;\n}\n\nconst css = `\n:host{all:initial}\n*{box-sizing:border-box}\n.app{position:relative;min-height:100%;height:100%;overflow:auto;background:#0b0909;color:#fff;font-family:Manrope,'Segoe UI',system-ui,sans-serif;padding:28px 32px 40px}\n.wrap{max-width:1440px;margin:0 auto;display:flex;flex-direction:column;gap:22px}\n.kicker{font-size:12px;font-weight:700;color:#e8a3a3;letter-spacing:.1em;text-transform:uppercase}\nh1{margin:0;font-size:30px;font-weight:800}\nh2{margin:0;font-size:16px;font-weight:800}\nh3{margin:0;font-size:16px;font-weight:800}\n.muted{font-size:12px;color:#e8a3a3}\n.row{display:flex;flex-wrap:wrap;align-items:center;gap:12px}\n.between{justify-content:space-between}\n.input{height:44px;border-radius:12px;border:1px solid #3a2a2a;background:#161212;color:#fff;padding:0 14px;font:inherit;font-size:14px}\n.input.dark{background:#0b0909}\n.btn{height:44px;padding:0 18px;border-radius:12px;border:1px solid #3a2a2a;background:transparent;color:#fff;font:inherit;font-size:14px;font-weight:700;cursor:pointer}\n.btn.primary{background:#b3121f;border-color:#b3121f;font-weight:800}\n.btn.sm{height:36px;padding:0 14px;font-size:13px;border-radius:10px}\n.btn[disabled]{opacity:.45;cursor:default}\n.seg{display:flex;border:1px solid #3a2a2a;border-radius:10px;overflow:hidden}\n.seg button{height:36px;padding:0 12px;border:none;background:transparent;color:#fff;font:inherit;font-size:12px;font-weight:700;cursor:pointer}\n.seg button.on{background:#b3121f}\n.cols{display:flex;flex-wrap:wrap;gap:24px;align-items:flex-start}\n.left{flex:1 1 520px;min-width:0;display:flex;flex-direction:column;gap:8px}\n.panel{flex:1 1 560px;min-width:0;background:#161212;border-radius:18px;padding:24px;display:flex;flex-direction:column;gap:22px}\n.card{width:100%;text-align:left;background:#161212;border:2px solid #161212;border-radius:14px;padding:12px 16px;display:grid;grid-template-columns:32px auto minmax(0,1fr) auto;gap:16px;align-items:center;color:#fff;font:inherit;cursor:pointer}\n.card.sel{background:#241b1b;border-color:#b3121f}\n.card .rank{font-size:18px;font-weight:700;color:#e8a3a3}\n.card .lbl{font-size:12px;font-weight:600;color:#e8a3a3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.cname{display:flex;flex-direction:column;min-width:0;gap:2px}\n.cname .cn{font-size:18px;font-weight:800;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.mem{display:flex;gap:12px}\n.dps{font-size:22px;font-weight:700;text-align:right}\n.tag{display:inline-block;font-size:10px;font-weight:800;padding:2px 7px;border-radius:999px;background:#3a2a2a;color:#fff;margin-left:6px;vertical-align:middle}\n.more{align-self:flex-start;height:30px;padding:0 10px;border:none;background:transparent;color:#e8a3a3;font:inherit;font-size:12px;font-weight:700;cursor:pointer}\n.child{margin-left:28px;width:calc(100% - 28px)}\n.gpill{display:inline-flex;align-items:center;margin-top:6px;height:22px;padding:0 10px;border:1px solid #6b1a22;border-radius:999px;font-size:11px;font-weight:700;color:#f2b8ae;white-space:nowrap;cursor:pointer}\n.gpill:hover{background:#2a1c1c;border-color:#b3121f}\n.gpill.on{background:#2a1c1c;border-color:#b3121f;color:#fff}\n.avw{position:relative;display:inline-block;flex-shrink:0}\n.av{display:flex;align-items:center;justify-content:center;border-radius:50%;font-weight:800;overflow:hidden}\n.badge{position:absolute;right:-7px;bottom:-4px;background:#b3121f;color:#fff;font-weight:800;padding:1px 5px;border-radius:999px;border:2px solid #161212}\n.big{font-size:36px;font-weight:700;line-height:1}\n.grid4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}\n.stat{background:#211a1a;border-radius:12px;padding:12px 14px;display:flex;flex-direction:column;gap:2px}\n.stat b{font-size:20px}\n.memcol{display:flex;flex-direction:column;align-items:center;gap:10px;min-width:0}\n.memcol .n{font-size:13px;font-weight:700;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.chips{display:flex;flex-wrap:wrap;gap:8px}\n.chip{height:34px;padding:0 12px;border-radius:999px;border:1px solid #3a2a2a;background:transparent;color:#fff;font:inherit;font-size:12px;font-weight:700;cursor:pointer}\n.chip.on{background:#b3121f;border-color:#b3121f}\n.bar{display:flex;height:14px;border-radius:999px;overflow:hidden;gap:2px;background:#0b0909}\ntable{width:100%;border-collapse:collapse;font-size:14px}\nth{text-align:left;padding:8px 10px;font-size:11px;font-weight:700;color:#e8a3a3;border-bottom:1px solid #3a2a2a}\ntd{padding:4px 10px;border-bottom:1px solid #211a1a}\ntd.r,th.r{text-align:right}\n.notebtn{width:100%;min-height:32px;text-align:left;border:none;background:transparent;color:#fff;font:inherit;font-size:13px;cursor:pointer;padding:4px 6px;border-radius:8px}\n.notebtn:hover{background:#211a1a}\n.icon{width:36px;height:36px;border:none;border-radius:10px;background:transparent;color:#e8a3a3;cursor:pointer;font-size:16px}\n.overlay{position:fixed;inset:0;background:#050404cc;display:flex;align-items:center;justify-content:center;padding:24px;z-index:10}\n.modal{width:100%;max-width:620px;background:#161212;border:1px solid #3a2a2a;border-radius:20px;padding:28px;display:flex;flex-direction:column;gap:16px}\n.warn{background:#211a1a;border:1px solid #b3121f;border-radius:12px;padding:12px 14px;font-size:14px;line-height:1.5}\n.note{background:#211a1a;border-radius:12px;padding:10px 14px;font-size:13px;line-height:1.5}\nselect{height:42px;border-radius:10px;border:1px solid #3a2a2a;background:#0b0909;color:#fff;padding:0 8px;font:inherit;font-size:13px;font-weight:700;width:100%}\nlabel.f{font-size:12px;font-weight:700;color:#e8a3a3}\n.loading{display:flex;align-items:center;justify-content:center;gap:12px;height:60vh;font-size:15px;color:#e8a3a3}\n.authwrap{min-height:80vh;display:flex;align-items:center;justify-content:center}\n.authcard{width:100%;max-width:420px;background:#161212;border:1px solid #3a2a2a;border-radius:20px;padding:32px;display:flex;flex-direction:column;gap:12px}\n.authcard h1{font-size:26px;margin-bottom:4px}\n.authcard .btn{width:100%;margin-top:6px}\n.drop{border:2px dashed #3a2a2a;border-radius:16px;background:#161212;padding:16px 20px;display:flex;flex-wrap:wrap;align-items:center;gap:16px}\n.drop .t{font-size:15px;font-weight:800}\n.chgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(84px,1fr));gap:10px}\n.chcell{background:transparent;border:2px solid transparent;border-radius:12px;padding:8px 2px;display:flex;flex-direction:column;align-items:center;gap:6px;color:#fff;font:inherit;cursor:pointer;min-width:0}\n.chcell.on{background:#241b1b;border-color:#b3121f}\n.chcell .n{font-size:11px;font-weight:600;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.eldot{width:22px;height:22px;border-radius:50%;border:2px solid transparent;cursor:pointer;padding:0;opacity:.55}\n.eldot.on{opacity:1;border-color:#fff;box-shadow:0 0 8px currentColor}\ninput[type=range]{width:100%;accent-color:#b3121f}\n.toast{background:#241b1b;border:1px solid #b3121f;border-radius:12px;padding:10px 14px;display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:14px;font-weight:700}\n`;\n\nexport default {\n  css,\n  async mounted(d2) {\n    d2.setState({ loading: true });\n    const pick = (ev, el, attr) => {\n      const path = ev && ev.composedPath ? ev.composedPath() : [];\n      for (const n of path) { if (n && n.getAttribute && n.getAttribute(attr) != null) return n; }\n      if (el && el.getAttribute && el.getAttribute(attr) != null) return el;\n      const t = ev && ev.target;\n      return t && t.closest ? t.closest('[' + attr + ']') : null;\n    };\n\n    d2.on('[data-act]', 'click', (ev, mt) => {\n      if (ev && ev.__giAct) return;\n      if (ev) ev.__giAct = true;\n      const el = pick(ev, mt, 'data-act');\n      if (!el) return;\n      act(d2, el.getAttribute('data-act'), el.dataset);\n    });\n    const onInput = (ev, mt) => {\n      const elIn = pick(ev, mt, 'data-in');\n      if (elIn) { d2.state[elIn.getAttribute('data-in')] = elIn.value; return; }\n      const elPr = pick(ev, mt, 'data-pr');\n      if (elPr) { prInput(d2, elPr); return; }\n      const elPh = pick(ev, mt, 'data-ph');\n      if (elPh) phInput(d2, elPh);\n    };\n    const onChange = (ev, mt) => {\n      const elSel = pick(ev, mt, 'data-sel');\n      if (elSel) {\n        const i = +elSel.getAttribute('data-sel');\n        const m = (d2.state.editMembers || []).slice();\n        m[i] = elSel.value;\n        d2.state.editMembers = m;\n        d2.refresh();\n        return;\n      }\n      const elPr = pick(ev, mt, 'data-pr');\n      if (elPr) { prInput(d2, elPr); return; }\n      const elFile = pick(ev, mt, 'data-file');\n      if (elFile) { const f = elFile.files && elFile.files[0]; if (f) handlePrintFile(d2, f); elFile.value = ''; return; }\n      const elPh = pick(ev, mt, 'data-phfile');\n      if (elPh) { const f = elPh.files && elPh.files[0]; if (f) handlePhotoFile(d2, f); elPh.value = ''; }\n    };\n    d2.on('[data-in],[data-pr],[data-ph]', 'input', onInput);\n    d2.on('[data-sel],[data-pr],[data-file],[data-phfile]', 'change', onChange);\n    d2.on('[data-key-enter]', 'keydown', (ev, mt) => {\n      const el = pick(ev, mt, 'data-key-enter');\n      if (!el) return;\n      if (ev.key === 'Enter') act(d2, el.getAttribute('data-key-enter'), el.dataset);\n      if (ev.key === 'Escape') d2.setState({ editRun: null, nickEdit: false });\n    });\n\n    d2.on('[data-drop]', 'dragover', (ev) => { ev.preventDefault(); });\n    d2.on('[data-drop]', 'drop', (ev) => { ev.preventDefault(); const f = ev.dataTransfer && ev.dataTransfer.files && ev.dataTransfer.files[0]; if (f) handlePrintFile(d2, f); });\n    window.__giD2 = d2;\n    if (!window.__giPaste) {\n      window.__giPaste = true;\n      document.addEventListener('paste', (ev) => {\n        const dd = window.__giD2;\n        if (!dd || !dd.state.authed || dd.state.page || dd.state.modal) return;\n        const items = (ev.clipboardData && ev.clipboardData.items) || [];\n        for (const it of items) { if (it.type && it.type.indexOf('image/') === 0) { const f = it.getAsFile(); if (f) { ev.preventDefault(); handlePrintFile(dd, f); return; } } }\n      });\n    }\n\n    await loadAllData(d2);\n  },\n  render(d2) {\n    if (!d2.state.dataLoaded) return `<div class=\"app\"><div class=\"loading\">Carregando…</div></div>`;\n    if (!d2.state.authed) return authScreen(d2);\n    const M = model(d2);\n    if (!M.uid) return authScreen(d2);\n    const s = d2.state;\n    if (s.page === 'acessos' && M.me.role === 'admin') return adminPage(d2, M);\n    if (s.page === 'welcome' || (!s.page && M.me && M.me.onboarded === false && !Object.keys(M.rosterBy).length)) return welcomePage(d2, M);\n    if (s.page === 'personagens') return charsPage(d2, M);\n    const q = String(s.q || '').trim().toLowerCase();\n    const showAll = !!s.showAll;\n    const expanded = s.expanded || {};\n\n    const ranked = M.teamInfo.slice().sort((a, b) => (b.best ? b.best.avg : -1) - (a.best ? a.best.avg : -1));\n    ranked.forEach((x, i) => { x.rank = i + 1; });\n    const selId = s.sel && ranked.find((x) => x.t._id === s.sel) ? s.sel : (ranked[0] ? ranked[0].t._id : null);\n    const firstName = (x) => (M.charById[x.t.firstCharacterId] || {}).namePt || '';\n    const hasChar = (x, txt) => (x.t.memberOrder || []).some((id) => ((M.charById[id] || {}).namePt || '').toLowerCase().includes(txt) || ((M.charById[id] || {}).aliases || []).some((a) => a.toLowerCase().includes(txt)));\n    const firstMatches = (x, txt) => { const c = M.charById[x.t.firstCharacterId] || {}; return (c.namePt || '').toLowerCase().includes(txt) || (c.aliases || []).some((a) => a.toLowerCase().includes(txt)); };\n\n    const card = (x, child, extra) => {\n      const show = x.best;\n      const builds = show ? show.v.builds : M.currentBuilds(x.t.memberOrder || []);\n      const old = show && !show.isCurrent;\n      return `<button class=\"card ${x.t._id === selId ? 'sel' : ''} ${child ? 'child' : ''}\" data-act=\"select\" data-id=\"${x.t._id}\" data-key=\"c-${x.t._id}\">\n        <span class=\"rank\">${child ? '' : (x.gRank || x.rank)}</span>\n        <span class=\"mem\">${builds.map((b) => avatar(M.charById[b.characterId], b, 62)).join('')}</span>\n        <span class=\"cname\"><span class=\"cn\">${esc((M.charById[x.t.firstCharacterId] || {}).namePt || x.t.label)}</span>${x.t.label && x.t.label !== (M.charById[x.t.firstCharacterId] || {}).namePt ? `<span class=\"lbl\">${esc(x.t.label)}</span>` : ''}${old ? '<span class=\"tag\" style=\"margin:4px 0 0;align-self:flex-start\">build anterior</span>' : ''}</span>\n        <span><span class=\"dps\" style=\"display:block\">${show ? fmt(show.avg) : '—'}</span><span class=\"muted\" style=\"display:block;text-align:right\">${show ? show.count + ' testes' : 'sem testes'}</span>${extra || ''}</span>\n      </button>`;\n    };\n\n    let list = '';\n    let support = '';\n    let info = '';\n    if (q) {\n      const main = ranked.filter((x) => firstMatches(x, q));\n      const sup = ranked.filter((x) => !firstMatches(x, q) && hasChar(x, q));\n      list = main.map((x) => card(x)).join('');\n      if (sup.length) support = `<div class=\"row\" style=\"padding-top:10px;border-top:1px solid #211a1a\"><h3 style=\"font-size:14px\">Com \"${esc(s.q.trim())}\" em outra posição</h3><span class=\"muted\">${sup.length} times</span></div>` + sup.map((x) => card(x)).join('');\n      info = main.length + ' em primeiro';\n      if (!main.length && !sup.length) list = `<div class=\"note\">Nenhum time com esse personagem.</div>`;\n    } else if (showAll) {\n      list = ranked.map((x) => card(x)).join('');\n      info = ranked.length + ' times';\n    } else {\n      const groups = {}; const order = [];\n      ranked.forEach((x) => { const f = x.t.firstCharacterId; if (!groups[f]) { groups[f] = []; order.push(f); } groups[f].push(x); });\n      order.forEach((f, gi) => {\n        const g = groups[f]; const others = g.slice(1);\n        g[0].gRank = gi + 1; others.forEach((o) => { o.isChild = true; });\n        const open = expanded[f] !== undefined ? expanded[f] : others.some((o) => o.t._id === selId);\n        const pill = others.length ? `<span style=\"display:flex;justify-content:flex-end\"><span class=\"gpill ${open ? 'on' : ''}\" data-act=\"toggleGroup\" data-f=\"${f}\" data-open=\"${open ? 1 : 0}\" title=\"${open ? 'Ocultar outros times de ' : 'Ver outros times de '}${esc(firstName(g[0]))}\">${open ? '− ocultar' : '+ ' + others.length + (others.length > 1 ? ' times' : ' time')}</span></span>` : '';\n        list += card(g[0], false, pill);\n        if (open) others.forEach((o) => { list += card(o, true); });\n      });\n      info = order.length + ' personagens · ' + ranked.length + ' times';\n    }\n\n    const cur = ranked.find((x) => x.t._id === selId);\n    const panel = cur ? renderPanel(d2, M, cur) : `<div class=\"panel\"><div class=\"note\">Nenhum time ainda.</div></div>`;\n\n    const header = `<div class=\"row between\">\n      <div><div class=\"kicker\">Genshin · DPS</div><h1>Times</h1><div class=\"row\" style=\"gap:8px\">${s.nickEdit ? `<input class=\"input dark\" style=\"height:30px;width:180px\" maxlength=\"30\" placeholder=\"Seu apelido\" value=\"${esc(s.nickDraft || '')}\" data-in=\"nickDraft\" data-key-enter=\"nickSave\"><button class=\"btn sm primary\" data-act=\"nickSave\" ${s.busy ? 'disabled' : ''}>Salvar</button><button class=\"btn sm\" data-act=\"nickCancel\">Cancelar</button>` : `<button class=\"more\" style=\"color:#cbb;font-weight:600\" data-act=\"nickEdit\" title=\"Editar apelido\">${esc(M.me.apelido || M.me.nickname || 'Definir apelido')} ✎</button>`}<button class=\"more\" data-act=\"openChars\">Personagens</button>${M.me.role === 'admin' ? '<button class=\"more\" data-act=\"openAdmin\">Acessos</button>' : ''}<button class=\"more\" data-act=\"logout\">Sair</button></div></div>\n      <div class=\"row\">\n        <label class=\"f\" for=\"busca\">Filtrar por personagem</label>\n        <input id=\"busca\" class=\"input\" style=\"width:260px\" placeholder=\"Ex.: Furina\" value=\"${esc(s.q || '')}\" data-in=\"q\">\n      </div></div>`;\n\n    const left = `<div class=\"left\">\n      <div class=\"row between\"><div class=\"row\"><h2>Ranking</h2><span class=\"muted\">${info}</span></div>\n      <div class=\"seg\"><button class=\"${showAll ? '' : 'on'}\" data-act=\"view\" data-v=\"best\">Melhor por personagem</button><button class=\"${showAll ? 'on' : ''}\" data-act=\"view\" data-v=\"all\">Todos os times</button></div></div>\n      ${list}${support}</div>`;\n\n    const drop = `<div class=\"drop\" data-drop><div style=\"flex:1 1 320px\"><div class=\"t\">Arraste a print do resultado aqui</div><div class=\"muted\">ou Ctrl+V em qualquer lugar da tela · o app acha o time pelos 4 personagens, ou cria um novo</div></div><label class=\"btn sm\" for=\"pfile\" style=\"display:inline-flex;align-items:center\">Escolher arquivo</label><input id=\"pfile\" type=\"file\" accept=\"image/*\" data-file style=\"display:none\"></div>`;\n    const toast = s.prToast ? `<div class=\"toast\"><span>${esc(s.prToast.text)}</span><button class=\"more\" data-act=\"prCloseToast\">Fechar</button></div>` : '';\n    return `<div class=\"app\"><div class=\"wrap\">${header}${toast}${drop}<div class=\"cols\">${left}${panel}</div></div>${renderModals(d2, M, cur)}${renderPrint(d2)}</div>`;\n  }\n};\n\nfunction renderPanel(d2, M, x) {\n  const s = d2.state;\n  const vs = x.versions.slice().sort((a, b) => new Date(a.v.createdAt || 0) - new Date(b.v.createdAt || 0));\n  let vSel = vs.find((y) => y.v._id === s.selVersion) || x.current || x.best || vs[vs.length - 1] || null;\n  const builds = vSel ? vSel.v.builds : M.currentBuilds(x.t.memberOrder || []);\n  const vals = vSel ? vSel.runs.map((r) => r.dps) : [];\n  const avg = mean(vals);\n  const min = vals.length ? Math.min.apply(null, vals) : 0;\n  const max = vals.length ? Math.max.apply(null, vals) : 0;\n  const firstId = (x.t.memberOrder || [])[0];\n  const firstChar = M.charById[firstId] || {};\n\n  const versionChips = vs.length > 1 ? `<div class=\"chips\">${vs.map((y) => {\n    const label = (y.isCurrent ? 'Atual' : 'Anterior') + ' · ' + (y.count ? fmt(y.avg) : 'sem testes');\n    return `<button class=\"chip ${vSel && y.v._id === vSel.v._id ? 'on' : ''}\" data-act=\"selVersion\" data-id=\"${y.v._id}\" title=\"${esc(y.v.builds.map((b) => ((M.charById[b.characterId] || {}).namePt || '') + ' ' + buildStr(b.constellation, b.refinement)).join(' · '))}\">${label}</button>`;\n  }).join('')}</div>` : '';\n\n  const brRuns = vSel ? vSel.runs.filter((r) => r.breakdown && Object.keys(r.breakdown).length) : [];\n  const total = (br) => Object.keys(br).reduce((a, k) => a + (+br[k] || 0), 0);\n  let contrib;\n  if (brRuns.length) {\n    const parts = builds.map((b) => {\n      const share = mean(brRuns.map((r) => (+r.breakdown[b.characterId] || 0) / (total(r.breakdown) || 1)));\n      const c = M.charById[b.characterId] || {};\n      return { name: c.namePt || '?', share, dmg: mean(brRuns.map((r) => +r.breakdown[b.characterId] || 0)), color: EL[c.element] || '#6b5a5a' };\n    });\n    contrib = `<div class=\"bar\">${parts.map((p) => `<div title=\"${esc(p.name)}\" style=\"width:${(p.share * 100).toFixed(2)}%;min-width:4px;background:${p.color}\"></div>`).join('')}</div>\n      <div class=\"grid4\">${parts.map((p) => `<div><div class=\"row\" style=\"gap:6px\"><span style=\"width:10px;height:10px;border-radius:50%;background:${p.color}\"></span><b style=\"font-size:12px\">${esc(p.name)}</b></div><div style=\"font-size:20px;font-weight:700\">${Math.round(p.share * 100)}%</div><div class=\"muted\">${fmt(p.dmg)} de dano</div></div>`).join('')}</div>`;\n  } else {\n    contrib = `<div class=\"note\">Aparece quando a versão tiver testes registrados por print, que trazem o dano de cada personagem.</div>`;\n  }\n\n  const rows = vSel ? vSel.runs.slice().sort((a, b) => new Date(b.createdAt || 0) - new Date(a.createdAt || 0)).map((r) => {\n    const share = r.breakdown && total(r.breakdown) ? Math.round((+r.breakdown[firstId] || 0) / total(r.breakdown) * 100) + '%' : '—';\n    const editing = s.editRun === r._id;\n    const note = editing\n      ? `<input class=\"input dark\" style=\"height:34px;width:100%\" value=\"${esc(s.noteDraft || '')}\" data-in=\"noteDraft\" data-key-enter=\"saveNote\" data-id=\"${r._id}\" placeholder=\"Enter salva · Esc cancela\">`\n      : `<button class=\"notebtn\" data-act=\"editNote\" data-id=\"${r._id}\" title=\"Editar observação\">${esc(r.note || '—')}</button>`;\n    return `<tr data-key=\"r-${r._id}\"><td class=\"muted\">${dateBR(r.createdAt)}</td><td class=\"r\"><b>${fmt(r.dps)}</b></td><td class=\"r muted\">${avg ? signed((r.dps - avg) / avg * 100) : ''}</td><td class=\"r\">${share}</td><td>${note}</td><td><button class=\"icon\" data-act=\"askDeleteRun\" data-id=\"${r._id}\" title=\"Excluir teste\">🗑</button></td></tr>`;\n  }).join('') : '';\n\n  const parsed = parseNum(s.draft);\n  const sameAsCurrent = vSel && vSel.isCurrent;\n  const newAvg = parsed ? (vals.reduce((a, b) => a + b, 0) + parsed) / (vals.length + 1) : 0;\n  const preview = parsed && sameAsCurrent && avg ? `<div class=\"row between note\"><span>Nova média</span><span><b>${fmt(newAvg)}</b> <span class=\"muted\">${signed((newAvg - avg) / avg * 100)}</span></span></div>` : '';\n  const addLabel = sameAsCurrent || !vs.length ? 'Registrar dano' : 'Registrar com o build atual';\n  const addHint = !sameAsCurrent && vs.length ? `<div class=\"note\">Esta versão usa um build anterior. O teste vai para a versão com o build atual do seu roster (criada se ainda não existir).</div>` : '';\n\n  return `<div class=\"panel\">\n    <div class=\"row between\" style=\"align-items:flex-start\">\n      <div style=\"display:flex;flex-direction:column;gap:4px\">\n        <div class=\"muted\">#${x.gRank || x.rank} no ${x.isChild ? 'geral' : 'ranking'}${vSel && !vSel.isCurrent ? ' · versão com build anterior' : ''}</div>\n        <div style=\"font-size:24px;font-weight:800\">${esc(x.t.label)}</div>\n        <div class=\"row\" style=\"gap:8px;margin-top:6px\"><button class=\"btn sm\" data-act=\"openEdit\">Editar</button><button class=\"btn sm\" data-act=\"openDelete\" style=\"color:#e8a3a3\">Excluir</button></div>\n      </div>\n      <div style=\"text-align:right\"><div class=\"big\">${vals.length ? fmt(avg) : '—'}</div><div class=\"muted\">DPS médio</div></div>\n    </div>\n    ${versionChips}\n    <div class=\"grid4\">${builds.map((b) => { const c = M.charById[b.characterId]; return `<div class=\"memcol\">${avatar(c, b, 80)}<span class=\"n\">${esc(c ? c.namePt : '?')}</span></div>`; }).join('')}</div>\n    <div class=\"grid4\">\n      <div class=\"stat\"><span class=\"muted\">Testes</span><b>${vals.length}</b></div>\n      <div class=\"stat\"><span class=\"muted\">Mínimo</span><b>${vals.length ? fmt(min) : '—'}</b></div>\n      <div class=\"stat\"><span class=\"muted\">Máximo</span><b>${vals.length ? fmt(max) : '—'}</b></div>\n      <div class=\"stat\"><span class=\"muted\">Dispersão</span><b>${vals.length > 1 ? ((max - min) / avg * 100).toFixed(1).replace('.', ',') + '%' : '—'}</b></div>\n    </div>\n    <div style=\"display:flex;flex-direction:column;gap:12px\"><div class=\"row between\"><h3>Contribuição no time</h3><span class=\"muted\">${brRuns.length ? 'média de ' + brRuns.length + ' teste(s) com print' : ''}</span></div>${contrib}</div>\n    <div class=\"cols\" style=\"gap:24px\">\n      <div style=\"flex:1 1 240px;min-width:0;display:flex;flex-direction:column;gap:12px\">\n        <h3>Novo teste manual</h3>\n        <label class=\"f\" for=\"dano\">Dano (DPS) · Enter registra</label>\n        <input id=\"dano\" class=\"input dark\" style=\"height:52px;font-size:20px;font-weight:700\" inputmode=\"numeric\" placeholder=\"Ex.: 198.500\" value=\"${esc(s.draft || '')}\" data-in=\"draft\" data-key-enter=\"addRun\">\n        <label class=\"f\" for=\"nota\">Observação (opcional)</label>\n        <input id=\"nota\" class=\"input dark\" placeholder=\"Ex.: rotação alternativa\" value=\"${esc(s.noteNew || '')}\" data-in=\"noteNew\" data-key-enter=\"addRun\">\n        ${preview}${addHint}\n        <button class=\"btn primary\" data-act=\"addRun\" ${s.busy ? 'disabled' : ''}>${addLabel}</button>\n      </div>\n      <div style=\"flex:2 1 340px;min-width:0;display:flex;flex-direction:column;gap:12px\">\n        <h3>Testes registrados</h3>\n        <div style=\"overflow-x:auto\"><table><thead><tr><th>Data</th><th class=\"r\">Dano</th><th class=\"r\">vs média</th><th class=\"r\">${esc(firstChar.namePt || '1º')} %</th><th>Observação</th><th></th></tr></thead><tbody>${rows || '<tr><td colspan=\"6\" class=\"muted\">Nenhum teste nesta versão.</td></tr>'}</tbody></table></div>\n      </div>\n    </div>\n  </div>`;\n}\n\nfunction renderModals(d2, M, x) {\n  const s = d2.state;\n  if (s.modal === 'deleteRun') {\n    return `<div class=\"overlay\"><div class=\"modal\"><h2 style=\"font-size:22px\">Excluir este teste?</h2><div class=\"warn\">O teste de <b>${fmt(s.modalDps)}</b> será apagado e a média recalculada.</div><div class=\"row\"><button class=\"btn primary\" data-act=\"deleteRun\" data-id=\"${s.modalId}\" ${s.busy ? 'disabled' : ''}>Excluir</button><button class=\"btn\" data-act=\"closeModal\">Cancelar</button></div></div></div>`;\n  }\n  if (!x) return '';\n  if (s.modal === 'delete') {\n    const vs = x.versions;\n    const totalRuns = vs.reduce((a, y) => a + y.count, 0);\n    const vSel = vs.find((y) => y.v._id === s.selVersion) || x.current || x.best || vs[vs.length - 1];\n    const one = vs.length > 1 && vSel ? `<button class=\"btn\" data-act=\"deleteVersion\" data-id=\"${vSel.v._id}\" ${s.busy ? 'disabled' : ''}>Excluir só esta versão (${vSel.count} testes)</button>` : '';\n    return `<div class=\"overlay\"><div class=\"modal\"><h2 style=\"font-size:22px\">Excluir \"${esc(x.t.label)}\"?</h2>\n      ${totalRuns ? `<div class=\"warn\">Este time tem <b>${totalRuns} testes registrados</b>${vs.length > 1 ? ' em ' + vs.length + ' versões' : ''}. Eles serão apagados e não dá pra recuperar.</div>` : ''}\n      <div class=\"row\">${one}<button class=\"btn primary\" data-act=\"deleteTeam\" ${s.busy ? 'disabled' : ''}>Excluir o time inteiro</button><button class=\"btn\" data-act=\"closeModal\">Cancelar</button></div></div></div>`;\n  }\n  if (s.modal === 'edit') {\n    const members = s.editMembers || (x.t.memberOrder || []).slice();\n    const owned = Object.keys(M.rosterBy).filter((id) => M.rosterBy[id].owned !== false && M.charById[id]).sort((a, b) => M.charById[a].namePt.localeCompare(M.charById[b].namePt));\n    const dup = members.some((m, i) => members.indexOf(m) !== i);\n    const changed = !dup && groupOf(members) !== groupOf(x.t.memberOrder || []);\n    const existing = changed ? M.teamInfo.find((y) => groupOf(y.t.memberOrder || []) === groupOf(members)) : null;\n    const name = s.editName !== undefined ? s.editName : x.t.label;\n    const runs = x.versions.reduce((a, y) => a + y.count, 0);\n    const cantRename = changed || dup || !name.trim() || name.trim() === x.t.label;\n    return `<div class=\"overlay\"><div class=\"modal\"><h2 style=\"font-size:22px\">Editar time</h2>\n      ${runs ? `<div class=\"note\">Este time tem <b>${runs} testes registrados</b>. Renomear não muda nada neles. Trocar um personagem não altera este time: cria outro.</div>` : ''}\n      <label class=\"f\" for=\"enome\">Nome do time</label><input id=\"enome\" class=\"input dark\" value=\"${esc(name)}\" data-in=\"editName\">\n      <div class=\"grid4\">${members.map((m, i) => `<div style=\"display:flex;flex-direction:column;gap:6px;min-width:0\"><label class=\"f\">${i === 0 ? '1º personagem' : 'Slot ' + (i + 1)}</label><select data-sel=\"${i}\" style=\"border-color:${m !== (x.t.memberOrder || [])[i] ? '#b3121f' : '#3a2a2a'}\">${owned.map((id) => `<option value=\"${id}\" ${id === m ? 'selected' : ''}>${esc(M.charById[id].namePt)}</option>`).join('')}</select></div>`).join('')}</div>\n      ${dup ? '<div class=\"muted\"><b>Um personagem não pode aparecer duas vezes no time.</b></div>' : ''}\n      ${changed && !existing ? `<div class=\"warn row between\"><span style=\"flex:1 1 260px\">Essa composição ainda não existe. Ela vira um <b>time novo</b>, sem testes; este time continua como está.</span><button class=\"btn sm primary\" data-act=\"createFromEdit\" ${s.busy ? 'disabled' : ''}>Criar time novo</button></div>` : ''}\n      ${existing ? `<div class=\"warn row between\"><span style=\"flex:1 1 260px\">Você já tem esse time: <b>${esc(existing.t.label)}</b>.</span><button class=\"btn sm primary\" data-act=\"goTeam\" data-id=\"${existing.t._id}\">Ir para esse time</button></div>` : ''}\n      <div class=\"row\"><button class=\"btn primary\" data-act=\"saveRename\" ${cantRename || s.busy ? 'disabled' : ''}>Salvar nome</button><button class=\"btn\" data-act=\"closeModal\">Cancelar</button></div></div></div>`;\n  }\n  return '';\n}\n\nasync function mustOk(d2, param, body) {\n  const r = await callRush(d2, param, body);\n  if (!r || r.ok === false) throw new Error((r && r.error) || 'erro no servidor');\n  return r;\n}\n\nfunction applyData(d2, r) {\n  if (!r || !Array.isArray(r.teams)) return false;\n  d2.state.db = Object.assign({}, d2.state.db || {}, { roster: r.roster || [], teams: r.teams || [], versions: r.versions || [], runs: r.runs || [] });\n  return true;\n}\n\nasync function act(d2, a, data) {\n  const s = d2.state;\n  const M = model(d2);\n  const ranked = M.teamInfo.slice().sort((x, y) => (y.best ? y.best.avg : -1) - (x.best ? x.best.avg : -1));\n  const cur = ranked.find((x) => x.t._id === s.sel) || ranked[0];\n  const run = async (fn) => { if (s.busy) return; d2.setState({ busy: true }); try { await fn(); } catch (e) { d2.log(e); await d2.dialog.alert('Não foi possível salvar: ' + (e && e.message ? e.message : e)); } d2.setState({ busy: false }); };\n\n  if (a === 'goView') return d2.setState({ view: data.v, authErr: '', authMsg: '', auPass: '', auPass2: '', auCode: '' });\n  if (a === 'logout') {\n    try { await d2.auth('auth').logout(); } catch (e) { d2.log(e); }\n    d2.state.db = null;\n    return d2.setState({ authed: false, dataLoaded: true, view: 'login', auPass: '', sel: null, modal: null, page: null });\n  }\n  if (a === 'doLogin' || a === 'doSignup' || a === 'doReset') {\n    if (s.busy) return;\n    const email = String(s.auEmail || '').trim().toLowerCase();\n    const pass = String(s.auPass || '');\n    if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) return d2.setState({ authErr: 'Digite um e-mail válido.' });\n    if (a !== 'doLogin' && pass.length < 6) return d2.setState({ authErr: 'A senha precisa ter pelo menos 6 caracteres.' });\n    if (a !== 'doLogin' && pass !== String(s.auPass2 || '')) return d2.setState({ authErr: 'As senhas não são iguais.' });\n    if (a === 'doReset' && !String(s.auCode || '').trim()) return d2.setState({ authErr: 'Digite o código recebido do administrador.' });\n    d2.setState({ busy: true, authErr: '', authMsg: '' });\n    const unwrap = (r) => (r && r.data && typeof r.data === 'object' ? r.data : r) || {};\n    try {\n      if (a === 'doSignup') {\n        const r = unwrap(await d2.rush(d2.param('rushCriar')).invoke({ action: 'criarConta', email, password: pass }));\n        if (!r.ok) { d2.setState({ busy: false, authErr: r.error || 'Não foi possível criar a conta.' }); return; }\n      }\n      if (a === 'doReset') {\n        const r = unwrap(await d2.rush(d2.param('rushCriar')).invoke({ action: 'redefinirSenha', email, code: String(s.auCode).trim(), password: pass }));\n        if (!r.ok) { d2.setState({ busy: false, authErr: r.error || 'Não foi possível redefinir a senha.' }); return; }\n      }\n      const A = d2.auth('auth');\n      const inst = A.raw;\n      if (inst && inst.cursor) { if (!inst.cursor.current) inst.cursor.current = {}; inst.cursor.current.credentials = { email, password: pass }; }\n      if (inst && typeof inst.login === 'function') await inst.login({ credentials: { email, password: pass } });\n      else await A.login({ credentials: { email, password: pass } });\n      d2.setState({ auPass: '', auPass2: '', auCode: '' });\n      let okLoad = false;\n      for (let i = 0; i < 3 && !okLoad; i++) { if (i) await sleep(800); okLoad = await loadAllData(d2); }\n      d2.setState({ busy: false });\n      if (!okLoad) d2.setState({ view: 'login', authErr: 'Entrou, mas não foi possível carregar seus dados. Tente de novo.' });\n    } catch (e) {\n      d2.log(e);\n      d2.setState({ busy: false, view: 'login', authErr: a === 'doLogin' ? 'E-mail ou senha incorretos.' : 'Conta pronta, mas o login falhou. Tente entrar.' });\n    }\n    return;\n  }\n  if (a === 'openAdmin') { d2.setState({ page: 'acessos', adm: null, admMsg: '', admErr: '' }); return loadAdmin(d2); }\n  if (a === 'closeAdmin') return d2.setState({ page: null, admCode: null });\n  if (a === 'admRole') return d2.setState({ admRole: data.v });\n  if (a === 'admCloseCode') return d2.setState({ admCode: null });\n  if (a === 'admAdd') return run(async () => {\n    const email = String(s.admEmail || '').trim().toLowerCase();\n    if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) { d2.setState({ admMsg: 'Digite um e-mail válido.' }); return; }\n    const r = await callRush(d2, 'rushAdminAdd', { email, role: s.admRole || 'player' });\n    if (!r.ok) { d2.setState({ admMsg: r.error || 'Não foi possível liberar.' }); return; }\n    d2.setState({ admEmail: '', admMsg: 'Acesso liberado para ' + email + '.' });\n    await loadAdmin(d2);\n  });\n  if (a === 'admUpd') return run(async () => {\n    const r = await callRush(d2, 'rushAdminUpdate', { id: data.id, role: data.role, active: data.active === '1' });\n    if (!r.ok) { d2.setState({ admMsg: r.error || 'Não foi possível alterar.' }); return; }\n    d2.setState({ admMsg: '' });\n    await loadAdmin(d2);\n  });\n  if (a === 'admCode') return run(async () => {\n    const r = await callRush(d2, 'rushGerarCodigo', { email: data.email });\n    if (!r.ok) { d2.setState({ admMsg: r.error || 'Não foi possível gerar o código.' }); return; }\n    d2.setState({ admCode: { email: data.email, code: String(r.code) } });\n  });\n  if (a === 'wImport' || a === 'chSync') return syncFromEnka(d2, a === 'wImport' ? s.uidDraft : (s.uidDraft || (M.me && M.me.uid)));\n  if (a === 'wDone') return run(async () => { await mustOk(d2, 'rushOnboard', {}); d2.state.db.me = Object.assign({}, d2.state.db.me, { onboarded: true }); d2.setState({ page: null, syncMsg: null }); });\n  if (a === 'scPick') { const sc = s.syncConf; const it = sc.items[+data.i]; if (data.k === 'C') it.choiceC = data.v; else it.choiceR = data.v; d2.setState({ syncConf: Object.assign({}, sc, { items: sc.items.slice() }) }); d2.refresh(); return; }\n  if (a === 'scKeepAll') { const sm = s.syncConf.summary; return d2.setState({ syncConf: null, syncMsg: { text: syncText(sm) } }); }\n  if (a === 'scApply') return run(async () => {\n    const sc = s.syncConf; let resolved = 0;\n    for (const it of sc.items) {\n      const c = it.lowerC && it.choiceC === 'change' ? it.vc : it.nextC;\n      const r = it.lostSig && it.choiceR === 'change' ? 0 : it.cr;\n      if (c !== it.cc || r !== it.cr) { await saveRoster(d2, it.id, { owned: true, constellation: c, refinement: r }); resolved++; }\n    }\n    d2.setState({ syncConf: null, syncMsg: { text: syncText(Object.assign({}, sc.summary, { resolved })) } });\n  });\n  if (a === 'openChars') return d2.setState({ page: 'personagens', chConfirmRemove: null, syncMsg: null });\n  if (a === 'closeChars') return d2.setState({ page: null });\n  if (a === 'chSel') return d2.setState({ chSel: data.id, chConfirmRemove: null, chAliasDraft: undefined, chAliasFor: data.id });\n  if (a === 'chSort') return d2.setState({ chSort: data.v, chElF: null });\n  if (a === 'chElF') return d2.setState({ chElF: s.chElF === data.v ? null : data.v });\n  if (a === 'chOwnF') { const nx = { all: 'have', have: 'missing', missing: 'all' }[s.chOwnF || 'all']; return d2.setState({ chOwnF: nx }); }\n  if (a === 'phCancel') return d2.setState({ ph: null });\n  if (a === 'phSave') return run(async () => {\n    const ph = s.ph; if (!ph || !ph.src) return;\n    const iconUrl = await cropPhoto(ph);\n    const r = await mustOk(d2, 'rushCatalog', { id: ph.id, iconUrl });\n    if (r.chars) d2.state.db = Object.assign({}, d2.state.db, { chars: r.chars });\n    d2.setState({ ph: null });\n  });\n  if (a === 'phRemove') return run(async () => {\n    const r = await mustOk(d2, 'rushCatalog', { id: s.chSel, iconUrl: ' ' });\n    if (r.chars) d2.state.db = Object.assign({}, d2.state.db, { chars: r.chars });\n  });\n  if (a === 'chOwnCancel') return d2.setState({ chConfirmRemove: null });\n  if (a === 'chOwn' || a === 'chOwnConfirm') return run(async () => {\n    const id = s.chSel; if (!id) return;\n    const owned = M.rosterBy[id] && M.rosterBy[id].owned !== false;\n    if (owned && a === 'chOwn' && M.teamInfo.some((x) => (x.t.memberOrder || []).indexOf(id) >= 0)) { d2.setState({ chConfirmRemove: id }); return; }\n    await saveRoster(d2, id, { owned: !owned });\n    d2.setState({ chConfirmRemove: null });\n  });\n  if (a === 'chC') return run(async () => { await saveRoster(d2, s.chSel, { constellation: +data.v }); });\n  if (a === 'chR') return run(async () => {\n    const r = M.rosterBy[s.chSel] || {};\n    const v = +data.v;\n    await saveRoster(d2, s.chSel, { refinement: (r.refinement || 0) === v && v > 0 ? 0 : v });\n  });\n  if (a === 'chEl') return run(async () => {\n    const r = await mustOk(d2, 'rushCatalog', { id: s.chSel, element: data.v });\n    if (r.chars) d2.state.db = Object.assign({}, d2.state.db, { chars: r.chars });\n  });\n  if (a === 'nickEdit') return d2.setState({ nickEdit: true, nickDraft: M.me.apelido || M.me.nickname || '' });\n  if (a === 'nickCancel') return d2.setState({ nickEdit: false });\n  if (a === 'nickSave') return run(async () => {\n    const ap = String(s.nickDraft || '').trim().slice(0, 30);\n    if (!ap) { await d2.dialog.alert('Digite um apelido.'); return; }\n    await mustOk(d2, 'rushApelido', { apelido: ap });\n    d2.state.db = Object.assign({}, d2.state.db, { me: Object.assign({}, d2.state.db.me, { apelido: ap }) });\n    d2.setState({ nickEdit: false });\n  });\n  if (a === 'chAliasSave') return run(async () => {\n    const c = M.charById[s.chSel]; if (!c) return;\n    const txt = s.chAliasDraft !== undefined ? s.chAliasDraft : (c.aliases || []).join(', ');\n    const aliases = String(txt).split(',').map((x) => x.trim()).filter(Boolean);\n    const r = await mustOk(d2, 'rushCatalog', { id: s.chSel, aliases });\n    if (r.chars) d2.state.db = Object.assign({}, d2.state.db, { chars: r.chars });\n    d2.setState({ chAliasDraft: undefined });\n  });\n  if (a === 'prDiscard') return d2.setState({ pr: null });\n  if (a === 'prCloseToast') return d2.setState({ prToast: null });\n  if (a === 'prAddSlot') { const pr = s.pr; if (pr && pr.members.length < 4) { pr.members.push({ raw: '', damage: 0, added: true, charId: null }); d2.setState({ pr: Object.assign({}, pr, { members: pr.members.slice() }) }); d2.refresh(); } return; }\n  if (a === 'prSave') { if (s.pr && s.pr.stage === 'review') return savePrint(d2); return; }\n  if (a === 'select') return d2.setState({ sel: data.id, selVersion: null, draft: '', noteNew: '', editRun: null });\n  if (a === 'view') return d2.setState({ showAll: data.v === 'all' });\n  if (a === 'toggleGroup') { const e = Object.assign({}, s.expanded || {}); e[data.f] = data.open !== '1'; return d2.setState({ expanded: e }); }\n  if (a === 'selVersion') return d2.setState({ selVersion: data.id, editRun: null });\n  if (a === 'closeModal') return d2.setState({ modal: null, editMembers: null, editName: undefined });\n  if (a === 'openEdit') return d2.setState({ modal: 'edit', editMembers: null, editName: undefined });\n  if (a === 'openDelete') return d2.setState({ modal: 'delete' });\n  if (a === 'goTeam') return d2.setState({ sel: data.id, selVersion: null, modal: null, editMembers: null, editName: undefined, q: '' });\n  if (a === 'editNote') { const r = M.runs.find((x) => x._id === data.id); return d2.setState({ editRun: data.id, noteDraft: r ? r.note || '' : '' }); }\n  if (a === 'askDeleteRun') { const r = M.runs.find((x) => x._id === data.id); return d2.setState({ modal: 'deleteRun', modalId: data.id, modalDps: r ? r.dps : 0 }); }\n\n  if (a === 'saveNote') return run(async () => {\n    const r = await mustOk(d2, 'rushRunNote', { runId: data.id, note: String(s.noteDraft || '').trim() });\n    if (!applyData(d2, r)) await loadAllData(d2);\n    d2.setState({ editRun: null });\n  });\n\n  if (a === 'deleteRun') return run(async () => {      const r = await mustOk(d2, 'rushRunDelete', { id: data.id });\n      if (!applyData(d2, r)) await loadAllData(d2);\n      const teamOk = ((d2.state.db || {}).teams || []).some((t) => t._id === d2.state.sel);\n      d2.setState(teamOk ? { modal: null } : { modal: null, sel: null, selVersion: null });\n  });\n\n  if (a === 'addRun') return run(async () => {\n    if (!cur) return;\n    const dps = parseNum(s.draft);\n    if (!dps) { await d2.dialog.alert('Digite um valor de dano válido.'); return; }\n    const builds = M.currentBuilds(cur.t.memberOrder || []);\n    const r = await mustOk(d2, 'rushRunAdd', { teamId: cur.t._id, compositionKey: keyOfBuilds(builds), builds, dps, note: String(s.noteNew || '').trim(), source: 'manual' });\n    const versionId = r.versionId;\n    if (!applyData(d2, r)) await loadAllData(d2);\n    d2.setState({ draft: '', noteNew: '', selVersion: versionId });\n  });\n\n  if (a === 'saveRename') return run(async () => {\n    const name = String(s.editName || '').trim();\n    if (!name || !cur) return;\n    const r = await mustOk(d2, 'rushTeamRename', { id: cur.t._id, label: name });\n    if (!applyData(d2, r)) await loadAllData(d2);\n    d2.setState({ modal: null, editName: undefined, editMembers: null });\n  });\n\n  if (a === 'createFromEdit') return run(async () => {\n    const members = s.editMembers;\n    if (!members || !cur) return;\n    const label = (M.charById[members[0]] || {}).namePt || 'Novo time';\n    const r = await callRush(d2, 'rushTeamCreate', { groupKey: groupOf(members), label, memberOrder: members, firstCharacterId: members[0] });\n    if (!applyData(d2, r)) await loadAllData(d2);\n    d2.setState({ sel: r.teamId || null, selVersion: null, modal: null, editMembers: null, editName: undefined, showAll: true });\n  });\n\n  if (a === 'deleteVersion') return run(async () => {      const r = await mustOk(d2, 'rushVersionDelete', { id: data.id });\n      if (!applyData(d2, r)) await loadAllData(d2);\n      const teamOk = ((d2.state.db || {}).teams || []).some((t) => t._id === d2.state.sel);\n      d2.setState(teamOk ? { modal: null, selVersion: null } : { modal: null, sel: null, selVersion: null });\n  });\n\n  if (a === 'deleteTeam') return run(async () => {\n    if (!cur) return;\n    const r = await mustOk(d2, 'rushTeamDelete', { id: cur.t._id });\n    if (!applyData(d2, r)) await loadAllData(d2);\n    d2.setState({ modal: null, sel: null, selVersion: null });\n  });\n}\n"}},"auth":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"auth"}}}},"rushAdminAdd":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushAdminAdd"}}}},"rushAdminList":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushAdminList"}}}},"rushAdminUpdate":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushAdminUpdate"}}}},"rushCatalog":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushCatalog"}}}},"rushCriar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushCriar"}}}},"rushDados":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushDados"}}}},"rushExport":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushExport"}}}},"rushGerarCodigo":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushGerarCodigo"}}}},"rushPrint":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushPrint"}}}},"rushProfile":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushProfile"}}}},"rushRedefinir":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushRedefinir"}}}},"rushRoster":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushRoster"}}}},"rushRunAdd":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushRunAdd"}}}},"rushRunDelete":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushRunDelete"}}}},"rushRunNote":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushRunNote"}}}},"rushSync":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushSync"}}}},"rushTeamCreate":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushTeamCreate"}}},"disabled":false},"rushTeamDelete":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushTeamDelete"}}},"disabled":false},"rushTeamRename":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushTeamRename"}}}},"rushVersionDelete":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushVersionDelete"}}}}}}}}}},{"_id":"6adacec16eff2882d0defd2a","component":"data2-core-types@Component","system":"686bd24b4fcbdb97284775e3","params":{"extends":"data2-core-primitives@Block","component":"moti-app","package":"massayuki-playground","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 MEM = { plan: null, run: null }\n\n// rolagem na página (celular): o documento rola, não o .main — assim o pull-to-refresh do APK só dispara no topo\nconst PG_CSS = `html.moti-pg,html.moti-pg body{height:auto!important;min-height:100%;background:#F4F1EA}\nhtml.moti-pg #app{position:static!important;height:auto!important}\nhtml.moti-pg #app .data2-artboard{height:auto!important;min-height:100vh;overflow:visible!important}\nhtml.moti-pg #app .data2-player-block{position:relative!important;height:auto!important;min-height:100vh;overflow:visible!important}\nhtml.moti-pg.moti-lock,html.moti-pg.moti-lock body{overflow:hidden!important}\nhtml.moti-pg.moti-nopull #app .data2-artboard{min-height:calc(100vh + 2px)!important}`\nconst pgSync = (S) => {\n  const h = document.documentElement, on = !!S.pg && !S.wide\n  if (!h || !h.classList) return\n  h.classList.toggle('moti-pg', on)\n  h.classList.toggle('moti-lock', on && !!(S.form || S.sheet || S.conf))\n  // formulário de parâmetros aberto: página fica 1 px rolada, assim o pull-to-refresh do APK não dispara\n  const np = on && !!S.sheet && !S.form\n  h.classList.toggle('moti-nopull', np)\n  if (np && (window.scrollY || 0) < 1) window.scrollTo(0, 1)\n}\n\nexport default {\n  css: `\n.app{position:relative;display:flex;flex-direction:column;height:100%;background:#F4F1EA;color:#1F1B24;font-family:Outfit,system-ui,-apple-system,sans-serif;font-size:14px;overflow:hidden}\n.app.wide{flex-direction:row}\n.main{flex:1;min-width:0;overflow:auto;-webkit-overflow-scrolling:touch}\n.inner{max-width:520px;margin:0 auto;padding:22px 18px 28px;box-sizing:border-box}\n.wide .inner{max-width:1100px;padding:28px 32px}\n.tabs{display:flex;flex-shrink:0;border-top:1px solid #E4DFD4;padding:6px 8px calc(10px + env(safe-area-inset-bottom,0px));background:#F4F1EA}\n.tb{flex:1;text-align:center;font-size:11px;color:#57515C;padding:7px 0;cursor:pointer;border-radius:999px}\n.tb .ic{display:block;height:20px;margin-bottom:2px}\n.tb.on{color:#1F1B24;background:#EDE8DE}\n.side{width:190px;flex-shrink:0;border-right:1px solid #E4DFD4;padding:24px 12px}\n.brand{font-size:18px;padding:0 12px 18px}\n.sb{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:12px;cursor:pointer;color:#57515C;font-size:14px;margin-bottom:2px}\n.sb.on{background:#EDE8DE;color:#1F1B24}\n.panel{width:340px;flex-shrink:0;border-left:1px solid #E4DFD4;overflow:auto;padding:24px 20px;box-sizing:border-box}\n.cd{background:#FFF;border:1px solid #E4DFD4;border-radius:18px;padding:14px 16px;margin-bottom:10px}\n.r{display:flex;justify-content:space-between;align-items:center;gap:8px}\n.mut{color:#57515C;font-size:12px}\n.box{background:#FAF8F3;border-radius:12px;padding:8px 12px;margin-top:8px}\n.ln{margin-top:10px;padding-top:10px;border-top:1px solid #EFEBE3}\n.b{border-radius:999px;font-family:inherit;cursor:pointer;font-size:12px;height:32px;padding:0 14px;background:#FFF;border:1px solid #E4DFD4;color:#1F1B24;white-space:nowrap}\n.bd{background:#1F1B24;color:#FFF;border:none;height:38px;padding:0 18px;font-size:14px}\n.b[disabled]{opacity:.5;cursor:default}\n.wa{color:#3F5E44;border-color:#C9DCC6}\n.ch{display:inline-block;font-size:11px;padding:4px 10px;border-radius:999px;white-space:nowrap}\n.f{border-radius:999px;border:1px solid #E4DFD4;padding:6px 14px;font-size:13px;cursor:pointer;background:transparent;color:#1F1B24;font-family:inherit}\n.f.on{background:#1F1B24;color:#FFF;border-color:#1F1B24}\n.chips{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:10px}\n.sec{font-size:14px;margin:20px 0 10px}\n.h1{font-size:28px;line-height:1.15}\n.head{display:flex;justify-content:space-between;align-items:flex-start;gap:10px;margin-bottom:14px}\n.busca{width:100%;height:42px;border:1px solid #E4DFD4;border-radius:999px;background:#FFF;color:#1F1B24;font-family:inherit;font-size:14px;padding:0 16px;box-sizing:border-box;margin-bottom:10px;outline:none}\n.tap{cursor:pointer}\n.grid2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}\n.grid4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}\n.cols{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:18px}\n.plancols{display:grid;grid-template-columns:minmax(0,1fr) 280px;gap:18px;align-items:start}\n.tbl{width:100%;border-collapse:collapse;font-size:14px}\n.tbl th{text-align:left;font-weight:400;color:#57515C;font-size:12px;padding:10px;border-bottom:1px solid #E4DFD4}\n.tbl td{padding:12px 10px;border-bottom:1px solid #EFEBE3}\n.tbl tr.tap:hover td{background:#FAF8F3}\n.lb{font-size:11px;color:#57515C;letter-spacing:.05em;margin-top:4px}\n.in{width:100%;height:46px;border:1px solid #E4DFD4;border-radius:12px;background:#FFF;color:#1F1B24;font-family:inherit;font-size:15px;padding:0 14px;box-sizing:border-box;margin:4px 0 12px;outline:none}\n.num{width:88px;height:34px;text-align:right;border:1px solid #E4DFD4;border-radius:10px;background:#FFF;color:#1F1B24;font-family:inherit;font-size:14px;padding:0 8px;box-sizing:border-box;outline:none}\n.pin{padding:7px 0;border-bottom:1px solid #EFEBE3}\n.grp{font-size:11px;color:#57515C;padding:12px 0 2px;letter-spacing:.05em}\n.prev{font-size:11px;color:#8A848D;margin-top:2px}\n.ov{position:absolute;inset:0;background:rgba(31,27,36,.55);z-index:20}\n.ovc{position:absolute;inset:0}\n.sheet{position:absolute;left:6px;right:6px;bottom:0;max-height:calc(100% - 40px);overflow:auto;background:#F4F1EA;border-radius:22px 22px 0 0;padding:12px 20px calc(20px + env(safe-area-inset-bottom,0px));box-sizing:border-box}\n.handle{width:38px;height:5px;border-radius:3px;background:#1F1B24;margin:0 auto 14px}\n.modal{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:min(380px,calc(100% - 40px));background:#F4F1EA;border-radius:22px;padding:22px;box-sizing:border-box}\n.dark{background:#1F1B24;color:#FFF;border:none}\n.toast{position:absolute;left:50%;bottom:90px;transform:translateX(-50%);background:#1F1B24;color:#FFF;padding:10px 16px;border-radius:999px;font-size:13px;z-index:30}\n.stp{display:flex;align-items:center;gap:8px}\n.stp .b{width:32px;padding:0;font-size:16px}\n.loading{padding:40px;text-align:center;color:#57515C}\n.app.pg{height:auto;min-height:100vh;overflow:visible}\n.app.pg .main{flex:none;overflow:visible}\n.app.pg .inner{padding-bottom:calc(100px + env(safe-area-inset-bottom,0px))}\n.app.pg .tabs{position:fixed;left:0;right:0;bottom:0;z-index:15}\n.app.pg .ov{position:fixed}\n.app.pg .toast{position:fixed}\n`,\n\n  render(d2) {\n    const S = d2.state\n    const esc = (v) => String(v == null ? '' : v).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;')\n    const f2 = (n) => (Number(n) || 0).toFixed(2)\n    const money = (n) => 'R$ ' + f2(n)\n    // ---------- login ----------\n    const au = d2.auth('auth')\n    if (!au) return `<div class=\"app\"><div class=\"loading\">Conectando…</div></div>`\n    const userOf = (a) => { if (!a) return null; const u = a.user; if (u && u.email) return u; const c = a.raw && a.raw.cursor && a.raw.cursor.current; if (c && c.credentials && c.credentials.email) return c.credentials; if (c && c.email) return c; let g = null; try { g = a.raw && a.raw.getSelectedSession && a.raw.getSelectedSession() } catch (e) {} if (g && g.authStrategy === 'moti-auth' && g.credentials && g.credentials.email) return g.credentials; return null }\n    const me = userOf(au)\n    const lgWrap = (inner) => `<div class=\"app\"><div class=\"main\"><div class=\"inner\" style=\"max-width:400px;padding-top:56px\"><div class=\"h1\" style=\"margin-bottom:6px\">App Moti</div>${inner}</div></div></div>`\n    if (!me || !me.email) {\n      const L = S.lg || {}, cad = L.modo === 'cad'\n      return lgWrap(`<div class=\"mut\" style=\"margin-bottom:22px\">${cad ? 'Crie sua conta. O acesso libera depois da aprovação.' : 'Entre para ver clientes e pedidos.'}</div>\n        ${cad ? `<div class=\"lb\">NOME</div><input class=\"in\" id=\"lg-nome\" data-lgin autocomplete=\"name\">` : ''}\n        <div class=\"lb\">E-MAIL</div><input class=\"in\" id=\"lg-email\" type=\"email\" data-lgin autocomplete=\"username\" value=\"${esc(L.email || '')}\">\n        <div class=\"lb\">SENHA</div><input class=\"in\" id=\"lg-senha\" type=\"password\" data-lgin autocomplete=\"${cad ? 'new-password' : 'current-password'}\">\n        ${L.err ? `<div style=\"color:#A3402F;font-size:13px;margin:-4px 0 12px\">${esc(L.err)}</div>` : ''}\n        <button class=\"b bd\" data-auth=\"${cad ? 'criar' : 'entrar'}\" style=\"width:100%;height:46px\" ${L.busy ? 'disabled' : ''}>${L.busy ? 'Aguarde…' : (cad ? 'Criar conta' : 'Entrar')}</button>\n        <button class=\"b\" data-auth=\"modo\" style=\"width:100%;height:40px;margin-top:10px;border:none;background:transparent;font-size:13px\">${cad ? 'Já tenho conta' : 'Criar conta'}</button>`)\n    }\n    if (me.role !== 'admin') {\n      return lgWrap(`<div class=\"cd\" style=\"margin-top:18px\">Olá${me.nome ? ', ' + esc(me.nome) : ''}! Seu acesso (${esc(me.email)}) está aguardando aprovação.</div>\n        <button class=\"b\" data-auth=\"sair\" style=\"width:100%;height:42px;margin-top:6px\">Sair</button>`)\n    }\n    const sair = `<div style=\"text-align:center;margin-top:28px\"><button class=\"b\" data-auth=\"sair\">Sair</button></div>`\n\n    const pedDs = d2.data('pedidos'), cliDs = d2.data('clientes'), proDs = d2.data('produtos'), plaDs = d2.data('planos')\n    if (!pedDs || !cliDs || !proDs || !plaDs) return `<div class=\"app\"><div class=\"loading\">Conectando aos dados…</div></div>`\n    const wide = !!S.wide\n    const scr = S.scr || 'resumo'\n    const anoAtual = String(new Date().getFullYear())\n\n    // ---------- data ----------\n    const idOf = (v) => (v && typeof v === 'object') ? (v._id || '') : (v || '')\n    const tsOf = (r) => r.createdAt ? new Date(r.createdAt).getTime() : (r._id ? parseInt(String(r._id).slice(0, 8), 16) * 1000 : Date.now())\n    const pad = (n) => String(n).padStart(2, '0')\n    const PROD = (proDs.records() || []).slice().sort((a, b) => String(a.nome_produto).localeCompare(String(b.nome_produto)))\n    const PESO = (nome) => { const n = String(nome || '').toLowerCase(); return n.includes(' p') && n.includes('osonae') ? 0.25 : 0.5 }\n    const embKey = (nome) => { const n = String(nome || '').toLowerCase(); return n.includes('osonae') ? (n.endsWith(' p') || n.includes('peq') ? 'eP' : 'eG') : 'eM' }\n    const precoDe = (p, rev) => (rev && Number(p.preco_revenda) > 0) ? Number(p.preco_revenda) : (Number(p.preco) || 0)\n    const revChip = (t) => `<span class=\"ch\" style=\"background:transparent;border:1px solid #C9C4CC;color:#57515C;padding:3px 9px\">${t}</span>`\n    const CLI = (cliDs.records() || []).slice().sort((a, b) => String(a.nome).localeCompare(String(b.nome)))\n    const PED = (pedDs.records() || []).map((r, i) => {\n      const t = tsOf(r), d = new Date(t)\n      const it = (r.produtosNomes || []).map((s) => { const m = String(s).match(/^(.*) x(\\d+)$/); return m ? [m[1], +m[2]] : [String(s), 1] })\n      const st = r.pago ? (r.formaPagamento === 'pix' ? 'pix' : 'din') : 'np'\n      return { r, id: r._id || `pending-${i}`, real: !!r._id, c: r.usuarioNome || '', uid: idOf(r.usuarioId), t: Number(r.total) || 0, it, st, e: !!r.entregue, rev: !!r.revenda, ts: t, dt: pad(d.getDate()) + '/' + pad(d.getMonth() + 1) + '/' + String(d.getFullYear()).slice(-2), ano: String(d.getFullYear()) }\n    }).sort((a, b) => b.ts - a.ts)\n    const q = (S.q || '').trim().toLowerCase()\n    const match = (n) => !q || String(n || '').toLowerCase().includes(q)\n\n    const CH = { np: ['Não pago', '#F2D9D0', '#A3402F'], din: ['Pago · Dinheiro', '#DCE7DA', '#3F5E44'], pix: ['Pago · Pix', '#D5E4E6', '#3B5A61'] }\n    const chip = (s) => `<span class=\"ch\" style=\"background:${CH[s][1]};color:${CH[s][2]}\">${CH[s][0]}</span>`\n    const pct = (m) => `<span class=\"ch\" style=\"background:${m < 0 ? '#F2D9D0' : '#DCE7DA'};color:${m < 0 ? '#A3402F' : '#3F5E44'}\">${m}%</span>`\n    const head = (t, btn, sub) => `<div class=\"head\"><div><div class=\"h1\">${esc(t)}</div>${sub ? `<div class=\"mut\" style=\"font-size:13px;margin-top:2px\">${sub}</div>` : ''}</div>${btn ? `<button class=\"b bd\" data-act=\"${btn[1]}\">${btn[0]}</button>` : ''}</div>`\n    const grid = (items) => wide ? `<div class=\"grid2\">${items.map((x) => `<div>${x}</div>`).join('')}</div>` : items.join('')\n    const busca = (ph) => `<input class=\"busca\" id=\"busca\" placeholder=\"${ph}\" value=\"${esc(S.q || '')}\">`\n\n    const pcard = (p, cli) => `<div class=\"cd tap\" data-key=\"${esc(p.id)}\" data-edit=\"pedido:${esc(p.id)}\" style=\"margin:0 0 10px\">\n      <div class=\"r\"><span style=\"font-size:15px\">${cli ? money(p.t) : esc(p.c)} <span class=\"mut\">· ${p.dt}</span></span>${cli ? '' : `<span style=\"font-size:17px\">${money(p.t)}</span>`}</div>\n      <div class=\"box mut\">${p.it.map((x) => `<div class=\"r\" style=\"padding:1px 0\"><span>${esc(x[0])}</span><span style=\"color:#1F1B24\">×${x[1]}</span></div>`).join('') || '<span>Sem itens</span>'}</div>\n      <div style=\"display:flex;gap:6px;margin-top:10px;align-items:center;flex-wrap:wrap\">${chip(p.st)}${p.rev ? revChip('Revenda') : ''}${p.e ? '<span class=\"ch\" style=\"background:#EDE8DE;color:#1F1B24\">Entregue</span>' : ''}<span style=\"flex:1\"></span>\n      <button class=\"b ${p.e ? 'bd' : ''}\" style=\"height:32px;font-size:12px\" data-ent=\"${esc(p.id)}\" ${p.real ? '' : 'disabled'}>${p.e ? 'Entregue ✓' : 'Entregar'}</button></div></div>`\n\n    // ---------- screens ----------\n    const resumo = () => {\n      const fa = S.anoRes || anoAtual\n      const anos = Array.from(new Set([anoAtual, String(+anoAtual - 1), ...PED.map((p) => p.ano)])).sort().reverse().slice(0, 3)\n      const L = PED.filter((p) => fa === 'todos' || p.ano === fa)\n      let din = 0, pix = 0, rec = 0, ab = 0\n      L.forEach((p) => { if (p.st === 'din') din += p.t; else if (p.st === 'pix') pix += p.t; else { rec += p.t; ab++ } })\n      const prodQ = {}\n      L.filter((p) => !p.e).forEach((p) => p.it.forEach((x) => { prodQ[x[0]] = (prodQ[x[0]] || 0) + x[1] }))\n      const fin = [['A receber', rec, ab + (ab === 1 ? ' pedido em aberto' : ' pedidos em aberto'), 1], ['Dinheiro', din], ['Pix', pix], ['Total recebido', din + pix]]\n      const fc = fin.map((x) => `<div class=\"cd ${x[3] ? 'dark' : ''}\" style=\"margin:0\"><div style=\"font-size:12px;color:${x[3] ? '#C9C4CC' : '#57515C'}\">${x[0]}</div><div style=\"font-size:${x[3] && !wide ? 30 : 22}px;margin-top:4px;color:${x[3] ? '#FFF' : '#3F5E44'}\">${money(x[1])}</div>${x[2] ? `<div style=\"font-size:12px;color:#C9C4CC;margin-top:4px\">${x[2]}</div>` : ''}</div>`)\n      const pk = Object.keys(prodQ).filter((k) => prodQ[k] > 0)\n      const prod = `<div class=\"cd\">${pk.length ? pk.map((k, i) => `<div class=\"r\" style=\"padding:6px 0;${i ? 'border-top:1px solid #EFEBE3' : ''}\"><span style=\"font-size:22px\">${prodQ[k]}</span><span>${esc(k)}</span></div>`).join('') : '<div class=\"mut\">Nada pendente para produzir</div>'}</div>`\n      const ult = L.slice(0, 4).map((p) => `<div class=\"cd r\" data-key=\"u-${esc(p.id)}\" style=\"padding:10px 14px\"><div style=\"display:flex;gap:10px;align-items:center;min-width:0\"><div style=\"width:36px;height:36px;border-radius:50%;background:#EDE8DE;display:flex;align-items:center;justify-content:center;flex-shrink:0\">${esc((p.c || '?')[0])}</div><div style=\"min-width:0\"><div>${esc(p.c)} <span class=\"mut\">· ${p.dt}</span></div><div class=\"mut\">${esc(p.it.map((x) => x[0] + ' ×' + x[1]).join(', '))}</div></div></div><span style=\"white-space:nowrap\">${money(p.t)}</span></div>`).join('') || '<div class=\"mut\">Nenhum pedido neste ano</div>'\n      const yrs = `<div class=\"chips\">${anos.map((a) => `<button class=\"f ${fa === a ? 'on' : ''}\" data-anores=\"${a}\">${a}</button>`).join('')}<button class=\"f ${fa === 'todos' ? 'on' : ''}\" data-anores=\"todos\">Todos</button></div>`\n      const lucroDe = (ano) => {\n        const pr = planOf(ano), pv = planOf(String(+ano - 1))\n        if (!pr && !(ano === anoAtual && pv)) return null\n        const P = Object.assign({}, DEF, (pv && pv.params) || {}, (pr && pr.params) || {})\n        const LA = PED.filter((p) => p.ano === ano)\n        let un = 0\n        LA.forEach((p) => p.it.forEach((x) => { un += x[1] }))\n        const agU = un ? (Number(P.agua) || 0) / un : 0, mzU = un ? (Number(P.maiz) || 0) / un : 0, rmn = (Number(P.rmin) || 0) / 3\n        const temR = P.arrozR !== undefined && P.arrozR !== null && P.arrozR !== ''\n        const cuDe = (nome, rv) => { const arr = rv && temR ? Number(P.arrozR) : Number(P.arroz); return (rmn ? PESO(nome) / rmn * (arr || 0) : 0) + agU + mzU + (Number(P[embKey(nome)]) || 0) }\n        let rc = 0, cs = 0, pk = 0\n        LA.filter((p) => p.st !== 'np').forEach((p) => { rc += p.t; p.it.forEach((x) => { cs += cuDe(x[0], p.rev) * x[1]; pk += x[1] }) })\n        return { rc, cs, pk }\n      }\n      const anosLuc = fa === 'todos' ? Array.from(new Set(L.map((p) => p.ano))).sort() : [fa]\n      let lRc = 0, lCs = 0, lPk = 0\n      const semPl = []\n      anosLuc.forEach((a) => { const x = lucroDe(a); if (!x) semPl.push(a); else { lRc += x.rc; lCs += x.cs; lPk += x.pk } })\n      const temLuc = anosLuc.length > semPl.length\n      const lV = lRc - lCs\n      const lChip = `<span class=\"ch\" style=\"font-size:${wide ? 15 : 13}px;background:${lV < 0 ? '#F2D9D0' : '#DCE7DA'};color:${lV < 0 ? '#A3402F' : '#3F5E44'}\">${lV < 0 ? '−' : ''}${money(Math.abs(lV))}</span>`\n      const lNota = !temLuc ? '' : (fa === 'todos' ? 'Custo do Planejamento de cada ano' + (semPl.length ? ' · sem planejamento: ' + semPl.join(', ') + ' (fora da conta)' : '') : 'Custo por pacote do Planejamento ' + fa)\n      const lBorda = 'border:2px solid ' + (temLuc && lV < 0 ? '#F2D9D0' : '#C9DCC6')\n      const luc = !temLuc\n        ? `<div class=\"cd\" style=\"margin:${wide ? '10px 0 0' : '0'};${lBorda}\"><div class=\"mut\">Lucro dos pedidos pagos</div><div style=\"margin-top:6px\">Sem planejamento de ${fa === 'todos' ? 'nenhum ano' : fa}</div></div>`\n        : wide\n          ? `<div class=\"cd\" style=\"margin:10px 0 0;${lBorda};display:flex;align-items:center;gap:22px;flex-wrap:wrap\"><div style=\"min-width:160px\"><div class=\"mut\">Lucro dos pedidos pagos</div><div class=\"mut\" style=\"margin-top:3px\">${lPk} pacotes · ${esc(lNota)}</div></div><div style=\"flex:1;display:flex;gap:22px;justify-content:flex-end;align-items:center;flex-wrap:wrap\"><div><div class=\"mut\">Total recebido</div><div style=\"margin-top:2px\">${money(lRc)}</div></div><div><div class=\"mut\">Custo dos pacotes</div><div style=\"margin-top:2px\">− ${money(lCs)}</div></div><div style=\"border-left:1px solid #EFEBE3;padding-left:18px\"><div class=\"mut\">Lucro</div><div style=\"margin-top:2px\">${lChip}</div></div></div></div>`\n          : `<div class=\"cd\" style=\"margin:0;${lBorda}\"><div class=\"r\"><span class=\"mut\">Lucro dos pedidos pagos</span><span class=\"mut\" style=\"font-size:11px\">${lPk} pacotes</span></div><div class=\"r\" style=\"margin-top:10px\"><span>Total recebido</span><span>${money(lRc)}</span></div><div class=\"r\" style=\"margin-top:6px\"><span>Custo dos pacotes</span><span>− ${money(lCs)}</span></div><div class=\"r ln\"><span style=\"font-size:15px\">Lucro</span>${lChip}</div><div class=\"mut\" style=\"margin-top:8px\">${esc(lNota)}</div></div>`\n      return head('Resumo') + yrs + `<div class=\"sec\">Financeiro</div>` + (wide\n        ? `<div class=\"grid4\">${fc.join('')}</div>${luc}<div class=\"cols\"><div><div class=\"sec\">Produção necessária</div>${prod}</div><div><div class=\"sec\">Últimos pedidos</div>${ult}</div></div>`\n        : `<div style=\"display:grid;gap:10px\">${fc.join('')}${luc}</div><div class=\"sec\">Produção necessária</div>${prod}<div class=\"sec\">Últimos pedidos</div>${ult}`)\n    }\n\n    const pedidos = () => {\n      const fil = S.fil || 'todos'\n      const F = [['todos', 'Todos'], ['pagos', 'Pagos'], ['np', 'Não pagos'], ['ent', 'A entregar']]\n      const fano = S.anoPed || 'todos'\n      const anosP = Array.from(new Set([anoAtual, String(+anoAtual - 1), ...PED.map((p) => p.ano)])).sort().reverse().slice(0, 3)\n      const l = PED.filter((p) => match(p.c)).filter((p) => fano === 'todos' || p.ano === fano).filter((p) => fil === 'todos' || (fil === 'ent' ? !p.e : fil === 'pagos' ? p.st !== 'np' : p.st === 'np'))\n      return head('Pedidos', ['+ Pedido', 'new:pedido']) + busca('Buscar por cliente') +\n        `<div class=\"chips\">${F.map((x) => `<button class=\"f ${fil === x[0] ? 'on' : ''}\" data-fil=\"${x[0]}\">${x[1]}</button>`).join('')}</div>` +\n        `<div class=\"chips\">${anosP.map((a) => `<button class=\"f ${fano === a ? 'on' : ''}\" data-anoped=\"${a}\">${a}</button>`).join('')}<button class=\"f ${fano === 'todos' ? 'on' : ''}\" data-anoped=\"todos\">Todos</button></div>` +\n        (pedDs.loading ? '<div class=\"mut\">Carregando…</div>' : (l.length ? grid(l.map((p) => pcard(p))) : '<div class=\"mut\">Nenhum pedido encontrado</div>'))\n    }\n\n    const waBtn = (c) => c.telefone ? `<button class=\"b wa\" data-wa=\"${esc(c.telefone)}\">WhatsApp</button>` : ''\n    const clientes = () => {\n      const st = (id) => { const p = PED.filter((x) => x.uid === id); return [p.length, p.reduce((a, x) => a + x.t, 0), p.filter((x) => x.st === 'np' || !x.e).length] }\n      const L = CLI.filter((c) => match(c.nome))\n      if (wide) return head('Clientes', ['+ Cliente', 'new:cliente']) + busca('Buscar cliente') +\n        `<div class=\"cd\" style=\"padding:4px 10px\"><table class=\"tbl\"><tr><th>Nome</th><th>Telefone</th><th>Pedidos em aberto</th><th>Pedidos totais</th><th></th></tr>${L.map((c) => { const s = st(c._id); return `<tr class=\"tap\" data-key=\"${esc(c._id || 'pc-' + c.nome)}\" data-edit=\"cliente:${esc(c._id)}\"><td>${esc(c.nome)} ${c.revendedor ? revChip('Revendedor') : ''}</td><td class=\"mut\">${esc(c.telefone) || '—'}</td><td>${s[2]}</td><td>${s[0]}</td><td style=\"text-align:right;white-space:nowrap\">${waBtn(c)} <button class=\"b\" data-cli=\"${esc(c._id)}\">Pedidos</button></td></tr>` }).join('')}</table></div>`\n      return head('Clientes', ['+ Cliente', 'new:cliente']) + busca('Buscar cliente') +\n        (L.map((c) => `<div class=\"cd r tap\" data-key=\"${esc(c._id || 'pc-' + c.nome)}\" data-edit=\"cliente:${esc(c._id)}\"><div style=\"min-width:0\"><div>${esc(c.nome)} ${c.revendedor ? revChip('Revendedor') : ''}</div><div class=\"mut\">${esc(c.telefone) || 'Sem telefone'}</div></div><div style=\"display:flex;gap:6px\">${waBtn(c)}<button class=\"b\" data-cli=\"${esc(c._id)}\">Pedidos</button></div></div>`).join('') || '<div class=\"mut\">Nenhum cliente encontrado</div>')\n    }\n\n    const produtos = () => {\n      if (wide) return head('Produtos', ['+ Produto', 'new:produto']) + `<div class=\"cd\" style=\"padding:4px 10px\"><table class=\"tbl\"><tr><th>Produto</th><th>Peso</th><th>Preço</th><th>Revenda</th></tr>${PROD.map((p) => `<tr class=\"tap\" data-key=\"${esc(p._id || 'pp-' + p.nome_produto)}\" data-edit=\"produto:${esc(p._id)}\"><td>${esc(p.nome_produto)}</td><td class=\"mut\">${PESO(p.nome_produto) * 1000} g</td><td>${money(p.preco)}</td><td class=\"mut\">${Number(p.preco_revenda) > 0 ? money(p.preco_revenda) : '—'}</td></tr>`).join('')}</table></div>`\n      return head('Produtos', ['+ Produto', 'new:produto']) + PROD.map((p) => `<div class=\"cd r tap\" data-key=\"${esc(p._id || 'pp-' + p.nome_produto)}\" data-edit=\"produto:${esc(p._id)}\"><div>${esc(p.nome_produto)}<div class=\"mut\">${PESO(p.nome_produto) * 1000} g</div></div><div style=\"text-align:right\">${money(p.preco)}${Number(p.preco_revenda) > 0 ? `<div class=\"mut\">Revenda ${money(p.preco_revenda)}</div>` : ''}</div></div>`).join('')\n    }\n\n    const pedCli = () => {\n      const c = CLI.find((x) => x._id === S.cli) || {}\n      const l = PED.filter((p) => p.uid === S.cli)\n      return `<button class=\"b\" data-act=\"voltar\" style=\"margin-bottom:12px\">← Clientes</button>` + head(c.nome || 'Cliente', ['+ Pedido', 'new:pedido'], l.length + (l.length === 1 ? ' pedido' : ' pedidos')) + (l.length ? grid(l.map((p) => pcard(p, 1))) : '<div class=\"mut\">Nenhum pedido</div>')\n    }\n\n    // ---------- planejamento ----------\n    const DEF = { arroz: 15, rmin: 4.5, rmax: 4.7, agua: 0, maiz: 0, eM: 0, eG: 0, eP: 0, lucro: 100 }\n    const planos = plaDs.records() || []\n    const planOf = (a) => planos.find((p) => String(p.ano) === String(a))\n    const plano = () => {\n      const pa = S.planAno || anoAtual\n      const cur = pa === anoAtual\n      const rev = !!S.planRev\n      const rec = planOf(pa), prevRec = planOf(String(+pa - 1))\n      const P = Object.assign({}, DEF, (prevRec && prevRec.params) || {}, (rec && rec.params) || {})\n      const queroSaved = (rec && rec.quero) || {}\n      const quero = Object.assign({}, queroSaved, S.queroLocal || {})\n      let qd, qdR\n      if (cur) { qd = {}; qdR = {}; PED.filter((p) => p.ano === pa && !p.e).forEach((p) => p.it.forEach((x) => { qd[x[0]] = (qd[x[0]] || 0) + x[1]; if (p.rev) qdR[x[0]] = (qdR[x[0]] || 0) + x[1] })) }\n      else { qd = (rec && rec.foto && rec.foto.demanda) || {}; qdR = (rec && rec.foto && rec.foto.demandaRev) || {} }\n      const rmin = P.rmin / 3, rmax = P.rmax / 3\n      let un = 0\n      PROD.forEach((p) => { un += qd[p.nome_produto] || 0 })\n      const agU = un ? P.agua / un : 0, mzU = un ? P.maiz / un : 0\n      const temArrR = P.arrozR !== undefined && P.arrozR !== null && P.arrozR !== ''\n      const calc = (rv) => {\n        const arrKg = rv ? (temArrR ? Number(P.arrozR) : null) : Number(P.arroz)\n        const marg = rv ? P.lucro * 0.8 : P.lucro\n        let kg = 0, unP = 0, tot = 0, gan = 0\n        const linhas = PROD.map((p) => {\n          const peso = PESO(p.nome_produto), nT = qd[p.nome_produto] || 0, nR = qdR[p.nome_produto] || 0, n = rv ? nR : nT - nR\n          kg += n * peso; unP += n\n          const ar = arrKg === null ? null : (rmin ? peso / rmin * arrKg : 0), em = Number(P[embKey(p.nome_produto)]) || 0\n          const cu = ar === null ? null : ar + agU + mzU + em\n          const sug = cu === null ? null : Math.ceil(cu * (1 + marg / 100) * 2 - 1e-9) / 2\n          const key = (rv ? 'r:' : '') + p._id\n          const qv = quero[key]; const has = qv !== undefined && qv !== '' && qv !== null\n          if (cu !== null) tot += cu * n\n          gan += (has ? Number(qv) : 0) * n\n          const mg = (v) => cu ? Math.round((v - cu) / cu * 100) : 0\n          const atual = rv ? (Number(p.preco_revenda) || 0) : (Number(p.preco) || 0)\n          return { p, n, ar, em, cu, sug, key, qv: has ? qv : '', has, mg, atual }\n        })\n        return { linhas, kg, unP, tot, gan, arrKg, marg, ok: arrKg !== null && linhas.every((l) => l.has) }\n      }\n      const C = calc(false), R = calc(true), V = rev ? R : C\n      MEM.plan = { pa, P, rev, linhas: V.linhas, ok: V.ok, qd, qdR, kg: C.kg + R.kg, tot: C.tot + R.tot, gan: C.gan + R.gan }\n      const aMin = rmax ? V.kg / rmax : 0, aMax = rmin ? V.kg / rmin : 0, pac = Math.ceil(aMax - 1e-9)\n      const luc = V.gan - V.tot\n      const nada = '<span class=\"mut\">—</span>'\n      const cards = V.linhas.map((l) => `<div class=\"cd\" data-key=\"pl-${rev ? 'r' : 'c'}-${esc(l.p._id)}\" style=\"margin:0 0 10px\">\n        <div class=\"r\"><span style=\"font-size:16px\">${esc(l.p.nome_produto)} <span class=\"mut\">${PESO(l.p.nome_produto) * 1000} g</span></span><span style=\"font-size:19px\">${l.cu === null ? '—' : money(l.cu)}</span></div>\n        <div class=\"box mut\"><div class=\"r\"><span>Arroz</span><span>${l.ar === null ? 'defina o preço nos parâmetros' : money(l.ar)}</span></div><div class=\"r\"><span>Água e luz</span><span>${money(agU)}</span></div><div class=\"r\"><span>Maizena</span><span>${money(mzU)}</span></div><div class=\"r\"><span>Embalagem</span><span>${money(l.em)}</span></div></div>\n        ${cur ? `<div class=\"r ln\"><span class=\"mut\" style=\"font-size:13px\">${rev ? 'Preço atual de revenda' : 'Preço atual'}</span><span style=\"display:flex;gap:6px;align-items:center\">${l.atual > 0 ? money(l.atual) + (l.cu === null ? '' : ' ' + pct(l.mg(l.atual))) : '—'}</span></div>` : ''}\n        <div class=\"r\" style=\"margin-top:8px\"><span class=\"mut\" style=\"font-size:13px\">Preço sugerido (para ${Math.round(V.marg * 10) / 10}% de margem)</span><span>${l.sug === null ? '—' : money(l.sug)}</span></div>\n        <div class=\"r ln\"><span>${cur ? 'Quero cobrar' : 'Preço cobrado'}</span><span style=\"display:flex;gap:8px;align-items:center\">${cur ? `<input class=\"num\" type=\"text\" inputmode=\"decimal\" placeholder=\"R$\" data-q=\"${esc(l.key)}\" value=\"${esc(l.qv)}\">` : (l.has ? money(l.qv) : '—')}${l.has && l.cu !== null ? pct(l.mg(Number(l.qv))) : nada}</span></div>\n        <div class=\"r\" style=\"margin-top:8px\"><span class=\"mut\" style=\"font-size:13px\">Lucro por pacote</span><span>${l.has && l.cu !== null ? ((Number(l.qv) - l.cu) < 0 ? '−' : '') + money(Math.abs(Number(l.qv) - l.cu)) : '—'}</span></div></div>`).join('')\n      const tots = `<div class=\"cd\"><div class=\"r\"><span>Custo total da produção</span><span>${money(V.tot)}</span></div><div class=\"r\" style=\"margin-top:6px\"><span>Ganho estimado</span><span>${money(V.gan)}</span></div><div class=\"r ln\"><span style=\"font-size:15px\">Lucro estimado</span><span class=\"ch\" style=\"font-size:13px;background:${luc < 0 ? '#F2D9D0' : '#DCE7DA'};color:${luc < 0 ? '#A3402F' : '#3F5E44'}\">${luc < 0 ? '−' : ''}${money(Math.abs(luc))}</span></div></div>` +\n        (cur ? `<button class=\"b\" data-act=\"aplicar\" style=\"width:100%;height:46px;font-size:14px;border:none;background:${V.ok ? '#1F1B24' : '#D8D2C6'};color:${V.ok ? '#FFF' : '#57515C'}\">Aplicar preços de ${rev ? 'revenda' : 'cliente'}</button>${V.ok ? '' : `<div class=\"mut\" style=\"text-align:center;margin-top:6px\">${V.arrKg === null ? 'Defina o preço do arroz de revendedor nos parâmetros' : 'Defina os preços dos 3 produtos para aplicar'}</div>`}` : '')\n      const anos = Array.from(new Set([anoAtual, ...planos.map((p) => String(p.ano))])).sort().reverse()\n      const swap = '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M7 4L3 8l4 4\"/><path d=\"M3 8h13\"/><path d=\"M17 20l4-4-4-4\"/><path d=\"M21 16H8\"/></svg>'\n      const quem = rev ? 'revendedores' : 'clientes comuns'\n      const top = `<div class=\"chips\" style=\"align-items:center\">${anos.map((a) => `<button class=\"f ${pa === a ? 'on' : ''}\" data-planano=\"${a}\">${a}</button>`).join('')}<span style=\"flex:1\"></span><button class=\"f\" data-planrev style=\"display:inline-flex;align-items:center;gap:6px;border-color:#1F1B24\">${swap}${rev ? 'Revendedor' : 'Cliente'}</button></div>` +\n        (cur ? '' : `<div class=\"box mut\" style=\"margin:0 0 6px\">Planejamento guardado de ${pa}, só consulta.</div>`) +\n        `<div class=\"sec\">${cur ? 'Demanda · pedidos não entregues de ' + quem : 'Demanda de ' + quem + ' em ' + pa}</div><div class=\"cd\">${V.linhas.map((l) => `<div class=\"r\" style=\"padding:3px 0\"><span>${esc(l.p.nome_produto)}</span><span class=\"mut\">${l.n} un · ${(l.n * PESO(l.p.nome_produto)).toFixed(1)} kg</span></div>`).join('')}<div class=\"r ln\"><span>Total a produzir</span><span>${V.unP} pacotes · ${V.kg.toFixed(1)} kg</span></div><div class=\"mut\" style=\"margin-top:6px\">Água, luz e maizena divididas pelos ${un} pacotes de clientes e revendedores</div></div>\n        <div class=\"cd dark\"><div style=\"font-size:12px;color:#C9C4CC\">Arroz de moti necessário · ${rev ? 'revendedor' : 'cliente'}</div><div style=\"font-size:28px;margin:2px 0\">${aMin.toFixed(1)} a ${aMax.toFixed(1)} kg</div><div style=\"font-size:12px;color:#C9C4CC\">Comprar ${pac} pacotes de 1 kg${V.arrKg === null ? '' : ' · ' + money(pac * V.arrKg)}</div></div>`\n      if (wide) return head('Planejamento', null, 'Produção de fim de ano') + `<div class=\"plancols\"><div style=\"min-width:0\">${top}<div class=\"sec\">Custo por pacote</div>${cards}${tots}</div><div class=\"cd\" style=\"padding:8px 16px\">${paramsForm(P, prevRec, pa, cur)}</div></div>`\n      return head('Planejamento', ['Parâmetros', 'sheet'], 'Produção de fim de ano') + top + `<div class=\"sec\">Custo por pacote</div>` + cards + tots\n    }\n    const LBL = [['ARROZ DE MOTI'], ['arroz', 'Preço cliente (R$/kg)'], ['arrozR', 'Preço revendedor (R$/kg)'], ['rmin', '3 kg rendem, mínimo (kg)'], ['rmax', '3 kg rendem, máximo (kg)'], ['GASTOS ÚNICOS DO MÊS'], ['agua', 'Aumento de água e luz (R$)'], ['maiz', 'Maizena (R$)'], ['EMBALAGENS'], ['eM', 'Moti (R$)'], ['eG', 'Osonae G (R$)'], ['eP', 'Osonae P (R$)'], ['VENDA'], ['lucro', 'Margem de lucro (%)']]\n    function paramsForm(P, prevRec, pa, cur) {\n      return `<div style=\"font-size:18px;padding:6px 0 2px\">Parâmetros</div>` + LBL.map((l) => l.length === 1 ? `<div class=\"grp\">${l[0]}</div>` :\n        `<div class=\"pin\"><div class=\"r\"><span>${l[1]}</span><input class=\"num\" type=\"text\" inputmode=\"decimal\" data-p=\"${l[0]}\" value=\"${esc(S.pDraft && S.pDraft[l[0]] !== undefined ? S.pDraft[l[0]] : P[l[0]])}\" ${cur ? '' : 'disabled'}></div>${prevRec && prevRec.params && prevRec.params[l[0]] !== undefined ? `<div class=\"prev\">${+pa - 1}: ${esc(prevRec.params[l[0]])}</div>` : ''}</div>`).join('') +\n        (cur ? `<button class=\"b bd\" data-act=\"salvarparams\" style=\"width:100%;height:46px;margin-top:14px\">Salvar parâmetros</button>` : '')\n    }\n\n    // ---------- forms ----------\n    const form = () => {\n      const fm = S.form; if (!fm) return ''\n      const k = fm.k, ed = !!fm.id\n      let T = '', body = ''\n      if (k === 'pedido') {\n        T = 'pedido'\n        const cliSel = CLI.find((c) => c._id === fm.cli)\n        const rev = (fm.id && fm.cli === fm.cli0) ? !!fm.rev0 : !!(cliSel && cliSel.revendedor)\n        const total = PROD.reduce((a, p) => a + (Number(fm.qtd[p._id]) || 0) * precoDe(p, rev), 0)\n        body = `<div class=\"lb\">CLIENTE</div><select class=\"in\" data-fm=\"cli\">${['<option value=\"\">Selecione um cliente</option>'].concat(CLI.map((c) => `<option value=\"${esc(c._id)}\" ${fm.cli === c._id ? 'selected' : ''}>${esc(c.nome)}</option>`)).join('')}</select>${rev ? '<div class=\"mut\" style=\"margin:-6px 0 12px\">Cliente revendedor · preços de revenda</div>' : ''}\n        <div class=\"lb\">PRODUTOS</div><div class=\"cd\" style=\"padding:6px 14px;margin:4px 0 12px\">${PROD.map((p) => `<div class=\"r\" style=\"padding:6px 0\"><span>${esc(p.nome_produto)}<div class=\"mut\">${money(precoDe(p, rev))}</div></span><span class=\"stp\"><button class=\"b\" data-qty=\"${esc(p._id)}:-1\">−</button><span style=\"min-width:22px;text-align:center\">${Number(fm.qtd[p._id]) || 0}</span><button class=\"b bd\" style=\"width:32px;height:32px;padding:0\" data-qty=\"${esc(p._id)}:1\">+</button></span></div>`).join('')}</div>\n        <div class=\"lb\">PAGAMENTO</div><div class=\"chips\" style=\"margin:4px 0 12px\">${[['', 'Não pago'], ['dinheiro', 'Dinheiro'], ['pix', 'Pix']].map((o) => `<button class=\"f ${fm.pag === o[0] ? 'on' : ''}\" data-pag=\"${o[0]}\">${o[1]}</button>`).join('')}</div>\n        <div class=\"r ln\" style=\"margin-bottom:4px\"><span class=\"mut\">Total</span><span style=\"font-size:24px\">${money(total)}</span></div>`\n      }\n      if (k === 'cliente') { T = 'cliente'; body = `<div class=\"lb\">NOME</div><input class=\"in\" data-fm=\"nome\" value=\"${esc(fm.nome)}\" placeholder=\"Nome do cliente\"><div class=\"lb\">TELEFONE</div><input class=\"in\" data-fm=\"tel\" inputmode=\"tel\" value=\"${esc(fm.tel)}\" placeholder=\"11 99999-9999\"><div class=\"lb\">TIPO</div><div class=\"chips\" style=\"margin:4px 0 12px\"><button class=\"f ${fm.rev ? '' : 'on'}\" data-rev=\"0\">Consumidor</button><button class=\"f ${fm.rev ? 'on' : ''}\" data-rev=\"1\">Revendedor</button></div>` }\n      if (k === 'produto') { T = 'produto'; body = `<div class=\"lb\">NOME</div><input class=\"in\" data-fm=\"nome\" value=\"${esc(fm.nome)}\" placeholder=\"Nome do produto\"><div class=\"lb\">PREÇO (R$)</div><input class=\"in\" data-fm=\"preco\" type=\"text\" inputmode=\"decimal\" value=\"${esc(fm.preco)}\" placeholder=\"0.00\"><div class=\"lb\">PREÇO DE REVENDA (R$)</div><input class=\"in\" data-fm=\"precoRev\" type=\"text\" inputmode=\"decimal\" value=\"${esc(fm.precoRev)}\" placeholder=\"Vazio = preço normal\">` }\n      return `<div style=\"font-size:21px;margin-bottom:12px\">${ed ? 'Editar' : 'Novo'} ${T}</div>${body}${fm.err ? `<div style=\"color:#A3402F;font-size:13px;margin-bottom:8px\">${esc(fm.err)}</div>` : ''}\n        <button class=\"b bd\" data-act=\"salvar\" style=\"width:100%;height:50px;margin-top:6px;font-size:15px\" ${S.busy ? 'disabled' : ''}>${S.busy ? 'Salvando…' : 'Salvar'}</button>\n        <button class=\"b\" data-act=\"fechar\" style=\"width:100%;height:44px;margin-top:8px;font-size:14px\">Cancelar</button>\n        ${ed ? `<button class=\"b\" data-act=\"excluir\" style=\"width:100%;height:40px;margin-top:8px;border:none;background:transparent;color:#A3402F;font-size:14px\">Excluir ${T}</button>` : ''}`\n    }\n\n    // ---------- confirm ----------\n    const conf = () => {\n      const c = S.conf; if (!c) return ''\n      return `<div class=\"ov\"><div class=\"ovc\" data-act=\"confno\"></div><div class=\"modal\"><div style=\"font-size:20px;margin-bottom:10px\">${esc(c.title)}</div>${c.html || ''}\n        <div style=\"display:flex;gap:10px;margin-top:16px\"><button class=\"b\" data-act=\"confno\" style=\"flex:1;height:46px;font-size:14px\">Cancelar</button><button class=\"b bd\" data-act=\"confsim\" style=\"flex:1;height:46px;${c.danger ? 'background:#A3402F' : ''}\" ${S.busy ? 'disabled' : ''}>${S.busy ? 'Aguarde…' : esc(c.ok)}</button></div></div></div>`\n    }\n\n    // ---------- shell ----------\n    const ico = (d) => `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"display:block;margin:0 auto\">${d}</svg>`\n    const NAV = [['resumo', 'Resumo', ico('<path d=\"M12 3v9h9\"/><circle cx=\"12\" cy=\"12\" r=\"9\"/>')], ['pedidos', 'Pedidos', ico('<path d=\"M6 8h12l-1 12H7z\"/><path d=\"M9 8V6a3 3 0 0 1 6 0v2\"/>')], ['clientes', 'Clientes', ico('<circle cx=\"12\" cy=\"8\" r=\"4\"/><path d=\"M4 21c1-4 4-6 8-6s7 2 8 6\"/>')], ['produtos', 'Produtos', ico('<path d=\"M12 3l8 4.5v9L12 21l-8-4.5v-9z\"/><path d=\"M12 12l8-4.5M12 12v9M12 12L4 7.5\"/>')], ['plan', 'Planejar', ico('<rect x=\"5\" y=\"3\" width=\"14\" height=\"18\" rx=\"2\"/><path d=\"M8 7h8M8 12h2M14 12h2M8 16h2M14 16h2\"/>')]]\n    let body\n    try {\n      body = (scr === 'clientes' && S.cli) ? pedCli() : ({ resumo, pedidos, clientes, produtos, plan: plano }[scr] || resumo)()\n    } catch (e) { body = `<div style=\"color:#A3402F\">Erro: ${esc(e.message)}</div>` }\n    if (scr === 'resumo') body += sair\n    const toast = S.toast ? `<div class=\"toast\">${esc(S.toast)}</div>` : ''\n    if (wide) {\n      return `<div class=\"app wide\"><div class=\"side\"><div class=\"brand\">App Moti</div>${NAV.map((n) => `<div class=\"sb ${scr === n[0] ? 'on' : ''}\" data-nav=\"${n[0]}\"><span style=\"width:18px\">${n[2]}</span>${n[1]}</div>`).join('')}</div>\n        <div class=\"main\"><div class=\"inner\">${body}</div></div>${S.form ? `<div class=\"panel\">${form()}</div>` : ''}${conf()}${toast}</div>`\n    }\n    const sheet = S.form ? form() : (S.sheet && MEM.plan ? paramsForm(MEM.plan.P, planOf(String(+MEM.plan.pa - 1)), MEM.plan.pa, MEM.plan.pa === anoAtual) : '')\n    return `<div class=\"app${S.pg ? ' pg' : ''}\"><div class=\"main\"><div class=\"inner\">${body}</div></div>\n      <div class=\"tabs\">${NAV.map((n) => `<div class=\"tb ${scr === n[0] ? 'on' : ''}\" data-nav=\"${n[0]}\"><span class=\"ic\">${n[2]}</span>${n[1]}</div>`).join('')}</div>\n      ${sheet ? `<div class=\"ov\"><div class=\"ovc\" data-act=\"fechar\"></div><div class=\"sheet\"><div class=\"handle\"></div>${sheet}</div></div>` : ''}${conf()}${toast}</div>`\n  },\n\n  updated(d2) { pgSync(d2.state) },\n\n  mounted(d2, root) {\n    const S = d2.state\n    if (S.scr === undefined) S.scr = 'resumo'\n    const DSM = { pedidos: () => d2.data('pedidos'), clientes: () => d2.data('clientes'), produtos: () => d2.data('produtos'), planos: () => d2.data('planos') }\n    const loadAllDs = () => [DSM.pedidos(), DSM.clientes(), DSM.produtos(), DSM.planos()].forEach((h) => { if (h && h.loadAll) Promise.resolve(h.loadAll()).catch(() => {}) })\n    loadAllDs()\n    const userOf = (a) => { if (!a) return null; const u = a.user; if (u && u.email) return u; const c = a.raw && a.raw.cursor && a.raw.cursor.current; if (c && c.credentials && c.credentials.email) return c.credentials; if (c && c.email) return c; let g = null; try { g = a.raw && a.raw.getSelectedSession && a.raw.getSelectedSession() } catch (e) {} if (g && g.authStrategy === 'moti-auth' && g.credentials && g.credentials.email) return g.credentials; return null }\n    const isAdmin = () => { const u = userOf(d2.auth('auth')); return !!(u && u.email && u.role === 'admin') }\n\n    // ---------- login / cadastro / sair ----------\n    const val = (id) => { const el = root.querySelector('#' + id); return el ? String(el.value || '').trim() : '' }\n    d2.on('[data-lgin]', 'keydown', (e) => { if (e.key === 'Enter') { const b = root.querySelector('[data-auth=\"entrar\"],[data-auth=\"criar\"]'); if (b) b.click() } })\n    d2.on('[data-auth]', 'click', async (e, el) => {\n      const a = el.dataset.auth, au = d2.auth('auth')\n      if (!au) return\n      if (a === 'modo') { S.lg = { modo: (S.lg && S.lg.modo === 'cad') ? 'login' : 'cad', email: val('lg-email') }; return }\n      if (a === 'sair') { try { await au.logout() } catch (err) {} S.scr = 'resumo'; S.form = null; S.lg = {}; return }\n      const email = val('lg-email').toLowerCase(), password = val('lg-senha'), nome = val('lg-nome')\n      const modo = a === 'criar' ? 'cad' : 'login'\n      if (!email || !password || (modo === 'cad' && !nome)) { S.lg = { modo, email, err: 'Preencha todos os campos' }; return }\n      S.lg = { modo, email, busy: true }\n      let falhou = false, errMsg = ''\n      try {\n        if (modo === 'cad') { const res = await d2.rush(d2.param('rushCriar')).invoke({ email, password, nome }); const r = (res && res.data && typeof res.data === 'object') ? res.data : (res || {}); if (!r.ok) { S.lg = { modo, email, err: r.error || 'Não foi possível criar a conta' }; return } }\n        const inst = au.raw\n        if (inst && inst.cursor) { if (!inst.cursor.current) inst.cursor.current = {}; inst.cursor.current.credentials = { email, password } }\n        if (inst && typeof inst.login === 'function') await inst.login({ credentials: { email, password } })\n        else await au.login({ credentials: { email, password } })\n      } catch (err) { falhou = true; try { console.error('[moti-login]', err, err && err.response && err.response.data) } catch (e3) {} errMsg = (err && ((err.response && err.response.data && (err.response.data.message || err.response.data.error)) || err.message || (err.error && err.error.message))) || String(err || ''); try { const i2 = au.raw; if (i2 && i2.cursor) i2.cursor.current = null } catch (e2) {} }\n      const u = userOf(au)\n      if (!falhou && u && u.email) { S.lg = {}; loadAllDs() } else S.lg = { modo, email, err: (modo === 'cad' ? 'Não foi possível criar a conta (e-mail já usado?)' : 'E-mail ou senha incorretos') + (errMsg && errMsg !== 'erro' ? ' — ' + errMsg : '') }\n    })\n    const measure = () => { const w = root.clientWidth || 0; const wide = w >= 900; if (!!S.wide !== wide) S.wide = wide }\n    measure()\n    const naCanvas = !!(d2.context && d2.context.isBuilder && !d2.context.isPlaying)\n    if (!naCanvas && document.head && document.documentElement) {\n      if (!document.getElementById('moti-pg-css')) { const st = document.createElement('style'); st.id = 'moti-pg-css'; st.textContent = PG_CSS; document.head.appendChild(st) }\n      S.pg = true\n      pgSync(S)\n      d2.onUnmount(() => document.documentElement.classList.remove('moti-pg', 'moti-lock', 'moti-nopull'))\n    }\n    if (typeof ResizeObserver !== 'undefined') { const ro = new ResizeObserver(measure); ro.observe(root); d2.onUnmount(() => ro.disconnect()) }\n\n    // ---------- auto-refresh: ao voltar para o app + a cada 30s com o app visível ----------\n    let lastLoad = Date.now()\n    const editing = () => { const rn = root.getRootNode ? root.getRootNode() : null; const ae = (rn && rn.activeElement) || null; return !!(ae && /^(INPUT|SELECT|TEXTAREA)$/.test(ae.tagName) && ae.id !== 'busca') }\n    const reload = (force) => {\n      if (document.hidden || S.busy || S.conf || editing() || !isAdmin()) return\n      if (!force && Date.now() - lastLoad < 5000) return\n      lastLoad = Date.now()\n      Object.keys(DSM).forEach((n) => { const h = DSM[n](); if (h && h.loadAll) Promise.resolve(h.loadAll()).catch(() => {}) })\n    }\n    const timer = setInterval(() => reload(true), 30000)\n    d2.onUnmount(() => clearInterval(timer))\n    d2.on(document, 'visibilitychange', () => { if (!document.hidden) reload() })\n    d2.on(window, 'focus', () => reload())\n\n    const num = (v) => { const t = String(v == null ? '' : v).trim().replace(/\\s/g, '').replace(',', '.'); return t === '' ? NaN : Number(t) }\n    const anoAtual = String(new Date().getFullYear())\n    const toast = (m) => { S.toast = m; setTimeout(() => { if (S.toast === m) S.toast = null }, 2600) }\n    const idOf = (v) => (v && typeof v === 'object') ? (v._id || '') : (v || '')\n    const recs = (n) => (DSM[n]().records() || [])\n    const pedRec = (id) => recs('pedidos').find((r) => r._id === id)\n    const sigOf = (k, r) => !r ? '' : JSON.stringify(k === 'pedido' ? [idOf(r.usuarioId), r.produtosNomes, r.total, !!r.pago, r.formaPagamento || '', !!r.entregue] : k === 'cliente' ? [r.nome, r.telefone, !!r.revendedor] : [r.nome_produto, r.preco, r.preco_revenda])\n    const parseItens = (r) => (r.produtosNomes || []).map((s) => { const m = String(s).match(/^(.*) x(\\d+)$/); return m ? [m[1], +m[2]] : [String(s), 1] })\n    const precoDe = (p, rev) => (rev && Number(p.preco_revenda) > 0) ? Number(p.preco_revenda) : (Number(p.preco) || 0)\n    const pedidoPayload = (base, cliId, qtd, pag, entregue, rev) => {\n      const prods = recs('produtos'), cli = recs('clientes').find((c) => c._id === cliId) || {}\n      const sel = prods.filter((p) => (Number(qtd[p._id]) || 0) > 0)\n      return Object.assign({}, base, {\n        usuarioId: cliId, usuarioNome: cli.nome || '',\n        produtosIds: sel.map((p) => p._id), produtosNomes: sel.map((p) => `${p.nome_produto} x${Number(qtd[p._id])}`),\n        total: sel.reduce((a, p) => a + Number(qtd[p._id]) * precoDe(p, rev), 0),\n        pago: pag !== '', formaPagamento: pag, entregue: !!entregue, revenda: !!rev\n      })\n    }\n\n    d2.on('[data-nav]', 'click', (e, el) => { S.scr = el.dataset.nav; S.q = ''; S.cli = null; S.form = null; S.sheet = false; S.pDraft = {}; S.pBase = null })\n    d2.on('[data-fil]', 'click', (e, el) => { S.fil = el.dataset.fil })\n    d2.on('[data-anores]', 'click', (e, el) => { S.anoRes = el.dataset.anores })\n    d2.on('[data-anoped]', 'click', (e, el) => { S.anoPed = el.dataset.anoped })\n    d2.on('[data-planano]', 'click', (e, el) => { S.planAno = el.dataset.planano; S.queroLocal = {}; S.pDraft = {}; S.pBase = null })\n    d2.on('[data-planrev]', 'click', () => { S.planRev = !S.planRev })\n    d2.on('#busca', 'input', (e, el) => { S.q = el.value })\n    d2.on('[data-cli]', 'click', (e, el) => { e.stopPropagation(); S.cli = el.dataset.cli; S.q = ''; S.form = null })\n    d2.on('[data-wa]', 'click', (e, el) => {\n      e.stopPropagation()\n      let n = String(el.dataset.wa).replace(/\\D/g, '')\n      if (n.length <= 11) n = '55' + n\n      window.open('https://wa.me/' + n, '_blank')\n    })\n    d2.on('[data-ent]', 'click', async (e, el) => {\n      e.stopPropagation()\n      const id = el.dataset.ent, r0 = pedRec(id); if (!r0) return\n      const want = !r0.entregue\n      try { await d2.data('pedidos').loadAll() } catch (err) {}\n      const r = pedRec(id); if (!r) { toast('Pedido não existe mais'); return }\n      if (!!r.entregue === want) return\n      try { await d2.data('pedidos').update(Object.assign({}, r, { usuarioId: idOf(r.usuarioId), entregue: want })) } catch (err) { toast('Não foi possível atualizar') }\n    })\n    d2.on('[data-edit]', 'click', (e, el) => {\n      if (e.target.closest && e.target.closest('[data-ent],[data-cli],[data-wa]')) return\n      const [k, id] = el.dataset.edit.split(':')\n      if (k === 'pedido') {\n        const r = pedRec(id); if (!r) return\n        const prods = recs('produtos'), qtd = {}\n        parseItens(r).forEach(([nome, n]) => { const p = prods.find((x) => x.nome_produto === nome); if (p) qtd[p._id] = n })\n        S.form = { k, id, cli: idOf(r.usuarioId), cli0: idOf(r.usuarioId), rev0: !!r.revenda, qtd, pag: r.pago ? (r.formaPagamento || 'dinheiro') : '', entregue: !!r.entregue, snap: sigOf(k, r) }\n      } else if (k === 'cliente') {\n        const c = recs('clientes').find((x) => x._id === id); if (!c) return\n        S.form = { k, id, nome: c.nome || '', tel: c.telefone || '', rev: !!c.revendedor, snap: sigOf(k, c) }\n      } else {\n        const p = recs('produtos').find((x) => x._id === id); if (!p) return\n        S.form = { k, id, nome: p.nome_produto || '', preco: p.preco, precoRev: Number(p.preco_revenda) > 0 ? p.preco_revenda : '', snap: sigOf(k, p) }\n      }\n      S.sheet = false\n    })\n    d2.on('[data-act]', 'click', async (e, el) => {\n      const a = el.dataset.act\n      if (a.indexOf('new:') === 0) {\n        const k = a.slice(4)\n        S.form = k === 'pedido' ? { k, id: null, cli: S.scr === 'clientes' && S.cli ? S.cli : '', qtd: {}, pag: '', entregue: false } : k === 'cliente' ? { k, id: null, nome: '', tel: '', rev: false } : { k, id: null, nome: '', preco: '', precoRev: '' }\n        S.sheet = false; return\n      }\n      if (a === 'fechar') { if (S.sheet) { S.pDraft = {}; S.pBase = null } S.form = null; S.sheet = false; return }\n      if (a === 'voltar') { S.cli = null; return }\n      if (a === 'sheet') { S.sheet = true; return }\n      if (a === 'confno') { S.conf = null; return }\n      if (a === 'confsim') { const c = S.conf; if (!c || S.busy || !MEM.run) return; S.busy = true; try { await MEM.run() } catch (err) { toast('Algo deu errado. Tente de novo.') } S.busy = false; S.conf = null; return }\n      if (a === 'salvar') {\n        const fm = S.form; if (!fm || S.busy) return\n        if (fm.k === 'pedido' && !fm.cli) { S.form = Object.assign({}, fm, { err: 'Selecione um cliente' }); return }\n        if (fm.k === 'pedido' && !Object.values(fm.qtd).some((n) => Number(n) > 0)) { S.form = Object.assign({}, fm, { err: 'Adicione pelo menos um produto' }); return }\n        if (fm.k !== 'pedido' && !String(fm.nome || '').trim()) { S.form = Object.assign({}, fm, { err: 'Preencha o nome' }); return }\n        if (fm.k === 'produto' && !(num(fm.preco) > 0)) { S.form = Object.assign({}, fm, { err: 'Preço inválido. Use, por exemplo, 25,50' }); return }\n        if (fm.k === 'produto' && String(fm.precoRev == null ? '' : fm.precoRev).trim() !== '' && !(num(fm.precoRev) > 0)) { S.form = Object.assign({}, fm, { err: 'Preço de revenda inválido' }); return }\n        S.busy = true\n        if (fm.id) {\n          const dsk = fm.k === 'pedido' ? DSM.pedidos() : fm.k === 'cliente' ? DSM.clientes() : DSM.produtos()\n          try { await dsk.loadAll() } catch (err) {}\n          const cur = (dsk.records() || []).find((x) => x._id === fm.id)\n          if (!cur) { S.busy = false; S.form = Object.assign({}, fm, { err: 'Este registro foi excluído por outra pessoa.' }); return }\n          if (!fm.force && sigOf(fm.k, cur) !== fm.snap) { S.busy = false; S.form = Object.assign({}, fm, { force: true, err: 'Outra pessoa alterou este registro enquanto você editava. Toque em Salvar de novo para gravar a sua versão, ou em Cancelar para ver a atual.' }); return }\n        }\n        try {\n          if (fm.k === 'pedido') {\n            const base = fm.id ? Object.assign({}, pedRec(fm.id)) : {}\n            const cliR = recs('clientes').find((c) => c._id === fm.cli)\n            const rev = (fm.id && fm.cli === fm.cli0) ? !!fm.rev0 : !!(cliR && cliR.revendedor)\n            const o = pedidoPayload(base, fm.cli, fm.qtd, fm.pag, fm.entregue, rev)\n            if (fm.id) await d2.data('pedidos').update(o); else await d2.data('pedidos').create(o)\n          } else if (fm.k === 'cliente') {\n            const o = { nome: fm.nome.trim(), telefone: String(fm.tel || '').trim(), revendedor: !!fm.rev }\n            if (fm.id) await d2.data('clientes').update(Object.assign({ _id: fm.id }, o)); else await d2.data('clientes').create(o)\n          } else {\n            const o = { nome_produto: fm.nome.trim(), preco: num(fm.preco), preco_revenda: num(fm.precoRev) > 0 ? num(fm.precoRev) : null }\n            if (fm.id) await d2.data('produtos').update(Object.assign({ _id: fm.id }, o)); else await d2.data('produtos').create(o)\n          }\n          S.form = null; toast('Salvo')\n        } catch (err) { S.form = Object.assign({}, fm, { err: 'Não foi possível salvar' }) }\n        S.busy = false; return\n      }\n      if (a === 'excluir') {\n        const fm = S.form; if (!fm || !fm.id) return\n        const dsh = fm.k === 'pedido' ? DSM.pedidos() : fm.k === 'cliente' ? DSM.clientes() : DSM.produtos()\n        MEM.run = async () => { await dsh.remove(fm.id); S.form = null; toast('Excluído') }\n        S.conf = { title: 'Excluir ' + fm.k + '?', html: '<div class=\"mut\" style=\"font-size:13px\">Essa ação não pode ser desfeita.</div>', ok: 'Excluir', danger: true }\n        return\n      }\n      if (a === 'salvarparams') {\n        const vals = {}\n        d2.$$('[data-p]').forEach((i) => { const x = num(i.value); if (!isNaN(x)) vals[i.dataset.p] = x })\n        const doSave = async () => { const okSave = await savePlan({ params: vals }); if (okSave) { S.pDraft = {}; S.pBase = null; S.sheet = false; toast('Parâmetros salvos') } }\n        try { await DSM.planos().loadAll() } catch (err) {}\n        const paS = (MEM.plan && MEM.plan.pa) || anoAtual\n        const rS = recs('planos').find((p) => String(p.ano) === paS)\n        const curP = (rS && rS.params) || {}, baseP = S.pBase ? JSON.parse(S.pBase) : null\n        const conflito = baseP && Object.keys(S.pDraft || {}).some((k) => String(baseP[k]) !== String(curP[k]))\n        if (conflito) {\n          MEM.run = doSave\n          S.conf = { title: 'Parâmetros alterados', ok: 'Salvar mesmo assim', html: '<div class=\"mut\" style=\"font-size:13px\">Outra pessoa salvou alguns desses parâmetros enquanto você editava. Se continuar, os valores da sua tela substituem os dela.</div>' }\n          return\n        }\n        await doSave()\n        return\n      }\n      if (a === 'aplicar') {\n        const pl = MEM.plan; if (!pl || !pl.ok) return\n        const rv = !!pl.rev\n        const atualDe = (p) => rv ? Number(p.preco_revenda) : Number(p.preco)\n        const muda = pl.linhas.filter((l) => Number(l.qv) !== atualDe(l.p))\n        const alvo = recs('pedidos').filter((r) => !r.entregue && !r.pago && !!r.revenda === rv)\n        const esc2 = (v) => String(v).replace(/</g, '&lt;')\n        const linha = (nome, de, para) => `<div class=\"r\" style=\"padding:3px 0\"><span>${esc2(nome)}</span><span class=\"mut\" style=\"font-size:13px\">${de > 0 ? 'R$ ' + Number(de).toFixed(2) : '—'} → <b style=\"color:#1F1B24;font-weight:500\">R$ ${Number(para).toFixed(2)}</b></span></div>`\n        const lista = pl.linhas.map((l) => linha(l.p.nome_produto + (rv ? ' (revenda)' : ''), atualDe(l.p), l.qv)).join('')\n        MEM.run = async () => {\n            const novo = {}\n            pl.linhas.forEach((l) => { novo[l.p._id] = Number(l.qv) })\n            for (const l of muda) await DSM.produtos().update(Object.assign({}, l.p, rv ? { preco_revenda: Number(l.qv) } : { preco: Number(l.qv) }))\n            const prods = recs('produtos')\n            for (const r of alvo) {\n              const total = parseItens(r).reduce((acc, [nome, n]) => {\n                const p = prods.find((x) => x.nome_produto === nome); if (!p) return acc\n                const pr = novo[p._id] !== undefined ? novo[p._id] : precoDe(p, rv)\n                return acc + n * pr }, 0)\n              await DSM.pedidos().update(Object.assign({}, r, { usuarioId: idOf(r.usuarioId), total }))\n            }\n            await savePlan({})\n            toast(rv ? 'Preços de revenda aplicados' : 'Preços aplicados')\n        }\n        S.conf = { title: rv ? 'Aplicar preços de revenda?' : 'Aplicar preços de cliente?', ok: 'Aplicar', html: lista + `<div class=\"mut\" style=\"margin-top:10px;font-size:13px\">${alvo.length} ${alvo.length === 1 ? 'pedido não entregue e não pago será recalculado' : 'pedidos não entregues e não pagos serão recalculados'}, só de ${rv ? 'revendedores' : 'clientes comuns'}. Pedidos pagos ou entregues não mudam.</div>` }\n        return\n      }\n    })\n    d2.on('[data-qty]', 'click', (e, el) => {\n      const [id, d] = el.dataset.qty.split(':'); const fm = S.form; if (!fm) return\n      const qtd = Object.assign({}, fm.qtd); qtd[id] = Math.max(0, (Number(qtd[id]) || 0) + Number(d))\n      S.form = Object.assign({}, fm, { qtd, err: null })\n    })\n    d2.on('[data-rev]', 'click', (e, el) => { if (S.form) S.form = Object.assign({}, S.form, { rev: el.dataset.rev === '1' }) })\n    d2.on('[data-pag]', 'click', (e, el) => { if (S.form) S.form = Object.assign({}, S.form, { pag: el.dataset.pag }) })\n    d2.on('[data-fm]', 'input', (e, el) => { if (S.form) { const f = S.form; f[el.dataset.fm] = el.value; f.err = null } })\n    d2.on('[data-fm]', 'change', (e, el) => { if (S.form) S.form = Object.assign({}, S.form, { [el.dataset.fm]: el.value, err: null }) })\n    d2.on('[data-p]', 'input', (e, el) => {\n      if (!S.pBase) { const pa = (MEM.plan && MEM.plan.pa) || anoAtual; const r = recs('planos').find((p) => String(p.ano) === pa); S.pBase = JSON.stringify((r && r.params) || {}) }\n      S.pDraft = Object.assign({}, S.pDraft || {}, { [el.dataset.p]: el.value })\n    })\n    d2.on('[data-q]', 'change', async (e, el) => {\n      const ql = Object.assign({}, S.queroLocal || {}); const v = num(el.value); ql[el.dataset.q] = isNaN(v) ? '' : v\n      S.queroLocal = ql\n      await savePlan({ quero: ql })\n    })\n\n    async function savePlan(change) {\n      const pl = MEM.plan; const pa = (pl && pl.pa) || anoAtual\n      if (pa !== anoAtual) return\n      const ds = DSM.planos()\n      const rec = (ds.records() || []).find((p) => String(p.ano) === pa)\n      const params = Object.assign({}, (pl && pl.P) || {}, (rec && rec.params) || {}, change.params || {})\n      const quero = Object.assign({}, (rec && rec.quero) || {}, S.queroLocal || {}, change.quero || {})\n      const o = { ano: pa, params, quero }\n      if (pl && pl.kg > 0) o.foto = { demanda: pl.qd, demandaRev: pl.qdR || {}, custoTotal: pl.tot, ganho: pl.gan, em: new Date().toISOString() }\n      else if (rec && rec.foto) o.foto = rec.foto\n      try {\n        if (rec && rec._id) await ds.update(Object.assign({ _id: rec._id }, o)); else await ds.create(o)\n        return true\n      } catch (err) { toast('Não foi possível salvar o planejamento'); return false }\n    }\n  },\n}\n"}},"clientes":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"clientes"}}}},"pedidos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"pedidos"}}}},"planos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"planos"}}}},"produtos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"produtos"}}}},"auth":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"auth"}}}},"rushCriar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushCriar"}}}}}}}}}},{"_id":"5ed9bed7b9e0891ce913e884","component":"data2-core-types@Component","params":{"package":"data2-core","component":"DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}},{"_id":"5f472ae463c680de4ff296e9","component":"data2-core-types@Component","params":{"package":"data2-core","component":"Data2TableDataSource","extends":"data2-core@DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}},{"_id":"687dff024de75d5ca013c0a2","component":"data2-core-types@Component","system":"686bd24b4fcbdb97284775e3","params":{"extends":"data2-core-primitives@Block","package":"massayuki-playground","component":"uEcsego23YOb1_6V2V_dY","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Artboard","reference":"uEcsego23YOb1_6V2V_dY"}}}}}},{"_id":"687e4d01f382841e9d41aa89","component":"data2-core-types@Component","system":"686bd24b4fcbdb97284775e3","params":{"extends":"data2-core-primitives@Block","package":"massayuki-playground","component":"p6m5qOinrn4v5UqSE-y_e","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Artboard","reference":"p6m5qOinrn4v5UqSE-y_e"}}}}}},{"_id":"687e24b3e5d32d7202d203ec","component":"data2-core-types@Component","system":"686bd24b4fcbdb97284775e3","params":{"extends":"data2-core-primitives@Block","package":"massayuki-playground","component":"SBeCKlDH0N59PZtiiG056","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Artboard","reference":"SBeCKlDH0N59PZtiiG056"}}}}}},{"_id":"5ecd05ded68ce41360f74b43","component":"data2-core-types@Component","params":{"extendable":{"placeholder":"children"},"component":"Block","package":"data2-core-primitives"}},{"_id":"6436f04bac93122e72906101","component":"data2-core-types@Component","params":{"extends":"data2-core-primitives@Block","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"html@i","params":{"aria-hidden":"true","style":{"display":"flex","justifyContent":"center","alignItems":"center","width":"100%","height":"100%","fontSize":{"params":{"reference":"size"},"component":"data2-core-types@Reference"},"color":{"params":{"compare":[{"params":{"subject":{"params":{"reference":"color"},"component":"data2-core-types@Reference"},"pattern":{"component":"data2-core-primitives@String","params":{"content":"gradient"}}},"component":"data2-core-functions@Includes"}],"else":{"params":{"components":[{"params":{"reference":"color"},"component":"data2-core-types@Reference"},{"params":{"reference":"super.textColor"},"component":"data2-core-types@Reference"}]},"component":"data2-core-logical-operators@Or"},"then":{"component":"data2-core-primitives@String","params":{"content":"transparent"}}},"component":"data2-core-flow@If"},"backgroundClip":{"component":"data2-core-primitives@String","params":{"content":"text"}},"WebkitBackgroundClip":{"component":"data2-core-primitives@String","params":{"content":"text"}},"backgroundImage":{"params":{"compare":[{"params":{"subject":{"params":{"reference":"color"},"component":"data2-core-types@Reference"},"pattern":{"component":"data2-core-primitives@String","params":{"content":"gradient"}}},"component":"data2-core-functions@Includes"}],"then":{"params":{"portions":[{"params":{"reference":"color"},"component":"data2-core-types@Reference"}]},"component":"data2-core-functions@StringConcat"},"else":{"component":"data2-core-primitives@String","params":{"content":"linear-gradient(transparent,transparent)"}}},"component":"data2-core-flow@If"},"transition":{"component":"data2-core-primitives@String","params":{"content":"inherit"}}},"className":{"component":"data2-core-types@Reference","params":{"reference":"icon"}}}}}},"component":"IconBlock","package":"data2-blocks"}}]}},{"reference":"ExternalComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"_id":"5f060d9b1ca96def42f3c40a","displayName":"Builder AuthStrategy","component":"data2-core@AuthenticationStrategy","system":"5e3b796d6228227ca637d0f4","params":{"credentials":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"verifier":{"component":"data2-core-types@DataSetReference","params":{"reference":"UsersDataSet"}},"sessionShared":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"password":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},"email":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},"resetPassword":{"resetEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"nR6Q9d7qdaPtZhJ28Q8Dy"},"component":"data2-core-types@ArtboardReference"}},"resetSuccessEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"yPCJBTKo8q1Mw0B_3Kpwl"},"component":"data2-core-types@ArtboardReference"}}},"session":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"name"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"sessionMetadata":{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},{"params":{"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"active"}},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.status"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is active user"}]},"component":"data2-core-logical-operators@And","displayName":"is active and has _id"}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $user"},{"params":{"action":{"component":"data2-core-types@Getter","displayName":"isData2User","params":{"module":{"component":"data2-core-functions@Match","params":{"pattern":{"component":"data2-core-types@Regex","params":{"pattern":"@data2\\.app$","flags":"i"}},"text":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.email"}}}}}},"prop":{"component":"data2-core-primitives@String","params":{"content":"0"}}}},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}},"component":"data2-core-flow@Step"},{"params":{"action":{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.d2_app"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"management"}}]},"component":"data2-core-functions@Includes","displayName":"isData2App Exception"},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}},"component":"data2-core-flow@Step"},{"params":{"resultName":{"component":"data2-core-primitives@String","params":{"content":"has_access"}},"action":{"params":{"compare":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}}},{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}}}]},"component":"data2-core-logical-operators@Or"},"else":{"params":{"actions":[{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $metadata.system"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":"filter","args":[{"_id":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records.length"}}}}},"component":"data2-core-logical-operators@Not","displayName":"systems not found"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check system found"},{"params":{"actions":[{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"organization":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"cursor.current.organization._id"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"}]},"component":"data2-core-flow@Parallel"}]},"component":"data2-core-flow@Series","displayName":"common setup"},{"params":{"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"},"else":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"compare":{"params":{"components":{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"mapper":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"system"}}],"body":{"params":{"expression":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.visibility"}}}},"defaultCase":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"cases":[{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"public"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"billing-owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}},{"component":"data2-core-primitives@String","params":{"content":"member"}}]},"component":"data2-core-functions@Includes","displayName":"has role with access"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"collaborator"}}},"component":"data2-core-comparison-operators@Equal","displayName":"is collaborator"}]},"component":"data2-core-logical-operators@And","displayName":"is org member and collaborator"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is collaborator"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is collaborator and has system access"}]},"component":"data2-core-logical-operators@Or"}}},{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"private"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}}]},"component":"data2-core-functions@Includes","displayName":"is owner/admin"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is owner/admin"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is member and has system access"}]},"component":"data2-core-logical-operators@Or","displayName":"is owner/admin or has system access"}}}]},"component":"data2-core-flow@Switch"}}}},"component":"data2-core-functions@ArrayMap"}},"component":"data2-core-logical-operators@And","displayName":"has org member for all systems in request"}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"}},"component":"data2-core-flow@If"}},"component":"data2-core-flow@Step"},{"params":{"then":{"component":"data2-core-flow@If","displayName":"management exception never picks the system","params":{"compare":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}}},{"component":"data2-core-logical-operators@Not","params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}}}}}]}},"then":{"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"else":{"d2_app":"management"}}},"else":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"},"compare":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"has_access"}}}}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"sessionExpiresIn":{"component":"data2-core-primitives@Number","params":{"content":604800}},"sessionRenewal":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"identityProviders":[{"provider":{"component":"data2-core-primitives@String","params":{"content":"GOOGLE"}},"clientId":{"component":"data2-core-primitives@String","params":{"content":"55470861603-22pvfc1t49lp8cjnbfk71s5ct9hp1q1v.apps.googleusercontent.com"}}}]},"reference":"Data2BuilderAuthentication","updatedAt":"2026-10-29T19:05:43.007Z","updateMetadata":{"updatedBy":{"user":"5f1609be1ca96def427e1559"}}},{"_id":"5f060ee51ca96def42f3fbd1","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"UsersTableDataSource"}},"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}}},"reference":"UsersDataSet","updatedAt":"2026-03-04T21:16:40.291Z"},{"component":"data2-core@DataSet","reference":"SessionsDataSet","params":{"requiresConfirmation":false,"pk":"key","datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"data2sessionsdatasource"}}}},{"component":"data2-core@ServerSessionsDataSource","reference":"data2sessionsdatasource","params":{}},{"reference":"UsersTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"_id":"5f1600b70528b92601890f75","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ServiceComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ServiceComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:20.208Z","createdAt":"2020-07-20T20:38:15.436Z"},{"_id":"5f1602190528b92601890f7d","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":40000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentInstancesTableDataSource"}},"sort":{"_id":1},"pk":"_id","autoEdit":true,"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:07.089Z","createdAt":"2020-07-20T20:44:09.350Z"},{"_id":"5f16017f0528b92601890f7a","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"clientApplicationDomain"}}},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":[{"component":"data2-core-auth@PublicPolicy","params":{"reason":"Explicit so data2 can go private, 2026-11-05. Access is decided by the drive/file gate (applyFileTableGates, docs/drive-file-access.md), which runs after this policy; same behavior as today."}}]},"reference":"FileComponentInstancesDataSet","updatedAt":"2026-11-05T17:23:34.217Z","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"},"policies":[{"component":"data2-core-auth@PublicPolicy","params":{"reason":"Explicit so data2 can go private, 2026-11-05. Access is decided by the drive/file gate (applyFileTableGates, docs/drive-file-access.md), which runs after this policy; same behavior as today."}}]},"reference":"OneFileComponentInstancesDataSet","updatedAt":"2026-11-05T17:23:34.254Z","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}},"policies":[{"component":"data2-core-auth@PublicPolicy","params":{"reason":"Explicit so data2 can go private, 2026-11-05. Access is decided by the drive/file gate (applyFileTableGates, docs/drive-file-access.md), which runs after this policy; same behavior as today."}}]},"reference":"DriveFileComponentInstancesDataSet","updatedAt":"2026-11-05T17:23:34.347Z","createdAt":"2023-02-16T14:27:07.797Z"},{"reference":"ServiceComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"ComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"687f8b0458612eba76109a47","component":"data2-core-primitives@Router","system":"686bd24b4fcbdb97284775e3","displayName":"router","params":{"initialPath":{"component":"data2-core-primitives@String","params":{"content":"/"}},"routes":[{"component":"data2-core-primitives@Route","params":{"path":{"component":"data2-core-primitives@String","params":{"content":"/"}},"url":{"component":"data2-core-primitives@String","params":{"content":" "}},"content":{"disabled":false,"component":"data2-core-types@ArtboardReference","params":{"reference":"c7x_46WK9_58IHsFmSoFe"}}}},{"component":"data2-core-primitives@Route","params":{"path":{"component":"data2-core-primitives@String","params":{"content":"/workshop"}},"content":{"disabled":false,"component":"data2-core-types@ArtboardReference","params":{"reference":"HeWfKT2hulHZPBJx5l17-"}}}},{"component":"data2-core-primitives@Route","params":{"path":{"component":"data2-core-primitives@String","params":{"content":"/calendario"}},"content":{"disabled":false,"component":"data2-core-types@ArtboardReference","params":{"reference":"DZBNWnpdgcCSw6m3jnq6C"}}}},{"component":"data2-core-primitives@Route","params":{"path":{"component":"data2-core-primitives@String","params":{"content":"/:nome"}},"url":{"component":"data2-core-primitives@String","params":{"content":" "}},"content":{"disabled":false,"component":"data2-core-types@ArtboardReference","params":{"reference":"c7x_46WK9_58IHsFmSoFe"}}}}]},"reference":"r0UvisOv4rxqSjgNtVb5d"},{"_id":"687e358cf90f3baaf0733c69","component":"data2-core-primitives@Artboard","system":"686bd24b4fcbdb97284775e3","displayName":"Workshop_routers","params":{"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1366,"height":768}},"fill":{"params":{"backgrounds":[{"params":{"color":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,1)"}},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"}},"reference":"c7x_46WK9_58IHsFmSoFe"},{"_id":"687e940dcd31f27f1ebac22c","component":"data2-core-primitives@Artboard","system":"686bd24b4fcbdb97284775e3","displayName":"calendario","params":{"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1366,"height":768}},"fill":{"params":{"backgrounds":[{"params":{"color":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,1)"}},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"}},"reference":"DZBNWnpdgcCSw6m3jnq6C"},{"_id":"687e234fe5d32d7202d2038e","component":"data2-core-primitives@Artboard","system":"686bd24b4fcbdb97284775e3","displayName":"Workshop_componentes_desafio","params":{"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1366,"height":755,"exactWidth":1366,"exactHeight":754.83}},"fill":{"params":{"backgrounds":[{"params":{"color":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,1)"}},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"}},"reference":"HeWfKT2hulHZPBJx5l17-"},{"_id":"6880cdd6a6964b64ecdcbd94","parent":"687e358cf90f3baaf0733c69","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":320,"height":112}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":789,"y":127,"exactX":788.6,"exactY":126.96}},"text":"usando series para tirar o hover do botão ao clicar, além de quando o mouse sair\n\ncolocando um menu para as páginas"}},{"_id":"6880cf30d6255e4907b71706","parent":"687e358cf90f3baaf0733c69","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":214,"height":411}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":0,"y":150,"exactX":false,"exactY":false,"top":true,"left":true}},"childrenMode":"reference","childrenReference":{"disabled":false,"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Artboard","reference":"SJmSAypd6hrhRUw1iXHG7"}}}},{"_id":"6880d44dd6255e4907b71712","parent":"687e358cf90f3baaf0733c69","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":198,"height":51}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":19,"y":576,"top":true,"exactX":false,"exactY":false,"left":true}},"text":{"params":{"portions":[{"component":"data2-core-primitives@String","params":{"content":"Olá, "}},{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"r0UvisOv4rxqSjgNtVb5dInterface"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"routeParams.nome"}}}},{"component":"data2-core-primitives@String","params":{"content":", seja bem vindo"}}]},"component":"data2-core-functions@StringConcat"}}},{"_id":"6880dcf2d6255e4907b71718","parent":"687e358cf90f3baaf0733c69","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":311,"height":227}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":807,"y":372,"exactX":807,"exactY":371.66}},"text":"terminado workshop routers e versionamento\n\nworkshop de domain assistido\n\naplicar workshop domain\n\n\n\n\n"}},{"_id":"69fb6c1c7729dd5fde31e25b","parent":"687e358cf90f3baaf0733c69","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":265,"height":254}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":355,"y":361}},"text":{"component":"data2-core-primitives@String","params":{"content":"A "}}}},{"_id":"687e940dcd31f27f1ebac22d","parent":"687e940dcd31f27f1ebac22c","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":201,"height":69,"exactWidth":201.1,"exactHeight":68.92}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"y":22,"fixed":false,"exactX":260.5,"exactY":22.14,"x":261}},"repeat":{"disabled":false,"component":"data2-core-types@DataSetReference","params":{}},"text":{"component":"data2-core-primitives@String","params":{"content":""}},"textColor":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(16,41,245,1)"}}}},{"_id":"687e940dcd31f27f1ebac22e","parent":"687e940dcd31f27f1ebac22c","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1052,"height":543,"exactWidth":1051.71,"exactHeight":543.05}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":240,"y":122,"exactX":240.12,"exactY":122.23,"fixed":false,"top":true,"left":false}},"repeat":{"params":{"end":{"params":{"date":{"params":{"period":"week","date":{"params":{"period":"month","date":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e940dcd31f27f1ebac230"}},"key":{"component":"data2-core-primitives@String","params":{"content":"mes_atual"}}}}}}},"component":"data2-core-functions@DateEndOf"}},"component":"data2-core-functions@DateEndOf"}},"component":"data2-core-functions@DateFormat"},"start":{"params":{"date":{"params":{"period":"week","date":{"params":{"period":"month","date":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e940dcd31f27f1ebac230"}},"key":{"component":"data2-core-primitives@String","params":{"content":"mes_atual"}}}}}}},"component":"data2-core-functions@DateStartOf"}},"component":"data2-core-functions@DateStartOf"}},"component":"data2-core-functions@DateFormat"}},"component":"data2-core-functions@DateRange"},"repeatLimit":{"component":"data2-core-primitives@Number","params":{"content":""}},"childrenMode":"grid","repeatReference":{"component":"data2-core-primitives@String","params":{"content":"date"}},"scroll":{"disabled":false,"component":"data2-core-types@Scroll","params":{"dragToScroll":false,"hideScrollBar":true,"y":true,"x":true}}}},{"_id":"687e940dcd31f27f1ebac230","parent":"687e940dcd31f27f1ebac22c","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":314,"height":67,"exactWidth":314.37,"exactHeight":67.34}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":548,"y":55,"exactX":547.87,"exactY":55.49}},"stateDefinitions":[{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"mes_atual"}},"initialValue":{"params":{"format":{"component":"data2-core-primitives@String","params":{"content":""}}},"component":"data2-core-functions@DateFormat"},"component":"data2-core-primitives@Object"}}],"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle","fontWeight":700}},"text":{"params":{"string":{"params":{"date":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e940dcd31f27f1ebac230"}},"key":{"component":"data2-core-primitives@String","params":{"content":"mes_atual"}}}}}},"format":{"component":"data2-core-primitives@String","params":{"content":"MMMM"}}},"component":"data2-core-functions@DateFormat"}},"component":"data2-core-functions@toUpperCase"}}},{"_id":"687e940dcd31f27f1ebac231","parent":"687e940dcd31f27f1ebac22c","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":80,"height":48,"exactWidth":80.2}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":535,"y":87,"exactX":534.6899999999999,"exactY":87.31}},"text":"<","onClick":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e940dcd31f27f1ebac230"}},"key":{"component":"data2-core-primitives@String","params":{"content":"mes_atual"}}}},"value":{"params":{"date":{"params":{"date":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"disabled":false,"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e940dcd31f27f1ebac230"}},"key":{"component":"data2-core-primitives@String","params":{"content":"mes_atual"}}}}}},"count":{"component":"data2-core-primitives@Number","params":{"content":1}},"period":"months"},"component":"data2-core-functions@DateSubtract"}},"component":"data2-core-functions@DateFormat"}}},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle"}}}},{"_id":"687e940dcd31f27f1ebac232","parent":"687e940dcd31f27f1ebac22c","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":84,"height":49,"exactWidth":84.3}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":791,"y":90,"exactX":791.26,"exactY":90.24}},"text":">","onClick":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e940dcd31f27f1ebac230"}},"key":{"component":"data2-core-primitives@String","params":{"content":"mes_atual"}}}},"value":{"params":{"date":{"params":{"count":{"component":"data2-core-primitives@Number","params":{"content":1}},"period":"months","date":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"disabled":false,"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e940dcd31f27f1ebac230"}},"key":{"component":"data2-core-primitives@String","params":{"content":"mes_atual"}}}}}}},"component":"data2-core-functions@DateAdd"}},"component":"data2-core-functions@DateFormat"}}},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"textOverflow":false,"verticalAlignment":"middle","horizontalAlignment":"center"}}}},{"_id":"687e940dcd31f27f1ebac234","parent":"687e940dcd31f27f1ebac22c","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":174,"height":67,"exactWidth":174.46,"exactHeight":67.34}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":617,"y":122,"exactX":616.72,"exactY":122.09}},"stateDefinitions":[{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"mes_atual"}},"initialValue":{"params":{"format":{"component":"data2-core-primitives@String","params":{"content":""}}},"component":"data2-core-functions@DateFormat"},"component":"data2-core-primitives@Object"}},{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"mes_atual_por_extenso"}},"component":"data2-core-primitives@Object"}}],"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle","fontWeight":700}},"text":{"params":{"string":{"params":{"date":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e940dcd31f27f1ebac230"}},"key":{"component":"data2-core-primitives@String","params":{"content":"mes_atual"}}}}}},"format":{"component":"data2-core-primitives@String","params":{"content":"y"}}},"component":"data2-core-functions@DateFormat"}},"component":"data2-core-functions@toUpperCase"}}},{"_id":"687e940dcd31f27f1ebac235","parent":"687e940dcd31f27f1ebac22c","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":37,"height":22,"exactWidth":37.02,"exactHeight":22.14}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":688,"y":113,"exactX":687.92,"exactY":112.92}},"text":{"params":{"portions":[{"component":"data2-core-primitives@String","params":{"content":" de "}}]},"component":"data2-core-functions@StringConcat"}}},{"_id":"687e940dcd31f27f1ebac236","parent":"687e940dcd31f27f1ebac22c","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":201,"height":42,"exactWidth":201.1,"exactHeight":42.28}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"y":-660,"fixed":false,"exactX":261.08000000000004,"exactY":-659.99,"x":261}},"repeat":{"disabled":false,"component":"data2-core-types@DataSetReference","params":{}},"text":{"component":"data2-core-primitives@String","params":{"content":""}},"textColor":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(245,74,16,1)"}}}},{"_id":"687ea0e0cd31f27f1ebac237","parent":"687e940dcd31f27f1ebac22c","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1050,"height":25,"exactHeight":25}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":241,"y":184,"exactY":184.32,"exactX":240.63,"top":true,"left":false}},"repeat":{"params":{"start":{"component":"data2-core-primitives@Date","params":{"content":"2025-07-20T20:22:00.000Z"}},"end":{"component":"data2-core-primitives@Date","params":{"content":"2025-07-26T20:22:00.000Z"}}},"component":"data2-core-functions@DateRange"},"repeatReference":{"component":"data2-core-primitives@String","params":{"content":"diadasemana"}},"childrenMode":"cols","textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle"}}}},{"_id":"6880d039d6255e4907b7170f","parent":"687e940dcd31f27f1ebac22c","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":203,"height":411,"exactWidth":203.36}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":0,"y":150,"exactX":false,"exactY":false}},"childrenMode":"reference","childrenReference":{"disabled":false,"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Artboard","reference":"SJmSAypd6hrhRUw1iXHG7"}}}},{"_id":"687e234fe5d32d7202d203b9","parent":"687e234fe5d32d7202d2038e","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,1)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1366,"height":768,"exactWidth":false,"exactHeight":768}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":0,"exactX":false,"exactY":false,"top":true,"left":true,"fixed":false,"growH":true,"growV":true}},"text":"","childrenMode":"rows","childrenOverflow":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"hide":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"index":0},{"_id":"6880ce29a6964b64ecdcbd95","component":"data2-core-primitives@Artboard","system":"686bd24b4fcbdb97284775e3","displayName":"menu","params":{"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":205,"height":510,"exactWidth":204.66,"exactHeight":510.26}},"fill":{"params":{"backgrounds":[{"params":{"color":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,1)"}},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"}},"reference":"SJmSAypd6hrhRUw1iXHG7"},{"_id":"687e940dcd31f27f1ebac22f","parent":"687e940dcd31f27f1ebac22e","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"else":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,26,45,0.05)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"then":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(3,149,251,0.5)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"compare":{"params":{"subject":{"params":{"date":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"dateRepeater"}}}},"format":{"component":"data2-core-primitives@String","params":{"content":"M"}}},"component":"data2-core-functions@DateFormat"},"comparisonSubject":{"params":{"date":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e940dcd31f27f1ebac230"}},"key":{"component":"data2-core-primitives@String","params":{"content":"mes_atual"}}}}}},"format":{"component":"data2-core-primitives@String","params":{"content":"M"}}},"component":"data2-core-functions@DateFormat"}},"component":"data2-core-comparison-operators@Equal"}},"component":"data2-core-flow@If"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":150,"height":80,"exactWidth":150,"exactHeight":80}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"y":0,"fixed":false,"exactX":false,"exactY":false,"x":0}},"text":{"params":{"format":{"component":"data2-core-primitives@String","params":{"content":"D"}},"date":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"dateRepeater"}}}}},"component":"data2-core-functions@DateFormat"},"repeat":{"disabled":false,"component":"data2-core-types@DataSetReference","params":{}},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"top"}}}},{"_id":"687ea19fcd31f27f1ebac239","parent":"687ea0e0cd31f27f1ebac237","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":150,"height":25,"exactWidth":150,"exactHeight":25}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":0,"exactX":0,"exactY":0,"fixed":false}},"text":{"params":{"format":{"component":"data2-core-primitives@String","params":{"content":"dddd"}},"date":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"diadasemanaRepeater"}}}}},"component":"data2-core-functions@DateFormat"},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle","fontWeight":700}}}},{"_id":"687e33155e54d3a02dfb5248","parent":"687e234fe5d32d7202d203b9","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1366,"height":768,"exactWidth":false,"exactHeight":768}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"y":0,"exactX":false,"exactY":false,"fixed":false,"left":true,"growH":true,"top":true,"growV":true}},"childrenMode":"cols","text":{"component":"data2-core-primitives@String","params":{"content":""}}},"index":1},{"_id":"687e234fe5d32d7202d203ba","parent":"687e234fe5d32d7202d203b9","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(242,242,242,1)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1366,"height":2,"exactWidth":false,"exactHeight":2}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":0,"y":47,"exactX":false,"exactY":false,"growV":false,"top":true,"left":true,"growH":true}}}},{"_id":"687e234fe5d32d7202d203bb","parent":"687e234fe5d32d7202d203b9","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":93,"height":25}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":67,"y":16,"exactX":67.1,"exactY":15.75}},"text":"Learn"}},{"_id":"687e234fe5d32d7202d203bc","parent":"687e234fe5d32d7202d203b9","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":95,"height":26}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":152,"y":15,"exactX":152.25,"exactY":15.120000000000001}},"text":"Docs"}},{"_id":"687e234fe5d32d7202d203bd","parent":"687e234fe5d32d7202d203b9","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"component":"data2-core-types@FileComponentUrlReference","params":{"reference":"e0c48jqOd-Jvz9meY0Wu2"}},"size":"cover"},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":30,"height":26}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":20,"y":12,"exactX":20.35,"exactY":11.56}}}},{"_id":"6880cec1d6255e4907b71702","parent":"6880ce29a6964b64ecdcbd95","component":"massayuki-playground@uEcsego23YOb1_6V2V_dY","system":"686bd24b4fcbdb97284775e3","params":{"super":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":200,"height":68}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":0,"exactX":false,"exactY":false,"fixed":false}},"text":{"component":"data2-core-primitives@String","params":{"content":""}}},"label":{"component":"data2-core-primitives@String","params":{"content":"ir para página inicial"}},"click":{"disabled":false,"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"r0UvisOv4rxqSjgNtVb5dInterface"}},"prop":"goTo","args":[{"component":"data2-core-primitives@String","params":{"content":"/"}}]}},"componentState":{"component":"data2-core-primitives@String","params":{"content":""}}}},{"_id":"6880cec1d6255e4907b71705","parent":"6880ce29a6964b64ecdcbd95","component":"massayuki-playground@uEcsego23YOb1_6V2V_dY","system":"686bd24b4fcbdb97284775e3","params":{"super":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":200,"height":68}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":0,"exactX":false,"exactY":false,"fixed":false}},"text":{"component":"data2-core-primitives@String","params":{"content":""}}},"label":{"component":"data2-core-primitives@String","params":{"content":"ir para calendário"}},"click":{"disabled":false,"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"r0UvisOv4rxqSjgNtVb5dInterface"}},"prop":"goTo","args":[{"component":"data2-core-primitives@String","params":{"content":"/calendario"}}]}},"componentState":{"component":"data2-core-primitives@String","params":{"content":""}}}},{"_id":"6880cf60d6255e4907b71709","parent":"6880ce29a6964b64ecdcbd95","component":"massayuki-playground@uEcsego23YOb1_6V2V_dY","system":"686bd24b4fcbdb97284775e3","params":{"super":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":200,"height":68}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":0,"exactX":false,"exactY":false,"fixed":false}},"text":{"component":"data2-core-primitives@String","params":{"content":""}}},"label":{"component":"data2-core-primitives@String","params":{"content":"ir para desafio componentes"}},"click":{"disabled":false,"component":"data2-core-types@Interaction","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"r0UvisOv4rxqSjgNtVb5dInterface"}},"prop":"goTo","args":[{"component":"data2-core-primitives@String","params":{"content":"/workshop"}}]}},"componentState":{"component":"data2-core-primitives@String","params":{"content":""}}}},{"_id":"687e33155e54d3a02dfb5249","parent":"687e33155e54d3a02dfb5248","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","displayName":"menu esquerda","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,1)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"height":684,"exactWidth":false,"exactHeight":false,"width":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5252"}},"key":{"component":"data2-core-primitives@String","params":{"content":"largura_aba"}}}}}}},"break":true},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":51,"exactX":false,"exactY":false,"fixed":false,"top":true,"growV":true,"left":true}},"stateDefinitions":[],"childrenMode":"cols"},"index":0},{"_id":"687e33155e54d3a02dfb5261","parent":"687e33155e54d3a02dfb5248","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(237,237,237,1)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":2,"exactWidth":false,"exactHeight":false,"height":720}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":50,"exactX":false,"exactY":false,"fixed":false,"growV":true,"top":true}}},"index":1},{"_id":"6880d00cd6255e4907b7170b","parent":"687e33155e54d3a02dfb5248","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":214,"height":411}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"exactX":false,"exactY":false,"fixed":false,"y":104}},"childrenMode":"reference","childrenReference":{"disabled":false,"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Artboard","reference":"SJmSAypd6hrhRUw1iXHG7"}}},"index":2},{"_id":"687e33155e54d3a02dfb5253","parent":"687e33155e54d3a02dfb5248","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","displayName":"slider","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":339,"height":257,"exactWidth":338.8,"exactHeight":256.85999999999996}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":468,"y":414,"exactX":467.7,"exactY":414.49,"fixed":false}}},"index":3},{"_id":"687e33155e54d3a02dfb5268","parent":"687e33155e54d3a02dfb5248","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":554,"height":387,"exactHeight":386.84}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"exactX":-534.11,"exactY":54.400000000000006,"fixed":false,"x":-534,"y":54,"top":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"left":{"component":"data2-core-primitives@Boolean","params":{"content":false}}}},"textColor":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(223,19,19,1)"}},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"left","textOverflow":false,"verticalAlignment":"middle"}},"textSize":{"component":"data2-core-primitives@Number","params":{"content":36}},"text":"fazendo os botões da língua com componente de opção de língua já com:\n-borda\n-hover\n-on click set idioma\n-on click outside"},"index":4},{"_id":"687e33155e54d3a02dfb5252","parent":"687e33155e54d3a02dfb5248","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","displayName":"block de ui states","params":{"0":{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_altura_icone"}},"component":"data2-core-primitives@Number","initialValue":{"component":"data2-core-primitives@Number","params":{"content":738}}}},"2":{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"largura_aba"}},"component":"data2-core-primitives@Number","initialValue":{"component":"data2-core-primitives@Number","params":{"content":30}}}},"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":129,"height":119,"exactWidth":129.08,"exactHeight":118.51}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":1017,"y":397,"fixed":false,"exactX":1016.58,"exactY":397.24}},"stateDefinitions":[{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_altura_icone"}},"component":"data2-core-primitives@Number","initialValue":{"component":"data2-core-primitives@Number","params":{"content":738}}}},{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_largura_icone"}},"component":"data2-core-primitives@Number","initialValue":{"component":"data2-core-primitives@Number","params":{"content":30}}}},{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"largura_aba"}},"component":"data2-core-primitives@Number","initialValue":{"component":"data2-core-primitives@Number","params":{"content":30}}}}],"text":"\n"},"index":5},{"_id":"687e33155e54d3a02dfb5262","parent":"687e33155e54d3a02dfb5248","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","displayName":"seletor de idiomas","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":150,"height":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5262"}},"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_seletor_idioma"}}}}}},"exactWidth":150},"break":true},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":1100,"exactX":false,"exactY":false,"y":10,"top":true,"right":true}},"childrenMode":"rows","stateDefinitions":[{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_seletor_idioma"}},"component":"data2-core-primitives@Number","initialValue":{"component":"data2-core-primitives@Number","params":{"content":30}}}}],"childrenOverflow":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"index":6},{"_id":"687e509d63bcb3c825bbc37b","parent":"687e33155e54d3a02dfb5248","component":"massayuki-playground@p6m5qOinrn4v5UqSE-y_e","system":"686bd24b4fcbdb97284775e3","params":{"super":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":278,"height":70,"exactWidth":277.51,"exactHeight":69.61}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":1042,"y":564,"exactX":1041.92,"exactY":564.22}}}},"index":7},{"_id":"687e33155e54d3a02dfb524a","parent":"687e33155e54d3a02dfb5249","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"686ffe35eab3d450a604510d"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}}}}}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"exactWidth":false,"exactHeight":false,"width":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5252"}},"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_largura_icone"}}}}}},"height":687},"break":true},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":0,"exactX":false,"exactY":false,"growV":true,"fixed":false,"left":true,"top":true}},"text":{"component":"data2-core-primitives@String","params":{"content":""}},"onClick":{"params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5252"}},"key":{"component":"data2-core-primitives@String","params":{"content":"largura_aba"}}}},"value":{"component":"data2-core-primitives@String","params":{"content":"300"}}}},{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5252"}},"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_altura_icone"}}}},"value":{"component":"data2-core-primitives@String","params":{"content":"1"}}}},{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5252"}},"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_largura_icone"}}}},"value":{"component":"data2-core-primitives@String","params":{"content":"0"}}}}]},"component":"data2-core-flow@Series"},"stateDefinitions":[{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_altura_icone"}},"component":"data2-core-primitives@Number","initialValue":{"component":"data2-core-primitives@Number","params":{"content":738}}}},{"component":"data2-core-user-interface@StateDefinition","params":{}}],"onMouseEnter":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"686ffe35eab3d450a604510d"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}}}},"value":{"params":{"backgrounds":[{"params":{"color":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(242,242,242,1)"}},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"}}},"onMouseLeave":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"686ffe35eab3d450a604510d"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}}}},"value":{"params":{"backgrounds":[{"params":{"color":{"disabled":true,"component":"data2-core-types@Color","params":{}},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}}}]},"component":"data2-core-types@Fill"}}}},"index":0},{"_id":"687e33155e54d3a02dfb524c","parent":"687e33155e54d3a02dfb5249","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":276,"height":738,"exactWidth":false,"exactHeight":false}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":0,"fixed":false,"exactX":false,"exactY":false}},"childrenMode":"rows"},"index":0},{"_id":"687e33155e54d3a02dfb5254","parent":"687e33155e54d3a02dfb5253","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":47,"height":29,"exactWidth":46.85,"exactHeight":29.21}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":173,"y":212,"exactX":173.37,"exactY":211.59,"fixed":false}},"text":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5256"}},"key":{"component":"data2-core-primitives@String","params":{"content":"posiçãox"}}}}}}}},{"_id":"687e33155e54d3a02dfb5255","parent":"687e33155e54d3a02dfb5253","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":81,"height":26,"exactWidth":80.83,"exactHeight":25.84}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":79,"y":209,"exactX":78.83,"exactY":209.49,"fixed":false}},"text":"posição x : "}},{"_id":"687e33155e54d3a02dfb5256","parent":"687e33155e54d3a02dfb5253","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.1)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":300,"height":194,"exactWidth":300,"exactHeight":193.55}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"x":0,"y":0,"exactX":58.19,"exactY":6.86,"fixed":false}},"childrenMode":"cols","stateDefinitions":[{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"posiçãox"}},"component":"data2-core-primitives@Number","initialValue":{"component":"data2-core-primitives@Number","params":{"content":0}}}}]}},{"_id":"687e33155e54d3a02dfb5263","parent":"687e33155e54d3a02dfb5262","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","displayName":"idioma","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"1","top":"1","right":"1","bottom":"1"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(26,28,28,0.08)"},"disabled":false},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":150,"height":30,"exactWidth":150,"exactHeight":30}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":0,"exactX":false,"exactY":false,"fixed":false,"top":true,"right":true}},"stateDefinitions":[{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"idioma"}},"component":"data2-core-primitives@String","initialValue":{"component":"data2-core-primitives@String","params":{"content":"Português"}}}}],"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle"}},"text":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5263"}},"key":{"component":"data2-core-primitives@String","params":{"content":"idioma"}}}}}},"onClick":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5262"}},"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_seletor_idioma"}}}},"value":{"component":"data2-core-primitives@String","params":{"content":"300"}}}}}},{"_id":"687e33155e54d3a02dfb5265","parent":"687e33155e54d3a02dfb5262","component":"massayuki-playground@SBeCKlDH0N59PZtiiG056","system":"686bd24b4fcbdb97284775e3","params":{"super":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":150,"exactWidth":false,"exactHeight":30,"height":30}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":0,"exactX":false,"exactY":false,"fixed":false}}},"field":{"component":"data2-core-primitives@String","params":{"content":"Português"}}}},{"_id":"687e33155e54d3a02dfb5266","parent":"687e33155e54d3a02dfb5262","component":"massayuki-playground@SBeCKlDH0N59PZtiiG056","system":"686bd24b4fcbdb97284775e3","params":{"super":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":150,"exactWidth":false,"exactHeight":30,"height":30}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":0,"exactX":false,"exactY":false,"fixed":false}}},"field":{"component":"data2-core-primitives@String","params":{"content":"Inglês"}}}},{"_id":"687e33155e54d3a02dfb5267","parent":"687e33155e54d3a02dfb5262","component":"massayuki-playground@SBeCKlDH0N59PZtiiG056","system":"686bd24b4fcbdb97284775e3","params":{"super":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":150,"exactWidth":false,"exactHeight":30,"height":30}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":0,"exactX":false,"exactY":false,"fixed":false}}},"field":{"component":"data2-core-primitives@String","params":{"content":"Espanhol"}}}},{"_id":"687dfe894de75d5ca013c0a1","component":"data2-core-primitives@Artboard","system":"686bd24b4fcbdb97284775e3","displayName":"@custom-button","params":{"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":205,"height":87,"exactWidth":205.22,"exactHeight":87.24}},"fill":{"params":{"backgrounds":[{"params":{"color":{"disabled":true,"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,1)"}},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"componentClass":{"disabled":false,"component":"data2-core-types@ComponentClass","params":{}}},"reference":"uEcsego23YOb1_6V2V_dY"},{"_id":"687e33155e54d3a02dfb524b","parent":"687e33155e54d3a02dfb524a","component":"data2-blocks@IconBlock","system":"686bd24b4fcbdb97284775e3","params":{"super":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":30,"height":28,"exactWidth":30.42,"exactHeight":false}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":0,"y":344,"exactX":false,"exactY":false,"fixed":false,"growH":false,"growV":false,"top":false}}},"icon":{"disabled":false,"component":"data2-core-web@Icon","params":{"icon":"fa fa-angle-double-right"}}},"index":1},{"_id":"687e33155e54d3a02dfb524e","parent":"687e33155e54d3a02dfb524c","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb524e"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}}}}}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":300,"exactWidth":300,"exactHeight":50,"height":50}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":0,"exactX":false,"exactY":false,"left":false,"fixed":false,"growH":true}},"text":{"component":"data2-core-primitives@String","params":{"content":"menu1"}},"onVisibleOnScreen":{"disabled":true,"component":"data2-core-types@Interaction","params":{}},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle"}},"onDragEnter":{"disabled":true,"component":"data2-core-types@Interaction","params":{}},"stateDefinitions":[{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}},"component":"data2-core-primitives@Object","initialValue":{"params":{},"component":"data2-core-types@Fill"}}}],"onMouseEnter":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"value":{"params":{"backgrounds":[{"params":{"color":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(242,242,242,1)"}},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb524e"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}}}}}},"onMouseLeave":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb524e"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}}}},"value":{"params":{},"component":"data2-core-types@Fill"}}}},"index":2},{"_id":"687e33155e54d3a02dfb524f","parent":"687e33155e54d3a02dfb524c","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb524f"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}}}}}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":300,"exactWidth":300,"exactHeight":50,"height":50}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":0,"exactX":false,"exactY":false,"left":false,"fixed":false,"growH":true}},"text":{"component":"data2-core-primitives@String","params":{"content":"menu2"}},"onVisibleOnScreen":{"disabled":true,"component":"data2-core-types@Interaction","params":{}},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle"}},"onDragEnter":{"disabled":true,"component":"data2-core-types@Interaction","params":{}},"stateDefinitions":[{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}},"component":"data2-core-primitives@Object","initialValue":{"params":{},"component":"data2-core-types@Fill"}}}],"onMouseEnter":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"value":{"params":{"backgrounds":[{"params":{"color":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(242,242,242,1)"}},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb524f"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}}}}}},"onMouseLeave":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb524f"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}}}},"value":{"params":{},"component":"data2-core-types@Fill"}}}},"index":2},{"_id":"687e33155e54d3a02dfb5250","parent":"687e33155e54d3a02dfb524c","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5250"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}}}}}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":300,"exactWidth":300,"exactHeight":50,"height":50}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":0,"exactX":false,"exactY":false,"left":false,"fixed":false,"growH":true}},"text":{"component":"data2-core-primitives@String","params":{"content":"menu3"}},"onVisibleOnScreen":{"disabled":true,"component":"data2-core-types@Interaction","params":{}},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle"}},"onDragEnter":{"disabled":true,"component":"data2-core-types@Interaction","params":{}},"stateDefinitions":[{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}},"component":"data2-core-primitives@Object","initialValue":{"params":{},"component":"data2-core-types@Fill"}}}],"onMouseEnter":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"value":{"params":{"backgrounds":[{"params":{"color":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(242,242,242,1)"}},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5250"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}}}}}},"onMouseLeave":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5250"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}}}},"value":{"params":{},"component":"data2-core-types@Fill"}}}},"index":2},{"_id":"687e33155e54d3a02dfb5251","parent":"687e33155e54d3a02dfb524c","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5251"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}}}}}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":300,"exactWidth":300,"exactHeight":50,"height":50}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"x":0,"y":0,"exactX":false,"exactY":false,"left":false,"fixed":false,"growH":true}},"text":{"component":"data2-core-primitives@String","params":{"content":"menu4"}},"onVisibleOnScreen":{"disabled":true,"component":"data2-core-types@Interaction","params":{}},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle"}},"onDragEnter":{"disabled":true,"component":"data2-core-types@Interaction","params":{}},"stateDefinitions":[{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}},"component":"data2-core-primitives@Object","initialValue":{"params":{},"component":"data2-core-types@Fill"}}}],"onMouseEnter":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"value":{"params":{"backgrounds":[{"params":{"color":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(242,242,242,1)"}},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5251"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}}}}}},"onMouseLeave":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5251"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hovered"}}}},"value":{"params":{},"component":"data2-core-types@Fill"}}}},"index":2},{"_id":"687e33155e54d3a02dfb524d","parent":"687e33155e54d3a02dfb524c","component":"data2-blocks@IconBlock","system":"686bd24b4fcbdb97284775e3","params":{"super":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(220,21,0,1)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"height":30,"exactWidth":300,"exactHeight":30,"width":300}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":false,"y":207,"exactX":false,"exactY":false,"fixed":false,"x":null,"left":true,"growH":true}},"text":{"component":"data2-core-primitives@String","params":{"content":""}},"onClick":{"params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5252"}},"key":{"component":"data2-core-primitives@String","params":{"content":"largura_aba"}}}},"value":{"component":"data2-core-primitives@String","params":{"content":"30"}}}},{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5252"}},"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_altura_icone"}}}},"value":{"component":"data2-core-primitives@String","params":{"content":"50"}}}},{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5252"}},"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_largura_icone"}}}},"value":{"component":"data2-core-primitives@String","params":{"content":"50"}}}}]},"component":"data2-core-flow@Series"}},"icon":{"disabled":false,"component":"data2-core-web@Icon","params":{"icon":"fa fa-angle-double-left"}}},"index":3},{"_id":"687e33155e54d3a02dfb5257","parent":"687e33155e54d3a02dfb5256","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(222,232,43,0.94)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":300,"height":150,"exactWidth":300,"exactHeight":150}},"position":{"disabled":false,"component":"data2-core-types@Position","params":{"exactX":false,"exactY":false,"x":{"params":{"components":[{"component":"data2-core-primitives@Number","params":{"content":-300}},{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5256"}},"key":{"component":"data2-core-primitives@String","params":{"content":"posiçãox"}}}}}}]},"component":"data2-core-numerical-operators@Add"},"freeTransform":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"break":true},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle"}},"text":{"component":"data2-core-primitives@String","params":{"content":"0"}}}},{"_id":"687e33155e54d3a02dfb5258","parent":"687e33155e54d3a02dfb5256","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(5,149,237,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":300,"height":150,"exactWidth":300,"exactHeight":150}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"x":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5256"}},"key":{"component":"data2-core-primitives@String","params":{"content":"posiçãox"}}}}}},"y":0,"exactX":false,"exactY":0,"fixed":false},"break":true},"text":{"component":"data2-core-primitives@String","params":{"content":"1"}},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle"}}}},{"_id":"687e33155e54d3a02dfb5259","parent":"687e33155e54d3a02dfb5256","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(255,103,11,0.82)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":300,"height":150,"exactWidth":300,"exactHeight":150}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"y":0,"exactX":false,"exactY":false,"fixed":false,"x":{"params":{"components":[{"component":"data2-core-primitives@Number","params":{"content":300}},{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5256"}},"key":{"component":"data2-core-primitives@String","params":{"content":"posiçãox"}}}}}}]},"component":"data2-core-numerical-operators@Add"}},"break":true},"text":{"disabled":false,"component":"data2-core-primitives@String","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle","content":"2"}},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle"}}}},{"_id":"687e33155e54d3a02dfb525a","parent":"687e33155e54d3a02dfb5256","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,220,47,0.78)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":300,"height":150,"exactWidth":300,"exactHeight":150}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"x":{"params":{"components":[{"component":"data2-core-primitives@Number","params":{"content":600}},{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5256"}},"key":{"component":"data2-core-primitives@String","params":{"content":"posiçãox"}}}}}}]},"component":"data2-core-numerical-operators@Add"},"exactX":0,"exactY":-2.46,"fixed":false}},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle"}},"text":{"component":"data2-core-primitives@String","params":{"content":"3"}}}},{"_id":"687e33155e54d3a02dfb525b","parent":"687e33155e54d3a02dfb5256","component":"data2-blocks@IconBlock","system":"686bd24b4fcbdb97284775e3","params":{"super":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":30,"height":29}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":263,"y":54,"exactX":262.97,"exactY":54.03}},"onClick":{"params":{"compare":{"params":{"subject":{"component":"data2-core-primitives@Number","params":{"content":-600}},"comparisonSubject":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5256"}},"key":{"component":"data2-core-primitives@String","params":{"content":"posiçãox"}}}}}}},"component":"data2-core-comparison-operators@LesserThan"},"then":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5256"}},"key":{"component":"data2-core-primitives@String","params":{"content":"posiçãox"}}}},"value":{"params":{"components":[{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5256"}},"key":{"component":"data2-core-primitives@String","params":{"content":"posiçãox"}}}}}},{"component":"data2-core-primitives@Number","params":{"content":-300}}]},"component":"data2-core-numerical-operators@Add"}}},"else":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5256"}},"key":{"component":"data2-core-primitives@String","params":{"content":"posiçãox"}}}},"value":{"component":"data2-core-primitives@String","params":{"content":"300"}}}}},"component":"data2-core-flow@If"},"transitions":[]},"icon":{"disabled":false,"component":"data2-core-web@Icon","params":{"icon":"fa fa-angle-right"}}}},{"_id":"687e33155e54d3a02dfb525c","parent":"687e33155e54d3a02dfb5256","component":"data2-blocks@IconBlock","system":"686bd24b4fcbdb97284775e3","params":{"super":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":32,"height":30}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":7,"y":52,"exactX":6.8,"exactY":52.29}},"onClick":{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5256"}},"key":{"component":"data2-core-primitives@String","params":{"content":"posiçãox"}}}}}},"comparisonSubject":{"component":"data2-core-primitives@Number","params":{"content":300}}},"component":"data2-core-comparison-operators@LesserThan"},"then":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5256"}},"key":{"component":"data2-core-primitives@String","params":{"content":"posiçãox"}}}},"value":{"params":{"components":[{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5256"}},"key":{"component":"data2-core-primitives@String","params":{"content":"posiçãox"}}}}}},{"component":"data2-core-primitives@Number","params":{"content":300}}]},"component":"data2-core-numerical-operators@Add"}}},"else":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5256"}},"key":{"component":"data2-core-primitives@String","params":{"content":"posiçãox"}}}},"value":{"component":"data2-core-primitives@String","params":{"content":"-600"}}}}},"component":"data2-core-flow@If"}},"icon":{"disabled":false,"component":"data2-core-web@Icon","params":{"icon":"fa fa-angle-left"}}}},{"_id":"687e33155e54d3a02dfb525d","parent":"687e33155e54d3a02dfb5256","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{"leftTop":"30"},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":23,"height":23}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":71,"y":159,"exactX":70.85,"exactY":159.03}}}},{"_id":"687e33155e54d3a02dfb525e","parent":"687e33155e54d3a02dfb5256","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{"leftTop":"30"},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":23,"height":23}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":108,"y":159,"exactX":107.81,"exactY":159.04}}}},{"_id":"687e33155e54d3a02dfb525f","parent":"687e33155e54d3a02dfb5256","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{"leftTop":"30"},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":23,"height":23}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":145,"y":158,"exactX":144.77,"exactY":158.07}}}},{"_id":"687e33155e54d3a02dfb5260","parent":"687e33155e54d3a02dfb5256","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{"leftTop":"30"},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":23,"height":23}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":179,"y":158,"exactX":178.81,"exactY":158.07}}}},{"_id":"687e33155e54d3a02dfb5264","parent":"687e33155e54d3a02dfb5263","component":"data2-blocks@IconBlock","system":"686bd24b4fcbdb97284775e3","params":{"super":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"0","top":"0","right":"0","bottom":"0"}}},"fill":{"params":{"backgrounds":[{"params":{"color":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,120,220,0.3)"},"disabled":true},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":11,"height":10,"exactHeight":10}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":132,"y":10,"fixed":false,"exactX":132.29,"exactY":9.71}}},"icon":{"disabled":false,"component":"data2-core-web@Icon","params":{"icon":"fa fa-caret-down"}}}},{"_id":"687e4b8cf382841e9d41aa86","component":"data2-core-primitives@Artboard","system":"686bd24b4fcbdb97284775e3","displayName":"mybutton","params":{"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":300,"exactWidth":300,"exactHeight":50,"height":50}},"fill":{"params":{"backgrounds":[{"params":{"color":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,1)"}},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"componentStates":[],"componentClass":{"disabled":false,"component":"data2-core-types@ComponentClass","params":{}}},"reference":"p6m5qOinrn4v5UqSE-y_e"},{"_id":"687e002d4de75d5ca013c0a3","parent":"687dfe894de75d5ca013c0a1","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{"leftTop":"15"},"width":{"left":"1","top":"1","right":"1","bottom":"1"}}},"fill":{"params":{"then":{"params":{"backgrounds":[{"params":{"color":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(3,46,207,0.22)"}},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"else":{"params":{"backgrounds":[{"params":{"color":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,1)"}},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"compare":[{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e002d4de75d5ca013c0a3"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}}}}},"component":"data2-core-types@Getter"}]},"component":"data2-core-flow@If"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":205,"height":87,"exactWidth":false,"exactHeight":false}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":0,"y":0,"exactX":false,"exactY":false,"left":true,"top":true,"bottom":true,"growV":false,"right":true,"growH":false}},"text":{"params":{"portions":[{"params":{"string":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"label"}}}}},"component":"data2-core-functions@toLowerCase"},{"component":"data2-core-primitives@String","params":{"content":""}}]},"component":"data2-core-functions@StringConcat"},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle"}},"textSize":{"component":"data2-core-primitives@Number","params":{"content":26}},"stateDefinitions":[{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}},"component":"data2-core-primitives@Boolean","initialValue":{"component":"data2-core-primitives@Boolean","params":{"content":false}}}}],"onMouseEnter":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e002d4de75d5ca013c0a3"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}}}},"value":{"params":{"content":true},"component":"data2-core-primitives@Boolean"}}},"onMouseLeave":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e002d4de75d5ca013c0a3"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}}}},"value":{"params":{"content":false},"component":"data2-core-primitives@Boolean"}}},"textColor":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(27,184,176,1)"}},"onClick":{"params":{"actions":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"click"}}}},{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e002d4de75d5ca013c0a3"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}}}},"value":{"params":{"content":false},"component":"data2-core-primitives@Boolean"}}}]},"component":"data2-core-flow@Series"}}},{"_id":"687e242ee5d32d7202d203ea","component":"data2-core-primitives@Artboard","system":"686bd24b4fcbdb97284775e3","displayName":"@language","params":{"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":150,"height":30,"exactWidth":150,"exactHeight":30}},"fill":{"params":{"backgrounds":[{"params":{"color":{"disabled":false,"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,1)"}},"gradient":{"disabled":true,"component":"data2-core-types@ColorGradient","params":{}},"image":{"disabled":true,"component":"data2-core-types@String","params":{}}},"component":"data2-core-types@Background"}]},"component":"data2-core-types@Fill"},"componentClass":{"disabled":false,"component":"data2-core-types@ComponentClass","params":{}}},"reference":"SBeCKlDH0N59PZtiiG056"},{"_id":"687e506163bcb3c825bbc37a","parent":"687e4b8cf382841e9d41aa86","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"1","top":"1","right":"1","bottom":"1"}}},"fill":{"params":{"compare":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e506163bcb3c825bbc37a"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}}}}},"component":"data2-core-types@Getter"},"then":{"params":{"rgba":"rgba(0,0,0,0.11)"},"component":"data2-core-types@Color"},"else":{"params":{"rgba":"rgba(255,255,255,0)"},"component":"data2-core-types@Color"}},"component":"data2-core-flow@If"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":300,"height":50,"exactWidth":300,"exactHeight":50}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":0,"y":0,"exactX":0,"exactY":0,"top":true,"right":true,"bottom":false,"growV":false,"left":true,"growH":false}},"text":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"text"}}}},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle"}},"onMouseEnter":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e506163bcb3c825bbc37a"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}}}},"value":{"params":{"content":true},"component":"data2-core-primitives@Boolean"}}},"stateDefinitions":[{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}},"component":"data2-core-primitives@Boolean"}}],"onMouseLeave":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e506163bcb3c825bbc37a"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}}}},"value":{"params":{"content":false},"component":"data2-core-primitives@Boolean"}}},"onClick":{"params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5263"}},"key":{"component":"data2-core-primitives@String","params":{"content":"idioma"}}}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"field"}}}}}},{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5262"}},"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_seletor_idioma"}}}},"value":{"component":"data2-core-primitives@String","params":{"content":"30"}}}}]},"component":"data2-core-flow@Series"},"onClickOutside":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5262"}},"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_seletor_idioma"}}}},"value":{"component":"data2-core-primitives@String","params":{"content":"30"}}}}}},{"_id":"687e2463e5d32d7202d203eb","parent":"687e242ee5d32d7202d203ea","component":"data2-core-primitives@Block","system":"686bd24b4fcbdb97284775e3","params":{"border":{"component":"data2-core-types@Border","params":{"color":"#808080","radius":{},"width":{"left":"1","top":"0","right":"1","bottom":"1"}}},"fill":{"params":{"compare":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e2463e5d32d7202d203eb"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}}}}},"component":"data2-core-types@Getter"},"then":{"params":{"rgba":"rgba(0,0,0,0.11)"},"component":"data2-core-types@Color"},"else":{"params":{"rgba":"rgba(255,255,255,0)"},"component":"data2-core-types@Color"}},"component":"data2-core-flow@If"},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":150,"height":30,"exactWidth":false,"exactHeight":false}},"position":{"component":"data2-core-types@Position","params":{"freeTransform":true,"x":0,"y":0,"exactX":0,"exactY":0,"top":true,"right":true,"bottom":false,"growV":false,"left":true,"growH":false}},"text":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"field"}}}},"textFormat":{"disabled":false,"component":"data2-core-types@TextFormat","params":{"horizontalAlignment":"center","textOverflow":false,"verticalAlignment":"middle"}},"onMouseEnter":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e2463e5d32d7202d203eb"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}}}},"value":{"params":{"content":true},"component":"data2-core-primitives@Boolean"}}},"stateDefinitions":[{"component":"data2-core-user-interface@StateDefinition","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}},"component":"data2-core-primitives@Boolean"}}],"onMouseLeave":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e2463e5d32d7202d203eb"}},"key":{"component":"data2-core-primitives@String","params":{"content":"hover"}}}},"value":{"params":{"content":false},"component":"data2-core-primitives@Boolean"}}},"onClick":{"params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5263"}},"key":{"component":"data2-core-primitives@String","params":{"content":"idioma"}}}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"field"}}}}}},{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5262"}},"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_seletor_idioma"}}}},"value":{"component":"data2-core-primitives@String","params":{"content":"30"}}}}]},"component":"data2-core-flow@Series"},"onClickOutside":{"component":"data2-core-types@Setter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"__UIState"}},"prop":{"component":"data2-core-user-interface@StateProp","params":{"componentId":{"component":"data2-core-primitives@String","params":{"content":"687e33155e54d3a02dfb5262"}},"key":{"component":"data2-core-primitives@String","params":{"content":"tamanho_seletor_idioma"}}}},"value":{"component":"data2-core-primitives@String","params":{"content":"30"}}}}}}]}},{"_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":"687e398ff90f3baaf0733c6c","displayName":"App","reference":"J3ATnc_XoVihH8xrqSAJy","params":{"entryPoint":{"disabled":false,"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Router","reference":"r0UvisOv4rxqSjgNtVb5d"}},"domain":{"component":"data2-core-primitives@String","params":{"content":"app"}}},"system":"686bd24b4fcbdb97284775e3","component":"data2-core-primitives@Application"}]}},{"reference":"DataComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a8381a745ad40122b07bb62","component":"data2-core@Data2TableDataSource","system":"686bd24b4fcbdb97284775e3","params":{"table":"pedidos","schema":[{"component":"data2-core-types@Field","params":{"key":"usuarioId","title":"Usuário","component":"data2-core-primitives@ObjectId","required":true}},{"component":"data2-core-types@Field","params":{"key":"usuarioNome","title":"Nome do Usuário","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"produtosIds","title":"Produtos (IDs)","component":"data2-core-primitives@Array"}},{"component":"data2-core-types@Field","params":{"key":"produtosNomes","title":"Produtos (Nomes)","component":"data2-core-primitives@Array"}},{"component":"data2-core-types@Field","params":{"key":"total","title":"Total","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"pago","title":"Pago","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"formaPagamento","title":"Forma de Pagamento","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"entregue","title":"Entregue","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"revenda","title":"Pedido de revenda","component":"data2-core-primitives@Boolean"}}]},"reference":"pedidos"},{"_id":"6a8381a3809f62e448266023","component":"data2-core@Data2TableDataSource","system":"686bd24b4fcbdb97284775e3","params":{"table":"produtos","schema":[{"component":"data2-core-types@Field","params":{"key":"nome_produto","title":"Nome do Produto","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"preco","title":"Preço","component":"data2-core-primitives@Number","required":true}},{"component":"data2-core-types@Field","params":{"key":"qtyTemp","title":"Quantidade Temporária","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"preco_revenda","title":"Preço de revenda","component":"data2-core-primitives@Number"}}]},"reference":"produtos"}]}},{"reference":"BundlesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}}],"processesParams":{}}}}