{"context":{"domain":"adonis"},"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":"69651bdddc863af2ecd97d3d","name":"app","domain":"adonis","visibility":"public","settings":{"defaultAccessPolicy":"public"},"updatedAt":"2026-07-27T14:19:36.810Z","createdAt":"2026-01-12T16:05:49.767Z"}]}},{"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":"6a330e4d926d2ad8226384d8","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"PanelSidebar","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  :host,.sb{height:100%}\n  .sb{background:#141414;border-right:1px solid #2a2a2a;display:flex;flex-direction:column;font-family:'Inter',system-ui,sans-serif;color:#fff;box-sizing:border-box}\n  .top{background:var(--acc,#F4C400);color:#000;padding:9px 20px;font-size:11px;letter-spacing:.14em;font-weight:700;text-transform:uppercase;display:flex;align-items:center;gap:8px}\n  .dot{width:7px;height:7px;border-radius:50%;background:#000}\n  .brand{padding:22px 20px 18px;border-bottom:1px solid #2a2a2a}\n  .brand .w{font-family:'Anton',sans-serif;font-size:26px;letter-spacing:.04em;line-height:.85}\n  .brand small{display:block;font-size:9px;letter-spacing:.4em;color:#9a9a9a;margin-top:6px;font-weight:600}\n  .brand small b{color:#fff}\n  .sec{padding:18px 20px 6px;font-size:9px;letter-spacing:.22em;color:#5a5a5a;font-weight:700;text-transform:uppercase}\n  .nav{display:flex;flex-direction:column;gap:2px;padding:0 10px}\n  .nl{display:flex;align-items:center;gap:11px;padding:12px 14px;border-radius:8px;color:#9a9a9a;font-size:13px;letter-spacing:.1em;font-weight:700;text-transform:uppercase;cursor:pointer;transition:.13s;border-left:3px solid transparent}\n  .nl:hover{color:#fff;background:#1a1a1a}\n  .nl.on{color:var(--acc,#F4C400);background:#1a1a1a;border-left-color:var(--acc,#F4C400)}\n  .nl .ic{font-size:15px;width:18px;text-align:center}\n  .grow{flex:1}\n  .foot{padding:18px 20px;border-top:1px solid #2a2a2a;color:#4b5563;font-size:9px;letter-spacing:.2em;font-weight:600}\n  `,\n  render(d2){\n    const acc = d2.param('accent') || '#F4C400';\n    let path = '';\n    try{ path = d2.router().path || ''; }catch(e){}\n    if(!path || path==='/') path = d2.param('currentPath') || '/catalogo';\n    if(path && path[0]!=='/') path = '/'+path;\n    const items = [\n      {p:'/catalogo', ic:'▦', t:'Catálogo'},\n      {p:'/membros',  ic:'◆', t:'Membros'},\n      {p:'/clientes', ic:'●', t:'Clientes'},\n      {p:'/entrada',  ic:'✓', t:'Entrada'}\n    ];\n    const isOn = (p)=> path===p || (p==='/catalogo' && (path==='/'||path===''));\n    return `<div class=\"sb\" style=\"--acc:${acc}\">\n      <div class=\"top\"><span class=\"dot\"></span> Painel Interno</div>\n      <div class=\"brand\"><div class=\"w\">TEMPO</div><small>by <b>PORSCHE</b></small></div>\n      <div class=\"sec\">Gestão</div>\n      <div class=\"nav\">\n        ${items.map(i=>`<div class=\"nl ${isOn(i.p)?'on':''}\" data-p=\"${i.p}\"><span class=\"ic\">${i.ic}</span>${i.t}</div>`).join('')}\n      </div>\n      <div class=\"grow\"></div>\n      <div class=\"foot\">v1.0 · BY PORSCHE</div>\n    </div>`;\n  },\n  mounted(d2){\n    d2.on('.nl','click',(e,el)=>{ d2.router().goTo(el.dataset.p); });\n  }\n}"}},"currentPath":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"currentPath"}}}},"accent":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"accent"}}}}}}}}}},{"_id":"6a330eac2464545b1a616c3e","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"PersonCard","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .card{background:#141417;border:1px solid #2a2a31;border-radius:16px;padding:16px;font-family:-apple-system,system-ui,sans-serif;color:#f4f4f5;box-sizing:border-box}\n  .row{display:flex;align-items:center;gap:14px}\n  .num{font-size:30px;font-weight:800;letter-spacing:1px;font-variant-numeric:tabular-nums;min-width:96px;color:#fff}\n  .num.rsv{font-size:22px;min-width:64px;color:#F4C400}\n  .grow{flex:1;min-width:0}\n  .nm{font-size:19px;font-weight:700}\n  .meta{color:#8b8b94;font-size:13px;margin-top:3px}\n  .badges{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}\n  .tag{font-size:12px;font-weight:700;padding:4px 9px;border-radius:999px;background:#1c1c21;color:#8b8b94}\n  .tag.f{background:#3b1f3a;color:#f0a6e6}.tag.m{background:#1c2c40;color:#8fc0ff}\n  .tag.canc{background:#2a2a31;color:#ffce7a}.tag.obs{background:#332a12;color:#ffce7a}.tag.in{background:#143524;color:#7ee2a8}\n  .tag.rsv{background:#F4C400;color:#000}.tag.rsv.seated{background:#143524;color:#7ee2a8}\n  .orig{font-size:11px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;padding:4px 9px;border-radius:999px}\n  .orig.membro{background:#3a2d12;color:#F4C400}\n  .orig.reserva{background:#143a30;color:#7ee2a8}\n  .orig.entrada{background:#1c2c40;color:#8fc0ff}\n  .orig.cliente{background:#2a2a31;color:#cfcfcf}\n  .btn{border:0;border-radius:12px;padding:14px 18px;font-size:16px;font-weight:700;background:#1c1c21;color:#f4f4f5;cursor:pointer;white-space:nowrap}\n  .btn.ok{background:var(--acc,#F4C400);color:#000}\n  .btn:disabled{opacity:.5;cursor:default}\n  `,\n  render(d2){\n    const e = d2.param('record') || {};\n    const acc = d2.param('accent') || '#F4C400';\n    const esc = s => String(s==null?'':s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));\n    const hhmm = iso => { if(!iso) return ''; const d=new Date(iso); return d2.fmt.time(d); };\n    const digits = s => String(s==null?'':s).replace(/\\D/g,'');\n    const tail = s => { let d=digits(s); if(d.length>11 && d.slice(0,2)==='55') d=d.slice(2); return d.slice(-10); };\n    const isReserva = e.__orig==='reserva';\n    // matched reservation: either this IS a reservation, or a person whose phone matches a reservation\n    const reservas = d2.param('reservas') || [];\n    const pTail = tail(e.telefone);\n    let matchRes = e.__reserva || null;\n    if(!matchRes && !isReserva && pTail && pTail.length>=8){\n      matchRes = reservas.find(r=>{ if(!r||r.status==='Canceled')return false; const rt=tail((r.customer||{}).phone); return rt && rt===pTail; }) || null;\n    }\n    d2.state._matchRes = matchRes;\n    const rsvObj = isReserva ? (e.__reserva||{}) : matchRes;\n    const rsvSeated = rsvObj && rsvObj.status==='Seated';\n    const rsv = rsvObj\n      ? `<span class=\"tag rsv${rsvSeated?' seated':''}\">${rsvSeated?'✓ sentou':'Reserva'} ${esc(rsvObj.reservationTime||'')}${rsvObj.partySize?' · '+rsvObj.partySize+'pax':''}</span>`\n      : '';\n    // origin badges (may be combined)\n    const origs = e.__origs && e.__origs.length ? e.__origs : (e.__orig?[e.__orig]:[]);\n    const LBL={membro:'Membro',reserva:'Reserva',entrada:'Entrada',cliente:'Cliente'};\n    const origBadges = origs.map(o=>`<span class=\"orig ${o}\">${LBL[o]||o}</span>`).join('');\n    const g = e.genero==='F'?'<span class=\"tag f\">♀</span>':e.genero==='M'?'<span class=\"tag m\">♂</span>':'';\n    const pax = e.pax?`<span class=\"tag\">${e.pax} pax</span>`:'';\n    const canc = e.reservaStatus==='cancelado'?'<span class=\"tag canc\">CANCELADO</span>':'';\n    const obs = e.obs?`<span class=\"tag obs\">${esc(e.obs)}</span>`:'';\n    const mc = e.member_code?`<span class=\"tag\">cód ${esc(e.member_code)}</span>`:'';\n    const inb = e.checkin?`<span class=\"tag in\">✓ entrou ${hhmm(e.checkin)}</span>`:'';\n    let btn, num;\n    if(isReserva){\n      const c = (e.__reserva||{}).customer||{};\n      num = `<div class=\"num rsv\">${esc((e.__reserva||{}).reservationTime||'--:--')}</div>`;\n      btn = rsvSeated\n        ? `<button class=\"btn\" disabled>✓ Sentou</button>`\n        : `<button class=\"btn ok\" data-act=\"checkin\">Check-in ✓</button>`;\n    } else {\n      num = `<div class=\"num\">${esc(e.codTerceiro||'—')}</div>`;\n      btn = e.checkin\n        ? `<button class=\"btn\" data-act=\"undo\">Desfazer</button>`\n        : `<button class=\"btn ok\" data-act=\"in\">Entrou ✓</button>`;\n    }\n    const metaParts=[];\n    if(!isReserva){ metaParts.push('NrPessoa '+esc(e.nrPessoa==null?'—':e.nrPessoa)); if(e.cpf)metaParts.push('CPF '+esc(e.cpf)); }\n    if(e.telefone)metaParts.push(esc(e.telefone));\n    return `<div class=\"card\" style=\"--acc:${acc}\"><div class=\"row\">\n      ${num}\n      <div class=\"grow\"><div class=\"nm\">${esc(e.nome)}</div>\n        <div class=\"meta\">${metaParts.join(' · ')}</div>\n        <div class=\"badges\">${origBadges}${rsv}${mc}${g}${pax}${canc}${obs}${inb}</div></div>\n      <div>${btn}</div></div></div>`;\n  },\n  mounted(d2){\n    d2.on('.btn','click',(ev,el)=>{ const e=d2.param('record')||{}; const act=el.dataset.act; if(!act)return;\n      if(act==='checkin'){ d2.emit('onCheckin',{reservaOnly:true, reserva:e.__reserva||null}); return; }\n      d2.emit('onCheckin',{codTerceiro:e.codTerceiro, nome:e.nome, telefone:e.telefone, cpf:e.cpf, pax:e.pax, desfazer: act==='undo', reserva:d2.state._matchRes||null}); });\n  }\n}"}},"record":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"record"}}}},"accent":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"accent"}}}},"reservas":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"reservas"}}}}}}}}}},{"_id":"6a330eac293ce144a47dec8b","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"MemberCard","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .mcard{background:#141414;border:1px solid #2a2a2a;border-left:3px solid #2a2a2a;border-radius:4px;padding:16px;display:flex;flex-direction:column;gap:10px;font-family:'Inter',system-ui,sans-serif;color:#fff;box-sizing:border-box;height:100%}\n  .mcard.founder{border-left-color:#F4C400}\n  .mhead{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}\n  .mcard h3{font-family:'Anton',sans-serif;font-size:17px;line-height:1.1;letter-spacing:.02em;margin:0}\n  .code{font-family:'Anton',sans-serif;font-size:15px;color:#F4C400;white-space:nowrap}\n  .tipo{font-size:9px;font-weight:700;letter-spacing:.14em;padding:4px 8px;text-transform:uppercase;background:#3a3a3a;color:#bbb;align-self:flex-start;border-radius:2px}\n  .tipo.founder{background:#F4C400;color:#000}\n  .info{display:grid;grid-template-columns:auto 1fr;gap:3px 10px;font-size:12px;color:#cfcfcf}\n  .info .k{color:#9a9a9a;font-size:9px;letter-spacing:.14em;text-transform:uppercase;align-self:center}\n  .porsche{border-top:1px solid #2a2a2a;padding-top:10px;display:flex;gap:6px;flex-wrap:wrap;align-items:center}\n  .porsche b{background:#1c1c1c;border:1px solid #2a2a2a;padding:3px 7px;font-size:9px;letter-spacing:.08em;color:#bbb;font-weight:600;text-transform:uppercase;border-radius:2px}\n  .thumb{width:54px;height:36px;border-radius:4px;background:#000 center/cover no-repeat;border:1px solid #2a2a2a;flex:0 0 auto}\n  `,\n  render(d2){\n    const m = d2.param('record')||{};\n    const esc = s => String(s==null?'':s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));\n    const founder = String(m.tipo_cadastro||'').toUpperCase()==='FOUNDER';\n    const local = [m.cidade,m.estado].filter(Boolean).map(esc).join(' · ') || '—';\n    const porsche = m.tem_porsche ? `<div class=\"porsche\">\n      ${m.car_image?`<span class=\"thumb\" style=\"background-image:url('${m.car_image}')\"></span>`:''}\n      ${m.modelo_porsche?`<b>${esc(m.modelo_porsche)}</b>`:''}\n      ${m.versao_porsche?`<b>${esc(m.versao_porsche)}</b>`:''}\n      ${m.ano_porsche?`<b>${esc(m.ano_porsche)}</b>`:''}\n      ${m.cor_porsche?`<b>${esc(m.cor_porsche)}</b>`:''}\n      ${m.placa?`<b>${esc(m.placa)}</b>`:''}</div>` : '';\n    return `<div class=\"mcard ${founder?'founder':''}\">\n      <div class=\"mhead\"><h3>${esc(m.nome_completo)||'—'}</h3><span class=\"code\">#${esc(m.member_code)||'—'}</span></div>\n      <span class=\"tipo ${founder?'founder':''}\">${esc(m.tipo_cadastro)||'—'}</span>\n      <div class=\"info\">\n        <span class=\"k\">E-mail</span><span>${esc(m.email)||'—'}</span>\n        <span class=\"k\">Telefone</span><span>${esc(m.telefone)||'—'}</span>\n        <span class=\"k\">Local</span><span>${local}</span>\n      </div>${porsche}</div>`;\n  }\n}"}},"record":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"record"}}}}}}}}}},{"_id":"6a330eadb4151ec91819f683","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"ProductCard","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .card{background:#141414;border:1px solid #2a2a2a;border-radius:4px;overflow:hidden;display:flex;flex-direction:column;font-family:'Inter',system-ui,sans-serif;color:#fff;box-sizing:border-box;height:100%}\n  .top{display:flex;gap:14px;padding:16px;border-bottom:1px solid #2a2a2a}\n  .thumb{width:74px;height:74px;flex:0 0 74px;background:#000 center/cover no-repeat;border:1px solid #2a2a2a;border-radius:3px}\n  .ti{flex:1;min-width:0}\n  h3{font-family:'Anton',sans-serif;font-size:16px;line-height:1.05;letter-spacing:.02em;margin:0}\n  .price{color:#F4C400;font-family:'Anton',sans-serif;font-size:18px;margin-top:4px}\n  .meta{display:flex;gap:6px;flex-wrap:wrap;font-size:9px;letter-spacing:.1em;color:#9a9a9a;text-transform:uppercase;margin-top:8px;align-items:center}\n  .meta b{background:#1c1c1c;border:1px solid #2a2a2a;padding:3px 7px;color:#bbb;font-weight:600;border-radius:2px}\n  .badge{font-size:9px;font-weight:700;letter-spacing:.14em;padding:4px 8px;text-transform:uppercase;background:#F4C400;color:#000;border-radius:2px}\n  .badge.exp{background:#3a3a3a;color:#bbb}\n  .cfg{padding:16px;display:flex;flex-direction:column;gap:12px}\n  .cfg label{font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:#9a9a9a;font-weight:600;display:block;margin-bottom:5px}\n  select,input{background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;padding:9px 11px;font-family:inherit;font-size:14px;font-weight:600;outline:none;width:100%;box-sizing:border-box;border-radius:3px}\n  select:focus,input:focus{border-color:#F4C400}\n  .two{display:grid;grid-template-columns:1fr 1fr;gap:12px}\n  .ig{position:relative}.ig .unit{position:absolute;right:11px;top:50%;transform:translateY(-50%);color:#9a9a9a;font-size:13px;font-weight:600;pointer-events:none}.ig input{padding-right:32px}\n  .actions{display:flex;align-items:center;gap:10px}\n  .save{flex:1;background:#F4C400;color:#000;border:none;padding:11px;font-size:11px;letter-spacing:.16em;font-weight:700;text-transform:uppercase;cursor:pointer;border-radius:3px}\n  .save:disabled{opacity:.5}\n  .sync{font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:#9a9a9a;white-space:nowrap}\n  .sync.ok{color:#4ade80}.sync.dirty{color:#F4C400}\n  `,\n  render(d2){\n    const p = d2.param('record')||{};\n    const esc = s => String(s==null?'':s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));\n    const TIPOS=['Founder','VIP','Membro','Corporativo','Convidado'];\n    const member = !!p.isMembership;\n    const st = d2.state;\n    if(st.tipo===undefined){\n      const saved = p.savedConfig;\n      const DEF={Founder:{c:5000,d:30},VIP:{c:2000,d:20},Membro:{c:800,d:10},Corporativo:{c:3000,d:15},Convidado:{c:0,d:0}};\n      const dt = member?'Founder':'Convidado';\n      st.tipo = saved?saved.tipo_cliente: dt;\n      st.consumo = saved?saved.consumo: DEF[dt].c;\n      st.desconto = saved?saved.desconto: DEF[dt].d;\n      st.synced = saved?!!saved.synced:false;\n      st.dirty = false;\n    }\n    const opts = TIPOS.map(t=>`<option value=\"${t}\" ${t===st.tipo?'selected':''}>${t}</option>`).join('');\n    const syncCls = st.err?'sync':(st.dirty?'sync dirty':(st.synced?'sync ok':'sync'));\n    const syncTxt = st.err?'⚠ não salvou':(st.dirty?'● não salvo':(st.synced?'✓ sincronizado':'○ não sincronizado'));\n    return `<div class=\"card\">\n      <div class=\"top\">\n        <div class=\"thumb\" ${p.image?`style=\"background-image:url('${p.image}')\"`:''}></div>\n        <div class=\"ti\"><h3>${esc(p.name)}</h3><div class=\"price\">${esc(p.price)||'—'}</div>\n          <div class=\"meta\"><b>#${esc(p.id)}</b>${p.sku?`<b>SKU ${esc(p.sku)}</b>`:''}<span class=\"badge ${member?'':'exp'}\">${member?'MEMBERSHIP':'EXPERIÊNCIA'}</span></div></div>\n      </div>\n      <div class=\"cfg\">\n        <div><label>Tipo de cliente</label><select class=\"f-tipo\">${opts}</select></div>\n        <div class=\"two\">\n          <div><label>Consumo</label><div class=\"ig\"><input class=\"f-consumo\" type=\"number\" min=\"0\" step=\"50\" value=\"${st.consumo}\"><span class=\"unit\">R$</span></div></div>\n          <div><label>Desconto</label><div class=\"ig\"><input class=\"f-desconto\" type=\"number\" min=\"0\" max=\"100\" value=\"${st.desconto}\"><span class=\"unit\">%</span></div></div>\n        </div>\n        <div class=\"actions\"><button class=\"save\" ${st.saving?'disabled':''}>${st.saving?'Salvando…':'Salvar & Sincronizar'}</button><span class=\"${syncCls}\" style=\"${st.err?'color:#ffce7a':''}\">${syncTxt}</span></div>\n        ${st.err?`<div style=\"font-size:11px;color:#ffce7a;letter-spacing:.04em;line-height:1.4\">${esc(st.err)}</div>`:''}\n      </div></div>`;\n  },\n  mounted(d2){\n    const DEF={Founder:{c:5000,d:30},VIP:{c:2000,d:20},Membro:{c:800,d:10},Corporativo:{c:3000,d:15},Convidado:{c:0,d:0}};\n    d2.on('.f-tipo','change',(e,el)=>{ d2.state.tipo=el.value; const x=DEF[el.value]; if(x){d2.state.consumo=x.c;d2.state.desconto=x.d;} d2.state.dirty=true; d2.state.synced=false; d2.state.err=null; });\n    d2.on('.f-consumo','input',(e,el)=>{ d2.state.consumo=+el.value||0; d2.state.dirty=true; d2.state.err=null; });\n    d2.on('.f-desconto','input',(e,el)=>{ d2.state.desconto=+el.value||0; d2.state.dirty=true; d2.state.err=null; });\n    d2.on('.save','click',async ()=>{\n      const p=d2.param('record')||{}; const ds=d2.data('config');\n      if(!ds){ d2.state.err='Config indisponível (tabela ainda não publicada).'; return; }\n      d2.state.saving=true; d2.state.err=null;\n      const rec={product_id:String(p.id), tipo_cliente:d2.state.tipo, consumo:d2.state.consumo, desconto:d2.state.desconto, synced:true, updatedAt:new Date().toISOString()};\n      try{\n        const existing=(ds.records()||[]).find(r=>String(r.product_id)===String(p.id));\n        if(existing){ await ds.update({...existing, ...rec}); } else { await ds.create(rec); }\n        d2.state.synced=true; d2.state.dirty=false; d2.state.err=null;\n      }catch(err){ d2.log('save cfg err', err); d2.state.err='Não foi possível salvar agora. Tente novamente.'; }\n      finally{ d2.state.saving=false; }\n    });\n  }\n}"}},"record":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"record"}}}},"config":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"config"}}}}}}}}}},{"_id":"6a330ead2464545b1a616c47","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"ClienteRow","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .wrap{font-family:'Inter',system-ui,sans-serif;color:#fff}\n  .row-item{background:#141414;border:1px solid #2a2a2a;border-left:3px solid #2a2a2a;border-radius:4px;padding:13px 16px;display:flex;align-items:center;gap:14px;flex-wrap:wrap}\n  .main{flex:1;min-width:200px}\n  .name{font-weight:700;font-size:14px}\n  .sub{font-size:11px;color:#9a9a9a;margin-top:3px;letter-spacing:.04em}\n  .tag{font-size:9px;font-weight:700;letter-spacing:.12em;padding:4px 8px;text-transform:uppercase;background:#1c1c1c;border:1px solid #2a2a2a;color:#bbb;border-radius:2px}\n  .btn{background:transparent;border:1px solid #2a2a2a;color:#9a9a9a;padding:7px 12px;font-size:10px;letter-spacing:.1em;text-transform:uppercase;cursor:pointer;white-space:nowrap;border-radius:3px}\n  .btn:hover{color:#fff;border-color:#F4C400}\n  .btn.on{color:#F4C400;border-color:#F4C400}\n  .box{background:#1c1c1c;border:1px solid #2a2a2a;border-top:0;margin:0 0 0 0;padding:12px 16px;font-size:12px;color:#cfcfcf;border-radius:0 0 4px 4px}\n  .vrow{display:flex;justify-content:space-between;padding:4px 0;border-bottom:1px solid #2a2a2a}.vrow:last-child{border-bottom:none}\n  .tot{color:#F4C400;font-family:'Anton',sans-serif;font-size:16px}\n  .conv{display:flex;align-items:flex-end;gap:12px;flex-wrap:wrap}\n  .conv .c{display:flex;flex-direction:column;gap:5px}\n  .conv label{font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:#9a9a9a;font-weight:600}\n  .conv input,.conv select{background:#141414;border:1px solid #2a2a2a;color:#fff;padding:9px 11px;font-size:13px;outline:none;min-width:170px;border-radius:3px}\n  .conv input:focus,.conv select:focus{border-color:#F4C400}\n  .save{background:#F4C400;color:#000;border:none;padding:10px 16px;font-size:11px;letter-spacing:.12em;font-weight:700;text-transform:uppercase;cursor:pointer;border-radius:3px}\n  .save:disabled{opacity:.5}\n  .msg{align-self:center;font-size:12px}.msg.ok{color:#4ade80}.msg.err{color:#ff6b6b}\n  `,\n  render(d2){\n    const c = d2.param('record')||{};\n    const esc = s => String(s==null?'':s).replace(/[&<>]/g,ch=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[ch]));\n    const tel = [c.DDDTelefone,c.Telefone].filter(Boolean).join(' ').trim();\n    const st=d2.state;\n    const mode=st.mode||'';\n    let box='';\n    if(mode==='vendas'){\n      if(st.vLoading) box=`<div class=\"box\">Carregando vendas (90 dias)…</div>`;\n      else if(st.vErr) box=`<div class=\"box\" style=\"color:#ff6b6b\">${esc(st.vErr)}</div>`;\n      else { const vs=st.vendas||[]; if(!vs.length) box=`<div class=\"box\"><div class=\"sub\">Sem vendas nos últimos 90 dias.</div></div>`;\n        else { let tot=0; const rows=vs.map(v=>{const val=Number(v.ValorTotal||v.Valor||v.VlTotal||0);tot+=val;const dt=esc(v.DataVenda||v.Data||v.DtVenda||'');return `<div class=\"vrow\"><span>${dt} · ${esc(v.NrVenda||v.Documento||'')}</span><span>${d2.fmt.currency(val,'BRL')}</span></div>`;}).join('');\n          box=`<div class=\"box\">${rows}<div class=\"vrow\"><span>Total (${vs.length})</span><span class=\"tot\">${d2.fmt.currency(tot,'BRL')}</span></div></div>`; } }\n    } else if(mode==='membro'){\n      const msgCls=st.msgKind==='ok'?'msg ok':st.msgKind==='err'?'msg err':'msg';\n      box=`<div class=\"box\"><div class=\"conv\">\n        <div class=\"c\"><label>E-mail *</label><input class=\"m-email\" type=\"email\" placeholder=\"obrigatório\" value=\"${esc(st.email||'')}\"></div>\n        <div class=\"c\"><label>Tipo</label><select class=\"m-tipo\"><option>MEMBER</option><option>ENTHUSIAST</option><option>GUEST</option><option>FOUNDER</option></select></div>\n        <div class=\"c\"><label>Telefone</label><input class=\"m-tel\" value=\"${esc(tel)}\"></div>\n        <button class=\"save m-save\" ${st.saving?'disabled':''}>${st.saving?'Cadastrando…':'Cadastrar membro'}</button>\n        <span class=\"${msgCls}\">${esc(st.msg||'')}</span></div></div>`;\n    }\n    return `<div class=\"wrap\"><div class=\"row-item\">\n      <div class=\"main\"><div class=\"name\">${esc(c.Nome)||'—'}</div>\n        <div class=\"sub\">Nr ${esc(c.NrPessoa)} · ${c.TpPessoa==='J'?'PJ':'PF'} · ${esc(c.CpfCnpj)||'—'}${tel?' · '+esc(tel):''}</div></div>\n      <span class=\"tag\">${esc(c.Situacao)||'—'}</span>\n      <button class=\"btn v-btn ${mode==='vendas'?'on':''}\">Vendas</button>\n      <button class=\"btn m-btn ${mode==='membro'?'on':''}\">Tornar membro</button>\n    </div>${box}</div>`;\n  },\n  mounted(d2){\n    const ymd=dt=>dt.toISOString().slice(0,10).replace(/-/g,'');\n    function wins(){const out=[];const today=new Date();for(let i=0;i<3;i++){const fim=new Date(today);fim.setDate(today.getDate()-i*30);const ini=new Date(fim);ini.setDate(fim.getDate()-29);out.push([ymd(ini),ymd(fim)]);}return out;}\n    const KEY={authorization:'sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'};\n    d2.on('.v-btn','click',async ()=>{ const c=d2.param('record')||{};\n      if(d2.state.mode==='vendas'){ d2.state.mode=''; return; }\n      d2.state.mode='vendas'; d2.state.vLoading=true; d2.state.vErr=null;\n      try{ const rs=await Promise.all(wins().map(([di,df])=> d2.rush(d2.params.vendas).invoke({NrPessoa:c.NrPessoa,DataInicio:di,DataFim:df},{headers:KEY}).then(r=>{let d=r&&r.data!==undefined?r.data:r; if(d&&d.data!==undefined)d=d.data; return d;}).catch(()=>({})) ));\n        const vendas=rs.flatMap(d=> (d&&(d.DadosVenda||d.Vendas||d.DadosVendas))||[]); d2.state.vendas=vendas; }\n      catch(e){ d2.state.vErr='Erro: '+e.message; } finally{ d2.state.vLoading=false; }\n    });\n    d2.on('.m-btn','click',()=>{ if(d2.state.mode==='membro'){d2.state.mode='';return;} d2.state.mode='membro'; d2.state.msg=''; d2.state.msgKind=''; });\n    d2.on('.m-email','input',(e,el)=>{ d2.state.email=el.value; });\n    d2.on('.m-save','click',async ()=>{ const c=d2.param('record')||{};\n      const email=(d2.$('.m-email')||{}).value||d2.state.email||''; const tipo=(d2.$('.m-tipo')||{}).value||'MEMBER'; const tel=(d2.$('.m-tel')||{}).value||'';\n      if(!email.trim()){ d2.state.msg='Informe um e-mail.'; d2.state.msgKind='err'; return; }\n      d2.state.saving=true; d2.state.msg='Cadastrando no adonis…'; d2.state.msgKind='';\n      try{ const r=await d2.rush(d2.params.signup).invoke({nome_completo:c.Nome,email,telefone:tel,cpf:c.CpfCnpj,tipo_cadastro:tipo,tem_porsche:false,pais_origem:'Brasil',origin:'PAINEL'},{headers:{authorization:'Bearer sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'}});\n        const d=r&&r.data!==undefined?r.data:r;\n        if(d&&d.success){ d2.state.msg='✓ Membro criado — código '+((d.data&&d.data.member_code)||'?'); d2.state.msgKind='ok'; d2.emit('onConvert',c); }\n        else { d2.state.msg='✗ '+((d&&(d.error||d.message))||'falha'); d2.state.msgKind='err'; }\n      }catch(e){ d2.state.msg='✗ '+e.message; d2.state.msgKind='err'; } finally{ d2.state.saving=false; }\n    });\n  }\n}"}},"record":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"record"}}}},"vendas":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"vendas"}}}},"signup":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"signup"}}}}}}}}}},{"_id":"6a330f0fec12023d1caffcb9","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"EntradaSearch","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .wrap{font-family:-apple-system,system-ui,sans-serif;color:#f4f4f5}\n  .big{width:100%;box-sizing:border-box;font-size:22px;padding:18px;text-align:center;font-weight:600;background:#141417;border:1px solid #2a2a31;color:#f4f4f5;border-radius:12px;outline:none}\n  .big:focus{border-color:#F4C400}\n  .hint{color:#8b8b94;font-size:13px;margin:8px 2px}\n  .blockbtn{width:100%;border:0;border-radius:12px;padding:14px 18px;font-size:16px;font-weight:700;background:#1c1c21;color:#f4f4f5;cursor:pointer;margin:10px 0}\n  .empty{text-align:center;color:#8b8b94;padding:40px 12px}\n  .res>div{margin:12px 0}\n  dialog{border:0;border-radius:18px;background:#141417;color:#f4f4f5;padding:0;width:min(94vw,440px)}\n  dialog::backdrop{background:rgba(0,0,0,.6)}\n  .dh{padding:18px;border-bottom:1px solid #2a2a31;font-weight:700;font-size:18px}\n  .db{padding:18px;display:flex;flex-direction:column;gap:12px}\n  .db input{width:100%;box-sizing:border-box;background:#1c1c21;border:1px solid #2a2a31;color:#f4f4f5;border-radius:12px;padding:14px;font-size:16px;outline:none}\n  .df{padding:14px 18px;display:flex;gap:10px;border-top:1px solid #2a2a31}\n  .df .btn{flex:1;border:0;border-radius:12px;padding:14px;font-size:16px;font-weight:700;background:#1c1c21;color:#f4f4f5;cursor:pointer}\n  .df .btn.acc{background:#F4C400;color:#000}\n  .mlead{color:#ffce7a;font-size:14px;font-weight:700;margin:2px 0 2px}\n  .msub{color:#8b8b94;font-size:12px;margin:-4px 0 6px}\n  .cand{display:flex;align-items:center;gap:10px;background:#1c1c21;border:1px solid #2a2a31;border-radius:12px;padding:12px 14px;cursor:pointer;text-align:left;width:100%}\n  .cand:hover{border-color:#F4C400}\n  .cand .cg{flex:1;min-width:0}\n  .cand .cn{font-size:16px;font-weight:700;color:#f4f4f5}\n  .cand .cm{font-size:12px;color:#8b8b94;margin-top:2px}\n  .cand .orig{font-size:11px;font-weight:700;padding:3px 8px;border-radius:999px;background:#143524;color:#7ee2a8;white-space:nowrap}\n  .cand .orig.cfy{background:#1c2c40;color:#8fc0ff}\n  .cand .orig.membro{background:#3a2d12;color:#F4C400}\n  .cand .pick{font-size:11px;font-weight:700;padding:3px 8px;border-radius:999px;background:#F4C400;color:#000;white-space:nowrap}\n  `,\n  render(d2){\n    const st=d2.state; const results=st.results||[];\n    const qsafe=(st.q||'').replace(/</g,'&lt;');\n    let body;\n    if(st.loading) body=`<div class=\"empty\">Buscando…</div>`;\n    else if(st.err) body=`<div class=\"empty\" style=\"color:#ffce7a\">⚠ ${st.err}</div>`;\n    else if(!st.q) body=`<div class=\"empty\">Comece digitando um nome, número de comanda, telefone ou CPF.</div>`;\n    else if(!results.length) body=`<div class=\"empty\">Nada encontrado para “${qsafe}”.</div>`;\n    else body=`<div class=\"res\">${results.map(r=> d2.render(d2.param('card'),{record:r,reservas:(d2.state._res||d2.param('reservas')||[])},{key:r.__key||r._id||r.codTerceiro, onCheckin:(p)=>d2.state._ck=p})).join('')}</div>`;\n    return `<div class=\"wrap\">\n      <input class=\"q big\" inputmode=\"search\" placeholder=\"Nome, nº da comanda, telefone ou CPF\" autocomplete=\"off\" value=\"${(st.q||'').replace(/\"/g,'&quot;')}\">\n      <div class=\"hint\">Busca unificada: membros · reservas de hoje · entrada · clientes Cloudfy (nome/nº/CPF).</div>\n      <button class=\"walk blockbtn\">＋ Cadastrar na hora</button>\n      ${body}\n      <dialog class=\"dlg\">${this.dialogBody(d2,st)}</dialog>\n    </div>`;\n  },\n  dialogBody(d2,st){\n    const esc = s => String(s==null?'':s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));\n    const errBox = st.walkErr?`<div style=\"color:#ffce7a;font-size:13px\">⚠ ${esc(st.walkErr)}</div>`:'';\n    if(st.walkStage==='match'){\n      const cands=st.walkCandidates||[];\n      const rows=cands.map((c,i)=>{\n        const cls = c.__orig==='cloudfy'?'cfy':(c.__orig==='membro'?'membro':'');\n        const lbl = c.__orig==='cloudfy'?'Cloudfy':(c.__orig==='membro'?'Membro':'Lista');\n        const cod = c.codTerceiro?('nº '+esc(c.codTerceiro)):'';\n        const nr = (c.nrPessoa!=null&&c.nrPessoa!=='')?('NrPessoa '+esc(c.nrPessoa)):'';\n        const tel = c.telefone?esc(c.telefone):'';\n        const meta=[cod,nr,tel].filter(Boolean).join(' · ');\n        return `<button class=\"cand\" data-i=\"${i}\"><span class=\"orig ${cls}\">${lbl}</span>\n          <span class=\"cg\"><span class=\"cn\">${esc(c.nome)}</span><span class=\"cm\">${meta}</span></span>\n          <span class=\"pick\">Selecionar</span></button>`;\n      }).join('');\n      return `<div class=\"dh\">Já existe? Selecione</div>\n        <div class=\"db\">\n          <div class=\"mlead\">Encontramos cadastros que podem ser a mesma pessoa</div>\n          <div class=\"msub\">Selecione para registrar a entrada sem duplicar no Cloudfy, ou crie um novo cadastro.</div>\n          ${rows||'<div class=\"msub\">Nenhum candidato.</div>'}\n          ${errBox}\n        </div>\n        <div class=\"df\"><button class=\"btn w-back\">Voltar</button><button class=\"btn acc w-createnew\">Criar novo</button></div>`;\n    }\n    return `<div class=\"dh\">Cadastrar na hora</div>\n        <div class=\"db\"><input class=\"w-nome\" placeholder=\"Nome*\"><input class=\"w-tel\" placeholder=\"Telefone (opcional)\"><input class=\"w-cpf\" placeholder=\"CPF (opcional)\"><input class=\"w-pax\" inputmode=\"numeric\" placeholder=\"Pax (opcional)\"><input class=\"w-obs\" placeholder=\"Observação (opcional)\">${errBox}</div>\n        <div class=\"df\"><button class=\"btn w-cancel\">Cancelar</button><button class=\"btn acc w-save\">${st.walkBusy?'Verificando…':'Continuar'}</button></div>`;\n  },\n  mounted(d2){\n    const KEY={authorization:'sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'};\n    const VENUE='69fcd30c55153376bd62ca81';\n    const ACTOR='6a3d1f42b40a901a4bd7c45b';\n    const digits=s=>String(s==null?'':s).replace(/\\D/g,'');\n    const tail=s=>{ let d=digits(s); if(d.length>11 && d.slice(0,2)==='55') d=d.slice(2); return d.slice(-10); };\n    const unwrap=r=>{ let d=r&&r.data!==undefined?r.data:r; if(d&&d.data!==undefined)d=d.data; return d; };\n\n    // ---- members: load once, filter client-side ----\n    let MEMBERS=[];\n    const loadMembers=async()=>{ try{ const r=await d2.rush('list-members').invoke({},{headers:KEY}); const d=unwrap(r); MEMBERS=(d&&d.members)||[]; }catch(e){ d2.log('members err',e); MEMBERS=[]; } };\n    loadMembers();\n    // ---- ALL Cloudfy clients: load once (~1022), search by name client-side (Cloudfy has no name filter) ----\n    let CLIENTS=[];\n    const loadClients=async()=>{ try{ const r=await d2.rush('proxy-cliente').invoke({NrPessoa:'',CodigoTerceiro:'',TpPessoa:'',CpfCnpj:'',Documento:'',Situacao:'1'},{headers:KEY}); const d=unwrap(r); CLIENTS=(d&&d.DadosCliente)||[]; d2.state._cliCount=CLIENTS.length; }catch(e){ d2.log('clients err',e); CLIENTS=[]; } };\n    loadClients();\n    // ---- today's TAGME reservations: load locally (parent param arrives stale at mount) ----\n    let RES=[];\n    const loadRes=async()=>{ try{ const now=new Date(); const path=`/Reservation/List/${VENUE}/${now.getFullYear()}/${now.getMonth()+1}/${now.getDate()}?isArray=true`; const r=await d2.rush('tagme-read').invoke({path},{headers:KEY}); const arr=unwrap(r); RES=Array.isArray(arr)?arr:[]; d2.state._res=RES; if(d2.state.q) doSearch(d2.state.q); }catch(e){ d2.log('res err',e); RES=[]; } };\n    loadRes();\n\n    const seatReserva=async(r)=>{\n      if(!r||!r._id) return;\n      if(r.status==='Seated'||r.status==='Canceled') return;\n      try{\n        await d2.rush(d2.params.tagmeWrite).invoke({ path:`/Reservation/${VENUE}/${r._id}/Seat`, method:'PUT', payload:{ table:null, note:'', vouchers:[], logs:{ user:ACTOR, actionType:'Seat' }, originalReservationData:r } },{headers:KEY});\n        r.status='Seated';\n      }catch(e){ d2.log('seat err',e); }\n    };\n    // TAGME WalkIn — only with a REAL phone (TAGME upserts customer BY PHONE); name-only allowed when no phone.\n    const tagmeWalkIn=async(p)=>{\n      try{\n        const phoneDigits=digits(p.telefone);\n        const customer={ name:p.nome||'' };\n        if(phoneDigits.length>=10) customer.phone = phoneDigits.slice(0,2)==='55'?phoneDigits:('55'+phoneDigits);\n        if(p.email) customer.email=p.email;\n        const payload={ partySize:(parseInt(p.pax,10)||1), customer, note:'Walk-in via Painel', origin:{label:'Restaurant'}, vouchers:[], state:null, city:null, venue:VENUE };\n        const r=await d2.rush(d2.params.tagmeWrite).invoke({ path:`/WalkIn/${VENUE}`, method:'POST', payload },{headers:KEY});\n        return unwrap(r);\n      }catch(e){ d2.log('walkin err',e); return null; }\n    };\n\n    // ---- normalize helpers ----\n    const normMember=m=>({ __orig:'membro', __key:'m_'+(m._id||m.member_code), _id:m._id, nome:m.nome_completo||m.nome, cpf:m.cpf, telefone:m.telefone, member_code:m.member_code, codTerceiro:null, nrPessoa:null, checkin:null });\n    const normClient=c=>({ __orig:'cliente', __key:'cf_'+(c.NrPessoa||c.CpfCnpj||c.Nome), _id:null, nome:c.Nome, cpf:c.CpfCnpj, telefone:((c.DDDTelefone||'')+''+(c.Telefone||'')), member_code:null, codTerceiro:null, nrPessoa:c.NrPessoa, checkin:null });\n    const normReserva=r=>{ const c=r.customer||{}; const nm=[c.name,c.lastName].filter(Boolean).join(' ')||'—'; return { __orig:'reserva', __key:'r_'+r._id, _id:r._id, nome:nm, telefone:c.phone, cpf:null, __reserva:r }; };\n    const normLocal=x=>{ const orig=(x.status==='cloudfy')?'cliente':'entrada'; return Object.assign({},x,{ __orig:orig, __key:(orig==='cliente'?'c_':'e_')+(x.codTerceiro||x._id||x.nome) }); };\n\n    const matchesQuery=(name,q)=>{ name=(name||'').toLowerCase(); q=q.toLowerCase(); return name.indexOf(q)>=0; };\n\n    // dedupe & combine: person (entrada/cliente/membro) absorbs matching reserva; show combined badges.\n    const mergeResults=(local,clientes,members,reservas,q)=>{\n      const out=[]; const byTail={}; const byCpf={}; const byCod={};\n      const idx=(p)=>{ const t=tail(p.telefone); const cpf=digits(p.cpf); const cod=p.codTerceiro?String(p.codTerceiro):'';\n        let hit=null;\n        if(t&&t.length>=8&&byTail[t]) hit=byTail[t];\n        else if(cpf&&cpf.length>=11&&byCpf[cpf]) hit=byCpf[cpf];\n        else if(cod&&byCod[cod]) hit=byCod[cod];\n        return hit; };\n      const register=(p)=>{ const t=tail(p.telefone); const cpf=digits(p.cpf); const cod=p.codTerceiro?String(p.codTerceiro):'';\n        if(t&&t.length>=8) byTail[t]=p; if(cpf&&cpf.length>=11) byCpf[cpf]=p; if(cod) byCod[cod]=p; };\n      const add=(p)=>{ const hit=idx(p);\n        if(hit){\n          // combine origin badges; keep richest record (person over reserva)\n          hit.__origs=hit.__origs||[hit.__orig];\n          if(hit.__origs.indexOf(p.__orig)<0) hit.__origs.push(p.__orig);\n          if(p.__orig==='reserva'&&!hit.__reserva) hit.__reserva=p.__reserva;\n          // fill missing identity fields\n          ['cpf','telefone','member_code','codTerceiro','nrPessoa','nome'].forEach(k=>{ if((hit[k]==null||hit[k]==='')&&p[k]!=null&&p[k]!=='') hit[k]=p[k]; });\n          register(hit);\n          return;\n        }\n        p.__origs=[p.__orig]; out.push(p); register(p);\n      };\n      // order: persons first (entrada/cliente), then members, then reservations (so reservas merge into persons when phone matches)\n      local.forEach(x=>add(normLocal(x)));\n      clientes.forEach(c=>add(c));\n      members.forEach(m=>add(normMember(m)));\n      reservas.forEach(r=>add(normReserva(r)));\n      out.sort((a,b)=>{ const ar=((a.__reserva||(a.__origs&&a.__origs.indexOf('reserva')>=0))?0:1); const br=((b.__reserva||(b.__origs&&b.__origs.indexOf('reserva')>=0))?0:1); return ar-br; });\n      return out;\n    };\n\n    let qT;\n    const doSearch=async(q)=>{ q=(q||'').trim(); d2.state.q=q; if(!q){d2.state.results=[];d2.state.err=null;return;}\n      d2.state.loading=true; d2.state.err=null;\n      try{\n        const qDigits=digits(q);\n        // 1) local + cloudfy fallback (proven listener)\n        let local=[];\n        try{ const r=await d2.rush(d2.params.buscar).invoke({q},{headers:KEY}); const d=unwrap(r); local=(d&&d.resultados)||[]; }catch(e){ d2.log('busca err',e); }\n        // 2) members (client-side filter by name or member_code)\n        const members=(MEMBERS||[]).filter(m=> matchesQuery(m.nome_completo||m.nome,q) || (m.member_code&&String(m.member_code).indexOf(q)>=0) || (qDigits.length>=8 && tail(m.telefone)===tail(qDigits)));\n        // 3) today's reservations (exclude Canceled), match name or phone\n        const reservas=(RES||[]).filter(r=>{ if(!r||r.status==='Canceled')return false; const c=r.customer||{}; const nm=[c.name,c.lastName].filter(Boolean).join(' '); return matchesQuery(nm,q) || (qDigits.length>=8 && tail(c.phone)===tail(qDigits)); });\n        const clientes=(CLIENTS||[]).filter(c=> matchesQuery(c.Nome,q) || (qDigits.length>=11 && digits(c.CpfCnpj)===qDigits) || (qDigits.length>0 && String(c.NrPessoa)===qDigits) ).slice(0,40).map(normClient);\n        d2.state.results = mergeResults(local,clientes,members,reservas,q);\n      }\n      catch(e){ d2.log('merge err',e); d2.state.results=[]; d2.state.err='Erro na busca. Tente de novo.'; } finally{ d2.state.loading=false; } };\n    d2.on('.q','input',(e,el)=>{ clearTimeout(qT); const v=el.value; qT=setTimeout(()=>doSearch(v),240); });\n    d2.on('.q','keydown',(e,el)=>{ if(e.key==='Enter'){ clearTimeout(qT); doSearch(el.value); } });\n\n    let lastCk=null;\n    const ckLoop=setInterval(async()=>{ const p=d2.state._ck; if(p&&p!==lastCk){ lastCk=p; d2.state._ck=null;\n      try{\n        if(p.reservaOnly){ if(p.reserva) await seatReserva(p.reserva); doSearch(d2.state.q); return; }\n        // DUAL WRITE on ENTROU: Cloudfy entry (entrada-checkin) + TAGME WalkIn\n        await d2.rush(d2.params.checkin).invoke({codTerceiro:p.codTerceiro,desfazer:p.desfazer},{headers:KEY});\n        if(!p.desfazer){\n          await tagmeWalkIn({nome:p.nome,telefone:p.telefone,pax:p.pax});\n          if(p.reserva) await seatReserva(p.reserva);\n        }\n        doSearch(d2.state.q);\n      }catch(e){d2.log(e);} } },300);\n    d2.onUnmount(()=>clearInterval(ckLoop));\n\n    d2.on('.walk','click',()=>{ d2.state.walkErr=null; d2.state.walkStage='form'; d2.state.walkCandidates=[]; d2.state.walkPessoa=null; d2.state.walkBusy=false; const dlg=d2.$('.dlg'); if(dlg&&dlg.showModal)dlg.showModal(); });\n    d2.on('.w-cancel','click',()=>{ const dlg=d2.$('.dlg'); if(dlg)dlg.close(); });\n    d2.on('.w-back','click',()=>{ d2.state.walkStage='form'; d2.state.walkErr=null; });\n\n    const dedupeCands=(arr)=>{ const seen={}; const out=[]; (arr||[]).forEach(c=>{ if(!c)return; const k=(c.codTerceiro||'')+'|'+(c.nrPessoa==null?'':c.nrPessoa)+'|'+((c.nome||'').toUpperCase()); if(seen[k])return; seen[k]=1; out.push(c); }); return out; };\n    const searchBy=async(q)=>{ q=(q||'').trim(); if(!q)return []; try{ const r=await d2.rush(d2.params.buscar).invoke({q},{headers:KEY}); const d=unwrap(r); return (d&&d.resultados)||[]; }catch(e){ d2.log('coinc err',e); return []; } };\n\n    d2.on('.w-save','click',async()=>{\n      if(d2.state.walkBusy)return;\n      const nome=((d2.$('.w-nome')||{}).value||'').trim(); if(!nome){ d2.state.walkErr='Informe o nome.'; return; }\n      const pessoa={nome,telefone:(d2.$('.w-tel')||{}).value||'',cpf:(d2.$('.w-cpf')||{}).value||'',pax:(d2.$('.w-pax')||{}).value||'',obs:(d2.$('.w-obs')||{}).value||''};\n      d2.state.walkPessoa=pessoa; d2.state.walkErr=null; d2.state.walkBusy=true;\n      try{\n        const telDigits=digits(pessoa.telefone);\n        const queries=[nome]; if(telDigits.length>=8) queries.push(telDigits);\n        const lists=await Promise.all(queries.map(searchBy));\n        let cands=dedupeCands([].concat.apply([],lists));\n        cands.forEach(c=>{ c.__orig = (c.status==='cloudfy')?'cloudfy':'local'; });\n        // also surface member matches by name\n        const memHits=(MEMBERS||[]).filter(m=>matchesQuery(m.nome_completo||m.nome,nome)).map(m=>({nome:m.nome_completo||m.nome,cpf:m.cpf,telefone:m.telefone,nrPessoa:null,codTerceiro:null,__orig:'membro'}));\n        cands=dedupeCands(cands.concat(memHits));\n        d2.state.walkCandidates=cands;\n        if(cands.length){ d2.state.walkStage='match'; }\n        else { await doCreate(pessoa,null); }\n      }catch(e){ d2.log('coincidencia err',e); d2.state.walkErr='Erro ao verificar duplicados. Tente de novo.'; }\n      finally{ d2.state.walkBusy=false; }\n    });\n    d2.on('.cand','click',async(e,el)=>{\n      const i=parseInt(el.dataset.i,10); const cands=d2.state.walkCandidates||[]; const c=cands[i]; const pessoa=d2.state.walkPessoa; if(!c||!pessoa)return;\n      const selected = (c.nrPessoa!=null&&c.nrPessoa!=='') ? {nrPessoa:c.nrPessoa,codTerceiro:c.codTerceiro,cpf:c.cpf,nome:c.nome} : null;\n      await doCreate(pessoa,selected);\n    });\n    d2.on('.w-createnew','click',async()=>{ const pessoa=d2.state.walkPessoa; if(!pessoa)return; await doCreate(pessoa,null); });\n    async function doCreate(pessoa,selected){\n      d2.state.walkErr=null;\n      try{\n        const payload=selected?{pessoa,selected}:{pessoa};\n        const r=await d2.rush(d2.params.cadastrar).invoke(payload,{headers:KEY}); const d=unwrap(r);\n        // DUAL WRITE: TAGME WalkIn (real phone only / name-only)\n        await tagmeWalkIn(pessoa);\n        const dlg=d2.$('.dlg'); if(dlg)dlg.close(); d2.state.walkStage='form'; d2.state.walkCandidates=[]; d2.state.walkPessoa=null;\n        const cod=(d&&d.result&&d.result.codTerceiro)||(d&&d.codUsed); if(cod){ const qel=d2.$('.q'); if(qel)qel.value=String(cod); doSearch(String(cod)); } else { doSearch(d2.state.q); }\n      }catch(e){ d2.log('cadastrar err',e); d2.state.walkErr='Não foi possível cadastrar. Tente novamente.'; }\n    }\n  }\n}"}},"buscar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"buscar"}}}},"cadastrar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cadastrar"}}}},"checkin":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"checkin"}}}},"card":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"card"}}}},"reservas":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"reservas"}}}},"tagmeWrite":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tagmeWrite"}}}}}}}}}},{"_id":"6a330f0f926d2ad8226386f1","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"EntradaList","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .wrap{font-family:-apple-system,system-ui,sans-serif;color:#f4f4f5}\n  .toolbar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:10px}\n  .chip{padding:8px 13px;border-radius:999px;background:#141417;border:1px solid #2a2a31;color:#8b8b94;font-size:13px;font-weight:600;cursor:pointer}\n  .chip.on{background:#F4C400;color:#000;border-color:#F4C400}\n  .spacer{flex:1}\n  .csv{border:0;border-radius:12px;padding:8px 14px;font-size:14px;font-weight:700;background:#1c1c21;color:#f4f4f5;cursor:pointer}\n  .lq{width:100%;box-sizing:border-box;background:#141417;border:1px solid #2a2a31;color:#f4f4f5;border-radius:12px;padding:13px;font-size:16px;outline:none;margin-bottom:10px}\n  .lq:focus{border-color:#F4C400}\n  table{width:100%;border-collapse:collapse;font-size:14px}\n  th,td{text-align:left;padding:10px 8px;border-bottom:1px solid #2a2a31}\n  th{color:#8b8b94;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.4px}\n  td .n{font-weight:800;font-variant-numeric:tabular-nums}\n  .tag{font-size:11px;font-weight:700;padding:3px 8px;border-radius:999px;background:#1c1c21;color:#8b8b94}\n  .tag.in{background:#143524;color:#7ee2a8}.tag.canc{background:#2a2a31;color:#ffce7a}.tag.obs{background:#332a12;color:#ffce7a}\n  .muted{color:#8b8b94}\n  .btn{border:0;border-radius:10px;padding:8px 12px;font-size:13px;font-weight:700;background:#1c1c21;color:#f4f4f5;cursor:pointer}\n  .btn.ok{background:#F4C400;color:#000}\n  .empty{text-align:center;color:#8b8b94;padding:40px 12px}\n  `,\n  render(d2){\n    const st=d2.state; const esc=s=>String(s==null?'':s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));\n    const lista=st.lista||[]; const fH=st.fH||''; const fIn=!!st.fIn; const q=(st.lq||'').trim().toLowerCase();\n    let l=lista.filter(e=>(!fH||(e.horarios||[]).includes(fH))&&(!fIn||e.checkin)&&(!q||(e.nome||'').toLowerCase().includes(q)||String(e.codTerceiro).includes(q)));\n    const chips=['','12:00','14:00','18:00','20:00'];\n    const chipLbl={'':'Todos','12:00':'12h','14:00':'14h','18:00':'18h','20:00':'20h'};\n    const toolbar=`<div class=\"toolbar\">${chips.map(c=>`<span class=\"chip ${fH===c?'on':''}\" data-h=\"${c}\">${chipLbl[c]}</span>`).join('')}<span class=\"spacer\"></span><span class=\"chip ${fIn?'on':''}\" data-in=\"1\">Só quem entrou</span><button class=\"csv\">⬇︎ CSV</button></div>`;\n    const search=`<input class=\"lq\" placeholder=\"filtrar por nome/nº…\" value=\"${esc(st.lq||'')}\">`;\n    let tbl;\n    if(st.loading) tbl=`<div class=\"empty\">Carregando lista…</div>`;\n    else if(st.err) tbl=`<div class=\"empty\" style=\"color:#ffce7a\">⚠ ${esc(st.err)}</div>`;\n    else if(!l.length) tbl=`<div class=\"empty\">${(st.lista||[]).length?'Nenhum registro com esse filtro.':'Nenhum registro.'}</div>`;\n    else tbl=`<table><thead><tr><th>Nº</th><th>Nome</th><th>Hora</th><th></th><th></th></tr></thead><tbody>`+l.map(e=>`<tr data-key=\"${esc(e.codTerceiro)}\"><td><span class=\"n\">${esc(e.codTerceiro)}</span></td><td>${esc(e.nome)}${e.reservaStatus==='cancelado'?' <span class=\"tag canc\">CANC</span>':''}${e.obs?' <span class=\"tag obs\">!</span>':''}</td><td class=\"muted\">${(e.horarios||[]).join('/')}</td><td>${e.checkin?'<span class=\"tag in\">✓</span>':''}</td><td>${e.checkin?`<button class=\"btn\" data-undo=\"${esc(e.codTerceiro)}\">↺</button>`:`<button class=\"btn ok\" data-ck=\"${esc(e.codTerceiro)}\">ENTROU</button>`}</td></tr>`).join('')+`</tbody></table>`;\n    return `<div class=\"wrap\">${toolbar}${search}${tbl}</div>`;\n  },\n  mounted(d2){\n    const KEY={authorization:'sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'};\n    const load=async()=>{ d2.state.loading=true; d2.state.err=null; try{ const r=await d2.rush(d2.params.lista).invoke({},{headers:KEY}); const d=r&&r.data!==undefined?r.data:r; d2.state.lista=(d&&d.entradas)||[]; d2.state.total=d&&d.total; d2.state.entrados=d&&d.entrados; d2.emit('onStats',{total:d&&d.total,entrados:d&&d.entrados}); }catch(e){d2.log('lista err',e); d2.state.err='Erro ao carregar a lista. Tente de novo.';}finally{d2.state.loading=false;} };\n    load();\n    d2.on('.chip','click',(e,el)=>{ if(el.dataset.in){ d2.state.fIn=!d2.state.fIn; } else { d2.state.fH=el.dataset.h; } });\n    d2.on('.lq','input',(e,el)=>{ d2.state.lq=el.value; });\n    const ck=async(cod,undo)=>{ try{ await d2.rush(d2.params.checkin).invoke({codTerceiro:cod,desfazer:undo},{headers:KEY}); load(); }catch(e){d2.log(e);} };\n    d2.on('[data-ck]','click',(e,el)=>ck(el.dataset.ck,false));\n    d2.on('[data-undo]','click',(e,el)=>ck(el.dataset.undo,true));\n    d2.on('.csv','click',async()=>{ try{ const r=await d2.rush(d2.params.exportar).invoke({},{headers:KEY}); const d=r&&r.data!==undefined?r.data:r; const csv=(d&&d.csv)||''; const blob=new Blob([csv],{type:'text/csv'}); const a=document.createElement('a'); a.href=URL.createObjectURL(blob); a.download='entrada.csv'; a.click(); }catch(e){d2.log('csv err',e); if(d2.dialog&&d2.dialog.alert)d2.dialog.alert('Não foi possível exportar o CSV agora.');} });\n  }\n}"}},"lista":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"lista"}}}},"checkin":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"checkin"}}}},"exportar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"exportar"}}}}}}}}}},{"_id":"6a330f109f6e1c72479eb65c","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"ImportPanel","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .wrap{font-family:-apple-system,system-ui,sans-serif;color:#f4f4f5}\n  .hint{color:#8b8b94;font-size:13px;margin:6px 2px}\n  textarea{width:100%;box-sizing:border-box;background:#141417;border:1px solid #2a2a31;color:#f4f4f5;border-radius:12px;padding:14px;min-height:160px;font-size:15px;font-family:ui-monospace,Menlo,monospace;outline:none}\n  textarea:focus{border-color:#F4C400}\n  .rowb{display:flex;gap:10px;margin-top:10px}\n  .btn{flex:1;border:0;border-radius:12px;padding:14px;font-size:16px;font-weight:700;background:#1c1c21;color:#f4f4f5;cursor:pointer}\n  .btn.acc{background:#F4C400;color:#000}.btn:disabled{opacity:.4}\n  table{width:100%;border-collapse:collapse;font-size:14px;margin-top:12px}\n  th,td{text-align:left;padding:9px 8px;border-bottom:1px solid #2a2a31}\n  th{color:#8b8b94;font-size:12px;text-transform:uppercase}\n  .n{font-weight:800}\n  .tag{font-size:11px;font-weight:700;padding:3px 8px;border-radius:999px}\n  .tag.new{background:#143524;color:#7ee2a8}.tag.dup{background:#2a2a31;color:#ffce7a}\n  .empty{text-align:center;color:#8b8b94;padding:24px}\n  `,\n  render(d2){\n    const st=d2.state; const esc=s=>String(s==null?'':s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));\n    const prev=st.preview||null; let pv='';\n    if(prev){ if(!prev.length) pv=`<div class=\"empty\">Não entendi nenhuma pessoa.</div>`;\n      else pv=`<div class=\"hint\">${prev.length} pessoa(s) · ${prev.filter(p=>!p.jaExiste).length} novo(s)</div><table><thead><tr><th>Nome</th><th>CPF</th><th>Tel</th><th>Situação</th></tr></thead><tbody>`+prev.map(p=>`<tr><td>${esc(p.nome)||'?'}</td><td class=\"muted\">${esc(p.cpf)||'—'}</td><td class=\"muted\">${esc(p.telefone)||'—'}</td><td><span class=\"tag ${p.jaExiste?'dup':'new'}\">${esc(p.situacao)}</span></td></tr>`).join('')+`</tbody></table>`; }\n    let resu='';\n    if(st.err) resu=`<div class=\"hint\" style=\"color:#ffce7a\">⚠ ${esc(st.err)}</div>`;\n    else if(st.previewing) resu=`<div class=\"hint\">Analisando lista…</div>`;\n    else if(st.resumo) resu=`<div class=\"hint\" style=\"color:#7ee2a8\">✓ Resumo: ${Object.entries(st.resumo).map(([k,v])=>k+'='+v).join(' · ')}</div>`;\n    return `<div class=\"wrap\"><div class=\"hint\">Cole a lista (uma pessoa por linha). Aceita nome, CPF, telefone, e-mail em qualquer ordem.</div>\n      <textarea class=\"imp\" placeholder=\"João da Silva, 123.456.789-00, (11) 99999-8888\">${esc(st.text||'')}</textarea>\n      <div class=\"rowb\"><button class=\"btn prev\">Pré-visualizar</button><button class=\"btn acc imp-all\" ${(!prev||!prev.length||st.importing)?'disabled':''}>${st.importing?'Cadastrando…':'Cadastrar todos'}</button></div>\n      ${resu}${pv}</div>`;\n  },\n  mounted(d2){\n    const KEY={authorization:'sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'};\n    const onlyDigits=s=>String(s||'').replace(/\\D/g,'');\n    const isValidCPF=cpf=>{ cpf=onlyDigits(cpf); if(cpf.length!==11||/^(\\d)\\1{10}$/.test(cpf))return false; let s=0; for(let i=0;i<9;i++)s+=+cpf[i]*(10-i); let d1=11-s%11; if(d1>=10)d1=0; if(d1!==+cpf[9])return false; s=0; for(let i=0;i<10;i++)s+=+cpf[i]*(11-i); let d2v=11-s%11; if(d2v>=10)d2v=0; return d2v===+cpf[10]; };\n    const normName=s=>String(s||'').trim().replace(/\\s+/g,' ').toUpperCase();\n    const EMAIL=/[\\w.+-]+@[\\w.-]+\\.[a-z]{2,}/i;\n    function parseLinha(linha){ const raw=linha.trim(); if(!raw)return null; let rest=raw; let email='',cpf='',telefone='';\n      const em=rest.match(EMAIL); if(em){email=em[0]; rest=rest.replace(em[0],' ');}\n      const cpfm=rest.match(/\\d[\\d.\\-\\/\\s]{9,}\\d/g)||[];\n      for(const cand of cpfm){ const dig=onlyDigits(cand); if(dig.length===11&&isValidCPF(dig)){cpf=dig; rest=rest.replace(cand,' '); break;} }\n      const telm=rest.match(/\\(?\\d{2}\\)?\\s?\\d{4,5}-?\\d{4}/); if(telm){telefone=onlyDigits(telm[0]); rest=rest.replace(telm[0],' ');}\n      let nome=normName(rest.replace(/[,;|]+/g,' ').replace(/\\d+/g,' ')); \n      return {nome,cpf,telefone,email}; }\n    let existing=[];\n    const loadExisting=async()=>{ try{ const r=await d2.rush(d2.params.lista).invoke({},{headers:KEY}); const d=r&&r.data!==undefined?r.data:r; existing=(d&&d.entradas)||[]; }catch(e){d2.log('load existing err',e); existing=[]; throw e;} return existing; };\n    d2.on('.imp','input',(e,el)=>{ d2.state.text=el.value; });\n    d2.on('.prev','click',async()=>{ const txt=(d2.$('.imp')||{}).value||d2.state.text||''; if(!txt.trim())return;\n      d2.state.previewing=true; d2.state.err=null; d2.state.resumo=null;\n      try{ await loadExisting(); const existCpf=new Set(existing.map(x=>x.cpf).filter(Boolean)); const existNome=new Set(existing.map(x=>normName(x.nome)));\n      const ppl=txt.split(/\\n/).map(parseLinha).filter(Boolean).map(p=>{ const jaExiste=(p.cpf&&existCpf.has(p.cpf))||(p.nome&&existNome.has(p.nome)); return {...p,jaExiste,situacao:jaExiste?'Já existe':'Novo'}; });\n      d2.state.preview=ppl; }\n      catch(e){ d2.state.err='Erro ao verificar duplicados. Tente de novo.'; }\n      finally{ d2.state.previewing=false; } });\n    d2.on('.imp-all','click',async()=>{ const prev=d2.state.preview||[]; if(!prev.length)return; d2.state.importing=true; d2.state.err=null;\n      try{ await loadExisting(); }catch(e){ d2.state.err='Erro ao validar a lista. Tente de novo.'; d2.state.importing=false; return; }\n      let nextCod=Math.max(22000,...existing.map(x=>+x.codTerceiro||0))+1; if(!isFinite(nextCod)||nextCod<22001)nextCod=22001;\n      const resumo={novo:0,jaExiste:0,erro:0};\n      for(const p of prev){ if(p.jaExiste){resumo.jaExiste++; continue;} try{ const r=await d2.rush(d2.params.cadastrar).invoke({pessoa:p,nextCod},{headers:KEY}); const d=r&&r.data!==undefined?r.data:r; const used=(d&&d.codUsed)||nextCod; nextCod=(+used||nextCod)+1; resumo.novo++; }catch(e){resumo.erro++;} }\n      d2.state.resumo=resumo; d2.state.importing=false; d2.state.preview=null; d2.state.text=''; const ta=d2.$('.imp'); if(ta)ta.value=''; });\n  }\n}"}},"lista":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"lista"}}}},"cadastrar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cadastrar"}}}}}}}}}},{"_id":"6a330f5b926d2ad8226387a6","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"CatalogoScreen","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .scr{height:100%;overflow:auto;background:#0a0a0a;font-family:'Inter',system-ui,sans-serif;color:#fff;box-sizing:border-box}\n  .head{display:flex;align-items:center;gap:14px;padding:28px 36px 18px}\n  .head h2{font-family:'Anton',sans-serif;font-size:22px;letter-spacing:.08em;text-transform:uppercase;margin:0}\n  .bar{flex:1;height:1px;background:#2a2a2a}\n  .tabs{display:flex;gap:8px}\n  .tab{background:transparent;border:1px solid #2a2a2a;color:#9a9a9a;padding:8px 16px;font-size:12px;letter-spacing:.12em;font-weight:600;cursor:pointer;text-transform:uppercase;border-radius:3px}\n  .tab.on{background:#F4C400;color:#000;border-color:#F4C400}\n  .stats{display:flex;gap:14px;flex-wrap:wrap;padding:0 36px 6px}\n  .stat{background:#141414;border:1px solid #2a2a2a;border-left:3px solid #F4C400;padding:12px 20px;min-width:130px}\n  .stat .n{font-family:'Anton',sans-serif;font-size:26px;color:#F4C400}\n  .stat .l{font-size:9px;letter-spacing:.18em;color:#9a9a9a;text-transform:uppercase;margin-top:4px}\n  .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));grid-auto-rows:minmax(320px,auto);gap:20px;padding:24px 36px 50px}\n  .loading{padding:40px;color:#9a9a9a}\n  `,\n  render(d2){\n    const st=d2.state; const all=st.all||[]; const f=st.filter||'all';\n    const MEMBER_RE=/(member|founder|sócio|socio|plano|subscription|assinatura)/i;\n    const isMember=p=> MEMBER_RE.test([p.name,p.slug,(p.categories||[]).join(' ')].join(' '));\n    let list=all; if(f==='member')list=all.filter(isMember); if(f==='exp')list=all.filter(p=>!isMember(p));\n    if(st.loading) return `<div class=\"scr\"><div class=\"loading\">Carregando catálogo do site…</div></div>`;\n    if(st.err) return `<div class=\"scr\"><div class=\"loading\" style=\"color:#ffce7a\">⚠ ${st.err}<div style=\"margin-top:14px\"><button class=\"tab retry\" style=\"cursor:pointer\">↺ Tentar de novo</button></div></div></div>`;\n    const cfgDs=d2.data('config'); const cfgs=(cfgDs&&cfgDs.records())||[];\n    const byId=id=>cfgs.find(c=>String(c.product_id)===String(id));\n    const cards=list.map(p=> d2.render(d2.param('productCard'),{record:{...p,isMembership:isMember(p),savedConfig:byId(p.id)},config:cfgDs?cfgDs.raw||d2.params.config:d2.params.config},{key:p.id})).join('');\n    const stats=[[all.length,'Produtos'],[all.filter(isMember).length,'Memberships'],[cfgs.length,'Parametrizados'],[cfgs.filter(c=>c.synced).length,'Sincronizados']];\n    return `<div class=\"scr\">\n      <div class=\"head\"><h2>Catálogo</h2><div class=\"bar\"></div><div class=\"tabs\">\n        <button class=\"tab ${f==='all'?'on':''}\" data-f=\"all\">Tudo</button>\n        <button class=\"tab ${f==='member'?'on':''}\" data-f=\"member\">Memberships</button>\n        <button class=\"tab ${f==='exp'?'on':''}\" data-f=\"exp\">Experiências</button></div></div>\n      <div class=\"stats\">${stats.map(([n,l])=>`<div class=\"stat\"><div class=\"n\">${n}</div><div class=\"l\">${l}</div></div>`).join('')}</div>\n      <div class=\"grid\">${cards||'<div class=\"loading\">Nada por aqui.</div>'}</div></div>`;\n  },\n  mounted(d2){\n    const decode=s=>String(s||'').replace(/&amp;/g,'&').replace(/&#8211;/g,'–').replace(/&#038;/g,'&');\n    const KEY={authorization:'sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'};\n    const load=async()=>{ d2.state.loading=true; d2.state.err=null;\n      try{ const r=await d2.rush('proxy-products').invoke({},{headers:KEY}); const body=r&&r.data!==undefined?r.data:r; const arr=Array.isArray(body)?body:(body&&body.products)||[];\n        d2.state.all=arr.map(p=>({ id:p.id, name:decode(p.name), slug:p.slug, sku:p.sku, price:(p.prices&&(p.prices.price?('R$ '+(Number(p.prices.price)/Math.pow(10,p.prices.currency_minor_unit||2)).toLocaleString('pt-BR')):''))||(p.price_html||''), categories:(p.categories||[]).map(c=>c.name||c.slug||c), image:(p.images&&p.images[0]&&(p.images[0].thumbnail||p.images[0].src))||'' }));\n      }catch(e){ d2.log('woo err',e); d2.state.err='Erro ao carregar catálogo: '+e.message; } finally{ d2.state.loading=false; } };\n    load();\n    d2.on('.retry','click',()=>{ load(); });\n    d2.on('.tab','click',(e,el)=>{ if(el.dataset.f) d2.state.filter=el.dataset.f; });\n  }\n}"}},"woo":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"woo"}}}},"config":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"config"}}}},"productCard":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"productCard"}}}}}}}}}},{"_id":"6a330f5cec12023d1caffd95","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"EntradaScreen","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .scr{height:100%;display:flex;flex-direction:column;background:#0a0a0b;font-family:-apple-system,system-ui,sans-serif;color:#f4f4f5;box-sizing:border-box}\n  .top{position:sticky;top:0;z-index:5;background:rgba(10,10,11,.94);backdrop-filter:blur(10px);border-bottom:1px solid #2a2a31}\n  .barr{display:flex;align-items:center;justify-content:space-between;padding:16px 22px}\n  .brand{font-weight:700;letter-spacing:.5px;font-size:19px}.brand b{color:#F4C400}\n  .stat{font-size:14px;color:#8b8b94}.stat b{color:#f4f4f5;font-size:17px}\n  nav{display:flex;gap:8px;padding:0 16px 14px}\n  nav button{flex:1;max-width:200px;padding:13px;border:0;border-radius:12px;background:#141417;color:#8b8b94;font-size:15px;font-weight:600;cursor:pointer}\n  nav button.on{background:#F4C400;color:#000}\n  .body{flex:1;overflow:auto;max-width:780px;width:100%;margin:0 auto;padding:18px 16px 60px;box-sizing:border-box}\n  .pane{display:none}.pane.on{display:block}\n  `,\n  render(d2){\n    const st=d2.state; const v=st.view||'buscar';\n    return `<div class=\"scr\">\n      <div class=\"top\">\n        <div class=\"barr\"><div class=\"brand\">TEMPO <b>·</b> Entrada</div></div>\n        <nav><button class=\"${v==='buscar'?'on':''}\" data-v=\"buscar\">🔎 Buscar</button><button class=\"${v==='reservas'?'on':''}\" data-v=\"reservas\">📅 Reservas${st.reservas&&st.reservas.length?` <b style=\"opacity:.7\">${st.reservas.filter(r=>r&&r.status!=='Canceled').length}</b>`:''}</button></nav>\n      </div>\n      <div class=\"body\">\n        <div class=\"pane ${v==='buscar'?'on':''}\">${d2.render(d2.param('search'),{buscar:d2.params.buscar,cadastrar:d2.params.cadastrar,checkin:d2.params.checkin,card:d2.param('personCard'),reservas:st.reservas||[],tagmeWrite:d2.params.tagmeWrite},{key:'search',style:'min-height:200px'})}</div>\n        <div class=\"pane ${v==='reservas'?'on':''}\">${d2.render('adonis@ReservasScreen',{venueId:'69fcd30c55153376bd62ca81',tagmeRead:d2.params.tagmeRead,tagmeWrite:d2.params.tagmeWrite},{key:'reservas',style:'min-height:200px'})}</div>\n      </div></div>`;\n  },\n  mounted(d2){\n    const KEY={authorization:'sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'};\n    const stats=async()=>{ try{ const r=await d2.rush(d2.params.lista).invoke({},{headers:KEY}); const d=r&&r.data!==undefined?r.data:r; d2.state.total=d&&d.total; d2.state.entrados=d&&d.entrados; }catch(e){} };\n    stats();\n    const VENUE='69fcd30c55153376bd62ca81';\n    const unwrap=r=>{ let d=r&&r.data!==undefined?r.data:r; if(d&&d.data!==undefined)d=d.data; return d; };\n    const loadReservas=async()=>{ try{ const now=new Date(); const path=`/Reservation/List/${VENUE}/${now.getFullYear()}/${now.getMonth()+1}/${now.getDate()}?isArray=true`; const r=await d2.rush(d2.params.tagmeRead).invoke({path},{headers:KEY}); const arr=unwrap(r); d2.state.reservas=Array.isArray(arr)?arr:[]; }catch(e){ d2.log('reservas err',e); } };\n    loadReservas();\n    d2.on('nav button','click',(e,el)=>{ d2.state.view=el.dataset.v; });\n  }\n}"}},"search":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"search"}}}},"list":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"list"}}}},"importPanel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"importPanel"}}}},"buscar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"buscar"}}}},"cadastrar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cadastrar"}}}},"checkin":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"checkin"}}}},"lista":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"lista"}}}},"exportar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"exportar"}}}},"personCard":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"personCard"}}}},"entradaReservas":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"entradaReservas"}}}},"tagmeRead":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tagmeRead"}}}},"tagmeWrite":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tagmeWrite"}}}}}}}}}},{"_id":"6a33e235293ce144a47f2bef","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"PainelApp","package":"adonis","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 TAB_PATHS={inicio:'/inicio',catalogo:'/catalogo',membros:'/membros',clientes:'/clientes',reservas:'/reservas',entrada:'/entrada',agente:'/agente'};\nconst tabFromPath=()=>{ try{ const p=String(location.pathname||'').replace(/\\/+$/,''); if(!p) return null; const k=Object.keys(TAB_PATHS).find(x=>TAB_PATHS[x]===p); return k||null; }catch(e){ return null; } };\nconst pushTab=(t)=>{ try{ const p=TAB_PATHS[t]; if(p&&location.pathname!==p) history.pushState({},'',p); }catch(e){} };\n\nexport default {\n  css: `\n  .app{display:grid;grid-template-columns:280px 1fr;height:100%;width:100%;background:#0a0a0a;font-family:'Inter',system-ui,sans-serif;color:#fff;box-sizing:border-box}\n  .sb{background:#141414;border-right:1px solid #2a2a2a;display:flex;flex-direction:column;box-sizing:border-box;height:100%}\n  .sb .top{background:var(--acc,#F4C400);color:#000;padding:9px 20px;font-size:11px;letter-spacing:.14em;font-weight:700;text-transform:uppercase;display:flex;align-items:center;gap:8px}\n  .sb .dot{width:7px;height:7px;border-radius:50%;background:#000}\n  .sb .brand{padding:22px 20px 18px;border-bottom:1px solid #2a2a2a}\n  .sb .brand .w{font-family:'Anton',sans-serif;font-size:26px;letter-spacing:.04em;line-height:.85}\n  .sb .brand small{display:block;font-size:9px;letter-spacing:.4em;color:#9a9a9a;margin-top:6px;font-weight:600}\n  .sb .brand small b{color:#fff}\n  .sb .sec{padding:18px 20px 6px;font-size:9px;letter-spacing:.22em;color:#5a5a5a;font-weight:700;text-transform:uppercase}\n  .sb .nav{display:flex;flex-direction:column;gap:2px;padding:0 10px}\n  .nl{display:flex;align-items:center;gap:11px;padding:12px 14px;border-radius:8px;color:#9a9a9a;font-size:13px;letter-spacing:.1em;font-weight:700;text-transform:uppercase;cursor:pointer;transition:.13s;border-left:3px solid transparent}\n  .nl:hover{color:#fff;background:#1a1a1a}\n  .nl.on{color:var(--acc,#F4C400);background:#1a1a1a;border-left-color:var(--acc,#F4C400)}\n  .nl .ic{font-size:15px;width:18px;text-align:center}\n  .sb .grow{flex:1}\n  .sb .logout{display:flex;align-items:center;gap:11px;margin:0 10px 12px;padding:12px 14px;border-radius:8px;border:1px solid #2a2a2a;color:#7a7a7a;font-size:12px;letter-spacing:.1em;font-weight:700;text-transform:uppercase;cursor:pointer;transition:.13s;user-select:none}\n  .sb .logout:hover{color:#ff8a8a;border-color:#ff5a5a;background:#180f0f}\n  .sb .foot{padding:18px 20px;border-top:1px solid #2a2a2a;color:#4b5563;font-size:9px;letter-spacing:.2em;font-weight:600}\n  .content{height:100%;overflow:hidden;position:relative}\n  .lockscr{position:fixed;inset:0;z-index:99999;background:#0a0a0a;display:flex;align-items:center;justify-content:center;font-family:'Inter',system-ui,sans-serif}\n  .lockbox{width:340px;max-width:88vw;background:#141414;border:1px solid #2a2a2a;border-radius:16px;padding:34px 30px;text-align:center}\n  .lockbox .w{font-family:'Anton',sans-serif;font-size:34px;color:#fff;letter-spacing:.04em;line-height:.9}\n  .lockbox small{display:block;font-size:9px;letter-spacing:.4em;color:#9a9a9a;margin:6px 0 26px;font-weight:600}\n  .lockbox small b{color:#fff}\n  .lockbox .pwd{width:100%;box-sizing:border-box;background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;border-radius:10px;padding:13px 14px;font-size:15px;outline:none;text-align:center;letter-spacing:.1em}\n  .lockbox .pwd:focus{border-color:#F4C400}\n  .lockbox .eml{width:100%;box-sizing:border-box;background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;border-radius:10px;padding:13px 14px;font-size:15px;outline:none;text-align:center;letter-spacing:.06em;margin-bottom:10px}\n  .lockbox .eml:focus{border-color:#F4C400}\n  .lockbox .unlock{width:100%;margin-top:12px;background:#F4C400;color:#000;border:0;border-radius:10px;padding:13px;font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;cursor:pointer}\n  .lockbox .lerr{color:#cfcfcf;font-size:12px;margin-top:12px;min-height:14px}\n  `,\n  render(d2){\n    if(d2.state.unlocked===undefined){ try{ var _a=JSON.parse(localStorage.getItem('tempoAuth')||'null'); if(_a&&_a.user&&(Date.now()-(_a.ts||0)<2592000000)&&((_a.user.role==='admin')||(_a.user.apps&&_a.user.apps.indexOf('painel')>=0))){ d2.state.unlocked=true; d2.state.user=_a.user; } }catch(e){} }\n    if(!d2.state.unlocked){ return `<div class=\"lockscr\"><div class=\"lockbox\"><div class=\"w\">TEMPO</div><small>by <b>PORSCHE</b></small><input type=\"email\" class=\"eml\" placeholder=\"E-mail\" autocomplete=\"username\" value=\"${(d2.state.email||'').replace(/\"/g,'&quot;')}\"><input type=\"password\" class=\"pwd\" placeholder=\"Senha\" autocomplete=\"current-password\"><button class=\"unlock\">${d2.state.authLoading?'Entrando…':'Entrar'}</button><div class=\"lerr\">${d2.state.lockErr||''}</div></div></div>`; }\n    const base=d2.param('accent')||'#F4C400';\n    if(d2.state.tab===undefined){ d2.state.tab=tabFromPath()||'inicio'; }\n    const tab=d2.state.tab||'inicio';\n    const acc=base;\n    const items=[\n      {p:'inicio',ic:'⬚',t:'Início'},\n      {p:'catalogo',ic:'▦',t:'Catálogo'},\n      {p:'membros',ic:'◆',t:'Membros'},\n      {p:'clientes',ic:'●',t:'Clientes'},\n      {p:'reservas',ic:'◷',t:'Reservas'},\n      {p:'entrada',ic:'✓',t:'Entrada'},\n      {p:'agente',ic:'✦',t:'Agente'}\n    ];\n    let screen='';\n    if(tab==='inicio') screen=d2.render('adonis@DashboardScreen',{},{key:'inicio'});\n    else if(tab==='catalogo') screen=d2.render('adonis@CatalogoScreen',{config:d2.params.config,productCard:'adonis@ProductCard',woo:'proxy-products'},{key:'catalogo'});\n    else if(tab==='membros') screen=d2.render('adonis@MembrosScreen',{listMembers:'list-members',memberCard:'adonis@MemberCard'},{key:'membros'});\n    else if(tab==='clientes') screen=d2.render('adonis@ClientesScreen',{listar:'pessoas-listar',proxyCliente:'proxy-cliente',proxyVendas:'proxy-vendas',signup:'signup',clienteRow:'adonis@ClienteRow'},{key:'clientes'});\n    else if(tab==='reservas') screen=d2.render('adonis@ReservasScreen',{venueId:'69fcd30c55153376bd62ca81',tagmeRead:'tagme-read'},{key:'reservas'});\n    else if(tab==='entrada') screen=d2.render('adonis@EntradaScreen',{search:'adonis@EntradaSearch',buscar:'entrada-buscar',cadastrar:'entrada-cadastrar-um',checkin:'entrada-checkin',lista:'entrada-lista',personCard:'adonis@PersonCard',entradaReservas:'adonis@EntradaReservas',tagmeRead:'tagme-read',tagmeWrite:'tagme-write'},{key:'entrada'});\n    else if(tab==='agente') screen=d2.render('adonis@AgenteScreen',{assistant:'agente-tempo',buscarMembros:'list-members',buscarClientes:'proxy-cliente'},{key:'agente',onNavigate:(t)=>{ if(t){ d2.state.tab=t; pushTab(t); } }});\n    return `<div class=\"app\" style=\"--acc:${acc}\">\n      <div class=\"sb\">\n        <div class=\"top\"><span class=\"dot\"></span> Painel Interno</div>\n        <div class=\"brand\"><div class=\"w\">TEMPO</div><small>by <b>PORSCHE</b></small></div>\n        <div class=\"sec\">Gestão</div>\n        <div class=\"nav\">${items.map(i=>`<div class=\"nl ${tab===i.p?'on':''}\" data-p=\"${i.p}\"><span class=\"ic\">${i.ic}</span>${i.t}</div>`).join('')}</div>\n        <div class=\"grow\"></div>\n        <div class=\"logout\" title=\"Encerrar a sessão neste navegador\">← Sair</div>\n        <div class=\"foot\">v1.0 · BY PORSCHE</div>\n      </div>\n      <div class=\"content\">${screen}</div>\n    </div>`;\n  },\n  mounted(d2){\n    const AUTH=d2.params.authRush||'auth-login';\n    const tryUnlock=async()=>{\n      const em=d2.$('.eml'), pw=d2.$('.pwd');\n      const email=((em&&em.value)||'').trim(), password=((pw&&pw.value)||'');\n      if(!email||!password){ d2.state.lockErr='Informe e-mail e senha'; return; }\n      d2.state.email=email; d2.state.authLoading=true; d2.state.lockErr='';\n      try{\n        const r=await d2.rush(AUTH).invoke({email,password});\n        const d=r&&r.data!==undefined?r.data:r;\n        if(d&&d.ok){ var _ac=(d.user.role==='admin')||(d.user.apps&&d.user.apps.indexOf('painel')>=0); if(_ac){ d2.state.user=d.user; d2.state.unlocked=true; d2.state.lockErr=''; try{ localStorage.setItem('tempoAuth', JSON.stringify({user:d.user, ts:Date.now()})); }catch(e){} } else { d2.state.lockErr='Sem acesso ao Painel'; } }\n        else{ d2.state.lockErr=(d&&d.message)||'E-mail ou senha inválidos'; }\n      }catch(e){ d2.log('auth err',e); d2.state.lockErr='Erro de conexão. Tente de novo.'; }\n      finally{ d2.state.authLoading=false; }\n    };\n    d2.on('.unlock','click',()=>{ tryUnlock(); });\n    d2.on('.pwd','keydown',(e)=>{ if(e.key==='Enter'){ tryUnlock(); } });\n    d2.on('.eml','keydown',(e)=>{ if(e.key==='Enter'){ const pw=d2.$('.pwd'); if(pw) pw.focus(); } });\n    d2.on('.nl','click',(e,el)=>{ const t=el.dataset.p; d2.state.tab=t; pushTab(t); });\n    try{\n      window.__painelD2=d2;\n      if(!window.__painelPopBound){\n        window.__painelPopBound=true;\n        window.addEventListener('popstate',()=>{ const t=tabFromPath(); const dd=window.__painelD2; if(t&&dd) dd.state.tab=t; });\n      }\n    }catch(e){}\n    d2.on('.logout','click',()=>{\n      try{ localStorage.removeItem('tempoAuth'); }catch(e){}\n      d2.state.user=null; d2.state.tab='inicio'; d2.state.email=''; d2.state.lockErr=''; d2.state.authLoading=false;\n      d2.state.unlocked=false;\n    });\n  }\n}"}},"config":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"config"}}}},"accent":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"accent"}}}}}}}}}},{"_id":"6a3402d823b312eaa4d37ecb","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"ClienteDetail","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .det{height:100%;overflow:auto;background:#0a0a0a;color:#fff;font-family:'Inter',system-ui,sans-serif;box-sizing:border-box;padding:0 0 60px}\n  .top{display:flex;align-items:flex-start;gap:16px;padding:22px 30px 16px;border-bottom:1px solid #2a2a2a;flex-wrap:wrap}\n  .back{background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;border-radius:10px;padding:9px 14px;font-size:13px;font-weight:700;cursor:pointer}\n  .ttl{flex:1;min-width:200px}\n  .ttl h2{font-family:'Anton',sans-serif;font-size:26px;margin:0;letter-spacing:.02em}\n  .ttl .fant{color:#9a9a9a;font-size:13px;margin-top:2px}\n  .badges{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}\n  .b{font-size:11px;font-weight:700;padding:4px 10px;border-radius:999px;background:#1c1c1c;border:1px solid #2a2a2a;color:#9a9a9a;text-transform:uppercase;letter-spacing:.05em}\n  .b.y{background:#F4C400;color:#000;border-color:#F4C400}\n  .b.on{color:#4ade80;border-color:#264a33}\n  .wrap{display:grid;grid-template-columns:1fr 1fr;gap:16px;padding:20px 30px}\n  .panel{background:#141414;border:1px solid #2a2a2a;border-radius:12px;padding:16px 18px}\n  .panel h3{font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:#9a9a9a;margin:0 0 12px;font-weight:700}\n  .kv{display:flex;justify-content:space-between;gap:12px;padding:6px 0;border-bottom:1px solid #1f1f1f;font-size:13px}\n  .kv:last-child{border:0}\n  .kv .k{color:#9a9a9a}.kv .v{font-weight:600;text-align:right;word-break:break-word}\n  .full{grid-column:1/-1}\n  .li{font-size:13px;padding:8px 10px;background:#0f0f0f;border:1px solid #1f1f1f;border-radius:8px;margin-bottom:6px}\n  .li .meta{color:#9a9a9a;font-size:12px;margin-top:2px}\n  .muted{color:#5a5a5a;font-size:13px}\n  .act{display:flex;gap:10px;flex-wrap:wrap;margin-top:10px}\n  .ipt{flex:1;min-width:150px;background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;border-radius:8px;padding:10px 12px;font-size:13px;outline:none}\n  .ipt:focus{border-color:#F4C400}\n  .btn{background:#F4C400;color:#000;border:0;border-radius:8px;padding:0 16px;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;cursor:pointer}\n  .tot{font-family:'Anton',sans-serif;color:#F4C400;font-size:22px}\n  .tagh{display:flex;align-items:center;gap:8px}\n  .tagh .pill{font-size:9px;letter-spacing:.1em;font-weight:800;text-transform:uppercase;padding:3px 8px;border-radius:999px;background:#F4C400;color:#000}\n  .tagh .pill.off{background:#2a2a2a;color:#9a9a9a}\n  .tstats{display:flex;flex-wrap:wrap;gap:14px 28px;margin-bottom:14px}\n  .tstats .cell .n{font-family:'Anton',sans-serif;font-size:26px;color:#F4C400;line-height:1}\n  .tstats .cell .n.grey{color:#fff}\n  .tstats .cell .l{font-size:9px;letter-spacing:.12em;color:#7a7a7a;text-transform:uppercase;margin-top:5px;font-weight:700}\n  .tchips{display:flex;gap:6px;flex-wrap:wrap;margin-top:4px}\n  .tchip{font-size:11px;font-weight:600;padding:4px 10px;border-radius:999px;background:#1c1c1c;border:1px solid #2a2a2a;color:#cfcfcf}\n  .tnone{display:flex;align-items:center;gap:10px;color:#7a7a7a;font-size:13px;padding:4px 0}\n  .tnone .dot{width:8px;height:8px;border-radius:50%;background:#3a3a3a}\n  .vrow{background:#0f0f0f;border:1px solid #1f1f1f;border-radius:8px;margin-bottom:6px;overflow:hidden}\n  .vrow.open{border-color:#2f2f2f}\n  .vhead{display:flex;align-items:center;gap:10px;padding:10px 12px;cursor:pointer;flex-wrap:wrap}\n  .vhead:hover{background:#161616}\n  .vhead .vd{font-size:12px;color:#9a9a9a;min-width:112px}\n  .vhead .vm{font-size:12px;color:#9a9a9a;flex:1;min-width:120px}\n  .vhead .vt{font-weight:700;font-size:14px}\n  .car{color:#5a5a5a;font-size:10px;transition:.15s}\n  .vrow.open .car{transform:rotate(90deg);color:#F4C400}\n  .dpill{font-size:10px;font-weight:800;padding:3px 8px;border-radius:999px;background:#173321;color:#4ade80;border:1px solid #264a33;white-space:nowrap}\n  .vx{border-top:1px solid #1f1f1f;padding:12px;background:#0c0c0c}\n  .it{display:flex;align-items:baseline;gap:8px;padding:5px 0;border-bottom:1px solid #161616;font-size:12.5px}\n  .it:last-child{border-bottom:0}\n  .it .q{color:#F4C400;font-weight:700;min-width:34px;text-align:right;flex-shrink:0}\n  .it .p{flex:1}\n  .it .g{color:#5a5a5a;font-size:10.5px;text-transform:uppercase;letter-spacing:.04em}\n  .it .dv{color:#4ade80;font-size:11px;white-space:nowrap}\n  .it .tv{font-weight:600;white-space:nowrap}\n  .vxh{font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:#7a7a7a;font-weight:800;margin:10px 0 4px}\n  .vx .vxh:first-child{margin-top:0}\n  .pay{display:flex;gap:8px;align-items:center;font-size:12px;color:#cfcfcf;padding:4px 0}\n  .vtotals{display:flex;gap:18px;flex-wrap:wrap;margin-top:10px;padding-top:8px;border-top:1px dashed #222;font-size:12px}\n  .vtotals .k{color:#7a7a7a;margin-right:5px}\n  .vtotals .green{color:#4ade80}\n  .discbox{border:1px solid #264a33;background:#10190f;border-radius:10px;padding:12px 14px;margin:4px 0 12px;font-size:13px}\n  .discbox.no{border-color:#2a2a2a;background:#101010;color:#7a7a7a}\n  .discbox b{color:#4ade80}\n  .gbar{display:flex;align-items:center;gap:10px;padding:4px 0;font-size:12px}\n  .gbar .gl{width:150px;color:#cfcfcf;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex-shrink:0}\n  .gbar .track{flex:1;height:8px;background:#1a1a1a;border-radius:4px;overflow:hidden}\n  .gbar .fill{display:block;height:100%;background:#F4C400;border-radius:4px}\n  .gbar .gv{width:130px;text-align:right;color:#9a9a9a;white-space:nowrap;flex-shrink:0}\n  .two{display:grid;grid-template-columns:1fr 1fr;gap:18px}\n  @media(max-width:900px){.two{grid-template-columns:1fr}}\n  `,\n  render(d2){\n    const esc=s=>String(s==null?'':s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));\n    const c=d2.param('record')||{}; const st=d2.state;\n    const CAT={1:'Founder',2:'Member',3:'Member expirado'};\n    const members=st.members||[];\n    const cpfDigits=String(c.CpfCnpj||'').replace(/\\D/g,'');\n    const matchedMember=members.find(mm=>(mm.member_code&&c.CodTerceiro&&String(mm.member_code)===String(c.CodTerceiro))||(cpfDigits&&mm.cpf&&String(mm.cpf).replace(/\\D/g,'')===cpfDigits));\n    const end=c.DadosEndereco||{};\n    const fmtD=n=>{ const s=String(n||''); return s.length===8?`${s.slice(6,8)}/${s.slice(4,6)}/${s.slice(0,4)}`:(s||'—'); };\n    const tel=c.Telefone?`(${c.DDDTelefone||''}) ${c.Telefone}`:'—';\n    const promos=(c.DadosPromocao||[]).map(p=>p.DescPromocao||('Promoção '+p.CodPromocao));\n    const notas=st.notas||[]; const vendas=st.vendas||[];\n    const num=x=>{const n=Number(x);return isNaN(n)?0:n;};\n    const cur=x=>d2.fmt.currency(num(x),'BRL');\n    const grpName=g=>String(g||'OUTROS').replace(/^[0-9. ]+-\\s*/,'').trim()||'OUTROS';\n    const isTaxa=it=>/TAXA/i.test(String(it.GrupoProduto||''))||/^TAXA DE SERVICO/i.test(String(it.Produto||''));\n    const saleVal=v=>num(v.VlrTotal!=null?v.VlrTotal:v.VlrTotalPago);\n    const vtot=vendas.reduce((s,v)=>s+saleVal(v),0);\n    const vsub=vendas.reduce((s,v)=>s+num(v.VlrSubTotal),0);\n    const vdesc=vendas.reduce((s,v)=>s+num(v.VlrDescontos),0);\n    const prodMap={},grpMap={},promoAgg={};let taxaTot=0,itensTot=0;const diasSet={};\n    vendas.forEach(v=>{ if(v.DataMovimento)diasSet[String(v.DataMovimento)]=1;\n      (v.Itens||[]).forEach(it=>{\n        if(it.DescPromocao){const pm=promoAgg[it.DescPromocao]||(promoAgg[it.DescPromocao]={n:0,v:0});pm.n++;pm.v+=num(it.VlrDescontos);}\n        if(isTaxa(it)){taxaTot+=num(it.VlrTotal);return;}\n        const q=num(it.QtdeProdutos)||1;itensTot+=q;\n        const pn=String(it.Produto||'—');const p=prodMap[pn]||(prodMap[pn]={q:0,v:0,g:grpName(it.GrupoProduto)});p.q+=q;p.v+=num(it.VlrTotal);\n        const gn=grpName(it.GrupoProduto);const g=grpMap[gn]||(grpMap[gn]={q:0,v:0});g.q+=q;g.v+=num(it.VlrTotal);\n      });});\n    const nDias=Object.keys(diasSet).length;\n    const ticket=vendas.length?vtot/vendas.length:0;\n    const topProds=Object.entries(prodMap).sort((a,b)=>b[1].v-a[1].v).slice(0,8);\n    const grpsMix=Object.entries(grpMap).sort((a,b)=>b[1].v-a[1].v);\n    const gmax=grpsMix.length?Math.max(grpsMix[0][1].v,0.01):1;\n    const promoList=Object.entries(promoAgg);\n    const descPct=vsub>0?Math.round(vdesc/vsub*100):0;\n    const discHtml=vendas.length?(vdesc>0\n      ?`<div class=\"discbox\">Este cliente <b>TEVE desconto</b> nos últimos 90 dias: <b>−${esc(cur(vdesc))}</b> (${descPct}% sobre o subtotal de ${esc(cur(vsub))})${promoList.length?`<div class=\"tchips\" style=\"margin-top:8px\">${promoList.map(pp=>`<span class=\"tchip\">${esc(pp[0])} · ${pp[1].n}× · −${esc(cur(pp[1].v))}</span>`).join('')}</div>`:''}</div>`\n      :`<div class=\"discbox no\">Sem descontos nos últimos 90 dias — pagou tabela cheia (${esc(cur(vsub))}).</div>`):'';\n    const consumoHtml=vendas.length?`<div class=\"panel full\"><h3>Consumo — Perfil (90 dias)</h3>\n      <div class=\"tstats\">\n        <div class=\"cell\"><div class=\"n\">${esc(cur(vtot))}</div><div class=\"l\">Gasto total</div></div>\n        <div class=\"cell\"><div class=\"n grey\">${vendas.length}</div><div class=\"l\">Comandas</div></div>\n        <div class=\"cell\"><div class=\"n grey\">${esc(cur(ticket))}</div><div class=\"l\">Ticket médio</div></div>\n        <div class=\"cell\"><div class=\"n grey\">${nDias}</div><div class=\"l\">Dias c/ consumo</div></div>\n        <div class=\"cell\"><div class=\"n grey\">${itensTot}</div><div class=\"l\">Itens</div></div>\n        <div class=\"cell\"><div class=\"n\" style=\"color:${vdesc>0?'#4ade80':'#fff'}\">${vdesc>0?'−'+esc(cur(vdesc)):'R$ 0'}</div><div class=\"l\">Descontos</div></div>\n        <div class=\"cell\"><div class=\"n grey\">${esc(cur(taxaTot))}</div><div class=\"l\">Taxa de serviço</div></div>\n      </div>\n      ${discHtml}\n      <div class=\"two\">\n        <div><div class=\"vxh\">Mix por grupo</div>${grpsMix.map(gg=>`<div class=\"gbar\"><span class=\"gl\" title=\"${esc(gg[0])}\">${esc(gg[0])}</span><span class=\"track\"><span class=\"fill\" style=\"width:${Math.max(3,Math.round(gg[1].v/gmax*100))}%\"></span></span><span class=\"gv\">${esc(cur(gg[1].v))} · ${gg[1].q} it.</span></div>`).join('')||'<div class=\"muted\">—</div>'}</div>\n        <div><div class=\"vxh\">Produtos favoritos</div>${topProds.map(tp=>`<div class=\"it\"><span class=\"q\">${tp[1].q}×</span><span class=\"p\">${esc(tp[0])} <span class=\"g\">${esc(tp[1].g)}</span></span><span class=\"tv\">${esc(cur(tp[1].v))}</span></div>`).join('')||'<div class=\"muted\">—</div>'}</div>\n      </div>\n    </div>`:'';\n    const vendaRow=(v,i)=>{\n      const open=String(st.expv)===String(i);\n      const mesas=Object.keys((v.Itens||[]).reduce((mm,it)=>{if(it.MesaComanda!=null)mm[it.MesaComanda]=1;return mm;},{}));\n      const dt=String(v.DataCupom||'').slice(0,16)||fmtD(v.DataMovimento);\n      const dv=num(v.VlrDescontos);\n      let bodyX='';\n      if(open){\n        const agg={};(v.Itens||[]).forEach(it=>{const k=String(it.Produto||'—')+'|'+num(it.VlrVenda);const r=agg[k]||(agg[k]={p:String(it.Produto||'—'),g:grpName(it.GrupoProduto),q:0,t:0,d:0,promos:{}});r.q+=num(it.QtdeProdutos)||1;r.t+=num(it.VlrTotal);r.d+=num(it.VlrDescontos);if(it.DescPromocao)r.promos[it.DescPromocao]=1;});\n        const rowsX=Object.values(agg).sort((a,b)=>b.t-a.t);\n        const pays=(v.Pagamentos||[]);\n        bodyX=`<div class=\"vx\">\n          <div class=\"vxh\">Itens da comanda</div>\n          ${rowsX.map(r=>`<div class=\"it\"><span class=\"q\">${r.q}×</span><span class=\"p\">${esc(r.p)} <span class=\"g\">${esc(r.g)}</span>${Object.keys(r.promos).map(pn2=>` <span class=\"dpill\">${esc(pn2)}</span>`).join('')}</span>${r.d>0?`<span class=\"dv\">−${esc(cur(r.d))}</span>`:''}<span class=\"tv\">${esc(cur(r.t))}</span></div>`).join('')||'<div class=\"muted\">Sem itens detalhados.</div>'}\n          ${pays.length?`<div class=\"vxh\">Pagamento</div>${pays.map(p=>`<div class=\"pay\">${esc(p.DescFormaPagto||'—')}${p.DescProdCartao?' · '+esc(p.DescProdCartao):''}${p.DescAdquirente?' · '+esc(p.DescAdquirente):''}${num(p.QtdeParcelas)>1?' · '+num(p.QtdeParcelas)+'x':''} <b style=\"margin-left:auto\">${esc(cur(p.VlrPago))}</b></div>`).join('')}`:''}\n          <div class=\"vtotals\"><span><span class=\"k\">Subtotal</span>${esc(cur(v.VlrSubTotal))}</span>${dv>0?`<span class=\"green\"><span class=\"k\" style=\"color:#3f7a52\">Descontos</span>−${esc(cur(dv))}</span>`:''}${num(v.VlrAcrescimos)>0?`<span><span class=\"k\">Acréscimos</span>${esc(cur(v.VlrAcrescimos))}</span>`:''}<span><span class=\"k\">Total</span><b>${esc(cur(saleVal(v)))}</b></span><span><span class=\"k\">Pago</span>${esc(cur(v.VlrTotalPago))}</span></div>\n          <div class=\"muted\" style=\"margin-top:8px;font-size:11px\">${esc(v.DescricaoCaixa||'')}${v.UsuarioVenda?' · lançada por '+esc(v.UsuarioVenda):''}${v.SeqCupom?' · cupom '+esc(v.SeqCupom):''}${v.NrMovimento?' · mov. '+esc(v.NrMovimento):''}</div>\n        </div>`;\n      }\n      return `<div class=\"vrow ${open?'open':''}\"><div class=\"vhead\" data-i=\"${i}\"><span class=\"car\">▶</span><span class=\"vd\">${esc(dt)}</span><span class=\"vm\">${mesas.length?'Mesa '+esc(mesas.join(', '))+' · ':''}${num(v.QtdeProdutos)||num(v.QtdeItens)||'?'} itens</span>${dv>0?`<span class=\"dpill\">−${esc(cur(dv))} desc.</span>`:''}<span class=\"vt\">${esc(cur(saleVal(v)))}</span></div>${bodyX}</div>`;\n    };\n    const vendasHtml=`<div class=\"panel full\"><h3>Vendas — Comandas (90 dias)</h3>${st.vloading?'<div class=\"muted\">Carregando vendas do Cloudfy…</div>':(vendas.length?`<div style=\"margin-bottom:10px\"><span class=\"tot\">${esc(cur(vtot))}</span> <span class=\"muted\">· ${vendas.length} venda(s) · clique numa venda para abrir a comanda</span></div>`+vendas.map(vendaRow).join(''):'<div class=\"muted\">Sem vendas no período.</div>')}</div>`;\n    const kv=(k,v)=>`<div class=\"kv\"><span class=\"k\">${esc(k)}</span><span class=\"v\">${esc(v)}</span></div>`;\n    return `<div class=\"det\">\n      <div class=\"top\">\n        <div class=\"ttl\"><h2>${esc(c.Nome||'—')}</h2>${(c.NomeFantasia&&c.NomeFantasia!==c.Nome)?`<div class=\"fant\">${esc(c.NomeFantasia)}</div>`:''}\n          <div class=\"badges\">\n            <span class=\"b\">${c.TpPessoa==='J'?'PJ':'PF'}</span>\n            <span class=\"b ${c.Situacao?'on':''}\">${c.Situacao?'Ativo':'Inativo'}</span>\n            ${c.CodCategoria?`<span class=\"b y\">${esc(CAT[c.CodCategoria]||('Cat '+c.CodCategoria))}</span>`:''}\n            ${c.CodTerceiro?`<span class=\"b\">Comanda ${esc(c.CodTerceiro)}</span>`:''}\n          </div>\n        </div>\n      </div>\n      <div class=\"wrap\">\n        <div class=\"panel\"><h3>Cadastro</h3>${kv('Documento',c.CpfCnpj||'—')}${kv('Cadastro',fmtD(c.DtCadastro))}${kv('Sexo',c.Sexo||'—')}${kv('NrPessoa',c.NrPessoa==null?'—':c.NrPessoa)}</div>\n        <div class=\"panel\"><h3>Contato</h3>${kv('E-mail',c.Email||'—')}<div class=\"kv\"><span class=\"k\">Telefone</span><span class=\"v\">${esc(tel)}</span></div><div class=\"act\"><input class=\"teldd ipt\" style=\"max-width:74px;flex:0 0 auto\" placeholder=\"DDD\" inputmode=\"tel\" maxlength=\"2\" value=\"${esc(st.telddVal!=null?st.telddVal:(c.DDDCelular||c.DDDTelefone||''))}\"><input class=\"telnum ipt\" placeholder=\"Número (celular)\" inputmode=\"tel\" value=\"${esc(st.telnumVal!=null?st.telnumVal:(c.Celular||c.Telefone||''))}\"><button class=\"saltel btn\">Salvar telefone</button></div>${st.telMsg?`<div class=\"muted\" style=\"margin-top:8px;${st.telOk?'color:#4ade80':''}\">${esc(st.telMsg)}</div>`:''}</div>\n        <div class=\"panel full\"><h3 class=\"tagh\">TAGME ${st.tagLoading?'':(st.tagme?'<span class=\"pill\">cadastrado</span>':(st.tagDone?'<span class=\"pill off\">sem cadastro</span>':''))}</h3>${(()=>{ if(st.tagLoading)return '<div class=\"muted\">Consultando TAGME…</div>'; const t=st.tagme; if(!t){ return '<div class=\"tnone\"><span class=\"dot\"></span>Sem cadastro na TAGME para este telefone.</div>'; } const s=t.stats||{}; const cells=[['Reservas',s.reservationsQuantity||0,true],['Cancelamentos',s.cancelsQuantity||0,false],['No-shows',s.noShowsQuantity||0,false],['Walk-ins',s.walkInsQuantity||0,false]]; const stHtml=cells.map(cc=>`<div class=\"cell\"><div class=\"n ${cc[2]?'':'grey'}\">${cc[1]}</div><div class=\"l\">${esc(cc[0])}</div></div>`).join(''); const nameLine=[t.name,t.lastName].filter(Boolean).join(' '); const chips=[]; (t.preferences||[]).forEach(p=>chips.push(typeof p==='string'?p:(p&&(p.name||p.label||p.title)||''))); (t.crmCategories||[]).forEach(cat=>chips.push(typeof cat==='string'?cat:(cat&&(cat.name||cat.label||cat.title)||''))); const chipsHtml=chips.filter(Boolean).length?`<div class=\"tchips\">${chips.filter(Boolean).map(ch=>`<span class=\"tchip\">${esc(ch)}</span>`).join('')}</div>`:''; const obs=t.obs?`<div class=\"li\" style=\"margin-top:8px\">${esc(t.obs)}</div>`:''; return `<div class=\"tstats\">${stHtml}</div>${kv('Nome',nameLine||'—')}${kv('E-mail',t.email||'—')}${kv('Telefone',t.phone||'—')}${kv('Última visita',t.lastVisitDate?d2.fmt.relative(t.lastVisitDate):'—')}${chipsHtml}${obs}<div class=\"muted\" style=\"margin-top:10px;font-size:11px\">Estatísticas do venue TEMPO By Porsche. O histórico completo de reservas por cliente não é exposto pela TAGME — exibimos os totais e a última visita.</div>`; })()}</div>\n        <div class=\"panel full\"><h3>Endereço</h3>${(end.Endereco||end.Cidade)?`${kv('Logradouro',`${end.Endereco||''}${end.Numero?', '+end.Numero:''}${end.Complemento?' · '+end.Complemento:''}`)}${kv('Bairro',end.Bairro||'—')}${kv('Cidade/UF',`${end.Cidade||'—'}${end.UF?' / '+end.UF:''}`)}${kv('CEP',end.Cep||'—')}`:'<div class=\"muted\">Sem endereço cadastrado.</div>'}</div>\n        ${promos.length?`<div class=\"panel full\"><h3>Promoções</h3>${promos.map(p=>`<div class=\"li\">${esc(p)}</div>`).join('')}</div>`:''}\n        <div class=\"panel full\"><h3>Observações</h3>${notas.length?notas.map(n=>`<div class=\"li\">${esc(n.nota)}<div class=\"meta\">${n.criadoEm?d2.fmt.relative(n.criadoEm):''}</div></div>`).join(''):'<div class=\"muted\">Nenhuma observação ainda.</div>'}<div class=\"act\"><input class=\"notaipt ipt\" placeholder=\"Adicionar observação (ex: prefere mesa na varanda)\"><button class=\"addnota btn\">+ Nota</button></div></div>\n        ${consumoHtml}${vendasHtml}\n        ${matchedMember?`<div class=\"panel full\"><h3 class=\"tagh\">Membro Tempo <span class=\"pill\">já é membro</span></h3>${kv('Código de membro','#'+(matchedMember.member_code||'—'))}${kv('Tipo',matchedMember.tipo_cadastro||'—')}${kv('Sincronizado c/ Cloudfy',matchedMember.cloudfy_synced?'Sim (NrPessoa '+(matchedMember.cloudfy_nrpessoa||'—')+')':'Não')}${kv('Adesão',matchedMember.data_cadastro?String(matchedMember.data_cadastro).slice(0,10).split('-').reverse().join('/'):'—')}</div>`:`<div class=\"panel full\"><h3>Tornar membro</h3><div class=\"act\"><input class=\"memail ipt\" placeholder=\"E-mail do membro*\" inputmode=\"email\"><input class=\"mtel ipt\" placeholder=\"Telefone (opcional)\" inputmode=\"tel\"><select class=\"mtipo ipt\"><option value=\"MEMBER\">Member</option><option value=\"FOUNDER\">Founder</option><option value=\"ENTHUSIAST\">Enthusiast</option><option value=\"GUEST\">Guest</option></select><button class=\"tornar btn\">Cadastrar</button></div>${st.msg?`<div class=\"muted\" style=\"margin-top:8px\">${esc(st.msg)}</div>`:''}</div>`}\n      </div>\n    </div>`;\n  },\n  mounted(d2){\n    const KEY={authorization:'sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'};\n    const c=d2.param('record')||{};\n    const loadVendas=async()=>{ if(!c.NrPessoa){ d2.state.vendas=[]; return; } d2.state.vloading=true;\n      const day=864e5; const hoje=new Date(); const fmt=dt=>`${dt.getFullYear()}${String(dt.getMonth()+1).padStart(2,'0')}${String(dt.getDate()).padStart(2,'0')}`;\n      const wins=[[30,0],[60,30],[90,60]].map(p=>({DataInicio:fmt(new Date(hoje.getTime()-p[0]*day)),DataFim:fmt(new Date(hoje.getTime()-p[1]*day))}));\n      try{ const rs=await Promise.all(wins.map(w=>d2.rush('proxy-vendas').invoke({NrPessoa:String(c.NrPessoa),DataInicio:w.DataInicio,DataFim:w.DataFim},{headers:KEY}).catch(()=>null)));\n        const all=[]; rs.forEach(r=>{ if(!r)return; let d=r&&r.data!==undefined?r.data:r; if(d&&d.data!==undefined)d=d.data; (d&&d.Vendas||[]).forEach(v=>all.push(v)); });\n        all.sort((a,b)=>(Number(b.DataMovimento)||0)-(Number(a.DataMovimento)||0)); d2.state.vendas=all; }\n      catch(e){ d2.state.vendas=[]; } finally{ d2.state.vloading=false; } };\n    const loadNotas=async()=>{ try{ const r=await d2.rush('nota-listar').invoke({},{headers:KEY}); let a=r&&r.data!==undefined?r.data:r; if(a&&a.data!==undefined)a=a.data; const all=Array.isArray(a)?a:[]; const q=String(c.Nome||'').trim().toLowerCase(); d2.state.notas=q?all.filter(n=>String(n.alvo||'').toLowerCase().includes(q)||q.includes(String(n.alvo||'').toLowerCase())):[]; }catch(e){ d2.state.notas=[]; } };\n    const VENUE='69fcd30c55153376bd62ca81';\n    const unwrap=r=>{ let d=r&&r.data!==undefined?r.data:r; if(d&&d.data!==undefined)d=d.data; return d; };\n    const loadTagme=async()=>{\n      let digits=String((c.DDDTelefone||c.DDDCelular||'')+''+(c.Telefone||c.Celular||'')).replace(/[^0-9]/g,'');\n      if(!digits){ d2.state.tagme=null; d2.state.tagDone=true; return; }\n      if(!/^55/.test(digits)) digits='55'+digits;\n      d2.state.tagLoading=true; d2.state.tagme=null; d2.state.tagDone=false;\n      try{\n        const r=await d2.rush('tagme-read').invoke({path:`/Customer?limit=10&phone=%2B${digits}`},{headers:KEY});\n        const arr=unwrap(r); const cust=Array.isArray(arr)?arr.find(x=>x&&x._id):null;\n        if(!cust){ d2.state.tagme=null; d2.state.tagDone=true; return; }\n        const stats={reservationsQuantity:0,cancelsQuantity:0,noShowsQuantity:0,walkInsQuantity:0}; let lastVisitDate=null; const prefs=[]; const cats=[];\n        (cust.venuesDetails||[]).filter(v=>String(v.venue)===VENUE).forEach(v=>{\n          const s=v.statsDetails||{};\n          ['reservationsQuantity','cancelsQuantity','noShowsQuantity','walkInsQuantity'].forEach(k=>{ if(typeof s[k]==='number') stats[k]+=s[k]; });\n          if(s.lastVisitDate&&(!lastVisitDate||s.lastVisitDate>lastVisitDate)) lastVisitDate=s.lastVisitDate;\n          (v.preferences||[]).forEach(p=>prefs.push(p)); (v.crmCategories||[]).forEach(cc=>cats.push(cc));\n        });\n        d2.state.tagme={ _id:cust._id, name:cust.name, lastName:cust.lastName, email:cust.email, phone:cust.phone, obs:cust.obs||cust.observation||'', stats, lastVisitDate, preferences:prefs, crmCategories:cats };\n        d2.state.tagDone=true;\n      }catch(e){ d2.log('tagme err',e); d2.state.tagme=null; d2.state.tagDone=true; }\n      finally{ d2.state.tagLoading=false; }\n    };\n    const loadMembers=async()=>{ try{ const r=await d2.rush('list-members').invoke({limit:500},{headers:KEY}); const a=r&&r.data!==undefined?r.data:r; d2.state.members=(a&&a.members)||[]; }catch(e){ d2.state.members=[]; } };\n    loadVendas(); loadNotas(); loadTagme(); loadMembers();\n    d2.on('.vhead','click',(e,el)=>{ const i=el.dataset.i; d2.state.expv=(String(d2.state.expv)===String(i)?null:i); });\n    d2.on('.addnota','click',async()=>{ const ipt=d2.$('.notaipt'); const v=(ipt&&ipt.value||'').trim(); if(!v)return; await d2.rush('nota-salvar').invoke({alvo:c.Nome,nrPessoa:c.NrPessoa||null,nota:v,criadoEm:Date.now()},{headers:KEY}); if(ipt)ipt.value=''; loadNotas(); });\n    d2.on('.tornar','click',async()=>{ const email=((d2.$('.memail')||{}).value||'').trim(); const tipo=(d2.$('.mtipo')||{}).value||'MEMBER'; if(!email){ d2.state.msg='Informe um e-mail.'; return; } d2.state.msg='Cadastrando…';\n      const tel=((d2.$('.mtel')||{}).value||'').trim();\n      try{ const r=await d2.rush('signup').invoke({nome_completo:c.Nome,email:email,telefone:tel,cpf:c.CpfCnpj||'',tipo_cadastro:tipo,origin:'PAINEL'},{headers:{authorization:'Bearer sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'}}); const d=r&&r.data!==undefined?r.data:r;\n        d2.state.msg=(d&&d.success)?('✓ Membro criado'+(d.data&&d.data.member_code?' · código '+d.data.member_code:'')):('Falhou: '+((d&&d.message)||'erro')); }\n      catch(e){ d2.state.msg='Erro ao cadastrar membro.'; } });\n    d2.on('.saltel','click',async()=>{\n      const ddd=String(((d2.$('.teldd')||{}).value||'')).replace(/\\D/g,'');\n      const num=String(((d2.$('.telnum')||{}).value||'')).replace(/\\D/g,'');\n      d2.state.telddVal=ddd; d2.state.telnumVal=num;\n      if(!c.NrPessoa){ d2.state.telOk=false; d2.state.telMsg='Cliente sem NrPessoa — não é possível salvar.'; return; }\n      if(ddd.length!==2||num.length<8){ d2.state.telOk=false; d2.state.telMsg='Informe DDD (2 dígitos) e número (mín. 8 dígitos).'; return; }\n      d2.state.telOk=false; d2.state.telMsg='Salvando telefone no Cloudfy…';\n      try{\n        const r=await d2.rush('proxy-cliente-salvar').invoke({\n          Acao:'U',\n          NrPessoa:String(c.NrPessoa),\n          CodTerceiro:c.CodTerceiro||'',\n          Nome:c.Nome||'',\n          TpPessoa:c.TpPessoa||'F',\n          CpfCnpj:c.CpfCnpj||'',\n          Email:c.Email||'',\n          Sexo:c.Sexo||'',\n          Situacao:(c.Situacao==null?'1':String(c.Situacao)),\n          DDDCelular:ddd,\n          Celular:num\n        },{headers:{authorization:'Bearer sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'}});\n        let d=r&&r.data!==undefined?r.data:r; if(d&&d.data!==undefined)d=d.data;\n        if(d&&d.success){\n          c.DDDCelular=ddd; c.Celular=num; c.DDDTelefone=ddd; c.Telefone=num;\n          d2.state.telOk=true; d2.state.telMsg='✓ Telefone salvo no Cloudfy. Reconsultando TAGME…';\n          await loadTagme();\n          d2.state.telMsg='✓ Telefone salvo no Cloudfy.';\n        } else {\n          d2.state.telOk=false; d2.state.telMsg='Falhou: '+((d&&(d.MensagemRet||d.message))||'erro ao salvar');\n        }\n      }catch(e){ d2.log('saltel err',e); d2.state.telOk=false; d2.state.telMsg='Erro ao salvar telefone.'; }\n    });\n  }\n}"}},"record":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"record"}}}}}}}}}},{"_id":"6a34033e948195d3c9f69c72","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"ClientesScreen","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .scr{height:100%;overflow:auto;background:#0a0a0a;font-family:'Inter',system-ui,sans-serif;color:#fff;box-sizing:border-box}\n  .head{display:flex;align-items:center;gap:14px;padding:28px 36px 18px;flex-wrap:wrap}\n  .head h2{font-family:'Anton',sans-serif;font-size:22px;letter-spacing:.08em;text-transform:uppercase;margin:0}\n  .head .sm{font-size:11px;color:#9a9a9a;letter-spacing:.1em;font-weight:600}\n  .bar{flex:1;height:1px;background:#2a2a2a;min-width:30px}\n  .tabs{display:flex;gap:8px}\n  .tab{background:transparent;border:1px solid #2a2a2a;color:#9a9a9a;padding:8px 16px;font-size:12px;letter-spacing:.12em;font-weight:600;cursor:pointer;text-transform:uppercase;border-radius:3px}\n  .tab.on{background:#F4C400;color:#000;border-color:#F4C400}\n  .search{background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;padding:10px 13px;font-size:14px;outline:none;min-width:280px;border-radius:3px}\n  .search:focus{border-color:#F4C400}\n  .rows{display:flex;flex-direction:column;gap:8px;padding:18px 36px 50px}\n  .cnt{color:#9a9a9a;font-size:12px;margin:0 2px 4px}\n  .cli{display:flex;align-items:center;justify-content:space-between;gap:12px;background:#141414;border:1px solid #2a2a2a;border-radius:10px;padding:12px 16px;cursor:pointer;transition:.12s}\n  .cli:hover{border-color:#F4C400;background:#191919}\n  .cn{font-weight:700;font-size:15px}\n  .cm{color:#9a9a9a;font-size:12px;margin-top:3px}\n  .open{color:#F4C400;font-size:12px;font-weight:700;white-space:nowrap}\n  .loading{padding:40px;color:#9a9a9a}\n  .mchip{font-size:9px;letter-spacing:.14em;font-weight:800;text-transform:uppercase;padding:3px 8px;border-radius:999px;background:#F4C400;color:#000;margin-left:8px;vertical-align:middle}\n  .detwrap{flex:1;min-height:0}\n  .cold{display:flex;flex-direction:column;height:100%}\n  .detbar{padding:14px 30px;border-bottom:1px solid #2a2a2a;flex-shrink:0;display:flex;align-items:center;gap:12px}\n  .backbtn{background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;border-radius:10px;padding:9px 14px;font-size:13px;font-weight:700;cursor:pointer}\n  .backbtn:hover{border-color:#F4C400}\n  .dbn{color:#9a9a9a;font-size:13px}\n  `,\n  render(d2){\n    const esc=s=>String(s==null?'':s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));\n    const st=d2.state; const sel=st.sel;\n    if(st.selLoading){\n      return `<div class=\"scr cold\"><div class=\"detbar\"><button class=\"backbtn\">← Voltar</button><span class=\"dbn\">Abrindo…</span></div><div class=\"loading\">Buscando o cadastro no Cloudfy…</div></div>`;\n    }\n    if(sel){\n      return `<div class=\"scr cold\"><div class=\"detbar\"><button class=\"backbtn\">← Voltar</button><span class=\"dbn\">${esc(sel.Nome||'')}</span></div><div class=\"detwrap\">${d2.render('adonis@ClienteDetail',{record:sel},{key:'det'})}</div></div>`;\n    }\n    const rows=st.rows||[]; const tp=st.tp||'all';\n    let body;\n    if(st.loading)body=`<div class=\"loading\">Buscando…</div>`;\n    else if(st.err)body=`<div class=\"loading\" style=\"color:#ffce7a\">${esc(st.err)}</div>`;\n    else if(!rows.length)body=`<div class=\"loading\">Ninguém encontrado${st.q?` para \"${esc(st.q)}\"`:''}.</div>`;\n    else{ const tot=st.total==null?rows.length:st.total;\n      body=`<div class=\"cnt\">${tot} pessoa(s)${tot>rows.length?` · mostrando ${rows.length}, refine a busca`:''}</div>`+rows.map(r=>`<div class=\"cli\" data-nr=\"${esc(r.nr_pessoa==null?'':r.nr_pessoa)}\"><div><div class=\"cn\">${esc(r.nome||'—')}${r.eh_membro?`<span class=\"mchip\">Membro${r.member_code?' '+esc(r.member_code):''}</span>`:''}</div><div class=\"cm\">${r.tp==='J'?'PJ':'PF'}${r.cpf?' · '+esc(r.cpf):''}${r.nr_pessoa?' · Nr '+esc(r.nr_pessoa):''}${r.cidade?' · '+esc(r.cidade):''}</div></div><span class=\"open\">Abrir ›</span></div>`).join('');\n    }\n    return `<div class=\"scr\">\n      <div class=\"head\"><h2>Pessoas <span class=\"sm\">BASE PRÓPRIA · SYNC CLOUDFY</span></h2><div class=\"bar\"></div>\n        <div class=\"tabs\"><button class=\"tab ${tp==='all'?'on':''}\" data-c=\"all\">Todos</button><button class=\"tab ${tp==='F'?'on':''}\" data-c=\"F\">PF</button><button class=\"tab ${tp==='J'?'on':''}\" data-c=\"J\">PJ</button></div>\n        <input class=\"search q\" placeholder=\"Buscar por nome, CPF/CNPJ, e-mail ou Nr…\" value=\"${esc(st.q||'')}\"></div>\n      <div class=\"rows\">${body}</div></div>`;\n  },\n  mounted(d2){\n    const KEY={authorization:'sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'};\n    const load=async()=>{ d2.state.loading=true; d2.state.err=null;\n      try{\n        const tp=(d2.state.tp&&d2.state.tp!=='all')?d2.state.tp:'';\n        const r=await d2.rush(d2.params.listar||'pessoas-listar').invoke({q:(d2.state.q||'').trim(),tp,limit:300},{headers:KEY});\n        const d=r&&r.data!==undefined?r.data:r;\n        if(!d||d.success!==true){ d2.state.rows=[]; d2.state.total=0; d2.state.err='Não consegui carregar a lista: '+((d&&d.message)||'resposta inesperada do servidor.'); return; }\n        d2.state.rows=d.pessoas||[]; d2.state.total=d.total;\n      }catch(e){ d2.log('pessoas err',e); d2.state.err='Erro ao carregar: '+(e&&e.message||e); }\n      finally{ d2.state.loading=false; } };\n    load();\n    let deb=null, pend='';\n    d2.on('.q','input',(e,el)=>{ pend=el.value; clearTimeout(deb); deb=setTimeout(()=>{ d2.state.q=pend; load(); },350); });\n    d2.on('.tab','click',(e,el)=>{ d2.state.tp=el.dataset.c; load(); });\n    d2.on('.cli','click',async(e,el)=>{\n      const nr=el.dataset.nr;\n      if(!nr){ d2.state.err='Essa pessoa não tem cadastro no Cloudfy, então não dá para abrir o consumo.'; return; }\n      d2.state.selLoading=true; d2.state.err=null;\n      try{\n        const r=await d2.rush(d2.params.proxyCliente||'proxy-cliente').invoke({NrPessoa:String(nr)},{headers:KEY});\n        let d=r&&r.data!==undefined?r.data:r; if(d&&d.data!==undefined)d=d.data;\n        const rec=((d&&d.DadosCliente)||[])[0];\n        if(rec) d2.state.sel=rec; else d2.state.err='Cadastro Nr '+nr+' não encontrado no Cloudfy.';\n      }catch(err){ d2.log('detalhe err',err); d2.state.err='Erro ao abrir o cadastro no Cloudfy.'; }\n      finally{ d2.state.selLoading=false; } });\n    d2.on('.backbtn','click',()=>{ d2.state.sel=null; });\n  }\n}"}},"proxyCliente":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"proxyCliente"}}}},"proxyVendas":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"proxyVendas"}}}},"signup":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"signup"}}}},"clienteRow":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"clienteRow"}}}}}}}}}},{"_id":"6a34051423b312eaa4d386ab","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"MemberDetail","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .det{height:100%;overflow:auto;background:#0a0a0a;color:#fff;font-family:'Inter',system-ui,sans-serif;box-sizing:border-box;padding-bottom:50px}\n  .hero{position:relative;height:300px;background:#141414;border-bottom:1px solid #2a2a2a;overflow:hidden}\n  .hero img{width:100%;height:100%;object-fit:cover;opacity:.9}\n  .hero .grad{position:absolute;inset:0;background:linear-gradient(to top,rgba(10,10,10,.96),rgba(10,10,10,.15) 60%,rgba(10,10,10,.05))}\n  .hero .info{position:absolute;left:30px;bottom:20px;right:30px}\n  .hero .code{font-family:'Anton',sans-serif;font-size:14px;letter-spacing:.22em;color:#F4C400}\n  .hero h2{font-family:'Anton',sans-serif;font-size:32px;margin:4px 0 10px;letter-spacing:.02em;line-height:.95}\n  .badges{display:flex;gap:6px;flex-wrap:wrap}\n  .b{font-size:11px;font-weight:700;padding:4px 10px;border-radius:999px;background:rgba(0,0,0,.55);border:1px solid #2a2a2a;color:#cfcfcf;text-transform:uppercase;letter-spacing:.05em}\n  .b.y{background:#F4C400;color:#000;border-color:#F4C400}\n  .noimg{display:flex;align-items:center;justify-content:center;height:100%;color:#262626;font-family:'Anton',sans-serif;font-size:46px;letter-spacing:.1em}\n  .wrap{display:grid;grid-template-columns:1fr 1fr;gap:16px;padding:20px 30px}\n  .panel{background:#141414;border:1px solid #2a2a2a;border-radius:12px;padding:16px 18px}\n  .panel.full{grid-column:1/-1}\n  .panel h3{font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:#9a9a9a;margin:0 0 12px;font-weight:700}\n  .kv{display:flex;justify-content:space-between;gap:12px;padding:6px 0;border-bottom:1px solid #1f1f1f;font-size:13px}\n  .kv:last-child{border:0}.kv .k{color:#9a9a9a}.kv .v{font-weight:600;text-align:right;word-break:break-word}\n  .chips{display:flex;gap:8px;flex-wrap:wrap}\n  .chip{background:#0f0f0f;border:1px solid #1f1f1f;border-radius:8px;padding:8px 12px;font-size:13px}\n  .chip b{color:#F4C400}\n  .li{font-size:13px;padding:8px 10px;background:#0f0f0f;border:1px solid #1f1f1f;border-radius:8px;margin-bottom:6px}\n  .muted{color:#5a5a5a;font-size:13px}\n  .numrow{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:10px;padding-top:12px;border-top:1px solid #1f1f1f}\n  .numlbl{font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:#9a9a9a;font-weight:700;flex-basis:100%}\n  .numinput{background:#0f0f0f;border:1px solid #2a2a2a;color:#fff;padding:9px 12px;font-size:14px;border-radius:8px;outline:none;width:130px;font-family:'Anton',sans-serif;letter-spacing:.08em}\n  .numinput:focus{border-color:#F4C400}\n  .numbtn{background:#F4C400;border:1px solid #F4C400;color:#000;border-radius:8px;padding:9px 16px;font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;cursor:pointer}\n  .numbtn:hover{filter:brightness(1.08)}\n  .numbtn.ghost{background:transparent;color:#9a9a9a;border-color:#2a2a2a}\n  .numbtn.ghost:hover{border-color:#F4C400;color:#fff}\n  .numbtn[disabled]{opacity:.5;cursor:default}\n  .numconf{flex-basis:100%;background:#1a1505;border:1px solid #F4C400;border-radius:8px;padding:12px 14px;font-size:13px;line-height:1.4;color:#f5e6b0}\n  .numconf b{color:#F4C400}\n  .numactions{display:flex;gap:8px;margin-top:10px;flex-basis:100%}\n  .nummsg{flex-basis:100%;font-size:13px;padding:8px 0}\n  .nummsg.ok{color:#7ddf8e}.nummsg.err{color:#ffce7a}\n  `,\n  render(d2){\n    const esc=s=>String(s==null?'':s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));\n    const m=d2.param('record')||{}; const st=d2.state;\n    const kv=(k,v)=>`<div class=\"kv\"><span class=\"k\">${esc(k)}</span><span class=\"v\">${esc(v)}</span></div>`;\n    const tem=m.tem_porsche; const img=m.car_image; const notas=st.notas||[];\n    const porsche=[['Modelo',m.modelo_porsche],['Versão',m.versao_porsche],['Ano',m.ano_porsche],['Cor',m.cor_porsche],['Placa',m.placa]].filter(p=>p[1]);\n    const curCode=m.member_code||'';\n    const editor=(()=>{\n      if(st.numSaving) return `<div class=\"numrow\"><div class=\"nummsg\">Salvando número…</div></div>`;\n      if(st.numMsg) return `<div class=\"numrow\"><div class=\"nummsg ${st.numOk?'ok':'err'}\">${esc(st.numMsg)}</div><button class=\"numbtn ghost numreset\">OK</button></div>`;\n      const nv=st.numNew==null?curCode:st.numNew;\n      if(st.numConfirm){\n        return `<div class=\"numrow\"><span class=\"numlbl\">Alterar número (código)</span>`\n          +`<div class=\"numconf\">Alterar o número do membro de <b>#${esc(curCode)}</b> para <b>#${esc(nv)}</b>?<br>Isso muda o <b>codTerceiro</b> do cliente no Cloudfy.</div>`\n          +`<div class=\"numactions\"><button class=\"numbtn numconfirm\">Confirmar alteração</button><button class=\"numbtn ghost numcancel\">Cancelar</button></div></div>`;\n      }\n      return `<div class=\"numrow\"><span class=\"numlbl\">Alterar número (código)</span>`\n        +`<input class=\"numinput numfield\" value=\"${esc(nv)}\" placeholder=\"código\">`\n        +`<button class=\"numbtn numsave\">Salvar número</button></div>`;\n    })();\n    return `<div class=\"det\">\n      <div class=\"hero\">${img?`<img src=\"${esc(img)}\" alt=\"\">`:`<div class=\"noimg\">TEMPO</div>`}<div class=\"grad\"></div>\n        <div class=\"info\"><div class=\"code\">#${esc(m.member_code||'—')}</div><h2>${esc(m.nome_completo||'—')}</h2>\n          <div class=\"badges\"><span class=\"b y\">${esc(m.tipo_cadastro||'MEMBER')}</span>${tem?'<span class=\"b\">Porsche</span>':''}${m.newsletter?'<span class=\"b\">Newsletter</span>':''}</div></div>\n      </div>\n      <div class=\"wrap\">\n        <div class=\"panel\"><h3>Contato</h3>${kv('E-mail',m.email||'—')}${kv('Telefone',m.telefone||'—')}</div>\n        <div class=\"panel\"><h3>Localização</h3>${kv('Cidade/UF',`${m.cidade||'—'}${m.estado?' / '+m.estado:''}`)}${kv('CEP',m.cep||'—')}${kv('País',m.pais_origem||'—')}</div>\n        ${tem?`<div class=\"panel full\"><h3>Porsche</h3><div class=\"chips\">${porsche.length?porsche.map(p=>`<div class=\"chip\">${p[0]}: <b>${esc(p[1])}</b></div>`).join(''):'<span class=\"muted\">Sem detalhes do veículo.</span>'}</div></div>`:''}\n        <div class=\"panel\"><h3>Cadastro</h3>${kv('Código',m.member_code||'—')}${kv('Origem',m.origin||'—')}${kv('Data',m.data_cadastro?String(m.data_cadastro).slice(0,10).split('-').reverse().join('/'):'—')}${kv('Documento',m.cpf||'—')}${editor}</div>\n        <div class=\"panel full\"><h3>No Cloudfy (PDV)</h3>${(()=>{ const nrStored=m.cloudfy_nrpessoa||''; if(!nrStored) return '<div class=\"muted\">Membro não sincronizado com o Cloudfy (sem NrPessoa gravado).</div>'; const header=kv('NrPessoa (Cloudfy)',nrStored)+kv('Cod. Terceiro',m.cloudfy_codterceiro||'—'); if(st.cfyLoading) return header+'<div class=\"muted\" style=\"margin-top:8px\">Consultando Cloudfy ao vivo…</div>'; if(st.cfy) return header+kv('Situação',st.cfy.Situacao?'Ativo':'Inativo')+(st.cfyVendas!=null?kv('Compras 90d',d2.fmt.currency(st.cfyVendas,'BRL')):''); return header+'<div class=\"muted\" style=\"margin-top:8px\">Não consegui confirmar ao vivo agora (NrPessoa gravado acima, mas a consulta em tempo real falhou ou não achou nada nesse NrPessoa).</div>'; })()}</div>\n        <div class=\"panel\"><h3>Observações</h3>${notas.length?notas.map(n=>`<div class=\"li\">${esc(n.nota)}</div>`).join(''):'<div class=\"muted\">Nenhuma observação.</div>'}</div>\n      </div>\n    </div>`;\n  },\n  mounted(d2){\n    const KEY={authorization:'sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'};\n    const m=d2.param('record')||{}; const q=String(m.nome_completo||'').trim().toLowerCase();\n    const clean=v=>String(v==null?'':v).trim();\n    d2.on('.numfield','input',(e,el)=>{ d2.state.numNew=el.value; });\n    d2.on('.numsave','click',()=>{ const cur=clean(m.member_code); const nv=clean(d2.state.numNew==null?cur:d2.state.numNew);\n      if(!nv){ d2.state.numMsg='Informe um número válido.'; d2.state.numOk=false; return; }\n      if(nv===cur){ d2.state.numMsg='O número informado é igual ao atual.'; d2.state.numOk=false; return; }\n      d2.state.numNew=nv; d2.state.numConfirm=true; });\n    d2.on('.numcancel','click',()=>{ d2.state.numConfirm=false; });\n    d2.on('.numreset','click',()=>{ d2.state.numMsg=null; d2.state.numConfirm=false; d2.state.numNew=null; });\n    d2.on('.numconfirm','click',async()=>{ const cur=clean(m.member_code); const nv=clean(d2.state.numNew);\n      d2.state.numConfirm=false; d2.state.numSaving=true; d2.state.numMsg=null;\n      try{ const r=await d2.rush('member-update-number').invoke({member_code:cur,new_member_code:nv},{headers:KEY});\n        let a=r&&r.data!==undefined?r.data:r; if(a&&a.data!==undefined&&a.success===undefined)a=a.data;\n        if(a&&a.success){ m.member_code=nv; if(d2.state.cfy)d2.state.cfy.CodTerceiro=nv;\n          d2.state.numOk=true; d2.state.numMsg='Número alterado para #'+nv+' (codTerceiro atualizado no Cloudfy).'; d2.state.numNew=null; }\n        else { d2.state.numOk=false; d2.state.numMsg='Falha: '+((a&&(a.message||a.mensagem_ret))||'erro desconhecido'); }\n      }catch(e){ d2.log('numupd err',e); d2.state.numOk=false; d2.state.numMsg='Erro ao alterar número: '+(e&&e.message||e); }\n      finally{ d2.state.numSaving=false; } });\n    (async()=>{ try{ const r=await d2.rush('nota-listar').invoke({},{headers:KEY}); let a=r&&r.data!==undefined?r.data:r; if(a&&a.data!==undefined)a=a.data; const all=Array.isArray(a)?a:[]; d2.state.notas=q?all.filter(n=>String(n.alvo||'').toLowerCase().includes(q)||q.includes(String(n.alvo||'').toLowerCase())):[]; }catch(e){ d2.state.notas=[]; } })();\n    (async()=>{ const nr=String(m.cloudfy_nrpessoa||'').trim(); if(!nr){ d2.state.cfy=null; return; } d2.state.cfyLoading=true;\n      try{ const r=await d2.rush('proxy-cliente').invoke({NrPessoa:nr},{headers:KEY}); let a=r&&r.data!==undefined?r.data:r; if(a&&a.data!==undefined)a=a.data; const c=((a&&a.DadosCliente)||[])[0]; d2.state.cfy=c||null;\n        if(c&&c.NrPessoa){ const day=864e5; const hoje=new Date(); const fmt=dt=>`${dt.getFullYear()}${String(dt.getMonth()+1).padStart(2,'0')}${String(dt.getDate()).padStart(2,'0')}`; const wins=[[30,0],[60,30],[90,60]].map(p=>({DataInicio:fmt(new Date(hoje.getTime()-p[0]*day)),DataFim:fmt(new Date(hoje.getTime()-p[1]*day))})); const rs=await Promise.all(wins.map(w=>d2.rush('proxy-vendas').invoke({NrPessoa:String(c.NrPessoa),DataInicio:w.DataInicio,DataFim:w.DataFim},{headers:KEY}).catch(()=>null))); let tot=0; rs.forEach(rr=>{ if(!rr)return; let d=rr&&rr.data!==undefined?rr.data:rr; if(d&&d.data!==undefined)d=d.data; (d&&d.Vendas||[]).forEach(v=>{ tot+=Number(v.VlrTotal!=null?v.VlrTotal:v.VlrTotalPago)||0; }); }); d2.state.cfyVendas=tot; }\n      }catch(e){ d2.state.cfy=null; } finally{ d2.state.cfyLoading=false; } })();\n  }\n}"}},"record":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"record"}}}}}}}}}},{"_id":"6a34058bb4151ec9181b9988","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"MembrosScreen","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .scr{height:100%;overflow:auto;background:#0a0a0a;font-family:'Inter',system-ui,sans-serif;color:#fff;box-sizing:border-box}\n  .cold{display:flex;flex-direction:column;height:100%}\n  .detbar{padding:14px 30px;border-bottom:1px solid #2a2a2a;flex-shrink:0;display:flex;align-items:center;gap:12px}\n  .backbtn{background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;border-radius:10px;padding:9px 14px;font-size:13px;font-weight:700;cursor:pointer}\n  .backbtn:hover{border-color:#F4C400}.dbn{color:#9a9a9a;font-size:13px}\n  .detwrap{flex:1;min-height:0}\n  .head{display:flex;align-items:center;gap:14px;padding:28px 36px 18px;flex-wrap:wrap}\n  .head h2{font-family:'Anton',sans-serif;font-size:22px;letter-spacing:.08em;text-transform:uppercase;margin:0}\n  .bar{flex:1;height:1px;background:#2a2a2a;min-width:40px}\n  .tabs{display:flex;gap:8px}\n  .tab{background:transparent;border:1px solid #2a2a2a;color:#9a9a9a;padding:8px 16px;font-size:12px;letter-spacing:.12em;font-weight:600;cursor:pointer;text-transform:uppercase;border-radius:3px}\n  .tab.on{background:#F4C400;color:#000;border-color:#F4C400}\n  .search{background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;padding:9px 13px;font-size:13px;outline:none;min-width:260px;border-radius:3px}\n  .search:focus{border-color:#F4C400}\n  .sortsel{background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;padding:9px 10px;font-size:12px;outline:none;border-radius:3px;cursor:pointer}\n  .sortsel:focus{border-color:#F4C400}\n  .sortdirbtn{background:#1c1c1c;border:1px solid #2a2a2a;color:#F4C400;padding:8px 12px;font-size:13px;font-weight:700;cursor:pointer;border-radius:3px}\n  .sortdirbtn:hover{border-color:#F4C400}\n  .viewtoggle{display:flex;gap:4px;border:1px solid #2a2a2a;border-radius:3px;padding:2px}\n  .vbtn{background:transparent;border:none;color:#9a9a9a;padding:6px 10px;font-size:13px;cursor:pointer;border-radius:2px;line-height:1}\n  .vbtn.on{background:#F4C400;color:#000}\n  .list{padding:22px 36px 50px}\n  .listwrap{border:1px solid #2a2a2a;border-radius:12px;overflow:hidden}\n  .lrow{display:flex;align-items:center;gap:14px;padding:11px 16px;background:#141414;cursor:pointer;transition:.12s;border-bottom:1px solid #2a2a2a}\n  .lrow:last-child{border-bottom:none}\n  .lrow:hover{background:#1a1a1a}\n  .lph{width:54px;height:38px;border-radius:6px;flex-shrink:0;background-color:#0f0f0f;background-size:cover;background-position:center}\n  .lcode{font-family:'Anton',sans-serif;color:#F4C400;font-size:12px;letter-spacing:.1em;width:56px;flex-shrink:0}\n  .lname{font-weight:700;font-size:14px;width:200px;flex-shrink:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n  .lmeta{font-size:12px;color:#9a9a9a;width:140px;flex-shrink:0}\n  .lemail{font-size:12px;color:#7a7a7a;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n  .stats{display:flex;gap:14px;flex-wrap:wrap;padding:0 36px 6px}\n  .stat{background:#141414;border:1px solid #2a2a2a;border-left:3px solid #F4C400;padding:12px 20px;min-width:120px}\n  .stat .n{font-family:'Anton',sans-serif;font-size:26px;color:#F4C400}.stat .l{font-size:9px;letter-spacing:.18em;color:#9a9a9a;text-transform:uppercase;margin-top:4px}\n  .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:18px;padding:22px 36px 50px}\n  .mc{display:flex;flex-direction:column;background:#141414;border:1px solid #2a2a2a;border-radius:12px;overflow:hidden;cursor:pointer;transition:.12s}\n  .mc:hover{border-color:#F4C400}\n  .mph{height:150px;background-color:#0f0f0f;background-size:cover;background-position:center;border-bottom:1px solid #2a2a2a}\n  .mb{padding:14px 16px;flex:1}\n  .mcode{font-family:'Anton',sans-serif;color:#F4C400;font-size:12px;letter-spacing:.14em}\n  .mname{font-weight:700;font-size:16px;margin:3px 0 8px}\n  .mtags{display:flex;gap:6px;flex-wrap:wrap}\n  .mt{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;padding:3px 8px;border-radius:999px;background:#1c1c1c;border:1px solid #2a2a2a;color:#9a9a9a}\n  .mt.y{background:#F4C400;color:#000;border-color:#F4C400}\n  .cfy{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;padding:3px 8px;border-radius:999px;border:1px solid}\n  .cfy.on{background:rgba(61,220,132,.15);color:#3ddc84;border-color:rgba(61,220,132,.4)}\n  .cfy.off{background:rgba(255,107,107,.12);color:#ff8a8a;border-color:rgba(255,107,107,.35)}\n  .claim{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;padding:3px 8px;border-radius:999px;border:1px solid}\n  .claim.on{background:rgba(61,220,132,.15);color:#3ddc84;border-color:rgba(61,220,132,.4)}\n  .claim.off{background:#1c1c1c;color:#7a7a7a;border-color:#2a2a2a}\n  .exp{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;padding:3px 8px;border-radius:999px;border:1px solid}\n  .exp.off{background:#1c1c1c;color:#9a9a9a;border-color:#2a2a2a}\n  .exp.soon{background:rgba(244,196,0,.15);color:#F4C400;border-color:rgba(244,196,0,.4)}\n  .exp.on{background:rgba(255,90,90,.15);color:#ff5a5a;border-color:rgba(255,90,90,.4)}\n  .expbtn{background:#ff5a5a;border:1px solid #ff5a5a;color:#fff;font-size:10px;font-weight:700;padding:3px 10px;border-radius:999px;cursor:pointer;text-transform:uppercase}\n  .expbtn:hover{filter:brightness(1.1)}\n  .expconfirm{background:#ff5a5a;border:1px solid #ff5a5a;color:#fff;font-size:10px;font-weight:700;padding:3px 10px;border-radius:999px;cursor:pointer;margin-right:4px;text-transform:uppercase}\n  .expcancel{background:transparent;border:1px solid #2a2a2a;color:#9a9a9a;font-size:10px;font-weight:700;padding:3px 10px;border-radius:999px;cursor:pointer;text-transform:uppercase}\n  .open{padding:0 16px 14px;color:#F4C400;font-size:12px;font-weight:700}\n  .loading{padding:40px;color:#9a9a9a}\n  `,\n  render(d2){\n    const esc=s=>String(s==null?'':s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));\n    const fmtCpf=v=>{ const d=String(v||'').replace(/\\D/g,''); if(d.length===11) return d.replace(/(\\d{3})(\\d{3})(\\d{3})(\\d{2})/,'$1.$2.$3-$4'); if(d.length===14) return d.replace(/(\\d{2})(\\d{3})(\\d{3})(\\d{4})(\\d{2})/,'$1.$2.$3/$4-$5'); return d; };\n    const cloudfyTag=m=>`<span class=\"cfy ${m.cloudfy_synced?'on':'off'}\" title=\"${m.cloudfy_synced?'Encontrado no Cloudfy (NrPessoa '+esc(m.cloudfy_nrpessoa)+', via '+esc(m.cloudfy_check_method)+')':'Não encontrado no Cloudfy'}\">${m.cloudfy_synced?'☁ Cloudfy':'☁ Sem Cloudfy'}</span><span class=\"mt\" title=\"CPF cadastrado\">${m.cpf?'CPF '+fmtCpf(m.cpf):'Sem CPF'}</span><span class=\"mt\" title=\"Cod. Terceiro no Cloudfy\">Cod.Terc: ${esc(m.cloudfy_codterceiro||'—')}</span><span class=\"claim ${m.card_claimed?'on':'off'}\" title=\"${m.card_claimed?'Carteira digital resgatada'+(m.card_claimed_at?' em '+esc(String(m.card_claimed_at).slice(0,10).split('-').reverse().join('/')):''):'Ainda não resgatou a carteira digital'}\">${m.card_claimed?'✓ Resgatado':'○ Não resgatado'}</span>`;\n    const dayMs=86400000;\n    const expInfo=m=>{\n      if(!m.data_cadastro) return {label:'Sem data adesão', days:null, cls:'off', canExpire:false};\n      const start=new Date(m.data_cadastro);\n      const expDate=new Date(start.getTime()+365*dayMs);\n      const days=Math.ceil((expDate.getTime()-Date.now())/dayMs);\n      if(m.membership_expired) return {label:'Expirado (marcado)', days, cls:'off', canExpire:false};\n      if(days<0) return {label:'Expirado há '+(-days)+'d', days, cls:'on', canExpire:true};\n      if(days<=30) return {label:'Expira em '+days+'d', days, cls:'soon', canExpire:false};\n      return {label:'Expira em '+days+'d', days, cls:'off', canExpire:false};\n    };\n    const expTag=m=>{\n      const info=expInfo(m);\n      const dateStr=m.data_cadastro?esc(String(m.data_cadastro).slice(0,10).split('-').reverse().join('/')):'—';\n      const badge=`<span class=\"exp ${info.cls}\" title=\"Adesão: ${dateStr}\">⏳ ${esc(info.label)}</span>`;\n      if(!info.canExpire) return badge;\n      const code=m.member_code||'';\n      if(d2.state.expiring===code) return badge+`<span class=\"mt\">Expirando…</span>`;\n      if(d2.state.confirmExpire===code) return badge+`<button class=\"expconfirm\" data-code=\"${esc(code)}\">Confirmar</button><button class=\"expcancel\">Cancelar</button>`;\n      return badge+`<button class=\"expbtn\" data-code=\"${esc(code)}\" title=\"Marcar expirado + avisar no Cloudfy\">✕ Expirar</button>`;\n    };\n    const st=d2.state; const sel=st.sel;\n    if(sel) return `<div class=\"scr cold\"><div class=\"detbar\"><button class=\"backbtn\">← Voltar</button><span class=\"dbn\">${esc(sel.nome_completo||'')}</span></div><div class=\"detwrap\">${d2.render('adonis@MemberDetail',{record:sel},{key:'mdet'})}</div></div>`;\n    const members=st.members||[]; const f=st.filter||'all'; const q=(st.q||'').trim().toLowerCase();\n    let list=f==='all'?members:f==='EXPIRING'?members.filter(m=>{ if(!m.data_cadastro||m.membership_expired) return false; const days=Math.ceil((new Date(new Date(m.data_cadastro).getTime()+365*86400000).getTime()-Date.now())/86400000); return days<=30; }):members.filter(m=>String(m.tipo_cadastro||'').toUpperCase()===f);\n    if(q)list=list.filter(m=>[m.nome_completo,m.email,m.member_code,m.cidade].join(' ').toLowerCase().includes(q));\n    if(st.loading) return `<div class=\"scr\"><div class=\"loading\">Carregando membros…</div></div>`;\n    if(st.err) return `<div class=\"scr\"><div class=\"loading\" style=\"color:#ffce7a\">${esc(st.err)}</div></div>`;\n    const view=st.view||'grid';\n    const sortBy=st.sortBy||'nome'; const sortDir=st.sortDir||'asc'; const sdir=sortDir==='asc'?1:-1;\n    const sortKey=m=>{ if(sortBy==='codigo') return parseInt(m.member_code,10)||0; if(sortBy==='cidade') return (m.cidade||'').toLowerCase(); if(sortBy==='tier') return (m.tipo_cadastro||'').toUpperCase(); return (m.nome_completo||'').toLowerCase(); };\n    list=list.slice().sort((a,b)=>{ const ka=sortKey(a),kb=sortKey(b); if(ka<kb) return -1*sdir; if(ka>kb) return 1*sdir; return 0; });\n    const founders=members.filter(m=>String(m.tipo_cadastro||'').toUpperCase()==='FOUNDER').length;\n    const cards=list.map(m=>`<div class=\"mc\" data-code=\"${esc(m.member_code||'')}\"><div class=\"mph\" style=\"background-image:url('${esc(m.car_image||'')}')\"></div><div class=\"mb\"><div class=\"mcode\">#${esc(m.member_code||'—')}</div><div class=\"mname\">${esc(m.nome_completo||'—')}</div><div class=\"mtags\"><span class=\"mt y\">${esc(m.tipo_cadastro||'MEMBER')}</span>${cloudfyTag(m)}${expTag(m)}${m.cidade?`<span class=\"mt\">${esc(m.cidade)}${m.estado?'/'+esc(m.estado):''}</span>`:''}${m.tem_porsche?`<span class=\"mt\">${esc(m.modelo_porsche||'Porsche')}</span>`:''}</div></div><span class=\"open\">Abrir ›</span></div>`).join('');\n    const rows=list.map(m=>`<div class=\"lrow\" data-code=\"${esc(m.member_code||'')}\"><div class=\"lph\" style=\"background-image:url('${esc(m.car_image||'')}')\"></div><div class=\"lcode\">#${esc(m.member_code||'—')}</div><div class=\"lname\">${esc(m.nome_completo||'—')}</div><span class=\"mt y\">${esc(m.tipo_cadastro||'MEMBER')}</span>${cloudfyTag(m)}${expTag(m)}<div class=\"lmeta\">${m.cidade?esc(m.cidade)+(m.estado?'/'+esc(m.estado):''):''}</div><div class=\"lemail\">${esc(m.email||'')}</div><span class=\"open\">Abrir ›</span></div>`).join('');\n    return `<div class=\"scr\"><div class=\"head\"><h2>Membros</h2><div class=\"bar\"></div><div class=\"tabs\"><button class=\"tab ${f==='all'?'on':''}\" data-f=\"all\">Todos</button><button class=\"tab ${f==='FOUNDER'?'on':''}\" data-f=\"FOUNDER\">Founders</button><button class=\"tab ${f==='MEMBER'?'on':''}\" data-f=\"MEMBER\">Membros</button><button class=\"tab ${f==='EXPIRING'?'on':''}\" data-f=\"EXPIRING\">Expirando</button></div><input class=\"search q\" placeholder=\"Buscar nome, e-mail, código…\" value=\"${esc(st.q||'')}\"><select class=\"sortsel\"><option value=\"nome\" ${sortBy==='nome'?'selected':''}>Nome</option><option value=\"codigo\" ${sortBy==='codigo'?'selected':''}>Código</option><option value=\"tier\" ${sortBy==='tier'?'selected':''}>Tier</option><option value=\"cidade\" ${sortBy==='cidade'?'selected':''}>Cidade</option></select><button class=\"sortdirbtn\" title=\"Inverter ordem\">${sdir===1?'↑':'↓'}</button><div class=\"viewtoggle\"><button class=\"vbtn ${view==='grid'?'on':''}\" data-v=\"grid\" title=\"Grade\">▦</button><button class=\"vbtn ${view==='list'?'on':''}\" data-v=\"list\" title=\"Lista\">≡</button></div></div>\n      <div class=\"stats\"><div class=\"stat\"><div class=\"n\">${members.length}</div><div class=\"l\">Membros</div></div><div class=\"stat\"><div class=\"n\">${founders}</div><div class=\"l\">Founders</div></div></div>\n      ${view==='list'?`<div class=\"list\"><div class=\"listwrap\">${rows||'<div class=\"loading\">Nenhum membro neste filtro.</div>'}</div></div>`:`<div class=\"grid\">${cards||'<div class=\"loading\">Nenhum membro neste filtro.</div>'}</div>`}</div></div>`;\n  },\n  mounted(d2){\n    const KEY={authorization:'sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'};\n    const load=async()=>{ d2.state.loading=true; d2.state.err=null;\n      try{ const r=await d2.rush(d2.params.listMembers||'list-members').invoke({limit:500},{headers:KEY}); const d=r&&r.data!==undefined?r.data:r; d2.state.members=(d&&d.members)||[]; }\n      catch(e){ d2.log('membros err',e); d2.state.err='Erro ao carregar membros: '+(e&&e.message||e); } finally{ d2.state.loading=false; } };\n    load();\n    d2.on('.tab','click',(e,el)=>{ d2.state.filter=el.dataset.f; });\n    let qT; d2.on('.q','input',(e,el)=>{ clearTimeout(qT); const v=el.value; qT=setTimeout(()=>{d2.state.q=v;},200); });\n    d2.on('.mc','click',(e,el)=>{ if(e.target.closest('.expbtn,.expconfirm,.expcancel')) return; const code=el.dataset.code; const rec=(d2.state.members||[]).find(m=>String(m.member_code)===String(code)); if(rec) d2.state.sel=rec; });\n    d2.on('.lrow','click',(e,el)=>{ if(e.target.closest('.expbtn,.expconfirm,.expcancel')) return; const code=el.dataset.code; const rec=(d2.state.members||[]).find(m=>String(m.member_code)===String(code)); if(rec) d2.state.sel=rec; });\n    d2.on('.vbtn','click',(e,el)=>{ d2.state.view=el.dataset.v; });\n    d2.on('.sortsel','change',(e,el)=>{ d2.state.sortBy=el.value; });\n    d2.on('.sortdirbtn','click',()=>{ d2.state.sortDir=(d2.state.sortDir||'asc')==='asc'?'desc':'asc'; });\n    d2.on('.expbtn','click',(e,el)=>{ e.stopPropagation(); d2.state.confirmExpire=el.dataset.code; });\n    d2.on('.expcancel','click',(e)=>{ e.stopPropagation(); d2.state.confirmExpire=null; });\n    d2.on('.expconfirm','click',async(e,el)=>{ e.stopPropagation(); const code=el.dataset.code; d2.state.confirmExpire=null; d2.state.expiring=code;\n      try{ const today=new Date().toISOString().slice(0,10); const r=await d2.rush('member-expire').invoke({member_code:code,today},{headers:KEY});\n        const a=r&&r.data!==undefined?r.data:r; if(!a||!a.success){ d2.log('expire failed',a); } }\n      catch(err){ d2.log('expire err',err); } finally{ d2.state.expiring=null; load(); } });\n    d2.on('.backbtn','click',()=>{ d2.state.sel=null; });\n  }\n}"}},"listMembers":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"listMembers"}}}},"memberCard":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"memberCard"}}}}}}}}}},{"_id":"6a340fb4293ce144a47fc28e","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"AgenteScreen","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .ag{display:flex;flex-direction:column;height:100%;background:#0a0a0a;font-family:'Inter',system-ui,sans-serif;color:#fff;box-sizing:border-box}\n  .hd{display:flex;align-items:center;gap:14px;padding:24px 30px 14px}\n  .hd h2{font-family:'Anton',sans-serif;font-size:22px;letter-spacing:.08em;text-transform:uppercase;margin:0}\n  .hd .sm{font-size:11px;color:#9a9a9a;letter-spacing:.1em;font-weight:600}\n  .log{flex:1;overflow:auto;padding:10px 30px;display:flex;flex-direction:column;gap:10px}\n  .msg{max-width:78%;padding:11px 15px;border-radius:14px;font-size:14px;line-height:1.5;white-space:pre-wrap;word-break:break-word}\n  .me{align-self:flex-end;background:#F4C400;color:#000;font-weight:600}\n  .bot{align-self:flex-start;background:#141414;border:1px solid #2a2a2a;color:#f4f4f5}\n  .syn{align-self:flex-start;max-width:560px;background:#141414;border:1px solid #2a2a2a;border-left:3px solid #F4C400;color:#f4f4f5;font-size:14.5px;padding:13px 16px;border-radius:14px;line-height:1.55;word-break:break-word}\n  .syn p{margin:0 0 8px}.syn p:last-child{margin:0}\n  .syn ul{margin:6px 0;padding-left:18px}.syn li{margin:3px 0}\n  .syn b,.syn strong{color:#fff;font-weight:700}\n  .cards{align-self:flex-start;max-width:560px;width:100%;display:flex;flex-direction:column;gap:7px}\n  .sec{font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:#9a9a9a;font-weight:700;margin:2px 0}\n  .rc{background:#141414;border:1px solid #2a2a2a;border-left:3px solid #F4C400;border-radius:8px;padding:9px 12px;font-size:13px}\n  .rc .t{font-weight:700;font-size:14px}.rc .s{color:#9a9a9a;margin-top:3px;font-size:12px}\n  .acard{display:flex;align-items:center;gap:12px;width:100%;text-align:left;background:#141414;border:1px solid #2a2a2a;border-radius:11px;padding:11px 14px;cursor:pointer;transition:.12s;color:#fff}\n  .acard:hover{border-color:#F4C400;background:#181818;transform:translateX(2px)}\n  .acard .ai{width:38px;height:38px;border-radius:50%;background:#F4C400;color:#000;font-weight:800;font-size:13px;display:flex;align-items:center;justify-content:center;flex-shrink:0}\n  .acard .ab{flex:1;min-width:0;display:flex;flex-direction:column}\n  .acard .ab .t{font-weight:700;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .acard .ab .s{color:#9a9a9a;font-size:12px;margin-top:2px}\n  .acard .chev{color:#F4C400;font-size:20px;font-weight:700;flex-shrink:0}\n  .pickwrap,.confwrap{align-self:flex-start;max-width:560px;width:100%;display:flex;flex-direction:column;gap:7px}\n  .pickbtn{display:flex;align-items:center;gap:12px;text-align:left;background:#141414;border:1px solid #2a2a2a;border-radius:11px;padding:11px 14px;font-size:13px;cursor:pointer;color:#fff}\n  .pickbtn:hover{border-color:#F4C400;background:#181818}\n  .pickbtn .ai{width:34px;height:34px;border-radius:50%;background:#F4C400;color:#000;font-weight:800;font-size:12px;display:flex;align-items:center;justify-content:center;flex-shrink:0}\n  .pickbtn .pb{flex:1}.pickbtn .pb .t{font-weight:700;font-size:14px}.pickbtn .pb .s{color:#9a9a9a;font-size:12px;margin-top:2px}\n  .confwrap{flex-direction:row}\n  .cy{background:#F4C400;color:#000;border:0;border-radius:9px;padding:10px 20px;font-size:13px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;cursor:pointer}\n  .cn{background:#1c1c1c;border:1px solid #2a2a2a;color:#9a9a9a;border-radius:9px;padding:10px 18px;font-size:13px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;cursor:pointer}\n  .think{align-self:flex-start;color:#9a9a9a;font-size:13px;display:flex;align-items:center;gap:8px;padding:6px 2px}\n  .think .dots{letter-spacing:2px;animation:bl 1s infinite}\n  @keyframes bl{0%,100%{opacity:.3}50%{opacity:1}}\n  .empty{color:#5a5a5a;text-align:center;margin:auto;padding:34px;font-size:13px;max-width:520px;line-height:1.8}\n  .row{display:flex;gap:10px;padding:14px 30px;border-top:1px solid #2a2a2a}\n  .row input{flex:1;background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;padding:13px 15px;font-size:14px;border-radius:10px;outline:none}\n  .row input:focus{border-color:#F4C400}\n  .row button{background:#F4C400;color:#000;border:0;border-radius:10px;padding:0 22px;font-size:13px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;cursor:pointer}\n  .row button:disabled{opacity:.4}\n  .ovbar{display:flex;align-items:center;gap:12px;padding:14px 24px;border-bottom:1px solid #2a2a2a;flex-shrink:0}\n  .ovback{background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;border-radius:10px;padding:9px 14px;font-size:13px;font-weight:700;cursor:pointer}\n  .ovback:hover{border-color:#F4C400}.ovt{color:#9a9a9a;font-size:13px}\n  .ovbody{flex:1;min-height:0}\n  `,\n  render(d2){\n    const esc=s=>String(s==null?'':s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));\n    const aesc=s=>esc(s).replace(/\"/g,'&quot;');\n    const ini=s=>{ try{ return d2.fmt.initials(String(s||''),2); }catch(e){ return String(s||'?').trim().slice(0,2).toUpperCase(); } };\n    const mdi=s=>esc(s).replace(/\\*\\*([^*]+)\\*\\*/g,'<b>$1</b>').replace(/(^|[^*])\\*([^*\\n]+)\\*/g,'$1<em>$2</em>');\n    const md=t=>{ const ls=String(t==null?'':t).split(/\\r?\\n/); let h='',inl=false; for(const ln of ls){ const x=ln.trim(); if(/^[-•]\\s+/.test(x)||/^\\*\\s+/.test(x)){ if(!inl){h+='<ul>';inl=true;} h+='<li>'+mdi(x.replace(/^[-•*]\\s+/,''))+'</li>'; } else { if(inl){h+='</ul>';inl=false;} if(x)h+='<p>'+mdi(x)+'</p>'; } } if(inl)h+='</ul>'; return h; };\n    if(d2.state.detail){ const det=d2.state.detail; const comp=det.type==='membro'?'adonis@MemberDetail':'adonis@ClienteDetail'; const nm=det.record&&(det.record.Nome||det.record.nome_completo)||'';\n      return `<div class=\"ag\"><div class=\"ovbar\"><button class=\"ovback\">← Voltar ao agente</button><span class=\"ovt\">${esc(nm)}</span></div><div class=\"ovbody\">${d2.render(comp,{record:det.record},{key:'agdet'})}</div></div>`;\n    }\n    const msgs=d2.state.msgs||[]; const busy=!!d2.state.busy; const phase=d2.state.phase||'';\n    let body;\n    if(!msgs.length && !busy){\n      body=`<div class=\"empty\"><b style=\"color:#9a9a9a\">O agente consulta reservas, ocupação, entrada, clientes, membros, vendas e catálogo.</b><br><br>• \"quais as reservas de hoje?\" · \"achar a reserva da Ana\"<br>• \"como está a ocupação hoje?\" · \"tem mesa pra amanhã no jantar?\"<br>• \"quem entrou hoje?\" · \"walk-ins de hoje\" · \"resumo do dia\"<br>• \"o João chegou\" (acha em reservas/membros/clientes e senta/registra) · \"registra walk-in pro Luis, 2 pessoas\"<br>• \"me fala tudo sobre o cliente João\"<br>• \"lista de membros\" · \"valida o membro 0261\"<br>• \"quem está na lista de entrada hoje?\" · \"busca o José na entrada\"<br>• \"quais memberships temos no catálogo?\"<br>• \"cria uma reserva pro João amanhã 20h pra 2 telefone 11...\" · \"cancela a reserva da Ana hoje\"<br>• \"confirma a reserva do Pedro\" · \"senta a mesa do Lucas\"<br>• \"muda o telefone da Ana pra 11...\" · \"torna o João membro\"<br><br><span style=\"color:#5a5a5a\">Toda ação de escrita pede sua confirmação antes de gravar.</span></div>`;\n    } else {\n      body=msgs.map(m=>{\n        if(m.role==='user') return `<div class=\"msg me\">${esc(m.text)}</div>`;\n        if(m.role==='syn') return `<div class=\"syn\">${md(m.text)}</div>`;\n        if(m.role==='confirm') return `<div class=\"msg bot\"><b style=\"color:#F4C400\">Confirmar?</b><br>${(m.items||[]).map(x=>'• '+esc(x)).join('<br>')}</div><div class=\"confwrap\"><button class=\"cy\">Confirmar</button><button class=\"cn\">Cancelar</button></div>`;\n        if(m.role==='wconfirm') return `<div class=\"msg bot\"><b style=\"color:#F4C400\">${esc(m.title||'Confirmar ação?')}</b><br>${(m.items||[]).map(x=>'• '+esc(x)).join('<br>')}</div><div class=\"confwrap\"><button class=\"wy\">Confirmar</button><button class=\"wn\">Cancelar</button></div>`;\n        if(m.role==='nav') return `<div class=\"cards\"><button class=\"acard navbtn\" data-tab=\"${aesc(m.tab)}\"><span class=\"ai\">→</span><span class=\"ab\"><span class=\"t\">${esc(m.t)}</span><span class=\"s\">${esc(m.s)}</span></span><span class=\"chev\">›</span></button></div>`;\n        if(m.role==='confirmfree') return `<div class=\"msg bot\"><b style=\"color:#ffce7a\">Atenção</b><br>${esc((m.items||[])[0]||'')}</div><div class=\"confwrap\"><button class=\"cfreey\">Salvar assim</button><button class=\"cfreen\">Cancelar</button></div>`;\n        if(m.role==='pick') return `<div class=\"msg bot\">${esc(m.text)}</div><div class=\"pickwrap\">${(m.items||[]).map(c=>`<button class=\"pickbtn\" data-nr=\"${aesc(c.nr==null?'':c.nr)}\" data-nome=\"${aesc(c.nome||'')}\"><span class=\"ai\">${esc(ini(c.nome))}</span><span class=\"pb\"><span class=\"t\">${esc(c.nome)}</span><span class=\"s\">${c.doc?esc(c.doc):''}${c.nr?' · Nr '+esc(c.nr):''}</span></span></button>`).join('')}</div>`;\n        if(m.role==='cards'){ const it=(m.items||[]).map(c=> m.click\n            ? `<button class=\"acard\" data-key=\"${aesc(c.key)}\"><span class=\"ai\">${esc(ini(c.t))}</span><span class=\"ab\"><span class=\"t\">${esc(c.t)}</span><span class=\"s\">${esc(c.s)}</span></span><span class=\"chev\">›</span></button>`\n            : `<div class=\"rc\"><div class=\"t\">${esc(c.t)}</div><div class=\"s\">${esc(c.s)}</div></div>`).join('');\n          return `<div class=\"cards\">${m.title?`<div class=\"sec\">${esc(m.title)}</div>`:''}${it}</div>`; }\n        return `<div class=\"msg bot\">${esc(m.text)}</div>`;\n      }).join('');\n      if(busy) body+=`<div class=\"think\"><span class=\"dots\">●●●</span> ${esc(phase||'Pensando…')}</div>`;\n    }\n    return `<div class=\"ag\"><div class=\"hd\"><h2>Agente</h2><span class=\"sm\">ASSISTENTE INTERNO</span><span style=\"flex:1\"></span>${msgs.length?'<button class=\"newchat\" style=\"background:#1c1c1c;border:1px solid #2a2a2a;color:#9a9a9a;border-radius:8px;padding:7px 12px;font-size:12px;font-weight:600;cursor:pointer;text-transform:uppercase;letter-spacing:.06em\">＋ Nova conversa</button>':''}</div><div class=\"log\">${body}</div><div class=\"row\"><input class=\"in\" placeholder=\"Pergunte ao agente…\" ${busy?'disabled':''} autocomplete=\"off\"><button class=\"send\" ${busy?'disabled':''}>Enviar</button></div></div>`;\n  },\n  mounted(d2){\n    const KEY={authorization:'sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'};\n    const BEARER={authorization:'Bearer sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'};\n    const push=(m)=>{ d2.state.msgs=[...(d2.state.msgs||[]),m]; };\n    const reg=(k,type,record)=>{ const i=d2.state.index||{}; i[k]={type,record}; d2.state.index=i; };\n    const setPhase=(p)=>{ d2.state.phase=p; };\n    const norm=s=>String(s||'').trim().toLowerCase();\n    const decode=s=>String(s||'').replace(/&amp;/g,'&').replace(/&#8211;/g,'–').replace(/&#038;/g,'&').replace(/&#8217;/g,'’');\n    const unwrap=r=>{ let d=r&&r.data!==undefined?r.data:r; if(d&&d.data!==undefined)d=d.data; return d; };\n    const saveNota=async(nome,nr,nota)=>{ await d2.rush('nota-salvar').invoke({alvo:nome,nrPessoa:nr||null,nota:nota,criadoEm:Date.now()},{headers:KEY}); };\n    const fetchCliente=async(termo)=>{ const q=(termo||'').trim(); if(!q) return []; const dig=q.replace(/\\D/g,'');\n      if(dig.length>=11||/^\\d+$/.test(q)){ const b=dig.length>=11?{CpfCnpj:dig}:{NrPessoa:q}; const d=unwrap(await d2.rush('proxy-cliente').invoke(b,{headers:KEY})); return (d&&d.DadosCliente)||[]; }\n      const d=unwrap(await d2.rush('proxy-cliente').invoke({},{headers:KEY})); const all=(d&&d.DadosCliente)||[]; const n=norm(q); return all.filter(c=>norm(c.Nome).includes(n)).slice(0,12); };\n    const listMembros=async()=>{ const r=await d2.rush('list-members').invoke({limit:500},{headers:KEY}); const d=r&&r.data!==undefined?r.data:r; return (d&&d.members)||[]; };\n    const fetchVendas=async(nr)=>{ const day=864e5; const hoje=new Date(); const fmt=dt=>`${dt.getFullYear()}${String(dt.getMonth()+1).padStart(2,'0')}${String(dt.getDate()).padStart(2,'0')}`;\n      const wins=[[30,0],[60,30],[90,60]].map(p=>({DataInicio:fmt(new Date(hoje.getTime()-p[0]*day)),DataFim:fmt(new Date(hoje.getTime()-p[1]*day))}));\n      const rs=await Promise.all(wins.map(w=>d2.rush('proxy-vendas').invoke({NrPessoa:String(nr),DataInicio:w.DataInicio,DataFim:w.DataFim},{headers:KEY}).catch(()=>null)));\n      const all=[]; rs.forEach(r=>{ if(!r)return; const d=unwrap(r); (d&&d.DadosVenda||[]).forEach(v=>all.push(v)); }); return all; };\n    const fetchProdutos=async()=>{ const r=await d2.rush('proxy-products').invoke({},{headers:KEY}); const d=r&&r.data!==undefined?r.data:r; return Array.isArray(d)?d:((d&&d.products)||[]); };\n    const fetchNotas=async(alvo)=>{ try{ const arr=unwrap(await d2.rush('nota-listar').invoke({},{headers:KEY}))||[]; const all=Array.isArray(arr)?arr:[]; const q=norm(alvo); return q?all.filter(n=>norm(n.alvo).includes(q)||q.includes(norm(n.alvo))):[]; }catch(e){ return []; } };\n    const fetchEntrada=async()=>{ const r=await d2.rush('entrada-lista').invoke({},{headers:KEY}); const d=r&&r.data!==undefined?r.data:r; return {total:(d&&d.total)||0,entrados:(d&&d.entrados)||0,entradas:(d&&d.entradas)||[]}; };\n    const VENUE='69fcd30c55153376bd62ca81';\n    const ACTOR='6a3d1f42b40a901a4bd7c45b';\n    const SECTION_FALLBACK='69fe36ffb86391658ca82e08';\n    const navEmit=(tab)=>{ try{ d2.emit('onNavigate',tab); }catch(e){ d2.log('nav emit err',e); } };\n    const tagmeWrite=async(path,method,payload)=>{ const r=await d2.rush('tagme-write').invoke({path,method,payload},{headers:KEY}); const d=r&&r.data!==undefined?r.data:r; return d; };\n    // find a reservation on a given day by name/phone, excluding already-canceled\n    const findReserva=async(termo,data)=>{ const rs=await fetchReservas(data).catch(()=>[]); const q=norm(termo); const dig=String(termo||'').replace(/\\D/g,''); const hit=rs.filter(r=>r&&r.status!=='Canceled').filter(r=>{ const nm=norm(resName(r.customer)); const ph=String((r.customer&&r.customer.phone)||'').replace(/\\D/g,''); return q&&(nm.includes(q))||(dig.length>=4&&ph.includes(dig)); }); return hit; };\n    // load /Seat config: schedules (shift validity), section, maxParty\n    const loadSeatCfg=async()=>{ if(d2.state.seatCfg) return d2.state.seatCfg; const r=await d2.rush('tagme-read').invoke({path:`/Seat/${VENUE}`},{headers:BEARER}); const dd=r&&r.data!==undefined?r.data:r; const arr=(dd&&dd.data!==undefined)?dd.data:dd; const seat=Array.isArray(arr)?arr[0]:arr; const ba=(seat&&seat.bookingApps&&seat.bookingApps[0])||{}; const app=ba.app||{}; const sections=(app.venueSections||(seat&&seat.venueSections)||[]); const sec0=sections[0]||{}; const caps=sec0.capacityGroups||[]; const cfg={ schedules:Array.isArray(ba.schedules)?ba.schedules:[], section:app.section||sec0._id||SECTION_FALLBACK, maxParty:caps.reduce((mx,g)=>Math.max(mx,Number(g.max)||0),0)||0 }; d2.state.seatCfg=cfg; return cfg; };\n    const weekdayOf=(dayStr)=>{ if(!dayStr||!/^\\d{4}-\\d{2}-\\d{2}$/.test(dayStr))return 0; const [y,m,dd]=dayStr.split('-').map(Number); const js=new Date(y,m-1,dd).getDay(); return js===0?7:js; };\n    const shiftHit=(cfg,dayStr,time)=>{ if(!time||!/^\\d{2}:\\d{2}$/.test(time))return null; const wd=weekdayOf(dayStr); const list=(cfg.schedules||[]).filter(s=>Number(s.day)===wd).sort((a,b)=>String(a.start).localeCompare(String(b.start))); for(const sh of list){ if(time>=sh.start && time<sh.end) return sh; } return null; };\n    // lookup TAGME customer by phone — returns array with real _id\n    const lookupCustomerByPhone=async(phone)=>{ const raw=String(phone||'').replace(/[^0-9]/g,''); if(!raw)return []; const r=await d2.rush('tagme-read').invoke({path:`/Customer?limit=10&phone=%2B${raw}`},{headers:BEARER}); const dd=r&&r.data!==undefined?r.data:r; const arr=(dd&&dd.data!==undefined)?dd.data:dd; return Array.isArray(arr)?arr.filter(x=>x&&x._id):[]; };\n    // ---- write executors (proven contracts from ReservasScreen) ----\n    const doReservaCriar=async(cust,day,time,size,cfg)=>{ const SEC=cfg.section||SECTION_FALLBACK; const payload={ reservationDay:`${day}T03:00:00.000Z`, venue:VENUE, origin:{name:'Whatsapp',label:'whatsapp'}, type:'Regular', tags:[], status:'New', section:SEC, partySize:size, table:null, reservationTime:time, note:'Adicionado pelo Painel TEMPO', customer:{ _id:cust._id, name:cust.name, lastName:cust.lastName, phone:cust.phone, email:cust.email }, logs:{ user:ACTOR, actionType:'Add' } }; return tagmeWrite(`/Reservation/${VENUE}`,'POST',payload); };\n    const doReservaConfirmar=async(r)=>tagmeWrite(`/Reservation/${r._id}`,'PUT',{ _id:r._id, status:'Confirmed', logs:{ user:ACTOR, actionType:'Update' } });\n    const doReservaSentar=async(r)=>tagmeWrite(`/Reservation/${VENUE}/${r._id}/Seat`,'PUT',{ table:null, note:'', vouchers:[], logs:{ user:ACTOR, actionType:'Seat' }, originalReservationData:r });\n    const doReservaCancelar=async(r)=>tagmeWrite(`/Reservation/${VENUE}/${r._id}/Cancel`,'PUT',{ cancelReason:'Customer Requested', logs:{ user:ACTOR, actionType:'Remove' }, originalReservationData:r });\n    // Walk-in na TAGME (cliente identificado por telefone — _id real, nunca telefone inventado)\n    const doWalkinCriar=async(cust,size)=>{ const payload={ venue:VENUE, partySize:size||1, origin:{label:'Restaurant'}, note:'Walk-in via Painel TEMPO', customer:{ _id:cust._id, name:cust.name, lastName:cust.lastName, phone:cust.phone }, seatedAt:new Date().toISOString(), logs:{ user:ACTOR, actionType:'Add' } }; return tagmeWrite(`/WalkIn/${VENUE}`,'POST',payload); };\n    const doEditarTelefone=async(c,phone)=>{ const dig=String(phone||'').replace(/\\D/g,''); const ddd=dig.length>=11?dig.slice(0,2):(dig.length===10?dig.slice(0,2):''); const cel=dig.length>=11?dig.slice(2):(dig.length===10?dig.slice(2):dig); const r=await d2.rush('proxy-cliente-salvar').invoke({Acao:'U',NrPessoa:String(c.NrPessoa),CodTerceiro:c.CodTerceiro||'',DDDCelular:ddd,Celular:cel,Email:c.Email||'',Sexo:c.Sexo||''},{headers:KEY}); return r&&r.data!==undefined?r.data:r; };\n    const ymdParts=s=>{ const m=/^(\\d{4})-(\\d{2})-(\\d{2})/.exec(String(s||'')); if(m) return {y:+m[1],mo:+m[2],d:+m[3],iso:`${m[1]}-${m[2]}-${m[3]}`}; const t=new Date(); return {y:t.getFullYear(),mo:t.getMonth()+1,d:t.getDate(),iso:`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,'0')}-${String(t.getDate()).padStart(2,'0')}`}; };\n    const tagmeRead=async(path)=>{ const r=await d2.rush('tagme-read').invoke({path},{headers:BEARER}); const d=r&&r.data!==undefined?r.data:r; return (d&&d.data!==undefined)?d.data:d; };\n    const fetchReservas=async(data)=>{ const p=ymdParts(data); const arr=await tagmeRead(`/Reservation/List/${VENUE}/${p.y}/${p.mo}/${p.d}?isArray=true`).catch(()=>[]); return Array.isArray(arr)?arr:[]; };\n    const fetchOcupacao=async(data)=>{ const p=ymdParts(data); const arr=await tagmeRead(`/ReservationStatus/${VENUE}/${p.iso}/${p.iso}/dayRangeShifts`).catch(()=>[]); const day=(Array.isArray(arr)?arr:[])[0]||{}; const shifts=[]; ((day.sections)||[]).forEach(sec=>((sec.shifts)||[]).forEach(sh=>{ const lbl=(sh.label&&(sh.label.pt||sh.label))||sh.slug||''; shifts.push({turno:lbl,seats:sh.seats||0,freeSeats:sh.freeSeats==null?(sh.seats||0):sh.freeSeats,reservas:sh.reservationsQuantity||0,clientes:sh.customersQuantity||0}); })); return {data:p.iso,shifts}; };\n    const fetchWalkins=async(data)=>{ const p=ymdParts(data); const arr=await tagmeRead(`/WalkIn/${VENUE}/byVenueId?yearMonthDay=${p.iso}`).catch(()=>[]); return Array.isArray(arr)?arr:[]; };\n    // TAGME-backed \"quem entrou hoje\" — reservas sentadas + walk-ins (substitui a lista local legada)\n    const fetchEntradaHoje=async(data)=>{ const p=ymdParts(data); const [rs,ws]=await Promise.all([fetchReservas(p.iso).catch(()=>[]),fetchWalkins(p.iso).catch(()=>[])]);\n      const sentadas=(rs||[]).filter(r=>r&&r.status==='Seated').map(r=>({nome:resName(r.customer),pax:r.partySize||1,hora:r.reservationTime||'',tipo:'reserva'}));\n      const walkins=(ws||[]).map(w=>({nome:resName(w.customer),pax:w.partySize||1,hora:(w.seatedAt?String(w.seatedAt).slice(11,16):''),tipo:'walk-in'}));\n      const itens=[...sentadas,...walkins]; const pax=itens.reduce((s,x)=>s+(Number(x.pax)||0),0);\n      return {data:p.iso,sentadas:sentadas.length,walkins:walkins.length,total:itens.length,pax,itens}; };\n    const fetchResumoDia=async(data)=>{ const p=ymdParts(data); const arr=await tagmeRead(`/Report/dailySummary/${VENUE}?startDate=${p.iso}&endDate=${p.iso}`).catch(()=>null); return arr; };\n    const fetchEntradaBuscar=async(q)=>{ if(!q)return {total:0,resultados:[]}; const r=await d2.rush('entrada-buscar').invoke({q:String(q)},{headers:KEY}); const d=r&&r.data!==undefined?r.data:r; return {total:(d&&d.total)||0,resultados:(d&&d.resultados)||[]}; };\n    const getMember=async(code)=>{ if(!code)return null; const r=await d2.rush('get-member').invoke({member_code:String(code)},{headers:KEY}); const d=r&&r.data!==undefined?r.data:r; return (d&&d.success)?d:(d||null); };\n    const clientesSemTelefone=async()=>{ const d=unwrap(await d2.rush('proxy-cliente').invoke({},{headers:KEY})); const all=(d&&d.DadosCliente)||[]; const sem=all.filter(c=>{ const t=`${c.DDDTelefone||''}${c.Telefone||''}`.replace(/\\D/g,''); return !t; }); return {total:sem.length,total_clientes:all.length,lista:sem}; };\n    const resName=c=>`${(c&&c.name)||''}${c&&c.lastName?(' '+c.lastName):''}`.trim()||'—';\n    const statusPt=s=>({Confirmed:'Confirmada',Canceled:'Cancelada',Seated:'Sentou',NoShow:'No-show',Pending:'Pendente',WaitList:'Lista de espera',Finished:'Finalizada'}[s]||s||'');\n    const preco=p=>{ try{ return p.prices&&p.prices.price?('R$ '+(Number(p.prices.price)/Math.pow(10,p.prices.currency_minor_unit||2)).toLocaleString('pt-BR')):''; }catch(e){ return ''; } };\n    const startNota=async(nota,alvo)=>{ d2.state.busy=true; setPhase('Procurando o cliente…');\n      try{ const cand=alvo?await fetchCliente(alvo).catch(()=>[]):[];\n        if(cand.length){ d2.state.pending={nota}; push({role:'pick',text:`Sobre quem é a observação \"${nota}\"? Escolha o cliente:`,items:cand.slice(0,10).map(c=>({nr:c.NrPessoa,nome:c.Nome,doc:c.CpfCnpj}))}); }\n        else{ d2.state.pendingFree={nota,alvo}; push({role:'confirmfree',items:[`Não encontrei \"${alvo||'esse cliente'}\" no Cloudfy. Salvar a observação sem vincular (sem ID forte)?`]}); }\n      } finally{ d2.state.busy=false; d2.state.phase=''; } };\n    const executeTurn=async(plan,text)=>{\n      let didWrite=false;\n      if(plan.checkin){ const cod=String(plan.checkin).replace(/\\D/g,''); if(cod){ setPhase('Registrando check-in…'); const d=await d2.rush('entrada-checkin').invoke({codTerceiro:cod},{headers:KEY}).then(r=>r&&r.data!==undefined?r.data:r); const e=d&&d.entrada; push({role:'bot',text:e?`Check-in registrado: ${e.nome||cod} (nº ${e.codTerceiro}).`:`Não consegui o check-in do ${cod}.`}); didWrite=true; } }\n      if(plan.criar_membro){ const nome=(plan.membro_nome||plan.termo||'').trim(); let email=(plan.membro_email||'').trim(); let tel=''; const tipo=(plan.membro_tipo||'MEMBER').toUpperCase();\n        if(!nome){ push({role:'bot',text:'Qual o nome do novo membro?'}); }\n        else{ if(!email){ setPhase('Buscando dados do cliente…'); const cc=await fetchCliente(nome).catch(()=>[]); const c0=cc.find(c=>c.Email)||cc[0]; if(c0){ email=c0.Email||''; tel=`${c0.DDDTelefone||''}${c0.Telefone||''}`; } }\n          if(!email){ push({role:'bot',text:`Pra cadastrar ${nome} como membro, me passa o e-mail dele.`}); }\n          else{ setPhase('Cadastrando membro…'); const d=await d2.rush('signup').invoke({nome_completo:nome,email:email,telefone:tel,tipo_cadastro:tipo,origin:'PAINEL'},{headers:BEARER}).then(r=>r&&r.data!==undefined?r.data:r); push({role:'bot',text:(d&&d.success)?`✓ Membro ${nome} criado${d.data&&d.data.member_code?' · código '+d.data.member_code:''}.`:`Não consegui cadastrar: ${(d&&d.message)||'erro'}.`}); } }\n        didWrite=true; }\n      if(plan.criar_entrada){ const nome=(plan.entrada_nome||plan.termo||'').trim(); const cpf=String(plan.entrada_cpf||'').replace(/\\D/g,'');\n        if(!nome){ push({role:'bot',text:'Qual o nome da pessoa pra cadastrar na entrada?'}); }\n        else{ setPhase('Cadastrando na entrada…'); let nextCod=22001; try{ const ld=await d2.rush('entrada-lista').invoke({},{headers:KEY}).then(r=>r&&r.data!==undefined?r.data:r); const mx=Math.max(22000,...(((ld&&ld.entradas)||[]).map(x=>+x.codTerceiro||0))); nextCod=(isFinite(mx)?mx:22000)+1; }catch(e){}\n          const pessoa={nome,cpf,cpfGerado:!cpf,telefone:'',email:'',genero:'',horarios:[],pax:1,reservaStatus:'novo',obs:'via agente'};\n          const d=await d2.rush('entrada-cadastrar-um').invoke({pessoa,nextCod:String(nextCod)},{headers:KEY}).then(r=>r&&r.data!==undefined?r.data:r); const res=d&&d.result;\n          push({role:'bot',text:res?`✓ ${nome} cadastrado na entrada · comanda ${(res.codTerceiro||d.codUsed||nextCod)}.`:`Não consegui cadastrar ${nome} na entrada.`}); }\n        didWrite=true; }\n      const fontes=Array.isArray(plan.fontes)?plan.fontes:[]; const want=f=>fontes.includes(f);\n      // Capacidades — resumo do que o agente faz (sem chamadas externas)\n      if(want('capacidades')){\n        push({role:'syn',text:'Eu sou o assistente interno do TEMPO. Posso **consultar** e fazer **ações simples** (sempre com sua confirmação antes de gravar). Veja abaixo o que dá pra pedir:'});\n        push({role:'cards',title:'🔎 Consultas (leitura)',items:[\n          {t:'Reservas',s:'\"reservas de hoje\", \"reserva da Ana\", \"tem mesa amanhã no jantar?\"'},\n          {t:'Ocupação / disponibilidade',s:'\"como está a ocupação hoje?\", \"lugares livres no almoço\"'},\n          {t:'Entrou hoje / walk-ins',s:'\"quem entrou hoje?\", \"walk-ins de hoje\" (TAGME: sentados + walk-ins)'},\n          {t:'Resumo do dia',s:'\"resumo de hoje\" — reservas por status, ocupação por turno, walk-ins'},\n          {t:'Clientes & vendas',s:'\"tudo sobre o cliente João\", \"histórico de compras\", \"clientes sem telefone\"'},\n          {t:'Membros',s:'\"lista de membros\", \"valida o membro 0261\", \"quantos founders?\"'},\n          {t:'Catálogo',s:'\"quais memberships temos?\", \"produtos do catálogo\"'},\n          {t:'Observações',s:'\"o que temos anotado sobre a Ana?\"'}]});\n        push({role:'cards',title:'✍️ Ações no chat (pedem confirmação)',items:[\n          {t:'Criar / confirmar / sentar / cancelar reserva',s:'\"cria reserva pro João amanhã 20h, 2 pessoas, tel 11...\" · \"confirma a reserva do Pedro\"'},\n          {t:'Check-in / walk-in',s:'\"faz check-in da comanda 22001\" · \"registra walk-in pro Luis, 2 pessoas\"'},\n          {t:'Telefone do cliente',s:'\"muda o telefone da Ana pra 11...\"'},\n          {t:'Tornar membro',s:'\"torna o João membro\"'},\n          {t:'Anotar observação',s:'\"anota que o cliente X prefere mesa na janela\"'}]});\n        push({role:'cards',title:'➡️ Fluxos sensíveis (abro a tela certa)',items:[\n          {t:'Grupos grandes, pré-order, edição cadastral ampla, cobrança, importação em massa',s:'eu te levo pra tela de Reservas / Clientes / Membros / Entrada pra concluir com segurança'}]});\n        return;\n      }\n      if(fontes.length){\n        setPhase('Consultando: '+fontes.join(' · '));\n        const results={}; const termo=(plan.termo||'').trim(); const dataAlvo=(plan.data||'').trim(); const tasks=[];\n        if(want('reservas')) tasks.push(fetchReservas(dataAlvo).then(rs=>{ let list=rs; if(termo){ const q=norm(termo); const dig=termo.replace(/\\D/g,''); list=rs.filter(r=>{ const nm=norm(resName(r.customer)); const ph=String((r.customer&&r.customer.phone)||'').replace(/\\D/g,''); return nm.includes(q)||(dig.length>=4&&ph.includes(dig)); }); } results.reservas={data:ymdParts(dataAlvo).iso,termo,total:list.length,lista:list}; }).catch(()=>{}));\n        if(want('ocupacao')||want('disponibilidade')) tasks.push(fetchOcupacao(dataAlvo).then(o=>{ let sh=o.shifts; const tn=norm(plan.turno||''); if(tn) sh=o.shifts.filter(s=>norm(s.turno).includes(tn.includes('jant')?'jant':(tn.includes('almo')?'almo':tn))); results.ocupacao={data:o.data,turno:plan.turno||'',shifts:sh.length?sh:o.shifts,modo:want('disponibilidade')&&!want('ocupacao')?'disponibilidade':'ocupacao'}; }).catch(()=>{}));\n        if(want('walkins')) tasks.push(fetchWalkins(dataAlvo).then(ws=>{ results.walkins={data:ymdParts(dataAlvo).iso,total:ws.length,lista:ws}; }).catch(()=>{}));\n        if(want('resumo_dia')) tasks.push(Promise.all([fetchOcupacao(dataAlvo),fetchReservas(dataAlvo),fetchWalkins(dataAlvo)]).then(([o,rs,ws])=>{ const conf=rs.filter(r=>r.status==='Confirmed'||r.status==='Seated').length; const canc=rs.filter(r=>r.status==='Canceled').length; results.resumo_dia={data:ymdParts(dataAlvo).iso,reservas_total:rs.length,confirmadas:conf,canceladas:canc,walkins:ws.length,turnos:o.shifts}; }).catch(()=>{}));\n        if(want('entrada_buscar')) tasks.push(fetchEntradaBuscar(plan.entrada_q||termo).then(e=>{ results.entrada_buscar={q:plan.entrada_q||termo,total:e.total,lista:e.resultados}; }).catch(()=>{}));\n        if(want('clientes_sem_telefone')) tasks.push(clientesSemTelefone().then(c=>{ results.semtel=c; }).catch(()=>{}));\n        if(want('validar_membro')) tasks.push(getMember(plan.member_code||termo).then(m=>{ results.validar={code:plan.member_code||termo,encontrado:!!(m&&m.member),member:m&&m.member}; }).catch(()=>{ results.validar={code:plan.member_code||termo,encontrado:false}; }));\n        if(want('cliente')||want('vendas')) tasks.push(fetchCliente(termo).then(c=>{results.cliente=c;}).catch(()=>{}));\n        if(want('membro')&&(plan.member_code||'').trim()) tasks.push(getMember(plan.member_code).then(m=>{ results.membro=(m&&m.member)?[m.member]:[]; }).catch(()=>{ results.membro=[]; }));\n        else if(want('membro')) tasks.push(listMembros().then(ms=>{ const q=norm(termo); results.membro=q?ms.filter(m=>[m.nome_completo,m.email,m.member_code,m.cidade].map(norm).some(v=>v.includes(q))).slice(0,8):ms.slice(0,8); }).catch(()=>{}));\n        if(want('membros')) tasks.push(listMembros().then(ms=>{ results.membros={total:ms.length,founders:ms.filter(m=>String(m.tipo_cadastro||'').toUpperCase()==='FOUNDER').length,list:ms}; }).catch(()=>{}));\n        if(want('produtos')) tasks.push(fetchProdutos().then(ps=>{results.produtos=ps;}).catch(()=>{}));\n        if(want('entrada')) tasks.push(fetchEntrada().then(e=>{results.entrada=e;}).catch(()=>{}));\n        if(want('entrada_hoje')) tasks.push(fetchEntradaHoje(dataAlvo).then(e=>{results.entrada_hoje=e;}).catch(()=>{}));\n        if(want('notas')) tasks.push(fetchNotas(plan.alvo||termo).then(n=>{results.notas=n;}).catch(()=>{}));\n        await Promise.all(tasks);\n        if(want('vendas')){ let nr=/^\\d+$/.test(termo)?termo:(results.cliente&&results.cliente[0]&&results.cliente[0].NrPessoa); if(nr){ try{ results.vendas=await fetchVendas(nr); }catch(e){} } }\n        setPhase('Resumindo…');\n        const MR=/(member|founder|sócio|socio|plano|subscription|assinatura)/i;\n        const compact={};\n        if(results.cliente) compact.cliente=results.cliente.slice(0,3).map(c=>({nome:c.Nome,doc:c.CpfCnpj,nr:c.NrPessoa,tipo:c.TpPessoa}));\n        if(results.membro) compact.membros=results.membro.slice(0,8).map(m=>({nome:m.nome_completo,code:m.member_code,tipo:m.tipo_cadastro}));\n        if(results.membros) compact.membros_lista={total:results.membros.total,founders:results.membros.founders,nomes:results.membros.list.slice(0,30).map(m=>m.nome_completo)};\n        if(results.produtos) compact.produtos={total:results.produtos.length,itens:results.produtos.slice(0,15).map(p=>({nome:decode(p.name),preco:preco(p),membership:MR.test([p.name,p.slug].join(' '))}))};\n        if(results.vendas) compact.vendas={qtd:results.vendas.length,ultimas:results.vendas.slice(0,5).map(v=>({valor:v.ValorTotal||v.Valor,data:v.DataVenda||v.Data}))};\n        if(results.notas) compact.notas=results.notas.slice(0,8).map(n=>({alvo:n.alvo,nota:n.nota}));\n        if(results.entrada) compact.entrada={total:results.entrada.total,entrados:results.entrada.entrados};\n        if(results.entrada_hoje){ const eh=results.entrada_hoje; compact.entrada_hoje={data:eh.data,total:eh.total,sentadas:eh.sentadas,walkins:eh.walkins,pax:eh.pax,itens:eh.itens.slice(0,15).map(x=>({nome:x.nome,pax:x.pax,hora:x.hora,tipo:x.tipo}))}; }\n        if(results.reservas) compact.reservas={data:results.reservas.data,termo:results.reservas.termo,total:results.reservas.total,itens:results.reservas.lista.slice(0,12).map(r=>({nome:resName(r.customer),hora:r.reservationTime,pax:r.partySize,status:statusPt(r.status),nota:r.note||''}))};\n        if(results.ocupacao) compact.ocupacao={data:results.ocupacao.data,turno:results.ocupacao.turno,modo:results.ocupacao.modo,turnos:results.ocupacao.shifts.map(s=>({turno:s.turno,lugares:s.seats,livres:s.freeSeats,reservas:s.reservas,clientes:s.clientes}))};\n        if(results.walkins) compact.walkins={data:results.walkins.data,total:results.walkins.total,itens:results.walkins.lista.slice(0,12).map(w=>({nome:resName(w.customer),pax:w.partySize}))};\n        if(results.resumo_dia){ const rd=results.resumo_dia; compact.resumo_dia={data:rd.data,reservas_total:rd.reservas_total,confirmadas:rd.confirmadas,canceladas:rd.canceladas,walkins:rd.walkins,turnos:rd.turnos.map(s=>({turno:s.turno,lugares:s.seats,livres:s.freeSeats}))}; }\n        if(results.entrada_buscar) compact.entrada_buscar={q:results.entrada_buscar.q,total:results.entrada_buscar.total,itens:results.entrada_buscar.lista.slice(0,12).map(e=>({nome:e.nome,codTerceiro:e.codTerceiro,cpf:e.cpf,status:e.checkin?'entrou':(e.status||'na lista')}))};\n        if(results.semtel) compact.clientes_sem_telefone={total:results.semtel.total,de:results.semtel.total_clientes,nomes:results.semtel.lista.slice(0,20).map(c=>c.Nome)};\n        if(results.validar) compact.validar_membro={code:results.validar.code,membro:results.validar.encontrado,nome:results.validar.member&&results.validar.member.nome_completo,tipo:results.validar.member&&results.validar.member.tipo_cadastro};\n        let ans='';\n        try{ const sr=await d2.rush('agente-say').invoke({prompt:`Pergunta do usuário: ${text}\\n\\nDados (JSON):\\n${JSON.stringify(compact)}\\n\\nResponda de forma curta e útil. Não repita listas longas que já aparecem em cartões — resuma.`},{headers:KEY}); ans=sr&&sr.data!==undefined?sr.data:sr; }catch(e){ d2.log('say err',e); ans=''; }\n        if(ans && typeof ans==='string') push({role:'syn',text:ans});\n        if(results.cliente&&results.cliente.length){ const items=results.cliente.slice(0,8).map(c=>{ const k='cliente:'+(c.NrPessoa||c.CpfCnpj); reg(k,'cliente',c); return {key:k,t:c.Nome||'—',s:`${c.TpPessoa==='J'?'PJ':'PF'}${c.CpfCnpj?' · '+c.CpfCnpj:''}${c.NrPessoa?' · Nr '+c.NrPessoa:''}`}; }); push({role:'cards',title:'👤 Clientes',click:true,items}); }\n        if(results.membro&&results.membro.length){ const items=results.membro.slice(0,8).map(m=>{ const k='membro:'+m.member_code; reg(k,'membro',m); return {key:k,t:m.nome_completo||'—',s:`#${m.member_code||''} · ${m.tipo_cadastro||''}${m.cidade?' · '+m.cidade:''}`}; }); push({role:'cards',title:'⭐ Membros',click:true,items}); }\n        if(results.membros){ push({role:'cards',title:'📊 Membros',items:[{t:`${results.membros.total} membros`,s:`${results.membros.founders} founder(s)`}]}); if(results.membros.list.length){ const items=results.membros.list.slice(0,40).map(m=>{ const k='membro:'+m.member_code; reg(k,'membro',m); return {key:k,t:m.nome_completo||'—',s:`#${m.member_code||''} · ${m.tipo_cadastro||''}${m.cidade?' · '+m.cidade:''}`}; }); push({role:'cards',title:'⭐ Lista de membros',click:true,items}); } }\n        if(results.produtos&&results.produtos.length) push({role:'cards',title:'🛍️ Catálogo',items:results.produtos.slice(0,15).map(p=>({t:decode(p.name),s:`${preco(p)}${MR.test([p.name,p.slug].join(' '))?' · membership':''}`}))});\n        if(results.vendas&&results.vendas.length) push({role:'cards',title:'🧾 Vendas (90 dias)',items:results.vendas.slice(0,10).map(v=>({t:'R$ '+(v.ValorTotal||v.Valor||'?'),s:`${v.DataVenda||v.Data||''}${v.NrVenda?' · venda '+v.NrVenda:''}`}))});\n        if(results.notas&&results.notas.length) push({role:'cards',title:'📝 Observações',items:results.notas.slice(0,12).map(n=>({t:n.alvo,s:n.nota}))});\n        if(results.entrada_hoje){ const eh=results.entrada_hoje; if(eh.total){ push({role:'cards',title:`🚪 Entrou hoje · ${eh.data} (${eh.total} · ${eh.pax} pax)`,items:[{t:`${eh.total} pessoas entraram`,s:`${eh.sentadas} reserva(s) sentada(s) · ${eh.walkins} walk-in(s)`},...eh.itens.slice(0,20).map(x=>({t:`${x.hora?x.hora+' · ':''}${x.nome}`,s:`${x.pax} pax · ${x.tipo}`}))]}); } else push({role:'cards',title:'🚪 Entrou hoje',items:[{t:'Ninguém entrou ainda',s:`${eh.data} · sem reservas sentadas nem walk-ins`}]}); }\n        if(results.reservas){ if(results.reservas.lista.length){ push({role:'cards',title:`🍽️ Reservas ${results.reservas.data}${results.reservas.termo?(' · '+results.reservas.termo):''} (${results.reservas.total})`,items:results.reservas.lista.slice(0,20).map(r=>({t:`${r.reservationTime||'--:--'} · ${resName(r.customer)}`,s:`${r.partySize||'?'} pax · ${statusPt(r.status)}${r.note?(' · '+r.note):''}`}))}); } else push({role:'cards',title:'🍽️ Reservas',items:[{t:'Nenhuma reserva',s:`${results.reservas.data}${results.reservas.termo?(' · '+results.reservas.termo):''}`}]}); }\n        if(results.ocupacao) push({role:'cards',title:`📈 ${results.ocupacao.modo==='disponibilidade'?'Disponibilidade':'Ocupação'} ${results.ocupacao.data}`,items:results.ocupacao.shifts.map(s=>({t:`${s.turno}`,s:`${s.freeSeats}/${s.seats} lugares livres · ${s.reservas} reserva(s) · ${s.clientes} pax`}))});\n        if(results.walkins){ if(results.walkins.lista.length) push({role:'cards',title:`🚶 Walk-ins ${results.walkins.data} (${results.walkins.total})`,items:results.walkins.lista.slice(0,20).map(w=>({t:resName(w.customer),s:`${w.partySize||1} pax`}))}); else push({role:'cards',title:'🚶 Walk-ins',items:[{t:'Nenhum walk-in',s:results.walkins.data}]}); }\n        if(results.resumo_dia){ const rd=results.resumo_dia; push({role:'cards',title:`📊 Resumo ${rd.data}`,items:[{t:`${rd.reservas_total} reservas · ${rd.confirmadas} confirmadas · ${rd.canceladas} canceladas`,s:`${rd.walkins} walk-in(s)`},...rd.turnos.map(s=>({t:s.turno,s:`${s.freeSeats}/${s.seats} lugares livres · ${s.reservas} reserva(s)`}))]}); }\n        if(results.entrada_buscar){ const eb=results.entrada_buscar; if(eb.lista.length) push({role:'cards',title:`🔎 Entrada · \"${eb.q}\" (${eb.total})`,items:eb.lista.slice(0,20).map(e=>({t:e.nome||'—',s:`${e.codTerceiro?('comanda '+e.codTerceiro):''}${e.cpf?(' · '+e.cpf):''}${e.checkin?' · entrou':''}`}))}); else push({role:'cards',title:'🔎 Entrada',items:[{t:'Ninguém encontrado',s:`\"${eb.q}\"`}]}); }\n        if(results.semtel) push({role:'cards',title:'📵 Clientes sem telefone',items:[{t:`${results.semtel.total} de ${results.semtel.total_clientes}`,s:results.semtel.lista.slice(0,8).map(c=>c.Nome).join(', ')||'—'}]});\n        if(results.validar){ const v=results.validar; push({role:'cards',title:'✅ Validação de membro',items:[{t:v.encontrado?`Membro válido · ${v.member.nome_completo}`:`Não é membro (código ${v.code})`,s:v.encontrado?`#${v.member.member_code} · ${v.member.tipo_cadastro||''}`:'código não encontrado'}]}); }\n      } else if(!didWrite){ push({role:'bot',text:plan.resposta||'Como posso ajudar?'}); }\n    };\n    // ---- F2: build a confirmation card for a write, execute only on Confirmar ----\n    const armWrite=(title,summary,exec)=>{ d2.state.pendingWrite={exec}; push({role:'wconfirm',title,items:summary}); };\n    const dispatchWrite=async(plan)=>{ const tipo=plan.escrita_tipo;\n      if(tipo==='reserva_criar'){ setPhase('Verificando cliente e turno…');\n        const cfg=await loadSeatCfg().catch(()=>({schedules:[],section:SECTION_FALLBACK,maxParty:0}));\n        const day=(plan.data||'').trim(); const time=(plan.r_hora||'').trim(); const size=parseInt(plan.r_pax,10)||0; const tel=String(plan.r_telefone||'').replace(/\\D/g,'');\n        if(!day||!/^\\d{4}-\\d{2}-\\d{2}$/.test(day)){ push({role:'bot',text:'Pra criar a reserva preciso da data. Qual dia?'}); return; }\n        if(!time){ push({role:'bot',text:'Qual o horário da reserva?'}); return; }\n        if(size<1){ push({role:'bot',text:'Pra quantas pessoas é a reserva?'}); return; }\n        if(cfg.maxParty>0&&size>cfg.maxParty){ push({role:'bot',text:`Grupos acima de ${cfg.maxParty} pessoas precisam ser feitos na tela de Reservas.`}); push({role:'nav',tab:'reservas',t:'Abrir Reservas',s:`Grupo de ${size} pessoas`}); return; }\n        const sh=shiftHit(cfg,day,time); if((cfg.schedules||[]).length && !sh){ push({role:'bot',text:`Não há turno disponível em ${day} às ${time}. Confira a tela de Reservas pra ver os turnos do dia.`}); push({role:'nav',tab:'reservas',t:'Abrir Reservas',s:'Ver turnos disponíveis'}); return; }\n        if(!tel){ push({role:'bot',text:'Pra criar a reserva preciso do telefone do cliente (a TAGME identifica o cliente pelo telefone). Qual o número?'}); return; }\n        const custs=await lookupCustomerByPhone(tel).catch(()=>[]);\n        if(!custs.length){ push({role:'bot',text:`Não achei nenhum cliente na TAGME com o telefone ${tel}. Cadastre o cliente na TAGME (tela de Reservas) antes de criar a reserva — não crio cliente com telefone inventado.`}); push({role:'nav',tab:'reservas',t:'Abrir Reservas',s:'Cadastrar cliente / nova reserva'}); return; }\n        if(custs.length>1){ d2.state.pendingResv={day,time,size,cfg,custs}; push({role:'pick',text:'Achei mais de um cliente com esse telefone. Pra quem é a reserva?',items:custs.slice(0,8).map(c=>({nr:c._id,nome:[c.name,c.lastName].filter(Boolean).join(' ')||'—',doc:c.phone}))}); return; }\n        const c=custs[0]; const nm=[c.name,c.lastName].filter(Boolean).join(' ')||'—';\n        armWrite('Criar reserva?',[`Cliente: ${nm}`,`Telefone: ${c.phone||tel}`,`Data: ${day}  Hora: ${time}`,`Pessoas: ${size}`,`Origem: WhatsApp · status Nova`],async()=>{ const res=await doReservaCriar(c,day,time,size,cfg); const ok=res&&(res.success!==false)&&(res.status?res.status<300:true); push({role:'bot',text:ok?`✓ Reserva criada pra ${nm} em ${day} às ${time} (${size}p).`:`Não consegui criar a reserva. ${(res&&res.message)||''}`}); });\n        return; }\n      if(tipo==='reserva_confirmar'||tipo==='reserva_sentar'||tipo==='reserva_cancelar'){ const termo=(plan.termo||plan.alvo||'').trim(); const day=(plan.data||'').trim()||ymdParts('').iso;\n        if(!termo){ push({role:'bot',text:'De quem é a reserva? Me diz o nome ou telefone.'}); return; }\n        setPhase('Procurando a reserva…'); const hits=await findReserva(termo,day);\n        if(!hits.length){ push({role:'bot',text:`Não achei reserva de \"${termo}\" em ${day}.`}); return; }\n        const verbo=tipo==='reserva_confirmar'?'confirmar':(tipo==='reserva_sentar'?'sentar':'cancelar');\n        const arm=(r)=>{ const nm=resName(r.customer); const summary=[`Cliente: ${nm}`,`Data: ${day}  Hora: ${r.reservationTime||'--:--'}`,`Pessoas: ${r.partySize||'?'}  ·  Status atual: ${statusPt(r.status)}`,`Ação: ${verbo.toUpperCase()}`];\n          armWrite(`${verbo[0].toUpperCase()+verbo.slice(1)} reserva?`,summary,async()=>{ let res; if(tipo==='reserva_confirmar')res=await doReservaConfirmar(r); else if(tipo==='reserva_sentar')res=await doReservaSentar(r); else res=await doReservaCancelar(r); const ok=res&&res.success!==false; push({role:'bot',text:ok?`✓ Reserva de ${nm} ${verbo==='confirmar'?'confirmada':(verbo==='sentar'?'marcada como sentada':'cancelada')}.`:`Não consegui ${verbo} a reserva. ${(res&&res.message)||''}`}); }); };\n        if(hits.length>1){ d2.state.pendingResvAction={tipo,day}; d2.state.resvHits=hits; push({role:'pick',text:`Achei ${hits.length} reservas pra \"${termo}\". Qual delas?`,items:hits.slice(0,8).map(r=>({nr:r._id,nome:resName(r.customer),doc:`${r.reservationTime||'--:--'} · ${r.partySize||'?'}p · ${statusPt(r.status)}`}))}); return; }\n        arm(hits[0]); return; }\n      if(tipo==='editar_telefone'){ const termo=(plan.cli_termo||'').trim(); const novo=String(plan.cli_telefone||'').replace(/\\D/g,'');\n        if(!termo){ push({role:'bot',text:'De qual cliente você quer mudar o telefone?'}); return; }\n        if(!novo||novo.length<10){ push({role:'bot',text:'Qual o novo telefone (com DDD)?'}); return; }\n        setPhase('Procurando o cliente…'); const cs=await fetchCliente(termo).catch(()=>[]);\n        if(!cs.length){ push({role:'bot',text:`Não achei o cliente \"${termo}\" no Cloudfy.`}); return; }\n        const arm=(c)=>armWrite('Alterar telefone do cliente?',[`Cliente: ${c.Nome}`,`Nr ${c.NrPessoa}${c.CpfCnpj?(' · '+c.CpfCnpj):''}`,`Telefone atual: ${`${c.DDDTelefone||c.DDDCelular||''}${c.Telefone||c.Celular||''}`||'—'}`,`Novo telefone: ${novo}`,`(demais dados preservados)`],async()=>{ const res=await doEditarTelefone(c,novo); const ok=res&&res.success; push({role:'bot',text:ok?`✓ Telefone do(a) ${c.Nome} atualizado para ${novo}.`:`Não consegui atualizar: ${(res&&res.message)||(res&&res.MensagemRet)||'erro'}.`}); });\n        if(cs.length>1){ d2.state.pendingTelEdit={novo}; push({role:'pick',text:`Achei ${cs.length} clientes pra \"${termo}\". Em qual altero o telefone?`,items:cs.slice(0,8).map(c=>({nr:c.NrPessoa,nome:c.Nome,doc:c.CpfCnpj}))}); return; }\n        arm(cs[0]); return; }\n      if(tipo==='tornar_membro'){ const nome=(plan.membro_nome||plan.termo||'').trim(); let email=(plan.membro_email||'').trim(); const tipoC=(plan.membro_tipo||'MEMBER').toUpperCase();\n        if(!nome){ push({role:'bot',text:'Qual o nome de quem você quer tornar membro?'}); return; }\n        setPhase('Buscando dados do cliente…'); let tel=''; if(!email){ const cc=await fetchCliente(nome).catch(()=>[]); const c0=cc.find(c=>c.Email)||cc[0]; if(c0){ email=c0.Email||''; tel=`${c0.DDDTelefone||c0.DDDCelular||''}${c0.Telefone||c0.Celular||''}`; } }\n        if(!email){ push({role:'bot',text:`Pra tornar ${nome} membro preciso do e-mail dele. Qual é?`}); return; }\n        armWrite('Cadastrar como membro?',[`Nome: ${nome}`,`E-mail: ${email}`,`Tipo: ${tipoC}`],async()=>{ const d=await d2.rush('signup').invoke({nome_completo:nome,email:email,telefone:tel,tipo_cadastro:tipoC,origin:'PAINEL'},{headers:BEARER}).then(r=>r&&r.data!==undefined?r.data:r); push({role:'bot',text:(d&&d.success)?`✓ Membro ${nome} criado${d.data&&d.data.member_code?' · código '+d.data.member_code:''}.`:`Não consegui cadastrar: ${(d&&d.message)||'erro'}.`}); });\n        return; }\n      if(tipo==='checkin'){ const cod=String(plan.checkin||'').replace(/\\D/g,''); if(!cod){ push({role:'bot',text:'Qual o número da comanda pro check-in?'}); return; }\n        armWrite('Registrar check-in?',[`Comanda: ${cod}`],async()=>{ const d=await d2.rush('entrada-checkin').invoke({codTerceiro:cod},{headers:KEY}).then(r=>r&&r.data!==undefined?r.data:r); const e=d&&d.entrada; push({role:'bot',text:e?`✓ Check-in registrado: ${e.nome||cod} (nº ${e.codTerceiro}).`:`Não consegui o check-in do ${cod}.`}); });\n        return; }\n      if(tipo==='pessoa_chegou'){ const termo=(plan.r_nome||plan.termo||plan.alvo||'').trim(); const size=parseInt(plan.r_pax,10)||0; const day=(plan.data||'').trim()||ymdParts('').iso;\n        if(!termo){ push({role:'bot',text:'Quem chegou? Me diz o nome.'}); return; }\n        setPhase('Procurando em reservas, membros e clientes…');\n        const [resvs,membros,clientes]=await Promise.all([\n          findReserva(termo,day).catch(()=>[]),\n          listMembros().then(ms=>{ const q=norm(termo); return ms.filter(m=>norm(m.nome_completo).includes(q)).slice(0,5); }).catch(()=>[]),\n          fetchCliente(termo).then(cs=>cs.slice(0,5)).catch(()=>[])\n        ]);\n        const opts=[];\n        resvs.forEach(r=>{ const ph=String((r.customer&&r.customer.phone)||'').replace(/\\D/g,''); opts.push({kind:'reserva',_id:r._id,phone:ph,nome:resName(r.customer),doc:`Reserva ${r.reservationTime||'--:--'} · ${r.partySize||'?'}p · ${statusPt(r.status)}`,pax:r.partySize||size||1,r}); });\n        membros.forEach(m=>{ opts.push({kind:'membro',nome:m.nome_completo,doc:`Membro #${m.member_code||''} · ${m.tipo_cadastro||''}`,pax:size||1}); });\n        clientes.forEach(c=>{ const ph=`${c.DDDTelefone||c.DDDCelular||''}${c.Telefone||c.Celular||''}`.replace(/\\D/g,''); opts.push({kind:'cliente',phone:ph,nome:c.Nome,doc:`Cliente${c.CpfCnpj?(' · '+c.CpfCnpj):''}${ph?(' · '+ph):''}`,pax:size||1,c}); });\n        if(!opts.length){ push({role:'bot',text:`Não achei \"${termo}\" em reservas de ${day}, membros nem clientes. Quer registrar um walk-in novo só com o nome?`}); d2.state.pendingChegouNew={nome:termo,size:size||1}; push({role:'wconfirm',title:'Registrar walk-in novo?',items:[`Nome: ${termo}`,`Pessoas: ${size||1}`,'Sem cliente vinculado → só na lista de entrada local']}); d2.state.pendingWrite={exec:async()=>{ let nextCod=22001; try{ const ld=await d2.rush('entrada-lista').invoke({},{headers:KEY}).then(r=>r&&r.data!==undefined?r.data:r); const mx=Math.max(22000,...(((ld&&ld.entradas)||[]).map(x=>+x.codTerceiro||0))); nextCod=(isFinite(mx)?mx:22000)+1; }catch(e){} const pessoa={nome:termo,cpf:'',cpfGerado:true,telefone:'',email:'',genero:'',horarios:[],pax:size||1,reservaStatus:'walk-in',obs:'chegou — via agente'}; const d=await d2.rush('entrada-cadastrar-um').invoke({pessoa,nextCod:String(nextCod)},{headers:KEY}).then(r=>r&&r.data!==undefined?r.data:r); const res=d&&d.result; push({role:'bot',text:res?`✓ ${termo} registrado na lista de entrada · comanda ${(res.codTerceiro||d.codUsed||nextCod)}.`:`Não consegui registrar ${termo}.`}); }}; return; }\n        d2.state.chegouOpts=opts; d2.state.chegouSize=size||0;\n        push({role:'pick',text:`Achei ${opts.length} possível(is) \"${termo}\". Quem chegou? (eu senta/registra na hora)`,items:opts.slice(0,8).map((o,i)=>({nr:'chegou:'+i,nome:o.nome,doc:o.doc}))});\n        return; }\n      if(tipo==='walkin_criar'){ const nome=(plan.r_nome||plan.termo||'').trim(); const size=parseInt(plan.r_pax,10)||1; const tel=String(plan.r_telefone||'').replace(/\\D/g,'');\n        if(!nome&&!tel){ push({role:'bot',text:'Pra registrar o walk-in me diz o nome (e o telefone, se tiver — a TAGME identifica o cliente pelo telefone).'}); return; }\n        if(tel){ setPhase('Procurando o cliente na TAGME…'); const custs=await lookupCustomerByPhone(tel).catch(()=>[]);\n          if(!custs.length){ push({role:'bot',text:`Não achei cliente na TAGME com o telefone ${tel}. Posso registrar só na lista de entrada local (sem sentar na TAGME), ou cadastre o cliente na tela de Reservas antes.`}); push({role:'nav',tab:'reservas',t:'Abrir Reservas',s:'Cadastrar cliente na TAGME'}); return; }\n          const arm=(c)=>{ const nm=[c.name,c.lastName].filter(Boolean).join(' ')||nome||'—'; armWrite('Registrar walk-in?',[`Cliente: ${nm}`,`Telefone: ${c.phone||tel}`,`Pessoas: ${size}`,`Sentar agora na TAGME + check-in na lista local`],async()=>{ const res=await doWalkinCriar(c,size); const ok=res&&(res.success!==false)&&(res.status?res.status<300:true); let extra=''; try{ const cod=tel.slice(-6); await d2.rush('entrada-checkin').invoke({codTerceiro:cod},{headers:KEY}); }catch(e){} push({role:'bot',text:ok?`✓ Walk-in de ${nm} registrado (${size}p) e sentado na TAGME.`:`Não consegui registrar o walk-in. ${(res&&res.message)||''}`}); }); };\n          if(custs.length>1){ d2.state.pendingWalkin={size,custs}; push({role:'pick',text:'Achei mais de um cliente com esse telefone. Quem é o walk-in?',items:custs.slice(0,8).map(c=>({nr:c._id,nome:[c.name,c.lastName].filter(Boolean).join(' ')||'—',doc:c.phone}))}); return; }\n          arm(custs[0]); return; }\n        // sem telefone → walk-in só na lista de entrada local (caminho seguro existente), com confirmação\n        armWrite('Registrar walk-in na lista de entrada?',[`Nome: ${nome}`,`Pessoas: ${size}`,`Sem telefone → registro só na lista local (não senta na TAGME)`],async()=>{ let nextCod=22001; try{ const ld=await d2.rush('entrada-lista').invoke({},{headers:KEY}).then(r=>r&&r.data!==undefined?r.data:r); const mx=Math.max(22000,...(((ld&&ld.entradas)||[]).map(x=>+x.codTerceiro||0))); nextCod=(isFinite(mx)?mx:22000)+1; }catch(e){}\n          const pessoa={nome,cpf:'',cpfGerado:true,telefone:'',email:'',genero:'',horarios:[],pax:size,reservaStatus:'walk-in',obs:'walk-in via agente'}; const d=await d2.rush('entrada-cadastrar-um').invoke({pessoa,nextCod:String(nextCod)},{headers:KEY}).then(r=>r&&r.data!==undefined?r.data:r); const res=d&&d.result; push({role:'bot',text:res?`✓ Walk-in de ${nome} registrado na lista de entrada · comanda ${(res.codTerceiro||d.codUsed||nextCod)}.`:`Não consegui registrar o walk-in de ${nome}.`}); });\n        return; }\n      push({role:'bot',text:'Essa ação ainda não está disponível por aqui.'});\n    };\n    const send=async()=>{\n      const el=d2.$('.in'); if(!el) return; const text=(el.value||'').trim(); if(!text||d2.state.busy) return;\n      const prevCtx=(d2.state.msgs||[]).slice(-8).map(m=>m.role==='user'?('Usuário: '+m.text):((m.role==='syn'||m.role==='bot')?('Agente: '+m.text):null)).filter(Boolean).join('\\n');\n      el.value=''; push({role:'user',text}); d2.state.busy=true; setPhase('Entendendo o pedido…');\n      try{\n        let plan=null;\n        try{ const pr=await d2.rush('agente-plan').invoke({q:text,contexto:prevCtx,foco:d2.state.foco||''},{headers:KEY}); plan=pr&&pr.data!==undefined?pr.data:pr; }catch(e){ d2.log('plan err',e); plan=null; }\n        if(typeof plan==='string'){ try{plan=JSON.parse(plan);}catch(e){plan=null;} }\n        if(!plan){ push({role:'bot',text:'Não consegui entender. Tenta reformular o pedido.'}); return; }\n        const subj=(plan.alvo||plan.termo||plan.membro_nome||plan.entrada_nome||plan.r_nome||plan.cli_termo||'').trim(); if(subj) d2.state.foco=subj;\n        // F3 — complex/sensitive flow → button to the right screen\n        if(plan.navegar_tab){ const labels={reservas:'Reservas',clientes:'Clientes',entrada:'Entrada',membros:'Membros',catalogo:'Catálogo'}; const tab=plan.navegar_tab; if(plan.resposta) push({role:'syn',text:plan.resposta}); push({role:'nav',tab,t:`Abrir ${labels[tab]||tab}`,s:plan.navegar_motivo||'concluir por lá'}); return; }\n        // F2 — structured write with mandatory confirmation\n        if(plan.escrita_tipo){ await dispatchWrite(plan); return; }\n        // nota: handled via disambiguation pick (the pick IS the confirm)\n        if(plan.nota){ await startNota(plan.nota,(plan.alvo||plan.termo||'').trim()); return; }\n        // legacy criar_entrada flow (walk-in cadastro) keeps its own confirm\n        if(plan.criar_entrada){ d2.state.confirmTurn={plan,text}; push({role:'confirm',items:['Cadastrar na entrada: '+(plan.entrada_nome||plan.termo||'?')]}); return; }\n        await executeTurn(plan,text);\n      }catch(e){ d2.log('agente err',e); push({role:'bot',text:'Deu um erro ao processar. Tenta de novo.'}); }\n      finally{ d2.state.busy=false; d2.state.phase=''; }\n    };\n    d2.on('.cy','click',async()=>{ const ct=d2.state.confirmTurn; if(!ct||d2.state.busy)return; d2.state.confirmTurn=null; d2.state.busy=true; setPhase('Executando…'); try{ await executeTurn(ct.plan,ct.text); }catch(e){ d2.log('exec err',e); push({role:'bot',text:'Erro ao executar a ação.'}); } finally{ d2.state.busy=false; d2.state.phase=''; } });\n    d2.on('.cn','click',()=>{ if(d2.state.confirmTurn){ d2.state.confirmTurn=null; push({role:'bot',text:'Ok, cancelado.'}); } });\n    d2.on('.acard','click',(e,el)=>{ const k=el.dataset.key; const it=(d2.state.index||{})[k]; if(it) d2.state.detail=it; });\n    d2.on('.ovback','click',()=>{ d2.state.detail=null; });\n    d2.on('.pickbtn','click',async(e,el)=>{ const nr=el.dataset.nr, nome=el.dataset.nome;\n      // disambiguation: reserva_criar (nr holds the TAGME customer _id)\n      if(d2.state.pendingResv){ const pr=d2.state.pendingResv; d2.state.pendingResv=null; const c=(pr.custs||[]).find(x=>x._id===nr)||{_id:nr,name:nome}; armWrite('Criar reserva?',[`Cliente: ${nome}`,`Data: ${pr.day}  Hora: ${pr.time}`,`Pessoas: ${pr.size}`,`Origem: WhatsApp · status Nova`],async()=>{ const res=await doReservaCriar(c,pr.day,pr.time,pr.size,pr.cfg); const ok=res&&(res.success!==false)&&(res.status?res.status<300:true); push({role:'bot',text:ok?`✓ Reserva criada pra ${nome} em ${pr.day} às ${pr.time} (${pr.size}p).`:`Não consegui criar a reserva. ${(res&&res.message)||''}`}); }); return; }\n      // disambiguation: confirmar/sentar/cancelar (nr holds reservation _id)\n      if(d2.state.pendingResvAction){ const pa=d2.state.pendingResvAction; const r=(d2.state.resvHits||[]).find(x=>x._id===nr); d2.state.pendingResvAction=null; d2.state.resvHits=null; if(!r){ push({role:'bot',text:'Reserva não encontrada.'}); return; } const tipo=pa.tipo; const verbo=tipo==='reserva_confirmar'?'confirmar':(tipo==='reserva_sentar'?'sentar':'cancelar'); armWrite(`${verbo[0].toUpperCase()+verbo.slice(1)} reserva?`,[`Cliente: ${resName(r.customer)}`,`Data: ${pa.day}  Hora: ${r.reservationTime||'--:--'}`,`Pessoas: ${r.partySize||'?'}  ·  Status: ${statusPt(r.status)}`,`Ação: ${verbo.toUpperCase()}`],async()=>{ let res; if(tipo==='reserva_confirmar')res=await doReservaConfirmar(r); else if(tipo==='reserva_sentar')res=await doReservaSentar(r); else res=await doReservaCancelar(r); const ok=res&&res.success!==false; push({role:'bot',text:ok?`✓ Reserva de ${resName(r.customer)} ${verbo==='confirmar'?'confirmada':(verbo==='sentar'?'sentada':'cancelada')}.`:`Não consegui ${verbo}. ${(res&&res.message)||''}`}); }); return; }\n      // disambiguation: pessoa_chegou (nr = 'chegou:<idx>')\n      if(d2.state.chegouOpts && String(nr).indexOf('chegou:')===0){ const idx=parseInt(String(nr).split(':')[1],10); const o=(d2.state.chegouOpts||[])[idx]; const size=d2.state.chegouSize; d2.state.chegouOpts=null; d2.state.chegouSize=0; if(!o){ push({role:'bot',text:'Opção não encontrada.'}); return; }\n        if(o.kind==='reserva'){ const r=o.r; armWrite('Sentar a reserva (cliente chegou)?',[`Cliente: ${o.nome}`,`Hora: ${r.reservationTime||'--:--'} · ${r.partySize||'?'}p`,`Status atual: ${statusPt(r.status)}`,'Ação: SENTAR'],async()=>{ const res=await doReservaSentar(r); const ok=res&&res.success!==false; push({role:'bot',text:ok?`✓ Reserva de ${o.nome} marcada como sentada.`:`Não consegui sentar. ${(res&&res.message)||''}`}); }); return; }\n        // membro/cliente → walk-in na TAGME se tiver telefone, senão lista local\n        const pax=size||o.pax||1; const ph=String(o.phone||'').replace(/\\D/g,'');\n        if(ph){ d2.state.busy=true; setPhase('Procurando cliente na TAGME…'); let custs=[]; try{ custs=await lookupCustomerByPhone(ph); }catch(e){} d2.state.busy=false; d2.state.phase='';\n          if(custs.length){ const c=custs[0]; const nm=[c.name,c.lastName].filter(Boolean).join(' ')||o.nome; armWrite('Registrar walk-in?',[`${o.kind==='membro'?'Membro':'Cliente'}: ${nm}`,`Telefone: ${c.phone||ph}`,`Pessoas: ${pax}`,'Sentar agora na TAGME'],async()=>{ const res=await doWalkinCriar(c,pax); const ok=res&&(res.success!==false)&&(res.status?res.status<300:true); push({role:'bot',text:ok?`✓ Walk-in de ${nm} registrado (${pax}p) e sentado na TAGME.`:`Não consegui registrar. ${(res&&res.message)||''}`}); }); return; } }\n        // fallback: lista de entrada local\n        armWrite('Registrar walk-in na lista de entrada?',[`${o.kind==='membro'?'Membro':'Cliente'}: ${o.nome}`,`Pessoas: ${pax}`,'Registro na lista local (sem telefone na TAGME)'],async()=>{ let nextCod=22001; try{ const ld=await d2.rush('entrada-lista').invoke({},{headers:KEY}).then(r=>r&&r.data!==undefined?r.data:r); const mx=Math.max(22000,...(((ld&&ld.entradas)||[]).map(x=>+x.codTerceiro||0))); nextCod=(isFinite(mx)?mx:22000)+1; }catch(e){} const pessoa={nome:o.nome,cpf:'',cpfGerado:true,telefone:String(o.phone||''),email:'',genero:'',horarios:[],pax,reservaStatus:'walk-in',obs:'chegou — via agente'}; const d=await d2.rush('entrada-cadastrar-um').invoke({pessoa,nextCod:String(nextCod)},{headers:KEY}).then(r=>r&&r.data!==undefined?r.data:r); const res=d&&d.result; push({role:'bot',text:res?`✓ ${o.nome} registrado na lista de entrada · comanda ${(res.codTerceiro||d.codUsed||nextCod)}.`:`Não consegui registrar ${o.nome}.`}); }); return; }\n      // disambiguation: walkin_criar (nr holds TAGME customer _id)\n      if(d2.state.pendingWalkin){ const pw=d2.state.pendingWalkin; d2.state.pendingWalkin=null; const c=(pw.custs||[]).find(x=>x._id===nr)||{_id:nr,name:nome}; const nm=[c.name,c.lastName].filter(Boolean).join(' ')||nome||'—'; armWrite('Registrar walk-in?',[`Cliente: ${nm}`,`Telefone: ${c.phone||''}`,`Pessoas: ${pw.size}`,`Sentar agora na TAGME + check-in na lista local`],async()=>{ const res=await doWalkinCriar(c,pw.size); const ok=res&&(res.success!==false)&&(res.status?res.status<300:true); try{ const cod=String(c.phone||'').replace(/\\D/g,'').slice(-6); if(cod) await d2.rush('entrada-checkin').invoke({codTerceiro:cod},{headers:KEY}); }catch(e){} push({role:'bot',text:ok?`✓ Walk-in de ${nm} registrado (${pw.size}p) e sentado na TAGME.`:`Não consegui registrar o walk-in. ${(res&&res.message)||''}`}); }); return; }\n      // disambiguation: editar_telefone (nr holds NrPessoa)\n      if(d2.state.pendingTelEdit){ const pe=d2.state.pendingTelEdit; d2.state.pendingTelEdit=null; d2.state.busy=true; setPhase('Carregando cliente…'); try{ const cs=await fetchCliente(nome).catch(()=>[]); const c=cs.find(x=>String(x.NrPessoa)===String(nr))||{Nome:nome,NrPessoa:nr}; armWrite('Alterar telefone do cliente?',[`Cliente: ${c.Nome}`,`Nr ${c.NrPessoa}`,`Novo telefone: ${pe.novo}`,`(demais dados preservados)`],async()=>{ const res=await doEditarTelefone(c,pe.novo); const ok=res&&res.success; push({role:'bot',text:ok?`✓ Telefone do(a) ${c.Nome} atualizado para ${pe.novo}.`:`Não consegui atualizar: ${(res&&res.message)||(res&&res.MensagemRet)||'erro'}.`}); }); } finally{ d2.state.busy=false; d2.state.phase=''; } return; }\n      // default: nota disambiguation\n      const p=d2.state.pending; if(!p)return; d2.state.pending=null; try{ await saveNota(nome, nr?Number(nr):null, p.nota); push({role:'bot',text:`✓ Anotado sobre ${nome}${nr?(' (Nr '+nr+')'):''}: \"${p.nota}\".`}); }catch(x){ push({role:'bot',text:'Erro ao salvar a observação.'}); } });\n    d2.on('.wy','click',async()=>{ const pw=d2.state.pendingWrite; if(!pw||d2.state.busy)return; d2.state.pendingWrite=null; d2.state.busy=true; setPhase('Executando…'); try{ await pw.exec(); }catch(e){ d2.log('write err',e); push({role:'bot',text:'Erro ao executar a ação. Nada foi gravado com certeza — confira na tela.'}); } finally{ d2.state.busy=false; d2.state.phase=''; } });\n    d2.on('.wn','click',()=>{ if(d2.state.pendingWrite){ d2.state.pendingWrite=null; push({role:'bot',text:'Ok, cancelado. Nada foi gravado.'}); } });\n    d2.on('.navbtn','click',(e,el)=>{ const tab=el.dataset.tab; if(tab) navEmit(tab); });\n    d2.on('.cfreey','click',async()=>{ const pf=d2.state.pendingFree; if(!pf)return; d2.state.pendingFree=null; try{ await saveNota(pf.alvo||'(sem nome)', null, pf.nota); push({role:'bot',text:'Observação salva sem vínculo a um cliente.'}); }catch(e){ push({role:'bot',text:'Erro ao salvar.'}); } });\n    d2.on('.cfreen','click',()=>{ if(d2.state.pendingFree){ d2.state.pendingFree=null; push({role:'bot',text:'Ok, cancelado.'}); } });\n    d2.on('.newchat','click',()=>{ d2.state.msgs=[]; d2.state.foco=''; d2.state.index={}; d2.state.detail=null; d2.state.pending=null; d2.state.confirmTurn=null; d2.state.pendingWrite=null; d2.state.pendingResv=null; d2.state.pendingResvAction=null; d2.state.resvHits=null; d2.state.pendingTelEdit=null; d2.state.pendingFree=null; d2.state.pendingWalkin=null; d2.state.chegouOpts=null; d2.state.chegouSize=0; d2.state.pendingChegouNew=null; d2.state.seatCfg=null; });\n    d2.on('.send','click',send);\n    d2.on('.in','keydown',(e)=>{ if(e.key==='Enter') send(); });\n  },\n  updated(d2){ const l=d2.$('.log'); if(l) l.scrollTop=l.scrollHeight; }\n}"}},"assistant":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"assistant"}}}},"buscarMembros":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"buscarMembros"}}}},"buscarClientes":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"buscarClientes"}}}}}}}}}},{"_id":"6a341e0150d4364ed4d83ddc","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"DashboardScreen","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .dash{height:100%;overflow:auto;background:#0a0a0a;color:#fff;font-family:'Inter',system-ui,sans-serif;box-sizing:border-box}\n  .head{padding:30px 36px 6px}\n  .head h2{font-family:'Anton',sans-serif;font-size:28px;letter-spacing:.04em;margin:0;text-transform:uppercase}\n  .head .sm{color:#9a9a9a;font-size:12px;letter-spacing:.12em;margin-top:6px;font-weight:600}\n  .kpis{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:16px;padding:26px 36px}\n  .kpi{background:#141414;border:1px solid #2a2a2a;border-left:3px solid #F4C400;border-radius:12px;padding:22px 24px}\n  .kpi .n{font-family:'Anton',sans-serif;font-size:42px;color:#F4C400;line-height:1}\n  .kpi .l{font-size:11px;letter-spacing:.16em;color:#9a9a9a;text-transform:uppercase;margin-top:10px;font-weight:700}\n  .kpi .sub{color:#7a7a7a;font-size:12px;margin-top:6px}\n  .q{padding:6px 36px 40px}\n  .q h3{font-family:'Anton',sans-serif;font-size:18px;letter-spacing:.06em;text-transform:uppercase;margin:0 0 5px}\n  .q .qs{color:#9a9a9a;font-size:11px;letter-spacing:.14em;font-weight:700;margin-bottom:16px;text-transform:uppercase}\n  .q .box{background:#141414;border:1px solid #2a2a2a;border-radius:12px;overflow:hidden}\n  .qrow{display:grid;grid-template-columns:1fr auto;gap:18px;align-items:center;padding:16px 20px;border-bottom:1px solid #222}\n  .qrow:last-child{border-bottom:0}\n  .who{min-width:0}\n  .who .nm{font-size:14px;font-weight:700;letter-spacing:.02em;display:flex;align-items:center;gap:9px;flex-wrap:wrap}\n  .who .mt{color:#7a7a7a;font-size:12px;margin-top:5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n  .chip{font-size:9px;letter-spacing:.16em;font-weight:700;text-transform:uppercase;padding:3px 8px;border-radius:999px;border:1px solid #3a3a3a;color:#c9c9c9}\n  .chip.f{border-color:#F4C400;color:#F4C400}\n  .act{display:flex;align-items:center;gap:8px}\n  .act input{width:98px;box-sizing:border-box;background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;border-radius:8px;padding:9px 10px;font-size:14px;outline:none;text-align:center;letter-spacing:.08em;font-variant-numeric:tabular-nums}\n  .act input:focus{border-color:#F4C400}\n  .act button{background:#F4C400;color:#000;border:0;border-radius:8px;padding:10px 15px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.1em;cursor:pointer}\n  .act button:disabled{opacity:.45;cursor:default}\n  .qempty{padding:26px 20px;color:#7a7a7a;font-size:13px;text-align:center}\n  .qmsg{margin-top:12px;font-size:12px;min-height:16px;letter-spacing:.02em}\n  .qmsg.ok{color:#7ddc9a}\n  .qmsg.er{color:#ff9a9a}\n  `,\n  render(d2){\n    const st=d2.state; const n=v=>v==null?'…':v;\n    const esc=s=>String(s==null?'':s).replace(/[&<>\"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;',\"'\":'&#39;'}[c]));\n    const pend=st.pend;\n    let fila='';\n    if(pend==null) fila='<div class=\"qempty\">Carregando…</div>';\n    else if(!pend.length) fila='<div class=\"qempty\">Ninguém esperando número.</div>';\n    else fila=pend.map(p=>{\n      const founder=String(p.tier||'').toUpperCase()==='FOUNDER';\n      const meta=[p.email,p.origem,p.pagarme_order_id].filter(Boolean).map(esc).join(' · ');\n      return `<div class=\"qrow\"><div class=\"who\"><div class=\"nm\">${esc(p.nome)||'—'} <span class=\"chip ${founder?'f':''}\">${esc(p.tier)||'—'}</span></div><div class=\"mt\">${meta}</div></div>`+\n        `<div class=\"act\"><input data-num=\"${esc(p.id)}\" placeholder=\"nº\" ${st.busy?'disabled':''}><button class=\"atb\" data-id=\"${esc(p.id)}\" ${st.busy?'disabled':''}>${st.busy===p.id?'…':'Atribuir'}</button></div></div>`;\n    }).join('');\n    const secFila=`<div class=\"q\"><h3>Fila de números</h3><div class=\"qs\">Membros sem número · próximo Ignição ${st.proximo==null?'…':st.proximo}</div><div class=\"box\">${fila}</div><div class=\"qmsg ${st.msgOk?'ok':'er'}\">${esc(st.msg)}</div></div>`;\n    return `<div class=\"dash\"><div class=\"head\"><h2>Visão Geral</h2><div class=\"sm\">TEMPO BY PORSCHE · PAINEL INTERNO</div></div>\n      <div class=\"kpis\">\n        <div class=\"kpi\"><div class=\"n\">${n(st.membros)}</div><div class=\"l\">Membros</div><div class=\"sub\">${st.founders==null?'':st.founders+' founders'}</div></div>\n        <div class=\"kpi\"><div class=\"n\">${n(st.clientes)}</div><div class=\"l\">Clientes Cloudfy</div></div>\n        <div class=\"kpi\"><div class=\"n\">${st.entrados==null?'…':(st.entrados+'/'+st.total)}</div><div class=\"l\">Entrada · evento</div><div class=\"sub\">já entraram / total</div></div>\n        <div class=\"kpi\"><div class=\"n\">${n(st.produtos)}</div><div class=\"l\">Produtos</div><div class=\"sub\">${st.memberships==null?'':st.memberships+' memberships'}</div></div>\n      </div>${secFila}</div>`;\n  },\n  mounted(d2){\n    const KEY={authorization:'sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'};\n    const MR=/(member|founder|sócio|socio|plano|subscription|assinatura)/i;\n    (async()=>{ try{ const r=await d2.rush('list-members').invoke({limit:500},{headers:KEY}); const d=r&&r.data!==undefined?r.data:r; const ms=(d&&d.members)||[]; d2.state.membros=ms.length; d2.state.founders=ms.filter(m=>String(m.tipo_cadastro||'').toUpperCase()==='FOUNDER').length; }catch(e){ d2.state.membros='—'; } })();\n    (async()=>{ try{ const r=await d2.rush('proxy-cliente').invoke({},{headers:KEY}); let d=r&&r.data!==undefined?r.data:r; if(d&&d.data!==undefined)d=d.data; d2.state.clientes=((d&&d.DadosCliente)||[]).length; }catch(e){ d2.state.clientes='—'; } })();\n    (async()=>{ try{ const r=await d2.rush('entrada-lista').invoke({},{headers:KEY}); const d=r&&r.data!==undefined?r.data:r; d2.state.entrados=(d&&d.entrados)||0; d2.state.total=(d&&d.total)||0; }catch(e){ d2.state.entrados='—'; d2.state.total='—'; } })();\n    (async()=>{ try{ const r=await d2.rush('proxy-products').invoke({},{headers:KEY}); let d=r&&r.data!==undefined?r.data:r; const arr=Array.isArray(d)?d:((d&&d.products)||[]); d2.state.produtos=arr.length; d2.state.memberships=arr.filter(p=>MR.test([p.name,p.slug].join(' '))).length; }catch(e){ d2.state.produtos='—'; } })();\n    const carregarFila=async()=>{\n      try{\n        const r=await d2.rush('membros-pendentes').invoke({},{headers:KEY});\n        const d=r&&r.data!==undefined?r.data:r;\n        if(!d||d.success!==true){ d2.state.pend=[]; d2.state.proximo=null; d2.state.msgOk=false; d2.state.msg='A fila não carregou: '+((d&&d.message)||'resposta inesperada do servidor.'); return; }\n        d2.state.pend=d.pendentes||[];\n        d2.state.proximo=d.proximo_ignicao!=null?d.proximo_ignicao:null;\n      }catch(e){ d2.state.pend=[]; d2.state.msgOk=false; d2.state.msg='Não consegui carregar a fila.'; }\n    };\n    carregarFila();\n    d2.on('.atb','click',async(e,el)=>{\n      const id=el.dataset.id;\n      const inp=d2.$('[data-num=\"'+id+'\"]');\n      const numero=((inp&&inp.value)||'').trim();\n      if(!numero){ d2.state.msgOk=false; d2.state.msg='Digite o número antes de atribuir.'; return; }\n      d2.state.busy=id; d2.state.msg='';\n      try{\n        const r=await d2.rush('membro-atribuir-numero').invoke({id,numero},{headers:KEY});\n        const d=r&&r.data!==undefined?r.data:r;\n        const ok=!!(d&&d.success);\n        d2.state.msgOk=ok;\n        d2.state.msg=((d&&d.message)||'Resposta inesperada do servidor.')+((d&&d.ocupado_por)?' — '+d.ocupado_por:'');\n        if(ok) await carregarFila();\n      }catch(err){ d2.log('atribuir err',err); d2.state.msgOk=false; d2.state.msg='Erro de conexão. Tente de novo.'; }\n      finally{ d2.state.busy=null; }\n    });\n  }\n}"}}}}}}}},{"_id":"6a34c12072be6a1240deeb03","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"edNcvjvd4tkBUVrTL-Rz6","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .wrap{height:100%;box-sizing:border-box;background:#0f0f12;color:#f4f4f6;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;display:flex;flex-direction:column;overflow:hidden}\n  .head{padding:20px 24px 14px;border-bottom:1px solid #232329;display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap}\n  .ttl{display:flex;flex-direction:column;gap:2px}\n  .ttl h1{margin:0;font-size:19px;font-weight:800;letter-spacing:-.01em}\n  .ttl span{font-size:12px;color:#8a8a93;text-transform:uppercase;letter-spacing:.08em}\n  .count{display:flex;align-items:baseline;gap:6px}\n  .count b{font-size:30px;font-weight:800;color:#d5001c}\n  .count i{font-style:normal;font-size:14px;color:#8a8a93}\n  .bar{height:5px;background:#232329;border-radius:99px;margin:0 24px;overflow:hidden}\n  .bar>div{height:100%;background:#d5001c;border-radius:99px;transition:width .35s ease}\n  .list{flex:1;overflow:auto;padding:12px 16px 24px;display:flex;flex-direction:column;gap:8px}\n  .row{display:flex;align-items:center;gap:14px;padding:13px 16px;background:#17171b;border:1px solid #232329;border-radius:13px;cursor:pointer;transition:all .15s ease;user-select:none}\n  .row:hover{border-color:#34343c}\n  .row[data-here]{background:#11201a;border-color:#1f6b46}\n  .box{width:26px;height:26px;border-radius:8px;border:2px solid #3a3a42;display:flex;align-items:center;justify-content:center;flex:0 0 auto;font-size:15px;color:#fff;transition:all .15s ease}\n  .row[data-here] .box{background:#1f9d57;border-color:#1f9d57}\n  .info{flex:1;min-width:0}\n  .nm{font-size:15px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .row[data-here] .nm{color:#7fe0a8}\n  .sub{font-size:12px;color:#8a8a93;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .time{font-size:12px;color:#1f9d57;font-weight:600;flex:0 0 auto}\n  .empty{padding:40px;text-align:center;color:#8a8a93;font-size:14px}\n  `,\n  render(d2){\n    const ds = d2.data('dataset')\n    if (ds.loading) return `<div class=\"wrap\"><div class=\"empty\">Carregando…</div></div>`\n    const rows = ds.records().filter(r => r.nome_completo && !/teste/i.test(r.nome_completo))\n    const here = d2.state.here || {}\n    const arrived = rows.filter(r => here[r._id]).length\n    const pct = rows.length ? Math.round((arrived / rows.length) * 100) : 0\n    const list = rows.length ? rows.map(r => {\n      const on = !!here[r._id]\n      const loc = [r.cidade, r.estado].filter(Boolean).join(', ')\n      const sub = [r.modelo_porsche, loc].filter(Boolean).join('  ·  ') || '—'\n      return `<div class=\"row\" data-key=\"${r._id}\" data-id=\"${r._id}\" ${on?'data-here':''}>\n        <div class=\"box\">${on?'✓':''}</div>\n        <div class=\"info\">\n          <div class=\"nm\">${(r.nome_completo||'').replace(/</g,'&lt;')}</div>\n          <div class=\"sub\">${sub.replace(/</g,'&lt;')}</div>\n        </div>\n        ${on?`<div class=\"time\">${here[r._id]}</div>`:''}\n      </div>`\n    }).join('') : `<div class=\"empty\">Nenhum membro cadastrado ainda.</div>`\n    return `<div class=\"wrap\">\n      <div class=\"head\">\n        <div class=\"ttl\"><span>Check-in de hoje</span><h1>Recepção de Membros</h1></div>\n        <div class=\"count\"><b>${arrived}</b><i>de ${rows.length} chegaram</i></div>\n      </div>\n      <div class=\"bar\"><div style=\"width:${pct}%\"></div></div>\n      <div class=\"list\">${list}</div>\n    </div>`\n  },\n  mounted(d2){\n    d2.on('.row','click',(e,el)=>{\n      const id = el.dataset.id\n      const here = {...(d2.state.here||{})}\n      if(here[id]) delete here[id]\n      else here[id] = new Date().toLocaleTimeString('pt-BR',{hour:'2-digit',minute:'2-digit'})\n      d2.state.here = here\n    })\n  },\n}"}},"dataset":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"dataset"}}}}}}}}}},{"_id":"6a34c15072be6a1240deeb2e","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"F2PUvUEG1xekGQ7WFJdsV","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    .wrap{width:100%;height:100%;box-sizing:border-box;background:#0f1115;color:#e7e9ee;font-family:Inter,system-ui,-apple-system,sans-serif;padding:28px 22px;overflow-y:auto;}\n    .head{display:flex;align-items:baseline;justify-content:space-between;flex-wrap:wrap;gap:8px;margin-bottom:6px;}\n    .title{font-size:26px;font-weight:800;letter-spacing:-.4px;}\n    .sub{font-size:14px;color:#8b90a0;margin-bottom:20px;}\n    .count{font-size:14px;font-weight:700;color:#5b8cff;background:#1a2138;padding:6px 14px;border-radius:999px;}\n    .row{display:flex;align-items:center;gap:16px;padding:16px 18px;border-radius:16px;background:#171a21;border:1px solid #232733;margin-bottom:12px;transition:all .18s;}\n    .row.done{background:#13241a;border-color:#1f4d33;}\n    .check{flex:0 0 auto;width:34px;height:34px;border-radius:50%;border:2px solid #3a4150;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:18px;color:transparent;transition:all .15s;user-select:none;}\n    .row.done .check{background:#22c55e;border-color:#22c55e;color:#fff;}\n    .check:hover{border-color:#5b8cff;}\n    .info{flex:1 1 auto;min-width:0;}\n    .name{font-size:18px;font-weight:700;}\n    .row.done .name{text-decoration:line-through;color:#7c8aa0;}\n    .meta{font-size:13px;color:#8b90a0;margin-top:3px;display:flex;gap:12px;flex-wrap:wrap;}\n    .obs{color:#e0b341;}\n    .when{flex:0 0 auto;font-size:13px;font-weight:700;color:#22c55e;}\n    .empty{text-align:center;color:#8b90a0;padding:60px 0;}\n  `,\n  render(d2){\n    const data = d2.data();\n    const rows = data ? data.records() : [];\n    const done = rows.filter(r=>r.checkin).length;\n    const fmtTime = (d)=>{ try{ return new Date(d).toLocaleTimeString('pt-BR',{hour:'2-digit',minute:'2-digit'}); }catch(e){ return ''; } };\n    const body = rows.length ? rows.map(r=>{\n      const hor = Array.isArray(r.horarios)? r.horarios.join(' · ') : '';\n      const pax = r.pax ? `${r.pax} pax` : '';\n      const obs = r.obs ? `<span class=\"obs\">★ ${r.obs}</span>` : '';\n      const meta = [hor, pax].filter(Boolean).join(' &nbsp;•&nbsp; ');\n      return `<div class=\"row ${r.checkin?'done':''}\" data-key=\"${r._id}\">\n        <div class=\"check\" data-id=\"${r._id}\">✓</div>\n        <div class=\"info\">\n          <div class=\"name\">${r.nome||'—'}</div>\n          <div class=\"meta\">${meta} ${obs}</div>\n        </div>\n        ${r.checkin? `<div class=\"when\">chegou ${fmtTime(r.checkin)}</div>`:''}\n      </div>`;\n    }).join('') : `<div class=\"empty\">Nenhuma reserva pra hoje ainda.</div>`;\n    return `<div class=\"wrap\">\n      <div class=\"head\"><div class=\"title\">Check-in de hoje</div><div class=\"count\">${done}/${rows.length} chegaram</div></div>\n      <div class=\"sub\">Toque no círculo quando o membro chegar.</div>\n      ${body}\n    </div>`;\n  },\n  mounted(d2){\n    d2.on('.check','click', async (e,el)=>{\n      const id = el.getAttribute('data-id');\n      const data = d2.data();\n      const rec = data.records().find(r=>r._id===id);\n      if(!rec) return;\n      data.select(id);\n      const novo = rec.checkin ? null : new Date().toISOString();\n      data.set('checkin', novo);\n      await data.save();\n      data.refresh();\n    });\n  }\n}"}},"dataset":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"dataset"}}}}}}}}}},{"_id":"6a34c1c991e2b9586702a601","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"listaComprasUI","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    * { box-sizing: border-box; margin: 0; padding: 0; }\n    .wrap { width:100%; height:100%; overflow-y:auto; background:#f5f3ee; font-family: -apple-system, system-ui, sans-serif; color:#2a2521; padding: 20px 16px 40px; }\n    .inner { max-width: 640px; margin: 0 auto; }\n    .head { display:flex; align-items:baseline; justify-content:space-between; gap:12px; margin-bottom: 6px; flex-wrap:wrap; }\n    .title { font-size: 26px; font-weight: 800; letter-spacing:-0.02em; }\n    .count { font-size: 14px; font-weight:700; color:#7a6f63; background:#ece7df; padding:6px 12px; border-radius:999px; white-space:nowrap; }\n    .sub { font-size: 13px; color:#9a9088; margin-bottom: 18px; }\n    .cat { margin-top: 22px; }\n    .catname { font-size: 12px; font-weight:800; text-transform:uppercase; letter-spacing:0.08em; color:#b5703a; margin-bottom: 8px; padding-left:2px; }\n    .item { display:flex; align-items:center; gap:14px; background:#fff; border:1px solid #ece7df; border-radius:14px; padding:14px 16px; margin-bottom:8px; cursor:pointer; transition:all .12s; user-select:none; }\n    .item:active { transform:scale(0.99); }\n    .item.done { background:#f0ede7; border-color:#e3ddd3; }\n    .box { width:24px; height:24px; border-radius:8px; border:2px solid #d4cdc1; flex-shrink:0; display:flex; align-items:center; justify-content:center; transition:all .12s; }\n    .item.done .box { background:#5a9a4e; border-color:#5a9a4e; }\n    .box svg { width:14px; height:14px; opacity:0; transform:scale(.5); transition:all .14s; }\n    .item.done .box svg { opacity:1; transform:scale(1); }\n    .label { font-size:16px; font-weight:600; flex:1; }\n    .item.done .label { text-decoration:line-through; color:#a89e92; }\n    .addrow { display:flex; gap:8px; margin-top:24px; }\n    .addrow input { flex:1; border:1px solid #ddd6ca; background:#fff; border-radius:12px; padding:13px 15px; font-size:15px; font-family:inherit; outline:none; }\n    .addrow input:focus { border-color:#b5703a; }\n    .addrow button { background:#2a2521; color:#fff; border:none; border-radius:12px; padding:0 20px; font-size:15px; font-weight:700; cursor:pointer; }\n    .progress { height:6px; background:#ece7df; border-radius:999px; margin:14px 0 4px; overflow:hidden; }\n    .bar { height:100%; background:#5a9a4e; border-radius:999px; transition:width .25s; }\n  `,\n  render(d2) {\n    const store = d2.store('listaCompras');\n    const checked = d2.state.checked || store.get('checked', {}) || {};\n    const extra = d2.state.extra || store.get('extra', []) || [];\n\n    const base = {\n      'Proteínas': ['Picanha', 'Frango', 'Linguiça', 'Camarão', 'Queijo coalho'],\n      'Hortifruti': ['Alface', 'Tomate', 'Cebola', 'Limão', 'Batata', 'Alho'],\n      'Secos & Mercearia': ['Arroz', 'Feijão', 'Farinha', 'Sal grosso', 'Azeite', 'Pão de alho'],\n      'Bebidas': ['Cerveja', 'Refrigerante', 'Água', 'Gelo', 'Suco'],\n      'Descartáveis & Limpeza': ['Guardanapo', 'Copo descartável', 'Carvão', 'Saco de lixo'],\n    };\n    const cats = { ...base };\n    extra.forEach(e => { (cats[e.cat] = cats[e.cat] || []).push(e.name); });\n\n    const all = Object.values(cats).flat();\n    const done = all.filter(i => checked[i]).length;\n    const pct = all.length ? Math.round(done / all.length * 100) : 0;\n\n    const check = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"3.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>`;\n\n    const sections = Object.entries(cats).map(([cat, items]) => `\n      <div class=\"cat\">\n        <div class=\"catname\">${cat}</div>\n        ${items.map(i => `\n          <div class=\"item ${checked[i] ? 'done' : ''}\" data-item=\"${i}\">\n            <div class=\"box\">${check}</div>\n            <div class=\"label\">${i}</div>\n          </div>`).join('')}\n      </div>`).join('');\n\n    return `\n      <div class=\"wrap\"><div class=\"inner\">\n        <div class=\"head\">\n          <div class=\"title\">Lista de Compras</div>\n          <div class=\"count\">${done}/${all.length} no carrinho</div>\n        </div>\n        <div class=\"sub\">Toque no item quando colocar no carrinho.</div>\n        <div class=\"progress\"><div class=\"bar\" style=\"width:${pct}%\"></div></div>\n        ${sections}\n        <div class=\"addrow\">\n          <input id=\"newitem\" placeholder=\"Adicionar item...\" />\n          <button id=\"addbtn\">+ Add</button>\n        </div>\n      </div></div>`;\n  },\n  mounted(d2, root) {\n    const store = d2.store('listaCompras');\n    d2.on('.item', 'click', (e, el) => {\n      const item = el.getAttribute('data-item');\n      const checked = { ...(d2.state.checked || store.get('checked', {}) || {}) };\n      checked[item] = !checked[item];\n      d2.state.checked = checked;\n      store.set('checked', checked);\n    });\n    const add = () => {\n      const inp = d2.$('#newitem');\n      const name = (inp.value || '').trim();\n      if (!name) return;\n      const extra = [...(d2.state.extra || store.get('extra', []) || [])];\n      extra.push({ name, cat: 'Outros' });\n      d2.state.extra = extra;\n      store.set('extra', extra);\n      inp.value = '';\n    };\n    d2.on('#addbtn', 'click', add);\n    d2.on('#newitem', 'keydown', (e) => { if (e.key === 'Enter') add(); });\n  }\n}"}},"store":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"store"}}}}}}}}}},{"_id":"6a43ffa1e7591d10f645daea","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"ReservasScreen","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .scr{height:100%;overflow:auto;background:#0a0a0a;font-family:'Inter',system-ui,sans-serif;color:#fff;box-sizing:border-box}\n  .head{display:flex;align-items:center;gap:14px;padding:28px 36px 18px;flex-wrap:wrap}\n  .head h2{font-family:'Anton',sans-serif;font-size:22px;letter-spacing:.08em;text-transform:uppercase;margin:0}\n  .head .sm{font-size:11px;color:#9a9a9a;letter-spacing:.1em;font-weight:600}\n  .bar{flex:1;height:1px;background:#2a2a2a;min-width:30px}\n  .daysel{display:flex;align-items:center;gap:10px}\n  .nav{background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;width:38px;height:38px;border-radius:8px;font-size:17px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:.12s}\n  .nav:hover{border-color:#F4C400;color:#F4C400}\n  .dpick{background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;padding:9px 12px;font-size:14px;border-radius:8px;outline:none;font-weight:600;color-scheme:dark}\n  .dpick:focus{border-color:#F4C400}\n  .today{background:transparent;border:1px solid #2a2a2a;color:#9a9a9a;padding:9px 12px;font-size:11px;letter-spacing:.1em;font-weight:700;text-transform:uppercase;border-radius:8px;cursor:pointer}\n  .today:hover{border-color:#F4C400;color:#F4C400}\n  .kpis{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px;padding:6px 36px 8px}\n  .kpi{background:#141414;border:1px solid #2a2a2a;border-left:3px solid #F4C400;border-radius:12px;padding:18px 22px}\n  .kpi .shift{font-size:11px;letter-spacing:.16em;color:#9a9a9a;text-transform:uppercase;font-weight:700;margin-bottom:12px}\n  .kpi .grid{display:flex;flex-wrap:wrap;gap:18px 24px}\n  .kpi .cell .n{font-family:'Anton',sans-serif;font-size:27px;color:#F4C400;line-height:1}\n  .kpi .cell .l{font-size:10px;letter-spacing:.12em;color:#7a7a7a;text-transform:uppercase;margin-top:6px;font-weight:700}\n  .kpi .cell.free .n{color:#fff}\n  .sec{padding:18px 36px 4px;font-size:10px;letter-spacing:.22em;color:#5a5a5a;font-weight:700;text-transform:uppercase}\n  .rows{display:flex;flex-direction:column;gap:8px;padding:8px 36px 14px}\n  .res{display:flex;align-items:center;gap:16px;background:#141414;border:1px solid #2a2a2a;border-radius:10px;padding:13px 18px}\n  .res .time{font-family:'Anton',sans-serif;font-size:20px;color:#F4C400;min-width:62px}\n  .res .who{flex:1;min-width:0}\n  .res .cn{font-weight:700;font-size:15px}\n  .res .meta{color:#9a9a9a;font-size:12px;margin-top:3px;overflow:hidden;text-overflow:ellipsis}\n  .res .ppl{display:flex;align-items:center;gap:6px;color:#cfcfcf;font-size:13px;font-weight:700;white-space:nowrap}\n  .chip{font-size:10px;letter-spacing:.1em;font-weight:800;text-transform:uppercase;padding:5px 10px;border-radius:20px;white-space:nowrap}\n  .chip.go{background:#F4C400;color:#000}\n  .chip.warn{background:#3a3320;color:#F4C400;border:1px solid #6a5a1e}\n  .chip.neutral{background:#2a2a2a;color:#c9c9c9}\n  .chip.off{background:#1a1a1a;color:#6a6a6a;border:1px solid #2a2a2a}\n  .walk{display:flex;align-items:center;gap:16px;background:#121212;border:1px solid #222;border-radius:10px;padding:11px 18px}\n  .walk .time{font-family:'Inter';font-size:13px;color:#9a9a9a;min-width:62px;font-weight:700}\n  .walk .cn{font-weight:600;font-size:14px;flex:1}\n  .walk .ppl{color:#cfcfcf;font-size:13px;font-weight:700}\n  .empty{padding:22px 36px;color:#7a7a7a;font-size:13px}\n  .loading{padding:30px 36px;color:#9a9a9a;font-size:14px}\n  .errb{padding:18px 36px;color:#ffce7a;font-size:13px}\n  /* row actions */\n  .res .acts{display:flex;align-items:center;gap:7px;white-space:nowrap}\n  .abtn{font-size:11px;letter-spacing:.06em;font-weight:700;text-transform:uppercase;padding:7px 12px;border-radius:7px;cursor:pointer;border:1px solid #2a2a2a;background:#1c1c1c;color:#cfcfcf;transition:.12s}\n  .abtn:hover{border-color:#F4C400;color:#F4C400}\n  .abtn.prim{background:#F4C400;color:#000;border-color:#F4C400}\n  .abtn.prim:hover{background:#ffd633;color:#000}\n  .abtn.ghost{background:transparent}\n  .abtn[disabled]{opacity:.4;cursor:default;pointer-events:none}\n  .cfm{display:flex;align-items:center;gap:8px;background:#1a1812;border:1px solid #6a5a1e;border-radius:8px;padding:6px 10px}\n  .cfm .q{font-size:11px;color:#F4C400;font-weight:600}\n  .cfm .yes{background:#F4C400;color:#000;border:none;padding:6px 11px;border-radius:6px;font-size:11px;font-weight:800;cursor:pointer;text-transform:uppercase;letter-spacing:.05em}\n  .cfm .no{background:#2a2a2a;color:#c9c9c9;border:none;padding:6px 11px;border-radius:6px;font-size:11px;font-weight:700;cursor:pointer;text-transform:uppercase;letter-spacing:.05em}\n  .newbtn{background:#F4C400;color:#000;border:none;padding:10px 16px;font-size:12px;letter-spacing:.06em;font-weight:800;text-transform:uppercase;border-radius:8px;cursor:pointer;transition:.12s}\n  .newbtn:hover{background:#ffd633}\n  /* modal */\n  .ovl{position:absolute;inset:0;background:rgba(0,0,0,.72);display:flex;align-items:flex-start;justify-content:center;padding:48px 20px;z-index:50;overflow:auto}\n  .modal{background:#141414;border:1px solid #2a2a2a;border-radius:16px;width:100%;max-width:440px;box-shadow:0 24px 60px rgba(0,0,0,.6)}\n  .modal .mh{display:flex;align-items:center;justify-content:space-between;padding:20px 24px 14px;border-bottom:1px solid #222}\n  .modal .mh h3{font-family:'Anton',sans-serif;font-size:18px;letter-spacing:.06em;text-transform:uppercase;margin:0}\n  .modal .x{background:transparent;border:none;color:#9a9a9a;font-size:22px;cursor:pointer;line-height:1}\n  .modal .x:hover{color:#F4C400}\n  .mbody{padding:18px 24px 22px;display:flex;flex-direction:column;gap:14px}\n  .fld{display:flex;flex-direction:column;gap:6px}\n  .fld label{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:#7a7a7a;font-weight:700}\n  .fld input{background:#1c1c1c;border:1px solid #2a2a2a;color:#fff;padding:10px 12px;border-radius:8px;font-size:14px;outline:none;color-scheme:dark;font-family:inherit}\n  .fld input:focus{border-color:#F4C400}\n  .frow{display:flex;gap:12px}\n  .frow .fld{flex:1}\n  .lkrow{display:flex;gap:8px;align-items:flex-end}\n  .lkrow .fld{flex:1}\n  .lkbtn{background:#1c1c1c;border:1px solid #2a2a2a;color:#cfcfcf;padding:10px 14px;border-radius:8px;font-size:12px;font-weight:700;cursor:pointer;text-transform:uppercase;letter-spacing:.05em;height:40px}\n  .lkbtn:hover{border-color:#F4C400;color:#F4C400}\n  .matches{display:flex;flex-direction:column;gap:6px;max-height:170px;overflow:auto}\n  .match{display:flex;align-items:center;gap:10px;background:#1a1a1a;border:1px solid #2a2a2a;border-radius:8px;padding:9px 12px;cursor:pointer}\n  .match:hover{border-color:#F4C400}\n  .match.sel{border-color:#F4C400;background:#221f12}\n  .match .mn{font-weight:700;font-size:13px}\n  .match .mp{font-size:11px;color:#9a9a9a;margin-top:2px}\n  .match .pick{margin-left:auto;font-size:10px;letter-spacing:.08em;font-weight:800;text-transform:uppercase;color:#F4C400}\n  .mfoot{display:flex;justify-content:flex-end;gap:10px;padding-top:6px}\n  .mnote{font-size:11px;color:#7a7a7a}\n  .mnote.err{color:#ffce7a}\n  .mnote.ok{color:#F4C400}\n  .selpill{display:flex;align-items:center;gap:8px;background:#221f12;border:1px solid #6a5a1e;border-radius:8px;padding:9px 12px}\n  .selpill .sn{font-weight:700;font-size:13px;color:#fff}\n  .selpill .sp{font-size:11px;color:#cfcfcf}\n  .selpill .clr{margin-left:auto;background:transparent;border:none;color:#9a9a9a;cursor:pointer;font-size:12px}\n  .selpill .clr:hover{color:#F4C400}\n  .shiftrow{display:flex;flex-wrap:wrap;gap:8px}\n  .shiftchip{display:flex;align-items:center;gap:7px;background:#1c1c1c;border:1px solid #2a2a2a;color:#cfcfcf;padding:9px 13px;border-radius:8px;font-size:12px;font-weight:700;cursor:pointer;text-transform:none;letter-spacing:.02em;transition:.12s;font-family:inherit}\n  .shiftchip:hover{border-color:#F4C400;color:#F4C400}\n  .shiftchip .sw{font-size:11px;color:#9a9a9a;font-weight:600}\n  .shiftchip.on{background:#F4C400;color:#000;border-color:#F4C400}\n  .shiftchip.on .sw{color:#3a3000}\n  .tagrow{display:flex;flex-wrap:wrap;gap:8px}\n  .tagchip{background:#1c1c1c;border:1px solid #2a2a2a;color:#cfcfcf;padding:7px 12px;border-radius:20px;font-size:11px;font-weight:700;cursor:pointer;letter-spacing:.04em;transition:.12s;font-family:inherit}\n  .tagchip:hover{border-color:#F4C400;color:#F4C400}\n  .tagchip.on{background:#F4C400;color:#000;border-color:#F4C400}\n  `,\n  render(d2){\n    const esc=s=>String(s==null?'':s).replace(/[&<>\"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;'}[c]));\n    const st=d2.state;\n    const dstr=st.day||'';\n    const fmtDay=()=>{ if(!dstr)return ''; const [y,m,dd]=dstr.split('-').map(Number); const dt=new Date(y,m-1,dd); const dias=['Domingo','Segunda','Terça','Quarta','Quinta','Sexta','Sábado']; const mes=['jan','fev','mar','abr','mai','jun','jul','ago','set','out','nov','dez']; return `${dias[dt.getDay()]}, ${dd} ${mes[m-1]} ${y}`; };\n    // occupancy cards\n    const shiftCard=(slug,label)=>{ const sh=(st.shifts||[]).find(s=>s.slug===slug)||{}; const res=sh.reservationsQuantity||0; const cov=sh.customersQuantity||0; const seats=sh.seats||0; const free=sh.freeSeats!=null?sh.freeSeats:seats; return `<div class=\"kpi\"><div class=\"shift\">${label}</div><div class=\"grid\"><div class=\"cell\"><div class=\"n\">${res}</div><div class=\"l\">Reservas</div></div><div class=\"cell\"><div class=\"n\">${cov}</div><div class=\"l\">Pessoas</div></div><div class=\"cell free\"><div class=\"n\">${free}/${seats}</div><div class=\"l\">Lugares livres</div></div></div></div>`; };\n    // reservations\n    const STMAP={Confirmed:['go','Confirmada'],Seated:['go','Sentada'],New:['neutral','Nova'],Pending:['warn','Pendente'],Placeholder:['warn','Pré-reserva'],Overbook:['off','Overbook'],Canceled:['off','Cancelada']};\n    let resBody;\n    if(st.loading)resBody=`<div class=\"loading\">Carregando reservas da TAGME…</div>`;\n    else if(st.err)resBody=`<div class=\"errb\">${esc(st.err)}</div>`;\n    else { const list=(st.reservas||[]).slice().sort((a,b)=>String(a.reservationTime||'').localeCompare(String(b.reservationTime||'')));\n      if(!list.length)resBody=`<div class=\"empty\">Nenhuma reserva para este dia.</div>`;\n      else resBody=`<div class=\"rows\">`+list.map(r=>{ const c=r.customer||{}; const nm=[c.name,c.lastName].filter(Boolean).join(' ')||'—'; const sm=STMAP[r.status]||['neutral',r.status||'—']; const metaParts=[]; if(r.section)metaParts.push('Salão'); if(c.phone)metaParts.push(esc(c.phone)); if(r.note)metaParts.push(esc(r.note));\n        const id=esc(r._id||''); const stt=r.status||''; const busy=st.actId===r._id;\n        let actHtml;\n        if(st.confirmCancel===r._id){ actHtml=`<div class=\"cfm\"><span class=\"q\">Cancelar reserva de ${esc(nm)}?</span><button class=\"yes act-cancel-yes\" data-id=\"${id}\">Sim</button><button class=\"no act-cancel-no\">Não</button></div>`; }\n        else { const btns=[];\n          if(stt==='New'||stt==='Pending'){ btns.push(`<button class=\"abtn prim act-confirm\" data-id=\"${id}\"${busy?' disabled':''}>Confirmar</button>`); }\n          if(stt==='New'||stt==='Confirmed'){ btns.push(`<button class=\"abtn act-seat\" data-id=\"${id}\"${busy?' disabled':''}>Sentar</button>`); }\n          if(stt!=='Canceled'&&stt!=='Seated'){ btns.push(`<button class=\"abtn ghost act-cancel\" data-id=\"${id}\"${busy?' disabled':''}>Cancelar</button>`); }\n          actHtml=`<div class=\"acts\">${btns.join('')}</div>`;\n        }\n        return `<div class=\"res\"><div class=\"time\">${esc(r.reservationTime||'--:--')}</div><div class=\"who\"><div class=\"cn\">${esc(nm)}</div><div class=\"meta\">${metaParts.join(' · ')||'&nbsp;'}</div></div><div class=\"ppl\">▦ ${r.partySize||0}</div><span class=\"chip ${sm[0]}\">${esc(sm[1])}</span>${actHtml}</div>`; }).join('')+`</div>`;\n    }\n    // walk-ins\n    let walkBody;\n    if(st.loading)walkBody='';\n    else { const w=(st.walkins||[]).slice().sort((a,b)=>String(b.seatedAt||'').localeCompare(String(a.seatedAt||'')));\n      if(!w.length)walkBody=`<div class=\"empty\">Nenhum walk-in registrado.</div>`;\n      else walkBody=`<div class=\"rows\">`+w.map(x=>{ const c=x.customer||{}; const nm=[c.name,c.lastName].filter(Boolean).join(' ')||'—'; let t=''; if(x.seatedAt){const d=new Date(x.seatedAt); t=String(d.getHours()).padStart(2,'0')+':'+String(d.getMinutes()).padStart(2,'0');} return `<div class=\"walk\"><div class=\"time\">${esc(t||'—')}</div><div class=\"cn\">${esc(nm)}${x.note?` <span style=\"color:#7a7a7a;font-weight:400\">· ${esc(x.note)}</span>`:''}</div><div class=\"ppl\">▦ ${x.partySize||0}</div></div>`; }).join('')+`</div>`;\n    }\n    return `<div class=\"scr\">\n      <div class=\"head\"><h2>Reservas <span class=\"sm\">TAGME · TEMPO BY PORSCHE</span></h2><div class=\"bar\"></div>\n        <div class=\"daysel\"><button class=\"nav prev\" title=\"Dia anterior\">‹</button><input type=\"date\" class=\"dpick\" value=\"${esc(dstr)}\"><button class=\"nav next\" title=\"Próximo dia\">›</button><button class=\"today\">Hoje</button><button class=\"newbtn nova\">+ Nova reserva</button></div>\n        <span class=\"sm\" style=\"width:100%;color:#cfcfcf;font-size:13px;letter-spacing:.04em;text-transform:none\">${esc(fmtDay())}</span>\n      </div>\n      <div class=\"kpis\">${shiftCard('lunch','Almoço')}${shiftCard('dinner','Jantar')}</div>\n      <div class=\"sec\">Reservas do dia</div>\n      ${resBody}\n      <div class=\"sec\">Walk-ins</div>\n      ${walkBody}\n      ${st.showNew?(()=>{ const f=st.form||{}; const sel=st.selCustomer; const matches=st.matches||[];\n        const matchHtml=()=>{ if(st.lookupLoading)return `<div class=\"mnote\">Buscando cliente…</div>`; if(st.lookupErr)return `<div class=\"mnote err\">${esc(st.lookupErr)}</div>`; if(!matches.length)return st.lookupDone?`<div class=\"mnote err\">Nenhum cliente encontrado para este telefone. Cadastre o cliente na TAGME antes de criar a reserva.</div>`:''; return `<div class=\"matches\">`+matches.map(m=>{ const nm=[m.name,m.lastName].filter(Boolean).join(' ')||'—'; return `<div class=\"match${sel&&sel._id===m._id?' sel':''}\" data-cid=\"${esc(m._id)}\"><div><div class=\"mn\">${esc(nm)}</div><div class=\"mp\">${esc(m.phone||'')}${m.email?' · '+esc(m.email):''}</div></div><span class=\"pick\">Selecionar</span></div>`; }).join('')+`</div>`; };\n        const customerBlock= sel?`<div class=\"fld\"><label>Cliente</label><div class=\"selpill\"><div><div class=\"sn\">${esc([sel.name,sel.lastName].filter(Boolean).join(' '))}</div><div class=\"sp\">${esc(sel.phone||'')}${sel.email?' · '+esc(sel.email):''}</div></div><button class=\"clr clr-cust\">trocar</button></div></div>`\n          :`<div class=\"lkrow\"><div class=\"fld\"><label>Telefone do cliente</label><input type=\"tel\" class=\"f-phone\" placeholder=\"+55 11 9....\" value=\"${esc(f.phone||'')}\"></div><button class=\"lkbtn lookup\">Buscar</button></div>${matchHtml()}`;\n        // --- config-aware bits ---\n        const fday=f.day||dstr;\n        const shiftsForDay=st.shiftsForDay?st.shiftsForDay(fday):[];\n        const maxParty=st.maxParty||0;\n        const cfgLoading=st.cfgLoading; const cfgErr=st.cfgErr;\n        const curShift=(st.shiftHit?st.shiftHit(fday,f.time):null);\n        let shiftBlock;\n        if(cfgLoading){ shiftBlock=`<div class=\"fld\"><label>Turno</label><div class=\"mnote\">Carregando configuração do salão…</div></div>`; }\n        else if(cfgErr){ shiftBlock=`<div class=\"fld\"><label>Turno</label><div class=\"mnote err\">${esc(cfgErr)}</div></div>`; }\n        else if(!fday){ shiftBlock=`<div class=\"fld\"><label>Turno</label><div class=\"mnote\">Selecione a data.</div></div>`; }\n        else if(!shiftsForDay.length){ shiftBlock=`<div class=\"fld\"><label>Turno</label><div class=\"mnote err nosvc\">Sem turno neste dia. Escolha outra data.</div></div>`; }\n        else { const chips=shiftsForDay.map(sh=>{ const on=curShift&&curShift._id===sh._id; return `<button type=\"button\" class=\"shiftchip${on?' on':''}\" data-shift=\"${esc(sh._id)}\" data-start=\"${esc(sh.start)}\" data-end=\"${esc(sh.end)}\">${esc(sh.label)} <span class=\"sw\">${esc(sh.start)}–${esc(sh.end)}</span></button>`; }).join('');\n          shiftBlock=`<div class=\"fld\"><label>Turno disponível</label><div class=\"shiftrow\">${chips}</div></div>`; }\n        const tags=st.tags||[]; const selTags=st.selTags||[];\n        const tagBlock= tags.length?`<div class=\"fld\"><label>Tags (opcional)</label><div class=\"tagrow\">`+tags.map(t=>{ const on=selTags.indexOf(t.name)>=0; return `<button type=\"button\" class=\"tagchip${on?' on':''}\" data-tag=\"${esc(t.name)}\">${esc(t.name)}</button>`; }).join('')+`</div></div>`:'';\n        const sizeNum=parseInt(f.size,10)||0; const overCap=maxParty>0&&sizeNum>maxParty;\n        const sizeNote= overCap?`<div class=\"mnote err\">Para grupos acima de ${maxParty}, contate oi@tempobyporsche.com</div>`:'';\n        const timeValid=!!curShift; const dayHasShift=shiftsForDay.length>0;\n        const blockSubmit= !sel||st.creating||cfgLoading||!!cfgErr||!dayHasShift||!timeValid||overCap||!f.time;\n        const note= st.createErr?`<div class=\"mnote err\">${esc(st.createErr)}</div>`:(st.creating?`<div class=\"mnote\">Criando reserva…</div>`:(dayHasShift&&!timeValid&&f.time?`<div class=\"mnote err\">Horário fora dos turnos deste dia.</div>`:`<div class=\"mnote\">A reserva será criada como origem WhatsApp (canal do painel).</div>`));\n        return `<div class=\"ovl\"><div class=\"modal\"><div class=\"mh\"><h3>Nova reserva</h3><button class=\"x close-new\">×</button></div><div class=\"mbody\">\n          <div class=\"frow\"><div class=\"fld\"><label>Data</label><input type=\"date\" class=\"f-day\" value=\"${esc(fday)}\"></div><div class=\"fld\"><label>Horário</label><input type=\"time\" class=\"f-time\"${(!dayHasShift||cfgLoading)?' disabled':''} value=\"${esc(f.time||'')}\"></div><div class=\"fld\"><label>Pessoas${maxParty?` <span style=\"color:#7a7a7a\">(máx ${maxParty})</span>`:''}</label><input type=\"number\" min=\"1\"${maxParty?` max=\"${maxParty}\"`:''} class=\"f-size\" value=\"${esc(f.size||'2')}\"></div></div>\n          ${shiftBlock}\n          ${sizeNote}\n          ${tagBlock}\n          ${customerBlock}\n          ${note}\n          <div class=\"mfoot\"><button class=\"abtn ghost close-new\">Cancelar</button><button class=\"abtn prim create-res\"${blockSubmit?' disabled':''}>Criar reserva</button></div>\n        </div></div></div>`; })():''}\n    </div>`;\n  },\n  mounted(d2){\n    const KEY={authorization:'sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'};\n    const VENUE=d2.param('venueId')||'69fcd30c55153376bd62ca81';\n    const READ=d2.param('tagmeRead')||'tagme-read';\n    const WRITE=d2.param('tagmeWrite')||'tagme-write';\n    const SECTION=d2.param('sectionId')||'69fe36ffb86391658ca82e08';\n    const ACTOR=d2.param('actorUserId')||'6a3d1f42b40a901a4bd7c45b';\n    const pad=n=>String(n).padStart(2,'0');\n    const todayStr=()=>{ const d=new Date(); return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`; };\n    if(!d2.state.day) d2.state.day=todayStr();\n    const unwrap=r=>{ let d=r&&r.data!==undefined?r.data:r; if(d&&d.data!==undefined)d=d.data; return d; };\n    // weekday from YYYY-MM-DD using TAGME convention 1=Mon..7=Sun\n    const weekdayOf=(dayStr)=>{ if(!dayStr||!/^\\d{4}-\\d{2}-\\d{2}$/.test(dayStr))return 0; const [y,m,dd]=dayStr.split('-').map(Number); const js=new Date(y,m-1,dd).getDay(); return js===0?7:js; };\n    const labelForShift=(sh)=>{ const h=parseInt(String(sh.start||'').slice(0,2),10); return h<16?'Almoço':'Jantar'; };\n    // derive valid shifts for a given date from the live schedules config\n    const shiftsForDay=(dayStr)=>{ const wd=weekdayOf(dayStr); if(!wd)return []; const sch=(d2.state.schedules||[]).filter(s=>Number(s.day)===wd); return sch.map(s=>({_id:s._id,start:s.start,end:s.end,seats:s.seats,label:labelForShift(s)})).sort((a,b)=>String(a.start).localeCompare(String(b.start))); };\n    // returns the shift object a HH:mm falls within for that date, else null (boundary: start<=t<end)\n    const shiftHit=(dayStr,time)=>{ if(!time||!/^\\d{2}:\\d{2}$/.test(time))return null; const list=shiftsForDay(dayStr); for(const sh of list){ if(time>=sh.start && time<sh.end) return sh; } return null; };\n    // expose helpers to render() via state (functions are fine on d2.state)\n    d2.state.weekdayOf=weekdayOf; d2.state.shiftsForDay=shiftsForDay; d2.state.shiftHit=shiftHit;\n    // load /Seat config once on mount, cache in state\n    const loadConfig=async()=>{ if(d2.state.cfgLoaded)return; d2.state.cfgLoading=true; d2.state.cfgErr=null; try{ const r=await d2.rush(READ).invoke({path:`/Seat/${VENUE}`},{headers:KEY}); const arr=unwrap(r); const seat=Array.isArray(arr)?arr[0]:arr; if(!seat){ d2.state.cfgErr='Configuração do salão indisponível.'; return; } const ba=(seat.bookingApps&&seat.bookingApps[0])||{}; d2.state.schedules=Array.isArray(ba.schedules)?ba.schedules:[]; const app=ba.app||{}; const sections=(app.venueSections||seat.venueSections||[]); const sec0=sections[0]||{}; const caps=sec0.capacityGroups||[]; d2.state.maxParty=caps.reduce((mx,g)=>Math.max(mx,Number(g.max)||0),0)||0; d2.state.cfgSection=app.section||sec0._id||SECTION; const tags=(app.tags||seat.tags||[]); d2.state.tags=Array.isArray(tags)?tags.map(t=>({name:t.name,label:t.label})):[]; d2.state.cfgLoaded=true; }catch(e){ d2.log('cfg err',e); d2.state.cfgErr='Erro ao carregar configuração: '+(e&&e.message||e); } finally{ d2.state.cfgLoading=false; } };\n    loadConfig();\n    const loadDay=async(day)=>{\n      d2.state.loading=true; d2.state.err=null;\n      const [y,m,dd]=day.split('-').map(Number);\n      try{\n        const rh=d2.rush(READ);\n        const [resR,occR,wkR]=await Promise.all([\n          rh.invoke({path:`/Reservation/List/${VENUE}/${y}/${m}/${dd}?isArray=true`},{headers:KEY}).catch(e=>{d2.log('res err',e);return null;}),\n          rh.invoke({path:`/ReservationStatus/${VENUE}/${day}/${day}/dayRangeShifts`},{headers:KEY}).catch(e=>{d2.log('occ err',e);return null;}),\n          rh.invoke({path:`/WalkIn/${VENUE}/byVenueId?yearMonthDay=${day}`},{headers:KEY}).catch(e=>{d2.log('wk err',e);return null;})\n        ]);\n        const resD=unwrap(resR); d2.state.reservas=Array.isArray(resD)?resD:[];\n        const occD=unwrap(occR); let shifts=[]; if(Array.isArray(occD)&&occD.length){ const dayObj=occD.find(o=>String(o.reservationDay||'').slice(0,10)===day)||occD[0]; const secs=(dayObj&&dayObj.sections)||[]; if(secs.length)shifts=secs[0].shifts||[]; } d2.state.shifts=shifts;\n        const wkD=unwrap(wkR); d2.state.walkins=Array.isArray(wkD)?wkD:[];\n        if(!resR&&!occR&&!wkR) d2.state.err='Não foi possível carregar dados da TAGME.';\n      }catch(e){ d2.log('reservas err',e); d2.state.err='Erro ao carregar reservas: '+(e&&e.message||e); }\n      finally{ d2.state.loading=false; }\n    };\n    loadDay(d2.state.day);\n    const shift=(delta)=>{ const [y,m,dd]=d2.state.day.split('-').map(Number); const dt=new Date(y,m-1,dd); dt.setDate(dt.getDate()+delta); const ns=`${dt.getFullYear()}-${pad(dt.getMonth()+1)}-${pad(dt.getDate())}`; d2.state.day=ns; loadDay(ns); };\n    d2.on('.prev','click',()=>shift(-1));\n    d2.on('.next','click',()=>shift(1));\n    d2.on('.today','click',()=>{ const ns=todayStr(); d2.state.day=ns; loadDay(ns); });\n    d2.on('.dpick','change',(e,el)=>{ if(el.value){ d2.state.day=el.value; loadDay(el.value); } });\n\n    // ---- WRITE actions ----\n    const findRes=id=>(d2.state.reservas||[]).find(r=>r._id===id);\n    const write=async(path,method,payload)=>{ const r=await d2.rush(WRITE).invoke({path,method,payload},{headers:KEY}); return unwrap(r); };\n    const runAction=async(id,fn)=>{ if(st_busy())return; d2.state.actId=id; d2.state.err=null; try{ await fn(); d2.state.actId=null; d2.state.confirmCancel=null; await loadDay(d2.state.day); }catch(e){ d2.log('action err',e); d2.state.actId=null; d2.state.err='Erro na ação: '+(e&&e.message||e); } };\n    const st_busy=()=>!!d2.state.actId;\n\n    d2.on('.act-confirm','click',(e,el)=>{ const id=el.getAttribute('data-id'); runAction(id,async()=>{ await write(`/Reservation/${id}`,'PUT',{ _id:id, status:'Confirmed', logs:{ user:ACTOR, actionType:'Update' } }); }); });\n    d2.on('.act-seat','click',(e,el)=>{ const id=el.getAttribute('data-id'); const r=findRes(id); if(!r)return; runAction(id,async()=>{ await write(`/Reservation/${VENUE}/${id}/Seat`,'PUT',{ table:null, note:'', vouchers:[], logs:{ user:ACTOR, actionType:'Seat' }, originalReservationData:r }); }); });\n    d2.on('.act-cancel','click',(e,el)=>{ const id=el.getAttribute('data-id'); d2.state.confirmCancel=id; });\n    d2.on('.act-cancel-no','click',()=>{ d2.state.confirmCancel=null; });\n    d2.on('.act-cancel-yes','click',(e,el)=>{ const id=el.getAttribute('data-id'); const r=findRes(id); if(!r)return; runAction(id,async()=>{ await write(`/Reservation/${VENUE}/${id}/Cancel`,'PUT',{ cancelReason:'Customer Requested', logs:{ user:ACTOR, actionType:'Remove' }, originalReservationData:r }); }); });\n\n    // ---- NEW reservation modal ----\n    const openNew=()=>{ d2.state.showNew=true; d2.state.form={day:d2.state.day,time:'',size:'2',phone:''}; d2.state.selCustomer=null; d2.state.matches=[]; d2.state.lookupDone=false; d2.state.lookupErr=null; d2.state.createErr=null; d2.state.selTags=[]; loadConfig(); };\n    const closeNew=()=>{ d2.state.showNew=false; d2.state.selCustomer=null; d2.state.matches=[]; d2.state.createErr=null; d2.state.selTags=[]; };\n    d2.on('.nova','click',openNew);\n    d2.on('.close-new','click',closeNew);\n    d2.on('.f-day','change',(e,el)=>{ const day=el.value; const cur=(d2.state.form||{}).time; const stillValid=cur&&shiftHit(day,cur); d2.state.form=Object.assign({},d2.state.form,{day:day,time:stillValid?cur:''}); });\n    d2.on('.f-time','change',(e,el)=>{ d2.state.form=Object.assign({},d2.state.form,{time:el.value}); });\n    d2.on('.f-size','change',(e,el)=>{ d2.state.form=Object.assign({},d2.state.form,{size:el.value}); });\n    d2.on('.shiftchip','click',(e,el)=>{ const start=el.getAttribute('data-start')||''; d2.state.form=Object.assign({},d2.state.form,{time:start}); });\n    d2.on('.tagchip','click',(e,el)=>{ const name=el.getAttribute('data-tag'); const cur=(d2.state.selTags||[]).slice(); const i=cur.indexOf(name); if(i>=0)cur.splice(i,1); else cur.push(name); d2.state.selTags=cur; });\n    d2.on('.f-phone','input',(e,el)=>{ d2.state.form=Object.assign({},d2.state.form,{phone:el.value}); });\n\n    const lookup=async()=>{ const raw=String((d2.state.form||{}).phone||'').replace(/[^0-9]/g,''); if(!raw){ d2.state.lookupErr='Informe um telefone.'; d2.state.matches=[]; d2.state.lookupDone=false; return; } d2.state.lookupLoading=true; d2.state.lookupErr=null; d2.state.matches=[]; d2.state.lookupDone=false; try{ const enc='%2B'+raw; const r=await d2.rush(READ).invoke({path:`/Customer?limit=10&phone=${enc}`},{headers:KEY}); const arr=unwrap(r); d2.state.matches=Array.isArray(arr)?arr.filter(x=>x&&x._id):[]; d2.state.lookupDone=true; }catch(e){ d2.log('lookup err',e); d2.state.lookupErr='Erro na busca: '+(e&&e.message||e); } finally{ d2.state.lookupLoading=false; } };\n    d2.on('.lookup','click',lookup);\n    d2.on('.f-phone','keydown',(e,el)=>{ if(e.key==='Enter'){ e.preventDefault(); lookup(); } });\n    d2.on('.match','click',(e,el)=>{ const cid=el.getAttribute('data-cid'); const m=(d2.state.matches||[]).find(x=>x._id===cid); if(m)d2.state.selCustomer=m; });\n    d2.on('.clr-cust','click',()=>{ d2.state.selCustomer=null; });\n\n    d2.on('.create-res','click',()=>{ const f=d2.state.form||{}; const sel=d2.state.selCustomer; if(!sel||!sel._id){ d2.state.createErr='Selecione um cliente válido (busca por telefone).'; return; } const day=f.day; const time=f.time; const size=parseInt(f.size,10)||0; if(!day){ d2.state.createErr='Informe a data.'; return; } const dayShifts=shiftsForDay(day); if(!dayShifts.length){ d2.state.createErr='Sem turno neste dia. Escolha outra data.'; return; } if(!time||!/^\\d{2}:\\d{2}$/.test(time)){ d2.state.createErr='Informe um horário válido (HH:mm).'; return; } if(!shiftHit(day,time)){ d2.state.createErr='Horário fora dos turnos deste dia.'; return; } if(size<1){ d2.state.createErr='Número de pessoas inválido.'; return; } const maxP=d2.state.maxParty||0; if(maxP>0&&size>maxP){ d2.state.createErr='Para grupos acima de '+maxP+', contate oi@tempobyporsche.com'; return; }\n      d2.state.creating=true; d2.state.createErr=null;\n      const allTags=d2.state.tags||[]; const selTags=d2.state.selTags||[]; const tagsOut=allTags.filter(t=>selTags.indexOf(t.name)>=0).map(t=>({name:t.name,label:t.label}));\n      const SEC=d2.state.cfgSection||SECTION;\n      const payload={ reservationDay:`${day}T03:00:00.000Z`, venue:VENUE, origin:{name:'Whatsapp',label:'whatsapp'}, type:'Regular', tags:tagsOut, status:'New', section:SEC, partySize:size, table:null, reservationTime:time, note:'Adicionado pelo Painel TEMPO', customer:{ _id:sel._id, name:sel.name, lastName:sel.lastName, phone:sel.phone, email:sel.email }, logs:{ user:ACTOR, actionType:'Add' } };\n      (async()=>{ try{ await write(`/Reservation/${VENUE}`,'POST',payload); d2.state.creating=false; closeNew(); await loadDay(day); d2.state.day=day; }catch(e){ d2.log('create err',e); d2.state.creating=false; d2.state.createErr='Erro ao criar: '+(e&&e.message||e); } })();\n    });\n  }\n}"}},"venueId":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"venueId"}}}},"tagmeRead":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tagmeRead"}}}}}}}}}},{"_id":"6a44251c2e19654bbcdd8a21","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"EntradaReservas","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n  .wrap{font-family:-apple-system,system-ui,sans-serif;color:#f4f4f5}\n  .hd{display:flex;align-items:center;gap:10px;margin-bottom:12px}\n  .hd .t{font-size:15px;font-weight:700}\n  .hd .d{font-size:12px;color:#8b8b94}\n  .hd .sp{flex:1}\n  .ref{border:0;border-radius:10px;padding:8px 13px;font-size:13px;font-weight:700;background:#1c1c21;color:#f4f4f5;cursor:pointer}\n  .rows{display:flex;flex-direction:column;gap:8px}\n  .res{display:flex;align-items:center;gap:14px;background:#141417;border:1px solid #2a2a31;border-radius:12px;padding:12px 16px}\n  .res .time{font-size:20px;font-weight:800;color:#F4C400;min-width:58px;font-variant-numeric:tabular-nums}\n  .res .who{flex:1;min-width:0}\n  .res .cn{font-weight:700;font-size:15px}\n  .res .meta{color:#8b8b94;font-size:12px;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n  .res .ppl{color:#cfcfcf;font-size:13px;font-weight:700;white-space:nowrap}\n  .chip{font-size:10px;letter-spacing:.06em;font-weight:800;text-transform:uppercase;padding:5px 10px;border-radius:999px;white-space:nowrap}\n  .chip.go{background:#143524;color:#7ee2a8}\n  .chip.warn{background:#332a12;color:#ffce7a}\n  .chip.neutral{background:#1c1c21;color:#8b8b94}\n  .empty{text-align:center;color:#8b8b94;padding:40px 12px}\n  .err{text-align:center;color:#ffce7a;padding:30px 12px}\n  `,\n  render(d2){\n    const st=d2.state; const esc=s=>String(s==null?'':s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));\n    const STMAP={Confirmed:['go','Confirmada'],Seated:['go','Sentada'],New:['neutral','Nova'],Pending:['warn','Pendente'],Placeholder:['warn','Pré-reserva'],Overbook:['neutral','Overbook']};\n    let body;\n    if(st.loading) body=`<div class=\"empty\">Carregando reservas da TAGME…</div>`;\n    else if(st.err) body=`<div class=\"err\">⚠ ${esc(st.err)}</div>`;\n    else {\n      const list=(st.reservas||[]).filter(r=>r&&r.status!=='Canceled').slice().sort((a,b)=>String(a.reservationTime||'').localeCompare(String(b.reservationTime||'')));\n      if(!list.length) body=`<div class=\"empty\">Nenhuma reserva para hoje.</div>`;\n      else body=`<div class=\"rows\">`+list.map(r=>{ const c=r.customer||{}; const nm=[c.name,c.lastName].filter(Boolean).join(' ')||'—'; const sm=STMAP[r.status]||['neutral',r.status||'—']; const mp=[]; if(c.phone)mp.push(esc(c.phone)); if(r.note)mp.push(esc(r.note));\n        return `<div class=\"res\" data-key=\"${esc(r._id||'')}\"><div class=\"time\">${esc(r.reservationTime||'--:--')}</div><div class=\"who\"><div class=\"cn\">${esc(nm)}</div><div class=\"meta\">${mp.join(' · ')||'&nbsp;'}</div></div><div class=\"ppl\">▦ ${r.partySize||0}</div><span class=\"chip ${sm[0]}\">${esc(sm[1])}</span></div>`;\n      }).join('')+`</div>`;\n    }\n    return `<div class=\"wrap\"><div class=\"hd\"><div class=\"t\">Reservas de hoje</div><div class=\"d\">${esc(st.dlabel||'')}</div><div class=\"sp\"></div><button class=\"refresh ref\">↻ Atualizar</button></div>${body}</div>`;\n  },\n  mounted(d2){\n    const KEY={authorization:'sk_live_hhaK2dcQw0jAyYEfAcNpPgUTPqVVGwqC'};\n    const VENUE=d2.param('venueId')||'69fcd30c55153376bd62ca81';\n    const READ=d2.param('tagmeRead')||'tagme-read';\n    const pad=n=>String(n).padStart(2,'0');\n    const unwrap=r=>{ let d=r&&r.data!==undefined?r.data:r; if(d&&d.data!==undefined)d=d.data; return d; };\n    const load=async()=>{\n      const now=new Date(); const y=now.getFullYear(), m=now.getMonth()+1, dd=now.getDate();\n      const dias=['Domingo','Segunda','Terça','Quarta','Quinta','Sexta','Sábado']; const mes=['jan','fev','mar','abr','mai','jun','jul','ago','set','out','nov','dez'];\n      d2.state.dlabel=`${dias[now.getDay()]}, ${dd} ${mes[m-1]}`;\n      d2.state.loading=true; d2.state.err=null;\n      try{ const r=await d2.rush(READ).invoke({path:`/Reservation/List/${VENUE}/${y}/${m}/${dd}?isArray=true`},{headers:KEY}); const arr=unwrap(r); d2.state.reservas=Array.isArray(arr)?arr:[]; }\n      catch(e){ d2.log('reservas err',e); d2.state.err='Erro ao carregar reservas. Tente de novo.'; }\n      finally{ d2.state.loading=false; }\n    };\n    load();\n    d2.on('.refresh','click',load);\n  }\n}"}},"tagmeRead":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tagmeRead"}}}},"venueId":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"venueId"}}}}}}}}}},{"_id":"6a45b0df20611373d1f998de","component":"data2-core-types@Component","system":"69651bdddc863af2ecd97d3d","params":{"extends":"data2-core-primitives@Block","component":"PorscheLanding","package":"adonis","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    @font-face {\n      font-family: 'Pressio';\n      src: url('https://tempobyporsche.com/wp-content/uploads/2026/02/pressio-no44.woff2') format('woff2');\n      font-weight: 400 900; font-display: swap;\n    }\n    @font-face {\n      font-family: 'Raleway';\n      src: url('https://tempobyporsche.com/wp-content/uploads/2026/02/Raleway-VariableFont_wght.ttf') format('truetype');\n      font-weight: 100 900; font-display: swap;\n    }\n    *{box-sizing:border-box;margin:0;padding:0}\n    .page{\n      font-family:'Raleway',-apple-system,Segoe UI,sans-serif;\n      background:#0a0a0a;color:#fff;width:100%;\n      height:100%;max-height:100%;overflow-y:auto;overflow-x:hidden;\n      -webkit-overflow-scrolling:touch;\n      display:flex;flex-direction:column;align-items:center;\n      -webkit-font-smoothing:antialiased;\n    }\n    .hero{\n      position:relative;width:100%;flex:none;\n      min-height:min(72vh,620px);\n      display:flex;flex-direction:column;align-items:center;justify-content:center;\n      text-align:center;padding:56px 24px 64px;overflow:hidden;\n    }\n    .hero-bg{\n      position:absolute;inset:0;z-index:0;\n      background-image:url('https://photos.smugmug.com/photos/i-vs7TkHD/0/M5bFMCgwdF3BQmBmp5r7MpP8t6WF4p8n44JkmWGFD/XL/i-vs7TkHD-XL.jpg');\n      background-size:cover;background-position:center;\n    }\n    .hero-grad{\n      position:absolute;inset:0;z-index:1;\n      background:linear-gradient(180deg,rgba(10,10,10,.55) 0%,rgba(10,10,10,.35) 38%,rgba(10,10,10,.82) 82%,#0a0a0a 100%);\n    }\n    .hero-inner{position:relative;z-index:2;max-width:760px;width:100%;display:flex;flex-direction:column;align-items:center;gap:22px}\n    .logo{width:clamp(78px,16vw,116px);height:auto;filter:drop-shadow(0 4px 24px rgba(0,0,0,.45))}\n    .kicker{\n      font-size:clamp(10px,2.6vw,13px);letter-spacing:.32em;text-transform:uppercase;\n      color:#FFB81C;font-weight:600;\n    }\n    .headline{\n      font-family:'Pressio','Raleway',sans-serif;font-weight:800;\n      font-size:clamp(34px,8.2vw,74px);line-height:.98;letter-spacing:.01em;\n      text-transform:uppercase;color:#FFB81C;\n      text-shadow:0 4px 30px rgba(0,0,0,.5);\n    }\n    .subtitle{\n      font-size:clamp(14px,3.6vw,19px);line-height:1.55;color:rgba(255,255,255,.86);\n      max-width:560px;font-weight:400;\n    }\n    .card-wrap{width:100%;display:flex;justify-content:center;padding:0 20px 72px;margin-top:-36px;position:relative;z-index:3}\n    .card{\n      width:100%;max-width:520px;background:#111111;\n      border:1px solid rgba(255,184,28,.16);border-radius:20px;\n      padding:clamp(24px,6vw,40px);\n      box-shadow:0 30px 80px rgba(0,0,0,.6);\n    }\n    .card-lead{font-size:clamp(14px,3.4vw,16px);line-height:1.5;color:rgba(255,255,255,.72);margin-bottom:26px}\n    .field{margin-bottom:18px;display:flex;flex-direction:column;gap:8px}\n    .label{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:rgba(255,255,255,.55);font-weight:600}\n    .opt{color:rgba(255,255,255,.32);font-weight:400;text-transform:none;letter-spacing:0}\n    .in{\n      width:100%;background:#0a0a0a;border:1px solid rgba(255,255,255,.14);\n      border-radius:12px;padding:15px 16px;color:#fff;font-size:16px;\n      font-family:inherit;outline:none;transition:border-color .18s,box-shadow .18s;\n    }\n    .in::placeholder{color:rgba(255,255,255,.28)}\n    .in:focus{border-color:#FFB81C;box-shadow:0 0 0 3px rgba(255,184,28,.14)}\n    select.in{appearance:none;-webkit-appearance:none;cursor:pointer;\n      background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23FFB81C' d='M6 8L0 0h12z'/%3E%3C/svg%3E\");\n      background-repeat:no-repeat;background-position:right 16px center;padding-right:40px}\n    .row2{display:flex;gap:12px}\n    .row2 .field{flex:1;min-width:0}\n    .err{\n      color:#FFB81C;font-size:13px;font-weight:600;margin:2px 0 14px;\n      background:rgba(255,184,28,.08);border:1px solid rgba(255,184,28,.22);\n      border-radius:10px;padding:11px 13px;line-height:1.4;\n    }\n    .btn{\n      width:100%;margin-top:8px;background:#FFB81C;color:#0a0a0a;\n      border:none;border-radius:12px;padding:17px;font-size:15px;font-weight:800;\n      letter-spacing:.06em;text-transform:uppercase;cursor:pointer;\n      font-family:'Raleway',sans-serif;transition:transform .12s,box-shadow .18s,opacity .18s;\n      box-shadow:0 10px 30px rgba(255,184,28,.22);\n    }\n    .btn:hover{transform:translateY(-1px);box-shadow:0 14px 38px rgba(255,184,28,.32)}\n    .btn:active{transform:translateY(0)}\n    .btn[disabled]{opacity:.55;cursor:default;transform:none;box-shadow:none}\n    .success{text-align:center;padding:8px 4px}\n    .check{\n      width:64px;height:64px;border-radius:999px;margin:0 auto 22px;\n      border:2px solid #FFB81C;display:flex;align-items:center;justify-content:center;\n      color:#FFB81C;font-size:30px;\n    }\n    .s-title{font-family:'Pressio','Raleway',sans-serif;font-weight:800;font-size:clamp(22px,5.6vw,30px);color:#fff;margin-bottom:14px;line-height:1.15}\n    .s-body{font-size:clamp(14px,3.6vw,16px);color:rgba(255,255,255,.8);line-height:1.6;margin-bottom:22px}\n    .s-meta{border-top:1px solid rgba(255,255,255,.1);padding-top:20px;display:flex;flex-direction:column;gap:8px}\n    .s-meta .m{font-size:14px;color:rgba(255,255,255,.72)}\n    .s-meta .m b{color:#FFB81C;font-weight:600}\n    .foot{padding:22px 24px 40px;text-align:center;color:rgba(255,255,255,.34);font-size:12px;letter-spacing:.04em}\n    @media(max-width:420px){ .row2{flex-direction:column;gap:0} }\n  `,\n  render(d2){\n    const s = d2.state;\n    if (s.view === 'success'){\n      return `<div class=\"page\">\n        <div class=\"card-wrap\" style=\"margin-top:48px;padding-top:24px\">\n          <div class=\"card\">\n            <div class=\"success\">\n              <div class=\"check\">&#10003;</div>\n              <div class=\"s-title\">Recebemos seu contato.<br>Bem-vindo &agrave; Tempo.</div>\n              <div class=\"s-body\">Em breve falamos com voc&ecirc;.</div>\n              <div class=\"s-meta\">\n                <div class=\"m\"><b>Rua Maria Carolina, 624</b> &middot; Pinheiros, S&atilde;o Paulo</div>\n                <div class=\"m\">Ter&ccedil;a a Domingo &middot; 12h &agrave;s 22h</div>\n              </div>\n            </div>\n          </div>\n        </div>\n        <div class=\"foot\">TEMPO BY PORSCHE &middot; S&Atilde;O PAULO</div>\n      </div>`;\n    }\n    const v = s.values || {};\n    const esc = (x) => (x == null ? '' : String(x)).replace(/\"/g,'&quot;').replace(/</g,'&lt;');\n    const errBox = s.error ? `<div class=\"err\">${s.error}</div>` : '';\n    const opts = [\n      ['','Selecione (opcional)'],\n      ['Almoço 12h–15h','Almoço 12h–15h'],\n      ['Tarde 15h–18h','Tarde 15h–18h'],\n      ['Jantar 19h–22h','Jantar 19h–22h'],\n    ].map(([val,lab]) => `<option value=\"${esc(val)}\" ${(v.horario||'')===val?'selected':''}>${lab}</option>`).join('');\n    return `<div class=\"page\">\n      <div class=\"hero\">\n        <div class=\"hero-bg\"></div>\n        <div class=\"hero-grad\"></div>\n        <div class=\"hero-inner\">\n          <img class=\"logo\" alt=\"Tempo by Porsche\" src=\"https://tempobyporsche.com/wp-content/uploads/2026/02/logo_tempo_by_porsche_white_V.svg\"/>\n          <div class=\"kicker\">TEMPO BY PORSCHE &middot; S&Atilde;O PAULO</div>\n          <div class=\"headline\">PARA QUEM VIVE<br>AL&Eacute;M DA VELOCIDADE</div>\n          <div class=\"subtitle\">Um convite para conhecer a Tempo &mdash; caf&eacute;, restaurante e lounge onde a ess&ecirc;ncia da Porsche encontra a arte, a gastronomia e a m&uacute;sica. Este lugar &eacute; seu.</div>\n          <div class=\"subtitle\"><b>Apresente a chave do seu Porsche e ganhe 15% de desconto na sua primeira visita.</b></div>\n        </div>\n      </div>\n      <div class=\"card-wrap\">\n        <div class=\"card\">\n          <div class=\"card-lead\">Deixe seu contato e, se quiser, escolha um dia para vir. A gente te espera.</div>\n          ${errBox}\n          <div class=\"field\">\n            <div class=\"label\">Nome</div>\n            <input class=\"in\" data-f=\"nome\" value=\"${esc(v.nome)}\" placeholder=\"Seu nome\" autocomplete=\"name\"/>\n          </div>\n          <div class=\"field\">\n            <div class=\"label\">E-mail <span class=\"opt\">(opcional)</span></div>\n            <input class=\"in\" data-f=\"email\" type=\"email\" value=\"${esc(v.email)}\" placeholder=\"voce@email.com\" autocomplete=\"email\"/>\n          </div>\n          <div class=\"field\">\n            <div class=\"label\">Telefone / WhatsApp <span class=\"opt\">(opcional)</span></div>\n            <input class=\"in\" data-f=\"telefone\" type=\"tel\" value=\"${esc(v.telefone)}\" placeholder=\"(11) 90000-0000\" autocomplete=\"tel\"/>\n          </div>\n          <div class=\"row2\">\n            <div class=\"field\">\n              <div class=\"label\">Data da visita <span class=\"opt\">(opcional)</span></div>\n              <input class=\"in\" data-f=\"data_visita\" type=\"date\" value=\"${esc(v.data_visita)}\"/>\n            </div>\n            <div class=\"field\">\n              <div class=\"label\">Hor&aacute;rio <span class=\"opt\">(opcional)</span></div>\n              <select class=\"in\" data-f=\"horario\">${opts}</select>\n            </div>\n          </div>\n          <button class=\"btn\" data-act=\"submit\" ${s.submitting?'disabled':''}>${s.submitting?'ENVIANDO&hellip;':'QUERO CONHECER A TEMPO'}</button>\n        </div>\n      </div>\n      <div class=\"foot\">Rua Maria Carolina, 624 &middot; Pinheiros, S&atilde;o Paulo &middot; Ter&ccedil;a a Domingo, 12h &agrave;s 22h</div>\n    </div>`;\n  },\n  mounted(d2){\n    if (!d2.state.values) d2.state.values = {};\n    const setF = (el) => {\n      const k = el.getAttribute('data-f');\n      d2.state.values = { ...(d2.state.values||{}), [k]: el.value };\n    };\n    d2.on('.in', 'input', (e, el) => setF(el));\n    d2.on('.in', 'change', (e, el) => setF(el));\n    d2.on('[data-act=\"submit\"]', 'click', async () => {\n      if (d2.state.submitting) return;\n      const v = d2.state.values || {};\n      const nome = (v.nome||'').trim();\n      const email = (v.email||'').trim();\n      const telefone = (v.telefone||'').trim();\n      if (!nome){ d2.state.error = 'Por favor, informe seu nome para continuarmos.'; return; }\n      if (!email && !telefone){ d2.state.error = 'Deixe um e-mail ou telefone para que possamos falar com você.'; return; }\n      if (email){\n        const ok = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);\n        if (!ok){ d2.state.error = 'O e-mail informado parece inválido. Confira, por favor.'; return; }\n      }\n      d2.state.error = null;\n      d2.state.submitting = true;\n      try {\n        const ref = d2.param('rushref') || 'lead-salvar';\n        const res = await d2.rush(ref).invoke({ body: {\n          nome, email, telefone,\n          data_visita: (v.data_visita||''),\n          horario_visita: (v.horario||''),\n        }});\n        const payload = (res && res.data) ? res.data : res;\n        if (payload && payload.ok){\n          d2.state.view = 'success';\n        } else {\n          d2.state.error = 'Não foi possível enviar agora. Tente novamente em instantes.';\n        }\n      } catch (err){\n        d2.state.error = 'Falha de conexão. Verifique sua internet e tente novamente.';\n      } finally {\n        d2.state.submitting = false;\n      }\n    });\n  },\n}"}},"rushref":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rushref"}}}}}}}}}},{"_id":"5ed9bed7b9e0891ce913e884","component":"data2-core-types@Component","params":{"package":"data2-core","component":"DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}},{"_id":"5f472ae463c680de4ff296e9","component":"data2-core-types@Component","params":{"package":"data2-core","component":"Data2TableDataSource","extends":"data2-core@DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}}]}},{"reference":"ExternalComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"_id":"5f060d9b1ca96def42f3c40a","displayName":"Builder AuthStrategy","component":"data2-core@AuthenticationStrategy","system":"5e3b796d6228227ca637d0f4","params":{"credentials":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"verifier":{"component":"data2-core-types@DataSetReference","params":{"reference":"UsersDataSet"}},"sessionShared":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"password":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},"email":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},"resetPassword":{"resetEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"nR6Q9d7qdaPtZhJ28Q8Dy"},"component":"data2-core-types@ArtboardReference"}},"resetSuccessEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"yPCJBTKo8q1Mw0B_3Kpwl"},"component":"data2-core-types@ArtboardReference"}}},"session":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"name"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"sessionMetadata":{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},{"params":{"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"active"}},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.status"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is active user"}]},"component":"data2-core-logical-operators@And","displayName":"is active and has _id"}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $user"},{"params":{"action":{"params":{"pattern":{"component":"data2-core-primitives@String","params":{"content":"@data2.app"}},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.email"}}}}},"component":"data2-core-functions@Includes","displayName":"isData2User"},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}},"component":"data2-core-flow@Step"},{"params":{"action":{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.d2_app"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"management"}}]},"component":"data2-core-functions@Includes","displayName":"isData2App Exception"},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}},"component":"data2-core-flow@Step"},{"params":{"resultName":{"component":"data2-core-primitives@String","params":{"content":"has_access"}},"action":{"params":{"compare":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}}},{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}}}]},"component":"data2-core-logical-operators@Or"},"else":{"params":{"actions":[{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $metadata.system"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":"filter","args":[{"_id":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records.length"}}}}},"component":"data2-core-logical-operators@Not","displayName":"systems not found"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check system found"},{"params":{"actions":[{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"organization":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"cursor.current.organization._id"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"}]},"component":"data2-core-flow@Parallel"}]},"component":"data2-core-flow@Series","displayName":"common setup"},{"params":{"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"},"else":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"compare":{"params":{"components":{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"mapper":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"system"}}],"body":{"params":{"expression":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.visibility"}}}},"defaultCase":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"cases":[{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"public"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"billing-owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}},{"component":"data2-core-primitives@String","params":{"content":"member"}}]},"component":"data2-core-functions@Includes","displayName":"has role with access"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"collaborator"}}},"component":"data2-core-comparison-operators@Equal","displayName":"is collaborator"}]},"component":"data2-core-logical-operators@And","displayName":"is org member and collaborator"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is collaborator"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is collaborator and has system access"}]},"component":"data2-core-logical-operators@Or"}}},{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"private"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}}]},"component":"data2-core-functions@Includes","displayName":"is owner/admin"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is owner/admin"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is member and has system access"}]},"component":"data2-core-logical-operators@Or","displayName":"is owner/admin or has system access"}}}]},"component":"data2-core-flow@Switch"}}}},"component":"data2-core-functions@ArrayMap"}},"component":"data2-core-logical-operators@And","displayName":"has org member for all systems in request"}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"}},"component":"data2-core-flow@If"}},"component":"data2-core-flow@Step"},{"params":{"then":{"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"else":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"},"compare":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"has_access"}}}}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"sessionExpiresIn":{"component":"data2-core-primitives@Number","params":{"content":604800}},"sessionRenewal":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"identityProviders":[{"provider":{"component":"data2-core-primitives@String","params":{"content":"GOOGLE"}},"clientId":{"component":"data2-core-primitives@String","params":{"content":"55470861603-22pvfc1t49lp8cjnbfk71s5ct9hp1q1v.apps.googleusercontent.com"}}}]},"reference":"Data2BuilderAuthentication","updatedAt":"2026-08-06T19:31:23.557Z"},{"_id":"5f060ee51ca96def42f3fbd1","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"UsersTableDataSource"}},"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}}},"reference":"UsersDataSet","updatedAt":"2026-03-04T21:16:40.291Z"},{"_id":"68f938cf5fb002e33752a43d","displayName":"InternalApplicationsAuthenticationStrategy","component":"data2-core@AuthenticationStrategy","system":"5e3b796d6228227ca637d0f4","params":{"resetPassword":{"resetEmail":{"artboard":{"params":{"preventEvaluation":true},"component":"data2-core-types@ArtboardReference"}},"resetSuccessEmail":{"artboard":{"params":{"preventEvaluation":true},"component":"data2-core-types@ArtboardReference"}}},"verifier":{"disabled":false,"component":"data2-core-types@DataSetReference","params":{"reference":"InternalApplicationsVerifierDataSet"}},"password":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"secret"}},"credentials":[{"component":"data2-core-types@FieldReference","params":{"key":"application"}},{"component":"data2-core-types@FieldReference","params":{"key":"secret"}},{"component":"data2-core-types@FieldReference","params":{"key":"status"}}],"session":[{"component":"data2-core-types@FieldReference","params":{"key":"application"}},{"component":"data2-core-types@FieldReference","params":{"key":"secret"}},{"component":"data2-core-types@FieldReference","params":{"key":"status"}}]},"reference":"InternalApplicationsAuthenticationStrategy","updatedAt":"2025-10-22T20:08:54.442Z","createdAt":"2025-10-22T20:04:31.198Z"},{"component":"data2-core@DataSet","reference":"SessionsDataSet","params":{"requiresConfirmation":false,"pk":"key","datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"data2sessionsdatasource"}}}},{"reference":"UsersTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@ServerSessionsDataSource","reference":"data2sessionsdatasource","params":{}},{"_id":"5f1600b70528b92601890f75","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ServiceComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ServiceComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:20.208Z","createdAt":"2020-07-20T20:38:15.436Z"},{"_id":"5f1602190528b92601890f7d","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":40000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentInstancesTableDataSource"}},"sort":{"_id":1},"pk":"_id","autoEdit":true,"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:07.089Z","createdAt":"2020-07-20T20:44:09.350Z"},{"_id":"5f16017f0528b92601890f7a","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"clientApplicationDomain"}}},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"FileComponentInstancesDataSet","updatedAt":"2023-08-03T16:08:18.193Z","createdAt":"2020-07-20T20:41:35.797Z"},{"_id":"5f1601990528b92601890f7b","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ApplicationsTableDataSource"}},"pk":"_id","autoEdit":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"params":{"column":"_id"},"component":"data2-core-types@DataSetColumnReference"}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"ApplicationsDataSet","updatedAt":"2022-12-13T21:51:13.995Z","createdAt":"2020-07-20T20:42:01.657Z"},{"_id":"5f16172a0528b92601890f85","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":10000}}},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"DataComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"DataComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:12.831Z","createdAt":"2020-07-20T22:14:02.097Z"},{"_id":"60ddc1bbda3861ca65407c5a","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"clientApplicationDomain"}}},"pagination":{"size":1},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"}},"reference":"OneFileComponentInstancesDataSet","updatedAt":"2022-02-09T19:44:38.036Z","createdAt":"2020-07-20T20:41:35.797Z"},{"_id":"63ee3d38b8c9838c62fb05fb","displayName":"DriveFileComponentInstancesDataSet","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core@Drive"}}},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"DriveFileComponentInstancesDataSet","updatedAt":"2025-12-04T21:58:32.367Z","createdAt":"2023-02-16T14:27:07.797Z"},{"reference":"ServiceComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"69ef872682956177fcb2d6fb","component":"data2-rush@HTTPListener","reference":"list-members","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"69ff2cd0a958e5a344fc9061","component":"data2-rush@HTTPListener","reference":"proxy-cliente","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a43f53ab19f54f0960639c6","component":"data2-rush@HTTPListener","reference":"tagme-read","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a33df2a926d2ad82264a2a9","component":"data2-rush@HTTPListener","reference":"proxy-products","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a99cf2e784e6873cdf17af8","component":"data2-rush@HTTPListener","reference":"pessoas-listar","system":"69651bdddc863af2ecd97d3d","params":{},"deleteMetadata":{}},{"_id":"69ff2cd2c2d249fe94eb0099","component":"data2-rush@HTTPListener","reference":"proxy-vendas","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6973990ebca9cdece9c61862","component":"data2-rush@HTTPListener","reference":"signup","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a330b6cec12023d1caff264","component":"data2-rush@HTTPListener","reference":"entrada-buscar","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a330c8dfd2b35b0fa7b1845","component":"data2-rush@HTTPListener","reference":"entrada-cadastrar-um","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a330bb0926d2ad822637c97","component":"data2-rush@HTTPListener","reference":"entrada-checkin","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a330b37293ce144a47de264","component":"data2-rush@HTTPListener","reference":"entrada-lista","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a43fc07c931392b71df59ec","component":"data2-rush@HTTPListener","reference":"tagme-write","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a33f800b4151ec9181b6cbd","component":"data2-core-ai@Assistant","reference":"agente-tempo","system":"69651bdddc863af2ecd97d3d","params":{"model":"cerebras","_context":"Você é o PLANNER do painel interno TEMPO by Porsche. Tem acesso a: RESERVAS, OCUPAÇÃO e WALK-INS/ENTRADA do restaurante (TAGME), clientes (Cloudfy PDV), membros/sócios (adonis), vendas por cliente, lista de entrada/check-in legada, catálogo de produtos (WooCommerce) e observações sobre clientes. Decide QUAIS fontes consultar (em paralelo). IMPORTANTE: o prompt inclui 'Conversa recente' e 'Foco atual' — USE-OS para resolver referências como 'ele','dela','esse cliente','o mesmo','dele','a pessoa': nesses casos preencha termo (e/ou alvo) com o NOME do Foco atual. Resolva datas relativas para o campo 'data' no formato YYYY-MM-DD usando a data de hoje informada no prompt (timezone America/Sao_Paulo): 'hoje'=hoje, 'amanhã'=hoje+1, 'ontem'=hoje-1, dias da semana ('sábado','sexta') = a PRÓXIMA ocorrência desse dia (ou hoje se for o próprio dia). Se nenhuma data for citada para reservas/ocupação/walk-ins/entrada/resumo, use a data de hoje. Responda sempre em português.","behaviour":"Responda SOMENTE com JSON estrito, com EXATAMENTE estas chaves:\n{\n  \"fontes\": [],\n  \"termo\": \"\",\n  \"alvo\": \"\",\n  \"data\": \"\",\n  \"turno\": \"\",\n  \"entrada_q\": \"\",\n  \"member_code\": \"\",\n  \"nota\": \"\",\n  \"checkin\": \"\",\n  \"criar_membro\": false,\n  \"membro_nome\": \"\",\n  \"membro_email\": \"\",\n  \"membro_tipo\": \"\",\n  \"criar_entrada\": false,\n  \"entrada_nome\": \"\",\n  \"entrada_cpf\": \"\",\n  \"escrita_tipo\": \"\",\n  \"r_nome\": \"\",\n  \"r_telefone\": \"\",\n  \"r_hora\": \"\",\n  \"r_pax\": \"\",\n  \"cli_termo\": \"\",\n  \"cli_telefone\": \"\",\n  \"navegar_tab\": \"\",\n  \"navegar_motivo\": \"\",\n  \"acao_escrita\": \"\",\n  \"resposta\": \"\"\n}\n\"fontes\" é uma lista (pode ter várias) de: \"reservas\",\"ocupacao\",\"disponibilidade\",\"walkins\",\"resumo_dia\",\"entrada_hoje\",\"cliente\",\"vendas\",\"notas\",\"clientes_sem_telefone\",\"membro\",\"membros\",\"validar_membro\",\"entrada\",\"entrada_buscar\",\"produtos\",\"capacidades\".\n\nLEITURA (preencha fontes, NÃO preencha campos de escrita):\n- Reservas de um dia (R1) / período (RP2) → \"reservas\" (data = dia).\n- Ocupação / lotação / por turno (R2) → \"ocupacao\" (data; turno opcional 'almoço'/'jantar').\n- Tem mesa / disponibilidade / cabe X (R4) → \"disponibilidade\" (data; turno se citado).\n- Buscar a reserva de uma pessoa (R3) → \"reservas\" + termo = nome/telefone.\n- Walk-ins (R9) → \"walkins\" (data). Resumo do dia (RP1) → \"resumo_dia\" (data).\n- QUEM ENTROU / QUEM JÁ CHEGOU / QUEM ESTÁ NO RESTAURANTE / ENTRADA DE HOJE / OCUPAÇÃO ATUAL (pessoas presentes) → \"entrada_hoje\" (data; default hoje). Isto vem da TAGME (reservas SENTADAS + walk-ins), NÃO da lista local. SEMPRE prefira \"entrada_hoje\" a \"entrada\" para 'quem entrou/quem chegou/entrada de hoje'.\n- Consultar/ver cliente (C1/C2) → \"cliente\" (termo). 'tudo sobre o cliente X' → [\"cliente\",\"vendas\",\"notas\"].\n- Histórico compras (C3) → \"vendas\". Observações salvas (C6) → \"notas\" (alvo/termo). Clientes sem telefone (C8) → \"clientes_sem_telefone\".\n- Membros: listar/quantos (M1) → \"membros\"; buscar por nome/email → \"membro\"; por código → \"membro\"+member_code; validar (M3) → \"validar_membro\"+member_code/termo.\n- Buscar uma pessoa NA LISTA DE ENTRADA legada por nome (E2) → \"entrada_buscar\"+entrada_q. (NÃO use para 'quem entrou hoje' — isso é entrada_hoje.)\n- Reservas p/ recepção (E5) → \"reservas\".\n- Catálogo/produtos (P1) → \"produtos\".\n- O QUE VOCÊ FAZ / O QUE SABE FAZER / QUAIS SUAS FUNÇÕES / COMO USAR / AJUDA / MENU → \"capacidades\" (deixe todo o resto vazio).\n\nAÇÕES DE ESCRITA SIMPLES (executáveis no chat com confirmação) — preencha \"escrita_tipo\" e os campos, deixe fontes=[]:\n- ALGUÉM CHEGOU / 'o fulano chegou' / 'chegou a Ana' / 'cheguei com o cliente X' → escrita_tipo=\"pessoa_chegou\". r_nome (ou termo) = nome da pessoa; r_pax = nº de pessoas se citado; data = hoje (ou o dia citado). O painel busca em reservas+membros+clientes e oferece sentar/registrar na hora.\n- Registrar WALK-IN explícito ('registra walk-in pro X', 'walk-in do João 2 pessoas') → escrita_tipo=\"walkin_criar\". r_nome, r_pax, r_telefone (dígitos, se houver).\n- Criar reserva → escrita_tipo=\"reserva_criar\". Extraia: r_nome, r_telefone (só dígitos, com DDI/DDD), data (YYYY-MM-DD), r_hora (HH:mm 24h), r_pax. Grupo MAIOR que 8 → NÃO use reserva_criar: navegar_tab=\"reservas\" (F3). Pré-order/voucher/menu fechado → idem F3.\n- Confirmar reserva → escrita_tipo=\"reserva_confirmar\". termo = nome/telefone; data = dia (default hoje).\n- Sentar reserva (cliente chegou e TEM reserva) → escrita_tipo=\"reserva_sentar\". termo + data. (Se não souber se tem reserva, use pessoa_chegou.)\n- Cancelar reserva → escrita_tipo=\"reserva_cancelar\". termo + data.\n- Salvar observação/lembrete sobre cliente → escrita_tipo=\"nota_cliente\". nota = texto; alvo = nome.\n- Editar/alterar TELEFONE do cliente → escrita_tipo=\"editar_telefone\". cli_termo; cli_telefone (dígitos).\n- Tornar alguém membro/sócio → escrita_tipo=\"tornar_membro\". membro_nome, membro_email, membro_tipo ('MEMBER'/'FOUNDER').\n- Check-in por comanda → escrita_tipo=\"checkin\". checkin = número da comanda.\n- Cadastrar pessoa nova na lista de entrada legada → criar_entrada=true + entrada_nome (+entrada_cpf). [mantém fluxo existente]\n\nFLUXOS COMPLEXOS / SENSÍVEIS (F3) — NÃO execute no chat; preencha \"navegar_tab\" + \"navegar_motivo\" curto, deixe escrita_tipo=\"\" e fontes=[]:\n- Reserva de GRUPO grande (>8), com pré-order, menu fechado, voucher → navegar_tab=\"reservas\". termo = nome se houver.\n- Edição cadastral AMPLA do cliente (endereço, documento, CPF/CNPJ, dados de PJ, nome) — qualquer coisa além do telefone → navegar_tab=\"clientes\". termo = cliente.\n- Pagamento / pré-venda / cobrança / mensalidade → navegar_tab=\"membros\".\n- Export CSV / importação em massa / cadastrar muitos na entrada → navegar_tab=\"entrada\".\n- Relatório completo / dashboard detalhado → navegar_tab que faça sentido (\"reservas\" p/ ocupação detalhada).\nNa \"resposta\", explique em 1 frase que vai abrir a tela certa pra concluir.\n\nDESAMBIGUAÇÃO: se o pedido de escrita não tiver alvo claro (vários com mesmo nome, telefone faltando), ainda assim preencha escrita_tipo e os campos que tiver — o painel vai pedir pra escolher/confirmar. NUNCA invente telefone.\n\nRegras: combine fontes de LEITURA quando fizer sentido. Para ESCRITA, só UM escrita_tipo por vez. Preencha SÓ os campos relevantes; resto vazio (\"\") ou false. NÃO use o campo legado acao_escrita (deixe \"\"). \"resposta\" SEMPRE presente, curta, pt-BR. Nada de texto fora do JSON.\n- Saudação ou dúvida muito genérica → tudo vazio e escreva em \"resposta\" (mas 'o que você faz' usa fontes=[\"capacidades\"]).","creativity":10,"json":true}},{"_id":"6a34095c23b312eaa4d396b5","component":"data2-rush@HTTPListener","reference":"nota-listar","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a34095f83c2399a357c1e18","component":"data2-rush@HTTPListener","reference":"nota-salvar","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a441e3ffbbc6ccb061600aa","component":"data2-rush@HTTPListener","reference":"proxy-cliente-salvar","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a4430652e19654bbcdda8da","component":"data2-rush@HTTPListener","reference":"member-update-number","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a7e0887fb860f776ca50872","component":"data2-rush@HTTPListener","reference":"member-expire","system":"69651bdddc863af2ecd97d3d","params":{},"deleteMetadata":{}},{"_id":"69ef8723dc9e1e14b596a85a","component":"data2-rush@HTTPListener","reference":"get-member","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a3401e8c03e59866674afb2","component":"data2-rush@HTTPListener","reference":"agente-say","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a3401e5fd2b35b0fa7ca260","component":"data2-rush@HTTPListener","reference":"agente-plan","system":"69651bdddc863af2ecd97d3d","params":{}},{"_id":"6a99ba261010d0b021430962","component":"data2-rush@HTTPListener","reference":"membros-pendentes","system":"69651bdddc863af2ecd97d3d","params":{},"deleteMetadata":{}},{"_id":"6a99ba3751b790fa1731bcf1","component":"data2-rush@HTTPListener","reference":"membro-atribuir-numero","system":"69651bdddc863af2ecd97d3d","params":{},"deleteMetadata":{}}]}},{"reference":"ComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a33e24ac03e598666744d7b","component":"data2-core-primitives@Artboard","system":"69651bdddc863af2ecd97d3d","displayName":"PainelApp","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"PainelApp"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"iNNNzyri5LHlMFwLrkV8d"},{"_id":"3c8bb13c156800021ba976de","parent":"6a33e24ac03e598666744d7b","component":"adonis@PainelApp","system":"69651bdddc863af2ecd97d3d","displayName":"App","params":{"config":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"produto-configDataSet"}},"accent":"#F4C400","super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}}}},"reference":"_FJjiy3ZHq3L_8ajtarxw"}]}},{"_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":"6a36bdec68b2bdf974100021","displayName":"New Application (8)","reference":"gP03stTRYa8mmbmNtN6qb","params":{"domain":{"component":"data2-core-primitives@String","params":{"content":"app"}},"entryPoint":{"disabled":false,"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Artboard","reference":"iNNNzyri5LHlMFwLrkV8d"}}},"system":"69651bdddc863af2ecd97d3d","component":"data2-core-primitives@Application"}]}},{"reference":"DataComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a34c1ab60df893593c1af7e","component":"data2-core@Store","system":"69651bdddc863af2ecd97d3d","params":{"initialData":{"checked":{}}},"reference":"listaCompras"},{"_id":"6a330e1a926d2ad822638430","component":"data2-core@DataSet","system":"69651bdddc863af2ecd97d3d","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"produto-config"}}},"reference":"produto-configDataSet"},{"_id":"6a330e1a2464545b1a616a99","component":"data2-core@Data2TableDataSource","system":"69651bdddc863af2ecd97d3d","params":{"table":"produto-config","schema":[{"component":"data2-core-types@Field","params":{"key":"product_id","title":"Product ID","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"tipo_cliente","title":"Tipo Cliente","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"consumo","title":"Consumo","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"desconto","title":"Desconto","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"synced","title":"Synced","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"updatedAt","title":"Updated At","component":"data2-core-primitives@Date"}}]},"reference":"produto-config"}]}},{"reference":"BundlesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}}],"processesParams":{}}}}