{"context":{"domain":"fernando-playground"},"layers":{"ApplicationLayer":{"reference":"ApplicationLayer","availableInstances":[{"reference":"ComponentsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@DataSet","reference":"SystemsDataSet","params":{"filter":{"domain":"data2"},"pagination":{"size":1},"datasource":{"component":"data2-core-types@ProcessReference","params":{"reference":"SystemsDataSource"}}}},{"reference":"ExternalComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"SystemsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"5e3b796d6228227ca637d0f4","name":"data2","domain":"data2","organization":"62292184611f480b3191c37c","visibility":"public","updatedAt":"2026-07-27T14:19:36.810Z"}]}},{"reference":"OrganizationsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"DataComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@DataSet","reference":"OneFileComponentInstancesDataSet","params":{"pagination":{"size":1},"master":{"dataset":{"component":"data2-core-types@ProcessReference","params":{"reference":"SystemsDataSet"}},"localField":"system","masterField":"_id"},"datasource":{"component":"data2-core-types@ProcessReference","params":{"reference":"FileComponentInstancesDataSource"}}}},{"reference":"ApplicationsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"ComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"ServiceComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@Data2TableDataSource","reference":"FileComponentInstancesDataSource","params":{"table":"fileComponentInstances","schema":[{"component":"data2-core-types@Field","params":{"key":"component","title":"Component","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"system","title":"System","component":"data2-core-primitives@ObjectId"}},{"component":"data2-core-types@Field","params":{"key":"displayName","title":"Display Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"params","title":"Params","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"key":"reference","title":"Reference","component":"data2-core-primitives@String"}}]}},{"component":"data2-core@MemoryDataSource","reference":"EmptyDataSource","params":{"initialData":[]}},{"reference":"ComponentsDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"UserComponentsDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"DataComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ServiceComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ExternalComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ApplicationsDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}}],"processesParams":{}},"HostApplicationLayer":{"reference":"HostApplicationLayer","availableInstances":[{"_id":"5f15ff190528b92601890f71","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"SystemsTableDataSource"}},"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"domain"}}},"pk":"_id","fields":[{"component":"data2-core-types@FieldReference","params":{"key":"_id"}},{"component":"data2-core-types@FieldReference","params":{"key":"name"}},{"component":"data2-core-types@FieldReference","params":{"key":"domain"}},{"component":"data2-core-types@FieldReference","params":{"key":"visibility"}},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"customDomains"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization._id"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization.name"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization.billingStatus"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization.publicTrial.active"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"settings.defaultAccessPolicy"}}},"break":true}],"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}},"staticPagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}},"policies":[{"component":"data2-core-auth@Policy","params":{"allow":{"params":{"actions":[{"params":{"components":[{"params":{"query":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$params.query"}}}},"field":{"component":"data2-core-primitives@String","params":{"content":"_id"}},"fieldType":"string"},"component":"data2@7KkQq0vK4a7D2gg6IVJT7"},{"params":{"query":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$params.query"}}}},"field":{"component":"data2-core-primitives@String","params":{"content":"domain"}},"fieldType":"string"},"component":"data2@7KkQq0vK4a7D2gg6IVJT7"},{"params":{"query":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$params.query"}}}},"field":{"component":"data2-core-primitives@String","params":{"content":"customDomains"}},"fieldType":"string"},"component":"data2@7KkQq0vK4a7D2gg6IVJT7"}]},"component":"data2-core-logical-operators@Or"}]},"component":"data2-core-flow@Series"}}}]},"reference":"SystemsDataSet","updatedAt":"2026-08-07T21:51:24.037Z","createdAt":"2020-07-20T20:31:21.838Z"},{"_id":"5f1601ce0528b92601890f7c","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":1000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentsTableDataSource"}},"sort":{"params.package":1,"params.component":1},"pk":"_id","autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"staticFilter":{"system":{"exists":{"params":{"content":false},"component":"data2-core-primitives@Boolean"}}},"filter":{"system":{"exists":{"params":{"content":false},"component":"data2-core-primitives@Boolean"}}}},"reference":"ComponentsDataSet","updatedAt":"2025-11-05T19:37:01.935Z","createdAt":"2020-07-20T20:42:54.898Z"},{"_id":"5f9041dbc8da12be8b94aea4","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":2000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentsTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"UserComponentsDataSet","updatedAt":"2025-11-06T21:06:58.095Z","createdAt":"2020-07-20T20:44:09.350Z"},{"_id":"65d8c4fabc9dbb8f94de8d53","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ExternalComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ExternalComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:23.742Z","createdAt":"2024-02-23T16:17:01.816Z"},{"reference":"SystemsTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"66f6c624d8a4a0c67041a910","name":"Fernando Moreira","domain":"fernando-playground","visibility":"public","settings":{"defaultAccessPolicy":"private"},"updatedAt":"2026-08-14T19:26:29.927Z","createdAt":"2024-09-27T12:56:41.025Z"}]}},{"reference":"ComponentsTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"5f52a278a575399a45d239b4","component":"data2-core-types@Component","params":{"package":"data2-core-primitives","component":"Router","interactions":{"component":"data2-core-types@FieldSet","params":{"fields":{"goBack":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-types@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@This","params":{}},"prop":"history.goBack","args":[]}}}},"icon":{"component":"data2-core-primitives@String","params":{"content":"arrow-left"}},"visibility":"public"}},"goTo":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@This","params":{}},"prop":"history.push","args":[{"component":"data2-core-types@Reference","params":{"reference":"url"}},{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"preserveQuery"}}}}]}},"parameters":[{"component":"data2-core-primitives@String","params":{"content":"url"}},{"component":"data2-core-primitives@String","params":{"content":"preserveQuery"}}]},"break":true},"icon":{"component":"data2-core-primitives@String","params":{"content":"share"}},"visibility":"public","arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Path to route"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Path to redirect user"}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"},{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Boolean"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Preserve Query"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Preserve query string parameters  preserve query parameters on navigating."}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"}]}},"open":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-types@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@This","params":{}},"prop":"history.push","args":[{"pathname":{"component":"data2-core-types@Reference","params":{"reference":"value"}}}]}},"parameters":["value"]}},"icon":{"component":"data2-core-primitives@String","params":{"content":"share"}},"visibility":"public","arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Link to open"}},"description":{"component":"data2-core-primitives@String","params":{"content":""}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"},{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Target"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Where to open the link"}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"oneOf":[{"params":{"content":"_blank"},"component":"data2-core-primitives@String"},{"params":{"content":"_self"},"component":"data2-core-primitives@String"},{"params":{"content":"_parent"},"component":"data2-core-primitives@String"},{"params":{"content":"_top"},"component":"data2-core-primitives@String"}]},"component":"data2-core-types@ComponentParameter"}]}},"close":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-types@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"params":{},"component":"data2-core-web@Window"},"prop":"close"}},"parameters":["value"]}},"icon":{"component":"data2-core-primitives@String","params":{"content":"times"}},"visibility":"public","arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Link to open"}},"description":{"component":"data2-core-primitives@String","params":{"content":""}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"},{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Target"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Where to open the link"}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"oneOf":[{"params":{"content":"_blank"},"component":"data2-core-primitives@String"},{"params":{"content":"_self"},"component":"data2-core-primitives@String"},{"params":{"content":"_parent"},"component":"data2-core-primitives@String"},{"params":{"content":"_top"},"component":"data2-core-primitives@String"}]},"component":"data2-core-types@ComponentParameter"}],"description":{"component":"data2-core-primitives@String","params":{"content":"Closes a window that was opened via router.open."}}}}}}}}},{"_id":"620d28658271aa4129919d89","component":"data2-core-types@Component","params":{"package":"data2-interface-services","component":"DeviceController","interactions":{"params":{"fields":{"postMessage":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":"data2-core-primitives@String","title":{"component":"data2-core-primitives@String","params":{"content":"data"}}}}]},"component":"data2-core-types@ComponentParameter"},"print":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Object"}},"flat":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"parameters":{"zoom":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Number"}},"title":{"component":"data2-core-primitives@String","params":{"content":"zoom"}},"visibility":"public"}}},"visibility":"public"},"component":"data2-core-types@ComponentParameter"}],"visibility":"public"},"component":"data2-core-types@ComponentParameter"},"share":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}}},"component":"data2-core-types@ComponentParameter"},"clipboard.copy":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}}}}]},"component":"data2-core-types@ComponentParameter"},"clipboard.paste":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}}}}]},"component":"data2-core-types@ComponentParameter"},"download":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Filename"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Content"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Object"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Options"}},"parameters":{"params":{"fields":{"type":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Mimetype"}}}}}},"component":"data2-core-types@FieldSet"}}}]},"component":"data2-core-types@ComponentParameter"},"downloadUrl":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Filename"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Url"}}}}]},"component":"data2-core-types@ComponentParameter"},"promptFiles":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":"data2-core-primitives@Object","flat":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"parameters":{"params":{"fields":{"multiple":{"component":"data2-core-types@ComponentParameter","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Multiple"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Whether or not to allow selecting multiple files"}},"component":"data2-core-primitives@Boolean"}},"acceptedFormats":{"component":"data2-core-types@ComponentParameter","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Accepted Formats"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Accepted file formats"}},"component":"data2-core-primitives@String","list":{"component":"data2-core-primitives@Boolean","params":{"content":true}}}},"timeout":{"component":"data2-core-types@ComponentParameter","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Timeout"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Max milliseconds to wait for file upload"}},"component":"data2-core-primitives@Number"}}}},"component":"data2-core-types@FieldSet"}}}],"visibility":"public"},"component":"data2-core-types@ComponentParameter"},"meetingRecord":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","definition":{"params":{"actions":[{"params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"meeting"}},"script":{"component":"data2-core-primitives@String","params":{"content":"(function() {\n  let mediaRecorder;\n  let audioChunks = [];\n  let combinedStream;\n  let audioContext;\n  \n  window.meetingCapture = async function() {\n    try {\n      // Solicitar acesso ao áudio da guia (e vídeo, que será ignorado depois)\n      const tabStream = await navigator.mediaDevices.getDisplayMedia({ \n        video: true, // Necessário para alguns navegadores\n        audio: true\n      });\n      \n      // Remover a trilha de vídeo\n      const tabAudioTrack = tabStream.getAudioTracks()[0];\n      \n      // Solicitar acesso ao microfone\n      const micStream = await navigator.mediaDevices.getUserMedia({ audio: true });\n      const micAudioTrack = micStream.getAudioTracks()[0];\n      \n      // Criar um novo MediaStream com ambas as trilhas de áudio\n      combinedStream = new MediaStream([tabAudioTrack, micAudioTrack]);\n      \n      // Criar um contexto de áudio para misturar os streams\n      audioContext = new AudioContext();\n      const destination = audioContext.createMediaStreamDestination();\n      \n      // Conectar a trilha de áudio da guia\n      const tabSource = audioContext.createMediaStreamSource(new MediaStream([tabAudioTrack]));\n      tabSource.connect(destination);\n      \n      // Conectar a trilha de áudio do microfone\n      const micSource = audioContext.createMediaStreamSource(new MediaStream([micAudioTrack]));\n      micSource.connect(destination);\n      \n      // Iniciar gravação com o stream misturado\n      mediaRecorder = new MediaRecorder(destination.stream);\n      audioChunks = [];\n      mediaRecorder.ondataavailable = (e) => audioChunks.push(e.data);\n      mediaRecorder.start();\n      \n      console.log('Gravação iniciada. Chame meetingCaptureStop() para finalizar.');\n    } catch (error) {\n      console.error('Erro ao iniciar a captura:', error);\n    }\n  };\n  \n  window.meetingCaptureStop = function() {\n    return new Promise((resolve, reject) => {\n      if (!mediaRecorder) {\n        reject('Nenhuma gravação em andamento.');\n        return;\n      }\n      \n      mediaRecorder.onstop = () => {\n        const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });\n        combinedStream.getTracks().forEach(track => track.stop());\n        audioContext.close();\n        \n        resolve(audioBlob);\n        console.log('Gravação finalizada. O arquivo de áudio está pronto para upload.');\n      };\n      \n      mediaRecorder.stop();\n    });\n  };\n})();"}}},"component":"data2-core-web@Script"},{"component":"data2-core-types@Getter","params":{"module":{"params":{},"component":"data2-core-web@Window"},"prop":{"component":"data2-core-primitives@String","params":{"content":"meetingCapture"}}}}]},"component":"data2-core-flow@Series"}},"component":"data2-core-types@ComponentParameter"},"meetingRecordStop":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Filename"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Content"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Object"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Options"}},"parameters":{"params":{"fields":{"type":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Mimetype"}}}}}},"component":"data2-core-types@FieldSet"}}}],"definition":{"params":{"actions":[{"component":"data2-core-types@Getter","params":{"module":{"params":{},"component":"data2-core-web@Window"},"prop":{"component":"data2-core-primitives@String","params":{"content":"meetingCaptureStop"}}}}]},"component":"data2-core-flow@Series"}},"component":"data2-core-types@ComponentParameter"},"notify":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"private","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":"data2-core-primitives@Object","parameters":{"title":{"params":{"component":"data2-core-primitives@String","index":{"component":"data2-core-primitives@Number","params":{"content":0}},"title":{"component":"data2-core-primitives@String","params":{"content":"title"}}},"component":"data2-core-types@ComponentParameter"},"sound":{"params":{"component":"data2-core-types@FileComponentUrlReference","index":{"component":"data2-core-primitives@Number","params":{"content":1}},"title":{"component":"data2-core-primitives@String","params":{"content":"sound"}}},"component":"data2-core-types@ComponentParameter"}},"flat":{"component":"data2-core-primitives@Boolean","params":{"content":true}}}}]},"component":"data2-core-types@ComponentParameter"}}},"component":"data2-core-types@FieldSet"}}},{"_id":"6a464a40fd69f89bce071102","component":"data2-core-types@Component","system":"66f6c624d8a4a0c67041a910","params":{"extends":"data2-core-primitives@Block","component":"painel-login","package":"fernando-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    :host { position:absolute; inset:0; overflow:auto; font-family:system-ui,-apple-system,Segoe UI,sans-serif; }\n    .wrap { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; padding:24px; background:linear-gradient(135deg,#1A1512,#2A211A); }\n    .card { width:100%; max-width:400px; background:#FBF9F5; border-radius:20px; padding:34px; box-shadow:0 30px 80px rgba(0,0,0,.4); display:flex; flex-direction:column; }\n    .logo { font-family:Georgia,serif; font-size:24px; font-weight:600; color:#262019; text-align:center; }\n    .logo .dot { color:#B4633E; margin:0 4px; }\n    .sub { font-size:13px; color:#8C8578; text-align:center; margin:6px 0 20px; }\n    .tabs { display:flex; background:#F1ECE4; border-radius:11px; padding:4px; margin-bottom:22px; }\n    .tab { flex:1; border:none; background:none; padding:10px; border-radius:8px; font-size:13.5px; font-weight:700; color:#8C8578; cursor:pointer; transition:.15s; }\n    .tab.active { background:#fff; color:#262019; box-shadow:0 2px 8px rgba(38,32,25,.08); }\n    label { font-size:12px; font-weight:700; letter-spacing:.04em; text-transform:uppercase; color:#6E665A; margin-bottom:6px; }\n    .fld { width:100%; padding:12px 14px; border:1.5px solid #E2DACB; border-radius:11px; font-size:14px; color:#262019; background:#fff; margin-bottom:16px; outline:none; box-sizing:border-box; }\n    .fld:focus { border-color:#B4633E; }\n    .err { background:rgba(217,83,78,.1); border:1px solid rgba(217,83,78,.35); color:#B23B36; font-size:12.5px; border-radius:10px; padding:9px 12px; margin-bottom:14px; }\n    .btn { width:100%; border:none; border-radius:11px; background:#262019; color:#fff; padding:14px; font-size:14px; font-weight:700; cursor:pointer; transition:.15s; }\n    .btn:hover { background:#3d342a; }\n    .btn:disabled { opacity:.5; cursor:default; }\n    .fine { font-size:11.5px; color:#A69C8C; text-align:center; margin-top:12px; line-height:1.5; }\n    .back { background:none; border:none; color:#8C8578; font-size:12.5px; cursor:pointer; margin-top:14px; text-decoration:underline; }\n    .back:hover { color:#262019; }\n  `,\n  render(d2) {\n    const esc = (s) => (s ?? '').toString().replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;')\n    const mode = d2.state.mode || 'signup'\n    const err = d2.state.error || ''\n    const busy = !!d2.state.busy\n    const isLogin = mode === 'login'\n    const form = isLogin ? `\n      <label>E-mail</label>\n      <input class=\"fld js-email\" type=\"email\" placeholder=\"voce@empresa.com\" autocomplete=\"username\" />\n      <label>Senha</label>\n      <input class=\"fld js-pwd\" type=\"password\" placeholder=\"••••••••\" autocomplete=\"current-password\" />\n      ${err ? `<div class=\"err\">${esc(err)}</div>` : ''}\n      <button class=\"btn js-login\" ${busy ? 'disabled' : ''}>${busy ? 'Entrando…' : 'Entrar'}</button>` : `\n      <label>Nome</label>\n      <input class=\"fld js-name\" placeholder=\"Seu nome\" autocomplete=\"name\" />\n      <label>E-mail</label>\n      <input class=\"fld js-email\" type=\"email\" placeholder=\"voce@empresa.com\" autocomplete=\"username\" />\n      <label>Senha</label>\n      <input class=\"fld js-pwd\" type=\"password\" placeholder=\"crie uma senha\" autocomplete=\"new-password\" />\n      ${err ? `<div class=\"err\">${esc(err)}</div>` : ''}\n      <button class=\"btn js-signup\" ${busy ? 'disabled' : ''}>${busy ? 'Criando conta…' : 'Criar conta e ver o painel'}</button>\n      <div class=\"fine\">Grátis, sem cartão. Você ganha acesso ao painel comercial da demonstração — o que a consultoria por IA gera em receita.</div>`\n    return `<div class=\"wrap\"><div class=\"card\">\n      <div class=\"logo\">Ateliê<span class=\"dot\">·</span>Beleza</div>\n      <div class=\"sub\">Painel comercial — o impacto da consultoria por IA</div>\n      <div class=\"tabs\">\n        <button class=\"tab js-tab-signup ${!isLogin ? 'active' : ''}\" type=\"button\">Criar conta</button>\n        <button class=\"tab js-tab-login ${isLogin ? 'active' : ''}\" type=\"button\">Já tenho conta</button>\n      </div>\n      ${form}\n      <button class=\"back js-back\" type=\"button\">← Voltar à loja</button>\n    </div></div>`\n  },\n  mounted(d2) {\n    const val = (s) => { const el = d2.$(s); return el ? el.value : '' }\n    const enter = async (email, pwd) => {\n      // estabelece a sessão do runtime e marca o flag local; painel recarrega com policy\n      try { await d2.auth('painel-auth').login({ email, password: pwd }) } catch (e) { d2.log('strategy login', e) }\n      try { sessionStorage.setItem('painelAuthed', '1') } catch (e) {}\n      window.location.assign('/painel')\n    }\n    const doLogin = async () => {\n      const email = val('.js-email').trim().toLowerCase()\n      const pwd = val('.js-pwd')\n      if (!email || !pwd) { d2.state.error = 'Preencha e-mail e senha.'; return }\n      d2.state.error = ''\n      d2.state.busy = true\n      try {\n        const res = await d2.rush('verifica-login').invoke({ credentials: { email, password: pwd } })\n        const r = (res && res.data) ? res.data : res\n        if (!r || !r.user) { d2.state.busy = false; d2.state.error = 'E-mail ou senha inválidos.'; return }\n        await enter(email, pwd)\n      } catch (e) {\n        d2.log('login error', e)\n        d2.state.busy = false\n        d2.state.error = 'E-mail ou senha inválidos.'\n      }\n    }\n    const doSignup = async () => {\n      const name = val('.js-name').trim()\n      const email = val('.js-email').trim().toLowerCase()\n      const pwd = val('.js-pwd')\n      if (!name || !email || !pwd) { d2.state.error = 'Preencha nome, e-mail e senha.'; return }\n      d2.state.error = ''\n      d2.state.busy = true\n      try {\n        const res = await d2.rush('cria-conta').invoke({ name, email, password: pwd })\n        const r = (res && res.data) ? res.data : res\n        if (!r || !r.ok) { d2.state.busy = false; d2.state.error = (r && r.error) || 'Não foi possível criar a conta.'; return }\n        await enter(email, pwd)\n      } catch (e) {\n        d2.log('signup error', e)\n        d2.state.busy = false\n        d2.state.error = 'Não foi possível criar a conta. Tente de novo.'\n      }\n    }\n    d2.on('.js-tab-login', 'click', () => { d2.state.error = ''; d2.state.mode = 'login' })\n    d2.on('.js-tab-signup', 'click', () => { d2.state.error = ''; d2.state.mode = 'signup' })\n    d2.on('.js-login', 'click', doLogin)\n    d2.on('.js-signup', 'click', doSignup)\n    d2.on('.js-pwd', 'keydown', (e) => { if (e.key === 'Enter') { if ((d2.state.mode || 'signup') === 'login') doLogin(); else doSignup() } })\n    d2.on('.js-back', 'click', () => window.location.assign('/'))\n  },\n}"}}}}}}}},{"_id":"6a464d9ec4f6a71828526e27","component":"data2-core-types@Component","system":"66f6c624d8a4a0c67041a910","params":{"extends":"data2-core-primitives@Block","component":"painel-comercial","package":"fernando-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    :host { position:absolute; inset:0; overflow:auto; font-family:system-ui,-apple-system,Segoe UI,sans-serif; background:#1A1A2E; color:#fff; }\n    .page { min-height:100%; padding:40px 48px 64px; box-sizing:border-box; }\n    .top { display:flex; align-items:flex-start; justify-content:space-between; gap:16px; margin-bottom:6px; }\n    h1 { font-size:26px; font-weight:800; margin:0; }\n    .sub { font-size:15px; color:#8899bb; margin:6px 0 26px; }\n    .actions { display:flex; gap:10px; flex-shrink:0; }\n    .btn { border:none; border-radius:999px; padding:11px 20px; font-size:13.5px; font-weight:700; cursor:pointer; }\n    .btn.primary { background:#6C4DF6; color:#fff; } .btn.primary:hover { background:#5b3ce0; }\n    .btn.ghost { background:transparent; color:#8899bb; border:1px solid #3a3a55; } .btn.ghost:hover { color:#fff; border-color:#6C4DF6; }\n    .grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); gap:20px; margin-bottom:24px; }\n    .kpi { background:#26263A; border-radius:16px; padding:24px; }\n    .kpi .lbl { font-size:11px; font-weight:700; letter-spacing:1px; text-transform:uppercase; color:#8899bb; }\n    .kpi .val { font-size:34px; font-weight:800; margin:12px 0 10px; }\n    .kpi .foot { font-size:13px; color:#8899bb; }\n    .kpi .foot.hi { color:#E84393; }\n    .kpi .foot.up { color:#4ADE80; }\n    .panelcard { background:#26263A; border-radius:16px; padding:24px; margin-bottom:24px; }\n    .panelcard h2 { font-size:16px; font-weight:800; margin:0 0 16px; }\n    table { width:100%; border-collapse:collapse; font-size:13.5px; }\n    th { text-align:left; font-size:11px; text-transform:uppercase; letter-spacing:.04em; color:#8899bb; padding:8px 10px; border-bottom:1px solid #3a3a55; }\n    td { padding:11px 10px; border-bottom:1px solid #2f2f47; color:#dfe3f0; }\n    td.r, th.r { text-align:right; }\n    .disc { background:#2A2440; border-radius:10px; color:#F0D9A8; font-size:13px; padding:12px 16px; }\n    .del { background:none; border:1px solid #3a3a55; color:#8899bb; border-radius:8px; padding:4px 9px; cursor:pointer; font-size:13px; }\n    .del:hover { border-color:#E9534E; color:#E9534E; }\n    .delc { display:inline-flex; gap:6px; justify-content:flex-end; }\n    .delc-no { background:none; border:1px solid #3a3a55; color:#8899bb; border-radius:8px; padding:4px 10px; cursor:pointer; font-size:12px; }\n    .delc-no:hover { color:#fff; border-color:#8899bb; }\n    .delc-yes { background:#E9534E; border:none; color:#fff; border-radius:8px; padding:4px 11px; cursor:pointer; font-size:12px; font-weight:700; }\n    .delc-yes:hover { background:#d6423d; }\n    .empty { background:#26263A; border-radius:16px; padding:48px; text-align:center; color:#8899bb; }\n    .empty .big { font-size:40px; margin-bottom:10px; }\n  `,\n  render(d2) {\n    const esc = (s) => (s ?? '').toString().replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')\n    const money = (n) => d2.fmt.currency(Number(n) || 0, 'BRL')\n    const ds = d2.data('consultations')\n    const loading = !ds || ds.loading\n    const rows = (loading ? [] : ds.records()).filter((r) => !(d2.state.deletedIds || {})[r._id])\n    const n = rows.length\n    const avg = (f) => n ? rows.reduce((a, r) => a + (Number(r[f]) || 0), 0) / n : 0\n    const sum = (f) => rows.reduce((a, r) => a + (Number(r[f]) || 0), 0)\n    const avgTicket = avg('ticket_total')\n    const avgItens = avg('itens_count')\n    const avgBaseline = avg('baseline_avulso')\n    const uplift = avgBaseline > 0 ? ((avgTicket - avgBaseline) / avgBaseline) * 100 : 0\n    const recorrencia = sum('recorrencia_mensal_estimada')\n    const avgDevol = avg('devolucao_evitada_pct')\n    const ticketBot = sum('ticket_bot')\n    const grossAll = ticketBot + sum('ticket_manual')\n    const botShare = grossAll > 0 ? (ticketBot / grossAll) * 100 : 0\n    const itensBotAll = sum('itens_bot')\n\n    const head = `<div class=\"top\">\n        <div><h1>Painel comercial — impacto da consultoria</h1>\n          <div class=\"sub\">O que a IA gerou nas consultorias desta loja — traduzido em receita. Dados reais das consultas registradas.</div></div>\n        <div class=\"actions\"><button class=\"btn ghost js-logout\" type=\"button\">Sair</button><button class=\"btn primary js-loja\" type=\"button\">← Voltar à loja</button></div>\n      </div>`\n\n    if (loading) return `<div class=\"page\">${head}<div class=\"empty\">Carregando…</div></div>`\n    if (!n) return `<div class=\"page\">${head}<div class=\"empty\"><div class=\"big\">📊</div><div style=\"font-weight:800;color:#fff;font-size:16px;margin-bottom:6px\">Ainda sem consultorias registradas</div><div>Finalize um pedido na loja (com a ajuda da consultora) para os números aparecerem aqui em tempo real.</div></div></div>`\n\n    const kpis = `<div class=\"grid\">\n      <div class=\"kpi\"><div class=\"lbl\">Ticket médio da recomendação</div><div class=\"val\">${money(avgTicket)}</div><div class=\"foot hi\">vs ${money(avgBaseline)} numa compra avulsa</div></div>\n      <div class=\"kpi\"><div class=\"lbl\">Uplift de ticket</div><div class=\"val\">${uplift >= 0 ? '+' : ''}${Math.round(uplift)}%</div><div class=\"foot up\">acima da compra de um item só</div></div>\n      <div class=\"kpi\"><div class=\"lbl\">Receita puxada pela IA</div><div class=\"val\">${money(ticketBot)}</div><div class=\"foot up\">${Math.round(botShare)}% do valor em produtos · ${itensBotAll} itens recomendados</div></div>\n      <div class=\"kpi\"><div class=\"lbl\">Itens por consultoria</div><div class=\"val\">${(Math.round(avgItens * 10) / 10).toString().replace('.', ',')}</div><div class=\"foot\">cross-sell guiado pela rotina</div></div>\n      <div class=\"kpi\"><div class=\"lbl\">Receita recorrente projetada</div><div class=\"val\">${money(recorrencia)}/mês</div><div class=\"foot hi\">recompra estimada pela duração dos produtos</div></div>\n      <div class=\"kpi\"><div class=\"lbl\">Redução de devolução</div><div class=\"val\">~${Math.round(avgDevol)}%</div><div class=\"foot\">produto certo para a necessidade</div></div>\n      <div class=\"kpi\"><div class=\"lbl\">Consultorias registradas</div><div class=\"val\">${n}</div><div class=\"foot\">pedidos fechados com a consultora</div></div>\n    </div>`\n\n    const recent = rows.slice().reverse().slice(0, 12).map((r) => {\n      const ib = Number(r.itens_bot) || 0\n      const im = (Number(r.itens_count) || 0) - ib\n      const origem = (!ib && !im) ? '—' : `${ib ? '🤖 ' + ib : ''}${ib && im ? ' · ' : ''}${im ? '🖱️ ' + im : ''}`\n      return `<tr data-key=\"${r._id}\">\n        <td>${r.created_at ? esc(d2.fmt.relative(r.created_at)) : '—'}</td>\n        <td>${esc(d2.fmt.truncate(r.intent_summary || '—', 46))}</td>\n        <td class=\"r\">${origem}</td>\n        <td class=\"r\">${Number(r.itens_count) || 0}</td>\n        <td class=\"r\">${money(r.ticket_total)}</td>\n        <td class=\"r\">${(d2.state.confirmDel === r._id) ? `<span class=\"delc\"><button class=\"delc-no js-del-no\" type=\"button\">Não</button><button class=\"delc-yes js-del-yes\" data-id=\"${r._id}\" type=\"button\">Excluir?</button></span>` : `<button class=\"del js-del\" data-id=\"${r._id}\" type=\"button\" title=\"Excluir compra\">🗑</button>`}</td>\n      </tr>`\n    }).join('')\n\n    return `<div class=\"page\">${head}${kpis}\n      <div class=\"panelcard\"><h2>Consultorias recentes</h2>\n        <table><thead><tr><th>Quando</th><th>Itens</th><th class=\"r\">Origem</th><th class=\"r\">Qtd</th><th class=\"r\">Ticket</th><th></th></tr></thead><tbody>${recent}</tbody></table>\n      </div>\n      <div class=\"disc\">⚠️ Projeções de demonstração (recorrência e redução de devolução são estimativas) — não são métricas auditadas. Alinhar com o time comercial antes de prometer ROI.</div>\n    </div>`\n  },\n  mounted(d2) {\n    d2.on('.js-loja', 'click', () => window.location.assign('/'))\n    d2.on('.js-del', 'click', (e, el) => { d2.state.confirmDel = el.dataset.id })\n    d2.on('.js-del-no', 'click', () => { d2.state.confirmDel = null })\n    d2.on('.js-del-yes', 'click', async (e, el) => {\n      const id = el.dataset.id\n      d2.state.confirmDel = null\n      if (!id) return\n      d2.state.deletedIds = { ...(d2.state.deletedIds || {}), [id]: true }\n      try {\n        await d2.rush('exclui-consulta').invoke({ id })\n        const ds = d2.data('consultations'); if (ds && ds.refresh) ds.refresh()\n      } catch (err) { d2.log('del consultation', err) }\n    })\n    d2.on('.js-logout', 'click', async () => {\n      try { sessionStorage.removeItem('painelAuthed') } catch (e) {}\n      try { await d2.auth('painel-auth').logout() } catch (e) { d2.log('logout error', e) }\n      window.location.assign('/')\n    })\n  },\n}"}},"consultations":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"consultations"}}}}}}}}}},{"_id":"6a448ab5a92372895f253061","component":"data2-core-types@Component","system":"66f6c624d8a4a0c67041a910","params":{"extends":"data2-core-primitives@Block","component":"consultora-app","package":"fernando-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    :host { display:block; position:relative; width:100%; height:100%; overflow:hidden; font-family: system-ui,-apple-system,Segoe UI,sans-serif; color:#262019; }\n    * { box-sizing:border-box; }\n    .page { position:absolute; inset:0; overflow-y:auto; overflow-x:hidden; background:#FBF9F5; scrollbar-width:thin; scrollbar-color:#DED4C4 transparent; }\n    .page::-webkit-scrollbar, .drawer-body::-webkit-scrollbar { width:11px; }\n    .page::-webkit-scrollbar-track, .drawer-body::-webkit-scrollbar-track { background:transparent; }\n    .page::-webkit-scrollbar-thumb, .drawer-body::-webkit-scrollbar-thumb { background:#DBD1C0; border-radius:999px; border:3px solid transparent; background-clip:content-box; }\n    .page::-webkit-scrollbar-thumb:hover, .drawer-body::-webkit-scrollbar-thumb:hover { background:#C6B8A0; background-clip:content-box; }\n    .log { scrollbar-width:thin; scrollbar-color:rgba(255,255,255,.2) transparent; }\n    .log::-webkit-scrollbar { width:8px; }\n    .log::-webkit-scrollbar-track { background:transparent; }\n    .log::-webkit-scrollbar-thumb { background:rgba(255,255,255,.16); border-radius:999px; border:2px solid transparent; background-clip:content-box; }\n    .serif { font-family: Georgia,'Times New Roman',serif; }\n\n    .topbar { background:#262019; color:#F3EFE8; text-align:center; font-size:12px; letter-spacing:.04em; padding:8px 16px; }\n    .nav { position:sticky; top:0; z-index:6; display:flex; align-items:center; justify-content:space-between; gap:24px; padding:15px 40px; background:rgba(251,249,245,.92); backdrop-filter:blur(10px); border-bottom:1px solid #EAE3D8; }\n    .cats { display:flex; gap:22px; flex:1; justify-content:center; }\n    .cat { font-size:14px; font-weight:500; color:#6E665A; cursor:pointer; padding:4px 0; border-bottom:2px solid transparent; transition:.15s; white-space:nowrap; }\n    .cat:hover { color:#262019; }\n    .cat.active { color:#262019; border-bottom-color:#B4633E; font-weight:600; }\n    .navright { display:flex; align-items:center; gap:12px; position:relative; }\n    .pmenu-scrim { position:fixed; inset:0; z-index:30; }\n    .pmenu { position:absolute; top:52px; right:0; z-index:31; background:#fff; border:1px solid #EAE3D8; border-radius:12px; box-shadow:0 14px 36px rgba(38,32,25,.18); padding:6px; min-width:210px; animation:fade .15s ease; }\n    .pmenu-head { font-size:11px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:#A69C8C; padding:9px 12px 5px; }\n    .pmenu-item { display:flex; align-items:center; gap:9px; width:100%; border:none; background:none; text-align:left; padding:10px 12px; border-radius:8px; font-size:13.5px; color:#262019; cursor:pointer; font-weight:600; }\n    .pmenu-item:hover { background:#F4F0E9; }\n    .search { display:flex; align-items:center; gap:7px; background:#F1ECE4; border:1px solid #E8E1D6; border-radius:999px; padding:8px 14px; width:200px; }\n    .search .si { color:#9A9184; font-size:15px; }\n    .searchi { border:none; background:none; outline:none; font-size:13px; color:#262019; width:100%; font-family:inherit; }\n    .searchi::placeholder { color:#A69C8C; }\n    .iconbtn { position:relative; border:none; background:none; cursor:pointer; color:#262019; width:36px; height:36px; display:flex; align-items:center; justify-content:center; border-radius:50%; transition:.15s; }\n    .iconbtn:hover { background:#F1ECE4; }\n    .iconbtn svg { width:21px; height:21px; }\n    .ibadge { position:absolute; top:-1px; right:-1px; background:#B4633E; color:#fff; font-size:10px; font-weight:700; min-width:17px; height:17px; border-radius:999px; display:flex; align-items:center; justify-content:center; padding:0 4px; }\n    .banner { display:flex; align-items:stretch; min-height:340px; background:linear-gradient(120deg,#EFE7DA,#F7F2EA); overflow:hidden; }\n    .banner-in { flex:1; padding:56px 48px; display:flex; flex-direction:column; justify-content:center; }\n    .banner-eyebrow { font-size:12px; font-weight:700; letter-spacing:.18em; text-transform:uppercase; color:#B4633E; margin-bottom:14px; }\n    .banner-title { font-size:44px; line-height:1.08; font-weight:600; color:#262019; margin:0 0 14px; letter-spacing:-.5px; }\n    .banner-sub { font-size:16px; color:#6E665A; margin:0 0 24px; max-width:440px; line-height:1.55; }\n    .banner-cta { display:flex; align-items:center; gap:16px; flex-wrap:wrap; }\n    .banner-btn { border:none; background:#262019; color:#fff; border-radius:999px; padding:13px 24px; font-size:14px; font-weight:700; cursor:pointer; display:inline-flex; align-items:center; gap:7px; transition:.15s; }\n    .banner-btn:hover { background:#3d342a; }\n    .banner-coupon { font-size:12px; font-weight:700; letter-spacing:.06em; color:#B4633E; border:1px dashed rgba(180,99,62,.5); border-radius:8px; padding:9px 14px; }\n    .banner-art { width:36%; background:linear-gradient(150deg,#DBCCB6,#C4AF94); display:flex; align-items:center; justify-content:center; }\n    .banner-mono { font-family:Georgia,serif; font-size:170px; color:rgba(255,255,255,.4); font-weight:600; line-height:1; }\n    .logo { font-family:Georgia,serif; font-size:22px; font-weight:600; letter-spacing:.3px; color:#262019; cursor:pointer; }\n    .logo .dot { color:#B4633E; margin:0 4px; }\n    .cart-btn { position:relative; border:1px solid #DBD3C6; background:#fff; color:#262019; border-radius:999px;\n      padding:9px 20px; font-size:13px; font-weight:600; cursor:pointer; letter-spacing:.02em; }\n    .cart-btn:hover { border-color:#262019; }\n    .badge { position:absolute; top:-7px; right:-7px; background:#B4633E; color:#fff; font-size:11px; font-weight:700;\n      min-width:19px; height:19px; border-radius:999px; display:inline-flex; align-items:center; justify-content:center; padding:0 5px; }\n\n    .hero { padding:72px 48px 40px; }\n    .hero-in { max-width:600px; }\n    .eyebrow { font-size:12px; font-weight:700; letter-spacing:.18em; text-transform:uppercase; color:#B4633E; margin-bottom:14px; }\n    .hero h1 { font-family:Georgia,serif; font-size:52px; line-height:1.04; font-weight:600; margin:0 0 16px; letter-spacing:-.5px; }\n    .hero p { font-size:16px; line-height:1.6; color:#6E665A; margin:0; max-width:500px; }\n\n    .section { padding:20px 48px 90px; }\n    .section-head { display:flex; align-items:baseline; justify-content:space-between; margin-bottom:24px; border-bottom:1px solid #EAE3D8; padding-bottom:14px; }\n    .section-head h2 { font-family:Georgia,serif; font-size:24px; font-weight:600; margin:0; }\n    .count { font-size:13px; color:#9A9184; }\n    .grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(258px,1fr)); gap:26px; }\n\n    .pcard { background:#fff; border:1px solid #EAE3D8; border-radius:16px; overflow:hidden; display:flex; flex-direction:column; transition:box-shadow .2s, transform .2s; }\n    .pcard:hover { box-shadow:0 14px 40px rgba(38,32,25,.10); transform:translateY(-3px); }\n    .thumb { position:relative; height:210px; background:linear-gradient(140deg,#F1EBE1,#E6DCCD); display:flex; align-items:center; justify-content:center; }\n    .thumb .mono { font-family:Georgia,serif; font-size:64px; color:#CDC2B0; font-weight:600; }\n    .thumb .timg { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; display:block; }\n    .pm-img .pmimg { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; display:block; }\n    .co-thumb img { width:100%; height:100%; object-fit:cover; border-radius:10px; display:block; }\n    .sthumb img { width:100%; height:100%; object-fit:cover; border-radius:9px; display:block; }\n    .othumb img { width:100%; height:100%; object-fit:cover; border-radius:9px; display:block; }\n    .thumb-tag { position:absolute; top:14px; left:14px; background:rgba(255,255,255,.85); color:#6E665A; font-size:10.5px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; padding:5px 10px; border-radius:999px; }\n    .pbody { padding:18px; display:flex; flex-direction:column; gap:5px; flex:1; }\n    .pbrand { font-size:11px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:#B4633E; }\n    .pname { font-size:16px; font-weight:600; line-height:1.3; color:#262019; }\n    .pdesc { font-size:12.5px; color:#8C8578; line-height:1.5; flex:1; margin-bottom:6px; }\n    .pprice { font-family:Georgia,serif; font-size:22px; font-weight:600; margin:8px 0 12px; }\n    .addbtn { width:100%; padding:12px; border:1.5px solid #262019; background:transparent; color:#262019; border-radius:10px; font-size:13.5px; font-weight:700; cursor:pointer; transition:.15s; letter-spacing:.01em; }\n    .addbtn:hover { background:#262019; color:#fff; }\n    .stepper.full { display:flex; width:100%; }\n    .stepper.full .qbtn { width:42px; }\n    .stepper.full .qn { flex:1; }\n    .askpill { position:absolute; top:12px; right:12px; width:34px; height:34px; border-radius:50%; display:inline-flex; align-items:center; justify-content:center; background:rgba(255,255,255,.92); color:#B4633E; border:1px solid rgba(180,99,62,.45); font-size:15px; cursor:pointer; box-shadow:0 2px 10px rgba(38,32,25,.1); transition:.15s; }\n    .askpill:hover { background:#B4633E; color:#fff; border-color:#B4633E; transform:scale(1.08); }\n\n    .btn { border:none; border-radius:10px; font-size:13px; font-weight:600; cursor:pointer; padding:10px 16px; transition:.15s; letter-spacing:.01em; }\n    .btn.primary { background:#262019; color:#fff; }\n    .btn.primary:hover { background:#3d342a; }\n    .btn.lg { width:100%; padding:15px; font-size:14px; }\n    .stepper { display:inline-flex; align-items:center; border:1px solid #DBD3C6; border-radius:10px; overflow:hidden; background:#fff; }\n    .stepper.sm { transform:none; }\n    .stepper.sm .qbtn { width:32px; height:32px; font-size:16px; }\n    .stepper.sm .qn { min-width:26px; }\n    .qbtn { border:none; background:transparent; width:34px; height:38px; font-size:18px; cursor:pointer; color:#262019; display:inline-flex; align-items:center; justify-content:center; line-height:1; padding:0; }\n    .qbtn:hover { background:#F4F0E9; }\n    .qn { min-width:30px; text-align:center; font-size:14px; font-weight:700; }\n    .ask { margin-top:12px; width:100%; background:rgba(180,99,62,.09); color:#B4633E; border:1px solid rgba(180,99,62,.22); border-radius:10px; padding:9px; font-size:12.5px; font-weight:700; cursor:pointer; transition:.15s; }\n    .ask:hover { background:rgba(180,99,62,.16); }\n    .empty { grid-column:1/-1; padding:40px; text-align:center; color:#9A9184; }\n    .footer-note { padding:28px 48px 60px; color:#A69C8C; font-size:12.5px; text-align:center; border-top:1px solid #EAE3D8; }\n    .pcard { cursor:pointer; }\n    .mscrim { position:absolute; inset:0; background:rgba(38,32,25,.42); z-index:24; animation:fade .2s ease; }\n    .pmodal { position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); width:min(880px, calc(100% - 40px)); max-height:calc(100% - 40px); overflow-y:auto; background:#FBF9F5; border-radius:18px; z-index:25; display:grid; grid-template-columns:44% 1fr; box-shadow:0 30px 80px rgba(38,32,25,.35); animation:modalin .2s ease-out; scrollbar-width:thin; scrollbar-color:#DED4C4 transparent; }\n    @keyframes modalin { from { opacity:0; transform:translate(-50%,-50%) scale(.98); } to { opacity:1; transform:translate(-50%,-50%) scale(1); } }\n    .pmodal::-webkit-scrollbar { width:10px; }\n    .pmodal::-webkit-scrollbar-thumb { background:#DBD1C0; border-radius:999px; border:3px solid transparent; background-clip:content-box; }\n    .pm-close { position:absolute; top:16px; right:16px; z-index:2; border:none; background:rgba(255,255,255,.92); width:34px; height:34px; border-radius:50%; cursor:pointer; font-size:14px; color:#6E665A; box-shadow:0 2px 8px rgba(38,32,25,.12); }\n    .pm-close:hover { background:#fff; }\n    .pm-img { position:relative; background:linear-gradient(140deg,#F1EBE1,#E6DCCD); display:flex; align-items:center; justify-content:center; min-height:360px; }\n    .pm-img .mono { font-family:Georgia,serif; font-size:120px; color:#CDC2B0; font-weight:600; }\n    .pm-body { padding:34px 34px 30px; }\n    .pm-brand { font-size:12px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:#B4633E; }\n    .pm-name { font-size:28px; font-weight:600; line-height:1.15; margin:6px 0 10px; }\n    .pm-price { font-family:Georgia,serif; font-size:24px; font-weight:600; margin-bottom:14px; }\n    .pm-desc { font-size:14px; color:#6E665A; line-height:1.6; margin:0 0 18px; }\n    .pm-meta { border-top:1px solid #EAE3D8; margin-bottom:20px; }\n    .pm-mrow { display:grid; grid-template-columns:140px 1fr; gap:12px; padding:11px 0; border-bottom:1px solid #EAE3D8; font-size:13px; }\n    .pm-mk { font-weight:700; color:#262019; }\n    .pm-mv { color:#6E665A; line-height:1.5; }\n    .pm-consultora { margin-top:20px; display:flex; align-items:center; gap:13px; background:rgba(180,99,62,.07); border:1px solid rgba(180,99,62,.25); border-radius:14px; padding:14px 16px; }\n    .pm-cico { width:38px; height:38px; flex-shrink:0; border-radius:50%; background:linear-gradient(135deg,#B4633E,#E0A075); color:#fff; display:flex; align-items:center; justify-content:center; font-size:18px; }\n    .pm-ctxt { flex:1; display:flex; flex-direction:column; gap:2px; }\n    .pm-ctxt strong { font-size:13px; color:#262019; }\n    .pm-ctxt span { font-size:12.5px; color:#8C7F6E; line-height:1.4; }\n    .pm-cbtn { flex-shrink:0; border:none; background:#B4633E; color:#fff; border-radius:999px; padding:10px 18px; font-size:12.5px; font-weight:700; cursor:pointer; }\n    .pm-cbtn:hover { background:#c9714a; }\n\n    /* checkout */\n    .co { padding:34px 48px 90px; max-width:1120px; margin:0 auto; }\n    .co-head { display:flex; flex-direction:column; gap:10px; margin-bottom:26px; }\n    .co-back { align-self:flex-start; border:none; background:none; color:#B4633E; font-size:13px; font-weight:600; cursor:pointer; padding:0; }\n    .co-back:hover { text-decoration:underline; }\n    .co-head h1 { font-family:Georgia,serif; font-size:34px; font-weight:600; margin:0; }\n    .co-grid { display:grid; grid-template-columns:1fr 348px; gap:28px; align-items:start; }\n    .co-main { display:flex; flex-direction:column; gap:20px; }\n    .co-card { background:#fff; border:1px solid #EAE3D8; border-radius:16px; padding:24px; }\n    .co-card h2 { font-family:Georgia,serif; font-size:18px; font-weight:600; margin:0 0 16px; }\n    .co-item { display:grid; grid-template-columns:56px 1fr auto; gap:15px; align-items:center; padding:14px 0; border-top:1px solid #F0EAE0; }\n    .co-item:first-of-type { border-top:none; padding-top:0; }\n    .co-thumb { width:56px; height:56px; border-radius:10px; background:linear-gradient(140deg,#F1EBE1,#E6DCCD); display:flex; align-items:center; justify-content:center; }\n    .co-thumb .mono { font-family:Georgia,serif; font-size:22px; color:#CDC2B0; font-weight:600; }\n    .ci-info { display:flex; flex-direction:column; gap:6px; }\n    .ci-name { font-size:14px; font-weight:600; }\n    .ci-line { display:flex; align-items:center; gap:12px; }\n    .ci-price { font-size:13px; color:#8C8578; }\n    .ci-remove { border:none; background:none; color:#A69C8C; font-size:11.5px; cursor:pointer; padding:0; text-decoration:underline; }\n    .ci-total { font-family:Georgia,serif; font-size:16px; font-weight:600; }\n\n    .co-sugg { border:1px solid rgba(180,99,62,.28); background:linear-gradient(180deg,rgba(180,99,62,.05),#fff 60px); }\n    .sugg-head { display:flex; align-items:center; gap:12px; margin-bottom:16px; }\n    .sugg-ico { width:38px; height:38px; border-radius:50%; background:linear-gradient(135deg,#B4633E,#E0A075); display:flex; align-items:center; justify-content:center; font-size:18px; color:#fff; flex-shrink:0; }\n    .sugg-head h2 { margin:0; }\n    .sugg-head p { margin:2px 0 0; font-size:12.5px; color:#8C8578; }\n    .scard { display:grid; grid-template-columns:48px 1fr auto; gap:13px; align-items:center; padding:13px 0; border-top:1px solid #F0EAE0; }\n    .scard:first-of-type { border-top:none; }\n    .sthumb { width:48px; height:48px; border-radius:9px; background:linear-gradient(140deg,#F1EBE1,#E6DCCD); display:flex; align-items:center; justify-content:center; }\n    .sthumb .mono { font-family:Georgia,serif; font-size:19px; color:#CDC2B0; font-weight:600; }\n    .s-name { font-size:13.5px; font-weight:600; }\n    .s-reason { font-size:12px; color:#B4633E; margin-top:2px; }\n    .s-right { display:flex; flex-direction:column; align-items:flex-end; gap:6px; }\n    .s-price { font-size:13px; font-weight:600; }\n    .s-add { border:1px solid #B4633E; background:#fff; color:#B4633E; border-radius:8px; padding:6px 14px; font-size:12px; font-weight:700; cursor:pointer; }\n    .s-add:hover { background:#B4633E; color:#fff; }\n    .sugg-empty { font-size:13px; color:#9A9184; padding:6px 0; }\n\n    .pay-row { display:flex; align-items:center; gap:12px; padding:13px 15px; border:1px solid #E8E1D6; border-radius:11px; margin-bottom:10px; cursor:pointer; transition:.15s; }\n    .pay-row:hover { border-color:#C9BCA6; }\n    .pay-row.sel { border-color:#262019; background:#FBF9F5; }\n    .radio { width:18px; height:18px; border-radius:50%; border:2px solid #C9BCA6; flex-shrink:0; position:relative; }\n    .pay-row.sel .radio { border-color:#262019; }\n    .pay-row.sel .radio::after { content:''; position:absolute; inset:3px; border-radius:50%; background:#262019; }\n    .pay-label { font-size:13.5px; font-weight:600; }\n    .pay-sub { font-size:12px; color:#9A9184; }\n    .field-mock { width:100%; padding:12px 14px; border:1px solid #E8E1D6; border-radius:11px; font-size:13.5px; color:#6E665A; background:#FBF9F5; margin-bottom:10px; }\n    .secure { display:flex; align-items:center; gap:8px; font-size:12px; color:#6E8B6E; background:rgba(110,139,110,.08); border:1px solid rgba(110,139,110,.2); border-radius:10px; padding:11px 14px; margin-top:6px; }\n\n    .co-summary { position:sticky; top:24px; background:#fff; border:1px solid #EAE3D8; border-radius:16px; padding:24px; }\n    .co-summary h3 { font-family:Georgia,serif; font-size:18px; font-weight:600; margin:0 0 18px; }\n    .sum-row { display:flex; justify-content:space-between; font-size:13.5px; color:#6E665A; padding:7px 0; }\n    .sum-row.total { font-size:18px; font-weight:700; color:#262019; border-top:1px solid #EAE3D8; margin-top:8px; padding-top:14px; }\n    .sum-row.total span:last-child { font-family:Georgia,serif; }\n    .free { color:#6E8B6E; font-weight:600; }\n    .co-badges { display:flex; flex-direction:column; gap:7px; margin-top:16px; font-size:11.5px; color:#9A9184; }\n    .co-success { min-height:100%; display:flex; align-items:center; justify-content:center; padding:40px 24px; }\n    .co-done { background:#fff; border:1px solid #EAE3D8; border-radius:18px; padding:64px 48px; text-align:center; max-width:540px; width:100%; margin:0; display:flex; flex-direction:column; align-items:center; gap:14px; }\n    .cd-ico { width:70px; height:70px; border-radius:50%; background:#B4633E; color:#fff; display:flex; align-items:center; justify-content:center; font-size:34px; }\n    .cd-num { font-size:13px; color:#8C8578; letter-spacing:.05em; }\n    .cd-title { font-family:Georgia,serif; font-size:28px; font-weight:600; }\n    .cd-sub { font-size:13.5px; color:#8C8578; line-height:1.55; max-width:340px; }\n\n    /* cart drawer */\n    .scrim { position:absolute; inset:0; background:rgba(38,32,25,.34); z-index:14; animation:fade .2s ease; }\n    .drawer { position:absolute; top:0; right:0; bottom:0; width:400px; max-width:92%; background:#F8F5EF; z-index:15; display:flex; flex-direction:column; box-shadow:-20px 0 60px rgba(38,32,25,.2); animation:slidein .26s cubic-bezier(.22,1,.36,1); }\n    @keyframes slidein { from{transform:translateX(40px);opacity:.4} to{transform:none;opacity:1} }\n    @keyframes fade { from{opacity:0} to{opacity:1} }\n    .drawer-head { display:flex; align-items:center; justify-content:space-between; padding:22px 24px; border-bottom:1px solid #EAE3D8; }\n    .dh-title { font-family:Georgia,serif; font-size:20px; font-weight:600; }\n    .close { border:none; background:#EFE9DF; width:32px; height:32px; border-radius:50%; cursor:pointer; font-size:14px; color:#6E665A; }\n    .close:hover { background:#E4DACB; }\n    .drawer-body { flex:1; overflow-y:auto; padding:16px 24px; display:flex; flex-direction:column; gap:16px; }\n    .citem { display:grid; grid-template-columns:60px 1fr auto; gap:13px; align-items:start; }\n    .cthumb { width:60px; height:60px; border-radius:10px; overflow:hidden; background:linear-gradient(140deg,#F1EBE1,#E6DCCD); display:flex; align-items:center; justify-content:center; flex-shrink:0; }\n    .cthumb img { width:100%; height:100%; object-fit:cover; display:block; }\n    .cthumb .mono { font-family:Georgia,serif; font-size:22px; color:#CDC2B0; font-weight:600; }\n    .cinfo { display:flex; flex-direction:column; gap:5px; min-width:0; }\n    .cname { font-size:13.5px; font-weight:600; line-height:1.3; }\n    .cprice { font-size:12px; color:#8C8578; }\n    .crow { display:flex; align-items:center; gap:14px; margin-top:3px; }\n    .cremove { border:none; background:none; color:#A69C8C; font-size:11.5px; cursor:pointer; padding:0; text-decoration:underline; }\n    .cline { font-family:Georgia,serif; font-size:14px; font-weight:600; white-space:nowrap; }\n    .cart-consultora { margin-top:6px; background:rgba(180,99,62,.06); border:1px solid rgba(180,99,62,.22); border-radius:14px; padding:14px; }\n    .cc-head { display:flex; align-items:center; gap:8px; font-size:13px; font-weight:800; color:#262019; margin-bottom:9px; }\n    .cc-ico { width:24px; height:24px; border-radius:50%; background:linear-gradient(135deg,#B4633E,#E0A075); color:#fff; display:flex; align-items:center; justify-content:center; font-size:12px; }\n    .cc-line { font-size:12px; color:#8C7F6E; margin-bottom:8px; }\n    .cc-sitem { display:flex; align-items:center; gap:10px; background:#fff; border:1px solid #EAE3D8; border-radius:10px; padding:9px 11px; margin-bottom:7px; }\n    .cc-sinfo { flex:1; min-width:0; }\n    .cc-sname { font-size:12.5px; font-weight:600; }\n    .cc-sreason { font-size:11.5px; color:#B4633E; margin-top:1px; }\n    .cc-sadd { flex-shrink:0; border:1px solid #B4633E; background:#fff; color:#B4633E; border-radius:8px; padding:6px 11px; font-size:11.5px; font-weight:700; cursor:pointer; white-space:nowrap; }\n    .cc-sadd:hover { background:#B4633E; color:#fff; }\n    .cc-chat { width:100%; margin-top:4px; border:none; background:#262019; color:#fff; border-radius:10px; padding:11px; font-size:12.5px; font-weight:700; cursor:pointer; }\n    .cc-chat:hover { background:#3d342a; }\n    .drawer-foot { padding:20px 24px; border-top:1px solid #EAE3D8; background:#fff; }\n    .subtotal { display:flex; justify-content:space-between; font-size:16px; font-weight:700; margin-bottom:14px; }\n    .subtotal span:last-child { font-family:Georgia,serif; }\n    .foot-fine { font-size:11px; color:#A69C8C; text-align:center; margin-top:10px; }\n    .empty-cart { flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:10px; color:#9A9184; font-size:14px; }\n    .empty-cart div { font-size:36px; }\n\n    /* launcher */\n    .launcher { position:absolute; right:30px; bottom:30px; z-index:12; display:flex; align-items:center; gap:11px; background:#262019; color:#fff; border-radius:999px; padding:12px 20px 12px 14px; cursor:pointer; box-shadow:0 12px 34px rgba(38,32,25,.28); transition:transform .16s; }\n    .launcher:hover { transform:translateY(-2px); }\n    .l-ico { width:34px; height:34px; border-radius:50%; background:linear-gradient(135deg,#B4633E,#D98A5B); display:flex; align-items:center; justify-content:center; font-size:17px; }\n    .l-label { font-size:14px; font-weight:600; letter-spacing:.01em; }\n    .l-pulse { position:absolute; left:14px; top:12px; width:34px; height:34px; border-radius:50%; background:#B4633E; opacity:.5; animation:pulse 2.2s infinite; }\n    @keyframes pulse { 0%{transform:scale(1);opacity:.45} 70%{transform:scale(1.9);opacity:0} 100%{opacity:0} }\n\n    /* chat panel — AI signature */\n    .panel { position:absolute; right:30px; bottom:30px; width:412px; height:min(680px,calc(100% - 60px)); z-index:16; background:#17130F; border-radius:20px; overflow:hidden; display:flex; flex-direction:column; box-shadow:0 30px 80px rgba(20,15,10,.5); animation:panelin .3s cubic-bezier(.22,1,.36,1); border:1px solid rgba(255,255,255,.06); }\n    @keyframes panelin { from{transform:translateY(24px) scale(.98);opacity:0} to{transform:none;opacity:1} }\n    .phead { position:relative; padding:20px 20px 18px; overflow:hidden; flex-shrink:0; background:linear-gradient(135deg,#2A211A,#3A2A20); border-bottom:1px solid rgba(255,255,255,.07); }\n    .phead::after { content:''; position:absolute; right:-40px; top:-60px; width:180px; height:180px; border-radius:50%; background:radial-gradient(circle,rgba(217,138,91,.5),transparent 70%); }\n    .ph-row { position:relative; display:flex; align-items:center; justify-content:space-between; z-index:1; }\n    .ph-brand { display:flex; align-items:center; gap:11px; }\n    .ph-ico { width:38px; height:38px; border-radius:50%; background:linear-gradient(135deg,#B4633E,#E0A075); display:flex; align-items:center; justify-content:center; font-size:18px; }\n    .ptitle { font-size:15px; font-weight:700; color:#fff; letter-spacing:.01em; }\n    .psub { font-size:11px; color:rgba(236,228,217,.6); margin-top:1px; }\n    .pclose { border:none; background:rgba(255,255,255,.12); color:#fff; width:30px; height:30px; border-radius:50%; cursor:pointer; font-size:13px; }\n    .pclose:hover { background:rgba(255,255,255,.22); }\n    .log { flex:1; overflow-y:auto; padding:18px; display:flex; flex-direction:column; gap:12px; }\n    .estate { flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; text-align:center; gap:12px; padding:30px; }\n    .estate .wave { font-size:44px; }\n    .estate h3 { color:#fff; font-size:16px; font-weight:700; margin:0; font-family:Georgia,serif; }\n    .estate p { color:rgba(236,228,217,.6); font-size:13px; line-height:1.55; margin:0; max-width:280px; }\n    .chips { display:flex; flex-wrap:wrap; gap:8px; justify-content:center; margin-top:6px; }\n    .qchips { display:flex; flex-wrap:wrap; gap:8px; margin-top:9px; }\n    .mic { flex-shrink:0; width:42px; height:42px; border-radius:50%; border:none; cursor:pointer; background:rgba(255,255,255,.08); color:#ECE4D9; font-size:16px; display:flex; align-items:center; justify-content:center; transition:.15s; }\n    .mic:hover { background:rgba(255,255,255,.15); }\n    .mic.rec { background:#E9534E; color:#fff; animation:micpulse 1.1s infinite; }\n    @keyframes micpulse { 0%,100%{opacity:1} 50%{opacity:.5} }\n    .chip { background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.12); color:rgba(236,228,217,.9); font-size:12px; padding:8px 13px; border-radius:999px; cursor:pointer; transition:.15s; }\n    .chip:hover { background:rgba(180,99,62,.25); border-color:rgba(217,138,91,.5); }\n    .row { display:flex; flex-direction:column; max-width:100%; }\n    .row.user { align-items:flex-end; }\n    .row.bot { align-items:flex-start; }\n    .msg { max-width:86%; padding:11px 14px; border-radius:15px; font-size:13.5px; line-height:1.5; white-space:pre-line; }\n    .msg.user { background:#B4633E; color:#fff; border-bottom-right-radius:5px; }\n    .msg.bot { background:rgba(255,255,255,.055); color:#ECE4D9; border:1px solid rgba(255,255,255,.08); border-bottom-left-radius:5px; }\n    .dots span { width:6px; height:6px; border-radius:50%; background:rgba(236,228,217,.5); display:inline-block; margin-right:4px; animation:blink 1.2s infinite; }\n    .dots span:nth-child(2){animation-delay:.2s} .dots span:nth-child(3){animation-delay:.4s}\n    @keyframes blink { 0%,80%,100%{opacity:.25} 40%{opacity:1} }\n    .routines { display:flex; flex-direction:column; gap:11px; margin-top:10px; width:100%; }\n    .opts { display:flex; flex-direction:column; gap:9px; margin-top:10px; width:100%; }\n    .ocard { display:grid; grid-template-columns:44px 1fr auto; gap:11px; align-items:center; background:rgba(255,255,255,.045); border:1px solid rgba(255,255,255,.1); border-radius:12px; padding:10px 12px; }\n    .othumb { width:44px; height:44px; border-radius:9px; background:linear-gradient(140deg,rgba(255,255,255,.14),rgba(255,255,255,.05)); display:flex; align-items:center; justify-content:center; }\n    .othumb .mono { font-family:Georgia,serif; font-size:18px; color:rgba(255,255,255,.55); font-weight:600; }\n    .oname { font-size:13px; font-weight:700; color:#fff; }\n    .ostep { font-size:11.5px; color:rgba(236,228,217,.55); margin-top:1px; }\n    .oright { display:flex; flex-direction:column; align-items:flex-end; gap:6px; }\n    .oprice { font-size:13px; font-weight:600; color:#E0A075; font-family:Georgia,serif; }\n    .oadd { border:none; background:#B4633E; color:#fff; border-radius:8px; padding:6px 13px; font-size:12px; font-weight:700; cursor:pointer; }\n    .oadd:hover { background:#c9714a; }\n    .odetail { background:none; border:none; color:rgba(236,228,217,.6); font-size:11px; cursor:pointer; text-decoration:underline; margin-top:5px; padding:2px 0; }\n    .odetail:hover { color:#E0A075; }\n    .sidemodal { position:absolute; right:464px; bottom:28px; z-index:19; width:340px; max-height:min(680px, calc(100% - 56px)); overflow-y:auto; background:#17120E; border:1px solid rgba(255,255,255,.12); border-radius:18px; box-shadow:0 24px 70px rgba(0,0,0,.45); color:#ECE4D9; animation:fade .18s ease; }\n    .sm-head { display:flex; align-items:center; justify-content:space-between; padding:12px 14px 8px; }\n    .sm-tag { font-size:10px; font-weight:800; letter-spacing:.08em; text-transform:uppercase; color:#E0A075; background:rgba(180,99,62,.18); border-radius:999px; padding:4px 10px; }\n    .sm-close { background:rgba(255,255,255,.1); border:none; color:#fff; width:26px; height:26px; border-radius:50%; cursor:pointer; font-size:12px; }\n    .sm-close:hover { background:rgba(255,255,255,.2); }\n    .sm-img { height:180px; margin:0 14px; border-radius:12px; overflow:hidden; background:rgba(255,255,255,.05); display:flex; align-items:center; justify-content:center; }\n    .sm-img img { width:100%; height:100%; object-fit:cover; }\n    .sm-img .mono { font-family:Georgia,serif; font-size:56px; color:rgba(255,255,255,.4); }\n    .sm-body { padding:14px; display:flex; flex-direction:column; gap:5px; }\n    .sm-brand { font-size:11px; text-transform:uppercase; letter-spacing:.06em; color:rgba(236,228,217,.55); }\n    .sm-name { font-family:Georgia,serif; font-size:17px; font-weight:600; color:#fff; line-height:1.25; }\n    .sm-price { font-size:18px; font-weight:800; color:#E0A075; margin:2px 0; }\n    .sm-desc { font-size:12.5px; line-height:1.5; color:rgba(236,228,217,.75); margin:4px 0 10px; }\n    .sm-meta { display:flex; flex-direction:column; gap:8px; margin-bottom:12px; }\n    .sm-mrow { display:flex; flex-direction:column; gap:2px; border-top:1px solid rgba(255,255,255,.08); padding-top:8px; }\n    .sm-mk { font-size:10.5px; text-transform:uppercase; letter-spacing:.05em; color:rgba(236,228,217,.5); }\n    .sm-mv { font-size:12.5px; color:#ECE4D9; line-height:1.45; }\n    .sm-add { width:100%; border:none; border-radius:10px; background:#B4633E; color:#fff; padding:12px; font-size:13.5px; font-weight:800; cursor:pointer; }\n    .sm-add:hover { background:#c9714a; }\n    .catsw { display:inline-flex; align-items:center; gap:8px; border:1px solid #E2DACB; background:#fff; color:#262019; border-radius:999px; padding:8px 14px; font-size:12.5px; font-weight:800; cursor:pointer; white-space:nowrap; }\n    .catsw:hover { border-color:#B4633E; color:#B4633E; }\n    .catsw-swap { color:#B4633E; font-weight:700; font-size:14px; }\n    .rcard { background:rgba(255,255,255,.045); border:1px solid rgba(255,255,255,.1); border-radius:14px; padding:14px; }\n    .rtop { display:flex; align-items:center; justify-content:space-between; }\n    .rname { font-size:13.5px; font-weight:800; color:#fff; }\n    .rover { display:inline-block; margin-left:8px; font-size:9.5px; font-weight:700; letter-spacing:.04em; text-transform:uppercase; color:#E9A99E; background:rgba(224,138,120,.14); border:1px solid rgba(224,138,120,.4); border-radius:999px; padding:2px 7px; vertical-align:middle; }\n    .rok { display:inline-block; margin-left:8px; font-size:9.5px; font-weight:700; letter-spacing:.04em; text-transform:uppercase; color:#A8D8B0; background:rgba(150,200,150,.14); border:1px solid rgba(150,200,150,.36); border-radius:999px; padding:2px 7px; vertical-align:middle; }\n    .rcard-ok { border-color:rgba(150,200,150,.42); background:rgba(150,200,150,.07); }\n    .rcard-over { border-color:rgba(224,138,120,.45); background:rgba(224,138,120,.07); }\n    .rcard-ok .rtotal { color:#A8D8B0; }\n    .rcard-over .rtotal { color:#E9A99E; }\n    .rtotal { font-family:Georgia,serif; font-size:15px; font-weight:600; color:#E0A075; }\n    .rblurb { font-size:12px; color:rgba(236,228,217,.66); margin:5px 0 9px; line-height:1.45; }\n    .ritem { display:flex; justify-content:space-between; gap:10px; font-size:12px; color:rgba(236,228,217,.86); padding:5px 0; border-top:1px dashed rgba(255,255,255,.1); }\n    .ritem:first-child { border-top:none; }\n    .rwarn { font-size:11.5px; color:#F0CDA0; background:rgba(240,205,160,.09); border:1px solid rgba(240,205,160,.22); border-radius:9px; padding:8px 10px; margin-top:9px; line-height:1.45; }\n    .radd { margin-top:11px; width:100%; background:#B4633E; color:#fff; border:none; border-radius:9px; padding:10px; font-size:12.5px; font-weight:700; cursor:pointer; transition:.15s; }\n    .radd:hover { background:#c9714a; }\n    .cpn { width:100%; background:linear-gradient(135deg,rgba(180,99,62,.16),rgba(255,255,255,.04)); border:1px dashed rgba(217,138,91,.55); border-radius:14px; padding:14px; margin-top:10px; }\n    .cpn-top { display:flex; align-items:center; justify-content:space-between; margin-bottom:4px; }\n    .cpn-code { font-size:14px; font-weight:800; color:#fff; letter-spacing:.06em; }\n    .cpn-save { font-family:Georgia,serif; font-size:15px; font-weight:700; color:#A8D8B0; }\n    .cpn-desc { font-size:12px; color:rgba(236,228,217,.7); margin-bottom:10px; }\n    .cpn-apply { width:100%; border:none; border-radius:9px; background:#B4633E; color:#fff; padding:10px; font-size:12.5px; font-weight:800; cursor:pointer; }\n    .cpn-apply:hover { background:#c9714a; }\n    .cpn-apply:disabled { background:rgba(168,216,176,.2); color:#A8D8B0; cursor:default; }\n    .cpline { display:flex; justify-content:space-between; align-items:center; font-size:12.5px; color:#B4633E; font-weight:700; margin-bottom:8px; gap:8px; }\n    .cpline.off { color:#A69C8C; font-weight:600; }\n    .cpremove { border:none; background:none; color:#A69C8C; font-size:11px; cursor:pointer; text-decoration:underline; padding:0; }\n    .unread { position:absolute; left:50%; transform:translateX(-50%); bottom:86px; z-index:3; display:none; align-items:center; gap:6px; border:none; border-radius:999px; background:#D98A5B; color:#17130F; font-size:12px; font-weight:800; padding:8px 14px; cursor:pointer; box-shadow:0 8px 24px rgba(0,0,0,.35); animation:fade .2s ease; }\n    .unread:hover { background:#E0A075; }\n    .bar { flex-shrink:0; display:flex; align-items:flex-end; gap:9px; padding:14px; background:#120E0A; border-top:1px solid rgba(255,255,255,.07); }\n    .field { flex:1; background:rgba(255,255,255,.05); border:1.5px solid rgba(255,255,255,.09); border-radius:16px; padding:6px 14px; transition:.15s; }\n    .field:focus-within { border-color:#B4633E; }\n    .cin { width:100%; border:none; background:none; color:#ECE4D9; font-size:13.5px; font-family:inherit; resize:none; outline:none; line-height:1.5; height:24px; max-height:110px; padding:0; scrollbar-width:thin; scrollbar-color:rgba(255,255,255,.22) transparent; }\n    .cin::-webkit-scrollbar { width:7px; }\n    .cin::-webkit-scrollbar-button { display:none; height:0; width:0; }\n    .cin::-webkit-scrollbar-track { background:transparent; margin:2px 0; }\n    .cin::-webkit-scrollbar-thumb { background:rgba(255,255,255,.2); border-radius:999px; border:2px solid transparent; background-clip:content-box; }\n    .cin::-webkit-scrollbar-thumb:hover { background:rgba(255,255,255,.32); background-clip:content-box; }\n    .cin::placeholder { color:rgba(236,228,217,.4); }\n    .send { flex-shrink:0; width:42px; height:42px; border-radius:50%; border:none; cursor:pointer; background:linear-gradient(135deg,#B4633E,#D98A5B); color:#fff; display:flex; align-items:center; justify-content:center; }\n    .send:disabled { opacity:.4; cursor:default; }\n    .send svg { width:18px; height:18px; }\n    .photo { flex-shrink:0; width:42px; height:42px; border-radius:50%; border:none; cursor:pointer; background:rgba(255,255,255,.08); color:#ECE4D9; font-size:18px; display:flex; align-items:center; justify-content:center; transition:.15s; }\n    .photo:hover { background:rgba(255,255,255,.15); }\n    .imgmsg { padding:5px !important; background:rgba(255,255,255,.06) !important; }\n    .imgmsg img { max-width:190px; max-height:190px; border-radius:11px; display:block; }\n\n    /* ===== REDESIGN LUXO (override, vence na cascata) ===== */\n    :host { font-family:'Inter',system-ui,-apple-system,Segoe UI,sans-serif; -webkit-font-smoothing:antialiased; }\n    .serif { font-family:'Cormorant Garamond',Georgia,'Times New Roman',serif; }\n    .page { background:#F6F3EE; color:#2A2420; }\n    .topbar { background:#2A2420; color:#F3EFE8; font-size:11px; letter-spacing:.16em; text-transform:uppercase; padding:9px 16px; font-weight:500; }\n    .nav { padding:20px 52px; background:rgba(246,243,238,.86); backdrop-filter:blur(12px); border-bottom:1px solid rgba(42,36,32,.09); }\n    .logo { font-family:'Cormorant Garamond',Georgia,serif; font-size:27px; font-weight:600; letter-spacing:.02em; color:#2A2420; }\n    .logo .dot { color:#B4633E; }\n    .cats { gap:28px; }\n    .cat { font-size:11.5px; letter-spacing:.14em; text-transform:uppercase; font-weight:500; color:#7A6F64; border-bottom:none; }\n    .cat:hover { color:#2A2420; }\n    .cat.active { color:#2A2420; font-weight:600; border-bottom:none; position:relative; }\n    .cat.active::after { content:''; position:absolute; left:0; right:0; bottom:-3px; height:1px; background:#B4633E; }\n    .navright { gap:16px; }\n    .iconbtn { color:#2A2420; }\n    .iconbtn:hover { background:rgba(42,36,32,.06); }\n    .search { background:transparent; border:1px solid rgba(42,36,32,.16); border-radius:999px; }\n    .catsw { display:inline-flex; align-items:center; gap:9px; border:1px solid rgba(42,36,32,.2); background:transparent; color:#2A2420; border-radius:999px; padding:9px 16px; font-size:11px; font-weight:600; letter-spacing:.08em; text-transform:uppercase; cursor:pointer; white-space:nowrap; transition:.2s; }\n    .catsw:hover { border-color:#B4633E; color:#B4633E; }\n    .catsw-swap { color:#B4633E; font-size:13px; }\n\n    .banner { position:relative; overflow:hidden; display:block; min-height:300px; padding:52px 52px 58px; background:linear-gradient(160deg,#F6F3EE 0%,#EFE7DB 60%,#EAE0D2 100%); }\n    .banner-in { position:relative; z-index:2; max-width:680px; animation:rise .9s cubic-bezier(.2,.7,.2,1) both; }\n    .banner-eyebrow { font-size:12px; font-weight:500; letter-spacing:.26em; text-transform:uppercase; color:#B4633E; margin-bottom:14px; }\n    .banner-title { font-family:'Cormorant Garamond',Georgia,serif; font-size:54px; line-height:1.02; font-weight:500; letter-spacing:-.01em; color:#2A2420; margin:0 0 16px; }\n    .banner-title em, .ed-title em, .ai-title em { font-style:italic; color:#8A6A4F; }\n    .banner-sub { font-size:15.5px; line-height:1.65; color:#5C534B; max-width:480px; margin:0 0 26px; }\n    .banner-cta { display:flex; align-items:center; gap:24px; flex-wrap:wrap; }\n    .banner-btn { border:none; border-radius:0; background:#2A2420; color:#F6F3EE; padding:17px 32px; font-size:11.5px; font-weight:600; letter-spacing:.16em; text-transform:uppercase; cursor:pointer; transition:.28s; }\n    .banner-btn:hover { background:#B4633E; letter-spacing:.2em; }\n    .banner-coupon { font-size:11.5px; letter-spacing:.1em; text-transform:uppercase; color:#8A7E74; border:none; padding:0; background:none; }\n    .banner-art { position:absolute; inset:0; z-index:1; width:auto; background:none; pointer-events:none; }\n    .banner-orb { position:absolute; right:8%; top:50%; transform:translateY(-50%); width:250px; height:250px; border-radius:50%; background:radial-gradient(circle at 34% 30%,#EBD0B2,#D8A97F 55%,#C0855D); opacity:.5; filter:blur(1px); animation:floatc 9s ease-in-out infinite; }\n    .banner-orb.orb2 { right:23%; top:34%; transform:none; width:112px; height:112px; background:radial-gradient(circle at 40% 35%,#F1DEC9,#CBAF97); opacity:.38; animation:float 13s ease-in-out infinite; animation-delay:-3s; }\n    @keyframes floatc { 0%,100%{transform:translateY(-50%)} 50%{transform:translateY(calc(-50% - 22px))} }\n    @keyframes float { 0%,100%{transform:translateY(0)} 50%{transform:translateY(-28px)} }\n    @keyframes rise { from{opacity:0; transform:translateY(24px)} to{opacity:1; transform:none} }\n\n    .section { padding:84px 52px 44px; }\n    .section-head { border-bottom:1px solid rgba(42,36,32,.11); padding-bottom:20px; margin-bottom:44px; }\n    .section-head h2 { font-family:'Cormorant Garamond',Georgia,serif; font-size:38px; font-weight:500; }\n    .count { font-size:11px; letter-spacing:.16em; text-transform:uppercase; color:#8A7E74; }\n    .grid { grid-template-columns:repeat(4,1fr); gap:16px 30px; }\n    .pcard { background:transparent; border:none; border-radius:0; overflow:visible; }\n    .pcard:hover { box-shadow:none; transform:none; }\n    .thumb { height:auto; aspect-ratio:1/1; background:#EEE7DE; border-radius:3px; overflow:hidden; }\n    .thumb .timg, .thumb .timg.timg { position:static; inset:auto; width:100%; height:100%; object-fit:cover; transition:transform .8s cubic-bezier(.2,.7,.2,1); }\n    .pcard:hover .thumb .timg { transform:scale(1.06); }\n    .thumb .mono { font-family:'Cormorant Garamond',Georgia,serif; }\n    .fav { position:absolute; top:12px; right:12px; z-index:3; width:34px; height:34px; border:none; border-radius:50%; background:rgba(255,255,255,.8); color:#2A2420; font-size:16px; line-height:1; cursor:pointer; display:flex; align-items:center; justify-content:center; transition:.2s; }\n    .fav:hover { background:#fff; }\n    .fav.on { color:#B4633E; }\n    .askpill { top:auto; left:12px; right:12px; bottom:12px; width:auto; height:auto; border-radius:0; background:rgba(42,36,32,.93); color:#F6F3EE; border:none; box-shadow:none; display:flex; align-items:center; justify-content:center; gap:8px; padding:13px; font-size:11px; letter-spacing:.16em; text-transform:uppercase; opacity:0; transform:translateY(10px); transition:.3s; }\n    .pcard:hover .askpill { opacity:1; transform:none; }\n    .askpill:hover { background:#B4633E; color:#fff; transform:none; }\n    .askpill-ico { font-size:13px; }\n    .pbody { padding:16px 2px 0; gap:0; text-align:left; }\n    .pcat { font-size:10.5px; letter-spacing:.16em; text-transform:uppercase; color:#A2968A; margin-bottom:8px; }\n    .pname { font-family:'Cormorant Garamond',Georgia,serif; font-size:21px; font-weight:500; line-height:1.18; color:#2A2420; margin-bottom:7px; }\n    .pprice { font-family:'Inter',sans-serif; font-size:14px; font-weight:500; color:#5C534B; margin:0 0 14px; }\n    .addbtn { border-radius:0; border:1px solid rgba(42,36,32,.75); font-size:11px; letter-spacing:.14em; text-transform:uppercase; font-weight:600; padding:13px; }\n\n    .editorial { padding:104px 52px; max-width:920px; margin:0 auto; text-align:center; }\n    .ed-eyebrow { font-size:12px; font-weight:500; letter-spacing:.26em; text-transform:uppercase; color:#B4633E; margin-bottom:22px; }\n    .ed-eyebrow.light { color:#E7C9A8; }\n    .ed-title { font-family:'Cormorant Garamond',Georgia,serif; font-size:54px; font-weight:500; line-height:1.08; color:#2A2420; margin:0 0 22px; }\n    .ed-lead { font-size:17px; line-height:1.85; color:#5C534B; max-width:660px; margin:0 auto; }\n    .pillars { display:grid; grid-template-columns:repeat(3,1fr); gap:1px; background:rgba(42,36,32,.1); border-top:1px solid rgba(42,36,32,.1); border-bottom:1px solid rgba(42,36,32,.1); }\n    .pillar { background:#F6F3EE; padding:60px 46px; }\n    .pillar-n { font-family:'Cormorant Garamond',Georgia,serif; font-size:24px; color:#B4633E; margin-bottom:18px; }\n    .pillar h3 { font-family:'Cormorant Garamond',Georgia,serif; font-size:25px; font-weight:500; color:#2A2420; margin:0 0 12px; line-height:1.2; }\n    .pillar p { font-size:14.5px; line-height:1.75; color:#5C534B; margin:0; }\n    .ai-band { background:#2A2420; color:#F6F3EE; padding:116px 52px; text-align:center; }\n    .ai-band-in { max-width:780px; margin:0 auto; }\n    .ai-title { font-family:'Cormorant Garamond',Georgia,serif; font-size:58px; font-weight:500; line-height:1.06; margin:0 0 24px; }\n    .ai-title em { color:#E7C9A8; }\n    .ai-lead { font-size:17px; line-height:1.85; color:rgba(246,243,238,.72); margin:0 0 36px; }\n    .ai-cta { border:1px solid #F6F3EE; background:transparent; color:#F6F3EE; padding:17px 36px; font-size:11.5px; font-weight:600; letter-spacing:.16em; text-transform:uppercase; cursor:pointer; transition:.25s; }\n    .ai-cta:hover { background:#F6F3EE; color:#2A2420; }\n    .footer-note { background:#EFE7DB; color:#8A7E74; font-size:11px; letter-spacing:.06em; padding:44px 52px; border-top:1px solid rgba(42,36,32,.09); }\n\n    @media (max-width:1080px){ .grid{grid-template-columns:repeat(2,1fr)} .pillars{grid-template-columns:1fr} .banner-title{font-size:54px} .cats{display:none} .ed-title,.ai-title{font-size:40px} }\n  `,\n  render(d2) {\n    const esc = (s) => (s ?? '').toString().replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;')\n    const money = (n) => d2.fmt.currency(Number(n) || 0, 'BRL')\n    const mono = (name) => (name || '?').trim().slice(0,1).toUpperCase()\n    const catB = d2.state.catalog === 'b'\n    const ds = d2.data(catB ? 'bot-products-bDataSet' : 'products')\n    const loadingP = !ds || ds.loading\n    const products = loadingP ? [] : ds.records()\n    const imgOf = (id) => { const pp = products.filter((x) => x && x._id === id)[0]; return (pp && pp.image_url) ? pp.image_url : '' }\n    const selCat = d2.state.category || ''\n    const categories = [...new Set(products.map((p) => p.category).filter(Boolean))].sort()\n    const catLabel = (c) => c ? c.charAt(0).toUpperCase() + c.slice(1) : c\n    const visibleProducts = selCat ? products.filter((p) => p.category === selCat) : products\n    const cart = d2.state.cart || {}\n    const qOf = (id) => cart[id] || 0\n    const cartCount = Object.keys(cart).reduce((a,k) => a + cart[k], 0)\n    const cartItems = products.filter((p) => qOf(p._id) > 0)\n    const cartTotal = cartItems.reduce((a,p) => a + (Number(p.price) || 0) * qOf(p._id), 0)\n    const coupon = d2.state.coupon || null\n    const couponBase = coupon ? (coupon.scope === 'categoria' ? cartItems.reduce((a, p) => a + ((p.category === coupon.category) ? (Number(p.price) || 0) * qOf(p._id) : 0), 0) : cartTotal) : 0\n    const couponMinOk = coupon ? cartTotal >= (Number(coupon.min_total) || 0) : false\n    const couponDiscount = (coupon && couponMinOk) ? (coupon.discount_type === 'percent' ? couponBase * (Number(coupon.discount_value) || 0) / 100 : Math.min(Number(coupon.discount_value) || 0, couponBase)) : 0\n    const cartFinal = Math.max(0, cartTotal - couponDiscount)\n    const view = d2.state.view || 'store'\n\n    const card = (p) => {\n      const q = qOf(p._id)\n      const action = q > 0\n        ? `<div class=\"stepper full\"><button class=\"qbtn js-dec\" data-id=\"${p._id}\">−</button><span class=\"qn\">${q}</span><button class=\"qbtn js-inc\" data-id=\"${p._id}\">+</button></div>`\n        : `<button class=\"addbtn js-add\" data-id=\"${p._id}\">Adicionar à sacola</button>`\n      const fav = (d2.state.favs || {})[p._id]\n      return `<article class=\"pcard js-open-product\" data-key=\"${p._id}\" data-id=\"${p._id}\">\n        <div class=\"thumb\">${p.image_url ? `<img class=\"timg\" src=\"${esc(p.image_url)}\" alt=\"${esc(p.name || '')}\" />` : `<span class=\"mono\">${esc(mono(p.name))}</span>`}\n          <button class=\"fav js-fav ${fav ? 'on' : ''}\" data-id=\"${p._id}\" title=\"Favoritar\" aria-label=\"Favoritar\">${fav ? '♥' : '♡'}</button>\n          <button class=\"askpill js-ask\" data-id=\"${p._id}\" data-name=\"${esc(p.name || '')}\" title=\"Falar com a consultora\"><span class=\"askpill-ico\">✨</span><span class=\"askpill-txt\">Consultora</span></button></div>\n        <div class=\"pbody\">\n          <div class=\"pcat\">${esc(p.category || '')}</div>\n          <div class=\"pname\">${esc(p.name || '')}</div>\n          <div class=\"pprice\">${money(p.price)}</div>\n          ${action}\n        </div>\n      </article>`\n    }\n    const grid = loadingP ? `<div class=\"empty\">Carregando produtos…</div>` : (visibleProducts.length ? visibleProducts.map(card).join('') : `<div class=\"empty\">Nenhum produto nesta categoria.</div>`)\n    const store = `\n      <div class=\"topbar\">Frete grátis acima de R$ 279 · entrega expressa para todo o Brasil</div>\n      <header class=\"nav\">\n        <div class=\"logo js-home\">Ateliê<span class=\"dot\">·</span>Beleza</div>\n        <nav class=\"cats\">\n          <a class=\"cat js-cat ${selCat === '' ? 'active' : ''}\" data-cat=\"\">Todos</a>\n          ${categories.map((c) => `<a class=\"cat js-cat ${selCat === c ? 'active' : ''}\" data-cat=\"${esc(c)}\">${esc(catLabel(c))}</a>`).join('')}\n        </nav>\n        <div class=\"navright\">\n          <button class=\"catsw js-catsw\" type=\"button\" title=\"Trocar catálogo — demo do motor agnóstico\">${catB ? '💇 Cabelos' : '🧴 Skincare'}<span class=\"catsw-swap\">⇄</span></button>\n          <div class=\"search\"><span class=\"si\">⌕</span><input class=\"searchi\" placeholder=\"Buscar produtos...\" /></div>\n          <button class=\"iconbtn js-profile\" title=\"Minha conta\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\"><circle cx=\"12\" cy=\"8\" r=\"4\"/><path d=\"M4.5 20c0-3.6 3.6-5.6 7.5-5.6s7.5 2 7.5 5.6\"/></svg></button>\n          <button class=\"iconbtn\" title=\"Favoritos\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\"><path d=\"M12 20.5S4 15.5 4 9.8A4.3 4.3 0 0 1 12 7a4.3 4.3 0 0 1 8 2.8c0 5.7-8 10.7-8 10.7z\"/></svg></button>\n          <button class=\"iconbtn js-cart\" title=\"Sacola\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\"><path d=\"M6.5 8h11l-1 11.5H7.5L6.5 8z\"/><path d=\"M9.2 8V6.2a2.8 2.8 0 0 1 5.6 0V8\"/></svg>${cartCount ? `<span class=\"ibadge\">${cartCount}</span>` : ''}</button>\n          ${d2.state.profileMenu ? `<div class=\"pmenu-scrim js-profile-close\"></div><div class=\"pmenu\"><div class=\"pmenu-head\">Área interna</div><button class=\"pmenu-item js-goto-painel\" type=\"button\">📊 Painel comercial</button></div>` : ''}\n        </div>\n      </header>\n      <section class=\"banner\">\n        <div class=\"banner-art\"><span class=\"banner-orb\"></span><span class=\"banner-orb orb2\"></span></div>\n        <div class=\"banner-in\">\n          <div class=\"banner-eyebrow\">${catB ? 'Ritual capilar' : 'Beleza consultiva'}</div>\n          <h1 class=\"banner-title serif\">${catB ? 'Cabelos<br>como um <em>ritual.</em>' : 'Mais do que<br>pele. <em>Cuidado.</em>'}</h1>\n          <p class=\"banner-sub\">Uma consultora de IA lê a sua necessidade — por texto, voz ou foto — e monta a rotina certa para você. Beleza que começa em entender.</p>\n          <div class=\"banner-cta\">\n            <button class=\"banner-btn js-open\">Falar com a consultora</button>\n            <span class=\"banner-coupon\">Diagnóstico gratuito · em segundos</span>\n          </div>\n        </div>\n      </section>\n      <main class=\"section\">\n        <div class=\"section-head\"><h2 class=\"serif\">Mais desejados</h2><span class=\"count\">${loadingP ? '' : visibleProducts.length + ' produtos'}</span></div>\n        <div class=\"grid\">${grid}</div>\n      </main>\n      <section class=\"editorial\">\n        <div class=\"ed-eyebrow\">A nossa filosofia</div>\n        <h2 class=\"ed-title serif\">Beleza que vai <em>além da superfície.</em></h2>\n        <p class=\"ed-lead\">Fórmulas gentis e eficazes, pensadas para revelar a sua melhor versão — com o cuidado de quem entende de pele, de cabelo e de você.</p>\n      </section>\n      <section class=\"pillars\">\n        <div class=\"pillar\"><div class=\"pillar-n\">01</div><h3 class=\"serif\">Ingredientes que fazem sentido</h3><p>Ativos selecionados e combinações que respeitam a sua pele — sem misturas que competem entre si.</p></div>\n        <div class=\"pillar\"><div class=\"pillar-n\">02</div><h3 class=\"serif\">Personalização de verdade</h3><p>Cada recomendação nasce da sua necessidade, do seu tipo de pele ou cabelo e do seu momento — não de uma vitrine genérica.</p></div>\n        <div class=\"pillar\"><div class=\"pillar-n\">03</div><h3 class=\"serif\">Inteligência que consulta</h3><p>Uma IA que conversa, analisa uma foto do seu cabelo e monta a rotina ideal — a expertise de uma consultora, na hora.</p></div>\n      </section>\n      <section class=\"ai-band\">\n        <div class=\"ai-band-in\">\n          <div class=\"ed-eyebrow light\">Tecnologia Data2</div>\n          <h2 class=\"ai-title serif\">A consultora que entende <em>de você.</em></h2>\n          <p class=\"ai-lead\">Descreva o que precisa, mande um áudio ou uma foto do seu cabelo. Em segundos, a IA diagnostica, evita combinações erradas e monta o cuidado sob medida — e responde até por voz.</p>\n          <button class=\"ai-cta js-open\">Experimentar agora</button>\n        </div>\n      </section>\n      <div class=\"footer-note\">Demonstração Data2 · vitrine fictícia · a camada de consultoria por IA se integra a qualquer e-commerce existente, sem trocar nada.</div>`\n\n    // ---- checkout view ----\n    let checkout = ''\n    if (view === 'checkout') {\n      if (d2.state.checkoutDone) {\n        checkout = `<div class=\"co-success\"><div class=\"co-done\">\n          <div class=\"cd-ico\">✓</div>\n          <div class=\"cd-num\">Pedido ${esc(d2.state.orderNumber || '')}</div>\n          <div class=\"cd-title serif\">Pedido confirmado</div>\n          <div class=\"cd-sub\">Simulação de demonstração — nenhum pagamento foi processado. Numa loja real, o cliente receberia a confirmação por e-mail.</div>\n          <button class=\"btn primary js-home\">Voltar à loja</button>\n        </div></div>`\n      } else {\n        const pay = d2.state.payMethod || 'cartao'\n        const itemsHtml = cartItems.length ? cartItems.map((p) => `<div class=\"co-item\" data-key=\"${p._id}\">\n            <div class=\"co-thumb\">${p.image_url ? `<img src=\"${esc(p.image_url)}\" alt=\"${esc(p.name)}\" />` : `<span class=\"mono\">${esc(mono(p.name))}</span>`}</div>\n            <div class=\"ci-info\"><div class=\"ci-name\">${esc(p.name)}</div>\n              <div class=\"ci-line\"><div class=\"stepper sm\"><button class=\"qbtn js-dec\" data-id=\"${p._id}\">−</button><span class=\"qn\">${qOf(p._id)}</span><button class=\"qbtn js-inc\" data-id=\"${p._id}\">+</button></div>\n                <span class=\"ci-price\">${money(p.price)} un.</span><button class=\"ci-remove js-remove\" data-id=\"${p._id}\">remover</button></div></div>\n            <div class=\"ci-total\">${money((Number(p.price) || 0) * qOf(p._id))}</div>\n          </div>`).join('') : `<div class=\"sugg-empty\">Sua sacola está vazia.</div>`\n\n        const suggs = d2.state.suggestions || []\n        const suggBody = d2.state.suggestLoading\n          ? `<div class=\"sugg-empty\">A consultora está analisando seu pedido…</div>`\n          : (suggs.length ? suggs.map((s) => `<div class=\"scard\" data-key=\"${s.product_id}\">\n              <div class=\"sthumb\">${imgOf(s.product_id) ? `<img src=\"${esc(imgOf(s.product_id))}\" alt=\"${esc(s.name)}\" />` : `<span class=\"mono\">${esc(mono(s.name))}</span>`}</div>\n              <div><div class=\"s-name\">${esc(s.name)}</div><div class=\"s-reason\">${s.synergy ? '✨ ' : ''}${esc(s.reason)}</div></div>\n              <div class=\"s-right\"><div class=\"s-price\">${money(s.price)}</div><button class=\"s-add js-add-sugg\" data-id=\"${s.product_id}\">Adicionar</button></div>\n            </div>`).join('') : `<div class=\"sugg-empty\">Seu pedido já está completo. ✨</div>`)\n\n        checkout = `<div class=\"co\">\n          <div class=\"co-head\"><button class=\"co-back js-home\">← Continuar comprando</button><h1 class=\"serif\">Finalizar pedido</h1></div>\n          <div class=\"co-grid\">\n            <div class=\"co-main\">\n              <section class=\"co-card\"><h2>1 · Revise seu pedido</h2>${itemsHtml}</section>\n              <section class=\"co-card co-sugg\">\n                <div class=\"sugg-head\"><div class=\"sugg-ico\">✨</div><div><h2>A consultora sugere</h2><p>Itens que completam sua rotina, escolhidos pela IA com base no que você já tem.</p></div></div>\n                ${suggBody}\n              </section>\n              <section class=\"co-card\"><h2>2 · Entrega e pagamento</h2>\n                <div class=\"field-mock\">Rua das Flores, 123 · São Paulo, SP · 01234-000</div>\n                <div class=\"pay-row js-pay ${pay === 'cartao' ? 'sel' : ''}\" data-pay=\"cartao\"><div class=\"radio\"></div><div><div class=\"pay-label\">Cartão de crédito</div><div class=\"pay-sub\">Visa •••• 4242</div></div></div>\n                <div class=\"pay-row js-pay ${pay === 'pix' ? 'sel' : ''}\" data-pay=\"pix\"><div class=\"radio\"></div><div><div class=\"pay-label\">Pix</div><div class=\"pay-sub\">${pay === 'pix' ? 'QR Code gerado na confirmação' : 'Aprovação imediata'}</div></div></div>\n                <div class=\"secure\">🔒 Ambiente seguro · esta é uma demonstração, nenhum pagamento é processado.</div>\n              </section>\n            </div>\n            <aside class=\"co-summary\">\n              <h3>Resumo</h3>\n              <div class=\"sum-row\"><span>Subtotal (${cartCount} ${cartCount === 1 ? 'item' : 'itens'})</span><span>${money(cartTotal)}</span></div>\n              <div class=\"sum-row\"><span>Frete</span><span class=\"free\">Grátis</span></div>\n              ${couponDiscount > 0 ? `<div class=\"sum-row\"><span>🎟️ Cupom ${esc(coupon.code)}</span><span class=\"free\">− ${money(couponDiscount)}</span></div>` : ''}<div class=\"sum-row total\"><span>Total</span><span>${money(cartFinal)}</span></div>\n              <button class=\"btn primary lg js-confirm\" style=\"margin-top:16px\">Confirmar pedido</button>\n              <div class=\"co-badges\"><span>🔒 Compra 100% segura</span><span>🚚 Frete grátis acima de R$ 279</span><span>↩️ Troca fácil em 30 dias</span></div>\n            </aside>\n          </div>\n        </div>`\n      }\n    }\n\n    const mainView = view === 'checkout' ? checkout : store\n\n    let cartHtml = ''\n    if (d2.state.cartOpen) {\n      const suggs = d2.state.suggestions || []\n      const ccBlock = `<div class=\"cart-consultora\">\n          <div class=\"cc-head\"><span class=\"cc-ico\">✨</span>Sua consultora</div>\n          ${suggs.length ? `<div class=\"cc-line\">Leve também — combina com o que você escolheu:</div>${suggs.slice(0, 2).map((s) => `<div class=\"cc-sitem\" data-key=\"${s.product_id}\"><div class=\"cc-sinfo\"><div class=\"cc-sname\">${esc(s.name)}</div><div class=\"cc-sreason\">${s.synergy ? '✨ ' : ''}${esc(s.reason)}</div></div><button class=\"cc-sadd js-add-sugg\" data-id=\"${s.product_id}\">${money(s.price)} +</button></div>`).join('')}` : ''}\n          <button class=\"cc-chat js-cart-to-chat\">Não sabe se combina com a sua pele? Fale comigo →</button>\n        </div>`\n      const body = cartItems.length\n        ? `<div class=\"drawer-body\">${cartItems.map((p) => `<div class=\"citem\" data-key=\"${p._id}\">\n            <div class=\"cthumb\">${p.image_url ? `<img src=\"${esc(p.image_url)}\" alt=\"${esc(p.name)}\" />` : `<span class=\"mono\">${esc(mono(p.name))}</span>`}</div>\n            <div class=\"cinfo\"><div class=\"cname\">${esc(p.name)}</div><div class=\"cprice\">${money(p.price)} un.</div>\n              <div class=\"crow\"><div class=\"stepper sm\"><button class=\"qbtn js-dec\" data-id=\"${p._id}\">−</button><span class=\"qn\">${qOf(p._id)}</span><button class=\"qbtn js-inc\" data-id=\"${p._id}\">+</button></div><button class=\"cremove js-remove\" data-id=\"${p._id}\">remover</button></div></div>\n            <div class=\"cline\">${money((Number(p.price) || 0) * qOf(p._id))}</div></div>`).join('')}${ccBlock}</div>\n          <div class=\"drawer-foot\">${coupon && coupon.code ? (couponDiscount > 0 ? `<div class=\"cpline\"><span>🎟️ Cupom ${esc(coupon.code)} · <button class=\"cpremove js-remove-coupon\" type=\"button\">remover</button></span><span>− ${money(couponDiscount)}</span></div>` : `<div class=\"cpline off\"><span>🎟️ Cupom ${esc(coupon.code)} — mínimo de ${money(coupon.min_total)} não atingido</span><button class=\"cpremove js-remove-coupon\" type=\"button\">remover</button></div>`) : ''}<div class=\"subtotal\"><span>${couponDiscount > 0 ? 'Total com desconto' : 'Subtotal'}</span><span>${money(cartFinal)}</span></div>\n            <button class=\"btn primary lg js-checkout\">Finalizar compra</button>\n            <div class=\"foot-fine\">Revise e finalize com segurança na próxima etapa.</div></div>`\n        : `<div class=\"empty-cart\"><div>🛍️</div><p>Sua sacola está vazia.</p></div>`\n      cartHtml = `<div class=\"scrim js-cart-close\"></div><aside class=\"drawer\">\n        <div class=\"drawer-head\"><div class=\"dh-title serif\">Sua sacola</div><button class=\"close js-cart-close\">✕</button></div>${body}</aside>`\n    }\n\n    let chatHtml\n    if (!d2.state.open) {\n      chatHtml = `<div class=\"launcher js-open\"><span class=\"l-pulse\"></span><span class=\"l-ico\">✨</span><span class=\"l-label\">Consultora de beleza</span></div>`\n    } else {\n      const msgs = d2.state.messages || []\n      const loading = !!d2.state.loading || !!d2.state.hairAnalyzing\n      const couponCard = (c) => {\n        const applied = d2.state.coupon && d2.state.coupon.code === c.code\n        return `<div class=\"cpn\" data-key=\"${esc(c.code)}\">\n          <div class=\"cpn-top\"><span class=\"cpn-code\">🎟️ ${esc(c.code)}</span><span class=\"cpn-save\">− ${money(c.savings)}</span></div>\n          <div class=\"cpn-desc\">${esc(c.description)}</div>\n          <button class=\"cpn-apply js-apply-coupon\" data-code=\"${esc(c.code)}\" data-type=\"${esc(c.discount_type)}\" data-value=\"${Number(c.discount_value) || 0}\" data-scope=\"${esc(c.scope)}\" data-category=\"${esc(c.category || '')}\" data-min=\"${Number(c.min_total) || 0}\" type=\"button\" ${applied ? 'disabled' : ''}>${applied ? 'Cupom aplicado ✓' : 'Aplicar cupom'}</button>\n        </div>`\n      }\n      const optCard = (o) => `<div class=\"ocard\" data-key=\"${o.product_id}\"><div class=\"othumb\">${imgOf(o.product_id) ? `<img src=\"${esc(imgOf(o.product_id))}\" alt=\"${esc(o.name)}\" />` : `<span class=\"mono\">${esc(mono(o.name))}</span>`}</div><div class=\"oinfo\"><div class=\"oname\">${esc(o.name)}</div><div class=\"ostep\">${esc(o.step)}</div></div><div class=\"oright\"><div class=\"oprice\">${money(o.price)}</div><button class=\"oadd js-add-opt\" data-id=\"${o.product_id}\">Adicionar</button><button class=\"odetail js-open-side\" data-id=\"${o.product_id}\">Ver detalhes</button></div></div>`\n      const routineCard = (r) => `<div class=\"rcard ${r.budget_active ? (r.over_budget ? 'rcard-over' : 'rcard-ok') : ''}\" data-key=\"${esc(r.key)}\">\n          <div class=\"rtop\"><div class=\"rname\">${esc(r.name)}${r.budget_active ? (r.over_budget ? '<span class=\"rover\">acima do orçamento</span>' : '<span class=\"rok\">dentro do orçamento</span>') : ''}</div><div class=\"rtotal\">${money(r.total)}</div></div>\n          <div class=\"rblurb\">${esc(r.blurb)}</div>\n          ${(r.items || []).map((it) => `<div class=\"ritem\"><span>${esc(it.step)} · ${esc(it.name)}</span><span>${money(it.price)}</span></div>`).join('')}\n          ${(r.warnings || []).map((w) => `<div class=\"rwarn\">⚠️ ${esc(w)}</div>`).join('')}\n          <button class=\"radd js-addroutine\" data-key=\"${esc(r.key)}\">Adicionar rotina à sacola</button></div>`\n      const rows = msgs.length\n        ? msgs.map((m,i) => `<div class=\"row ${m.role}\" data-key=\"${i}\">${m.text ? `<div class=\"msg ${m.role}\">${esc(m.text)}</div>` : ''}${m.image ? `<div class=\"msg ${m.role} imgmsg\"><img src=\"${m.image}\" alt=\"Foto enviada\" /></div>` : ''}${m.routines && m.routines.length ? `<div class=\"routines\">${m.routines.map(routineCard).join('')}</div>` : ''}${m.options && m.options.length ? `<div class=\"opts\">${m.options.slice(0, 4).map(optCard).join('')}</div>` : ''}${m.coupon && m.coupon.code ? couponCard(m.coupon) : ''}${m.qoptions && m.qoptions.length ? `<div class=\"qchips\">${m.qoptions.map((q) => `<button class=\"chip js-chip\">${esc(q)}</button>`).join('')}</div>` : ''}</div>`).join('')\n        : `<div class=\"estate\"><div class=\"wave\">👋</div><h3>Oi! Sou sua consultora de beleza.</h3>\n            <p>Descreva sua necessidade que eu monto uma rotina completa — com avisos de compatibilidade entre ativos.</p>\n            <div class=\"chips\"><button class=\"chip js-chip\">Pele oleosa, controlar o brilho</button><button class=\"chip js-chip\">Quero cuidar de linhas finas</button></div></div>`\n      const dots = loading ? `<div class=\"row bot\"><div class=\"msg bot\"><span class=\"dots\"><span></span><span></span><span></span></span></div></div>` : ''\n      chatHtml = `<div class=\"panel\">\n        <div class=\"phead\"><div class=\"ph-row\"><div class=\"ph-brand\"><div class=\"ph-ico\">✨</div>\n          <div><div class=\"ptitle\">Consultora de Beleza</div><div class=\"psub\">IA Data2 · personal shopper</div></div></div>\n          <button class=\"pclose js-close\">✕</button></div></div>\n        <div class=\"log\">${rows}${dots}</div>\n        <button class=\"unread js-unread\" style=\"display:none\" type=\"button\">↓ nova mensagem</button>\n        <div class=\"bar\"><div class=\"field\"><textarea class=\"cin\" rows=\"1\" placeholder=\"Descreva sua necessidade...\"></textarea></div>\n          ${catB ? `<label class=\"photo js-photo-label\" title=\"Enviar foto do cabelo\">📷<input type=\"file\" accept=\"image/*\" class=\"js-photo-input\" hidden /></label>` : ''}\n          <button class=\"mic js-mic ${d2.state.recording ? 'rec' : ''}\" title=\"Gravar áudio\">${d2.state.recording ? '⏹' : '🎤'}</button>\n          <button class=\"send js-send\" ${loading ? 'disabled' : ''}><svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M3.4 20.4l17.45-7.48a1 1 0 0 0 0-1.84L3.4 3.6a.993.993 0 0 0-1.39.91L2 9.12c0 .5.37.93.87.99L17 12 2.87 13.88c-.5.07-.87.5-.87 1l.01 4.61c0 .67.68 1.13 1.39.91z\"/></svg></button></div>\n      </div>`\n    }\n\n    let modalHtml = ''\n    if (d2.state.selectedId) {\n      const mp = products.filter((x) => x._id === d2.state.selectedId)[0]\n      if (mp) {\n        const mq = qOf(mp._id)\n        const mact = mq > 0\n          ? `<div class=\"stepper full\"><button class=\"qbtn js-dec\" data-id=\"${mp._id}\">−</button><span class=\"qn\">${mq}</span><button class=\"qbtn js-inc\" data-id=\"${mp._id}\">+</button></div>`\n          : `<button class=\"addbtn js-add\" data-id=\"${mp._id}\">Adicionar à sacola</button>`\n        modalHtml = `<div class=\"mscrim js-modal-close\"></div>\n          <div class=\"pmodal\">\n            <button class=\"pm-close js-modal-close\">✕</button>\n            <div class=\"pm-img\">${mp.image_url ? `<img class=\"pmimg\" src=\"${esc(mp.image_url)}\" alt=\"${esc(mp.name || '')}\" />` : `<span class=\"mono\">${esc(mono(mp.name))}</span>`}<span class=\"thumb-tag\">${esc(mp.category || '')}</span></div>\n            <div class=\"pm-body\">\n              <div class=\"pm-brand\">${esc(mp.brand || '')}</div>\n              <div class=\"pm-name serif\">${esc(mp.name || '')}</div>\n              <div class=\"pm-price\">${money(mp.price)}</div>\n              <p class=\"pm-desc\">${esc(mp.description || '')}</p>\n              <div class=\"pm-meta\">\n                <div class=\"pm-mrow\"><span class=\"pm-mk\">Como usar</span><span class=\"pm-mv\">${esc(mp.how_to_use || '—')}</span></div>\n                <div class=\"pm-mrow\"><span class=\"pm-mk\">Duração</span><span class=\"pm-mv\">~${esc(mp.duration_days || '?')} dias de uso</span></div>\n                <div class=\"pm-mrow\"><span class=\"pm-mk\">Período</span><span class=\"pm-mv\">${esc(mp.usage_period || '—')}</span></div>\n                ${mp.contraindications ? `<div class=\"pm-mrow\"><span class=\"pm-mk\">Contraindicações</span><span class=\"pm-mv\">${esc(mp.contraindications)}</span></div>` : ''}\n              </div>\n              ${mact}\n              <div class=\"pm-consultora\">\n                <div class=\"pm-cico\">✨</div>\n                <div class=\"pm-ctxt\"><strong>Sua consultora</strong><span>Quer saber se combina com a sua pele e como encaixar na rotina?</span></div>\n                <button class=\"pm-cbtn js-ask-product\" data-id=\"${mp._id}\" data-name=\"${esc(mp.name || '')}\">Perguntar</button>\n              </div>\n            </div>\n          </div>`\n      }\n    }\n    let sideModalHtml = ''\n    if (d2.state.open && d2.state.sideProductId) {\n      const sp = products.filter((x) => x._id === d2.state.sideProductId)[0]\n      if (sp) {\n        const sq = qOf(sp._id)\n        const sact = sq > 0\n          ? `<div class=\"stepper full\"><button class=\"qbtn js-dec\" data-id=\"${sp._id}\">−</button><span class=\"qn\">${sq}</span><button class=\"qbtn js-inc\" data-id=\"${sp._id}\">+</button></div>`\n          : `<button class=\"sm-add js-add-side\" data-id=\"${sp._id}\">Adicionar à sacola</button>`\n        sideModalHtml = `<div class=\"sidemodal\">\n          <div class=\"sm-head\"><span class=\"sm-tag\">${esc(sp.category || '')}</span><button class=\"sm-close js-side-close\" type=\"button\">✕</button></div>\n          <div class=\"sm-img\">${sp.image_url ? `<img src=\"${esc(sp.image_url)}\" alt=\"${esc(sp.name || '')}\" />` : `<span class=\"mono\">${esc(mono(sp.name))}</span>`}</div>\n          <div class=\"sm-body\">\n            <div class=\"sm-brand\">${esc(sp.brand || '')}</div>\n            <div class=\"sm-name\">${esc(sp.name || '')}</div>\n            <div class=\"sm-price\">${money(sp.price)}</div>\n            <p class=\"sm-desc\">${esc(sp.description || '')}</p>\n            <div class=\"sm-meta\">\n              <div class=\"sm-mrow\"><span class=\"sm-mk\">Como usar</span><span class=\"sm-mv\">${esc(sp.how_to_use || '—')}</span></div>\n              <div class=\"sm-mrow\"><span class=\"sm-mk\">Quando</span><span class=\"sm-mv\">${esc(sp.usage_period || '—')}</span></div>\n              <div class=\"sm-mrow\"><span class=\"sm-mk\">Duração</span><span class=\"sm-mv\">~${esc(sp.duration_days || '?')} dias de uso</span></div>\n              ${sp.contraindications ? `<div class=\"sm-mrow\"><span class=\"sm-mk\">Contraindicações</span><span class=\"sm-mv\">${esc(sp.contraindications)}</span></div>` : ''}\n            </div>\n            ${sact}\n          </div>\n        </div>`\n      }\n    }\n    return `<div class=\"page\">${mainView}</div>${cartHtml}${chatHtml}${sideModalHtml}${modalHtml}`\n  },\n  mounted(d2) {\n    const sleep = (ms) => new Promise((r) => setTimeout(r, ms))\n    try {\n      if (!document.getElementById('d2-lux-fonts')) {\n        const l = document.createElement('link')\n        l.id = 'd2-lux-fonts'; l.rel = 'stylesheet'\n        l.href = 'https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400;1,500&family=Inter:wght@400;500;600&display=swap'\n        document.head.appendChild(l)\n      }\n    } catch (e) {}\n    // aquece o módulo de transcrição na carga da página (evita 1ª chamada em módulo frio)\n    try { d2.assistant('consultora-ouvido') } catch (e) {}\n    const addToCart = (id, n, source) => {\n      const c = { ...(d2.state.cart || {}) }\n      const src = { ...(d2.state.cartSource || {}) }\n      c[id] = (c[id] || 0) + n\n      if (c[id] <= 0) { delete c[id]; delete src[id] }\n      else if (source && !src[id]) { src[id] = source }\n      d2.state.cart = c\n      d2.state.cartSource = src\n    }\n    const loadSuggestions = async () => {\n      const ids = Object.keys(d2.state.cart || {})\n      d2.state.suggestLoading = true\n      try {\n        const res = await d2.rush('sugere-complemento').invoke({ cart_ids: ids })\n        const r = (res && res.data) ? res.data : res\n        d2.state.suggestions = (r && r.suggestions) || []\n      } catch (err) {\n        d2.log('sugere-complemento error', err)\n        d2.state.suggestions = []\n      } finally {\n        d2.state.suggestLoading = false\n      }\n    }\n    const send = async (preset, opts) => {\n      const spoken = !!(opts && opts.spoken)\n      const t = d2.$('.cin')\n      const text = (preset != null ? preset : (t ? t.value : '')).trim()\n      if (!text || d2.state.loading) return\n      if (t) { t.value = ''; t.style.height = '24px' }\n      const priorMsgs = (d2.state.messages || []).slice(-40).map((m) => ({ role: m.role, text: m.text }))\n      d2.state.messages = [...(d2.state.messages || []), { role: 'user', text }]\n      d2.state.loading = true\n      const t0 = Date.now()\n      try {\n        const pds = d2.data(d2.state.catalog === 'b' ? 'bot-products-bDataSet' : 'products')\n        const prodRows = (pds && !pds.loading) ? pds.records() : []\n        const curCart = d2.state.cart || {}\n        const cartPayload = prodRows.filter((p) => (curCart[p._id] || 0) > 0).map((p) => ({ product_id: p._id, name: p.name, qty: curCart[p._id] }))\n        const res = await d2.rush('consultoria-turn').invoke({ userMessage: text, cart: cartPayload, session_budget: d2.state.sessionBudget || {}, history: priorMsgs, applied_coupon: (d2.state.coupon && d2.state.coupon.code) || '', catalog: d2.state.catalog || 'a' })\n        const r = (res && res.data) ? res.data : res\n        if (!r || r.type === 'error') throw new Error((r && r.message) || 'resposta vazia')\n        // cadência humana: os pontinhos ficam ao menos ~1.1s na tela\n        const waitMs = 1100 - (Date.now() - t0)\n        if (waitMs > 0) await sleep(waitMs)\n        if (r && r.budget && (Number(r.budget.value) || 0) > 0) {\n          d2.state.sessionBudget = { scope: r.budget.scope || '', value: r.budget.value, hint: (r.intent && r.intent.product_hint) || (d2.state.sessionBudget && d2.state.sessionBudget.hint) || '' }\n        }\n        if (r.type === 'cart_action') {\n          const c = { ...(d2.state.cart || {}) }\n          const src = { ...(d2.state.cartSource || {}) }\n          ;(r.ops || []).forEach((o) => {\n            const id = o.product_id\n            if (!id) return\n            if (o.op === 'remove') { delete c[id]; delete src[id] }\n            else if (o.op === 'set_qty') { const q = Number(o.qty) || 0; if (q <= 0) { delete c[id]; delete src[id] } else { c[id] = q; if (!src[id]) src[id] = 'bot' } }\n            else { c[id] = (c[id] || 0) + (Number(o.qty) || 1); if (!src[id]) src[id] = 'bot' }\n            if (c[id] !== undefined && c[id] <= 0) { delete c[id]; delete src[id] }\n          })\n          d2.state.cart = c\n          d2.state.cartSource = src\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: r.reply || 'Pronto, atualizei sua sacola! 🛍️' }]\n        } else if (r.type === 'coupon_offer') {\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: r.reply || 'Deixa eu ver o que consigo de desconto pra você…' }]\n          if (r.has_coupon && r.coupon && r.coupon.code) {\n            await sleep(900)\n            d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '', coupon: r.coupon }]\n          }\n        } else if (r.type === 'product_options') {\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: r.reply || 'Veja as opções:' }]\n          await sleep(900)\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '', options: r.options || [] }]\n        } else if (r.type === 'chat') {\n          const csets = (r.routines || []).map((rt) => ({ key: 'set-' + Date.now() + '-' + Math.floor(Math.random() * 1000), name: rt.name, blurb: rt.rationale || '', warnings: [], items: rt.items_detailed || [], total: rt.total, budget_active: false, over_budget: false }))\n          if (csets.length) { const rmap = { ...(d2.state.routineMap || {}) }; csets.forEach((rt) => { rmap[rt.key] = rt.items.map((it) => it.product_id) }); d2.state.routineMap = rmap }\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: r.reply || 'Como posso ajudar?' }]\n          if (csets.length) { await sleep(900); d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '', routines: csets }] }\n        } else if (r.type === 'question') {\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: r.question || 'Pode me dar mais detalhes?', qoptions: r.question_options || [] }]\n        } else {\n          const copyByKey = {}\n          ;((r.copy && r.copy.routines) || []).forEach((c) => { copyByKey[c.key] = c })\n          const hasBudget = !!(r.budget && (Number(r.budget.value) || 0) > 0)\n          const routines = (r.routines || []).map((rt) => ({\n            key: rt.key, name: rt.name, total: rt.total,\n            blurb: (copyByKey[rt.key] && copyByKey[rt.key].blurb) || rt.rationale || '',\n            warnings: (copyByKey[rt.key] && copyByKey[rt.key].warnings) || [],\n            items: rt.items_detailed || [],\n            over_budget: !!rt.over_budget,\n            budget_active: hasBudget,\n          }))\n          const rmap = { ...(d2.state.routineMap || {}) }\n          routines.forEach((rt) => { rmap[rt.key] = rt.items.map((it) => it.product_id) })\n          d2.state.routineMap = rmap\n          const botText = (r.copy && r.copy.diagnosis) || r.diagnosis_seed || 'Aqui estão as rotinas que montei pra você:'\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: botText }]\n          await sleep(1000)\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '', routines }]\n        }\n        if (spoken) {\n          const msgs2 = d2.state.messages || []\n          let say = ''\n          for (let i = msgs2.length - 1; i >= 0; i--) { if (msgs2[i].role === 'bot' && msgs2[i].text) { say = msgs2[i].text; break } }\n          if (say) { try { d2.assistant('consultora-ouvido').speak(say, { language: 'pt-BR', voice: 'Camila' }) } catch (e) { d2.log('speak error', e) } }\n        }\n      } catch (err) {\n        d2.log('consultoria-turn error', err)\n        d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '⚠️ Tive um problema ao montar a rotina. Pode tentar de novo?' }]\n      } finally {\n        d2.state.loading = false\n      }\n    }\n\n    let mediaRecorder = null\n    let audioChunks = []\n    let micBusy = false\n    let recStartAt = 0\n    const startRec = async () => {\n      if (micBusy || d2.state.recording) return\n      micBusy = true\n      try {\n        // primeiro uso: se a permissão ainda vai ser pedida, só libera o mic e orienta — não grava\n        let perm = null\n        try { perm = navigator.permissions ? await navigator.permissions.query({ name: 'microphone' }) : null } catch (e) { perm = null }\n        if (perm && perm.state === 'prompt') {\n          const warmup = await navigator.mediaDevices.getUserMedia({ audio: true })\n          warmup.getTracks().forEach((t) => t.stop())\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: 'Microfone liberado! 🎤 Agora toque no microfone, fale sua mensagem e toque de novo para enviar.' }]\n          return\n        }\n        const stream = await navigator.mediaDevices.getUserMedia({ audio: true })\n        audioChunks = []\n        mediaRecorder = new MediaRecorder(stream)\n        mediaRecorder.ondataavailable = (e) => { if (e.data && e.data.size > 0) audioChunks.push(e.data) }\n        mediaRecorder.onstop = async () => {\n          stream.getTracks().forEach((t) => t.stop())\n          d2.state.recording = false\n          const tooShort = (Date.now() - recStartAt) < 700\n          const blob = new Blob(audioChunks, { type: mediaRecorder.mimeType || 'audio/webm' })\n          if (tooShort || !blob.size) {\n            d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: 'Não captei o áudio. 🎤 Toque no microfone, fale sua mensagem e toque de novo para enviar.' }]\n            return\n          }\n          const file = new File([blob], 'audio.webm', { type: blob.type })\n          d2.state.loading = true\n          try {\n            const hint = 'Mensagem de voz de um cliente de uma loja de beleza brasileira, falada em português do Brasil.'\n            const grab = (r) => (r && r.text) ? r.text : (typeof r === 'string' ? r : '')\n            let res = await d2.assistant('consultora-ouvido').listen(file, hint, { language: 'pt' })\n            let text = grab(res)\n            if (!text || !text.trim()) {\n              // 1º uso: módulo de transcrição pode estar inicializando — tenta 1x de novo com o mesmo áudio\n              await sleep(500)\n              res = await d2.assistant('consultora-ouvido').listen(file, hint, { language: 'pt' })\n              text = grab(res)\n            }\n            d2.state.loading = false\n            const clean = (text || '').trim()\n            const low = clean.toLowerCase().replace(/[.!?…\"'’]/g, '').trim()\n            const junk = ['amara.org', 'amara org', 'legendas pela comunidade', 'legendado pela comunidade', 'legendas pela', 'subtitles by', 'subtitle', 'thanks for watching', 'obrigado por assistir', 'inscreva-se', 'subscribe', 'www.']\n            const isJunk = !low || low.length < 2 || junk.some((b) => low.includes(b))\n            if (clean && !isJunk) { send(clean, { spoken: true }) }\n            else { d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '🎤 Não captei sua voz — parece que o microfone estava mudo ou sem áudio. Confira se ele está habilitado e tente de novo, ou escreva sua mensagem por aqui.' }] }\n          } catch (err) {\n            d2.log('listen error', err)\n            d2.state.loading = false\n            d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '⚠️ Tive um problema para transcrever o áudio. Pode escrever?' }]\n          }\n        }\n        mediaRecorder.start()\n        recStartAt = Date.now()\n        d2.state.recording = true\n      } catch (err) {\n        d2.log('mic error', err)\n        const denied = err && (err.name === 'NotAllowedError' || err.name === 'PermissionDeniedError' || err.name === 'SecurityError')\n        d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: denied ? 'O microfone está bloqueado pelo navegador. 🎤 Clique no cadeado ao lado do endereço do site, permita o microfone e tente de novo.' : 'Não consegui acessar o microfone. Verifique se outro aplicativo não está usando ele e tente de novo.' }]\n      } finally {\n        micBusy = false\n      }\n    }\n    d2.on('.js-mic', 'click', () => { if (d2.state.recording && mediaRecorder) { mediaRecorder.stop() } else { startRec() } })\n    const resizeImg = (file) => new Promise((resolve, reject) => {\n      const r = new FileReader()\n      r.onload = () => {\n        const img = new Image()\n        img.onload = () => {\n          const max = 768; let w = img.width; let h = img.height\n          if (w > h && w > max) { h = Math.round(h * max / w); w = max }\n          else if (h > max) { w = Math.round(w * max / h); h = max }\n          const c = document.createElement('canvas'); c.width = w; c.height = h\n          c.getContext('2d').drawImage(img, 0, 0, w, h)\n          resolve(c.toDataURL('image/jpeg', 0.85))\n        }\n        img.onerror = reject; img.src = r.result\n      }\n      r.onerror = reject; r.readAsDataURL(file)\n    })\n    const parseAnalysis = (resp) => {\n      let a = (resp && resp.data !== undefined) ? resp.data : resp\n      if (typeof a === 'string') { try { a = JSON.parse(a.replace(/```json/gi, '').replace(/```/g, '').trim()) } catch (e) { a = null } }\n      return a\n    }\n    const hairRoutine = (a) => {\n      const bds = d2.data('bot-products-bDataSet')\n      const prods = (bds && !bds.loading) ? bds.records() : []\n      if (!prods.length) return null\n      const want = []\n      const tx = (a.texture || '').toLowerCase()\n      if (/cach|crespo|ondul/.test(tx)) want.push('cach', 'crespo', 'textura')\n      const cond = (a.condition || '').toLowerCase()\n      if (cond === 'seco') want.push('seco', 'ressecad')\n      if (cond === 'danificado') want.push('danificad')\n      if (cond === 'oleoso') want.push('oleos')\n      if (a.colored) want.push('loiro', 'descolor')\n      const need = (a.needs || []).join(' ').toLowerCase()\n      const score = (p) => {\n        const sub = (p.subcategory || '').toLowerCase(); const nm = (p.name || '').toLowerCase(); let s = 0\n        want.forEach((t) => { if (sub.includes(t)) s += 3; if (nm.includes(t)) s += 1 })\n        if (need.includes('hidrat') && /hidrat/.test(nm)) s += 2\n        if (need.includes('reconstru') && /reconstru/.test(nm)) s += 2\n        if ((need.includes('cach') || need.includes('frizz') || need.includes('defini')) && /cach|frizz/.test(nm)) s += 2\n        if (need.includes('loiro') && /loiro/.test(nm)) s += 2\n        if (sub.includes('todos')) s += 0.3\n        return s\n      }\n      const cats = ['Shampoo', 'Condicionador', 'Máscara', 'Leave-in', 'Finalizador', 'Óleo']\n      const items = []\n      cats.forEach((c) => { const pool = prods.filter((p) => p.category === c); if (pool.length) { pool.sort((x, y) => score(y) - score(x)); items.push(pool[0]) } })\n      const chosen = items.slice(0, 4)\n      if (!chosen.length) return null\n      return {\n        key: 'hair-' + Date.now() + '-' + Math.floor(Math.random() * 1000),\n        name: 'Rotina para o seu cabelo',\n        blurb: a.summary || 'Selecionei com base na análise do seu cabelo.',\n        warnings: [],\n        items: chosen.map((p) => ({ product_id: p._id, name: p.name, price: p.price, step: p.category, image: p.image_url })),\n        total: chosen.reduce((t, p) => t + (Number(p.price) || 0), 0),\n        budget_active: false, over_budget: false,\n      }\n    }\n    d2.on('.js-photo-input', 'change', async (e, el) => {\n      const file = el.files && el.files[0]\n      el.value = ''\n      if (!file || !/^image\\//.test(file.type)) return\n      d2.state.open = true\n      d2.state.hairAnalyzing = true\n      let dataUrl = ''\n      try { dataUrl = await resizeImg(file) } catch (er) { d2.state.hairAnalyzing = false; d2.log('resize error', er); return }\n      try {\n        const resp = await d2.rush('analisa-cabelo').invoke({ image: dataUrl })\n        const a = parseAnalysis(resp)\n        d2.state.hairAnalyzing = false\n        if (!a || !a.is_hair) {\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '📷 ' + ((a && a.reject_reason) || 'Não consegui identificar seu cabelo nessa foto') + '. Pra eu recomendar direitinho — e pela sua segurança — me envie uma foto focada só no cabelo, tá? 💇' }]\n          return\n        }\n        d2.state.messages = [...(d2.state.messages || []), { role: 'user', text: '', image: dataUrl }]\n        const rt = hairRoutine(a)\n        d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: (a.summary || 'Analisei seu cabelo!') + (rt ? ' Montei uma rotina que combina com ele 👇' : ' Me conta o que você busca que eu recomendo.') }]\n        if (rt) {\n          const rmap = { ...(d2.state.routineMap || {}) }; rmap[rt.key] = rt.items.map((it) => it.product_id); d2.state.routineMap = rmap\n          await sleep(900)\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '', routines: [rt] }]\n        }\n      } catch (err) {\n        d2.log('analisa-cabelo error', err)\n        d2.state.hairAnalyzing = false\n        d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '⚠️ Não consegui analisar a foto agora. Pode tentar de novo?' }]\n      }\n    })\n    d2.on('.js-open-product', 'click', (e, el) => { if (e.target && e.target.closest && e.target.closest('button')) return; d2.state.selectedId = el.dataset.id })\n    d2.on('.js-modal-close', 'click', () => { d2.state.selectedId = null })\n    d2.on('.js-open-side', 'click', (e, el) => { d2.state.sideProductId = el.dataset.id })\n    d2.on('.js-side-close', 'click', () => { d2.state.sideProductId = null })\n    d2.on('.js-add-side', 'click', (e, el) => addToCart(el.dataset.id, 1, 'bot'))\n    d2.on('.js-ask-product', 'click', (e, el) => { d2.state.selectedId = null; d2.state.open = true; send('Me conta mais sobre o ' + el.dataset.name + ' — combina com a minha pele e como eu uso?') })\n    d2.on('.js-add', 'click', (e, el) => addToCart(el.dataset.id, 1, 'manual'))\n    d2.on('.js-inc', 'click', (e, el) => addToCart(el.dataset.id, 1, 'manual'))\n    d2.on('.js-dec', 'click', (e, el) => addToCart(el.dataset.id, -1))\n    d2.on('.js-remove', 'click', (e, el) => { const c = { ...(d2.state.cart || {}) }; const src = { ...(d2.state.cartSource || {}) }; delete c[el.dataset.id]; delete src[el.dataset.id]; d2.state.cart = c; d2.state.cartSource = src })\n    d2.on('.js-cart', 'click', () => { d2.state.cartOpen = true; loadSuggestions() })\n    d2.on('.js-fav', 'click', (e, el) => { const f = { ...(d2.state.favs || {}) }; const id = el.dataset.id; if (f[id]) { delete f[id] } else { f[id] = true }; d2.state.favs = f })\n    d2.on('.js-cat', 'click', (e, el) => { d2.state.category = el.dataset.cat || '' })\n    d2.on('.js-catsw', 'click', () => {\n      d2.state.catalog = (d2.state.catalog === 'b') ? 'a' : 'b'\n      d2.state.cart = {}; d2.state.cartSource = {}; d2.state.coupon = null; d2.state.category = ''\n    })\n    d2.on('.js-profile', 'click', () => {\n      let authed = false\n      try { authed = sessionStorage.getItem('painelAuthed') === '1' } catch (e) { authed = false }\n      if (!authed) { window.location.assign('/login'); return }\n      d2.state.profileMenu = !d2.state.profileMenu\n    })\n    d2.on('.js-profile-close', 'click', () => { d2.state.profileMenu = false })\n    d2.on('.js-goto-painel', 'click', () => {\n      d2.state.profileMenu = false\n      // navegação completa: o router monta na rota e reavalia a policy do /painel\n      window.location.assign('/painel')\n    })\n    d2.on('.js-cart-to-chat', 'click', () => { d2.state.cartOpen = false; d2.state.open = true; send('Os produtos da minha sacola combinam com a minha pele? Pode conferir?') })\n    d2.on('.js-pay', 'click', (e, el) => { d2.state.payMethod = el.dataset.pay })\n    d2.on('.js-cart-close', 'click', () => { d2.state.cartOpen = false })\n    d2.on('.js-checkout', 'click', () => { d2.state.cartOpen = false; d2.state.checkoutDone = false; d2.state.view = 'checkout'; loadSuggestions() })\n    d2.on('.js-home', 'click', () => { d2.state.view = 'store'; d2.state.checkoutDone = false })\n    d2.on('.js-confirm', 'click', async () => {\n      const order = '#AB' + Math.floor(100000 + Math.random() * 900000)\n      try {\n        const pds = d2.data(d2.state.catalog === 'b' ? 'bot-products-bDataSet' : 'products')\n        const prods = (pds && !pds.loading) ? pds.records() : []\n        const cart = d2.state.cart || {}\n        const items = prods.filter((p) => (cart[p._id] || 0) > 0)\n        const itensCount = items.reduce((a, p) => a + (cart[p._id] || 0), 0)\n        const gross = items.reduce((a, p) => a + (Number(p.price) || 0) * (cart[p._id] || 0), 0)\n        const cp = d2.state.coupon\n        let discount = 0\n        if (cp && cp.code) {\n          const base = cp.scope === 'categoria' ? items.reduce((a, p) => a + ((p.category === cp.category) ? (Number(p.price) || 0) * (cart[p._id] || 0) : 0), 0) : gross\n          if (gross >= (Number(cp.min_total) || 0)) {\n            discount = cp.discount_type === 'percent' ? base * (Number(cp.discount_value) || 0) / 100 : Math.min(Number(cp.discount_value) || 0, base)\n          }\n        }\n        const ticket = Math.max(0, gross - discount)\n        const baseline = items.reduce((m, p) => Math.max(m, Number(p.price) || 0), 0)\n        const recorrencia = items.reduce((a, p) => { const dd = Number(p.duration_days) || 0; return a + (dd > 0 ? (Number(p.price) || 0) * (cart[p._id] || 0) * 30 / dd : 0) }, 0)\n        const csrc = d2.state.cartSource || {}\n        const isBot = (p) => csrc[p._id] === 'bot'\n        const itensBot = items.reduce((a, p) => a + (isBot(p) ? (cart[p._id] || 0) : 0), 0)\n        const ticketBot = items.reduce((a, p) => a + (isBot(p) ? (Number(p.price) || 0) * (cart[p._id] || 0) : 0), 0)\n        await d2.rush('registra-consulta').invoke({\n          created_at: new Date().toISOString(),\n          session_id: order,\n          itens_count: itensCount,\n          ticket_total: Math.round(ticket * 100) / 100,\n          baseline_avulso: Math.round(baseline * 100) / 100,\n          recorrencia_mensal_estimada: Math.round(recorrencia * 100) / 100,\n          devolucao_evitada_pct: 30,\n          assinatura_selecionada: false,\n          intent_summary: items.map((p) => p.name).join(', '),\n          itens_bot: itensBot,\n          itens_manual: itensCount - itensBot,\n          ticket_bot: Math.round(ticketBot * 100) / 100,\n          ticket_manual: Math.round((gross - ticketBot) * 100) / 100,\n        })\n      } catch (e) { d2.log('log consultation error', e) }\n      d2.state.orderNumber = order\n      d2.state.checkoutDone = true\n      d2.state.cart = {}\n      d2.state.cartSource = {}\n      d2.state.coupon = null\n    })\n    d2.on('.js-add-sugg', 'click', (e, el) => { addToCart(el.dataset.id, 1, 'bot'); loadSuggestions() })\n    d2.on('.js-add-opt', 'click', (e, el) => { addToCart(el.dataset.id, 1, 'bot'); d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: 'Adicionei à sua sacola! 🛍️ Quer que eu te explique como usar esse produto no dia a dia?' }] })\n    d2.on('.js-apply-coupon', 'click', (e, el) => {\n      d2.state.coupon = { code: el.dataset.code, discount_type: el.dataset.type, discount_value: Number(el.dataset.value) || 0, scope: el.dataset.scope, category: el.dataset.category || '', min_total: Number(el.dataset.min) || 0 }\n      d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: 'Cupom ' + el.dataset.code + ' aplicado! 🎉 O desconto já está valendo na sua sacola. Lembrando: vale um cupom por carrinho — aplicar outro substitui este.' }]\n    })\n    d2.on('.js-remove-coupon', 'click', () => { d2.state.coupon = null })\n    d2.on('.js-unread', 'click', () => { const log = d2.$('.log'); if (log) log.scrollTo({ top: log.scrollHeight, behavior: 'smooth' }) })\n    d2.on('.js-open', 'click', () => { d2.state.open = true })\n    d2.on('.js-close', 'click', () => { d2.state.open = false })\n    d2.on('.js-send', 'click', () => send())\n    d2.on('.js-chip', 'click', (e, el) => send(el.textContent))\n    d2.on('.js-ask', 'click', (e, el) => { d2.state.open = true; send('Me conta mais sobre o ' + el.dataset.name + ' e como ele entra numa boa rotina pra mim.') })\n    d2.on('.js-addroutine', 'click', (e, el) => {\n      const ids = (d2.state.routineMap || {})[el.dataset.key] || []\n      const c = { ...(d2.state.cart || {}) }\n      const src = { ...(d2.state.cartSource || {}) }\n      ids.forEach((id) => { c[id] = (c[id] || 0) + 1; if (!src[id]) src[id] = 'bot' })\n      d2.state.cart = c\n      d2.state.cartSource = src\n      d2.state.open = false\n      d2.state.cartOpen = true\n    })\n    d2.on('.cin', 'keydown', (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send() } })\n    d2.on('.cin', 'input', () => { const t = d2.$('.cin'); if (!t) return; t.style.height = 'auto'; t.style.height = Math.min(t.scrollHeight, 110) + 'px' })\n  },\n  updated(d2) {\n    const log = d2.$('.log')\n    if (!log) return\n    const unread = d2.$('.js-unread')\n    const syncUnread = () => {\n      if (!unread) return\n      const below = (log.scrollHeight - log.scrollTop - log.clientHeight) > 24\n      unread.style.display = below ? 'inline-flex' : 'none'\n    }\n    if (!log.dataset.sl) {\n      log.dataset.sl = '1'\n      log.addEventListener('scroll', syncUnread)\n    }\n    const msgs = d2.state.messages || []\n    const prev = Number(log.dataset.mc || 0)\n    if (msgs.length > prev) {\n      log.dataset.mc = String(msgs.length)\n      const last = msgs[msgs.length - 1]\n      const row = log.querySelector('.row[data-key=\"' + (msgs.length - 1) + '\"]')\n      if (last.role === 'bot' && row) {\n        if (last.text) {\n          // foca no TOPO da resposta do bot; o indicador avisa se houver mais abaixo\n          log.scrollTop = Math.max(0, row.offsetTop - log.offsetTop - 8)\n        }\n        // follow-up sem texto (cards): mantém a posição de leitura; o indicador sinaliza o resto\n      } else {\n        log.scrollTop = log.scrollHeight\n      }\n    } else if (d2.state.loading) {\n      log.scrollTop = log.scrollHeight\n    }\n    syncUnread()\n  },\n}"}},"products":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"products"}}}}}}}},"__d2PrevCode":{"code":"export default {\n  css: `\n    :host { display:block; position:relative; width:100%; height:100%; overflow:hidden; font-family: system-ui,-apple-system,Segoe UI,sans-serif; color:#262019; }\n    * { box-sizing:border-box; }\n    .page { position:absolute; inset:0; overflow-y:auto; overflow-x:hidden; background:#FBF9F5; scrollbar-width:thin; scrollbar-color:#DED4C4 transparent; }\n    .page::-webkit-scrollbar, .drawer-body::-webkit-scrollbar { width:11px; }\n    .page::-webkit-scrollbar-track, .drawer-body::-webkit-scrollbar-track { background:transparent; }\n    .page::-webkit-scrollbar-thumb, .drawer-body::-webkit-scrollbar-thumb { background:#DBD1C0; border-radius:999px; border:3px solid transparent; background-clip:content-box; }\n    .page::-webkit-scrollbar-thumb:hover, .drawer-body::-webkit-scrollbar-thumb:hover { background:#C6B8A0; background-clip:content-box; }\n    .log { scrollbar-width:thin; scrollbar-color:rgba(255,255,255,.2) transparent; }\n    .log::-webkit-scrollbar { width:8px; }\n    .log::-webkit-scrollbar-track { background:transparent; }\n    .log::-webkit-scrollbar-thumb { background:rgba(255,255,255,.16); border-radius:999px; border:2px solid transparent; background-clip:content-box; }\n    .serif { font-family: Georgia,'Times New Roman',serif; }\n\n    .topbar { background:#262019; color:#F3EFE8; text-align:center; font-size:12px; letter-spacing:.04em; padding:8px 16px; }\n    .nav { position:sticky; top:0; z-index:6; display:flex; align-items:center; justify-content:space-between; gap:24px; padding:15px 40px; background:rgba(251,249,245,.92); backdrop-filter:blur(10px); border-bottom:1px solid #EAE3D8; }\n    .cats { display:flex; gap:22px; flex:1; justify-content:center; }\n    .cat { font-size:14px; font-weight:500; color:#6E665A; cursor:pointer; padding:4px 0; border-bottom:2px solid transparent; transition:.15s; white-space:nowrap; }\n    .cat:hover { color:#262019; }\n    .cat.active { color:#262019; border-bottom-color:#B4633E; font-weight:600; }\n    .navright { display:flex; align-items:center; gap:12px; position:relative; }\n    .pmenu-scrim { position:fixed; inset:0; z-index:30; }\n    .pmenu { position:absolute; top:52px; right:0; z-index:31; background:#fff; border:1px solid #EAE3D8; border-radius:12px; box-shadow:0 14px 36px rgba(38,32,25,.18); padding:6px; min-width:210px; animation:fade .15s ease; }\n    .pmenu-head { font-size:11px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:#A69C8C; padding:9px 12px 5px; }\n    .pmenu-item { display:flex; align-items:center; gap:9px; width:100%; border:none; background:none; text-align:left; padding:10px 12px; border-radius:8px; font-size:13.5px; color:#262019; cursor:pointer; font-weight:600; }\n    .pmenu-item:hover { background:#F4F0E9; }\n    .search { display:flex; align-items:center; gap:7px; background:#F1ECE4; border:1px solid #E8E1D6; border-radius:999px; padding:8px 14px; width:200px; }\n    .search .si { color:#9A9184; font-size:15px; }\n    .searchi { border:none; background:none; outline:none; font-size:13px; color:#262019; width:100%; font-family:inherit; }\n    .searchi::placeholder { color:#A69C8C; }\n    .iconbtn { position:relative; border:none; background:none; cursor:pointer; color:#262019; width:36px; height:36px; display:flex; align-items:center; justify-content:center; border-radius:50%; transition:.15s; }\n    .iconbtn:hover { background:#F1ECE4; }\n    .iconbtn svg { width:21px; height:21px; }\n    .ibadge { position:absolute; top:-1px; right:-1px; background:#B4633E; color:#fff; font-size:10px; font-weight:700; min-width:17px; height:17px; border-radius:999px; display:flex; align-items:center; justify-content:center; padding:0 4px; }\n    .banner { display:flex; align-items:stretch; min-height:340px; background:linear-gradient(120deg,#EFE7DA,#F7F2EA); overflow:hidden; }\n    .banner-in { flex:1; padding:56px 48px; display:flex; flex-direction:column; justify-content:center; }\n    .banner-eyebrow { font-size:12px; font-weight:700; letter-spacing:.18em; text-transform:uppercase; color:#B4633E; margin-bottom:14px; }\n    .banner-title { font-size:44px; line-height:1.08; font-weight:600; color:#262019; margin:0 0 14px; letter-spacing:-.5px; }\n    .banner-sub { font-size:16px; color:#6E665A; margin:0 0 24px; max-width:440px; line-height:1.55; }\n    .banner-cta { display:flex; align-items:center; gap:16px; flex-wrap:wrap; }\n    .banner-btn { border:none; background:#262019; color:#fff; border-radius:999px; padding:13px 24px; font-size:14px; font-weight:700; cursor:pointer; display:inline-flex; align-items:center; gap:7px; transition:.15s; }\n    .banner-btn:hover { background:#3d342a; }\n    .banner-coupon { font-size:12px; font-weight:700; letter-spacing:.06em; color:#B4633E; border:1px dashed rgba(180,99,62,.5); border-radius:8px; padding:9px 14px; }\n    .banner-art { width:36%; background:linear-gradient(150deg,#DBCCB6,#C4AF94); display:flex; align-items:center; justify-content:center; }\n    .banner-mono { font-family:Georgia,serif; font-size:170px; color:rgba(255,255,255,.4); font-weight:600; line-height:1; }\n    .logo { font-family:Georgia,serif; font-size:22px; font-weight:600; letter-spacing:.3px; color:#262019; cursor:pointer; }\n    .logo .dot { color:#B4633E; margin:0 4px; }\n    .cart-btn { position:relative; border:1px solid #DBD3C6; background:#fff; color:#262019; border-radius:999px;\n      padding:9px 20px; font-size:13px; font-weight:600; cursor:pointer; letter-spacing:.02em; }\n    .cart-btn:hover { border-color:#262019; }\n    .badge { position:absolute; top:-7px; right:-7px; background:#B4633E; color:#fff; font-size:11px; font-weight:700;\n      min-width:19px; height:19px; border-radius:999px; display:inline-flex; align-items:center; justify-content:center; padding:0 5px; }\n\n    .hero { padding:72px 48px 40px; }\n    .hero-in { max-width:600px; }\n    .eyebrow { font-size:12px; font-weight:700; letter-spacing:.18em; text-transform:uppercase; color:#B4633E; margin-bottom:14px; }\n    .hero h1 { font-family:Georgia,serif; font-size:52px; line-height:1.04; font-weight:600; margin:0 0 16px; letter-spacing:-.5px; }\n    .hero p { font-size:16px; line-height:1.6; color:#6E665A; margin:0; max-width:500px; }\n\n    .section { padding:20px 48px 90px; }\n    .section-head { display:flex; align-items:baseline; justify-content:space-between; margin-bottom:24px; border-bottom:1px solid #EAE3D8; padding-bottom:14px; }\n    .section-head h2 { font-family:Georgia,serif; font-size:24px; font-weight:600; margin:0; }\n    .count { font-size:13px; color:#9A9184; }\n    .grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(258px,1fr)); gap:26px; }\n\n    .pcard { background:#fff; border:1px solid #EAE3D8; border-radius:16px; overflow:hidden; display:flex; flex-direction:column; transition:box-shadow .2s, transform .2s; }\n    .pcard:hover { box-shadow:0 14px 40px rgba(38,32,25,.10); transform:translateY(-3px); }\n    .thumb { position:relative; height:210px; background:linear-gradient(140deg,#F1EBE1,#E6DCCD); display:flex; align-items:center; justify-content:center; }\n    .thumb .mono { font-family:Georgia,serif; font-size:64px; color:#CDC2B0; font-weight:600; }\n    .thumb .timg { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; display:block; }\n    .pm-img .pmimg { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; display:block; }\n    .co-thumb img { width:100%; height:100%; object-fit:cover; border-radius:10px; display:block; }\n    .sthumb img { width:100%; height:100%; object-fit:cover; border-radius:9px; display:block; }\n    .othumb img { width:100%; height:100%; object-fit:cover; border-radius:9px; display:block; }\n    .thumb-tag { position:absolute; top:14px; left:14px; background:rgba(255,255,255,.85); color:#6E665A; font-size:10.5px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; padding:5px 10px; border-radius:999px; }\n    .pbody { padding:18px; display:flex; flex-direction:column; gap:5px; flex:1; }\n    .pbrand { font-size:11px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:#B4633E; }\n    .pname { font-size:16px; font-weight:600; line-height:1.3; color:#262019; }\n    .pdesc { font-size:12.5px; color:#8C8578; line-height:1.5; flex:1; margin-bottom:6px; }\n    .pprice { font-family:Georgia,serif; font-size:22px; font-weight:600; margin:8px 0 12px; }\n    .addbtn { width:100%; padding:12px; border:1.5px solid #262019; background:transparent; color:#262019; border-radius:10px; font-size:13.5px; font-weight:700; cursor:pointer; transition:.15s; letter-spacing:.01em; }\n    .addbtn:hover { background:#262019; color:#fff; }\n    .stepper.full { display:flex; width:100%; }\n    .stepper.full .qbtn { width:42px; }\n    .stepper.full .qn { flex:1; }\n    .askpill { position:absolute; top:12px; right:12px; width:34px; height:34px; border-radius:50%; display:inline-flex; align-items:center; justify-content:center; background:rgba(255,255,255,.92); color:#B4633E; border:1px solid rgba(180,99,62,.45); font-size:15px; cursor:pointer; box-shadow:0 2px 10px rgba(38,32,25,.1); transition:.15s; }\n    .askpill:hover { background:#B4633E; color:#fff; border-color:#B4633E; transform:scale(1.08); }\n\n    .btn { border:none; border-radius:10px; font-size:13px; font-weight:600; cursor:pointer; padding:10px 16px; transition:.15s; letter-spacing:.01em; }\n    .btn.primary { background:#262019; color:#fff; }\n    .btn.primary:hover { background:#3d342a; }\n    .btn.lg { width:100%; padding:15px; font-size:14px; }\n    .stepper { display:inline-flex; align-items:center; border:1px solid #DBD3C6; border-radius:10px; overflow:hidden; background:#fff; }\n    .stepper.sm { transform:none; }\n    .stepper.sm .qbtn { width:32px; height:32px; font-size:16px; }\n    .stepper.sm .qn { min-width:26px; }\n    .qbtn { border:none; background:transparent; width:34px; height:38px; font-size:18px; cursor:pointer; color:#262019; display:inline-flex; align-items:center; justify-content:center; line-height:1; padding:0; }\n    .qbtn:hover { background:#F4F0E9; }\n    .qn { min-width:30px; text-align:center; font-size:14px; font-weight:700; }\n    .ask { margin-top:12px; width:100%; background:rgba(180,99,62,.09); color:#B4633E; border:1px solid rgba(180,99,62,.22); border-radius:10px; padding:9px; font-size:12.5px; font-weight:700; cursor:pointer; transition:.15s; }\n    .ask:hover { background:rgba(180,99,62,.16); }\n    .empty { grid-column:1/-1; padding:40px; text-align:center; color:#9A9184; }\n    .footer-note { padding:28px 48px 60px; color:#A69C8C; font-size:12.5px; text-align:center; border-top:1px solid #EAE3D8; }\n    .pcard { cursor:pointer; }\n    .mscrim { position:absolute; inset:0; background:rgba(38,32,25,.42); z-index:24; animation:fade .2s ease; }\n    .pmodal { position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); width:min(880px, calc(100% - 40px)); max-height:calc(100% - 40px); overflow-y:auto; background:#FBF9F5; border-radius:18px; z-index:25; display:grid; grid-template-columns:44% 1fr; box-shadow:0 30px 80px rgba(38,32,25,.35); animation:modalin .2s ease-out; scrollbar-width:thin; scrollbar-color:#DED4C4 transparent; }\n    @keyframes modalin { from { opacity:0; transform:translate(-50%,-50%) scale(.98); } to { opacity:1; transform:translate(-50%,-50%) scale(1); } }\n    .pmodal::-webkit-scrollbar { width:10px; }\n    .pmodal::-webkit-scrollbar-thumb { background:#DBD1C0; border-radius:999px; border:3px solid transparent; background-clip:content-box; }\n    .pm-close { position:absolute; top:16px; right:16px; z-index:2; border:none; background:rgba(255,255,255,.92); width:34px; height:34px; border-radius:50%; cursor:pointer; font-size:14px; color:#6E665A; box-shadow:0 2px 8px rgba(38,32,25,.12); }\n    .pm-close:hover { background:#fff; }\n    .pm-img { position:relative; background:linear-gradient(140deg,#F1EBE1,#E6DCCD); display:flex; align-items:center; justify-content:center; min-height:360px; }\n    .pm-img .mono { font-family:Georgia,serif; font-size:120px; color:#CDC2B0; font-weight:600; }\n    .pm-body { padding:34px 34px 30px; }\n    .pm-brand { font-size:12px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:#B4633E; }\n    .pm-name { font-size:28px; font-weight:600; line-height:1.15; margin:6px 0 10px; }\n    .pm-price { font-family:Georgia,serif; font-size:24px; font-weight:600; margin-bottom:14px; }\n    .pm-desc { font-size:14px; color:#6E665A; line-height:1.6; margin:0 0 18px; }\n    .pm-meta { border-top:1px solid #EAE3D8; margin-bottom:20px; }\n    .pm-mrow { display:grid; grid-template-columns:140px 1fr; gap:12px; padding:11px 0; border-bottom:1px solid #EAE3D8; font-size:13px; }\n    .pm-mk { font-weight:700; color:#262019; }\n    .pm-mv { color:#6E665A; line-height:1.5; }\n    .pm-consultora { margin-top:20px; display:flex; align-items:center; gap:13px; background:rgba(180,99,62,.07); border:1px solid rgba(180,99,62,.25); border-radius:14px; padding:14px 16px; }\n    .pm-cico { width:38px; height:38px; flex-shrink:0; border-radius:50%; background:linear-gradient(135deg,#B4633E,#E0A075); color:#fff; display:flex; align-items:center; justify-content:center; font-size:18px; }\n    .pm-ctxt { flex:1; display:flex; flex-direction:column; gap:2px; }\n    .pm-ctxt strong { font-size:13px; color:#262019; }\n    .pm-ctxt span { font-size:12.5px; color:#8C7F6E; line-height:1.4; }\n    .pm-cbtn { flex-shrink:0; border:none; background:#B4633E; color:#fff; border-radius:999px; padding:10px 18px; font-size:12.5px; font-weight:700; cursor:pointer; }\n    .pm-cbtn:hover { background:#c9714a; }\n\n    /* checkout */\n    .co { padding:34px 48px 90px; max-width:1120px; margin:0 auto; }\n    .co-head { display:flex; flex-direction:column; gap:10px; margin-bottom:26px; }\n    .co-back { align-self:flex-start; border:none; background:none; color:#B4633E; font-size:13px; font-weight:600; cursor:pointer; padding:0; }\n    .co-back:hover { text-decoration:underline; }\n    .co-head h1 { font-family:Georgia,serif; font-size:34px; font-weight:600; margin:0; }\n    .co-grid { display:grid; grid-template-columns:1fr 348px; gap:28px; align-items:start; }\n    .co-main { display:flex; flex-direction:column; gap:20px; }\n    .co-card { background:#fff; border:1px solid #EAE3D8; border-radius:16px; padding:24px; }\n    .co-card h2 { font-family:Georgia,serif; font-size:18px; font-weight:600; margin:0 0 16px; }\n    .co-item { display:grid; grid-template-columns:56px 1fr auto; gap:15px; align-items:center; padding:14px 0; border-top:1px solid #F0EAE0; }\n    .co-item:first-of-type { border-top:none; padding-top:0; }\n    .co-thumb { width:56px; height:56px; border-radius:10px; background:linear-gradient(140deg,#F1EBE1,#E6DCCD); display:flex; align-items:center; justify-content:center; }\n    .co-thumb .mono { font-family:Georgia,serif; font-size:22px; color:#CDC2B0; font-weight:600; }\n    .ci-info { display:flex; flex-direction:column; gap:6px; }\n    .ci-name { font-size:14px; font-weight:600; }\n    .ci-line { display:flex; align-items:center; gap:12px; }\n    .ci-price { font-size:13px; color:#8C8578; }\n    .ci-remove { border:none; background:none; color:#A69C8C; font-size:11.5px; cursor:pointer; padding:0; text-decoration:underline; }\n    .ci-total { font-family:Georgia,serif; font-size:16px; font-weight:600; }\n\n    .co-sugg { border:1px solid rgba(180,99,62,.28); background:linear-gradient(180deg,rgba(180,99,62,.05),#fff 60px); }\n    .sugg-head { display:flex; align-items:center; gap:12px; margin-bottom:16px; }\n    .sugg-ico { width:38px; height:38px; border-radius:50%; background:linear-gradient(135deg,#B4633E,#E0A075); display:flex; align-items:center; justify-content:center; font-size:18px; color:#fff; flex-shrink:0; }\n    .sugg-head h2 { margin:0; }\n    .sugg-head p { margin:2px 0 0; font-size:12.5px; color:#8C8578; }\n    .scard { display:grid; grid-template-columns:48px 1fr auto; gap:13px; align-items:center; padding:13px 0; border-top:1px solid #F0EAE0; }\n    .scard:first-of-type { border-top:none; }\n    .sthumb { width:48px; height:48px; border-radius:9px; background:linear-gradient(140deg,#F1EBE1,#E6DCCD); display:flex; align-items:center; justify-content:center; }\n    .sthumb .mono { font-family:Georgia,serif; font-size:19px; color:#CDC2B0; font-weight:600; }\n    .s-name { font-size:13.5px; font-weight:600; }\n    .s-reason { font-size:12px; color:#B4633E; margin-top:2px; }\n    .s-right { display:flex; flex-direction:column; align-items:flex-end; gap:6px; }\n    .s-price { font-size:13px; font-weight:600; }\n    .s-add { border:1px solid #B4633E; background:#fff; color:#B4633E; border-radius:8px; padding:6px 14px; font-size:12px; font-weight:700; cursor:pointer; }\n    .s-add:hover { background:#B4633E; color:#fff; }\n    .sugg-empty { font-size:13px; color:#9A9184; padding:6px 0; }\n\n    .pay-row { display:flex; align-items:center; gap:12px; padding:13px 15px; border:1px solid #E8E1D6; border-radius:11px; margin-bottom:10px; cursor:pointer; transition:.15s; }\n    .pay-row:hover { border-color:#C9BCA6; }\n    .pay-row.sel { border-color:#262019; background:#FBF9F5; }\n    .radio { width:18px; height:18px; border-radius:50%; border:2px solid #C9BCA6; flex-shrink:0; position:relative; }\n    .pay-row.sel .radio { border-color:#262019; }\n    .pay-row.sel .radio::after { content:''; position:absolute; inset:3px; border-radius:50%; background:#262019; }\n    .pay-label { font-size:13.5px; font-weight:600; }\n    .pay-sub { font-size:12px; color:#9A9184; }\n    .field-mock { width:100%; padding:12px 14px; border:1px solid #E8E1D6; border-radius:11px; font-size:13.5px; color:#6E665A; background:#FBF9F5; margin-bottom:10px; }\n    .secure { display:flex; align-items:center; gap:8px; font-size:12px; color:#6E8B6E; background:rgba(110,139,110,.08); border:1px solid rgba(110,139,110,.2); border-radius:10px; padding:11px 14px; margin-top:6px; }\n\n    .co-summary { position:sticky; top:24px; background:#fff; border:1px solid #EAE3D8; border-radius:16px; padding:24px; }\n    .co-summary h3 { font-family:Georgia,serif; font-size:18px; font-weight:600; margin:0 0 18px; }\n    .sum-row { display:flex; justify-content:space-between; font-size:13.5px; color:#6E665A; padding:7px 0; }\n    .sum-row.total { font-size:18px; font-weight:700; color:#262019; border-top:1px solid #EAE3D8; margin-top:8px; padding-top:14px; }\n    .sum-row.total span:last-child { font-family:Georgia,serif; }\n    .free { color:#6E8B6E; font-weight:600; }\n    .co-badges { display:flex; flex-direction:column; gap:7px; margin-top:16px; font-size:11.5px; color:#9A9184; }\n    .co-success { min-height:100%; display:flex; align-items:center; justify-content:center; padding:40px 24px; }\n    .co-done { background:#fff; border:1px solid #EAE3D8; border-radius:18px; padding:64px 48px; text-align:center; max-width:540px; width:100%; margin:0; display:flex; flex-direction:column; align-items:center; gap:14px; }\n    .cd-ico { width:70px; height:70px; border-radius:50%; background:#B4633E; color:#fff; display:flex; align-items:center; justify-content:center; font-size:34px; }\n    .cd-num { font-size:13px; color:#8C8578; letter-spacing:.05em; }\n    .cd-title { font-family:Georgia,serif; font-size:28px; font-weight:600; }\n    .cd-sub { font-size:13.5px; color:#8C8578; line-height:1.55; max-width:340px; }\n\n    /* cart drawer */\n    .scrim { position:absolute; inset:0; background:rgba(38,32,25,.34); z-index:14; animation:fade .2s ease; }\n    .drawer { position:absolute; top:0; right:0; bottom:0; width:400px; max-width:92%; background:#F8F5EF; z-index:15; display:flex; flex-direction:column; box-shadow:-20px 0 60px rgba(38,32,25,.2); animation:slidein .26s cubic-bezier(.22,1,.36,1); }\n    @keyframes slidein { from{transform:translateX(40px);opacity:.4} to{transform:none;opacity:1} }\n    @keyframes fade { from{opacity:0} to{opacity:1} }\n    .drawer-head { display:flex; align-items:center; justify-content:space-between; padding:22px 24px; border-bottom:1px solid #EAE3D8; }\n    .dh-title { font-family:Georgia,serif; font-size:20px; font-weight:600; }\n    .close { border:none; background:#EFE9DF; width:32px; height:32px; border-radius:50%; cursor:pointer; font-size:14px; color:#6E665A; }\n    .close:hover { background:#E4DACB; }\n    .drawer-body { flex:1; overflow-y:auto; padding:16px 24px; display:flex; flex-direction:column; gap:16px; }\n    .citem { display:grid; grid-template-columns:60px 1fr auto; gap:13px; align-items:start; }\n    .cthumb { width:60px; height:60px; border-radius:10px; overflow:hidden; background:linear-gradient(140deg,#F1EBE1,#E6DCCD); display:flex; align-items:center; justify-content:center; flex-shrink:0; }\n    .cthumb img { width:100%; height:100%; object-fit:cover; display:block; }\n    .cthumb .mono { font-family:Georgia,serif; font-size:22px; color:#CDC2B0; font-weight:600; }\n    .cinfo { display:flex; flex-direction:column; gap:5px; min-width:0; }\n    .cname { font-size:13.5px; font-weight:600; line-height:1.3; }\n    .cprice { font-size:12px; color:#8C8578; }\n    .crow { display:flex; align-items:center; gap:14px; margin-top:3px; }\n    .cremove { border:none; background:none; color:#A69C8C; font-size:11.5px; cursor:pointer; padding:0; text-decoration:underline; }\n    .cline { font-family:Georgia,serif; font-size:14px; font-weight:600; white-space:nowrap; }\n    .cart-consultora { margin-top:6px; background:rgba(180,99,62,.06); border:1px solid rgba(180,99,62,.22); border-radius:14px; padding:14px; }\n    .cc-head { display:flex; align-items:center; gap:8px; font-size:13px; font-weight:800; color:#262019; margin-bottom:9px; }\n    .cc-ico { width:24px; height:24px; border-radius:50%; background:linear-gradient(135deg,#B4633E,#E0A075); color:#fff; display:flex; align-items:center; justify-content:center; font-size:12px; }\n    .cc-line { font-size:12px; color:#8C7F6E; margin-bottom:8px; }\n    .cc-sitem { display:flex; align-items:center; gap:10px; background:#fff; border:1px solid #EAE3D8; border-radius:10px; padding:9px 11px; margin-bottom:7px; }\n    .cc-sinfo { flex:1; min-width:0; }\n    .cc-sname { font-size:12.5px; font-weight:600; }\n    .cc-sreason { font-size:11.5px; color:#B4633E; margin-top:1px; }\n    .cc-sadd { flex-shrink:0; border:1px solid #B4633E; background:#fff; color:#B4633E; border-radius:8px; padding:6px 11px; font-size:11.5px; font-weight:700; cursor:pointer; white-space:nowrap; }\n    .cc-sadd:hover { background:#B4633E; color:#fff; }\n    .cc-chat { width:100%; margin-top:4px; border:none; background:#262019; color:#fff; border-radius:10px; padding:11px; font-size:12.5px; font-weight:700; cursor:pointer; }\n    .cc-chat:hover { background:#3d342a; }\n    .drawer-foot { padding:20px 24px; border-top:1px solid #EAE3D8; background:#fff; }\n    .subtotal { display:flex; justify-content:space-between; font-size:16px; font-weight:700; margin-bottom:14px; }\n    .subtotal span:last-child { font-family:Georgia,serif; }\n    .foot-fine { font-size:11px; color:#A69C8C; text-align:center; margin-top:10px; }\n    .empty-cart { flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:10px; color:#9A9184; font-size:14px; }\n    .empty-cart div { font-size:36px; }\n\n    /* launcher */\n    .launcher { position:absolute; right:30px; bottom:30px; z-index:12; display:flex; align-items:center; gap:11px; background:#262019; color:#fff; border-radius:999px; padding:12px 20px 12px 14px; cursor:pointer; box-shadow:0 12px 34px rgba(38,32,25,.28); transition:transform .16s; }\n    .launcher:hover { transform:translateY(-2px); }\n    .l-ico { width:34px; height:34px; border-radius:50%; background:linear-gradient(135deg,#B4633E,#D98A5B); display:flex; align-items:center; justify-content:center; font-size:17px; }\n    .l-label { font-size:14px; font-weight:600; letter-spacing:.01em; }\n    .l-pulse { position:absolute; left:14px; top:12px; width:34px; height:34px; border-radius:50%; background:#B4633E; opacity:.5; animation:pulse 2.2s infinite; }\n    @keyframes pulse { 0%{transform:scale(1);opacity:.45} 70%{transform:scale(1.9);opacity:0} 100%{opacity:0} }\n\n    /* chat panel — AI signature */\n    .panel { position:absolute; right:30px; bottom:30px; width:412px; height:min(680px,calc(100% - 60px)); z-index:16; background:#17130F; border-radius:20px; overflow:hidden; display:flex; flex-direction:column; box-shadow:0 30px 80px rgba(20,15,10,.5); animation:panelin .3s cubic-bezier(.22,1,.36,1); border:1px solid rgba(255,255,255,.06); }\n    @keyframes panelin { from{transform:translateY(24px) scale(.98);opacity:0} to{transform:none;opacity:1} }\n    .phead { position:relative; padding:20px 20px 18px; overflow:hidden; flex-shrink:0; background:linear-gradient(135deg,#2A211A,#3A2A20); border-bottom:1px solid rgba(255,255,255,.07); }\n    .phead::after { content:''; position:absolute; right:-40px; top:-60px; width:180px; height:180px; border-radius:50%; background:radial-gradient(circle,rgba(217,138,91,.5),transparent 70%); }\n    .ph-row { position:relative; display:flex; align-items:center; justify-content:space-between; z-index:1; }\n    .ph-brand { display:flex; align-items:center; gap:11px; }\n    .ph-ico { width:38px; height:38px; border-radius:50%; background:linear-gradient(135deg,#B4633E,#E0A075); display:flex; align-items:center; justify-content:center; font-size:18px; }\n    .ptitle { font-size:15px; font-weight:700; color:#fff; letter-spacing:.01em; }\n    .psub { font-size:11px; color:rgba(236,228,217,.6); margin-top:1px; }\n    .pclose { border:none; background:rgba(255,255,255,.12); color:#fff; width:30px; height:30px; border-radius:50%; cursor:pointer; font-size:13px; }\n    .pclose:hover { background:rgba(255,255,255,.22); }\n    .log { flex:1; overflow-y:auto; padding:18px; display:flex; flex-direction:column; gap:12px; }\n    .estate { flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; text-align:center; gap:12px; padding:30px; }\n    .estate .wave { font-size:44px; }\n    .estate h3 { color:#fff; font-size:16px; font-weight:700; margin:0; font-family:Georgia,serif; }\n    .estate p { color:rgba(236,228,217,.6); font-size:13px; line-height:1.55; margin:0; max-width:280px; }\n    .chips { display:flex; flex-wrap:wrap; gap:8px; justify-content:center; margin-top:6px; }\n    .qchips { display:flex; flex-wrap:wrap; gap:8px; margin-top:9px; }\n    .mic { flex-shrink:0; width:42px; height:42px; border-radius:50%; border:none; cursor:pointer; background:rgba(255,255,255,.08); color:#ECE4D9; font-size:16px; display:flex; align-items:center; justify-content:center; transition:.15s; }\n    .mic:hover { background:rgba(255,255,255,.15); }\n    .mic.rec { background:#E9534E; color:#fff; animation:micpulse 1.1s infinite; }\n    @keyframes micpulse { 0%,100%{opacity:1} 50%{opacity:.5} }\n    .chip { background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.12); color:rgba(236,228,217,.9); font-size:12px; padding:8px 13px; border-radius:999px; cursor:pointer; transition:.15s; }\n    .chip:hover { background:rgba(180,99,62,.25); border-color:rgba(217,138,91,.5); }\n    .row { display:flex; flex-direction:column; max-width:100%; }\n    .row.user { align-items:flex-end; }\n    .row.bot { align-items:flex-start; }\n    .msg { max-width:86%; padding:11px 14px; border-radius:15px; font-size:13.5px; line-height:1.5; white-space:pre-line; }\n    .msg.user { background:#B4633E; color:#fff; border-bottom-right-radius:5px; }\n    .msg.bot { background:rgba(255,255,255,.055); color:#ECE4D9; border:1px solid rgba(255,255,255,.08); border-bottom-left-radius:5px; }\n    .dots span { width:6px; height:6px; border-radius:50%; background:rgba(236,228,217,.5); display:inline-block; margin-right:4px; animation:blink 1.2s infinite; }\n    .dots span:nth-child(2){animation-delay:.2s} .dots span:nth-child(3){animation-delay:.4s}\n    @keyframes blink { 0%,80%,100%{opacity:.25} 40%{opacity:1} }\n    .routines { display:flex; flex-direction:column; gap:11px; margin-top:10px; width:100%; }\n    .opts { display:flex; flex-direction:column; gap:9px; margin-top:10px; width:100%; }\n    .ocard { display:grid; grid-template-columns:44px 1fr auto; gap:11px; align-items:center; background:rgba(255,255,255,.045); border:1px solid rgba(255,255,255,.1); border-radius:12px; padding:10px 12px; }\n    .othumb { width:44px; height:44px; border-radius:9px; background:linear-gradient(140deg,rgba(255,255,255,.14),rgba(255,255,255,.05)); display:flex; align-items:center; justify-content:center; }\n    .othumb .mono { font-family:Georgia,serif; font-size:18px; color:rgba(255,255,255,.55); font-weight:600; }\n    .oname { font-size:13px; font-weight:700; color:#fff; }\n    .ostep { font-size:11.5px; color:rgba(236,228,217,.55); margin-top:1px; }\n    .oright { display:flex; flex-direction:column; align-items:flex-end; gap:6px; }\n    .oprice { font-size:13px; font-weight:600; color:#E0A075; font-family:Georgia,serif; }\n    .oadd { border:none; background:#B4633E; color:#fff; border-radius:8px; padding:6px 13px; font-size:12px; font-weight:700; cursor:pointer; }\n    .oadd:hover { background:#c9714a; }\n    .odetail { background:none; border:none; color:rgba(236,228,217,.6); font-size:11px; cursor:pointer; text-decoration:underline; margin-top:5px; padding:2px 0; }\n    .odetail:hover { color:#E0A075; }\n    .sidemodal { position:absolute; right:464px; bottom:28px; z-index:19; width:340px; max-height:min(680px, calc(100% - 56px)); overflow-y:auto; background:#17120E; border:1px solid rgba(255,255,255,.12); border-radius:18px; box-shadow:0 24px 70px rgba(0,0,0,.45); color:#ECE4D9; animation:fade .18s ease; }\n    .sm-head { display:flex; align-items:center; justify-content:space-between; padding:12px 14px 8px; }\n    .sm-tag { font-size:10px; font-weight:800; letter-spacing:.08em; text-transform:uppercase; color:#E0A075; background:rgba(180,99,62,.18); border-radius:999px; padding:4px 10px; }\n    .sm-close { background:rgba(255,255,255,.1); border:none; color:#fff; width:26px; height:26px; border-radius:50%; cursor:pointer; font-size:12px; }\n    .sm-close:hover { background:rgba(255,255,255,.2); }\n    .sm-img { height:180px; margin:0 14px; border-radius:12px; overflow:hidden; background:rgba(255,255,255,.05); display:flex; align-items:center; justify-content:center; }\n    .sm-img img { width:100%; height:100%; object-fit:cover; }\n    .sm-img .mono { font-family:Georgia,serif; font-size:56px; color:rgba(255,255,255,.4); }\n    .sm-body { padding:14px; display:flex; flex-direction:column; gap:5px; }\n    .sm-brand { font-size:11px; text-transform:uppercase; letter-spacing:.06em; color:rgba(236,228,217,.55); }\n    .sm-name { font-family:Georgia,serif; font-size:17px; font-weight:600; color:#fff; line-height:1.25; }\n    .sm-price { font-size:18px; font-weight:800; color:#E0A075; margin:2px 0; }\n    .sm-desc { font-size:12.5px; line-height:1.5; color:rgba(236,228,217,.75); margin:4px 0 10px; }\n    .sm-meta { display:flex; flex-direction:column; gap:8px; margin-bottom:12px; }\n    .sm-mrow { display:flex; flex-direction:column; gap:2px; border-top:1px solid rgba(255,255,255,.08); padding-top:8px; }\n    .sm-mk { font-size:10.5px; text-transform:uppercase; letter-spacing:.05em; color:rgba(236,228,217,.5); }\n    .sm-mv { font-size:12.5px; color:#ECE4D9; line-height:1.45; }\n    .sm-add { width:100%; border:none; border-radius:10px; background:#B4633E; color:#fff; padding:12px; font-size:13.5px; font-weight:800; cursor:pointer; }\n    .sm-add:hover { background:#c9714a; }\n    .catsw { display:inline-flex; align-items:center; gap:8px; border:1px solid #E2DACB; background:#fff; color:#262019; border-radius:999px; padding:8px 14px; font-size:12.5px; font-weight:800; cursor:pointer; white-space:nowrap; }\n    .catsw:hover { border-color:#B4633E; color:#B4633E; }\n    .catsw-swap { color:#B4633E; font-weight:700; font-size:14px; }\n    .rcard { background:rgba(255,255,255,.045); border:1px solid rgba(255,255,255,.1); border-radius:14px; padding:14px; }\n    .rtop { display:flex; align-items:center; justify-content:space-between; }\n    .rname { font-size:13.5px; font-weight:800; color:#fff; }\n    .rover { display:inline-block; margin-left:8px; font-size:9.5px; font-weight:700; letter-spacing:.04em; text-transform:uppercase; color:#E9A99E; background:rgba(224,138,120,.14); border:1px solid rgba(224,138,120,.4); border-radius:999px; padding:2px 7px; vertical-align:middle; }\n    .rok { display:inline-block; margin-left:8px; font-size:9.5px; font-weight:700; letter-spacing:.04em; text-transform:uppercase; color:#A8D8B0; background:rgba(150,200,150,.14); border:1px solid rgba(150,200,150,.36); border-radius:999px; padding:2px 7px; vertical-align:middle; }\n    .rcard-ok { border-color:rgba(150,200,150,.42); background:rgba(150,200,150,.07); }\n    .rcard-over { border-color:rgba(224,138,120,.45); background:rgba(224,138,120,.07); }\n    .rcard-ok .rtotal { color:#A8D8B0; }\n    .rcard-over .rtotal { color:#E9A99E; }\n    .rtotal { font-family:Georgia,serif; font-size:15px; font-weight:600; color:#E0A075; }\n    .rblurb { font-size:12px; color:rgba(236,228,217,.66); margin:5px 0 9px; line-height:1.45; }\n    .ritem { display:flex; justify-content:space-between; gap:10px; font-size:12px; color:rgba(236,228,217,.86); padding:5px 0; border-top:1px dashed rgba(255,255,255,.1); }\n    .ritem:first-child { border-top:none; }\n    .rwarn { font-size:11.5px; color:#F0CDA0; background:rgba(240,205,160,.09); border:1px solid rgba(240,205,160,.22); border-radius:9px; padding:8px 10px; margin-top:9px; line-height:1.45; }\n    .radd { margin-top:11px; width:100%; background:#B4633E; color:#fff; border:none; border-radius:9px; padding:10px; font-size:12.5px; font-weight:700; cursor:pointer; transition:.15s; }\n    .radd:hover { background:#c9714a; }\n    .cpn { width:100%; background:linear-gradient(135deg,rgba(180,99,62,.16),rgba(255,255,255,.04)); border:1px dashed rgba(217,138,91,.55); border-radius:14px; padding:14px; margin-top:10px; }\n    .cpn-top { display:flex; align-items:center; justify-content:space-between; margin-bottom:4px; }\n    .cpn-code { font-size:14px; font-weight:800; color:#fff; letter-spacing:.06em; }\n    .cpn-save { font-family:Georgia,serif; font-size:15px; font-weight:700; color:#A8D8B0; }\n    .cpn-desc { font-size:12px; color:rgba(236,228,217,.7); margin-bottom:10px; }\n    .cpn-apply { width:100%; border:none; border-radius:9px; background:#B4633E; color:#fff; padding:10px; font-size:12.5px; font-weight:800; cursor:pointer; }\n    .cpn-apply:hover { background:#c9714a; }\n    .cpn-apply:disabled { background:rgba(168,216,176,.2); color:#A8D8B0; cursor:default; }\n    .cpline { display:flex; justify-content:space-between; align-items:center; font-size:12.5px; color:#B4633E; font-weight:700; margin-bottom:8px; gap:8px; }\n    .cpline.off { color:#A69C8C; font-weight:600; }\n    .cpremove { border:none; background:none; color:#A69C8C; font-size:11px; cursor:pointer; text-decoration:underline; padding:0; }\n    .unread { position:absolute; left:50%; transform:translateX(-50%); bottom:86px; z-index:3; display:none; align-items:center; gap:6px; border:none; border-radius:999px; background:#D98A5B; color:#17130F; font-size:12px; font-weight:800; padding:8px 14px; cursor:pointer; box-shadow:0 8px 24px rgba(0,0,0,.35); animation:fade .2s ease; }\n    .unread:hover { background:#E0A075; }\n    .bar { flex-shrink:0; display:flex; align-items:flex-end; gap:9px; padding:14px; background:#120E0A; border-top:1px solid rgba(255,255,255,.07); }\n    .field { flex:1; background:rgba(255,255,255,.05); border:1.5px solid rgba(255,255,255,.09); border-radius:16px; padding:6px 14px; transition:.15s; }\n    .field:focus-within { border-color:#B4633E; }\n    .cin { width:100%; border:none; background:none; color:#ECE4D9; font-size:13.5px; font-family:inherit; resize:none; outline:none; line-height:1.5; height:24px; max-height:110px; padding:0; scrollbar-width:thin; scrollbar-color:rgba(255,255,255,.22) transparent; }\n    .cin::-webkit-scrollbar { width:7px; }\n    .cin::-webkit-scrollbar-button { display:none; height:0; width:0; }\n    .cin::-webkit-scrollbar-track { background:transparent; margin:2px 0; }\n    .cin::-webkit-scrollbar-thumb { background:rgba(255,255,255,.2); border-radius:999px; border:2px solid transparent; background-clip:content-box; }\n    .cin::-webkit-scrollbar-thumb:hover { background:rgba(255,255,255,.32); background-clip:content-box; }\n    .cin::placeholder { color:rgba(236,228,217,.4); }\n    .send { flex-shrink:0; width:42px; height:42px; border-radius:50%; border:none; cursor:pointer; background:linear-gradient(135deg,#B4633E,#D98A5B); color:#fff; display:flex; align-items:center; justify-content:center; }\n    .send:disabled { opacity:.4; cursor:default; }\n    .send svg { width:18px; height:18px; }\n    .photo { flex-shrink:0; width:42px; height:42px; border-radius:50%; border:none; cursor:pointer; background:rgba(255,255,255,.08); color:#ECE4D9; font-size:18px; display:flex; align-items:center; justify-content:center; transition:.15s; }\n    .photo:hover { background:rgba(255,255,255,.15); }\n    .imgmsg { padding:5px !important; background:rgba(255,255,255,.06) !important; }\n    .imgmsg img { max-width:190px; max-height:190px; border-radius:11px; display:block; }\n\n    /* ===== REDESIGN LUXO (override, vence na cascata) ===== */\n    :host { font-family:'Inter',system-ui,-apple-system,Segoe UI,sans-serif; -webkit-font-smoothing:antialiased; }\n    .serif { font-family:'Cormorant Garamond',Georgia,'Times New Roman',serif; }\n    .page { background:#F6F3EE; color:#2A2420; }\n    .topbar { background:#2A2420; color:#F3EFE8; font-size:11px; letter-spacing:.16em; text-transform:uppercase; padding:9px 16px; font-weight:500; }\n    .nav { padding:20px 52px; background:rgba(246,243,238,.86); backdrop-filter:blur(12px); border-bottom:1px solid rgba(42,36,32,.09); }\n    .logo { font-family:'Cormorant Garamond',Georgia,serif; font-size:27px; font-weight:600; letter-spacing:.02em; color:#2A2420; }\n    .logo .dot { color:#B4633E; }\n    .cats { gap:28px; }\n    .cat { font-size:11.5px; letter-spacing:.14em; text-transform:uppercase; font-weight:500; color:#7A6F64; border-bottom:none; }\n    .cat:hover { color:#2A2420; }\n    .cat.active { color:#2A2420; font-weight:600; border-bottom:none; position:relative; }\n    .cat.active::after { content:''; position:absolute; left:0; right:0; bottom:-3px; height:1px; background:#B4633E; }\n    .navright { gap:16px; }\n    .iconbtn { color:#2A2420; }\n    .iconbtn:hover { background:rgba(42,36,32,.06); }\n    .search { background:transparent; border:1px solid rgba(42,36,32,.16); border-radius:999px; }\n    .catsw { display:inline-flex; align-items:center; gap:9px; border:1px solid rgba(42,36,32,.2); background:transparent; color:#2A2420; border-radius:999px; padding:9px 16px; font-size:11px; font-weight:600; letter-spacing:.08em; text-transform:uppercase; cursor:pointer; white-space:nowrap; transition:.2s; }\n    .catsw:hover { border-color:#B4633E; color:#B4633E; }\n    .catsw-swap { color:#B4633E; font-size:13px; }\n\n    .banner { position:relative; overflow:hidden; display:block; min-height:300px; padding:52px 52px 58px; background:linear-gradient(160deg,#F6F3EE 0%,#EFE7DB 60%,#EAE0D2 100%); }\n    .banner-in { position:relative; z-index:2; max-width:680px; animation:rise .9s cubic-bezier(.2,.7,.2,1) both; }\n    .banner-eyebrow { font-size:12px; font-weight:500; letter-spacing:.26em; text-transform:uppercase; color:#B4633E; margin-bottom:14px; }\n    .banner-title { font-family:'Cormorant Garamond',Georgia,serif; font-size:54px; line-height:1.02; font-weight:500; letter-spacing:-.01em; color:#2A2420; margin:0 0 16px; }\n    .banner-title em, .ed-title em, .ai-title em { font-style:italic; color:#8A6A4F; }\n    .banner-sub { font-size:15.5px; line-height:1.65; color:#5C534B; max-width:480px; margin:0 0 26px; }\n    .banner-cta { display:flex; align-items:center; gap:24px; flex-wrap:wrap; }\n    .banner-btn { border:none; border-radius:0; background:#2A2420; color:#F6F3EE; padding:17px 32px; font-size:11.5px; font-weight:600; letter-spacing:.16em; text-transform:uppercase; cursor:pointer; transition:.28s; }\n    .banner-btn:hover { background:#B4633E; letter-spacing:.2em; }\n    .banner-coupon { font-size:11.5px; letter-spacing:.1em; text-transform:uppercase; color:#8A7E74; border:none; padding:0; background:none; }\n    .banner-art { position:absolute; inset:0; z-index:1; width:auto; background:none; pointer-events:none; }\n    .banner-orb { position:absolute; right:9%; top:16%; width:360px; height:360px; border-radius:50%; background:radial-gradient(circle at 34% 30%,#EBD0B2,#D8A97F 55%,#C0855D); opacity:.5; filter:blur(1px); animation:float 9s ease-in-out infinite; }\n    .banner-orb.orb2 { right:28%; top:46%; width:150px; height:150px; background:radial-gradient(circle at 40% 35%,#F1DEC9,#CBAF97); opacity:.38; animation-delay:-3s; animation-duration:13s; }\n    @keyframes float { 0%,100%{transform:translateY(0)} 50%{transform:translateY(-28px)} }\n    @keyframes rise { from{opacity:0; transform:translateY(24px)} to{opacity:1; transform:none} }\n\n    .section { padding:84px 52px 44px; }\n    .section-head { border-bottom:1px solid rgba(42,36,32,.11); padding-bottom:20px; margin-bottom:44px; }\n    .section-head h2 { font-family:'Cormorant Garamond',Georgia,serif; font-size:38px; font-weight:500; }\n    .count { font-size:11px; letter-spacing:.16em; text-transform:uppercase; color:#8A7E74; }\n    .grid { grid-template-columns:repeat(4,1fr); gap:16px 30px; }\n    .pcard { background:transparent; border:none; border-radius:0; overflow:visible; }\n    .pcard:hover { box-shadow:none; transform:none; }\n    .thumb { height:auto; aspect-ratio:1/1; background:#EEE7DE; border-radius:3px; overflow:hidden; }\n    .thumb .timg, .thumb .timg.timg { position:static; inset:auto; width:100%; height:100%; object-fit:cover; transition:transform .8s cubic-bezier(.2,.7,.2,1); }\n    .pcard:hover .thumb .timg { transform:scale(1.06); }\n    .thumb .mono { font-family:'Cormorant Garamond',Georgia,serif; }\n    .fav { position:absolute; top:12px; right:12px; z-index:3; width:34px; height:34px; border:none; border-radius:50%; background:rgba(255,255,255,.8); color:#2A2420; font-size:16px; line-height:1; cursor:pointer; display:flex; align-items:center; justify-content:center; transition:.2s; }\n    .fav:hover { background:#fff; }\n    .fav.on { color:#B4633E; }\n    .askpill { top:auto; left:12px; right:12px; bottom:12px; width:auto; height:auto; border-radius:0; background:rgba(42,36,32,.93); color:#F6F3EE; border:none; box-shadow:none; display:flex; align-items:center; justify-content:center; gap:8px; padding:13px; font-size:11px; letter-spacing:.16em; text-transform:uppercase; opacity:0; transform:translateY(10px); transition:.3s; }\n    .pcard:hover .askpill { opacity:1; transform:none; }\n    .askpill:hover { background:#B4633E; color:#fff; transform:none; }\n    .askpill-ico { font-size:13px; }\n    .pbody { padding:16px 2px 0; gap:0; text-align:left; }\n    .pcat { font-size:10.5px; letter-spacing:.16em; text-transform:uppercase; color:#A2968A; margin-bottom:8px; }\n    .pname { font-family:'Cormorant Garamond',Georgia,serif; font-size:21px; font-weight:500; line-height:1.18; color:#2A2420; margin-bottom:7px; }\n    .pprice { font-family:'Inter',sans-serif; font-size:14px; font-weight:500; color:#5C534B; margin:0 0 14px; }\n    .addbtn { border-radius:0; border:1px solid rgba(42,36,32,.75); font-size:11px; letter-spacing:.14em; text-transform:uppercase; font-weight:600; padding:13px; }\n\n    .editorial { padding:104px 52px; max-width:920px; margin:0 auto; text-align:center; }\n    .ed-eyebrow { font-size:12px; font-weight:500; letter-spacing:.26em; text-transform:uppercase; color:#B4633E; margin-bottom:22px; }\n    .ed-eyebrow.light { color:#E7C9A8; }\n    .ed-title { font-family:'Cormorant Garamond',Georgia,serif; font-size:54px; font-weight:500; line-height:1.08; color:#2A2420; margin:0 0 22px; }\n    .ed-lead { font-size:17px; line-height:1.85; color:#5C534B; max-width:660px; margin:0 auto; }\n    .pillars { display:grid; grid-template-columns:repeat(3,1fr); gap:1px; background:rgba(42,36,32,.1); border-top:1px solid rgba(42,36,32,.1); border-bottom:1px solid rgba(42,36,32,.1); }\n    .pillar { background:#F6F3EE; padding:60px 46px; }\n    .pillar-n { font-family:'Cormorant Garamond',Georgia,serif; font-size:24px; color:#B4633E; margin-bottom:18px; }\n    .pillar h3 { font-family:'Cormorant Garamond',Georgia,serif; font-size:25px; font-weight:500; color:#2A2420; margin:0 0 12px; line-height:1.2; }\n    .pillar p { font-size:14.5px; line-height:1.75; color:#5C534B; margin:0; }\n    .ai-band { background:#2A2420; color:#F6F3EE; padding:116px 52px; text-align:center; }\n    .ai-band-in { max-width:780px; margin:0 auto; }\n    .ai-title { font-family:'Cormorant Garamond',Georgia,serif; font-size:58px; font-weight:500; line-height:1.06; margin:0 0 24px; }\n    .ai-title em { color:#E7C9A8; }\n    .ai-lead { font-size:17px; line-height:1.85; color:rgba(246,243,238,.72); margin:0 0 36px; }\n    .ai-cta { border:1px solid #F6F3EE; background:transparent; color:#F6F3EE; padding:17px 36px; font-size:11.5px; font-weight:600; letter-spacing:.16em; text-transform:uppercase; cursor:pointer; transition:.25s; }\n    .ai-cta:hover { background:#F6F3EE; color:#2A2420; }\n    .footer-note { background:#EFE7DB; color:#8A7E74; font-size:11px; letter-spacing:.06em; padding:44px 52px; border-top:1px solid rgba(42,36,32,.09); }\n\n    @media (max-width:1080px){ .grid{grid-template-columns:repeat(2,1fr)} .pillars{grid-template-columns:1fr} .banner-title{font-size:54px} .cats{display:none} .ed-title,.ai-title{font-size:40px} }\n  `,\n  render(d2) {\n    const esc = (s) => (s ?? '').toString().replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;')\n    const money = (n) => d2.fmt.currency(Number(n) || 0, 'BRL')\n    const mono = (name) => (name || '?').trim().slice(0,1).toUpperCase()\n    const catB = d2.state.catalog === 'b'\n    const ds = d2.data(catB ? 'bot-products-bDataSet' : 'products')\n    const loadingP = !ds || ds.loading\n    const products = loadingP ? [] : ds.records()\n    const imgOf = (id) => { const pp = products.filter((x) => x && x._id === id)[0]; return (pp && pp.image_url) ? pp.image_url : '' }\n    const selCat = d2.state.category || ''\n    const categories = [...new Set(products.map((p) => p.category).filter(Boolean))].sort()\n    const catLabel = (c) => c ? c.charAt(0).toUpperCase() + c.slice(1) : c\n    const visibleProducts = selCat ? products.filter((p) => p.category === selCat) : products\n    const cart = d2.state.cart || {}\n    const qOf = (id) => cart[id] || 0\n    const cartCount = Object.keys(cart).reduce((a,k) => a + cart[k], 0)\n    const cartItems = products.filter((p) => qOf(p._id) > 0)\n    const cartTotal = cartItems.reduce((a,p) => a + (Number(p.price) || 0) * qOf(p._id), 0)\n    const coupon = d2.state.coupon || null\n    const couponBase = coupon ? (coupon.scope === 'categoria' ? cartItems.reduce((a, p) => a + ((p.category === coupon.category) ? (Number(p.price) || 0) * qOf(p._id) : 0), 0) : cartTotal) : 0\n    const couponMinOk = coupon ? cartTotal >= (Number(coupon.min_total) || 0) : false\n    const couponDiscount = (coupon && couponMinOk) ? (coupon.discount_type === 'percent' ? couponBase * (Number(coupon.discount_value) || 0) / 100 : Math.min(Number(coupon.discount_value) || 0, couponBase)) : 0\n    const cartFinal = Math.max(0, cartTotal - couponDiscount)\n    const view = d2.state.view || 'store'\n\n    const card = (p) => {\n      const q = qOf(p._id)\n      const action = q > 0\n        ? `<div class=\"stepper full\"><button class=\"qbtn js-dec\" data-id=\"${p._id}\">−</button><span class=\"qn\">${q}</span><button class=\"qbtn js-inc\" data-id=\"${p._id}\">+</button></div>`\n        : `<button class=\"addbtn js-add\" data-id=\"${p._id}\">Adicionar à sacola</button>`\n      const fav = (d2.state.favs || {})[p._id]\n      return `<article class=\"pcard js-open-product\" data-key=\"${p._id}\" data-id=\"${p._id}\">\n        <div class=\"thumb\">${p.image_url ? `<img class=\"timg\" src=\"${esc(p.image_url)}\" alt=\"${esc(p.name || '')}\" />` : `<span class=\"mono\">${esc(mono(p.name))}</span>`}\n          <button class=\"fav js-fav ${fav ? 'on' : ''}\" data-id=\"${p._id}\" title=\"Favoritar\" aria-label=\"Favoritar\">${fav ? '♥' : '♡'}</button>\n          <button class=\"askpill js-ask\" data-id=\"${p._id}\" data-name=\"${esc(p.name || '')}\" title=\"Falar com a consultora\"><span class=\"askpill-ico\">✨</span><span class=\"askpill-txt\">Consultora</span></button></div>\n        <div class=\"pbody\">\n          <div class=\"pcat\">${esc(p.category || '')}</div>\n          <div class=\"pname\">${esc(p.name || '')}</div>\n          <div class=\"pprice\">${money(p.price)}</div>\n          ${action}\n        </div>\n      </article>`\n    }\n    const grid = loadingP ? `<div class=\"empty\">Carregando produtos…</div>` : (visibleProducts.length ? visibleProducts.map(card).join('') : `<div class=\"empty\">Nenhum produto nesta categoria.</div>`)\n    const store = `\n      <div class=\"topbar\">Frete grátis acima de R$ 279 · entrega expressa para todo o Brasil</div>\n      <header class=\"nav\">\n        <div class=\"logo js-home\">Ateliê<span class=\"dot\">·</span>Beleza</div>\n        <nav class=\"cats\">\n          <a class=\"cat js-cat ${selCat === '' ? 'active' : ''}\" data-cat=\"\">Todos</a>\n          ${categories.map((c) => `<a class=\"cat js-cat ${selCat === c ? 'active' : ''}\" data-cat=\"${esc(c)}\">${esc(catLabel(c))}</a>`).join('')}\n        </nav>\n        <div class=\"navright\">\n          <button class=\"catsw js-catsw\" type=\"button\" title=\"Trocar catálogo — demo do motor agnóstico\">${catB ? '💇 Cabelos' : '🧴 Skincare'}<span class=\"catsw-swap\">⇄</span></button>\n          <div class=\"search\"><span class=\"si\">⌕</span><input class=\"searchi\" placeholder=\"Buscar produtos...\" /></div>\n          <button class=\"iconbtn js-profile\" title=\"Minha conta\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\"><circle cx=\"12\" cy=\"8\" r=\"4\"/><path d=\"M4.5 20c0-3.6 3.6-5.6 7.5-5.6s7.5 2 7.5 5.6\"/></svg></button>\n          <button class=\"iconbtn\" title=\"Favoritos\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\"><path d=\"M12 20.5S4 15.5 4 9.8A4.3 4.3 0 0 1 12 7a4.3 4.3 0 0 1 8 2.8c0 5.7-8 10.7-8 10.7z\"/></svg></button>\n          <button class=\"iconbtn js-cart\" title=\"Sacola\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\"><path d=\"M6.5 8h11l-1 11.5H7.5L6.5 8z\"/><path d=\"M9.2 8V6.2a2.8 2.8 0 0 1 5.6 0V8\"/></svg>${cartCount ? `<span class=\"ibadge\">${cartCount}</span>` : ''}</button>\n          ${d2.state.profileMenu ? `<div class=\"pmenu-scrim js-profile-close\"></div><div class=\"pmenu\"><div class=\"pmenu-head\">Área interna</div><button class=\"pmenu-item js-goto-painel\" type=\"button\">📊 Painel comercial</button></div>` : ''}\n        </div>\n      </header>\n      <section class=\"banner\">\n        <div class=\"banner-art\"><span class=\"banner-orb\"></span><span class=\"banner-orb orb2\"></span></div>\n        <div class=\"banner-in\">\n          <div class=\"banner-eyebrow\">${catB ? 'Ritual capilar' : 'Beleza consultiva'}</div>\n          <h1 class=\"banner-title serif\">${catB ? 'Cabelos<br>como um <em>ritual.</em>' : 'Mais do que<br>pele. <em>Cuidado.</em>'}</h1>\n          <p class=\"banner-sub\">Uma consultora de IA lê a sua necessidade — por texto, voz ou foto — e monta a rotina certa para você. Beleza que começa em entender.</p>\n          <div class=\"banner-cta\">\n            <button class=\"banner-btn js-open\">Falar com a consultora</button>\n            <span class=\"banner-coupon\">Diagnóstico gratuito · em segundos</span>\n          </div>\n        </div>\n      </section>\n      <main class=\"section\">\n        <div class=\"section-head\"><h2 class=\"serif\">Mais desejados</h2><span class=\"count\">${loadingP ? '' : visibleProducts.length + ' produtos'}</span></div>\n        <div class=\"grid\">${grid}</div>\n      </main>\n      <section class=\"editorial\">\n        <div class=\"ed-eyebrow\">A nossa filosofia</div>\n        <h2 class=\"ed-title serif\">Beleza que vai <em>além da superfície.</em></h2>\n        <p class=\"ed-lead\">Fórmulas gentis e eficazes, pensadas para revelar a sua melhor versão — com o cuidado de quem entende de pele, de cabelo e de você.</p>\n      </section>\n      <section class=\"pillars\">\n        <div class=\"pillar\"><div class=\"pillar-n\">01</div><h3 class=\"serif\">Ingredientes que fazem sentido</h3><p>Ativos selecionados e combinações que respeitam a sua pele — sem misturas que competem entre si.</p></div>\n        <div class=\"pillar\"><div class=\"pillar-n\">02</div><h3 class=\"serif\">Personalização de verdade</h3><p>Cada recomendação nasce da sua necessidade, do seu tipo de pele ou cabelo e do seu momento — não de uma vitrine genérica.</p></div>\n        <div class=\"pillar\"><div class=\"pillar-n\">03</div><h3 class=\"serif\">Inteligência que consulta</h3><p>Uma IA que conversa, analisa uma foto do seu cabelo e monta a rotina ideal — a expertise de uma consultora, na hora.</p></div>\n      </section>\n      <section class=\"ai-band\">\n        <div class=\"ai-band-in\">\n          <div class=\"ed-eyebrow light\">Tecnologia Data2</div>\n          <h2 class=\"ai-title serif\">A consultora que entende <em>de você.</em></h2>\n          <p class=\"ai-lead\">Descreva o que precisa, mande um áudio ou uma foto do seu cabelo. Em segundos, a IA diagnostica, evita combinações erradas e monta o cuidado sob medida — e responde até por voz.</p>\n          <button class=\"ai-cta js-open\">Experimentar agora</button>\n        </div>\n      </section>\n      <div class=\"footer-note\">Demonstração Data2 · vitrine fictícia · a camada de consultoria por IA se integra a qualquer e-commerce existente, sem trocar nada.</div>`\n\n    // ---- checkout view ----\n    let checkout = ''\n    if (view === 'checkout') {\n      if (d2.state.checkoutDone) {\n        checkout = `<div class=\"co-success\"><div class=\"co-done\">\n          <div class=\"cd-ico\">✓</div>\n          <div class=\"cd-num\">Pedido ${esc(d2.state.orderNumber || '')}</div>\n          <div class=\"cd-title serif\">Pedido confirmado</div>\n          <div class=\"cd-sub\">Simulação de demonstração — nenhum pagamento foi processado. Numa loja real, o cliente receberia a confirmação por e-mail.</div>\n          <button class=\"btn primary js-home\">Voltar à loja</button>\n        </div></div>`\n      } else {\n        const pay = d2.state.payMethod || 'cartao'\n        const itemsHtml = cartItems.length ? cartItems.map((p) => `<div class=\"co-item\" data-key=\"${p._id}\">\n            <div class=\"co-thumb\">${p.image_url ? `<img src=\"${esc(p.image_url)}\" alt=\"${esc(p.name)}\" />` : `<span class=\"mono\">${esc(mono(p.name))}</span>`}</div>\n            <div class=\"ci-info\"><div class=\"ci-name\">${esc(p.name)}</div>\n              <div class=\"ci-line\"><div class=\"stepper sm\"><button class=\"qbtn js-dec\" data-id=\"${p._id}\">−</button><span class=\"qn\">${qOf(p._id)}</span><button class=\"qbtn js-inc\" data-id=\"${p._id}\">+</button></div>\n                <span class=\"ci-price\">${money(p.price)} un.</span><button class=\"ci-remove js-remove\" data-id=\"${p._id}\">remover</button></div></div>\n            <div class=\"ci-total\">${money((Number(p.price) || 0) * qOf(p._id))}</div>\n          </div>`).join('') : `<div class=\"sugg-empty\">Sua sacola está vazia.</div>`\n\n        const suggs = d2.state.suggestions || []\n        const suggBody = d2.state.suggestLoading\n          ? `<div class=\"sugg-empty\">A consultora está analisando seu pedido…</div>`\n          : (suggs.length ? suggs.map((s) => `<div class=\"scard\" data-key=\"${s.product_id}\">\n              <div class=\"sthumb\">${imgOf(s.product_id) ? `<img src=\"${esc(imgOf(s.product_id))}\" alt=\"${esc(s.name)}\" />` : `<span class=\"mono\">${esc(mono(s.name))}</span>`}</div>\n              <div><div class=\"s-name\">${esc(s.name)}</div><div class=\"s-reason\">${s.synergy ? '✨ ' : ''}${esc(s.reason)}</div></div>\n              <div class=\"s-right\"><div class=\"s-price\">${money(s.price)}</div><button class=\"s-add js-add-sugg\" data-id=\"${s.product_id}\">Adicionar</button></div>\n            </div>`).join('') : `<div class=\"sugg-empty\">Seu pedido já está completo. ✨</div>`)\n\n        checkout = `<div class=\"co\">\n          <div class=\"co-head\"><button class=\"co-back js-home\">← Continuar comprando</button><h1 class=\"serif\">Finalizar pedido</h1></div>\n          <div class=\"co-grid\">\n            <div class=\"co-main\">\n              <section class=\"co-card\"><h2>1 · Revise seu pedido</h2>${itemsHtml}</section>\n              <section class=\"co-card co-sugg\">\n                <div class=\"sugg-head\"><div class=\"sugg-ico\">✨</div><div><h2>A consultora sugere</h2><p>Itens que completam sua rotina, escolhidos pela IA com base no que você já tem.</p></div></div>\n                ${suggBody}\n              </section>\n              <section class=\"co-card\"><h2>2 · Entrega e pagamento</h2>\n                <div class=\"field-mock\">Rua das Flores, 123 · São Paulo, SP · 01234-000</div>\n                <div class=\"pay-row js-pay ${pay === 'cartao' ? 'sel' : ''}\" data-pay=\"cartao\"><div class=\"radio\"></div><div><div class=\"pay-label\">Cartão de crédito</div><div class=\"pay-sub\">Visa •••• 4242</div></div></div>\n                <div class=\"pay-row js-pay ${pay === 'pix' ? 'sel' : ''}\" data-pay=\"pix\"><div class=\"radio\"></div><div><div class=\"pay-label\">Pix</div><div class=\"pay-sub\">${pay === 'pix' ? 'QR Code gerado na confirmação' : 'Aprovação imediata'}</div></div></div>\n                <div class=\"secure\">🔒 Ambiente seguro · esta é uma demonstração, nenhum pagamento é processado.</div>\n              </section>\n            </div>\n            <aside class=\"co-summary\">\n              <h3>Resumo</h3>\n              <div class=\"sum-row\"><span>Subtotal (${cartCount} ${cartCount === 1 ? 'item' : 'itens'})</span><span>${money(cartTotal)}</span></div>\n              <div class=\"sum-row\"><span>Frete</span><span class=\"free\">Grátis</span></div>\n              ${couponDiscount > 0 ? `<div class=\"sum-row\"><span>🎟️ Cupom ${esc(coupon.code)}</span><span class=\"free\">− ${money(couponDiscount)}</span></div>` : ''}<div class=\"sum-row total\"><span>Total</span><span>${money(cartFinal)}</span></div>\n              <button class=\"btn primary lg js-confirm\" style=\"margin-top:16px\">Confirmar pedido</button>\n              <div class=\"co-badges\"><span>🔒 Compra 100% segura</span><span>🚚 Frete grátis acima de R$ 279</span><span>↩️ Troca fácil em 30 dias</span></div>\n            </aside>\n          </div>\n        </div>`\n      }\n    }\n\n    const mainView = view === 'checkout' ? checkout : store\n\n    let cartHtml = ''\n    if (d2.state.cartOpen) {\n      const suggs = d2.state.suggestions || []\n      const ccBlock = `<div class=\"cart-consultora\">\n          <div class=\"cc-head\"><span class=\"cc-ico\">✨</span>Sua consultora</div>\n          ${suggs.length ? `<div class=\"cc-line\">Leve também — combina com o que você escolheu:</div>${suggs.slice(0, 2).map((s) => `<div class=\"cc-sitem\" data-key=\"${s.product_id}\"><div class=\"cc-sinfo\"><div class=\"cc-sname\">${esc(s.name)}</div><div class=\"cc-sreason\">${s.synergy ? '✨ ' : ''}${esc(s.reason)}</div></div><button class=\"cc-sadd js-add-sugg\" data-id=\"${s.product_id}\">${money(s.price)} +</button></div>`).join('')}` : ''}\n          <button class=\"cc-chat js-cart-to-chat\">Não sabe se combina com a sua pele? Fale comigo →</button>\n        </div>`\n      const body = cartItems.length\n        ? `<div class=\"drawer-body\">${cartItems.map((p) => `<div class=\"citem\" data-key=\"${p._id}\">\n            <div class=\"cthumb\">${p.image_url ? `<img src=\"${esc(p.image_url)}\" alt=\"${esc(p.name)}\" />` : `<span class=\"mono\">${esc(mono(p.name))}</span>`}</div>\n            <div class=\"cinfo\"><div class=\"cname\">${esc(p.name)}</div><div class=\"cprice\">${money(p.price)} un.</div>\n              <div class=\"crow\"><div class=\"stepper sm\"><button class=\"qbtn js-dec\" data-id=\"${p._id}\">−</button><span class=\"qn\">${qOf(p._id)}</span><button class=\"qbtn js-inc\" data-id=\"${p._id}\">+</button></div><button class=\"cremove js-remove\" data-id=\"${p._id}\">remover</button></div></div>\n            <div class=\"cline\">${money((Number(p.price) || 0) * qOf(p._id))}</div></div>`).join('')}${ccBlock}</div>\n          <div class=\"drawer-foot\">${coupon && coupon.code ? (couponDiscount > 0 ? `<div class=\"cpline\"><span>🎟️ Cupom ${esc(coupon.code)} · <button class=\"cpremove js-remove-coupon\" type=\"button\">remover</button></span><span>− ${money(couponDiscount)}</span></div>` : `<div class=\"cpline off\"><span>🎟️ Cupom ${esc(coupon.code)} — mínimo de ${money(coupon.min_total)} não atingido</span><button class=\"cpremove js-remove-coupon\" type=\"button\">remover</button></div>`) : ''}<div class=\"subtotal\"><span>${couponDiscount > 0 ? 'Total com desconto' : 'Subtotal'}</span><span>${money(cartFinal)}</span></div>\n            <button class=\"btn primary lg js-checkout\">Finalizar compra</button>\n            <div class=\"foot-fine\">Revise e finalize com segurança na próxima etapa.</div></div>`\n        : `<div class=\"empty-cart\"><div>🛍️</div><p>Sua sacola está vazia.</p></div>`\n      cartHtml = `<div class=\"scrim js-cart-close\"></div><aside class=\"drawer\">\n        <div class=\"drawer-head\"><div class=\"dh-title serif\">Sua sacola</div><button class=\"close js-cart-close\">✕</button></div>${body}</aside>`\n    }\n\n    let chatHtml\n    if (!d2.state.open) {\n      chatHtml = `<div class=\"launcher js-open\"><span class=\"l-pulse\"></span><span class=\"l-ico\">✨</span><span class=\"l-label\">Consultora de beleza</span></div>`\n    } else {\n      const msgs = d2.state.messages || []\n      const loading = !!d2.state.loading || !!d2.state.hairAnalyzing\n      const couponCard = (c) => {\n        const applied = d2.state.coupon && d2.state.coupon.code === c.code\n        return `<div class=\"cpn\" data-key=\"${esc(c.code)}\">\n          <div class=\"cpn-top\"><span class=\"cpn-code\">🎟️ ${esc(c.code)}</span><span class=\"cpn-save\">− ${money(c.savings)}</span></div>\n          <div class=\"cpn-desc\">${esc(c.description)}</div>\n          <button class=\"cpn-apply js-apply-coupon\" data-code=\"${esc(c.code)}\" data-type=\"${esc(c.discount_type)}\" data-value=\"${Number(c.discount_value) || 0}\" data-scope=\"${esc(c.scope)}\" data-category=\"${esc(c.category || '')}\" data-min=\"${Number(c.min_total) || 0}\" type=\"button\" ${applied ? 'disabled' : ''}>${applied ? 'Cupom aplicado ✓' : 'Aplicar cupom'}</button>\n        </div>`\n      }\n      const optCard = (o) => `<div class=\"ocard\" data-key=\"${o.product_id}\"><div class=\"othumb\">${imgOf(o.product_id) ? `<img src=\"${esc(imgOf(o.product_id))}\" alt=\"${esc(o.name)}\" />` : `<span class=\"mono\">${esc(mono(o.name))}</span>`}</div><div class=\"oinfo\"><div class=\"oname\">${esc(o.name)}</div><div class=\"ostep\">${esc(o.step)}</div></div><div class=\"oright\"><div class=\"oprice\">${money(o.price)}</div><button class=\"oadd js-add-opt\" data-id=\"${o.product_id}\">Adicionar</button><button class=\"odetail js-open-side\" data-id=\"${o.product_id}\">Ver detalhes</button></div></div>`\n      const routineCard = (r) => `<div class=\"rcard ${r.budget_active ? (r.over_budget ? 'rcard-over' : 'rcard-ok') : ''}\" data-key=\"${esc(r.key)}\">\n          <div class=\"rtop\"><div class=\"rname\">${esc(r.name)}${r.budget_active ? (r.over_budget ? '<span class=\"rover\">acima do orçamento</span>' : '<span class=\"rok\">dentro do orçamento</span>') : ''}</div><div class=\"rtotal\">${money(r.total)}</div></div>\n          <div class=\"rblurb\">${esc(r.blurb)}</div>\n          ${(r.items || []).map((it) => `<div class=\"ritem\"><span>${esc(it.step)} · ${esc(it.name)}</span><span>${money(it.price)}</span></div>`).join('')}\n          ${(r.warnings || []).map((w) => `<div class=\"rwarn\">⚠️ ${esc(w)}</div>`).join('')}\n          <button class=\"radd js-addroutine\" data-key=\"${esc(r.key)}\">Adicionar rotina à sacola</button></div>`\n      const rows = msgs.length\n        ? msgs.map((m,i) => `<div class=\"row ${m.role}\" data-key=\"${i}\">${m.text ? `<div class=\"msg ${m.role}\">${esc(m.text)}</div>` : ''}${m.image ? `<div class=\"msg ${m.role} imgmsg\"><img src=\"${m.image}\" alt=\"Foto enviada\" /></div>` : ''}${m.routines && m.routines.length ? `<div class=\"routines\">${m.routines.map(routineCard).join('')}</div>` : ''}${m.options && m.options.length ? `<div class=\"opts\">${m.options.slice(0, 4).map(optCard).join('')}</div>` : ''}${m.coupon && m.coupon.code ? couponCard(m.coupon) : ''}${m.qoptions && m.qoptions.length ? `<div class=\"qchips\">${m.qoptions.map((q) => `<button class=\"chip js-chip\">${esc(q)}</button>`).join('')}</div>` : ''}</div>`).join('')\n        : `<div class=\"estate\"><div class=\"wave\">👋</div><h3>Oi! Sou sua consultora de beleza.</h3>\n            <p>Descreva sua necessidade que eu monto uma rotina completa — com avisos de compatibilidade entre ativos.</p>\n            <div class=\"chips\"><button class=\"chip js-chip\">Pele oleosa, controlar o brilho</button><button class=\"chip js-chip\">Quero cuidar de linhas finas</button></div></div>`\n      const dots = loading ? `<div class=\"row bot\"><div class=\"msg bot\"><span class=\"dots\"><span></span><span></span><span></span></span></div></div>` : ''\n      chatHtml = `<div class=\"panel\">\n        <div class=\"phead\"><div class=\"ph-row\"><div class=\"ph-brand\"><div class=\"ph-ico\">✨</div>\n          <div><div class=\"ptitle\">Consultora de Beleza</div><div class=\"psub\">IA Data2 · personal shopper</div></div></div>\n          <button class=\"pclose js-close\">✕</button></div></div>\n        <div class=\"log\">${rows}${dots}</div>\n        <button class=\"unread js-unread\" style=\"display:none\" type=\"button\">↓ nova mensagem</button>\n        <div class=\"bar\"><div class=\"field\"><textarea class=\"cin\" rows=\"1\" placeholder=\"Descreva sua necessidade...\"></textarea></div>\n          ${catB ? `<label class=\"photo js-photo-label\" title=\"Enviar foto do cabelo\">📷<input type=\"file\" accept=\"image/*\" class=\"js-photo-input\" hidden /></label>` : ''}\n          <button class=\"mic js-mic ${d2.state.recording ? 'rec' : ''}\" title=\"Gravar áudio\">${d2.state.recording ? '⏹' : '🎤'}</button>\n          <button class=\"send js-send\" ${loading ? 'disabled' : ''}><svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M3.4 20.4l17.45-7.48a1 1 0 0 0 0-1.84L3.4 3.6a.993.993 0 0 0-1.39.91L2 9.12c0 .5.37.93.87.99L17 12 2.87 13.88c-.5.07-.87.5-.87 1l.01 4.61c0 .67.68 1.13 1.39.91z\"/></svg></button></div>\n      </div>`\n    }\n\n    let modalHtml = ''\n    if (d2.state.selectedId) {\n      const mp = products.filter((x) => x._id === d2.state.selectedId)[0]\n      if (mp) {\n        const mq = qOf(mp._id)\n        const mact = mq > 0\n          ? `<div class=\"stepper full\"><button class=\"qbtn js-dec\" data-id=\"${mp._id}\">−</button><span class=\"qn\">${mq}</span><button class=\"qbtn js-inc\" data-id=\"${mp._id}\">+</button></div>`\n          : `<button class=\"addbtn js-add\" data-id=\"${mp._id}\">Adicionar à sacola</button>`\n        modalHtml = `<div class=\"mscrim js-modal-close\"></div>\n          <div class=\"pmodal\">\n            <button class=\"pm-close js-modal-close\">✕</button>\n            <div class=\"pm-img\">${mp.image_url ? `<img class=\"pmimg\" src=\"${esc(mp.image_url)}\" alt=\"${esc(mp.name || '')}\" />` : `<span class=\"mono\">${esc(mono(mp.name))}</span>`}<span class=\"thumb-tag\">${esc(mp.category || '')}</span></div>\n            <div class=\"pm-body\">\n              <div class=\"pm-brand\">${esc(mp.brand || '')}</div>\n              <div class=\"pm-name serif\">${esc(mp.name || '')}</div>\n              <div class=\"pm-price\">${money(mp.price)}</div>\n              <p class=\"pm-desc\">${esc(mp.description || '')}</p>\n              <div class=\"pm-meta\">\n                <div class=\"pm-mrow\"><span class=\"pm-mk\">Como usar</span><span class=\"pm-mv\">${esc(mp.how_to_use || '—')}</span></div>\n                <div class=\"pm-mrow\"><span class=\"pm-mk\">Duração</span><span class=\"pm-mv\">~${esc(mp.duration_days || '?')} dias de uso</span></div>\n                <div class=\"pm-mrow\"><span class=\"pm-mk\">Período</span><span class=\"pm-mv\">${esc(mp.usage_period || '—')}</span></div>\n                ${mp.contraindications ? `<div class=\"pm-mrow\"><span class=\"pm-mk\">Contraindicações</span><span class=\"pm-mv\">${esc(mp.contraindications)}</span></div>` : ''}\n              </div>\n              ${mact}\n              <div class=\"pm-consultora\">\n                <div class=\"pm-cico\">✨</div>\n                <div class=\"pm-ctxt\"><strong>Sua consultora</strong><span>Quer saber se combina com a sua pele e como encaixar na rotina?</span></div>\n                <button class=\"pm-cbtn js-ask-product\" data-id=\"${mp._id}\" data-name=\"${esc(mp.name || '')}\">Perguntar</button>\n              </div>\n            </div>\n          </div>`\n      }\n    }\n    let sideModalHtml = ''\n    if (d2.state.open && d2.state.sideProductId) {\n      const sp = products.filter((x) => x._id === d2.state.sideProductId)[0]\n      if (sp) {\n        const sq = qOf(sp._id)\n        const sact = sq > 0\n          ? `<div class=\"stepper full\"><button class=\"qbtn js-dec\" data-id=\"${sp._id}\">−</button><span class=\"qn\">${sq}</span><button class=\"qbtn js-inc\" data-id=\"${sp._id}\">+</button></div>`\n          : `<button class=\"sm-add js-add-side\" data-id=\"${sp._id}\">Adicionar à sacola</button>`\n        sideModalHtml = `<div class=\"sidemodal\">\n          <div class=\"sm-head\"><span class=\"sm-tag\">${esc(sp.category || '')}</span><button class=\"sm-close js-side-close\" type=\"button\">✕</button></div>\n          <div class=\"sm-img\">${sp.image_url ? `<img src=\"${esc(sp.image_url)}\" alt=\"${esc(sp.name || '')}\" />` : `<span class=\"mono\">${esc(mono(sp.name))}</span>`}</div>\n          <div class=\"sm-body\">\n            <div class=\"sm-brand\">${esc(sp.brand || '')}</div>\n            <div class=\"sm-name\">${esc(sp.name || '')}</div>\n            <div class=\"sm-price\">${money(sp.price)}</div>\n            <p class=\"sm-desc\">${esc(sp.description || '')}</p>\n            <div class=\"sm-meta\">\n              <div class=\"sm-mrow\"><span class=\"sm-mk\">Como usar</span><span class=\"sm-mv\">${esc(sp.how_to_use || '—')}</span></div>\n              <div class=\"sm-mrow\"><span class=\"sm-mk\">Quando</span><span class=\"sm-mv\">${esc(sp.usage_period || '—')}</span></div>\n              <div class=\"sm-mrow\"><span class=\"sm-mk\">Duração</span><span class=\"sm-mv\">~${esc(sp.duration_days || '?')} dias de uso</span></div>\n              ${sp.contraindications ? `<div class=\"sm-mrow\"><span class=\"sm-mk\">Contraindicações</span><span class=\"sm-mv\">${esc(sp.contraindications)}</span></div>` : ''}\n            </div>\n            ${sact}\n          </div>\n        </div>`\n      }\n    }\n    return `<div class=\"page\">${mainView}</div>${cartHtml}${chatHtml}${sideModalHtml}${modalHtml}`\n  },\n  mounted(d2) {\n    const sleep = (ms) => new Promise((r) => setTimeout(r, ms))\n    try {\n      if (!document.getElementById('d2-lux-fonts')) {\n        const l = document.createElement('link')\n        l.id = 'd2-lux-fonts'; l.rel = 'stylesheet'\n        l.href = 'https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400;1,500&family=Inter:wght@400;500;600&display=swap'\n        document.head.appendChild(l)\n      }\n    } catch (e) {}\n    // aquece o módulo de transcrição na carga da página (evita 1ª chamada em módulo frio)\n    try { d2.assistant('consultora-ouvido') } catch (e) {}\n    const addToCart = (id, n, source) => {\n      const c = { ...(d2.state.cart || {}) }\n      const src = { ...(d2.state.cartSource || {}) }\n      c[id] = (c[id] || 0) + n\n      if (c[id] <= 0) { delete c[id]; delete src[id] }\n      else if (source && !src[id]) { src[id] = source }\n      d2.state.cart = c\n      d2.state.cartSource = src\n    }\n    const loadSuggestions = async () => {\n      const ids = Object.keys(d2.state.cart || {})\n      d2.state.suggestLoading = true\n      try {\n        const res = await d2.rush('sugere-complemento').invoke({ cart_ids: ids })\n        const r = (res && res.data) ? res.data : res\n        d2.state.suggestions = (r && r.suggestions) || []\n      } catch (err) {\n        d2.log('sugere-complemento error', err)\n        d2.state.suggestions = []\n      } finally {\n        d2.state.suggestLoading = false\n      }\n    }\n    const send = async (preset, opts) => {\n      const spoken = !!(opts && opts.spoken)\n      const t = d2.$('.cin')\n      const text = (preset != null ? preset : (t ? t.value : '')).trim()\n      if (!text || d2.state.loading) return\n      if (t) { t.value = ''; t.style.height = '24px' }\n      const priorMsgs = (d2.state.messages || []).slice(-40).map((m) => ({ role: m.role, text: m.text }))\n      d2.state.messages = [...(d2.state.messages || []), { role: 'user', text }]\n      d2.state.loading = true\n      const t0 = Date.now()\n      try {\n        const pds = d2.data(d2.state.catalog === 'b' ? 'bot-products-bDataSet' : 'products')\n        const prodRows = (pds && !pds.loading) ? pds.records() : []\n        const curCart = d2.state.cart || {}\n        const cartPayload = prodRows.filter((p) => (curCart[p._id] || 0) > 0).map((p) => ({ product_id: p._id, name: p.name, qty: curCart[p._id] }))\n        const res = await d2.rush('consultoria-turn').invoke({ userMessage: text, cart: cartPayload, session_budget: d2.state.sessionBudget || {}, history: priorMsgs, applied_coupon: (d2.state.coupon && d2.state.coupon.code) || '', catalog: d2.state.catalog || 'a' })\n        const r = (res && res.data) ? res.data : res\n        if (!r || r.type === 'error') throw new Error((r && r.message) || 'resposta vazia')\n        // cadência humana: os pontinhos ficam ao menos ~1.1s na tela\n        const waitMs = 1100 - (Date.now() - t0)\n        if (waitMs > 0) await sleep(waitMs)\n        if (r && r.budget && (Number(r.budget.value) || 0) > 0) {\n          d2.state.sessionBudget = { scope: r.budget.scope || '', value: r.budget.value, hint: (r.intent && r.intent.product_hint) || (d2.state.sessionBudget && d2.state.sessionBudget.hint) || '' }\n        }\n        if (r.type === 'cart_action') {\n          const c = { ...(d2.state.cart || {}) }\n          const src = { ...(d2.state.cartSource || {}) }\n          ;(r.ops || []).forEach((o) => {\n            const id = o.product_id\n            if (!id) return\n            if (o.op === 'remove') { delete c[id]; delete src[id] }\n            else if (o.op === 'set_qty') { const q = Number(o.qty) || 0; if (q <= 0) { delete c[id]; delete src[id] } else { c[id] = q; if (!src[id]) src[id] = 'bot' } }\n            else { c[id] = (c[id] || 0) + (Number(o.qty) || 1); if (!src[id]) src[id] = 'bot' }\n            if (c[id] !== undefined && c[id] <= 0) { delete c[id]; delete src[id] }\n          })\n          d2.state.cart = c\n          d2.state.cartSource = src\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: r.reply || 'Pronto, atualizei sua sacola! 🛍️' }]\n        } else if (r.type === 'coupon_offer') {\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: r.reply || 'Deixa eu ver o que consigo de desconto pra você…' }]\n          if (r.has_coupon && r.coupon && r.coupon.code) {\n            await sleep(900)\n            d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '', coupon: r.coupon }]\n          }\n        } else if (r.type === 'product_options') {\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: r.reply || 'Veja as opções:' }]\n          await sleep(900)\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '', options: r.options || [] }]\n        } else if (r.type === 'chat') {\n          const csets = (r.routines || []).map((rt) => ({ key: 'set-' + Date.now() + '-' + Math.floor(Math.random() * 1000), name: rt.name, blurb: rt.rationale || '', warnings: [], items: rt.items_detailed || [], total: rt.total, budget_active: false, over_budget: false }))\n          if (csets.length) { const rmap = { ...(d2.state.routineMap || {}) }; csets.forEach((rt) => { rmap[rt.key] = rt.items.map((it) => it.product_id) }); d2.state.routineMap = rmap }\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: r.reply || 'Como posso ajudar?' }]\n          if (csets.length) { await sleep(900); d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '', routines: csets }] }\n        } else if (r.type === 'question') {\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: r.question || 'Pode me dar mais detalhes?', qoptions: r.question_options || [] }]\n        } else {\n          const copyByKey = {}\n          ;((r.copy && r.copy.routines) || []).forEach((c) => { copyByKey[c.key] = c })\n          const hasBudget = !!(r.budget && (Number(r.budget.value) || 0) > 0)\n          const routines = (r.routines || []).map((rt) => ({\n            key: rt.key, name: rt.name, total: rt.total,\n            blurb: (copyByKey[rt.key] && copyByKey[rt.key].blurb) || rt.rationale || '',\n            warnings: (copyByKey[rt.key] && copyByKey[rt.key].warnings) || [],\n            items: rt.items_detailed || [],\n            over_budget: !!rt.over_budget,\n            budget_active: hasBudget,\n          }))\n          const rmap = { ...(d2.state.routineMap || {}) }\n          routines.forEach((rt) => { rmap[rt.key] = rt.items.map((it) => it.product_id) })\n          d2.state.routineMap = rmap\n          const botText = (r.copy && r.copy.diagnosis) || r.diagnosis_seed || 'Aqui estão as rotinas que montei pra você:'\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: botText }]\n          await sleep(1000)\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '', routines }]\n        }\n        if (spoken) {\n          const msgs2 = d2.state.messages || []\n          let say = ''\n          for (let i = msgs2.length - 1; i >= 0; i--) { if (msgs2[i].role === 'bot' && msgs2[i].text) { say = msgs2[i].text; break } }\n          if (say) { try { d2.assistant('consultora-ouvido').speak(say, { language: 'pt-BR', voice: 'Camila' }) } catch (e) { d2.log('speak error', e) } }\n        }\n      } catch (err) {\n        d2.log('consultoria-turn error', err)\n        d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '⚠️ Tive um problema ao montar a rotina. Pode tentar de novo?' }]\n      } finally {\n        d2.state.loading = false\n      }\n    }\n\n    let mediaRecorder = null\n    let audioChunks = []\n    let micBusy = false\n    let recStartAt = 0\n    const startRec = async () => {\n      if (micBusy || d2.state.recording) return\n      micBusy = true\n      try {\n        // primeiro uso: se a permissão ainda vai ser pedida, só libera o mic e orienta — não grava\n        let perm = null\n        try { perm = navigator.permissions ? await navigator.permissions.query({ name: 'microphone' }) : null } catch (e) { perm = null }\n        if (perm && perm.state === 'prompt') {\n          const warmup = await navigator.mediaDevices.getUserMedia({ audio: true })\n          warmup.getTracks().forEach((t) => t.stop())\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: 'Microfone liberado! 🎤 Agora toque no microfone, fale sua mensagem e toque de novo para enviar.' }]\n          return\n        }\n        const stream = await navigator.mediaDevices.getUserMedia({ audio: true })\n        audioChunks = []\n        mediaRecorder = new MediaRecorder(stream)\n        mediaRecorder.ondataavailable = (e) => { if (e.data && e.data.size > 0) audioChunks.push(e.data) }\n        mediaRecorder.onstop = async () => {\n          stream.getTracks().forEach((t) => t.stop())\n          d2.state.recording = false\n          const tooShort = (Date.now() - recStartAt) < 700\n          const blob = new Blob(audioChunks, { type: mediaRecorder.mimeType || 'audio/webm' })\n          if (tooShort || !blob.size) {\n            d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: 'Não captei o áudio. 🎤 Toque no microfone, fale sua mensagem e toque de novo para enviar.' }]\n            return\n          }\n          const file = new File([blob], 'audio.webm', { type: blob.type })\n          d2.state.loading = true\n          try {\n            const hint = 'Mensagem de voz de um cliente de uma loja de beleza brasileira, falada em português do Brasil.'\n            const grab = (r) => (r && r.text) ? r.text : (typeof r === 'string' ? r : '')\n            let res = await d2.assistant('consultora-ouvido').listen(file, hint, { language: 'pt' })\n            let text = grab(res)\n            if (!text || !text.trim()) {\n              // 1º uso: módulo de transcrição pode estar inicializando — tenta 1x de novo com o mesmo áudio\n              await sleep(500)\n              res = await d2.assistant('consultora-ouvido').listen(file, hint, { language: 'pt' })\n              text = grab(res)\n            }\n            d2.state.loading = false\n            const clean = (text || '').trim()\n            const low = clean.toLowerCase().replace(/[.!?…\"'’]/g, '').trim()\n            const junk = ['amara.org', 'amara org', 'legendas pela comunidade', 'legendado pela comunidade', 'legendas pela', 'subtitles by', 'subtitle', 'thanks for watching', 'obrigado por assistir', 'inscreva-se', 'subscribe', 'www.']\n            const isJunk = !low || low.length < 2 || junk.some((b) => low.includes(b))\n            if (clean && !isJunk) { send(clean, { spoken: true }) }\n            else { d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '🎤 Não captei sua voz — parece que o microfone estava mudo ou sem áudio. Confira se ele está habilitado e tente de novo, ou escreva sua mensagem por aqui.' }] }\n          } catch (err) {\n            d2.log('listen error', err)\n            d2.state.loading = false\n            d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '⚠️ Tive um problema para transcrever o áudio. Pode escrever?' }]\n          }\n        }\n        mediaRecorder.start()\n        recStartAt = Date.now()\n        d2.state.recording = true\n      } catch (err) {\n        d2.log('mic error', err)\n        const denied = err && (err.name === 'NotAllowedError' || err.name === 'PermissionDeniedError' || err.name === 'SecurityError')\n        d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: denied ? 'O microfone está bloqueado pelo navegador. 🎤 Clique no cadeado ao lado do endereço do site, permita o microfone e tente de novo.' : 'Não consegui acessar o microfone. Verifique se outro aplicativo não está usando ele e tente de novo.' }]\n      } finally {\n        micBusy = false\n      }\n    }\n    d2.on('.js-mic', 'click', () => { if (d2.state.recording && mediaRecorder) { mediaRecorder.stop() } else { startRec() } })\n    const resizeImg = (file) => new Promise((resolve, reject) => {\n      const r = new FileReader()\n      r.onload = () => {\n        const img = new Image()\n        img.onload = () => {\n          const max = 768; let w = img.width; let h = img.height\n          if (w > h && w > max) { h = Math.round(h * max / w); w = max }\n          else if (h > max) { w = Math.round(w * max / h); h = max }\n          const c = document.createElement('canvas'); c.width = w; c.height = h\n          c.getContext('2d').drawImage(img, 0, 0, w, h)\n          resolve(c.toDataURL('image/jpeg', 0.85))\n        }\n        img.onerror = reject; img.src = r.result\n      }\n      r.onerror = reject; r.readAsDataURL(file)\n    })\n    const parseAnalysis = (resp) => {\n      let a = (resp && resp.data !== undefined) ? resp.data : resp\n      if (typeof a === 'string') { try { a = JSON.parse(a.replace(/```json/gi, '').replace(/```/g, '').trim()) } catch (e) { a = null } }\n      return a\n    }\n    const hairRoutine = (a) => {\n      const bds = d2.data('bot-products-bDataSet')\n      const prods = (bds && !bds.loading) ? bds.records() : []\n      if (!prods.length) return null\n      const want = []\n      const tx = (a.texture || '').toLowerCase()\n      if (/cach|crespo|ondul/.test(tx)) want.push('cach', 'crespo', 'textura')\n      const cond = (a.condition || '').toLowerCase()\n      if (cond === 'seco') want.push('seco', 'ressecad')\n      if (cond === 'danificado') want.push('danificad')\n      if (cond === 'oleoso') want.push('oleos')\n      if (a.colored) want.push('loiro', 'descolor')\n      const need = (a.needs || []).join(' ').toLowerCase()\n      const score = (p) => {\n        const sub = (p.subcategory || '').toLowerCase(); const nm = (p.name || '').toLowerCase(); let s = 0\n        want.forEach((t) => { if (sub.includes(t)) s += 3; if (nm.includes(t)) s += 1 })\n        if (need.includes('hidrat') && /hidrat/.test(nm)) s += 2\n        if (need.includes('reconstru') && /reconstru/.test(nm)) s += 2\n        if ((need.includes('cach') || need.includes('frizz') || need.includes('defini')) && /cach|frizz/.test(nm)) s += 2\n        if (need.includes('loiro') && /loiro/.test(nm)) s += 2\n        if (sub.includes('todos')) s += 0.3\n        return s\n      }\n      const cats = ['Shampoo', 'Condicionador', 'Máscara', 'Leave-in', 'Finalizador', 'Óleo']\n      const items = []\n      cats.forEach((c) => { const pool = prods.filter((p) => p.category === c); if (pool.length) { pool.sort((x, y) => score(y) - score(x)); items.push(pool[0]) } })\n      const chosen = items.slice(0, 4)\n      if (!chosen.length) return null\n      return {\n        key: 'hair-' + Date.now() + '-' + Math.floor(Math.random() * 1000),\n        name: 'Rotina para o seu cabelo',\n        blurb: a.summary || 'Selecionei com base na análise do seu cabelo.',\n        warnings: [],\n        items: chosen.map((p) => ({ product_id: p._id, name: p.name, price: p.price, step: p.category, image: p.image_url })),\n        total: chosen.reduce((t, p) => t + (Number(p.price) || 0), 0),\n        budget_active: false, over_budget: false,\n      }\n    }\n    d2.on('.js-photo-input', 'change', async (e, el) => {\n      const file = el.files && el.files[0]\n      el.value = ''\n      if (!file || !/^image\\//.test(file.type)) return\n      d2.state.open = true\n      d2.state.hairAnalyzing = true\n      let dataUrl = ''\n      try { dataUrl = await resizeImg(file) } catch (er) { d2.state.hairAnalyzing = false; d2.log('resize error', er); return }\n      try {\n        const resp = await d2.rush('analisa-cabelo').invoke({ image: dataUrl })\n        const a = parseAnalysis(resp)\n        d2.state.hairAnalyzing = false\n        if (!a || !a.is_hair) {\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '📷 ' + ((a && a.reject_reason) || 'Não consegui identificar seu cabelo nessa foto') + '. Pra eu recomendar direitinho — e pela sua segurança — me envie uma foto focada só no cabelo, tá? 💇' }]\n          return\n        }\n        d2.state.messages = [...(d2.state.messages || []), { role: 'user', text: '', image: dataUrl }]\n        const rt = hairRoutine(a)\n        d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: (a.summary || 'Analisei seu cabelo!') + (rt ? ' Montei uma rotina que combina com ele 👇' : ' Me conta o que você busca que eu recomendo.') }]\n        if (rt) {\n          const rmap = { ...(d2.state.routineMap || {}) }; rmap[rt.key] = rt.items.map((it) => it.product_id); d2.state.routineMap = rmap\n          await sleep(900)\n          d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '', routines: [rt] }]\n        }\n      } catch (err) {\n        d2.log('analisa-cabelo error', err)\n        d2.state.hairAnalyzing = false\n        d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: '⚠️ Não consegui analisar a foto agora. Pode tentar de novo?' }]\n      }\n    })\n    d2.on('.js-open-product', 'click', (e, el) => { if (e.target && e.target.closest && e.target.closest('button')) return; d2.state.selectedId = el.dataset.id })\n    d2.on('.js-modal-close', 'click', () => { d2.state.selectedId = null })\n    d2.on('.js-open-side', 'click', (e, el) => { d2.state.sideProductId = el.dataset.id })\n    d2.on('.js-side-close', 'click', () => { d2.state.sideProductId = null })\n    d2.on('.js-add-side', 'click', (e, el) => addToCart(el.dataset.id, 1, 'bot'))\n    d2.on('.js-ask-product', 'click', (e, el) => { d2.state.selectedId = null; d2.state.open = true; send('Me conta mais sobre o ' + el.dataset.name + ' — combina com a minha pele e como eu uso?') })\n    d2.on('.js-add', 'click', (e, el) => addToCart(el.dataset.id, 1, 'manual'))\n    d2.on('.js-inc', 'click', (e, el) => addToCart(el.dataset.id, 1, 'manual'))\n    d2.on('.js-dec', 'click', (e, el) => addToCart(el.dataset.id, -1))\n    d2.on('.js-remove', 'click', (e, el) => { const c = { ...(d2.state.cart || {}) }; const src = { ...(d2.state.cartSource || {}) }; delete c[el.dataset.id]; delete src[el.dataset.id]; d2.state.cart = c; d2.state.cartSource = src })\n    d2.on('.js-cart', 'click', () => { d2.state.cartOpen = true; loadSuggestions() })\n    d2.on('.js-fav', 'click', (e, el) => { const f = { ...(d2.state.favs || {}) }; const id = el.dataset.id; if (f[id]) { delete f[id] } else { f[id] = true }; d2.state.favs = f })\n    d2.on('.js-cat', 'click', (e, el) => { d2.state.category = el.dataset.cat || '' })\n    d2.on('.js-catsw', 'click', () => {\n      d2.state.catalog = (d2.state.catalog === 'b') ? 'a' : 'b'\n      d2.state.cart = {}; d2.state.cartSource = {}; d2.state.coupon = null; d2.state.category = ''\n    })\n    d2.on('.js-profile', 'click', () => {\n      let authed = false\n      try { authed = sessionStorage.getItem('painelAuthed') === '1' } catch (e) { authed = false }\n      if (!authed) { window.location.assign('/login'); return }\n      d2.state.profileMenu = !d2.state.profileMenu\n    })\n    d2.on('.js-profile-close', 'click', () => { d2.state.profileMenu = false })\n    d2.on('.js-goto-painel', 'click', () => {\n      d2.state.profileMenu = false\n      // navegação completa: o router monta na rota e reavalia a policy do /painel\n      window.location.assign('/painel')\n    })\n    d2.on('.js-cart-to-chat', 'click', () => { d2.state.cartOpen = false; d2.state.open = true; send('Os produtos da minha sacola combinam com a minha pele? Pode conferir?') })\n    d2.on('.js-pay', 'click', (e, el) => { d2.state.payMethod = el.dataset.pay })\n    d2.on('.js-cart-close', 'click', () => { d2.state.cartOpen = false })\n    d2.on('.js-checkout', 'click', () => { d2.state.cartOpen = false; d2.state.checkoutDone = false; d2.state.view = 'checkout'; loadSuggestions() })\n    d2.on('.js-home', 'click', () => { d2.state.view = 'store'; d2.state.checkoutDone = false })\n    d2.on('.js-confirm', 'click', async () => {\n      const order = '#AB' + Math.floor(100000 + Math.random() * 900000)\n      try {\n        const pds = d2.data(d2.state.catalog === 'b' ? 'bot-products-bDataSet' : 'products')\n        const prods = (pds && !pds.loading) ? pds.records() : []\n        const cart = d2.state.cart || {}\n        const items = prods.filter((p) => (cart[p._id] || 0) > 0)\n        const itensCount = items.reduce((a, p) => a + (cart[p._id] || 0), 0)\n        const gross = items.reduce((a, p) => a + (Number(p.price) || 0) * (cart[p._id] || 0), 0)\n        const cp = d2.state.coupon\n        let discount = 0\n        if (cp && cp.code) {\n          const base = cp.scope === 'categoria' ? items.reduce((a, p) => a + ((p.category === cp.category) ? (Number(p.price) || 0) * (cart[p._id] || 0) : 0), 0) : gross\n          if (gross >= (Number(cp.min_total) || 0)) {\n            discount = cp.discount_type === 'percent' ? base * (Number(cp.discount_value) || 0) / 100 : Math.min(Number(cp.discount_value) || 0, base)\n          }\n        }\n        const ticket = Math.max(0, gross - discount)\n        const baseline = items.reduce((m, p) => Math.max(m, Number(p.price) || 0), 0)\n        const recorrencia = items.reduce((a, p) => { const dd = Number(p.duration_days) || 0; return a + (dd > 0 ? (Number(p.price) || 0) * (cart[p._id] || 0) * 30 / dd : 0) }, 0)\n        const csrc = d2.state.cartSource || {}\n        const isBot = (p) => csrc[p._id] === 'bot'\n        const itensBot = items.reduce((a, p) => a + (isBot(p) ? (cart[p._id] || 0) : 0), 0)\n        const ticketBot = items.reduce((a, p) => a + (isBot(p) ? (Number(p.price) || 0) * (cart[p._id] || 0) : 0), 0)\n        await d2.rush('registra-consulta').invoke({\n          created_at: new Date().toISOString(),\n          session_id: order,\n          itens_count: itensCount,\n          ticket_total: Math.round(ticket * 100) / 100,\n          baseline_avulso: Math.round(baseline * 100) / 100,\n          recorrencia_mensal_estimada: Math.round(recorrencia * 100) / 100,\n          devolucao_evitada_pct: 30,\n          assinatura_selecionada: false,\n          intent_summary: items.map((p) => p.name).join(', '),\n          itens_bot: itensBot,\n          itens_manual: itensCount - itensBot,\n          ticket_bot: Math.round(ticketBot * 100) / 100,\n          ticket_manual: Math.round((gross - ticketBot) * 100) / 100,\n        })\n      } catch (e) { d2.log('log consultation error', e) }\n      d2.state.orderNumber = order\n      d2.state.checkoutDone = true\n      d2.state.cart = {}\n      d2.state.cartSource = {}\n      d2.state.coupon = null\n    })\n    d2.on('.js-add-sugg', 'click', (e, el) => { addToCart(el.dataset.id, 1, 'bot'); loadSuggestions() })\n    d2.on('.js-add-opt', 'click', (e, el) => { addToCart(el.dataset.id, 1, 'bot'); d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: 'Adicionei à sua sacola! 🛍️ Quer que eu te explique como usar esse produto no dia a dia?' }] })\n    d2.on('.js-apply-coupon', 'click', (e, el) => {\n      d2.state.coupon = { code: el.dataset.code, discount_type: el.dataset.type, discount_value: Number(el.dataset.value) || 0, scope: el.dataset.scope, category: el.dataset.category || '', min_total: Number(el.dataset.min) || 0 }\n      d2.state.messages = [...(d2.state.messages || []), { role: 'bot', text: 'Cupom ' + el.dataset.code + ' aplicado! 🎉 O desconto já está valendo na sua sacola. Lembrando: vale um cupom por carrinho — aplicar outro substitui este.' }]\n    })\n    d2.on('.js-remove-coupon', 'click', () => { d2.state.coupon = null })\n    d2.on('.js-unread', 'click', () => { const log = d2.$('.log'); if (log) log.scrollTo({ top: log.scrollHeight, behavior: 'smooth' }) })\n    d2.on('.js-open', 'click', () => { d2.state.open = true })\n    d2.on('.js-close', 'click', () => { d2.state.open = false })\n    d2.on('.js-send', 'click', () => send())\n    d2.on('.js-chip', 'click', (e, el) => send(el.textContent))\n    d2.on('.js-ask', 'click', (e, el) => { d2.state.open = true; send('Me conta mais sobre o ' + el.dataset.name + ' e como ele entra numa boa rotina pra mim.') })\n    d2.on('.js-addroutine', 'click', (e, el) => {\n      const ids = (d2.state.routineMap || {})[el.dataset.key] || []\n      const c = { ...(d2.state.cart || {}) }\n      const src = { ...(d2.state.cartSource || {}) }\n      ids.forEach((id) => { c[id] = (c[id] || 0) + 1; if (!src[id]) src[id] = 'bot' })\n      d2.state.cart = c\n      d2.state.cartSource = src\n      d2.state.open = false\n      d2.state.cartOpen = true\n    })\n    d2.on('.cin', 'keydown', (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send() } })\n    d2.on('.cin', 'input', () => { const t = d2.$('.cin'); if (!t) return; t.style.height = 'auto'; t.style.height = Math.min(t.scrollHeight, 110) + 'px' })\n  },\n  updated(d2) {\n    const log = d2.$('.log')\n    if (!log) return\n    const unread = d2.$('.js-unread')\n    const syncUnread = () => {\n      if (!unread) return\n      const below = (log.scrollHeight - log.scrollTop - log.clientHeight) > 24\n      unread.style.display = below ? 'inline-flex' : 'none'\n    }\n    if (!log.dataset.sl) {\n      log.dataset.sl = '1'\n      log.addEventListener('scroll', syncUnread)\n    }\n    const msgs = d2.state.messages || []\n    const prev = Number(log.dataset.mc || 0)\n    if (msgs.length > prev) {\n      log.dataset.mc = String(msgs.length)\n      const last = msgs[msgs.length - 1]\n      const row = log.querySelector('.row[data-key=\"' + (msgs.length - 1) + '\"]')\n      if (last.role === 'bot' && row) {\n        if (last.text) {\n          // foca no TOPO da resposta do bot; o indicador avisa se houver mais abaixo\n          log.scrollTop = Math.max(0, row.offsetTop - log.offsetTop - 8)\n        }\n        // follow-up sem texto (cards): mantém a posição de leitura; o indicador sinaliza o resto\n      } else {\n        log.scrollTop = log.scrollHeight\n      }\n    } else if (d2.state.loading) {\n      log.scrollTop = log.scrollHeight\n    }\n    syncUnread()\n  },\n}","at":"2026-07-07T12:05:52.718Z"}}},{"_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":[]}},{"reference":"ComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a43e6a6bf38d38281478f07","component":"data2-core-primitives@Router","system":"66f6c624d8a4a0c67041a910","displayName":"Consultora Router","params":{"routerType":{"component":"data2-core-primitives@String","params":{"content":"browser"}},"routes":[{"component":"data2-core-primitives@Route","params":{"path":"","name":"Loja Consultora","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"QUp5ISBgg4ta1C3amriVk"}}}},{"component":"data2-core-primitives@Route","params":{"path":"/painel","name":"Painel Comercial","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"F8zedope419IB3Df3gwMm"}},"policies":[{"component":"data2-core-types@PolicyReference","params":{"authenticationStrategy":{"reference":"painel-auth"}}}]}},{"component":"data2-core-primitives@Route","params":{"path":"/login","name":"Login","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"d2Wa2CKTeY3wJcurcTzjv"}}}}],"login":{"component":"data2-core-types@ArtboardReference","params":{"reference":"d2Wa2CKTeY3wJcurcTzjv"}}},"reference":"consultora-router"},{"_id":"6a464a78b0a857d0aa5cb42c","component":"data2-core-primitives@Artboard","system":"66f6c624d8a4a0c67041a910","displayName":"Login Painel","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Login Painel"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"d2Wa2CKTeY3wJcurcTzjv"},{"_id":"6a43e4b5bf38d38281478646","component":"data2-core-primitives@Artboard","system":"66f6c624d8a4a0c67041a910","displayName":"Consultora - Painel Comercial","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Consultora - Painel Comercial"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"F8zedope419IB3Df3gwMm"},{"_id":"6a450ad7bf38d382814a36ef","component":"data2-core-primitives@Artboard","system":"66f6c624d8a4a0c67041a910","displayName":"Loja Consultora (code)","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Loja Consultora (code)"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"QUp5ISBgg4ta1C3amriVk"},{"_id":"3f45c1153cb91a349dd96d2d","parent":"6a464a78b0a857d0aa5cb42c","component":"fernando-playground@painel-login","system":"66f6c624d8a4a0c67041a910","displayName":"Login","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":1440,"height":900}}}},"reference":"sR-tvze-trIlXoDn6Gpoi"},{"_id":"aa73cf8ecc071c28b825e7c3","parent":"6a43e4b5bf38d38281478646","component":"fernando-playground@painel-comercial","system":"66f6c624d8a4a0c67041a910","displayName":"Painel Comercial","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":1440,"height":900}}},"consultations":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"bot-consultationsDataSet"}}},"reference":"2GdxIPq1he1NePZx9lE07"},{"_id":"c6c9f1950d40e7096db2cb76","parent":"6a450ad7bf38d382814a36ef","component":"fernando-playground@consultora-app","system":"66f6c624d8a4a0c67041a910","displayName":"consultora-app","params":{"products":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"bot-productsDataSet"}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}}}},"reference":"H-7-gpCw4yDD516SGl9qh"}]}},{"_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":"6a43e6b3114b69c0c3971893","displayName":"Consultora de Beleza por IA","reference":"OUNLqGgtOF3p8YI6vcs8L","params":{"domain":{"component":"data2-core-primitives@String","params":{"content":"consultora-beleza"}},"entryPoint":{"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Router","reference":"consultora-router"}}},"system":"66f6c624d8a4a0c67041a910","component":"data2-core-primitives@Application"}]}},{"reference":"DataComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a43d2c16cdbd94b4dfd325a","component":"data2-core@DataSet","system":"66f6c624d8a4a0c67041a910","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"bot-consultations"}}},"reference":"bot-consultationsDataSet"},{"_id":"6a43d2b0a92372895f22d31c","component":"data2-core@DataSet","system":"66f6c624d8a4a0c67041a910","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"bot-products"}}},"reference":"bot-productsDataSet"},{"_id":"6a43d2c1af6a4650d310e250","component":"data2-core@Data2TableDataSource","system":"66f6c624d8a4a0c67041a910","params":{"table":"bot-consultations","schema":[{"component":"data2-core-types@Field","params":{"key":"created_at","title":"Criado em","component":"data2-core-primitives@Date"}},{"component":"data2-core-types@Field","params":{"key":"session_id","title":"Sessão","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"profile_id","title":"Perfil","component":"data2-core-primitives@ObjectId"}},{"component":"data2-core-types@Field","params":{"key":"catalog_id","title":"Catálogo","component":"data2-core-primitives@ObjectId"}},{"component":"data2-core-types@Field","params":{"key":"intent_summary","title":"Diagnóstico","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"chosen_routine","title":"Rotina escolhida","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"key":"itens_count","title":"Itens","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"ticket_total","title":"Ticket total","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"baseline_avulso","title":"Baseline avulso","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"recorrencia_mensal_estimada","title":"Recorrência mensal est.","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"devolucao_evitada_pct","title":"Devolução evitada (%)","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"assinatura_selecionada","title":"Assinatura","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"itens_bot","title":"Itens pela IA","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"itens_manual","title":"Itens manuais","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"ticket_bot","title":"Valor pela IA","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"ticket_manual","title":"Valor manual","component":"data2-core-primitives@Number"}}]},"reference":"bot-consultations"},{"_id":"6a43d2affbbc6ccb0614deb5","component":"data2-core@Data2TableDataSource","system":"66f6c624d8a4a0c67041a910","params":{"table":"bot-products","schema":[{"component":"data2-core-types@Field","params":{"key":"catalog_id","title":"Catálogo","component":"data2-core-primitives@ObjectId"}},{"component":"data2-core-types@Field","params":{"key":"name","title":"Nome","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"brand","title":"Marca","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"routine_step","title":"Etapa da rotina","component":"data2-core-primitives@ObjectId"}},{"component":"data2-core-types@Field","params":{"key":"category","title":"Categoria","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"subcategory","title":"Subcategoria","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"price","title":"Preço","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"image_url","title":"Imagem","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"stock","title":"Estoque","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"duration_days","title":"Duração (dias)","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"usage_period","title":"Período de uso","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"description","title":"Descrição","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"how_to_use","title":"Modo de uso","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"contraindications","title":"Contraindicações","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"sku","title":"SKU","component":"data2-core-primitives@String"}}]},"reference":"bot-products"}]}},{"reference":"BundlesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}}],"processesParams":{}}}}