{"context":{"domain":"katia-party"},"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":"6abed5371a6b03943b9618d7","name":"Party","domain":"katia-party","visibility":"public","updatedAt":"2026-10-01T21:48:39.250Z","createdAt":"2026-10-01T21:48:39.250Z"}]}},{"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":"6abef9f4e9fa96de8a9fbe05","component":"data2-core-types@Component","system":"6abed5371a6b03943b9618d7","params":{"extends":"data2-core-primitives@Block","component":"kp-login","package":"katia-party","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"// kp-login — tela de login + esqueci senha + redefinir senha (?reset=TOKEN)\n// params: auth (service → @partyAuth), requestReset (rush → @request-reset), doReset (rush → @do-reset)\nfunction esc(s){return String(s??'').replace(/[&<>\"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;'}[c]))}\nfunction fonts(){try{if(document.getElementById('kp-fonts'))return;const l=document.createElement('link');l.id='kp-fonts';l.rel='stylesheet';l.href='https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&family=Nunito:wght@400;600;700;800&display=swap';document.head.appendChild(l)}catch(e){}}\nfunction pwa(){try{if(window.__kpPwa)return;window.__kpPwa=1\n  const svg=`<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><defs><linearGradient id=\"g\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\"><stop offset=\"0\" stop-color=\"#FBD3DB\"/><stop offset=\".6\" stop-color=\"#FDE3D3\"/><stop offset=\"1\" stop-color=\"#FFF2C9\"/></linearGradient></defs><rect width=\"512\" height=\"512\" fill=\"url(#g)\"/><circle cx=\"420\" cy=\"92\" r=\"40\" fill=\"#fff\" opacity=\".55\"/><circle cx=\"86\" cy=\"430\" r=\"26\" fill=\"#F9CDD4\" opacity=\".8\"/><g transform=\"translate(112 140) scale(2.4)\"><path d=\"M22 50 L30 8 L56 32 Z\" fill=\"#E59A55\"/><path d=\"M29 41 L33 18 L48 33 Z\" fill=\"#F8D7B5\"/><path d=\"M98 50 L90 8 L64 32 Z\" fill=\"#E59A55\"/><path d=\"M91 41 L87 18 L72 33 Z\" fill=\"#F8D7B5\"/><ellipse cx=\"60\" cy=\"62\" rx=\"44\" ry=\"40\" fill=\"#E59A55\"/><path d=\"M24 70 Q30 99 60 103 Q90 99 96 70 Q84 58 72 66 Q60 74 48 66 Q36 58 24 70Z\" fill=\"#FFF4E8\"/><ellipse cx=\"44\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><ellipse cx=\"76\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><ellipse cx=\"44\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><ellipse cx=\"76\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><circle cx=\"45.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/><circle cx=\"77.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/><path d=\"M54 72 Q60 68 66 72 Q63 78 60 78 Q57 78 54 72Z\" fill=\"#3B2A2E\"/><path d=\"M52 83 Q56 88 60 83 Q64 88 68 83\" stroke=\"#3B2A2E\" stroke-width=\"2.4\" fill=\"none\" stroke-linecap=\"round\"/><ellipse cx=\"32\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/><ellipse cx=\"88\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/><path d=\"M36 10 L60 -22 L84 10 Z\" fill=\"#E79AAB\"/><circle cx=\"60\" cy=\"-24\" r=\"6\" fill=\"#fff\"/><circle cx=\"50\" cy=\"0\" r=\"3\" fill=\"#fff\"/><circle cx=\"66\" cy=\"-8\" r=\"3\" fill=\"#FFF2C9\"/></g></svg>`\n  const mk=(size)=>new Promise(res=>{const img=new Image();img.onload=()=>{const c=document.createElement('canvas');c.width=c.height=size;c.getContext('2d').drawImage(img,0,0,size,size);res(c.toDataURL('image/png'))};img.onerror=()=>res('');img.src='data:image/svg+xml;charset=utf-8,'+encodeURIComponent(svg)})\n  Promise.all([mk(192),mk(512),mk(180)]).then(([i192,i512,i180])=>{\n    const o=location.origin+'/'\n    const m={name:'Katia faz 33 · Backoffice',short_name:'Katia 33',description:'Orçamento, convidados e o Milo 🐕',id:o,start_url:o,scope:o,display:'standalone',orientation:'portrait',background_color:'#FFF7F5',theme_color:'#FBD3DB',lang:'pt-BR',\n      icons:[{src:i192,sizes:'192x192',type:'image/png',purpose:'any'},{src:i512,sizes:'512x512',type:'image/png',purpose:'any'},{src:i512,sizes:'512x512',type:'image/png',purpose:'maskable'}]}\n    const put=(tag,match,attrs)=>{let el=[...document.head.querySelectorAll(tag)].find(match);if(!el){el=document.createElement(tag);document.head.appendChild(el)}for(const k in attrs)el.setAttribute(k,attrs[k]);return el}\n    put('link',e=>e.rel==='manifest',{rel:'manifest',href:'data:application/manifest+json;charset=utf-8,'+encodeURIComponent(JSON.stringify(m))})\n    put('link',e=>e.rel==='apple-touch-icon',{rel:'apple-touch-icon',href:i180})\n    put('link',e=>e.rel==='icon',{rel:'icon',type:'image/png',href:i192})\n    put('meta',e=>e.name==='theme-color',{name:'theme-color',content:'#FBD3DB'})\n    put('meta',e=>e.name==='apple-mobile-web-app-title',{name:'apple-mobile-web-app-title',content:'Katia 33'})\n    put('meta',e=>e.name==='apple-mobile-web-app-status-bar-style',{name:'apple-mobile-web-app-status-bar-style',content:'default'})\n    put('meta',e=>e.name==='description',{name:'description',content:m.description})\n  })}catch(e){}}\nfunction shiba(cls){return `<svg class=\"${cls||''}\" viewBox=\"0 0 120 110\" aria-hidden=\"true\"><path d=\"M22 50 L30 8 L56 32 Z\" fill=\"#E59A55\"/><path d=\"M29 41 L33 18 L48 33 Z\" fill=\"#F8D7B5\"/><path d=\"M98 50 L90 8 L64 32 Z\" fill=\"#E59A55\"/><path d=\"M91 41 L87 18 L72 33 Z\" fill=\"#F8D7B5\"/><ellipse cx=\"60\" cy=\"62\" rx=\"44\" ry=\"40\" fill=\"#E59A55\"/><path d=\"M24 70 Q30 99 60 103 Q90 99 96 70 Q84 58 72 66 Q60 74 48 66 Q36 58 24 70Z\" fill=\"#FFF4E8\"/><ellipse cx=\"44\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><ellipse cx=\"76\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><g class=\"eyes\"><ellipse cx=\"44\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><ellipse cx=\"76\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><circle cx=\"45.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/><circle cx=\"77.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/></g><path d=\"M54 72 Q60 68 66 72 Q63 78 60 78 Q57 78 54 72Z\" fill=\"#3B2A2E\"/><path d=\"M52 83 Q56 88 60 83 Q64 88 68 83\" stroke=\"#3B2A2E\" stroke-width=\"2.4\" fill=\"none\" stroke-linecap=\"round\"/><ellipse cx=\"32\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/><ellipse cx=\"88\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/></svg>`}\nfunction isErr(r){return r&&typeof r==='object'&&(r.isData2Error||r.error||r.name==='Data2Error'||r.status>=400)}\n\nexport default {\n  css:`\n:host{--bg:#FFF7F5;--card:#FFFFFF;--blush-50:#FFF1F2;--blush-100:#FDE4E7;--blush-200:#F9CDD4;--blush-300:#F2AEBA;--rose:#D9879A;--rose-deep:#B8647A;--ink:#4A3439;--muted:#94797E;--line:#F3DDE0;--peach:#FDE3D3;--sage:#DCEBDD;--sage-ink:#4F7A57;--shadow:0 6px 24px rgba(184,100,122,.12)}\n*{box-sizing:border-box}\n.page{position:relative;height:100%;min-height:100%;overflow:auto;display:flex;align-items:center;justify-content:center;padding:24px 16px;font-family:'Nunito',system-ui,sans-serif;color:var(--ink);\n  background:radial-gradient(1200px 600px at 10% -10%,#FDE4E7 0,transparent 60%),radial-gradient(900px 500px at 110% 110%,#FDE3D3 0,transparent 55%),var(--bg)}\n.balloon{position:absolute;width:56px;height:68px;border-radius:50% 50% 48% 48%;opacity:.55;animation:float 9s ease-in-out infinite}\n.balloon:after{content:'';position:absolute;left:50%;top:100%;width:1px;height:60px;background:rgba(184,100,122,.35)}\n.b1{left:7%;top:14%;background:#F9CDD4}.b2{left:84%;top:10%;background:#FDE3D3;animation-delay:-3s;width:44px;height:54px}\n.b3{left:78%;top:70%;background:#ECE3F6;animation-delay:-5s}.b4{left:12%;top:72%;background:#FFF2C9;animation-delay:-7s;width:40px;height:50px}\n@keyframes float{0%,100%{transform:translateY(0) rotate(-3deg)}50%{transform:translateY(-22px) rotate(3deg)}}\n.wrap{position:relative;width:100%;max-width:400px;z-index:1}\n.dog{display:block;width:96px;height:88px;margin:0 auto -18px;position:relative;z-index:2;cursor:pointer;filter:drop-shadow(0 6px 10px rgba(184,100,122,.18));transition:transform .2s}\n.dog:hover{transform:translateY(-3px) rotate(-3deg)}\n.dog.wink .eyes{transform-origin:76px 58px;animation:wink .4s}\n@keyframes wink{50%{transform:scaleY(.1)}}\n.bark{position:absolute;left:calc(50% + 40px);top:-6px;background:#fff;border:1px solid var(--line);border-radius:14px 14px 14px 4px;padding:4px 10px;font:600 13px 'Fredoka',sans-serif;color:var(--rose-deep);box-shadow:var(--shadow);opacity:0;transform:translateY(6px);transition:all .25s;pointer-events:none;z-index:3}\n.bark.on{opacity:1;transform:none}\n.card{background:var(--card);border:1px solid var(--line);border-radius:28px;box-shadow:0 20px 60px rgba(184,100,122,.16);padding:36px 28px 26px}\nh1{font:600 34px/1.05 'Fredoka',sans-serif;text-align:center;margin:6px 0 4px;color:var(--rose-deep);letter-spacing:-.5px}\nh1 span{color:var(--ink)}\n.sub{text-align:center;color:var(--muted);font-size:14px;margin:0 0 22px}\nlabel{display:block;font-weight:700;font-size:13px;margin:12px 0 6px;color:var(--ink)}\ninput{width:100%;border:1.5px solid var(--line);background:var(--blush-50);border-radius:14px;padding:12px 14px;font:600 15px 'Nunito',sans-serif;color:var(--ink);outline:none;transition:border .15s,background .15s}\ninput:focus{border-color:var(--blush-300);background:#fff}\n.btn{width:100%;margin-top:18px;border:0;border-radius:14px;padding:13px 16px;font:600 16px 'Fredoka',sans-serif;cursor:pointer;color:#fff;background:linear-gradient(135deg,#E79AAB,#D9879A);box-shadow:0 8px 20px rgba(217,135,154,.35);transition:transform .1s,filter .15s}\n.btn:hover{filter:brightness(1.04)}.btn:active{transform:scale(.98)}.btn[disabled]{opacity:.6;cursor:default}\n.link{display:block;text-align:center;margin-top:14px;color:var(--rose-deep);font-weight:700;font-size:13px;cursor:pointer;background:none;border:0;width:100%}\n.msg{margin-top:14px;padding:10px 12px;border-radius:12px;font-size:13px;font-weight:600}\n.err{background:#FDE4E7;color:#A2475E}.ok{background:var(--sage);color:var(--sage-ink)}\n.foot{text-align:center;color:var(--muted);font-size:12px;margin-top:16px}\n.heart{position:fixed;top:-30px;font-size:22px;pointer-events:none;animation:fall linear forwards;z-index:9}\n@keyframes fall{to{transform:translateY(110vh) rotate(360deg)}}\n`,\n  render(d2){\n    const s=d2.state, mode=s.mode||'login'\n    const msg=s.err?`<div class=\"msg err\">${esc(s.err)}</div>`:s.ok?`<div class=\"msg ok\">${esc(s.ok)}</div>`:''\n    let body=''\n    if(mode==='login') body=`\n      <form class=\"f-login\" autocomplete=\"on\">\n        <label>Email</label><input name=\"email\" type=\"email\" autocomplete=\"username\" placeholder=\"voce@email.com\" value=\"${esc(s.email||'')}\" required/>\n        <label>Senha</label><input name=\"password\" type=\"password\" autocomplete=\"current-password\" placeholder=\"••••••••\" required/>\n        <button class=\"btn\" type=\"submit\" ${s.busy?'disabled':''}>${s.busy?'Entrando…':'Entrar 🎈'}</button>\n      </form>${msg}<button class=\"link go-forgot\" type=\"button\">Esqueci minha senha</button>`\n    else if(mode==='forgot') body=`\n      <form class=\"f-forgot\"><p class=\"sub\" style=\"margin:0 0 4px\">Mandamos um link pro seu email pra você escolher uma senha nova.</p>\n        <label>Email</label><input name=\"email\" type=\"email\" placeholder=\"voce@email.com\" value=\"${esc(s.email||'')}\" required/>\n        <button class=\"btn\" type=\"submit\" ${s.busy?'disabled':''}>${s.busy?'Enviando…':'Enviar link ✉️'}</button>\n      </form>${msg}<button class=\"link go-login\" type=\"button\">← Voltar pro login</button>`\n    else if(mode==='reset') body=`\n      <form class=\"f-reset\"><p class=\"sub\" style=\"margin:0 0 4px\">Escolha sua nova senha (mínimo 6 caracteres).</p>\n        <label>Nova senha</label><input name=\"p1\" type=\"password\" autocomplete=\"new-password\" minlength=\"6\" required/>\n        <label>Repita a senha</label><input name=\"p2\" type=\"password\" autocomplete=\"new-password\" minlength=\"6\" required/>\n        <button class=\"btn\" type=\"submit\" ${s.busy?'disabled':''}>${s.busy?'Salvando…':'Salvar nova senha'}</button>\n      </form>${msg}<button class=\"link go-login\" type=\"button\">← Voltar pro login</button>`\n    return `<div class=\"page\">\n      <div class=\"balloon b1\"></div><div class=\"balloon b2\"></div><div class=\"balloon b3\"></div><div class=\"balloon b4\"></div>\n      <div class=\"wrap\">\n        <div class=\"bark ${s.bark?'on':''}\">${esc(s.bark||'au!')}</div>\n        <div class=\"dog-wrap\">${shiba('dog'+(s.wink?' wink':''))}</div>\n        <div class=\"card\">\n          <h1>Katia <span>faz 33</span></h1>\n          <p class=\"sub\">backoffice da festa · 15.11.2026</p>\n          ${body}\n        </div>\n        <div class=\"foot\">feito com 💗 e supervisão canina</div>\n      </div></div>`\n  },\n  mounted(d2){\n    fonts();pwa()\n    const s=d2.state\n    try{const t=new URLSearchParams(window.location.search).get('reset');if(t){s.token=t;s.mode='reset'}}catch(e){}\n    const set=(o)=>d2.setState(o)\n    d2.on('.go-forgot','click',()=>set({mode:'forgot',err:'',ok:''}))\n    d2.on('.go-login','click',()=>{set({mode:'login',err:'',ok:''});try{if(s.token)history.replaceState(null,'',window.location.pathname)}catch(e){}})\n    d2.on('form','submit',async(e,form)=>{\n      e.preventDefault()\n      const f=Object.fromEntries(new FormData(form).entries())\n      set({busy:true,err:'',ok:''})\n      try{\n        if(form.classList.contains('f-login')){\n          const email=String(f.email||'').trim().toLowerCase()\n          s.email=email\n          const auth=d2.auth(d2.param('auth'))\n          const r=await auth.login({credentials:{email,password:f.password}})\n          if(isErr(r)) throw r\n          set({ok:'Bem-vindo(a)! 🎉'})\n          setTimeout(()=>{window.location.replace(window.location.pathname)},350)\n          return\n        }\n        if(form.classList.contains('f-forgot')){\n          const email=String(f.email||'').trim().toLowerCase()\n          await d2.rush(d2.param('requestReset')).invoke({email})\n          set({ok:'Se esse email estiver cadastrado, o link chega em instantes. Olha o spam também 😉'})\n        }\n        if(form.classList.contains('f-reset')){\n          if(String(f.p1).length<6) throw new Error('A senha precisa ter pelo menos 6 caracteres.')\n          if(f.p1!==f.p2) throw new Error('As senhas não batem.')\n          const r=await d2.rush(d2.param('doReset')).invoke({token:s.token,password:f.p1})\n          const out=r&&r.data?r.data:r\n          if(!out||!out.ok) throw new Error((out&&out.error)||'Link inválido ou expirado.')\n          try{history.replaceState(null,'',window.location.pathname)}catch(e){}\n          set({mode:'login',email:out.email||'',token:'',ok:'Senha nova salva! Agora é só entrar 🐾'})\n        }\n      }catch(err){\n        const m=err&&err.message&&!/credential|unauthor|401|invalid/i.test(err.message)?err.message:'Email ou senha incorretos.'\n        set({err: form.classList.contains('f-login')?'Email ou senha incorretos.':m})\n      }finally{set({busy:false})}\n    })\n    let clicks=0,tm\n    d2.on('.dog','click',()=>{\n      clicks++; clearTimeout(tm); tm=setTimeout(()=>{clicks=0},1500)\n      const barks=['au!','au au! 🐾','*abana o rabo*','a festa vai ser linda 💗','auuu! 🎂']\n      set({wink:true,bark:barks[Math.min(clicks-1,barks.length-1)]})\n      setTimeout(()=>set({wink:false}),400); setTimeout(()=>set({bark:''}),1600)\n      if(clicks===5){\n        for(let i=0;i<26;i++){const h=document.createElement('div');h.className='heart';h.textContent=['💗','🎈','🐾','🌸','🎂'][i%5];h.style.left=Math.random()*100+'vw';h.style.animationDuration=(2.5+Math.random()*2.5)+'s';h.style.animationDelay=(Math.random()*1.2)+'s';d2.root.appendChild(h);setTimeout(()=>h.remove(),6500)}\n      }\n    })\n  },\n}\n"}},"auth":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"auth"}}}},"requestReset":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"requestReset"}}}},"doReset":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"doReset"}}}}}}}}}},{"_id":"6abefc2d0484650e9b1b43db","component":"data2-core-types@Component","system":"6abed5371a6b03943b9618d7","params":{"extends":"data2-core-primitives@Block","component":"kp-summary","package":"katia-party","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"// kp-summary — painel inicial: contagem regressiva, orçamento, convidados, próximos passos + shiba espiando\n// params: items quotes guests tasks settings (dataset), me (string)\nfunction esc(s){return String(s??'').replace(/[&<>\"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;'}[c]))}\nfunction shiba(cls){return `<svg class=\"${cls||''}\" viewBox=\"0 0 120 110\" aria-hidden=\"true\"><path d=\"M22 50 L30 8 L56 32 Z\" fill=\"#E59A55\"/><path d=\"M29 41 L33 18 L48 33 Z\" fill=\"#F8D7B5\"/><path d=\"M98 50 L90 8 L64 32 Z\" fill=\"#E59A55\"/><path d=\"M91 41 L87 18 L72 33 Z\" fill=\"#F8D7B5\"/><ellipse cx=\"60\" cy=\"62\" rx=\"44\" ry=\"40\" fill=\"#E59A55\"/><path d=\"M24 70 Q30 99 60 103 Q90 99 96 70 Q84 58 72 66 Q60 74 48 66 Q36 58 24 70Z\" fill=\"#FFF4E8\"/><ellipse cx=\"44\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><ellipse cx=\"76\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><ellipse cx=\"44\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><ellipse cx=\"76\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><circle cx=\"45.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/><circle cx=\"77.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/><path d=\"M54 72 Q60 68 66 72 Q63 78 60 78 Q57 78 54 72Z\" fill=\"#3B2A2E\"/><path d=\"M52 83 Q56 88 60 83 Q64 88 68 83\" stroke=\"#3B2A2E\" stroke-width=\"2.4\" fill=\"none\" stroke-linecap=\"round\"/><ellipse cx=\"32\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/><ellipse cx=\"88\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/></svg>`}\nconst BRL=(n)=>new Intl.NumberFormat('pt-BR',{style:'currency',currency:'BRL',maximumFractionDigits:(Number(n)||0)%1?2:0}).format(Number(n)||0)\nconst PARTY=new Date('2026-11-15T15:00:00-03:00')\nconst MAPS='https://maps.app.goo.gl/wVNFaGGmY8bLGoJt9'\nconst recs=(d2,k)=>{const h=d2.data(k);return h?h.records()||[]:[]}\n\nexport default {\n  css:`\n:host{--bg:#FFF7F5;--card:#FFFFFF;--blush-50:#FFF1F2;--blush-100:#FDE4E7;--blush-200:#F9CDD4;--blush-300:#F2AEBA;--rose:#D9879A;--rose-deep:#B8647A;--ink:#4A3439;--muted:#94797E;--line:#F3DDE0;--peach:#FDE3D3;--sage:#DCEBDD;--sage-ink:#4F7A57;--butter:#FFF2C9;--butter-ink:#8A6D1F;--lilac:#ECE3F6;--lilac-ink:#6B5390;--shadow:0 6px 24px rgba(184,100,122,.12)}\n*{box-sizing:border-box}\n.wrap{height:100%;overflow:auto;padding:28px clamp(16px,3vw,40px) 90px;font-family:'Nunito',system-ui,sans-serif;color:var(--ink);position:relative}\n.inner{max-width:1120px;margin:0 auto;display:grid;gap:18px}\n.hello{font:600 15px 'Fredoka';color:var(--muted);margin:0}\n.hero{position:relative;overflow:hidden;border-radius:28px;padding:28px clamp(20px,3vw,36px);background:linear-gradient(120deg,#FBD3DB 0%,#FDE3D3 55%,#FFF2C9 120%);box-shadow:0 18px 50px rgba(217,135,154,.22);display:grid;grid-template-columns:1fr auto;gap:18px;align-items:center}\n.hero h1{font:600 clamp(30px,4.4vw,48px)/1.02 'Fredoka',sans-serif;margin:0 0 8px;color:#8E4258;letter-spacing:-.5px}\n.hero p{margin:0;font-weight:700;color:#7A5560;font-size:15px}\n.hero .where{display:inline-flex;align-items:center;gap:8px;margin-top:14px;background:rgba(255,255,255,.7);border-radius:999px;padding:8px 14px;font-weight:800;font-size:13px;color:var(--rose-deep);text-decoration:none}\n.big{text-align:center;background:rgba(255,255,255,.75);border-radius:24px;padding:16px 22px;min-width:150px}\n.big b{display:block;font:600 64px/1 'Fredoka';color:var(--rose-deep)}\n.big span{font-weight:800;font-size:13px;color:#7A5560}\n.conf{position:absolute;border-radius:50%;opacity:.5}\n.grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px}\n.card{background:var(--card);border:1px solid var(--line);border-radius:22px;padding:18px;box-shadow:var(--shadow);cursor:pointer;transition:transform .15s,box-shadow .15s;min-width:0}\n.card:hover{transform:translateY(-2px);box-shadow:0 12px 30px rgba(184,100,122,.18)}\n.card .k{font-weight:800;font-size:12px;letter-spacing:.4px;text-transform:uppercase;color:var(--muted);display:flex;align-items:center;gap:6px}\n.card .v{font:600 28px/1.1 'Fredoka';margin:8px 0 4px;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.card .h{font-size:13px;color:var(--muted);font-weight:700}\n.bar{height:10px;border-radius:999px;background:var(--blush-50);overflow:hidden;margin-top:10px}\n.bar i{display:block;height:100%;border-radius:999px;background:linear-gradient(90deg,#F2AEBA,#D9879A)}\n.bar i.warn{background:linear-gradient(90deg,#F7C59F,#E8956B)}.bar i.over{background:linear-gradient(90deg,#EE9AA5,#C9506B)}\n.two{display:grid;grid-template-columns:1.3fr 1fr;gap:14px}\n.panel{background:var(--card);border:1px solid var(--line);border-radius:22px;padding:20px;box-shadow:var(--shadow);min-width:0}\n.panel h3{font:600 18px 'Fredoka';margin:0 0 12px;display:flex;align-items:center;gap:8px}\n.row{display:flex;align-items:center;gap:12px;padding:10px 4px;border-top:1px dashed var(--line);cursor:pointer}\n.row:first-of-type{border-top:0}\n.em{width:36px;height:36px;border-radius:12px;background:var(--blush-50);display:grid;place-items:center;font-size:18px;flex:none}\n.row .t{font-weight:800;font-size:14px;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.chip{font-weight:800;font-size:11px;border-radius:999px;padding:3px 9px;white-space:nowrap}\n.c-pend{background:var(--blush-100);color:var(--rose-deep)}.c-cot{background:var(--butter);color:var(--butter-ink)}.c-ok{background:var(--sage);color:var(--sage-ink)}.c-lil{background:var(--lilac);color:var(--lilac-ink)}\n.empty{color:var(--muted);font-weight:700;font-size:14px;padding:8px 4px}\n.peek{position:fixed;right:22px;bottom:-14px;width:92px;height:84px;cursor:pointer;transition:transform .35s cubic-bezier(.3,1.6,.5,1);z-index:5;filter:drop-shadow(0 -4px 10px rgba(184,100,122,.15))}\n.peek:hover{transform:translateY(-16px) rotate(-6deg)}\n.bubble{position:fixed;right:110px;bottom:56px;background:#fff;border:1px solid var(--line);border-radius:16px 16px 4px 16px;padding:10px 14px;font:600 14px 'Fredoka';color:var(--rose-deep);box-shadow:var(--shadow);z-index:5;max-width:240px}\n@media (max-width:1020px){.grid{grid-template-columns:repeat(2,minmax(0,1fr))}.two{grid-template-columns:1fr}}\n@media (max-width:560px){.hero{grid-template-columns:1fr}.big{display:flex;align-items:baseline;gap:10px;justify-content:center}.big b{font-size:44px}.card .v{font-size:22px}.peek{display:none}.wrap{padding-top:18px}}\n`,\n  render(d2){\n    const items=recs(d2,'items'),quotes=recs(d2,'quotes'),guests=recs(d2,'guests'),tasks=recs(d2,'tasks'),settings=recs(d2,'settings')\n    const party=(settings.find(r=>r.key==='party')||{}).value||{}\n    const cap=Number(party.budgetCap)||15000\n    const byItem={};for(const q of quotes){(byItem[q.itemId]=byItem[q.itemId]||[]).push(q)}\n    let chosen=0,closed=0,proj=0\n    const next=[]\n    for(const it of items){const qs=byItem[it._id]||[];const c=qs.find(q=>q.chosen)\n      if(c){chosen+=Number(c.price)||0;proj+=Number(c.price)||0;closed++}else if(it.free){closed++}\n      else{const min=qs.length?Math.min(...qs.map(q=>Number(q.price)||0)):0;proj+=min;next.push({it,n:qs.length,min})}}\n    const pct=Math.min(100,Math.round(chosen/cap*100))\n    const cls=chosen>cap?'over':pct>=85?'warn':''\n    const people=()=>1 // convite individual\n    const totalP=guests.reduce((a,g)=>a+people(g),0)\n    const confP=guests.filter(g=>g.status==='confirmado').reduce((a,g)=>a+people(g),0)\n    const pendT=tasks.filter(t=>['pendente','em andamento'].includes(t.status||'pendente'))\n    const days=Math.max(0,Math.ceil((PARTY.getTime()-Date.now())/86400000))\n    const me=d2.param('me')||''\n    const h=new Date().getHours(),greet=h<12?'Bom dia':h<18?'Boa tarde':'Boa noite'\n    const mood=chosen>cap?'Ih… estourou o teto 😬 bora rever?':pct>=85?'Tá chegando no teto, atenção! 🐾':closed===items.length&&items.length?'Tudo fechado! Melhores organizadores 🏆':'Tô de olho no orçamento pra vocês 🐕'\n    return `<div class=\"wrap\"><div class=\"inner\">\n      <p class=\"hello\">${greet}${me?', '+esc(me):''}! 💗</p>\n      <section class=\"hero\">\n        <div class=\"conf\" style=\"width:120px;height:120px;right:-30px;top:-40px;background:#fff\"></div>\n        <div class=\"conf\" style=\"width:60px;height:60px;left:40%;bottom:-24px;background:#F9CDD4\"></div>\n        <div><h1>Katia faz 33 🎂</h1><p>Domingo, 15 de novembro de 2026</p>\n          <a class=\"where\" href=\"${MAPS}\" target=\"_blank\" rel=\"noopener\">📍 Sítio Recanto dos Lagos · Mogi das Cruzes</a></div>\n        <div class=\"big\"><b>${days}</b><span>${days===1?'dia':'dias'} pra festa</span></div>\n      </section>\n      <div class=\"grid\">\n        <div class=\"card go\" data-go=\"budget\"><div class=\"k\">💸 Escolhido</div><div class=\"v\">${BRL(chosen)}</div><div class=\"h\">de ${BRL(cap)} · ${pct}%</div><div class=\"bar\"><i class=\"${cls}\" style=\"width:${pct}%\"></i></div></div>\n        <div class=\"card go\" data-go=\"budget\"><div class=\"k\">✅ Itens fechados</div><div class=\"v\">${closed}/${items.length}</div><div class=\"h\">projeção ${BRL(proj)}</div><div class=\"bar\"><i style=\"width:${items.length?Math.round(closed/items.length*100):0}%\"></i></div></div>\n        <div class=\"card go\" data-go=\"guests\"><div class=\"k\">💌 Convidados</div><div class=\"v\">${totalP} ${totalP===1?'pessoa':'pessoas'}</div><div class=\"h\">${confP} confirmados · ${totalP-confP} a confirmar</div><div class=\"bar\"><i style=\"width:${totalP?Math.round(confP/totalP*100):0}%\"></i></div></div>\n        <div class=\"card go\" data-go=\"chat\"><div class=\"k\">🐕 Tasks do Milo</div><div class=\"v\">${pendT.length}</div><div class=\"h\">${pendT.length?'esperando o Claude':'nada pendente ✨'}</div></div>\n      </div>\n      <div class=\"two\">\n        <div class=\"panel\"><h3>📝 Falta cotar / decidir</h3>\n          ${next.length?next.slice(0,8).map(x=>`<div class=\"row go\" data-go=\"budget\" data-item=\"${esc(x.it._id)}\"><div class=\"em\">${esc(x.it.glyph||'✨')}</div><div class=\"t\">${esc(x.it.name)}</div>${x.n?`<span class=\"chip c-cot\">${x.n} cotaç${x.n>1?'ões':'ão'} · a partir de ${BRL(x.min)}</span>`:'<span class=\"chip c-pend\">sem cotação</span>'}</div>`).join(''):'<div class=\"empty\">Tudo decidido por aqui 🎉</div>'}\n        </div>\n        <div class=\"panel\"><h3>🐾 Tasks pendentes</h3>\n          ${pendT.length?pendT.slice(0,6).map(t=>`<div class=\"row go\" data-go=\"chat\"><div class=\"em\">${t.status==='em andamento'?'⏳':'📌'}</div><div class=\"t\">${esc(t.title)}</div><span class=\"chip ${t.status==='em andamento'?'c-cot':'c-lil'}\">${esc(t.status||'pendente')}</span></div>`).join(''):'<div class=\"empty\">Nenhuma task. Fala com o Milo no chat! 🐕</div>'}\n        </div>\n      </div>\n    </div>\n    </div>`\n  },\n  mounted(d2){\n    d2.on('.go','click',(e,el)=>{if(el.dataset.item)d2.shared.set('kp-open-item',el.dataset.item,{global:true});d2.bus.emit('kp:nav',el.dataset.go)})\n    let tm\n    d2.on('.peek','click',()=>{const m=d2.$('.peek-wrap');d2.state.bubble=m?m.dataset.mood:'au!';clearTimeout(tm);tm=setTimeout(()=>{d2.state.bubble=''},3500)})\n  },\n}\n"}},"items":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"items"}}}},"quotes":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"quotes"}}}},"guests":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"guests"}}}},"tasks":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tasks"}}}},"settings":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"settings"}}}},"me":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"me"}}}}}}}}}},{"_id":"6abefc5ee9fa96de8a9fd12d","component":"data2-core-types@Component","system":"6abed5371a6b03943b9618d7","params":{"extends":"data2-core-primitives@Block","component":"kp-app","package":"katia-party","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"// kp-app — casca do backoffice: sidebar (desktop) / bottom-nav (mobile), topo com contagem regressiva,\n// menu do usuário (trocar senha / sair) e a view ativa renderizada via d2.render.\n// params: auth(service) requestReset(rush) items quotes guests messages tasks settings artworks(dataset)\n//         scribe artist(assistant) drive(service)\n//         vSummary vBudget vGuests vChat vArt (component)\nfunction esc(s){return String(s??'').replace(/[&<>\"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;'}[c]))}\nfunction fonts(){try{if(document.getElementById('kp-fonts'))return;const l=document.createElement('link');l.id='kp-fonts';l.rel='stylesheet';l.href='https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&family=Nunito:wght@400;600;700;800&display=swap';document.head.appendChild(l)}catch(e){}}\nfunction pwa(){try{if(window.__kpPwa)return;window.__kpPwa=1\n  const svg=`<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><defs><linearGradient id=\"g\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\"><stop offset=\"0\" stop-color=\"#FBD3DB\"/><stop offset=\".6\" stop-color=\"#FDE3D3\"/><stop offset=\"1\" stop-color=\"#FFF2C9\"/></linearGradient></defs><rect width=\"512\" height=\"512\" fill=\"url(#g)\"/><circle cx=\"420\" cy=\"92\" r=\"40\" fill=\"#fff\" opacity=\".55\"/><circle cx=\"86\" cy=\"430\" r=\"26\" fill=\"#F9CDD4\" opacity=\".8\"/><g transform=\"translate(112 140) scale(2.4)\"><path d=\"M22 50 L30 8 L56 32 Z\" fill=\"#E59A55\"/><path d=\"M29 41 L33 18 L48 33 Z\" fill=\"#F8D7B5\"/><path d=\"M98 50 L90 8 L64 32 Z\" fill=\"#E59A55\"/><path d=\"M91 41 L87 18 L72 33 Z\" fill=\"#F8D7B5\"/><ellipse cx=\"60\" cy=\"62\" rx=\"44\" ry=\"40\" fill=\"#E59A55\"/><path d=\"M24 70 Q30 99 60 103 Q90 99 96 70 Q84 58 72 66 Q60 74 48 66 Q36 58 24 70Z\" fill=\"#FFF4E8\"/><ellipse cx=\"44\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><ellipse cx=\"76\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><ellipse cx=\"44\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><ellipse cx=\"76\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><circle cx=\"45.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/><circle cx=\"77.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/><path d=\"M54 72 Q60 68 66 72 Q63 78 60 78 Q57 78 54 72Z\" fill=\"#3B2A2E\"/><path d=\"M52 83 Q56 88 60 83 Q64 88 68 83\" stroke=\"#3B2A2E\" stroke-width=\"2.4\" fill=\"none\" stroke-linecap=\"round\"/><ellipse cx=\"32\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/><ellipse cx=\"88\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/><path d=\"M36 10 L60 -22 L84 10 Z\" fill=\"#E79AAB\"/><circle cx=\"60\" cy=\"-24\" r=\"6\" fill=\"#fff\"/><circle cx=\"50\" cy=\"0\" r=\"3\" fill=\"#fff\"/><circle cx=\"66\" cy=\"-8\" r=\"3\" fill=\"#FFF2C9\"/></g></svg>`\n  const mk=(size)=>new Promise(res=>{const img=new Image();img.onload=()=>{const c=document.createElement('canvas');c.width=c.height=size;c.getContext('2d').drawImage(img,0,0,size,size);res(c.toDataURL('image/png'))};img.onerror=()=>res('');img.src='data:image/svg+xml;charset=utf-8,'+encodeURIComponent(svg)})\n  Promise.all([mk(192),mk(512),mk(180)]).then(([i192,i512,i180])=>{\n    const o=location.origin+'/'\n    const m={name:'Katia faz 33 · Backoffice',short_name:'Katia 33',description:'Orçamento, convidados e o Milo 🐕',id:o,start_url:o,scope:o,display:'standalone',orientation:'portrait',background_color:'#FFF7F5',theme_color:'#FBD3DB',lang:'pt-BR',\n      icons:[{src:i192,sizes:'192x192',type:'image/png',purpose:'any'},{src:i512,sizes:'512x512',type:'image/png',purpose:'any'},{src:i512,sizes:'512x512',type:'image/png',purpose:'maskable'}]}\n    const put=(tag,match,attrs)=>{let el=[...document.head.querySelectorAll(tag)].find(match);if(!el){el=document.createElement(tag);document.head.appendChild(el)}for(const k in attrs)el.setAttribute(k,attrs[k]);return el}\n    put('link',e=>e.rel==='manifest',{rel:'manifest',href:'data:application/manifest+json;charset=utf-8,'+encodeURIComponent(JSON.stringify(m))})\n    put('link',e=>e.rel==='apple-touch-icon',{rel:'apple-touch-icon',href:i180})\n    put('link',e=>e.rel==='icon',{rel:'icon',type:'image/png',href:i192})\n    put('meta',e=>e.name==='theme-color',{name:'theme-color',content:'#FBD3DB'})\n    put('meta',e=>e.name==='apple-mobile-web-app-title',{name:'apple-mobile-web-app-title',content:'Katia 33'})\n    put('meta',e=>e.name==='apple-mobile-web-app-status-bar-style',{name:'apple-mobile-web-app-status-bar-style',content:'default'})\n    put('meta',e=>e.name==='description',{name:'description',content:m.description})\n  })}catch(e){}}\nfunction shiba(cls){return `<svg class=\"${cls||''}\" viewBox=\"0 0 120 110\" aria-hidden=\"true\"><path d=\"M22 50 L30 8 L56 32 Z\" fill=\"#E59A55\"/><path d=\"M29 41 L33 18 L48 33 Z\" fill=\"#F8D7B5\"/><path d=\"M98 50 L90 8 L64 32 Z\" fill=\"#E59A55\"/><path d=\"M91 41 L87 18 L72 33 Z\" fill=\"#F8D7B5\"/><ellipse cx=\"60\" cy=\"62\" rx=\"44\" ry=\"40\" fill=\"#E59A55\"/><path d=\"M24 70 Q30 99 60 103 Q90 99 96 70 Q84 58 72 66 Q60 74 48 66 Q36 58 24 70Z\" fill=\"#FFF4E8\"/><ellipse cx=\"44\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><ellipse cx=\"76\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><ellipse cx=\"44\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><ellipse cx=\"76\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><circle cx=\"45.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/><circle cx=\"77.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/><path d=\"M54 72 Q60 68 66 72 Q63 78 60 78 Q57 78 54 72Z\" fill=\"#3B2A2E\"/><path d=\"M52 83 Q56 88 60 83 Q64 88 68 83\" stroke=\"#3B2A2E\" stroke-width=\"2.4\" fill=\"none\" stroke-linecap=\"round\"/><ellipse cx=\"32\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/><ellipse cx=\"88\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/></svg>`}\nfunction who(d2){const a=d2.auth(d2.param('auth'));const u=(a&&a.user)||{};let email=u.email||(a&&a.session&&a.session.credentials&&a.session.credentials.email)||'';if(!email){try{const t=localStorage.getItem('__data2-session-katia-party')||'';const p=JSON.parse(decodeURIComponent(escape(atob(t.split('.')[1].replace(/-/g,'+').replace(/_/g,'/')))));const s=(p.sessions||[]).find(x=>x.authStrategy==='partyAuth')||(p.sessions||[])[0];email=(s&&s.credentials&&s.credentials.email)||''}catch(e){}}return String(email).toLowerCase()}\nconst PARTY=new Date('2026-11-15T15:00:00-03:00')\nconst NAMES={'danilojun9@gmail.com':'Danilo','katia.s.honda@gmail.com':'Katia'}\nconst TABS=[\n  {id:'summary',label:'Resumo',glyph:'🏡',view:'vSummary'},\n  {id:'budget',label:'Orçamento',glyph:'💸',view:'vBudget'},\n  {id:'guests',label:'Convidados',glyph:'💌',view:'vGuests'},\n  {id:'chat',label:'Milo',glyph:'🐕',view:'vChat'},\n  {id:'art',label:'Artes',glyph:'🎨',view:'vArt'},\n]\nconst DS=['items','quotes','guests','messages','tasks','settings','artworks']\nconst SCAN=new WeakMap() // root → função que detecta mudança de status das tasks (chamada no updated)\n\nexport default {\n  css:`\n:host{--bg:#FFF7F5;--card:#FFFFFF;--blush-50:#FFF1F2;--blush-100:#FDE4E7;--blush-200:#F9CDD4;--blush-300:#F2AEBA;--rose:#D9879A;--rose-deep:#B8647A;--ink:#4A3439;--muted:#94797E;--line:#F3DDE0;--peach:#FDE3D3;--sage:#DCEBDD;--sage-ink:#4F7A57;--shadow:0 6px 24px rgba(184,100,122,.12)}\n*{box-sizing:border-box}\n.app{height:100%;display:grid;grid-template-columns:244px minmax(0,1fr);grid-template-rows:minmax(0,1fr);background:var(--bg);color:var(--ink);font-family:'Nunito',system-ui,sans-serif;overflow:hidden}\n.side{display:flex;flex-direction:column;gap:6px;padding:22px 16px 16px;background:linear-gradient(180deg,#FFFFFF 0,#FFF3F4 100%);border-right:1px solid var(--line);min-height:0}\n.logo{display:flex;align-items:center;gap:10px;padding:4px 8px 18px;cursor:pointer;user-select:none}\n.logo svg{width:44px;height:40px;flex:none;transition:transform .3s}.logo:hover svg{transform:rotate(-8deg)}\n.logo b{font:600 22px/1 'Fredoka',sans-serif;color:var(--rose-deep);display:block}\n.logo small{font-size:12px;color:var(--muted);font-weight:700}\n.nav{display:flex;flex-direction:column;gap:4px}\n.tab{display:flex;align-items:center;gap:12px;padding:11px 14px;border-radius:14px;cursor:pointer;font:600 15px 'Fredoka',sans-serif;color:var(--ink);border:0;background:none;text-align:left;transition:background .15s}\n.tab .g{font-size:18px;width:26px;text-align:center}\n.tab:hover{background:var(--blush-50)}\n.tab[data-on]{background:var(--blush-100);color:var(--rose-deep);box-shadow:inset 0 0 0 1px var(--blush-200)}\n.tab .badge{margin-left:auto;background:var(--rose);color:#fff;border-radius:999px;font:700 11px 'Nunito';padding:2px 7px}\n.spacer{flex:1}\n.count{margin:10px 4px;padding:14px;border-radius:18px;background:linear-gradient(135deg,#FDE4E7,#FDE3D3);text-align:center}\n.count b{display:block;font:600 34px/1 'Fredoka',sans-serif;color:var(--rose-deep)}\n.count span{font-size:12px;font-weight:700;color:var(--muted)}\n.me{position:relative;display:flex;align-items:center;gap:10px;padding:10px;border-radius:14px;cursor:pointer;border:1px solid transparent}\n.me:hover{background:#fff;border-color:var(--line)}\n.av{width:34px;height:34px;border-radius:50%;display:grid;place-items:center;font:600 14px 'Fredoka';color:#fff;background:linear-gradient(135deg,#E79AAB,#D9879A);flex:none}\n.me .n{font-weight:800;font-size:14px}.me .e{font-size:11px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:140px}\n.menu{position:absolute;bottom:calc(100% + 6px);left:0;right:0;background:#fff;border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);padding:6px;z-index:20}\n.menu.top{bottom:auto;top:calc(100% + 6px);left:auto;right:0;width:220px}\n.menu button{display:block;width:100%;text-align:left;border:0;background:none;padding:10px 12px;border-radius:10px;font:700 14px 'Nunito';color:var(--ink);cursor:pointer}\n.menu button:hover{background:var(--blush-50)}\n.main{display:grid;grid-template-rows:auto minmax(0,1fr);min-width:0;min-height:0}\n.top{display:none}\n.view{min-height:0;position:relative;grid-row:2}\n.top{grid-row:1}.bottom{grid-row:3}\n.view>*{position:absolute!important;inset:0!important;width:auto!important;height:auto!important}\n.bottom{display:none}\n.toast{position:fixed;left:50%;bottom:26px;transform:translateX(-50%);background:var(--ink);color:#fff;padding:10px 16px;border-radius:14px;font-weight:700;font-size:14px;box-shadow:var(--shadow);z-index:50;max-width:calc(100vw - 32px);text-align:center}\n.rain{position:fixed;top:-70px;width:54px;height:50px;pointer-events:none;z-index:60;animation:fall linear forwards}\n.rain svg{width:100%;height:100%}\n@keyframes fall{to{transform:translateY(115vh) rotate(540deg)}}\n.milo{position:fixed;right:20px;bottom:-14px;width:88px;height:80px;cursor:pointer;z-index:40;transition:transform .35s cubic-bezier(.3,1.6,.5,1);filter:drop-shadow(0 -4px 10px rgba(184,100,122,.18))}\n.milo:hover,.milo.up{transform:translateY(-18px) rotate(-6deg)}\n.mbub{position:fixed;right:106px;bottom:46px;max-width:min(320px,calc(100vw - 140px));background:#fff;border:1px solid var(--line);border-radius:16px 16px 4px 16px;padding:10px 14px;font:600 14px/1.35 'Fredoka',sans-serif;color:var(--rose-deep);box-shadow:0 10px 30px rgba(184,100,122,.22);z-index:41;cursor:pointer;animation:pop .3s ease-out}\n.mbub small{display:block;margin-top:3px;font:700 12px/1.3 'Nunito',sans-serif;color:var(--muted)}\n@keyframes pop{from{opacity:0;transform:translateY(8px) scale(.96)}}\n.mbub.top{bottom:auto;top:84px;border-radius:16px 4px 16px 16px}\n@media (max-width:820px){.milo{right:10px;bottom:62px;width:58px;height:53px}.mbub{right:16px;bottom:118px;max-width:calc(100vw - 32px)}}\n@media (max-width:820px){\n  .app{grid-template-columns:minmax(0,1fr)}\n  .side{display:none}\n  .main{grid-template-rows:auto minmax(0,1fr) auto}\n  .top{display:flex;align-items:center;gap:10px;padding:10px 16px;background:#fff;border-bottom:1px solid var(--line)}\n  .top .logo{padding:0;flex:1;min-width:0}.top .logo svg{width:34px;height:31px}.top .logo b{font-size:19px}\n  .pill{font:600 13px 'Fredoka';color:var(--rose-deep);background:var(--blush-100);border-radius:999px;padding:6px 10px;white-space:nowrap}\n  .top .me{padding:0}.top .me .txt{display:none}\n  .bottom{display:grid;grid-template-columns:repeat(5,1fr);background:#fff;border-top:1px solid var(--line);padding:6px 4px calc(6px + env(safe-area-inset-bottom))}\n  .bottom .tab{flex-direction:column;gap:2px;padding:6px 2px;font-size:11px;justify-content:center;align-items:center;border-radius:12px;position:relative}\n  .bottom .tab .g{font-size:20px;width:auto}\n  .bottom .tab .badge{position:absolute;top:2px;right:calc(50% - 22px);margin:0;padding:1px 5px;font-size:10px}\n}\n`,\n  render(d2){\n    const s=d2.state\n    const email=who(d2)\n    const me=NAMES[email]||(email?email.split('@')[0]:'Você')\n    const tab=TABS.find(t=>t.id===s.tab)||TABS[0]\n    const days=Math.max(0,Math.ceil((PARTY.getTime()-Date.now())/86400000))\n    const tasks=d2.data('tasks'), pend=tasks?tasks.records().filter(t=>['pendente','em andamento'].includes(t.status||'pendente')).length:0\n    const tabBtn=(t)=>`<button class=\"tab\" data-tab=\"${t.id}\" ${t.id===tab.id?'data-on':''}><span class=\"g\">${t.glyph}</span><span>${t.label}</span>${t.id==='chat'&&pend?`<span class=\"badge\">${pend}</span>`:''}</button>`\n    const menu=(cls)=>s.menu?`<div class=\"menu ${cls}\"><button class=\"m-pass\">🔑 Trocar senha</button><button class=\"m-out\">👋 Sair</button></div>`:''\n    const P=d2.params\n    const common={items:P.items,quotes:P.quotes,guests:P.guests,messages:P.messages,tasks:P.tasks,settings:P.settings,artworks:P.artworks,scribe:P.scribe,artist:P.artist,drive:P.drive,uploader:'upload-file',me}\n    return `<div class=\"app\">\n      <aside class=\"side\">\n        <div class=\"logo\">${shiba()}<div><b>Katia faz 33</b><small>15.11 · Sítio Recanto dos Lagos</small></div></div>\n        <nav class=\"nav\">${TABS.map(tabBtn).join('')}</nav>\n        <div class=\"spacer\"></div>\n        <div class=\"count\"><b>${days}</b><span>${days===0?'é hoje!!! 🎉':days===1?'dia pra festa 🎂':'dias pra festa 🎂'}</span></div>\n        <div class=\"me\"><div class=\"av\">${esc(me[0]||'?')}</div><div class=\"txt\"><div class=\"n\">${esc(me)}</div><div class=\"e\">${esc(email)}</div></div>${menu('')}</div>\n      </aside>\n      <section class=\"main\">\n        <header class=\"top\">\n          <div class=\"logo\">${shiba()}<div><b>Katia faz 33</b></div></div>\n          <span class=\"pill\">🎂 ${days}d</span>\n          <div class=\"me\"><div class=\"av\">${esc(me[0]||'?')}</div>${menu('top')}</div>\n        </header>\n        <div class=\"view\">${d2.render(d2.param(tab.view),common,{key:tab.id})}</div>\n        <nav class=\"bottom\">${TABS.map(tabBtn).join('')}</nav>\n      </section>\n      ${s.note?`<div class=\"mbub ${tab.id==='chat'?'top':''}\" data-go=\"${esc(s.note.go||'')}\">${esc(s.note.text)}${s.note.sub?`<small>${esc(s.note.sub)}</small>`:''}</div>`:''}\n      ${tab.id==='chat'?'':`<div class=\"milo-wrap\" title=\"Milo\">${shiba('milo'+(s.note?' up':''))}</div>`}\n      ${s.toast?`<div class=\"toast\">${esc(s.toast)}</div>`:''}\n    </div>`\n  },\n  mounted(d2){\n    fonts();pwa()\n    try{const t=localStorage.getItem('kp-tab');if(t)d2.state.tab=t}catch(e){}\n    for(const k of DS){try{const h=d2.data(k);if(h)h.loadAll()}catch(e){}}\n    const go=(id)=>{d2.setState({tab:id,menu:false});try{localStorage.setItem('kp-tab',id)}catch(e){}}\n    let tt;const toast=(m)=>{d2.state.toast=m;clearTimeout(tt);tt=setTimeout(()=>{d2.state.toast=''},3200)}\n    d2.on('.tab','click',(e,el)=>go(el.dataset.tab))\n    d2.bus.on('kp:nav',(id)=>go(id))\n    d2.bus.on('kp:toast',(m)=>toast(m))\n    // 🐕 Milo do canto: avisa quando o Claude pega/termina uma task. Tasks e mensagens são recarregadas a cada 30 s.\n    const seen=new Map(),gseen=new Map();let primed=false,gprimed=false,showing=false;const queue=[]\n    const show=()=>{if(showing||!queue.length)return;showing=true;d2.state.note=queue.shift();setTimeout(()=>{d2.state.note=null;showing=false;setTimeout(show,500)},8000)}\n    const notify=(n)=>{queue.push(n);show()}\n    SCAN.set(d2.root,()=>{const T=d2.data('tasks');if(!T||T.loading)return\n      for(const t of (T.records()||[])){if(!t._id)continue;const st=t.status||'pendente',prev=seen.get(t._id);seen.set(t._id,st)\n        if(!primed||prev===st)continue\n        if(st==='feita')notify({text:`Au! O Claude terminou: ${t.title} ✨`,sub:t.result?String(t.result).slice(0,140):'toca aqui pra ver no chat',go:'chat'})\n        else if(st==='em andamento')notify({text:`O Claude pegou a task: ${t.title} 🐾`,sub:'tô de olho, já te aviso!',go:'chat'})}\n      primed=true\n      const Gd=d2.data('guests');if(Gd&&!Gd.loading){for(const g of (Gd.records()||[])){if(!g._id)continue;const k=g.rsvpAt||'',prev=gseen.get(g._id);gseen.set(g._id,k)\n        if(!gprimed||prev===undefined||!k||prev===k)continue;const nm=String(g.name||'').split(' (')[0]\n        if(g.status==='confirmado')notify({text:`🎉 ${nm} confirmou presença!`,sub:g.rsvpNote&&g.rsvpNote!=='undefined'?`“${String(g.rsvpNote).slice(0,120)}”`:'pelo convite 💌',go:'guests'})\n        else if(g.status==='não vem')notify({text:`😢 ${nm} não vai conseguir ir`,sub:g.rsvpNote&&g.rsvpNote!=='undefined'?`“${String(g.rsvpNote).slice(0,120)}”`:'respondeu pelo convite',go:'guests'})}\n        gprimed=true}})\n    const poll=setInterval(()=>{for(const k of ['tasks','messages','guests']){try{const h=d2.data(k);h&&h.loadAll()}catch(e){}}},30000)\n    d2.onUnmount(()=>clearInterval(poll))\n    d2.on('.mbub','click',(e,el)=>{const g=el.dataset.go;d2.state.note=null;if(g)go(g)})\n    let bk=0\n    d2.on('.milo','click',()=>{if(d2.state.note)return\n      const days=Math.max(0,Math.ceil((PARTY.getTime()-Date.now())/86400000))\n      const qs=(d2.data('quotes')&&d2.data('quotes').records())||[],chosen=qs.filter(q=>q.chosen).reduce((a,q)=>a+(Number(q.price)||0),0)\n      const set=((d2.data('settings')&&d2.data('settings').records())||[]).find(r=>r.key==='party'),cap=Number(set&&set.value&&set.value.budgetCap)||15000\n      const brl=(n)=>new Intl.NumberFormat('pt-BR',{style:'currency',currency:'BRL',maximumFractionDigits:0}).format(n)\n      const open=((d2.data('tasks')&&d2.data('tasks').records())||[]).filter(t=>['pendente','em andamento'].includes(t.status||'pendente')).length\n      const B=['Au! 🐾',`Faltam ${days} dias pra festa 🎂`,`Já escolhemos ${brl(chosen)} de ${brl(cap)} 💸`,open?`Tem ${open} task${open>1?'s':''} na fila do Claude 📋`:'Fila de tasks zerada ✨','Cadê meu petisco? 🦴','*abana o rabo*']\n      notify({text:B[bk++%B.length]})})\n    // 🐕💬 easter egg: o Milo tagarela sozinho de vez em quando (3–8 min). Dois toques nele = modo quietinho.\n    const QUIET='kp-milo-quiet',isQuiet=()=>{try{return localStorage.getItem(QUIET)==='1'}catch(e){return false}}\n    const pick=(a)=>a[Math.floor(Math.random()*a.length)]\n    const R=(k)=>{const h=d2.data(k);return (h&&h.records())||[]}\n    const chatter=()=>{\n      const now=new Date(),h=now.getHours(),dow=now.getDay(),days=Math.max(0,Math.ceil((PARTY.getTime()-Date.now())/86400000))\n      if(days===0)return pick(['É HOJE!!! 🎂🎉🐕','HOJE TEM FESTA!!! Já tô de gravatinha 🎀','Parabéns, Katia!!! 33 lambeijos pra você 💗🐾'])\n      const me=NAMES[who(d2)]||'',tab=d2.state.tab||'summary'\n      const G=R('guests'),conf=G.filter(g=>g.status==='confirmado').length,duv=G.filter(g=>g.status==='em dúvida').length,inv=G.filter(g=>g.status==='convidado').length\n      const qs=R('quotes'),chosen=qs.filter(q=>q.chosen).reduce((a,q)=>a+(Number(q.price)||0),0)\n      const set=R('settings').find(r=>r.key==='party'),cap=Number(set&&set.value&&set.value.budgetCap)||15000,pct=Math.round(chosen/cap*100)\n      const open=R('tasks').filter(t=>['pendente','em andamento'].includes(t.status||'pendente')).length\n      const L=['Se sobrar espetinho, vocês sabem onde me encontrar 🍢👀','Lembrete importante: shibas também são convidados VIP 🐕✨','Será que rola um bolinho de patê pra mim? 🎂🐾',\n        'Eu cuido da portaria da festa. Só entra quem trouxer petisco 🦴','Tô treinando minha pose pro painel de fotos 📸','Balões: lindos. Balão estourando: meu pior pesadelo 🎈😱',\n        'Sabia que shiba sorri? Olha esse sorrisão 😁','*cheira o orçamento* hmm… cheirinho de festa boa 💸','Tô aqui no cantinho fingindo que não tô vendo vocês trabalharem 👀',\n        'Dica de shiba: bebe uma água aí 💧','Já pensaram na playlist? Eu voto em latido lo-fi 🎶','Se precisar de mim, é só chamar. Ou abrir um pacote de biscoito 🍪',\n        'Fato: festa com cachorro é 37% mais feliz. Fonte: eu 📊🐕',`Faltam ${days} dias e eu já tô abanando o rabo 🎂`,\n        `${G.length} convidados = ${G.length} pessoas pra me fazer carinho 🥹`,`Orçamento em ${pct}% do teto. Tô de olho, hein? 🧐`]\n      if(conf>2)L.push(`Já são ${conf} confirmados! Mais um e eu dou uma voltinha 🌀`)\n      if(duv)L.push(`Tem ${duv} convidados em dúvida… quer que eu decida no cara ou coroa? 🪙`)\n      if(!inv&&G.length)L.push('Psiu… ninguém foi convidado ainda. Bora mandar os convites? 💌')\n      if(open)L.push(`Tem ${open} task${open>1?'s':''} na fila do Claude. Ele é rápido, mas não mais que eu atrás de bolinha 🎾`)\n      if(me==='Katia')L.push('Katia, você vai arrasar nos 33! 💗','Aniversariante não trabalha! Deixa que eu e o Danilo cuidamos 😌')\n      if(me==='Danilo')L.push('Danilo, já falou hoje que a Katia é incrível? Fala aí 💗','Organizador do ano: Danilo 🏆 (patrocínio: Milo)')\n      if(h>=23||h<6)L.push('Zzz… sonhando com espetinho de queijo coalho 💤','Ainda acordado? Até eu já tô de pijama 🌙','Psiu, tá tarde… amanhã a gente continua? 😴')\n      else if(h<11)L.push('Bom dia! Já tomei meu café (era água) ☀️','Bom dia! Já levei vocês pra passear… ah não, é o contrário 🦮')\n      else if(h<14)L.push('Hora do almoço? Divide comigo? 🍽️🥺')\n      else if(h>=18)L.push('Fim de tarde é hora de passeio, só dizendo 🌇🦮')\n      if(dow===5)L.push('Sextou! Bora organizar a festa ou… só curtir? 🎉')\n      if(dow===1)L.push('Segunda-feira… até eu fico com preguiça 🥱')\n      if(dow===0||dow===6)L.push('Fim de semana bom tem passeio no parque, hein? 🌳')\n      if(days<=7)L.push('Falta só UMA semana!!! 🙀','Contagem final! Já tô escovando o pelo 🪮')\n      else if(days<=30)L.push('Menos de um mês! Contagem regressiva ativada ⏳')\n      const T={budget:['Escolhe o que tiver mais bacon… digo, mais custo-benefício 🥓','Cadê a cotação de petiscos? Esqueceram de mim? 🦴'],\n        guests:['Pode pôr meu nome na lista? Milo, nº 118 🐕','Conferindo a lista… cadê o nome do carteiro? (brincadeira, odeio o carteiro) 📮'],\n        chat:['Pode falar que eu anoto tudinho 📝','Prometo não comer as tasks 🙊'],art:['Me desenha de chapéu de festa? Por favor? 🥺🎨','Eu posaria pra um quadro, só dizendo 🖼️'],\n        summary:['Tá tudo indo bem! Eu acho. Sou um cachorro 🐕']}[tab]\n      if(T)L.push(...T,...T)\n      if(Math.random()<.06)return pick(['Psiu… segredo: toca 5 vezes no logo lá em cima 😉','Dica secreta: na tela de login, toca 5 vezes em mim 💗','Easter egg desbloqueado: você leu isso. Parabéns 🏅'])\n      return pick(L)}\n    let ct;const schedule=(first)=>{ct=setTimeout(tick,(first?90+Math.random()*90:180+Math.random()*300)*1000)}\n    const tick=()=>{if(!document.hidden&&!d2.state.note&&!showing&&!isQuiet())notify({text:chatter()});schedule()}\n    schedule(true);d2.onUnmount(()=>clearTimeout(ct))\n    d2.on('.milo','dblclick',()=>{const q=!isQuiet();try{localStorage.setItem(QUIET,q?'1':'0')}catch(e){}\n      queue.length=0;d2.state.note=null;showing=false;notify({text:q?'Tá bom, fico quietinho 🤐':'Voltei a tagarelar! 🐕💬',sub:q?'dois toques em mim pra eu voltar a falar (aviso de task continua aparecendo)':''})})\n    d2.on('.me','click',(e)=>{if(e.target.closest('.menu'))return;d2.state.menu=!d2.state.menu})\n    d2.on(document,'click',(e)=>{if(d2.state.menu&&!e.composedPath().some(n=>n.classList&&n.classList.contains('me')))d2.state.menu=false})\n    d2.on('.m-out','click',async()=>{const a=d2.auth(d2.param('auth'));try{await a.logout(a.session)}catch(e){}try{localStorage.removeItem('__data2-session-katia-party')}catch(e){}window.location.replace(window.location.pathname)})\n    d2.on('.m-pass','click',async()=>{\n      d2.state.menu=false\n      const email=who(d2)\n      if(!email)return toast('Não achei seu email 😕')\n      try{await d2.rush(d2.param('requestReset')).invoke({email});toast(`Link pra trocar a senha enviado pra ${email} ✉️`)}catch(e){toast('Ops, não consegui enviar agora.')}\n    })\n    // easter egg: 5 toques no logo = chuva de shibas\n    let n=0,tm\n    d2.on('.logo','click',()=>{n++;clearTimeout(tm);tm=setTimeout(()=>{n=0},1600);if(n<5)return;n=0\n      toast('au au au! 🐕🐕🐕')\n      for(let i=0;i<22;i++){const w=document.createElement('div');w.className='rain';w.innerHTML=shiba();w.style.left=(Math.random()*96)+'vw';w.style.animationDuration=(2.6+Math.random()*2.4)+'s';w.style.animationDelay=(Math.random()*1.4)+'s';d2.root.appendChild(w);setTimeout(()=>w.remove(),7000)}\n    })\n  },\n  updated(d2){const f=SCAN.get(d2.root);if(f)f()},\n}\n"}},"auth":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"auth"}}}},"requestReset":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"requestReset"}}}},"items":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"items"}}}},"quotes":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"quotes"}}}},"guests":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"guests"}}}},"messages":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"messages"}}}},"tasks":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tasks"}}}},"settings":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"settings"}}}},"artworks":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"artworks"}}}},"scribe":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"scribe"}}}},"artist":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"artist"}}}},"drive":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"drive"}}}},"vSummary":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"vSummary"}}}},"vBudget":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"vBudget"}}}},"vGuests":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"vGuests"}}}},"vChat":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"vChat"}}}},"vArt":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"vArt"}}}}}}}}}},{"_id":"6abefd25492457561460c69b","component":"data2-core-types@Component","system":"6abed5371a6b03943b9618d7","params":{"extends":"data2-core-primitives@Block","component":"kp-budget","package":"katia-party","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"// kp-budget — itens do orçamento + cotações (comparar, escolher ⭐, total vs teto ajustável)\n// params: items quotes settings (dataset), drive (service), uploader (rush → @upload-file), me (string)\nfunction esc(s){return String(s??'').replace(/[&<>\"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;'}[c]))}\nconst BRL=(n)=>new Intl.NumberFormat('pt-BR',{style:'currency',currency:'BRL',maximumFractionDigits:(Number(n)||0)%1?2:0}).format(Number(n)||0)\nconst num=(v)=>{let s=String(v??'').replace(/[^\\d,.-]/g,'');if(s.includes(','))s=s.replace(/\\./g,'').replace(',','.');const n=parseFloat(s);return isNaN(n)?0:n}\nconst recs=(d2,k)=>{const h=d2.data(k);return h?h.records()||[]:[]}\nconst toast=(d2,m)=>d2.bus.emit('kp:toast',m)\n// upload via Rush `upload-file` (o Drive recusa upload direto de usuário final). Imagens são reduzidas antes.\nasync function toB64(file){if(/^image\\/(png|jpe?g|webp)$/i.test(file.type||'')){try{const bmp=await createImageBitmap(file);const k=Math.min(1,1920/Math.max(bmp.width,bmp.height));const c=document.createElement('canvas');c.width=Math.round(bmp.width*k);c.height=Math.round(bmp.height*k);const g=c.getContext('2d');g.fillStyle='#fff';g.fillRect(0,0,c.width,c.height);g.drawImage(bmp,0,0,c.width,c.height);const du=c.toDataURL('image/jpeg',0.85);return {base64:du.split(',')[1],contentType:'image/jpeg',fileName:String(file.name||'foto').replace(/\\.[^.]+$/,'')+'.jpg'}}catch(e){}}\n  const du=await new Promise((res,rej)=>{const r=new FileReader();r.onload=()=>res(r.result);r.onerror=rej;r.readAsDataURL(file)});return {base64:String(du).split(',')[1],contentType:file.type||'application/octet-stream',fileName:file.name||'arquivo'}}\nasync function shrink(file){if(!/^image\\/(png|jpe?g|webp)$/i.test(file.type||''))return file;const p=await toB64(file);if(p.contentType!=='image/jpeg')return file;const bin=atob(p.base64),u8=new Uint8Array(bin.length);for(let i=0;i<bin.length;i++)u8[i]=bin.charCodeAt(i);return new File([u8],p.fileName,{type:'image/jpeg'})}\n// 1º upload direto no Drive (presigned S3, sem limite prático; liberado pela DrivePolicy upload). 2º fallback: Rush (até ~1 MB, limite da Lambda).\nasync function uploadAll(d2,files){const out=[];for(const f0 of files){if(f0.size>25e6)throw new Error(`${f0.name}: muito grande (máx. 25 MB)`);const f=await shrink(f0);let url=''\n  try{const up=await d2.drive(d2.param('drive')).upload([f]);const u=up&&up[0];url=(u&&(u.fileUrl||u.url))||''}catch(e){}\n  if(!url&&f.size<9e5){const p=await toB64(f);const r=await d2.rush('upload-file').invoke(p);const d=r&&r.data?r.data:r;url=(d&&d.url)||''}\n  if(!url)throw new Error(`${f0.name}: não consegui enviar`)\n  out.push({url,name:f0.name||f.name,type:f.type})}return out}\nconst STATUS={pendente:['c-pend','sem cotação'],cotando:['c-cot','cotando'],fechado:['c-ok','fechado']}\nconst GLYPHS=['🍽️','⛺','🎂','🪑','🎈','🧁','📸','🧵','🎶','🌸','🍰','🥂','🍹','💡','🎁','🚐','🧑‍🍳','🪅','🕯️','🧊','🎤','👗','💐','✨']\n\nexport default {\n  css:`\n:host{--bg:#FFF7F5;--card:#FFFFFF;--blush-50:#FFF1F2;--blush-100:#FDE4E7;--blush-200:#F9CDD4;--blush-300:#F2AEBA;--rose:#D9879A;--rose-deep:#B8647A;--ink:#4A3439;--muted:#94797E;--line:#F3DDE0;--peach:#FDE3D3;--sage:#DCEBDD;--sage-ink:#4F7A57;--butter:#FFF2C9;--butter-ink:#8A6D1F;--lilac:#ECE3F6;--lilac-ink:#6B5390;--shadow:0 6px 24px rgba(184,100,122,.12)}\n*{box-sizing:border-box}\n.wrap{height:100%;overflow:auto;padding:28px clamp(16px,3vw,40px) 90px;font-family:'Nunito',system-ui,sans-serif;color:var(--ink)}\n.inner{max-width:1120px;margin:0 auto;display:grid;gap:18px}\n.head{display:flex;align-items:flex-end;gap:12px;flex-wrap:wrap}\n.head h2{font:600 30px/1 'Fredoka';margin:0;flex:1;min-width:200px}\n.head p{margin:6px 0 0;color:var(--muted);font-weight:700;font-size:14px}\n.btn{border:0;border-radius:14px;padding:11px 16px;font:600 15px 'Fredoka';cursor:pointer;background:linear-gradient(135deg,#E79AAB,#D9879A);color:#fff;box-shadow:0 6px 16px rgba(217,135,154,.3);white-space:nowrap}\n.btn:active{transform:scale(.97)}.btn[disabled]{opacity:.55}\n.ghost{border:1.5px solid var(--line);background:#fff;color:var(--ink);box-shadow:none}\n.ghost:hover{border-color:var(--blush-300)}\n.danger{background:#fff;color:#B4475F;border:1.5px solid #F5C9D2;box-shadow:none}\n.sm{padding:7px 11px;font-size:13px;border-radius:11px}\n.sum{display:grid;grid-template-columns:1.4fr 1fr 1fr;gap:14px;background:var(--card);border:1px solid var(--line);border-radius:24px;padding:20px 22px;box-shadow:var(--shadow)}\n.sum .k{font-weight:800;font-size:12px;letter-spacing:.4px;text-transform:uppercase;color:var(--muted)}\n.sum .v{font:600 30px/1.1 'Fredoka';margin-top:6px}\n.sum .v small{font:700 15px 'Nunito';color:var(--muted)}\n.cap{cursor:pointer;border-bottom:1.5px dashed var(--blush-300)}\n.capin{width:140px;border:1.5px solid var(--blush-300);border-radius:10px;padding:4px 8px;font:700 15px 'Nunito';color:var(--ink)}\n.bar{height:12px;border-radius:999px;background:var(--blush-50);overflow:hidden;margin-top:12px;position:relative}\n.bar i{position:absolute;left:0;top:0;bottom:0;border-radius:999px;background:linear-gradient(90deg,#F2AEBA,#D9879A);transition:width .5s}\n.bar i.proj{background:repeating-linear-gradient(45deg,#FDE4E7 0 6px,#F9CDD4 6px 12px);transition:width .5s}\n.bar i.warn{background:linear-gradient(90deg,#F7C59F,#E8956B)}.bar i.over{background:linear-gradient(90deg,#EE9AA5,#C9506B)}\n.legend{display:flex;gap:14px;margin-top:8px;font-size:12px;font-weight:700;color:var(--muted);flex-wrap:wrap}\n.legend span:before{content:'';display:inline-block;width:10px;height:10px;border-radius:3px;margin-right:5px;vertical-align:-1px;background:#D9879A}\n.legend span.p:before{background:#F9CDD4}\n.filters{display:flex;gap:8px;flex-wrap:wrap}\n.f{border:1.5px solid var(--line);background:#fff;border-radius:999px;padding:7px 13px;font:700 13px 'Nunito';color:var(--ink);cursor:pointer}\n.f[data-on]{background:var(--blush-100);border-color:var(--blush-300);color:var(--rose-deep)}\n.list{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px}\n.item{background:var(--card);border:1px solid var(--line);border-radius:22px;padding:16px;box-shadow:var(--shadow);cursor:pointer;display:grid;grid-template-columns:auto 1fr;gap:12px;align-items:center;transition:transform .15s,box-shadow .15s}\n.item:hover{transform:translateY(-2px);box-shadow:0 12px 30px rgba(184,100,122,.18)}\n.em{width:48px;height:48px;border-radius:16px;background:var(--blush-50);display:grid;place-items:center;font-size:24px}\n.item .n{font:600 17px/1.2 'Fredoka';margin-bottom:5px}\n.item .d{font-size:13px;color:var(--muted);font-weight:700}\n.item .d b{color:var(--ink)}\n.chip{display:inline-block;font-weight:800;font-size:11px;border-radius:999px;padding:3px 9px;white-space:nowrap;margin-bottom:6px}\n.c-pend{background:var(--blush-100);color:var(--rose-deep)}.c-cot{background:var(--butter);color:var(--butter-ink)}.c-ok{background:var(--sage);color:var(--sage-ink)}.c-free{background:var(--lilac);color:var(--lilac-ink)}\n.card{background:var(--card);border:1px solid var(--line);border-radius:24px;padding:20px;box-shadow:var(--shadow)}\n.back{display:inline-flex;align-items:center;gap:6px;font:700 14px 'Nunito';color:var(--rose-deep);cursor:pointer;border:0;background:none;padding:0}\n.dh{display:grid;grid-template-columns:auto 1fr auto;gap:14px;align-items:center}\n.dh .em{width:64px;height:64px;font-size:32px;border-radius:20px;cursor:pointer}\n.dh h2{font:600 26px/1.15 'Fredoka';margin:0}\n.dh .meta{color:var(--muted);font-weight:700;font-size:13px;margin-top:4px}\n.glyphs{display:flex;flex-wrap:wrap;gap:6px;margin-top:12px}\n.glyphs button{width:40px;height:40px;border-radius:12px;border:1px solid var(--line);background:#fff;font-size:20px;cursor:pointer}\n.quotes{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px}\n.q{position:relative;background:var(--card);border:1.5px solid var(--line);border-radius:22px;padding:18px;display:flex;flex-direction:column;gap:6px;box-shadow:var(--shadow);min-width:0}\n.q[data-chosen]{border-color:#E7A2B1;background:linear-gradient(180deg,#FFF5F6,#fff);box-shadow:0 12px 34px rgba(217,135,154,.28)}\n.q .ven{font:600 18px 'Fredoka';padding-right:70px;word-break:break-word}\n.q .pr{font:600 28px 'Fredoka';color:var(--rose-deep)}\n.q .ln{font-size:13px;font-weight:700;color:var(--muted);word-break:break-word}\n.q .ln a{color:var(--rose-deep)}\n.q .tags{position:absolute;top:14px;right:14px;display:flex;flex-direction:column;align-items:flex-end;gap:4px}\n.q .tag{font-weight:800;font-size:11px;border-radius:999px;padding:3px 8px;background:var(--sage);color:var(--sage-ink)}\n.q .tag.star{background:#FBD3DB;color:#8E4258}\n.q .cmp{height:8px;border-radius:999px;background:var(--blush-50);overflow:hidden;margin:4px 0}\n.q .cmp i{display:block;height:100%;background:var(--blush-300);border-radius:999px}\n.q .acts{display:flex;gap:6px;flex-wrap:wrap;margin-top:auto;padding-top:8px}\n.files{display:flex;gap:6px;flex-wrap:wrap}\n.files a{font-size:12px;font-weight:800;color:var(--lilac-ink);background:var(--lilac);border-radius:8px;padding:3px 8px;text-decoration:none;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\nform.qf{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}\nform.qf .full{grid-column:1/-1}\nlabel{display:block;font-weight:800;font-size:12px;color:var(--muted);margin-bottom:4px}\ninput,textarea,select{width:100%;border:1.5px solid var(--line);background:var(--blush-50);border-radius:12px;padding:10px 12px;font:600 14px 'Nunito';color:var(--ink);outline:none}\ninput:focus,textarea:focus,select:focus{border-color:var(--blush-300);background:#fff}\ntextarea{resize:vertical;min-height:70px}\n.row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}\n.sect{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}\n.sect h3{font:600 20px 'Fredoka';margin:0}\n.empty{text-align:center;color:var(--muted);font-weight:700;padding:26px 10px;border:2px dashed var(--line);border-radius:22px;background:#fff}\n.empty .z{font-size:34px;display:block;margin-bottom:6px}\n.switch{display:flex;align-items:center;gap:8px;font-weight:800;font-size:13px;cursor:pointer;user-select:none}\n.switch input{width:auto}\n.notes{width:100%}\n@media (max-width:760px){.sum{grid-template-columns:1fr 1fr}.sum>div:first-child{grid-column:1/-1}form.qf{grid-template-columns:1fr}.dh{grid-template-columns:auto 1fr}.dh .acts{grid-column:1/-1}.wrap{padding-top:18px}.head h2{font-size:26px}}\n`,\n  render(d2){\n    const s=d2.state\n    const items=recs(d2,'items').slice().sort((a,b)=>(a.sort??999)-(b.sort??999))\n    const quotes=recs(d2,'quotes')\n    const settings=recs(d2,'settings'),setRec=settings.find(r=>r.key==='party')||{}\n    const cap=Number((setRec.value||{}).budgetCap)||15000\n    const byItem={};for(const q of quotes){(byItem[q.itemId]=byItem[q.itemId]||[]).push(q)}\n    const statusOf=(it)=>{const qs=byItem[it._id]||[];return it.free||qs.some(q=>q.chosen)?'fechado':qs.length?'cotando':'pendente'}\n    let chosen=0,proj=0,closed=0\n    for(const it of items){const qs=byItem[it._id]||[];const c=qs.find(q=>q.chosen)\n      if(c){chosen+=num(c.price);proj+=num(c.price);closed++}else if(it.free)closed++;else if(qs.length)proj+=Math.min(...qs.map(q=>num(q.price)))}\n    const pct=cap?Math.min(100,chosen/cap*100):0,ppct=cap?Math.min(100,proj/cap*100):0\n    const cls=chosen>cap?'over':pct>=85?'warn':''\n    const left=cap-chosen\n    const open=s.open&&items.find(i=>i._id===s.open)\n\n    if(open){\n      const it=open,qs=(byItem[it._id]||[]).slice().sort((a,b)=>num(a.price)-num(b.price))\n      const max=Math.max(1,...qs.map(q=>num(q.price))),min=qs.length?num(qs[0].price):0\n      const st=statusOf(it)\n      const form=(q)=>`<form class=\"qf card\" data-id=\"${esc(q?q._id:'')}\">\n          <div class=\"full sect\"><h3>${q?'Editar cotação':'Nova cotação'}</h3></div>\n          <div><label>Fornecedor</label><input name=\"vendor\" value=\"${esc(q?q.vendor:'')}\" placeholder=\"Ex.: Buffet da Dona Maria\" required/></div>\n          <div><label>Valor (R$)</label><input name=\"price\" inputmode=\"decimal\" value=\"${q?esc(String(q.price??'').replace('.',',')):''}\" placeholder=\"3.500,00\" required/></div>\n          <div><label>Contato</label><input name=\"contact\" value=\"${esc(q?q.contact:'')}\" placeholder=\"(11) 9…  /  @insta\"/></div>\n          <div><label>Link</label><input name=\"link\" value=\"${esc(q?q.link:'')}\" placeholder=\"https://…\"/></div>\n          <div class=\"full\"><label>Observações (o que inclui, prazos, condições…)</label><textarea name=\"notes\">${esc(q?q.notes:'')}</textarea></div>\n          <div class=\"full\"><label>Anexos (PDF, print, foto)</label><input name=\"files\" type=\"file\" multiple accept=\"image/*,application/pdf\"/></div>\n          <div class=\"full row\"><button class=\"btn\" type=\"submit\" ${s.busy?'disabled':''}>${s.busy?'Salvando…':'Salvar cotação'}</button><button class=\"btn ghost cancel-q\" type=\"button\">Cancelar</button></div>\n        </form>`\n      return `<div class=\"wrap\"><div class=\"inner\">\n        <button class=\"back\" type=\"button\">← Todos os itens</button>\n        <div class=\"card\"><div class=\"dh\">\n          <div class=\"em pick-glyph\" title=\"Trocar emoji\">${esc(it.glyph||'✨')}</div>\n          <div><h2>${esc(it.name)}</h2><div class=\"meta\"><span class=\"chip ${it.free?'c-free':STATUS[st][0]}\">${it.free?'grátis 💜':STATUS[st][1]}</span> ${qs.length} cotaç${qs.length===1?'ão':'ões'}${qs.length>1?` · de ${BRL(min)} a ${BRL(max)}`:''}</div></div>\n          <div class=\"row acts\"><button class=\"btn ghost sm rename\">✏️ Renomear</button><button class=\"btn danger sm del-item\">Excluir</button></div>\n        </div>\n        ${s.glyphs?`<div class=\"glyphs\">${GLYPHS.map(g=>`<button type=\"button\" class=\"g\" data-g=\"${g}\">${g}</button>`).join('')}</div>`:''}\n        <div style=\"margin-top:14px\" class=\"row\"><label class=\"switch\"><input type=\"checkbox\" class=\"free\" ${it.free?'checked':''}/> Item gratuito / já resolvido sem custo</label></div>\n        <div style=\"margin-top:12px\"><label>Anotações do item</label><textarea class=\"notes\" data-id=\"${esc(it._id)}\" placeholder=\"Ideias, requisitos, quantidade de pessoas…\">${esc(it.notes||'')}</textarea></div>\n        </div>\n        <div class=\"sect\"><h3>Cotações</h3>${s.editing?'':'<button class=\"btn new-q\">+ Cotação</button>'}</div>\n        ${s.editing==='new'?form(null):''}\n        ${qs.length?`<div class=\"quotes\">${qs.map((q,i)=>s.editing===q._id?form(q):`\n          <div class=\"q\" data-key=\"${esc(q._id||'p'+i)}\" ${q.chosen?'data-chosen':''}>\n            <div class=\"tags\">${q.chosen?'<span class=\"tag star\">⭐ escolhida</span>':''}${qs.length>1&&num(q.price)===min?'<span class=\"tag\">mais barata</span>':''}</div>\n            <div class=\"ven\">${esc(q.vendor||'Sem nome')}</div>\n            <div class=\"pr\">${BRL(q.price)}</div>\n            ${qs.length>1?`<div class=\"cmp\"><i style=\"width:${Math.round(num(q.price)/max*100)}%\"></i></div>`:''}\n            ${q.contact?`<div class=\"ln\">📞 ${esc(q.contact)}</div>`:''}\n            ${q.link?`<div class=\"ln\">🔗 <a href=\"${esc(q.link)}\" target=\"_blank\" rel=\"noopener\">${esc(q.link.replace(/^https?:\\/\\//,'').slice(0,40))}</a></div>`:''}\n            ${q.notes?`<div class=\"ln\" style=\"white-space:pre-wrap\">${esc(q.notes)}</div>`:''}\n            ${(q.attachments||[]).length?`<div class=\"files\">${q.attachments.map(a=>`<a href=\"${esc(a.url)}\" target=\"_blank\" rel=\"noopener\">📎 ${esc(a.name||'arquivo')}</a>`).join('')}</div>`:''}\n            <div class=\"acts\">\n              <button class=\"btn sm ${q.chosen?'ghost':''} choose\" data-id=\"${esc(q._id)}\">${q.chosen?'Desmarcar':'⭐ Escolher'}</button>\n              <button class=\"btn ghost sm edit-q\" data-id=\"${esc(q._id)}\">Editar</button>\n              <button class=\"btn danger sm del-q\" data-id=\"${esc(q._id)}\">Excluir</button>\n            </div>\n          </div>`).join('')}</div>`:(s.editing?'':`<div class=\"empty\"><span class=\"z\">🐕💤</span>Nenhuma cotação ainda. Adicione aqui ou mande pro Milo no chat!</div>`)}\n      </div></div>`\n    }\n\n    const f=s.filter||'todos'\n    const shown=items.filter(it=>f==='todos'||statusOf(it)===f)\n    const counts={todos:items.length,pendente:0,cotando:0,fechado:0};for(const it of items)counts[statusOf(it)]++\n    return `<div class=\"wrap\"><div class=\"inner\">\n      <div class=\"head\"><div style=\"flex:1;min-width:200px\"><h2>Orçamento 💸</h2><p>Lance os itens, registre as cotações e marque a ⭐ escolhida.</p></div><button class=\"btn new-item\">+ Item</button></div>\n      <div class=\"sum\">\n        <div><div class=\"k\">Total escolhido</div>\n          <div class=\"v\">${BRL(chosen)} <small>de ${s.capEdit?`<input class=\"capin\" inputmode=\"decimal\" value=\"${esc(String(cap))}\"/>`:`<span class=\"cap\" title=\"Clique para ajustar o teto\">${BRL(cap)}</span>`}</small></div>\n          <div class=\"bar\"><i class=\"proj\" style=\"width:${ppct}%\"></i><i class=\"${cls}\" style=\"width:${pct}%\"></i></div>\n          <div class=\"legend\"><span>escolhido</span><span class=\"p\">projeção (escolhidas + mais baratas)</span></div></div>\n        <div><div class=\"k\">${left>=0?'Ainda cabe':'Estourou'}</div><div class=\"v\" style=\"color:${left>=0?'var(--sage-ink)':'#B4475F'}\">${BRL(Math.abs(left))}</div></div>\n        <div><div class=\"k\">Projeção</div><div class=\"v\">${BRL(proj)}</div><div class=\"legend\" style=\"margin-top:4px\">${closed}/${items.length} itens fechados</div></div>\n      </div>\n      ${s.newItem?`<form class=\"ni card row\"><input name=\"name\" placeholder=\"Nome do item (ex.: Fotógrafo)\" required style=\"flex:1;min-width:180px\"/><button class=\"btn\" type=\"submit\">Adicionar</button><button class=\"btn ghost cancel-ni\" type=\"button\">Cancelar</button></form>`:''}\n      <div class=\"filters\">${[['todos','Todos'],['pendente','Sem cotação'],['cotando','Cotando'],['fechado','Fechados']].map(([k,l])=>`<button class=\"f\" data-f=\"${k}\" ${f===k?'data-on':''}>${l} · ${counts[k]}</button>`).join('')}</div>\n      ${shown.length?`<div class=\"list\">${shown.map((it,i)=>{const qs=byItem[it._id]||[],c=qs.find(q=>q.chosen),st=statusOf(it)\n        const mn=qs.length?Math.min(...qs.map(q=>num(q.price))):0,mx=qs.length?Math.max(...qs.map(q=>num(q.price))):0\n        return `<div class=\"item\" data-key=\"${esc(it._id||'p'+i)}\" data-id=\"${esc(it._id)}\"><div class=\"em\">${esc(it.glyph||'✨')}</div><div style=\"min-width:0\">\n          <span class=\"chip ${it.free?'c-free':STATUS[st][0]}\">${it.free?'grátis 💜':STATUS[st][1]}</span>\n          <div class=\"n\">${esc(it.name)}</div>\n          <div class=\"d\">${c?`⭐ ${esc(c.vendor||'')} · <b>${BRL(c.price)}</b>`:it.free?'Sem custo 🎉':qs.length?`${qs.length} cotaç${qs.length>1?'ões':'ão'} · <b>${qs.length>1?BRL(mn)+' – '+BRL(mx):BRL(mn)}</b>`:'Nenhuma cotação ainda'}</div></div></div>`}).join('')}</div>`\n        :`<div class=\"empty\"><span class=\"z\">🐕💤</span>Nada por aqui nesse filtro.</div>`}\n    </div></div>`\n  },\n  mounted(d2){\n    const s=d2.state\n    const I=()=>d2.data('items'),Q=()=>d2.data('quotes'),S=()=>d2.data('settings')\n    const pend=d2.shared.get('kp-open-item',null,{global:true});if(pend){s.open=pend;d2.shared.set('kp-open-item',null,{global:true})}\n    const openRec=()=>I().records().find(i=>i._id===s.open)\n    const saveItem=async(patch)=>{const it=openRec();if(!it)return;await I().update({...it,...patch})}\n    d2.on('.item','click',(e,el)=>d2.setState({open:el.dataset.id,editing:null,glyphs:false}))\n    d2.on('.back','click',()=>d2.setState({open:null,editing:null,glyphs:false}))\n    d2.on('.f','click',(e,el)=>{s.filter=el.dataset.f})\n    d2.on('.new-item','click',()=>{s.newItem=true;setTimeout(()=>{const i=d2.$('form.ni input');i&&i.focus()},30)})\n    d2.on('.cancel-ni','click',()=>{s.newItem=false})\n    d2.on('.cap','click',()=>{s.capEdit=true;setTimeout(()=>{const i=d2.$('.capin');i&&(i.focus(),i.select())},30)})\n    const saveCap=async()=>{const el=d2.$('.capin');if(!el)return;const v=num(el.value);s.capEdit=false;if(!v)return\n      const rec=S().records().find(r=>r.key==='party');if(rec)await S().update({...rec,value:{...(rec.value||{}),budgetCap:v}});else await S().create({key:'party',value:{budgetCap:v}})\n      toast(d2,`Teto ajustado pra ${BRL(v)} 💗`)}\n    d2.on('.capin','keydown',(e)=>{if(e.key==='Enter')saveCap();if(e.key==='Escape')s.capEdit=false})\n    d2.on('.capin','blur',()=>saveCap())\n    d2.on('.pick-glyph','click',()=>{s.glyphs=!s.glyphs})\n    d2.on('.g','click',async(e,el)=>{s.glyphs=false;await saveItem({glyph:el.dataset.g})})\n    d2.on('.rename','click',async()=>{const it=openRec();if(!it)return;const n=await d2.dialog.prompt('Novo nome do item',it.name);if(n&&n.trim())await saveItem({name:n.trim()})})\n    d2.on('.free','change',async(e,el)=>{await saveItem({free:el.checked,status:el.checked?'fechado':'pendente'});if(el.checked)toast(d2,'Item marcado como gratuito 💜')})\n    d2.on('.notes','change',async(e,el)=>{await saveItem({notes:el.value});toast(d2,'Anotação salva ✍️')})\n    d2.on('.del-item','click',async()=>{const it=openRec();if(!it)return\n      if(!await d2.dialog.confirm(`Excluir \"${it.name}\" e todas as cotações dele?`))return\n      for(const q of Q().records().filter(q=>q.itemId===it._id))await Q().remove(q)\n      await I().remove(it);d2.setState({open:null});toast(d2,'Item excluído')})\n    d2.on('.new-q','click',()=>{s.editing='new'})\n    d2.on('.edit-q','click',(e,el)=>{s.editing=el.dataset.id})\n    d2.on('.cancel-q','click',()=>{s.editing=null})\n    d2.on('.del-q','click',async(e,el)=>{const q=Q().records().find(r=>r._id===el.dataset.id);if(!q)return\n      if(!await d2.dialog.confirm(`Excluir a cotação de \"${q.vendor||'sem nome'}\"?`))return\n      await Q().remove(q);toast(d2,'Cotação excluída')})\n    d2.on('.choose','click',async(e,el)=>{const id=el.dataset.id;const all=Q().records().filter(q=>q.itemId===s.open)\n      const target=all.find(q=>q._id===id);if(!target)return\n      const on=!target.chosen\n      for(const q of all){const want=on&&q._id===id;if(!!q.chosen!==want)await Q().update({...q,chosen:want})}\n      await saveItem({status:on?'fechado':'cotando'})\n      toast(d2,on?`⭐ ${target.vendor||'Cotação'} escolhida! ${BRL(target.price)}`:'Escolha desfeita')})\n    d2.on('form','submit',async(e,form)=>{e.preventDefault()\n      if(form.classList.contains('ni')){const name=new FormData(form).get('name');if(!String(name).trim())return\n        const max=Math.max(0,...I().records().map(i=>Number(i.sort)||0))\n        s.newItem=false;await I().create({name:String(name).trim(),glyph:'✨',status:'pendente',sort:max+1});toast(d2,'Item criado ✨');return}\n      if(!form.classList.contains('qf'))return\n      const fd=new FormData(form);const id=form.dataset.id\n      s.busy=true\n      try{\n        let attachments=[]\n        const files=form.querySelector('input[type=file]').files\n        if(files&&files.length){try{attachments=await uploadAll(d2,[...files])}catch(e){attachments=[]}\n          if(!attachments.length)toast(d2,'Os anexos não subiram 😕 salvei a cotação sem eles')}\n        const data={itemId:s.open,vendor:String(fd.get('vendor')||'').trim(),price:num(fd.get('price')),contact:String(fd.get('contact')||'').trim(),link:String(fd.get('link')||'').trim(),notes:String(fd.get('notes')||'').trim()}\n        if(id){const q=Q().records().find(r=>r._id===id);await Q().update({...q,...data,attachments:[...((q&&q.attachments)||[]),...attachments]})}\n        else{await Q().create({...data,chosen:false,attachments});const it=openRec();if(it&&!it.free&&it.status==='pendente')await saveItem({status:'cotando'})}\n        d2.setState({editing:null});toast(d2,'Cotação salva 💸')\n      }catch(err){toast(d2,'Não consegui salvar 😕 tenta de novo?')}\n      finally{s.busy=false}\n    })\n  },\n}\n"}},"items":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"items"}}}},"quotes":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"quotes"}}}},"settings":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"settings"}}}},"drive":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"drive"}}}},"me":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"me"}}}}}}}}}},{"_id":"6abefd26ba309d7a9fad110b","component":"data2-core-types@Component","system":"6abed5371a6b03943b9618d7","params":{"extends":"data2-core-primitives@Block","component":"kp-guests","package":"katia-party","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"// kp-guests — lista de convidados: lista corrida ordenada pelo nº (ou A–Z), adultos/crianças,\n// status (toque pra alternar), busca, filtro \"incertos\" com edição rápida do nome, colar lista.\n// params: guests settings (dataset), me (string)\nfunction esc(s){return String(s??'').replace(/[&<>\"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;'}[c]))}\nconst recs=(d2,k)=>{const h=d2.data(k);return h?h.records()||[]:[]}\nconst toast=(d2,m)=>d2.bus.emit('kp:toast',m)\nconst ST=['em dúvida','a convidar','convidado','confirmado','não vem']\nconst GROUPS=['Família','Amigos','Salão','Extra']\nconst GC={'Família':'#F7C59F','Amigos':'#B9D8BF','Salão':'#CDB8EA','Extra':'#F2AEBA'}\nconst STC={'em dúvida':'c-duv','a convidar':'c-pend','convidado':'c-lil','confirmado':'c-ok','não vem':'c-no'}\nconst ppl=()=>1 // cada convidado = 1 pessoa (convite individual)\nconst UNC=/\\s*·?\\s*\\((sobrenome com )?leitura incerta\\)/i\nconst isUnc=(g)=>UNC.test(String(g.notes||''))\nconst numFromNotes=(g)=>{const m=String(g.notes||'').match(/Lista nº\\s*(\\d+)/i);return m?Number(m[1]):null}\nconst numOf=(g)=>Number(g.num)||numFromNotes(g)||null\nconst cleanNotes=(n)=>String(n||'').replace(UNC,'').trim()\n// convite individual: token aleatório por convidado → https://convite.katia-party.next.data2.app/?c=TOKEN\nconst INVITE='https://convite.katia-party.next.data2.app/?c='\nconst tok=()=>{const A='abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789',a=new Uint8Array(14);crypto.getRandomValues(a);return Array.from(a,b=>A[b%A.length]).join('')}\nconst firstName=(n)=>String(n||'').split(' (')[0].trim()\nfunction inviteMsg(g,p){p=p||{};return `Oi, ${firstName(g.name)}! 💗\n\nA Katia vai fazer 33 anos e a gente quer muito você lá! 🎂\n\n📅 ${p.dateLabel||'Domingo, 15 de novembro'}\n🕛 ${p.time||'Perto do almoço (horário a confirmar)'}\n📍 ${p.place||'Sítio Recanto dos Lagos'}, ${p.city||'Mogi das Cruzes - SP'}\n\nÉ num sítio: vem de calçado confortável pra terra e pedra 👟, traz roupa de banho (tem piscina! 👙) e protetor solar/repelente 🧴\n\nConfirma sua presença até ${p.rsvpDeadlineLabel||'20/10'} pelo seu convite:\n${INVITE}${g.rsvpToken}\n\nBeijos, Katia e Danilo 💗 (e o Milo 🐕)`}\n\nexport default {\n  css:`\n:host{--bg:#FFF7F5;--card:#FFFFFF;--blush-50:#FFF1F2;--blush-100:#FDE4E7;--blush-200:#F9CDD4;--blush-300:#F2AEBA;--rose:#D9879A;--rose-deep:#B8647A;--ink:#4A3439;--muted:#94797E;--line:#F3DDE0;--peach:#FDE3D3;--sage:#DCEBDD;--sage-ink:#4F7A57;--butter:#FFF2C9;--butter-ink:#8A6D1F;--lilac:#ECE3F6;--lilac-ink:#6B5390;--shadow:0 6px 24px rgba(184,100,122,.12)}\n*{box-sizing:border-box}\n.wrap{height:100%;overflow:auto;padding:28px clamp(16px,3vw,40px) 90px;font-family:'Nunito',system-ui,sans-serif;color:var(--ink)}\n.inner{max-width:1120px;margin:0 auto;display:grid;gap:16px}\n.head{display:flex;align-items:flex-end;gap:10px;flex-wrap:wrap}\n.head h2{font:600 30px/1 'Fredoka';margin:0}\n.head p{margin:6px 0 0;color:var(--muted);font-weight:700;font-size:14px}\n.btn{border:0;border-radius:14px;padding:11px 16px;font:600 15px 'Fredoka';cursor:pointer;background:linear-gradient(135deg,#E79AAB,#D9879A);color:#fff;box-shadow:0 6px 16px rgba(217,135,154,.3);white-space:nowrap}\n.btn:active{transform:scale(.97)}.btn[disabled]{opacity:.55}\n.ghost{border:1.5px solid var(--line);background:#fff;color:var(--ink);box-shadow:none}\n.danger{background:#fff;color:#B4475F;border:1.5px solid #F5C9D2;box-shadow:none}\n.sm{padding:7px 11px;font-size:13px;border-radius:11px}\n.stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}\n.st{background:var(--card);border:1px solid var(--line);border-radius:20px;padding:14px 16px;box-shadow:var(--shadow)}\n.st .k{font-weight:800;font-size:11px;letter-spacing:.4px;text-transform:uppercase;color:var(--muted)}\n.st .v{font:600 28px/1.1 'Fredoka';margin-top:4px}\n.st .h{font-size:12px;font-weight:700;color:var(--muted)}\n.tools{display:flex;gap:8px;flex-wrap:wrap;align-items:center}\n.search{flex:1;min-width:200px}\ninput,textarea,select{width:100%;border:1.5px solid var(--line);background:#fff;border-radius:12px;padding:10px 12px;font:600 14px 'Nunito';color:var(--ink);outline:none}\ninput:focus,textarea:focus,select:focus{border-color:var(--blush-300)}\n.f{border:1.5px solid var(--line);background:#fff;border-radius:999px;padding:7px 12px;font:700 13px 'Nunito';color:var(--ink);cursor:pointer;white-space:nowrap}\n.f[data-on]{background:var(--blush-100);border-color:var(--blush-300);color:var(--rose-deep)}\n.f.warn[data-on]{background:var(--butter);border-color:#EED48A;color:var(--butter-ink)}\n.seg{display:inline-flex;border:1.5px solid var(--line);border-radius:999px;overflow:hidden;background:#fff}\n.seg button{border:0;background:none;padding:7px 12px;font:700 13px 'Nunito';cursor:pointer;color:var(--ink)}\n.seg button[data-on]{background:var(--blush-100);color:var(--rose-deep)}\n.list{background:var(--card);border:1px solid var(--line);border-radius:22px;box-shadow:var(--shadow);overflow:hidden}\n.g{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;gap:12px;align-items:center;padding:11px 16px;border-top:1px solid var(--line)}\n.g:first-child{border-top:0}\n.num{min-width:40px;height:40px;padding:0 6px;border-radius:12px;display:grid;place-items:center;font:600 14px 'Fredoka';color:var(--rose-deep);background:var(--blush-50);border:1px solid var(--line)}\n.g.unc .num{background:var(--butter);color:var(--butter-ink);border-color:#EED48A}\n.g .n{font-weight:800;font-size:15px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.g .m{font-size:12px;font-weight:700;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.g .m a{color:var(--sage-ink);text-decoration:none}\n.g .m .w{color:var(--butter-ink)}\n.chip{border:0;font:800 12px 'Nunito';border-radius:999px;padding:6px 11px;white-space:nowrap;cursor:pointer}\n.c-pend{background:var(--blush-100);color:var(--rose-deep)}.c-lil{background:var(--lilac);color:var(--lilac-ink)}.c-ok{background:var(--sage);color:var(--sage-ink)}.c-no{background:#EFE7E8;color:#8C7377}.c-duv{background:var(--butter);color:var(--butter-ink)}.chips{display:flex;gap:6px;align-items:center}.gchip{border:1.5px solid var(--line);background:#fff;font:800 12px 'Nunito';border-radius:999px;padding:5px 10px;cursor:pointer;color:var(--ink);white-space:nowrap}.gchip i{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:5px}.gchip.none{border-style:dashed;color:var(--muted)}.gtag{font-weight:800;color:var(--rose-deep)}\n.ed{border:0;background:none;cursor:pointer;font-size:16px;padding:6px;border-radius:10px}\n.ed:hover{background:var(--blush-50)}\n.acts{display:flex;gap:2px;align-items:center}.wa,.lk{border:0;background:none;cursor:pointer;font-size:16px;padding:6px;border-radius:10px}.wa:hover,.lk:hover{background:var(--blush-50)}\n.g .m .rs{color:var(--sage-ink)}\n.fix{display:flex;gap:6px;align-items:center;min-width:0}\n.fix input{padding:8px 10px;font-size:15px;font-weight:800;background:var(--butter);border-color:#EED48A}\n.fix .ok{border:0;border-radius:10px;padding:8px 12px;font:700 13px 'Nunito';cursor:pointer;background:var(--sage);color:var(--sage-ink);white-space:nowrap}\n.tip{font-size:12px;font-weight:700;color:var(--muted)}\n.banner{background:var(--butter);color:var(--butter-ink);border-radius:16px;padding:10px 14px;font-weight:700;font-size:13px}\nform.gf{display:grid;grid-template-columns:.6fr 2fr 1.4fr;gap:10px;background:var(--card);border:1px solid var(--line);border-radius:22px;padding:16px;box-shadow:var(--shadow)}\nform.gf .full{grid-column:1/-1}\nform.gf .half{grid-column:span 2}\nlabel{display:block;font-weight:800;font-size:12px;color:var(--muted);margin-bottom:4px}\n.row{display:flex;gap:8px;flex-wrap:wrap;align-items:center}\n.paste{background:var(--card);border:1px solid var(--line);border-radius:22px;padding:16px;box-shadow:var(--shadow);display:grid;gap:10px}\n.paste textarea{min-height:140px;font-family:ui-monospace,Menlo,monospace;font-size:13px}\n.empty{text-align:center;color:var(--muted);font-weight:700;padding:30px 10px;border:2px dashed var(--line);border-radius:22px;background:#fff}\n.empty .z{font-size:36px;display:block;margin-bottom:6px}\n@media (max-width:760px){.stats{grid-template-columns:1fr 1fr}form.gf{grid-template-columns:1fr 1fr}form.gf .wide{grid-column:1/-1}.g{grid-template-columns:auto minmax(0,1fr) auto}.g .acts{grid-column:3;grid-row:1}.g .chips{grid-column:2/4;justify-self:start}.g .fix{grid-column:2/4}.wrap{padding-top:18px}.head h2{font-size:26px}}\n`,\n  render(d2){\n    const s=d2.state\n    const all=recs(d2,'guests')\n    const q=(s.q||'').toLowerCase().trim(),f=s.filter||'todos',sort=s.sort||'num',gf=s.gf||'todos'\n    const opts=all.filter(x=>numOf(x)).sort((a,b)=>numOf(a)-numOf(b))\n    const uncN=all.filter(isUnc).length\n    const list=all.filter(g=>(gf==='todos'||(gf==='sem'?!GROUPS.includes(g.group):g.group===gf))&&(f==='todos'||(f==='incertos'?isUnc(g):(g.status||'a convidar')===f))&&(!q||`${numOf(g)||''} ${g.name} ${g.group} ${g.phone} ${g.notes}`.toLowerCase().includes(q)))\n      .sort(sort==='az'?(a,b)=>String(a.name).localeCompare(String(b.name),'pt-BR'):(a,b)=>(numOf(a)??1e9)-(numOf(b)??1e9)||String(a.name).localeCompare(String(b.name),'pt-BR'))\n    const totalP=all.length\n    const conf=all.filter(g=>g.status==='confirmado'),confP=conf.reduce((a,g)=>a+ppl(g),0)\n    const no=all.filter(g=>g.status==='não vem').reduce((a,g)=>a+ppl(g),0)\n    const nextNum=Math.max(0,...all.map(g=>numOf(g)||0))+1\n    const form=(g)=>`<form class=\"gf\" data-id=\"${esc(g?g._id:'')}\">\n      <div><label>Nº</label><input name=\"num\" type=\"number\" min=\"1\" value=\"${g?(numOf(g)||''):nextNum}\"/></div>\n      <div class=\"wide\"><label>Nome</label><input name=\"name\" required value=\"${esc(g?g.name:'')}\" placeholder=\"Ex.: Tia Lúcia\"/></div>\n      <div class=\"wide\"><label>Grupo</label><select name=\"group\"><option value=\"\">—</option>${GROUPS.map(x=>`<option ${g&&g.group===x?'selected':''}>${x}</option>`).join('')}</select></div>\n      <div class=\"half wide comp\" style=\"${g&&g.group==='Extra'?'':'display:none'}\"><label>Agregado de</label><select name=\"companionOf\"><option value=\"\">—</option>${opts.filter(x=>!g||x._id!==g._id).map(x=>`<option value=\"${numOf(x)}\" ${g&&Number(g.companionOf)===numOf(x)?'selected':''}>#${numOf(x)} ${esc(x.name)}</option>`).join('')}</select></div>\n      <div class=\"half wide\"><label>Telefone</label><input name=\"phone\" inputmode=\"tel\" value=\"${esc(g?g.phone:'')}\" placeholder=\"(11) 9…\"/></div>\n      <div class=\"wide\"><label>Status</label><select name=\"status\">${ST.map(x=>`<option ${((g&&g.status)||'a convidar')===x?'selected':''}>${x}</option>`).join('')}</select></div>\n      <div class=\"half wide\"><label>Observações</label><input name=\"notes\" value=\"${esc(g?g.notes:'')}\" placeholder=\"Restrição alimentar, acompanhante…\"/></div>\n      <div class=\"full row\"><button class=\"btn\" type=\"submit\">${g?'Salvar':'Adicionar'}</button><button class=\"btn ghost cancel\" type=\"button\">Cancelar</button>${g?`<button class=\"btn danger del\" type=\"button\" data-id=\"${esc(g._id)}\" style=\"margin-left:auto\">Excluir</button>`:''}</div>\n    </form>`\n    const row=(g,i)=>{\n      if(s.editing===g._id)return form(g)\n      const n=numOf(g),unc=isUnc(g)\n      const meta=[]\n      if(g.group==='Extra'&&g.companionOf){const c=all.find(x=>numOf(x)===Number(g.companionOf));meta.push(`agregado de #${g.companionOf}${c?' '+esc(c.name):''}`)}\n      if(g.phone)meta.push(`<a href=\"https://wa.me/55${esc(String(g.phone).replace(/\\D/g,'').replace(/^55/,''))}\" target=\"_blank\" rel=\"noopener\">${esc(g.phone)}</a>`)\n      const extra=cleanNotes(String(g.notes||'').replace(/Lista nº\\s*\\d+\\s*·?\\s*/i,''))\n      if(extra)meta.push(esc(extra))\n      if(unc)meta.push('<span class=\"w\">⚠️ leitura incerta</span>')\n      if(g.rsvpNote&&g.rsvpNote!=='undefined')meta.push(`<span class=\"rs\">💬 “${esc(g.rsvpNote)}”</span>`)\n      else if(g.rsvpAt)meta.push('<span class=\"rs\">respondeu pelo convite</span>')\n      else if(g.invitedAt&&g.status==='convidado')meta.push('convite enviado 📲')\n      const fixing=f==='incertos'&&unc\n      return `<div class=\"g ${unc?'unc':''}\" data-key=\"${esc(g._id||'p'+i)}\">\n        <div class=\"num\">${n?esc(String(n)):'·'}</div>\n        ${fixing?`<div class=\"fix\"><input class=\"fixname\" data-id=\"${esc(g._id)}\" value=\"${esc(g.name)}\" aria-label=\"Nome correto\"/><button class=\"ok\" data-id=\"${esc(g._id)}\">✓ Confirmar</button></div>`\n          :`<div style=\"min-width:0\"><div class=\"n\">${esc(g.name)}</div>${meta.length?`<div class=\"m\">${meta.join(' · ')}</div>`:''}</div>`}\n        <div class=\"chips\">${GROUPS.includes(g.group)?`<button class=\"gchip\" data-id=\"${esc(g._id)}\" title=\"Toque pra trocar o grupo\"><i style=\"background:${GC[g.group]}\"></i>${esc(g.group)}</button>`:`<button class=\"gchip none\" data-id=\"${esc(g._id)}\" title=\"Toque pra escolher o grupo\">+ grupo</button>`}<button class=\"chip ${STC[g.status||'a convidar']||'c-pend'}\" data-id=\"${esc(g._id)}\">${esc(g.status||'a convidar')}</button></div>\n        <span class=\"acts\"><button class=\"wa\" data-id=\"${esc(g._id)}\" title=\"Enviar convite (WhatsApp)\">📲</button><button class=\"lk\" data-id=\"${esc(g._id)}\" title=\"Copiar link do convite\">🔗</button><button class=\"ed\" data-id=\"${esc(g._id)}\" title=\"Editar\">✏️</button></span></div>`}\n    return `<div class=\"wrap\"><div class=\"inner\">\n      <div class=\"head\"><div style=\"flex:1;min-width:200px\"><h2>Convidados 💌</h2><p>Toque no grupo ou no status pra trocar · status: em dúvida → a convidar → convidado → confirmado → não vem.</p></div>\n        <button class=\"btn ghost paste-open\">📋 Colar lista</button><button class=\"btn add\">+ Convidado</button></div>\n      <div class=\"stats\">\n        <div class=\"st\"><div class=\"k\">Convidados</div><div class=\"v\">${totalP}</div><div class=\"h\">${all.filter(g=>g.status==='em dúvida').length} em dúvida</div></div>\n        <div class=\"st\"><div class=\"k\">Confirmados</div><div class=\"v\" style=\"color:var(--sage-ink)\">${confP}</div><div class=\"h\">${totalP?Math.round(confP/totalP*100):0}% da lista</div></div>\n        <div class=\"st\"><div class=\"k\">A convidar</div><div class=\"v\">${all.filter(g=>(g.status||'a convidar')==='a convidar').length}</div><div class=\"h\">${all.filter(g=>g.status==='convidado').length} já convidados</div></div>\n        <div class=\"st\"><div class=\"k\">Não vêm</div><div class=\"v\">${no}</div><div class=\"h\">pessoas</div></div>\n      </div>\n      ${s.editing==='new'?form(null):''}\n      ${s.paste?`<div class=\"paste\"><b style=\"font:600 17px Fredoka\">Colar lista</b>\n        <div class=\"tip\">Um convidado por linha. Formato livre: <code>Nome; Grupo; telefone</code> (só o nome é obrigatório; grupo = Família, Amigos, Salão ou Extra). Cada linha = 1 convite individual. Os números continuam a partir do ${nextNum}. Listas bagunçadas ou em foto? Manda pro Milo no chat 🐕</div>\n        <textarea class=\"pastebox\" placeholder=\"Tia Lúcia; Família; 11999990000&#10;Ana Paula; Amigos&#10;Marcos\"></textarea>\n        <div class=\"row\"><button class=\"btn do-paste\">Importar</button><button class=\"btn ghost paste-close\">Cancelar</button></div></div>`:''}\n      <div class=\"tools\"><input class=\"search\" placeholder=\"🔎 Buscar por nº, nome, telefone…\" value=\"${esc(s.q||'')}\"/>\n        <span class=\"seg\"><button data-sort=\"num\" ${sort==='num'?'data-on':''}>Nº</button><button data-sort=\"az\" ${sort==='az'?'data-on':''}>A–Z</button></span></div>\n      <div class=\"tools\">${[['todos','Todos os grupos'],...GROUPS.map(x=>[x,x]),['sem','Sem grupo']].map(([k,l])=>`<button class=\"f\" data-gf=\"${k}\" ${gf===k?'data-on':''}>${l} · ${k==='todos'?all.length:all.filter(g=>k==='sem'?!GROUPS.includes(g.group):g.group===k).length}</button>`).join('')}</div>\n      <div class=\"tools\">${['todos',...ST].map(k=>`<button class=\"f\" data-f=\"${k}\" ${f===k?'data-on':''}>${k==='todos'?'Todos':k}</button>`).join('')}\n        ${uncN||f==='incertos'?`<button class=\"f warn\" data-f=\"incertos\" ${f==='incertos'?'data-on':''}>⚠️ Incertos · ${uncN}</button>`:''}</div>\n      ${f==='incertos'&&uncN?`<div class=\"banner\">Corrija o nome no campo e toque em ✓ Confirmar (ou Enter). A marca de \"leitura incerta\" sai sozinha 🐾</div>`:''}\n      ${list.length?`<div class=\"list\">${list.map(row).join('')}</div>`\n      :`<div class=\"empty\"><span class=\"z\">${f==='incertos'?'🎉':'🐕💤'}</span>${f==='incertos'?'Nenhum nome incerto, tudo conferido!':all.length?'Ninguém com esse filtro.':'Nenhum convidado ainda. Adicione, cole uma lista ou mande pro Milo no chat!'}</div>`}\n    </div></div>`\n  },\n  mounted(d2){\n    const s=d2.state,G=()=>d2.data('guests')\n    // backfill único: grava `num` a partir de \"Lista nº X\" nas observações\n    let tries=0\n    const backfill=async()=>{const rs=G().records()||[];if(!rs.length&&tries++<20){setTimeout(backfill,700);return}\n      for(const g of rs){const patch={};if(!Number(g.num)){const n=numFromNotes(g);if(n)patch.num=n}if(!g.rsvpToken)patch.rsvpToken=tok()\n        if(Object.keys(patch).length){try{await G().update({...g,...patch})}catch(e){}}}}\n    setTimeout(backfill,500)\n    const fix=async(id)=>{const el=d2.$(`.fixname[data-id=\"${id}\"]`);const g=G().records().find(r=>r._id===id);if(!g||!el)return\n      const name=el.value.trim();if(!name)return\n      await G().update({...g,name,notes:cleanNotes(g.notes)});toast(d2,`${name} conferido ✓`)}\n    d2.on('.ok','click',(e,el)=>fix(el.dataset.id))\n    d2.on('.fixname','keydown',(e,el)=>{if(e.key==='Enter'){e.preventDefault();fix(el.dataset.id)}})\n    d2.on('.add','click',()=>{d2.setState({editing:'new',paste:false});setTimeout(()=>{const i=d2.$('form.gf input[name=name]');i&&i.focus()},30)})\n    d2.on('.ed','click',(e,el)=>{s.editing=el.dataset.id})\n    d2.on('.cancel','click',()=>{s.editing=null})\n    d2.on('.paste-open','click',()=>d2.setState({paste:true,editing:null}))\n    d2.on('.paste-close','click',()=>{s.paste=false})\n    d2.on('.search','input',(e,el)=>{s.q=el.value})\n    d2.on('.f','click',(e,el)=>{if(el.dataset.gf)s.gf=el.dataset.gf;else s.filter=el.dataset.f})\n    d2.on('[data-sort]','click',(e,el)=>{s.sort=el.dataset.sort})\n    let partyCache={};(async()=>{try{const r=await d2.rush('rsvp-get').invoke({c:''});const d=r&&r.data?r.data:r;partyCache=(d&&d.party)||{}}catch(e){}})()\n    const party=()=>partyCache\n    const ensureTok=async(g)=>{if(g.rsvpToken)return g;const t=tok();await G().update({...g,rsvpToken:t});return {...g,rsvpToken:t}}\n    const markSent=async(g)=>{const cur=G().records().find(r=>r._id===g._id)||g;if(['a convidar','em dúvida'].includes(cur.status||'a convidar'))await G().update({...cur,status:'convidado',invitedAt:new Date().toISOString()})}\n    d2.on('.wa','click',async(e,el)=>{let g=G().records().find(r=>r._id===el.dataset.id);if(!g)return;g=await ensureTok(g)\n      const p=party(),text=inviteMsg(g,p)\n      if(p.inviteImage&&navigator.canShare){try{const b=await (await fetch(p.inviteImage)).blob();const f=new File([b],'convite-katia-33.png',{type:b.type||'image/png'})\n        if(navigator.canShare({files:[f]})){await navigator.share({files:[f],text});await markSent(g);toast(d2,`Convite enviado pra ${firstName(g.name)} 💌`);return}}catch(err){if(err&&err.name==='AbortError')return}}\n      const ph=String(g.phone||'').replace(/\\D/g,'').replace(/^55/,'')\n      window.open((ph?`https://wa.me/55${ph}?text=`:'https://wa.me/?text=')+encodeURIComponent(text),'_blank')\n      await markSent(g);toast(d2,p.inviteImage?`Mensagem pronta pra ${firstName(g.name)}. Anexa a imagem do convite 🖼️`:`Mensagem pronta pra ${firstName(g.name)} 💌`)})\n    d2.on('.lk','click',async(e,el)=>{let g=G().records().find(r=>r._id===el.dataset.id);if(!g)return;g=await ensureTok(g)\n      const link=INVITE+g.rsvpToken;try{await navigator.clipboard.writeText(link);toast(d2,`Link de ${firstName(g.name)} copiado 🔗`)}catch(err){await d2.dialog.prompt('Link do convite (copie):',link)}})\n    d2.on('.gchip','click',async(e,el)=>{const g=G().records().find(r=>r._id===el.dataset.id);if(!g)return\n      const order=['',...GROUPS],nx=order[(order.indexOf(GROUPS.includes(g.group)?g.group:'')+1)%order.length]\n      await G().update({...g,group:nx,companionOf:nx==='Extra'?(g.companionOf||null):null})\n      if(nx==='Extra'&&!g.companionOf)toast(d2,`${g.name} agora é Extra. Toque no ✏️ pra dizer de quem é agregado 🐾`)})\n    d2.on('select[name=group]','change',(e,el)=>{const w=el.form&&el.form.querySelector('.comp');if(w)w.style.display=el.value==='Extra'?'':'none'})\n    d2.on('.chip','click',async(e,el)=>{const g=G().records().find(r=>r._id===el.dataset.id);if(!g)return\n      const nx=ST[(ST.indexOf(g.status||'a convidar')+1)%ST.length];await G().update({...g,status:nx})\n      if(nx==='confirmado')toast(d2,`${g.name} confirmado(a)! 🎉`)})\n    d2.on('.del','click',async(e,el)=>{const g=G().records().find(r=>r._id===el.dataset.id);if(!g)return\n      if(!await d2.dialog.confirm(`Remover ${g.name} da lista?`))return\n      await G().remove(g);s.editing=null;toast(d2,'Convidado removido')})\n    d2.on('.do-paste','click',async()=>{const t=(d2.$('.pastebox')||{}).value||''\n      let n=Math.max(0,...G().records().map(g=>numOf(g)||0))\n      const rows=t.split(/\\n+/).map(l=>l.trim()).filter(Boolean).map(l=>{const p=l.split(/[;\\t|]/).map(x=>x.trim())\n        return {name:p[0],group:GROUPS.find(x=>x.toLowerCase()===String(p[1]||'').toLowerCase())||'',adults:1,kids:0,phone:p[2]||'',status:'a convidar'}}).filter(r=>r.name)\n      if(!rows.length)return\n      s.paste=false;for(const r of rows)await G().create({...r,num:++n});toast(d2,`${rows.length} convidado${rows.length>1?'s':''} importado${rows.length>1?'s':''} 💌`)})\n    d2.on('form','submit',async(e,form)=>{e.preventDefault()\n      const fd=new FormData(form),id=form.dataset.id\n      const data={num:Number(fd.get('num'))||null,name:String(fd.get('name')||'').trim(),group:String(fd.get('group')||'').trim(),companionOf:String(fd.get('group')||'')==='Extra'?(Number(fd.get('companionOf'))||null):null,adults:1,kids:0,phone:String(fd.get('phone')||'').trim(),status:fd.get('status')||'a convidar',notes:String(fd.get('notes')||'').trim()}\n      if(!data.name)return\n      if(id){const g=G().records().find(r=>r._id===id);if(g&&data.name!==g.name)data.notes=cleanNotes(data.notes);await G().update({...g,...data});s.editing=null;toast(d2,'Salvo ✨')}\n      else{await G().create(data);toast(d2,`${data.name} adicionado(a) 💌`);form.reset();const i=form.querySelector('input[name=num]');if(i)i.value=String((data.num||0)+1);const nm=form.querySelector('input[name=name]');nm&&nm.focus()}\n    })\n  },\n}\n"}},"guests":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"guests"}}}},"me":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"me"}}}}}}}}}},{"_id":"6abefda70484650e9b1b46bb","component":"data2-core-types@Component","system":"6abed5371a6b03943b9618d7","params":{"extends":"data2-core-primitives@Block","component":"kp-chat","package":"katia-party","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"// kp-chat — conversa única com o Milo (assistente) que registra TASKS estruturadas pro Claude executar depois.\n// Aceita fotos/arquivos (Drive). Painel lateral de tasks (desktop) / aba (mobile).\n// params: messages tasks (dataset), scribe (assistant), drive (service), uploader (rush → @upload-file), me (string)\nfunction esc(s){return String(s??'').replace(/[&<>\"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;'}[c]))}\nfunction md(s){return esc(s).replace(/\\*\\*(.+?)\\*\\*/g,'<b>$1</b>').replace(/(https?:\\/\\/[^\\s<]+)/g,'<a href=\"$1\" target=\"_blank\" rel=\"noopener\">$1</a>').replace(/\\n/g,'<br>')}\nfunction shiba(cls){return `<svg class=\"${cls||''}\" viewBox=\"0 0 120 110\" aria-hidden=\"true\"><path d=\"M22 50 L30 8 L56 32 Z\" fill=\"#E59A55\"/><path d=\"M29 41 L33 18 L48 33 Z\" fill=\"#F8D7B5\"/><path d=\"M98 50 L90 8 L64 32 Z\" fill=\"#E59A55\"/><path d=\"M91 41 L87 18 L72 33 Z\" fill=\"#F8D7B5\"/><ellipse cx=\"60\" cy=\"62\" rx=\"44\" ry=\"40\" fill=\"#E59A55\"/><path d=\"M24 70 Q30 99 60 103 Q90 99 96 70 Q84 58 72 66 Q60 74 48 66 Q36 58 24 70Z\" fill=\"#FFF4E8\"/><ellipse cx=\"44\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><ellipse cx=\"76\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><ellipse cx=\"44\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><ellipse cx=\"76\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><circle cx=\"45.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/><circle cx=\"77.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/><path d=\"M54 72 Q60 68 66 72 Q63 78 60 78 Q57 78 54 72Z\" fill=\"#3B2A2E\"/><path d=\"M52 83 Q56 88 60 83 Q64 88 68 83\" stroke=\"#3B2A2E\" stroke-width=\"2.4\" fill=\"none\" stroke-linecap=\"round\"/><ellipse cx=\"32\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/><ellipse cx=\"88\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/></svg>`}\nconst recs=(d2,k)=>{const h=d2.data(k);return h?h.records()||[]:[]}\nconst toast=(d2,m)=>d2.bus.emit('kp:toast',m)\n// upload via Rush `upload-file` (o Drive recusa upload direto de usuário final). Imagens são reduzidas antes.\nasync function toB64(file){if(/^image\\/(png|jpe?g|webp)$/i.test(file.type||'')){try{const bmp=await createImageBitmap(file);const k=Math.min(1,1920/Math.max(bmp.width,bmp.height));const c=document.createElement('canvas');c.width=Math.round(bmp.width*k);c.height=Math.round(bmp.height*k);const g=c.getContext('2d');g.fillStyle='#fff';g.fillRect(0,0,c.width,c.height);g.drawImage(bmp,0,0,c.width,c.height);const du=c.toDataURL('image/jpeg',0.85);return {base64:du.split(',')[1],contentType:'image/jpeg',fileName:String(file.name||'foto').replace(/\\.[^.]+$/,'')+'.jpg'}}catch(e){}}\n  const du=await new Promise((res,rej)=>{const r=new FileReader();r.onload=()=>res(r.result);r.onerror=rej;r.readAsDataURL(file)});return {base64:String(du).split(',')[1],contentType:file.type||'application/octet-stream',fileName:file.name||'arquivo'}}\nasync function shrink(file){if(!/^image\\/(png|jpe?g|webp)$/i.test(file.type||''))return file;const p=await toB64(file);if(p.contentType!=='image/jpeg')return file;const bin=atob(p.base64),u8=new Uint8Array(bin.length);for(let i=0;i<bin.length;i++)u8[i]=bin.charCodeAt(i);return new File([u8],p.fileName,{type:'image/jpeg'})}\n// 1º upload direto no Drive (presigned S3, sem limite prático; liberado pela DrivePolicy upload). 2º fallback: Rush (até ~1 MB, limite da Lambda).\nasync function uploadAll(d2,files){const out=[];for(const f0 of files){if(f0.size>25e6)throw new Error(`${f0.name}: muito grande (máx. 25 MB)`);const f=await shrink(f0);let url=''\n  try{const up=await d2.drive(d2.param('drive')).upload([f]);const u=up&&up[0];url=(u&&(u.fileUrl||u.url))||''}catch(e){}\n  if(!url&&f.size<9e5){const p=await toB64(f);const r=await d2.rush('upload-file').invoke(p);const d=r&&r.data?r.data:r;url=(d&&d.url)||''}\n  if(!url)throw new Error(`${f0.name}: não consegui enviar`)\n  out.push({url,name:f0.name||f.name,type:f.type})}return out}\nconst stamp=(r)=>r.createdAt?new Date(r.createdAt).getTime():Number.MAX_SAFE_INTEGER\nconst isImg=(a)=>/^image\\//.test(a.type||'')||/\\.(png|jpe?g|gif|webp|heic)(\\?|$)/i.test(a.url||'')\nconst KIND={convidados:'💌',orcamento:'💸',cotacao:'🧾',design:'🎨',convite:'✉️',lembrete:'⏰',outro:'📌'}\nconst TST={pendente:'c-lil','em andamento':'c-cot',feita:'c-ok',cancelada:'c-no'}\nconst LBL={pendente:'na fila','em andamento':'fazendo',feita:'feita',cancelada:'cancelada'}\nconst OPEN=(t)=>['pendente','em andamento'].includes(t.status||'pendente')\nconst SEEN=new WeakMap()\nconst sid=(id)=>String(id||'').slice(-6)\nfunction parseAnswer(a){if(a&&typeof a==='object')return a;let t=String(a||'').trim().replace(/^```(json)?/i,'').replace(/```$/,'').trim();try{return JSON.parse(t)}catch(e){const m=t.match(/\\{[\\s\\S]*\\}/);if(m){try{return JSON.parse(m[0])}catch(e2){}}return {reply:t||'Au? Não entendi direito, pode repetir? 🐕',task:null}}}\n\nexport default {\n  css:`\n:host{--bg:#FFF7F5;--card:#FFFFFF;--blush-50:#FFF1F2;--blush-100:#FDE4E7;--blush-200:#F9CDD4;--blush-300:#F2AEBA;--rose:#D9879A;--rose-deep:#B8647A;--ink:#4A3439;--muted:#94797E;--line:#F3DDE0;--peach:#FDE3D3;--sage:#DCEBDD;--sage-ink:#4F7A57;--butter:#FFF2C9;--butter-ink:#8A6D1F;--lilac:#ECE3F6;--lilac-ink:#6B5390;--shadow:0 6px 24px rgba(184,100,122,.12)}\n*{box-sizing:border-box}\n.wrap{height:100%;display:grid;grid-template-columns:minmax(0,1fr) 340px;font-family:'Nunito',system-ui,sans-serif;color:var(--ink);min-height:0}\n.chat{display:grid;grid-template-rows:auto minmax(0,1fr) auto;min-height:0;min-width:0}\n.ch{display:flex;align-items:center;gap:12px;padding:14px 20px;border-bottom:1px solid var(--line);background:#fff}\n.ch svg{width:44px;height:40px}\n.ch b{font:600 19px 'Fredoka';display:block}.ch small{font-size:12px;font-weight:700;color:var(--muted)}\n.ch .tg{margin-left:auto;display:none}\n.log{overflow:auto;padding:20px clamp(12px,3vw,32px);display:flex;flex-direction:column;gap:14px;background:radial-gradient(600px 300px at 100% 0,#FFF1F2,transparent),var(--bg)}\n.m{display:flex;gap:10px;align-items:flex-end;max-width:min(680px,92%)}\n.m.me{align-self:flex-end;flex-direction:row-reverse}\n.m .av{width:34px;height:34px;border-radius:50%;flex:none;display:grid;place-items:center;font:600 13px 'Fredoka';color:#fff;background:linear-gradient(135deg,#E79AAB,#D9879A)}\n.m .av.dog{background:#FFF4E8;border:1px solid var(--line)}.m .av.dog svg{width:28px;height:26px}\n.m .av.cl{background:linear-gradient(135deg,#CDB8EA,#9F86C9)}\n.bub{padding:11px 14px;border-radius:18px 18px 18px 6px;background:#fff;border:1px solid var(--line);box-shadow:0 2px 10px rgba(184,100,122,.06);font-size:15px;line-height:1.45;word-break:break-word;min-width:0}\n.m.me .bub{border-radius:18px 18px 6px 18px;background:linear-gradient(135deg,#FBD3DB,#F9CDD4);border-color:#F6C2CC}\n.m.cl .bub{background:var(--lilac);border-color:#DCCFF0}\n.bub a{color:var(--rose-deep);word-break:break-all}\n.who{font-size:11px;font-weight:800;color:var(--muted);margin-bottom:3px}\n.m.me .who{text-align:right}\n.att{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}\n.att img{width:120px;height:120px;object-fit:cover;border-radius:12px;border:1px solid var(--line);cursor:zoom-in;background:#fff}\n.att a.file{font-size:12px;font-weight:800;color:var(--lilac-ink);background:#fff;border:1px solid #DCCFF0;border-radius:10px;padding:5px 9px;text-decoration:none}\n.tchip{display:inline-flex;align-items:center;gap:6px;margin-top:8px;font-size:12px;font-weight:800;border-radius:10px;padding:5px 9px;background:var(--blush-50);border:1px dashed var(--blush-300);cursor:pointer}\n.typing{display:inline-flex;gap:4px;padding:4px 2px}\n.typing i{width:7px;height:7px;border-radius:50%;background:var(--rose);animation:bop 1s infinite}\n.typing i:nth-child(2){animation-delay:.15s}.typing i:nth-child(3){animation-delay:.3s}\n@keyframes bop{0%,100%{transform:translateY(0);opacity:.5}50%{transform:translateY(-5px);opacity:1}}\n.compose{padding:12px clamp(12px,3vw,24px) 14px;background:#fff;border-top:1px solid var(--line)}\n.pending{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}\n.pending span{font-size:12px;font-weight:800;background:var(--lilac);color:var(--lilac-ink);border-radius:10px;padding:4px 8px;display:inline-flex;gap:6px;align-items:center}\n.pending button{border:0;background:none;cursor:pointer;color:inherit;font-weight:900}\n.bar{display:flex;gap:8px;align-items:flex-end}\n.clip{width:44px;height:44px;flex:none;border-radius:14px;border:1.5px solid var(--line);background:#fff;display:grid;place-items:center;cursor:pointer;font-size:19px}\n.clip input{display:none}\ntextarea{flex:1;min-height:44px;max-height:160px;resize:none;border:1.5px solid var(--line);background:var(--blush-50);border-radius:14px;padding:11px 14px;font:600 15px 'Nunito';color:var(--ink);outline:none}\ntextarea:focus{border-color:var(--blush-300);background:#fff}\n.send{height:44px;border:0;border-radius:14px;padding:0 18px;font:600 15px 'Fredoka';cursor:pointer;background:linear-gradient(135deg,#E79AAB,#D9879A);color:#fff;box-shadow:0 6px 16px rgba(217,135,154,.3)}\n.send[disabled]{opacity:.5}\n.hint{font-size:11px;font-weight:700;color:var(--muted);margin-top:6px}\n.side{border-left:1px solid var(--line);background:#fff;display:grid;grid-template-rows:auto auto minmax(0,1fr);min-height:0}\n.sh{padding:16px 16px 8px;font:600 18px 'Fredoka';display:flex;align-items:center;gap:8px}\n.sh small{margin-left:auto;font:700 12px 'Nunito';color:var(--muted)}\n.fs{display:flex;gap:6px;padding:0 16px 10px;flex-wrap:wrap}\n.f{border:1.5px solid var(--line);background:#fff;border-radius:999px;padding:5px 10px;font:700 12px 'Nunito';color:var(--ink);cursor:pointer}\n.f[data-on]{background:var(--blush-100);border-color:var(--blush-300);color:var(--rose-deep)}\n.tl{overflow:auto;padding:0 12px 16px;display:flex;flex-direction:column;gap:8px}\n.t{border:1px solid var(--line);border-radius:16px;padding:11px 12px;background:#fff;cursor:pointer}\n.t[data-open]{border-color:var(--blush-300);box-shadow:var(--shadow)}\n.t .tt{font-weight:800;font-size:14px;display:flex;gap:6px}\n.t .tm{font-size:11px;font-weight:700;color:var(--muted);margin-top:4px;display:flex;gap:6px;flex-wrap:wrap;align-items:center}\n.chip{font-weight:800;font-size:11px;border-radius:999px;padding:2px 8px}\n.c-lil{background:var(--lilac);color:var(--lilac-ink)}.c-cot{background:var(--butter);color:var(--butter-ink)}.c-ok{background:var(--sage);color:var(--sage-ink)}.c-no{background:#EFE7E8;color:#8C7377}\n.t .td{font-size:13px;line-height:1.45;margin-top:8px;white-space:pre-wrap;word-break:break-word}\n.t pre{font-size:11px;background:var(--blush-50);border-radius:10px;padding:8px;overflow:auto;max-height:200px;margin:8px 0 0}\n.t .res{margin-top:8px;font-size:13px;background:var(--sage);color:var(--sage-ink);border-radius:10px;padding:8px;font-weight:700}\n.t .acts{display:flex;gap:6px;margin-top:8px}\n.t .acts button{border:1.5px solid var(--line);background:#fff;border-radius:10px;padding:5px 9px;font:700 12px 'Nunito';cursor:pointer;color:var(--ink)}\n.empty{color:var(--muted);font-weight:700;font-size:13px;text-align:center;padding:24px 8px}\n.welcome{align-self:center;text-align:center;max-width:440px;margin:auto;color:var(--muted);font-weight:700}\n.welcome svg{width:110px;height:100px}\n.welcome b{display:block;font:600 22px 'Fredoka';color:var(--rose-deep);margin:6px 0}\n.sugg{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;margin-top:12px}\n.sugg button{border:1.5px solid var(--line);background:#fff;border-radius:999px;padding:7px 12px;font:700 13px 'Nunito';cursor:pointer;color:var(--ink)}\n.zoom{position:fixed;inset:0;background:rgba(74,52,57,.75);display:grid;place-items:center;z-index:80;cursor:zoom-out;padding:16px}\n.zoom img{max-width:100%;max-height:100%;border-radius:16px}\n@media (max-width:980px){\n  .wrap{grid-template-columns:minmax(0,1fr)}\n  .side{display:none;border-left:0}\n  .wrap[data-pane=\"tasks\"] .chat{display:none}.wrap[data-pane=\"tasks\"] .side{display:grid}\n  .ch .tg{display:inline-flex}\n  .tgb{border:1.5px solid var(--line);background:#fff;border-radius:999px;padding:6px 12px;font:700 13px 'Nunito';cursor:pointer;color:var(--rose-deep)}\n  .bub{font-size:14px}\n  .tgb{white-space:nowrap}\n  .hint{display:none}\n  .ch{padding:10px 14px}\n}\n`,\n  render(d2){\n    const s=d2.state\n    const msgs=recs(d2,'messages').slice().sort((a,b)=>stamp(a)-stamp(b))\n    const tasks=recs(d2,'tasks').slice().sort((a,b)=>stamp(b)-stamp(a))\n    const tById={};for(const t of tasks)tById[t._id]=t\n    const me=d2.param('me')||'Você'\n    const a=d2.assistant(d2.param('scribe'))\n    const thinking=s.thinking||(a&&a.busy)\n    const pendN=tasks.filter(t=>(t.status||'pendente')==='pendente'||t.status==='em andamento').length\n    const atts=(list)=>list&&list.length?`<div class=\"att\">${list.map(x=>isImg(x)?`<img src=\"${esc(x.url)}\" data-zoom=\"${esc(x.url)}\" alt=\"${esc(x.name||'')}\" loading=\"lazy\"/>`:`<a class=\"file\" href=\"${esc(x.url)}\" target=\"_blank\" rel=\"noopener\">📎 ${esc(x.name||'arquivo')}</a>`).join('')}</div>`:''\n    const bubble=(m,i)=>{\n      const role=m.role||'user', mine=role==='user'&&m.author===me\n      const t=m.taskId&&tById[m.taskId]\n      const av=role==='assistant'?`<div class=\"av dog\">${shiba()}</div>`:role==='claude'?`<div class=\"av cl\">✨</div>`:`<div class=\"av\">${esc((m.author||'?')[0])}</div>`\n      return `<div class=\"m ${mine?'me':''} ${role==='claude'?'cl':''}\" data-key=\"${esc(m._id||'pm'+i)}\">${av}<div style=\"min-width:0\">\n        <div class=\"who\">${esc(role==='assistant'?'Milo 🐕':role==='claude'?'Claude ✨':m.author||'')}${m.createdAt?' · '+esc(d2.fmt.relative(m.createdAt)):''}</div>\n        <div class=\"bub\">${md(m.text||'')}${atts(m.attachments)}${t?`<div class=\"tchip\" data-task=\"${esc(t._id)}\">${KIND[t.kind]||'📌'} Task #${sid(t._id)} · ${esc(t.title)} · <span class=\"chip ${TST[t.status||'pendente']}\">${esc(LBL[t.status||'pendente']||t.status)}</span></div>`:''}</div></div></div>`}\n    const f=s.tf||'abertas'\n    const shownT=tasks.filter(t=>{const st=t.status||'pendente';return f==='todas'||(f==='abertas'?(st==='pendente'||st==='em andamento'):st===f)})\n    return `<div class=\"wrap\" data-pane=\"${s.pane||'chat'}\">\n      <section class=\"chat\">\n        <div class=\"ch\">${shiba()}<div><b>Milo</b><small>registra tasks pro Claude fazer depois · ${pendN} em aberto</small></div><span class=\"tg\"><button class=\"tgb to-tasks\">📋 Tasks${pendN?` (${pendN})`:''}</button></span></div>\n        <div class=\"log\">\n          ${msgs.length?msgs.map(bubble).join(''):`<div class=\"welcome\">${shiba()}<b>Oi! Eu sou o Milo 🐾</b>Me conta o que precisa: eu entendo, organizo e registro uma task pro Claude fazer depois. Pode mandar lista de convidados, print de orçamento, foto de inspiração…\n            <div class=\"sugg\"><button data-s=\"Registra essa lista de convidados: \">💌 Lista de convidados</button><button data-s=\"Tenho uma cotação nova de buffet: \">🧾 Nova cotação</button><button data-s=\"Quero ideias de decoração com essa foto de referência\">🎨 Inspiração</button></div></div>`}\n          ${s.optimistic?bubble({...s.optimistic},'opt'):''}\n          ${thinking?`<div class=\"m\"><div class=\"av dog\">${shiba()}</div><div><div class=\"who\">Milo 🐕</div><div class=\"bub\"><span class=\"typing\"><i></i><i></i><i></i></span></div></div></div>`:''}\n        </div>\n        <div class=\"compose\">\n          ${(s.files||[]).length||s.uploading?`<div class=\"pending\">${(s.files||[]).map((x,i)=>`<span>${isImg(x)?'🖼️':'📎'} ${esc(x.name)}<button class=\"rm\" data-i=\"${i}\">×</button></span>`).join('')}${s.uploading?'<span>⏫ enviando…</span>':''}</div>`:''}\n          <div class=\"bar\">\n            <label class=\"clip\" title=\"Anexar fotos/arquivos\">📎<input type=\"file\" class=\"file\" multiple accept=\"image/*,application/pdf,.doc,.docx,.xls,.xlsx,.csv,.txt\"/></label>\n            <textarea class=\"in\" rows=\"1\" placeholder=\"Escreve pro Milo…\" ${thinking?'disabled':''}></textarea>\n            <button class=\"send\" ${thinking||s.uploading?'disabled':''}>Enviar</button>\n          </div>\n          <div class=\"hint\">O Milo não executa nada: ele registra a task. O Claude pega as tasks em aberto, faz e responde aqui ✨</div>\n        </div>\n      </section>\n      <aside class=\"side\">\n        <div class=\"sh\">📋 Tasks <small><button class=\"tgb to-chat\" style=\"display:${s.pane==='tasks'?'inline-flex':'none'}\">← chat</button> ${tasks.length} no total</small></div>\n        <div class=\"fs\">${[['abertas','Abertas'],['em andamento','Fazendo'],['feita','Feitas'],['todas','Todas']].map(([k,l])=>`<button class=\"f\" data-tf=\"${k}\" ${f===k?'data-on':''}>${l}${k==='em andamento'?` · ${tasks.filter(t=>t.status==='em andamento').length}`:''}</button>`).join('')}</div>\n        <div class=\"tl\">${shownT.length?shownT.map((t,i)=>{const o=s.openT===t._id;return `<div class=\"t\" data-key=\"${esc(t._id||'pt'+i)}\" data-id=\"${esc(t._id)}\" ${o?'data-open':''}>\n          <div class=\"tt\"><span>${KIND[t.kind]||'📌'}</span><span>${esc(t.title)}</span></div>\n          <div class=\"tm\"><span class=\"chip ${TST[t.status||'pendente']}\">${esc(LBL[t.status||'pendente']||t.status)}</span>#${sid(t._id)} · ${esc(t.createdBy||'')}${t.createdAt?' · '+esc(d2.fmt.relative(t.createdAt)):''}</div>\n          ${o?`<div class=\"td\">${esc(t.description||'')}</div>${t.payload&&Object.keys(t.payload).length?`<pre>${esc(JSON.stringify(t.payload,null,2))}</pre>`:''}${atts(t.attachments)}${t.result?`<div class=\"res\">✨ ${esc(t.result)}</div>`:''}\n            <div class=\"acts\">${(t.status||'pendente')==='feita'?`<button class=\"reopen\" data-id=\"${esc(t._id)}\">Reabrir</button>`:`<button class=\"done\" data-id=\"${esc(t._id)}\">Marcar feita</button>`}<button class=\"cancel\" data-id=\"${esc(t._id)}\">Cancelar</button></div>`:''}\n        </div>`}).join(''):'<div class=\"empty\">🐕💤 Nenhuma task aqui.</div>'}</div>\n      </aside>\n      ${s.zoom?`<div class=\"zoom\"><img src=\"${esc(s.zoom)}\"/></div>`:''}\n    </div>`\n  },\n  mounted(d2){\n    const s=d2.state,M=()=>d2.data('messages'),T=()=>d2.data('tasks')\n    const me=()=>d2.param('me')||'Você'\n    const grow=(el)=>{el.style.height='auto';el.style.height=Math.min(160,el.scrollHeight)+'px'}\n    d2.on('.in','input',(e,el)=>grow(el))\n    d2.on('.sugg button','click',(e,el)=>{const i=d2.$('.in');if(i){i.value=el.dataset.s;i.focus()}})\n    d2.on('.file','change',async(e,el)=>{const files=el.files;if(!files||!files.length)return\n      s.uploading=true\n      try{const add=await uploadAll(d2,[...files])\n        if(!add.length)throw new Error('upload sem url')\n        s.files=[...(s.files||[]),...add]}\n      catch(err){s.upErr=String(err&&err.message||err).slice(0,140);toast(d2,`Não consegui subir o arquivo 😕 (${s.upErr})`)}\n      finally{s.uploading=false;el.value=''}})\n    d2.on('.rm','click',(e,el)=>{const f=(s.files||[]).slice();f.splice(Number(el.dataset.i),1);s.files=f})\n    d2.on('[data-zoom]','click',(e,el)=>{s.zoom=el.dataset.zoom})\n    d2.on('.zoom','click',()=>{s.zoom=null})\n    d2.on('.to-tasks','click',()=>{s.pane='tasks'});d2.on('.to-chat','click',()=>{s.pane='chat'})\n    d2.on('.tchip','click',(e,el)=>d2.setState({openT:el.dataset.task,pane:'tasks',tf:'todas'}))\n    d2.on('.f','click',(e,el)=>{s.tf=el.dataset.tf})\n    d2.on('.t','click',(e,el)=>{if(e.target.closest('button,a,img'))return;s.openT=s.openT===el.dataset.id?null:el.dataset.id})\n    const setT=async(id,status)=>{const t=T().records().find(r=>r._id===id);if(t)await T().update({...t,status})}\n    d2.on('.done','click',(e,el)=>setT(el.dataset.id,'feita'))\n    d2.on('.reopen','click',(e,el)=>setT(el.dataset.id,'pendente'))\n    d2.on('.cancel','click',async(e,el)=>{if(await d2.dialog.confirm('Cancelar essa task?'))setT(el.dataset.id,'cancelada')})\n\n    const send=async()=>{\n      const el=d2.$('.in');const text=(el&&el.value||'').trim();const files=s.files||[]\n      if((!text&&!files.length)||s.thinking||s.uploading)return\n      el.value='';grow(el)\n      const author=me()\n      s.optimistic={role:'user',author,text,attachments:files}\n      s.files=[];s.thinking=true\n      try{\n        const userMsg=await M().create({role:'user',author,text,attachments:files})\n        s.optimistic=null\n        const hist=M().records().slice().sort((a,b)=>stamp(a)-stamp(b)).slice(-60)\n          .map(m=>`[${m.role==='assistant'?'Milo':m.role==='claude'?'Claude (agente)':m.author||'usuário'}] ${m.text||''}${(m.attachments||[]).length?` (anexos: ${m.attachments.map(x=>x.url).join(', ')})`:''}${m.taskId?` → task #${sid(m.taskId)}`:''}`).join('\\n')\n        const tl=T().records().slice(-60).map(t=>OPEN(t)?`#${sid(t._id)} [${LBL[t.status||'pendente']} · EDITÁVEL · tipo ${t.kind||'outro'}] título: ${t.title}\\n   descrição: ${String(t.description||'').slice(0,400)}${t.payload&&Object.keys(t.payload).length?`\\n   payload: ${JSON.stringify(t.payload).slice(0,600)}`:''}`:`#${sid(t._id)} [${LBL[t.status]||t.status} · FECHADA, não pode alterar] ${t.title}`).join('\\n')||'(nenhuma)'\n        const imgs=files.filter(isImg).map(x=>x.url)\n        const prompt=`Hoje é ${new Date().toLocaleDateString('pt-BR',{weekday:'long',day:'2-digit',month:'long',year:'numeric'})}.\\n\\nTASKS JÁ REGISTRADAS:\\n${tl}\\n\\nHISTÓRICO DA CONVERSA (mais antigo → mais novo):\\n${hist}\\n\\nNOVA MENSAGEM de ${author}:\\n${text||'(sem texto, só anexos)'}\\n${files.length?`Anexos desta mensagem: ${files.map(x=>`${x.name} <${x.url}>`).join(', ')}`:''}\\n\\nResponda no formato JSON combinado.`\n        const raw=await d2.assistant(d2.param('scribe')).ask(prompt,{json:true,images:imgs.length?imgs:undefined})\n        const out=parseAnswer(raw)\n        let taskId=''\n        const notes=[];let opTask=''\n        for(const op of (Array.isArray(out.ops)?out.ops:[])){const ref=String(op.id||'').replace('#','').trim();const t=ref&&T().records().find(x=>sid(x._id)===ref||x._id===ref);if(!t){notes.push(`não achei a task #${ref}`);continue}\n          if(!OPEN(t)){notes.push(`a task #${sid(t._id)} já está ${LBL[t.status]||t.status}, então não dá pra mexer nela`);continue}\n          if(op.op==='cancel'){await T().update({...t,status:'cancelada',result:`Cancelada por ${author}${op.reason?': '+op.reason:''}`});opTask=t._id;toast(d2,`🗑️ Task #${sid(t._id)} cancelada`)}\n          else if(op.op==='update'){const ch={};if(op.title)ch.title=String(op.title);if(op.description)ch.description=String(op.description);if(op.kind)ch.kind=op.kind;if(op.payload&&typeof op.payload==='object')ch.payload={...(t.payload||{}),...op.payload};if(files.length)ch.attachments=[...(t.attachments||[]),...files];await T().update({...t,...ch,updatedBy:author});opTask=t._id;toast(d2,`✏️ Task #${sid(t._id)} atualizada`)}}\n        if(out.task&&out.task.title){\n          const tr=await T().create({title:String(out.task.title),description:String(out.task.description||text),kind:out.task.kind||'outro',payload:out.task.payload||{},attachments:files,status:'pendente',createdBy:author,messageId:(userMsg&&userMsg._id)||''})\n          taskId=(tr&&(tr._id||(tr.data&&tr.data._id)))||''\n          if(!taskId){const f=T().records().find(t=>t.title===String(out.task.title)&&t._id);taskId=f?f._id:''}\n        }\n        await M().create({role:'assistant',author:'Milo',text:String(out.reply||'Anotado! 🐾')+(notes.length?`\\n\\n⚠️ ${notes.join('; ')}.`:''),taskId:taskId||opTask})\n        if(taskId)toast(d2,'📌 Task registrada!')\n      }catch(err){\n        s.optimistic=null\n        await M().create({role:'assistant',author:'Milo',text:'Ops, tropecei na coleira 🐕💫 Não consegui processar agora. Tenta mandar de novo?'}).catch(()=>{})\n      }finally{s.thinking=false}\n    }\n    d2.on('.send','click',send)\n    d2.on('.in','keydown',(e)=>{if(e.key==='Enter'&&!e.shiftKey&&!e.isComposing){e.preventDefault();send()}})\n  },\n  updated(d2){const log=d2.$('.log');if(!log)return;const n=log.children.length;if(SEEN.get(d2.root)!==n){SEEN.set(d2.root,n);log.scrollTop=log.scrollHeight}},\n}\n"}},"messages":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"messages"}}}},"tasks":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tasks"}}}},"scribe":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"scribe"}}}},"drive":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"drive"}}}},"me":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"me"}}}}}}}}}},{"_id":"6abefda80484650e9b1b46c0","component":"data2-core-types@Component","system":"6abed5371a6b03943b9618d7","params":{"extends":"data2-core-primitives@Block","component":"kp-art","package":"katia-party","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"// kp-art — estúdio de artes: gera imagens (assistant draw) no estilo da festa e salva numa galeria (Drive + tabela)\n// params: artist (assistant), drive (service), artworks settings (dataset), me (string)\nfunction esc(s){return String(s??'').replace(/[&<>\"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;'}[c]))}\nfunction shiba(cls){return `<svg class=\"${cls||''}\" viewBox=\"0 0 120 110\" aria-hidden=\"true\"><path d=\"M22 50 L30 8 L56 32 Z\" fill=\"#E59A55\"/><path d=\"M29 41 L33 18 L48 33 Z\" fill=\"#F8D7B5\"/><path d=\"M98 50 L90 8 L64 32 Z\" fill=\"#E59A55\"/><path d=\"M91 41 L87 18 L72 33 Z\" fill=\"#F8D7B5\"/><ellipse cx=\"60\" cy=\"62\" rx=\"44\" ry=\"40\" fill=\"#E59A55\"/><path d=\"M24 70 Q30 99 60 103 Q90 99 96 70 Q84 58 72 66 Q60 74 48 66 Q36 58 24 70Z\" fill=\"#FFF4E8\"/><ellipse cx=\"44\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><ellipse cx=\"76\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><ellipse cx=\"44\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><ellipse cx=\"76\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><circle cx=\"45.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/><circle cx=\"77.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/><path d=\"M54 72 Q60 68 66 72 Q63 78 60 78 Q57 78 54 72Z\" fill=\"#3B2A2E\"/><path d=\"M52 83 Q56 88 60 83 Q64 88 68 83\" stroke=\"#3B2A2E\" stroke-width=\"2.4\" fill=\"none\" stroke-linecap=\"round\"/><ellipse cx=\"32\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/><ellipse cx=\"88\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/></svg>`}\nconst recs=(d2,k)=>{const h=d2.data(k);return h?h.records()||[]:[]}\nconst toast=(d2,m)=>d2.bus.emit('kp:toast',m)\nconst stamp=(r)=>r.createdAt?new Date(r.createdAt).getTime():Number.MAX_SAFE_INTEGER\nconst PRESETS=[\n  ['💌 Convite','Elegant birthday invitation background for \"Katia 33\", pastel blush pink and cream watercolor flowers, soft balloons, delicate gold accents, lots of empty space in the center for text'],\n  ['🐕 Shiba festeira','A cute smiling Shiba Inu wearing a tiny pink party hat next to a pastel birthday cake with candles \"33\", soft watercolor, pastel pink background'],\n  ['📸 Painel de fotos','Photo booth backdrop design, pastel pink balloon garland arch, cream and peach tones, dreamy, elegant, outdoor farm party'],\n  ['🎂 Topo de bolo','Cake topper illustration \"33\" in soft pastel pink with tiny flowers and a small Shiba Inu silhouette, flat pastel style, white background'],\n  ['🌸 Mesa posta','Inspiration board of a pastel pink birthday dessert table at a countryside farm, lace tablecloths, macarons, flowers, balloons'],\n  ['🏡 Sítio','Whimsical watercolor illustration of a countryside farm with a lake and a white party tent decorated with pastel pink balloons at golden hour'],\n]\n// 💌 compositor do convite: arte (cover) + título + cartão com infos → 1080×1350\nconst DRAWN=new WeakMap()\nfunction partyOf(d2){return {p:d2.state.party||{}}} // infos da festa vêm do Rush rsvp-get (leitura) e party-set (gravação)\nfunction rr(c,x,y,w,h,r){c.beginPath();c.moveTo(x+r,y);c.arcTo(x+w,y,x+w,y+h,r);c.arcTo(x+w,y+h,x,y+h,r);c.arcTo(x,y+h,x,y,r);c.arcTo(x,y,x+w,y,r);c.closePath()}\nfunction fit(c,t,max,size,weight,fam){let s=size;do{c.font=`${weight} ${s}px ${fam}`;if(c.measureText(t).width<=max)break;s-=2}while(s>18);return s}\nasync function drawInvite(cv,url,p){const c=cv.getContext('2d'),W=1080,H=1350\n  try{await Promise.all(['600 130px Fredoka','500 36px Fredoka','800 44px Nunito','700 30px Nunito'].map(f=>document.fonts.load(f)))}catch(e){}\n  c.fillStyle='#FFF7F5';c.fillRect(0,0,W,H)\n  if(url){const img=new Image();img.crossOrigin='anonymous';img.src=url;try{await img.decode();const k=Math.max(W/img.width,H/img.height),w=img.width*k,h=img.height*k;c.drawImage(img,(W-w)/2,(H-h)/2,w,h)}catch(e){}}\n  const g=c.createLinearGradient(0,0,0,420);g.addColorStop(0,'rgba(255,247,245,.85)');g.addColorStop(1,'rgba(255,247,245,0)');c.fillStyle=g;c.fillRect(0,0,W,420)\n  c.textAlign='center';c.fillStyle='#8E4258';c.shadowColor='rgba(255,255,255,.95)';c.shadowBlur=18\n  c.font=\"500 36px Fredoka\";c.fillText('V E M   C O M E M O R A R',W/2,96)\n  c.font=\"600 132px Fredoka\";c.fillText('Katia faz 33',W/2,236);c.shadowBlur=0\n  const y0=800;c.fillStyle='rgba(255,255,255,.93)';rr(c,56,y0,W-112,H-y0-50,44);c.fill();c.strokeStyle='#F3DDE0';c.lineWidth=3;c.stroke()\n  c.textAlign='left';c.fillStyle='#4A3439';let y=y0+80\n  const line=(t,size,weight,color)=>{c.fillStyle=color||'#4A3439';fit(c,t,W-200,size,weight,'Nunito');c.fillText(t,100,y)}\n  line('📅  '+(p.dateLabel||'Domingo, 15 de novembro'),46,800);y+=66\n  line('🕛  '+(p.time||'Perto do almoço (horário a confirmar)'),40,800);y+=64\n  line('📍  '+(p.place||'Sítio Recanto dos Lagos')+' · '+String(p.city||'Mogi das Cruzes').split(' - ')[0],38,800);y+=58\n  c.strokeStyle='#F3DDE0';c.lineWidth=2;c.beginPath();c.moveTo(100,y-24);c.lineTo(W-100,y-24);c.stroke();y+=18\n  line('👟 calçado pra terra e pedra   👙 tem piscina!',30,700,'#7A5560');y+=44\n  line('🧴 protetor e repelente   ☀️ torce pelo sol!',30,700,'#7A5560');y+=58\n  const pill='Confirme até '+(p.rsvpDeadlineLabel||'20/10')+' pelo seu link 💌';c.font=\"800 32px Nunito\";const pw=c.measureText(pill).width+64\n  c.fillStyle='#D9879A';rr(c,(W-pw)/2,y-46,pw,64,32);c.fill();c.fillStyle='#fff';c.textAlign='center';c.fillText(pill,W/2,y-4)}\nfunction urlFrom(r){try{if(r&&r.data&&r.data[0])return r.data[0].url||r.data[0].b64_json&&('data:image/png;base64,'+r.data[0].b64_json);if(typeof r==='string'){const j=JSON.parse(r);return j.data&&j.data[0]&&j.data[0].url}}catch(e){}return typeof r==='string'&&/^(https?:|data:image)/.test(r)?r:''}\n\nexport default {\n  css:`\n:host{--bg:#FFF7F5;--card:#FFFFFF;--blush-50:#FFF1F2;--blush-100:#FDE4E7;--blush-200:#F9CDD4;--blush-300:#F2AEBA;--rose:#D9879A;--rose-deep:#B8647A;--ink:#4A3439;--muted:#94797E;--line:#F3DDE0;--peach:#FDE3D3;--lilac:#ECE3F6;--lilac-ink:#6B5390;--shadow:0 6px 24px rgba(184,100,122,.12)}\n*{box-sizing:border-box}\n.wrap{height:100%;overflow:auto;padding:28px clamp(16px,3vw,40px) 90px;font-family:'Nunito',system-ui,sans-serif;color:var(--ink)}\n.inner{max-width:1120px;margin:0 auto;display:grid;gap:18px}\nh2{font:600 30px/1 'Fredoka';margin:0}\n.sub{margin:6px 0 0;color:var(--muted);font-weight:700;font-size:14px}\n.studio{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:16px}\n.card{background:var(--card);border:1px solid var(--line);border-radius:24px;padding:18px;box-shadow:var(--shadow);min-width:0}\ntextarea{width:100%;min-height:130px;resize:vertical;border:1.5px solid var(--line);background:var(--blush-50);border-radius:14px;padding:12px 14px;font:600 15px 'Nunito';color:var(--ink);outline:none}\ntextarea:focus{border-color:var(--blush-300);background:#fff}\n.pre{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0 14px}\n.pre button{border:1.5px solid var(--line);background:#fff;border-radius:999px;padding:7px 12px;font:700 13px 'Nunito';cursor:pointer;color:var(--ink)}\n.pre button:hover{border-color:var(--blush-300)}\n.btn{border:0;border-radius:14px;padding:12px 18px;font:600 15px 'Fredoka';cursor:pointer;background:linear-gradient(135deg,#E79AAB,#D9879A);color:#fff;box-shadow:0 6px 16px rgba(217,135,154,.3)}\n.btn[disabled]{opacity:.55}.ghost{border:1.5px solid var(--line);background:#fff;color:var(--ink);box-shadow:none}\n.row{display:flex;gap:8px;flex-wrap:wrap;align-items:center}\n.canvas{aspect-ratio:1;border-radius:20px;background:repeating-linear-gradient(45deg,#FFF1F2 0 14px,#FFF7F5 14px 28px);display:grid;place-items:center;overflow:hidden;position:relative;border:1px solid var(--line)}\n.canvas img{width:100%;height:100%;object-fit:cover}\n.canvas .ph{text-align:center;color:var(--muted);font-weight:700;padding:20px}\n.canvas .ph svg{width:90px;height:82px}\n.paint svg{width:96px;height:88px;animation:wig 1s ease-in-out infinite}\n@keyframes wig{0%,100%{transform:rotate(-8deg)}50%{transform:rotate(8deg)}}\n.gal{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px}\n.art{position:relative;border-radius:18px;overflow:hidden;aspect-ratio:1;background:var(--blush-50);border:1px solid var(--line);cursor:zoom-in}\n.art img{width:100%;height:100%;object-fit:cover;display:block}\n.art .cap{position:absolute;left:0;right:0;bottom:0;padding:22px 10px 8px;background:linear-gradient(transparent,rgba(74,52,57,.7));color:#fff;font-size:11px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.zoom{position:fixed;inset:0;background:rgba(74,52,57,.8);display:grid;place-items:center;z-index:80;padding:16px}\n.zoom .box{max-width:min(900px,100%);max-height:100%;display:grid;gap:10px;justify-items:center}\n.zoom img{max-width:100%;max-height:75vh;border-radius:16px}\n.zoom p{color:#fff;font-weight:700;font-size:13px;margin:0;text-align:center;max-width:700px}\n.empty{text-align:center;color:var(--muted);font-weight:700;padding:26px 10px;border:2px dashed var(--line);border-radius:22px;background:#fff}\n.inv{display:grid;gap:12px}.invgrid{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:16px;align-items:start}.thumbs{display:grid;grid-template-columns:repeat(auto-fill,minmax(92px,1fr));gap:8px}.th{width:100%;aspect-ratio:1;object-fit:cover;border-radius:12px;cursor:pointer;border:3px solid transparent;display:block}.th.on{border-color:#D9879A}.prev canvas{width:100%;height:auto;border-radius:16px;box-shadow:0 10px 30px rgba(184,100,122,.2);display:block}.tm{flex:1;min-width:200px;border:1.5px solid var(--line);border-radius:12px;padding:10px 12px;font:600 14px 'Nunito';color:var(--ink)}.inuse{font-weight:800;font-size:13px;color:#4F7A57}\n@media (max-width:820px){.invgrid{grid-template-columns:1fr}.studio{grid-template-columns:1fr}.wrap{padding-top:18px}h2{font-size:26px}.gal{grid-template-columns:repeat(2,minmax(0,1fr))}}\n`,\n  render(d2){\n    const s=d2.state\n    const arts=recs(d2,'artworks').slice().sort((a,b)=>stamp(b)-stamp(a))\n    const z=s.zoom&&arts.find(a=>a._id===s.zoom)\n    return `<div class=\"wrap\"><div class=\"inner\">\n      <div><h2>Estúdio de artes 🎨</h2><p class=\"sub\">Gere artes no clima da festa (rosa pastel + shiba) pra convite, painel, topo de bolo… e salve na galeria.</p></div>\n      <div class=\"studio\">\n        <div class=\"card\">\n          <textarea class=\"prompt\" placeholder=\"Descreva a arte (pode ser em português)…\">${esc(s.prompt||'')}</textarea>\n          <div class=\"pre\">${PRESETS.map((p,i)=>`<button data-p=\"${i}\">${p[0]}</button>`).join('')}</div>\n          <div class=\"row\"><button class=\"btn draw\" ${s.busy?'disabled':''}>${s.busy?'Pintando…':'✨ Desenhar'}</button>${s.img&&!s.saved?`<button class=\"btn ghost save\" ${s.saving?'disabled':''}>${s.saving?'Salvando…':'💾 Salvar na galeria'}</button>`:''}${s.img?`<a class=\"btn ghost\" href=\"${esc(s.img)}\" download=\"katia33-arte.png\" target=\"_blank\" rel=\"noopener\" style=\"text-decoration:none\">⬇️ Baixar</a>`:''}</div>\n          ${s.err?`<p class=\"sub\" style=\"color:#B4475F\">${esc(s.err)}</p>`:''}\n        </div>\n        <div class=\"canvas\">${s.busy?`<div class=\"ph paint\">${shiba()}<div>o Milo tá pintando… 🖌️</div></div>`:s.img?`<img src=\"${esc(s.img)}\" alt=\"arte gerada\"/>`:`<div class=\"ph\">${shiba()}<div>Sua arte aparece aqui</div></div>`}</div>\n      </div>\n      ${(()=>{const inv=arts.filter(a=>a.tag==='convite'),{p}=partyOf(d2),sel=s.invArt||(inv.find(a=>a.url===p.inviteArt)||inv[0]||{})._id\n        if(!inv.length)return ''\n        return `<div class=\"card inv\"><div class=\"row\" style=\"justify-content:space-between\"><h2 style=\"font-size:22px\">💌 Convite pronto</h2>${p.inviteImage?'<span class=\"inuse\">✓ já tem um convite em uso</span>':'<span class=\"sub\">escolha a arte · o texto entra por cima</span>'}</div>\n          <div class=\"invgrid\"><div style=\"display:grid;gap:12px;align-content:start\"><div class=\"thumbs\">${inv.map(a=>`<img class=\"th ${a._id===sel?'on':''}\" data-id=\"${esc(a._id)}\" src=\"${esc(a.url)}\" alt=\"\" title=\"${esc(a.prompt||'')}\"/>`).join('')}</div>\n            <div class=\"row\"><input class=\"tm\" value=\"${esc(p.time||'')}\" placeholder=\"Horário (ex.: a partir das 12h)\"/><button class=\"btn ghost savetm\">Salvar horário</button></div>\n            <div class=\"row\"><button class=\"btn dlinv\">⬇️ Baixar imagem</button><button class=\"btn ghost useinv\" ${s.saving?'disabled':''}>${s.saving?'Salvando…':'⭐ Usar no convite'}</button></div>\n            <p class=\"sub\" style=\"margin:0\">\"Usar no convite\" coloca essa imagem na página de cada convidado e no envio pelo 📲 da lista.</p></div>\n          <div class=\"prev\" data-d2-static><canvas class=\"invc\" width=\"1080\" height=\"1350\"></canvas></div></div></div>`})()}\n      <div class=\"row\" style=\"justify-content:space-between\"><h2 style=\"font-size:22px\">Galeria</h2><span class=\"sub\">${arts.length} arte${arts.length===1?'':'s'}</span></div>\n      ${arts.length?`<div class=\"gal\">${arts.map((a,i)=>`<div class=\"art\" data-key=\"${esc(a._id||'pa'+i)}\" data-id=\"${esc(a._id)}\"><img src=\"${esc(a.url)}\" loading=\"lazy\" alt=\"\"/><div class=\"cap\">${esc(a.by||'')} · ${esc(a.prompt||'')}</div></div>`).join('')}</div>`:`<div class=\"empty\">🐕💤 Nenhuma arte salva ainda.</div>`}\n    </div>\n    ${z?`<div class=\"zoom\"><div class=\"box\"><img src=\"${esc(z.url)}\"/><p>${esc(z.prompt||'')}</p><div class=\"row\"><a class=\"btn\" href=\"${esc(z.url)}\" target=\"_blank\" rel=\"noopener\" style=\"text-decoration:none\">Abrir</a><button class=\"btn ghost del\" data-id=\"${esc(z._id)}\">Excluir</button><button class=\"btn ghost close\">Fechar</button></div></div></div>`:''}\n    </div>`\n  },\n  updated(d2){const cv=d2.$('.invc');if(!cv)return;const A=d2.data('artworks');const inv=((A&&A.records())||[]).filter(a=>a.tag==='convite');const {p}=partyOf(d2)\n    const on=d2.$('.th.on'),art=(on&&inv.find(a=>a._id===on.dataset.id))||inv[0];if(!art)return\n    const key=art.url+'|'+(p.time||'');if(DRAWN.get(d2.root)===key&&cv.dataset.drawn===key)return;DRAWN.set(d2.root,key);cv.dataset.drawn=key;drawInvite(cv,art.url,p)},\n  mounted(d2){\n    const s=d2.state,A=()=>d2.data('artworks')\n    d2.on('.pre button','click',(e,el)=>{const t=d2.$('.prompt');if(t)t.value=PRESETS[Number(el.dataset.p)][1]})\n    d2.on('.draw','click',async()=>{const t=d2.$('.prompt');const p=(t&&t.value||'').trim();if(!p)return\n      d2.setState({busy:true,err:'',img:'',saved:false,prompt:p})\n      try{const r=await d2.assistant(d2.param('artist')).draw(p);let u=urlFrom(r)\n        if(!u){const a=d2.assistant(d2.param('artist'));u=urlFrom(a.answer)}\n        if(!u)throw new Error('sem imagem');d2.setState({img:u})}\n      catch(err){d2.setState({err:'Não consegui desenhar agora 😕 tenta de novo ou muda a descrição.'})}\n      finally{d2.setState({busy:false})}})\n    d2.on('.save','click',async()=>{if(!s.img)return;s.saving=true\n      try{let url=s.img\n        if(url.startsWith('data:')){const [meta,b64]=url.split(',')\n          const r=await d2.rush('upload-file').invoke({base64:b64,contentType:(meta.match(/data:(.*?);/)||[])[1]||'image/png',fileName:`arte-${Date.now()}.png`})\n          const d=r&&r.data?r.data:r;url=(d&&d.url)||url}\n        else{try{const out=await d2.drive(d2.param('drive')).uploadFromUrls([url]);url=(out&&out[0]&&(out[0].fileUrl||out[0].url))||url}catch(e){}}\n        await A().create({prompt:s.prompt,url,by:d2.param('me')||'',tag:''});d2.setState({saved:true});toast(d2,'Arte salva na galeria 🎨')}\n      catch(err){toast(d2,'Não consegui salvar 😕')}finally{s.saving=false}})\n    d2.on('.art','click',(e,el)=>{s.zoom=el.dataset.id})\n    d2.on('.th','click',(e,el)=>{s.invArt=el.dataset.id})\n    const curArt=()=>{const inv=A().records().filter(a=>a.tag==='convite'),on=d2.$('.th.on');return (on&&inv.find(a=>a._id===on.dataset.id))||inv[0]}\n    const saveParty=async(patch)=>{const r=await d2.rush('party-set').invoke({patch});const d=r&&r.data?r.data:r;if(d&&d.party)d2.state.party=d.party}\n    ;(async()=>{try{const r=await d2.rush('rsvp-get').invoke({c:''});const d=r&&r.data?r.data:r;d2.state.party=(d&&d.party)||{}}catch(e){}})()\n    d2.on('.savetm','click',async()=>{const v=(d2.$('.tm')||{}).value||'';await saveParty({time:v.trim()});DRAWN.delete(d2.root);d2.refresh();toast(d2,'Horário salvo 🕛')})\n    d2.on('.dlinv','click',()=>{const cv=d2.$('.invc');if(!cv)return;cv.toBlob(b=>{const a=document.createElement('a');a.href=URL.createObjectURL(b);a.download='convite-katia-33.jpg';a.click();setTimeout(()=>URL.revokeObjectURL(a.href),4000)},'image/jpeg',.92)})\n    d2.on('.useinv','click',async()=>{const cv=d2.$('.invc'),art=curArt();if(!cv||!art)return;s.saving=true\n      try{const b=await new Promise(r=>cv.toBlob(r,'image/jpeg',.9));const f=new File([b],'convite-katia-33.jpg',{type:'image/jpeg'})\n        let url='';try{const up=await d2.drive(d2.param('drive')).upload([f]);url=(up&&up[0]&&(up[0].fileUrl||up[0].url))||''}catch(e){}\n        if(!url)throw new Error('upload')\n        await saveParty({inviteImage:url,inviteArt:art.url});toast(d2,'Convite definido ⭐ já aparece pros convidados 💌')}\n      catch(e){toast(d2,'Não consegui salvar o convite 😕')}finally{s.saving=false}})\n    d2.on('.close','click',()=>{s.zoom=null})\n    d2.on('.zoom','click',(e)=>{if(e.target.classList.contains('zoom'))s.zoom=null})\n    d2.on('.del','click',async(e,el)=>{const a=A().records().find(r=>r._id===el.dataset.id);if(!a)return;if(!await d2.dialog.confirm('Excluir essa arte?'))return;await A().remove(a);s.zoom=null})\n  },\n}\n"}},"artist":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"artist"}}}},"drive":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"drive"}}}},"artworks":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"artworks"}}}},"me":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"me"}}}}}}}}}},{"_id":"6ac06ecdf716dbfbc7dde26a","component":"data2-core-types@Component","system":"6abed5371a6b03943b9618d7","params":{"extends":"data2-core-primitives@Block","component":"kp-invite","package":"katia-party","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"// kp-invite — página PÚBLICA do convite + RSVP individual (?c=TOKEN).\n// Fala só com os Rush públicos `rsvp-get` / `rsvp-answer` (token aleatório por convidado). Sem params.\nfunction esc(s){return String(s??'').replace(/[&<>\"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;'}[c]))}\nfunction fonts(){try{if(document.getElementById('kp-fonts'))return;const l=document.createElement('link');l.id='kp-fonts';l.rel='stylesheet';l.href='https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&family=Nunito:wght@400;600;700;800&display=swap';document.head.appendChild(l)}catch(e){}}\nfunction shiba(cls){return `<svg class=\"${cls||''}\" viewBox=\"0 0 120 110\" aria-hidden=\"true\"><path d=\"M22 50 L30 8 L56 32 Z\" fill=\"#E59A55\"/><path d=\"M29 41 L33 18 L48 33 Z\" fill=\"#F8D7B5\"/><path d=\"M98 50 L90 8 L64 32 Z\" fill=\"#E59A55\"/><path d=\"M91 41 L87 18 L72 33 Z\" fill=\"#F8D7B5\"/><ellipse cx=\"60\" cy=\"62\" rx=\"44\" ry=\"40\" fill=\"#E59A55\"/><path d=\"M24 70 Q30 99 60 103 Q90 99 96 70 Q84 58 72 66 Q60 74 48 66 Q36 58 24 70Z\" fill=\"#FFF4E8\"/><ellipse cx=\"44\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><ellipse cx=\"76\" cy=\"45\" rx=\"6\" ry=\"4\" fill=\"#FFF4E8\"/><ellipse cx=\"44\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><ellipse cx=\"76\" cy=\"58\" rx=\"4.5\" ry=\"5.5\" fill=\"#3B2A2E\"/><circle cx=\"45.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/><circle cx=\"77.5\" cy=\"56\" r=\"1.5\" fill=\"#fff\"/><path d=\"M54 72 Q60 68 66 72 Q63 78 60 78 Q57 78 54 72Z\" fill=\"#3B2A2E\"/><path d=\"M52 83 Q56 88 60 83 Q64 88 68 83\" stroke=\"#3B2A2E\" stroke-width=\"2.4\" fill=\"none\" stroke-linecap=\"round\"/><ellipse cx=\"32\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/><ellipse cx=\"88\" cy=\"74\" rx=\"7\" ry=\"4.5\" fill=\"#F4A7B5\" opacity=\".75\"/></svg>`}\nconst first=(n)=>String(n||'').split(' (')[0].trim()\nconst CAL='https://calendar.google.com/calendar/render?action=TEMPLATE&text='+encodeURIComponent('Aniversário da Katia 🎂 (33)')+'&dates=20261115/20261116&location='+encodeURIComponent('Sítio Recanto dos Lagos, Av. Joaquim Pereira de Carvalho, 985 - Volta Fria, Mogi das Cruzes - SP')+'&details='+encodeURIComponent('Horário perto do almoço (a confirmar). Leve roupa de banho, protetor e repelente!')\n\nexport default {\n  css:`\n:host{--bg:#FFF7F5;--card:#FFFFFF;--blush-50:#FFF1F2;--blush-100:#FDE4E7;--blush-200:#F9CDD4;--blush-300:#F2AEBA;--rose:#D9879A;--rose-deep:#B8647A;--ink:#4A3439;--muted:#94797E;--line:#F3DDE0;--sage:#DCEBDD;--sage-ink:#4F7A57;--butter:#FFF2C9;--butter-ink:#8A6D1F;--shadow:0 6px 24px rgba(184,100,122,.12)}\n*{box-sizing:border-box}\n.page{height:100%;overflow:auto;font-family:'Nunito',system-ui,sans-serif;color:var(--ink);background:radial-gradient(900px 500px at 0 0,#FDE4E7,transparent 60%),radial-gradient(800px 500px at 100% 100%,#FDE3D3,transparent 55%),var(--bg);padding:22px 16px 120px}\n.card{max-width:480px;margin:0 auto;background:var(--card);border:1px solid var(--line);border-radius:28px;box-shadow:0 20px 60px rgba(184,100,122,.18);overflow:hidden}\n.art{position:relative;aspect-ratio:1;background:linear-gradient(135deg,#FBD3DB,#FDE3D3 60%,#FFF2C9)}\n.art img{width:100%;height:100%;object-fit:cover;display:block}\n.art.r45{aspect-ratio:4/5}\n.art .ov{position:absolute;left:0;right:0;top:9%;text-align:center;color:#8E4258;text-shadow:0 1px 10px rgba(255,255,255,.95)}\n.ov small{font:500 13px 'Fredoka';letter-spacing:3px}\n.ov b{display:block;font:600 46px/1 'Fredoka';margin:6px 0}\n.ov span{font:800 13px 'Nunito'}\n.body{padding:22px 22px 26px;display:grid;gap:16px}\nh1{font:600 26px/1.15 'Fredoka';margin:0;color:var(--rose-deep)}\n.lead{margin:0;font-size:16px;font-weight:700;line-height:1.45}\n.info{display:grid;gap:10px;background:var(--blush-50);border-radius:20px;padding:14px 16px}\n.info div{display:flex;gap:10px;align-items:flex-start;font-weight:700;font-size:15px;line-height:1.35}\n.info div span:first-child{font-size:18px;width:24px;text-align:center;flex:none}\n.info small{display:block;font-weight:600;color:var(--muted);font-size:13px}\n.links{display:flex;gap:8px;flex-wrap:wrap}\n.lnk{flex:1;min-width:150px;text-align:center;border:1.5px solid var(--line);background:#fff;border-radius:14px;padding:10px 12px;font:700 14px 'Nunito';color:var(--rose-deep);text-decoration:none}\n.tips{display:grid;gap:8px}\n.tips h3,.rsvp h3{font:600 18px 'Fredoka';margin:0}\n.tip{background:#fff;border:1px dashed var(--blush-300);border-radius:14px;padding:10px 12px;font-weight:700;font-size:14px;line-height:1.4}\n.rsvp{display:grid;gap:10px;border-top:1px solid var(--line);padding-top:16px}\n.dl{font-size:13px;font-weight:800;color:var(--butter-ink);background:var(--butter);border-radius:10px;padding:6px 10px;justify-self:start}\n.btns{display:grid;grid-template-columns:1fr 1fr;gap:10px}\n.btn{border:0;border-radius:16px;padding:15px 10px;font:600 17px 'Fredoka';cursor:pointer;color:#fff;background:linear-gradient(135deg,#E79AAB,#D9879A);box-shadow:0 8px 20px rgba(217,135,154,.35)}\n.btn.no{background:#fff;color:var(--ink);border:1.5px solid var(--line);box-shadow:none}\n.btn[disabled]{opacity:.6}\ntextarea{width:100%;min-height:70px;resize:vertical;border:1.5px solid var(--line);background:var(--blush-50);border-radius:14px;padding:10px 12px;font:600 14px 'Nunito';color:var(--ink);outline:none}\ntextarea:focus{border-color:var(--blush-300);background:#fff}\n.done{border-radius:18px;padding:16px;text-align:center;font-weight:800;font-size:16px;line-height:1.4}\n.done.yes{background:var(--sage);color:var(--sage-ink)}.done.no{background:#EFE7E8;color:#7A6468}\n.done small{display:block;margin-top:6px;font-weight:700;font-size:13px;opacity:.85}\n.change{border:0;background:none;color:var(--rose-deep);font:800 13px 'Nunito';cursor:pointer;text-decoration:underline}\n.sign{text-align:center;color:var(--muted);font-weight:700;font-size:13px}\n.err{text-align:center;font-weight:700;color:var(--muted);padding:6px}\n.load{display:grid;place-items:center;height:60vh;color:var(--muted);font-weight:800}\n.load svg{width:90px;height:82px;animation:wig 1s ease-in-out infinite}\n@keyframes wig{0%,100%{transform:rotate(-8deg)}50%{transform:rotate(8deg)}}\n.milo{position:fixed;right:14px;bottom:-12px;width:80px;height:73px;cursor:pointer;z-index:5;transition:transform .35s cubic-bezier(.3,1.6,.5,1);filter:drop-shadow(0 -4px 10px rgba(184,100,122,.18))}\n.milo:hover,.milo.up{transform:translateY(-16px) rotate(-6deg)}\n.bub{position:fixed;right:96px;bottom:40px;max-width:min(260px,calc(100vw - 120px));background:#fff;border:1px solid var(--line);border-radius:16px 16px 4px 16px;padding:9px 13px;font:600 14px 'Fredoka';color:var(--rose-deep);box-shadow:var(--shadow);z-index:6}\n.conf{position:fixed;top:-30px;font-size:22px;pointer-events:none;animation:fall linear forwards;z-index:9}\n@keyframes fall{to{transform:translateY(110vh) rotate(360deg)}}\n`,\n  render(d2){\n    const s=d2.state\n    if(!s.loaded)return `<div class=\"page\"><div class=\"load\"><div>${shiba()}<div>abrindo seu convite… 💌</div></div></div></div>`\n    const p=s.party||{},ok=s.ok,name=first(s.name)\n    const img=p.inviteImage?`<img src=\"${esc(p.inviteImage)}\" alt=\"Convite\"/>`\n      :`${p.inviteArt?`<img src=\"${esc(p.inviteArt)}\" alt=\"\"/>`:''}<div class=\"ov\"><small>VEM COMEMORAR</small><b>Katia faz 33</b><span>domingo · 15.11.2026</span></div>`\n    const past=p.rsvpDeadline&&Date.now()>new Date(p.rsvpDeadline+'T23:59:59-03:00').getTime()\n    let rsvp=''\n    if(ok){\n      if(s.status==='confirmado'&&!s.editing)rsvp=`<div class=\"done yes\">Oba! Presença confirmada 🎉<small>${s.note?`Seu recado: “${esc(s.note)}”`:'Mal podemos esperar pra te ver!'}</small></div><button class=\"change\">mudar minha resposta</button>`\n      else if(s.status==='não vem'&&!s.editing)rsvp=`<div class=\"done no\">Poxa, que pena! 😢<small>Obrigado por avisar. Se os planos mudarem, é só responder de novo.</small></div><button class=\"change\">mudar minha resposta</button>`\n      else rsvp=`<span class=\"dl\">${past?'O prazo era até '+esc(p.rsvpDeadlineLabel||'')+', mas ainda dá pra avisar 💗':'Confirme até '+esc(p.rsvpDeadlineLabel||'20/10')}</span>\n        <textarea class=\"note\" placeholder=\"Quer deixar um recado pra Katia? (opcional)\">${esc(s.note||'')}</textarea>\n        <div class=\"btns\"><button class=\"btn yes\" ${s.busy?'disabled':''}>Eu vou! 🎉</button><button class=\"btn no\" ${s.busy?'disabled':''}>Não vou conseguir 😢</button></div>`\n    }\n    return `<div class=\"page\"><div class=\"card\">\n      <div class=\"art ${p.inviteImage?'r45':''}\">${img}</div>\n      <div class=\"body\">\n        <h1>${ok&&name?`Oi, ${esc(name)}! 💗`:'Oi! 💗'}</h1>\n        <p class=\"lead\">A Katia vai fazer 33 anos e a gente quer muito você lá pra comemorar junto! 🎂</p>\n        <div class=\"info\">\n          <div><span>📅</span><span>${esc(p.dateLabel||'Domingo, 15 de novembro')}</span></div>\n          <div><span>🕛</span><span>${esc(p.time||'Perto do almoço (horário a confirmar)')}</span></div>\n          <div><span>📍</span><span>${esc(p.place||'Sítio Recanto dos Lagos')}<small>${esc(p.address||'')}</small></span></div>\n        </div>\n        <div class=\"links\">${p.maps?`<a class=\"lnk\" href=\"${esc(p.maps)}\" target=\"_blank\" rel=\"noopener\">🗺️ Abrir no mapa</a>`:''}<a class=\"lnk\" href=\"${CAL}\" target=\"_blank\" rel=\"noopener\">🗓️ Salvar na agenda</a></div>\n        ${(p.tips||[]).length?`<div class=\"tips\"><h3>Pra aproveitar bem ☀️</h3>${p.tips.map(t=>`<div class=\"tip\">${esc(t)}</div>`).join('')}</div>`:''}\n        ${ok?`<div class=\"rsvp\"><h3>Você vem? 💌</h3>${rsvp}</div>`:`<div class=\"err\">Esse convite é pessoal 💌 Use o link que a Katia ou o Danilo te mandaram pra confirmar presença.</div>`}\n        ${s.err?`<div class=\"err\">${esc(s.err)}</div>`:''}\n        <div class=\"sign\">Com carinho, Katia e Danilo 💗 (e o Milo 🐕)</div>\n      </div></div>\n      ${s.bark?`<div class=\"bub\">${esc(s.bark)}</div>`:''}\n      ${shiba('milo'+(s.bark?' up':''))}\n    </div>`\n  },\n  mounted(d2){\n    fonts()\n    const s=d2.state\n    let c='';try{c=new URLSearchParams(window.location.search).get('c')||''}catch(e){}\n    s.c=c\n    ;(async()=>{try{const r=await d2.rush('rsvp-get').invoke({c});const d=r&&r.data?r.data:r\n      d2.setState({loaded:true,ok:!!(d&&d.ok),name:d&&d.name,status:d&&d.status,note:(d&&d.note&&d.note!=='undefined')?d.note:'',party:(d&&d.party)||{}})}\n    catch(e){d2.setState({loaded:true,ok:false,party:{},err:'Não consegui abrir o convite agora 😕 tenta de novo daqui a pouquinho.'})}})()\n    const party=()=>{for(let i=0;i<30;i++){const h=document.createElement('div');h.className='conf';h.textContent=['🎉','💗','🎈','🐾','🎂','✨'][i%6];h.style.left=Math.random()*100+'vw';h.style.animationDuration=(2.4+Math.random()*2.4)+'s';h.style.animationDelay=(Math.random()*1)+'s';d2.root.appendChild(h);setTimeout(()=>h.remove(),6000)}}\n    const answer=async(a)=>{const ta=d2.$('.note');const note=(ta&&ta.value||'').trim().slice(0,500)\n      d2.setState({busy:true,err:''})\n      try{const r=await d2.rush('rsvp-answer').invoke({c:s.c,answer:a,note});const d=r&&r.data?r.data:r\n        if(!d||!d.ok)throw new Error('x')\n        d2.setState({status:d.status,note,editing:false});if(a==='sim')party()}\n      catch(e){d2.setState({err:'Ops, não consegui salvar sua resposta 😕 tenta de novo?'})}\n      finally{d2.setState({busy:false})}}\n    d2.on('.btn.yes','click',()=>answer('sim'))\n    d2.on('.btn.no','click',()=>answer('nao'))\n    d2.on('.change','click',()=>{s.editing=true})\n    const barks=['Au! Te espero lá! 🐾','Traz petisco? 🦴','Vai ter piscina! 💦','Eu vou estar de gravatinha 🎀','Confirma logo, vai! 🥺']\n    let n=0,tm\n    d2.on('.milo','click',()=>{d2.state.bark=barks[n++%barks.length];clearTimeout(tm);tm=setTimeout(()=>{d2.state.bark=''},2600)})\n  },\n}\n"}}}}}}}},{"_id":"5ed9bed7b9e0891ce913e884","component":"data2-core-types@Component","params":{"package":"data2-core","component":"DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}},{"_id":"5f472ae463c680de4ff296e9","component":"data2-core-types@Component","params":{"package":"data2-core","component":"Data2TableDataSource","extends":"data2-core@DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}}]}},{"reference":"ExternalComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"_id":"5f060d9b1ca96def42f3c40a","displayName":"Builder AuthStrategy","component":"data2-core@AuthenticationStrategy","system":"5e3b796d6228227ca637d0f4","params":{"credentials":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"verifier":{"component":"data2-core-types@DataSetReference","params":{"reference":"UsersDataSet"}},"sessionShared":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"password":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},"email":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},"resetPassword":{"resetEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"nR6Q9d7qdaPtZhJ28Q8Dy"},"component":"data2-core-types@ArtboardReference"}},"resetSuccessEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"yPCJBTKo8q1Mw0B_3Kpwl"},"component":"data2-core-types@ArtboardReference"}}},"session":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"name"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"sessionMetadata":{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},{"params":{"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"active"}},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.status"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is active user"}]},"component":"data2-core-logical-operators@And","displayName":"is active and has _id"}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $user"},{"params":{"action":{"params":{"pattern":{"component":"data2-core-primitives@String","params":{"content":"@data2.app"}},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.email"}}}}},"component":"data2-core-functions@Includes","displayName":"isData2User"},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}},"component":"data2-core-flow@Step"},{"params":{"action":{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.d2_app"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"management"}}]},"component":"data2-core-functions@Includes","displayName":"isData2App Exception"},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}},"component":"data2-core-flow@Step"},{"params":{"resultName":{"component":"data2-core-primitives@String","params":{"content":"has_access"}},"action":{"params":{"compare":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}}},{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}}}]},"component":"data2-core-logical-operators@Or"},"else":{"params":{"actions":[{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $metadata.system"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":"filter","args":[{"_id":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records.length"}}}}},"component":"data2-core-logical-operators@Not","displayName":"systems not found"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check system found"},{"params":{"actions":[{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"organization":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"cursor.current.organization._id"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"}]},"component":"data2-core-flow@Parallel"}]},"component":"data2-core-flow@Series","displayName":"common setup"},{"params":{"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"},"else":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"compare":{"params":{"components":{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"mapper":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"system"}}],"body":{"params":{"expression":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.visibility"}}}},"defaultCase":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"cases":[{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"public"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"billing-owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}},{"component":"data2-core-primitives@String","params":{"content":"member"}}]},"component":"data2-core-functions@Includes","displayName":"has role with access"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"collaborator"}}},"component":"data2-core-comparison-operators@Equal","displayName":"is collaborator"}]},"component":"data2-core-logical-operators@And","displayName":"is org member and collaborator"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is collaborator"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is collaborator and has system access"}]},"component":"data2-core-logical-operators@Or"}}},{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"private"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}}]},"component":"data2-core-functions@Includes","displayName":"is owner/admin"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is owner/admin"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is member and has system access"}]},"component":"data2-core-logical-operators@Or","displayName":"is owner/admin or has system access"}}}]},"component":"data2-core-flow@Switch"}}}},"component":"data2-core-functions@ArrayMap"}},"component":"data2-core-logical-operators@And","displayName":"has org member for all systems in request"}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"}},"component":"data2-core-flow@If"}},"component":"data2-core-flow@Step"},{"params":{"then":{"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"else":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"},"compare":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"has_access"}}}}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"sessionExpiresIn":{"component":"data2-core-primitives@Number","params":{"content":604800}},"sessionRenewal":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"identityProviders":[{"provider":{"component":"data2-core-primitives@String","params":{"content":"GOOGLE"}},"clientId":{"component":"data2-core-primitives@String","params":{"content":"55470861603-22pvfc1t49lp8cjnbfk71s5ct9hp1q1v.apps.googleusercontent.com"}}}]},"reference":"Data2BuilderAuthentication","updatedAt":"2026-08-06T19:31:23.557Z"},{"_id":"5f060ee51ca96def42f3fbd1","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"UsersTableDataSource"}},"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}}},"reference":"UsersDataSet","updatedAt":"2026-03-04T21:16:40.291Z"},{"_id":"68f938cf5fb002e33752a43d","displayName":"InternalApplicationsAuthenticationStrategy","component":"data2-core@AuthenticationStrategy","system":"5e3b796d6228227ca637d0f4","params":{"resetPassword":{"resetEmail":{"artboard":{"params":{"preventEvaluation":true},"component":"data2-core-types@ArtboardReference"}},"resetSuccessEmail":{"artboard":{"params":{"preventEvaluation":true},"component":"data2-core-types@ArtboardReference"}}},"verifier":{"disabled":false,"component":"data2-core-types@DataSetReference","params":{"reference":"InternalApplicationsVerifierDataSet"}},"password":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"secret"}},"credentials":[{"component":"data2-core-types@FieldReference","params":{"key":"application"}},{"component":"data2-core-types@FieldReference","params":{"key":"secret"}},{"component":"data2-core-types@FieldReference","params":{"key":"status"}}],"session":[{"component":"data2-core-types@FieldReference","params":{"key":"application"}},{"component":"data2-core-types@FieldReference","params":{"key":"secret"}},{"component":"data2-core-types@FieldReference","params":{"key":"status"}}]},"reference":"InternalApplicationsAuthenticationStrategy","updatedAt":"2025-10-22T20:08:54.442Z","createdAt":"2025-10-22T20:04:31.198Z"},{"component":"data2-core@DataSet","reference":"SessionsDataSet","params":{"requiresConfirmation":false,"pk":"key","datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"data2sessionsdatasource"}}}},{"reference":"UsersTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@ServerSessionsDataSource","reference":"data2sessionsdatasource","params":{}},{"_id":"5f1600b70528b92601890f75","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ServiceComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ServiceComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:20.208Z","createdAt":"2020-07-20T20:38:15.436Z"},{"_id":"5f1602190528b92601890f7d","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":40000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentInstancesTableDataSource"}},"sort":{"_id":1},"pk":"_id","autoEdit":true,"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:07.089Z","createdAt":"2020-07-20T20:44:09.350Z"},{"_id":"5f16017f0528b92601890f7a","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"clientApplicationDomain"}}},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"FileComponentInstancesDataSet","updatedAt":"2023-08-03T16:08:18.193Z","createdAt":"2020-07-20T20:41:35.797Z"},{"_id":"5f1601990528b92601890f7b","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ApplicationsTableDataSource"}},"pk":"_id","autoEdit":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"params":{"column":"_id"},"component":"data2-core-types@DataSetColumnReference"}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"ApplicationsDataSet","updatedAt":"2022-12-13T21:51:13.995Z","createdAt":"2020-07-20T20:42:01.657Z"},{"_id":"5f16172a0528b92601890f85","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":10000}}},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"DataComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"DataComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:12.831Z","createdAt":"2020-07-20T22:14:02.097Z"},{"_id":"60ddc1bbda3861ca65407c5a","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"clientApplicationDomain"}}},"pagination":{"size":1},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"}},"reference":"OneFileComponentInstancesDataSet","updatedAt":"2022-02-09T19:44:38.036Z","createdAt":"2020-07-20T20:41:35.797Z"},{"_id":"63ee3d38b8c9838c62fb05fb","displayName":"DriveFileComponentInstancesDataSet","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core@Drive"}}},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"DriveFileComponentInstancesDataSet","updatedAt":"2025-12-04T21:58:32.367Z","createdAt":"2023-02-16T14:27:07.797Z"},{"reference":"ServiceComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6abf06d627cc7cea8f5b99c2","component":"data2-rush@HTTPListener","reference":"upload-file","system":"6abed5371a6b03943b9618d7","params":{}},{"_id":"6ac06e29c1d9b5fa79c9fe10","component":"data2-rush@HTTPListener","reference":"rsvp-get","system":"6abed5371a6b03943b9618d7","params":{}},{"_id":"6ac070821a6b03943b9936e0","component":"data2-rush@HTTPListener","reference":"party-set","system":"6abed5371a6b03943b9618d7","params":{}},{"_id":"6ac06e2a6ef68381dfeda8c2","component":"data2-rush@HTTPListener","reference":"rsvp-answer","system":"6abed5371a6b03943b9618d7","params":{}}]}},{"reference":"ComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6ac06ece6ef68381dfeda99a","component":"data2-core-primitives@Artboard","system":"6abed5371a6b03943b9618d7","displayName":"Convite (público)","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Convite (público)"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":480,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"TDHBy9CZxUqyLKzkZx9Nj"},{"_id":"63e25cb982b50416eba918e1","parent":"6ac06ece6ef68381dfeda99a","component":"katia-party@kp-invite","system":"6abed5371a6b03943b9618d7","displayName":"Convite","params":{"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":480,"height":900}}}},"reference":"kHtrgsuaiUuzB6JZn93FA"}]}},{"_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":"6ac06ed76ef68381dfeda9a9","displayName":"Katia Party · Convite","reference":"zPXzjolFIT0SJk5GCvdYo","params":{"domain":{"component":"data2-core-primitives@String","params":{"content":"convite"}},"entryPoint":{"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Artboard","reference":"TDHBy9CZxUqyLKzkZx9Nj"}}},"system":"6abed5371a6b03943b9618d7","component":"data2-core-primitives@Application"}]}},{"reference":"DataComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6abef7e1ea8ac94fb092942e","component":"data2-core@Data2TableDataSource","system":"6abed5371a6b03943b9618d7","params":{"table":"items","schema":[{"component":"data2-core-types@Field","params":{"key":"name","title":"Nome","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"glyph","title":"Emoji","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"status","title":"Status","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"notes","title":"Observações","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"sort","title":"Ordem","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"free","title":"Grátis","component":"data2-core-primitives@Boolean"}}]},"reference":"items"},{"_id":"6abef7e456470c270674b6f8","component":"data2-core@Data2TableDataSource","system":"6abed5371a6b03943b9618d7","params":{"table":"quotes","schema":[{"component":"data2-core-types@Field","params":{"key":"itemId","title":"Item","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"vendor","title":"Fornecedor","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"price","title":"Valor","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"contact","title":"Contato","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"link","title":"Link","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"notes","title":"Observações","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"chosen","title":"Escolhida","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"attachments","title":"Anexos","component":"data2-core-primitives@Array"}}]},"reference":"quotes"},{"_id":"6abef7e6c5d15a59091ad1fa","component":"data2-core@Data2TableDataSource","system":"6abed5371a6b03943b9618d7","params":{"table":"guests","schema":[{"component":"data2-core-types@Field","params":{"key":"name","title":"Nome","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"group","title":"Grupo","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"adults","title":"Adultos","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"kids","title":"Crianças","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"phone","title":"Telefone","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"status","title":"Status","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"notes","title":"Observações","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"num","title":"Nº","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"companionOf","title":"Agregado de (nº)","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"rsvpToken","title":"Token do convite","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"rsvpAt","title":"Respondeu em","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"rsvpNote","title":"Recado","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"invitedAt","title":"Convidado em","component":"data2-core-primitives@String"}}]},"reference":"guests"},{"_id":"6abef7e827cc7cea8f5b6a57","component":"data2-core@Data2TableDataSource","system":"6abed5371a6b03943b9618d7","params":{"table":"tasks","schema":[{"component":"data2-core-types@Field","params":{"key":"title","title":"Título","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"description","title":"Descrição","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"kind","title":"Tipo","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"payload","title":"Dados extraídos","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"key":"attachments","title":"Anexos","component":"data2-core-primitives@Array"}},{"component":"data2-core-types@Field","params":{"key":"status","title":"Status","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"createdBy","title":"Criado por","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"messageId","title":"Mensagem","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"result","title":"Resultado","component":"data2-core-primitives@String"}}]},"reference":"tasks"},{"_id":"6abef7e956470c270674b707","component":"data2-core@Data2TableDataSource","system":"6abed5371a6b03943b9618d7","params":{"table":"settings","schema":[{"component":"data2-core-types@Field","params":{"key":"key","title":"Chave","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"value","title":"Valor","component":"data2-core-primitives@Object"}}]},"reference":"settings"},{"_id":"6abef7e7ba309d7a9facfa3c","component":"data2-core@Data2TableDataSource","system":"6abed5371a6b03943b9618d7","params":{"table":"messages","schema":[{"component":"data2-core-types@Field","params":{"key":"role","title":"Papel","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"author","title":"Autor","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"text","title":"Texto","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"attachments","title":"Anexos","component":"data2-core-primitives@Array"}},{"component":"data2-core-types@Field","params":{"key":"taskId","title":"Task","component":"data2-core-primitives@String"}}]},"reference":"messages"},{"_id":"6abefa4d0484650e9b1b3371","component":"data2-core@Data2TableDataSource","system":"6abed5371a6b03943b9618d7","params":{"table":"artworks","schema":[{"component":"data2-core-types@Field","params":{"key":"prompt","title":"Prompt","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"url","title":"URL","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"by","title":"Autor","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"tag","title":"Uso","component":"data2-core-primitives@String"}}]},"reference":"artworks"}]}},{"reference":"BundlesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}}],"processesParams":{}}}}