{"context":{"domain":"gabz-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":"6863d782e78450ee0fd57fc7","name":"Gabz Playground","domain":"gabz-playground","visibility":"public","settings":{"defaultAccessPolicy":"private"},"updatedAt":"2026-08-14T19:26:29.927Z"}]}},{"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":"6a2c70391b1e52cefa10afa0","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"central-de-chamados","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const STATUS = {\n  aberto:       { label: 'Aberto',        fg: '#1d4ed8', bg: '#dbeafe' },\n  em_andamento: { label: 'Em andamento',  fg: '#b45309', bg: '#fef3c7' },\n  resolvido:    { label: 'Resolvido',     fg: '#15803d', bg: '#dcfce7' },\n  cancelado:    { label: 'Cancelado',     fg: '#64748b', bg: '#f1f5f9' }\n};\nconst PRIORIDADE = {\n  baixa:   { label: 'Baixa',   cor: '#94a3b8' },\n  media:   { label: 'Média',   cor: '#f59e0b' },\n  alta:    { label: 'Alta',    cor: '#f97316' },\n  critica: { label: 'Crítica', cor: '#dc2626' }\n};\nconst CATEGORIAS = ['Acesso', 'Financeiro', 'Bug', 'Infraestrutura', 'Solicitação'];\n\nconst esc = t => String(t == null ? '' : t).replace(/[&<>\"]/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;' }[c]));\n\nfunction tempoAtras(iso) {\n  if (!iso) return '';\n  const diff = Date.now() - new Date(iso).getTime();\n  const min = Math.floor(diff / 60000);\n  if (min < 1) return 'agora';\n  if (min < 60) return min + 'min atrás';\n  const h = Math.floor(min / 60);\n  if (h < 24) return h + 'h atrás';\n  const d = Math.floor(h / 24);\n  return d + 'd atrás';\n}\n\nconst iniciais = nome => String(nome || '?').trim().split(/\\s+/).slice(0, 2).map(p => p[0]).join('').toUpperCase();\n\nfunction badgeStatus(st) {\n  const m = STATUS[st] || { label: st, fg: '#475569', bg: '#f1f5f9' };\n  return '<span class=\"chm-badge\" style=\"color:' + m.fg + ';background:' + m.bg + '\">' + esc(m.label) + '</span>';\n}\n\nfunction dotPrioridade(p) {\n  const m = PRIORIDADE[p] || PRIORIDADE.baixa;\n  return '<span class=\"chm-prio\"><i style=\"background:' + m.cor + '\"></i>' + esc(m.label) + '</span>';\n}\n\nexport default {\n  css: `\n    .chm { font-family: 'Inter', system-ui, sans-serif; background: #f8fafc; color: #0f172a; height: 100%; min-height: 540px; display: flex; flex-direction: column; border: 1px solid #e2e8f0; border-radius: 14px; overflow: hidden; }\n    .chm-top { display: flex; align-items: center; gap: 12px; padding: 16px 20px; background: #fff; border-bottom: 1px solid #e2e8f0; }\n    .chm-top h2 { margin: 0; font-size: 17px; font-weight: 700; }\n    .chm-top .chm-total { font-size: 12px; color: #64748b; }\n    .chm-busca { margin-left: auto; width: 220px; padding: 8px 12px; border: 1px solid #e2e8f0; border-radius: 8px; font-size: 13px; outline: none; background: #f8fafc; }\n    .chm-busca:focus { border-color: #6366f1; background: #fff; }\n    .chm-novo { padding: 8px 14px; background: #4f46e5; color: #fff; border: 0; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer; }\n    .chm-novo:hover { background: #4338ca; }\n    .chm-tabs { display: flex; gap: 4px; padding: 10px 20px 0; background: #fff; border-bottom: 1px solid #e2e8f0; }\n    .chm-tab { padding: 8px 12px 10px; font-size: 13px; color: #64748b; background: none; border: 0; border-bottom: 2px solid transparent; cursor: pointer; }\n    .chm-tab b { font-weight: 600; }\n    .chm-tab .chm-n { margin-left: 5px; font-size: 11px; background: #f1f5f9; border-radius: 99px; padding: 1px 7px; color: #475569; }\n    .chm-tab.on { color: #4f46e5; border-bottom-color: #4f46e5; }\n    .chm-body { display: flex; flex: 1; min-height: 0; }\n    .chm-lista { flex: 1; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 8px; }\n    .chm-card { background: #fff; border: 1px solid #e2e8f0; border-radius: 10px; padding: 12px 14px; cursor: pointer; transition: border-color .12s, box-shadow .12s; }\n    .chm-card:hover { border-color: #c7d2fe; }\n    .chm-card.sel { border-color: #4f46e5; box-shadow: 0 0 0 2px #e0e7ff; }\n    .chm-card-top { display: flex; align-items: center; gap: 8px; }\n    .chm-card-top h3 { margin: 0; font-size: 14px; font-weight: 600; flex: 1; }\n    .chm-card-meta { display: flex; align-items: center; gap: 12px; margin-top: 8px; font-size: 12px; color: #64748b; flex-wrap: wrap; }\n    .chm-badge { font-size: 11px; font-weight: 600; padding: 2px 9px; border-radius: 99px; white-space: nowrap; }\n    .chm-prio { display: inline-flex; align-items: center; gap: 5px; }\n    .chm-prio i { width: 8px; height: 8px; border-radius: 99px; display: inline-block; }\n    .chm-cat { background: #f1f5f9; padding: 1px 8px; border-radius: 6px; }\n    .chm-resp-n { margin-left: auto; }\n    .chm-vazio { text-align: center; color: #94a3b8; font-size: 13px; padding: 48px 0; }\n    .chm-det { width: 46%; max-width: 520px; border-left: 1px solid #e2e8f0; background: #fff; overflow-y: auto; display: flex; flex-direction: column; }\n    .chm-det-head { padding: 16px 18px; border-bottom: 1px solid #f1f5f9; }\n    .chm-det-head h3 { margin: 6px 0 10px; font-size: 16px; }\n    .chm-det-desc { font-size: 13px; color: #475569; line-height: 1.55; margin: 0; }\n    .chm-det-info { display: flex; gap: 16px; margin-top: 12px; font-size: 12px; color: #64748b; flex-wrap: wrap; }\n    .chm-acoes { display: flex; gap: 8px; margin-top: 14px; }\n    .chm-acao { padding: 6px 12px; font-size: 12px; font-weight: 600; border-radius: 7px; border: 1px solid #e2e8f0; background: #fff; cursor: pointer; color: #334155; }\n    .chm-acao:hover { background: #f8fafc; }\n    .chm-acao.ok { border-color: #bbf7d0; color: #15803d; }\n    .chm-acao.no { border-color: #fecaca; color: #b91c1c; }\n    .chm-thread { flex: 1; padding: 14px 18px; display: flex; flex-direction: column; gap: 12px; }\n    .chm-msg { display: flex; gap: 10px; }\n    .chm-avatar { width: 30px; height: 30px; border-radius: 99px; background: #e0e7ff; color: #4338ca; font-size: 11px; font-weight: 700; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }\n    .chm-msg-body { background: #f8fafc; border: 1px solid #f1f5f9; border-radius: 0 10px 10px 10px; padding: 8px 12px; font-size: 13px; }\n    .chm-msg-body b { font-size: 12px; }\n    .chm-msg-body time { font-size: 11px; color: #94a3b8; margin-left: 8px; }\n    .chm-msg-body p { margin: 4px 0 0; color: #334155; line-height: 1.5; }\n    .chm-sem-resp { font-size: 12px; color: #94a3b8; }\n    .chm-responder { padding: 14px 18px; border-top: 1px solid #f1f5f9; }\n    .chm-responder textarea { width: 100%; box-sizing: border-box; border: 1px solid #e2e8f0; border-radius: 8px; padding: 9px 12px; font: inherit; font-size: 13px; resize: vertical; min-height: 64px; outline: none; }\n    .chm-responder textarea:focus { border-color: #6366f1; }\n    .chm-responder button { margin-top: 8px; padding: 8px 16px; background: #4f46e5; color: #fff; border: 0; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer; }\n    .chm-overlay { position: absolute; inset: 0; background: rgba(15,23,42,.45); display: flex; align-items: center; justify-content: center; z-index: 10; }\n    .chm-modal { background: #fff; border-radius: 14px; width: 440px; max-width: 92%; padding: 20px 22px; box-shadow: 0 24px 60px rgba(15,23,42,.25); }\n    .chm-modal h3 { margin: 0 0 14px; font-size: 16px; }\n    .chm-modal label { display: block; font-size: 12px; font-weight: 600; color: #475569; margin: 10px 0 4px; }\n    .chm-modal input, .chm-modal select, .chm-modal textarea { width: 100%; box-sizing: border-box; border: 1px solid #e2e8f0; border-radius: 8px; padding: 8px 11px; font: inherit; font-size: 13px; outline: none; }\n    .chm-modal input:focus, .chm-modal select:focus, .chm-modal textarea:focus { border-color: #6366f1; }\n    .chm-modal-row { display: flex; gap: 10px; }\n    .chm-modal-row > div { flex: 1; }\n    .chm-form-erro { color: #b91c1c; font-size: 12px; margin-top: 8px; min-height: 15px; }\n    .chm-modal-acoes { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }\n    .chm-cancelar { padding: 8px 14px; background: #fff; border: 1px solid #e2e8f0; border-radius: 8px; font-size: 13px; cursor: pointer; color: #475569; }\n    .chm-wrap { position: relative; height: 100%; }\n  `,\n\n  render(d2) {\n    const ds = d2.data('chamados');\n    if (!ds) return '<div class=\"chm\"><div class=\"chm-vazio\">Conecte um dataset de chamados no parâmetro <b>chamados</b>.</div></div>';\n    if (ds.loading) return '<div class=\"chm\"><div class=\"chm-vazio\">Carregando chamados…</div></div>';\n\n    const s = d2.state;\n    const filtro = s.filtro || 'todos';\n    const busca = (s.busca || '').toLowerCase();\n    const todos = (ds.records() || []).slice().sort((a, b) => new Date(b.criadoEm || 0) - new Date(a.criadoEm || 0));\n\n    const porStatus = { todos: todos.length };\n    Object.keys(STATUS).forEach(k => { porStatus[k] = todos.filter(r => r.status === k).length; });\n\n    let lista = filtro === 'todos' ? todos : todos.filter(r => r.status === filtro);\n    if (busca) lista = lista.filter(r =>\n      [r.titulo, r.descricao, r.solicitante, r.categoria].join(' ').toLowerCase().includes(busca));\n\n    const sel = todos.find(r => String(r._id) === s.selId);\n\n    const tabs = ['todos'].concat(Object.keys(STATUS)).map(k => {\n      const lbl = k === 'todos' ? 'Todos' : STATUS[k].label;\n      return '<button class=\"chm-tab ' + (filtro === k ? 'on' : '') + '\" data-act=\"tab\" data-val=\"' + k + '\"><b>' + lbl + '</b><span class=\"chm-n\">' + (porStatus[k] || 0) + '</span></button>';\n    }).join('');\n\n    const cards = lista.length ? lista.map(r => {\n      const nResp = (r.respostas || []).length;\n      return '<div class=\"chm-card ' + (String(r._id) === s.selId ? 'sel' : '') + '\" data-act=\"sel\" data-id=\"' + esc(r._id) + '\">' +\n        '<div class=\"chm-card-top\"><h3>' + esc(r.titulo) + '</h3>' + badgeStatus(r.status) + '</div>' +\n        '<div class=\"chm-card-meta\">' + dotPrioridade(r.prioridade) +\n          '<span class=\"chm-cat\">' + esc(r.categoria || '—') + '</span>' +\n          '<span>' + esc(r.solicitante || '—') + '</span>' +\n          '<span>' + tempoAtras(r.criadoEm) + '</span>' +\n          '<span class=\"chm-resp-n\">💬 ' + nResp + '</span>' +\n        '</div></div>';\n    }).join('') : '<div class=\"chm-vazio\">Nenhum chamado por aqui.</div>';\n\n    let det = '';\n    if (sel) {\n      const aberto = sel.status === 'aberto' || sel.status === 'em_andamento';\n      const acoes = (aberto\n        ? '<button class=\"chm-acao ok\" data-act=\"status\" data-val=\"resolvido\" data-id=\"' + esc(sel._id) + '\">✓ Resolver</button>' +\n          '<button class=\"chm-acao no\" data-act=\"status\" data-val=\"cancelado\" data-id=\"' + esc(sel._id) + '\">✕ Cancelar chamado</button>'\n        : '<button class=\"chm-acao\" data-act=\"status\" data-val=\"aberto\" data-id=\"' + esc(sel._id) + '\">↺ Reabrir</button>');\n\n      const thread = (sel.respostas || []).length\n        ? sel.respostas.map(m =>\n            '<div class=\"chm-msg\"><div class=\"chm-avatar\">' + esc(iniciais(m.autor)) + '</div>' +\n            '<div class=\"chm-msg-body\"><b>' + esc(m.autor) + '</b><time>' + tempoAtras(m.data) + '</time><p>' + esc(m.texto) + '</p></div></div>'\n          ).join('')\n        : '<div class=\"chm-sem-resp\">Ainda sem respostas.</div>';\n\n      det = '<aside class=\"chm-det\">' +\n        '<div class=\"chm-det-head\">' + badgeStatus(sel.status) +\n          '<h3>' + esc(sel.titulo) + '</h3>' +\n          '<p class=\"chm-det-desc\">' + esc(sel.descricao) + '</p>' +\n          '<div class=\"chm-det-info\">' + dotPrioridade(sel.prioridade) +\n            '<span class=\"chm-cat\">' + esc(sel.categoria || '—') + '</span>' +\n            '<span>👤 ' + esc(sel.solicitante || '—') + '</span>' +\n            '<span>🛠 ' + esc(sel.responsavel || 'sem responsável') + '</span>' +\n          '</div>' +\n          '<div class=\"chm-acoes\">' + acoes + '</div>' +\n        '</div>' +\n        '<div class=\"chm-thread\">' + thread + '</div>' +\n        (aberto\n          ? '<div class=\"chm-responder\"><textarea id=\"chm-resp-texto\" placeholder=\"Escreva uma resposta…\"></textarea>' +\n            '<button data-act=\"responder\" data-id=\"' + esc(sel._id) + '\">Responder</button></div>'\n          : '') +\n      '</aside>';\n    }\n\n    const modal = s.modal ? '<div class=\"chm-overlay\" data-act=\"overlay\"><div class=\"chm-modal\">' +\n      '<h3>Novo chamado</h3>' +\n      '<label>Título</label><input id=\"chm-f-titulo\" placeholder=\"Resumo do problema\" />' +\n      '<div class=\"chm-modal-row\">' +\n        '<div><label>Categoria</label><select id=\"chm-f-cat\">' + CATEGORIAS.map(c => '<option>' + c + '</option>').join('') + '</select></div>' +\n        '<div><label>Prioridade</label><select id=\"chm-f-prio\">' + Object.keys(PRIORIDADE).map(k => '<option value=\"' + k + '\">' + PRIORIDADE[k].label + '</option>').join('') + '</select></div>' +\n      '</div>' +\n      '<label>Solicitante</label><input id=\"chm-f-sol\" placeholder=\"Seu nome\" />' +\n      '<label>Descrição</label><textarea id=\"chm-f-desc\" rows=\"3\" placeholder=\"Detalhe o que está acontecendo\"></textarea>' +\n      '<div class=\"chm-form-erro\" id=\"chm-form-erro\"></div>' +\n      '<div class=\"chm-modal-acoes\">' +\n        '<button class=\"chm-cancelar\" data-act=\"fechar-modal\">Cancelar</button>' +\n        '<button class=\"chm-novo\" data-act=\"criar\">Abrir chamado</button>' +\n      '</div>' +\n    '</div></div>' : '';\n\n    return '<div class=\"chm-wrap\"><div class=\"chm\">' +\n      '<div class=\"chm-top\"><h2>Central de Chamados</h2><span class=\"chm-total\">' + todos.length + ' no total</span>' +\n        '<input class=\"chm-busca\" placeholder=\"Buscar chamados…\" value=\"' + esc(s.busca || '') + '\" />' +\n        '<button class=\"chm-novo\" data-act=\"novo\">+ Novo chamado</button>' +\n      '</div>' +\n      '<div class=\"chm-tabs\">' + tabs + '</div>' +\n      '<div class=\"chm-body\"><div class=\"chm-lista\">' + cards + '</div>' + det + '</div>' +\n    '</div>' + modal + '</div>';\n  },\n\n  mounted(d2) {\n    const ds = () => d2.data('chamados');\n    const autor = () => d2.param('autor', 'Gabriel Cardoso');\n    const rec = id => (ds().records() || []).find(r => String(r._id) === String(id));\n    const alvo = (e, sel) => e.target.closest(sel);\n\n    d2.on('[data-act=\"novo\"]', 'click', () => { d2.state.modal = true; });\n    d2.on('[data-act=\"fechar-modal\"]', 'click', () => { d2.state.modal = false; });\n    d2.on('[data-act=\"overlay\"]', 'click', e => { if (e.target === alvo(e, '[data-act=\"overlay\"]')) d2.state.modal = false; });\n\n    d2.on('[data-act=\"tab\"]', 'click', e => { d2.state.filtro = alvo(e, '[data-act=\"tab\"]').dataset.val; });\n\n    d2.on('.chm-busca', 'input', e => { d2.state._focoBusca = true; d2.state.busca = e.target.value; });\n\n    d2.on('[data-act=\"sel\"]', 'click', e => {\n      const id = alvo(e, '[data-act=\"sel\"]').dataset.id;\n      d2.state.selId = d2.state.selId === id ? null : id;\n    });\n\n    d2.on('[data-act=\"criar\"]', 'click', async e => {\n      const v = sel => { const el = d2.$(sel); return el ? el.value.trim() : ''; };\n      const titulo = v('#chm-f-titulo');\n      const erro = d2.$('#chm-form-erro');\n      if (!titulo) { if (erro) erro.textContent = 'Dê um título ao chamado.'; return; }\n      const btn = alvo(e, '[data-act=\"criar\"]');\n      btn.disabled = true; btn.textContent = 'Abrindo…';\n      try {\n        await ds().create({\n          titulo,\n          descricao: v('#chm-f-desc'),\n          categoria: v('#chm-f-cat') || CATEGORIAS[0],\n          prioridade: d2.$('#chm-f-prio').value || 'media',\n          status: 'aberto',\n          solicitante: v('#chm-f-sol') || autor(),\n          responsavel: '',\n          criadoEm: new Date().toISOString(),\n          respostas: []\n        });\n        d2.state.modal = false;\n        d2.state.filtro = 'todos';\n      } catch (err) {\n        btn.disabled = false; btn.textContent = 'Abrir chamado';\n        if (erro) erro.textContent = 'Falha ao salvar: ' + (err && err.message || err);\n      }\n    });\n\n    d2.on('[data-act=\"responder\"]', 'click', async e => {\n      const id = alvo(e, '[data-act=\"responder\"]').dataset.id;\n      const r = rec(id);\n      const ta = d2.$('#chm-resp-texto');\n      const texto = ta ? ta.value.trim() : '';\n      if (!r || !texto) { if (ta) ta.focus(); return; }\n      await ds().update(Object.assign({}, r, {\n        status: r.status === 'aberto' ? 'em_andamento' : r.status,\n        responsavel: r.responsavel || autor(),\n        respostas: (r.respostas || []).concat([{ autor: autor(), texto, data: new Date().toISOString() }])\n      }));\n      d2.refresh();\n    });\n\n    d2.on('[data-act=\"status\"]', 'click', async e => {\n      const el = alvo(e, '[data-act=\"status\"]');\n      const r = rec(el.dataset.id);\n      if (!r) return;\n      const novo = el.dataset.val;\n      const patch = { status: novo };\n      if (novo === 'resolvido' || novo === 'em_andamento') patch.responsavel = r.responsavel || autor();\n      await ds().update(Object.assign({}, r, patch));\n      d2.refresh();\n    });\n  },\n\n  updated(d2, root) {\n    if (d2.state._focoBusca) {\n      const el = root.querySelector('.chm-busca');\n      if (el && document.activeElement !== el) {\n        el.focus();\n        const n = el.value.length;\n        el.setSelectionRange(n, n);\n      }\n    }\n  }\n};"}},"chamados":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"chamados"}}}},"autor":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"autor"}}}}}}}}}},{"_id":"6a2d926558bb101c909482da","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-button","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const defaults = {\n  colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorPrimaryBgHover:'#bae0ff',\n  colorSuccess:'#52c41a', colorSuccessHover:'#73d13d', colorSuccessActive:'#389e0d', colorSuccessBg:'#f6ffed', colorSuccessBgHover:'#d9f7be',\n  colorWarning:'#faad14', colorWarningHover:'#ffc53d', colorWarningActive:'#d48806', colorWarningBg:'#fffbe6', colorWarningBgHover:'#fff1b8',\n  colorError:'#ff4d4f', colorErrorHover:'#ff7875', colorErrorActive:'#d9363e', colorErrorBg:'#fff2f0', colorErrorBgHover:'#ffece8',\n  colorInfo:'#1677ff', colorInfoHover:'#4096ff', colorInfoActive:'#0958d9', colorInfoBg:'#e6f4ff', colorInfoBgHover:'#bae0ff',\n  colorText:'rgba(0,0,0,0.88)', colorTextLightSolid:'#ffffff', colorTextDisabled:'rgba(0,0,0,0.25)',\n  colorBorder:'#d9d9d9',\n  colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)',\n  colorBgSolid:'rgba(0,0,0,0.88)', colorBgSolidHover:'rgba(0,0,0,0.75)', colorBgSolidActive:'rgba(0,0,0,1)',\n  colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)',\n  colorBgTextHover:'rgba(0,0,0,0.06)', colorBgTextActive:'rgba(0,0,0,0.15)',\n  borderRadius:6, borderRadiusSM:4, borderRadiusLG:8,\n  controlHeight:32, controlHeightSM:24, controlHeightLG:40,\n  fontSize:14, fontSizeLG:16,\n  paddingInline:15, paddingInlineSM:7, paddingInlineLG:15,\n  lineWidth:1,\n  fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\",\n};\n\nfunction statusPal(D, color){\n  const map = {\n    primary:['colorPrimary','colorPrimaryHover','colorPrimaryActive','colorPrimaryBg','colorPrimaryBgHover'],\n    success:['colorSuccess','colorSuccessHover','colorSuccessActive','colorSuccessBg','colorSuccessBgHover'],\n    warning:['colorWarning','colorWarningHover','colorWarningActive','colorWarningBg','colorWarningBgHover'],\n    error:['colorError','colorErrorHover','colorErrorActive','colorErrorBg','colorErrorBgHover'],\n    info:['colorInfo','colorInfoHover','colorInfoActive','colorInfoBg','colorInfoBgHover'],\n  }[color];\n  if(!map) return null;\n  return { main:D[map[0]], hover:D[map[1]], active:D[map[2]], bg:D[map[3]], bgHover:D[map[4]] };\n}\n\nfunction clamp(x){ return Math.max(0, Math.min(255, Math.round(x))); }\nfunction parseColor(c){\n  if(c == null) return null;\n  if(typeof c === 'object'){ c = c.rgba || c.hex || c.value || c.color || ''; }\n  c = String(c).trim();\n  let m = c.match(/^#([0-9a-fA-F]{3})$/);\n  if(m){ const h=m[1]; return { r:parseInt(h[0]+h[0],16), g:parseInt(h[1]+h[1],16), b:parseInt(h[2]+h[2],16) }; }\n  m = c.match(/^#([0-9a-fA-F]{6})$/);\n  if(m){ const h=m[1]; return { r:parseInt(h.slice(0,2),16), g:parseInt(h.slice(2,4),16), b:parseInt(h.slice(4,6),16) }; }\n  m = c.match(/^rgba?\\(([^)]+)\\)$/i);\n  if(m){ const p=m[1].split(',').map(s=>parseFloat(s)); return { r:p[0], g:p[1], b:p[2] }; }\n  return null;\n}\nfunction rgbStr(o){ return 'rgb('+clamp(o.r)+','+clamp(o.g)+','+clamp(o.b)+')'; }\nfunction mix(a,b,w){ return { r:a.r+(b.r-a.r)*w, g:a.g+(b.g-a.g)*w, b:a.b+(b.b-a.b)*w }; }\nfunction derivePal(rgb){\n  const W={r:255,g:255,b:255}, B={r:0,g:0,b:0};\n  return { main:rgbStr(rgb), hover:rgbStr(mix(rgb,W,0.18)), active:rgbStr(mix(rgb,B,0.13)),\n           bg:rgbStr(mix(rgb,W,0.9)), bgHover:rgbStr(mix(rgb,W,0.82)) };\n}\n\nfunction resolve(D, pal, variant, disabled){\n  const white = D.colorTextLightSolid;\n  const v = { bw:D.lineWidth, bs:'solid', bc:'transparent', bch:'transparent', bca:'transparent',\n              bg:'transparent', bgh:'transparent', bga:'transparent',\n              fg:D.colorText, fgh:D.colorText, fga:D.colorText };\n  if(!pal){\n    if(variant==='solid'){ v.bg=D.colorBgSolid; v.bgh=D.colorBgSolidHover; v.bga=D.colorBgSolidActive; v.fg=v.fgh=v.fga=white; v.bc=v.bg; v.bch=v.bgh; v.bca=v.bga; }\n    else if(variant==='dashed'){ v.bs='dashed'; v.bg=v.bgh=v.bga=D.colorBgContainer; v.fg=D.colorText; v.fgh=D.colorPrimaryHover; v.fga=D.colorPrimaryActive; v.bc=D.colorBorder; v.bch=D.colorPrimaryHover; v.bca=D.colorPrimaryActive; }\n    else if(variant==='filled'){ v.bg=D.colorFillTertiary; v.bgh=D.colorFillSecondary; v.bga=D.colorFill; v.fg=v.fgh=v.fga=D.colorText; }\n    else if(variant==='text'){ v.bgh=D.colorBgTextHover; v.bga=D.colorBgTextActive; v.fg=v.fgh=v.fga=D.colorText; }\n    else if(variant==='link'){ v.fg=D.colorText; v.fgh=D.colorPrimaryHover; v.fga=D.colorPrimaryActive; }\n    else { v.bg=v.bgh=v.bga=D.colorBgContainer; v.fg=D.colorText; v.fgh=D.colorPrimaryHover; v.fga=D.colorPrimaryActive; v.bc=D.colorBorder; v.bch=D.colorPrimaryHover; v.bca=D.colorPrimaryActive; }\n  } else {\n    const p = pal;\n    if(variant==='solid'){ v.bg=p.main; v.bgh=p.hover; v.bga=p.active; v.fg=v.fgh=v.fga=white; v.bc=p.main; v.bch=p.hover; v.bca=p.active; }\n    else if(variant==='dashed'){ v.bs='dashed'; v.bg=v.bgh=v.bga=D.colorBgContainer; v.fg=p.main; v.fgh=p.hover; v.fga=p.active; v.bc=p.main; v.bch=p.hover; v.bca=p.active; }\n    else if(variant==='filled'){ v.bg=p.bg; v.bgh=p.bgHover; v.bga=p.bgHover; v.fg=p.main; v.fgh=p.main; v.fga=p.active; }\n    else if(variant==='text'){ v.bgh=D.colorBgTextHover; v.bga=D.colorBgTextActive; v.fg=v.fgh=v.fga=p.main; }\n    else if(variant==='link'){ v.fg=p.main; v.fgh=p.hover; v.fga=p.active; }\n    else { v.bg=v.bgh=v.bga=D.colorBgContainer; v.fg=p.main; v.fgh=p.hover; v.fga=p.active; v.bc=p.main; v.bch=p.hover; v.bca=p.active; }\n  }\n  if(disabled){\n    v.fg=v.fgh=v.fga=D.colorTextDisabled;\n    if(variant==='solid'||variant==='filled'){ v.bg=v.bgh=v.bga=D.colorBgContainerDisabled; } else { v.bg=v.bgh=v.bga='transparent'; }\n    if(variant==='outlined'||variant==='dashed'||!variant){ v.bc=v.bch=v.bca=D.colorBorder; } else { v.bc=v.bch=v.bca='transparent'; }\n  }\n  return v;\n}\n\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-btn{ box-sizing:border-box; display:inline-flex; align-items:center; justify-content:center; gap:8px;\n      height:var(--h); padding:0 var(--pad); font-size:var(--fs); font-family:var(--ff); font-weight:400;\n      line-height:1; white-space:nowrap; border-radius:var(--radius); border:var(--bw) var(--bs) var(--bc);\n      background:var(--bg); color:var(--fg); cursor:pointer; user-select:none; outline:none;\n      transition:all .2s cubic-bezier(.4,0,.2,1); vertical-align:middle; text-decoration:none; }\n    .ant-btn:hover{ background:var(--bg-h); color:var(--fg-h); border-color:var(--bc-h); }\n    .ant-btn:active{ background:var(--bg-a); color:var(--fg-a); border-color:var(--bc-a); }\n    .ant-btn.block{ width:100%; }\n    .ant-btn.disabled{ cursor:not-allowed; }\n    .ant-btn.loading{ cursor:default; pointer-events:none; }\n    .ant-btn.icon-only{ padding:0; width:var(--h); }\n    .ant-btn.is-link{ height:auto; padding:0; border-width:0; }\n    .ant-btn .ic{ display:inline-flex; align-items:center; justify-content:center; font-size:1em; line-height:0; }\n    .ant-btn .spin{ width:1em; height:1em; border:2px solid currentColor; border-top-color:transparent;\n      border-radius:50%; display:inline-block; animation:antspin .8s linear infinite; }\n    @keyframes antspin{ to{ transform:rotate(360deg); } }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const variant = p.variant || 'outlined';\n    const size = p.size || 'middle';\n    const shape = p.shape || 'default';\n    const label = p.label != null ? String(p.label) : '';\n    const glyph = p.glyph || '';\n    const iconPos = p.iconPosition || 'start';\n    const loading = !!p.loading;\n    const disabled = !!p.disabled;\n    const block = !!p.block;\n\n    // ---- token resolution: accept the AntDesignTokens shape (semanticsLight/Dark + state) OR a flat token object\n    const tk = (p.tokens && typeof p.tokens === 'object') ? p.tokens : {};\n    let sem = tk;\n    if(tk.semanticsLight || tk.semanticsDark){ sem = tk.darkMode ? (tk.semanticsDark || {}) : (tk.semanticsLight || {}); }\n    const T = {};\n    for(const k in sem){ let val = sem[k]; if(val == null || val === '') continue; if(typeof val === 'object') val = val.rgba || val.hex || val.value || val.color; if(val != null && val !== '') T[k] = val; }\n    const D = Object.assign({}, defaults, T);\n    if(tk.fontFamily) D.fontFamily = tk.fontFamily;\n    if((tk.density || 'comfortable') === 'compact'){ D.controlHeight=28; D.controlHeightSM=22; D.controlHeightLG=36; D.paddingInline=12; D.paddingInlineSM=6; D.paddingInlineLG=12; }\n    ['Primary','Success','Warning','Error','Info'].forEach(function(C){\n      const bk = 'color'+C;\n      if(T[bk] && !T[bk+'Hover']){ const rgb = parseColor(T[bk]); if(rgb){ const dp = derivePal(rgb); D[bk+'Hover']=dp.hover; D[bk+'Active']=dp.active; D[bk+'Bg']=dp.bg; D[bk+'BgHover']=dp.bgHover; } }\n    });\n\n    let colorRaw = p.color;\n    if(colorRaw && typeof colorRaw === 'object') colorRaw = colorRaw.rgba || colorRaw.hex || colorRaw.value || colorRaw.color || '';\n    let color = (colorRaw == null || colorRaw === '') ? 'default' : String(colorRaw).trim();\n    if(color === 'danger') color = 'error';\n    let pal = null;\n    if(color !== 'default'){\n      pal = statusPal(D, color);\n      if(!pal){ const rgb = parseColor(color); pal = rgb ? derivePal(rgb) : null; }\n    }\n\n    const v = resolve(D, pal, variant, disabled);\n    const SZ = ({\n      small:{ h:D.controlHeightSM, fs:D.fontSize, pad:D.paddingInlineSM, r:D.borderRadiusSM },\n      large:{ h:D.controlHeightLG, fs:D.fontSizeLG, pad:D.paddingInlineLG, r:D.borderRadiusLG },\n      middle:{ h:D.controlHeight, fs:D.fontSize, pad:D.paddingInline, r:D.borderRadius },\n    })[size] || { h:D.controlHeight, fs:D.fontSize, pad:D.paddingInline, r:D.borderRadius };\n\n    let radius = SZ.r + 'px';\n    if(shape==='round') radius = (SZ.h/2) + 'px';\n    if(shape==='circle') radius = '50%';\n    const iconOnly = !label && (!!glyph || shape==='circle');\n    const isLink = variant==='link';\n\n    const style = [\n      '--h:'+SZ.h+'px', '--pad:'+SZ.pad+'px', '--fs:'+SZ.fs+'px', '--radius:'+radius,\n      '--bw:'+v.bw+'px', '--bs:'+v.bs,\n      '--bc:'+v.bc, '--bc-h:'+v.bch, '--bc-a:'+v.bca,\n      '--bg:'+v.bg, '--bg-h:'+v.bgh, '--bg-a:'+v.bga,\n      '--fg:'+v.fg, '--fg-h:'+v.fgh, '--fg-a:'+v.fga,\n      '--ff:'+D.fontFamily\n    ].join(';');\n\n    const classes = ['ant-btn'];\n    if(block) classes.push('block');\n    if(disabled) classes.push('disabled');\n    if(loading) classes.push('loading');\n    if(iconOnly) classes.push('icon-only');\n    if(isLink) classes.push('is-link');\n\n    const isFa = /(^|\\s)fa[srlbd]?(\\s|-)/.test(glyph);\n    const iconHtml = glyph ? (String(glyph).charAt(0)==='<' ? '<span class=\"ic\">'+glyph+'</span>' : (isFa ? '<i class=\"ic '+esc(glyph)+'\"></i>' : '<span class=\"ic\">'+esc(glyph)+'</span>')) : '';\n    const spinHtml = '<span class=\"spin\"></span>';\n    const lead = loading ? spinHtml : (iconPos==='start' ? iconHtml : '');\n    const trail = (!loading && iconPos==='end') ? iconHtml : '';\n    const labelHtml = label ? '<span class=\"lbl\">'+esc(label)+'</span>' : '';\n\n    return '<button type=\"button\" class=\"'+classes.join(' ')+'\" style=\"'+style+'\"'+(disabled?' disabled':'')+'>'+lead+labelHtml+trail+'</button>';\n  },\n  mounted(d2){\n    d2.on('.ant-btn','click',(e)=>{\n      const p = d2.params || {};\n      if(p.disabled || p.loading) return;\n      d2.emit('onClick', {});\n    });\n  }\n};"}},"color":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"color"}}}},"variant":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"variant"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"shape":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"shape"}}}},"iconPosition":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"iconPosition"}}}},"label":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"label"}}}},"glyph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"glyph"}}}},"loading":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"loading"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"block":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"block"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}},"onClick":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onClick"}}}}}}}}}},{"_id":"6a2d92bd1b1e52cefa121ca8","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-button-lab","package":"gabz-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":"function antTokens(seed, darkMode, density){\n  const mix = (c,p,w) => 'color-mix(in srgb, '+c+' '+p+'%, '+w+')';\n  const light = {\n    colorPrimary:seed, colorPrimaryHover:mix(seed,72,'white'), colorPrimaryActive:mix(seed,80,'black'), colorPrimaryBg:mix(seed,8,'white'), colorPrimaryBgHover:mix(seed,16,'white'),\n    colorSuccess:'#52c41a', colorSuccessHover:mix('#52c41a',72,'white'), colorSuccessActive:mix('#52c41a',80,'black'), colorSuccessBg:mix('#52c41a',8,'white'), colorSuccessBgHover:mix('#52c41a',16,'white'),\n    colorError:'#ff4d4f', colorErrorHover:mix('#ff4d4f',72,'white'), colorErrorActive:mix('#ff4d4f',80,'black'), colorErrorBg:mix('#ff4d4f',8,'white'), colorErrorBgHover:mix('#ff4d4f',16,'white'),\n    colorText:'rgba(0,0,0,0.88)', colorTextLightSolid:'#ffffff', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9',\n    colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)',\n    colorBgSolid:'rgba(0,0,0,0.88)', colorBgSolidHover:'rgba(0,0,0,0.75)', colorBgSolidActive:'#000000',\n    colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)',\n    colorBgTextHover:'rgba(0,0,0,0.06)', colorBgTextActive:'rgba(0,0,0,0.15)'\n  };\n  const dark = {\n    colorPrimary:mix(seed,86,'white'), colorPrimaryHover:mix(seed,66,'white'), colorPrimaryActive:mix(seed,78,'black'), colorPrimaryBg:mix(seed,22,'black'), colorPrimaryBgHover:mix(seed,32,'black'),\n    colorSuccess:mix('#52c41a',86,'white'), colorSuccessHover:mix('#52c41a',66,'white'), colorSuccessActive:mix('#52c41a',78,'black'), colorSuccessBg:mix('#52c41a',22,'black'), colorSuccessBgHover:mix('#52c41a',32,'black'),\n    colorError:mix('#ff4d4f',86,'white'), colorErrorHover:mix('#ff4d4f',66,'white'), colorErrorActive:mix('#ff4d4f',78,'black'), colorErrorBg:mix('#ff4d4f',22,'black'), colorErrorBgHover:mix('#ff4d4f',32,'black'),\n    colorText:'rgba(255,255,255,0.85)', colorTextLightSolid:'#ffffff', colorTextDisabled:'rgba(255,255,255,0.25)', colorBorder:'#424242',\n    colorBgContainer:'#141414', colorBgContainerDisabled:'rgba(255,255,255,0.08)',\n    colorBgSolid:'rgba(255,255,255,0.85)', colorBgSolidHover:'rgba(255,255,255,0.95)', colorBgSolidActive:'#ffffff',\n    colorFillTertiary:'rgba(255,255,255,0.08)', colorFillSecondary:'rgba(255,255,255,0.12)', colorFill:'rgba(255,255,255,0.18)',\n    colorBgTextHover:'rgba(255,255,255,0.08)', colorBgTextActive:'rgba(255,255,255,0.15)'\n  };\n  return { darkMode:darkMode, density:density, semanticsLight:light, semanticsDark:dark };\n}\n\nexport default {\n  css: `\n    .wrap{ padding:28px 32px; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif; background:#ffffff; color:rgba(0,0,0,.88); box-sizing:border-box; }\n    .h1{ font-size:20px; font-weight:600; margin:0 0 4px; }\n    .sub{ font-size:13px; color:rgba(0,0,0,.45); margin:0 0 8px; }\n    .title{ font-size:12px; font-weight:600; text-transform:uppercase; letter-spacing:.05em; color:rgba(0,0,0,.45); margin:28px 0 14px; }\n    .matrix{ display:grid; grid-template-columns:120px repeat(6,minmax(0,1fr)); gap:14px; align-items:center; max-width:1100px; }\n    .row{ display:flex; flex-wrap:wrap; gap:14px; align-items:center; }\n    .cell{ display:flex; align-items:center; justify-content:center; min-height:40px; }\n    .head{ font-size:12px; color:rgba(0,0,0,.45); font-weight:500; text-align:center; }\n    .rowh{ justify-content:flex-start; text-align:left; }\n    .panel{ display:flex; flex-wrap:wrap; gap:14px; align-items:center; padding:20px; border-radius:10px; }\n    .panel.dark{ background:#141414; }\n    .panel.light{ background:#fafafa; }\n    .lbl2{ font-size:12px; color:rgba(0,0,0,.45); margin:0 0 8px; }\n  `,\n  render(d2){\n    const colors=['default','primary','success','warning','error','info'];\n    const variants=['solid','outlined','dashed','filled','text','link'];\n    const host='width:auto;height:auto;display:inline-flex';\n    const btn=(p,key)=> d2.render('gabz-playground@ant-button', p, { key:key, style:host });\n    let h='<div class=\"wrap\"><div class=\"h1\">AntButton</div><div class=\"sub\">Ant Design Button + AntDesignTokens (code components)</div>';\n    h+='<div class=\"title\">color &times; variant</div><div class=\"matrix\">';\n    h+='<div class=\"cell head\"></div>'+colors.map(c=>'<div class=\"cell head\">'+c+'</div>').join('');\n    variants.forEach(vr=>{\n      h+='<div class=\"cell head rowh\">'+vr+'</div>';\n      colors.forEach(c=>{ h+='<div class=\"cell\">'+btn({color:c,variant:vr,label:'Button'}, 'm_'+vr+'_'+c)+'</div>'; });\n    });\n    h+='</div>';\n    h+='<div class=\"title\">sizes &amp; shape</div><div class=\"row\">';\n    ['small','middle','large'].forEach(s=>{ h+='<span>'+btn({color:'primary',variant:'solid',size:s,label:'Primary '+s},'sz_'+s)+'</span>'; });\n    h+='<span>'+btn({color:'primary',variant:'solid',shape:'round',label:'Round'},'sh2')+'</span>';\n    h+='<span>'+btn({color:'primary',variant:'solid',shape:'circle',glyph:'fa fa-search'},'sh3')+'</span>';\n    h+='</div>';\n    h+='<div class=\"title\">icon &amp; states</div><div class=\"row\">';\n    h+='<span>'+btn({color:'primary',variant:'solid',glyph:'fa fa-download',label:'Download'},'st_dl')+'</span>';\n    h+='<span>'+btn({color:'primary',variant:'solid',glyph:'fa fa-arrow-right',iconPosition:'end',label:'Next'},'st_nx')+'</span>';\n    h+='<span>'+btn({color:'primary',variant:'solid',loading:true,label:'Loading'},'st_ld')+'</span>';\n    h+='<span>'+btn({color:'primary',variant:'solid',disabled:true,label:'Disabled'},'st_di')+'</span>';\n    h+='<span>'+btn({color:'default',variant:'outlined',disabled:true,label:'Disabled'},'st_di2')+'</span>';\n    h+='</div>';\n\n    // ---- Theming via the AntDesignTokens shape ----\n    const purple = antTokens('#722ed1', false, 'comfortable');\n    const purpleDark = antTokens('#722ed1', true, 'comfortable');\n    const teal = antTokens('#13c2c2', false, 'compact');\n    h+='<div class=\"title\">theming &mdash; AntDesignTokens (dynamic seed &middot; light / dark / density)</div>';\n    h+='<div class=\"lbl2\">default Ant &middot; purple seed #722ed1 &middot; teal seed #13c2c2 (compact)</div>';\n    h+='<div class=\"panel light\">';\n    ['solid','outlined','filled','text'].forEach(vr=>{ h+='<span>'+btn({color:'primary',variant:vr,label:'Default'},'th_def_'+vr)+'</span>'; });\n    h+='</div>';\n    h+='<div class=\"panel light\">';\n    ['solid','outlined','filled','text'].forEach(vr=>{ h+='<span>'+btn({color:'primary',variant:vr,label:'Purple',tokens:purple},'th_pp_'+vr)+'</span>'; });\n    h+='<span>'+btn({color:'success',variant:'solid',label:'Success',tokens:purple},'th_pp_succ')+'</span>';\n    h+='</div>';\n    h+='<div class=\"panel light\">';\n    ['solid','outlined','filled','text'].forEach(vr=>{ h+='<span>'+btn({color:'primary',variant:vr,label:'Teal compact',tokens:teal},'th_tl_'+vr)+'</span>'; });\n    h+='</div>';\n    h+='<div class=\"lbl2\" style=\"margin-top:14px\">dark mode (same purple instance, darkMode:true)</div>';\n    h+='<div class=\"panel dark\">';\n    ['solid','outlined','filled','text','link'].forEach(vr=>{ h+='<span>'+btn({color:'primary',variant:vr,label:'Purple dark',tokens:purpleDark},'th_dk_'+vr)+'</span>'; });\n    h+='<span>'+btn({color:'default',variant:'outlined',label:'Default dark',tokens:purpleDark},'th_dk_def')+'</span>';\n    h+='</div>';\n    return h+'</div>';\n  }\n};"}}}}}}}},{"_id":"6a2ec08a75a8dfffb1d210a8","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-divider","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\n\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    .ant-divider{ box-sizing:border-box; font-family:var(--ff); color:var(--txt); }\n    .ant-divider-h{ display:flex; align-items:center; width:100%; margin:16px 0; }\n    .ant-divider-h.plain-line{ display:block; width:100%; border:0; border-top:var(--bw) var(--bs) var(--line); margin:16px 0; }\n    .ant-divider-h .seg{ flex:0 0 auto; border-top:var(--bw) var(--bs) var(--line); }\n    .ant-divider-h .seg.grow{ flex:1 1 auto; }\n    .ant-divider-h .seg.left{ flex:0 0 5%; }\n    .ant-divider-h .seg.right{ flex:0 0 5%; }\n    .ant-divider-h .txt{ flex:0 0 auto; padding:0 16px; white-space:nowrap; font-size:var(--fs); color:var(--txt); }\n    .ant-divider-h .txt.plain{ font-weight:400; }\n    .ant-divider-h .txt.bold{ font-weight:600; }\n    .ant-divider-v{ display:inline-block; height:0.9em; margin:0 8px; border-left:var(--bw) var(--bs) var(--line); vertical-align:middle; }\n  `,\n  render(d2){\n    const D = resolveTokens(d2.params||{});\n    const p = d2.params || {};\n    const type = p.type || 'horizontal';\n    const orientation = p.orientation || 'center';\n    let variant = p.variant || 'solid';\n    if(variant !== 'solid' && variant !== 'dashed' && variant !== 'dotted') variant = 'solid';\n    const plain = !!p.plain;\n    const label = (p.label != null && p.label !== '') ? String(p.label) : '';\n\n    const style = [\n      '--ff:'+D.fontFamily,\n      '--line:'+D.colorBorderSecondary,\n      '--bw:'+D.lineWidth+'px',\n      '--bs:'+variant,\n      '--fs:'+D.fontSize+'px',\n      '--txt:'+D.colorText\n    ].join(';');\n\n    if(type === 'vertical'){\n      return '<span class=\"ant-divider ant-divider-v\" style=\"'+style+'\"></span>';\n    }\n\n    if(!label){\n      return '<div class=\"ant-divider ant-divider-h plain-line\" style=\"'+style+'\"></div>';\n    }\n\n    let leftCls = 'seg grow';\n    let rightCls = 'seg grow';\n    if(orientation === 'left'){ leftCls = 'seg left'; rightCls = 'seg grow'; }\n    else if(orientation === 'right'){ leftCls = 'seg grow'; rightCls = 'seg right'; }\n\n    const txtCls = 'txt ' + (plain ? 'plain' : 'bold');\n    return '<div class=\"ant-divider ant-divider-h\" style=\"'+style+'\">'\n      + '<span class=\"'+leftCls+'\"></span>'\n      + '<span class=\"'+txtCls+'\">'+esc(label)+'</span>'\n      + '<span class=\"'+rightCls+'\"></span>'\n      + '</div>';\n  }\n};"}},"type":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"type"}}}},"orientation":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"orientation"}}}},"variant":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"variant"}}}},"plain":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"plain"}}}},"label":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"label"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2ec0a19421d071c9102346","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-tag","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\n\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nfunction presetPalette(D, name){\n  const map = {\n    'default':   { bg:D.colorFillTertiary, fg:D.colorText,    bc:D.colorBorder },\n    'success':   { bg:D.colorSuccessBg,    fg:D.colorSuccess, bc:'color-mix(in srgb, '+D.colorSuccess+' 40%, white)' },\n    'error':     { bg:D.colorErrorBg,      fg:D.colorError,   bc:'color-mix(in srgb, '+D.colorError+' 40%, white)' },\n    'warning':   { bg:D.colorWarningBg,    fg:D.colorWarning, bc:'color-mix(in srgb, '+D.colorWarning+' 40%, white)' },\n    'processing':{ bg:D.colorInfoBg,       fg:D.colorInfo,    bc:'color-mix(in srgb, '+D.colorInfo+' 40%, white)' },\n    'info':      { bg:D.colorInfoBg,       fg:D.colorInfo,    bc:'color-mix(in srgb, '+D.colorInfo+' 40%, white)' },\n    'primary':   { bg:D.colorPrimaryBg,    fg:D.colorPrimary, bc:'color-mix(in srgb, '+D.colorPrimary+' 40%, white)' }\n  };\n  return map[name] || null;\n}\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-tag{ box-sizing:border-box; display:inline-flex; align-items:center; gap:4px; height:22px; padding:0 7px;\n      font-family:var(--ff); font-size:var(--fs); line-height:20px; border-radius:var(--radius);\n      background:var(--bg); color:var(--fg); border:var(--bw) solid var(--bc); white-space:nowrap; vertical-align:middle; }\n    .ant-tag.no-border{ border-color:transparent; }\n    .ant-tag .ic{ display:inline-flex; align-items:center; justify-content:center; font-size:1em; line-height:0; }\n    .ant-tag .tag-close{ display:inline-flex; align-items:center; justify-content:center; cursor:pointer;\n      font-size:10px; line-height:1; opacity:0.65; margin-left:1px; }\n    .ant-tag .tag-close:hover{ opacity:1; }\n  `,\n  render(d2){\n    const D = resolveTokens(d2.params||{});\n    const p = d2.params || {};\n    const bordered = (p.bordered == null) ? true : !!p.bordered;\n    const closable = !!p.closable;\n    const glyph = p.glyph || '';\n    const label = (p.label != null) ? String(p.label) : '';\n\n    let colorRaw = p.color;\n    if(colorRaw && typeof colorRaw === 'object') colorRaw = colorRaw.rgba || colorRaw.hex || colorRaw.value || colorRaw.color || '';\n    let color = (colorRaw == null || colorRaw === '') ? 'default' : String(colorRaw).trim();\n\n    let pal = presetPalette(D, color);\n    if(!pal){\n      if(/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(color)){\n        pal = { bg:'color-mix(in srgb, '+color+' 12%, white)', fg:color, bc:'color-mix(in srgb, '+color+' 40%, white)' };\n      } else {\n        pal = presetPalette(D, 'default');\n      }\n    }\n\n    const style = [\n      '--ff:'+D.fontFamily,\n      '--fs:'+D.fontSizeSM+'px',\n      '--radius:'+D.borderRadiusSM+'px',\n      '--bw:'+D.lineWidth+'px',\n      '--bg:'+pal.bg,\n      '--fg:'+pal.fg,\n      '--bc:'+pal.bc\n    ].join(';');\n\n    const classes = ['ant-tag'];\n    if(!bordered) classes.push('no-border');\n\n    const isFa = /(^|\\s)fa[srlbd]?(\\s|-)/.test(glyph);\n    const iconHtml = glyph ? (isFa ? '<i class=\"ic '+esc(glyph)+'\"></i>' : '<span class=\"ic\">'+esc(glyph)+'</span>') : '';\n    const labelHtml = label ? '<span class=\"lbl\">'+esc(label)+'</span>' : '';\n    const closeHtml = closable ? '<span class=\"tag-close\">×</span>' : '';\n\n    return '<span class=\"'+classes.join(' ')+'\" style=\"'+style+'\">'+iconHtml+labelHtml+closeHtml+'</span>';\n  },\n  mounted(d2){\n    d2.on('.tag-close','click',(e)=>{\n      if(e && e.stopPropagation) e.stopPropagation();\n      d2.emit('onClose', {});\n    });\n  }\n};"}},"color":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"color"}}}},"bordered":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bordered"}}}},"closable":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"closable"}}}},"glyph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"glyph"}}}},"label":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"label"}}}},"onClose":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onClose"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2ec1242ae3e526cfd274ee","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-typography","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorSuccess:'#52c41a', colorWarning:'#faad14', colorError:'#ff4d4f', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorFillTertiary:'rgba(0,0,0,0.04)', borderRadiusSM:4, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: ` .ant-typo{ display:inline; } .ant-typo.block{ display:block; } `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const variant = p.variant || 'text';\n    const type = p.type || 'default';\n    const level = Number(p.level) || 1;\n    const content = p.content != null ? String(p.content) : '';\n    const typeColor = ({ secondary:D.colorTextSecondary, success:D.colorSuccess, warning:D.colorWarning, danger:D.colorError })[type] || D.colorText;\n    const color = p.disabled ? D.colorTextDisabled : (variant === 'link' ? D.colorPrimary : typeColor);\n\n    let inner = esc(content);\n    if(p.strong) inner = '<strong>' + inner + '</strong>';\n    if(p.italic) inner = '<em>' + inner + '</em>';\n    if(p.underline) inner = '<u>' + inner + '</u>';\n    if(p.del) inner = '<del>' + inner + '</del>';\n    if(p.mono) inner = '<code style=\"font-family:ui-monospace,Menlo,Consolas,monospace;background:' + D.colorFillTertiary + ';border:1px solid ' + D.colorBorderSecondary + ';border-radius:' + D.borderRadiusSM + 'px;padding:2px 5px;font-size:.9em\">' + inner + '</code>';\n    if(p.mark) inner = '<mark style=\"background:#ffe58f;padding:0 2px\">' + inner + '</mark>';\n\n    const titleSizes = { 1:38, 2:30, 3:24, 4:20, 5:16 };\n    const base = 'font-family:' + D.fontFamily + ';color:' + color + ';margin:0;';\n    let tag = 'span', extra = 'font-size:' + D.fontSize + 'px;';\n    let cls = 'ant-typo';\n    if(variant === 'title'){ tag='div'; cls+=' block'; extra='font-weight:600;line-height:1.3;font-size:' + (titleSizes[level] || 38) + 'px;'; }\n    else if(variant === 'paragraph'){ tag='div'; cls+=' block'; extra='font-size:' + D.fontSize + 'px;line-height:1.6;'; }\n    else if(variant === 'link'){ extra='font-size:' + D.fontSize + 'px;cursor:pointer;text-decoration:none;'; }\n\n    return '<' + tag + ' class=\"' + cls + '\" style=\"' + base + extra + '\">' + inner + '</' + tag + '>';\n  }\n};"}},"variant":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"variant"}}}},"level":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"level"}}}},"type":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"type"}}}},"strong":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"strong"}}}},"italic":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"italic"}}}},"underline":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"underline"}}}},"del":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"del"}}}},"mono":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"mono"}}}},"mark":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"mark"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"content":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"content"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2ec13275a8dfffb1d21175","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-spin","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\n\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    .ant-spin{ display:inline-flex; flex-direction:column; align-items:center; justify-content:center; gap:8px; font-family:var(--ff); }\n    .ant-spin .ring{ width:var(--sz); height:var(--sz); border:2px solid var(--ring-track); border-top-color:transparent; border-radius:50%; display:inline-block; animation:antspin-rot .9s linear infinite; box-sizing:border-box; }\n    .ant-spin .tip{ color:var(--accent); font-size:var(--fs); line-height:1.2; }\n    @keyframes antspin-rot{ to{ transform:rotate(360deg); } }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const spinning = p.spinning !== false;\n    if(!spinning) return '';\n\n    const size = p.size || 'default';\n    const szMap = { small:14, default:20, large:32 };\n    const sz = szMap[size] || 20;\n    const tip = p.tip != null ? String(p.tip) : '';\n    const accent = D.colorPrimary;\n\n    const style = [\n      '--ff:' + D.fontFamily,\n      '--sz:' + sz + 'px',\n      '--accent:' + accent,\n      '--ring-track:' + accent,\n      '--fs:' + D.fontSize + 'px'\n    ].join(';');\n\n    const tipHtml = tip ? '<span class=\"tip\">' + esc(tip) + '</span>' : '';\n    return '<div class=\"ant-spin\" style=\"' + style + '\"><span class=\"ring\"></span>' + tipHtml + '</div>';\n  }\n};"}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"spinning":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"spinning"}}}},"tip":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tip"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2ec1485710297996c5db57","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-badge","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-badge{ display:inline-flex; align-items:center; gap:8px; font-family:var(--ff); line-height:1; vertical-align:middle; }\n    .ant-badge .b-dot{ width:6px; height:6px; border-radius:50%; flex:0 0 auto; position:relative; }\n    .ant-badge .b-dot.pulse::after{ content:''; position:absolute; inset:0; border-radius:50%; background:inherit; opacity:.6; animation:antbadgepulse 1.2s ease-in-out infinite; }\n    @keyframes antbadgepulse{ 0%{ transform:scale(1); opacity:.6; } 70%{ transform:scale(2.6); opacity:0; } 100%{ transform:scale(2.6); opacity:0; } }\n    .ant-badge .b-text{ font-size:var(--fs); color:var(--tx); }\n    .ant-badge .b-count{ display:inline-flex; align-items:center; justify-content:center; box-sizing:border-box; height:20px; min-width:20px; padding:0 6px; border-radius:10px; background:var(--err); color:#fff; font-size:12px; font-weight:400; line-height:1; white-space:nowrap; }\n    .ant-badge .b-reddot{ width:6px; height:6px; border-radius:50%; background:var(--err); flex:0 0 auto; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const ff = D.fontFamily;\n\n    let statusRaw = p.status;\n    if(statusRaw && typeof statusRaw === 'object') statusRaw = statusRaw.value || statusRaw.color || '';\n    const status = statusRaw == null ? '' : String(statusRaw).trim();\n\n    let customColor = p.color;\n    if(customColor && typeof customColor === 'object') customColor = customColor.rgba || customColor.hex || customColor.value || customColor.color || '';\n    customColor = (customColor == null) ? '' : String(customColor).trim();\n\n    const text = p.text != null ? String(p.text) : '';\n    const baseStyle = '--ff:'+ff+';--err:'+D.colorError+';--tx:'+D.colorText+';--fs:'+D.fontSize+'px';\n\n    // status / color dot mode\n    if(status || customColor){\n      const statusMap = { success:D.colorSuccess, error:D.colorError, warning:D.colorWarning, processing:D.colorPrimary, default:D.colorTextTertiary };\n      let dotColor = customColor || statusMap[status] || D.colorTextTertiary;\n      const isPulse = !customColor && status === 'processing';\n      const dotCls = 'b-dot' + (isPulse ? ' pulse' : '');\n      const dotHtml = '<span class=\"'+dotCls+'\" style=\"background:'+esc(dotColor)+'\"></span>';\n      const textHtml = text ? '<span class=\"b-text\" style=\"margin-left:8px\">'+esc(text)+'</span>' : '';\n      return '<span class=\"ant-badge\" style=\"'+baseStyle+'\">'+dotHtml+textHtml+'</span>';\n    }\n\n    // pure red dot mode\n    if(p.dot){\n      return '<span class=\"ant-badge\" style=\"'+baseStyle+'\"><span class=\"b-reddot\"></span></span>';\n    }\n\n    // count pill mode\n    const count = Number(p.count) || 0;\n    const showZero = !!p.showZero;\n    const overflow = (p.overflowCount != null && Number(p.overflowCount) > 0) ? Number(p.overflowCount) : 99;\n    if(count === 0 && !showZero){\n      return '<span class=\"ant-badge\" style=\"'+baseStyle+'\"></span>';\n    }\n    const display = count > overflow ? (overflow + '+') : String(count);\n    return '<span class=\"ant-badge\" style=\"'+baseStyle+'\"><span class=\"b-count\">'+esc(display)+'</span></span>';\n  }\n};"}},"count":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"count"}}}},"showZero":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"showZero"}}}},"overflowCount":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"overflowCount"}}}},"dot":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"dot"}}}},"status":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"status"}}}},"color":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"color"}}}},"text":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"text"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2ec148ed769e0c58256ae8","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-avatar","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-avatar{ box-sizing:border-box; display:inline-flex; align-items:center; justify-content:center; overflow:hidden; flex:0 0 auto; vertical-align:middle; font-family:var(--ff); width:var(--sz); height:var(--sz); border-radius:var(--radius); background:var(--bg); color:#fff; font-size:var(--fs); line-height:1; white-space:nowrap; user-select:none; }\n    .ant-avatar img{ display:block; width:100%; height:100%; object-fit:cover; }\n    .ant-avatar .av-ic{ font-size:1em; line-height:0; display:inline-flex; align-items:center; justify-content:center; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n\n    const size = p.size || 'default';\n    const shape = p.shape || 'circle';\n    const sizePx = ({ small:24, large:40, 'default':32 })[size] || 32;\n    const radius = shape === 'square' ? (D.borderRadius + 'px') : '50%';\n\n    let bg = p.bg;\n    if(bg && typeof bg === 'object') bg = bg.rgba || bg.hex || bg.value || bg.color || '';\n    bg = (bg == null || bg === '') ? D.colorTextTertiary : String(bg).trim();\n\n    const fs = Math.round(sizePx * 0.45);\n    const style = '--ff:'+D.fontFamily+';--sz:'+sizePx+'px;--radius:'+radius+';--bg:'+esc(bg)+';--fs:'+fs+'px';\n\n    let src = p.src;\n    if(src && typeof src === 'object') src = src.url || src.fileUrl || src.value || '';\n    src = (src == null) ? '' : String(src).trim();\n\n    const glyph = p.glyph ? String(p.glyph) : '';\n    const label = p.label != null ? String(p.label) : '';\n\n    let inner;\n    if(src){\n      inner = '<img src=\"'+esc(src)+'\" alt=\"'+esc(label)+'\">';\n    } else if(glyph){\n      const isFa = /(^|\\s)fa[srlbd]?(\\s|-)/.test(glyph);\n      inner = isFa ? '<i class=\"av-ic '+esc(glyph)+'\"></i>' : '<span class=\"av-ic\">'+esc(glyph)+'</span>';\n    } else {\n      inner = '<span class=\"av-lbl\">'+esc(label)+'</span>';\n    }\n\n    return '<span class=\"ant-avatar\" style=\"'+style+'\">'+inner+'</span>';\n  }\n};"}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"shape":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"shape"}}}},"src":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"src"}}}},"glyph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"glyph"}}}},"label":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"label"}}}},"bg":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bg"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2ec14c9307b10171573747","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-switch","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    .ant-switch{ box-sizing:border-box; display:inline-flex; align-items:center; position:relative;\n      border:0; outline:none; cursor:pointer; user-select:none; vertical-align:middle; padding:0;\n      transition:background .2s,opacity .2s; }\n    .ant-switch.disabled{ opacity:.4; cursor:not-allowed; }\n    .ant-switch.loading{ cursor:default; }\n    .ant-switch .knob{ position:absolute; top:2px; background:#fff; border-radius:50%;\n      transition:left .2s cubic-bezier(.4,0,.2,1),right .2s cubic-bezier(.4,0,.2,1);\n      box-shadow:0 2px 4px 0 rgba(0,35,11,.2); display:flex; align-items:center; justify-content:center; }\n    .ant-switch .inner{ color:#fff; font-size:12px; line-height:1; white-space:nowrap; }\n    .ant-switch .spin{ border:2px solid currentColor; border-top-color:transparent; border-radius:50%;\n      display:inline-block; animation:antswspin .8s linear infinite; }\n    @keyframes antswspin{ to{ transform:rotate(360deg); } }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const small = (p.size || 'default') === 'small';\n    const disabled = !!p.disabled;\n    const loading = !!p.loading;\n    // Controlled: always mirror the `checked` prop so external state (e.g. store) drives the switch in BOTH directions.\n    d2.state.checked = !!p.checked;\n    const on = !!d2.state.checked;\n\n    const W = small ? 28 : 44;\n    const H = small ? 16 : 22;\n    const K = small ? 12 : 18;\n    const trackBg = on ? D.colorPrimary : 'rgba(0,0,0,0.25)';\n    const knobLeft = on ? (W - K - 2) : 2;\n    const knobColor = on ? D.colorPrimary : 'rgba(0,0,0,0.45)';\n\n    const classes = ['ant-switch'];\n    if(disabled) classes.push('disabled');\n    if(loading) classes.push('loading');\n\n    const style = 'min-width:'+W+'px;width:'+W+'px;height:'+H+'px;border-radius:'+H+'px;background:'+trackBg+';font-family:'+D.fontFamily+';';\n\n    const label = on ? p.checkedLabel : p.uncheckedLabel;\n    let innerHtml = '';\n    if(label != null && label !== ''){\n      const padOn = '0 '+(K + 4)+'px 0 0';\n      const padOff = '0 0 0 '+(K + 4)+'px';\n      innerHtml = '<span class=\"inner\" style=\"font-size:12px;padding:'+(on?padOn:padOff)+';\">'+esc(label)+'</span>';\n    }\n\n    const spinSz = small ? 8 : 12;\n    const knobInner = loading ? '<span class=\"spin\" style=\"width:'+spinSz+'px;height:'+spinSz+'px;color:'+knobColor+';\"></span>' : '';\n    const knobStyle = 'width:'+K+'px;height:'+K+'px;left:'+knobLeft+'px;';\n\n    return '<button type=\"button\" role=\"switch\" aria-checked=\"'+on+'\" class=\"'+classes.join(' ')+'\" style=\"'+style+'\"'+(disabled?' disabled':'')+'>'+innerHtml+'<span class=\"knob\" style=\"'+knobStyle+'\">'+knobInner+'</span></button>';\n  },\n  mounted(d2){\n    d2.on('.ant-switch','click',()=>{\n      const p = d2.params || {};\n      if(p.disabled || p.loading) return;\n      d2.state.checked = !d2.state.checked;\n      d2.emit('onChange', d2.state.checked);\n    });\n  }\n};"}},"checked":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"checked"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"checkedLabel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"checkedLabel"}}}},"uncheckedLabel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"uncheckedLabel"}}}},"loading":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"loading"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2ec1600e623bb3377fa0eb","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-checkbox","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    .ant-cb{ box-sizing:border-box; display:inline-flex; align-items:center; cursor:pointer; user-select:none;\n      vertical-align:middle; line-height:1; }\n    .ant-cb.disabled{ cursor:not-allowed; }\n    .ant-cb .box{ box-sizing:border-box; position:relative; width:16px; height:16px; flex:0 0 16px;\n      border-style:solid; border-width:1px; background:#fff; transition:all .2s; }\n    .ant-cb .box .check{ position:absolute; display:block; opacity:0; transition:all .15s; }\n    .ant-cb .box.on .check{ opacity:1; }\n    .ant-cb .lbl{ margin-left:8px; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const disabled = !!p.disabled;\n    if(d2.state.checked === undefined) d2.state.checked = !!p.checked;\n    if(d2.state.indeterminate === undefined) d2.state.indeterminate = !!p.indeterminate;\n    const on = !!d2.state.checked;\n    const indeterminate = !!d2.state.indeterminate && !on;\n\n    const classes = ['ant-cb'];\n    if(disabled) classes.push('disabled');\n\n    let boxBg, boxBorder, boxClass = 'box';\n    if(disabled){\n      boxBg = D.colorBgContainerDisabled;\n      boxBorder = D.colorBorder;\n    } else if(indeterminate || on){\n      boxBg = D.colorPrimary;\n      boxBorder = D.colorPrimary;\n    } else {\n      boxBg = D.colorBgContainer;\n      boxBorder = D.colorBorder;\n    }\n    if(indeterminate || on) boxClass += ' on';\n\n    const markColor = disabled ? D.colorTextDisabled : D.colorTextLightSolid;\n    let mark = '';\n    if(indeterminate){\n      mark = '<span class=\"check\" style=\"left:3px;top:6.5px;width:8px;height:2px;background:'+markColor+';\"></span>';\n    } else {\n      mark = '<span class=\"check\" style=\"left:5px;top:2px;width:4px;height:8px;border:2px solid '+markColor+';border-top:0;border-left:0;transform:rotate(45deg);\"></span>';\n    }\n\n    const boxStyle = 'background:'+boxBg+';border-color:'+boxBorder+';border-radius:'+D.borderRadiusSM+'px;';\n    const lblColor = disabled ? D.colorTextDisabled : D.colorText;\n    const lblHtml = (p.label != null && p.label !== '') ? '<span class=\"lbl\" style=\"color:'+lblColor+';font-size:'+D.fontSize+'px;\">'+esc(p.label)+'</span>' : '';\n\n    const rootStyle = 'font-family:'+D.fontFamily+';';\n    return '<label class=\"'+classes.join(' ')+'\" style=\"'+rootStyle+'\"><span class=\"'+boxClass+'\" style=\"'+boxStyle+'\">'+mark+'</span>'+lblHtml+'</label>';\n  },\n  mounted(d2){\n    d2.on('.ant-cb','click',(e)=>{\n      if(d2.param('disabled')) return;\n      if(e && e.preventDefault) e.preventDefault();\n      if(d2.state.indeterminate){ d2.state.indeterminate = false; d2.state.checked = true; }\n      else { d2.state.checked = !d2.state.checked; }\n      d2.emit('onChange', d2.state.checked);\n    });\n  }\n};"}},"checked":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"checked"}}}},"indeterminate":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"indeterminate"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"label":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"label"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2ec16a2ae3e526cfd27549","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"77jKxlVC6-FNn6r7rHQV4","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\n\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nfunction normOptions(arr){\n  if(!Array.isArray(arr)) return [];\n  return arr.map(function(it){\n    if(it && typeof it === 'object'){ return { label: it.label != null ? String(it.label) : String(it.value), value: it.value != null ? String(it.value) : String(it.label) }; }\n    return { label: String(it), value: String(it) };\n  });\n}\n\nexport default {\n  css: `\n    .ant-radio-group{ display:inline-flex; flex-wrap:wrap; align-items:center; gap:8px; font-family:var(--ff); font-size:var(--fs); color:var(--text); }\n    .ant-radio-wrap{ display:inline-flex; align-items:center; gap:8px; cursor:pointer; user-select:none; line-height:1; }\n    .ant-radio-wrap.disabled{ cursor:not-allowed; color:var(--text-disabled); }\n    .ant-radio-dot{ box-sizing:border-box; position:relative; width:16px; height:16px; border-radius:50%; border:var(--bw)px solid var(--border); background:var(--bg-container); transition:all .2s; flex:none; }\n    .ant-radio-dot::after{ content:''; position:absolute; top:50%; left:50%; width:16px; height:16px; border-radius:50%; background:var(--primary); transform:translate(-50%,-50%) scale(0); transition:transform .2s cubic-bezier(.78,.14,.15,.86); }\n    .ant-radio-wrap.checked .ant-radio-dot{ border-color:var(--primary); }\n    .ant-radio-wrap.checked .ant-radio-dot::after{ transform:translate(-50%,-50%) scale(0.5); }\n    .ant-radio-wrap:not(.disabled):hover .ant-radio-dot{ border-color:var(--primary); }\n    .ant-radio-wrap.disabled .ant-radio-dot{ background:var(--bg-disabled); border-color:var(--border); }\n    .ant-radio-wrap.disabled.checked .ant-radio-dot::after{ background:var(--text-disabled); }\n\n    .ant-radio-buttons{ display:inline-flex; }\n    .ant-radio-btn{ box-sizing:border-box; display:inline-flex; align-items:center; justify-content:center; height:var(--h); padding:0 var(--pad); font-size:var(--fs); border:var(--bw)px solid var(--border); border-left-width:0; background:var(--bg-container); color:var(--text); cursor:pointer; user-select:none; line-height:1; transition:all .2s; white-space:nowrap; position:relative; }\n    .ant-radio-btn:first-child{ border-left-width:var(--bw)px; border-radius:var(--radius)px 0 0 var(--radius)px; }\n    .ant-radio-btn:last-child{ border-radius:0 var(--radius)px var(--radius)px 0; }\n    .ant-radio-btn:only-child{ border-radius:var(--radius)px; }\n    .ant-radio-btn:not(.disabled):hover{ color:var(--primary); }\n    .ant-radio-btn.checked{ color:var(--primary); border-color:var(--primary); background:var(--bg-container); z-index:1; }\n    .ant-radio-btn.checked + .ant-radio-btn{ border-left-color:var(--primary); }\n    .ant-radio-btn.disabled{ cursor:not-allowed; color:var(--text-disabled); background:var(--bg-disabled); }\n    .ant-radio-btn.checked.disabled{ color:var(--text-disabled); border-color:var(--border); background:var(--bg-disabled); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const optionType = p.optionType || 'default';\n    const size = p.size || 'middle';\n    const groupDisabled = !!p.disabled;\n    const options = normOptions(p.options);\n\n    if(d2.state.value === undefined){ d2.state.value = (p.value != null && p.value !== '') ? String(p.value) : undefined; }\n    const selected = d2.state.value;\n\n    const SZ = ({\n      small:{ h:D.controlHeightSM, fs:D.fontSizeSM, pad:8, r:D.borderRadiusSM },\n      large:{ h:D.controlHeightLG, fs:D.fontSizeLG, pad:16, r:D.borderRadiusLG },\n      middle:{ h:D.controlHeight, fs:D.fontSize, pad:16, r:D.borderRadius },\n    })[size] || { h:D.controlHeight, fs:D.fontSize, pad:16, r:D.borderRadius };\n\n    const vars = [\n      '--ff:'+D.fontFamily, '--fs:'+SZ.fs+'px', '--h:'+SZ.h+'px', '--pad:'+SZ.pad+'px', '--radius:'+SZ.r,\n      '--bw:'+D.lineWidth, '--primary:'+D.colorPrimary, '--border:'+D.colorBorder,\n      '--text:'+D.colorText, '--text-disabled:'+D.colorTextDisabled,\n      '--bg-container:'+D.colorBgContainer, '--bg-disabled:'+D.colorBgContainerDisabled\n    ].join(';');\n\n    if(optionType === 'button'){\n      const btns = options.map(function(o){\n        const checked = String(o.value) === selected;\n        const dis = groupDisabled;\n        const cls = ['ant-radio-btn']; if(checked) cls.push('checked'); if(dis) cls.push('disabled');\n        return '<div class=\"'+cls.join(' ')+'\" data-value=\"'+esc(o.value)+'\"'+(dis?' data-disabled=\"1\"':'')+'>'+esc(o.label)+'</div>';\n      }).join('');\n      return '<div class=\"ant-radio-group\" style=\"'+vars+'\"><div class=\"ant-radio-buttons\">'+btns+'</div></div>';\n    }\n\n    const items = options.map(function(o){\n      const checked = String(o.value) === selected;\n      const dis = groupDisabled;\n      const cls = ['ant-radio-wrap']; if(checked) cls.push('checked'); if(dis) cls.push('disabled');\n      return '<label class=\"'+cls.join(' ')+'\" data-value=\"'+esc(o.value)+'\"'+(dis?' data-disabled=\"1\"':'')+'><span class=\"ant-radio-dot\"></span><span class=\"ant-radio-label\">'+esc(o.label)+'</span></label>';\n    }).join('');\n    return '<div class=\"ant-radio-group\" style=\"'+vars+'\">'+items+'</div>';\n  },\n  mounted(d2){\n    function pick(el){\n      if(!el) return;\n      if(el.getAttribute('data-disabled') === '1') return;\n      const val = el.getAttribute('data-value');\n      if(val == null) return;\n      if(d2.state.value === val) return;\n      d2.state.value = val;\n      d2.emit('onChange', val);\n    }\n    d2.on('.ant-radio-wrap','click',function(e,el){ pick(el || (e.target && e.target.closest && e.target.closest('.ant-radio-wrap'))); });\n    d2.on('.ant-radio-btn','click',function(e,el){ pick(el || (e.target && e.target.closest && e.target.closest('.ant-radio-btn'))); });\n  }\n};"}},"options":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"options"}}}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"optionType":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"optionType"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2ec1839421d071c9102461","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"1uItAWOI4tKqy-AV2DQnD","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\n\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-alert{ box-sizing:border-box; display:flex; align-items:flex-start; gap:8px; padding:8px 12px; border-radius:var(--radius)px; border:var(--bw)px solid var(--bc); background:var(--bg); font-family:var(--ff); font-size:var(--fs)px; line-height:1.5715; color:var(--text); position:relative; }\n    .ant-alert.with-desc{ padding:16px 16px 16px 24px; align-items:flex-start; }\n    .ant-alert.banner{ border-radius:0; border-width:0; display:flex; }\n    .ant-alert .ant-alert-icon{ flex:none; font-size:var(--icon-fs)px; line-height:inherit; color:var(--icon-color); margin-top:0; }\n    .ant-alert.with-desc .ant-alert-icon{ font-size:24px; margin-top:0; }\n    .ant-alert .ant-alert-content{ flex:1 1 auto; min-width:0; }\n    .ant-alert .ant-alert-message{ color:var(--text); }\n    .ant-alert.with-desc .ant-alert-message{ display:block; margin-bottom:4px; font-size:16px; font-weight:600; color:var(--text); }\n    .ant-alert .ant-alert-desc{ display:block; color:var(--text-secondary); font-size:var(--fs)px; }\n    .ant-alert .ant-alert-close{ flex:none; cursor:pointer; color:var(--text-tertiary); font-size:12px; line-height:1; background:none; border:none; padding:0; margin-left:8px; transition:color .2s; align-self:flex-start; }\n    .ant-alert .ant-alert-close:hover{ color:var(--text-secondary); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    if(d2.state.closed){ return ''; }\n\n    const type = p.type || 'info';\n    const message = p.message != null ? String(p.message) : '';\n    const description = p.description != null ? String(p.description) : '';\n    const hasDesc = description !== '';\n    const showIcon = !!p.showIcon;\n    const closable = !!p.closable;\n    const banner = !!p.banner;\n\n    const TYPE = {\n      success:{ color:D.colorSuccess, bg:D.colorSuccessBg, icon:'fa fa-check-circle' },\n      info:{ color:D.colorInfo, bg:D.colorInfoBg, icon:'fa fa-info-circle' },\n      warning:{ color:D.colorWarning, bg:D.colorWarningBg, icon:'fa fa-exclamation-circle' },\n      error:{ color:D.colorError, bg:D.colorErrorBg, icon:'fa fa-times-circle' },\n    }[type] || { color:D.colorInfo, bg:D.colorInfoBg, icon:'fa fa-info-circle' };\n\n    const borderColor = 'color-mix(in srgb, '+TYPE.color+' 30%, white)';\n    const glyph = p.glyph || TYPE.icon;\n    const isFa = /(^|\\s)fa[srlbd]?(\\s|-)/.test(glyph);\n    const iconFs = hasDesc ? 24 : 16;\n\n    const vars = [\n      '--ff:'+D.fontFamily, '--fs:'+D.fontSize, '--radius:'+(banner?0:D.borderRadius),\n      '--bw:'+(banner?0:D.lineWidth), '--bc:'+borderColor, '--bg:'+TYPE.bg,\n      '--text:'+D.colorText, '--text-secondary:'+D.colorTextSecondary, '--text-tertiary:'+D.colorTextTertiary,\n      '--icon-color:'+TYPE.color, '--icon-fs:'+iconFs\n    ].join(';');\n\n    const cls = ['ant-alert']; if(hasDesc) cls.push('with-desc'); if(banner) cls.push('banner');\n\n    const iconHtml = showIcon ? (isFa ? '<i class=\"ant-alert-icon '+esc(glyph)+'\"></i>' : '<span class=\"ant-alert-icon\">'+esc(glyph)+'</span>') : '';\n    const msgHtml = message ? '<span class=\"ant-alert-message\">'+esc(message)+'</span>' : '';\n    const descHtml = hasDesc ? '<span class=\"ant-alert-desc\">'+esc(description)+'</span>' : '';\n    const closeHtml = closable ? '<button type=\"button\" class=\"ant-alert-close\" aria-label=\"Close\"><i class=\"fa fa-times\"></i></button>' : '';\n\n    return '<div class=\"'+cls.join(' ')+'\" style=\"'+vars+'\">'+iconHtml+'<div class=\"ant-alert-content\">'+msgHtml+descHtml+'</div>'+closeHtml+'</div>';\n  },\n  mounted(d2){\n    d2.on('.ant-alert-close','click',function(e){\n      e.stopPropagation();\n      d2.state.closed = true;\n      d2.emit('onClose', {});\n    });\n  }\n};"}},"type":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"type"}}}},"message":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"message"}}}},"description":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"description"}}}},"showIcon":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"showIcon"}}}},"closable":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"closable"}}}},"banner":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"banner"}}}},"glyph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"glyph"}}}},"onClose":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onClose"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2ec1892ae3e526cfd27564","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-input","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\n\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\n\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-input-wrap{ box-sizing:border-box; display:inline-flex; align-items:center; gap:8px; width:100%;\n      height:var(--h); padding:0 11px; font-size:var(--fs); font-family:var(--ff); color:var(--fg);\n      background:var(--bg); border:var(--bw) solid var(--bc); border-radius:var(--radius);\n      transition:all .2s; cursor:text; }\n    .ant-input-wrap.borderless{ border-color:transparent; background:transparent; }\n    .ant-input-wrap:not(.disabled):hover{ border-color:var(--bc-h); }\n    .ant-input-wrap:not(.disabled):focus-within{ border-color:var(--bc-f); box-shadow:0 0 0 2px var(--ring); }\n    .ant-input-wrap.borderless:focus-within{ box-shadow:none; }\n    .ant-input-wrap.disabled{ background:var(--bg-dis); color:var(--fg-dis); cursor:not-allowed; }\n    .ant-input-wrap .ant-input-el{ flex:1 1 auto; min-width:0; border:none; outline:none; background:transparent;\n      font-size:inherit; font-family:inherit; color:inherit; line-height:1.5; padding:0; margin:0; height:100%; }\n    .ant-input-wrap.disabled .ant-input-el{ cursor:not-allowed; }\n    .ant-input-wrap .ant-input-el::placeholder{ color:var(--fg-ph); }\n    .ant-input-wrap .ic{ display:inline-flex; align-items:center; justify-content:center; font-size:1em; line-height:0; color:var(--fg-tert); flex:none; }\n    .ant-input-wrap .ant-act{ cursor:pointer; color:var(--fg-tert); transition:color .2s; flex:none; display:inline-flex; align-items:center; }\n    .ant-input-wrap .ant-act:hover{ color:var(--fg-sec); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const size = p.size || 'middle';\n    const variant = p.variant || 'outlined';\n    const status = p.status || '';\n    const disabled = !!p.disabled;\n    const allowClear = !!p.allowClear;\n    const password = !!p.password;\n\n    if(d2.state.value === undefined){ d2.state.value = p.value != null ? String(p.value) : ''; }\n    const val = d2.state.value;\n\n    const SZ = ({ small:{h:D.controlHeightSM,fs:D.fontSizeSM,r:D.borderRadiusSM}, large:{h:D.controlHeightLG,fs:D.fontSizeLG,r:D.borderRadiusLG}, middle:{h:D.controlHeight,fs:D.fontSize,r:D.borderRadius} })[size] || { h:D.controlHeight, fs:D.fontSize, r:D.borderRadius };\n\n    let bc = D.colorBorder, bch = D.colorPrimaryHover, bcf = D.colorPrimary, ring = 'rgba(5,145,255,0.1)';\n    if(status === 'error'){ bc = D.colorError; bch = D.colorError; bcf = D.colorError; ring = 'rgba(255,38,5,0.06)'; }\n    else if(status === 'warning'){ bc = D.colorWarning; bch = D.colorWarning; bcf = D.colorWarning; ring = 'rgba(255,215,5,0.1)'; }\n\n    let bg = D.colorBgContainer, bw = D.lineWidth;\n    if(variant === 'filled'){ bg = D.colorFillTertiary; if(!status) bc = 'transparent'; }\n    else if(variant === 'borderless'){ bg = 'transparent'; bw = 0; }\n\n    const style = [\n      '--h:'+SZ.h+'px', '--fs:'+SZ.fs+'px', '--radius:'+SZ.r+'px',\n      '--bw:'+bw+'px', '--bc:'+bc, '--bc-h:'+bch, '--bc-f:'+bcf, '--ring:'+ring,\n      '--bg:'+bg, '--fg:'+D.colorText, '--fg-ph:'+D.colorTextTertiary, '--fg-tert:'+D.colorTextTertiary,\n      '--fg-sec:'+D.colorTextSecondary, '--bg-dis:'+D.colorBgContainerDisabled, '--fg-dis:'+D.colorTextDisabled,\n      '--ff:'+D.fontFamily\n    ].join(';');\n\n    const cls = ['ant-input-wrap'];\n    if(variant === 'borderless') cls.push('borderless');\n    if(disabled) cls.push('disabled');\n\n    function iconHtml(glyph){\n      if(!glyph) return '';\n      if(String(glyph).trim().charAt(0) === '<') return '<span class=\"ic\">'+glyph+'</span>';\n      const isFa = /(^|\\s)fa[srlbd]?(\\s|-)/.test(glyph);\n      return isFa ? '<span class=\"ic\"><i class=\"'+esc(glyph)+'\"></i></span>' : '<span class=\"ic\">'+esc(glyph)+'</span>';\n    }\n\n    const prefix = iconHtml(p.prefixGlyph);\n\n    let suffix = '';\n    if(allowClear && val && !disabled){\n      suffix += '<span class=\"ant-act ant-clear\" title=\"clear\"><i class=\"fa fa-times-circle\"></i></span>';\n    }\n    if(password){\n      const revealed = !!d2.state.reveal;\n      suffix += '<span class=\"ant-act ant-eye\"><i class=\"fa '+(revealed?'fa-eye':'fa-eye-slash')+'\"></i></span>';\n    }\n    if(p.suffixGlyph) suffix += iconHtml(p.suffixGlyph);\n\n    const inputType = (password && !d2.state.reveal) ? 'password' : 'text';\n    const maxAttr = (p.maxLength != null && p.maxLength !== '') ? ' maxlength=\"'+esc(p.maxLength)+'\"' : '';\n\n    const inputEl = '<input class=\"ant-input-el\" type=\"'+inputType+'\" value=\"'+esc(val)+'\"'\n      + ' placeholder=\"'+esc(p.placeholder != null ? p.placeholder : '')+'\"'\n      + (disabled?' disabled':'') + maxAttr + ' />';\n\n    return '<div class=\"'+cls.join(' ')+'\" style=\"'+style+'\">'+prefix+inputEl+suffix+'</div>';\n  },\n  mounted(d2){\n    d2.on('.ant-input-el','input',(e,el)=>{\n      d2.state.value = el.value;\n      d2.emit('onChange', el.value);\n    });\n    d2.on('.ant-input-el','keydown',(e,el)=>{\n      if(e.key === 'Enter'){ d2.emit('onPressEnter', el.value); }\n    });\n    d2.on('.ant-clear','click',(e)=>{\n      e.stopPropagation();\n      d2.state.value = '';\n      d2.emit('onChange', '');\n      const inp = d2.$('.ant-input-el'); if(inp) inp.focus();\n    });\n    d2.on('.ant-eye','click',(e)=>{\n      e.stopPropagation();\n      d2.state.reveal = !d2.state.reveal;\n    });\n    d2.on('.ant-input-wrap','mousedown',(e,el)=>{\n      if(e.target.closest('.ant-act')) return;\n      if(e.target.classList && e.target.classList.contains('ant-input-el')) return;\n      e.preventDefault();\n      const inp = d2.$('.ant-input-el'); if(inp && !d2.params.disabled) inp.focus();\n    });\n  }\n};"}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"placeholder":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"placeholder"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"variant":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"variant"}}}},"status":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"status"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"allowClear":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"allowClear"}}}},"prefixGlyph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"prefixGlyph"}}}},"suffixGlyph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"suffixGlyph"}}}},"password":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"password"}}}},"maxLength":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"maxLength"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"onPressEnter":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onPressEnter"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2ec1a6ed769e0c58256b47","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-inputnumber","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\n\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\n\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nfunction clampNum(D, n){\n  if(n == null || isNaN(n)) return n;\n  if(D.min != null && D.min !== '' && !isNaN(+D.min)) n = Math.max(+D.min, n);\n  if(D.max != null && D.max !== '' && !isNaN(+D.max)) n = Math.min(+D.max, n);\n  return n;\n}\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-inum{ box-sizing:border-box; display:inline-flex; align-items:stretch; width:100%;\n      height:var(--h); font-size:var(--fs); font-family:var(--ff); color:var(--fg);\n      background:var(--bg); border:var(--bw) solid var(--bc); border-radius:var(--radius);\n      transition:all .2s; overflow:hidden; }\n    .ant-inum:not(.disabled):hover{ border-color:var(--bc-h); }\n    .ant-inum:not(.disabled):focus-within{ border-color:var(--bc-f); box-shadow:0 0 0 2px var(--ring); }\n    .ant-inum.disabled{ background:var(--bg-dis); color:var(--fg-dis); }\n    .ant-inum .ant-inum-el{ flex:1 1 auto; min-width:0; border:none; outline:none; background:transparent;\n      font-size:inherit; font-family:inherit; color:inherit; line-height:1.5; padding:0 11px; margin:0; height:100%; }\n    .ant-inum.disabled .ant-inum-el{ cursor:not-allowed; }\n    .ant-inum .ant-inum-el::placeholder{ color:var(--fg-ph); }\n    .ant-inum .ant-steps{ display:flex; flex-direction:column; width:22px; flex:none; border-left:var(--bw) solid var(--bc); }\n    .ant-inum .ant-step{ flex:1 1 50%; display:flex; align-items:center; justify-content:center;\n      cursor:pointer; color:var(--fg-tert); font-size:9px; transition:color .2s,background .2s; user-select:none; }\n    .ant-inum .ant-step:hover{ color:var(--fg-f); }\n    .ant-inum .ant-step.up{ border-bottom:var(--bw) solid var(--bc); }\n    .ant-inum.disabled .ant-step{ cursor:not-allowed; color:var(--fg-dis); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const size = p.size || 'middle';\n    const disabled = !!p.disabled;\n    const controls = (p.controls === undefined || p.controls === null) ? true : !!p.controls;\n\n    if(d2.state.value === undefined){ d2.state.value = (p.value != null && p.value !== '') ? String(p.value) : ''; }\n    const val = d2.state.value;\n\n    const SZ = ({ small:{h:D.controlHeightSM,fs:D.fontSizeSM,r:D.borderRadiusSM}, large:{h:D.controlHeightLG,fs:D.fontSizeLG,r:D.borderRadiusLG}, middle:{h:D.controlHeight,fs:D.fontSize,r:D.borderRadius} })[size] || { h:D.controlHeight, fs:D.fontSize, r:D.borderRadius };\n\n    const style = [\n      '--h:'+SZ.h+'px', '--fs:'+SZ.fs+'px', '--radius:'+SZ.r+'px',\n      '--bw:'+D.lineWidth+'px', '--bc:'+D.colorBorder, '--bc-h:'+D.colorPrimaryHover, '--bc-f:'+D.colorPrimary,\n      '--ring:rgba(5,145,255,0.1)', '--bg:'+D.colorBgContainer, '--fg:'+D.colorText,\n      '--fg-ph:'+D.colorTextTertiary, '--fg-tert:'+D.colorTextTertiary, '--fg-f:'+D.colorPrimary,\n      '--bg-dis:'+D.colorBgContainerDisabled, '--fg-dis:'+D.colorTextDisabled, '--ff:'+D.fontFamily\n    ].join(';');\n\n    const cls = ['ant-inum'];\n    if(disabled) cls.push('disabled');\n\n    const maxAttr = (p.max != null && p.max !== '') ? ' max=\"'+esc(p.max)+'\"' : '';\n    const minAttr = (p.min != null && p.min !== '') ? ' min=\"'+esc(p.min)+'\"' : '';\n    const stepAttr = ' step=\"'+esc(p.step != null && p.step !== '' ? p.step : 1)+'\"';\n\n    const inputEl = '<input class=\"ant-inum-el\" type=\"number\" value=\"'+esc(val)+'\"'\n      + ' placeholder=\"'+esc(p.placeholder != null ? p.placeholder : '')+'\"'\n      + (disabled?' disabled':'') + minAttr + maxAttr + stepAttr + ' />';\n\n    let steps = '';\n    if(controls){\n      steps = '<div class=\"ant-steps\">'\n        + '<div class=\"ant-step up\"><i class=\"fa fa-angle-up\"></i></div>'\n        + '<div class=\"ant-step down\"><i class=\"fa fa-angle-down\"></i></div>'\n        + '</div>';\n    }\n\n    return '<div class=\"'+cls.join(' ')+'\" style=\"'+style+'\">'+inputEl+steps+'</div>';\n  },\n  mounted(d2){\n    const stepBy = (dir)=>{\n      const p = d2.params || {};\n      if(p.disabled) return;\n      const step = (p.step != null && p.step !== '' && !isNaN(+p.step)) ? +p.step : 1;\n      let cur = parseFloat(d2.state.value);\n      if(isNaN(cur)) cur = (p.min != null && p.min !== '' && !isNaN(+p.min)) ? +p.min : 0;\n      let next = cur + dir * step;\n      next = clampNum(p, next);\n      next = Math.round(next * 1e10) / 1e10;\n      d2.state.value = String(next);\n      d2.emit('onChange', next);\n    };\n    d2.on('.ant-inum-el','input',(e,el)=>{\n      const p = d2.params || {};\n      d2.state.value = el.value;\n      const n = el.value === '' ? null : parseFloat(el.value);\n      d2.emit('onChange', (n != null && !isNaN(n)) ? n : null);\n    });\n    d2.on('.ant-inum-el','blur',(e,el)=>{\n      const p = d2.params || {};\n      if(el.value === '') return;\n      let n = parseFloat(el.value);\n      if(isNaN(n)) return;\n      const c = clampNum(p, n);\n      if(c !== n){ d2.state.value = String(c); d2.emit('onChange', c); }\n    });\n    d2.on('.ant-step.up','click',()=> stepBy(1));\n    d2.on('.ant-step.down','click',()=> stepBy(-1));\n  }\n};"}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"min":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"min"}}}},"max":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"max"}}}},"step":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"step"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"placeholder":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"placeholder"}}}},"controls":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"controls"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2ec1ad2ae3e526cfd2757b","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-tooltip","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorText:'rgba(0,0,0,0.88)', colorTextTertiary:'rgba(0,0,0,0.45)', borderRadius:6, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .att-wrap{ position:relative; display:inline-flex; font-family:var(--ff); }\n    .att-trigger{ display:inline-flex; align-items:center; gap:6px; cursor:default; color:var(--fg); font-size:var(--fs); line-height:1.4; border-bottom:1px dashed var(--bc); padding-bottom:1px; }\n    .att-trigger .ic{ display:inline-flex; align-items:center; font-size:1em; }\n    .att-tip{ position:fixed; left:0; top:0; z-index:1200; background:rgba(0,0,0,0.85); color:#fff; font-size:var(--fs);\n      padding:6px 8px; border-radius:var(--radius); max-width:250px; white-space:normal; line-height:1.5;\n      box-shadow:0 6px 16px 0 rgba(0,0,0,.18); opacity:0; transform:scale(.85); pointer-events:none;\n      transition:opacity .15s ease, transform .15s ease; }\n    .att-wrap.open .att-tip{ opacity:1; transform:scale(1); }\n    .att-arrow{ position:absolute; width:8px; height:8px; background:rgba(0,0,0,0.85); transform:rotate(45deg); }\n    .att-tip.p-top .att-arrow{ bottom:-3px; left:50%; margin-left:-4px; }\n    .att-tip.p-bottom .att-arrow{ top:-3px; left:50%; margin-left:-4px; }\n    .att-tip.p-left .att-arrow{ right:-3px; top:50%; margin-top:-4px; }\n    .att-tip.p-right .att-arrow{ left:-3px; top:50%; margin-top:-4px; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const placement = ['top','bottom','left','right'].includes(p.placement) ? p.placement : 'top';\n    const title = p.title != null ? String(p.title) : '';\n    const label = p.targetLabel != null ? String(p.targetLabel) : '';\n    const glyph = p.targetGlyph || '';\n    const visible = !!d2.state.visible;\n    const style = ['--ff:'+D.fontFamily,'--fs:'+D.fontSize+'px','--fg:'+D.colorText,'--bc:'+D.colorTextTertiary,'--radius:'+D.borderRadius+'px'].join(';');\n    const isFa = /(^|\\s)fa[srlbd]?(\\s|-)/.test(glyph);\n    const iconHtml = glyph ? (isFa ? '<i class=\"ic '+esc(glyph)+'\"></i>' : '<span class=\"ic\">'+esc(glyph)+'</span>') : '';\n    return '<span class=\"att-wrap'+(visible?' open':'')+'\" style=\"'+style+'\">'\n      + '<span class=\"att-trigger\">'+iconHtml+(label?'<span>'+esc(label)+'</span>':'')+'</span>'\n      + '<span class=\"att-tip p-'+placement+'\"><span class=\"att-arrow\"></span>'+esc(title)+'</span>'\n      + '</span>';\n  },\n  mounted(d2){\n    const trig = d2.param('trigger') === 'click' ? 'click' : 'hover';\n    if(trig === 'click'){\n      d2.on('.att-trigger','click',()=>{ d2.state.visible = !d2.state.visible; });\n      d2.on(document,'click',(e)=>{ if(!d2.state.visible) return; const path=(e.composedPath&&e.composedPath())||[]; if(d2.root && path.indexOf(d2.root)!==-1) return; d2.state.visible=false; });\n    } else {\n      d2.on('.att-trigger','mouseover',()=>{ d2.state.visible = true; });\n      d2.on('.att-trigger','mouseout',()=>{ d2.state.visible = false; });\n    }\n  },\n  updated(d2){\n    const tip = d2.$('.att-tip'), trig = d2.$('.att-trigger');\n    if(!tip || !trig) return;\n    if(!d2.state.visible){ return; }\n    const placement = ['top','bottom','left','right'].includes(d2.param('placement')) ? d2.param('placement') : 'top';\n    const r = trig.getBoundingClientRect();\n    const t = tip.getBoundingClientRect();\n    const gap = 8; let left, top;\n    if(placement === 'top'){ left = r.left + r.width/2 - t.width/2; top = r.top - t.height - gap; }\n    else if(placement === 'bottom'){ left = r.left + r.width/2 - t.width/2; top = r.bottom + gap; }\n    else if(placement === 'left'){ left = r.left - t.width - gap; top = r.top + r.height/2 - t.height/2; }\n    else { left = r.right + gap; top = r.top + r.height/2 - t.height/2; }\n    tip.style.left = Math.round(left) + 'px';\n    tip.style.top = Math.round(top) + 'px';\n  }\n};"}},"title":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"title"}}}},"placement":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"placement"}}}},"trigger":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"trigger"}}}},"targetLabel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"targetLabel"}}}},"targetGlyph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"targetGlyph"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2ec1bce6cc9d55d3ddb295","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-select","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\n\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\n\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nfunction normOptions(raw){\n  const out = [];\n  if(Array.isArray(raw)){\n    for(const o of raw){\n      if(o==null) continue;\n      if(typeof o === 'object'){\n        const val = (o.value!=null) ? String(o.value) : (o.label!=null ? String(o.label) : '');\n        const lab = (o.label!=null) ? String(o.label) : val;\n        out.push({ label:lab, value:val });\n      } else {\n        out.push({ label:String(o), value:String(o) });\n      }\n    }\n  }\n  return out;\n}\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-sel{ position:relative; box-sizing:border-box; display:inline-block; width:100%; font-family:var(--ff); font-size:var(--fs); }\n    .ant-sel *{ box-sizing:border-box; }\n    .ant-sel-ctl{ position:relative; display:flex; align-items:center; gap:4px; min-height:var(--h); padding:0 11px;\n      background:var(--bg); border:var(--bw)px solid var(--bc); border-radius:var(--radius); cursor:pointer;\n      transition:border-color .2s, box-shadow .2s; }\n    .ant-sel-ctl:hover{ border-color:var(--bc-h); }\n    .ant-sel.is-open .ant-sel-ctl, .ant-sel-ctl.focused{ border-color:var(--bc-f); box-shadow:0 0 0 2px var(--ring); }\n    .ant-sel.is-disabled .ant-sel-ctl{ background:var(--bg-dis); border-color:var(--bc); cursor:not-allowed; }\n    .ant-sel.is-disabled .ant-sel-content{ color:var(--c-dis); }\n    .ant-sel-content{ flex:1 1 auto; display:flex; flex-wrap:wrap; align-items:center; gap:4px; min-width:0;\n      overflow:hidden; color:var(--c-text); }\n    .ant-sel-single{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n    .ant-sel-ph{ color:var(--c-ph); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n    .ant-sel-tag{ display:inline-flex; align-items:center; gap:4px; max-width:100%; padding:0 4px 0 8px; height:24px;\n      background:var(--tag-bg); border-radius:var(--radius-sm); font-size:var(--fs); color:var(--c-text); }\n    .ant-sel-tag span{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n    .ant-sel-tag .tag-x{ cursor:pointer; font-size:10px; color:var(--c-ph); line-height:1; padding:2px; }\n    .ant-sel-tag .tag-x:hover{ color:var(--c-text); }\n    .ant-sel-search{ flex:1 1 40px; min-width:40px; border:none; outline:none; background:transparent; padding:0;\n      font-size:var(--fs); font-family:var(--ff); color:var(--c-text); height:calc(var(--h) - 4px); }\n    .ant-sel-suffix{ display:inline-flex; align-items:center; gap:6px; margin-left:6px; flex:0 0 auto; }\n    .ant-sel-caret{ color:var(--c-ph); font-size:12px; transition:transform .2s, color .2s; }\n    .ant-sel.is-open .ant-sel-caret{ transform:rotate(180deg); }\n    .ant-sel-clear{ display:none; color:var(--c-ph); font-size:12px; cursor:pointer; background:var(--bg); }\n    .ant-sel-clear:hover{ color:var(--c-text); }\n    .ant-sel.has-clear .ant-sel-ctl:hover .ant-sel-clear{ display:inline-flex; }\n    .ant-sel.has-clear .ant-sel-ctl:hover .ant-sel-caret{ display:none; }\n    .ant-sel-panel{ position:fixed; left:0; top:0; z-index:1200;\n      background:var(--bg); border:var(--bw)px solid var(--panel-bc); border-radius:var(--radius);\n      box-shadow:0 6px 16px rgba(0,0,0,.12); max-height:256px; overflow:auto; padding:4px; display:none; }\n    .ant-sel.is-open .ant-sel-panel{ display:block; }\n    .ant-sel-opt{ display:flex; align-items:center; justify-content:space-between; gap:8px; padding:5px 12px;\n      border-radius:var(--radius-sm); cursor:pointer; color:var(--c-text); white-space:nowrap; }\n    .ant-sel-opt:hover{ background:var(--opt-hover); }\n    .ant-sel-opt.selected{ background:var(--opt-sel-bg); color:var(--c-text); font-weight:600; }\n    .ant-sel-opt .opt-label{ overflow:hidden; text-overflow:ellipsis; }\n    .ant-sel-opt .opt-check{ color:var(--c-primary); font-size:12px; }\n    .ant-sel-empty{ padding:16px; text-align:center; color:var(--c-ph); font-size:var(--fs); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const opts = normOptions(p.options);\n    const mode = p.mode === 'multiple' ? 'multiple' : 'single';\n    const size = p.size || 'middle';\n    const status = p.status || '';\n    const disabled = !!p.disabled;\n    const allowClear = !!p.allowClear;\n    const showSearch = !!p.showSearch;\n    const placeholder = p.placeholder != null ? String(p.placeholder) : '';\n\n    // lazy state init from params\n    if(d2.state.open == null) d2.state.open = false;\n    if(d2.state.search == null) d2.state.search = '';\n    if(d2.state.value == null) d2.state.value = (p.value != null ? String(p.value) : '');\n\n    const open = !!d2.state.open;\n    const search = String(d2.state.search || '');\n\n    // selected values as array\n    const rawVal = String(d2.state.value || '');\n    const selectedVals = mode === 'multiple'\n      ? rawVal.split(',').map(s=>s.trim()).filter(s=>s!=='')\n      : (rawVal !== '' ? [rawVal] : []);\n    const selSet = {};\n    selectedVals.forEach(v=>{ selSet[v]=true; });\n\n    const labelOf = {};\n    opts.forEach(o=>{ labelOf[o.value]=o.label; });\n\n    // sizing\n    const SZ = ({\n      small:{ h:D.controlHeightSM, fs:D.fontSizeSM, r:D.borderRadiusSM },\n      large:{ h:D.controlHeightLG, fs:D.fontSizeLG, r:D.borderRadiusLG },\n      middle:{ h:D.controlHeight, fs:D.fontSize, r:D.borderRadius },\n    })[size] || { h:D.controlHeight, fs:D.fontSize, r:D.borderRadius };\n\n    // border colors per status / focus\n    let bc = D.colorBorder, bcH = D.colorPrimaryHover, bcF = D.colorPrimary, ring = 'rgba(5,145,255,0.1)', panelBc = D.colorBorderSecondary;\n    if(status === 'error'){ bc = D.colorError; bcH = D.colorError; bcF = D.colorError; ring = 'rgba(255,38,5,0.06)'; }\n    else if(status === 'warning'){ bc = D.colorWarning; bcH = D.colorWarning; bcF = D.colorWarning; ring = 'rgba(255,215,5,0.1)'; }\n\n    const hasValue = selectedVals.length > 0;\n    const showClear = allowClear && hasValue && !disabled;\n\n    const style = [\n      '--h:'+SZ.h+'px', '--fs:'+SZ.fs+'px', '--radius:'+SZ.r+'px', '--radius-sm:'+D.borderRadiusSM+'px',\n      '--bw:'+D.lineWidth, '--bc:'+bc, '--bc-h:'+bcH, '--bc-f:'+bcF, '--ring:'+ring,\n      '--bg:'+D.colorBgContainer, '--bg-dis:'+D.colorBgContainerDisabled,\n      '--c-text:'+D.colorText, '--c-ph:'+D.colorTextTertiary, '--c-dis:'+D.colorTextDisabled,\n      '--c-primary:'+D.colorPrimary, '--tag-bg:'+D.colorFillSecondary,\n      '--opt-hover:'+D.colorFillTertiary, '--opt-sel-bg:'+D.colorPrimaryBg, '--panel-bc:'+panelBc,\n      '--ff:'+D.fontFamily\n    ].join(';');\n\n    const rootClasses = ['ant-sel'];\n    if(open) rootClasses.push('is-open');\n    if(disabled) rootClasses.push('is-disabled');\n    if(showClear) rootClasses.push('has-clear');\n\n    // content\n    let contentHtml = '';\n    if(showSearch && open){\n      // when searching, show typed input (plus tags for multiple, plus selected label faded for single)\n      if(mode === 'multiple'){\n        contentHtml += selectedVals.map(v=>{\n          const lab = labelOf[v] != null ? labelOf[v] : v;\n          return '<span class=\"ant-sel-tag\"><span>'+esc(lab)+'</span>'+(disabled?'':'<i class=\"fa fa-times tag-x\" data-remove=\"'+esc(v)+'\"></i>')+'</span>';\n        }).join('');\n      }\n      contentHtml += '<input class=\"ant-sel-search\" type=\"text\" autocomplete=\"off\" value=\"'+esc(search)+'\" placeholder=\"'+(hasValue?'':esc(placeholder))+'\" />';\n    } else {\n      if(!hasValue){\n        contentHtml = '<span class=\"ant-sel-ph\">'+esc(placeholder)+'</span>';\n      } else if(mode === 'multiple'){\n        contentHtml = selectedVals.map(v=>{\n          const lab = labelOf[v] != null ? labelOf[v] : v;\n          return '<span class=\"ant-sel-tag\"><span>'+esc(lab)+'</span>'+(disabled?'':'<i class=\"fa fa-times tag-x\" data-remove=\"'+esc(v)+'\"></i>')+'</span>';\n        }).join('');\n      } else {\n        const v = selectedVals[0];\n        const lab = labelOf[v] != null ? labelOf[v] : v;\n        contentHtml = '<span class=\"ant-sel-single\">'+esc(lab)+'</span>';\n      }\n    }\n\n    const suffixHtml = '<span class=\"ant-sel-suffix\">'\n      + (showClear ? '<i class=\"fa fa-times-circle ant-sel-clear\" data-clear=\"1\"></i>' : '')\n      + '<i class=\"fa fa-angle-down ant-sel-caret\"></i>'\n      + '</span>';\n\n    // panel options (filtered by search)\n    const q = search.toLowerCase();\n    const filtered = (showSearch && q) ? opts.filter(o=>String(o.label).toLowerCase().indexOf(q) !== -1) : opts;\n    let panelInner = '';\n    if(filtered.length === 0){\n      panelInner = '<div class=\"ant-sel-empty\">No data</div>';\n    } else {\n      panelInner = filtered.map(o=>{\n        const sel = !!selSet[o.value];\n        return '<div class=\"ant-sel-opt'+(sel?' selected':'')+'\" data-value=\"'+esc(o.value)+'\">'\n          + '<span class=\"opt-label\">'+esc(o.label)+'</span>'\n          + (sel ? '<i class=\"fa fa-check opt-check\"></i>' : '')\n          + '</div>';\n      }).join('');\n    }\n\n    return '<div class=\"'+rootClasses.join(' ')+'\" style=\"'+style+'\">'\n      + '<div class=\"ant-sel-ctl\">'\n      +   '<div class=\"ant-sel-content\">'+contentHtml+'</div>'\n      +   suffixHtml\n      + '</div>'\n      + '<div class=\"ant-sel-panel\">'+panelInner+'</div>'\n      + '</div>';\n  },\n  mounted(d2){\n    const isMultiple = ()=> (d2.params && d2.params.mode) === 'multiple';\n    const curList = ()=>{\n      const raw = String(d2.state.value || '');\n      return isMultiple()\n        ? raw.split(',').map(s=>s.trim()).filter(s=>s!=='')\n        : (raw !== '' ? [raw] : []);\n    };\n\n    // toggle dropdown on control click (ignore clicks on clear / tag-remove)\n    d2.on('.ant-sel-ctl','click',(e)=>{\n      const p = d2.params || {};\n      if(p.disabled) return;\n      if(e.target.closest('[data-clear]')) return;\n      if(e.target.closest('[data-remove]')) return;\n      if(e.target.closest('.ant-sel-search')){ if(!d2.state.open) d2.state.open = true; return; }\n      d2.state.open = !d2.state.open;\n      if(!d2.state.open) d2.state.search = '';\n    });\n\n    // clear all\n    d2.on('[data-clear]','click',(e)=>{\n      e.stopPropagation();\n      if((d2.params||{}).disabled) return;\n      d2.state.value = '';\n      d2.state.search = '';\n      d2.emit('onChange', { value: isMultiple() ? [] : '' });\n    });\n\n    // remove a tag (multiple)\n    d2.on('[data-remove]','click',(e)=>{\n      e.stopPropagation();\n      if((d2.params||{}).disabled) return;\n      const val = e.target.closest('[data-remove]').getAttribute('data-remove');\n      const next = curList().filter(v=>v!==val);\n      d2.state.value = next.join(',');\n      d2.emit('onChange', { value: next });\n    });\n\n    // pick an option\n    d2.on('.ant-sel-opt','click',(e)=>{\n      if((d2.params||{}).disabled) return;\n      const val = e.target.closest('.ant-sel-opt').getAttribute('data-value');\n      if(isMultiple()){\n        const cur = curList();\n        const idx = cur.indexOf(val);\n        let next;\n        if(idx === -1) next = cur.concat([val]);\n        else { next = cur.slice(); next.splice(idx,1); }\n        d2.state.value = next.join(',');\n        d2.state.search = '';\n        d2.emit('onChange', { value: next });\n        // keep open\n      } else {\n        d2.state.value = val;\n        d2.state.open = false;\n        d2.state.search = '';\n        d2.emit('onChange', { value: val });\n      }\n    });\n\n    // search typing\n    d2.on('.ant-sel-search','input',(e)=>{\n      d2.state.search = e.target.value;\n      if(!d2.state.open) d2.state.open = true;\n    });\n\n    // outside click closes\n    d2.on(document,'click',(e)=>{\n      if(!d2.state.open) return;\n      const path = (e.composedPath && e.composedPath()) || [];\n      if(d2.root && (path.indexOf(d2.root) !== -1 || d2.root.contains(e.target))) return;\n      d2.state.open = false;\n      d2.state.search = '';\n    });\n  },\n  updated(d2){\n    if(!d2.state.open) return;\n    const ctl = d2.$('.ant-sel-ctl'), panel = d2.$('.ant-sel-panel');\n    if(!ctl || !panel) return;\n    const r = ctl.getBoundingClientRect();\n    panel.style.left = Math.round(r.left) + 'px';\n    panel.style.top = Math.round(r.bottom + 4) + 'px';\n    panel.style.width = Math.round(r.width) + 'px';\n  }\n};"}},"options":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"options"}}}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"mode":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"mode"}}}},"placeholder":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"placeholder"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"status":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"status"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"allowClear":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"allowClear"}}}},"showSearch":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"showSearch"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2ec1c156f919e5230ee31c","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-card","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    .ant-card{ box-sizing:border-box; background:var(--bg); border-radius:var(--radius); overflow:hidden;\n      font-family:var(--ff); color:var(--fg); position:relative; transition:box-shadow .2s,border-color .2s; }\n    .ant-card.bordered{ border:var(--bw) solid var(--bc); }\n    .ant-card.hoverable{ cursor:pointer; }\n    .ant-card.hoverable:hover{ box-shadow:0 1px 2px -2px rgba(0,0,0,.16),0 3px 6px 0 rgba(0,0,0,.12),0 5px 12px 4px rgba(0,0,0,.09); border-color:transparent; }\n    .ant-card .ac-cover{ display:block; }\n    .ant-card .ac-cover img{ display:block; width:100%; height:160px; object-fit:cover; }\n    .ant-card .ac-head{ display:flex; align-items:center; justify-content:space-between; gap:8px;\n      padding:var(--head-pad); border-bottom:var(--bw) solid var(--bcsec); min-height:var(--head-h); }\n    .ant-card .ac-title{ font-weight:600; color:var(--fg); font-size:var(--title-fs);\n      overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n    .ant-card .ac-extra{ color:var(--primary); font-size:var(--fs); white-space:nowrap; }\n    .ant-card .ac-body{ padding:var(--body-pad); color:var(--fg); font-size:var(--fs); line-height:1.5715; white-space:pre-wrap; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const small = p.size === 'small';\n    const bordered = p.bordered !== false;\n    const hoverable = !!p.hoverable;\n    const title = p.title != null ? String(p.title) : '';\n    const extra = p.extra != null ? String(p.extra) : '';\n    const content = p.content != null ? String(p.content) : '';\n    const cover = p.coverSrc ? String(p.coverSrc) : '';\n    const hasHead = !!(title || extra);\n\n    const style = ['--ff:'+D.fontFamily,'--fs:'+D.fontSize+'px','--fg:'+D.colorText,\n      '--primary:'+D.colorPrimary,'--bg:'+D.colorBgContainer,'--bc:'+D.colorBorderSecondary,\n      '--bcsec:'+D.colorBorderSecondary,'--bw:'+D.lineWidth+'px','--radius:'+D.borderRadiusLG+'px',\n      '--head-pad:'+(small?'8px 16px':'16px 24px'),'--head-h:'+(small?'38px':'48px'),\n      '--title-fs:'+(small?'14px':'16px'),'--body-pad:'+(small?'12px 16px':'24px')].join(';');\n\n    const classes = ['ant-card'];\n    if(bordered) classes.push('bordered');\n    if(hoverable) classes.push('hoverable');\n\n    const coverHtml = cover ? '<div class=\"ac-cover\"><img src=\"'+esc(cover)+'\" alt=\"\"/></div>' : '';\n    const headHtml = hasHead\n      ? '<div class=\"ac-head\"><div class=\"ac-title\">'+esc(title)+'</div>'+(extra?'<div class=\"ac-extra\">'+esc(extra)+'</div>':'')+'</div>'\n      : '';\n    let body;\n    if(Array.isArray(p.slots) && p.slots.length){\n      body = p.slots.map((s,i)=> d2.render(s.type||s.component, s.props||s.params||{}, {key:s.key||('cs'+i), style:'height:auto;display:block'})).join('');\n    } else {\n      body = esc(content);\n    }\n    const bodyHtml = '<div class=\"ac-body\">'+body+'</div>';\n\n    return '<div class=\"'+classes.join(' ')+'\" style=\"'+style+'\">'+coverHtml+headHtml+bodyHtml+'</div>';\n  }\n};"}},"title":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"title"}}}},"extra":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"extra"}}}},"content":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"content"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"bordered":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bordered"}}}},"hoverable":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"hoverable"}}}},"coverSrc":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"coverSrc"}}}},"slots":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"slots"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efcc62ae3e526cfd2b109","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-components-lab","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const RADIO = 'gabz-playground@77jKxlVC6-FNn6r7rHQV4';\nconst ALERT = 'gabz-playground@1uItAWOI4tKqy-AV2DQnD';\n\nexport default {\n  css: `\n    .gal{ padding:28px 32px; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif; background:#fff; color:rgba(0,0,0,.88); box-sizing:border-box; }\n    .gal h1{ font-size:22px; font-weight:600; margin:0 0 2px; }\n    .gal .sub{ font-size:13px; color:rgba(0,0,0,.45); margin:0 0 8px; }\n    .sec{ margin:30px 0 0; }\n    .sec > .t{ font-size:12px; font-weight:600; text-transform:uppercase; letter-spacing:.05em; color:rgba(0,0,0,.45); margin:0 0 14px; padding-bottom:6px; border-bottom:1px solid #f0f0f0; }\n    .row{ display:flex; flex-wrap:wrap; gap:16px; align-items:center; }\n    .row.top{ align-items:flex-start; }\n    .cell{ display:inline-flex; }\n    .w240{ width:240px; } .w300{ width:300px; } .w420{ width:420px; } .w280{ width:280px; }\n    .stk{ display:flex; flex-direction:column; gap:10px; }\n  `,\n  render(d2){\n    const I = (id,p,key)=> d2.render(id, p, { key:key, style:'width:auto;height:auto;display:inline-flex' });\n    const B = (id,p,key,w)=> '<div class=\"'+(w||'w240')+'\">'+d2.render(id, p, { key:key, style:'width:100%;height:auto;display:block' })+'</div>';\n    let h = '<div class=\"gal\"><h1>Ant Design — Tier 1</h1><div class=\"sub\">15 code components, all themed via AntDesignTokens</div>';\n\n    // Typography\n    h += '<div class=\"sec\"><div class=\"t\">Typography</div><div class=\"row top\">';\n    h += I('gabz-playground@ant-typography',{variant:'title',level:2,content:'Title h2'},'ty1');\n    h += I('gabz-playground@ant-typography',{variant:'title',level:4,content:'Title h4'},'ty2');\n    h += I('gabz-playground@ant-typography',{variant:'text',content:'Default text'},'ty3');\n    h += I('gabz-playground@ant-typography',{variant:'text',type:'secondary',content:'Secondary'},'ty4');\n    h += I('gabz-playground@ant-typography',{variant:'text',type:'success',content:'Success'},'ty5');\n    h += I('gabz-playground@ant-typography',{variant:'text',type:'danger',content:'Danger'},'ty6');\n    h += I('gabz-playground@ant-typography',{variant:'text',strong:true,content:'Strong'},'ty7');\n    h += I('gabz-playground@ant-typography',{variant:'text',italic:true,content:'Italic'},'ty8');\n    h += I('gabz-playground@ant-typography',{variant:'text',code:true,content:'code()'},'ty9');\n    h += I('gabz-playground@ant-typography',{variant:'text',mark:true,content:'marked'},'ty10');\n    h += I('gabz-playground@ant-typography',{variant:'link',content:'A link'},'ty11');\n    h += '</div></div>';\n\n    // Divider\n    h += '<div class=\"sec\"><div class=\"t\">Divider</div>';\n    h += '<div class=\"w420\">'+d2.render('gabz-playground@ant-divider',{label:'Center'},{key:'dv1',style:'width:100%;height:auto;display:block'})+'</div>';\n    h += '<div class=\"w420\">'+d2.render('gabz-playground@ant-divider',{label:'Left',orientation:'left',variant:'dashed'},{key:'dv2',style:'width:100%;height:auto;display:block'})+'</div>';\n    h += '<div class=\"row\">'+I('gabz-playground@ant-typography',{content:'Text'},'dvt1')+I('gabz-playground@ant-divider',{type:'vertical'},'dv3')+I('gabz-playground@ant-typography',{content:'Text'},'dvt2')+I('gabz-playground@ant-divider',{type:'vertical'},'dv4')+I('gabz-playground@ant-typography',{variant:'link',content:'Link'},'dvt3')+'</div>';\n    h += '</div>';\n\n    // Tag\n    h += '<div class=\"sec\"><div class=\"t\">Tag</div><div class=\"row\">';\n    ['default','success','processing','error','warning'].forEach((c,i)=>{ h += I('gabz-playground@ant-tag',{color:c,label:c},'tg'+i); });\n    h += I('gabz-playground@ant-tag',{color:'#722ed1',label:'custom'},'tgc');\n    h += I('gabz-playground@ant-tag',{color:'success',label:'icon',glyph:'fa fa-check'},'tgi');\n    h += I('gabz-playground@ant-tag',{color:'default',label:'closable',closable:true},'tgx');\n    h += '</div></div>';\n\n    // Badge\n    h += '<div class=\"sec\"><div class=\"t\">Badge</div><div class=\"row\">';\n    h += I('gabz-playground@ant-badge',{count:5},'bd1');\n    h += I('gabz-playground@ant-badge',{count:128,overflowCount:99},'bd2');\n    h += I('gabz-playground@ant-badge',{dot:true},'bd3');\n    ['success','processing','error','warning','default'].forEach((s,i)=>{ h += I('gabz-playground@ant-badge',{status:s,text:s},'bds'+i); });\n    h += '</div></div>';\n\n    // Avatar\n    h += '<div class=\"sec\"><div class=\"t\">Avatar</div><div class=\"row\">';\n    h += I('gabz-playground@ant-avatar',{size:'small',label:'S'},'av1');\n    h += I('gabz-playground@ant-avatar',{size:'default',label:'U'},'av2');\n    h += I('gabz-playground@ant-avatar',{size:'large',glyph:'fa fa-user'},'av3');\n    h += I('gabz-playground@ant-avatar',{shape:'square',glyph:'fa fa-user'},'av4');\n    h += I('gabz-playground@ant-avatar',{src:'https://i.pravatar.cc/80',size:'large'},'av5');\n    h += I('gabz-playground@ant-avatar',{label:'AD',bg:'#722ed1'},'av6');\n    h += '</div></div>';\n\n    // Spin\n    h += '<div class=\"sec\"><div class=\"t\">Spin</div><div class=\"row\">';\n    h += I('gabz-playground@ant-spin',{size:'small'},'sp1');\n    h += I('gabz-playground@ant-spin',{size:'default'},'sp2');\n    h += I('gabz-playground@ant-spin',{size:'large'},'sp3');\n    h += '</div></div>';\n\n    // Switch\n    h += '<div class=\"sec\"><div class=\"t\">Switch</div><div class=\"row\">';\n    h += I('gabz-playground@ant-switch',{checked:true},'sw1');\n    h += I('gabz-playground@ant-switch',{checked:false},'sw2');\n    h += I('gabz-playground@ant-switch',{checked:true,size:'small'},'sw3');\n    h += I('gabz-playground@ant-switch',{checked:true,checkedLabel:'ON',uncheckedLabel:'OFF'},'sw4');\n    h += I('gabz-playground@ant-switch',{checked:true,loading:true},'sw5');\n    h += I('gabz-playground@ant-switch',{checked:false,disabled:true},'sw6');\n    h += '</div></div>';\n\n    // Checkbox\n    h += '<div class=\"sec\"><div class=\"t\">Checkbox</div><div class=\"row\">';\n    h += I('gabz-playground@ant-checkbox',{label:'Unchecked'},'cb1');\n    h += I('gabz-playground@ant-checkbox',{label:'Checked',checked:true},'cb2');\n    h += I('gabz-playground@ant-checkbox',{label:'Indeterminate',indeterminate:true},'cb3');\n    h += I('gabz-playground@ant-checkbox',{label:'Disabled',disabled:true},'cb4');\n    h += '</div></div>';\n\n    // Radio\n    h += '<div class=\"sec\"><div class=\"t\">Radio</div><div class=\"row top\">';\n    h += I(RADIO,{options:['Apple','Pear','Orange'],value:'Apple'},'rd1');\n    h += I(RADIO,{options:['Daily','Weekly','Monthly'],value:'Weekly',optionType:'button'},'rd2');\n    h += '</div></div>';\n\n    // Input\n    h += '<div class=\"sec\"><div class=\"t\">Input</div><div class=\"row top\">';\n    h += B('gabz-playground@ant-input',{placeholder:'Basic'},'in1');\n    h += B('gabz-playground@ant-input',{placeholder:'Filled',variant:'filled'},'in2');\n    h += B('gabz-playground@ant-input',{placeholder:'Search',prefixGlyph:'fa fa-search',allowClear:true,value:'hello'},'in3');\n    h += B('gabz-playground@ant-input',{placeholder:'Password',password:true,value:'secret'},'in4');\n    h += B('gabz-playground@ant-input',{placeholder:'Error',status:'error',value:'bad'},'in5');\n    h += B('gabz-playground@ant-inputnumber',{value:3,min:0,max:10},'in6');\n    h += '</div></div>';\n\n    // Select\n    h += '<div class=\"sec\"><div class=\"t\">Select</div><div class=\"row top\">';\n    h += B('gabz-playground@ant-select',{options:['Beijing','Shanghai','Guangzhou'],value:'Shanghai',placeholder:'Pick a city'},'se1');\n    h += B('gabz-playground@ant-select',{options:['Red','Green','Blue','Purple'],mode:'multiple',value:'Red,Blue',placeholder:'Multiple'},'se2');\n    h += B('gabz-playground@ant-select',{options:['Apple','Banana','Cherry','Date'],showSearch:true,placeholder:'Searchable'},'se3');\n    h += '</div></div>';\n\n    // Alert\n    h += '<div class=\"sec\"><div class=\"t\">Alert</div><div class=\"stk\">';\n    h += B(ALERT,{type:'success',message:'Success',showIcon:true},'al1','w420');\n    h += B(ALERT,{type:'info',message:'Informational notes',description:'Additional description with more detail.',showIcon:true},'al2','w420');\n    h += B(ALERT,{type:'warning',message:'Warning',showIcon:true,closable:true},'al3','w420');\n    h += B(ALERT,{type:'error',message:'Error',showIcon:true},'al4','w420');\n    h += '</div></div>';\n\n    // Tooltip + Card\n    h += '<div class=\"sec\"><div class=\"t\">Tooltip &amp; Card</div><div class=\"row top\">';\n    h += I('gabz-playground@ant-tooltip',{title:'Helpful hint shown on hover',targetLabel:'Hover me',placement:'top'},'tt1');\n    h += '<div class=\"w280\">'+d2.render('gabz-playground@ant-card',{title:'Card title',extra:'More',content:'This is the card body content. Code components take body text as a param.'},{key:'cd1',style:'width:100%;height:auto;display:block'})+'</div>';\n    h += '<div class=\"w280\">'+d2.render('gabz-playground@ant-card',{title:'Small + hoverable',size:'small',hoverable:true,content:'Compact card with hover shadow.'},{key:'cd2',style:'width:100%;height:auto;display:block'})+'</div>';\n    h += '</div></div>';\n\n    return h + '</div>';\n  }\n};"}}}}}}}},{"_id":"6a2efd65ccdaee8ef640b144","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-modal","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorErrorHover:'#ff7875', colorErrorActive:'#d9363e', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .am-mask{ position:fixed; inset:0; background:rgba(0,0,0,.45); z-index:1000; display:flex; justify-content:center; }\n    .am-mask.top{ align-items:flex-start; padding-top:100px; }\n    .am-mask.centered{ align-items:center; }\n    .am-dialog{ box-sizing:border-box; background:var(--bg); border-radius:var(--radius); box-shadow:0 6px 16px 0 rgba(0,0,0,.08),0 3px 6px -4px rgba(0,0,0,.12),0 9px 28px 8px rgba(0,0,0,.05); max-width:90vw; max-height:calc(100vh - 120px); display:flex; flex-direction:column; font-family:var(--ff); overflow:hidden; }\n    .am-head{ position:relative; padding:16px 24px 0 24px; }\n    .am-title{ font-size:16px; font-weight:600; color:var(--text); line-height:1.5; padding-right:24px; word-wrap:break-word; }\n    .am-close{ position:absolute; top:16px; right:16px; width:22px; height:22px; display:inline-flex; align-items:center; justify-content:center; border:none; background:transparent; color:var(--text3); cursor:pointer; border-radius:4px; font-size:16px; line-height:1; transition:color .2s,background .2s; }\n    .am-close:hover{ color:var(--text); background:var(--fill3); }\n    .am-body{ padding:8px 24px 24px 24px; color:var(--text); font-size:14px; line-height:1.5715; word-wrap:break-word; overflow:auto; }\n    .am-foot{ padding:0 24px 16px 24px; display:flex; justify-content:flex-end; gap:8px; }\n    .am-btn{ box-sizing:border-box; display:inline-flex; align-items:center; justify-content:center; gap:8px; height:32px; padding:0 15px; font-size:14px; font-family:var(--ff); font-weight:400; line-height:1; border-radius:var(--bradius); cursor:pointer; user-select:none; outline:none; transition:all .2s cubic-bezier(.4,0,.2,1); }\n    .am-btn-default{ background:var(--bg); color:var(--text); border:1px solid var(--border); }\n    .am-btn-default:hover{ color:var(--primaryH); border-color:var(--primaryH); }\n    .am-btn-primary{ background:var(--primary); color:#fff; border:1px solid var(--primary); }\n    .am-btn-primary:hover{ background:var(--primaryH); border-color:var(--primaryH); }\n    .am-btn-danger{ background:var(--error); color:#fff; border:1px solid var(--error); }\n    .am-btn-danger:hover{ background:var(--errorH); border-color:var(--errorH); }\n    .am-btn.is-loading{ cursor:default; pointer-events:none; opacity:.85; }\n    .am-spin{ width:14px; height:14px; border:2px solid currentColor; border-top-color:transparent; border-radius:50%; display:inline-block; animation:amspin .8s linear infinite; }\n    @keyframes amspin{ to{ transform:rotate(360deg); } }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    let _open = p.open;\n    if(p.openStore && p.openKey){ try{ _open = !!d2.store(p.openStore).get(p.openKey); }catch(e){ _open = !!p.open; } }\n    if(!_open) return '';\n    const D = resolveTokens(p);\n    const width = (typeof p.width === 'number' && p.width > 0) ? p.width : 520;\n    const centered = !!p.centered;\n    const closable = p.closable !== false;\n    const confirmLoading = !!p.confirmLoading;\n    const okDanger = !!p.okDanger;\n    const title = p.title != null ? String(p.title) : '';\n    const content = p.content != null ? String(p.content) : '';\n    const okText = p.okText != null && p.okText !== '' ? String(p.okText) : 'OK';\n    const cancelText = p.cancelText != null && p.cancelText !== '' ? String(p.cancelText) : 'Cancel';\n\n    const style = [\n      '--bg:'+D.colorBgContainer, '--text:'+D.colorText, '--text3:'+D.colorTextTertiary,\n      '--border:'+D.colorBorder, '--primary:'+D.colorPrimary, '--primaryH:'+D.colorPrimaryHover,\n      '--error:'+D.colorError, '--errorH:'+D.colorErrorHover,\n      '--fill3:'+D.colorFillTertiary, '--radius:'+D.borderRadiusLG+'px', '--bradius:'+D.borderRadius+'px',\n      '--ff:'+D.fontFamily\n    ].join(';');\n\n    const closeHtml = closable ? '<button type=\"button\" class=\"am-close\" data-act=\"cancel\" aria-label=\"Close\"><i class=\"fa fa-times\"></i></button>' : '';\n    const titleHtml = title ? '<div class=\"am-title\">'+esc(title)+'</div>' : '';\n    const headHtml = (titleHtml || closeHtml) ? '<div class=\"am-head\">'+titleHtml+closeHtml+'</div>' : '';\n    let bodyInner;\n    if(Array.isArray(p.slots) && p.slots.length){\n      bodyInner = p.slots.map((s,i)=> d2.render(s.type||s.component, s.props||s.params||{}, {key:s.key||('ms'+i), style:'height:auto;display:block'})).join('');\n    } else {\n      bodyInner = esc(content);\n    }\n    const bodyHtml = '<div class=\"am-body\">'+bodyInner+'</div>';\n\n    const showFoot = !(Array.isArray(p.slots) && p.slots.length);\n    let footHtml = '';\n    if(showFoot){\n      const okClasses = 'am-btn ' + (okDanger ? 'am-btn-danger' : 'am-btn-primary') + (confirmLoading ? ' is-loading' : '');\n      const okInner = (confirmLoading ? '<span class=\"am-spin\"></span>' : '') + '<span>'+esc(okText)+'</span>';\n      footHtml = '<div class=\"am-foot\">'\n        + '<button type=\"button\" class=\"am-btn am-btn-default\" data-act=\"cancel\">'+esc(cancelText)+'</button>'\n        + '<button type=\"button\" class=\"'+okClasses+'\" data-act=\"ok\"'+(confirmLoading?' disabled':'')+'>'+okInner+'</button>'\n        + '</div>';\n    }\n\n    const dialog = '<div class=\"am-dialog\" data-role=\"dialog\" style=\"width:'+width+'px\">'+headHtml+bodyHtml+footHtml+'</div>';\n    const maskClass = 'am-mask ' + (centered ? 'centered' : 'top');\n    return '<div class=\"'+maskClass+'\" data-act=\"mask\" style=\"'+style+'\">'+dialog+'</div>';\n  },\n  mounted(d2){\n    d2.on('.am-dialog','click',(e)=>{ e.stopPropagation(); });\n    d2.on('[data-act=\"mask\"]','click',(e)=>{\n      if(e.target && e.target.closest && e.target.closest('.am-dialog')) return;\n      d2.emit('onCancel', {});\n    });\n    d2.on('[data-act=\"cancel\"]','click',(e)=>{\n      e.stopPropagation();\n      d2.emit('onCancel', {});\n    });\n    d2.on('[data-act=\"ok\"]','click',(e)=>{\n      e.stopPropagation();\n      const p = d2.params || {};\n      if(p.confirmLoading) return;\n      d2.emit('onOk', {});\n    });\n  }\n};"}},"open":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"open"}}}},"openStore":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"openStore"}}}},"openKey":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"openKey"}}}},"title":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"title"}}}},"content":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"content"}}}},"okText":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"okText"}}}},"cancelText":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cancelText"}}}},"okDanger":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"okDanger"}}}},"width":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"width"}}}},"centered":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"centered"}}}},"closable":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"closable"}}}},"confirmLoading":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"confirmLoading"}}}},"slots":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"slots"}}}},"onOk":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onOk"}}}},"onCancel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onCancel"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efd78ccdaee8ef640b154","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-tabs","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction asArr(x){ if(Array.isArray(x))return x; if(x==null)return []; return [x]; }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-tabs{ box-sizing:border-box; font-family:var(--ff); font-size:var(--fs); color:var(--c-text); width:100%; }\n    .ant-tabs *{ box-sizing:border-box; }\n    .ant-tabs-bar{ display:flex; align-items:flex-end; gap:var(--gap); }\n    .ant-tabs-bar.centered{ justify-content:center; }\n    .ant-tabs.line .ant-tabs-bar{ border-bottom:var(--bw) solid var(--c-border2); }\n    .ant-tabs-tab{ display:inline-flex; align-items:center; gap:8px; cursor:pointer; user-select:none;\n      transition:color .2s, background .2s, border-color .2s; white-space:nowrap; line-height:1; }\n    .ant-tabs.line .ant-tabs-tab{ padding:var(--tabpad); color:var(--c-text); position:relative; }\n    .ant-tabs.line .ant-tabs-tab:hover{ color:var(--c-primary-h); }\n    .ant-tabs.line .ant-tabs-tab.active{ color:var(--c-primary); }\n    .ant-tabs.line .ant-tabs-tab.active::after{ content:''; position:absolute; left:0; right:0; bottom:calc(-1 * var(--bw));\n      height:2px; background:var(--c-primary); }\n    .ant-tabs.card .ant-tabs-bar{ gap:2px; }\n    .ant-tabs.card .ant-tabs-tab{ padding:var(--tabpad); border:var(--bw) solid var(--c-border2);\n      border-radius:var(--radius) var(--radius) 0 0; background:var(--c-fill3); color:var(--c-text);\n      margin-bottom:calc(-1 * var(--bw)); }\n    .ant-tabs.card .ant-tabs-tab:hover{ color:var(--c-primary-h); }\n    .ant-tabs.card .ant-tabs-tab.active{ background:var(--c-bg); border-bottom-color:var(--c-bg); color:var(--c-primary); }\n    .ant-tabs.card{ }\n    .ant-tabs.card .ant-tabs-bar{ border-bottom:var(--bw) solid var(--c-border2); }\n    .ant-tabs-tab.disabled{ color:var(--c-disabled); cursor:not-allowed; }\n    .ant-tabs-tab.disabled:hover{ color:var(--c-disabled); }\n    .ant-tabs-tab .ic{ display:inline-flex; align-items:center; font-size:1em; }\n    .ant-tabs-panel{ padding:16px 0; color:var(--c-text); white-space:pre-wrap; line-height:1.5715; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const items = asArr(p.items).filter(it=>it && typeof it==='object');\n    const type = p.type || 'line';\n    const size = p.size || 'middle';\n    const centered = !!p.centered;\n\n    if(d2.state.activeKey == null){\n      const ak = (p.activeKey!=null && p.activeKey!=='') ? String(p.activeKey) : (items.length ? String(items[0].key!=null?items[0].key:0) : '');\n      d2.state.activeKey = ak;\n    }\n    let activeKey = String(d2.state.activeKey);\n    const keys = items.map((it,i)=> String(it.key!=null?it.key:i));\n    if(keys.length && keys.indexOf(activeKey)===-1){ activeKey = keys[0]; d2.state.activeKey = activeKey; }\n\n    const fs = size==='large'?D.fontSizeLG:(size==='small'?D.fontSizeSM:D.fontSize);\n    const tabPad = size==='large'?'12px 0':(size==='small'?'6px 0':'9px 0');\n    const cardPad = size==='large'?'10px 16px':(size==='small'?'5px 12px':'7px 16px');\n    const radius = size==='large'?D.borderRadiusLG:(size==='small'?D.borderRadiusSM:D.borderRadius);\n\n    const style = [\n      '--ff:'+D.fontFamily, '--fs:'+fs+'px', '--bw:'+D.lineWidth+'px',\n      '--c-text:'+D.colorText, '--c-primary:'+D.colorPrimary, '--c-primary-h:'+D.colorPrimaryHover,\n      '--c-border2:'+D.colorBorderSecondary, '--c-bg:'+D.colorBgContainer, '--c-fill3:'+D.colorFillTertiary,\n      '--c-disabled:'+D.colorTextDisabled, '--radius:'+radius+'px',\n      '--gap:'+(type==='card'?'2px':'24px'),\n      '--tabpad:'+(type==='card'?cardPad:tabPad)\n    ].join(';');\n\n    const tabsHtml = items.map((it,i)=>{\n      const k = String(it.key!=null?it.key:i);\n      const disabled = !!it.disabled;\n      const cls = ['ant-tabs-tab']; if(k===activeKey) cls.push('active'); if(disabled) cls.push('disabled');\n      const glyph = it.glyph || '';\n      const isFa = /(^|\\s)fa[srlbd]?(\\s|-)/.test(glyph);\n      const ic = glyph ? (isFa ? '<i class=\"ic '+esc(glyph)+'\"></i>' : '<span class=\"ic\">'+esc(glyph)+'</span>') : '';\n      const lbl = it.label!=null ? esc(it.label) : '';\n      return '<div class=\"'+cls.join(' ')+'\" data-key=\"'+esc(k)+'\">'+ic+'<span>'+lbl+'</span></div>';\n    }).join('');\n\n    let panel = '';\n    const act = items.find((it,i)=> String(it.key!=null?it.key:i)===activeKey);\n    if(act){\n      let inner;\n      if(Array.isArray(act.slots) && act.slots.length){\n        inner = act.slots.map((s,i)=> d2.render(s.type||s.component, s.props||s.params||{}, {key:s.key||('ts'+i), style:'height:auto;display:block'})).join('');\n      } else {\n        inner = esc(act.content!=null?act.content:'');\n      }\n      panel = '<div class=\"ant-tabs-panel\">'+inner+'</div>';\n    }\n\n    const barCls = ['ant-tabs-bar']; if(centered) barCls.push('centered');\n    return '<div class=\"ant-tabs '+esc(type)+'\" style=\"'+style+'\"><div class=\"'+barCls.join(' ')+'\">'+tabsHtml+'</div>'+panel+'</div>';\n  },\n  mounted(d2){\n    d2.on('.ant-tabs-tab','click',(e,el)=>{\n      if(el.classList.contains('disabled')) return;\n      const k = el.getAttribute('data-key');\n      if(k==null) return;\n      d2.state.activeKey = k;\n      d2.emit('onChange', k);\n    });\n  }\n};"}},"items":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"items"}}}},"activeKey":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"activeKey"}}}},"type":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"type"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"centered":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"centered"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efd7c75a8dfffb1d251d2","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-drawer","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ad-mask{ position:fixed; inset:0; background:rgba(0,0,0,.45); z-index:1000; }\n    .ad-panel{ position:fixed; box-sizing:border-box; background:var(--bg); display:flex; flex-direction:column; font-family:var(--ff); box-shadow:0 6px 16px 0 rgba(0,0,0,.08),0 3px 6px -4px rgba(0,0,0,.12),0 9px 28px 8px rgba(0,0,0,.05); transition:transform .3s cubic-bezier(.4,0,.2,1); }\n    .ad-panel.right{ top:0; right:0; height:100%; transform:translateX(0); }\n    .ad-panel.left{ top:0; left:0; height:100%; transform:translateX(0); }\n    .ad-panel.top{ top:0; left:0; width:100%; transform:translateY(0); }\n    .ad-panel.bottom{ bottom:0; left:0; width:100%; transform:translateY(0); }\n    .ad-head{ display:flex; align-items:center; gap:12px; padding:16px 24px; border-bottom:1px solid var(--border2); flex:0 0 auto; }\n    .ad-title{ font-size:16px; font-weight:600; color:var(--text); line-height:1.5; flex:1 1 auto; word-wrap:break-word; }\n    .ad-close{ width:22px; height:22px; display:inline-flex; align-items:center; justify-content:center; border:none; background:transparent; color:var(--text3); cursor:pointer; border-radius:4px; font-size:16px; line-height:1; transition:color .2s,background .2s; flex:0 0 auto; }\n    .ad-close:hover{ color:var(--text); background:var(--fill3); }\n    .ad-body{ padding:24px; color:var(--text); font-size:14px; line-height:1.5715; word-wrap:break-word; overflow:auto; flex:1 1 auto; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    let _open = p.open;\n    if(p.openStore && p.openKey){ try{ _open = !!d2.store(p.openStore).get(p.openKey); }catch(e){ _open = !!p.open; } }\n    if(!_open) return '';\n    const D = resolveTokens(p);\n    const allowed = ['top','right','bottom','left'];\n    const placement = allowed.indexOf(p.placement) >= 0 ? p.placement : 'right';\n    const width = (typeof p.width === 'number' && p.width > 0) ? p.width : 378;\n    const height = (typeof p.height === 'number' && p.height > 0) ? p.height : 378;\n    const closable = p.closable !== false;\n    const title = p.title != null ? String(p.title) : '';\n    const content = p.content != null ? String(p.content) : '';\n\n    const style = [\n      '--bg:'+D.colorBgContainer, '--text:'+D.colorText, '--text3:'+D.colorTextTertiary,\n      '--border2:'+D.colorBorderSecondary, '--fill3:'+D.colorFillTertiary, '--ff:'+D.fontFamily\n    ].join(';');\n\n    let panelSize = '';\n    if(placement === 'right' || placement === 'left') panelSize = 'width:'+Math.min(width, window.innerWidth || width)+'px;max-width:100vw';\n    else panelSize = 'height:'+Math.min(height, window.innerHeight || height)+'px;max-height:100vh';\n\n    const closeHtml = closable ? '<button type=\"button\" class=\"ad-close\" data-act=\"close\" aria-label=\"Close\"><i class=\"fa fa-times\"></i></button>' : '';\n    const titleHtml = '<div class=\"ad-title\">'+esc(title)+'</div>';\n    const headHtml = '<div class=\"ad-head\">'+closeHtml+titleHtml+'</div>';\n    let bodyInner;\n    if(Array.isArray(p.slots) && p.slots.length){\n      bodyInner = p.slots.map((s,i)=> d2.render(s.type||s.component, s.props||s.params||{}, {key:s.key||('ds'+i), style:'height:auto;display:block'})).join('');\n    } else {\n      bodyInner = esc(content);\n    }\n    const bodyHtml = '<div class=\"ad-body\">'+bodyInner+'</div>';\n\n    const panel = '<div class=\"ad-panel '+placement+'\" data-role=\"panel\" style=\"'+panelSize+'\">'+headHtml+bodyHtml+'</div>';\n    return '<div class=\"ad-mask\" data-act=\"mask\" style=\"'+style+'\">'+panel+'</div>';\n  },\n  mounted(d2){\n    d2.on('.ad-panel','click',(e)=>{ e.stopPropagation(); });\n    d2.on('[data-act=\"mask\"]','click',(e)=>{\n      if(e.target && e.target.closest && e.target.closest('.ad-panel')) return;\n      d2.emit('onClose', {});\n    });\n    d2.on('[data-act=\"close\"]','click',(e)=>{\n      e.stopPropagation();\n      d2.emit('onClose', {});\n    });\n  }\n};"}},"open":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"open"}}}},"openStore":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"openStore"}}}},"openKey":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"openKey"}}}},"title":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"title"}}}},"content":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"content"}}}},"placement":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"placement"}}}},"width":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"width"}}}},"height":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"height"}}}},"closable":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"closable"}}}},"slots":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"slots"}}}},"onClose":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onClose"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efd919307b10171577480","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-menu","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\n\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction isFa(g){ return /(^|\\s)fa[srlbd]?(\\s|-)/.test(g||''); }\nfunction iconHtml(g){ if(!g) return ''; return isFa(g) ? '<i class=\"ic '+esc(g)+'\"></i>' : '<span class=\"ic\">'+esc(g)+'</span>'; }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-menu{ box-sizing:border-box; font-family:var(--ff); font-size:var(--fs)px; list-style:none; margin:0; padding:0; color:var(--fg); background:var(--bg); }\n    .ant-menu *{ box-sizing:border-box; }\n    .ant-menu.vertical, .ant-menu.inline{ width:100%; }\n    .ant-menu.inline{ border-right:var(--lw)px solid var(--border); }\n    .ant-menu.vertical{ border-right:var(--lw)px solid var(--border); }\n    .ant-menu.horizontal{ display:flex; align-items:center; border-bottom:var(--lw)px solid var(--border); line-height:46px; }\n    .am-item{ position:relative; display:flex; align-items:center; gap:10px; height:40px; padding:0 16px; cursor:pointer; white-space:nowrap; color:var(--fg); transition:color .15s, background .15s, border-color .15s; }\n    .ant-menu.horizontal .am-item{ height:46px; padding:0 16px; }\n    .am-item:hover{ color:var(--fg-hover); }\n    .am-item.selected{ color:var(--sel-fg); }\n    .ant-menu.vertical > .am-row > .am-item.selected, .ant-menu.inline .am-item.selected{ background:var(--sel-bg); border-right:3px solid var(--sel-bar); }\n    .ant-menu.horizontal > .am-row > .am-item.selected{ border-bottom:2px solid var(--sel-bar); }\n    .am-item.danger{ color:var(--danger); }\n    .am-item.danger:hover{ color:var(--danger); background:var(--danger-bg); }\n    .am-item.disabled{ color:var(--disabled) !important; cursor:not-allowed; background:transparent !important; }\n    .am-item .ic{ display:inline-flex; align-items:center; justify-content:center; font-size:14px; width:14px; }\n    .am-item .lbl{ flex:1 1 auto; overflow:hidden; text-overflow:ellipsis; }\n    .am-item .caret{ font-size:10px; transition:transform .2s; opacity:.75; }\n    .am-item .caret.open{ transform:rotate(180deg); }\n    .am-sub{ overflow:hidden; }\n    .am-sub.inline-sub{ background:var(--sub-bg); }\n    .am-sub.inline-sub .am-item{ padding-left:42px; }\n    .am-flyout{ position:absolute; min-width:160px; background:var(--flyout-bg); box-shadow:0 6px 16px rgba(0,0,0,.12); border-radius:8px; padding:4px; z-index:1050; }\n    .ant-menu.horizontal .am-flyout{ top:100%; left:0; }\n    .ant-menu.vertical .am-flyout{ top:0; left:100%; }\n    .am-flyout .am-item{ height:36px; border-radius:6px; }\n    .am-flyout .am-item.selected{ background:var(--sel-bg); color:var(--sel-fg); border:none; }\n    .am-row{ position:relative; }\n    .ant-menu.horizontal > .am-row{ display:inline-flex; }\n    .am-row .am-flyout{ display:none; }\n    .am-row:hover > .am-flyout{ display:block; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const mode = p.mode || 'vertical';\n    const theme = p.theme || 'light';\n    const items = Array.isArray(p.items) ? p.items : [];\n\n    if(d2.state.selectedKey === undefined) d2.state.selectedKey = p.selectedKey != null ? p.selectedKey : null;\n    if(d2.state.openKeys === undefined) d2.state.openKeys = {};\n    const selKey = d2.state.selectedKey;\n    const openKeys = d2.state.openKeys || {};\n\n    const dark = theme === 'dark';\n    const bg = dark ? '#001529' : D.colorBgContainer;\n    const fg = dark ? 'rgba(255,255,255,0.65)' : D.colorText;\n    const fgHover = dark ? '#ffffff' : D.colorPrimary;\n    const selFg = dark ? '#ffffff' : D.colorPrimary;\n    const selBg = dark ? D.colorPrimary : D.colorPrimaryBg;\n    const selBar = D.colorPrimary;\n    const subBg = dark ? '#000c17' : D.colorFillTertiary;\n    const flyoutBg = dark ? '#001529' : D.colorBgContainer;\n\n    const style = [\n      '--ff:'+D.fontFamily, '--fs:'+D.fontSize, '--lw:'+D.lineWidth,\n      '--bg:'+bg, '--fg:'+fg, '--fg-hover:'+fgHover,\n      '--sel-fg:'+selFg, '--sel-bg:'+selBg, '--sel-bar:'+selBar,\n      '--danger:'+D.colorError, '--danger-bg:'+D.colorErrorBg, '--disabled:'+D.colorTextDisabled,\n      '--border:'+(dark?'transparent':D.colorBorderSecondary), '--sub-bg:'+subBg, '--flyout-bg:'+flyoutBg\n    ].join(';');\n\n    function renderLeaf(it, inFlyout){\n      const k = it.key != null ? String(it.key) : '';\n      const cls = ['am-item'];\n      if(k && k === String(selKey)) cls.push('selected');\n      if(it.danger) cls.push('danger');\n      if(it.disabled) cls.push('disabled');\n      return '<div class=\"'+cls.join(' ')+'\" data-key=\"'+esc(k)+'\"'+(it.disabled?'':' role=\"menuitem\"')+'>'+\n        iconHtml(it.glyph)+'<span class=\"lbl\">'+esc(it.label)+'</span></div>';\n    }\n\n    function renderItem(it){\n      const k = it.key != null ? String(it.key) : '';\n      const kids = Array.isArray(it.children) ? it.children : [];\n      if(!kids.length){\n        return '<div class=\"am-row\">'+renderLeaf(it, false)+'</div>';\n      }\n      const isOpen = !!openKeys[k];\n      const useInline = mode === 'inline';\n      const parentCls = ['am-item'];\n      if(it.danger) parentCls.push('danger');\n      if(it.disabled) parentCls.push('disabled');\n      const caretCls = 'caret'+(useInline && isOpen ? ' open' : '');\n      const parent = '<div class=\"'+parentCls.join(' ')+'\" data-sub=\"'+esc(k)+'\"'+(it.disabled?'':'')+'>'+\n        iconHtml(it.glyph)+'<span class=\"lbl\">'+esc(it.label)+'</span>'+\n        '<i class=\"caret fa fa-angle-down '+(useInline&&isOpen?'open':'')+'\"></i></div>';\n      let sub = '';\n      if(useInline){\n        if(isOpen){\n          sub = '<div class=\"am-sub inline-sub\">'+kids.map(function(c){ return renderLeaf(c, false); }).join('')+'</div>';\n        }\n      } else {\n        sub = '<div class=\"am-flyout\">'+kids.map(function(c){ return renderLeaf(c, true); }).join('')+'</div>';\n      }\n      return '<div class=\"am-row\">'+parent+sub+'</div>';\n    }\n\n    const body = items.map(renderItem).join('');\n    return '<div class=\"ant-menu '+mode+' '+theme+'\" style=\"'+style+'\" role=\"menu\">'+body+'</div>';\n  },\n  mounted(d2){\n    d2.on('.am-item','click',function(e){\n      const el = e.target.closest('.am-item');\n      if(!el) return;\n      if(el.classList.contains('disabled')) return;\n      const sub = el.getAttribute('data-sub');\n      if(sub != null){\n        const ok = Object.assign({}, d2.state.openKeys || {});\n        ok[sub] = !ok[sub];\n        d2.state.openKeys = ok;\n        return;\n      }\n      const key = el.getAttribute('data-key');\n      if(key == null) return;\n      d2.state.selectedKey = key;\n      d2.emit('onClick', { key: key });\n    });\n  }\n};"}},"items":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"items"}}}},"mode":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"mode"}}}},"selectedKey":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"selectedKey"}}}},"theme":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"theme"}}}},"onClick":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onClick"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efd91ccdaee8ef640b16f","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-collapse","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction asArr(x){ if(Array.isArray(x))return x; if(x==null)return []; if(typeof x==='string')return x.split(',').map(function(s){return s.trim();}).filter(Boolean); return [x]; }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .acol{ box-sizing:border-box; font-family:var(--ff); font-size:14px; color:var(--text); width:100%; }\n    .acol *{ box-sizing:border-box; }\n    .acol.bordered{ border:1px solid var(--b2); border-radius:6px; overflow:hidden; }\n    .acol-item + .acol-item{ border-top:1px solid var(--b2); }\n    .acol-hd{ display:flex; align-items:center; gap:10px; cursor:pointer; user-select:none; padding:10px 16px; color:var(--text); background:var(--fill3); line-height:1.57; transition:background .2s; }\n    .acol-hd:hover{ background:var(--fill2); }\n    .acol-car{ display:inline-flex; align-items:center; transition:transform .2s; color:var(--text2); font-size:.9em; }\n    .acol-item.open .acol-car{ transform:rotate(90deg); }\n    .acol-tx{ flex:1; }\n    .acol-bd{ padding:12px 16px; color:var(--text); white-space:pre-wrap; border-top:1px solid var(--b2); background:var(--bg); line-height:1.57; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const items = asArr(p.items).filter(function(it){ return it && typeof it === 'object'; });\n    const bordered = p.bordered !== false;\n    if(d2.state.open == null){ let init = asArr(p.activeKeys).map(String); if(p.accordion && init.length>1) init=[init[0]]; d2.state.open = init; }\n    const open = asArr(d2.state.open).map(String);\n\n    const style = '--ff:'+D.fontFamily+';--text:'+D.colorText+';--text2:'+D.colorTextSecondary+';--b2:'+D.colorBorderSecondary+';--bg:'+D.colorBgContainer+';--fill3:'+D.colorFillTertiary+';--fill2:'+D.colorFillSecondary;\n\n    const rows = items.map(function(it,i){\n      const k = String(it.key!=null?it.key:i);\n      const isOpen = open.indexOf(k)!==-1;\n      let bodyInner = '';\n      if(isOpen){\n        if(Array.isArray(it.slots) && it.slots.length){\n          bodyInner = it.slots.map(function(s,si){ return d2.render(s.type||s.component, s.props||s.params||{}, {key:s.key||('cps'+si), style:'height:auto;display:block'}); }).join('');\n        } else {\n          bodyInner = esc(it.content!=null?it.content:'');\n        }\n      }\n      const body = isOpen ? '<div class=\"acol-bd\">'+bodyInner+'</div>' : '';\n      return '<div class=\"acol-item'+(isOpen?' open':'')+'\" data-key=\"'+esc(k)+'\">'\n        + '<div class=\"acol-hd\" data-key=\"'+esc(k)+'\"><span class=\"acol-car\"><i class=\"fa fa-angle-right\"></i></span><span class=\"acol-tx\">'+esc(it.header!=null?it.header:(it.label!=null?it.label:''))+'</span></div>'\n        + body + '</div>';\n    }).join('');\n\n    return '<div class=\"acol'+(bordered?' bordered':'')+'\" style=\"'+style+'\">'+rows+'</div>';\n  },\n  mounted(d2){\n    d2.on('.acol-hd','click',function(e,el){\n      const k = el.getAttribute('data-key');\n      if(k==null) return;\n      const acc = !!(d2.params||{}).accordion;\n      let open = (Array.isArray(d2.state.open)?d2.state.open:[]).map(String);\n      const idx = open.indexOf(k);\n      if(idx!==-1) open = open.filter(function(x){return x!==k;});\n      else open = acc ? [k] : open.concat([k]);\n      d2.state.open = open;\n    });\n  }\n};"}},"items":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"items"}}}},"activeKeys":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"activeKeys"}}}},"accordion":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"accordion"}}}},"bordered":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bordered"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efd9c6202ef3347df1f42","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-dropdown","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction isFa(g){ return /(^|\\s)fa[srlbd]?(\\s|-)/.test(g); }\nfunction iconHtml(g,cls){ if(!g)return ''; return isFa(g) ? '<i class=\"'+(cls||'ic')+' '+esc(g)+'\"></i>' : '<span class=\"'+(cls||'ic')+'\">'+esc(g)+'</span>'; }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .dd-wrap{ position:relative; display:inline-flex; font-family:var(--ff); font-size:var(--fs); }\n    .dd-trigger{ display:inline-flex; align-items:center; gap:8px; cursor:pointer; color:var(--text); user-select:none; line-height:1; }\n    .dd-trigger .ic{ display:inline-flex; align-items:center; }\n    .dd-caret{ transition:transform .2s cubic-bezier(.4,0,.2,1); font-size:.75em; color:var(--text-tertiary); }\n    .dd-wrap.open .dd-caret{ transform:rotate(180deg); }\n    .dd-menu{ position:fixed; min-width:140px; background:var(--bg); border:var(--bw) solid var(--border); border-radius:var(--radius); box-shadow:0 6px 16px rgba(0,0,0,.12); padding:4px 0; z-index:1200; }\n    .dd-item{ display:flex; align-items:center; gap:8px; padding:5px 12px; color:var(--text); cursor:pointer; line-height:1.5; white-space:nowrap; transition:background .15s; }\n    .dd-item .ic{ display:inline-flex; align-items:center; width:1em; }\n    .dd-item:hover{ background:var(--fill-tertiary); }\n    .dd-item.danger{ color:var(--error); }\n    .dd-item.danger:hover{ background:var(--error-bg); }\n    .dd-item.disabled{ color:var(--text-disabled); cursor:not-allowed; }\n    .dd-item.disabled:hover{ background:transparent; }\n    .dd-divider{ height:0; margin:4px 0; border-top:var(--bw) solid var(--border-secondary); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    if(d2.state.open == null) d2.state.open = false;\n    const D = resolveTokens(p);\n    const items = Array.isArray(p.menuItems) ? p.menuItems : [];\n    const trigger = p.trigger || 'hover';\n    const targetLabel = p.targetLabel != null ? String(p.targetLabel) : 'Menu';\n    const targetGlyph = p.targetGlyph || '';\n    const showCaret = p.caret !== false;\n\n    const style = [\n      '--ff:'+D.fontFamily, '--fs:'+D.fontSize+'px', '--bw:'+D.lineWidth+'px',\n      '--radius:'+D.borderRadius+'px', '--bg:'+D.colorBgContainer, '--border:'+D.colorBorder,\n      '--border-secondary:'+D.colorBorderSecondary, '--text:'+D.colorText,\n      '--text-tertiary:'+D.colorTextTertiary, '--text-disabled:'+D.colorTextDisabled,\n      '--fill-tertiary:'+D.colorFillTertiary, '--error:'+D.colorError, '--error-bg:'+D.colorErrorBg\n    ].join(';');\n\n    let menuHtml = '';\n    if(d2.state.open){\n      const rows = items.map(function(it, i){\n        if(!it) return '';\n        if(it.divider) return '<div class=\"dd-divider\"></div>';\n        const cls = ['dd-item']; if(it.danger) cls.push('danger'); if(it.disabled) cls.push('disabled');\n        const key = it.key != null ? it.key : i;\n        const dataKey = it.disabled ? '' : ' data-key=\"'+esc(key)+'\"';\n        const ic = it.glyph ? iconHtml(it.glyph) : (items.some(function(x){return x&&x.glyph;}) ? '<span class=\"ic\"></span>' : '');\n        return '<div class=\"'+cls.join(' ')+'\"'+dataKey+'>'+ic+'<span class=\"lbl\">'+esc(it.label!=null?it.label:'')+'</span></div>';\n      }).join('');\n      menuHtml = '<div class=\"dd-menu\">'+rows+'</div>';\n    }\n\n    const caretHtml = showCaret ? '<i class=\"dd-caret fa fa-angle-down\"></i>' : '';\n    const triggerIcon = targetGlyph ? iconHtml(targetGlyph) : '';\n    const wrapCls = 'dd-wrap' + (d2.state.open ? ' open' : '');\n\n    return '<div class=\"'+wrapCls+'\" style=\"'+style+'\" data-trigger=\"'+esc(trigger)+'\">'+\n      '<div class=\"dd-trigger\">'+triggerIcon+'<span class=\"dd-label\">'+esc(targetLabel)+'</span>'+caretHtml+'</div>'+\n      menuHtml+'</div>';\n  },\n  mounted(d2){\n    const trig = (d2.params&&d2.params.trigger)||'hover';\n    if(trig==='click'){\n      d2.on('.dd-trigger','click',function(e){ e.stopPropagation(); d2.state.open = !d2.state.open; });\n    } else {\n      d2.on('.dd-wrap','mouseover',function(){ d2.state.open = true; });\n      d2.on('.dd-wrap','mouseout',function(e){ const to=e.relatedTarget; if(to && d2.root.contains(to)) return; d2.state.open = false; });\n    }\n    d2.on('.dd-item','click',function(e, el){\n      if(!el) return;\n      const key = el.getAttribute('data-key');\n      if(key==null) return; // disabled has no data-key\n      d2.emit('onClick', key);\n      d2.state.open = false;\n    });\n    d2.on(document,'click',function(e){\n      if(!d2.state.open) return;\n      const path=(e.composedPath&&e.composedPath())||[]; if(d2.root && path.indexOf(d2.root)!==-1) return;\n      d2.state.open = false;\n    });\n  },\n  updated(d2){\n    if(!d2.state.open) return;\n    const trig = d2.$('.dd-trigger'), menu = d2.$('.dd-menu');\n    if(!trig || !menu) return;\n    const r = trig.getBoundingClientRect();\n    menu.style.left = Math.round(r.left) + 'px';\n    menu.style.top = Math.round(r.bottom + 4) + 'px';\n  }\n};"}},"menuItems":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"menuItems"}}}},"trigger":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"trigger"}}}},"targetLabel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"targetLabel"}}}},"targetGlyph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"targetGlyph"}}}},"caret":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"caret"}}}},"onClick":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onClick"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efda12ae3e526cfd2b1b8","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-breadcrumb","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\n\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction isFa(g){ return /(^|\\s)fa[srlbd]?(\\s|-)/.test(g||''); }\nfunction iconHtml(g){ if(!g) return ''; return isFa(g) ? '<i class=\"ic '+esc(g)+'\"></i>' : '<span class=\"ic\">'+esc(g)+'</span>'; }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-breadcrumb{ box-sizing:border-box; display:flex; align-items:center; flex-wrap:wrap; font-family:var(--ff); font-size:var(--fs)px; line-height:1.5; color:var(--current); }\n    .ant-breadcrumb *{ box-sizing:border-box; }\n    .ab-item{ display:inline-flex; align-items:center; gap:5px; color:var(--link); transition:color .15s; }\n    .ab-item.linky{ cursor:pointer; }\n    .ab-item.linky:hover{ color:var(--link-hover); }\n    .ab-item.current{ color:var(--current); }\n    .ab-sep{ margin:0 8px; color:var(--sep); }\n    .ant-breadcrumb .ic{ display:inline-flex; align-items:center; font-size:14px; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const items = Array.isArray(p.items) ? p.items : [];\n    const sep = p.separator != null && p.separator !== '' ? p.separator : '/';\n\n    const style = [\n      '--ff:'+D.fontFamily, '--fs:'+D.fontSize,\n      '--link:'+D.colorTextSecondary, '--link-hover:'+D.colorPrimary,\n      '--current:'+D.colorText, '--sep:'+D.colorTextTertiary\n    ].join(';');\n\n    const parts = items.map(function(it, i){\n      const last = i === items.length - 1;\n      const cls = ['ab-item'];\n      if(last) cls.push('current'); else if(it.href != null && it.href !== '') cls.push('linky');\n      const attr = (!last && it.href != null && it.href !== '') ? ' data-href=\"'+esc(it.href)+'\"' : '';\n      const node = '<span class=\"'+cls.join(' ')+'\"'+attr+'>'+iconHtml(it.glyph)+'<span class=\"ab-title\">'+esc(it.title)+'</span></span>';\n      const sepNode = last ? '' : '<span class=\"ab-sep\">'+esc(sep)+'</span>';\n      return node + sepNode;\n    }).join('');\n\n    return '<nav class=\"ant-breadcrumb\" style=\"'+style+'\">'+parts+'</nav>';\n  },\n  mounted(d2){\n    d2.on('.ab-item.linky','click',function(e){\n      const el = e.target.closest('.ab-item.linky');\n      if(!el) return;\n      const href = el.getAttribute('data-href');\n      if(href) d2.emit('onClick', { href: href });\n    });\n  }\n};"}},"items":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"items"}}}},"separator":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"separator"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efdb46202ef3347df1f73","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-steps","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction isFa(g){ return /(^|\\s)fa[srlbd]?(\\s|-)/.test(g||''); }\nfunction glyphHtml(g){ if(!g)return ''; return isFa(g)?'<i class=\"'+esc(g)+'\"></i>':esc(g); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-steps{ box-sizing:border-box; display:flex; font-family:var(--ff); width:100%; }\n    .ant-steps *{ box-sizing:border-box; }\n    .ant-steps.horizontal{ flex-direction:row; align-items:flex-start; }\n    .ant-steps.vertical{ flex-direction:column; }\n    .as-step{ display:flex; position:relative; min-width:0; }\n    .ant-steps.horizontal .as-step{ flex:1; flex-direction:column; }\n    .ant-steps.horizontal.lp-horizontal .as-step{ flex-direction:row; align-items:flex-start; }\n    .ant-steps.vertical .as-step{ flex-direction:row; align-items:flex-start; padding-bottom:var(--vgap); }\n    .ant-steps.vertical .as-step:last-child{ padding-bottom:0; }\n    .as-head{ display:flex; align-items:center; position:relative; }\n    .ant-steps.horizontal:not(.lp-horizontal) .as-head{ flex-direction:column; }\n    .as-marker{ flex:0 0 auto; width:var(--mk); height:var(--mk); border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:var(--mkfs); font-weight:500; line-height:1; transition:all .2s; }\n    .as-marker.finish{ background:var(--primary); color:var(--white); }\n    .as-marker.process{ background:var(--primary); color:var(--white); }\n    .as-marker.wait{ background:var(--bg); border:var(--lw) solid var(--border); color:var(--tt); }\n    .as-marker.error{ background:var(--error); color:var(--white); }\n    .as-conn{ position:absolute; background:var(--connbg); }\n    .as-conn.done{ background:var(--primary); }\n    .ant-steps.horizontal:not(.lp-horizontal) .as-conn{ top:calc(var(--mk) / 2); height:var(--lw); left:calc(50% + var(--mk) / 2 + 8px); right:calc(-50% + var(--mk) / 2 + 8px); }\n    .ant-steps.horizontal.lp-horizontal .as-conn{ top:calc(var(--mk) / 2); height:var(--lw); left:calc(var(--mk) + 8px); right:8px; }\n    .ant-steps.vertical .as-conn{ left:calc(var(--mk) / 2); top:calc(var(--mk) + 8px); bottom:8px; width:var(--lw); }\n    .as-body{ min-width:0; }\n    .ant-steps.horizontal:not(.lp-horizontal) .as-body{ margin-top:8px; text-align:center; padding:0 8px; }\n    .ant-steps.horizontal.lp-horizontal .as-body{ margin-left:8px; padding-right:12px; }\n    .ant-steps.vertical .as-body{ margin-left:12px; padding-bottom:4px; }\n    .as-title{ font-size:var(--tfs); line-height:1.4; color:var(--tt); font-weight:400; }\n    .as-title.on{ color:var(--text); }\n    .as-desc{ font-size:var(--dfs); line-height:1.5; color:var(--ts); margin-top:2px; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const items = Array.isArray(p.items) ? p.items : [];\n    const current = typeof p.current === 'number' ? p.current : 0;\n    const direction = p.direction === 'vertical' ? 'vertical' : 'horizontal';\n    const small = p.size === 'small';\n    const lp = p.labelPlacement === 'vertical' ? 'vertical' : 'horizontal';\n    const mk = small ? D.controlHeightSM : D.controlHeight;\n    const isHoriz = direction === 'horizontal';\n    const lpHorizontal = isHoriz && lp === 'horizontal';\n\n    const vars = [\n      '--ff:'+D.fontFamily, '--mk:'+mk+'px', '--mkfs:'+(small?D.fontSizeSM:D.fontSize)+'px',\n      '--tfs:'+(small?D.fontSize:D.fontSizeLG)+'px', '--dfs:'+D.fontSizeSM+'px',\n      '--primary:'+D.colorPrimary, '--white:'+D.colorTextLightSolid, '--error:'+D.colorError,\n      '--bg:'+D.colorBgContainer, '--border:'+D.colorBorder, '--connbg:'+D.colorBorderSecondary,\n      '--text:'+D.colorText, '--ts:'+D.colorTextSecondary, '--tt:'+D.colorTextTertiary,\n      '--lw:'+D.lineWidth+'px', '--vgap:24px'\n    ].join(';');\n\n    const cls = ['ant-steps', direction];\n    if(lpHorizontal) cls.push('lp-horizontal');\n\n    const stepsHtml = items.map(function(it, i){\n      it = it || {};\n      let status = it.status;\n      if(!status) status = i < current ? 'finish' : (i === current ? 'process' : 'wait');\n      let inner;\n      if(it.glyph){ inner = glyphHtml(it.glyph); }\n      else if(status === 'finish'){ inner = '<i class=\"fa fa-check\"></i>'; }\n      else if(status === 'error'){ inner = '<i class=\"fa fa-times\"></i>'; }\n      else { inner = String(i + 1); }\n      const titleOn = status === 'finish' || status === 'process' || status === 'error';\n      const isLast = i === items.length - 1;\n      const connDone = i < current;\n      const conn = isLast ? '' : '<span class=\"as-conn'+(connDone?' done':'')+'\"></span>';\n      const desc = it.description ? '<div class=\"as-desc\">'+esc(it.description)+'</div>' : '';\n      return '<div class=\"as-step\">'\n        + '<div class=\"as-head\">'\n        + '<span class=\"as-marker '+status+'\">'+inner+'</span>'\n        + (lpHorizontal ? '' : conn)\n        + '</div>'\n        + (lpHorizontal ? conn : '')\n        + '<div class=\"as-body\">'\n        + '<div class=\"as-title'+(titleOn?' on':'')+'\">'+esc(it.title||'')+'</div>'\n        + desc\n        + '</div>'\n        + '</div>';\n    }).join('');\n\n    return '<div class=\"'+cls.join(' ')+'\" style=\"'+vars+'\">'+stepsHtml+'</div>';\n  }\n};"}},"items":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"items"}}}},"current":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"current"}}}},"direction":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"direction"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"labelPlacement":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"labelPlacement"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efdbae6cc9d55d3ddeae8","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-pagination","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nfunction buildPages(current, pageCount){\n  // returns array of numbers or '...' tokens\n  if(pageCount <= 7){ const a=[]; for(let i=1;i<=pageCount;i++) a.push(i); return a; }\n  const out = [1];\n  const left = Math.max(2, current-1);\n  const right = Math.min(pageCount-1, current+1);\n  if(left > 2) out.push('left-ellipsis');\n  for(let i=left;i<=right;i++) out.push(i);\n  if(right < pageCount-1) out.push('right-ellipsis');\n  out.push(pageCount);\n  return out;\n}\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .pg{ display:inline-flex; align-items:center; gap:8px; font-family:var(--ff); font-size:var(--fs); color:var(--text); user-select:none; }\n    .pg-item{ box-sizing:border-box; min-width:var(--h); height:var(--h); padding:0 6px; display:inline-flex; align-items:center; justify-content:center; border:var(--bw) solid var(--border); border-radius:var(--radius); background:var(--bg); color:var(--text); cursor:pointer; transition:all .2s cubic-bezier(.4,0,.2,1); line-height:1; }\n    .pg-item:hover{ color:var(--primary); border-color:var(--primary); }\n    .pg-item.active{ color:var(--primary); border-color:var(--primary); font-weight:600; }\n    .pg-arrow{ box-sizing:border-box; min-width:var(--h); height:var(--h); display:inline-flex; align-items:center; justify-content:center; border:var(--bw) solid var(--border); border-radius:var(--radius); background:var(--bg); color:var(--text); cursor:pointer; transition:all .2s; }\n    .pg-arrow:hover{ color:var(--primary); border-color:var(--primary); }\n    .pg-ellipsis{ min-width:var(--h); height:var(--h); display:inline-flex; align-items:center; justify-content:center; color:var(--text-disabled); letter-spacing:1px; }\n    .pg-item.dis, .pg-arrow.dis{ color:var(--text-disabled); border-color:var(--border); cursor:not-allowed; background:var(--bg); }\n    .pg-item.dis:hover, .pg-arrow.dis:hover{ color:var(--text-disabled); border-color:var(--border); }\n    .pg.is-disabled .pg-item, .pg.is-disabled .pg-arrow{ color:var(--text-disabled); border-color:var(--border); cursor:not-allowed; }\n    .pg.is-disabled .pg-item:hover, .pg.is-disabled .pg-arrow:hover{ color:var(--text-disabled); border-color:var(--border); }\n    .pg-simple{ display:inline-flex; align-items:center; gap:8px; }\n    .pg-simple .sep{ color:var(--text-secondary); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const total = Math.max(0, Number(p.total)||0);\n    const pageSize = Math.max(1, Number(p.pageSize)||10);\n    const pageCount = Math.max(1, Math.ceil(total/pageSize));\n    if(d2.state.current == null) d2.state.current = Math.min(Math.max(1, Number(p.current)||1), pageCount);\n    let current = Math.min(Math.max(1, d2.state.current), pageCount);\n    const disabled = !!p.disabled;\n    const simple = !!p.simple;\n\n    const style = [\n      '--ff:'+D.fontFamily, '--fs:'+D.fontSize+'px', '--h:'+D.controlHeight+'px',\n      '--bw:'+D.lineWidth+'px', '--radius:'+D.borderRadius+'px', '--bg:'+D.colorBgContainer,\n      '--border:'+D.colorBorder, '--text:'+D.colorText, '--text-secondary:'+D.colorTextSecondary,\n      '--text-disabled:'+D.colorTextDisabled, '--primary:'+D.colorPrimary\n    ].join(';');\n\n    const wrapCls = 'pg' + (disabled ? ' is-disabled' : '');\n    const atFirst = current <= 1;\n    const atLast = current >= pageCount;\n    const prevDis = disabled || atFirst;\n    const nextDis = disabled || atLast;\n\n    const prevHtml = '<div class=\"pg-arrow'+(prevDis?' dis':'')+'\"'+(prevDis?'':' data-go=\"prev\"')+'><i class=\"fa fa-angle-left\"></i></div>';\n    const nextHtml = '<div class=\"pg-arrow'+(nextDis?' dis':'')+'\"'+(nextDis?'':' data-go=\"next\"')+'><i class=\"fa fa-angle-right\"></i></div>';\n\n    if(simple){\n      return '<div class=\"'+wrapCls+'\" style=\"'+style+'\"><div class=\"pg-simple\">'+\n        prevHtml+'<span class=\"sep\">'+current+' / '+pageCount+'</span>'+nextHtml+\n        '</div></div>';\n    }\n\n    const pages = buildPages(current, pageCount).map(function(tok){\n      if(tok==='left-ellipsis' || tok==='right-ellipsis') return '<div class=\"pg-ellipsis\">…</div>';\n      const active = tok===current;\n      const cls = ['pg-item']; if(active) cls.push('active');\n      const dp = disabled ? ' dis' : '';\n      const dataPage = (disabled||active) ? '' : ' data-page=\"'+tok+'\"';\n      return '<div class=\"'+cls.join(' ')+dp+'\"'+dataPage+'>'+tok+'</div>';\n    }).join('');\n\n    return '<div class=\"'+wrapCls+'\" style=\"'+style+'\">'+prevHtml+pages+nextHtml+'</div>';\n  },\n  mounted(d2){\n    function go(page){\n      const p = d2.params || {};\n      if(p.disabled) return;\n      const total = Math.max(0, Number(p.total)||0);\n      const pageSize = Math.max(1, Number(p.pageSize)||10);\n      const pageCount = Math.max(1, Math.ceil(total/pageSize));\n      const clamped = Math.min(Math.max(1, page), pageCount);\n      if(clamped === d2.state.current) return;\n      d2.state.current = clamped;\n      d2.emit('onChange', clamped);\n    }\n    d2.on('.pg-arrow','click',function(e){\n      const el = e.target.closest('.pg-arrow'); if(!el) return;\n      const dir = el.getAttribute('data-go'); if(!dir) return;\n      go(d2.state.current + (dir==='next' ? 1 : -1));\n    });\n    d2.on('.pg-item','click',function(e){\n      const el = e.target.closest('.pg-item'); if(!el) return;\n      const pg = el.getAttribute('data-page'); if(pg==null) return;\n      go(Number(pg));\n    });\n  }\n};"}},"total":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"total"}}}},"pageSize":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"pageSize"}}}},"current":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"current"}}}},"simple":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"simple"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efdc60e623bb3377fe197","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-segmented","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction normOptions(raw){\n  if(!Array.isArray(raw)) return [];\n  return raw.map(function(o){\n    if(o==null) return null;\n    if(typeof o!=='object') return { label:String(o), value:String(o), glyph:'', disabled:false };\n    const val = o.value!=null ? String(o.value) : (o.label!=null?String(o.label):'');\n    const lbl = o.label!=null ? String(o.label) : val;\n    return { label:lbl, value:val, glyph:o.glyph||'', disabled:!!o.disabled };\n  }).filter(function(o){ return o!=null; });\n}\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-seg{ box-sizing:border-box; display:inline-flex; align-items:stretch; padding:2px; gap:2px;\n      background:var(--track); border-radius:var(--radius); font-family:var(--ff); font-size:var(--fs);\n      line-height:1; vertical-align:middle; }\n    .ant-seg.block{ display:flex; width:100%; }\n    .ant-seg .seg{ box-sizing:border-box; display:inline-flex; align-items:center; justify-content:center; gap:6px;\n      height:var(--h); padding:0 11px; border-radius:var(--iradius); color:var(--fg); cursor:pointer;\n      background:transparent; white-space:nowrap; user-select:none; transition:color .2s,background .2s,box-shadow .2s; }\n    .ant-seg.block .seg{ flex:1 1 0; }\n    .ant-seg .seg:hover{ color:var(--fg-hover); }\n    .ant-seg .seg.selected{ background:var(--sel-bg); color:var(--fg-sel); box-shadow:0 2px 8px -2px rgba(0,0,0,0.10),0 1px 2px rgba(0,0,0,0.06); cursor:default; }\n    .ant-seg .seg.selected:hover{ color:var(--fg-sel); }\n    .ant-seg .seg.disabled{ color:var(--fg-dis); cursor:not-allowed; }\n    .ant-seg .seg.disabled:hover{ color:var(--fg-dis); }\n    .ant-seg.is-disabled{ cursor:not-allowed; }\n    .ant-seg.is-disabled .seg{ color:var(--fg-dis); cursor:not-allowed; }\n    .ant-seg.is-disabled .seg.selected{ color:var(--fg-dis); background:var(--sel-bg); }\n    .ant-seg .ic{ display:inline-flex; align-items:center; justify-content:center; font-size:1em; line-height:0; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const opts = normOptions(p.options);\n    const size = p.size || 'middle';\n    const block = !!p.block;\n    const groupDisabled = !!p.disabled;\n\n    if(d2.state.value === undefined){\n      const init = (p.value!=null && p.value!=='') ? String(p.value) : (opts.length ? opts[0].value : '');\n      d2.state.value = init;\n    }\n    const current = String(d2.state.value);\n\n    const SZ = ({\n      small:{ h:D.controlHeightSM, fs:D.fontSizeSM, r:D.borderRadiusSM },\n      large:{ h:D.controlHeightLG, fs:D.fontSizeLG, r:D.borderRadiusLG },\n      middle:{ h:D.controlHeight, fs:D.fontSize, r:D.borderRadius },\n    })[size] || { h:D.controlHeight, fs:D.fontSize, r:D.borderRadius };\n    const innerH = SZ.h - 4;\n    const iradius = Math.max(2, SZ.r - 2);\n\n    const fgHoverDark = 'rgba(0,0,0,0.88)';\n    const style = [\n      '--track:'+D.colorFillTertiary,\n      '--radius:'+SZ.r+'px',\n      '--iradius:'+iradius+'px',\n      '--h:'+innerH+'px',\n      '--fs:'+SZ.fs+'px',\n      '--ff:'+D.fontFamily,\n      '--fg:'+D.colorTextSecondary,\n      '--fg-hover:'+D.colorText,\n      '--fg-sel:'+D.colorText,\n      '--sel-bg:'+D.colorBgContainer,\n      '--fg-dis:'+D.colorTextDisabled\n    ].join(';');\n\n    const cls = ['ant-seg'];\n    if(block) cls.push('block');\n    if(groupDisabled) cls.push('is-disabled');\n\n    const segs = opts.map(function(o){\n      const selected = o.value === current;\n      const itemDisabled = groupDisabled || o.disabled;\n      const c = ['seg'];\n      if(selected) c.push('selected');\n      if(itemDisabled) c.push('disabled');\n      let icon = '';\n      if(o.glyph){\n        const isFa = /(^|\\s)fa[srlbd]?(\\s|-)/.test(o.glyph);\n        icon = isFa ? '<i class=\"ic '+esc(o.glyph)+'\"></i>' : '<span class=\"ic\">'+esc(o.glyph)+'</span>';\n      }\n      const lbl = o.label ? '<span class=\"lbl\">'+esc(o.label)+'</span>' : '';\n      return '<div class=\"'+c.join(' ')+'\" data-value=\"'+esc(o.value)+'\"'+(itemDisabled?' data-disabled=\"1\"':'')+'>'+icon+lbl+'</div>';\n    }).join('');\n\n    return '<div class=\"'+cls.join(' ')+'\" style=\"'+style+'\">'+segs+'</div>';\n  },\n  mounted(d2){\n    d2.on('.ant-seg .seg','click',(e,el)=>{\n      const p = d2.params || {};\n      if(p.disabled) return;\n      const node = el.closest ? el.closest('.seg') : el;\n      if(!node) return;\n      if(node.getAttribute('data-disabled')==='1') return;\n      const val = node.getAttribute('data-value');\n      if(val==null) return;\n      if(String(d2.state.value)===val) return;\n      d2.state.value = val;\n      d2.emit('onChange', val);\n    });\n  }\n};"}},"options":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"options"}}}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"block":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"block"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efdd775a8dfffb1d25243","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-progress","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction strColor(s){ if(s==null)return ''; if(typeof s==='object')return s.rgba||s.hex||s.value||s.color||''; return String(s); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-progress{ box-sizing:border-box; font-family:var(--ff); display:inline-flex; }\n    .ant-progress *{ box-sizing:border-box; }\n    .ant-progress.line{ display:flex; align-items:center; width:100%; gap:8px; }\n    .ap-rail{ position:relative; flex:1; background:var(--track); border-radius:var(--railh); height:var(--railh); overflow:hidden; }\n    .ap-fill{ position:absolute; left:0; top:0; bottom:0; border-radius:var(--railh); background:var(--stroke); transition:width .3s cubic-bezier(.4,0,.2,1); }\n    .ap-fill.active::after{ content:''; position:absolute; inset:0; background:linear-gradient(90deg, transparent, rgba(255,255,255,0.5), transparent); animation:apshimmer 2.4s ease infinite; }\n    @keyframes apshimmer{ 0%{ transform:translateX(-100%); } 100%{ transform:translateX(100%); } }\n    .ap-info{ flex:0 0 auto; font-size:var(--ifs); line-height:1; color:var(--text); min-width:2em; text-align:right; }\n    .ap-info.success{ color:var(--success); }\n    .ap-info.error{ color:var(--error); }\n    .ap-circle{ position:relative; display:inline-flex; align-items:center; justify-content:center; }\n    .ap-circle svg{ transform:rotate(-90deg); display:block; }\n    .ap-circle.dashboard svg{ transform:rotate(90deg); }\n    .ap-ring-bg{ fill:none; stroke:var(--track); }\n    .ap-ring-fg{ fill:none; stroke:var(--stroke); stroke-linecap:round; transition:stroke-dashoffset .3s cubic-bezier(.4,0,.2,1); }\n    .ap-center{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center; font-size:var(--cfs); color:var(--text); }\n    .ap-center.success{ color:var(--success); }\n    .ap-center.error{ color:var(--error); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    let percent = typeof p.percent === 'number' ? p.percent : 0;\n    if(percent < 0) percent = 0; if(percent > 100) percent = 100;\n    const type = (p.type === 'circle' || p.type === 'dashboard') ? p.type : 'line';\n    const status = ['success','exception','active'].indexOf(p.status) >= 0 ? p.status : '';\n    const showInfo = p.showInfo !== false;\n    const small = p.size === 'small';\n    const track = D.colorFillSecondary;\n\n    let stroke;\n    if(status === 'success' || percent >= 100) stroke = D.colorSuccess;\n    else if(status === 'exception') stroke = D.colorError;\n    else stroke = strColor(p.strokeColor) || D.colorPrimary;\n\n    const isDone = percent >= 100 && (status === 'success' || status === '');\n    const isExc = status === 'exception';\n\n    const vars = [\n      '--ff:'+D.fontFamily, '--track:'+track, '--stroke:'+stroke,\n      '--text:'+D.colorText, '--success:'+D.colorSuccess, '--error:'+D.colorError,\n      '--ifs:'+D.fontSize+'px'\n    ];\n\n    function infoHtml(){\n      if(!showInfo) return '';\n      if(isDone) return '<span class=\"ap-info success\"><i class=\"fa fa-check-circle\"></i></span>';\n      if(isExc) return '<span class=\"ap-info error\"><i class=\"fa fa-times-circle\"></i></span>';\n      return '<span class=\"ap-info\">'+esc(Math.round(percent))+'%</span>';\n    }\n\n    if(type === 'line'){\n      const railh = small ? 6 : 8;\n      vars.push('--railh:'+railh+'px');\n      const fillCls = 'ap-fill' + (status === 'active' ? ' active' : '');\n      return '<div class=\"ant-progress line\" style=\"'+vars.join(';')+'\">'\n        + '<div class=\"ap-rail\"><div class=\"'+fillCls+'\" style=\"width:'+percent+'%\"></div></div>'\n        + infoHtml()\n        + '</div>';\n    }\n\n    const sz = small ? 80 : 120;\n    const sw = small ? 6 : 8;\n    const r = (sz - sw) / 2;\n    const cx = sz / 2;\n    const circ = 2 * Math.PI * r;\n    const gap = type === 'dashboard' ? 0.75 : 1;\n    const arcLen = circ * gap;\n    const dash = arcLen * (percent / 100);\n    const cfs = small ? D.fontSizeLG : 24;\n    vars.push('--cfs:'+cfs+'px');\n\n    let centerInner;\n    if(showInfo){\n      if(isDone) centerInner = '<i class=\"fa fa-check\"></i>';\n      else if(isExc) centerInner = '<i class=\"fa fa-times\"></i>';\n      else centerInner = esc(Math.round(percent)) + '%';\n    } else centerInner = '';\n    const centerCls = 'ap-center' + (isDone ? ' success' : (isExc ? ' error' : ''));\n\n    const bgDash = type === 'dashboard' ? (arcLen + ' ' + circ) : '';\n    const bgStyle = type === 'dashboard' ? ' stroke-dasharray=\"'+arcLen+' '+circ+'\"' : '';\n\n    return '<div class=\"ant-progress\" style=\"'+vars.join(';')+'\">'\n      + '<div class=\"ap-circle'+(type==='dashboard'?' dashboard':'')+'\" style=\"width:'+sz+'px;height:'+sz+'px\">'\n      + '<svg width=\"'+sz+'\" height=\"'+sz+'\" viewBox=\"0 0 '+sz+' '+sz+'\">'\n      + '<circle class=\"ap-ring-bg\" cx=\"'+cx+'\" cy=\"'+cx+'\" r=\"'+r+'\" stroke-width=\"'+sw+'\"'+bgStyle+'></circle>'\n      + '<circle class=\"ap-ring-fg\" cx=\"'+cx+'\" cy=\"'+cx+'\" r=\"'+r+'\" stroke-width=\"'+sw+'\" stroke-dasharray=\"'+dash+' '+circ+'\"></circle>'\n      + '</svg>'\n      + '<div class=\"'+centerCls+'\">'+centerInner+'</div>'\n      + '</div>'\n      + '</div>';\n  }\n};"}},"percent":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"percent"}}}},"type":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"type"}}}},"status":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"status"}}}},"showInfo":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"showInfo"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"strokeColor":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"strokeColor"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efdda0e623bb3377fe1bf","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-rate","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorFill:'rgba(0,0,0,0.15)', colorBgContainer:'#ffffff', fontSize:14, fontSizeLG:16, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nconst GOLD = '#fadb14';\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-rate{ display:inline-flex; align-items:center; gap:8px; font-family:var(--ff); font-size:var(--fs);\n      color:var(--empty); line-height:1; outline:none; user-select:none; vertical-align:middle; }\n    .ant-rate.disabled{ cursor:default; }\n    .ant-rate .star{ position:relative; display:inline-block; cursor:pointer; transition:transform .15s ease; }\n    .ant-rate:not(.disabled) .star:hover{ transform:scale(1.1); }\n    .ant-rate.disabled .star{ cursor:default; }\n    .ant-rate .star .layer{ display:block; }\n    .ant-rate .star .full{ color:var(--empty); }\n    .ant-rate .star .half{ position:absolute; top:0; left:0; width:50%; height:100%; overflow:hidden;\n      color:var(--gold); white-space:nowrap; }\n    .ant-rate .star.on .full{ color:var(--gold); }\n    .ant-rate .zone{ position:absolute; top:0; height:100%; width:50%; z-index:2; }\n    .ant-rate .zone.left{ left:0; }\n    .ant-rate .zone.right{ right:0; }\n    .ant-rate .ic{ display:inline-block; line-height:1; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const count = Math.max(1, Math.floor(Number(p.count!=null?p.count:5)) || 5);\n    const allowHalf = !!p.allowHalf;\n    const disabled = !!p.disabled;\n    const glyph = p.glyph || 'fa fa-star';\n\n    if(d2.state.value === undefined){\n      let init = Number(p.value);\n      if(!isFinite(init)) init = 0;\n      d2.state.value = init;\n    }\n    const stored = Number(d2.state.value) || 0;\n    const preview = (!disabled && d2.state.hover != null) ? Number(d2.state.hover) : null;\n    const display = preview != null ? preview : stored;\n\n    const empty = D.colorFill || 'rgba(0,0,0,0.15)';\n    const isFa = /(^|\\s)fa[srlbd]?(\\s|-)/.test(glyph);\n    function iconHtml(){\n      if(isFa) return '<i class=\"ic '+glyph.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;')+'\"></i>';\n      return '<span class=\"ic\">'+String(glyph).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')+'</span>';\n    }\n\n    const style = [\n      '--ff:'+D.fontFamily,\n      '--fs:'+(D.fontSizeLG?(D.fontSizeLG+8):20)+'px',\n      '--gold:'+GOLD,\n      '--empty:'+empty\n    ].join(';');\n\n    let stars = '';\n    for(let i=1;i<=count;i++){\n      const fullOn = display >= i;\n      const halfOn = !fullOn && display >= (i - 0.5);\n      const cls = ['star'];\n      if(fullOn) cls.push('on');\n      const ic = iconHtml();\n      const halfLayer = halfOn ? '<span class=\"layer half\">'+ic+'</span>' : '';\n      let zones = '';\n      if(!disabled){\n        if(allowHalf){\n          zones = '<span class=\"zone left\" data-val=\"'+(i-0.5)+'\"></span><span class=\"zone right\" data-val=\"'+i+'\"></span>';\n        } else {\n          zones = '<span class=\"zone left\" data-val=\"'+i+'\" style=\"width:100%\"></span>';\n        }\n      }\n      stars += '<span class=\"'+cls.join(' ')+'\" data-index=\"'+i+'\"><span class=\"layer full\">'+ic+'</span>'+halfLayer+zones+'</span>';\n    }\n\n    const rootCls = ['ant-rate'];\n    if(disabled) rootCls.push('disabled');\n    return '<div class=\"'+rootCls.join(' ')+'\" style=\"'+style+'\">'+stars+'</div>';\n  },\n  mounted(d2){\n    d2.on('.ant-rate .zone','mouseover',(e,el)=>{\n      if(d2.params && d2.params.disabled) return;\n      const v = parseFloat(el.getAttribute('data-val'));\n      if(isFinite(v)) d2.state.hover = v;\n    });\n    d2.on('.ant-rate','mouseout',(e,el)=>{\n      if(d2.params && d2.params.disabled) return;\n      d2.state.hover = null;\n    });\n    d2.on('.ant-rate .zone','click',(e,el)=>{\n      if(d2.params && d2.params.disabled) return;\n      const v = parseFloat(el.getAttribute('data-val'));\n      if(!isFinite(v)) return;\n      d2.state.value = v;\n      d2.emit('onChange', v);\n    });\n  }\n};"}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"count":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"count"}}}},"allowHalf":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"allowHalf"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"glyph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"glyph"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efde375a8dfffb1d25264","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-slider","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction num(v,fb){ const n=Number(v); return isFinite(n)?n:fb; }\n\nexport default {\n  css: `\n    .ant-slider{ box-sizing:border-box; position:relative; width:100%; height:32px; padding:14px 6px; cursor:pointer; font-family:var(--ff); }\n    .ant-slider.disabled{ cursor:not-allowed; }\n    .ant-slider .rail{ position:absolute; left:6px; right:6px; top:14px; height:4px; border-radius:2px; background:var(--rail); }\n    .ant-slider .track{ position:absolute; top:14px; height:4px; border-radius:2px; background:var(--track); }\n    .ant-slider .handle{ position:absolute; top:16px; width:14px; height:14px; margin-left:-7px; margin-top:-7px; border-radius:50%; background:#fff; border:2px solid var(--handle); box-shadow:0 0 0 0 rgba(22,119,255,0); transition:box-shadow .2s, border-color .2s; cursor:grab; outline:none; }\n    .ant-slider:not(.disabled):hover .handle{ border-color:var(--handle-h); }\n    .ant-slider .handle:hover, .ant-slider .handle.dragging{ box-shadow:0 0 0 5px var(--handle-shadow); }\n    .ant-slider .handle.dragging{ cursor:grabbing; }\n    .ant-slider.disabled .handle{ border-color:var(--handle-dis); cursor:not-allowed; box-shadow:none; }\n    .ant-slider.disabled .track{ background:var(--fill); }\n    .ant-slider .mark-dot{ position:absolute; top:14px; width:8px; height:8px; margin-top:-2px; margin-left:-4px; border-radius:50%; background:#fff; border:2px solid var(--rail); box-sizing:border-box; }\n    .ant-slider .mark-dot.active{ border-color:var(--track); }\n    .ant-slider .mark-label{ position:absolute; top:24px; transform:translateX(-50%); font-size:var(--fs); color:var(--mark); white-space:nowrap; }\n    .ant-slider .mark-label.active{ color:var(--mark-active); }\n    .ant-slider .tip{ position:absolute; top:-8px; transform:translateX(-50%); background:rgba(0,0,0,0.85); color:#fff; font-size:var(--fs); line-height:1; padding:5px 8px; border-radius:6px; pointer-events:none; opacity:0; transition:opacity .15s; white-space:nowrap; }\n    .ant-slider .handle:hover + .tip, .ant-slider.dragging .tip{ opacity:1; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const min = num(p.min, 0);\n    const max = num(p.max, 100);\n    const step = num(p.step, 1) || 1;\n    const disabled = !!p.disabled;\n    const span = (max - min) || 1;\n    if(d2.state.value == null){\n      let init = num(p.value, min);\n      d2.state.value = Math.max(min, Math.min(max, init));\n    }\n    let value = num(d2.state.value, min);\n    value = Math.max(min, Math.min(max, value));\n    const pct = ((value - min) / span) * 100;\n\n    const railC = disabled ? D.colorFillTertiary : D.colorFillSecondary;\n    const trackC = disabled ? D.colorFill : D.colorPrimary;\n    const handleC = disabled ? D.colorTextDisabled : D.colorPrimary;\n\n    const style = [\n      '--rail:'+railC, '--track:'+trackC, '--fill:'+D.colorFill,\n      '--handle:'+handleC, '--handle-h:'+D.colorPrimaryHover, '--handle-dis:'+D.colorTextDisabled,\n      '--handle-shadow:'+D.colorPrimaryBg, '--mark:'+D.colorTextSecondary, '--mark-active:'+D.colorText,\n      '--fs:'+D.fontSizeSM+'px', '--ff:'+D.fontFamily\n    ].join(';');\n\n    let marksHtml = '';\n    const marks = (p.marks && typeof p.marks === 'object') ? p.marks : null;\n    if(marks){\n      for(const k in marks){\n        const mv = num(k, NaN);\n        if(!isFinite(mv) || mv < min || mv > max) continue;\n        const mpct = ((mv - min) / span) * 100;\n        const act = mv <= value;\n        marksHtml += '<span class=\"mark-dot'+(act?' active':'')+'\" style=\"left:'+mpct+'%\"></span>';\n        marksHtml += '<span class=\"mark-label'+(act?' active':'')+'\" style=\"left:'+mpct+'%\">'+esc(marks[k])+'</span>';\n      }\n    }\n\n    const cls = ['ant-slider']; if(disabled) cls.push('disabled');\n    return '<div class=\"'+cls.join(' ')+'\" style=\"'+style+'\">'\n      + '<div class=\"rail\"></div>'\n      + '<div class=\"track\" style=\"left:6px;width:calc('+pct+'% - 12px*'+(pct/100)+' + 6px - 6px)\"></div>'\n      + marksHtml\n      + '<div class=\"handle\" tabindex=\"0\" style=\"left:calc('+pct+'% + 6px - 12px*'+(pct/100)+')\"></div>'\n      + '<div class=\"tip\" style=\"left:calc('+pct+'% + 6px - 12px*'+(pct/100)+')\">'+esc(value)+'</div>'\n      + '</div>';\n  },\n  mounted(d2){\n    const p0 = d2.params || {};\n    let dragging = false;\n\n    function bounds(){\n      const rail = d2.$('.rail');\n      if(!rail) return null;\n      const r = rail.getBoundingClientRect();\n      return { left:r.left, width:r.width };\n    }\n    function settings(){\n      const p = d2.params || {};\n      return { min:num(p.min,0), max:num(p.max,100), step:(num(p.step,1)||1), disabled:!!p.disabled };\n    }\n    function valueFromX(clientX){\n      const b = bounds(); if(!b || b.width<=0) return null;\n      const s = settings();\n      const span = (s.max - s.min) || 1;\n      let ratio = (clientX - b.left) / b.width;\n      ratio = Math.max(0, Math.min(1, ratio));\n      let raw = s.min + ratio * span;\n      let stepped = Math.round((raw - s.min) / s.step) * s.step + s.min;\n      stepped = Math.max(s.min, Math.min(s.max, stepped));\n      const decimals = (String(s.step).split('.')[1] || '').length;\n      if(decimals) stepped = Number(stepped.toFixed(decimals));\n      return stepped;\n    }\n    function setFromX(clientX){\n      const v = valueFromX(clientX);\n      if(v == null) return;\n      if(v !== d2.state.value){\n        d2.state.value = v;\n        d2.emit('onChange', { value:v });\n      }\n    }\n\n    function onMove(e){\n      if(!dragging) return;\n      const cx = (e.touches && e.touches[0]) ? e.touches[0].clientX : e.clientX;\n      if(cx == null) return;\n      if(e.cancelable) e.preventDefault();\n      setFromX(cx);\n    }\n    function onUp(){\n      if(!dragging) return;\n      dragging = false;\n      const root = d2.root;\n      if(root){ root.querySelector('.ant-slider')?.classList.remove('dragging'); root.querySelector('.handle')?.classList.remove('dragging'); }\n    }\n    function startDrag(e){\n      const s = settings();\n      if(s.disabled) return;\n      dragging = true;\n      const root = d2.root;\n      if(root){ root.querySelector('.ant-slider')?.classList.add('dragging'); root.querySelector('.handle')?.classList.add('dragging'); }\n      const cx = (e.touches && e.touches[0]) ? e.touches[0].clientX : e.clientX;\n      if(cx != null) setFromX(cx);\n      if(e.cancelable) e.preventDefault();\n    }\n\n    d2.on('.handle','mousedown', startDrag);\n    d2.on('.handle','touchstart', startDrag);\n    d2.on('.ant-slider','mousedown', (e)=>{ if(e.target && e.target.classList && e.target.classList.contains('handle')) return; const s=settings(); if(s.disabled) return; const cx=e.clientX; if(cx!=null) setFromX(cx); startDrag(e); });\n\n    d2.on(document,'mousemove', onMove);\n    d2.on(document,'touchmove', onMove);\n    d2.on(document,'mouseup', onUp);\n    d2.on(document,'touchend', onUp);\n  }\n};"}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"min":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"min"}}}},"max":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"max"}}}},"step":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"step"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"marks":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"marks"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efdefccdaee8ef640b1f0","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-result","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-result{ box-sizing:border-box; display:flex; flex-direction:column; align-items:center; text-align:center; padding:48px 32px; font-family:var(--ff); }\n    .ant-result .ar-icon{ font-size:72px; line-height:1; }\n    .ant-result .ar-status{ font-size:64px; line-height:1; font-weight:600; color:var(--muted); }\n    .ant-result .ar-title{ font-size:24px; color:var(--text); margin-top:24px; line-height:1.3; }\n    .ant-result .ar-sub{ font-size:var(--fs); color:var(--sub); margin-top:8px; max-width:440px; margin-left:auto; margin-right:auto; line-height:1.5; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const status = p.status || 'info';\n    const title = p.title != null ? String(p.title) : '';\n    const subTitle = p.subTitle != null ? String(p.subTitle) : '';\n\n    const style = ['--ff:'+D.fontFamily,'--fs:'+D.fontSize+'px','--text:'+D.colorText,'--sub:'+D.colorTextSecondary,'--muted:'+D.colorTextTertiary].join(';');\n\n    const iconMap = {\n      success:{ cls:'fa fa-check-circle', color:D.colorSuccess },\n      error:{ cls:'fa fa-times-circle', color:D.colorError },\n      warning:{ cls:'fa fa-exclamation-circle', color:D.colorWarning },\n      info:{ cls:'fa fa-info-circle', color:D.colorPrimary }\n    };\n\n    let head = '';\n    if(iconMap[status]){\n      const ic = iconMap[status];\n      head = '<i class=\"ar-icon '+ic.cls+'\" style=\"color:'+ic.color+'\"></i>';\n    } else {\n      head = '<div class=\"ar-status\">'+esc(status)+'</div>';\n    }\n\n    const titleHtml = title ? '<div class=\"ar-title\">'+esc(title)+'</div>' : '';\n    const subHtml = subTitle ? '<div class=\"ar-sub\">'+esc(subTitle)+'</div>' : '';\n\n    return '<div class=\"ant-result\" style=\"'+style+'\">'+head+titleHtml+subHtml+'</div>';\n  }\n};"}},"status":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"status"}}}},"title":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"title"}}}},"subTitle":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"subTitle"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efdef75a8dfffb1d25277","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-skeleton","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorBorder:'#d9d9d9', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\n\nexport default {\n  css: `\n    .ant-skeleton{ box-sizing:border-box; display:flex; align-items:flex-start; gap:16px; width:100%; font-family:var(--ff); }\n    .ant-skeleton .sk-avatar{ flex:0 0 auto; width:40px; height:40px; border-radius:var(--avatar-radius); background:var(--base); }\n    .ant-skeleton .sk-content{ flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:16px; }\n    .ant-skeleton .sk-bar{ height:16px; border-radius:var(--radius); background:var(--base); }\n    .ant-skeleton.active .sk-avatar, .ant-skeleton.active .sk-bar{ background:linear-gradient(90deg, var(--base) 25%, var(--hl) 37%, var(--base) 63%); background-size:400% 100%; animation:sk-shimmer 1.4s ease infinite; }\n    @keyframes sk-shimmer{ 0%{ background-position:100% 50%; } 100%{ background-position:0 50%; } }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const loading = p.loading === undefined ? true : !!p.loading;\n    if(!loading) return '';\n    const active = p.active === undefined ? true : !!p.active;\n    const avatar = !!p.avatar;\n    const showTitle = p.title === undefined ? true : !!p.title;\n    const round = !!p.round;\n    let rows = (p.paragraph === undefined || p.paragraph === null) ? 3 : Number(p.paragraph);\n    if(!(rows >= 0)) rows = 3;\n    rows = Math.floor(rows);\n\n    const barRadius = round ? '100px' : (D.borderRadiusSM + 'px');\n    const avatarRadius = '50%';\n    const style = ['--ff:'+D.fontFamily,'--base:rgba(0,0,0,0.06)','--hl:rgba(0,0,0,0.12)','--radius:'+barRadius,'--avatar-radius:'+avatarRadius].join(';');\n\n    let content = '';\n    if(showTitle){ content += '<div class=\"sk-bar\" style=\"width:38%\"></div>'; }\n    for(let i=0;i<rows;i++){\n      const w = (i === rows-1 && rows>0) ? '61%' : '100%';\n      content += '<div class=\"sk-bar\" style=\"width:'+w+'\"></div>';\n    }\n\n    const avatarHtml = avatar ? '<div class=\"sk-avatar\"></div>' : '';\n    const cls = 'ant-skeleton' + (active ? ' active' : '');\n\n    return '<div class=\"'+cls+'\" style=\"'+style+'\">'+avatarHtml+'<div class=\"sk-content\">'+content+'</div></div>';\n  }\n};"}},"loading":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"loading"}}}},"active":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"active"}}}},"avatar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"avatar"}}}},"title":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"title"}}}},"paragraph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"paragraph"}}}},"round":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"round"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efdf59307b10171577506","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-empty","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', fontSize:14, fontSizeSM:12, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nconst DEFAULT_SVG = `<svg class=\"ant-empty-img\" width=\"184\" height=\"100\" viewBox=\"0 0 184 100\" xmlns=\"http://www.w3.org/2000/svg\"><g fill=\"none\" fill-rule=\"evenodd\"><ellipse cx=\"92\" cy=\"84\" rx=\"92\" ry=\"8\" fill=\"#f5f5f5\"/><g fill-rule=\"nonzero\" stroke=\"#d9d9d9\"><path d=\"M52 22.7L13.8 65.2c-.7.8-1 1.8-1 2.9V79c0 2.2 1.8 4 4 4h150.4c2.2 0 4-1.8 4-4V68c0-1-.4-2-1-2.8L132 22.7c-.8-.8-1.9-1.3-3-1.3H55c-1.1 0-2.2.5-3 1.3z\"/><path d=\"M124.5 21.4h-65c-2 0-3.8 1.3-4.4 3.3l-9.7 28.8c-.3.8-.4 1.6-.4 2.4v.7c0 4.4 3.6 8 8 8h82c4.4 0 8-3.6 8-8v-.7c0-.8-.1-1.6-.4-2.4l-9.7-28.8c-.6-2-2.4-3.3-4.4-3.3z\" fill=\"#fafafa\"/></g></g></svg>`;\n\nconst SIMPLE_SVG = `<svg class=\"ant-empty-img\" width=\"64\" height=\"41\" viewBox=\"0 0 64 41\" xmlns=\"http://www.w3.org/2000/svg\"><g transform=\"translate(0 1)\" fill=\"none\" fill-rule=\"evenodd\"><ellipse cx=\"32\" cy=\"33\" rx=\"32\" ry=\"7\" fill=\"#f5f5f5\"/><g fill-rule=\"nonzero\" stroke=\"#d9d9d9\"><path d=\"M55 12.8L44.9 1.3C44.5.5 43.6 0 42.7 0H21.3c-.9 0-1.8.5-2.2 1.3L9 12.8v9.2h46v-9.2z\"/><path d=\"M41.6 16.8a3.5 3.5 0 0 1 3.5 3.5v2c0 .6.4 1 1 1h6.9c.5 0 1-.4 1-1v-2a3.5 3.5 0 0 1 3.5-3.5H55v-3.7H9v3.7h32.6z\" fill=\"#fafafa\"/></g></g></svg>`;\n\nexport default {\n  css: `\n    .ant-empty{ box-sizing:border-box; display:flex; flex-direction:column; align-items:center; justify-content:center; text-align:center; margin:0; padding:16px 0; font-family:var(--ff); }\n    .ant-empty .ant-empty-img{ display:block; }\n    .ant-empty .ant-empty-desc{ margin-top:8px; font-size:var(--fs); color:var(--desc); line-height:1.5; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const description = (p.description != null && p.description !== '') ? String(p.description) : 'No data';\n    const image = (p.image === 'simple') ? 'simple' : 'default';\n    const svg = image === 'simple' ? SIMPLE_SVG : DEFAULT_SVG;\n    const style = ['--fs:'+D.fontSize+'px','--desc:'+D.colorTextTertiary,'--ff:'+D.fontFamily].join(';');\n    return '<div class=\"ant-empty\" style=\"'+style+'\">'\n      + svg\n      + '<div class=\"ant-empty-desc\">'+esc(description)+'</div>'\n      + '</div>';\n  }\n};"}},"description":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"description"}}}},"image":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"image"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efe0156f919e5230f252b","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-popover","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .apo-wrap{ position:relative; display:inline-flex; font-family:var(--ff); }\n    .apo-trigger{ display:inline-flex; align-items:center; gap:6px; cursor:pointer; color:var(--fg);\n      font-size:var(--fs); line-height:1.4; }\n    .apo-trigger .ic{ display:inline-flex; align-items:center; font-size:1em; }\n    .apo-pop{ position:fixed; left:0; top:0; z-index:1200; background:var(--bg); border-radius:var(--radius); min-width:177px;\n      box-shadow:0 6px 16px 0 rgba(0,0,0,.12),0 3px 6px -4px rgba(0,0,0,.08),0 9px 28px 8px rgba(0,0,0,.05);\n      padding:0; opacity:0; transform:scale(.85); pointer-events:none; transition:opacity .15s ease,transform .15s ease; }\n    .apo-wrap.open .apo-pop{ opacity:1; transform:scale(1); pointer-events:auto; }\n    .apo-title{ font-weight:600; color:var(--fg); padding:8px 16px; border-bottom:1px solid var(--bd); font-size:var(--fs); }\n    .apo-content{ color:var(--fg); padding:12px 16px; font-size:var(--fs); line-height:1.6; }\n    .apo-arrow{ position:absolute; width:12px; height:12px; background:var(--bg); transform:rotate(45deg);\n      box-shadow:3px 3px 7px rgba(0,0,0,.07); }\n    .apo-pop.p-top{ transform-origin:bottom center; }\n    .apo-pop.p-top .apo-arrow{ bottom:-6px; left:50%; margin-left:-6px; box-shadow:3px 3px 7px rgba(0,0,0,.07); }\n    .apo-pop.p-bottom{ transform-origin:top center; }\n    .apo-pop.p-bottom .apo-arrow{ top:-6px; left:50%; margin-left:-6px; box-shadow:-2px -2px 5px rgba(0,0,0,.06); }\n    .apo-pop.p-left{ transform-origin:right center; }\n    .apo-pop.p-left .apo-arrow{ right:-6px; top:50%; margin-top:-6px; box-shadow:3px -2px 5px rgba(0,0,0,.06); }\n    .apo-pop.p-right{ transform-origin:left center; }\n    .apo-pop.p-right .apo-arrow{ left:-6px; top:50%; margin-top:-6px; box-shadow:-2px 3px 5px rgba(0,0,0,.06); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const placement = ['top','bottom','left','right'].includes(p.placement) ? p.placement : 'top';\n    const title = p.title != null ? String(p.title) : '';\n    const content = p.content != null ? String(p.content) : '';\n    const label = p.targetLabel != null && p.targetLabel !== '' ? String(p.targetLabel) : 'Click me';\n    const glyph = p.targetGlyph || '';\n    const visible = !!d2.state.visible;\n\n    const style = ['--ff:'+D.fontFamily,'--fs:'+D.fontSize+'px','--fg:'+D.colorText,\n      '--bg:'+D.colorBgContainer,'--bd:'+D.colorBorderSecondary,'--radius:'+D.borderRadiusLG+'px'].join(';');\n\n    const isFa = /(^|\\s)fa[srlbd]?(\\s|-)/.test(glyph);\n    const iconHtml = glyph ? (isFa ? '<i class=\"ic '+esc(glyph)+'\"></i>' : '<span class=\"ic\">'+esc(glyph)+'</span>') : '';\n\n    const titleHtml = title ? '<div class=\"apo-title\">'+esc(title)+'</div>' : '';\n    const contentHtml = content ? '<div class=\"apo-content\">'+esc(content)+'</div>' : '';\n\n    return '<span class=\"apo-wrap'+(visible?' open':'')+'\" style=\"'+style+'\">'\n      + '<span class=\"apo-trigger\">'+iconHtml+'<span>'+esc(label)+'</span></span>'\n      + '<span class=\"apo-pop p-'+placement+'\"><span class=\"apo-arrow\"></span>'+titleHtml+contentHtml+'</span>'\n      + '</span>';\n  },\n  mounted(d2){\n    const trig = d2.param('trigger') === 'click' ? 'click' : 'hover';\n    if(trig === 'click'){\n      d2.on('.apo-trigger','click',(e)=>{ d2.state.visible = !d2.state.visible; });\n      d2.on(document,'click',(e)=>{ if(!d2.state.visible) return; const path=(e.composedPath&&e.composedPath())||[]; if(d2.root && path.indexOf(d2.root)!==-1) return; d2.state.visible=false; });\n    } else {\n      d2.on('.apo-wrap','mouseover',()=>{ d2.state.visible = true; });\n      d2.on('.apo-wrap','mouseout',(e)=>{ if(!d2.root.contains(e.relatedTarget)) d2.state.visible = false; });\n    }\n  },\n  updated(d2){\n    const bubble = d2.$('.apo-pop'), trig = d2.$('.apo-trigger');\n    if(!d2.state.visible) return;\n    if(!trig || !bubble) return;\n    const placement = ['top','bottom','left','right'].includes(d2.param('placement')) ? d2.param('placement') : 'top';\n    const r = trig.getBoundingClientRect();\n    const t = bubble.getBoundingClientRect();\n    const gap = 8; let left, top;\n    if(placement === 'top'){ left = r.left + r.width/2 - t.width/2; top = r.top - t.height - gap; }\n    else if(placement === 'bottom'){ left = r.left + r.width/2 - t.width/2; top = r.bottom + gap; }\n    else if(placement === 'left'){ left = r.left - t.width - gap; top = r.top + r.height/2 - t.height/2; }\n    else { left = r.right + gap; top = r.top + r.height/2 - t.height/2; }\n    bubble.style.left = Math.round(left) + 'px';\n    bubble.style.top = Math.round(top) + 'px';\n  }\n};"}},"title":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"title"}}}},"content":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"content"}}}},"targetLabel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"targetLabel"}}}},"targetGlyph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"targetGlyph"}}}},"trigger":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"trigger"}}}},"placement":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"placement"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efe189421d071c9106694","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-list","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', colorFillAlter:'rgba(0,0,0,0.02)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\n\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\n\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction isFa(g){ return /(^|\\s)fa[srlbd]?(\\s|-)/.test(g); }\nfunction isUrl(s){ return /^(https?:|data:|\\/\\/|\\/)/.test(String(s)); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-list{ box-sizing:border-box; width:100%; font-family:var(--ff); font-size:var(--fs); color:var(--ct); background:var(--bg); position:relative; }\n    .ant-list.bordered{ border:var(--bw) solid var(--cb); border-radius:var(--radius); }\n    .ant-list-header{ padding:var(--pad); color:var(--ct); border-bottom:var(--bw) solid var(--cbs); }\n    .ant-list-footer{ padding:var(--pad); color:var(--ct); border-top:var(--bw) solid var(--cbs); }\n    .ant-list-item{ box-sizing:border-box; display:flex; align-items:flex-start; gap:12px; padding:var(--pad); }\n    .ant-list.split .ant-list-item:not(:last-child){ border-bottom:var(--bw) solid var(--cbs); }\n    .ant-list-item.clickable{ cursor:pointer; transition:background .2s; }\n    .ant-list-item.clickable:hover{ background:var(--cft); }\n    .ant-list-avatar{ flex:0 0 auto; }\n    .ant-list-avatar img{ width:40px; height:40px; border-radius:50%; object-fit:cover; display:block; }\n    .ant-list-avatar .glyph{ width:40px; height:40px; border-radius:50%; background:var(--cft); display:inline-flex; align-items:center; justify-content:center; color:var(--cts); font-size:18px; }\n    .ant-list-main{ flex:1 1 auto; min-width:0; }\n    .ant-list-title{ font-weight:600; color:var(--ct); line-height:1.4; word-break:break-word; }\n    .ant-list-title a{ color:var(--cp); text-decoration:none; }\n    .ant-list-title a:hover{ text-decoration:underline; }\n    .ant-list-desc{ color:var(--cts); font-size:var(--fs); line-height:1.5; margin-top:2px; word-break:break-word; }\n    .ant-list-content{ color:var(--ct); margin-top:8px; line-height:1.5; word-break:break-word; }\n    .ant-list-extra{ flex:0 0 auto; color:var(--cts); margin-left:auto; padding-left:16px; text-align:right; }\n    .ant-list-empty{ padding:32px 16px; text-align:center; color:var(--ctt); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const size = p.size || 'default';\n    const split = p.split !== false;\n    const bordered = !!p.bordered;\n    const data = Array.isArray(p.dataSource) ? p.dataSource : [];\n\n    const padMap = { small:'8px 16px', large:'16px 24px', default:'12px 24px' };\n    const pad = padMap[size] || padMap.default;\n\n    const style = [\n      '--ff:'+D.fontFamily, '--fs:'+D.fontSize+'px',\n      '--ct:'+D.colorText, '--cts:'+D.colorTextSecondary, '--ctt:'+D.colorTextTertiary,\n      '--cp:'+D.colorPrimary,\n      '--cb:'+D.colorBorder, '--cbs:'+D.colorBorderSecondary,\n      '--cft:'+D.colorFillTertiary,\n      '--bg:'+D.colorBgContainer, '--bw:'+D.lineWidth+'px',\n      '--radius:'+D.borderRadiusLG+'px', '--pad:'+pad\n    ].join(';');\n\n    const classes = ['ant-list'];\n    if(split) classes.push('split');\n    if(bordered) classes.push('bordered');\n\n    let html = '<div class=\"'+classes.join(' ')+'\" style=\"'+style+'\">';\n    if(p.header != null && p.header !== '') html += '<div class=\"ant-list-header\">'+esc(p.header)+'</div>';\n\n    if(data.length === 0){\n      html += '<div class=\"ant-list-empty\">No data</div>';\n    } else {\n      for(let i=0;i<data.length;i++){\n        const it = data[i] || {};\n        let avatarHtml = '';\n        if(it.avatar){\n          if(isUrl(it.avatar)) avatarHtml = '<div class=\"ant-list-avatar\"><img src=\"'+esc(it.avatar)+'\" alt=\"\"></div>';\n          else if(isFa(it.avatar)) avatarHtml = '<div class=\"ant-list-avatar\"><span class=\"glyph\"><i class=\"'+esc(it.avatar)+'\"></i></span></div>';\n          else avatarHtml = '<div class=\"ant-list-avatar\"><span class=\"glyph\">'+esc(it.avatar)+'</span></div>';\n        }\n        let titleInner = esc(it.title);\n        if(it.href) titleInner = '<a href=\"'+esc(it.href)+'\">'+esc(it.title)+'</a>';\n        let main = '<div class=\"ant-list-main\">';\n        if(it.title != null && it.title !== '') main += '<div class=\"ant-list-title\">'+titleInner+'</div>';\n        if(it.description != null && it.description !== '') main += '<div class=\"ant-list-desc\">'+esc(it.description)+'</div>';\n        if(it.content != null && it.content !== '') main += '<div class=\"ant-list-content\">'+esc(it.content)+'</div>';\n        main += '</div>';\n        const extra = (it.extra != null && it.extra !== '') ? '<div class=\"ant-list-extra\">'+esc(it.extra)+'</div>' : '';\n        html += '<div class=\"ant-list-item clickable\" data-idx=\"'+i+'\" data-key=\"row-'+i+'\">'+avatarHtml+main+extra+'</div>';\n      }\n    }\n    html += '</div>';\n    return html;\n  },\n  mounted(d2){\n    d2.on('.ant-list-item','click',(e,el)=>{\n      const idx = parseInt(el.getAttribute('data-idx'),10);\n      if(!isNaN(idx)) d2.emit('onItemClick', idx);\n    });\n  }\n};"}},"dataSource":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"dataSource"}}}},"header":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"header"}}}},"footer":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"footer"}}}},"bordered":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bordered"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"split":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"split"}}}},"onItemClick":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onItemClick"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efe280e623bb3377fe205","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-popconfirm","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorSuccessBg:'#f6ffed', colorWarning:'#faad14', colorWarningBg:'#fffbe6', colorError:'#ff4d4f', colorErrorHover:'#ff7875', colorErrorActive:'#d9363e', colorErrorBg:'#fff2f0', colorInfo:'#1677ff', colorInfoBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgContainerDisabled:'rgba(0,0,0,0.04)', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFill:'rgba(0,0,0,0.15)', borderRadius:6, borderRadiusSM:4, borderRadiusLG:8, controlHeight:32, controlHeightSM:24, controlHeightLG:40, fontSize:14, fontSizeSM:12, fontSizeLG:16, lineWidth:1, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; if((tk.density||'comfortable')==='compact'){D.controlHeight=28;D.controlHeightSM=22;D.controlHeightLG=36;} return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .apc-wrap{ position:relative; display:inline-flex; font-family:var(--ff); }\n    .apc-trigger{ display:inline-flex; align-items:center; gap:6px; cursor:pointer; color:var(--fg);\n      font-size:var(--fs); line-height:1.4; }\n    .apc-trigger .ic{ display:inline-flex; align-items:center; font-size:1em; }\n    .apc-pop{ position:fixed; left:0; top:0; z-index:1200; background:var(--bg); border-radius:var(--radius); min-width:177px; max-width:300px;\n      box-shadow:0 6px 16px 0 rgba(0,0,0,.12),0 3px 6px -4px rgba(0,0,0,.08),0 9px 28px 8px rgba(0,0,0,.05);\n      padding:12px 16px; opacity:0; transform:scale(.85); pointer-events:none; transition:opacity .15s ease,transform .15s ease; }\n    .apc-wrap.open .apc-pop{ opacity:1; transform:scale(1); pointer-events:auto; }\n    .apc-body{ display:flex; gap:8px; align-items:flex-start; }\n    .apc-warn{ color:var(--warn); font-size:var(--fs); line-height:1.5; flex:0 0 auto; margin-top:1px; }\n    .apc-texts{ flex:1 1 auto; }\n    .apc-title{ font-weight:600; color:var(--fg); font-size:var(--fs); line-height:1.5; }\n    .apc-desc{ color:var(--fg2); font-size:var(--fs); line-height:1.5; margin-top:4px; }\n    .apc-footer{ display:flex; justify-content:flex-end; gap:8px; margin-top:12px; }\n    .apc-btn{ box-sizing:border-box; display:inline-flex; align-items:center; justify-content:center;\n      height:var(--bh); padding:0 8px; font-size:var(--fsm); font-family:var(--ff); font-weight:400; line-height:1;\n      white-space:nowrap; border-radius:var(--radiusSM); border:1px solid transparent; cursor:pointer; outline:none;\n      transition:all .2s cubic-bezier(.4,0,.2,1); }\n    .apc-btn.cancel{ background:var(--bg); color:var(--fg); border-color:var(--border); }\n    .apc-btn.cancel:hover{ color:var(--primaryH); border-color:var(--primaryH); }\n    .apc-btn.ok{ background:var(--okBg); color:#fff; border-color:var(--okBg); }\n    .apc-btn.ok:hover{ background:var(--okBgH); border-color:var(--okBgH); }\n    .apc-arrow{ position:absolute; width:12px; height:12px; background:var(--bg); transform:rotate(45deg);\n      box-shadow:3px 3px 7px rgba(0,0,0,.07); }\n    .apc-pop.p-top{ transform-origin:bottom center; }\n    .apc-pop.p-top .apc-arrow{ bottom:-6px; left:50%; margin-left:-6px; box-shadow:3px 3px 7px rgba(0,0,0,.07); }\n    .apc-pop.p-bottom{ transform-origin:top center; }\n    .apc-pop.p-bottom .apc-arrow{ top:-6px; left:50%; margin-left:-6px; box-shadow:-2px -2px 5px rgba(0,0,0,.06); }\n    .apc-pop.p-left{ transform-origin:right center; }\n    .apc-pop.p-left .apc-arrow{ right:-6px; top:50%; margin-top:-6px; box-shadow:3px -2px 5px rgba(0,0,0,.06); }\n    .apc-pop.p-right{ transform-origin:left center; }\n    .apc-pop.p-right .apc-arrow{ left:-6px; top:50%; margin-top:-6px; box-shadow:-2px 3px 5px rgba(0,0,0,.06); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const placement = ['top','bottom','left','right'].includes(p.placement) ? p.placement : 'top';\n    const title = p.title != null && p.title !== '' ? String(p.title) : 'Are you sure?';\n    const description = p.description != null ? String(p.description) : '';\n    const label = p.targetLabel != null && p.targetLabel !== '' ? String(p.targetLabel) : 'Delete';\n    const glyph = p.targetGlyph || '';\n    const warnGlyph = p.glyph || 'fa fa-exclamation-circle';\n    const okText = p.okText != null && p.okText !== '' ? String(p.okText) : 'Yes';\n    const cancelText = p.cancelText != null && p.cancelText !== '' ? String(p.cancelText) : 'No';\n    const okDanger = !!p.okDanger;\n    const visible = !!d2.state.visible;\n\n    const okBg = okDanger ? D.colorError : D.colorPrimary;\n    const okBgH = okDanger ? D.colorErrorHover : D.colorPrimaryHover;\n\n    const style = ['--ff:'+D.fontFamily,'--fs:'+D.fontSize+'px','--fsm:'+D.fontSizeSM+'px','--fg:'+D.colorText,\n      '--fg2:'+D.colorTextSecondary,'--bg:'+D.colorBgContainer,'--border:'+D.colorBorder,\n      '--warn:'+D.colorWarning,'--primaryH:'+D.colorPrimaryHover,\n      '--okBg:'+okBg,'--okBgH:'+okBgH,'--bh:'+D.controlHeightSM+'px',\n      '--radius:'+D.borderRadiusLG+'px','--radiusSM:'+D.borderRadiusSM+'px'].join(';');\n\n    const isFa = /(^|\\s)fa[srlbd]?(\\s|-)/.test(glyph);\n    const iconHtml = glyph ? (isFa ? '<i class=\"ic '+esc(glyph)+'\"></i>' : '<span class=\"ic\">'+esc(glyph)+'</span>') : '';\n\n    const isFaW = /(^|\\s)fa[srlbd]?(\\s|-)/.test(warnGlyph);\n    const warnHtml = isFaW ? '<i class=\"apc-warn '+esc(warnGlyph)+'\"></i>' : '<span class=\"apc-warn\">'+esc(warnGlyph)+'</span>';\n\n    const descHtml = description ? '<div class=\"apc-desc\">'+esc(description)+'</div>' : '';\n\n    return '<span class=\"apc-wrap'+(visible?' open':'')+'\" style=\"'+style+'\">'\n      + '<span class=\"apc-trigger\">'+iconHtml+'<span>'+esc(label)+'</span></span>'\n      + '<span class=\"apc-pop p-'+placement+'\"><span class=\"apc-arrow\"></span>'\n      + '<div class=\"apc-body\">'+warnHtml+'<div class=\"apc-texts\"><div class=\"apc-title\">'+esc(title)+'</div>'+descHtml+'</div></div>'\n      + '<div class=\"apc-footer\"><button type=\"button\" class=\"apc-btn cancel\">'+esc(cancelText)+'</button>'\n      + '<button type=\"button\" class=\"apc-btn ok\">'+esc(okText)+'</button></div>'\n      + '</span>'\n      + '</span>';\n  },\n  mounted(d2){\n    d2.on('.apc-trigger','click',(e)=>{ d2.state.visible = !d2.state.visible; });\n    d2.on('.apc-btn.cancel','click',(e)=>{ e.stopPropagation(); d2.state.visible = false; d2.emit('onCancel', {}); });\n    d2.on('.apc-btn.ok','click',(e)=>{ e.stopPropagation(); d2.state.visible = false; d2.emit('onConfirm', {}); });\n    d2.on(document,'click',(e)=>{\n      if(!d2.state.visible) return;\n      const path=(e.composedPath&&e.composedPath())||[];\n      if(d2.root && path.indexOf(d2.root)!==-1) return;\n      d2.state.visible=false;\n    });\n  },\n  updated(d2){\n    const pop = d2.$('.apc-pop'), trig = d2.$('.apc-trigger');\n    if(!pop || !trig) return;\n    if(!d2.state.visible){ return; }\n    const placement = ['top','bottom','left','right'].includes(d2.param('placement')) ? d2.param('placement') : 'top';\n    const r = trig.getBoundingClientRect();\n    const t = pop.getBoundingClientRect();\n    const gap = 10; let left, top;\n    if(placement === 'top'){ left = r.left + r.width/2 - t.width/2; top = r.top - t.height - gap; }\n    else if(placement === 'bottom'){ left = r.left + r.width/2 - t.width/2; top = r.bottom + gap; }\n    else if(placement === 'left'){ left = r.left - t.width - gap; top = r.top + r.height/2 - t.height/2; }\n    else { left = r.right + gap; top = r.top + r.height/2 - t.height/2; }\n    pop.style.left = Math.round(left) + 'px';\n    pop.style.top = Math.round(top) + 'px';\n  }\n};"}},"title":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"title"}}}},"description":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"description"}}}},"targetLabel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"targetLabel"}}}},"targetGlyph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"targetGlyph"}}}},"okText":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"okText"}}}},"cancelText":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cancelText"}}}},"okDanger":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"okDanger"}}}},"glyph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"glyph"}}}},"placement":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"placement"}}}},"onConfirm":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onConfirm"}}}},"onCancel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onCancel"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a2efe342ae3e526cfd2b277","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-table","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', colorFillAlter:'rgba(0,0,0,0.02)', borderRadius:6, borderRadiusLG:8, fontSize:14, lineWidth:1, controlHeight:32, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\n\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nfunction rowKey(row, i){ return (row && row.key!=null && row.key!=='') ? String(row.key) : (row && row._id!=null ? String(row._id) : String(i)); }\nfunction svg(inner, size){ return '<svg width=\"'+(size||14)+'\" height=\"'+(size||14)+'\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">'+inner+'</svg>'; }\nconst SVG_FILTER = svg('<polygon points=\"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\"/>', 12);\nconst SVG_DOTS = '<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><circle cx=\"12\" cy=\"5\" r=\"1.6\"/><circle cx=\"12\" cy=\"12\" r=\"1.6\"/><circle cx=\"12\" cy=\"19\" r=\"1.6\"/></svg>';\nconst SVG_PREV = svg('<path d=\"m15 18-6-6 6-6\"/>', 14);\nconst SVG_NEXT = svg('<path d=\"m9 18 6-6-6-6\"/>', 14);\nconst SVG_UP = svg('<path d=\"m18 15-6-6-6 6\"/>', 13);\nconst SVG_DOWN = svg('<path d=\"m6 9 6 6 6-6\"/>', 13);\nconst SVG_UPDOWN = svg('<path d=\"m7 15 5 5 5-5\"/><path d=\"m7 9 5-5 5 5\"/>', 13);\nconst SVG_CHECK = svg('<path d=\"M20 6 9 17l-5-5\"/>', 14);\nconst cleanNum = s => String(s==null?'':s).replace(/[^0-9.\\-]/g,'');\n\nexport default {\n  css: `\n    .att-wrap{ box-sizing:border-box; width:100%; font-family:var(--ff); position:relative; color:var(--ct); }\n    .att-toolbar{ display:flex; align-items:center; gap:10px; margin-bottom:10px; }\n    .att-search{ width:240px; max-width:60%; padding:6px 11px; border:var(--bw) solid var(--cbs); border-radius:var(--radius); font-size:var(--fs); outline:none; background:var(--bg); color:var(--ct); }\n    .att-search:focus{ border-color:var(--cp); }\n    .att-count{ margin-left:auto; font-size:12px; color:var(--ctt); }\n    .att-table-box{ border:var(--bw) solid transparent; border-radius:var(--radius); overflow-x:hidden; overflow-y:auto; max-height:560px; }\n    .att-table-box table.att thead th{ position:sticky; top:0; z-index:1; }\n    .att-table-box.bordered{ border-color:var(--cbs); }\n    table.att{ border-collapse:collapse; width:100%; font-size:var(--fs); color:var(--ct); background:var(--bg); }\n    table.att th{ background:var(--cfa); color:var(--ct); font-weight:600; text-align:left; padding:var(--pad); border-bottom:var(--bw) solid var(--cbs); white-space:nowrap; }\n    table.att td{ padding:var(--pad); border-bottom:var(--bw) solid var(--cbs); color:var(--ct); }\n    table.att tbody tr{ transition:background .15s; }\n    table.att tbody tr.clickable{ cursor:pointer; }\n    table.att tbody tr:hover{ background:var(--cft); }\n    .att-table-box.bordered table.att th, .att-table-box.bordered table.att td{ border-right:var(--bw) solid var(--cbs); }\n    .att-table-box.bordered table.att th:last-child, .att-table-box.bordered table.att td:last-child{ border-right:none; }\n    .att-empty td{ text-align:center; color:var(--ctt); padding:32px 16px; }\n    .att-th-inner{ display:inline-flex; align-items:center; gap:5px; }\n    .att-th-inner.sortable{ cursor:pointer; user-select:none; }\n    .att-th-inner.sortable:hover{ color:var(--cp); }\n    .att-sort{ display:inline-flex; opacity:.3; }\n    .att-sort.on{ opacity:1; color:var(--cp); }\n    .att-funnel{ cursor:pointer; opacity:.4; border:0; background:none; color:var(--ct); padding:0 2px; display:inline-flex; }\n    .att-funnel:hover, .att-funnel.on{ opacity:1; color:var(--cp); }\n    .att-funnel svg, .att-sort svg, .att-kebab svg, .att-pg svg{ display:block; }\n    .att-actcell{ width:44px; text-align:center; }\n    .att-kebab{ cursor:pointer; border:0; background:none; color:var(--ctt); padding:2px 6px; border-radius:6px; display:inline-flex; }\n    .att-kebab:hover{ background:var(--cft); color:var(--ct); }\n    .att-pop{ position:fixed; z-index:9999; background:var(--bg); border:var(--bw) solid var(--cbs); border-radius:8px; box-shadow:0 8px 28px rgba(0,0,0,.18); padding:4px; min-width:170px; }\n    .att-pop button{ display:flex; align-items:center; gap:8px; width:100%; text-align:left; border:0; background:none; padding:8px 10px; font:inherit; font-size:13px; color:var(--ct); cursor:pointer; border-radius:6px; }\n    .att-pop button:hover{ background:var(--cft); }\n    .att-pop button.danger{ color:#cf1322; }\n    .att-pop .att-aci{ display:inline-flex; align-items:center; }\n    .att-filter{ position:fixed; z-index:9999; background:var(--bg); border:var(--bw) solid var(--cbs); border-radius:8px; box-shadow:0 8px 28px rgba(0,0,0,.18); padding:6px; min-width:180px; max-height:280px; overflow:auto; }\n    .att-fopt{ display:flex; align-items:center; gap:8px; padding:7px 8px; font-size:13px; cursor:pointer; border-radius:6px; color:var(--ct); }\n    .att-fopt:hover{ background:var(--cft); }\n    .att-fopt.on{ color:var(--cp); font-weight:600; }\n    .att-fck{ width:16px; height:16px; display:inline-flex; align-items:center; justify-content:center; color:var(--cp); }\n    .att-filter-foot{ display:flex; justify-content:space-between; border-top:var(--bw) solid var(--cbs); margin-top:4px; padding-top:6px; }\n    .att-filter-foot button{ border:0; background:none; font-size:12px; color:var(--cp); cursor:pointer; }\n    .att-pager{ display:flex; align-items:center; gap:6px; justify-content:flex-end; margin-top:12px; }\n    .att-pg{ min-width:30px; height:30px; padding:0 8px; display:inline-flex; align-items:center; justify-content:center; border:var(--bw) solid var(--cbs); background:var(--bg); color:var(--ct); border-radius:6px; cursor:pointer; font-size:13px; }\n    .att-pg:hover:not(:disabled){ border-color:var(--cp); color:var(--cp); }\n    .att-pg.on{ border-color:var(--cp); color:var(--cp); font-weight:600; }\n    .att-pg:disabled{ opacity:.4; cursor:not-allowed; }\n  `,\n\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const size = p.size || 'default';\n    const bordered = !!p.bordered;\n    const showHeader = p.showHeader !== false;\n    const searchable = !!p.searchable;\n    const sortableDefault = p.sortable !== false;\n    const cols = Array.isArray(p.columns) ? p.columns : [];\n    const actions = Array.isArray(p.rowActions) ? p.rowActions : [];\n\n    let all = Array.isArray(p.dataSource) ? p.dataSource : [];\n    if(all.length === 0 && typeof d2.data === 'function'){ try{ const recs = d2.data().records(); if(Array.isArray(recs)) all = recs; }catch(e){} }\n\n    const padMap = { small:'8px 8px', large:'16px 16px', middle:'12px 8px' };\n    const pad = padMap[size] || padMap.middle;\n\n    const q = (d2.state.q || '').toLowerCase();\n    let filtered = all;\n    if(searchable && q){ filtered = filtered.filter(row => cols.some(c => c.dataIndex!=null && String(row[c.dataIndex]==null?'':row[c.dataIndex]).toLowerCase().indexOf(q)!==-1)); }\n    const cf = d2.state.colFilters || {};\n    cols.forEach(c => { const selv = cf[c.dataIndex]; if(selv && selv.length){ filtered = filtered.filter(row => selv.indexOf(String(row[c.dataIndex])) !== -1); } });\n\n    // sort\n    if(d2.state.sortBy != null && d2.state.sortBy !== ''){\n      const sb = d2.state.sortBy, dir = d2.state.sortDir === 'desc' ? -1 : 1;\n      filtered = filtered.slice().sort((a,b)=>{\n        const ax = a[sb], bx = b[sb]; const ca = cleanNum(ax), cb = cleanNum(bx);\n        if(ca!=='' && cb!=='' && !isNaN(parseFloat(ca)) && !isNaN(parseFloat(cb))) return (parseFloat(ca)-parseFloat(cb))*dir;\n        const sa = String(ax==null?'':ax).toLowerCase(), sbv = String(bx==null?'':bx).toLowerCase();\n        return (sa<sbv?-1:sa>sbv?1:0)*dir;\n      });\n    }\n\n    const total = filtered.length;\n    let ps = (p.pageSize!=null && p.pageSize!=='') ? Math.floor(Number(p.pageSize)) : 8;\n    if(!(ps > 0)) ps = 8;\n    const pages = Math.max(1, Math.ceil(total / ps));\n    let page = Math.min(Math.max(1, d2.state.page || 1), pages);\n    const showPager = total > ps;\n    const pageRows = filtered.slice((page-1)*ps, (page-1)*ps + ps);\n\n    const style = [ '--ff:'+D.fontFamily, '--fs:'+D.fontSize+'px', '--ct:'+D.colorText, '--ctt:'+D.colorTextTertiary, '--cbs:'+D.colorBorderSecondary, '--cft:'+D.colorFillTertiary, '--cfa:'+D.colorFillAlter, '--bg:'+D.colorBgContainer, '--cp:'+D.colorPrimary, '--bw:'+D.lineWidth+'px', '--radius:'+D.borderRadius+'px', '--pad:'+pad ].join(';');\n    const colCount = cols.length + (actions.length ? 1 : 0) || 1;\n\n    let toolbar = '';\n    if(searchable){ toolbar = '<div class=\"att-toolbar\"><input class=\"att-search\" placeholder=\"'+esc(p.searchPlaceholder||'Search…')+'\" value=\"'+esc(d2.state.q||'')+'\" /><span class=\"att-count\">'+total+' items</span></div>'; }\n\n    let head = '';\n    if(showHeader && cols.length){\n      head += '<thead><tr>';\n      for(let c=0;c<cols.length;c++){\n        const col = cols[c] || {};\n        const align = col.align ? 'text-align:'+esc(col.align)+';' : '';\n        const w = (col.width!=null && col.width!=='') ? 'width:'+esc(typeof col.width==='number'?col.width+'px':col.width)+';' : '';\n        const st = (align||w) ? ' style=\"'+align+w+'\"' : '';\n        const canSort = col.sortable!==false && sortableDefault && col.dataIndex!=null;\n        const isActive = d2.state.sortBy === col.dataIndex;\n        const sortIco = canSort ? '<span class=\"att-sort '+(isActive?'on':'')+'\">'+(isActive ? (d2.state.sortDir==='desc'?SVG_DOWN:SVG_UP) : SVG_UPDOWN)+'</span>' : '';\n        const hasFilter = (Array.isArray(col.filters) && col.filters.length) || col.filterable;\n        const active = cf[col.dataIndex] && cf[col.dataIndex].length;\n        const funnel = hasFilter ? '<button class=\"att-funnel '+(active?'on':'')+'\" data-act=\"filter\" data-col=\"'+c+'\" data-fcol=\"'+c+'\">'+SVG_FILTER+'</button>' : '';\n        head += '<th'+st+'><span class=\"att-th-inner '+(canSort?'sortable':'')+'\" '+(canSort?'data-act=\"sort\" data-col=\"'+c+'\"':'')+'>'+esc(col.title)+sortIco+funnel+'</span></th>';\n      }\n      if(actions.length) head += '<th class=\"att-actcell\"></th>';\n      head += '</tr></thead>';\n    }\n\n    let body = '<tbody>';\n    if(pageRows.length === 0){ body += '<tr class=\"att-empty\"><td colspan=\"'+colCount+'\">No data</td></tr>'; }\n    else {\n      for(let r=0;r<pageRows.length;r++){\n        const row = pageRows[r] || {};\n        const rk = rowKey(row, (page-1)*ps + r);\n        body += '<tr class=\"clickable\" data-act=\"row\" data-rk=\"'+esc(rk)+'\">';\n        for(let c=0;c<cols.length;c++){ const col = cols[c] || {}; const align = col.align ? ' style=\"text-align:'+esc(col.align)+';\"' : ''; const cell = col.dataIndex!=null ? row[col.dataIndex] : ''; body += '<td'+align+'>'+esc(cell)+'</td>'; }\n        if(actions.length){ body += '<td class=\"att-actcell\"><button class=\"att-kebab\" data-act=\"rowmenu\" data-rk=\"'+esc(rk)+'\" data-rmk=\"'+esc(rk)+'\">'+SVG_DOTS+'</button></td>'; }\n        body += '</tr>';\n      }\n    }\n    body += '</tbody>';\n\n    let pops = '';\n    if(d2.state.menuFor != null && actions.length){\n      pops += '<div class=\"att-pop\">' + actions.map(a => '<button data-act=\"rowaction\" data-rk=\"'+esc(d2.state.menuFor)+'\" data-ak=\"'+esc(a.key)+'\" class=\"'+(a.danger?'danger':'')+'\">'+(a.glyph?'<span class=\"att-aci\">'+a.glyph+'</span>':'')+esc(a.label)+'</button>').join('') + '</div>';\n    }\n    if(d2.state.filterFor != null){\n      const ci = Number(d2.state.filterFor); const col = cols[ci] || {};\n      let opts = Array.isArray(col.filters) && col.filters.length ? col.filters.map(f => ({text:f.text, value:String(f.value)})) : [];\n      if(!opts.length){ const seen={}; const arr=[]; all.forEach(rw=>{ const v=String(rw[col.dataIndex]==null?'':rw[col.dataIndex]); if(v!=='' && !seen[v]){ seen[v]=1; arr.push({text:v, value:v}); } }); opts = arr; }\n      const cur = (cf[col.dataIndex]||[]);\n      pops += '<div class=\"att-filter\">' + opts.map(o => '<div class=\"att-fopt '+(cur.indexOf(o.value)!==-1?'on':'')+'\" data-act=\"filteropt\" data-col=\"'+ci+'\" data-val=\"'+esc(o.value)+'\"><span class=\"att-fck\">'+(cur.indexOf(o.value)!==-1?SVG_CHECK:'')+'</span>'+esc(o.text)+'</div>').join('') + '<div class=\"att-filter-foot\"><button data-act=\"filterreset\" data-col=\"'+ci+'\">Reset</button><button data-act=\"filterclose\">Done</button></div></div>';\n    }\n\n    let pager = '';\n    if(showPager){\n      let btns = '<button class=\"att-pg\" data-act=\"page\" data-p=\"'+(page-1)+'\" '+(page<=1?'disabled':'')+'>'+SVG_PREV+'</button>';\n      const win = []; for(let i=1;i<=pages;i++){ if(i===1||i===pages||(i>=page-1&&i<=page+1)) win.push(i); }\n      let last=0; win.forEach(i => { if(last && i-last>1) btns += '<span class=\"att-pg\" style=\"border:none;cursor:default\">…</span>'; btns += '<button class=\"att-pg '+(i===page?'on':'')+'\" data-act=\"page\" data-p=\"'+i+'\">'+i+'</button>'; last=i; });\n      btns += '<button class=\"att-pg\" data-act=\"page\" data-p=\"'+(page+1)+'\" '+(page>=pages?'disabled':'')+'>'+SVG_NEXT+'</button>';\n      pager = '<div class=\"att-pager\"><span class=\"att-count\" style=\"margin-right:auto\">'+total+' items</span>'+btns+'</div>';\n    }\n\n    return '<div class=\"att-wrap\" style=\"'+style+'\">'+toolbar+'<div class=\"att-table-box '+(bordered?'bordered':'')+'\"><table class=\"att\">'+head+body+'</table></div>'+pager+pops+'</div>';\n  },\n\n  mounted(d2){\n    if(typeof d2.data === 'function'){ try{ const ds=d2.data(); if(ds && typeof ds.records==='function' && ds.records().length===0 && typeof ds.refresh==='function') ds.refresh(); }catch(e){} }\n    const cols = () => Array.isArray(d2.params.columns) ? d2.params.columns : [];\n    const findRow = (rk) => { const p=d2.params||{}; let all=Array.isArray(p.dataSource)?p.dataSource:[]; if(all.length===0&&typeof d2.data==='function'){ try{all=d2.data().records()||[];}catch(e){} } for(let i=0;i<all.length;i++){ if(rowKey(all[i],i)===String(rk)) return all[i]; } return null; };\n    const writeSelection = (ak, rk, row) => { try{ const sref=(d2.params&&d2.params.selectionStore)?d2.params.selectionStore:null; if(!sref) return; let s=null; try{ s=d2.store(sref); }catch(e2){} if(s){ s.set('actionType', ak); s.set('actionKey', String(rk)); s.set('actionRow', row?JSON.stringify(row):''); if(row&&typeof row==='object'){ for(const k in row){ const v=row[k]; if(v==null||typeof v==='object')continue; s.set('draft_'+k, v); } } } }catch(e){} };\n\n    d2.on('.att-search','input',(e)=>{ d2.state._focus=true; d2.state.q=e.target.value; d2.state.page=1; });\n\n    d2.on('[data-act=\"sort\"]','click',(e,el)=>{\n      if(e.target.closest('[data-act=\"filter\"]')) return;\n      const ci = Number(el.getAttribute('data-col')); const di = (cols()[ci]||{}).dataIndex; if(di==null) return;\n      if(d2.state.sortBy !== di){ d2.state.sortBy = di; d2.state.sortDir = 'asc'; }\n      else if(d2.state.sortDir === 'asc'){ d2.state.sortDir = 'desc'; }\n      else { d2.state.sortBy = null; d2.state.sortDir = null; }\n    });\n\n    d2.on('tr[data-act=\"row\"]','click',(e,el)=>{ if(e.target.closest('[data-act=\"rowmenu\"]')) return; const rk = el.getAttribute('data-rk'); const row=findRow(rk); writeSelection('row', rk, row); d2.emit('onRowClick', { row: row, key: rk }); });\n\n    d2.on('[data-act=\"rowmenu\"]','click',(e,el)=>{ const rk = el.getAttribute('data-rk'); d2.state.filterFor=null; d2.state.menuFor = (String(d2.state.menuFor)===String(rk)) ? null : rk; });\n    d2.on('[data-act=\"rowaction\"]','click',(e,el)=>{ const rk=el.getAttribute('data-rk'), ak=el.getAttribute('data-ak'); d2.state.menuFor=null; const row=findRow(rk); writeSelection(ak, rk, row); d2.emit('onAction', { action:ak, key:rk, row:row }); });\n\n    d2.on('[data-act=\"filter\"]','click',(e,el)=>{ const ci=el.getAttribute('data-col'); d2.state.menuFor=null; d2.state.filterFor = (String(d2.state.filterFor)===String(ci)) ? null : ci; });\n    d2.on('[data-act=\"filteropt\"]','click',(e,el)=>{\n      const ci = Number(el.getAttribute('data-col')); const di = (cols()[ci]||{}).dataIndex; const val = el.getAttribute('data-val');\n      const c = Object.assign({}, d2.state.colFilters||{}); const arr = (c[di]||[]).slice(); const idx = arr.indexOf(val);\n      if(idx===-1) arr.push(val); else arr.splice(idx,1);\n      c[di] = arr; d2.state.colFilters = c; d2.state.page = 1;\n    });\n    d2.on('[data-act=\"filterreset\"]','click',(e,el)=>{ const ci=Number(el.getAttribute('data-col')); const di=(cols()[ci]||{}).dataIndex; const c=Object.assign({},d2.state.colFilters||{}); delete c[di]; d2.state.colFilters=c; d2.state.filterFor=null; d2.state.page=1; });\n    d2.on('[data-act=\"filterclose\"]','click',()=>{ d2.state.filterFor=null; });\n\n    d2.on('[data-act=\"page\"]','click',(e,el)=>{ const pg=parseInt(el.getAttribute('data-p'),10); if(!isNaN(pg)) d2.state.page=pg; });\n\n    d2.on(document,'click',(e)=>{\n      if(d2.state.menuFor==null && d2.state.filterFor==null) return;\n      const path = e.composedPath ? e.composedPath() : [];\n      for(let i=0;i<path.length;i++){ const n=path[i]; if(n && n.getAttribute){ const a=n.getAttribute('data-act'); if(a==='rowmenu'||a==='filter'||a==='rowaction'||a==='filteropt'||a==='filterreset') return; } if(n && n.classList && (n.classList.contains('att-pop')||n.classList.contains('att-filter'))) return; }\n      d2.state.menuFor=null; d2.state.filterFor=null;\n    });\n  },\n\n  updated(d2, root){\n    if(d2.state._focus){ const el=root.querySelector('.att-search'); if(el && document.activeElement!==el){ el.focus(); const n=el.value.length; el.setSelectionRange(n,n); } }\n    const place = (trigSel, popSel) => { const t=root.querySelector(trigSel), m=root.querySelector(popSel); if(t&&m){ const r=t.getBoundingClientRect(); let left=r.left; const mw=m.offsetWidth||180; if(left+mw > window.innerWidth-8) left=window.innerWidth-mw-8; m.style.top=(r.bottom+4)+'px'; m.style.left=Math.max(8,left)+'px'; } };\n    if(d2.state.menuFor != null) place('[data-rmk=\"'+d2.state.menuFor+'\"]', '.att-pop');\n    if(d2.state.filterFor != null) place('[data-fcol=\"'+d2.state.filterFor+'\"]', '.att-filter');\n  }\n};"}},"columns":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"columns"}}}},"dataSource":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"dataSource"}}}},"dataset":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"dataset"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"bordered":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bordered"}}}},"showHeader":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"showHeader"}}}},"pageSize":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"pageSize"}}}},"searchable":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"searchable"}}}},"searchPlaceholder":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"searchPlaceholder"}}}},"sortable":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"sortable"}}}},"rowActions":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rowActions"}}}},"onRowClick":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onRowClick"}}}},"onAction":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onAction"}}}},"selectionStore":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"selectionStore"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a3045f10e623bb33782223d","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-statistic","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorSuccess:'#52c41a', colorWarning:'#faad14', colorError:'#ff4d4f', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusLG:8, fontSize:14, fontSizeLG:16, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-stat{ box-sizing:border-box; display:inline-block; font-family:var(--ff); line-height:1.4; }\n    .ant-stat .stat-title{ font-size:var(--fs); color:var(--c-sec); margin-bottom:4px; }\n    .ant-stat .stat-value{ display:inline-flex; align-items:baseline; gap:4px; font-size:24px; color:var(--c-val); font-variant-numeric:tabular-nums; }\n    .ant-stat .stat-glyph{ font-size:20px; display:inline-flex; align-items:center; }\n    .ant-stat .stat-prefix, .ant-stat .stat-suffix{ font-size:var(--fs-lg); color:var(--c-sec); }\n    .ant-stat .stat-suffix{ font-size:var(--fs); }\n    .ant-stat .stat-main{ font-size:24px; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const title = p.title != null ? String(p.title) : '';\n    const rawValue = p.value != null ? String(p.value) : '';\n    const precision = (p.precision != null && p.precision !== '') ? Number(p.precision) : null;\n    const prefix = p.prefix != null ? String(p.prefix) : '';\n    const suffix = p.suffix != null ? String(p.suffix) : '';\n    let valueColor = p.valueColor;\n    if(valueColor && typeof valueColor === 'object') valueColor = valueColor.rgba || valueColor.hex || valueColor.value || valueColor.color || '';\n    valueColor = (valueColor == null || valueColor === '') ? D.colorText : String(valueColor);\n    const glyph = p.glyph || '';\n\n    let displayValue = rawValue;\n    const num = Number(rawValue);\n    if(precision != null && !isNaN(precision) && rawValue !== '' && !isNaN(num)){\n      displayValue = num.toFixed(Math.max(0, Math.floor(precision)));\n    }\n\n    const style = [\n      '--ff:'+D.fontFamily,\n      '--fs:'+D.fontSize+'px',\n      '--fs-lg:'+D.fontSizeLG+'px',\n      '--c-sec:'+D.colorTextSecondary,\n      '--c-val:'+valueColor\n    ].join(';');\n\n    const isFa = /(^|\\s)fa[srlbd]?(\\s|-)/.test(glyph);\n    const glyphHtml = glyph ? (isFa ? '<span class=\"stat-glyph\"><i class=\"'+esc(glyph)+'\"></i></span>' : '<span class=\"stat-glyph\">'+esc(glyph)+'</span>') : '';\n    const prefixHtml = prefix ? '<span class=\"stat-prefix\">'+esc(prefix)+'</span>' : '';\n    const suffixHtml = suffix ? '<span class=\"stat-suffix\">'+esc(suffix)+'</span>' : '';\n    const titleHtml = title ? '<div class=\"stat-title\">'+esc(title)+'</div>' : '';\n\n    return '<div class=\"ant-stat\" style=\"'+style+'\">'+titleHtml+\n      '<div class=\"stat-value\">'+glyphHtml+prefixHtml+'<span class=\"stat-main\">'+esc(displayValue)+'</span>'+suffixHtml+'</div>'+\n      '</div>';\n  }\n};"}},"title":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"title"}}}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"precision":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"precision"}}}},"prefix":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"prefix"}}}},"suffix":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"suffix"}}}},"valueColor":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"valueColor"}}}},"glyph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"glyph"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a30460f0e623bb3378222be","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-timeline","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorSuccess:'#52c41a', colorWarning:'#faad14', colorError:'#ff4d4f', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusLG:8, fontSize:14, fontSizeLG:16, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nfunction dotColor(D, color){\n  if(color == null || color === '') return D.colorPrimary;\n  if(typeof color === 'object') color = color.rgba || color.hex || color.value || color.color || '';\n  const c = String(color).trim();\n  const named = { blue:D.colorPrimary, green:D.colorSuccess, red:D.colorError, gray:D.colorTextTertiary, grey:D.colorTextTertiary };\n  if(named[c.toLowerCase()]) return named[c.toLowerCase()];\n  return c;\n}\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-tl{ box-sizing:border-box; font-family:var(--ff); font-size:var(--fs); color:var(--c-text); list-style:none; margin:0; padding:0; }\n    .ant-tl .tl-item{ position:relative; display:flex; padding-bottom:20px; }\n    .ant-tl .tl-item:last-child{ padding-bottom:0; }\n    .ant-tl .tl-rail{ position:relative; flex:0 0 auto; width:12px; display:flex; flex-direction:column; align-items:center; }\n    .ant-tl .tl-dot{ position:relative; z-index:1; width:10px; height:10px; border-radius:50%; box-sizing:border-box; border:2px solid var(--dot); background:transparent; margin-top:4px; }\n    .ant-tl .tl-dot.glyph{ width:auto; height:auto; border:0; font-size:14px; color:var(--dot); line-height:1; }\n    .ant-tl .tl-line{ position:absolute; top:6px; bottom:-20px; left:50%; transform:translateX(-50%); width:2px; background:var(--c-line); }\n    .ant-tl .tl-item:last-child .tl-line{ display:none; }\n    .ant-tl .tl-content{ flex:1 1 auto; padding-left:14px; padding-bottom:2px; }\n    .ant-tl .tl-label{ color:var(--c-sec); font-size:13px; margin-bottom:2px; }\n    .ant-tl .tl-body{ color:var(--c-text); }\n    .ant-tl.right .tl-item{ flex-direction:row-reverse; }\n    .ant-tl.right .tl-content{ padding-left:0; padding-right:14px; text-align:right; }\n    .ant-tl.alternate .tl-item:nth-child(even){ flex-direction:row-reverse; }\n    .ant-tl.alternate .tl-item:nth-child(even) .tl-content{ padding-left:0; padding-right:14px; text-align:right; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const mode = p.mode || 'left';\n    let items = p.items;\n    if(typeof items === 'string'){ try{ items = JSON.parse(items); }catch(e){ items = []; } }\n    if(!Array.isArray(items)) items = [];\n\n    const style = [\n      '--ff:'+D.fontFamily,\n      '--fs:'+D.fontSize+'px',\n      '--c-text:'+D.colorText,\n      '--c-sec:'+D.colorTextSecondary,\n      '--c-line:'+D.colorBorderSecondary\n    ].join(';');\n\n    const rows = items.map(function(it){\n      it = it || {};\n      const col = dotColor(D, it.color);\n      const glyph = it.dot || '';\n      const isFa = /(^|\\s)fa[srlbd]?(\\s|-)/.test(glyph);\n      let dotHtml;\n      if(glyph){\n        dotHtml = '<span class=\"tl-dot glyph\" style=\"--dot:'+esc(col)+'\">'+(isFa?'<i class=\"'+esc(glyph)+'\"></i>':esc(glyph))+'</span>';\n      } else {\n        dotHtml = '<span class=\"tl-dot\" style=\"--dot:'+esc(col)+'\"></span>';\n      }\n      const labelHtml = (it.label != null && it.label !== '') ? '<div class=\"tl-label\">'+esc(it.label)+'</div>' : '';\n      const bodyHtml = '<div class=\"tl-body\">'+esc(it.children)+'</div>';\n      return '<li class=\"tl-item\">'+\n        '<span class=\"tl-rail\">'+dotHtml+'<span class=\"tl-line\"></span></span>'+\n        '<div class=\"tl-content\">'+labelHtml+bodyHtml+'</div>'+\n        '</li>';\n    }).join('');\n\n    return '<ul class=\"ant-tl '+esc(mode)+'\" style=\"'+style+'\">'+rows+'</ul>';\n  }\n};"}},"items":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"items"}}}},"mode":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"mode"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a304611e6cc9d55d3e0032d","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-tree","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorWarning:'#faad14', colorError:'#ff4d4f', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusLG:8, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-tree{ font-family:var(--ff); font-size:var(--fs); color:var(--c-text); user-select:none; }\n    .ant-tree-node{ }\n    .ant-tree-row{ display:flex; align-items:center; height:28px; line-height:28px; border-radius:4px; padding-right:4px; }\n    .ant-tree-caret{ width:24px; flex:0 0 24px; display:inline-flex; align-items:center; justify-content:center; cursor:pointer; color:var(--c-tertiary); transition:transform .15s; }\n    .ant-tree-caret.spacer{ cursor:default; }\n    .ant-tree-caret.open{ transform:rotate(90deg); }\n    .ant-tree-check{ width:16px; height:16px; flex:0 0 16px; margin-right:8px; border:1px solid var(--c-border); border-radius:4px; background:var(--c-bg); cursor:pointer; display:inline-flex; align-items:center; justify-content:center; font-size:11px; color:#fff; }\n    .ant-tree-check.checked{ background:var(--c-primary); border-color:var(--c-primary); }\n    .ant-tree-title{ flex:1 1 auto; cursor:pointer; padding:0 6px; border-radius:4px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n    .ant-tree-title:hover{ background:var(--c-fill); }\n    .ant-tree-row.selected .ant-tree-title{ background:var(--c-primary-bg); }\n    .ant-tree-row.disabled .ant-tree-title{ color:var(--c-disabled); cursor:not-allowed; }\n    .ant-tree-children{ }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const checkable = !!p.checkable;\n    const treeData = Array.isArray(p.treeData) ? p.treeData : [];\n\n    if(d2.state.expanded === undefined){\n      const init = {};\n      const def = Array.isArray(p.defaultExpandedKeys) ? p.defaultExpandedKeys : [];\n      def.forEach(function(k){ init[String(k)] = true; });\n      d2.state.expanded = init;\n    }\n    if(d2.state.selected === undefined){\n      d2.state.selected = (p.selectedKey != null && p.selectedKey !== '') ? String(p.selectedKey) : null;\n    }\n    if(d2.state.checked === undefined) d2.state.checked = {};\n\n    const expanded = d2.state.expanded || {};\n    const selected = d2.state.selected;\n    const checked = d2.state.checked || {};\n\n    function renderNode(node, depth){\n      if(!node || typeof node !== 'object') return '';\n      const key = esc(node.key);\n      const kraw = String(node.key);\n      const kids = Array.isArray(node.children) ? node.children : [];\n      const hasKids = kids.length > 0;\n      const isOpen = !!expanded[kraw];\n      const isSel = selected != null && String(selected) === kraw;\n      const disabled = !!node.disabled;\n      const indent = depth * 24;\n\n      const caret = hasKids\n        ? '<span class=\"ant-tree-caret'+(isOpen?' open':'')+'\" data-caret=\"'+key+'\"><i class=\"fa fa-caret-right\"></i></span>'\n        : '<span class=\"ant-tree-caret spacer\"></span>';\n\n      const checkbox = checkable\n        ? '<span class=\"ant-tree-check'+(checked[kraw]?' checked':'')+'\" data-check=\"'+key+'\">'+(checked[kraw]?'<i class=\"fa fa-check\"></i>':'')+'</span>'\n        : '';\n\n      const rowCls = ['ant-tree-row'];\n      if(isSel) rowCls.push('selected');\n      if(disabled) rowCls.push('disabled');\n\n      let html = '<div class=\"ant-tree-node\" data-node=\"'+key+'\">';\n      html += '<div class=\"'+rowCls.join(' ')+'\" style=\"padding-left:'+indent+'px\">';\n      html += caret + checkbox;\n      html += '<span class=\"ant-tree-title\" data-title=\"'+key+'\">'+esc(node.title)+'</span>';\n      html += '</div>';\n      if(hasKids && isOpen){\n        html += '<div class=\"ant-tree-children\">';\n        for(let i=0;i<kids.length;i++){ html += renderNode(kids[i], depth+1); }\n        html += '</div>';\n      }\n      html += '</div>';\n      return html;\n    }\n\n    let body = '';\n    for(let i=0;i<treeData.length;i++){ body += renderNode(treeData[i], 0); }\n    if(!body) body = '<div style=\"color:'+D.colorTextTertiary+';padding:8px\">No data</div>';\n\n    const style = [\n      '--ff:'+D.fontFamily, '--fs:'+D.fontSize+'px',\n      '--c-text:'+D.colorText, '--c-tertiary:'+D.colorTextTertiary, '--c-disabled:'+D.colorTextDisabled,\n      '--c-border:'+D.colorBorder, '--c-bg:'+D.colorBgContainer, '--c-fill:'+D.colorFillTertiary,\n      '--c-primary:'+D.colorPrimary, '--c-primary-bg:'+D.colorPrimaryBg\n    ].join(';');\n\n    return '<div class=\"ant-tree\" style=\"'+style+'\">'+body+'</div>';\n  },\n  mounted(d2){\n    function findNode(nodes, key){\n      if(!Array.isArray(nodes)) return null;\n      for(let i=0;i<nodes.length;i++){\n        const n = nodes[i];\n        if(!n || typeof n !== 'object') continue;\n        if(String(n.key) === key) return n;\n        const f = findNode(n.children, key);\n        if(f) return f;\n      }\n      return null;\n    }\n    d2.on('.ant-tree-caret', 'click', (e, el) => {\n      const key = el.getAttribute('data-caret');\n      if(key == null) return;\n      const ex = Object.assign({}, d2.state.expanded || {});\n      ex[key] = !ex[key];\n      d2.state.expanded = ex;\n    });\n    d2.on('.ant-tree-check', 'click', (e, el) => {\n      const key = el.getAttribute('data-check');\n      if(key == null) return;\n      const ch = Object.assign({}, d2.state.checked || {});\n      ch[key] = !ch[key];\n      d2.state.checked = ch;\n    });\n    d2.on('.ant-tree-title', 'click', (e, el) => {\n      const key = el.getAttribute('data-title');\n      if(key == null) return;\n      const node = findNode(d2.params && d2.params.treeData, key);\n      if(node && node.disabled) return;\n      d2.state.selected = key;\n      d2.emit('onSelect', key);\n    });\n  }\n};"}},"treeData":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"treeData"}}}},"defaultExpandedKeys":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"defaultExpandedKeys"}}}},"checkable":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"checkable"}}}},"selectedKey":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"selectedKey"}}}},"onSelect":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onSelect"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a304619ccdaee8ef642dbaf","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-image","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusLG:8, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-image{ position:relative; display:inline-block; overflow:hidden; line-height:0; }\n    .ant-image img.thumb{ display:block; object-fit:cover; }\n    .ant-image .ovl{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center;\n      gap:6px; color:#fff; font-size:14px; background:rgba(0,0,0,0.45); opacity:0; cursor:pointer;\n      transition:opacity .2s; }\n    .ant-image.has-preview:hover .ovl{ opacity:1; }\n    .ant-image .ovl .fa{ font-size:16px; }\n    .ant-preview-mask{ position:fixed; inset:0; z-index:1200; display:flex; align-items:center; justify-content:center;\n      background:rgba(0,0,0,0.45); cursor:zoom-out; }\n    .ant-preview-mask img{ max-width:90vw; max-height:90vh; object-fit:contain; box-shadow:0 6px 24px rgba(0,0,0,0.45); }\n    .ant-preview-mask .close{ position:absolute; top:24px; right:24px; width:44px; height:44px; border-radius:50%;\n      display:flex; align-items:center; justify-content:center; background:rgba(0,0,0,0.4); color:#fff; font-size:20px; cursor:pointer; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const src = p.src != null ? String(p.src) : '';\n    const w = (p.imgWidth != null && p.imgWidth !== '') ? Number(p.imgWidth) : 200;\n    const h = (p.imgHeight != null && p.imgHeight !== '') ? Number(p.imgHeight) : null;\n    const preview = p.preview === undefined ? true : !!p.preview;\n    const alt = p.alt != null ? String(p.alt) : '';\n    const open = !!d2.state.preview;\n\n    const wStyle = isNaN(w) ? '' : ('width:'+w+'px;');\n    const hStyle = (h!=null && !isNaN(h)) ? ('height:'+h+'px;') : 'height:auto;';\n    const imgStyle = wStyle + hStyle + 'border-radius:'+D.borderRadius+'px;';\n\n    const thumb = '<img class=\"thumb\" src=\"'+esc(src)+'\" alt=\"'+esc(alt)+'\" style=\"'+imgStyle+'\">';\n    const ovl = preview ? '<div class=\"ovl\" data-open=\"1\"><i class=\"fa fa-eye\"></i><span>Preview</span></div>' : '';\n    const wrapClass = 'ant-image' + (preview ? ' has-preview' : '');\n    const wrapStyle = 'font-family:'+D.fontFamily+';' + wStyle + (preview ? 'cursor:pointer;' : '');\n\n    let mask = '';\n    if(open && preview){\n      mask = '<div class=\"ant-preview-mask\" data-close=\"1\">'\n        + '<div class=\"close\" data-close=\"1\"><i class=\"fa fa-close\"></i></div>'\n        + '<img src=\"'+esc(src)+'\" alt=\"'+esc(alt)+'\">'\n        + '</div>';\n    }\n\n    return '<div class=\"'+wrapClass+'\" style=\"'+wrapStyle+'\">'+thumb+ovl+'</div>'+mask;\n  },\n  mounted(d2){\n    d2.on('.ant-image','click',(e)=>{\n      const p = d2.params || {};\n      const preview = p.preview === undefined ? true : !!p.preview;\n      if(!preview) return;\n      d2.state.preview = true;\n    });\n    d2.on('.ant-preview-mask','click',(e)=>{\n      d2.state.preview = false;\n    });\n  }\n};"}},"src":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"src"}}}},"imgWidth":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"imgWidth"}}}},"imgHeight":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"imgHeight"}}}},"preview":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"preview"}}}},"alt":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"alt"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a30462c56f919e523116606","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-qrcode","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusLG:8, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    .ant-qr{ display:inline-block; box-sizing:border-box; }\n    .ant-qr img{ display:block; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const value = (p.value != null && p.value !== '') ? String(p.value) : 'https://ant.design';\n    const size = (p.qrSize != null && p.qrSize !== '' && !isNaN(Number(p.qrSize))) ? Number(p.qrSize) : 160;\n    const color = (p.color != null && p.color !== '') ? String(p.color) : '#000000';\n    const bgColor = (p.bgColor != null && p.bgColor !== '') ? String(p.bgColor) : '#ffffff';\n    const fg = color.replace('#','');\n    const bg = bgColor.replace('#','');\n\n    const src = 'https://api.qrserver.com/v1/create-qr-code/?size=' + size + 'x' + size\n      + '&data=' + encodeURIComponent(value)\n      + '&color=' + fg\n      + '&bgcolor=' + bg;\n\n    const boxStyle = 'box-sizing:border-box; padding:12px; border:1px solid ' + D.colorBorderSecondary\n      + '; border-radius:' + D.borderRadiusLG + 'px; background:' + bgColor\n      + '; font-family:' + D.fontFamily + ';';\n    const imgStyle = 'width:' + size + 'px; height:' + size + 'px;';\n\n    return '<div class=\"ant-qr\" style=\"' + boxStyle + '\">'\n      + '<img src=\"' + esc(src) + '\" alt=\"QR code\" style=\"' + imgStyle + '\">'\n      + '</div>';\n  }\n};"}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"qrSize":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"qrSize"}}}},"color":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"color"}}}},"bgColor":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bgColor"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a30462eccdaee8ef642dc26","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-descriptions","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorSuccess:'#52c41a', colorWarning:'#faad14', colorError:'#ff4d4f', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusLG:8, fontSize:14, fontSizeLG:16, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    .ant-desc{ box-sizing:border-box; font-family:var(--ff); font-size:var(--fs); color:var(--c-text); width:100%; }\n    .ant-desc .desc-title{ font-weight:600; color:var(--c-text); font-size:var(--fs-title); margin-bottom:var(--gap); }\n    .ant-desc table{ width:100%; border-collapse:collapse; table-layout:fixed; }\n    .ant-desc.plain .desc-row{ display:block; }\n    .ant-desc.plain .desc-cell{ padding:var(--cellpad) 0; vertical-align:top; }\n    .ant-desc.plain .desc-label{ color:var(--c-sec); }\n    .ant-desc.plain .desc-label:after{ content:':'; margin:0 8px 0 2px; }\n    .ant-desc.plain .desc-val{ color:var(--c-text); }\n    .ant-desc.plain.vertical .desc-label:after{ content:''; margin:0; }\n    .ant-desc.bordered table{ border:1px solid var(--c-border); border-radius:var(--radius); border-collapse:separate; border-spacing:0; overflow:hidden; table-layout:auto; }\n    .ant-desc.bordered td{ border-right:1px solid var(--c-border); border-bottom:1px solid var(--c-border); padding:var(--cellpad) var(--cellpadx); vertical-align:top; word-break:break-word; }\n    .ant-desc.bordered tr td:last-child{ border-right:none; }\n    .ant-desc.bordered tr:last-child td{ border-bottom:none; }\n    .ant-desc.bordered .desc-label{ background:var(--c-fill); color:var(--c-sec); font-weight:400; white-space:nowrap; }\n    .ant-desc.bordered .desc-val{ color:var(--c-text); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const title = p.title != null ? String(p.title) : '';\n    const bordered = !!p.bordered;\n    const layout = p.layout || 'horizontal';\n    const size = p.size || 'middle';\n    let column = (p.column != null && p.column !== '') ? Math.floor(Number(p.column)) : 3;\n    if(!(column > 0)) column = 3;\n    let items = p.items;\n    if(typeof items === 'string'){ try{ items = JSON.parse(items); }catch(e){ items = []; } }\n    if(!Array.isArray(items)) items = [];\n\n    const cellpad = size === 'small' ? 8 : (size === 'large' ? 16 : 12);\n    const titleFs = size === 'large' ? D.fontSizeLG : D.fontSize;\n\n    const style = [\n      '--ff:'+D.fontFamily,\n      '--fs:'+D.fontSize+'px',\n      '--fs-title:'+titleFs+'px',\n      '--c-text:'+D.colorText,\n      '--c-sec:'+D.colorTextSecondary,\n      '--c-border:'+D.colorBorderSecondary,\n      '--c-fill:'+D.colorFillTertiary,\n      '--radius:'+D.borderRadiusLG+'px',\n      '--cellpad:'+cellpad+'px',\n      '--cellpadx:'+(cellpad+4)+'px',\n      '--gap:'+(size==='large'?16:12)+'px'\n    ].join(';');\n\n    const classes = ['ant-desc', bordered ? 'bordered' : 'plain'];\n    if(layout === 'vertical') classes.push('vertical');\n\n    const titleHtml = title ? '<div class=\"desc-title\">'+esc(title)+'</div>' : '';\n    let tableInner = '';\n\n    // chunk items into rows of `column`\n    const rows = [];\n    for(let i = 0; i < items.length; i += column){ rows.push(items.slice(i, i + column)); }\n\n    if(layout === 'vertical'){\n      tableInner = rows.map(function(row){\n        const labelTds = row.map(function(it){ it = it || {}; return '<td class=\"desc-label\">'+esc(it.label)+'</td>'; }).join('');\n        const valTds = row.map(function(it){ it = it || {}; return '<td class=\"desc-val\">'+esc(it.children)+'</td>'; }).join('');\n        return '<tr class=\"desc-row\">'+labelTds+'</tr><tr class=\"desc-row\">'+valTds+'</tr>';\n      }).join('');\n    } else {\n      tableInner = rows.map(function(row){\n        const cells = row.map(function(it){\n          it = it || {};\n          if(bordered){\n            return '<td class=\"desc-label\">'+esc(it.label)+'</td><td class=\"desc-val\">'+esc(it.children)+'</td>';\n          }\n          return '<td class=\"desc-cell\"><span class=\"desc-label\">'+esc(it.label)+'</span><span class=\"desc-val\">'+esc(it.children)+'</span></td>';\n        }).join('');\n        return '<tr class=\"desc-row\">'+cells+'</tr>';\n      }).join('');\n    }\n\n    return '<div class=\"'+classes.join(' ')+'\" style=\"'+style+'\">'+titleHtml+'<table><tbody>'+tableInner+'</tbody></table></div>';\n  }\n};"}},"items":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"items"}}}},"title":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"title"}}}},"bordered":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"bordered"}}}},"column":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"column"}}}},"layout":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"layout"}}}},"size":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"size"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a30463eed769e0c5827d35b","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-calendar","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorWarning:'#faad14', colorError:'#ff4d4f', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusLG:8, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nconst MONTHS = ['January','February','March','April','May','June','July','August','September','October','November','December'];\nconst WEEKDAYS = ['Su','Mo','Tu','We','Th','Fr','Sa'];\n\nfunction parseISO(s){\n  if(s == null || s === '') return null;\n  const parts = String(s).slice(0,10).split('-');\n  if(parts.length < 3) return null;\n  const y = parseInt(parts[0],10), m = parseInt(parts[1],10), d = parseInt(parts[2],10);\n  if(isNaN(y)||isNaN(m)||isNaN(d)) return null;\n  return { y:y, m:m-1, d:d };\n}\nfunction daysInMonth(y, m){\n  const dim = [31,28,31,30,31,30,31,31,30,31,30,31];\n  if(m === 1 && ((y%4===0 && y%100!==0) || y%400===0)) return 29;\n  return dim[m];\n}\nfunction dayOfWeek(y, m, d){\n  // Sakamoto's algorithm; m is 0-based, convert to 1-based.\n  const mm = m + 1;\n  const t = [0,3,2,5,0,3,5,1,4,6,2,4];\n  let yy = y;\n  if(mm < 3) yy -= 1;\n  return (yy + Math.floor(yy/4) - Math.floor(yy/100) + Math.floor(yy/400) + t[mm-1] + d) % 7;\n}\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-cal{ font-family:var(--ff); font-size:var(--fs); color:var(--c-text); background:var(--c-bg); box-sizing:border-box; }\n    .ant-cal.fs{ border:none; }\n    .ant-cal.card{ border:1px solid var(--c-border-2); border-radius:var(--radius); padding:8px 12px; display:inline-block; }\n    .ant-cal-head{ display:flex; align-items:center; justify-content:space-between; padding:8px 4px; }\n    .ant-cal-head.fs{ justify-content:flex-end; gap:12px; border-bottom:1px solid var(--c-border-2); }\n    .ant-cal-label{ font-weight:600; font-size:1.1em; flex:1 1 auto; }\n    .ant-cal-nav{ width:28px; height:28px; display:inline-flex; align-items:center; justify-content:center; cursor:pointer; border-radius:4px; color:var(--c-secondary); }\n    .ant-cal-nav:hover{ background:var(--c-fill); color:var(--c-primary); }\n    .ant-cal-grid{ width:100%; border-collapse:collapse; table-layout:fixed; }\n    .ant-cal-grid th{ color:var(--c-secondary); font-weight:400; text-align:center; padding:6px 0; font-size:.9em; }\n    .ant-cal-cell{ text-align:center; padding:2px; }\n    .ant-cal-day{ display:inline-flex; align-items:center; justify-content:center; cursor:pointer; box-sizing:border-box; }\n    .ant-cal.card .ant-cal-day{ width:28px; height:28px; line-height:28px; border-radius:4px; margin:0 auto; }\n    .ant-cal.fs .ant-cal-cell{ height:60px; vertical-align:top; border-top:2px solid var(--c-border-2); }\n    .ant-cal.fs .ant-cal-day{ width:100%; justify-content:flex-end; padding:4px 8px 0 0; height:auto; }\n    .ant-cal-day:hover{ background:var(--c-primary-bg); }\n    .ant-cal-day.other{ color:var(--c-disabled); }\n    .ant-cal.card .ant-cal-day.selected{ background:var(--c-primary); color:#fff; }\n    .ant-cal.fs .ant-cal-cell.selected{ border-top-color:var(--c-primary); }\n    .ant-cal.fs .ant-cal-cell.selected .ant-cal-day{ color:var(--c-primary); font-weight:600; }\n    .ant-cal-day.today{ font-weight:600; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const fullscreen = (p.fullscreen === undefined) ? true : !!p.fullscreen;\n\n    const valStr = (p.value != null && p.value !== '') ? String(p.value) : '2026-06-01';\n    const valDate = parseISO(valStr) || { y:2026, m:5, d:1 };\n\n    if(d2.state.month === undefined) d2.state.month = { y: valDate.y, m: valDate.m };\n    if(d2.state.selected === undefined) d2.state.selected = valStr.slice(0,10);\n\n    const cur = d2.state.month;\n    const sel = parseISO(d2.state.selected);\n\n    const firstDow = dayOfWeek(cur.y, cur.m, 1);\n    const dim = daysInMonth(cur.y, cur.m);\n    const prevM = cur.m === 0 ? 11 : cur.m - 1;\n    const prevY = cur.m === 0 ? cur.y - 1 : cur.y;\n    const dimPrev = daysInMonth(prevY, prevM);\n    const nextM = cur.m === 11 ? 0 : cur.m + 1;\n    const nextY = cur.m === 11 ? cur.y + 1 : cur.y;\n\n    // build 6x7 cells\n    const cells = [];\n    for(let i = 0; i < 42; i++){\n      let cy, cm, cd, other;\n      if(i < firstDow){ cd = dimPrev - firstDow + 1 + i; cm = prevM; cy = prevY; other = true; }\n      else if(i < firstDow + dim){ cd = i - firstDow + 1; cm = cur.m; cy = cur.y; other = false; }\n      else { cd = i - firstDow - dim + 1; cm = nextM; cy = nextY; other = true; }\n      cells.push({ y:cy, m:cm, d:cd, other:other });\n    }\n\n    const head = WEEKDAYS.map(function(w){ return '<th>'+w+'</th>'; }).join('');\n\n    let rows = '';\n    for(let r = 0; r < 6; r++){\n      let tr = '<tr>';\n      for(let c = 0; c < 7; c++){\n        const cell = cells[r*7 + c];\n        const iso = cell.y + '-' + String(cell.m+1).padStart(2,'0') + '-' + String(cell.d).padStart(2,'0');\n        const isSel = sel && sel.y === cell.y && sel.m === cell.m && sel.d === cell.d;\n        const cellCls = ['ant-cal-cell']; if(isSel) cellCls.push('selected');\n        const dayCls = ['ant-cal-day']; if(cell.other) dayCls.push('other'); if(isSel) dayCls.push('selected');\n        tr += '<td class=\"'+cellCls.join(' ')+'\"><div class=\"'+dayCls.join(' ')+'\" data-date=\"'+iso+'\">'+cell.d+'</div></td>';\n      }\n      tr += '</tr>';\n      rows += tr;\n    }\n\n    const style = [\n      '--ff:'+D.fontFamily, '--fs:'+D.fontSize+'px', '--radius:'+D.borderRadiusLG+'px',\n      '--c-text:'+D.colorText, '--c-secondary:'+D.colorTextSecondary, '--c-disabled:'+D.colorTextDisabled,\n      '--c-border-2:'+D.colorBorderSecondary, '--c-bg:'+D.colorBgContainer, '--c-fill:'+D.colorFillTertiary,\n      '--c-primary:'+D.colorPrimary, '--c-primary-bg:'+D.colorPrimaryBg\n    ].join(';');\n\n    const wrapCls = 'ant-cal ' + (fullscreen ? 'fs' : 'card');\n    const headCls = 'ant-cal-head ' + (fullscreen ? 'fs' : '');\n    const label = MONTHS[cur.m] + ' ' + cur.y;\n\n    let html = '<div class=\"'+wrapCls+'\" style=\"'+style+'\">';\n    html += '<div class=\"'+headCls+'\">';\n    html += '<span class=\"ant-cal-nav\" data-nav=\"prev\"><i class=\"fa fa-angle-left\"></i></span>';\n    html += '<span class=\"ant-cal-label\">'+esc(label)+'</span>';\n    html += '<span class=\"ant-cal-nav\" data-nav=\"next\"><i class=\"fa fa-angle-right\"></i></span>';\n    html += '</div>';\n    html += '<table class=\"ant-cal-grid\"><thead><tr>'+head+'</tr></thead><tbody>'+rows+'</tbody></table>';\n    html += '</div>';\n    return html;\n  },\n  mounted(d2){\n    d2.on('.ant-cal-nav', 'click', (e, el) => {\n      const dir = el.getAttribute('data-nav');\n      const cur = d2.state.month || { y:2026, m:5 };\n      let y = cur.y, m = cur.m;\n      if(dir === 'prev'){ m -= 1; if(m < 0){ m = 11; y -= 1; } }\n      else { m += 1; if(m > 11){ m = 0; y += 1; } }\n      d2.state.month = { y:y, m:m };\n    });\n    d2.on('.ant-cal-day', 'click', (e, el) => {\n      const iso = el.getAttribute('data-date');\n      if(iso == null) return;\n      d2.state.selected = iso;\n    });\n  }\n};"}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"fullscreen":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"fullscreen"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a3046406202ef3347e13215","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-watermark","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusLG:8, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    .ant-wm{ position:relative; overflow:hidden; box-sizing:border-box; }\n    .ant-wm .wm-content{ position:relative; z-index:1; padding:16px; }\n    .ant-wm .wm-overlay{ position:absolute; inset:0; z-index:2; pointer-events:none; background-repeat:repeat; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const content = (p.content != null && p.content !== '') ? String(p.content) : 'Watermark';\n    const panelH = (p.panelHeight != null && p.panelHeight !== '' && !isNaN(Number(p.panelHeight))) ? Number(p.panelHeight) : 180;\n    const fontColor = (p.fontColor != null && p.fontColor !== '') ? String(p.fontColor) : 'rgba(0,0,0,0.12)';\n    const rotate = (p.rotate != null && p.rotate !== '' && !isNaN(Number(p.rotate))) ? Number(p.rotate) : -22;\n\n    // build an SVG tile with the rotated watermark text\n    const tileW = 140, tileH = 100;\n    const svgFont = (D.fontFamily || 'sans-serif').replace(/\"/g, \"'\");\n    const svg = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"' + tileW + '\" height=\"' + tileH + '\">'\n      + '<text x=\"' + (tileW/2) + '\" y=\"' + (tileH/2) + '\" fill=\"' + fontColor + '\" font-size=\"14\" '\n      + 'font-family=\"' + svgFont + '\" text-anchor=\"middle\" dominant-baseline=\"middle\" '\n      + 'transform=\"rotate(' + rotate + ' ' + (tileW/2) + ' ' + (tileH/2) + ')\">' + esc(content) + '</text>'\n      + '</svg>';\n    const dataUri = \"url(\\\"data:image/svg+xml,\" + encodeURIComponent(svg) + \"\\\")\";\n\n    const panelStyle = 'height:' + panelH + 'px; background:' + D.colorBgContainer\n      + '; border:1px solid ' + D.colorBorderSecondary + '; border-radius:' + D.borderRadius\n      + 'px; font-family:' + D.fontFamily + ';';\n    const contentStyle = 'color:' + D.colorText + '; font-size:' + D.fontSize + 'px; line-height:1.6;';\n    const overlayStyle = 'background-image:' + dataUri + '; background-size:' + tileW + 'px ' + tileH + 'px;';\n\n    return '<div class=\"ant-wm\" style=\"' + panelStyle + '\">'\n      + '<div class=\"wm-content\" style=\"' + contentStyle + '\">Your content here</div>'\n      + '<div class=\"wm-overlay\" style=\"' + overlayStyle + '\"></div>'\n      + '</div>';\n  }\n};"}},"content":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"content"}}}},"panelHeight":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"panelHeight"}}}},"fontColor":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"fontColor"}}}},"rotate":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rotate"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a3046496202ef3347e1322f","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-datepicker","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusSM:4, controlHeight:32, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nconst WEEKDAYS = ['Su','Mo','Tu','We','Th','Fr','Sa'];\nconst MONTHS = ['January','February','March','April','May','June','July','August','September','October','November','December'];\nfunction pad2(n){ return (n<10?'0':'')+n; }\nfunction parseYMD(s){ if(!s||typeof s!=='string') return null; const m=s.split('-'); if(m.length<3) return null; const y=parseInt(m[0],10),mo=parseInt(m[1],10),d=parseInt(m[2],10); if(!(y>0)||!(mo>=1&&mo<=12)||!(d>=1&&d<=31)) return null; return {y:y,mo:mo,d:d}; }\nfunction fmtYMD(o){ return o.y+'-'+pad2(o.mo)+'-'+pad2(o.d); }\nfunction isLeap(y){ return (y%4===0&&y%100!==0)||(y%400===0); }\nfunction daysInMonth(y,mo){ return [31,(isLeap(y)?29:28),31,30,31,30,31,31,30,31,30,31][mo-1]; }\n// Zeller-ish: day of week for the 1st of a month (0=Sun). Uses Sakamoto's algorithm.\nfunction dowFirst(y,mo){ const t=[0,3,2,5,0,3,5,1,4,6,2,4]; let yy=y; if(mo<3) yy-=1; const d=1; const w=(yy+Math.floor(yy/4)-Math.floor(yy/100)+Math.floor(yy/400)+t[mo-1]+d)%7; return ((w%7)+7)%7; }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .adp{ position:relative; box-sizing:border-box; display:inline-block; width:100%; font-family:var(--ff); font-size:var(--fs); }\n    .adp *{ box-sizing:border-box; }\n    .adp-ctl{ position:relative; display:flex; align-items:center; gap:4px; min-height:var(--h); padding:0 11px;\n      background:var(--bg); border:1px solid var(--bc); border-radius:var(--radius); cursor:pointer; transition:border-color .2s, box-shadow .2s; }\n    .adp-ctl:hover{ border-color:var(--bc-h); }\n    .adp.is-open .adp-ctl{ border-color:var(--bc-f); box-shadow:0 0 0 2px var(--ring); }\n    .adp.is-disabled .adp-ctl{ background:var(--bg-dis); border-color:var(--bc); cursor:not-allowed; }\n    .adp.is-disabled .adp-text{ color:var(--c-dis); }\n    .adp-text{ flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--c-text); }\n    .adp-text.is-ph{ color:var(--c-ph); }\n    .adp-icon{ flex:0 0 auto; margin-left:6px; color:var(--c-ph); font-size:13px; }\n    .adp-panel{ position:fixed; left:0; top:0; z-index:1200; width:280px; background:var(--bg);\n      border:1px solid var(--panel-bc); border-radius:var(--radius); box-shadow:0 6px 16px rgba(0,0,0,.12);\n      padding:8px; display:none; }\n    .adp.is-open .adp-panel{ display:block; }\n    .adp-head{ display:flex; align-items:center; justify-content:space-between; padding:4px 4px 8px; border-bottom:1px solid var(--panel-bc); margin-bottom:6px; }\n    .adp-nav{ width:28px; height:28px; display:inline-flex; align-items:center; justify-content:center; border-radius:var(--radius-sm); cursor:pointer; color:var(--c-ph); }\n    .adp-nav:hover{ color:var(--c-text); background:var(--cell-hover); }\n    .adp-title{ font-weight:600; color:var(--c-text); }\n    .adp-grid{ display:grid; grid-template-columns:repeat(7,1fr); gap:2px; }\n    .adp-wd{ text-align:center; color:var(--c-ph); font-size:12px; height:24px; line-height:24px; }\n    .adp-cell{ text-align:center; height:30px; line-height:30px; border-radius:var(--radius-sm); cursor:pointer; color:var(--c-text); }\n    .adp-cell.muted{ color:var(--c-dis); }\n    .adp-cell.empty{ cursor:default; }\n    .adp-cell:not(.empty):hover{ background:var(--cell-hover); }\n    .adp-cell.today{ border:1px solid var(--c-primary); }\n    .adp-cell.sel{ background:var(--c-primary); color:#fff; }\n    .adp-cell.sel:hover{ background:var(--c-primary); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const disabled = !!p.disabled;\n    const placeholder = p.placeholder != null ? String(p.placeholder) : 'Select date';\n\n    if(d2.state.open == null) d2.state.open = false;\n    if(d2.state.value == null) d2.state.value = (p.value != null ? String(p.value) : '');\n\n    const open = !!d2.state.open;\n    const selObj = parseYMD(String(d2.state.value||''));\n\n    // view month: from state, else selected, else param value, else default\n    if(d2.state.viewY == null || d2.state.viewM == null){\n      const base = selObj || parseYMD(String(p.value||'')) || {y:2026,mo:6,d:1};\n      d2.state.viewY = base.y; d2.state.viewM = base.mo;\n    }\n    const vy = d2.state.viewY, vm = d2.state.viewM;\n\n    const style = [\n      '--h:'+D.controlHeight+'px','--fs:'+D.fontSize+'px','--radius:'+D.borderRadius+'px','--radius-sm:'+D.borderRadiusSM+'px',\n      '--bc:'+D.colorBorder,'--bc-h:'+D.colorPrimaryHover,'--bc-f:'+D.colorPrimary,'--ring:rgba(5,145,255,0.1)',\n      '--bg:'+D.colorBgContainer,'--bg-dis:'+D.colorFillTertiary,\n      '--c-text:'+D.colorText,'--c-ph:'+D.colorTextTertiary,'--c-dis:'+D.colorTextDisabled,\n      '--c-primary:'+D.colorPrimary,'--cell-hover:'+D.colorFillTertiary,'--panel-bc:'+D.colorBorderSecondary,'--ff:'+D.fontFamily\n    ].join(';');\n\n    const rootClasses=['adp']; if(open) rootClasses.push('is-open'); if(disabled) rootClasses.push('is-disabled');\n\n    const hasValue = !!selObj;\n    const text = hasValue ? fmtYMD(selObj) : placeholder;\n    const ctlHtml = '<div class=\"adp-ctl\">'\n      + '<span class=\"adp-text'+(hasValue?'':' is-ph')+'\">'+esc(text)+'</span>'\n      + '<i class=\"fa fa-calendar adp-icon\"></i>'\n      + '</div>';\n\n    // build grid\n    const first = dowFirst(vy,vm);\n    const dim = daysInMonth(vy,vm);\n    let cells = '';\n    for(let i=0;i<first;i++){ cells += '<div class=\"adp-cell empty\"></div>'; }\n    for(let d=1; d<=dim; d++){\n      const cls = ['adp-cell'];\n      if(selObj && selObj.y===vy && selObj.mo===vm && selObj.d===d) cls.push('sel');\n      const dateStr = vy+'-'+pad2(vm)+'-'+pad2(d);\n      cells += '<div class=\"'+cls.join(' ')+'\" data-date=\"'+dateStr+'\">'+d+'</div>';\n    }\n    const wdRow = WEEKDAYS.map(w=>'<div class=\"adp-wd\">'+w+'</div>').join('');\n\n    const panelHtml = '<div class=\"adp-panel\">'\n      + '<div class=\"adp-head\">'\n      +   '<span class=\"adp-nav\" data-nav=\"prev\"><i class=\"fa fa-angle-left\"></i></span>'\n      +   '<span class=\"adp-title\">'+esc(MONTHS[vm-1]+' '+vy)+'</span>'\n      +   '<span class=\"adp-nav\" data-nav=\"next\"><i class=\"fa fa-angle-right\"></i></span>'\n      + '</div>'\n      + '<div class=\"adp-grid\">'+wdRow+cells+'</div>'\n      + '</div>';\n\n    return '<div class=\"'+rootClasses.join(' ')+'\" style=\"'+style+'\">'+ctlHtml+panelHtml+'</div>';\n  },\n  mounted(d2){\n    d2.on('.adp-ctl','click',(e)=>{\n      if((d2.params||{}).disabled) return;\n      d2.state.open = !d2.state.open;\n    });\n    d2.on('[data-nav]','click',(e,el)=>{\n      e.stopPropagation();\n      const dir = el.getAttribute('data-nav');\n      let y = d2.state.viewY, m = d2.state.viewM;\n      if(dir==='prev'){ m--; if(m<1){ m=12; y--; } } else { m++; if(m>12){ m=1; y++; } }\n      d2.state.viewY = y; d2.state.viewM = m;\n    });\n    d2.on('.adp-cell','click',(e,el)=>{\n      const date = el.getAttribute('data-date');\n      if(!date) return;\n      d2.state.value = date;\n      d2.state.open = false;\n      d2.emit('onChange', date);\n    });\n    d2.on(document,'click',(e)=>{\n      if(!d2.state.open) return;\n      const path = (e.composedPath && e.composedPath()) || [];\n      if(d2.root && path.indexOf(d2.root) !== -1) return;\n      d2.state.open = false;\n    });\n  },\n  updated(d2){\n    if(!d2.state.open) return;\n    const ctl = d2.$('.adp-ctl'), panel = d2.$('.adp-panel');\n    if(!ctl || !panel) return;\n    const r = ctl.getBoundingClientRect();\n    panel.style.left = Math.round(r.left) + 'px';\n    panel.style.top = Math.round(r.bottom + 4) + 'px';\n  }\n};"}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"placeholder":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"placeholder"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a30465fd73289eb8a0dcf3b","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-carousel","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryBg:'#e6f4ff', colorSuccess:'#52c41a', colorWarning:'#faad14', colorError:'#ff4d4f', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusLG:8, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nfunction normSlides(raw){\n  const arr = Array.isArray(raw) ? raw : [];\n  return arr.map(function(s){\n    if(s == null) return { content:'', bg:null };\n    if(typeof s === 'object') return { content: s.content != null ? String(s.content) : '', bg: s.bg || null };\n    return { content: String(s), bg: null };\n  });\n}\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-carousel{ position:relative; width:100%; overflow:hidden; border-radius:var(--radius); font-family:var(--ff); }\n    .ant-carousel-track{ display:flex; height:var(--ch); transition:transform .45s cubic-bezier(.4,0,.2,1); }\n    .ant-carousel-slide{ flex:0 0 100%; width:100%; height:var(--ch); display:flex; align-items:center; justify-content:center; color:#fff; font-size:18px; padding:0 16px; box-sizing:border-box; text-align:center; }\n    .ant-carousel-arrow{ position:absolute; top:50%; transform:translateY(-50%); width:32px; height:32px; border-radius:50%; background:rgba(0,0,0,0.25); color:#fff; display:flex; align-items:center; justify-content:center; cursor:pointer; opacity:0; transition:opacity .2s, background .2s; z-index:2; }\n    .ant-carousel:hover .ant-carousel-arrow{ opacity:1; }\n    .ant-carousel-arrow:hover{ background:rgba(0,0,0,0.45); }\n    .ant-carousel-arrow.prev{ left:12px; }\n    .ant-carousel-arrow.next{ right:12px; }\n    .ant-carousel-dots{ position:absolute; left:0; right:0; bottom:12px; display:flex; align-items:center; justify-content:center; gap:8px; z-index:2; }\n    .ant-carousel-dot{ width:16px; height:4px; border-radius:2px; background:rgba(255,255,255,0.45); cursor:pointer; transition:background .2s, width .2s; }\n    .ant-carousel-dot.active{ background:var(--c-primary); width:24px; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const slides = normSlides(p.slides);\n    const dots = (p.dots === undefined) ? true : !!p.dots;\n    const h = (typeof p.slideHeight === 'number' && p.slideHeight > 0) ? p.slideHeight : 160;\n    const n = slides.length;\n\n    if(d2.state.index === undefined) d2.state.index = 0;\n    let idx = d2.state.index;\n    if(n === 0) idx = 0;\n    else if(idx >= n) idx = n - 1;\n    else if(idx < 0) idx = 0;\n\n    const style = [\n      '--ff:'+D.fontFamily, '--radius:'+D.borderRadiusLG+'px', '--ch:'+h+'px',\n      '--c-primary:'+D.colorPrimary\n    ].join(';');\n\n    if(n === 0){\n      return '<div class=\"ant-carousel\" style=\"'+style+'\"><div class=\"ant-carousel-slide\" style=\"background:'+D.colorFillTertiary+';color:'+D.colorTextTertiary+'\">No slides</div></div>';\n    }\n\n    let track = '<div class=\"ant-carousel-track\" style=\"transform:translateX(-'+(idx*100)+'%)\">';\n    for(let i = 0; i < n; i++){\n      const bg = slides[i].bg || D.colorPrimary;\n      track += '<div class=\"ant-carousel-slide\" style=\"background:'+esc(bg)+'\">'+esc(slides[i].content)+'</div>';\n    }\n    track += '</div>';\n\n    let arrows = '';\n    if(n > 1){\n      arrows += '<div class=\"ant-carousel-arrow prev\" data-arrow=\"prev\"><i class=\"fa fa-angle-left\"></i></div>';\n      arrows += '<div class=\"ant-carousel-arrow next\" data-arrow=\"next\"><i class=\"fa fa-angle-right\"></i></div>';\n    }\n\n    let dotsHtml = '';\n    if(dots && n > 1){\n      dotsHtml = '<div class=\"ant-carousel-dots\">';\n      for(let i = 0; i < n; i++){\n        dotsHtml += '<span class=\"ant-carousel-dot'+(i===idx?' active':'')+'\" data-dot=\"'+i+'\"></span>';\n      }\n      dotsHtml += '</div>';\n    }\n\n    return '<div class=\"ant-carousel\" style=\"'+style+'\">'+track+arrows+dotsHtml+'</div>';\n  },\n  mounted(d2){\n    function count(){ const s = (d2.params && d2.params.slides); return Array.isArray(s) ? s.length : 0; }\n    function go(to){\n      const n = count();\n      if(n <= 0) return;\n      let i = ((to % n) + n) % n;\n      d2.state.index = i;\n    }\n    d2.on('.ant-carousel-arrow', 'click', (e, el) => {\n      const dir = el.getAttribute('data-arrow');\n      const cur = d2.state.index || 0;\n      go(dir === 'prev' ? cur - 1 : cur + 1);\n    });\n    d2.on('.ant-carousel-dot', 'click', (e, el) => {\n      const i = parseInt(el.getAttribute('data-dot'), 10);\n      if(!isNaN(i)) d2.state.index = i;\n    });\n    if(d2.params && d2.params.autoplay && count() > 1){\n      const timer = setInterval(function(){\n        go((d2.state.index || 0) + 1);\n      }, 3000);\n      d2.onUnmount(function(){ clearInterval(timer); });\n    }\n  }\n};"}},"slides":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"slides"}}}},"dots":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"dots"}}}},"autoplay":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"autoplay"}}}},"slideHeight":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"slideHeight"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a30466fe6cc9d55d3e00484","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-treeselect","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusSM:4, controlHeight:32, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nfunction normTree(raw){\n  const out=[];\n  if(Array.isArray(raw)){\n    for(const n of raw){\n      if(n==null) continue;\n      const key = n.key!=null ? String(n.key) : (n.title!=null ? String(n.title) : '');\n      const title = n.title!=null ? String(n.title) : key;\n      const children = normTree(n.children);\n      out.push({ key, title, children });\n    }\n  }\n  return out;\n}\nfunction findTitle(nodes, key){\n  for(const n of nodes){\n    if(n.key===key) return n.title;\n    if(n.children && n.children.length){ const t=findTitle(n.children,key); if(t!=null) return t; }\n  }\n  return null;\n}\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-ts{ position:relative; box-sizing:border-box; display:inline-block; width:100%; font-family:var(--ff); font-size:var(--fs); }\n    .ant-ts *{ box-sizing:border-box; }\n    .ant-ts-ctl{ position:relative; display:flex; align-items:center; gap:4px; min-height:var(--h); padding:0 11px;\n      background:var(--bg); border:1px solid var(--bc); border-radius:var(--radius); cursor:pointer;\n      transition:border-color .2s, box-shadow .2s; }\n    .ant-ts-ctl:hover{ border-color:var(--bc-h); }\n    .ant-ts.is-open .ant-ts-ctl{ border-color:var(--bc-f); box-shadow:0 0 0 2px var(--ring); }\n    .ant-ts.is-disabled .ant-ts-ctl{ background:var(--bg-dis); border-color:var(--bc); cursor:not-allowed; }\n    .ant-ts-content{ flex:1 1 auto; min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; color:var(--c-text); }\n    .ant-ts-ph{ color:var(--c-ph); }\n    .ant-ts.is-disabled .ant-ts-content{ color:var(--c-dis); }\n    .ant-ts-caret{ color:var(--c-ph); font-size:12px; margin-left:6px; flex:0 0 auto; transition:transform .2s; }\n    .ant-ts.is-open .ant-ts-caret{ transform:rotate(180deg); }\n    .ant-ts-panel{ position:fixed; left:0; top:0; z-index:1200;\n      background:var(--bg); border:1px solid var(--panel-bc); border-radius:var(--radius);\n      box-shadow:0 6px 16px rgba(0,0,0,.12); max-height:300px; overflow:auto; padding:4px; display:none; }\n    .ant-ts.is-open .ant-ts-panel{ display:block; }\n    .ant-ts-node{ display:flex; align-items:center; gap:4px; padding:4px 8px; border-radius:var(--radius-sm);\n      cursor:pointer; color:var(--c-text); white-space:nowrap; }\n    .ant-ts-node:hover{ background:var(--opt-hover); }\n    .ant-ts-node.selected{ background:var(--opt-sel-bg); font-weight:600; }\n    .ant-ts-switcher{ width:16px; flex:0 0 16px; text-align:center; color:var(--c-ph); font-size:11px; cursor:pointer; }\n    .ant-ts-switcher.empty{ visibility:hidden; }\n    .ant-ts-label{ overflow:hidden; text-overflow:ellipsis; }\n    .ant-ts-empty{ padding:16px; text-align:center; color:var(--c-ph); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const tree = normTree(p.treeData);\n    const disabled = !!p.disabled;\n    const placeholder = p.placeholder != null ? String(p.placeholder) : 'Select';\n\n    if(d2.state.open == null) d2.state.open = false;\n    if(d2.state.value == null) d2.state.value = (p.value != null ? String(p.value) : '');\n    if(d2.state.expanded == null) d2.state.expanded = {};\n\n    const open = !!d2.state.open;\n    const value = String(d2.state.value || '');\n    const expanded = d2.state.expanded || {};\n\n    const selTitle = value !== '' ? findTitle(tree, value) : null;\n\n    const style = [\n      '--h:'+D.controlHeight+'px', '--fs:'+D.fontSize+'px',\n      '--radius:'+D.borderRadius+'px', '--radius-sm:'+D.borderRadiusSM+'px',\n      '--bc:'+D.colorBorder, '--bc-h:'+D.colorPrimaryHover, '--bc-f:'+D.colorPrimary,\n      '--ring:rgba(5,145,255,0.1)',\n      '--bg:'+D.colorBgContainer, '--bg-dis:'+D.colorFillTertiary,\n      '--c-text:'+D.colorText, '--c-ph:'+D.colorTextTertiary, '--c-dis:'+D.colorTextDisabled,\n      '--opt-hover:'+D.colorFillTertiary, '--opt-sel-bg:'+D.colorPrimaryBg,\n      '--panel-bc:'+D.colorBorderSecondary, '--ff:'+D.fontFamily\n    ].join(';');\n\n    const rootClasses = ['ant-ts'];\n    if(open) rootClasses.push('is-open');\n    if(disabled) rootClasses.push('is-disabled');\n\n    const contentHtml = (selTitle != null)\n      ? '<span>'+esc(selTitle)+'</span>'\n      : '<span class=\"ant-ts-ph\">'+esc(placeholder)+'</span>';\n\n    function renderNodes(nodes, depth){\n      let html = '';\n      for(const n of nodes){\n        const hasKids = n.children && n.children.length > 0;\n        const isExp = !!expanded[n.key];\n        const isSel = n.key === value;\n        const sw = hasKids\n          ? '<span class=\"ant-ts-switcher\" data-toggle=\"'+esc(n.key)+'\"><i class=\"fa fa-caret-'+(isExp?'down':'right')+'\"></i></span>'\n          : '<span class=\"ant-ts-switcher empty\"></span>';\n        html += '<div class=\"ant-ts-node'+(isSel?' selected':'')+'\" data-key=\"'+esc(n.key)+'\" style=\"padding-left:'+(8 + depth*20)+'px\">'\n          + sw\n          + '<span class=\"ant-ts-label\">'+esc(n.title)+'</span>'\n          + '</div>';\n        if(hasKids && isExp) html += renderNodes(n.children, depth+1);\n      }\n      return html;\n    }\n\n    const panelInner = tree.length === 0\n      ? '<div class=\"ant-ts-empty\">No data</div>'\n      : renderNodes(tree, 0);\n\n    return '<div class=\"'+rootClasses.join(' ')+'\" style=\"'+style+'\">'\n      + '<div class=\"ant-ts-ctl\">'\n      +   '<div class=\"ant-ts-content\">'+contentHtml+'</div>'\n      +   '<i class=\"fa fa-angle-down ant-ts-caret\"></i>'\n      + '</div>'\n      + '<div class=\"ant-ts-panel\">'+panelInner+'</div>'\n      + '</div>';\n  },\n  mounted(d2){\n    d2.on('.ant-ts-ctl','click',(e,el)=>{\n      if((d2.params||{}).disabled) return;\n      d2.state.open = !d2.state.open;\n    });\n\n    d2.on('.ant-ts-switcher','click',(e,el)=>{\n      e.stopPropagation();\n      const key = el.getAttribute('data-toggle');\n      if(key==null) return;\n      const exp = Object.assign({}, d2.state.expanded || {});\n      exp[key] = !exp[key];\n      d2.state.expanded = exp;\n    });\n\n    d2.on('.ant-ts-node','click',(e,el)=>{\n      if((d2.params||{}).disabled) return;\n      if(e.target.closest('.ant-ts-switcher')) return;\n      const key = el.getAttribute('data-key');\n      d2.state.value = key;\n      d2.state.open = false;\n      d2.emit('onChange', key);\n    });\n\n    d2.on(document,'click',(e)=>{\n      if(!d2.state.open) return;\n      const path = (e.composedPath && e.composedPath()) || [];\n      if(d2.root && path.indexOf(d2.root) !== -1) return;\n      d2.state.open = false;\n    });\n  },\n  updated(d2){\n    if(!d2.state.open) return;\n    const ctl = d2.$('.ant-ts-ctl'), panel = d2.$('.ant-ts-panel');\n    if(!ctl || !panel) return;\n    const r = ctl.getBoundingClientRect();\n    panel.style.left = Math.round(r.left) + 'px';\n    panel.style.top = Math.round(r.bottom + 4) + 'px';\n    panel.style.minWidth = Math.round(r.width) + 'px';\n  }\n};"}},"treeData":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"treeData"}}}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"placeholder":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"placeholder"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a30466fccdaee8ef642dce1","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-autocomplete","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusSM:4, controlHeight:32, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\n\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\n\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nfunction normOptions(raw){\n  const out = [];\n  if(Array.isArray(raw)){\n    for(const o of raw){\n      if(o==null) continue;\n      if(typeof o === 'object'){\n        const val = (o.value!=null) ? String(o.value) : (o.label!=null ? String(o.label) : '');\n        const lab = (o.label!=null) ? String(o.label) : val;\n        out.push({ label:lab, value:val });\n      } else {\n        out.push({ label:String(o), value:String(o) });\n      }\n    }\n  }\n  return out;\n}\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-ac{ position:relative; box-sizing:border-box; display:inline-block; width:100%; font-family:var(--ff); font-size:var(--fs); }\n    .ant-ac *{ box-sizing:border-box; }\n    .ant-ac-input{ width:100%; min-height:var(--h); padding:0 11px; background:var(--bg);\n      border:1px solid var(--bc); border-radius:var(--radius); color:var(--c-text); font-size:var(--fs);\n      font-family:var(--ff); outline:none; transition:border-color .2s, box-shadow .2s; }\n    .ant-ac-input::placeholder{ color:var(--c-ph); }\n    .ant-ac-input:hover{ border-color:var(--bc-h); }\n    .ant-ac.is-open .ant-ac-input, .ant-ac-input:focus{ border-color:var(--bc-f); box-shadow:0 0 0 2px var(--ring); }\n    .ant-ac.is-disabled .ant-ac-input{ background:var(--bg-dis); color:var(--c-dis); cursor:not-allowed; }\n    .ant-ac-panel{ position:fixed; left:0; top:0; z-index:1200; background:var(--bg);\n      border:1px solid var(--panel-bc); border-radius:var(--radius); box-shadow:0 6px 16px rgba(0,0,0,.12);\n      max-height:256px; overflow:auto; padding:4px; display:none; }\n    .ant-ac.is-open .ant-ac-panel{ display:block; }\n    .ant-ac-opt{ display:flex; align-items:center; padding:5px 12px; border-radius:var(--radius-sm);\n      cursor:pointer; color:var(--c-text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n    .ant-ac-opt:hover{ background:var(--opt-hover); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const opts = normOptions(p.options);\n    const disabled = !!p.disabled;\n    const placeholder = p.placeholder != null ? String(p.placeholder) : '';\n\n    if(d2.state.open == null) d2.state.open = false;\n    if(d2.state.value == null) d2.state.value = (p.value != null ? String(p.value) : '');\n\n    const value = String(d2.state.value || '');\n    const q = value.toLowerCase();\n    const matches = q ? opts.filter(o=>String(o.label).toLowerCase().indexOf(q) !== -1) : opts;\n    const open = !!d2.state.open && matches.length > 0 && !disabled;\n\n    const style = [\n      '--h:'+D.controlHeight+'px', '--fs:'+D.fontSize+'px', '--radius:'+D.borderRadius+'px',\n      '--radius-sm:'+D.borderRadiusSM+'px', '--bc:'+D.colorBorder, '--bc-h:'+D.colorPrimaryHover,\n      '--bc-f:'+D.colorPrimary, '--ring:rgba(5,145,255,0.1)', '--bg:'+D.colorBgContainer,\n      '--bg-dis:'+D.colorFillTertiary, '--c-text:'+D.colorText, '--c-ph:'+D.colorTextTertiary,\n      '--c-dis:'+D.colorTextDisabled, '--opt-hover:'+D.colorFillTertiary,\n      '--panel-bc:'+D.colorBorderSecondary, '--ff:'+D.fontFamily\n    ].join(';');\n\n    const cls = ['ant-ac'];\n    if(open) cls.push('is-open');\n    if(disabled) cls.push('is-disabled');\n\n    let panelInner = matches.map(o=>{\n      return '<div class=\"ant-ac-opt\" data-value=\"'+esc(o.value)+'\">'+esc(o.label)+'</div>';\n    }).join('');\n\n    return '<div class=\"'+cls.join(' ')+'\" style=\"'+style+'\">'\n      + '<input class=\"ant-ac-input\" type=\"text\" autocomplete=\"off\" value=\"'+esc(value)+'\" placeholder=\"'+esc(placeholder)+'\"'+(disabled?' disabled':'')+' />'\n      + '<div class=\"ant-ac-panel\">'+panelInner+'</div>'\n      + '</div>';\n  },\n  mounted(d2){\n    d2.on('.ant-ac-input','input',(e)=>{\n      if((d2.params||{}).disabled) return;\n      d2.state.value = e.target.value;\n      d2.state.open = true;\n      d2.emit('onChange', { value: e.target.value });\n    });\n    d2.on('.ant-ac-input','focus',()=>{\n      if((d2.params||{}).disabled) return;\n      d2.state.open = true;\n    });\n    d2.on('.ant-ac-opt','click',(e, el)=>{\n      if((d2.params||{}).disabled) return;\n      const node = el || e.target.closest('.ant-ac-opt');\n      const val = node.getAttribute('data-value');\n      d2.state.value = val;\n      d2.state.open = false;\n      d2.emit('onChange', { value: val });\n      d2.emit('onSelect', { value: val });\n    });\n    d2.on(document,'click',(e)=>{\n      if(!d2.state.open) return;\n      const path = (e.composedPath && e.composedPath()) || [];\n      if(d2.root && path.indexOf(d2.root) !== -1) return;\n      d2.state.open = false;\n    });\n  },\n  updated(d2){\n    if(!d2.state.open) return;\n    const inp = d2.$('.ant-ac-input'), panel = d2.$('.ant-ac-panel');\n    if(!inp || !panel) return;\n    const r = inp.getBoundingClientRect();\n    panel.style.left = Math.round(r.left) + 'px';\n    panel.style.top = Math.round(r.bottom + 4) + 'px';\n    panel.style.width = Math.round(r.width) + 'px';\n  }\n};"}},"options":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"options"}}}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"placeholder":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"placeholder"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"onSelect":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onSelect"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a3046702ae3e526cfd4dad3","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-timepicker","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusSM:4, controlHeight:32, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nfunction pad2(n){ return (n<10?'0':'')+n; }\nfunction parseHM(s){ if(!s||typeof s!=='string') return null; const m=s.split(':'); if(m.length<2) return null; const h=parseInt(m[0],10),mi=parseInt(m[1],10); if(!(h>=0&&h<=23)||!(mi>=0&&mi<=59)) return null; return {h:h,m:mi}; }\nfunction fmt24(o){ return pad2(o.h)+':'+pad2(o.m); }\nfunction fmt12(o){ const ap=o.h<12?'AM':'PM'; let hh=o.h%12; if(hh===0) hh=12; return pad2(hh)+':'+pad2(o.m)+' '+ap; }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .atp{ position:relative; box-sizing:border-box; display:inline-block; width:100%; font-family:var(--ff); font-size:var(--fs); }\n    .atp *{ box-sizing:border-box; }\n    .atp-ctl{ position:relative; display:flex; align-items:center; gap:4px; min-height:var(--h); padding:0 11px;\n      background:var(--bg); border:1px solid var(--bc); border-radius:var(--radius); cursor:pointer; transition:border-color .2s, box-shadow .2s; }\n    .atp-ctl:hover{ border-color:var(--bc-h); }\n    .atp.is-open .atp-ctl{ border-color:var(--bc-f); box-shadow:0 0 0 2px var(--ring); }\n    .atp.is-disabled .atp-ctl{ background:var(--bg-dis); border-color:var(--bc); cursor:not-allowed; }\n    .atp.is-disabled .atp-text{ color:var(--c-dis); }\n    .atp-text{ flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--c-text); }\n    .atp-text.is-ph{ color:var(--c-ph); }\n    .atp-icon{ flex:0 0 auto; margin-left:6px; color:var(--c-ph); font-size:13px; }\n    .atp-panel{ position:fixed; left:0; top:0; z-index:1200; background:var(--bg);\n      border:1px solid var(--panel-bc); border-radius:var(--radius); box-shadow:0 6px 16px rgba(0,0,0,.12);\n      padding:0; display:none; }\n    .atp.is-open .atp-panel{ display:block; }\n    .atp-cols{ display:flex; }\n    .atp-col{ width:56px; max-height:200px; overflow-y:auto; padding:4px 0; }\n    .atp-col + .atp-col{ border-left:1px solid var(--panel-bc); }\n    .atp-row{ height:28px; line-height:28px; text-align:center; cursor:pointer; color:var(--c-text); border-radius:var(--radius-sm); margin:1px 4px; }\n    .atp-row:hover{ background:var(--cell-hover); }\n    .atp-row.sel{ background:var(--c-primary-bg); color:var(--c-primary); font-weight:600; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const disabled = !!p.disabled;\n    const use12 = !!p.use12Hours;\n    const placeholder = p.placeholder != null ? String(p.placeholder) : 'Select time';\n\n    if(d2.state.open == null) d2.state.open = false;\n    if(d2.state.value == null) d2.state.value = (p.value != null ? String(p.value) : '');\n\n    const open = !!d2.state.open;\n    const selObj = parseHM(String(d2.state.value||''));\n\n    const style = [\n      '--h:'+D.controlHeight+'px','--fs:'+D.fontSize+'px','--radius:'+D.borderRadius+'px','--radius-sm:'+D.borderRadiusSM+'px',\n      '--bc:'+D.colorBorder,'--bc-h:'+D.colorPrimaryHover,'--bc-f:'+D.colorPrimary,'--ring:rgba(5,145,255,0.1)',\n      '--bg:'+D.colorBgContainer,'--bg-dis:'+D.colorFillTertiary,\n      '--c-text:'+D.colorText,'--c-ph:'+D.colorTextTertiary,'--c-dis:'+D.colorTextDisabled,\n      '--c-primary:'+D.colorPrimary,'--c-primary-bg:'+D.colorPrimaryBg,'--cell-hover:'+D.colorFillTertiary,'--panel-bc:'+D.colorBorderSecondary,'--ff:'+D.fontFamily\n    ].join(';');\n\n    const rootClasses=['atp']; if(open) rootClasses.push('is-open'); if(disabled) rootClasses.push('is-disabled');\n\n    const hasValue = !!selObj;\n    const text = hasValue ? (use12 ? fmt12(selObj) : fmt24(selObj)) : placeholder;\n    const ctlHtml = '<div class=\"atp-ctl\">'\n      + '<span class=\"atp-text'+(hasValue?'':' is-ph')+'\">'+esc(text)+'</span>'\n      + '<i class=\"fa fa-clock-o atp-icon\"></i>'\n      + '</div>';\n\n    const curH = selObj ? selObj.h : -1;\n    const curM = selObj ? selObj.m : -1;\n    let hourRows = '';\n    for(let h=0; h<=23; h++){\n      hourRows += '<div class=\"atp-row'+(h===curH?' sel':'')+'\" data-h=\"'+h+'\">'+pad2(h)+'</div>';\n    }\n    let minRows = '';\n    for(let mi=0; mi<=59; mi++){\n      minRows += '<div class=\"atp-row'+(mi===curM?' sel':'')+'\" data-m=\"'+mi+'\">'+pad2(mi)+'</div>';\n    }\n\n    const panelHtml = '<div class=\"atp-panel\">'\n      + '<div class=\"atp-cols\">'\n      +   '<div class=\"atp-col atp-col-h\">'+hourRows+'</div>'\n      +   '<div class=\"atp-col atp-col-m\">'+minRows+'</div>'\n      + '</div>'\n      + '</div>';\n\n    return '<div class=\"'+rootClasses.join(' ')+'\" style=\"'+style+'\">'+ctlHtml+panelHtml+'</div>';\n  },\n  mounted(d2){\n    const emit = ()=>{\n      const o = parseHM(String(d2.state.value||''));\n      if(o) d2.emit('onChange', fmt24(o));\n    };\n    d2.on('.atp-ctl','click',(e)=>{\n      if((d2.params||{}).disabled) return;\n      d2.state.open = !d2.state.open;\n    });\n    d2.on('[data-h]','click',(e,el)=>{\n      const h = parseInt(el.getAttribute('data-h'),10);\n      const cur = parseHM(String(d2.state.value||'')) || {h:0,m:0};\n      d2.state.value = pad2(h)+':'+pad2(cur.m);\n      emit();\n    });\n    d2.on('[data-m]','click',(e,el)=>{\n      const mi = parseInt(el.getAttribute('data-m'),10);\n      const cur = parseHM(String(d2.state.value||'')) || {h:0,m:0};\n      d2.state.value = pad2(cur.h)+':'+pad2(mi);\n      emit();\n    });\n    d2.on(document,'click',(e)=>{\n      if(!d2.state.open) return;\n      const path = (e.composedPath && e.composedPath()) || [];\n      if(d2.root && path.indexOf(d2.root) !== -1) return;\n      d2.state.open = false;\n    });\n  },\n  updated(d2){\n    if(!d2.state.open) return;\n    const ctl = d2.$('.atp-ctl'), panel = d2.$('.atp-panel');\n    if(!ctl || !panel) return;\n    const r = ctl.getBoundingClientRect();\n    panel.style.left = Math.round(r.left) + 'px';\n    panel.style.top = Math.round(r.bottom + 4) + 'px';\n    // scroll selected rows into view\n    const selH = d2.$('.atp-col-h .atp-row.sel'), selM = d2.$('.atp-col-m .atp-row.sel');\n    if(selH && selH.parentNode) selH.parentNode.scrollTop = selH.offsetTop - 4;\n    if(selM && selM.parentNode) selM.parentNode.scrollTop = selM.offsetTop - 4;\n  }\n};"}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"placeholder":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"placeholder"}}}},"use12Hours":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"use12Hours"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a30467f9421d071c912b3a4","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-form","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorError:'#ff4d4f', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', borderRadius:6, controlHeight:32, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    .ant-form{ box-sizing:border-box; font-family:var(--ff); font-size:var(--fs); color:var(--ct); }\n    .ant-form *{ box-sizing:border-box; }\n    .ant-form .af-item{ margin-bottom:24px; }\n    .ant-form.af-vertical .af-item{ display:flex; flex-direction:column; gap:8px; }\n    .ant-form.af-horizontal .af-item{ display:flex; flex-direction:row; align-items:flex-start; gap:12px; }\n    .ant-form.af-horizontal .af-label{ width:100px; flex:0 0 100px; text-align:right; padding-top:6px; }\n    .ant-form.af-horizontal .af-control{ flex:1 1 auto; }\n    .ant-form.af-inline{ display:flex; flex-wrap:wrap; align-items:flex-end; gap:16px; }\n    .ant-form.af-inline .af-item{ margin-bottom:0; display:flex; flex-direction:column; gap:8px; }\n    .ant-form .af-label{ line-height:1.5; color:var(--ct); }\n    .ant-form .af-req{ color:var(--cerr); margin-right:4px; font-family:SimSun,sans-serif; }\n    .ant-form .af-control{ display:flex; }\n    .ant-form .af-field{ width:100%; }\n    .ant-form .af-field input, .ant-form .af-field textarea, .ant-form .af-field select{\n      width:100%; box-sizing:border-box; font-family:inherit; font-size:var(--fs); color:var(--ct);\n      background:var(--cbg); border:1px solid var(--cbd); border-radius:var(--radius);\n      padding:4px 11px; line-height:1.5; outline:none; transition:border-color .2s,box-shadow .2s; }\n    .ant-form .af-field input, .ant-form .af-field select{ height:var(--h); }\n    .ant-form .af-field textarea{ min-height:64px; resize:vertical; padding-top:5px; padding-bottom:5px; }\n    .ant-form .af-field input:hover, .ant-form .af-field textarea:hover, .ant-form .af-field select:hover{ border-color:var(--cph); }\n    .ant-form .af-field input:focus, .ant-form .af-field textarea:focus, .ant-form .af-field select:focus{ border-color:var(--cp); box-shadow:0 0 0 2px var(--cpbg); }\n    .ant-form .af-submit{ display:inline-flex; align-items:center; justify-content:center; height:var(--h);\n      padding:0 15px; font-size:var(--fs); font-family:inherit; border:1px solid var(--cp); border-radius:var(--radius);\n      background:var(--cp); color:var(--cwhite); cursor:pointer; outline:none; transition:all .2s; }\n    .ant-form .af-submit:hover{ background:var(--cph); border-color:var(--cph); }\n    .ant-form .af-submit:active{ background:var(--cpa); border-color:var(--cpa); }\n    .ant-form.af-vertical .af-actions, .ant-form.af-horizontal .af-actions{ margin-top:4px; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const layout = p.layout || 'vertical';\n    const submitText = p.submitText != null ? String(p.submitText) : 'Submit';\n    let fields = Array.isArray(p.fields) ? p.fields : [];\n    if(!d2.state.values) d2.state.values = {};\n    const values = d2.state.values;\n\n    const style = [\n      '--ff:'+D.fontFamily, '--fs:'+D.fontSize+'px', '--ct:'+D.colorText,\n      '--cerr:'+D.colorError, '--cbd:'+D.colorBorder, '--cbg:'+D.colorBgContainer,\n      '--cp:'+D.colorPrimary, '--cph:'+D.colorPrimaryHover, '--cpa:'+D.colorPrimaryActive,\n      '--cpbg:'+D.colorPrimaryBg, '--cwhite:'+D.colorTextLightSolid,\n      '--h:'+D.controlHeight+'px', '--radius:'+D.borderRadius+'px'\n    ].join(';');\n\n    let itemsHtml = '';\n    fields.forEach(function(f, i){\n      const name = f && f.name != null ? String(f.name) : ('field'+i);\n      const type = f && f.type ? String(f.type) : 'text';\n      const label = f && f.label != null ? String(f.label) : '';\n      const ph = f && f.placeholder != null ? String(f.placeholder) : '';\n      const req = !!(f && f.required);\n      const val = values[name] != null ? values[name] : '';\n      const labelHtml = label ? ('<div class=\"af-label\">'+(req?'<span class=\"af-req\">*</span>':'')+esc(label)+'</div>') : '';\n      let control = '';\n      if(type === 'textarea'){\n        control = '<textarea class=\"af-field\" data-name=\"'+esc(name)+'\" placeholder=\"'+esc(ph)+'\">'+esc(val)+'</textarea>';\n      } else if(type === 'select'){\n        const opts = Array.isArray(f.options) ? f.options : [];\n        let optsHtml = '<option value=\"\"'+(val===''?' selected':'')+' disabled>'+esc(ph||'Select')+'</option>';\n        opts.forEach(function(o){\n          const ov = (o && typeof o === 'object') ? (o.value != null ? o.value : o.label) : o;\n          const ol = (o && typeof o === 'object') ? (o.label != null ? o.label : o.value) : o;\n          optsHtml += '<option value=\"'+esc(ov)+'\"'+(String(val)===String(ov)?' selected':'')+'>'+esc(ol)+'</option>';\n        });\n        control = '<select class=\"af-field\" data-name=\"'+esc(name)+'\">'+optsHtml+'</select>';\n      } else {\n        const itype = type === 'password' ? 'password' : 'text';\n        control = '<input class=\"af-field\" type=\"'+itype+'\" data-name=\"'+esc(name)+'\" placeholder=\"'+esc(ph)+'\" value=\"'+esc(val)+'\">';\n      }\n      itemsHtml += '<div class=\"af-item\"><div class=\"af-label-wrap\">'+labelHtml+'</div><div class=\"af-control\">'+control+'</div></div>';\n    });\n\n    const actions = '<div class=\"af-item af-actions\"><div class=\"af-control\"><button type=\"button\" class=\"af-submit\">'+esc(submitText)+'</button></div></div>';\n\n    return '<form class=\"ant-form af-'+esc(layout)+'\" style=\"'+style+'\" onsubmit=\"return false;\">'+itemsHtml+actions+'</form>';\n  },\n  mounted(d2){\n    function sync(el){ const name = el.getAttribute('data-name'); if(!name) return; if(!d2.state.values) d2.state.values = {}; d2.state.values[name] = el.value; }\n    d2.on('.af-field','input',(e, el)=>{ sync(el); });\n    d2.on('.af-field','change',(e, el)=>{ sync(el); });\n    d2.on('.af-submit','click',(e, el)=>{ d2.emit('onSubmit', Object.assign({}, d2.state.values || {})); });\n  }\n};"}},"fields":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"fields"}}}},"layout":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"layout"}}}},"submitText":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"submitText"}}}},"onSubmit":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onSubmit"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a30469756f919e52311677e","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-transfer","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusSM:4, controlHeight:32, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nfunction normItems(raw){\n  const out=[];\n  if(Array.isArray(raw)){\n    for(const o of raw){\n      if(o==null) continue;\n      if(typeof o === 'object'){\n        const key = o.key!=null ? String(o.key) : (o.title!=null ? String(o.title) : '');\n        const title = o.title!=null ? String(o.title) : key;\n        out.push({ key, title });\n      } else {\n        out.push({ key:String(o), title:String(o) });\n      }\n    }\n  }\n  return out;\n}\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-tr{ box-sizing:border-box; display:inline-flex; align-items:stretch; gap:8px; font-family:var(--ff); font-size:var(--fs); color:var(--c-text); }\n    .ant-tr *{ box-sizing:border-box; }\n    .ant-tr-list{ width:180px; display:flex; flex-direction:column; border:1px solid var(--bc); border-radius:var(--radius); background:var(--bg); overflow:hidden; }\n    .ant-tr-head{ display:flex; align-items:center; justify-content:space-between; gap:8px; padding:8px 12px;\n      border-bottom:1px solid var(--bc-sec); background:var(--head-bg); font-weight:500; }\n    .ant-tr-head .cnt{ color:var(--c-sec); font-weight:400; font-size:12px; }\n    .ant-tr-body{ flex:1 1 auto; max-height:220px; min-height:120px; overflow:auto; padding:4px 0; }\n    .ant-tr-item{ display:flex; align-items:center; gap:8px; padding:5px 12px; cursor:pointer; }\n    .ant-tr-item:hover{ background:var(--opt-hover); }\n    .ant-tr-cb{ width:16px; height:16px; flex:0 0 16px; border:1px solid var(--bc); border-radius:var(--radius-sm);\n      display:inline-flex; align-items:center; justify-content:center; background:var(--bg); transition:all .2s; }\n    .ant-tr-item.checked .ant-tr-cb{ background:var(--c-primary); border-color:var(--c-primary); color:#fff; }\n    .ant-tr-cb i{ font-size:10px; opacity:0; }\n    .ant-tr-item.checked .ant-tr-cb i{ opacity:1; }\n    .ant-tr-title{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n    .ant-tr-empty{ padding:24px 12px; text-align:center; color:var(--c-ph); }\n    .ant-tr-ops{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:8px; }\n    .ant-tr-arrow{ width:28px; height:28px; border:1px solid var(--bc); border-radius:var(--radius);\n      background:var(--bg); color:var(--c-sec); cursor:pointer; display:inline-flex; align-items:center; justify-content:center; transition:all .2s; }\n    .ant-tr-arrow:hover:not(.disabled){ border-color:var(--c-primary); color:var(--c-primary); }\n    .ant-tr-arrow.disabled{ cursor:not-allowed; color:var(--c-dis); border-color:var(--bc); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const items = normItems(p.dataSource);\n    const titles = Array.isArray(p.titles) && p.titles.length ? p.titles : ['Source','Target'];\n\n    if(d2.state.target == null){\n      d2.state.target = Array.isArray(p.targetKeys) ? p.targetKeys.map(String) : [];\n    }\n    if(d2.state.checked == null) d2.state.checked = {};\n\n    const target = (d2.state.target || []).map(String);\n    const targetSet = {}; target.forEach(k=>{ targetSet[k]=true; });\n    const checked = d2.state.checked || {};\n\n    const left = items.filter(i=>!targetSet[i.key]);\n    const right = items.filter(i=>targetSet[i.key]);\n\n    const leftChecked = left.filter(i=>checked[i.key]).length;\n    const rightChecked = right.filter(i=>checked[i.key]).length;\n\n    const style = [\n      '--fs:'+D.fontSize+'px', '--radius:'+D.borderRadius+'px', '--radius-sm:'+D.borderRadiusSM+'px',\n      '--bc:'+D.colorBorder, '--bc-sec:'+D.colorBorderSecondary,\n      '--bg:'+D.colorBgContainer, '--head-bg:'+D.colorFillTertiary,\n      '--c-text:'+D.colorText, '--c-sec:'+D.colorTextSecondary, '--c-ph:'+D.colorTextTertiary, '--c-dis:'+D.colorTextDisabled,\n      '--c-primary:'+D.colorPrimary, '--opt-hover:'+D.colorFillTertiary, '--ff:'+D.fontFamily\n    ].join(';');\n\n    function listHtml(side, list, title){\n      const rows = list.length\n        ? list.map(i=>{\n            const on = !!checked[i.key];\n            return '<div class=\"ant-tr-item'+(on?' checked':'')+'\" data-toggle=\"'+esc(i.key)+'\" data-key=\"'+esc(i.key)+'\">'\n              + '<span class=\"ant-tr-cb\"><i class=\"fa fa-check\"></i></span>'\n              + '<span class=\"ant-tr-title\">'+esc(i.title)+'</span>'\n              + '</div>';\n          }).join('')\n        : '<div class=\"ant-tr-empty\">No data</div>';\n      return '<div class=\"ant-tr-list\" data-side=\"'+side+'\">'\n        + '<div class=\"ant-tr-head\"><span>'+esc(title)+'</span><span class=\"cnt\">'+list.length+'</span></div>'\n        + '<div class=\"ant-tr-body\">'+rows+'</div>'\n        + '</div>';\n    }\n\n    const toRightDis = leftChecked === 0;\n    const toLeftDis = rightChecked === 0;\n\n    return '<div class=\"ant-tr\" style=\"'+style+'\">'\n      + listHtml('left', left, titles[0])\n      + '<div class=\"ant-tr-ops\">'\n      +   '<span class=\"ant-tr-arrow'+(toRightDis?' disabled':'')+'\" data-move=\"right\"><i class=\"fa fa-angle-right\"></i></span>'\n      +   '<span class=\"ant-tr-arrow'+(toLeftDis?' disabled':'')+'\" data-move=\"left\"><i class=\"fa fa-angle-left\"></i></span>'\n      + '</div>'\n      + listHtml('right', right, titles[1])\n      + '</div>';\n  },\n  mounted(d2){\n    d2.on('.ant-tr-item','click',(e,el)=>{\n      const key = el.getAttribute('data-toggle');\n      const chk = Object.assign({}, d2.state.checked || {});\n      chk[key] = !chk[key];\n      d2.state.checked = chk;\n    });\n\n    d2.on('.ant-tr-arrow','click',(e,el)=>{\n      if(el.classList.contains('disabled')) return;\n      const dir = el.getAttribute('data-move');\n      const items = (function(raw){ const o=[]; if(Array.isArray(raw)) for(const x of raw){ if(x&&typeof x==='object') o.push(String(x.key!=null?x.key:x.title)); else if(x!=null) o.push(String(x)); } return o; })((d2.params||{}).dataSource);\n      const target = (d2.state.target || []).map(String);\n      const targetSet = {}; target.forEach(k=>{ targetSet[k]=true; });\n      const checked = d2.state.checked || {};\n      let next;\n      if(dir === 'right'){\n        // move checked items NOT in target -> into target\n        const moving = items.filter(k=>!targetSet[k] && checked[k]);\n        next = target.concat(moving);\n      } else {\n        // move checked items IN target -> out\n        next = target.filter(k=>!checked[k]);\n      }\n      // clear checked state for moved items\n      const chk = Object.assign({}, checked);\n      Object.keys(chk).forEach(k=>{ delete chk[k]; });\n      d2.state.target = next;\n      d2.state.checked = chk;\n      d2.emit('onChange', next);\n    });\n  }\n};"}},"dataSource":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"dataSource"}}}},"targetKeys":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"targetKeys"}}}},"titles":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"titles"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a3046980e623bb33782248b","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-colorpicker","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusSM:4, controlHeight:32, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nconst PRESETS = ['#1677ff','#52c41a','#faad14','#ff4d4f','#722ed1','#13c2c2','#eb2f96','#000000'];\nfunction normHex(v){ if(!v||typeof v!=='string') return '#1677ff'; let s=v.trim(); if(s[0]!=='#') s='#'+s; return s; }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .acp{ position:relative; box-sizing:border-box; display:inline-block; font-family:var(--ff); font-size:var(--fs); }\n    .acp *{ box-sizing:border-box; }\n    .acp-ctl{ position:relative; display:inline-flex; align-items:center; gap:8px; min-height:var(--h); padding:3px 8px;\n      background:var(--bg); border:1px solid var(--bc); border-radius:var(--radius); cursor:pointer; transition:border-color .2s, box-shadow .2s; }\n    .acp-ctl:hover{ border-color:var(--bc-h); }\n    .acp.is-open .acp-ctl{ border-color:var(--bc-f); box-shadow:0 0 0 2px var(--ring); }\n    .acp.is-disabled .acp-ctl{ background:var(--bg-dis); border-color:var(--bc); cursor:not-allowed; }\n    .acp-swatch{ width:24px; height:24px; border-radius:var(--radius-sm); border:1px solid var(--swatch-bc); flex:0 0 auto;\n      background-image:linear-gradient(45deg,#eee 25%,transparent 25%),linear-gradient(-45deg,#eee 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#eee 75%),linear-gradient(-45deg,transparent 75%,#eee 75%); background-size:8px 8px; background-position:0 0,0 4px,4px -4px,-4px 0; }\n    .acp-swatch-fill{ width:100%; height:100%; border-radius:inherit; }\n    .acp-textval{ color:var(--c-text); font-size:var(--fs); }\n    .acp-panel{ position:fixed; left:0; top:0; z-index:1200; width:240px; background:var(--bg);\n      border:1px solid var(--panel-bc); border-radius:var(--radius); box-shadow:0 6px 16px rgba(0,0,0,.12);\n      padding:12px; display:none; }\n    .acp.is-open .acp-panel{ display:block; }\n    .acp-native{ width:100%; height:120px; border:none; border-radius:var(--radius-sm); cursor:pointer; padding:0; background:none; }\n    .acp-hexrow{ display:flex; align-items:center; gap:8px; margin-top:10px; }\n    .acp-hexrow label{ color:var(--c-ph); font-size:12px; }\n    .acp-hex{ flex:1 1 auto; min-width:0; height:28px; padding:0 8px; border:1px solid var(--bc); border-radius:var(--radius-sm);\n      font-size:var(--fs); font-family:var(--ff); color:var(--c-text); outline:none; }\n    .acp-hex:focus{ border-color:var(--bc-f); box-shadow:0 0 0 2px var(--ring); }\n    .acp-presets{ display:flex; flex-wrap:wrap; gap:6px; margin-top:12px; }\n    .acp-preset{ width:20px; height:20px; border-radius:var(--radius-sm); cursor:pointer; border:1px solid var(--swatch-bc); }\n    .acp-preset:hover{ transform:scale(1.1); }\n    .acp-preset.sel{ box-shadow:0 0 0 2px var(--bg),0 0 0 4px var(--c-primary); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const disabled = !!p.disabled;\n    const showText = !!p.showText;\n\n    if(d2.state.open == null) d2.state.open = false;\n    if(d2.state.value == null) d2.state.value = normHex(p.value != null ? String(p.value) : '#1677ff');\n\n    const open = !!d2.state.open;\n    const value = normHex(String(d2.state.value||'#1677ff'));\n\n    const style = [\n      '--h:'+D.controlHeight+'px','--fs:'+D.fontSize+'px','--radius:'+D.borderRadius+'px','--radius-sm:'+D.borderRadiusSM+'px',\n      '--bc:'+D.colorBorder,'--bc-h:'+D.colorPrimaryHover,'--bc-f:'+D.colorPrimary,'--ring:rgba(5,145,255,0.1)',\n      '--bg:'+D.colorBgContainer,'--bg-dis:'+D.colorFillTertiary,\n      '--c-text:'+D.colorText,'--c-ph:'+D.colorTextTertiary,\n      '--c-primary:'+D.colorPrimary,'--swatch-bc:'+D.colorBorderSecondary,'--panel-bc:'+D.colorBorderSecondary,'--ff:'+D.fontFamily\n    ].join(';');\n\n    const rootClasses=['acp']; if(open) rootClasses.push('is-open'); if(disabled) rootClasses.push('is-disabled');\n\n    const ctlHtml = '<div class=\"acp-ctl\">'\n      + '<span class=\"acp-swatch\"><span class=\"acp-swatch-fill\" style=\"background:'+esc(value)+'\"></span></span>'\n      + (showText ? '<span class=\"acp-textval\">'+esc(value)+'</span>' : '')\n      + '</div>';\n\n    let presetHtml = '';\n    for(const c of PRESETS){\n      const sel = c.toLowerCase() === value.toLowerCase();\n      presetHtml += '<span class=\"acp-preset'+(sel?' sel':'')+'\" data-preset=\"'+esc(c)+'\" style=\"background:'+esc(c)+'\"></span>';\n    }\n\n    const panelHtml = '<div class=\"acp-panel\">'\n      + '<input class=\"acp-native\" type=\"color\" value=\"'+esc(value)+'\" />'\n      + '<div class=\"acp-hexrow\"><label>Hex</label><input class=\"acp-hex\" type=\"text\" value=\"'+esc(value)+'\" /></div>'\n      + '<div class=\"acp-presets\">'+presetHtml+'</div>'\n      + '</div>';\n\n    return '<div class=\"'+rootClasses.join(' ')+'\" style=\"'+style+'\">'+ctlHtml+panelHtml+'</div>';\n  },\n  mounted(d2){\n    const setVal = (v)=>{\n      const hex = normHex(v);\n      d2.state.value = hex;\n      d2.emit('onChange', hex);\n    };\n    d2.on('.acp-ctl','click',(e)=>{\n      if((d2.params||{}).disabled) return;\n      d2.state.open = !d2.state.open;\n    });\n    // native color input — live update on input, commit on change\n    d2.on('.acp-native','input',(e,el)=>{ setVal(el.value); });\n    d2.on('.acp-native','change',(e,el)=>{ setVal(el.value); });\n    // hex text input\n    d2.on('.acp-hex','change',(e,el)=>{ setVal(el.value); });\n    // presets\n    d2.on('.acp-preset','click',(e,el)=>{\n      e.stopPropagation();\n      setVal(el.getAttribute('data-preset'));\n    });\n    d2.on(document,'click',(e)=>{\n      if(!d2.state.open) return;\n      const path = (e.composedPath && e.composedPath()) || [];\n      if(d2.root && path.indexOf(d2.root) !== -1) return;\n      d2.state.open = false;\n    });\n  },\n  updated(d2){\n    if(!d2.state.open) return;\n    const ctl = d2.$('.acp-ctl'), panel = d2.$('.acp-panel');\n    if(!ctl || !panel) return;\n    const r = ctl.getBoundingClientRect();\n    panel.style.left = Math.round(r.left) + 'px';\n    panel.style.top = Math.round(r.bottom + 4) + 'px';\n  }\n};"}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"showText":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"showText"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a30469b7fc78eca6d2aae17","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-anchor","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorError:'#ff4d4f', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', borderRadius:6, controlHeight:32, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    .ant-anchor{ box-sizing:border-box; font-family:var(--ff); font-size:var(--fs); }\n    .ant-anchor *{ box-sizing:border-box; }\n    .ant-anchor a{ text-decoration:none; }\n    /* vertical */\n    .ant-anchor.aa-vertical{ position:relative; padding-left:2px; }\n    .ant-anchor.aa-vertical .aa-rail{ position:absolute; left:0; top:0; bottom:0; width:2px; background:var(--cbd2); }\n    .ant-anchor.aa-vertical .aa-ink{ position:absolute; left:0; width:2px; background:var(--cp); transition:top .2s,height .2s; }\n    .ant-anchor.aa-vertical .aa-link{ display:block; padding:4px 0 4px 16px; line-height:1.5; color:var(--ct); transition:color .2s; }\n    .ant-anchor.aa-vertical .aa-link:hover{ color:var(--cp); }\n    .ant-anchor.aa-vertical .aa-link.active{ color:var(--cp); }\n    /* horizontal */\n    .ant-anchor.aa-horizontal{ display:flex; flex-direction:row; align-items:center; gap:0; border-bottom:1px solid var(--cbd2); }\n    .ant-anchor.aa-horizontal .aa-link{ position:relative; display:inline-block; padding:8px 16px; color:var(--ct); transition:color .2s; }\n    .ant-anchor.aa-horizontal .aa-link:hover{ color:var(--cp); }\n    .ant-anchor.aa-horizontal .aa-link.active{ color:var(--cp); }\n    .ant-anchor.aa-horizontal .aa-link.active::after{ content:''; position:absolute; left:16px; right:16px; bottom:-1px; height:2px; background:var(--cp); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const direction = p.direction || 'vertical';\n    let items = Array.isArray(p.items) ? p.items : [];\n    if(d2.state.active == null){ d2.state.active = (p.activeKey != null ? p.activeKey : (items[0] ? items[0].key : null)); }\n    const active = d2.state.active;\n\n    const style = [\n      '--ff:'+D.fontFamily, '--fs:'+D.fontSize+'px', '--ct:'+D.colorText,\n      '--cp:'+D.colorPrimary, '--cbd2:'+D.colorBorderSecondary\n    ].join(';');\n\n    let activeIdx = -1;\n    let linksHtml = '';\n    items.forEach(function(it, i){\n      const key = it && it.key != null ? String(it.key) : ('item'+i);\n      const title = it && it.title != null ? String(it.title) : key;\n      const href = it && it.href != null ? String(it.href) : '#';\n      const isActive = String(active) === key;\n      if(isActive) activeIdx = i;\n      linksHtml += '<a class=\"aa-link'+(isActive?' active':'')+'\" data-key=\"'+esc(key)+'\" href=\"'+esc(href)+'\">'+esc(title)+'</a>';\n    });\n\n    if(direction === 'horizontal'){\n      return '<div class=\"ant-anchor aa-horizontal\" style=\"'+style+'\">'+linksHtml+'</div>';\n    }\n    const rowH = (D.fontSize * 1.5) + 8;\n    const inkTop = activeIdx >= 0 ? (activeIdx * rowH + 4) : 0;\n    const inkH = activeIdx >= 0 ? (D.fontSize * 1.5) : 0;\n    const ink = '<span class=\"aa-ink\" style=\"top:'+inkTop+'px;height:'+inkH+'px\"></span>';\n    const rail = '<span class=\"aa-rail\"></span>';\n    return '<div class=\"ant-anchor aa-vertical\" style=\"'+style+'\">'+rail+ink+linksHtml+'</div>';\n  },\n  mounted(d2){\n    d2.on('.aa-link','click',(e, el)=>{\n      e.preventDefault();\n      const key = el.getAttribute('data-key');\n      d2.state.active = key;\n      d2.emit('onClick', key);\n    });\n  }\n};"}},"items":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"items"}}}},"activeKey":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"activeKey"}}}},"direction":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"direction"}}}},"onClick":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onClick"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a3046aa6202ef3347e13354","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-mentions","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusSM:4, controlHeight:32, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\n\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\n\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nfunction normNames(raw){\n  const out = [];\n  if(Array.isArray(raw)){\n    for(const o of raw){\n      if(o==null) continue;\n      if(typeof o === 'object'){ out.push(String(o.value!=null?o.value:(o.label!=null?o.label:''))); }\n      else out.push(String(o));\n    }\n  }\n  return out.filter(s=>s!=='');\n}\n\n// trailing @word at end of the typed value\nfunction trailingMention(value){\n  const m = /(^|\\s)@([^\\s@]*)$/.exec(value);\n  if(!m) return null;\n  return { query: m[2], start: value.length - m[2].length - 1 };\n}\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-mn{ position:relative; box-sizing:border-box; display:inline-block; width:100%; font-family:var(--ff); font-size:var(--fs); }\n    .ant-mn *{ box-sizing:border-box; }\n    .ant-mn-ta{ width:100%; padding:5px 11px; background:var(--bg); border:1px solid var(--bc);\n      border-radius:var(--radius); color:var(--c-text); font-size:var(--fs); font-family:var(--ff);\n      line-height:1.5715; outline:none; resize:vertical; transition:border-color .2s, box-shadow .2s; }\n    .ant-mn-ta::placeholder{ color:var(--c-ph); }\n    .ant-mn-ta:hover{ border-color:var(--bc-h); }\n    .ant-mn.is-open .ant-mn-ta, .ant-mn-ta:focus{ border-color:var(--bc-f); box-shadow:0 0 0 2px var(--ring); }\n    .ant-mn.is-disabled .ant-mn-ta{ background:var(--bg-dis); color:var(--c-dis); cursor:not-allowed; }\n    .ant-mn-panel{ position:fixed; left:0; top:0; z-index:1200; background:var(--bg);\n      border:1px solid var(--panel-bc); border-radius:var(--radius); box-shadow:0 6px 16px rgba(0,0,0,.12);\n      max-height:256px; overflow:auto; padding:4px; display:none; min-width:120px; }\n    .ant-mn.is-open .ant-mn-panel{ display:block; }\n    .ant-mn-opt{ display:flex; align-items:center; padding:5px 12px; border-radius:var(--radius-sm);\n      cursor:pointer; color:var(--c-text); white-space:nowrap; }\n    .ant-mn-opt:hover{ background:var(--opt-hover); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const names = normNames(p.options);\n    const disabled = !!p.disabled;\n    const placeholder = p.placeholder != null ? String(p.placeholder) : '';\n    const rows = (p.rows != null && !isNaN(p.rows)) ? Number(p.rows) : 3;\n\n    if(d2.state.open == null) d2.state.open = false;\n    if(d2.state.value == null) d2.state.value = (p.value != null ? String(p.value) : '');\n\n    const value = String(d2.state.value || '');\n    const mention = trailingMention(value);\n    const q = mention ? mention.query.toLowerCase() : '';\n    const matches = mention ? names.filter(n=>n.toLowerCase().indexOf(q) !== -1) : [];\n    const open = !!d2.state.open && !!mention && matches.length > 0 && !disabled;\n\n    const style = [\n      '--fs:'+D.fontSize+'px', '--radius:'+D.borderRadius+'px', '--radius-sm:'+D.borderRadiusSM+'px',\n      '--bc:'+D.colorBorder, '--bc-h:'+D.colorPrimaryHover, '--bc-f:'+D.colorPrimary,\n      '--ring:rgba(5,145,255,0.1)', '--bg:'+D.colorBgContainer, '--bg-dis:'+D.colorFillTertiary,\n      '--c-text:'+D.colorText, '--c-ph:'+D.colorTextTertiary, '--c-dis:'+D.colorTextDisabled,\n      '--opt-hover:'+D.colorFillTertiary, '--panel-bc:'+D.colorBorderSecondary, '--ff:'+D.fontFamily\n    ].join(';');\n\n    const cls = ['ant-mn'];\n    if(open) cls.push('is-open');\n    if(disabled) cls.push('is-disabled');\n\n    const panelInner = matches.map(n=>{\n      return '<div class=\"ant-mn-opt\" data-name=\"'+esc(n)+'\">'+esc(n)+'</div>';\n    }).join('');\n\n    return '<div class=\"'+cls.join(' ')+'\" style=\"'+style+'\">'\n      + '<textarea class=\"ant-mn-ta\" rows=\"'+rows+'\" autocomplete=\"off\" placeholder=\"'+esc(placeholder)+'\"'+(disabled?' disabled':'')+'>'+esc(value)+'</textarea>'\n      + '<div class=\"ant-mn-panel\">'+panelInner+'</div>'\n      + '</div>';\n  },\n  mounted(d2){\n    d2.on('.ant-mn-ta','input',(e)=>{\n      if((d2.params||{}).disabled) return;\n      d2.state.value = e.target.value;\n      d2.state.open = true;\n      d2.emit('onChange', { value: e.target.value });\n    });\n    d2.on('.ant-mn-opt','click',(e, el)=>{\n      if((d2.params||{}).disabled) return;\n      const node = el || e.target.closest('.ant-mn-opt');\n      const name = node.getAttribute('data-name');\n      const value = String(d2.state.value || '');\n      const next = value.replace(/(^|\\s)@([^\\s@]*)$/, function(full, pre){ return pre + '@' + name + ' '; });\n      d2.state.value = next;\n      d2.state.open = false;\n      d2.emit('onChange', { value: next });\n    });\n    d2.on(document,'click',(e)=>{\n      if(!d2.state.open) return;\n      const path = (e.composedPath && e.composedPath()) || [];\n      if(d2.root && path.indexOf(d2.root) !== -1) return;\n      d2.state.open = false;\n    });\n  },\n  updated(d2){\n    if(!d2.state.open) return;\n    const ta = d2.$('.ant-mn-ta'), panel = d2.$('.ant-mn-panel');\n    if(!ta || !panel) return;\n    const r = ta.getBoundingClientRect();\n    panel.style.left = Math.round(r.left) + 'px';\n    panel.style.top = Math.round(r.bottom + 4) + 'px';\n    panel.style.minWidth = Math.round(r.width) + 'px';\n  }\n};"}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"options":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"options"}}}},"placeholder":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"placeholder"}}}},"rows":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rows"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a3046b8ed769e0c5827d4e5","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-floatbutton","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryActive:'#0958d9', colorPrimaryBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorTextLightSolid:'#ffffff', colorError:'#ff4d4f', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', borderRadius:6, controlHeight:32, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-fab-wrap{ position:relative; width:100%; height:96px; box-sizing:border-box; font-family:var(--ff); }\n    .ant-fab-wrap *{ box-sizing:border-box; }\n    .ant-fab{ position:absolute; right:24px; bottom:24px; width:48px; height:48px; display:inline-flex;\n      align-items:center; justify-content:center; border:none; cursor:pointer; outline:none;\n      box-shadow:0 6px 16px 0 rgba(0,0,0,.08), 0 3px 6px -4px rgba(0,0,0,.12), 0 9px 28px 8px rgba(0,0,0,.05);\n      background:var(--bg); color:var(--fg); font-size:18px; transition:all .2s; }\n    .ant-fab.shape-circle{ border-radius:50%; }\n    .ant-fab.shape-square{ border-radius:var(--radius); }\n    .ant-fab:hover{ background:var(--bgh); }\n    .ant-fab:active{ background:var(--bga); }\n    .ant-fab .fab-ic{ display:inline-flex; align-items:center; justify-content:center; line-height:0; }\n    .ant-fab .fab-badge{ position:absolute; top:-4px; right:-4px; min-width:18px; height:18px; padding:0 5px;\n      display:inline-flex; align-items:center; justify-content:center; font-size:12px; line-height:1;\n      color:#fff; background:var(--cerr); border-radius:9px; box-shadow:0 0 0 1px #fff; }\n    .ant-fab .fab-tip{ position:absolute; bottom:calc(100% + 8px); right:0; white-space:nowrap;\n      background:rgba(0,0,0,0.85); color:#fff; font-size:13px; padding:6px 8px; border-radius:6px;\n      opacity:0; transform:translateY(4px); pointer-events:none; transition:opacity .2s,transform .2s; }\n    .ant-fab:hover .fab-tip{ opacity:1; transform:translateY(0); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const glyph = p.glyph || 'fa fa-question';\n    const type = p.type || 'default';\n    const shape = p.shape || 'circle';\n    const tooltip = p.tooltip != null ? String(p.tooltip) : '';\n    const hasBadge = p.badge != null && p.badge !== '' && !isNaN(Number(p.badge));\n    const badge = hasBadge ? Number(p.badge) : 0;\n\n    const isPrimary = type === 'primary';\n    const bg = isPrimary ? D.colorPrimary : D.colorBgContainer;\n    const bgh = isPrimary ? D.colorPrimaryHover : D.colorFillTertiary;\n    const bga = isPrimary ? D.colorPrimaryActive : D.colorBorderSecondary;\n    const fg = isPrimary ? D.colorTextLightSolid : D.colorText;\n\n    const style = [\n      '--ff:'+D.fontFamily, '--bg:'+bg, '--bgh:'+bgh, '--bga:'+bga, '--fg:'+fg,\n      '--cerr:'+D.colorError, '--radius:'+D.borderRadius+'px'\n    ].join(';');\n\n    const isFa = /(^|\\s)fa[srlbd]?(\\s|-)/.test(glyph);\n    const iconHtml = isFa ? '<i class=\"fab-ic '+esc(glyph)+'\"></i>' : '<span class=\"fab-ic\">'+esc(glyph)+'</span>';\n    const badgeHtml = hasBadge ? '<span class=\"fab-badge\">'+esc(badge > 99 ? '99+' : badge)+'</span>' : '';\n    const tipHtml = tooltip ? '<span class=\"fab-tip\">'+esc(tooltip)+'</span>' : '';\n    const titleAttr = tooltip ? ' title=\"'+esc(tooltip)+'\"' : '';\n\n    return '<div class=\"ant-fab-wrap\" style=\"'+style+'\">'\n      + '<button type=\"button\" class=\"ant-fab shape-'+esc(shape)+'\"'+titleAttr+'>'\n      + tipHtml + iconHtml + badgeHtml\n      + '</button></div>';\n  },\n  mounted(d2){\n    d2.on('.ant-fab','click',(e, el)=>{ d2.emit('onClick', {}); });\n  }\n};"}},"glyph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"glyph"}}}},"type":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"type"}}}},"shape":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"shape"}}}},"tooltip":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tooltip"}}}},"badge":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"badge"}}}},"onClick":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onClick"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a3046d7ed769e0c5827d546","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-upload","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorError:'#ff4d4f', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusSM:4, controlHeight:32, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nfunction normFiles(raw){\n  const out=[];\n  if(Array.isArray(raw)){\n    for(const f of raw){\n      if(f==null) continue;\n      if(typeof f === 'object'){\n        const uid = f.uid!=null ? String(f.uid) : String(Math.random()).slice(2);\n        const name = f.name!=null ? String(f.name) : 'file';\n        const status = f.status || 'done';\n        out.push({ uid, name, status });\n      } else {\n        out.push({ uid:String(Math.random()).slice(2), name:String(f), status:'done' });\n      }\n    }\n  }\n  return out;\n}\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-up{ box-sizing:border-box; display:inline-block; font-family:var(--ff); font-size:var(--fs); color:var(--c-text); }\n    .ant-up *{ box-sizing:border-box; }\n    .ant-up-btn{ display:inline-flex; align-items:center; gap:8px; height:var(--h); padding:0 15px;\n      border:1px solid var(--bc); border-radius:var(--radius); background:var(--bg); color:var(--c-text);\n      cursor:pointer; user-select:none; transition:all .2s; }\n    .ant-up-btn:hover{ border-color:var(--c-primary); color:var(--c-primary); }\n    .ant-up-list{ margin-top:8px; display:flex; flex-direction:column; gap:4px; }\n    .ant-up-list.picture .ant-up-row{ border:1px solid var(--bc-sec); border-radius:var(--radius); padding:8px; }\n    .ant-up-row{ display:flex; align-items:center; gap:8px; padding:4px 8px; border-radius:var(--radius-sm); transition:background .2s; }\n    .ant-up-row:hover{ background:var(--opt-hover); }\n    .ant-up-icon{ flex:0 0 auto; color:var(--c-sec); }\n    .ant-up-list.picture .ant-up-icon{ width:32px; height:32px; border-radius:var(--radius-sm); background:var(--fill); display:inline-flex; align-items:center; justify-content:center; font-size:16px; }\n    .ant-up-row.error .ant-up-icon, .ant-up-row.error .ant-up-name{ color:var(--c-error); }\n    .ant-up-name{ flex:1 1 auto; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--c-text); }\n    .ant-up-spin{ width:14px; height:14px; border:2px solid var(--c-primary); border-top-color:transparent;\n      border-radius:50%; display:inline-block; animation:antupspin .8s linear infinite; }\n    @keyframes antupspin{ to{ transform:rotate(360deg); } }\n    .ant-up-x{ flex:0 0 auto; color:var(--c-ph); cursor:pointer; padding:2px; transition:color .2s; }\n    .ant-up-x:hover{ color:var(--c-error); }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const listType = p.listType === 'picture' ? 'picture' : 'text';\n    const buttonText = p.buttonText != null ? String(p.buttonText) : 'Click to Upload';\n\n    if(d2.state.list == null) d2.state.list = normFiles(p.fileList);\n    if(d2.state.n == null) d2.state.n = d2.state.list.length;\n\n    const list = d2.state.list || [];\n\n    const style = [\n      '--h:'+D.controlHeight+'px', '--fs:'+D.fontSize+'px',\n      '--radius:'+D.borderRadius+'px', '--radius-sm:'+D.borderRadiusSM+'px',\n      '--bc:'+D.colorBorder, '--bc-sec:'+D.colorBorderSecondary,\n      '--bg:'+D.colorBgContainer, '--fill:'+D.colorFillTertiary, '--opt-hover:'+D.colorFillTertiary,\n      '--c-text:'+D.colorText, '--c-sec:'+D.colorTextSecondary, '--c-ph:'+D.colorTextTertiary,\n      '--c-primary:'+D.colorPrimary, '--c-error:'+D.colorError, '--ff:'+D.fontFamily\n    ].join(';');\n\n    const rows = list.map(f=>{\n      const status = f.status || 'done';\n      let icon;\n      if(status === 'uploading') icon = '<span class=\"ant-up-spin\"></span>';\n      else if(listType === 'picture') icon = '<span class=\"ant-up-icon\"><i class=\"fa fa-picture-o\"></i></span>';\n      else icon = '<i class=\"fa fa-paperclip ant-up-icon\"></i>';\n      return '<div class=\"ant-up-row '+esc(status)+'\" data-uid=\"'+esc(f.uid)+'\">'\n        + icon\n        + '<span class=\"ant-up-name\">'+esc(f.name)+'</span>'\n        + '<i class=\"fa fa-times ant-up-x\" data-remove=\"'+esc(f.uid)+'\"></i>'\n        + '</div>';\n    }).join('');\n\n    const listHtml = list.length\n      ? '<div class=\"ant-up-list '+listType+'\">'+rows+'</div>'\n      : '';\n\n    return '<div class=\"ant-up\" style=\"'+style+'\">'\n      + '<span class=\"ant-up-btn\"><i class=\"fa fa-upload\"></i><span>'+esc(buttonText)+'</span></span>'\n      + listHtml\n      + '</div>';\n  },\n  mounted(d2){\n    d2.on('.ant-up-btn','click',(e,el)=>{\n      const n = (d2.state.n || 0) + 1;\n      const file = { uid:'u'+n+'-'+String(Math.random()).slice(2,7), name:'example-'+n+'.png', status:'done' };\n      const list = (d2.state.list || []).concat([file]);\n      d2.state.n = n;\n      d2.state.list = list;\n    });\n\n    d2.on('[data-remove]','click',(e,el)=>{\n      e.stopPropagation();\n      const uid = el.getAttribute('data-remove');\n      const list = (d2.state.list || []).filter(f=>f.uid !== uid);\n      d2.state.list = list;\n      d2.emit('onRemove', uid);\n    });\n  }\n};"}},"fileList":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"fileList"}}}},"listType":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"listType"}}}},"buttonText":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"buttonText"}}}},"onRemove":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onRemove"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a3046f82ae3e526cfd4dce8","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"ant-cascader","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorPrimaryHover:'#4096ff', colorPrimaryBg:'#e6f4ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorTextDisabled:'rgba(0,0,0,0.25)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillSecondary:'rgba(0,0,0,0.06)', borderRadius:6, borderRadiusSM:4, controlHeight:32, fontSize:14, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\n\nfunction resolveTokens(p){ const tk=(p.tokens&&typeof p.tokens==='object')?p.tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\n\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nfunction normTree(raw){\n  const out = [];\n  if(Array.isArray(raw)){\n    for(const o of raw){\n      if(o==null) continue;\n      if(typeof o === 'object'){\n        const val = (o.value!=null)?String(o.value):(o.label!=null?String(o.label):'');\n        const lab = (o.label!=null)?String(o.label):val;\n        const kids = Array.isArray(o.children) ? normTree(o.children) : [];\n        out.push({ value:val, label:lab, children:kids });\n      } else {\n        out.push({ value:String(o), label:String(o), children:[] });\n      }\n    }\n  }\n  return out;\n}\n\nfunction parsePath(raw){\n  if(Array.isArray(raw)) return raw.map(s=>String(s));\n  if(raw==null || raw==='') return [];\n  return String(raw).split(',').map(s=>s.trim()).filter(s=>s!=='');\n}\n\n// build columns for the active path; activePath drives which children are shown\nfunction buildColumns(tree, activePath){\n  const cols = [];\n  let level = tree;\n  let depth = 0;\n  cols.push(level);\n  while(depth < activePath.length){\n    const sel = activePath[depth];\n    const node = level.find(n=>n.value===sel);\n    if(node && node.children && node.children.length){ cols.push(node.children); level = node.children; depth++; }\n    else break;\n  }\n  return cols;\n}\n\n// label path for the committed value\nfunction labelPath(tree, pathVals){\n  const labels = [];\n  let level = tree;\n  for(const v of pathVals){\n    const node = level.find(n=>n.value===v);\n    if(!node) break;\n    labels.push(node.label);\n    level = node.children || [];\n  }\n  return labels;\n}\n\nexport default {\n  css: `\n    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');\n    .ant-cas{ position:relative; box-sizing:border-box; display:inline-block; width:100%; font-family:var(--ff); font-size:var(--fs); }\n    .ant-cas *{ box-sizing:border-box; }\n    .ant-cas-ctl{ position:relative; display:flex; align-items:center; min-height:var(--h); padding:0 11px;\n      background:var(--bg); border:1px solid var(--bc); border-radius:var(--radius); cursor:pointer;\n      transition:border-color .2s, box-shadow .2s; }\n    .ant-cas-ctl:hover{ border-color:var(--bc-h); }\n    .ant-cas.is-open .ant-cas-ctl{ border-color:var(--bc-f); box-shadow:0 0 0 2px var(--ring); }\n    .ant-cas.is-disabled .ant-cas-ctl{ background:var(--bg-dis); cursor:not-allowed; }\n    .ant-cas-val{ flex:1 1 auto; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--c-text); }\n    .ant-cas-ph{ color:var(--c-ph); }\n    .ant-cas-caret{ color:var(--c-ph); font-size:12px; margin-left:6px; transition:transform .2s; }\n    .ant-cas.is-open .ant-cas-caret{ transform:rotate(180deg); }\n    .ant-cas-panel{ position:fixed; left:0; top:0; z-index:1200; display:none; background:var(--bg);\n      border:1px solid var(--panel-bc); border-radius:var(--radius); box-shadow:0 6px 16px rgba(0,0,0,.12); }\n    .ant-cas.is-open .ant-cas-panel{ display:flex; }\n    .ant-cas-col{ width:140px; max-height:256px; overflow:auto; padding:4px; border-right:1px solid var(--panel-bc); }\n    .ant-cas-col:last-child{ border-right:none; }\n    .ant-cas-opt{ display:flex; align-items:center; justify-content:space-between; gap:8px; padding:5px 12px;\n      border-radius:var(--radius-sm); cursor:pointer; color:var(--c-text); white-space:nowrap; }\n    .ant-cas-opt:hover{ background:var(--opt-hover); }\n    .ant-cas-opt.active{ background:var(--opt-sel-bg); font-weight:600; }\n    .ant-cas-opt .opt-label{ overflow:hidden; text-overflow:ellipsis; }\n    .ant-cas-opt .opt-arrow{ color:var(--c-ph); font-size:12px; }\n  `,\n  render(d2){\n    const p = d2.params || {};\n    const D = resolveTokens(p);\n    const tree = normTree(p.options);\n    const disabled = !!p.disabled;\n    const placeholder = p.placeholder != null ? String(p.placeholder) : 'Select';\n\n    if(d2.state.open == null) d2.state.open = false;\n    if(d2.state.path == null) d2.state.path = parsePath(p.value);\n    if(d2.state.active == null) d2.state.active = (d2.state.path || []).slice();\n\n    const open = !!d2.state.open && !disabled;\n    const committed = (d2.state.path || []);\n    const active = (d2.state.active || []);\n\n    const labels = labelPath(tree, committed);\n    const valText = labels.length ? labels.join(' / ') : '';\n\n    const style = [\n      '--h:'+D.controlHeight+'px', '--fs:'+D.fontSize+'px', '--radius:'+D.borderRadius+'px',\n      '--radius-sm:'+D.borderRadiusSM+'px', '--bc:'+D.colorBorder, '--bc-h:'+D.colorPrimaryHover,\n      '--bc-f:'+D.colorPrimary, '--ring:rgba(5,145,255,0.1)', '--bg:'+D.colorBgContainer,\n      '--bg-dis:'+D.colorFillTertiary, '--c-text:'+D.colorText, '--c-ph:'+D.colorTextTertiary,\n      '--opt-hover:'+D.colorFillTertiary, '--opt-sel-bg:'+D.colorPrimaryBg,\n      '--panel-bc:'+D.colorBorderSecondary, '--ff:'+D.fontFamily\n    ].join(';');\n\n    const cls = ['ant-cas'];\n    if(open) cls.push('is-open');\n    if(disabled) cls.push('is-disabled');\n\n    const cols = buildColumns(tree, active);\n    let panelInner = '';\n    for(let ci=0; ci<cols.length; ci++){\n      const colVals = cols[ci];\n      const activeAtLevel = active[ci];\n      let colHtml = '';\n      for(const node of colVals){\n        const hasKids = node.children && node.children.length > 0;\n        const isActive = node.value === activeAtLevel;\n        colHtml += '<div class=\"ant-cas-opt'+(isActive?' active':'')+'\" data-level=\"'+ci+'\" data-value=\"'+esc(node.value)+'\">'\n          + '<span class=\"opt-label\">'+esc(node.label)+'</span>'\n          + (hasKids ? '<i class=\"fa fa-angle-right opt-arrow\"></i>' : '')\n          + '</div>';\n      }\n      panelInner += '<div class=\"ant-cas-col\">'+colHtml+'</div>';\n    }\n\n    const valHtml = valText\n      ? '<span class=\"ant-cas-val\">'+esc(valText)+'</span>'\n      : '<span class=\"ant-cas-val ant-cas-ph\">'+esc(placeholder)+'</span>';\n\n    return '<div class=\"'+cls.join(' ')+'\" style=\"'+style+'\">'\n      + '<div class=\"ant-cas-ctl\">'+valHtml+'<i class=\"fa fa-angle-down ant-cas-caret\"></i></div>'\n      + '<div class=\"ant-cas-panel\">'+panelInner+'</div>'\n      + '</div>';\n  },\n  mounted(d2){\n    const tree = ()=> normTree((d2.params||{}).options);\n    function findNode(level, val){ for(const n of level){ if(n.value===val) return n; } return null; }\n\n    d2.on('.ant-cas-ctl','click',()=>{\n      if((d2.params||{}).disabled) return;\n      d2.state.open = !d2.state.open;\n      if(d2.state.open) d2.state.active = (d2.state.path || []).slice();\n    });\n\n    d2.on('.ant-cas-opt','click',(e, el)=>{\n      if((d2.params||{}).disabled) return;\n      const node = el || e.target.closest('.ant-cas-opt');\n      const level = parseInt(node.getAttribute('data-level'), 10);\n      const val = node.getAttribute('data-value');\n      // new active path truncated to this level + the clicked value\n      const nextActive = (d2.state.active || []).slice(0, level);\n      nextActive[level] = val;\n      d2.state.active = nextActive;\n\n      // resolve the clicked node to see if it is a leaf\n      let cur = tree(); let target = null;\n      for(let i=0;i<nextActive.length;i++){ target = findNode(cur, nextActive[i]); if(!target) break; cur = target.children || []; }\n      const isLeaf = !target || !target.children || target.children.length === 0;\n      if(isLeaf){\n        d2.state.path = nextActive.slice();\n        d2.state.open = false;\n        d2.emit('onChange', { value: nextActive.slice() });\n      }\n    });\n\n    d2.on(document,'click',(e)=>{\n      if(!d2.state.open) return;\n      const path = (e.composedPath && e.composedPath()) || [];\n      if(d2.root && path.indexOf(d2.root) !== -1) return;\n      d2.state.open = false;\n    });\n  },\n  updated(d2){\n    if(!d2.state.open) return;\n    const ctl = d2.$('.ant-cas-ctl'), panel = d2.$('.ant-cas-panel');\n    if(!ctl || !panel) return;\n    const r = ctl.getBoundingClientRect();\n    panel.style.left = Math.round(r.left) + 'px';\n    panel.style.top = Math.round(r.bottom + 4) + 'px';\n  }\n};"}},"options":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"options"}}}},"value":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"value"}}}},"placeholder":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"placeholder"}}}},"disabled":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"disabled"}}}},"onChange":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onChange"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a305a12d73289eb8a0e1162","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"orders-admin","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ICONS = {\n  bag:'<path d=\"M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z\"/><path d=\"M3 6h18\"/><path d=\"M16 10a4 4 0 0 1-8 0\"/>',\n  dashboard:'<rect width=\"7\" height=\"9\" x=\"3\" y=\"3\" rx=\"1\"/><rect width=\"7\" height=\"5\" x=\"14\" y=\"3\" rx=\"1\"/><rect width=\"7\" height=\"9\" x=\"14\" y=\"12\" rx=\"1\"/><rect width=\"7\" height=\"5\" x=\"3\" y=\"16\" rx=\"1\"/>',\n  cart:'<circle cx=\"8\" cy=\"21\" r=\"1\"/><circle cx=\"19\" cy=\"21\" r=\"1\"/><path d=\"M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12\"/>',\n  users:'<path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><path d=\"M22 21v-2a4 4 0 0 0-3-3.87\"/><path d=\"M16 3.13a4 4 0 0 1 0 7.75\"/>',\n  box:'<path d=\"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z\"/><path d=\"m3.3 7 8.7 5 8.7-5\"/><path d=\"M12 22V12\"/>',\n  gear:'<circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z\"/>',\n  sun:'<circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M6.3 17.7l-1.4 1.4M19.1 4.9l-1.4 1.4\"/>',\n  moon:'<path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\"/>',\n  bell:'<path d=\"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9\"/><path d=\"M10.3 21a1.94 1.94 0 0 0 3.4 0\"/>',\n  plus:'<path d=\"M5 12h14M12 5v14\"/>',\n  x:'<path d=\"M18 6 6 18M6 6l12 12\"/>',\n  eye:'<path d=\"M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>',\n  check:'<path d=\"M20 6 9 17l-5-5\"/>',\n  ban:'<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m4.9 4.9 14.2 14.2\"/>',\n  search:'<circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21-4.3-4.3\"/>'\n};\nfunction ic(n, s){ s = s || 18; return '<svg width=\"'+s+'\" height=\"'+s+'\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">'+(ICONS[n]||'')+'</svg>'; }\nconst STATUS = { pending:{label:'Pending',color:'warning',hex:'#faad14'}, processing:{label:'Processing',color:'processing',hex:'#1677ff'}, shipped:{label:'Shipped',color:'info',hex:'#13c2c2'}, delivered:{label:'Delivered',color:'success',hex:'#52c41a'}, cancelled:{label:'Cancelled',color:'default',hex:'#8c8c8c'}, refunded:{label:'Refunded',color:'error',hex:'#ff4d4f'} };\nconst CHANNELS = ['Web','iOS','Android'];\nconst STEP_INDEX = { pending:0, processing:1, shipped:2, delivered:3, cancelled:1, refunded:1 };\nconst LIGHT = { colorPrimary:'#1677ff', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorBorder:'#d9d9d9', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', colorBgLayout:'#f4f6f8', colorFillTertiary:'rgba(0,0,0,0.04)', colorFillAlter:'rgba(0,0,0,0.02)' };\nconst DARK = { colorPrimary:'#1668dc', colorText:'rgba(255,255,255,0.85)', colorTextSecondary:'rgba(255,255,255,0.65)', colorTextTertiary:'rgba(255,255,255,0.45)', colorBorder:'#424242', colorBorderSecondary:'#303030', colorBgContainer:'#1f1f1f', colorBgLayout:'#141414', colorFillTertiary:'rgba(255,255,255,0.08)', colorFillAlter:'rgba(255,255,255,0.04)' };\nconst esc = t => String(t==null?'':t).replace(/[&<>\"]/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;'}[c]));\nconst money = n => '$' + Number(n||0).toLocaleString('en-US');\nconst vstr = v => (v && typeof v==='object') ? (v.value!==undefined ? v.value : (v.key!==undefined ? v.key : (v.target && v.target.value!==undefined ? v.target.value : ''))) : v;\nfunction resolveTheme(tokens, dark){ const base = Object.assign({}, dark ? DARK : LIGHT); const tk=(tokens&&typeof tokens==='object')?tokens:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=dark?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')base[k]=v; } if(tk.colorPrimary)base.colorPrimary=tk.colorPrimary; if(tk.fontFamily)base.fontFamily=tk.fontFamily; return base; }\n\nexport default {\n  css: `\n    .oa-wrap { position:relative; height:100%; font-family:var(--ff,'Inter',system-ui,sans-serif); }\n    .oa { display:flex; height:100%; min-height:700px; background:var(--bgLayout); color:var(--text); border-radius:14px; overflow:hidden; }\n    .oa-side { width:230px; flex-shrink:0; background:#001529; color:#fff; display:flex; flex-direction:column; }\n    .oa-logo { padding:18px 20px; font-size:16px; font-weight:700; display:flex; align-items:center; gap:9px; } .oa-logo svg { color:var(--primary); }\n    .oa-nav { padding:8px 0; }\n    .oa-nav-item { display:flex; align-items:center; gap:12px; padding:11px 22px; font-size:14px; color:rgba(255,255,255,0.65); cursor:pointer; border-left:3px solid transparent; }\n    .oa-nav-item:hover { color:#fff; background:rgba(255,255,255,0.05); }\n    .oa-nav-item.on { color:#fff; background:var(--primary); border-left-color:#fff; }\n    .oa-main { flex:1; display:flex; flex-direction:column; min-width:0; }\n    .oa-top { height:60px; flex-shrink:0; background:var(--bgContainer); border-bottom:1px solid var(--borderSec); display:flex; align-items:center; gap:10px; padding:0 22px; }\n    .oa-crumb { font-size:13px; color:var(--textSec); } .oa-crumb b { color:var(--text); }\n    .oa-grow { flex:1; }\n    .oa-search-box { width:240px; }\n    .oa-avatar { width:34px; height:34px; border-radius:50%; background:var(--primary); color:#fff; display:flex; align-items:center; justify-content:center; font-size:13px; font-weight:700; }\n    .oa-scroll { flex:1; overflow-y:auto; padding:20px 22px; }\n    .oa-h1 { font-size:20px; font-weight:700; margin:0 0 16px; }\n    .oa-kpis { display:grid; grid-template-columns:repeat(4,1fr); gap:16px; margin-bottom:18px; }\n    .oa-kpi { background:var(--bgContainer); border:1px solid var(--borderSec); border-radius:12px; padding:16px 18px; min-height:78px; }\n    .oa-bar { display:flex; align-items:center; gap:14px; margin-bottom:16px; }\n    .oa-seg { flex:1; min-width:0; max-width:520px; }\n    .oa-content { display:flex; gap:18px; align-items:flex-start; }\n    .oa-card { background:var(--bgContainer); border:1px solid var(--borderSec); border-radius:12px; padding:16px 18px; }\n    .oa-card-t { font-size:14px; font-weight:600; margin:0 0 14px; }\n    .oa-table { flex:1; min-width:0; }\n    .oa-grid2 { display:grid; grid-template-columns:1.3fr 1fr; gap:18px; margin-bottom:18px; align-items:start; }\n    .oa-prow { display:flex; align-items:center; gap:12px; margin-bottom:12px; }\n    .oa-prow-l { width:92px; font-size:13px; color:var(--textSec); flex-shrink:0; } .oa-prow-b { flex:1; }\n    .oa-detail { width:380px; flex-shrink:0; background:var(--bgContainer); border:1px solid var(--borderSec); border-radius:12px; padding:18px; }\n    .oa-detail-head { display:flex; align-items:center; gap:10px; margin-bottom:14px; } .oa-detail-head h3 { margin:0; font-size:16px; flex:1; }\n    .oa-section-t { font-size:12px; font-weight:600; color:var(--textSec); text-transform:uppercase; letter-spacing:.04em; margin:16px 0 10px; }\n    .oa-empty { padding:56px 20px; text-align:center; color:var(--textTer); font-size:13px; }\n    .oa-set-row { display:flex; align-items:center; gap:16px; padding:14px 0; border-bottom:1px solid var(--borderSec); } .oa-set-row:last-child { border-bottom:0; }\n    .oa-set-row > div:first-child { flex:1; } .oa-set-t { font-size:14px; font-weight:600; } .oa-set-d { font-size:12px; color:var(--textSec); margin-top:2px; }\n    .oa-iconbtn { width:36px; flex-shrink:0; } .oa-btnw { display:inline-flex; }\n    .oa-overlay { position:absolute; inset:0; background:rgba(0,0,0,.5); display:flex; align-items:center; justify-content:center; z-index:50; }\n    .oa-modal { background:var(--bgContainer); color:var(--text); border-radius:14px; width:470px; max-width:92%; padding:22px 24px; box-shadow:0 24px 60px rgba(0,0,0,.35); }\n    .oa-modal h3 { margin:0 0 16px; font-size:17px; }\n    .oa-fl { display:block; font-size:12px; font-weight:600; color:var(--textSec); margin:12px 0 5px; }\n    .oa-modal-row { display:flex; gap:12px; } .oa-modal-row > div { flex:1; }\n    .oa-err { color:#cf1322; font-size:12px; min-height:16px; margin-top:8px; }\n    .oa-modal-actions { display:flex; justify-content:flex-end; gap:10px; margin-top:18px; }\n  `,\n\n  render(d2){\n    const ds = d2.data('orders');\n    const tokens = d2.param('tokens');\n    const dark = (d2.state.dark !== undefined) ? d2.state.dark : !!(tokens && tokens.darkMode);\n    const T = resolveTheme(tokens, dark);\n    if(d2.state.primary) T.colorPrimary = d2.state.primary;\n    const ff = T.fontFamily || \"'Inter',system-ui,sans-serif\";\n    const vars = ['--ff:'+ff,'--text:'+T.colorText,'--textSec:'+T.colorTextSecondary,'--textTer:'+T.colorTextTertiary,'--border:'+T.colorBorder,'--borderSec:'+T.colorBorderSecondary,'--bgContainer:'+T.colorBgContainer,'--bgLayout:'+T.colorBgLayout,'--primary:'+T.colorPrimary].join(';');\n    const themeSig = (dark?'d':'l') + '_' + (T.colorPrimary||'');\n    const child = (type, params, key, opts) => { opts = opts || {}; if(opts.width==null && opts.height==null && opts.style==null) opts = Object.assign({}, opts, {style:'height:auto;display:block'}); return d2.render('gabz-playground@'+type, Object.assign({ tokens:T }, params), Object.assign({ key:key+'_'+themeSig }, opts)); };\n    const h1 = (text,key) => '<div class=\"oa-h1\">'+child('ant-typography',{variant:'title',level:4,content:text},key)+'</div>'+child('ant-divider',{},key+'-dv');\n\n    if(!ds) return '<div class=\"oa-wrap\" style=\"'+vars+'\"><div class=\"oa\"><div class=\"oa-empty\">Connect an orders dataset to the <b>orders</b> param.</div></div></div>';\n    if(ds.loading) return '<div class=\"oa-wrap\" style=\"'+vars+'\"><div class=\"oa\"><div class=\"oa-empty\">Loading orders…</div></div></div>';\n\n    const rows = ds.records() || [];\n    const nav = d2.state.nav || 'orders';\n    const revenue = rows.reduce((s,r)=> s + (Number(r.total)||0), 0);\n    const customersCount = (function(){ const set={}; rows.forEach(r=>{ if(r.customer) set[r.customer]=1; }); return Object.keys(set).length; })();\n    const openCount = rows.filter(r=> r.status==='pending' || r.status==='processing').length;\n    const revStr = money(revenue); const ordStr = String(rows.length); const custStr = String(customersCount); const openStr = String(openCount);\n    const kpiRow = '<div class=\"oa-kpis\">'+\n      child('ant-card',{bordered:true,slots:[{type:'gabz-playground@'+'ant-statistic',props:{title:'Revenue',value:revStr,valueColor:'#3f8600',tokens:T},key:'kr'}]},'kc-rev')+\n      child('ant-card',{bordered:true,slots:[{type:'gabz-playground@'+'ant-statistic',props:{title:'Total Orders',value:ordStr,tokens:T},key:'ko'}]},'kc-ord')+\n      child('ant-card',{bordered:true,slots:[{type:'gabz-playground@'+'ant-statistic',props:{title:'Customers',value:custStr,tokens:T},key:'kcu'}]},'kc-cust')+\n      child('ant-card',{bordered:true,slots:[{type:'gabz-playground@'+'ant-statistic',props:{title:'Open',value:openStr,suffix:'orders',valueColor:'#cf1322',tokens:T},key:'kp'}]},'kc-open')+'</div>';\n    const recent = rows.slice().sort((a,b)=> String(b.date||'').localeCompare(String(a.date||''))).slice(0,5);\n\n    function pageDashboard(){\n      const counts={}; Object.keys(STATUS).forEach(k=>counts[k]=0); rows.forEach(r=>{ if(counts[r.status]!=null) counts[r.status]++; }); const total=rows.length||1;\n      const bars = Object.keys(STATUS).filter(k=>counts[k]>0).map(k=> '<div class=\"oa-prow\"><div class=\"oa-prow-l\">'+STATUS[k].label+'</div><div class=\"oa-prow-b\">'+child('ant-progress',{percent:Math.round(counts[k]/total*100),strokeColor:STATUS[k].hex,size:'small'},'pg-'+k)+'</div></div>').join('');\n      const tl = child('ant-timeline',{items:recent.map(r=>({children:r.orderId+' · '+(STATUS[r.status]||{}).label+' · '+money(r.total),color:(r.status==='cancelled'||r.status==='refunded')?'red':(r.status==='delivered'?'green':'blue')}))},'dash-tl');\n      const list = child('ant-list',{header:'Recent orders',dataSource:recent.map(r=>({title:r.orderId+' — '+r.customer,description:(STATUS[r.status]||{}).label+' · '+r.channel,extra:money(r.total)}))},'dash-list');\n      return ''+h1('Dashboard','t-dash')+''+kpiRow+'<div class=\"oa-grid2\"><div class=\"oa-card\"><div class=\"oa-card-t\">Orders by status</div>'+bars+'</div><div class=\"oa-card\"><div class=\"oa-card-t\">Activity</div>'+tl+'</div></div><div class=\"oa-card\">'+list+'</div>';\n    }\n\n    function pageOrders(){\n      const filtro = d2.state.filtro || 'all';\n      const busca = (d2.state.busca || '').toLowerCase();\n      let list = filtro==='all' ? rows : rows.filter(r=> r.status===filtro);\n      if(busca) list = list.filter(r=> [r.orderId,r.customer,r.email,r.channel].join(' ').toLowerCase().indexOf(busca)!==-1);\n      const displayRows = list.map(r=> Object.assign({},r,{statusLabel:(STATUS[r.status]||{}).label||r.status, totalFmt:money(r.total)}));\n      const sel = rows.find(r=> String(r._id)===d2.state.selId || String(r.orderId)===d2.state.selId);\n      const segmented = child('ant-segmented',{value:filtro,options:[{label:'All',value:'all'},{label:'Pending',value:'pending'},{label:'Processing',value:'processing'},{label:'Shipped',value:'shipped'},{label:'Delivered',value:'delivered'}],onChange:(v)=>{ d2.state.filtro=vstr(v); }},'seg');\n      const newBtn = child('ant-button',{label:'New Order',glyph:ic('plus',16),color:'primary',variant:'solid',onClick:()=>{ d2.state.form={}; d2.state.formErr=''; d2.state.modal=true; }},'newbtn',{style:'width:auto;display:inline-flex'});\n      const table = child('ant-table',{\n        columns:[{title:'Order',dataIndex:'orderId',width:90},{title:'Customer',dataIndex:'customer'},{title:'Status',dataIndex:'statusLabel',filterable:true},{title:'Channel',dataIndex:'channel',filterable:true},{title:'Items',dataIndex:'items',align:'right'},{title:'Total',dataIndex:'totalFmt',align:'right'}],\n        dataSource:displayRows, pageSize:8,\n        rowActions:[{key:'view',label:'View details',glyph:ic('eye',15)},{key:'deliver',label:'Mark delivered',glyph:ic('check',15)},{key:'cancel',label:'Cancel order',glyph:ic('ban',15),danger:true}],\n        onRowClick:(e)=>{ const r=e&&e.row; d2.state.selId=r?String(r._id||r.orderId):null; },\n        onAction:(e)=>{ const r=e&&e.row; if(!r) return; if(e.action==='view'){ d2.state.selId=String(r._id||r.orderId); return; } const ns=e.action==='deliver'?'delivered':(e.action==='cancel'?'cancelled':null); if(ns){ const o=d2.data('orders'); if(o) o.update(Object.assign({},r,{status:ns})); } }\n      },'orders-table-'+filtro+'_'+(busca||'')+'_'+rows.length+'_'+rows.map(function(r){return String(r._id)+r.status;}).join(','));\n      let detail='';\n      if(sel){\n        const st=STATUS[sel.status]||{label:sel.status,color:'default'};\n        const tag=child('ant-tag',{label:st.label,color:st.color},'d-tag-'+sel._id);\n        const closeBtn=child('ant-button',{glyph:ic('x',16),variant:'text',shape:'circle',onClick:()=>{ d2.state.selId=null; }},'d-close',{width:32,height:32});\n        const desc=child('ant-descriptions',{bordered:true,column:1,size:'small',items:[{label:'Customer',children:sel.customer},{label:'Email',children:sel.email},{label:'Channel',children:sel.channel},{label:'Items',children:String(sel.items)},{label:'Total',children:money(sel.total)},{label:'Date',children:sel.date}]},'d-desc-'+sel._id);\n        const steps=child('ant-steps',{size:'small',direction:'vertical',current:STEP_INDEX[sel.status]!=null?STEP_INDEX[sel.status]:0,items:[{title:'Placed'},{title:'Processing'},{title:'Shipped'},{title:'Delivered'}]},'d-steps-'+sel._id);\n        const tl=child('ant-timeline',{items:[{children:'Order placed · '+sel.date,color:'green'},{children:'Payment confirmed',color:'green'},{children:st.label,color:(sel.status==='cancelled'||sel.status==='refunded')?'red':'blue'}]},'d-tl-'+sel._id);\n        detail='<aside class=\"oa-detail\"><div class=\"oa-detail-head\"><h3>'+esc(sel.orderId)+'</h3><div class=\"oa-btnw\">'+tag+'</div>'+closeBtn+'</div>'+desc+'<div class=\"oa-section-t\">Fulfillment</div>'+steps+'<div class=\"oa-section-t\">History</div>'+tl+'</aside>';\n      }\n      return ''+h1('Orders','t-ord')+''+kpiRow+'<div class=\"oa-bar\"><div class=\"oa-seg\">'+segmented+'</div><div class=\"oa-grow\"></div>'+newBtn+'</div><div class=\"oa-content\"><div class=\"oa-table\">'+table+'</div>'+detail+'</div>';\n    }\n\n    function pageCustomers(){\n      const m={}; rows.forEach(r=>{ const k=r.customer||'—'; if(!m[k]) m[k]={_id:k,customer:k,email:r.email,orders:0,spent:0,channel:r.channel}; m[k].orders++; m[k].spent+=Number(r.total)||0; });\n      const custRows=Object.keys(m).map(k=>{ const c=m[k]; return Object.assign({},c,{spentFmt:money(c.spent)}); });\n      const table=child('ant-table',{searchable:true,searchPlaceholder:'Search customers…',pageSize:6,bordered:false,columns:[{title:'Customer',dataIndex:'customer'},{title:'Email',dataIndex:'email'},{title:'Orders',dataIndex:'orders',align:'right'},{title:'Total spent',dataIndex:'spentFmt',align:'right'},{title:'Channel',dataIndex:'channel',filterable:true}],dataSource:custRows},'cust-table');\n      return ''+h1('Customers','t-cust')+'<div class=\"oa-card\">'+table+'</div>';\n    }\n\n    function pageProducts(){\n      let prods=[]; try{ const pd=d2.data('admin-productsDataSet'); if(pd) prods=pd.records()||[]; }catch(e){}\n      const prows=prods.map(function(r){ return Object.assign({},r,{priceFmt:money(r.price)}); });\n      const addBtn=child('ant-button',{label:'Add product',glyph:ic('plus',16),color:'primary',variant:'solid',onClick:function(){ d2.state.prodForm={}; d2.state.prodErr=''; d2.state.prodModal=true; }},'prod-add',{style:'width:auto;display:inline-flex'});\n      let inner;\n      if(prows.length===0){ inner=child('ant-empty',{description:'No products yet — add your first product.'},'prod-empty'); }\n      else { inner=child('ant-table',{bordered:false,pageSize:8,columns:[{title:'Name',dataIndex:'name'},{title:'SKU',dataIndex:'sku'},{title:'Category',dataIndex:'category',filterable:true},{title:'Price',dataIndex:'priceFmt',align:'right'},{title:'Stock',dataIndex:'stock',align:'right'}],dataSource:prows},'prod-table-'+prows.length); }\n      let pm='';\n      if(d2.state.prodModal){\n        const pf=d2.state.prodForm||{};\n        const pName=child('ant-input',{value:pf.name||'',placeholder:'Product name',onChange:(v)=>{ d2.state.prodForm=Object.assign({},d2.state.prodForm||{},{name:vstr(v)}); }},'pf-name');\n        const pSku=child('ant-input',{value:pf.sku||'',placeholder:'SKU',onChange:(v)=>{ d2.state.prodForm=Object.assign({},d2.state.prodForm||{},{sku:vstr(v)}); }},'pf-sku');\n        const pCat=child('ant-select',{value:pf.category||'Accessories',options:['Accessories','Displays','Other'].map(c=>({label:c,value:c})),onChange:(v)=>{ d2.state.prodForm=Object.assign({},d2.state.prodForm||{},{category:vstr(v)}); }},'pf-cat');\n        const pPrice=child('ant-inputnumber',{value:pf.price,min:0,placeholder:'0',onChange:(v)=>{ d2.state.prodForm=Object.assign({},d2.state.prodForm||{},{price:vstr(v)}); }},'pf-price');\n        const pStock=child('ant-inputnumber',{value:pf.stock,min:0,placeholder:'0',onChange:(v)=>{ d2.state.prodForm=Object.assign({},d2.state.prodForm||{},{stock:vstr(v)}); }},'pf-stock');\n        const pCancel=child('ant-button',{label:'Cancel',variant:'outlined',onClick:()=>{ d2.state.prodModal=false; }},'pf-cancel',{style:'width:auto;display:inline-flex'});\n        const pCreate=child('ant-button',{label:'Create product',glyph:ic('check',15),color:'primary',variant:'solid',onClick:async()=>{ const g=d2.state.prodForm||{}; if(!g.name){ d2.state.prodErr='Name is required.'; return; } const pd=d2.data('admin-productsDataSet'); if(!pd) return; try{ await pd.create({name:g.name,sku:g.sku||'',category:g.category||'Accessories',price:Number(g.price)||0,stock:Number(g.stock)||0}); d2.state.prodModal=false; d2.state.prodForm={}; d2.state.prodErr=''; }catch(ex){ d2.state.prodErr='Failed: '+((ex&&ex.message)||ex); } }},'pf-create',{style:'width:auto;display:inline-flex'});\n        pm='<div class=\"oa-overlay\" data-act=\"prodoverlay\"><div class=\"oa-modal\"><h3>New product</h3><label class=\"oa-fl\">Name</label>'+pName+'<div class=\"oa-modal-row\"><div><label class=\"oa-fl\">SKU</label>'+pSku+'</div><div><label class=\"oa-fl\">Category</label>'+pCat+'</div></div><div class=\"oa-modal-row\"><div><label class=\"oa-fl\">Price</label>'+pPrice+'</div><div><label class=\"oa-fl\">Stock</label>'+pStock+'</div></div><div class=\"oa-err\">'+esc(d2.state.prodErr||'')+'</div><div class=\"oa-modal-actions\">'+pCancel+pCreate+'</div></div></div>';\n      }\n      return h1('Products','t-prod')+'<div class=\"oa-bar\"><div class=\"oa-grow\"></div>'+addBtn+'</div><div class=\"oa-card\">'+inner+'</div>'+pm;\n    }\n\n    function pageSettings(){\n      const sw=child('ant-switch',{checked:dark,checkedLabel:'On',uncheckedLabel:'Off',onChange:(v)=>{ d2.state.dark=(v&&typeof v==='object')?!!v.checked:!!v; }},'set-dark',{style:'width:auto;display:inline-flex'});\n      const cp=child('ant-colorpicker',{value:T.colorPrimary,showText:true,onChange:(v)=>{ d2.state.primary=vstr(v); }},'set-color',{style:'width:auto;display:inline-flex'});\n      const reset=child('ant-button',{label:'Reset theme',variant:'outlined',onClick:()=>{ d2.state.primary=null; d2.state.dark=false; }},'set-reset',{style:'width:auto;display:inline-flex'});\n      const res=child('ant-result',{status:'success',title:'Theme applies live',subTitle:'Every change cascades to all nested Ant components.'},'set-res');\n      const faq=child('ant-collapse',{accordion:true,bordered:true,items:[{key:'1',label:'How does theming work?',content:'One tokens prop cascades to every nested Ant component; the dark switch and color picker above update it live.'},{key:'2',label:'Where does data come from?',content:'Orders and Products are real Data2 datasets; the table reads them and create writes back.'},{key:'3',label:'Are the components reusable?',content:'Yes — this admin nests the Ant library by reference, so improving any component updates the app everywhere.'}]},'set-faq');\n      const tip=child('ant-tooltip',{title:'Theme changes apply instantly to every nested component.',placement:'right',targetLabel:'What is this?'},'set-tip');\n      return ''+h1('Settings','t-set')+'<div class=\"oa-card\" style=\"max-width:560px\">'+\n        '<div class=\"oa-set-row\"><div><div class=\"oa-set-t\">Dark mode</div><div class=\"oa-set-d\">Toggle the whole admin + every component</div></div><div class=\"oa-btnw\">'+sw+'</div></div>'+\n        '<div class=\"oa-set-row\"><div><div class=\"oa-set-t\">Primary color</div><div class=\"oa-set-d\">Seeds the theme passed down to all components</div></div><div class=\"oa-btnw\">'+cp+'</div></div>'+\n        '<div class=\"oa-set-row\"><div class=\"oa-btnw\">'+reset+'</div></div></div>'+\n        '<div class=\"oa-card\" style=\"max-width:560px;margin-top:16px\">'+res+'<div style=\"margin-top:10px\">'+tip+'</div></div>'+\n        '<div class=\"oa-card\" style=\"max-width:560px;margin-top:16px\"><div class=\"oa-card-t\">Help &amp; FAQ</div>'+faq+'</div>';\n    }\n\n    let page;\n    if(nav==='dashboard') page=pageDashboard(); else if(nav==='customers') page=pageCustomers(); else if(nav==='products') page=pageProducts(); else if(nav==='settings') page=pageSettings(); else page=pageOrders();\n\n    const navItems=[{k:'dashboard',ic:'dashboard',label:'Dashboard'},{k:'orders',ic:'cart',label:'Orders'},{k:'customers',ic:'users',label:'Customers'},{k:'products',ic:'box',label:'Products'},{k:'settings',ic:'gear',label:'Settings'}].map(n=>'<div class=\"oa-nav-item '+(n.k===nav?'on':'')+'\" data-act=\"nav\" data-k=\"'+n.k+'\">'+ic(n.ic,17)+'<span>'+n.label+'</span></div>').join('');\n\n    const searchInput = child('ant-input',{value:d2.state.busca||'',placeholder:'Search orders…',allowClear:true,prefixGlyph:ic('search',14),onChange:(v)=>{ d2.state.busca=vstr(v); }},'topsearch',{width:240,height:36});\n    const toggleBtn = child('ant-button',{glyph:ic(dark?'sun':'moon',17),variant:'text',shape:'circle',onClick:()=>{ const tk=d2.param('tokens'); const cur=(d2.state.dark!==undefined)?d2.state.dark:!!(tk&&tk.darkMode); d2.state.dark=!cur; }},'toggle',{width:36,height:36});\n    const bellBtn = child('ant-button',{glyph:ic('bell',17),variant:'text',shape:'circle'},'bell',{width:36,height:36});\n\n    let modal='';\n    if(d2.state.modal){\n      const f=d2.state.form||{};\n      const fCust=child('ant-input',{value:f.customer||'',placeholder:'Customer name',onChange:(v)=>{ d2.state.form=Object.assign({},d2.state.form||{},{customer:vstr(v)}); }},'mf-cust');\n      const fEmail=child('ant-input',{value:f.email||'',placeholder:'email@example.com',onChange:(v)=>{ d2.state.form=Object.assign({},d2.state.form||{},{email:vstr(v)}); }},'mf-email');\n      const fChannel=child('ant-select',{value:f.channel||'Web',options:CHANNELS.map(c=>({label:c,value:c})),onChange:(v)=>{ d2.state.form=Object.assign({},d2.state.form||{},{channel:vstr(v)}); }},'mf-chan');\n      const fTotal=child('ant-inputnumber',{value:f.total,min:0,placeholder:'0',onChange:(v)=>{ d2.state.form=Object.assign({},d2.state.form||{},{total:vstr(v)}); }},'mf-total');\n      const fItems=child('ant-inputnumber',{value:f.items,min:0,placeholder:'1',onChange:(v)=>{ d2.state.form=Object.assign({},d2.state.form||{},{items:vstr(v)}); }},'mf-items');\n      const fDate=child('ant-datepicker',{value:f.date||'',placeholder:'Order date',onChange:(v)=>{ d2.state.form=Object.assign({},d2.state.form||{},{date:vstr(v)}); }},'mf-date');\n      const cancelBtn=child('ant-button',{label:'Cancel',variant:'outlined',onClick:()=>{ d2.state.modal=false; }},'mf-cancel',{style:'width:auto;display:inline-flex'});\n      const createBtn=child('ant-button',{label:'Create order',glyph:ic('check',15),color:'primary',variant:'solid',onClick:async()=>{ const ff2=d2.state.form||{}; if(!ff2.customer){ d2.state.formErr='Customer is required.'; return; } const o=d2.data('orders'); if(!o) return; const n=(o.records()||[]).length; try{ await o.create({orderId:'#'+(10258+n),customer:ff2.customer,email:ff2.email||'',channel:ff2.channel||'Web',status:'pending',total:Number(ff2.total)||0,items:Number(ff2.items)||1,date:new Date().toISOString().slice(0,10)}); d2.state.modal=false; d2.state.form={}; d2.state.formErr=''; d2.state.filtro='all'; d2.state.nav='orders'; }catch(ex){ d2.state.formErr='Failed: '+((ex&&ex.message)||ex); } }},'mf-create',{style:'width:auto;display:inline-flex'});\n      modal='<div class=\"oa-overlay\" data-act=\"overlay\"><div class=\"oa-modal\"><h3>New order</h3>'+\n        '<label class=\"oa-fl\">Customer</label>'+fCust+\n        '<div class=\"oa-modal-row\"><div><label class=\"oa-fl\">Email</label>'+fEmail+'</div><div><label class=\"oa-fl\">Channel</label>'+fChannel+'</div></div>'+\n        '<div class=\"oa-modal-row\"><div><label class=\"oa-fl\">Total ($)</label>'+fTotal+'</div><div><label class=\"oa-fl\">Items</label>'+fItems+'</div></div>'+\n        '<label class=\"oa-fl\">Order date</label>'+fDate+\n        '<div class=\"oa-err\">'+esc(d2.state.formErr||'')+'</div>'+\n        '<div class=\"oa-modal-actions\">'+cancelBtn+createBtn+'</div></div></div>';\n    }\n\n    const crumbLabel={dashboard:'Dashboard',orders:'Orders',customers:'Customers',products:'Products',settings:'Settings'}[nav]||'Orders';\n    return '<div class=\"oa-wrap\" style=\"'+vars+'\"><div class=\"oa\">'+\n      '<aside class=\"oa-side\"><div class=\"oa-logo\">'+ic('bag',20)+'OrdersAdmin</div><div class=\"oa-nav\">'+navItems+'</div></aside>'+\n      '<div class=\"oa-main\"><div class=\"oa-top\"><div class=\"oa-crumb\">'+child('ant-breadcrumb',{items:[{title:'Home'},{title:crumbLabel}]},'crumb')+'</div><div class=\"oa-grow\"></div>'+\n        '<div class=\"oa-search-box\">'+searchInput+'</div>'+toggleBtn+'<div style=\"position:relative;display:inline-flex\">'+bellBtn+'<div style=\"position:absolute;top:-3px;right:-3px;pointer-events:none\">'+child('ant-badge',{count:openCount},'bellbadge')+'</div></div>'+'<div class=\"oa-avatar\">'+esc((d2.param('userName','GA')||'GA').slice(0,2).toUpperCase())+'</div></div>'+\n        '<div class=\"oa-scroll\">'+page+'</div></div>'+\n    '</div>'+modal+'</div>';\n  },\n\n  mounted(d2){\n    const orders=()=>d2.data('orders');\n    const tgt=(e,sel)=>e.target.closest(sel);\n    if(orders() && typeof orders().records==='function' && orders().records().length===0 && typeof orders().refresh==='function'){ orders().refresh(); }\n    d2.on('[data-act=\"nav\"]','click',e=>{ d2.state.nav=tgt(e,'[data-act=\"nav\"]').dataset.k; d2.state.selId=null; });\n    d2.on('[data-act=\"overlay\"]','click',e=>{ if(e.target===tgt(e,'[data-act=\"overlay\"]')) d2.state.modal=false; });\n    try{ const pp=d2.data('admin-productsDataSet'); if(pp && typeof pp.records==='function' && pp.records().length===0 && typeof pp.refresh==='function') pp.refresh(); }catch(e){}\n    d2.on('[data-act=\"prodoverlay\"]','click',e=>{ if(e.target===tgt(e,'[data-act=\"prodoverlay\"]')) d2.state.prodModal=false; });\n  }\n};"}},"orders":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"orders"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}},"userName":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"userName"}}}}}}}}}},{"_id":"6a457b62209db9c366371ee4","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"mcp-test-badge","package":"gabz-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: `.badge { display:inline-flex; align-items:center; gap:8px; padding:8px 14px; border-radius:999px; background:#111; color:#fff; font:600 14px system-ui; }\n  .dot { width:8px; height:8px; border-radius:50%; background:#22c55e; }`,\n  render(d2) {\n    const label = d2.params.label || 'MCP OK'\n    return `<div class=\"badge\"><span class=\"dot\"></span>${label}</div>`\n  }\n}"}},"label":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"label"}}}}}}}}}},{"_id":"6a46504c8c5c69fa78ed082f","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"crm-funnel","package":"gabz-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: `.funnel{display:flex;flex-direction:column;align-items:center;gap:6px;height:100%;box-sizing:border-box;padding:18px 16px;overflow:auto}\n    .funnel-title{width:100%;font-size:13px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;opacity:.6;margin:0 0 6px}\n    .funnel-band{display:flex;align-items:center;justify-content:center;min-height:38px;border-radius:8px;\n      color:#fff;font-size:13px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;\n      padding:0 12px;box-sizing:border-box;transition:width .25s ease}\n    .funnel-empty{opacity:.6;font-size:13px;padding:24px 0}\n    .funnel-foot{margin-top:10px;font-size:12px;opacity:.55;display:flex;align-items:center;gap:6px}\n    .funnel-foot .dot{width:8px;height:8px;border-radius:50%;display:inline-block}`,\n  render(d2) {\n    const tokens = d2.param('tokens', {}) || {};\n    const dark = !!tokens.darkMode;\n    const sem = (dark ? tokens.semanticsDark : tokens.semanticsLight) || {};\n    const accent = sem.colorPrimary || '#1677ff';\n    const text = sem.colorText || (dark ? 'rgba(255,255,255,0.85)' : 'rgba(0,0,0,0.88)');\n    const surface = sem.colorBgContainer || (dark ? '#141414' : '#ffffff');\n    const errorC = sem.colorError || '#ef4444';\n    const font = tokens.fontFamily || \"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif\";\n\n    const nfmt = (n) => {\n      try { return d2.fmt.number(n); } catch (e) { return String(n).replace(/\\B(?=(\\d{3})+(?!\\d))/g, ','); }\n    };\n\n    const ds = d2.data('deals');\n    if (ds && ds.loading) {\n      return `<div class=\"funnel\" style=\"background:${surface};color:${text};font-family:${font}\">\n        <div class=\"funnel-empty\">Loading…</div></div>`;\n    }\n    const rows = ds ? ds.records() : [];\n\n    const ORDER = ['Prospecting', 'Qualification', 'Proposal', 'Negotiation', 'Won'];\n    const agg = {};\n    ORDER.forEach((s) => { agg[s] = { count: 0, sum: 0 }; });\n    let lostCount = 0, lostSum = 0;\n    (rows || []).forEach((r) => {\n      const stage = r && r.stage;\n      const amt = Number(r && r.amount) || 0;\n      if (stage === 'Lost') { lostCount += 1; lostSum += amt; return; }\n      if (agg[stage]) { agg[stage].count += 1; agg[stage].sum += amt; }\n    });\n\n    const maxCount = Math.max(1, ...ORDER.map((s) => agg[s].count));\n    const total = ORDER.reduce((acc, s) => acc + agg[s].count, 0);\n\n    if (total === 0 && lostCount === 0) {\n      return `<div class=\"funnel\" style=\"background:${surface};color:${text};font-family:${font}\">\n        <div class=\"funnel-empty\">No deals to display</div></div>`;\n    }\n\n    const bands = ORDER.map((stage, i) => {\n      const { count, sum } = agg[stage];\n      const widthPct = Math.round((count / maxCount) * 100);\n      // Top band = full accent; lower bands blend progressively lighter (funnel tint).\n      // In dark mode blend toward white (keep visible on dark bg); in light mode toward black\n      // so white band-text stays legible on every tint.\n      const blend = Math.round((i / (ORDER.length - 1)) * 42); // 0 -> 42%\n      const mixTo = dark ? 'white' : 'black';\n      const bg = `color-mix(in srgb, ${accent} ${100 - blend}%, ${mixTo})`;\n      const label = `${stage} · ${count} · $${nfmt(sum)}`;\n      return `<div class=\"funnel-band\" data-key=\"${stage}\" data-stage=\"${stage}\"\n        style=\"width:${widthPct}%;background:${bg}\">${label}</div>`;\n    }).join('');\n\n    const foot = lostCount > 0\n      ? `<div class=\"funnel-foot\"><span class=\"dot\" style=\"background:${errorC}\"></span>Lost · ${lostCount} · $${nfmt(lostSum)}</div>`\n      : '';\n\n    return `<div class=\"funnel\" style=\"background:${surface};color:${text};font-family:${font}\">\n      <p class=\"funnel-title\">Sales Funnel</p>\n      ${bands}\n      ${foot}\n    </div>`;\n  },\n};\n"}},"deals":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"deals"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a4651f352c2becc94e1a72c","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"crm-kpi","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', fontSize:14, fontSizeLG:16, fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p&&typeof p==='object')?p:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    .ant-stat{ box-sizing:border-box; display:inline-block; font-family:var(--ff); line-height:1.4; }\n    .ant-stat .stat-title{ font-size:var(--fs); color:var(--c-sec); margin-bottom:4px; }\n    .ant-stat .stat-value{ display:inline-flex; align-items:baseline; gap:4px; font-size:24px; color:var(--c-val); font-variant-numeric:tabular-nums; }\n    .ant-stat .stat-prefix{ font-size:var(--fs-lg); color:var(--c-sec); }\n    .ant-stat .stat-suffix{ font-size:var(--fs); color:var(--c-sec); }\n    .ant-stat .stat-main{ font-size:24px; }\n  `,\n  render(d2) {\n    const metric = d2.param('metric', '');\n    const tokens = d2.param('tokens', {}) || {};\n    const D = resolveTokens(tokens);\n\n    const usesLeads = metric === 'newLeads';\n    const ds = usesLeads ? d2.data('leads') : d2.data('deals');\n    const rows = (ds && ds.records) ? (ds.records() || []) : [];\n    const loading = ds ? ds.loading : false;\n\n    const CLOSED = { Won: true, Lost: true };\n    let raw = 0;\n    if (metric === 'openPipeline') {\n      rows.forEach((r) => { const st = r && r.stage; if (!CLOSED[st]) raw += Number(r && r.amount) || 0; });\n    } else if (metric === 'dealsWon') {\n      raw = rows.filter((r) => r && r.stage === 'Won').length;\n    } else if (metric === 'conversion') {\n      const won = rows.filter((r) => r && r.stage === 'Won').length;\n      const lost = rows.filter((r) => r && r.stage === 'Lost').length;\n      raw = (won + lost) > 0 ? Math.round((won / (won + lost)) * 100) : 0;\n    } else if (metric === 'newLeads') {\n      raw = rows.filter((r) => r && r.status === 'New').length;\n    }\n\n    let display;\n    if (rows.length === 0 && loading) {\n      display = '…';\n    } else {\n      try { display = d2.fmt.number(raw); } catch (e) { display = String(raw).replace(/\\B(?=(\\d{3})+(?!\\d))/g, ','); }\n    }\n\n    const valueColor = d2.param('valueColor', '') || D.colorText;\n    const prefix = d2.param('prefix', '');\n    const suffix = d2.param('suffix', '');\n    const title = d2.param('title', '');\n\n    const style = ['--ff:'+D.fontFamily,'--fs:'+D.fontSize+'px','--fs-lg:'+D.fontSizeLG+'px','--c-sec:'+D.colorTextSecondary,'--c-val:'+valueColor].join(';');\n    const prefixHtml = prefix ? '<span class=\"stat-prefix\">'+esc(prefix)+'</span>' : '';\n    const suffixHtml = suffix ? '<span class=\"stat-suffix\">'+esc(suffix)+'</span>' : '';\n    const titleHtml = title ? '<div class=\"stat-title\">'+esc(title)+'</div>' : '';\n\n    return '<div class=\"ant-stat\" style=\"'+style+'\">'+titleHtml+\n      '<div class=\"stat-value\">'+prefixHtml+'<span class=\"stat-main\">'+esc(display)+'</span>'+suffixHtml+'</div></div>';\n  }\n};"}},"deals":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"deals"}}}},"leads":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"leads"}}}},"metric":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"metric"}}}},"title":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"title"}}}},"prefix":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"prefix"}}}},"suffix":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"suffix"}}}},"valueColor":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"valueColor"}}}},"glyph":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"glyph"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a4652877c6927a8469780c4","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"crm-activity-timeline","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorSuccess:'#52c41a', colorWarning:'#faad14', colorError:'#ff4d4f', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorBorderSecondary:'#f0f0f0', fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p&&typeof p==='object')?p:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nexport default {\n  css: `\n    .ant-tl{ box-sizing:border-box; font-family:var(--ff); font-size:var(--fs); color:var(--c-text); list-style:none; margin:0; padding:0; width:100%; height:100%; overflow:auto; }\n    .ant-tl .tl-item{ position:relative; display:flex; padding-bottom:20px; }\n    .ant-tl .tl-item:last-child{ padding-bottom:0; }\n    .ant-tl .tl-rail{ position:relative; flex:0 0 auto; width:12px; display:flex; flex-direction:column; align-items:center; }\n    .ant-tl .tl-dot{ position:relative; z-index:1; width:10px; height:10px; border-radius:50%; box-sizing:border-box; border:2px solid var(--dot); background:transparent; margin-top:4px; }\n    .ant-tl .tl-line{ position:absolute; top:6px; bottom:-20px; left:50%; transform:translateX(-50%); width:2px; background:var(--c-line); }\n    .ant-tl .tl-item:last-child .tl-line{ display:none; }\n    .ant-tl .tl-content{ flex:1 1 auto; padding-left:14px; padding-bottom:2px; }\n    .ant-tl .tl-label{ color:var(--c-sec); font-size:13px; margin-bottom:2px; }\n    .ant-tl .tl-body{ color:var(--c-text); }\n    .ant-tl .tl-empty{ color:var(--c-sec); font-size:13px; padding:8px 0; }\n  `,\n  render(d2) {\n    const tokens = d2.param('tokens', {}) || {};\n    const D = resolveTokens(tokens);\n    const style = ['--ff:'+D.fontFamily,'--fs:'+D.fontSize+'px','--c-text:'+D.colorText,'--c-sec:'+D.colorTextSecondary,'--c-line:'+D.colorBorderSecondary].join(';');\n\n    const ds = d2.data('activities');\n    const loading = ds && ds.loading;\n    const rows = (ds && !loading) ? (ds.records() || []) : [];\n\n    if (loading) {\n      return '<ul class=\"ant-tl\" style=\"'+style+'\"><li class=\"tl-empty\">Loading…</li></ul>';\n    }\n    if (!rows.length) {\n      return '<ul class=\"ant-tl\" style=\"'+style+'\"><li class=\"tl-empty\">No recent activity</li></ul>';\n    }\n\n    const sorted = rows.slice().sort((a, b) => {\n      const da = new Date((a && a.createdAt) || 0).getTime() || 0;\n      const db = new Date((b && b.createdAt) || 0).getTime() || 0;\n      return db - da;\n    }).slice(0, 8);\n\n    const NAMED = { blue:D.colorPrimary, green:D.colorSuccess, red:D.colorError, gray:D.colorTextTertiary };\n    const TYPECOLOR = { call:'blue', email:'green', meeting:'blue', task:'gray', note:'gray' };\n\n    const rowsHtml = sorted.map((r) => {\n      const type = (r && r.type != null) ? String(r.type) : '';\n      const subject = (r && r.subject != null) ? String(r.subject) : '';\n      let label = '';\n      if (r && r.createdAt) { try { label = d2.fmt.date(r.createdAt); } catch (e) { label = String(r.createdAt); } }\n      const dot = NAMED[TYPECOLOR[type.toLowerCase()] || 'blue'];\n      const body = (type ? type + ': ' : '') + subject;\n      return '<li class=\"tl-item\">'+\n        '<span class=\"tl-rail\"><span class=\"tl-dot\" style=\"--dot:'+esc(dot)+'\"></span><span class=\"tl-line\"></span></span>'+\n        '<div class=\"tl-content\">'+\n          (label ? '<div class=\"tl-label\">'+esc(label)+'</div>' : '')+\n          '<div class=\"tl-body\">'+esc(body)+'</div>'+\n        '</div></li>';\n    }).join('');\n\n    return '<ul class=\"ant-tl\" style=\"'+style+'\">'+rowsHtml+'</ul>';\n  }\n};"}},"activities":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"activities"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a46562a7c6927a846978db9","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"crm-kanban","package":"gabz-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: `.kb{display:flex;gap:12px;height:100%;box-sizing:border-box;padding:14px;overflow:auto;align-items:stretch}\n    .kanban-column{flex:1;min-width:200px;display:flex;flex-direction:column;border-radius:12px;\n      background:var(--col-bg);border:1px solid var(--stroke);box-sizing:border-box;overflow:hidden;transition:background .15s,border-color .15s}\n    .kanban-column[data-over]{border-color:var(--accent);background:var(--col-over)}\n    .col-head{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:12px 14px;border-bottom:1px solid var(--stroke)}\n    .col-title{font-size:13px;font-weight:700;letter-spacing:.02em}\n    .col-dot{width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:7px;vertical-align:middle}\n    .col-count{font-size:12px;font-weight:600;min-width:22px;text-align:center;padding:1px 8px;border-radius:999px;background:var(--pill-bg);color:var(--pill-text)}\n    .col-body{flex:1;padding:10px;display:flex;flex-direction:column;gap:9px;overflow:auto;min-height:60px}\n    .kanban-card{position:relative;padding:11px 12px;border-radius:10px;background:var(--card-bg);border:1px solid var(--stroke);\n      cursor:grab;box-shadow:0 1px 2px rgba(0,0,0,.05);transition:box-shadow .15s,opacity .15s,transform .1s}\n    .kanban-card:hover{box-shadow:0 3px 10px rgba(0,0,0,.10)}\n    .kanban-card[data-drag]{opacity:.45}\n    .card-top{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}\n    .card-name{font-size:14px;font-weight:700;line-height:1.25;word-break:break-word}\n    .card-company{font-size:12px;opacity:.62;margin-top:1px;word-break:break-word}\n    .card-meta{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:10px}\n    .score{font-size:11px;font-weight:700;padding:2px 8px;border-radius:999px;background:var(--score-bg);color:var(--score-text);white-space:nowrap}\n    .owner{display:flex;align-items:center;gap:6px;font-size:11px;opacity:.75;min-width:0}\n    .avatar{width:20px;height:20px;border-radius:50%;object-fit:cover;flex:0 0 auto;background:var(--pill-bg)}\n    .avatar-i{width:20px;height:20px;border-radius:50%;flex:0 0 auto;display:flex;align-items:center;justify-content:center;\n      font-size:9px;font-weight:700;background:var(--accent);color:#fff}\n    .owner-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n    .menu-btn{flex:0 0 auto;width:24px;height:24px;border:0;border-radius:6px;background:transparent;color:var(--text);\n      cursor:pointer;font-size:16px;line-height:1;opacity:.55}\n    .menu-btn:hover{opacity:1;background:var(--pill-bg)}\n    .menu{position:absolute;top:34px;right:8px;z-index:20;min-width:150px;padding:5px;border-radius:10px;\n      background:var(--card-bg);border:1px solid var(--stroke);box-shadow:0 8px 28px rgba(0,0,0,.22)}\n    .menu-item{display:block;width:100%;text-align:left;padding:8px 10px;border:0;border-radius:7px;background:transparent;\n      color:var(--text);font-size:13px;cursor:pointer}\n    .menu-item:hover{background:var(--pill-bg)}\n    .col-empty{font-size:12px;opacity:.4;padding:14px 6px;text-align:center}\n    .kb-loading{padding:24px;font-size:13px;opacity:.6}`,\n\n  render(d2) {\n    const tokens = d2.param('tokens', {}) || {};\n    const dark = !!tokens.darkMode;\n    const sem = (dark ? tokens.semanticsDark : tokens.semanticsLight) || {};\n    const accent = sem.colorPrimary || '#1677ff';\n    const text = sem.colorText || (dark ? 'rgba(255,255,255,0.85)' : 'rgba(0,0,0,0.88)');\n    const surface = sem.colorBgContainer || (dark ? '#141414' : '#ffffff');\n    const layout = sem.colorBgLayout || (dark ? '#000000' : '#f5f5f5');\n    const font = tokens.fontFamily || \"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif\";\n\n    const colBg = dark ? 'rgba(255,255,255,0.03)' : 'rgba(0,0,0,0.025)';\n    const colOver = dark ? 'rgba(255,255,255,0.07)' : 'rgba(0,0,0,0.045)';\n    const stroke = dark ? 'rgba(255,255,255,0.12)' : 'rgba(0,0,0,0.09)';\n    const pillBg = dark ? 'rgba(255,255,255,0.10)' : 'rgba(0,0,0,0.06)';\n    const scoreBg = 'color-mix(in srgb, ' + accent + ' 16%, transparent)';\n\n    const esc = (s) => String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n\n    const COLUMNS = [\n      { key: 'New', dot: '#8c8c8c' },\n      { key: 'Contacted', dot: '#1677ff' },\n      { key: 'Qualified', dot: '#faad14' },\n      { key: 'Converted', dot: '#52c41a' }\n    ];\n\n    const rootStyle = 'background:' + layout + ';color:' + text + ';font-family:' + font +\n      ';--text:' + text + ';--accent:' + accent + ';--col-bg:' + colBg + ';--col-over:' + colOver +\n      ';--card-bg:' + surface + ';--stroke:' + stroke + ';--pill-bg:' + pillBg +\n      ';--pill-text:' + text + ';--score-bg:' + scoreBg + ';--score-text:' + accent + '';\n\n    const ds = d2.data('leads');\n    if (ds && ds.loading) {\n      return '<div class=\"kb\" style=\"' + rootStyle + '\"><div class=\"kb-loading\">Loading leads…</div></div>';\n    }\n    const rows = (ds ? ds.records() : []) || [];\n\n    // Resolve owners (optional dataset param) into an id -> {name, avatar} map.\n    const owners = {};\n    const od = d2.data('owners');\n    const orows = (od && !od.loading ? od.records() : []) || [];\n    orows.forEach((o) => { if (o && o._id) owners[o._id] = o; });\n\n    const openId = d2.state.menuOpen || null;\n\n    const columnHtml = COLUMNS.map((col) => {\n      const cards = rows.filter((r) => (r && r.status) === col.key);\n      const cardsHtml = cards.length\n        ? cards.map((r) => {\n            const owner = r.ownerId && owners[r.ownerId] ? owners[r.ownerId] : null;\n            const ownerName = owner ? (owner.name || '') : '';\n            const avatarUrl = owner ? (owner.avatar || '') : '';\n            const inits = ownerName ? d2.fmt.initials(ownerName, 2) : '';\n            const ownerBlock = ownerName\n              ? '<div class=\"owner\">' +\n                  (avatarUrl\n                    ? '<img class=\"avatar\" src=\"' + esc(avatarUrl) + '\" alt=\"\"/>'\n                    : '<span class=\"avatar-i\">' + esc(inits) + '</span>') +\n                  '<span class=\"owner-name\">' + esc(ownerName) + '</span></div>'\n              : '<div class=\"owner\"></div>';\n            const isOpen = openId === r._id;\n            const menu = isOpen\n              ? '<div class=\"menu\" data-menu=\"' + esc(r._id) + '\">' +\n                  '<button class=\"menu-item\" data-act=\"edit\" data-id=\"' + esc(r._id) + '\">Edit</button>' +\n                  '<button class=\"menu-item\" data-act=\"followup\" data-id=\"' + esc(r._id) + '\">Log follow-up</button>' +\n                  '<button class=\"menu-item\" data-act=\"convert\" data-id=\"' + esc(r._id) + '\">Convert</button>' +\n                '</div>'\n              : '';\n            const score = Number(r.score) || 0;\n            return '<div class=\"kanban-card\" draggable=\"true\" data-key=\"' + esc(r._id) + '\" data-id=\"' + esc(r._id) + '\">' +\n                '<div class=\"card-top\">' +\n                  '<div style=\"min-width:0\">' +\n                    '<div class=\"card-name\">' + esc(r.name) + '</div>' +\n                    '<div class=\"card-company\">' + esc(r.company) + '</div>' +\n                  '</div>' +\n                  '<button class=\"menu-btn\" data-menu-toggle=\"' + esc(r._id) + '\" aria-label=\"Actions\">⋯</button>' +\n                '</div>' +\n                '<div class=\"card-meta\">' +\n                  '<span class=\"score\">Score ' + score + '</span>' +\n                  ownerBlock +\n                '</div>' +\n                menu +\n              '</div>';\n          }).join('')\n        : '<div class=\"col-empty\">No leads</div>';\n\n      return '<div class=\"kanban-column\" data-status=\"' + col.key + '\">' +\n          '<div class=\"col-head\">' +\n            '<span class=\"col-title\"><span class=\"col-dot\" style=\"background:' + col.dot + '\"></span>' + col.key + '</span>' +\n            '<span class=\"col-count\">' + cards.length + '</span>' +\n          '</div>' +\n          '<div class=\"col-body\" data-status=\"' + col.key + '\">' + cardsHtml + '</div>' +\n        '</div>';\n    }).join('');\n\n    return '<div class=\"kb\" style=\"' + rootStyle + '\">' + columnHtml + '</div>';\n  },\n\n  mounted(d2) {\n    // --- Card actions (menu) ---\n    d2.on('.menu-btn', 'click', (e, el) => {\n      e.stopPropagation();\n      const id = el.getAttribute('data-menu-toggle');\n      d2.state.menuOpen = d2.state.menuOpen === id ? null : id;\n    });\n\n    d2.on('.menu-item', 'click', (e, el) => {\n      e.stopPropagation();\n      const id = el.getAttribute('data-id');\n      const act = el.getAttribute('data-act');\n      const ds = d2.data('leads');\n      const rec = (ds ? ds.records() : []).find((r) => r && r._id === id) || { _id: id };\n      d2.state.menuOpen = null;\n      if (act === 'edit') {\n        // store-driven edit (emit payloads are uncapturable in handlers — Task 16); fan the lead into draft_* and open the edit drawer\n        try {\n          const s = d2.store('crm-ui');\n          if (s) {\n            s.set('editType', 'leads');\n            s.set('editId', String(id));\n            s.set('draft_name', (rec && rec.name) || '');\n            s.set('draft_company', (rec && rec.company) || '');\n            s.set('draft_email', (rec && rec.email) || '');\n            s.set('draft_phone', (rec && rec.phone) || '');\n            s.set('draft_source', (rec && rec.source) || '');\n            s.set('draft_status', (rec && rec.status) || '');\n            s.set('draft_score', (rec && rec.score != null) ? String(rec.score) : '');\n            s.set('draft_ownerId', (rec && rec.ownerId) || '');\n            s.set('draft_notes', (rec && rec.notes) || '');\n            s.set('editOpen', true);\n          }\n        } catch (_e) {}\n        d2.emit('onEdit', rec);\n      }\n      else if (act === 'followup') {\n        // store-driven follow-up (emit payloads are uncapturable in handlers — Task 16); scope to this lead\n        try {\n          const s = d2.store('crm-ui');\n          if (s) {\n            ['type','subject','notes','dueDate'].forEach((k) => s.set('f_'+k, ''));\n            s.set('followupType', 'lead');\n            s.set('followupRelatedId', String(id));\n            s.set('followupOwnerId', (rec && rec.ownerId) || '');\n            s.set('followupOpen', true);\n          }\n        } catch (_e) {}\n        d2.emit('onFollowUp', rec);\n      }\n      else if (act === 'convert') { try { d2.store('crm-ui').set('convertPending', id); } catch (_e) {} d2.emit('onConvert', rec); }\n    });\n\n    // Close any open menu on outside click.\n    d2.on(document, 'click', () => { if (d2.state.menuOpen) d2.state.menuOpen = null; });\n\n    // --- HTML5 drag & drop (cards draggable, columns are drop targets) ---\n    d2.on('.kanban-card', 'dragstart', (e, el) => {\n      const id = el.getAttribute('data-id');\n      if (e.dataTransfer) {\n        e.dataTransfer.setData('text/plain', id);\n        e.dataTransfer.effectAllowed = 'move';\n      }\n      el.setAttribute('data-drag', '');\n    });\n    d2.on('.kanban-card', 'dragend', (e, el) => el.removeAttribute('data-drag'));\n\n    d2.on('.kanban-column', 'dragover', (e, el) => {\n      e.preventDefault();\n      if (e.dataTransfer) e.dataTransfer.dropEffect = 'move';\n      el.setAttribute('data-over', '');\n    });\n    d2.on('.kanban-column', 'dragleave', (e, el) => {\n      // Only clear when leaving the column entirely (not moving between its children).\n      if (!el.contains(e.relatedTarget)) el.removeAttribute('data-over');\n    });\n\n    d2.on('.kanban-column', 'drop', async (e, el) => {\n      e.preventDefault();\n      el.removeAttribute('data-over');\n      const id = e.dataTransfer ? e.dataTransfer.getData('text/plain') : '';\n      const target = el.getAttribute('data-status');\n      if (!id || !target) return;\n      const ds = d2.data('leads');\n      if (!ds) return;\n      const rec = (ds.records() || []).find((r) => r && r._id === id);\n      if (!rec) return;\n      if (rec.status === target) return; // same column - no-op\n      // PERSIST: patch the crm_leads record's status; reactive re-read updates the board.\n      await ds.update({ ...rec, status: target });\n    });\n  }\n};"}},"leads":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"leads"}}}},"owners":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"owners"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}},"onEdit":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onEdit"}}}},"onFollowUp":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onFollowUp"}}}},"onConvert":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"onConvert"}}}}}}}}}},{"_id":"6a466596fd69f89bce077384","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"crm-lead-form","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const FIELDS = [\n  { key:'name', label:'Name', ph:'Full name', type:'text' },\n  { key:'company', label:'Company', ph:'Company', type:'text' },\n  { key:'email', label:'Email', ph:'name@company.com', type:'text' },\n  { key:'phone', label:'Phone', ph:'Phone', type:'text' },\n  { key:'source', label:'Source', ph:'Web / Event / Referral / Outbound', type:'select', opts:['Web','Event','Referral','Outbound'] },\n  { key:'status', label:'Status', ph:'Status', type:'select', opts:['New','Contacted','Qualified','Converted'] },\n  { key:'score', label:'Score', ph:'0', type:'number' },\n  { key:'ownerId', label:'Owner ID', ph:'Owner ID', type:'text' },\n  { key:'notes', label:'Notes', ph:'Notes', type:'textarea' }\n];\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nexport default {\n  css: `\n    .clf{ box-sizing:border-box; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif; color:var(--fg); display:flex; flex-direction:column; gap:16px; }\n    .clf *{ box-sizing:border-box; }\n    .clf-item{ display:flex; flex-direction:column; gap:6px; }\n    .clf-label{ font-size:13px; font-weight:500; color:var(--fg); }\n    .clf-field{ width:100%; font-size:14px; font-family:inherit; color:var(--fg); background:var(--bg); border:1px solid var(--bd); border-radius:6px; padding:5px 11px; height:34px; outline:none; transition:border-color .2s,box-shadow .2s; }\n    .clf-field:focus{ border-color:var(--cp); box-shadow:0 0 0 2px var(--cpbg); }\n    textarea.clf-field{ height:72px; resize:vertical; }\n    .clf-actions{ display:flex; gap:10px; justify-content:flex-end; margin-top:4px; }\n    .clf-btn{ height:36px; padding:0 18px; font-size:14px; border-radius:6px; cursor:pointer; border:1px solid var(--bd); background:var(--bg); color:var(--fg); transition:all .2s; }\n    .clf-btn:hover{ border-color:var(--cp); color:var(--cp); }\n    .clf-btn.primary{ background:var(--cp); border-color:var(--cp); color:#fff; }\n    .clf-btn.primary:hover{ opacity:.9; color:#fff; }\n    .clf-err{ color:#ef4444; font-size:12px; min-height:14px; }\n  `,\n  render(d2){\n    const s = d2.store('crm-ui');\n    const dark = !!(s && s.get('darkMode'));\n    const accent = (s && s.get('accent')) || '#4f46e5';\n    const vars = [\n      '--fg:'+(dark?'rgba(255,255,255,0.85)':'rgba(0,0,0,0.88)'),\n      '--bg:'+(dark?'#1f1f1f':'#ffffff'),\n      '--bd:'+(dark?'#424242':'#d9d9d9'),\n      '--cp:'+accent,\n      '--cpbg:'+(dark?'rgba(255,255,255,0.12)':'rgba(0,0,0,0.06)')\n    ].join(';');\n    let items = FIELDS.map(function(f){\n      const v = (s ? s.get('draft_'+f.key) : '');\n      const val = v==null?'':String(v);\n      let control;\n      if(f.type==='textarea'){\n        control = '<textarea class=\"clf-field\" data-k=\"'+f.key+'\" placeholder=\"'+esc(f.ph)+'\">'+esc(val)+'</textarea>';\n      } else if(f.type==='select'){\n        let o = f.opts.map(function(op){ return '<option value=\"'+esc(op)+'\"'+(String(val)===String(op)?' selected':'')+'>'+esc(op)+'</option>'; }).join('');\n        control = '<select class=\"clf-field\" data-k=\"'+f.key+'\"><option value=\"\"'+(val===''?' selected':'')+'>Select…</option>'+o+'</select>';\n      } else {\n        control = '<input class=\"clf-field\" type=\"text\" data-k=\"'+f.key+'\" placeholder=\"'+esc(f.ph)+'\" value=\"'+esc(val)+'\">';\n      }\n      return '<div class=\"clf-item\"><div class=\"clf-label\">'+esc(f.label)+'</div>'+control+'</div>';\n    }).join('');\n    const okLabel = (s && s.get('addOpen')) ? 'Create Lead' : 'Save';\n    return '<div class=\"clf\" style=\"'+vars+'\">'+items+'<div class=\"clf-err\" data-role=\"err\"></div><div class=\"clf-actions\"><button class=\"clf-btn\" data-act=\"cancel\">Cancel</button><button class=\"clf-btn primary\" data-act=\"save\">'+okLabel+'</button></div></div>';\n  },\n  mounted(d2){\n    const s = d2.store('crm-ui');\n    const sync = function(el){ const k=el.getAttribute('data-k'); if(k&&s) s.set('draft_'+k, el.value); };\n    d2.on('.clf-field','input',function(e,el){ sync(el); });\n    d2.on('.clf-field','change',function(e,el){ sync(el); });\n    d2.on('[data-act=\"cancel\"]','click',function(){ if(s){ s.set('editOpen',false); s.set('addOpen',false); } });\n    d2.on('[data-act=\"save\"]','click',async function(e,el){\n      if(!s) return;\n      const rec = {};\n      FIELDS.forEach(function(f){ let v=s.get('draft_'+f.key); if(f.key==='score'){ v=(v===''||v==null)?null:Number(v); } rec[f.key]=v; });\n      const errEl = d2.$('[data-role=\"err\"]');\n      if(!rec.name){ if(errEl) errEl.textContent='Name is required.'; return; }\n      const isEdit = !!s.get('editOpen');\n      const editId = s.get('editId');\n      const ds = d2.data('leads');\n      el.textContent = 'Saving…';\n      try{\n        if(isEdit && editId){ await ds.update(Object.assign({ _id: editId }, rec)); }\n        else { await ds.create(rec); }\n        if(typeof ds.refresh==='function') ds.refresh();\n        s.set('editOpen', false); s.set('addOpen', false);\n      }catch(err){ if(errEl) errEl.textContent = 'Save failed: '+(err&&err.message?err.message:err); el.textContent = isEdit?'Save':'Create Lead'; }\n    });\n  }\n};"}},"leads":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"leads"}}}},"mode":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"mode"}}}}}}}}}},{"_id":"6a466b5352c2becc94e21167","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"crm-convert","package":"gabz-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    .crmcv{ display:block; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif; font-size:12px; }\n    .crmcv-msg{ color:rgba(0,0,0,0.45); }\n  `,\n  async runConvert(d2, leadId){\n    const leadsDs = d2.data('leads');\n    const accountsDs = d2.data('accounts');\n    const contactsDs = d2.data('contacts');\n    const dealsDs = d2.data('deals');\n    // Fetch the lead by id\n    const rows = await leadsDs.query({ _id: leadId });\n    const lead = Array.isArray(rows) ? rows.find(function(r){ return String(r._id)===String(leadId); }) || rows[0] : null;\n    if(!lead){ throw new Error('lead not found: '+leadId); }\n    // 1. Account\n    const acct = await accountsDs.create({\n      name: lead.company,\n      industry: '',\n      size: '',\n      website: '',\n      annualRevenue: 0,\n      ownerId: lead.ownerId,\n      status: 'prospect',\n      createdAt: new Date().toISOString()\n    });\n    const acctId = acct && (acct._id || (acct.record && acct.record._id));\n    // 2. Contact (split name)\n    const parts = String(lead.name || '').trim().split(/\\s+/);\n    const firstName = parts.shift() || '';\n    const lastName = parts.join(' ');\n    const contact = await contactsDs.create({\n      firstName: firstName,\n      lastName: lastName,\n      email: lead.email,\n      phone: lead.phone,\n      title: '',\n      accountId: acctId,\n      isPrimary: true\n    });\n    const contactId = contact && (contact._id || (contact.record && contact.record._id));\n    // 3. Deal\n    const deal = await dealsDs.create({\n      name: lead.company + ' — New Opportunity',\n      accountId: acctId,\n      contactId: contactId,\n      amount: 0,\n      stage: 'Prospecting',\n      probability: 10,\n      expectedCloseDate: '',\n      ownerId: lead.ownerId,\n      createdAt: new Date().toISOString()\n    });\n    const dealId = deal && (deal._id || (deal.record && deal.record._id));\n    // 4. Update lead status\n    await leadsDs.update({ _id: leadId, status: 'Converted' });\n    return { acctId: acctId, contactId: contactId, dealId: dealId };\n  },\n  render(d2){\n    const s = d2.store('crm-ui');\n    const pending = s ? s.get('convertPending') : '';\n    const busy = !!d2.state.busy;\n    const last = d2.state.lastMsg || '';\n    if(pending && !busy && String(pending) !== String(d2.state.handledId || '')){\n      d2.state.busy = true;\n      d2.state.handledId = String(pending);\n      const self = this;\n      const leadId = String(pending);\n      (async function(){\n        try{\n          const res = await self.runConvert(d2, leadId);\n          d2.state.lastMsg = 'Converted '+leadId+' → acct '+res.acctId+', contact '+res.contactId+', deal '+res.dealId;\n        }catch(err){\n          d2.state.lastMsg = 'Convert failed: '+(err && err.message ? err.message : err);\n        }finally{\n          if(s){ s.set('convertPending', ''); s.set('convertResult', d2.state.lastMsg); }\n          d2.state.busy = false;\n        }\n      })();\n    }\n    return '<div class=\"crmcv\"><span class=\"crmcv-msg\">'+(busy?'Converting…':(last?'':''))+'</span></div>';\n  }\n};"}},"leads":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"leads"}}}},"accounts":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"accounts"}}}},"contacts":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"contacts"}}}},"deals":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"deals"}}}}}}}}}},{"_id":"6a466f54bf38d382814f3b68","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"crm-detail","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const ANT_DEFAULTS = { colorPrimary:'#1677ff', colorSuccess:'#52c41a', colorWarning:'#faad14', colorError:'#ff4d4f', colorText:'rgba(0,0,0,0.88)', colorTextSecondary:'rgba(0,0,0,0.65)', colorTextTertiary:'rgba(0,0,0,0.45)', colorBorderSecondary:'#f0f0f0', colorBgContainer:'#ffffff', fontFamily:\"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif\" };\nfunction resolveTokens(p){ const tk=(p&&typeof p==='object')?p:{}; let sem=tk; if(tk.semanticsLight||tk.semanticsDark){ sem=tk.darkMode?(tk.semanticsDark||{}):(tk.semanticsLight||{}); } const D=Object.assign({},ANT_DEFAULTS); for(const k in sem){ let v=sem[k]; if(v==null||v==='')continue; if(typeof v==='object')v=v.rgba||v.hex||v.value||v.color; if(v!=null&&v!=='')D[k]=v; } if(tk.fontFamily)D.fontFamily=tk.fontFamily; return D; }\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\n\nconst TYPES = {\n  lead: {\n    ds: 'leads', label: 'Lead', titleField: 'name',\n    fields: [\n      { k:'name', label:'Name' }, { k:'company', label:'Company' },\n      { k:'email', label:'Email' }, { k:'phone', label:'Phone' },\n      { k:'source', label:'Source' }, { k:'status', label:'Status' },\n      { k:'score', label:'Score' }, { k:'ownerId', label:'Owner ID' },\n      { k:'notes', label:'Notes', span:2 }\n    ]\n  },\n  deal: {\n    ds: 'deals', label: 'Deal', titleField: 'name',\n    fields: [\n      { k:'name', label:'Name', span:2 }, { k:'amount', label:'Amount', money:true },\n      { k:'stage', label:'Stage' }, { k:'probability', label:'Probability', pct:true },\n      { k:'expectedCloseDate', label:'Expected Close', date:true },\n      { k:'accountId', label:'Account ID' }, { k:'contactId', label:'Contact ID' },\n      { k:'ownerId', label:'Owner ID' }\n    ]\n  },\n  account: {\n    ds: 'accounts', label: 'Account', titleField: 'name',\n    fields: [\n      { k:'name', label:'Name', span:2 }, { k:'industry', label:'Industry' },\n      { k:'size', label:'Size (employees)' }, { k:'website', label:'Website' },\n      { k:'annualRevenue', label:'Annual Revenue', money:true },\n      { k:'status', label:'Status' }, { k:'ownerId', label:'Owner ID' }\n    ]\n  },\n  contact: {\n    ds: 'contacts', label: 'Contact', titleField: null,\n    fields: [\n      { k:'firstName', label:'First Name' }, { k:'lastName', label:'Last Name' },\n      { k:'email', label:'Email' }, { k:'phone', label:'Phone' },\n      { k:'title', label:'Title' }, { k:'accountId', label:'Account ID' },\n      { k:'isPrimary', label:'Primary Contact' }\n    ]\n  }\n};\n\nfunction fmtVal(d2, f, rec){\n  let v = rec ? rec[f.k] : null;\n  if (v == null || v === '') return '—';\n  try {\n    if (f.money) return d2.fmt.currency(Number(v));\n    if (f.pct) return String(v) + '%';\n    if (f.date) return d2.fmt.date(v);\n    if (typeof v === 'boolean') return v ? 'Yes' : 'No';\n  } catch(e) {}\n  return String(v);\n}\n\nfunction recordTitle(cfg, rec){\n  if (!rec) return '';\n  if (cfg.titleField && rec[cfg.titleField]) return String(rec[cfg.titleField]);\n  const nm = [rec.firstName, rec.lastName].filter(Boolean).join(' ');\n  return nm || String(rec._id || '');\n}\n\nexport default {\n  css: `\n    .cd{ box-sizing:border-box; font-family:var(--ff); color:var(--c-text); width:100%; height:100%; overflow:auto; padding:4px; }\n    .cd *{ box-sizing:border-box; }\n    .cd-head{ display:flex; align-items:flex-start; justify-content:space-between; gap:16px; margin-bottom:20px; }\n    .cd-title{ font-size:24px; font-weight:600; color:var(--c-text); line-height:1.2; }\n    .cd-sub{ font-size:13px; color:var(--c-sec); margin-top:4px; }\n    .cd-editbtn{ height:36px; padding:0 18px; font-size:14px; border-radius:6px; cursor:pointer; border:1px solid var(--cp); background:var(--cp); color:#fff; transition:opacity .2s; white-space:nowrap; }\n    .cd-editbtn:hover{ opacity:.9; }\n    .cd-editbtn[disabled]{ opacity:.4; cursor:not-allowed; }\n    .cd-headbtns{ display:flex; gap:10px; flex-shrink:0; }\n    .cd-followbtn{ height:36px; padding:0 18px; font-size:14px; border-radius:6px; cursor:pointer; border:1px solid var(--cp); background:transparent; color:var(--cp); transition:all .2s; white-space:nowrap; }\n    .cd-followbtn:hover{ background:var(--cp); color:#fff; }\n    .cd-followbtn[disabled]{ opacity:.4; cursor:not-allowed; }\n    .cd-cols{ display:flex; gap:24px; align-items:flex-start; }\n    .cd-left{ flex:1 1 60%; min-width:0; }\n    .cd-right{ flex:1 1 40%; min-width:0; }\n    .cd-sec-title{ font-size:15px; font-weight:600; color:var(--c-text); margin:0 0 12px; }\n    .cd-desc{ border:1px solid var(--c-line); border-radius:8px; overflow:hidden; }\n    .cd-desc-row{ display:flex; border-bottom:1px solid var(--c-line); }\n    .cd-desc-row:last-child{ border-bottom:none; }\n    .cd-desc-cell{ display:flex; flex:1 1 0; min-width:0; border-right:1px solid var(--c-line); }\n    .cd-desc-cell:last-child{ border-right:none; }\n    .cd-desc-cell.span2{ flex:2 2 0; }\n    .cd-desc-lbl{ flex:0 0 130px; padding:10px 14px; background:var(--c-lblbg); font-weight:500; color:var(--c-sec); font-size:13px; }\n    .cd-desc-val{ flex:1 1 auto; padding:10px 14px; color:var(--c-text); font-size:14px; word-break:break-word; }\n    .cd-tl{ list-style:none; margin:0; padding:0; }\n    .cd-tl .tl-item{ position:relative; display:flex; padding-bottom:20px; }\n    .cd-tl .tl-item:last-child{ padding-bottom:0; }\n    .cd-tl .tl-rail{ position:relative; flex:0 0 auto; width:12px; display:flex; flex-direction:column; align-items:center; }\n    .cd-tl .tl-dot{ position:relative; z-index:1; width:10px; height:10px; border-radius:50%; box-sizing:border-box; border:2px solid var(--dot,var(--cp)); background:transparent; margin-top:4px; }\n    .cd-tl .tl-line{ position:absolute; top:6px; bottom:-20px; left:50%; transform:translateX(-50%); width:2px; background:var(--c-line); }\n    .cd-tl .tl-item:last-child .tl-line{ display:none; }\n    .cd-tl .tl-content{ flex:1 1 auto; padding-left:14px; padding-bottom:2px; }\n    .cd-tl .tl-label{ color:var(--c-sec); font-size:13px; margin-bottom:2px; }\n    .cd-tl .tl-body{ color:var(--c-text); }\n    .cd-empty{ color:var(--c-sec); font-size:13px; padding:8px 0; }\n    .cd-count{ font-size:12px; color:var(--c-sec); font-weight:400; margin-left:6px; }\n  `,\n  render(d2){\n    const tokens = d2.param('tokens', {}) || {};\n    const D = resolveTokens(tokens);\n\n    let type = '', id = '';\n    try {\n      const r = d2.router('crm-router');\n      const rp = (r && r.params) || {};\n      type = rp.type || ''; id = rp.id || '';\n    } catch(e) {}\n    const store = d2.store('crm-ui');\n    if (!type && store) type = store.get('detailType') || '';\n    if (!id && store) id = store.get('detailId') || '';\n    type = String(type || '').toLowerCase();\n\n    const dark = !!((tokens && tokens.darkMode) || (store && store.get('darkMode')));\n    // colorText IS set per-mode by the recipe; secondary/tertiary/line are NOT, so derive them from `dark`.\n    const cText = D.colorText || (dark?'rgba(255,255,255,0.85)':'rgba(0,0,0,0.88)');\n    const cSec = dark ? 'rgba(255,255,255,0.55)' : 'rgba(0,0,0,0.55)';\n    const cLine = dark ? '#303030' : (D.colorBorderSecondary||'#f0f0f0');\n    const cp = D.colorPrimary || (store && store.get('accent')) || '#4f46e5';\n    const lblBg = dark ? 'rgba(255,255,255,0.04)' : '#fafafa';\n    const style = [\n      '--ff:'+D.fontFamily, '--c-text:'+cText, '--c-sec:'+cSec,\n      '--c-line:'+cLine, '--cp:'+cp, '--c-lblbg:'+lblBg\n    ].join(';');\n\n    const cfg = TYPES[type];\n    if (!cfg) {\n      return '<div class=\"cd\" style=\"'+style+'\"><div class=\"cd-empty\">No record selected. Expected a /record/:type/:id route (type = lead | deal | account | contact).</div></div>';\n    }\n\n    const ds = d2.data(cfg.ds);\n    const dsLoading = ds && ds.loading;\n    const rows = (ds && !dsLoading) ? (ds.records() || []) : [];\n    let rec = null;\n    for (let i=0;i<rows.length;i++){ if (rows[i] && String(rows[i]._id) === String(id)) { rec = rows[i]; break; } }\n\n    const acts = d2.data('activities');\n    const actLoading = acts && acts.loading;\n    const allActs = (acts && !actLoading) ? (acts.records() || []) : [];\n    const mine = allActs.filter(function(a){ return a && String(a.relatedId) === String(id); })\n      .sort(function(a,b){ const da=new Date((a&&a.createdAt)||0).getTime()||0; const db=new Date((b&&b.createdAt)||0).getTime()||0; return db-da; });\n\n    const title = rec ? recordTitle(cfg, rec) : (dsLoading ? 'Loading…' : 'Record not found');\n    const sub = cfg.label + (id ? ' · ' + id : '');\n    const canEdit = (type === 'lead' && !!rec);\n    const editBtn = '<button class=\"cd-editbtn\" data-act=\"edit\"'+(canEdit?'':' disabled title=\"Edit available for leads\"')+'>Edit '+esc(cfg.label)+'</button>';\n    const canFollow = !!rec;\n    const followBtn = '<button class=\"cd-followbtn\" data-act=\"followup\"'+(canFollow?'':' disabled')+'>Log follow-up</button>';\n    const head = '<div class=\"cd-head\"><div><div class=\"cd-title\">'+esc(title)+'</div><div class=\"cd-sub\">'+esc(sub)+'</div></div><div class=\"cd-headbtns\">'+followBtn+editBtn+'</div></div>';\n\n    let descHtml;\n    if (!rec) {\n      descHtml = '<div class=\"cd-empty\">'+(dsLoading?'Loading record…':'No '+cfg.label.toLowerCase()+' found for id '+esc(id))+'</div>';\n    } else {\n      const cells = cfg.fields.map(function(f){\n        const span = f.span===2;\n        return '<div class=\"cd-desc-cell'+(span?' span2':'')+'\"><div class=\"cd-desc-lbl\">'+esc(f.label)+'</div><div class=\"cd-desc-val\">'+esc(fmtVal(d2,f,rec))+'</div></div>';\n      });\n      const rowsOut = []; let buf = []; let units = 0;\n      for (let i=0;i<cfg.fields.length;i++){\n        const f = cfg.fields[i]; const u = f.span===2 ? 2 : 1;\n        if (units + u > 2){ rowsOut.push('<div class=\"cd-desc-row\">'+buf.join('')+'</div>'); buf=[]; units=0; }\n        buf.push(cells[i]); units += u;\n        if (units === 2){ rowsOut.push('<div class=\"cd-desc-row\">'+buf.join('')+'</div>'); buf=[]; units=0; }\n      }\n      if (buf.length){ rowsOut.push('<div class=\"cd-desc-row\">'+buf.join('')+'</div>'); }\n      descHtml = '<div class=\"cd-desc\">'+rowsOut.join('')+'</div>';\n    }\n\n    const NAMED = { blue:D.colorPrimary, green:D.colorSuccess, red:D.colorError, gray:D.colorTextTertiary };\n    const TYPECOLOR = { call:'blue', email:'green', meeting:'blue', task:'gray', note:'gray' };\n    let tlHtml;\n    if (actLoading) { tlHtml = '<div class=\"cd-empty\">Loading activity…</div>'; }\n    else if (!mine.length) { tlHtml = '<div class=\"cd-empty\">No follow-up activity for this record.</div>'; }\n    else {\n      tlHtml = '<ul class=\"cd-tl\">'+mine.map(function(r){\n        const t = (r&&r.type!=null)?String(r.type):'';\n        const subj = (r&&r.subject!=null)?String(r.subject):'';\n        let label=''; if(r&&r.createdAt){ try{ label=d2.fmt.date(r.createdAt);}catch(e){label=String(r.createdAt);} }\n        const dot = NAMED[TYPECOLOR[t.toLowerCase()]||'blue'] || cp;\n        const body = (t?t+': ':'')+subj;\n        return '<li class=\"tl-item\"><span class=\"tl-rail\"><span class=\"tl-dot\" style=\"--dot:'+esc(dot)+'\"></span><span class=\"tl-line\"></span></span>'+\n          '<div class=\"tl-content\">'+(label?'<div class=\"tl-label\">'+esc(label)+'</div>':'')+'<div class=\"tl-body\">'+esc(body)+'</div></div></li>';\n      }).join('')+'</ul>';\n    }\n    const tlCount = mine.length ? '<span class=\"cd-count\">('+mine.length+')</span>' : '';\n\n    const left = '<div class=\"cd-left\"><div class=\"cd-sec-title\">Details</div>'+descHtml+'</div>';\n    const right = '<div class=\"cd-right\"><div class=\"cd-sec-title\">Follow-up Timeline'+tlCount+'</div>'+tlHtml+'</div>';\n\n    return '<div class=\"cd\" style=\"'+style+'\">'+head+'<div class=\"cd-cols\">'+left+right+'</div></div>';\n  },\n  mounted(d2){\n    d2.on('[data-act=\"edit\"]','click',function(){\n      const s = d2.store('crm-ui');\n      if (!s) return;\n      let type='', id='';\n      try { const r=d2.router('crm-router'); const rp=(r&&r.params)||{}; type=rp.type||''; id=rp.id||''; } catch(e){}\n      if (!type) type = s.get('detailType')||'';\n      if (!id) id = s.get('detailId')||'';\n      type = String(type||'').toLowerCase();\n      const cfg = TYPES[type];\n      if (type !== 'lead' || !cfg) return;\n      const ds = d2.data(cfg.ds);\n      const rows = (ds && !ds.loading) ? (ds.records()||[]) : [];\n      let rec=null; for(let i=0;i<rows.length;i++){ if(rows[i]&&String(rows[i]._id)===String(id)){ rec=rows[i]; break; } }\n      if (!rec) return;\n      ['name','company','email','phone','source','status','score','ownerId','notes'].forEach(function(k){\n        s.set('draft_'+k, rec[k]==null?'':rec[k]);\n      });\n      s.set('editType','leads');\n      s.set('editId', String(rec._id));\n      s.set('addOpen', false);\n      s.set('editOpen', true);\n    });\n    d2.on('[data-act=\"followup\"]','click',function(){\n      const s = d2.store('crm-ui');\n      if (!s) return;\n      let type='', id='';\n      try { const r=d2.router('crm-router'); const rp=(r&&r.params)||{}; type=rp.type||''; id=rp.id||''; } catch(e){}\n      if (!type) type = s.get('detailType')||'';\n      if (!id) id = s.get('detailId')||'';\n      type = String(type||'').toLowerCase();\n      const cfg = TYPES[type];\n      if (!cfg || !id) return;\n      // resolve the record's owner (falls back to a default owner in the form)\n      let ownerId = '';\n      const ds = d2.data(cfg.ds);\n      const rows = (ds && !ds.loading) ? (ds.records()||[]) : [];\n      for(let i=0;i<rows.length;i++){ if(rows[i]&&String(rows[i]._id)===String(id)){ ownerId = rows[i].ownerId||''; break; } }\n      // clear the draft + scope the follow-up to THIS record (store-driven, Task 16 pattern)\n      ['type','subject','notes','dueDate'].forEach(function(k){ s.set('f_'+k, ''); });\n      s.set('followupType', type);\n      s.set('followupRelatedId', String(id));\n      s.set('followupOwnerId', ownerId);\n      s.set('editOpen', false);\n      s.set('followupOpen', true);\n    });\n  }\n};"}},"leads":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"leads"}}}},"deals":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"deals"}}}},"accounts":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"accounts"}}}},"contacts":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"contacts"}}}},"activities":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"activities"}}}},"tokens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tokens"}}}}}}}}}},{"_id":"6a46723e20611373d1fb180f","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"crm-followup-form","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const FIELDS = [\n  { key:'type', label:'Type', ph:'Type', type:'select', opts:['Call','Email','Meeting','Note','Task'] },\n  { key:'subject', label:'Subject', ph:'Short summary', type:'text' },\n  { key:'notes', label:'Notes', ph:'Details of the follow-up', type:'textarea' },\n  { key:'dueDate', label:'Due Date', ph:'', type:'date' }\n];\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;'); }\nexport default {\n  css: `\n    .cff{ box-sizing:border-box; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif; color:var(--fg); display:flex; flex-direction:column; gap:16px; }\n    .cff *{ box-sizing:border-box; }\n    .cff-item{ display:flex; flex-direction:column; gap:6px; }\n    .cff-label{ font-size:13px; font-weight:500; color:var(--fg); }\n    .cff-field{ width:100%; font-size:14px; font-family:inherit; color:var(--fg); background:var(--bg); border:1px solid var(--bd); border-radius:6px; padding:5px 11px; height:34px; outline:none; transition:border-color .2s,box-shadow .2s; }\n    .cff-field:focus{ border-color:var(--cp); box-shadow:0 0 0 2px var(--cpbg); }\n    textarea.cff-field{ height:80px; resize:vertical; }\n    .cff-ctx{ font-size:12px; color:var(--sec); }\n    .cff-actions{ display:flex; gap:10px; justify-content:flex-end; margin-top:4px; }\n    .cff-btn{ height:36px; padding:0 18px; font-size:14px; border-radius:6px; cursor:pointer; border:1px solid var(--bd); background:var(--bg); color:var(--fg); transition:all .2s; }\n    .cff-btn:hover{ border-color:var(--cp); color:var(--cp); }\n    .cff-btn.primary{ background:var(--cp); border-color:var(--cp); color:#fff; }\n    .cff-btn.primary:hover{ opacity:.9; color:#fff; }\n    .cff-err{ color:#ef4444; font-size:12px; min-height:14px; }\n  `,\n  render(d2){\n    const s = d2.store('crm-ui');\n    const dark = !!(s && s.get('darkMode'));\n    const accent = (s && s.get('accent')) || '#4f46e5';\n    const vars = [\n      '--fg:'+(dark?'rgba(255,255,255,0.85)':'rgba(0,0,0,0.88)'),\n      '--sec:'+(dark?'rgba(255,255,255,0.55)':'rgba(0,0,0,0.55)'),\n      '--bg:'+(dark?'#1f1f1f':'#ffffff'),\n      '--bd:'+(dark?'#424242':'#d9d9d9'),\n      '--cp:'+accent,\n      '--cpbg:'+(dark?'rgba(255,255,255,0.12)':'rgba(0,0,0,0.06)')\n    ].join(';');\n    const relType = (s ? s.get('followupType') : '') || '';\n    const relId = (s ? s.get('followupRelatedId') : '') || '';\n    let items = FIELDS.map(function(f){\n      const v = (s ? s.get('f_'+f.key) : '');\n      const val = v==null?'':String(v);\n      let control;\n      if(f.type==='textarea'){\n        control = '<textarea class=\"cff-field\" data-k=\"'+f.key+'\" placeholder=\"'+esc(f.ph)+'\">'+esc(val)+'</textarea>';\n      } else if(f.type==='select'){\n        let o = f.opts.map(function(op){ return '<option value=\"'+esc(op)+'\"'+(String(val)===String(op)?' selected':'')+'>'+esc(op)+'</option>'; }).join('');\n        control = '<select class=\"cff-field\" data-k=\"'+f.key+'\"><option value=\"\"'+(val===''?' selected':'')+'>Select…</option>'+o+'</select>';\n      } else if(f.type==='date'){\n        control = '<input class=\"cff-field\" type=\"date\" data-k=\"'+f.key+'\" value=\"'+esc(val)+'\">';\n      } else {\n        control = '<input class=\"cff-field\" type=\"text\" data-k=\"'+f.key+'\" placeholder=\"'+esc(f.ph)+'\" value=\"'+esc(val)+'\">';\n      }\n      return '<div class=\"cff-item\"><div class=\"cff-label\">'+esc(f.label)+'</div>'+control+'</div>';\n    }).join('');\n    const ctx = (relType||relId) ? '<div class=\"cff-ctx\">Logging against '+esc(relType||'record')+(relId?' · '+esc(relId):'')+'</div>' : '';\n    return '<div class=\"cff\" style=\"'+vars+'\">'+ctx+items+'<div class=\"cff-err\" data-role=\"err\"></div><div class=\"cff-actions\"><button class=\"cff-btn\" data-act=\"cancel\">Cancel</button><button class=\"cff-btn primary\" data-act=\"save\">Log Follow-up</button></div></div>';\n  },\n  mounted(d2){\n    const s = d2.store('crm-ui');\n    const sync = function(el){ const k=el.getAttribute('data-k'); if(k&&s) s.set('f_'+k, el.value); };\n    d2.on('.cff-field','input',function(e,el){ sync(el); });\n    d2.on('.cff-field','change',function(e,el){ sync(el); });\n    d2.on('[data-act=\"cancel\"]','click',function(){ if(s) s.set('followupOpen',false); });\n    d2.on('[data-act=\"save\"]','click',async function(e,el){\n      if(!s) return;\n      const errEl = d2.$('[data-role=\"err\"]');\n      const relId = s.get('followupRelatedId') || '';\n      const relType = s.get('followupType') || 'lead';\n      if(!relId){ if(errEl) errEl.textContent='No related record.'; return; }\n      const rec = {\n        type: s.get('f_type') || 'Call',\n        subject: s.get('f_subject') || '',\n        notes: s.get('f_notes') || '',\n        dueDate: (s.get('f_dueDate') || null) || null,\n        completed: false,\n        relatedType: relType,\n        relatedId: String(relId),\n        ownerId: s.get('followupOwnerId') || '6a45856852d425f2d2f2857a',\n        createdAt: new Date().toISOString()\n      };\n      if(!rec.subject){ if(errEl) errEl.textContent='Subject is required.'; return; }\n      const ds = d2.data('activities');\n      if(!ds){ if(errEl) errEl.textContent='Activities dataset unavailable.'; return; }\n      el.textContent = 'Saving…';\n      try{\n        await ds.create(rec);\n        if(typeof ds.refresh==='function') ds.refresh();\n        // clear draft + close\n        ['type','subject','notes','dueDate'].forEach(function(k){ s.set('f_'+k, ''); });\n        s.set('followupOpen', false);\n      }catch(err){ if(errEl) errEl.textContent = 'Save failed: '+(err&&err.message?err.message:err); el.textContent = 'Log Follow-up'; }\n    });\n  }\n};"}},"activities":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"activities"}}}},"mode":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"mode"}}}}}}}}}},{"_id":"6a6697089f8782fe4af28846","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"sec-example-card","package":"gabz-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  .card{font-family:ui-sans-serif,system-ui,-apple-system,\"Segoe UI\",Roboto,sans-serif;background:#0e1620;color:#e9eef2;border:1px solid #22303d;border-radius:14px;padding:22px;box-sizing:border-box;width:100%;max-width:940px;margin:0 auto}\n  .hd h2{margin:0 0 4px;font-size:19px;font-weight:680;color:#fff}\n  .why{margin:0 0 12px;color:#9fb2c2;font-size:13px;line-height:1.5}\n  .blink{display:inline-block;margin:0 0 14px;font-family:ui-monospace,monospace;font-size:11px;color:#7fd0c8;text-decoration:none;border:1px solid #1f5a54;padding:5px 9px;border-radius:6px}\n  .blink:hover{background:#0e2b28}\n  .blink2{float:right;font-family:ui-monospace,monospace;font-size:10px;color:#7fd0c8;text-decoration:none;border:1px solid #2c3b49;padding:1px 7px;border-radius:5px;text-transform:none;letter-spacing:0}\n  .blink2:hover{background:#0e2b28;color:#fff}\n  .row{margin:0 0 14px}\n  .lbl{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:#5c7180;margin:0 0 8px}\n  .lbl b{color:#e6b98a}\n  .ctrls{display:flex;flex-wrap:wrap;gap:8px}\n  .btn{font-family:inherit;font-size:13px;border:1px solid #2c3b49;background:#16212e;color:#cdd9e2;padding:8px 12px;border-radius:8px;cursor:pointer;transition:.12s}\n  .btn:hover{border-color:#3a4b5a;color:#fff}\n  .btn.on{border-color:#0f766e;color:#7fd0c8;background:#0e2b28}\n  .btn.danger{background:#3a1620;border-color:#7a2436;color:#f3b0b8;font-weight:600}\n  .btn.danger:hover{background:#511b28}\n  .btn.ok{background:#12281f;border-color:#2f7d4f;color:#9fe0b6;font-weight:600}\n  .btn.ok:hover{background:#173a2b}\n  .btn:disabled{opacity:.45;cursor:default}\n  .sess{margin-top:8px;font-family:ui-monospace,monospace;font-size:12px;color:#7fd0c8}\n  .run{display:flex;gap:10px}\n  .panes{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:14px 0}\n  .pane{background:#0b121a;border:1px solid #22303d;border-radius:10px;overflow:hidden}\n  .pane.bad{border-color:#5a2836}\n  .pane.good{border-color:#26543f}\n  .pt{font-family:ui-monospace,monospace;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:#6f8496;padding:8px 12px;border-bottom:1px solid #1a2530}\n  pre{margin:0;padding:12px;font-family:ui-monospace,Menlo,Consolas,monospace;font-size:11.5px;line-height:1.5;color:#cfe0d8;white-space:pre-wrap;word-break:break-word;max-height:300px;overflow:auto}\n  .pane.bad pre{color:#f2c9b8}\n  .code{color:#b8c6d0}\n  .cx{display:flex;gap:10px;padding:7px 10px;border:1px solid #1a2530;border-radius:8px;margin-top:6px;background:#0b121a}\n  .cxn{font-family:ui-monospace,monospace;font-size:12px;color:#7fd0c8;flex:none;min-width:190px}\n  .cxw{font-size:12px;color:#9fb2c2}\n  @media(max-width:680px){.panes{grid-template-columns:1fr}.cxn{min-width:0}}\n  `,\n  render(d2){\n    const s=d2.state, esc=(x)=>(x==null?'':String(x)).replace(/&/g,'&amp;').replace(/</g,'&lt;');\n    const targets=d2.param('targets',[])||[], users=d2.param('users',[])||[], constructs=d2.param('constructs',[])||[];\n    const key=d2.param('paramKey','owner');\n    const owner=s.owner!=null?s.owner:((targets[0]||{}).value||'');\n    const loginBtns=users.map(u=>`<button class=\"btn login\" data-email=\"${esc(u.email)}\" data-pass=\"${esc(u.password)}\" data-label=\"${esc(u.label)}\">Entrar: ${esc(u.label)}</button>`).join('');\n    const tgtBtns=targets.map(t=>`<button class=\"btn tgt ${t.value===owner?'on':''}\" data-val=\"${esc(t.value)}\">${esc(t.label)}</button>`).join('');\n    const cx=constructs.map(c=>`<div class=\"cx\"><span class=\"cxn\">${esc(c.name)}</span><span class=\"cxw\">${esc(c.what)}</span></div>`).join('');\n    return `<div class=\"card\">\n      <div class=\"hd\"><h2>${esc(d2.param('title','Exemplo'))}</h2><p class=\"why\">${esc(d2.param('why',''))}</p>${d2.param('builderLink')?`<a class=\"blink\" href=\"${esc(d2.param('builderLink'))}\" target=\"_blank\">abrir a implementacao no builder</a>`:''}</div>\n      <div class=\"row\"><div class=\"lbl\">1 · Sessao (login real via sec_auth)</div><div class=\"ctrls\">${loginBtns}</div><div class=\"sess\">${s.sessionLabel?('logado como '+esc(s.sessionLabel)):'(ninguem logado — entre pra ter sessao)'}</div></div>\n      <div class=\"row\"><div class=\"lbl\">${esc(d2.param('payloadLabel','2 · Payload do atacante'))} — ${esc(key)} = <b>${esc(owner)}</b></div><div class=\"ctrls\">${tgtBtns}</div></div>\n      <div class=\"row run\"><button class=\"btn danger\" data-run=\"ins\" ${s.busy?'disabled':''}>Rodar INSEGURO</button><button class=\"btn ok\" data-run=\"sec\" ${s.busy?'disabled':''}>Rodar SEGURO</button></div>\n      <div class=\"panes\">\n        <div class=\"pane bad\"><div class=\"pt\">Resultado inseguro (o que vazou)</div><pre>${esc(s.insecureOut||'— rode o ataque —')}</pre></div>\n        <div class=\"pane good\"><div class=\"pt\">Resultado seguro (bloqueado)</div><pre>${esc(s.secureOut||'— rode o ataque —')}</pre></div>\n      </div>\n      <div class=\"panes\">\n        <div class=\"pane\"><div class=\"pt\">Handler INSEGURO${d2.param('builderInsecure')?` <a class=\"blink2\" href=\"${esc(d2.param('builderInsecure'))}\" target=\"_blank\">abrir no builder</a>`:''}</div><pre class=\"code\">${esc(d2.param('insecureCode',''))}</pre></div>\n        <div class=\"pane\"><div class=\"pt\">Handler SEGURO${d2.param('builderSecure')?` <a class=\"blink2\" href=\"${esc(d2.param('builderSecure'))}\" target=\"_blank\">abrir no builder</a>`:''}</div><pre class=\"code\">${esc(d2.param('secureCode',''))}</pre></div>\n      </div>\n      <div class=\"row\"><div class=\"lbl\">Construtos usados no lado seguro</div>${cx}</div>\n    </div>`;\n  },\n  mounted(d2){\n    d2.on('.login','click',async(e,el)=>{\n      d2.state.sessionLabel='entrando...';\n      try{ await d2.auth(d2.param('authRef','sec-auth')).login({email:el.dataset.email,password:el.dataset.pass}); d2.state.sessionLabel=el.dataset.label; d2.state.identity=el.dataset.email; }\n      catch(err){ d2.state.sessionLabel='falha no login ('+((err&&err.message)||err)+')'; }\n    });\n    d2.on('.tgt','click',(e,el)=>{ d2.state.owner=el.dataset.val; });\n    d2.on('[data-run]','click',async(e,el)=>{\n      const which=el.dataset.run, ref=which==='ins'?d2.param('insecureRef'):d2.param('secureRef'), key=d2.param('paramKey','owner');\n      const targets=d2.param('targets',[])||[]; const owner=d2.state.owner!=null?d2.state.owner:((targets[0]||{}).value||'');\n      d2.state.busy=true;\n      const body={}; body[key]=owner; body.as=d2.state.identity;\n      try{ const res=await d2.rush(ref).invoke(body); const out=JSON.stringify(res,null,2); if(which==='ins')d2.state.insecureOut=out; else d2.state.secureOut=out; }\n      catch(err){ const m='ERRO: '+((err&&err.message)||err); if(which==='ins')d2.state.insecureOut=m; else d2.state.secureOut=m; }\n      finally{ d2.state.busy=false; }\n    });\n  }\n}"}},"title":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"title"}}}},"why":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"why"}}}},"authRef":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"authRef"}}}},"insecureRef":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"insecureRef"}}}},"secureRef":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"secureRef"}}}},"paramKey":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"paramKey"}}}},"payloadLabel":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"payloadLabel"}}}},"users":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"users"}}}},"targets":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"targets"}}}},"constructs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"constructs"}}}},"insecureCode":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"insecureCode"}}}},"secureCode":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"secureCode"}}}},"builderLink":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"builderLink"}}}},"builderInsecure":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"builderInsecure"}}}},"builderSecure":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"builderSecure"}}}}}}}}}},{"_id":"6a66b2240613f70fa450c320","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"sec-tabs","package":"gabz-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: `.tabs{display:flex;gap:10px;font-family:ui-sans-serif,system-ui,-apple-system,\"Segoe UI\",sans-serif;padding:16px 20px;background:#080d13}\n  .tab{font-size:14px;color:#9fb2c2;text-decoration:none;padding:9px 16px;border:1px solid #22303d;border-radius:9px;background:#0e1620}\n  .tab:hover{color:#fff;border-color:#3a4b5a}\n  .tab.on{color:#7fd0c8;border-color:#0f766e;background:#0e2b28;font-weight:600}`,\n  render(d2){\n    const a=d2.param('active','vetores'), esc=(x)=>(x==null?'':String(x)).replace(/</g,'&lt;');\n    return `<div class=\"tabs\">\n      <a class=\"tab ${a==='vetores'?'on':''}\" href=\"${esc(d2.param('vetoresUrl','#'))}\">Vetores (inseguro vs seguro)</a>\n      <a class=\"tab ${a==='guia'?'on':''}\" href=\"${esc(d2.param('guiaUrl','#'))}\">Guia de dev seguro Data2</a>\n    </div>`;\n  }\n}"}},"active":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"active"}}}},"vetoresUrl":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"vetoresUrl"}}}},"guiaUrl":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"guiaUrl"}}}}}}}}}},{"_id":"6a66b225b768b226f05b14b0","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"sec-guide","package":"gabz-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  .g{font-family:ui-sans-serif,system-ui,-apple-system,\"Segoe UI\",Roboto,sans-serif;background:#0e1620;color:#e9eef2;border:1px solid #22303d;border-radius:14px;padding:28px;box-sizing:border-box;width:100%;max-width:860px;margin:0 auto}\n  .g h1{margin:0 0 6px;font-size:24px;color:#fff;letter-spacing:-.01em}\n  .g .sub{color:#9fb2c2;font-size:14.5px;margin:0 0 4px;line-height:1.6}\n  .gold{border:1px solid #2f5c54;background:#0e2622;border-radius:12px;padding:14px 16px;margin:18px 0 24px;color:#cfeee6;font-size:14px;line-height:1.6}\n  .gold b{color:#8ce0d2}\n  .sec{border:1px solid #22303d;border-radius:12px;padding:18px 20px;margin:14px 0;background:#0b121a}\n  .sec.warn{border-color:#5a2836;background:#160d11}\n  .cam{font-size:12px;letter-spacing:.02em;color:#8aa0b2;margin:0 0 4px}\n  .sec h3{margin:0 0 10px;font-size:17px;color:#fff;font-weight:640;letter-spacing:-.01em}\n  .rule{margin:0 0 12px;font-size:14.5px;line-height:1.55;color:#8ce0d2;font-weight:600;border-left:3px solid #0f766e;padding-left:11px}\n  .sec p{margin:8px 0;font-size:13.5px;line-height:1.65;color:#c2d0da}\n  .sec b{color:#e6b98a;font-weight:600}\n  .sec code{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12px;background:#111c26;padding:2px 6px;border-radius:5px;color:#cfe0d8}\n  .lab{font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;color:#5c7180;margin:12px 0 5px;font-weight:600}\n  .sec ul{margin:5px 0;padding-left:4px;list-style:none}\n  .sec li{font-size:13.5px;line-height:1.6;color:#c2d0da;margin:6px 0;padding-left:20px;position:relative}\n  .sec li:before{content:\"→\";position:absolute;left:0;color:#4a8f85}\n  .how{background:#0a1017;border:1px solid #1a2530;border-radius:9px;padding:11px 13px;margin-top:12px;font-family:ui-monospace,Menlo,Consolas,monospace;font-size:11.5px;color:#9fe0b6;white-space:pre-wrap;line-height:1.55}\n  `,\n  render(){\n    return `<div class=\"g\">\n      <h1>Guia de desenvolvimento seguro no Data2</h1>\n      <p class=\"sub\">Um mapa das ferramentas da plataforma: o que cada uma resolve, as opcoes, e como usar. Cada camada abre com a regra que importa. Par pratico: o lab de vetores na aba ao lado.</p>\n      <div class=\"gold\"><b>A regra de ouro:</b> no Data2 quase tudo <b>nasce aberto</b> (<code>policies</code> vazio = liberado). Seguranca aqui e sobre <b>fechar cada porta</b> e <b>validar o dado que passa</b>. Pensa em duas perguntas: <b>quem</b> pode entrar (policy) e <b>de quem</b> e a forma do dado (sessao + schema).<br><br><b style=\"color:#f3b0b8\">Historico que importa:</b> nem todo construto sempre pode ter policy — o suporte foi vindo aos poucos. Por isso muita coisa esta <u>aberta por heranca</u> (grandfathering, nao por escolha), e alguns (inbound: Email/Phone/WhatsApp) <u>ainda nao dao pra gatear</u>. Consequencia: <b>\"existe\" != \"protegido\"</b> — cheque construto por construto (e por isso o security_scan existe).</div>\n\n      <div class=\"sec\"><div class=\"cam\">🔒 Camada 1</div><h3>Autorizacao — Policy, RushPolicy, InvokedByBuilder</h3>\n      <p class=\"rule\">A regra: toda porta (endpoint, dataset, Drive, assistant, rota) nasce aberta — feche cada uma explicitamente.</p>\n      <p>O gate de cada construto. Tres coisas que enganam todo mundo:</p>\n      <ul>\n        <li><b>Array e OU; dois construtos e E.</b> <code>[A,B]</code> = A ou B. Pra exigir os dois (ex.: logado E via rush), um na DataSet, outro na DataSource.</li>\n        <li><b>Vazio ABRE, nao fecha.</b> <code>policies:[]</code> reabre. Pra negar geral: <code>deny:true</code>.</li>\n        <li><b>O resto e fail-closed</b> — na duvida, nega.</li>\n      </ul>\n      <div class=\"lab\">Opcoes</div>\n      <ul>\n        <li><code>Policy(authenticationStrategy)</code> — exige sessao daquela strategy (+ <code>allowedRoles</code>/<code>blockedRoles</code>).</li>\n        <li><code>RushPolicy(systems,rushes)</code> — pra leitura server-side/scheduler sem sessao. Vazio = so o proprio sistema.</li>\n        <li><code>InvokedByBuilder</code> / <code>InvokedByRush</code> — resolvers dentro do <code>allow</code>, nao forjaveis.</li>\n      </ul>\n      <div class=\"lab\">Como usar</div>\n      <p>Derive por uso: tela → auth da rota; rush sem sessao → RushPolicy; sempre + <code>InvokedByBuilder</code>. O <b>verifier</b> da strategy fica sem policy. Inbound (Email/Phone/WhatsApp) nao e gateado — filtre no handler. Policy assenta em ~15s.</p>\n      <div class=\"how\">set_policies({target:'ordersDataSet', policies:[{authenticationStrategy:'appAuth'}]})\nset_policies({target:'orders',        policies:[{rushes:{allow:[]}}]})   // logado E via rush</div></div>\n\n      <div class=\"sec\"><div class=\"cam\">👤 Camada 2</div><h3>Identidade & sessao</h3>\n      <p class=\"rule\">A regra: quem e o dono do dado vem da SESSAO, nunca do body. O body diz o QUE, nunca DE QUEM.</p>\n      <p>A sessao corrente vive em <code>@SessionsDataSet.cursor.current</code> (credentials/metadata) — e o que a plataforma le server-side.</p>\n      <div class=\"lab\">Opcoes</div>\n      <ul>\n        <li>Login local (email/senha) ou IdP/SSO (<code>loginIdentityProvider</code>).</li>\n        <li>Enriquecer a sessao: <code>session:</code> fields (do verifier) ou <code>sessionMetadata</code> (lookup no login).</li>\n        <li>Roles: <code>session.credentials[roleField]</code> — precisa de <code>roleField</code>. Uma strategy, muitos roles.</li>\n      </ul>\n      <div class=\"how\">me = @SessionsDataSet.cursor.current.credentials   // escopo daqui, nao do $body</div></div>\n\n      <div class=\"sec\"><div class=\"cam\">🧬 Camada 3</div><h3>Integridade — Schema / SchemaSet</h3>\n      <p class=\"rule\">A regra: valide a FORMA na entrada e mascare a saida — o \"Zod do Data2\".</p>\n      <p>A validacao do campo da tabela e piso raso; o Schema faz o resto (cross-field, sanitizacao, mascara).</p>\n      <div class=\"lab\">Opcoes</div>\n      <ul>\n        <li><code>validate</code>/<code>parse</code> com modes <code>strict</code>/<code>strip</code>/<code>coerce</code>/<code>partial</code>.</li>\n        <li><code>derive('omit'|'pick'|'partial')</code>, <code>SchemaSet.fromTable</code>.</li>\n        <li><code>customValidations</code> (regra que ve o record), <code>transform</code> (sanitiza), <code>mask()</code> (tira campo da saida).</li>\n      </ul>\n      <div class=\"lab\">Como usar</div>\n      <p>Request schema que <b>omite</b> campos de identidade/privilegio (strict/strip mata overposting); <code>mask()</code> no que sai.</p>\n      <div class=\"how\">@ReqSchema.validate($body,{mode:'strict'})   //  e  @Pub.mask(rec) na saida</div></div>\n\n      <div class=\"sec\"><div class=\"cam\">🧱 Camada 4</div><h3>Row-level — leitura escopada</h3>\n      <p class=\"rule\">A regra: policy libera o DATASET, nao a LINHA. Filtro do cliente nao e controle de acesso.</p>\n      <div class=\"lab\">Opcoes</div>\n      <ul>\n        <li>Ler via rush handler que filtra pela sessao.</li>\n        <li>Relacao <code>master</code> — o detail ja vem filtrado pela identidade.</li>\n      </ul>\n      <div class=\"how\">rows = filter(dados, r => r.owner == @SessionsDataSet.cursor.current.credentials.owner)</div></div>\n\n      <div class=\"sec\"><div class=\"cam\">🔑 Camada 5</div><h3>Segredos & SQL/integracoes</h3>\n      <p class=\"rule\">A regra: segredo so no KeyVault; SQL com bound params, nunca input cru concatenado.</p>\n      <p>Segredo literal no config vira plaintext no artefato publicado.</p>\n      <div class=\"lab\">Opcoes</div>\n      <ul>\n        <li><code>KeyVault</code> (cifrado; <code>getValue('KEY')</code> ou <code>~~vault/KEY~~</code>).</li>\n        <li>1 HttpClient/sistema + 1 HttpRequest/operacao; a UI nunca chama API externa (so via rush).</li>\n        <li>Bound params ou allowlist de queries — <b>nunca</b> <code>template()</code> com input do request.</li>\n      </ul>\n      <p>⚠ KeyVault nao tem back-reference: apagar uma chave quebra callers em silencio — varra antes.</p>\n      <div class=\"how\">Authorization: Bearer {{ @Vault.getValue('DATABRICKS_TOKEN') }}</div></div>\n\n      <div class=\"sec\"><div class=\"cam\">📝 Camada 6</div><h3>Logs</h3>\n      <p class=\"rule\">A regra: log e dado — nao logue o corpo quando tem segredo/PII.</p>\n      <p><code>shouldLogRequestBody</code> defaulta pra <b>true</b>; muita tabela de log antiga esta sem policy (o scan rateia como high).</p>\n      <div class=\"lab\">Opcoes</div>\n      <ul>\n        <li><code>shouldLogRequestBody:false</code> + <code>omitHeaders:['authorization']</code>.</li>\n        <li>Policy append-only no log; revisar acesso e purga.</li>\n      </ul>\n      <div class=\"how\">create_rush_listener({ shouldLogRequestBody:false, omitHeaders:['authorization'] })</div></div>\n\n      <div class=\"sec\"><div class=\"cam\">🤖 Camada IA</div><h3>Prompt injection</h3>\n      <p class=\"rule\">A regra: o input do usuario e DADO, nunca instrucao.</p>\n      <p>Input colado no prompt vira comando e o modelo obedece. Assistant sem policy = LLM aberto (custo + injecao + acesso a dado via tools).</p>\n      <div class=\"lab\">Opcoes</div>\n      <ul>\n        <li>Delimitar o input como dado (<code>&lt;user_input&gt;</code>) + system prompt blindado.</li>\n        <li>Policy no assistant; escopar tools/dados a sessao; validar/mask a saida.</li>\n        <li>Nunca por segredo no contexto do modelo.</li>\n      </ul>\n      <div class=\"how\">prompt = sistema + '&lt;user_input&gt;' + $input + '&lt;/user_input&gt;'</div></div>\n\n      <div class=\"sec\"><div class=\"cam\">🔎 Verificacao</div><h3>security_scan (MCP) & Security Hub</h3>\n      <p class=\"rule\">A regra: rode o scan e trace ANTES de gatear (o que quebra?).</p>\n      <p>O relatorio de exposicao numa chamada. Responde 3 perguntas: como e alcancavel, o que protege agora, e o que quebra se eu gatear.</p>\n      <div class=\"lab\">Opcoes</div>\n      <ul>\n        <li>Index (default) com <code>kind</code>/<code>severity</code>/<code>limit</code>.</li>\n        <li><code>secrets:true</code> — sweep de credenciais literais.</li>\n        <li><code>target:&lt;ref&gt;</code> — cadeias de reachability + break-impact daquele recurso.</li>\n      </ul>\n      <div class=\"lab\">Como usar</div>\n      <p>scan → target (ver o que quebra) → <code>set_policies({dryRun:true})</code> → aplicar → re-checar (~15s). <b>Gatear o DADO, nao so a porta</b> — handler gateado na frente de dataset aberto deixa a tabela lível pelo SSP.</p>\n      <div class=\"how\">security_scan({severity:'high'})      security_scan({target:'meuDataset'})</div></div>\n\n      <div class=\"sec warn\"><div class=\"cam\">⚠️ Armadilhas que mordem</div><h3>evite estas</h3>\n      <ul>\n        <li><code>policies:[]</code> ABRE (nao fecha). Deny-all = <code>deny:true</code>.</li>\n        <li>Duas condicoes num array so = OU. Separe DataSet + DataSource pra E.</li>\n        <li>Gatear so o rush handler e deixar o DataSet aberto — lível direto pelo SSP.</li>\n        <li><code>allowedRoles</code> sem <code>roleField</code> na strategy: nunca casa.</li>\n        <li><code>PolicyReference</code> nao existe — 401a todo mundo. Use <code>data2-core-auth@Policy</code>/<code>@RushPolicy</code>.</li>\n      </ul></div>\n    </div>`;\n  }\n}"}}}}}}}},{"_id":"6a8451ba62e28978c053b900","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"brutalist-kanban-board","package":"gabz-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    * { box-sizing: border-box; margin: 0; padding: 0; font-family: system-ui, -apple-system, sans-serif; }\n    .kanban-root { display: flex; flex-direction: column; width: 100%; height: 100%; padding: 16px; background: #F0F0E8; gap: 16px; }\n    .kanban-header { display: flex; justify-content: space-between; align-items: center; background: #fff; border: 3px solid #000; box-shadow: 4px 4px 0px #000; padding: 12px 20px; }\n    .kanban-title { font-weight: 900; font-size: 20px; text-transform: uppercase; letter-spacing: 0.5px; display: flex; align-items: center; gap: 8px; }\n    .btn-action { background: #FFE600; border: 2px solid #000; box-shadow: 3px 3px 0px #000; font-weight: 800; font-size: 12px; padding: 8px 16px; cursor: pointer; text-transform: uppercase; transition: transform 0.05s; }\n    .btn-action:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0px #000; }\n    .columns-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; flex: 1; min-height: 0; }\n    .kanban-col { background: #FDFDFD; border: 3px solid #000; box-shadow: 5px 5px 0px #000; display: flex; flex-direction: column; overflow: hidden; }\n    .col-header { padding: 12px 16px; border-bottom: 3px solid #000; display: flex; justify-content: space-between; align-items: center; font-weight: 900; font-size: 14px; text-transform: uppercase; }\n    .col-header.todo { background: #FFE600; }\n    .col-header.in_progress { background: #00F0FF; }\n    .col-header.done { background: #00FF66; }\n    .col-badge { background: #000; color: #fff; padding: 2px 8px; font-size: 11px; font-weight: 800; border-radius: 0; }\n    .cards-list { flex: 1; padding: 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 14px; background: #F9F9F6; }\n    .task-card { background: #fff; border: 3px solid #000; box-shadow: 4px 4px 0px #000; padding: 14px; display: flex; flex-direction: column; gap: 8px; position: relative; }\n    .card-top { display: flex; justify-content: space-between; align-items: center; }\n    .priority-badge { font-size: 10px; font-weight: 900; padding: 2px 6px; border: 2px solid #000; text-transform: uppercase; }\n    .priority-URGENT, .priority-HIGH { background: #FFE600; }\n    .priority-MED { background: #00F0FF; }\n    .priority-LOW { background: #00FF66; }\n    .assignee-badge { background: #000; color: #fff; font-size: 10px; font-weight: 800; padding: 2px 6px; }\n    .card-title { font-weight: 900; font-size: 13px; text-transform: uppercase; color: #000; line-height: 1.3; }\n    .card-desc { font-size: 11px; font-weight: 600; color: #555; line-height: 1.4; }\n    .card-actions { display: flex; justify-content: space-between; align-items: center; margin-top: 6px; padding-top: 8px; border-top: 2px dashed #ddd; }\n    .btn-nav { background: #fff; border: 2px solid #000; box-shadow: 2px 2px 0px #000; font-weight: 800; font-size: 10px; padding: 4px 8px; cursor: pointer; text-transform: uppercase; }\n    .btn-nav:hover { background: #00F0FF; }\n    .btn-nav.btn-done:hover { background: #00FF66; }\n    .btn-del { background: #fff; border: 2px solid #000; box-shadow: 2px 2px 0px #000; font-weight: 900; font-size: 11px; padding: 2px 6px; cursor: pointer; color: #000; }\n    .btn-del:hover { background: #ff4757; color: #fff; }\n    .empty-state { border: 2px dashed #000; padding: 24px; text-align: center; font-size: 11px; font-weight: 800; color: #888; text-transform: uppercase; }\n  `,\n\n  render(d2) {\n    const ds = d2.data(\"dataset\");\n    let rawRecords = [];\n    if (ds && typeof ds.records === \"function\") {\n      rawRecords = ds.records() || [];\n    }\n    \n    const fallbackTasks = [\n      { _id: \"task_1\", title: \"REFACTOR CODE HOST ENGINE\", description: \"Streamline d2.render lifecycle and dynamic mounting\", status: \"todo\", priority: \"URGENT\", assignee: \"GABZ\" },\n      { _id: \"task_2\", title: \"OPTIMIZE REACTIVE STORE GETTERS\", description: \"Ensure two-way binding synchronization on modal inputs\", status: \"todo\", priority: \"HIGH\", assignee: \"ALEX\" },\n      { _id: \"task_3\", title: \"BRUTALIST CODE COMPONENT SUITE\", description: \"Implement draggable cards and column transitions in Code Component\", status: \"in_progress\", priority: \"HIGH\", assignee: \"SARAH\" },\n      { _id: \"task_4\", title: \"HARD SHADOWS & CSS VARIABLES\", description: \"Audit zero-blur 4px offset shadows across all render templates\", status: \"in_progress\", priority: \"MED\", assignee: \"ELENA\" },\n      { _id: \"task_5\", title: \"MONOREPO INIT & TYPESCRIPT SCHEMAS\", description: \"Export strong TypeScript types for code component props and events\", status: \"done\", priority: \"LOW\", assignee: \"VICTOR\" }\n    ];\n\n    const tasks = rawRecords.length > 0 ? rawRecords : (d2.state.localTasks || fallbackTasks);\n    if (!d2.state.localTasks && rawRecords.length === 0) {\n      d2.state.localTasks = fallbackTasks;\n    }\n\n    const cols = [\n      { id: \"todo\", title: \"// 01. A FAZER\", badge: \"TODO\", class: \"todo\" },\n      { id: \"in_progress\", title: \"// 02. EM PROGRESSO\", badge: \"DOING\", class: \"in_progress\" },\n      { id: \"done\", title: \"// 03. CONCLUÍDO\", badge: \"DONE\", class: \"done\" }\n    ];\n\n    return `\n      <div class=\"kanban-root\">\n        <div class=\"kanban-header\">\n          <div class=\"kanban-title\">⚡ BRUTALIST CODE KANBAN</div>\n          <button class=\"btn-action\" data-action=\"new-task\">+ NEW TASK</button>\n        </div>\n        <div class=\"columns-grid\">\n          ${cols.map(col => {\n            const colTasks = tasks.filter(t => (t.status || \"todo\") === col.id);\n            return `\n              <div class=\"kanban-col\">\n                <div class=\"col-header ${col.class}\">\n                  <span>${col.title}</span>\n                  <span class=\"col-badge\">${colTasks.length} ${col.badge}</span>\n                </div>\n                <div class=\"cards-list\">\n                  ${colTasks.length === 0 ? `<div class=\"empty-state\">// NO ACTIVE TASKS</div>` : colTasks.map(t => `\n                    <div class=\"task-card\" data-key=\"${t._id}\" data-id=\"${t._id}\">\n                      <div class=\"card-top\">\n                        <span class=\"priority-badge priority-${t.priority || \"HIGH\"}\">${t.priority || \"HIGH\"}</span>\n                        <span class=\"assignee-badge\">👤 ${t.assignee || \"UNASSIGNED\"}</span>\n                      </div>\n                      <div class=\"card-title\">${t.title}</div>\n                      <div class=\"card-desc\">${t.description || \"\"}</div>\n                      <div class=\"card-actions\">\n                        <button class=\"btn-del\" data-action=\"delete\" data-id=\"${t._id}\">✕</button>\n                        <div style=\"display:flex; gap:6px;\">\n                          ${col.id !== \"todo\" ? `<button class=\"btn-nav\" data-action=\"move-prev\" data-id=\"${t._id}\" data-from=\"${col.id}\">◀ PREV</button>` : \"\"}\n                          ${col.id !== \"done\" ? `<button class=\"btn-nav ${col.id === \"in_progress\" ? \"btn-done\" : \"\"}\" data-action=\"move-next\" data-id=\"${t._id}\" data-from=\"${col.id}\">NEXT ▶</button>` : \"\"}\n                        </div>\n                      </div>\n                    </div>\n                  `).join(\"\")}\n                </div>\n              </div>\n            `;\n          }).join(\"\")}\n        </div>\n      </div>\n    `;\n  },\n\n  mounted(d2) {\n    d2.on(\"[data-action=move-next]\", \"click\", (e, el) => {\n      const id = el.dataset.id;\n      const from = el.dataset.from;\n      const nextStatus = from === \"todo\" ? \"in_progress\" : \"done\";\n      \n      const ds = d2.data(\"dataset\");\n      if (ds && typeof ds.update === \"function\" && ds.records().some(r => r._id === id)) {\n        ds.update({ _id: id, status: nextStatus });\n      } else if (d2.state.localTasks) {\n        d2.state.localTasks = d2.state.localTasks.map(t => t._id === id ? { ...t, status: nextStatus } : t);\n      }\n      d2.emit(\"onTaskMoved\", { id, status: nextStatus });\n    });\n\n    d2.on(\"[data-action=move-prev]\", \"click\", (e, el) => {\n      const id = el.dataset.id;\n      const from = el.dataset.from;\n      const prevStatus = from === \"done\" ? \"in_progress\" : \"todo\";\n      \n      const ds = d2.data(\"dataset\");\n      if (ds && typeof ds.update === \"function\" && ds.records().some(r => r._id === id)) {\n        ds.update({ _id: id, status: prevStatus });\n      } else if (d2.state.localTasks) {\n        d2.state.localTasks = d2.state.localTasks.map(t => t._id === id ? { ...t, status: prevStatus } : t);\n      }\n      d2.emit(\"onTaskMoved\", { id, status: prevStatus });\n    });\n\n    d2.on(\"[data-action=delete]\", \"click\", (e, el) => {\n      const id = el.dataset.id;\n      const ds = d2.data(\"dataset\");\n      if (ds && typeof ds.remove === \"function\" && ds.records().some(r => r._id === id)) {\n        ds.remove(id);\n      } else if (d2.state.localTasks) {\n        d2.state.localTasks = d2.state.localTasks.filter(t => t._id !== id);\n      }\n      d2.emit(\"onTaskDeleted\", { id });\n    });\n\n    d2.on(\"[data-action=new-task]\", \"click\", () => {\n      const store = d2.store(\"state\");\n      if (store && typeof store.set === \"function\") {\n        store.set(\"isModalOpen\", true);\n      }\n      d2.emit(\"onOpenNewTaskModal\", {});\n    });\n  }\n}"}},"dataset":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"dataset"}}}},"state":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"state"}}}}}}}}}},{"_id":"6a85c32cfbfb07f820908573","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"agent-chat-shell","package":"gabz-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    @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap');\n    \n    .chat-container {\n      box-sizing: border-box;\n      display: flex;\n      flex-direction: column;\n      height: 100%;\n      width: 100%;\n      background: #09090d;\n      color: #e4e4e7;\n      font-family: 'Inter', -apple-system, sans-serif;\n      overflow: hidden;\n    }\n\n    /* Topbar */\n    .chat-header {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      padding: 14px 24px;\n      background: #101015;\n      border-bottom: 1px solid #1f1f2a;\n    }\n    .header-left {\n      display: flex;\n      align-items: center;\n      gap: 12px;\n    }\n    .header-title {\n      font-weight: 600;\n      font-size: 15px;\n      color: #fff;\n      display: flex;\n      align-items: center;\n      gap: 8px;\n    }\n    .status-dot {\n      width: 8px;\n      height: 8px;\n      border-radius: 50%;\n      background: #10b981;\n      box-shadow: 0 0 10px rgba(16, 185, 129, 0.7);\n    }\n    .header-right {\n      display: flex;\n      align-items: center;\n      gap: 10px;\n    }\n    .profile-select {\n      background: #181820;\n      border: 1px solid #2e2e3e;\n      color: #cbd5e1;\n      padding: 6px 12px;\n      border-radius: 6px;\n      font-size: 12px;\n      outline: none;\n      font-family: inherit;\n    }\n\n    /* Message Area */\n    .chat-messages {\n      flex: 1;\n      overflow-y: auto;\n      padding: 24px;\n      display: flex;\n      flex-direction: column;\n      gap: 20px;\n      scroll-behavior: smooth;\n    }\n\n    .msg-user {\n      align-self: flex-end;\n      max-width: 75%;\n      background: #2563eb;\n      color: #fff;\n      padding: 12px 18px;\n      border-radius: 16px 16px 4px 16px;\n      font-size: 14px;\n      line-height: 1.5;\n      box-shadow: 0 4px 12px rgba(37, 99, 235, 0.2);\n      word-break: break-word;\n    }\n\n    .msg-agent {\n      align-self: flex-start;\n      max-width: 88%;\n      background: #121217;\n      border: 1px solid #232330;\n      border-radius: 16px 16px 16px 4px;\n      padding: 18px;\n      display: flex;\n      flex-direction: column;\n      gap: 14px;\n      font-size: 14px;\n      line-height: 1.6;\n      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);\n      word-break: break-word;\n    }\n\n    /* Markdown Styling Inside Agent Messages */\n    .md-content h1, .md-content h2, .md-content h3 {\n      color: #f4f4f5;\n      margin: 12px 0 6px 0;\n      font-weight: 600;\n    }\n    .md-content h1 { font-size: 18px; border-bottom: 1px solid #262636; padding-bottom: 4px; }\n    .md-content h2 { font-size: 16px; }\n    .md-content h3 { font-size: 14px; }\n    .md-content p { margin: 6px 0; }\n    .md-content ul, .md-content ol {\n      margin: 6px 0 6px 20px;\n      padding: 0;\n    }\n    .md-content li { margin-bottom: 4px; }\n    .md-content strong { color: #fff; font-weight: 600; }\n    .md-content em { color: #93c5fd; font-style: italic; }\n    \n    .md-content code.inline-code {\n      background: #1c1c28;\n      border: 1px solid #2d2d3f;\n      color: #38bdf8;\n      padding: 2px 6px;\n      border-radius: 4px;\n      font-family: 'JetBrains Mono', monospace;\n      font-size: 12.5px;\n    }\n\n    .code-block-wrapper {\n      background: #08080c;\n      border: 1px solid #1f1f2e;\n      border-radius: 8px;\n      margin: 10px 0;\n      overflow: hidden;\n    }\n    .code-block-header {\n      background: #101016;\n      border-bottom: 1px solid #1f1f2e;\n      padding: 6px 12px;\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      font-family: 'JetBrains Mono', monospace;\n      font-size: 11px;\n      color: #71717a;\n    }\n    .code-block-pre {\n      margin: 0;\n      padding: 12px;\n      overflow-x: auto;\n      font-family: 'JetBrains Mono', monospace;\n      font-size: 12.5px;\n      line-height: 1.5;\n      color: #e4e4e7;\n    }\n\n    /* Tables in Markdown */\n    .md-table {\n      width: 100%;\n      border-collapse: collapse;\n      margin: 12px 0;\n      font-size: 13px;\n    }\n    .md-table th, .md-table td {\n      border: 1px solid #262638;\n      padding: 8px 12px;\n      text-align: left;\n    }\n    .md-table th {\n      background: #181824;\n      color: #f4f4f5;\n      font-weight: 600;\n    }\n    .md-table tr:nth-child(even) {\n      background: #0e0e14;\n    }\n\n    /* Accordion de Raciocínio (Traces) */\n    .trace-box {\n      background: #09090d;\n      border: 1px solid #1c1c26;\n      border-radius: 8px;\n      padding: 10px 14px;\n      font-family: 'JetBrains Mono', monospace;\n      font-size: 12px;\n    }\n    .trace-header {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      cursor: pointer;\n      color: #a1a1aa;\n      user-select: none;\n    }\n    .trace-header:hover {\n      color: #e4e4e7;\n    }\n    .trace-content {\n      margin-top: 10px;\n      display: flex;\n      flex-direction: column;\n      gap: 6px;\n      border-top: 1px solid #1c1c26;\n      padding-top: 8px;\n    }\n    .trace-item {\n      display: flex;\n      align-items: center;\n      gap: 8px;\n      color: #38bdf8;\n    }\n\n    /* Visual DAG Flowchart Container */\n    .dag-container {\n      background: #0e0e14;\n      border: 1px solid #252533;\n      border-radius: 12px;\n      padding: 16px;\n      display: flex;\n      flex-direction: column;\n      gap: 12px;\n    }\n    .dag-header {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      border-bottom: 1px solid #1c1c28;\n      padding-bottom: 10px;\n    }\n    .dag-title {\n      font-weight: 600;\n      font-size: 14px;\n      color: #f4f4f5;\n      display: flex;\n      align-items: center;\n      gap: 8px;\n    }\n    .dag-nodes-flow {\n      display: flex;\n      flex-direction: column;\n      gap: 8px;\n      margin: 8px 0;\n    }\n    .dag-node {\n      display: flex;\n      align-items: center;\n      background: #15151e;\n      border: 1px solid #282838;\n      border-radius: 8px;\n      padding: 10px 14px;\n      gap: 12px;\n      transition: all 0.2s;\n    }\n    .dag-node:hover {\n      border-color: #3b82f6;\n    }\n    .dag-node.active {\n      border-color: #3b82f6;\n      background: #181d2d;\n      box-shadow: 0 0 12px rgba(59, 130, 246, 0.2);\n    }\n    .dag-node.done {\n      border-color: #10b981;\n      background: #11221b;\n    }\n    .node-status-icon {\n      font-size: 14px;\n    }\n    .node-info {\n      flex: 1;\n    }\n    .node-title {\n      font-weight: 600;\n      font-size: 13px;\n      color: #f4f4f5;\n    }\n    .node-desc {\n      font-size: 12px;\n      color: #a1a1aa;\n      margin-top: 2px;\n    }\n    .dag-connector {\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      color: #4b5563;\n      font-size: 12px;\n      margin: -4px 0;\n    }\n\n    /* Badges de Workers */\n    .tag-worker {\n      padding: 3px 8px;\n      border-radius: 5px;\n      font-size: 11px;\n      font-weight: 600;\n      text-transform: uppercase;\n      letter-spacing: 0.5px;\n    }\n    .tag-data { background: #1e3a8a; color: #93c5fd; }\n    .tag-logic { background: #581c87; color: #d8b4fe; }\n    .tag-ui { background: #064e3b; color: #6ee7b7; }\n\n    /* Budget & Actions */\n    .dag-footer {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      border-top: 1px solid #1c1c28;\n      padding-top: 12px;\n      margin-top: 6px;\n      flex-wrap: wrap;\n      gap: 10px;\n    }\n    .budget-pill {\n      font-size: 12px;\n      color: #10b981;\n      font-weight: 500;\n      display: flex;\n      align-items: center;\n      gap: 6px;\n    }\n    .btn-group {\n      display: flex;\n      gap: 8px;\n    }\n    .btn-action {\n      padding: 8px 16px;\n      border-radius: 6px;\n      font-size: 13px;\n      font-weight: 500;\n      cursor: pointer;\n      border: none;\n      transition: all 0.2s;\n      display: flex;\n      align-items: center;\n      gap: 6px;\n    }\n    .btn-approve { background: #10b981; color: #fff; }\n    .btn-approve:hover { background: #059669; }\n    .btn-request { background: #22222c; color: #e4e4e7; border: 1px solid #353545; }\n    .btn-request:hover { background: #2d2d3b; }\n    .btn-publish { background: #6366f1; color: #fff; }\n    .btn-publish:hover { background: #4f46e5; }\n\n    /* Suggestions / Chips */\n    .suggestions-box {\n      display: flex;\n      flex-wrap: wrap;\n      gap: 6px;\n      margin-top: 8px;\n    }\n    .sug-chip {\n      background: #181822;\n      border: 1px solid #2c2c3d;\n      border-radius: 14px;\n      padding: 5px 14px;\n      font-size: 12.5px;\n      color: #93c5fd;\n      cursor: pointer;\n      transition: all 0.2s;\n      user-select: none;\n    }\n    .sug-chip:hover {\n      background: #2563eb;\n      color: #fff;\n      border-color: #3b82f6;\n      transform: translateY(-1px);\n    }\n\n    /* Footer Input */\n    .chat-footer {\n      padding: 16px 24px;\n      background: #101015;\n      border-top: 1px solid #1f1f2a;\n      display: flex;\n      flex-direction: column;\n      gap: 10px;\n    }\n    .input-row {\n      display: flex;\n      gap: 10px;\n      align-items: center;\n    }\n    .chat-input {\n      flex: 1;\n      background: #16161f;\n      border: 1px solid #2a2a3a;\n      border-radius: 10px;\n      padding: 12px 16px;\n      color: #fff;\n      font-size: 14px;\n      outline: none;\n      font-family: inherit;\n      transition: border-color 0.2s;\n    }\n    .chat-input:focus {\n      border-color: #3b82f6;\n    }\n    .btn-send {\n      background: #2563eb;\n      color: #fff;\n      border: none;\n      border-radius: 10px;\n      width: 44px;\n      height: 44px;\n      cursor: pointer;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      font-size: 16px;\n      transition: background 0.2s;\n    }\n    .btn-send:hover {\n      background: #1d4ed8;\n    }\n  `,\n\n  render(d2) {\n    const p = d2.params || {}\n    const systemSlug = p.systemSlug || 'gabz-playground'\n    const agentEndpoint = p.agentEndpoint || 'https://data2-gcp-agent-f354azrtjq-uc.a.run.app'\n\n    return `\n      <div class=\"chat-container\" data-system=\"${systemSlug}\" data-endpoint=\"${agentEndpoint}\">\n        <!-- Topbar -->\n        <div class=\"chat-header\">\n          <div class=\"header-left\">\n            <span class=\"status-dot\"></span>\n            <div class=\"header-title\">Data2 Autonomous Agent <span>(Gemini 3.7 Flash)</span></div>\n          </div>\n          <div class=\"header-right\">\n            <select class=\"profile-select\" id=\"profile-select\">\n              <option value=\"data2-way\">The Data2 Way (Canônico)</option>\n              <option value=\"free-flow\">Free-Flow (Prototipagem)</option>\n              <option value=\"backend-first\">Backend-First (Rush & APIs)</option>\n              <option value=\"hardening\">Security Hardening (RBAC)</option>\n            </select>\n          </div>\n        </div>\n\n        <!-- Messages Area -->\n        <div class=\"chat-messages\" id=\"chat-messages\">\n          <div class=\"msg-agent\">\n            <div class=\"md-content\">\n              Olá! Sou o arquiteto autônomo do Data2 no GCP. Como posso ajudar no <b>${systemSlug}</b>?\n            </div>\n            <div class=\"suggestions-box\">\n              <div class=\"sug-chip\" data-prompt=\"Criar tela de Helpdesk com tabela de tickets e formulário\">Criar Helpdesk</div>\n              <div class=\"sug-chip\" data-prompt=\"Auditar a segurança e permissões de acesso das tabelas\">Auditar Segurança</div>\n              <div class=\"sug-chip\" data-prompt=\"Estimar custos mensais de infraestrutura do sistema\">Estimar Custos</div>\n              <div class=\"sug-chip\" data-prompt=\"Como funciona o binding de Repeater com DataSet no Data2?\">Como funciona Repeater?</div>\n            </div>\n          </div>\n        </div>\n\n        <!-- Footer / Input -->\n        <div class=\"chat-footer\">\n          <div class=\"input-row\">\n            <input type=\"text\" class=\"chat-input\" id=\"chat-input\" placeholder=\"Converse, tire dúvidas ou descreva o que deseja construir...\" />\n            <button class=\"btn-send\" id=\"btn-send\">▲</button>\n          </div>\n        </div>\n      </div>\n    `\n  },\n\n  mounted(d2) {\n    const root = d2.root || document\n    const messagesEl = root.querySelector('#chat-messages')\n    const inputEl = root.querySelector('#chat-input')\n    const sendBtn = root.querySelector('#btn-send')\n    const profileSelect = root.querySelector('#profile-select')\n    const container = root.querySelector('.chat-container')\n\n    const systemSlug = container?.getAttribute('data-system') || 'gabz-playground'\n    const agentEndpoint = container?.getAttribute('data-endpoint') || 'https://data2-gcp-agent-f354azrtjq-uc.a.run.app'\n\n    let currentRunId = null\n    let currentWorkflowStage = null\n    const conversationMessages = []\n    const sessionId = (function() {\n      try {\n        let sid = sessionStorage.getItem('d2_agent_session_id')\n        if (!sid) {\n          sid = 'sess_' + Math.random().toString(36).substring(2, 12)\n          sessionStorage.setItem('d2_agent_session_id', sid)\n        }\n        return sid\n      } catch {\n        return 'sess_' + Math.random().toString(36).substring(2, 12)\n      }\n    })()\n\n    function resolveUserToken() {\n      if (d2?.auth?.token) return d2.auth.token\n      if (d2?.token) return d2.token\n      if (d2?.user?.token) return d2.user.token\n      try {\n        const lsToken = localStorage.getItem('d2_token') || localStorage.getItem('token') || sessionStorage.getItem('token')\n        if (lsToken) return lsToken\n      } catch {}\n      try {\n        const m = document.cookie.match(/(?:^|;\\s*)(?:token|d2_token|auth_token)=([^;]+)/)\n        if (m) return decodeURIComponent(m[1])\n      } catch {}\n      return ''\n    }\n\n    // ── Parser Completo de Markdown para HTML Elegante ────────────────────────\n    function parseMarkdown(md) {\n      if (!md) return ''\n      let html = md\n\n      // 1. Code Blocks com Syntax Box\n      html = html.replace(/```([a-zA-Z0-9_-]*)\\n([\\s\\S]*?)```/g, function (match, lang, code) {\n        const cleanCode = code.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')\n        return `<div class=\"code-block-wrapper\"><div class=\"code-block-header\"><span>${lang || 'code'}</span></div><pre class=\"code-block-pre\"><code>${cleanCode}</code></pre></div>`\n      })\n\n      // 2. Inline Code\n      html = html.replace(/`([^`]+)`/g, '<code class=\"inline-code\">$1</code>')\n\n      // 3. Headings\n      html = html.replace(/^### (.*$)/gim, '<h3>$1</h3>')\n      html = html.replace(/^## (.*$)/gim, '<h2>$1</h2>')\n      html = html.replace(/^# (.*$)/gim, '<h1>$1</h1>')\n\n      // 4. Bold e Italic\n      html = html.replace(/\\*\\*([^*]+)\\*\\*/g, '<strong>$1</strong>')\n      html = html.replace(/\\*([^*]+)\\*/g, '<em>$1</em>')\n\n      // 5. Tables\n      html = html.replace(/\\n\\|(.+)\\|\\n\\|[-:| ]+\\|\\n((?:\\|.+\\|\\n?)+)/g, function (match, header, rows) {\n        const ths = header\n          .split('|')\n          .filter((c) => c.trim())\n          .map((c) => `<th>${c.trim()}</th>`)\n          .join('')\n        const trs = rows\n          .trim()\n          .split('\\n')\n          .map((r) => {\n            const tds = r\n              .split('|')\n              .filter((c) => c.trim())\n              .map((c) => `<td>${c.trim()}</td>`)\n              .join('')\n            return `<tr>${tds}</tr>`\n          })\n          .join('')\n        return `<table class=\"md-table\"><thead><tr>${ths}</tr></thead><tbody>${trs}</tbody></table>`\n      })\n\n      // 6. Lists\n      html = html.replace(/^\\s*-\\s+(.*$)/gim, '<li>$1</li>')\n      html = html.replace(/(<li>.*<\\/li>)/gims, '<ul>$1</ul>')\n\n      // 7. Line breaks\n      html = html.replace(/\\n\\n/g, '<p></p>')\n      html = html.replace(/\\n/g, '<br/>')\n\n      return `<div class=\"md-content\">${html}</div>`\n    }\n\n    function appendMessage(role, rawContent, isHtml = false) {\n      if (!messagesEl) return null\n      const msg = document.createElement('div')\n      msg.className = role === 'user' ? 'msg-user' : 'msg-agent'\n      msg.innerHTML = isHtml ? rawContent : parseMarkdown(rawContent)\n      messagesEl.appendChild(msg)\n      messagesEl.scrollTop = messagesEl.scrollHeight\n      return msg\n    }\n\n    async function streamWorkflow(payload) {\n      const agentMsg = appendMessage('agent', '<div class=\"agent-live-text\">Conectando ao agente no GCP...</div>', true)\n      if (!agentMsg) return\n\n      let traceBox = null\n      let traceContent = null\n\n      function addTrace(text, isError = false) {\n        if (!traceBox) {\n          traceBox = document.createElement('div')\n          traceBox.className = 'trace-box'\n          traceBox.innerHTML = '<div class=\"trace-header\"><span>💭 Raciocínio & Ferramentas</span><span>▼</span></div><div class=\"trace-content\"></div>'\n          agentMsg.insertBefore(traceBox, agentMsg.firstChild)\n          traceContent = traceBox.querySelector('.trace-content')\n\n          traceBox.querySelector('.trace-header')?.addEventListener('click', () => {\n            if (traceContent) {\n              traceContent.style.display = traceContent.style.display === 'none' ? 'flex' : 'none'\n            }\n          })\n        }\n        if (traceContent) {\n          const item = document.createElement('div')\n          item.className = 'trace-item'\n          item.style.color = isError ? '#ef4444' : '#38bdf8'\n          item.innerHTML = `<span>${isError ? '❌' : '⚙'}</span> <span>${text}</span>`\n          traceContent.appendChild(item)\n          messagesEl.scrollTop = messagesEl.scrollHeight\n        }\n      }\n\n      try {\n        const token = resolveUserToken()\n        const headers = {\n          'Content-Type': 'application/json',\n          'Accept': 'text/event-stream',\n          'x-data2-system-slug': systemSlug,\n        }\n        if (token) {\n          headers['x-data2-builder-key'] = token\n          headers['Authorization'] = `Bearer ${token}`\n        }\n        if (d2?.auth?.userId || d2?.user?._id) {\n          headers['x-data2-user-id'] = String(d2.auth?.userId || d2.user._id)\n        }\n\n        const requestPayload = {\n          sessionId,\n          messages: conversationMessages,\n          ...payload,\n        }\n\n        const response = await fetch(`${agentEndpoint}/workflow/stream`, {\n          method: 'POST',\n          headers,\n          body: JSON.stringify(requestPayload),\n        })\n\n        if (!response.body) throw new Error('Stream indisponível')\n        const reader = response.body.getReader()\n        const decoder = new TextDecoder('utf-8')\n        let buffer = ''\n\n        while (true) {\n          const { done, value } = await reader.read()\n          if (done) break\n\n          buffer += decoder.decode(value, { stream: true })\n          const lines = buffer.split('\\n\\n')\n          buffer = lines.pop() || ''\n\n          for (const block of lines) {\n            const eventMatch = block.match(/event:\\s*(\\w+)/)\n            const dataMatch = block.match(/data:\\s*(.+)/s)\n            if (!eventMatch || !dataMatch) continue\n\n            const eventType = eventMatch[1]\n            let eventData = {}\n            try {\n              eventData = JSON.parse(dataMatch[1])\n            } catch {}\n\n            if (eventType === 'init') {\n              currentRunId = eventData.runId\n            } else if (eventType === 'thought') {\n              addTrace(eventData.text)\n            } else if (eventType === 'chat_response') {\n              currentWorkflowStage = 'chat'\n              if (eventData.message) {\n                conversationMessages.push({ role: 'assistant', content: eventData.message })\n              }\n              const renderedMd = parseMarkdown(eventData.message)\n              const sugHtml = (eventData.suggestions || [])\n                .map((s) => `<div class=\"sug-chip\" data-prompt=\"${s}\">${s}</div>`)\n                .join('')\n\n              const chatHtml = `\n                ${renderedMd}\n                ${sugHtml ? `<div class=\"suggestions-box\">${sugHtml}</div>` : ''}\n              `\n              const liveText = agentMsg.querySelector('.agent-live-text')\n              if (liveText) liveText.innerHTML = chatHtml\n            } else if (eventType === 'step_start') {\n              addTrace(`▶ [${eventData.worker}] ${eventData.title || eventData.description}`)\n              const nodeEl = agentMsg.querySelector(`#node-${eventData.stepId}`)\n              if (nodeEl) {\n                nodeEl.className = 'dag-node active'\n                nodeEl.querySelector('.node-status-icon').innerHTML = '⚙️'\n              }\n            } else if (eventType === 'step_finish') {\n              if (eventData.success === false) {\n                addTrace(`❌ [${eventData.worker}] Falha: ${eventData.summary}`, true)\n                const nodeEl = agentMsg.querySelector(`#node-${eventData.stepId}`)\n                if (nodeEl) {\n                  nodeEl.className = 'dag-node failed'\n                  nodeEl.style.borderColor = '#ef4444'\n                  nodeEl.querySelector('.node-status-icon').innerHTML = '❌'\n                }\n              } else {\n                addTrace(`✓ [${eventData.worker}] ${eventData.summary || 'Concluído'}`)\n                const nodeEl = agentMsg.querySelector(`#node-${eventData.stepId}`)\n                if (nodeEl) {\n                  nodeEl.className = 'dag-node done'\n                  nodeEl.querySelector('.node-status-icon').innerHTML = '✅'\n                }\n              }\n            } else if (eventType === 'plan_proposed') {\n              currentWorkflowStage = 'plan_approval'\n              if (eventData.runId) currentRunId = eventData.runId\n              conversationMessages.push({ role: 'assistant', content: `Plano Proposto com ${eventData.plan?.length || 0} etapas.` })\n\n              // Renderiza o Visual DAG Flowchart interativo\n              const steps = eventData.plan || []\n              const nodesHtml = steps\n                .map((s, idx) => `\n                  <div class=\"dag-node\" id=\"node-${s.id}\">\n                    <span class=\"node-status-icon\">⏳</span>\n                    <div class=\"node-info\">\n                      <div class=\"node-title\">${s.title || s.id}</div>\n                      <div class=\"node-desc\">${s.description}</div>\n                    </div>\n                    <span class=\"tag-worker tag-${s.worker}\">${s.worker}</span>\n                  </div>\n                  ${idx < steps.length - 1 ? '<div class=\"dag-connector\">▼</div>' : ''}\n                `)\n                .join('')\n\n              const dagHtml = `\n                <div class=\"dag-container\">\n                  <div class=\"dag-header\">\n                    <div class=\"dag-title\"><span>📊</span> Grafo de Arquitetura (DAG) Proposto</div>\n                  </div>\n                  <div class=\"dag-nodes-flow\">\n                    ${nodesHtml}\n                  </div>\n                  <div class=\"dag-footer\">\n                    <div class=\"budget-pill\">💰 ${eventData.tokenCostEstimate?.summary || ''}</div>\n                    <div class=\"btn-group\">\n                      <button class=\"btn-action btn-approve\" data-run=\"${currentRunId}\">✅ Aprovar e Executar DAG</button>\n                      <button class=\"btn-action btn-request\" data-run=\"${currentRunId}\">✏️ Ajustar Escopo</button>\n                    </div>\n                  </div>\n                </div>\n              `\n              const liveText = agentMsg.querySelector('.agent-live-text')\n              if (liveText) liveText.innerHTML = dagHtml\n            } else if (eventType === 'preview_ready') {\n              currentWorkflowStage = 'review_preview'\n              conversationMessages.push({ role: 'assistant', content: 'Artefatos gerados em estágio (draft).' })\n              const previewHtml = `\n                <div class=\"dag-container\">\n                  <div class=\"dag-header\">\n                    <div class=\"dag-title\"><span>✨</span> Artefatos Construídos em Estágio (Draft)</div>\n                  </div>\n                  <div>As tabelas, endpoints Rush e telas foram geradas no <b>${systemSlug}</b> e estão prontas para revisão.</div>\n                  <div class=\"dag-footer\">\n                    <div></div>\n                    <div class=\"btn-group\">\n                      <button class=\"btn-action btn-publish\" data-run=\"${currentRunId}\">🚀 Publicar em Produção</button>\n                      <button class=\"btn-action btn-request\" data-run=\"${currentRunId}\">✏️ Ajustar Detalhes</button>\n                    </div>\n                  </div>\n                </div>\n              `\n              const liveText = agentMsg.querySelector('.agent-live-text')\n              if (liveText) liveText.innerHTML = previewHtml\n            } else if (eventType === 'published') {\n              currentWorkflowStage = 'published'\n              addTrace('Sistema publicado com sucesso em produção!')\n            }\n          }\n        }\n      } catch (err) {\n        addTrace(`Erro no streaming: ${err.message}`, true)\n      }\n    }\n\n    function handleSend() {\n      const text = inputEl?.value?.trim()\n      if (!text) return\n      inputEl.value = ''\n\n      appendMessage('user', text)\n      conversationMessages.push({ role: 'user', content: text })\n      const profile = profileSelect?.value || 'data2-way'\n\n      if (currentRunId && (currentWorkflowStage === 'plan_approval' || currentWorkflowStage === 'review_preview')) {\n        streamWorkflow({\n          sessionId,\n          runId: currentRunId,\n          action: 'request_changes',\n          feedback: text,\n          goal: text,\n          systemSlug,\n          profile,\n        })\n      } else {\n        streamWorkflow({\n          sessionId,\n          systemSlug,\n          goal: text,\n          profile,\n        })\n      }\n    }\n\n    if (sendBtn) d2.on('#btn-send', 'click', handleSend)\n    if (inputEl) {\n      d2.on('#chat-input', 'keydown', (e) => {\n        if (e.key === 'Enter') handleSend()\n      })\n    }\n\n    // ── Delegação Global de Eventos de Clique (Chips & Botões Dinâmicos) ────────\n    d2.on('.chat-container', 'click', (e) => {\n      const target = e.target\n\n      // 1. Clique em Sugestão / Chip\n      const chip = target.closest('.sug-chip')\n      if (chip) {\n        const prompt = chip.getAttribute('data-prompt') || chip.innerText.trim()\n        if (prompt && inputEl) {\n          inputEl.value = prompt\n          handleSend()\n        }\n        return\n      }\n\n      // 2. Clique em Aprovar DAG\n      const btnApprove = target.closest('.btn-approve')\n      if (btnApprove) {\n        const runId = btnApprove.getAttribute('data-run') || currentRunId\n        if (runId) {\n          appendMessage('user', '✅ Plano Aprovado. Pode executar o DAG.')\n          conversationMessages.push({ role: 'user', content: '✅ Plano Aprovado. Pode executar o DAG.' })\n          streamWorkflow({\n            sessionId,\n            runId,\n            action: 'approve',\n          })\n        }\n        return\n      }\n\n      // 3. Clique em Publicar em Produção\n      const btnPublish = target.closest('.btn-publish')\n      if (btnPublish) {\n        const runId = btnPublish.getAttribute('data-run') || currentRunId\n        if (runId) {\n          appendMessage('user', '🚀 Aprovado para Produção. Pode publicar.')\n          conversationMessages.push({ role: 'user', content: '🚀 Aprovado para Produção. Pode publicar.' })\n          streamWorkflow({\n            sessionId,\n            runId,\n            action: 'publish',\n          })\n        }\n        return\n      }\n\n      // 4. Clique em Pedir Ajustes\n      const btnRequest = target.closest('.btn-request')\n      if (btnRequest) {\n        const runId = btnRequest.getAttribute('data-run') || currentRunId\n        if (runId) currentRunId = runId\n        if (inputEl) {\n          inputEl.placeholder = 'Descreva o ajuste que deseja fazer no plano ou no código...'\n          inputEl.focus()\n        }\n        return\n      }\n    })\n  },\n}\n"}},"systemSlug":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"systemSlug"}}}},"agentEndpoint":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"agentEndpoint"}}}}}}}}}},{"_id":"6ace52a3f16ae5077d71bce3","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"pm-visao-geral","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const LIB = { url: 'https://gabz-playground.data2.media/file/dPZUG5PfHXNVs-sT1YERj', css: 'https://gabz-playground.data2.media/file/qChFGH9hteWjSZxe3rSAl' }\nconst carregando = (d2) => `<div class=\"root carregando\">${d2.lib.state(LIB) === 'error' ? `Não carregou a skin: ${d2.lib.error(LIB)}` : 'Carregando…'}</div>`\nlet ui, esc, id, ms, recs, eu, rel, quem, evid, estado, estadoPlano, linkCard, projetoAtual, travado\n\nfunction recarregar(d2) {\n  ui.carregar(d2, 'projetos').then(() => {\n    const projetoId = ui.projetoAtual(d2, ui.recs(d2.data('projetos')))\n    if (!projetoId) return\n    for (const k of ['cards', 'decisoes', 'planos']) ui.carregar(d2, k, { projetoId })\n    ui.carregar(d2, 'mensagens', { tipo: 'pergunta' })\n    ui.carregar(d2, 'saude')\n  })\n}\n\nexport default {\n  css: `\n    main { padding:24px; display:grid; gap:16px; max-width:1440px; }\n    .kpis { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:12px; }\n    .kpi { background:var(--p1); border:1px solid var(--line); border-radius:8px; padding:12px 16px; }\n    .kpi b { display:block; font-size:24px; font-weight:600; letter-spacing:-.015em; line-height:1.2; }\n    .kpi span { color:var(--tx2); font-size:11px; }\n    .grid2 { display:grid; grid-template-columns:minmax(0,3fr) minmax(0,2fr); gap:16px; align-items:start; }\n    .col { display:grid; gap:16px; }\n    .saude .row { grid-template-columns:auto 1fr; align-items:center; gap:10px; }\n    @media (max-width:900px) { .kpis { grid-template-columns:1fr; } .grid2 { grid-template-columns:1fr; } main { padding:16px; } }\n  `,\n\n  mounted(d2) {\n    d2.on('[data-abrir]', 'click', (e, el) => { d2.setState({ abrindo: el.dataset.abrir, erro: '' }) })\n    d2.on('[data-cancelar]', 'click', () => { d2.setState({ abrindo: '', erro: '' }) })\n\n    d2.on('[data-responder]', 'click', async (e, el) => {\n      const mensagemId = el.dataset.responder\n      const texto = (d2.$(`textarea[data-id=\"${mensagemId}\"]`)?.value || '').trim()\n      if (!texto) return d2.setState({ erro: 'Escreva a resposta antes de enviar.' })\n      d2.setState({ enviando: mensagemId, erro: '' })\n      try {\n        await ui.invocar(d2, 'responder', { mensagemId, atorId: eu(d2), texto, via: 'painel' })\n        d2.setState({ abrindo: '' })\n        ui.carregar(d2, 'mensagens', { tipo: 'pergunta' })\n      } catch (err) {\n        d2.setState({ erro: `Não respondeu: ${err.message}` })\n      } finally {\n        d2.setState({ enviando: '' })\n      }\n    })\n\n    d2.on('[data-aprovar]', 'click', async (e, el) => {\n      const planoId = el.dataset.aprovar\n      d2.setState({ enviando: planoId, erro: '' })\n      try {\n        await ui.invocar(d2, 'aprovarPlano', { planoId, usuarioId: eu(d2) })\n        recarregar(d2)\n      } catch (err) {\n        d2.setState({ erro: `Não aprovou: ${err.message}` })\n      } finally {\n        d2.setState({ enviando: '' })\n      }\n    })\n  },\n\n  // a lib chega depois do mounted; carga, seletores e polling começam no primeiro render com ela\n  updated(d2) {\n    if (!ui || d2.state.iniciado) return\n    d2.state.iniciado = true\n    ui.carregarUsuarios(d2)\n    ui.ligarTopo(d2, () => recarregar(d2))\n    ui.vigiar(d2, () => recarregar(d2))\n  },\n\n  render(d2) {\n    ui = d2.lib(LIB)\n    if (!ui) return carregando(d2)\n    ;({ esc, id, ms, recs, eu, rel, quem, evid, estado, estadoPlano, linkCard, projetoAtual, travado } = ui)\n    const projetos = recs(d2.data('projetos'))\n    const projetoId = projetoAtual(d2, projetos)\n    const usuarioId = eu(d2) || '-'\n    const doProjeto = (r) => !projetoId || id(r.projetoId) === projetoId\n\n    const cards = recs(d2.data('cards')).filter(doProjeto)\n    const decisoes = recs(d2.data('decisoes')).filter(doProjeto)\n      .slice().sort((a, b) => ms(b.createdAt) - ms(a.createdAt)).slice(0, 5)\n    const planos = recs(d2.data('planos')).filter(doProjeto)\n    const cardIds = new Set(cards.map(id))\n    const mensagens = recs(d2.data('mensagens')).filter((m) => m.anexadoA?.entidade === 'card' && cardIds.has(m.anexadoA?.id))\n\n    const nome = (uid) => ui.nome(d2, uid) || '—'\n    const card = (cid) => cards.find((c) => id(c) === cid)\n\n    const abertas = mensagens.filter((m) => m.tipo === 'pergunta' && !m.respondidaEm)\n      .sort((a, b) => (id(b.para) === usuarioId) - (id(a.para) === usuarioId) || ms(a.createdAt) - ms(b.createdAt))\n    const rascunhos = planos.filter((p) => p.estado === 'rascunho')\n    const andamento = cards.filter((c) => c.coluna === 'em_desenvolvimento' || c.coluna === 'review')\n\n    // ponytail: o snapshot do pm-saude-rodar é do system inteiro; filtrar por projeto quando houver mais de um\n    const snap = recs(d2.data('saude')).find((s) => s.chave === 'atual')\n    const parados = snap?.parados || []\n    const wipLimite = projetos.find((p) => id(p) === projetoId)?.wipLimite || 3\n    const estourados = (snap?.wip || []).filter((w) => w.n > wipLimite)\n    const semCard = snap?.planosSemCard || []\n    const semRevisor = (snap?.reviewSemRevisor || []).filter(doProjeto)\n\n    const ocupado = (k) => d2.state.enviando === k\n    const trava = travado(d2)\n\n    const pendencias = abertas.length ? abertas.map((m) => {\n      const c = card(m.anexadoA?.id)\n      const aberta = d2.state.abrindo === id(m)\n      return `<div class=\"row\" data-key=\"${esc(id(m))}\">\n        <div class=\"meta\">${quem(d2, m.autor, m)}${id(m.para) === usuarioId ? '<span class=\"chip voce\">Pra você</span>' : ''}\n          <span>${linkCard(m.anexadoA?.id, esc(c?.titulo || 'card'))}</span><span>· ${esc(rel(m.createdAt))}</span></div>\n        <div class=\"txt\">${esc(m.texto)}</div>${evid(m.evidencia)}\n        ${aberta ? `<textarea data-id=\"${esc(id(m))}\" placeholder=\"Resposta\"></textarea>\n          <div class=\"acoes\"><button data-cancelar>Cancelar</button>\n          <button class=\"pri\" data-responder=\"${esc(id(m))}\" ${ocupado(id(m)) ? 'disabled' : trava}>${ocupado(id(m)) ? 'Enviando…' : 'Enviar resposta'}</button></div>`\n        : `<div class=\"acoes\"><button data-abrir=\"${esc(id(m))}\" ${trava}>Responder</button></div>`}\n      </div>`\n    }).join('') : '<div class=\"vazio\">Nenhuma pergunta aberta.</div>'\n\n    const lista = (itens) => itens.length ? ': ' + itens.map((c) => linkCard(id(c._id), esc(c.titulo))).join(', ') : ''\n    const saude = !snap ? '<div class=\"vazio\">Sem snapshot ainda: o pm-saude-agenda roda a cada 15 min.</div>' : [\n      [parados.length ? estado(`${parados.length}`, 'warn') : estado('ok', 'ok'), `Tarefas paradas há mais de 5 dias${lista(parados)}`],\n      [estourados.length ? estado(`${estourados.length}`, 'bad') : estado('ok', 'ok'), `WIP acima de ${wipLimite} por pessoa${estourados.length ? ': ' + estourados.map((w) => `${esc(nome(w._id))} (${w.n})`).join(', ') : ''}`],\n      [semRevisor.length ? estado(`${semRevisor.length}`, 'warn') : estado('ok', 'ok'), `Review sem revisor há mais de 24 h${lista(semRevisor)}`],\n      [semCard.length ? estado(`${semCard.length}`, 'warn') : estado('ok', 'ok'), `Planos aprovados sem tarefa há 14 dias${semCard.length ? ': ' + semCard.map((p) => esc(p.titulo)).join(', ') : ''}`],\n    ].map(([chip, txt]) => `<div class=\"row\">${chip}<span>${txt}</span></div>`).join('')\n\n    const planosHtml = rascunhos.length ? rascunhos.map((p) => {\n      return `<div class=\"row\" data-key=\"${esc(id(p))}\">\n        <div class=\"meta\">${estadoPlano('rascunho')}<span>${esc(rel(p.createdAt))}</span></div>\n        <div class=\"tit\">${esc(p.titulo)}</div>\n        <div class=\"acoes\"><button class=\"pri\" data-aprovar=\"${esc(id(p))}\" ${ocupado(id(p)) ? 'disabled' : trava}>${ocupado(id(p)) ? 'Aprovando…' : 'Aprovar plano'}</button></div>\n      </div>`\n    }).join('') : '<div class=\"vazio\">Nenhum plano em rascunho.</div>'\n\n    const emAndamento = planos.filter((p) => ['aprovado', 'em_execucao', 'pronto_para_publicar', 'pronto_oculto'].includes(p.estado))\n    const ativosHtml = emAndamento.length ? emAndamento.map((p) => {\n      const c = ui.conclusaoPlano(p, cards)\n      const pend = (p.itensPendentes || []).length\n      return `<div class=\"row\" data-key=\"${esc(id(p))}\">\n        <div class=\"meta\">${estadoPlano(p.estado)}<span>${c.feitas} de ${c.total} feitas</span>${pend ? `<span>· ${pend} pendente${pend > 1 ? 's' : ''}</span>` : ''}</div>\n        <div class=\"tit\">${ui.linkAba('Planos', esc(p.titulo))}</div>\n        ${ui.progresso(c.feitas, c.total)}\n      </div>`\n    }).join('') : '<div class=\"vazio\">Nenhum plano em andamento.</div>'\n\n    const decisoesHtml = decisoes.length ? decisoes.map((d) => `<div class=\"row\" data-key=\"${esc(id(d))}\">\n        <div class=\"meta\"><span class=\"mono\">#${esc(d.numero)}</span>${estado(d.escopo, 'info')}${quem(d2, d.autor, d)}<span>· ${esc(rel(d.createdAt))}</span></div>\n        <div class=\"tit\">${esc(d.titulo)}</div>\n      </div>`).join('') : '<div class=\"vazio\">Nenhuma decisão registrada.</div>'\n\n    return `<div class=\"root\">\n      ${ui.topo(d2, 'Visão geral', projetos, projetoId)}\n      ${ui.banner(d2)}\n      <main>\n        ${d2.state.erro ? `<div class=\"erro\">${esc(d2.state.erro)}</div>` : ''}\n        <div class=\"kpis\">\n          <div class=\"kpi\"><b>${abertas.length}</b><span>Perguntas abertas</span></div>\n          <div class=\"kpi\"><b>${andamento.length}</b><span>Tarefas em dev ou review</span></div>\n          <div class=\"kpi\"><b>${rascunhos.length}</b><span>Planos em rascunho</span></div>\n        </div>\n        <div class=\"grid2\">\n          <div class=\"col\">\n            <section><header><h2>Pendências</h2><span class=\"n\">${abertas.length}</span></header>${pendencias}</section>\n            <section><header><h2>Planos em andamento</h2><span class=\"n\">${emAndamento.length}</span></header>${ativosHtml}</section>\n            <section><header><h2>Decisões recentes</h2></header>${decisoesHtml}</section>\n          </div>\n          <div class=\"col\">\n            <section class=\"saude\"><header><h2>Saúde do board</h2><span class=\"n\">${snap ? `atualizado ${esc(rel(snap.em))}` : ''}</span></header>${saude}</section>\n            <section><header><h2>Planos em rascunho</h2><span class=\"n\">${rascunhos.length}</span></header>${planosHtml}</section>\n          </div>\n        </div>\n      </main>\n    </div>`\n  },\n}"}},"usuarios":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"usuarios"}}}},"projetos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"projetos"}}}},"features":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"features"}}}},"cards":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cards"}}}},"mensagens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"mensagens"}}}},"decisoes":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"decisoes"}}}},"planos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"planos"}}}},"saude":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"saude"}}}},"responder":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"responder"}}}},"aprovarPlano":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"aprovarPlano"}}}}}}}}}},{"_id":"6ace7b14ecc6eec098adc43f","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"pm-planos","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const LIB = { url: 'https://gabz-playground.data2.media/file/dPZUG5PfHXNVs-sT1YERj', css: 'https://gabz-playground.data2.media/file/qChFGH9hteWjSZxe3rSAl' }\nconst carregando = (d2) => `<div class=\"root carregando\">${d2.lib.state(LIB) === 'error' ? `Não carregou a skin: ${d2.lib.error(LIB)}` : 'Carregando…'}</div>`\nlet ui, esc, id, ms, recs, eu, estado, estadoPlano, tagChips, linkCard, projetoAtual, travado\nconst planoDe = (e, el) => (e.target.closest?.('[data-plano]') || el).dataset.plano\nconst dataBr = (d) => (d ? new Date(d).toLocaleDateString('pt-BR') : '')\nconst GRUPOS = [\n  ['Em andamento', ['aprovado', 'em_execucao', 'pronto_para_publicar', 'pronto_oculto']],\n  ['Rascunhos', ['rascunho']],\n  ['Publicados', ['publicada']],\n  ['Abandonados', ['abandonado']],\n]\n\n// ponytail: item numerado e \"-\" recuado viram linhas iguais; [sec], [bug] etc. no título viram tags, edição manual cobre o resto\nconst secao = (corpo, re) => String(corpo || '').split(/^##\\s+/m).find((s) => re.test(s.split('\\n')[0]))\nconst limpar = (t) => t.replace(/[*`]/g, '').replace(/\\s*\\[(hist[oó]ria|tarefa)\\]\\s*/gi, ' ').replace(/[.:]\\s*$/, '').trim()\nconst passos = (corpo, permitidas) => {\n  const linhas = []\n  for (const l of String(secao(corpo, /cards sugeridos|tarefas sugeridas/i) ?? secao(corpo, /^passos/i) ?? corpo).split('\\n')) {\n    const t = l.match(/^\\d+[.)]\\s+(.+)/)?.[1] || l.match(/^\\s+[-*]\\s+(.+)/)?.[1]\n    if (!t) continue\n    const { tags, titulo } = ui.tagsDoTitulo(t, permitidas)\n    linhas.push({ k: `l${linhas.length}`, titulo: limpar(titulo), tags: tags.join(', '), agora: false })\n  }\n  return linhas\n}\nconst novaLinha = () => ({ k: `n${Date.now()}`, titulo: '', tags: '', agora: false })\nconst tagsDe = (txt) => String(txt || '').split(',').map((t) => t.trim().toLowerCase()).filter(Boolean)\n\nconst lerLinhas = (d2) => d2.$$('[data-linha]').map((el) => ({\n  k: el.dataset.linha,\n  titulo: el.querySelector('input[name=titulo]').value.trim(),\n  tags: el.querySelector('input[name=tags]').value,\n  agora: !!el.querySelector('input[name=agora]')?.checked,\n}))\n\nfunction recarregar(d2) {\n  ui.carregar(d2, 'projetos').then(() => {\n    const projetoId = ui.projetoAtual(d2, ui.recs(d2.data('projetos')))\n    if (projetoId) for (const k of ['planos', 'cards']) ui.carregar(d2, k, { projetoId })\n  })\n}\n\nexport default {\n  css: `\n    main { padding:24px; display:grid; grid-template-columns:minmax(260px,1fr) minmax(0,2fr); gap:16px; align-items:start; max-width:1440px; }\n    .grupo { padding:8px 0; border-bottom:1px solid var(--line2); }\n    .grupo:last-child { border-bottom:0; }\n    .grupo h3 { font-size:11px; font-weight:500; color:var(--tx2); padding:4px 16px 6px; }\n    .item { display:grid; gap:4px; padding:8px 16px; cursor:pointer; border-left:2px solid transparent; transition:background .14s var(--ease); }\n    .item:hover { background:var(--p2); }\n    .item.on { background:var(--acc-soft); border-left-color:var(--acc); }\n    .corpo { padding:16px; white-space:pre-wrap; color:var(--tx2); line-height:1.6; border-bottom:1px solid var(--line); }\n    .bloco { padding:12px 16px; display:grid; gap:8px; border-bottom:1px solid var(--line2); }\n    .bloco:last-child { border-bottom:0; }\n    .bloco h4 { font-size:10px; font-weight:600; color:var(--tx3); text-transform:uppercase; letter-spacing:.06em; }\n    .linha { display:grid; grid-template-columns:1fr 200px 120px auto; gap:8px; align-items:center; }\n    .linha label { display:flex; align-items:center; gap:6px; color:var(--tx2); font-size:11px; white-space:nowrap; }\n    .linha label input { height:auto; }\n    .card { display:flex; align-items:center; gap:8px; }\n    .pend { display:flex; align-items:flex-start; gap:8px; }\n    .pend > div { flex:1; display:grid; gap:2px; }\n    @media (max-width:900px) { main { grid-template-columns:1fr; padding:16px; } }\n  `,\n\n  mounted(d2) {\n    const permitidas = () => {\n      const ps = recs(d2.data('projetos'))\n      return ps.find((p) => id(p) === projetoAtual(d2, ps))?.tags || []\n    }\n    d2.on('[data-sel]', 'click', (e, el) => {\n      const sel = (e.target.closest?.('[data-sel]') || el).dataset.sel\n      d2.setState({ sel, linhas: null, perguntaDup: '', erro: '', aviso: '', novoCard: '' })\n    })\n\n    const abrirEditor = (sel) => {\n      const p = recs(d2.data('planos')).find((x) => id(x) === sel)\n      const sugestao = passos(p?.corpo, permitidas())\n      d2.setState({ sel, perguntaDup: '', linhas: sugestao.length ? sugestao : [novaLinha()], erro: '', aviso: '' })\n    }\n    d2.on('[data-explodir]', 'click', (e, el) => {\n      const sel = planoDe(e, el)\n      const jaTem = recs(d2.data('cards')).some((c) => id(c.planoId) === sel) || (recs(d2.data('planos')).find((x) => id(x) === sel)?.itensPendentes || []).length\n      if (jaTem) return d2.setState({ sel, perguntaDup: sel, erro: '', aviso: '' })\n      abrirEditor(sel)\n    })\n    d2.on('[data-dup-sim]', 'click', (e, el) => abrirEditor(planoDe(e, el)))\n    d2.on('[data-add]', 'click', () => { d2.setState({ linhas: [...lerLinhas(d2), novaLinha()] }) })\n    d2.on('[data-rm]', 'click', (e, el) => {\n      const k = (e.target.closest?.('[data-rm]') || el).dataset.rm\n      d2.setState({ linhas: lerLinhas(d2).filter((l) => l.k !== k) })\n    })\n    d2.on('[data-cancelar]', 'click', () => { d2.setState({ linhas: null, perguntaDup: '', erro: '' }) })\n\n    const chamar = async (rush, body, ok) => {\n      d2.setState({ enviando: true, erro: '', aviso: '', novoCard: '' })\n      try {\n        ok(await ui.invocar(d2, rush, body))\n      } catch (err) {\n        d2.setState({ erro: err.message })\n      } finally {\n        d2.setState({ enviando: false })\n        recarregar(d2)\n      }\n    }\n\n    d2.on('[data-aprovar]', 'click', (e, el) => chamar('aprovarPlano', { planoId: planoDe(e, el), usuarioId: eu(d2) },\n      () => d2.setState({ aviso: 'Plano aprovado.' })))\n\n    d2.on('[data-iniciar]', 'click', (e, el) => {\n      const b = e.target.closest?.('[data-iniciar]') || el\n      const planoId = b.dataset.plano\n      const item = (recs(d2.data('planos')).find((x) => id(x) === planoId)?.itensPendentes || [])[Number(b.dataset.iniciar)]\n      if (!item) return\n      chamar('iniciarItem', { planoId, titulo: item.titulo, atorId: eu(d2), via: 'painel' },\n        (r) => d2.setState({ aviso: `\"${item.titulo}\" começou: tarefa em desenvolvimento.`, novoCard: r.cardId }))\n    })\n\n    d2.on('[data-confirmar]', 'click', (e, el) => {\n      const planoId = planoDe(e, el)\n      const linhas = lerLinhas(d2).filter((l) => l.titulo)\n      if (!linhas.length) return d2.setState({ erro: 'Preencha pelo menos um título.' })\n      const ok = permitidas()\n      const fora = [...new Set(linhas.flatMap((l) => tagsDe(l.tags)).filter((t) => !ok.includes(t)))]\n      if (fora.length) return d2.setState({ erro: `Tags fora da lista do projeto: ${fora.join(', ')} (permitidas: ${ok.join(', ')})` })\n      const item = (l) => ({ titulo: l.titulo, tags: tagsDe(l.tags) })\n      chamar('explodirPlano', { planoId, atorId: eu(d2), cards: linhas.filter((l) => l.agora).map(item), pendentes: linhas.filter((l) => !l.agora).map(item) }, (r) => {\n        const n = (r.cardsCriados || []).length\n        const f = (r.falhas || []).length\n        const p = r.pendentes || 0\n        d2.setState({ linhas: null, aviso: `${n} tarefa${n === 1 ? '' : 's'} em desenvolvimento, ${p} ite${p === 1 ? 'm' : 'ns'} pendente${p === 1 ? '' : 's'}${f ? `, ${f} falharam` : ''}.` })\n      })\n    })\n  },\n\n  updated(d2) {\n    if (!ui || d2.state.iniciado) return\n    d2.state.iniciado = true\n    ui.carregarUsuarios(d2)\n    ui.ligarTopo(d2, () => recarregar(d2), { sel: '', linhas: null })\n    ui.vigiar(d2, () => recarregar(d2))\n  },\n\n  render(d2) {\n    ui = d2.lib(LIB)\n    if (!ui) return carregando(d2)\n    ;({ esc, id, ms, recs, eu, estado, estadoPlano, tagChips, linkCard, projetoAtual, travado } = ui)\n    const projetos = recs(d2.data('projetos'))\n    const projetoId = projetoAtual(d2, projetos)\n    const planos = recs(d2.data('planos')).filter((p) => id(p.projetoId) === projetoId)\n      .sort((a, b) => ms(b.createdAt) - ms(a.createdAt))\n    const cards = recs(d2.data('cards'))\n    const trava = travado(d2)\n    const ocupado = d2.state.enviando ? 'disabled' : trava\n\n    const selId = d2.state.sel || id(planos.find((p) => GRUPOS[0][1].includes(p.estado)) || planos[0])\n    const lista = GRUPOS.map(([rot, estados]) => {\n      const deles = planos.filter((p) => estados.includes(p.estado || 'rascunho'))\n      if (!deles.length) return ''\n      return `<div class=\"grupo\" data-key=\"${esc(rot)}\"><h3>${esc(rot)}</h3>\n        ${deles.map((p) => {\n          const n = cards.filter((c) => id(c.planoId) === id(p) && c.coluna !== 'descartado')\n          const prontas = n.filter((c) => c.coluna === 'pronto').length\n          return `<div class=\"item ${id(p) === selId ? 'on' : ''}\" data-sel=\"${esc(id(p))}\" data-key=\"${esc(id(p))}\">\n          <div class=\"tit\">${esc(p.titulo)}</div>\n          <div class=\"meta\">${estadoPlano(p.estado)}\n            ${n.length ? `<span>· ${prontas}/${n.length} tarefas</span>` : ''}\n            ${(p.itensPendentes || []).length ? `<span>· ${p.itensPendentes.length} pendentes</span>` : ''}</div>\n          ${p.estado === 'rascunho' ? '' : ui.progresso(ui.conclusaoPlano(p, cards).feitas, ui.conclusaoPlano(p, cards).total)}\n        </div>`\n        }).join('')}\n      </div>`\n    }).join('')\n\n    const p = planos.find((x) => id(x) === selId)\n    let detalhe = '<div class=\"vazio\">Escolha um plano na lista.</div>'\n    if (p) {\n      const gerados = cards.filter((c) => id(c.planoId) === id(p))\n      const pendentes = p.itensPendentes || []\n      const podeExplodir = ['aprovado', 'em_execucao', 'pronto_para_publicar', 'publicada'].includes(p.estado)\n      const linhas = d2.state.linhas\n      detalhe = `\n        <div class=\"bloco\"><div class=\"meta\">${estadoPlano(p.estado)}\n          ${p.aprovadoEm ? `<span>· aprovado por ${esc(ui.nome(d2, p.aprovadoPor))} em ${esc(dataBr(p.aprovadoEm))}</span>` : ''}\n          ${p.bundlePublicado ? `<span>· publicado em <span class=\"mono\">${esc(p.bundlePublicado)}</span></span>` : ''}</div>\n          <div class=\"tit\">${esc(p.titulo)}</div>\n          ${p.estado === 'rascunho' ? '' : (() => { const c = ui.conclusaoPlano(p, cards); return `${ui.progresso(c.feitas, c.total)}<span class=\"meta\">${c.feitas} de ${c.total} feitas (tarefas prontas sobre tarefas ativas + itens pendentes)</span>` })()}</div>\n        <div class=\"corpo\">${esc(p.corpo)}</div>\n        ${linhas ? `<div class=\"bloco\"><h4>Itens do plano</h4>\n            <span class=\"meta\">Marque \"começar agora\" no que já vai pra desenvolvimento; o resto fica pendente no plano. Tags separadas por vírgula, só da lista do projeto ([sec], [bug] no texto do plano já preenchem).</span>\n            ${linhas.map((l) => `<div class=\"linha\" data-linha=\"${esc(l.k)}\" data-key=\"${esc(l.k)}\">\n              <input name=\"titulo\" value=\"${esc(l.titulo)}\" placeholder=\"Título\">\n              <input name=\"tags\" value=\"${esc(l.tags)}\" placeholder=\"tags\">\n              <label><input type=\"checkbox\" name=\"agora\" ${l.agora ? 'checked' : ''}> começar agora</label>\n              <button class=\"x\" data-rm=\"${esc(l.k)}\" title=\"Remover\">×</button></div>`).join('')}\n            <div class=\"acoes\"><button data-add>Adicionar linha</button><span class=\"sp\"></span>\n              <button data-cancelar>Cancelar</button>\n              <button class=\"pri\" data-confirmar data-plano=\"${esc(id(p))}\" ${ocupado}>${d2.state.enviando ? 'Gravando…' : 'Gravar itens'}</button></div>\n          </div>`\n        : d2.state.perguntaDup === id(p) ? `<div class=\"bloco\"><div class=\"erro\">Este plano já tem ${gerados.length} tarefa${gerados.length === 1 ? '' : 's'} e ${pendentes.length} ite${pendentes.length === 1 ? 'm' : 'ns'} pendente${pendentes.length === 1 ? '' : 's'}. Explodir de novo grava itens novos, sem conferir duplicados.</div>\n            <div class=\"acoes\"><button data-cancelar>Cancelar</button>\n            <button class=\"pri\" data-dup-sim data-plano=\"${esc(id(p))}\">Explodir mesmo assim</button></div></div>`\n        : `<div class=\"bloco\"><div class=\"acoes\">\n            ${p.estado === 'rascunho' ? `<button class=\"pri\" data-aprovar data-plano=\"${esc(id(p))}\" ${ocupado}>${d2.state.enviando ? 'Aprovando…' : 'Aprovar plano'}</button>` : ''}\n            ${podeExplodir ? `<button class=\"pri\" data-explodir data-plano=\"${esc(id(p))}\" ${trava}>Explodir em itens</button>` : ''}\n          </div></div>`}\n        <div class=\"bloco\"><h4>Pendentes (${pendentes.length})</h4>\n          ${pendentes.length ? pendentes.map((it, i) => `<div class=\"pend\" data-key=\"${esc(`${id(p)}:${it.titulo}`)}\">\n            <div><span>${esc(it.titulo)}</span><span class=\"meta\">${tagChips(it.tags)}</span></div>\n            ${podeExplodir ? `<button data-iniciar=\"${i}\" data-plano=\"${esc(id(p))}\" ${ocupado}>Começar</button>` : ''}</div>`).join('')\n          : '<span class=\"meta\">Nada pendente.</span>'}\n        </div>\n        <div class=\"bloco\"><h4>Tarefas (${gerados.length})</h4>\n          ${gerados.length ? gerados.map((c) => `<div class=\"card\" data-key=\"${esc(id(c))}\">${estado(ui.ROTULO[c.coluna] || c.coluna || '—', c.coluna === 'descartado' ? 'muted' : 'info')}<span>${linkCard(id(c), esc(c.titulo))}</span>${tagChips(c.tags)}</div>`).join('') : '<span class=\"meta\">Nenhuma ainda.</span>'}\n        </div>`\n    }\n\n    return `<div class=\"root\">\n      ${ui.topo(d2, 'Planos', projetos, projetoId)}\n      ${ui.banner(d2)}\n      <main>\n        ${d2.state.erro ? `<div class=\"erro\">${esc(d2.state.erro)}</div>` : ''}\n        ${d2.state.aviso ? `<div class=\"ok-msg\">${esc(d2.state.aviso)}${d2.state.novoCard ? ` ${linkCard(d2.state.novoCard, 'Abrir tarefa')}` : ''}</div>` : ''}\n        <section><header><h2>Planos</h2></header>${lista || '<div class=\"vazio\">Nenhum plano neste projeto.</div>'}</section>\n        <section><header><h2>Plano</h2></header>${detalhe}</section>\n      </main>\n    </div>`\n  },\n}"}},"usuarios":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"usuarios"}}}},"projetos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"projetos"}}}},"features":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"features"}}}},"planos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"planos"}}}},"cards":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cards"}}}},"aprovarPlano":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"aprovarPlano"}}}},"explodirPlano":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"explodirPlano"}}}},"iniciarItem":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"iniciarItem"}}}}}}}}}},{"_id":"6acf72b5c461cf9549b12cde","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"pm-card","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const LIB = { url: 'https://gabz-playground.data2.media/file/dPZUG5PfHXNVs-sT1YERj', css: 'https://gabz-playground.data2.media/file/qChFGH9hteWjSZxe3rSAl' }\nconst carregando = (d2) => `<div class=\"root carregando\">${d2.lib.state(LIB) === 'error' ? `Não carregou a skin: ${d2.lib.error(LIB)}` : 'Carregando…'}</div>`\nlet ui, esc, id, ms, recs, eu, estado, estadoPlano, quando, quem, evid, norm, travado\nconst PROXIMA = { em_desenvolvimento: 'review', review: 'pronto' }\nconst ORDEM = { review: 0, em_desenvolvimento: 1, bloqueado: 2, pronto: 3 }\n\nconst cardDaUrl = () => new URLSearchParams(location.search).get('card') || ''\n// card pedido (clique ou ?card=) decide o projeto até o usuário trocar no seletor\nconst projetoDe = (d2) => d2.state.projetoId || d2.state.projetoDoCard || ui.projetoAtual(d2, recs(d2.data('projetos')))\nconst doProjeto = (d2) => recs(d2.data('cards')).filter((c) => id(c.projetoId) === projetoDe(d2) && c.coluna !== 'descartado')\nconst atual = (d2) => {\n  const lista = doProjeto(d2)\n  const pedido = d2.state.cardId || cardDaUrl()\n  if (lista.some((c) => id(c) === pedido)) return pedido\n  return id(lista.slice().sort((a, b) => ms(b.movidoEm || b.updatedAt) - ms(a.movidoEm || a.updatedAt))[0])\n}\nconst cardDe = (d2, cid) => recs(d2.data('cards')).find((c) => id(c) === cid)\n\nfunction carregarCard(d2, cardId) {\n  d2.state.cargaDe = cardId\n  ui.carregar(d2, 'transicoes', { entidadeId: cardId })\n  ui.carregar(d2, 'mensagens', { 'anexadoA.id': cardId })\n  ui.carregar(d2, 'rodadas', { cardId })\n}\n\nasync function avaliarDod(d2, cardId) {\n  const card = cardDe(d2, cardId)\n  const para = PROXIMA[card?.coluna]\n  const chave = `${cardId}:${card?.coluna}`\n  d2.state.dodPedido = chave\n  if (!para) return\n  try {\n    const res = await d2.rush('transicao').invoke({ entidade: 'card', entidadeId: cardId, para, avaliar: true, atorId: eu(d2) || undefined, via: 'painel' })\n    if (d2.state.dodPedido === chave) d2.setState({ dod: { chave, para, ...(res?.data ?? res) } })\n  } catch (err) {\n    if (d2.state.dodPedido === chave) d2.setState({ dod: { chave, para, erro: err.message } })\n  }\n}\n\nfunction recarregar(d2) {\n  return ui.carregar(d2, 'projetos').then(() => {\n    const projetoId = projetoDe(d2)\n    if (!projetoId) return\n    return Promise.all(['cards', 'planos'].map((k) => ui.carregar(d2, k, { projetoId }))).then(() => {\n      const cardId = atual(d2)\n      if (!cardId) return\n      carregarCard(d2, cardId)\n      avaliarDod(d2, cardId)\n    })\n  })\n}\n\nasync function mover(d2, para, rotulo, motivoObrigatorio) {\n  const cardId = atual(d2)\n  let motivo\n  if (motivoObrigatorio) {\n    motivo = (await d2.dialog.prompt(`Motivo (${rotulo}):`, '') || '').trim()\n    if (!motivo) return ui.avisar(d2, 'warn', `${rotulo} cancelado: o motivo é obrigatório.`)\n  }\n  d2.setState({ enviando: para, erro: '' })\n  try {\n    const r = await ui.invocar(d2, 'transicao', { entidade: 'card', entidadeId: cardId, para, atorId: eu(d2), via: 'painel', motivo })\n    ui.avisar(d2, 'ok', `${ui.ROTULO[r.de] || r.de} → ${ui.ROTULO[r.para] || r.para}`)\n  } catch (err) {\n    d2.setState({ erro: `Não moveu para ${ui.ROTULO[para] || para}: ${err.message}` })\n  } finally {\n    d2.setState({ enviando: '' })\n    recarregar(d2)\n  }\n}\n\nexport default {\n  css: `\n    .pagina { display:grid; grid-template-columns:260px minmax(0,1fr); align-items:start; }\n    .rail { position:sticky; top:53px; height:calc(100vh - 53px); overflow:auto; border-right:1px solid var(--line); background:var(--p1); }\n    .rail input { position:sticky; top:0; z-index:1; width:100%; height:36px; padding:0 16px; border:0; border-radius:0; border-bottom:1px solid var(--line); background:var(--p1); }\n    .rail input:focus { box-shadow:inset 0 0 0 2px var(--focus); }\n    .rail h3 { font-size:10px; font-weight:600; color:var(--tx3); text-transform:uppercase; letter-spacing:.06em; padding:12px 16px 4px; }\n    .rail a { display:grid; gap:2px; padding:6px 16px; color:var(--tx); text-decoration:none; border-left:2px solid transparent; transition:background .14s var(--ease); }\n    .rail a:hover { background:var(--p2); }\n    .rail a.on { background:var(--acc-soft); border-left-color:var(--acc); }\n    .rail a.feito { opacity:.5; }\n    .rail a .t { font-size:11px; line-height:1.35; }\n    main { padding:24px; display:grid; grid-template-columns:minmax(0,3fr) minmax(260px,2fr); gap:16px; align-items:start; }\n    .col { display:grid; gap:16px; }\n    .cab { padding:16px; display:grid; gap:10px; }\n    .cab h1 { font-size:16px; font-weight:600; letter-spacing:-.015em; line-height:1.2; }\n    .campos { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:12px; }\n    .campo .rot { display:block; font-size:10px; color:var(--tx3); text-transform:uppercase; letter-spacing:.06em; margin-bottom:2px; }\n    .desc { color:var(--tx2); white-space:pre-wrap; }\n    ul.crit { padding-left:16px; color:var(--tx2); display:grid; gap:4px; }\n    .ev { display:grid; grid-template-columns:96px 1fr; gap:12px; padding:10px 16px; border-bottom:1px solid var(--line2); }\n    .ev:last-child { border-bottom:0; }\n    .ev.aberta { box-shadow:inset 2px 0 0 var(--warn); }\n    .ev .hora { color:var(--tx3); font-size:11px; }\n    .ev .corpo { display:grid; gap:4px; }\n    .extra { color:var(--tx2); white-space:pre-wrap; font-size:11px; }\n    .ev .txt { color:var(--tx); }\n    .cab .meta a, .chk a { color:var(--tx); text-decoration:underline; text-decoration-color:var(--tx3); text-underline-offset:2px; }\n    .chk { display:flex; align-items:flex-start; gap:8px; padding:8px 16px; border-bottom:1px solid var(--line2); }\n    .chk:last-child { border-bottom:0; }\n    .decidir { padding:12px 16px; display:flex; flex-wrap:wrap; gap:6px; }\n    .tags { display:flex; flex-wrap:wrap; align-items:center; gap:4px; }\n    .tags .rot { font-size:10px; color:var(--tx3); text-transform:uppercase; letter-spacing:.06em; margin-right:4px; }\n    .tags button { height:22px; padding:0 8px; font-size:11px; }\n    .tags button.on { background:var(--acc-soft); border-color:var(--acc); color:var(--tx); }\n    @media (max-width:1100px) { main { grid-template-columns:1fr; } }\n    @media (max-width:760px) { .pagina { grid-template-columns:1fr; } .rail { position:static; height:auto; max-height:40vh; } main { padding:16px; } .campos { grid-template-columns:repeat(2,1fr); } }\n  `,\n\n  mounted(d2) {\n    d2.on('input[name=busca]', 'input', (e, el) => { d2.state.busca = el.value })\n    d2.on('[data-card]', 'click', (e, el) => {\n      if (e.metaKey || e.ctrlKey || e.shiftKey) return\n      e.preventDefault()\n      const cid = (e.target.closest?.('[data-card]') || el).dataset.card\n      history.replaceState(null, '', `?card=${encodeURIComponent(cid)}`)\n      d2.setState({ cardId: cid, abrindo: '', erro: '' })\n    })\n    d2.on('[data-mover]', 'click', (e, el) => {\n      const b = e.target.closest?.('[data-mover]') || el\n      mover(d2, b.dataset.mover, b.dataset.rotulo, b.dataset.motivo === '1')\n    })\n    d2.on('[data-tag]', 'click', async (e, el) => {\n      const t = (e.target.closest?.('[data-tag]') || el).dataset.tag\n      const cardId = atual(d2)\n      const atuais = cardDe(d2, cardId)?.tags || []\n      const tags = atuais.includes(t) ? atuais.filter((x) => x !== t) : [...atuais, t]\n      d2.setState({ enviando: 'tags', erro: '' })\n      try {\n        await ui.invocar(d2, 'tarefaTags', { cardId, tags, atorId: eu(d2) })\n        ui.avisar(d2, 'ok', `Tags: ${tags.join(', ') || 'nenhuma'}`)\n      } catch (err) {\n        d2.setState({ erro: `Não trocou as tags: ${err.message}` })\n      } finally {\n        d2.setState({ enviando: '' })\n        recarregar(d2)\n      }\n    })\n    d2.on('[data-abrir]', 'click', (e, el) => { d2.setState({ abrindo: el.dataset.abrir, erro: '' }) })\n    d2.on('[data-cancelar]', 'click', () => { d2.setState({ abrindo: '', erro: '' }) })\n    d2.on('[data-responder]', 'click', async (e, el) => {\n      const mensagemId = el.dataset.responder\n      const texto = (d2.$(`textarea[data-id=\"${mensagemId}\"]`)?.value || '').trim()\n      if (!texto) return d2.setState({ erro: 'Escreva a resposta antes de enviar.' })\n      d2.setState({ enviando: mensagemId, erro: '' })\n      try {\n        await ui.invocar(d2, 'responder', { mensagemId, atorId: eu(d2), texto, via: 'painel' })\n        d2.setState({ abrindo: '' })\n      } catch (err) {\n        d2.setState({ erro: `Não respondeu: ${err.message}` })\n      } finally {\n        d2.setState({ enviando: '' })\n        recarregar(d2)\n      }\n    })\n  },\n\n  updated(d2) {\n    if (!ui) return\n    if (!d2.state.iniciado) {\n      d2.state.iniciado = true\n      ui.carregarUsuarios(d2)\n      ui.ligarTopo(d2, () => recarregar(d2), { cardId: '' })\n      // ?card= de outro projeto: descobre o projeto do card antes da primeira carga\n      const pedido = cardDaUrl()\n      const pronto = !pedido ? Promise.resolve() : Promise.resolve(d2.data('cards')?.query({ _id: pedido }))\n        .then((res) => { const c = (res?.data ?? res)?.[0]; if (c) { d2.state.projetoDoCard = id(c.projetoId); ui.guardar('projetoId', id(c.projetoId)) } })\n        .catch(() => {})\n      pronto.then(() => ui.vigiar(d2, () => recarregar(d2)))\n      return\n    }\n    // card trocado (clique, seletor): carrega a trilha dele e reavalia o DoD\n    const cardId = atual(d2)\n    const card = cardDe(d2, cardId)\n    if (cardId && d2.state.cargaDe !== cardId) carregarCard(d2, cardId)\n    if (card && d2.state.dodPedido !== `${cardId}:${card.coluna}`) avaliarDod(d2, cardId)\n  },\n\n  render(d2) {\n    ui = d2.lib(LIB)\n    if (!ui) return carregando(d2)\n    ;({ esc, id, ms, recs, eu, estado, estadoPlano, quando, quem, evid, norm, travado } = ui)\n    const cards = recs(d2.data('cards'))\n    const projetos = recs(d2.data('projetos'))\n    const projetoId = projetoDe(d2)\n    const cardId = atual(d2)\n    const card = cards.find((c) => id(c) === cardId)\n    const nome = (uid) => ui.nome(d2, uid)\n    const planos = recs(d2.data('planos'))\n    const tagsProjeto = projetos.find((p) => id(p) === projetoId)?.tags || []\n    const trava = travado(d2)\n    const rot = (col) => ui.ROTULO[col] || col || '—'\n\n    const busca = norm(d2.state.busca)\n    const visiveis = doProjeto(d2).filter((c) => !busca || norm(c.titulo).includes(busca) || id(c).includes(busca))\n    const grupos = {}\n    for (const c of visiveis) (grupos[id(c.planoId)] ||= []).push(c)\n    const rail = `<aside class=\"rail\"><input name=\"busca\" placeholder=\"Buscar tarefa\" value=\"${esc(d2.state.busca || '')}\" autocomplete=\"off\">\n      ${Object.entries(grupos).map(([pid, lista]) => `<h3>${esc(planos.find((p) => id(p) === pid)?.titulo || 'Sem plano')}</h3>\n        ${lista.sort((a, b) => (ORDEM[a.coluna] ?? 9) - (ORDEM[b.coluna] ?? 9) || String(a.titulo).localeCompare(b.titulo)).map((c) => `<a href=\"?card=${esc(id(c))}\" data-card=\"${esc(id(c))}\" data-key=\"${esc(id(c))}\"\n          class=\"${id(c) === cardId ? 'on' : ''} ${c.coluna === 'pronto' ? 'feito' : ''}\"><span class=\"t\">${esc(c.titulo)}</span><span class=\"meta\">${esc(rot(c.coluna))}</span></a>`).join('')}`).join('') || '<div class=\"vazio\">Nenhuma tarefa.</div>'}\n      </aside>`\n\n    let corpo = '<main><section><div class=\"vazio\">Escolha uma tarefa na lista.</div></section></main>'\n    if (card) {\n      const mensagens = recs(d2.data('mensagens')).filter((m) => m.anexadoA?.id === cardId)\n      const transicoes = recs(d2.data('transicoes')).filter((t) => id(t.entidadeId) === cardId)\n      const rodadas = recs(d2.data('rodadas')).filter((r) => id(r.cardId) === cardId).sort((a, b) => ms(b.createdAt) - ms(a.createdAt))\n      const plano = planos.find((p) => id(p) === id(card.planoId)) || planos.find((p) => (p.cardsGerados || []).includes(cardId))\n      const dod = d2.state.dod?.chave === `${cardId}:${card.coluna}` ? d2.state.dod : null\n      const para = PROXIMA[card.coluna]\n      const ocupado = (k) => (d2.state.enviando ? 'disabled' : trava) + (d2.state.enviando === k ? ' aria-busy=\"true\"' : '')\n\n      const evs = [\n        ...transicoes.map((t) => ({ k: id(t), em: t.em || t.createdAt, autor: t.por, ctx: t, tipo: 'transição',\n          texto: `${rot(t.de)} → ${rot(t.para)}${t.forcado ? ' (forçada)' : ''}`,\n          extra: [t.motivo, t.revisor ? `revisor: ${nome(t.revisor) || t.revisor}` : '', (t.dodResultado?.faltando || []).length ? `DoD faltando: ${t.dodResultado.faltando.join('; ')}` : ''].filter(Boolean).join('\\n') })),\n        ...mensagens.map((m) => ({ k: id(m), em: m.createdAt, autor: m.autor, ctx: m, tipo: m.tipo || 'mensagem', texto: m.texto, msg: m,\n          tom: m.tipo === 'pergunta' ? (m.respondidaEm ? 'ok' : 'warn') : '' })),\n      ].sort((a, b) => ms(b.em) - ms(a.em))\n\n      const timeline = evs.length ? evs.map((e) => {\n        const aberta = e.msg?.tipo === 'pergunta' && !e.msg.respondidaEm\n        return `<div class=\"ev ${aberta ? 'aberta' : ''}\" data-key=\"${esc(e.k)}\">\n          <div class=\"hora mono\">${esc(quando(e.em))}</div>\n          <div class=\"corpo\"><div class=\"meta\">${quem(d2, e.autor, e.ctx)}${e.tom ? estado(e.tipo, e.tom) : `<span class=\"chip\">${esc(e.tipo)}</span>`}</div>\n            <div class=\"txt\">${esc(e.texto)}</div>${evid(e.ctx.evidencia)}${e.extra ? `<div class=\"extra\">${esc(e.extra)}</div>` : ''}\n            ${!aberta ? '' : d2.state.abrindo === e.k ? `<textarea data-id=\"${esc(e.k)}\" placeholder=\"Resposta\"></textarea>\n              <div class=\"acoes\"><button data-cancelar>Cancelar</button>\n              <button class=\"pri\" data-responder=\"${esc(e.k)}\" ${ocupado(e.k)}>${d2.state.enviando === e.k ? 'Enviando…' : 'Enviar resposta'}</button></div>`\n              : `<div class=\"acoes\"><button data-abrir=\"${esc(e.k)}\" ${trava}>Responder</button></div>`}\n          </div>\n        </div>`\n      }).join('') : '<div class=\"vazio\">Nada registrado ainda.</div>'\n\n      const dodHtml = !para ? `<div class=\"vazio\">Sem próxima coluna a partir de ${esc(rot(card.coluna))}.</div>`\n        : !dod ? '<div class=\"vazio\">Avaliando…</div>'\n        : dod.erro ? `<div class=\"vazio\">Não avaliou: ${esc(dod.erro)}</div>`\n        : (dod.faltando || []).length ? dod.faltando.map((f) => `<div class=\"chk\">${estado('falta', 'warn')}<span>${esc(f)}</span></div>`).join('')\n        : `<div class=\"chk\">${estado('ok', 'ok')}<span>Tudo certo pra ${esc(rot(para))}.</span></div>`\n\n      const botao = (para, rotulo, motivo, pri) => `<button ${pri ? 'class=\"pri\"' : ''} data-mover=\"${para}\" data-rotulo=\"${rotulo}\" data-motivo=\"${motivo ? 1 : 0}\" ${ocupado(para)}>${d2.state.enviando === para ? 'Enviando…' : rotulo}</button>`\n      const decidir = [\n        card.coluna === 'review' ? botao('pronto', 'Aprovar', false, true) + botao('em_desenvolvimento', 'Devolver', true) : '',\n        ['em_desenvolvimento', 'review'].includes(card.coluna) ? botao('bloqueado', 'Bloquear', true) : '',\n        card.coluna !== 'pronto' ? botao('descartado', 'Descartar', true) : '',\n      ].join('')\n\n      const testes = rodadas.length ? rodadas.slice(0, 10).map((r) => {\n        const fixture = r.fonte === 'fixture'\n        const tom = fixture ? 'muted' : r.total && r.aprovados === r.total ? 'ok' : 'bad'\n        return `<div class=\"chk\" data-key=\"${esc(id(r))}\">${estado(`${r.aprovados}/${r.total}`, tom)}<span>${esc(r.camada)} · ${fixture ? estado('fixture (não conta)', 'warn') : esc(r.fonte || '')} · ${esc(quando(r.createdAt))}</span></div>`\n      }).join('') : `<div class=\"chk\">${estado('sem rodada', 'warn')}<span>Nenhuma rodada registrada pra esta tarefa.</span></div>`\n\n      const pendentes = plano?.itensPendentes || []\n      const planoHtml = !plano ? '<div class=\"vazio\">Tarefa fora de plano.</div>'\n        : `<div class=\"chk\">${estadoPlano(plano.estado)}<span>${ui.linkAba('Planos', esc(plano.titulo))}</span></div>\n          ${pendentes.map((it) => `<div class=\"chk\" data-key=\"${esc(it.titulo)}\">${estado('pendente', 'info')}<span>${esc(it.titulo)}</span></div>`).join('')}`\n\n      const temTag = (t) => (card.tags || []).includes(t)\n      const tagsHtml = `<div class=\"tags\"><span class=\"rot\">Tags</span>${tagsProjeto.map((t) => `<button data-tag=\"${esc(t)}\" class=\"${temTag(t) ? 'on' : ''}\" ${d2.state.enviando ? 'disabled' : trava}>${esc(t)}</button>`).join('') || '<span class=\"meta\">o projeto não tem tags</span>'}</div>`\n\n      corpo = `<main>\n        ${d2.state.erro ? `<div class=\"erro\">${esc(d2.state.erro)}</div>` : ''}\n        <div class=\"col\">\n          <section><div class=\"cab\">\n            <div class=\"meta\">${estado(rot(card.coluna), 'info')}${ui.tagChips(card.tags)}<span class=\"mono\">${esc(cardId)}</span></div>\n            <h1>${esc(card.titulo)}</h1>\n            ${tagsHtml}\n            <div class=\"campos\">\n              <div class=\"campo\"><span class=\"rot\">Plano</span>${plano ? `${ui.linkAba('Planos', esc(plano.titulo))} ${estadoPlano(plano.estado)}` : '—'}</div>\n              <div class=\"campo\"><span class=\"rot\">Responsável</span>${esc(nome(card.responsavel) || '—')}</div>\n              <div class=\"campo\"><span class=\"rot\">Revisor</span>${card.revisor ? esc(nome(card.revisor)) : estado('sem revisor', card.coluna === 'review' ? 'warn' : 'info')}</div>\n              <div class=\"campo\"><span class=\"rot\">Autonomia</span>${esc(card.autonomia || '—')}</div>\n            </div>\n            ${card.descricao ? `<div class=\"desc\">${esc(card.descricao)}</div>` : ''}\n            ${(card.criteriosAceite || []).length ? `<ul class=\"crit\">${card.criteriosAceite.map((c) => `<li>${esc(c)}</li>`).join('')}</ul>` : ''}\n          </div>\n          ${decidir ? `<div class=\"decidir\">${decidir}</div>` : ''}</section>\n          <section><header><h2>O que aconteceu</h2><span class=\"meta\">${evs.length}</span></header>${timeline}</section>\n        </div>\n        <div class=\"col\">\n          <section><header><h2>DoD ${para ? `para ${esc(rot(para))}` : ''}</h2></header>${dodHtml}</section>\n          <section><header><h2>Testes</h2></header>${testes}</section>\n          <section><header><h2>Plano</h2></header>${planoHtml}</section>\n        </div>\n      </main>`\n    }\n\n    return `<div class=\"root\">\n      ${ui.topo(d2, 'Tarefa', projetos, projetoId)}\n      ${ui.banner(d2)}\n      <div class=\"pagina\">${rail}${corpo}</div>\n      ${ui.avisoHtml(d2)}\n    </div>`\n  },\n}"}},"usuarios":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"usuarios"}}}},"transicao":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"transicao"}}}},"responder":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"responder"}}}},"cards":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cards"}}}},"features":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"features"}}}},"transicoes":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"transicoes"}}}},"mensagens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"mensagens"}}}},"rodadas":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rodadas"}}}},"projetos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"projetos"}}}},"planos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"planos"}}}},"tarefaTags":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tarefaTags"}}}}}}}}}},{"_id":"6acf761ac3c24771b0ef48e0","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"pm-conversas","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const LIB = { url: 'https://gabz-playground.data2.media/file/dPZUG5PfHXNVs-sT1YERj', css: 'https://gabz-playground.data2.media/file/qChFGH9hteWjSZxe3rSAl' }\nconst carregando = (d2) => `<div class=\"root carregando\">${d2.lib.state(LIB) === 'error' ? `Não carregou a skin: ${d2.lib.error(LIB)}` : 'Carregando…'}</div>`\nlet ui, esc, id, ms, recs, ativos, eu, rel, quando, quem, evid, estado, linkCard, norm, projetoAtual, travado\nconst ENTIDADE = { card: 'Tarefa', plano: 'Plano' }\nconst chave = (m) => `${m.anexadoA?.entidade || 'card'}:${m.anexadoA?.id || ''}`\nconst MENCAO = /@([\\p{L}\\d._-]+)/gu\nconst apelidos = (u) => [u.mcpSubject, String(u.nome || '').split(' ')[0]].filter(Boolean).map(norm)\nconst mencionados = (m, usuarios) => {\n  const nomes = [...String(m.texto || '').matchAll(MENCAO)].map((x) => norm(x[1]))\n  const doTexto = usuarios.filter((u) => apelidos(u).some((a) => nomes.includes(a))).map((u) => id(u))\n  return new Set([...(m.mencoes || []).map((x) => id(x)), ...doTexto])\n}\nconst comMencoes = (texto, usuarios) => esc(texto).replace(MENCAO, (t, nome) =>\n  usuarios.some((u) => apelidos(u).includes(norm(nome))) ? `<span class=\"mencao\">${t}</span>` : t)\n\nfunction nomeDe(d2, entidade, oid) {\n  if (entidade === 'plano') return recs(d2.data('planos')).find((p) => id(p) === oid)?.titulo\n  return recs(d2.data('cards')).find((c) => id(c) === oid)?.titulo\n}\n\n// mensagens não têm projetoId: carrega as anexadas às tarefas e aos planos do projeto\nfunction recarregar(d2) {\n  ui.carregar(d2, 'projetos').then(() => {\n    const projetoId = ui.projetoAtual(d2, ui.recs(d2.data('projetos')))\n    if (!projetoId) return\n    Promise.all(['cards', 'planos'].map((k) => ui.carregar(d2, k, { projetoId }))).then(() => {\n      const ids = ['cards', 'planos'].flatMap((k) => ui.recs(d2.data(k)).filter((r) => id(r.projetoId) === projetoId).map(id))\n      ui.carregar(d2, 'mensagens', { 'anexadoA.id': { $in: ids } })\n    })\n  })\n}\n\nexport default {\n  css: `\n    .pagina { display:grid; grid-template-columns:300px minmax(0,1fr); align-items:start; }\n    .rail { position:sticky; top:53px; height:calc(100vh - 53px); overflow:auto; border-right:1px solid var(--line); background:var(--p1); }\n    .filtros { position:sticky; top:0; z-index:1; display:flex; gap:4px; padding:8px; background:var(--p1); border-bottom:1px solid var(--line); }\n    .filtros button { flex:1; }\n    .filtros button.on { background:var(--acc-soft); border-color:transparent; color:var(--tx); }\n    .rail a { display:grid; gap:2px; padding:8px 16px; color:var(--tx); text-decoration:none; border-left:2px solid transparent; border-bottom:1px solid var(--line2); transition:background .14s var(--ease); }\n    .rail a:hover { background:var(--p2); }\n    .rail a.on { background:var(--acc-soft); border-left-color:var(--acc); }\n    .rail a .t { font-size:11px; line-height:1.35; }\n    main { padding:24px; display:grid; gap:16px; max-width:960px; }\n    .fio { display:grid; gap:6px; padding:12px 16px; border-bottom:1px solid var(--line2); }\n    .fio:last-child { border-bottom:0; }\n    .fio.aberta { box-shadow:inset 2px 0 0 var(--warn); }\n    .mencao { color:var(--acc); background:var(--acc-soft); border-radius:3px; padding:0 2px; }\n    .resp { margin-left:16px; padding-left:12px; border-left:1px solid var(--line); display:grid; gap:4px; }\n    @media (max-width:760px) { .pagina { grid-template-columns:1fr; } .rail { position:static; height:auto; max-height:40vh; } main { padding:16px; } }\n  `,\n\n  mounted(d2) {\n    d2.on('[data-filtro]', 'click', (e, el) => { d2.setState({ filtro: el.dataset.filtro, sel: '' }) })\n    d2.on('[data-sel]', 'click', (e, el) => {\n      e.preventDefault()\n      d2.setState({ sel: (e.target.closest?.('[data-sel]') || el).dataset.sel, abrindo: '', erro: '' })\n    })\n    d2.on('[data-abrir]', 'click', (e, el) => { d2.setState({ abrindo: el.dataset.abrir, erro: '' }) })\n    d2.on('[data-cancelar]', 'click', () => { d2.setState({ abrindo: '', erro: '' }) })\n    d2.on('[data-responder]', 'click', async (e, el) => {\n      const mensagemId = el.dataset.responder\n      const texto = (d2.$(`textarea[data-id=\"${mensagemId}\"]`)?.value || '').trim()\n      if (!texto) return d2.setState({ erro: 'Escreva a resposta antes de enviar.' })\n      d2.setState({ enviando: mensagemId, erro: '' })\n      try {\n        await ui.invocar(d2, 'responder', { mensagemId, atorId: eu(d2), texto, via: 'painel' })\n        d2.setState({ abrindo: '' })\n        recarregar(d2)\n      } catch (err) {\n        d2.setState({ erro: `Não respondeu: ${err.message}` })\n      } finally {\n        d2.setState({ enviando: '' })\n      }\n    })\n  },\n\n  updated(d2) {\n    if (!ui || d2.state.iniciado) return\n    d2.state.iniciado = true\n    ui.carregarUsuarios(d2)\n    ui.ligarTopo(d2, () => recarregar(d2), { sel: '' })\n    ui.vigiar(d2, () => recarregar(d2))\n  },\n\n  render(d2) {\n    ui = d2.lib(LIB)\n    if (!ui) return carregando(d2)\n    ;({ esc, id, ms, recs, ativos, eu, rel, quando, quem, evid, estado, linkCard, norm, projetoAtual, travado } = ui)\n\n    const usuarioId = eu(d2)\n    const filtro = d2.state.filtro || 'inbox'\n    const projetos = recs(d2.data('projetos'))\n    const projetoId = projetoAtual(d2, projetos)\n    const doProjeto = new Set(['cards', 'planos'].flatMap((k) => recs(d2.data(k)).filter((r) => id(r.projetoId) === projetoId).map(id)))\n    const msgs = recs(d2.data('mensagens')).filter((m) => doProjeto.has(m.anexadoA?.id))\n    const aberta = (m) => m.tipo === 'pergunta' && !m.respondidaEm\n    const todos = ativos(d2)\n    const meMenciona = (m) => !!usuarioId && mencionados(m, todos).has(usuarioId)\n    const praMim = (m) => (!!usuarioId && m.tipo === 'pergunta' && id(m.para) === usuarioId) || meMenciona(m)\n    const trava = travado(d2)\n\n    const grupos = {}\n    for (const m of msgs) (grupos[chave(m)] ||= []).push(m)\n    const itens = Object.entries(grupos)\n      .filter(([, lista]) => filtro === 'todas' || lista.some(praMim))\n      .map(([k, lista]) => ({ k, lista, abertas: lista.filter(aberta).length, ult: Math.max(...lista.map((m) => ms(m.createdAt))) }))\n      .sort((a, b) => (b.abertas > 0) - (a.abertas > 0) || b.ult - a.ult)\n\n    const sel = d2.state.sel || itens[0]?.k || ''\n    const [entidade, oid] = sel.split(':')\n\n    const rail = `<aside class=\"rail\">\n      <div class=\"filtros\">\n        <button data-filtro=\"inbox\" class=\"${filtro === 'inbox' ? 'on' : ''}\">Pra mim</button>\n        <button data-filtro=\"todas\" class=\"${filtro === 'todas' ? 'on' : ''}\">Todas</button>\n      </div>\n      ${itens.length ? itens.map((it) => {\n        const [ent, eid] = it.k.split(':')\n        return `<a href=\"#\" data-sel=\"${esc(it.k)}\" data-key=\"${esc(it.k)}\" class=\"${it.k === sel ? 'on' : ''}\">\n          <span class=\"t\">${esc(nomeDe(d2, ent, eid) || eid)}</span>\n          <span class=\"meta\"><span class=\"chip\">${esc(ENTIDADE[ent] || ent)}</span>${it.abertas ? estado(`${it.abertas} aberta${it.abertas > 1 ? 's' : ''}`, 'warn') : ''}<span>${esc(rel(new Date(it.ult)))}</span></span>\n        </a>`\n      }).join('') : `<div class=\"vazio\">${filtro === 'inbox' ? 'Nenhuma pergunta pra você.' : 'Nenhuma conversa.'}</div>`}\n    </aside>`\n\n    let corpo = '<main><section><div class=\"vazio\">Escolha uma conversa.</div></section></main>'\n    const lista = grupos[sel]\n    if (lista) {\n      const respostasDe = (pid) => lista.filter((m) => m.tipo === 'resposta' && id(m.respondeA) === pid)\n        .sort((a, b) => ms(a.createdAt) - ms(b.createdAt))\n      const raiz = lista.filter((m) => m.tipo !== 'resposta').sort((a, b) => ms(a.createdAt) - ms(b.createdAt))\n      const titulo = nomeDe(d2, entidade, oid) || oid\n      const fio = raiz.map((m) => {\n        const abrindo = d2.state.abrindo === id(m)\n        const enviando = d2.state.enviando === id(m)\n        return `<div class=\"fio ${aberta(m) ? 'aberta' : ''}\" data-key=\"${esc(id(m))}\">\n          <div class=\"meta\">${quem(d2, m.autor, m)}<span class=\"chip\">${esc(m.tipo || 'mensagem')}</span>\n            ${aberta(m) ? estado('aberta', 'warn') : m.tipo === 'pergunta' ? estado('respondida', 'ok') : ''}\n            ${meMenciona(m) ? '<span class=\"chip voce\">Menciona você</span>' : praMim(m) ? '<span class=\"chip voce\">Pra você</span>' : ''}<span class=\"mono\">${esc(quando(m.createdAt))}</span></div>\n          <div class=\"txt\">${comMencoes(m.texto, todos)}</div>${evid(m.evidencia)}\n          ${respostasDe(id(m)).map((r) => `<div class=\"resp\" data-key=\"${esc(id(r))}\">\n            <div class=\"meta\">${quem(d2, r.autor, r)}${meMenciona(r) ? '<span class=\"chip voce\">Menciona você</span>' : ''}<span class=\"mono\">${esc(quando(r.createdAt))}</span></div>\n            <div class=\"txt\">${comMencoes(r.texto, todos)}</div>${evid(r.evidencia)}</div>`).join('')}\n          ${!aberta(m) ? '' : abrindo ? `<textarea data-id=\"${esc(id(m))}\" placeholder=\"Resposta\"></textarea>\n            <div class=\"acoes\"><button data-cancelar>Cancelar</button>\n            <button class=\"pri\" data-responder=\"${esc(id(m))}\" ${enviando ? 'disabled' : trava}>${enviando ? 'Enviando…' : 'Enviar resposta'}</button></div>`\n            : `<div class=\"acoes\"><button data-abrir=\"${esc(id(m))}\" ${trava}>Responder</button></div>`}\n        </div>`\n      }).join('')\n      corpo = `<main>\n        ${d2.state.erro ? `<div class=\"erro\">${esc(d2.state.erro)}</div>` : ''}\n        <section><header><span class=\"chip\">${esc(ENTIDADE[entidade] || entidade)}</span>\n          <h2>${entidade === 'card' ? linkCard(oid, esc(titulo)) : esc(titulo)}</h2><span class=\"n\">${lista.length}</span></header>\n          ${fio || '<div class=\"vazio\">Sem mensagens.</div>'}</section>\n      </main>`\n    }\n\n    return `<div class=\"root\">\n      ${ui.topo(d2, 'Conversas', projetos, projetoId)}\n      ${ui.banner(d2)}\n      <div class=\"pagina\">${rail}${corpo}</div>\n    </div>`\n  },\n}"}},"usuarios":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"usuarios"}}}},"responder":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"responder"}}}},"mensagens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"mensagens"}}}},"cards":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cards"}}}},"features":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"features"}}}},"planos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"planos"}}}},"projetos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"projetos"}}}}}}}}}},{"_id":"6acf7a2c3b040e4cec33f306","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"pm-kanban","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const LIB = { url: 'https://gabz-playground.data2.media/file/dPZUG5PfHXNVs-sT1YERj', css: 'https://gabz-playground.data2.media/file/qChFGH9hteWjSZxe3rSAl' }\nconst carregando = (d2) => `<div class=\"root carregando\">${d2.lib.state(LIB) === 'error' ? `Não carregou a skin: ${d2.lib.error(LIB)}` : 'Carregando…'}</div>`\nlet ui, esc, id, ms, recs, ativos, eu, rel, estado, linkCard, opts, projetoAtual, tagChips\n\nfunction recarregar(d2) {\n  ui.carregar(d2, 'projetos').then(() => {\n    const projetoId = ui.projetoAtual(d2, ui.recs(d2.data('projetos')))\n    if (!projetoId) return\n    for (const k of ['cards', 'planos', 'rodadas']) ui.carregar(d2, k, { projetoId })\n    ui.carregar(d2, 'mensagens', { tipo: 'pergunta' })\n  })\n}\n\nasync function mover(d2, cardId, para) {\n  const card = recs(d2.data('cards')).find((c) => id(c) === cardId)\n  if (!card || card.coluna === para) return\n  const rotulo = ui.ROTULO[para] || para\n  let motivo\n  if (ui.PEDE_MOTIVO.includes(para)) {\n    motivo = (await d2.dialog.prompt(`Motivo (${rotulo}):`, '') || '').trim()\n    if (!motivo) return ui.avisar(d2, 'warn', `Não moveu para ${rotulo}: o motivo é obrigatório.`)\n  }\n  d2.setState({ movendo: cardId })\n  try {\n    const r = await ui.invocar(d2, 'transicao', { entidade: 'card', entidadeId: cardId, para, atorId: eu(d2), via: 'painel', motivo })\n    ui.avisar(d2, 'ok', `${card.titulo}: ${ui.ROTULO[r.de] || r.de} → ${ui.ROTULO[r.para] || r.para}`)\n  } catch (err) {\n    ui.avisar(d2, 'bad', `Não moveu para ${rotulo}: ${err.message}`, 12000)\n  } finally {\n    d2.setState({ movendo: '' })\n    recarregar(d2)\n  }\n}\n\nexport default {\n  css: `\n    .filtros { display:flex; align-items:center; gap:8px; padding:12px 24px; border-bottom:1px solid var(--line); flex-wrap:wrap; }\n    .filtros input { width:220px; }\n    .board { display:grid; grid-template-columns:repeat(4,minmax(240px,1fr)); gap:12px; padding:16px 24px; overflow-x:auto; align-items:start; }\n    .col { background:var(--p1); border:1px solid var(--line); border-radius:8px; min-height:240px; display:flex; flex-direction:column; transition:border-color .14s var(--ease), background .14s var(--ease); }\n    .col > header { display:flex; align-items:center; gap:8px; padding:10px 12px; border-bottom:1px solid var(--line); }\n    .col > header h2 { font-size:11px; font-weight:600; color:var(--tx2); text-transform:uppercase; letter-spacing:.06em; }\n    .col .lista { display:grid; gap:8px; padding:8px; flex:1; }\n    .col.alvo { border-color:var(--acc); background:var(--acc-soft); }\n    .k { background:var(--p2); border:1px solid var(--line); border-radius:6px; padding:10px; display:grid; gap:8px; cursor:grab; user-select:none; transition:opacity .14s var(--ease), transform .11s var(--ease); }\n    .k:active { cursor:grabbing; }\n    .k[draggable=false] { cursor:default; }\n    .k.arrastando { opacity:.4; }\n    .k.movendo { opacity:.6; pointer-events:none; }\n    .k .tit { font-size:12px; line-height:1.35; }\n    .k .feat { color:var(--tx3); font-size:10px; text-transform:uppercase; letter-spacing:.06em; }\n    .k .mae { color:var(--tx3); font-size:11px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n    .k .linha { display:flex; flex-wrap:wrap; gap:4px; }\n    .pessoas { display:grid; grid-template-columns:auto 1fr; gap:2px 8px; font-size:11px; }\n    .pessoas span:nth-child(odd) { color:var(--tx3); }\n  `,\n\n  mounted(d2) {\n    d2.on('select[name=plano]', 'change', (e, el) => { d2.state.plano = el.value })\n    d2.on('select[name=tag]', 'change', (e, el) => { d2.state.tag = el.value })\n    d2.on('select[name=resp]', 'change', (e, el) => { d2.state.resp = el.value })\n    d2.on('input[name=busca]', 'input', (e, el) => { d2.state.busca = el.value })\n\n    // ponytail: drag & drop nativo do HTML5 (só mouse); trocar pela receita de pointer events se precisar de toque\n    let arrastado = ''\n    d2.on('[data-k]', 'dragstart', (e, el) => {\n      arrastado = (e.target.closest?.('[data-k]') || el).dataset.k\n      e.dataTransfer.setData('text/plain', arrastado)\n      e.dataTransfer.effectAllowed = 'move'\n      requestAnimationFrame(() => d2.$(`[data-k=\"${arrastado}\"]`)?.classList.add('arrastando'))\n    })\n    d2.on('[data-k]', 'dragend', () => {\n      d2.$$('.arrastando, .alvo').forEach((n) => n.classList.remove('arrastando', 'alvo'))\n      arrastado = ''\n    })\n    d2.on('[data-col]', 'dragover', (e, el) => {\n      e.preventDefault()\n      e.dataTransfer.dropEffect = 'move'\n      const col = e.target.closest?.('[data-col]') || el\n      d2.$$('.alvo').forEach((n) => n !== col && n.classList.remove('alvo'))\n      col.classList.add('alvo')\n    })\n    d2.on('[data-col]', 'drop', (e, el) => {\n      e.preventDefault()\n      const col = e.target.closest?.('[data-col]') || el\n      col.classList.remove('alvo')\n      const cardId = e.dataTransfer.getData('text/plain') || arrastado\n      if (cardId) mover(d2, cardId, col.dataset.col)\n    })\n  },\n\n  updated(d2) {\n    if (!ui || d2.state.iniciado) return\n    d2.state.iniciado = true\n    ui.carregarUsuarios(d2)\n    ui.ligarTopo(d2, () => recarregar(d2), { plano: '', tag: '' })\n    ui.vigiar(d2, () => recarregar(d2))\n  },\n\n  render(d2) {\n    ui = d2.lib(LIB)\n    if (!ui) return carregando(d2)\n    ;({ esc, id, ms, recs, ativos, eu, rel, estado, linkCard, opts, projetoAtual, tagChips } = ui)\n\n    const usuarios = ativos(d2)\n    const nome = (uid) => ui.nome(d2, uid) || '—'\n    const projetos = recs(d2.data('projetos'))\n    const projetoId = projetoAtual(d2, projetos)\n    const planos = recs(d2.data('planos')).filter((p) => id(p.projetoId) === projetoId && p.estado !== 'rascunho')\n    const tagsProjeto = projetos.find((p) => id(p) === projetoId)?.tags || []\n    const mensagens = recs(d2.data('mensagens'))\n    const rodadas = recs(d2.data('rodadas')).filter((r) => r.fonte !== 'fixture')\n    const busca = String(d2.state.busca || '').toLowerCase()\n    const podeMover = !!eu(d2)\n\n    const todos = recs(d2.data('cards')).filter((c) => id(c.projetoId) === projetoId && c.coluna !== 'descartado')\n    const cards = todos.filter((c) =>\n      (!d2.state.plano || id(c.planoId) === d2.state.plano) &&\n      (!d2.state.tag || (c.tags || []).includes(d2.state.tag)) &&\n      (!d2.state.resp || id(c.responsavel) === d2.state.resp) &&\n      (!busca || String(c.titulo).toLowerCase().includes(busca)))\n\n    const perguntas = {}\n    for (const m of mensagens) if (m.tipo === 'pergunta' && !m.respondidaEm) perguntas[m.anexadoA?.id] = (perguntas[m.anexadoA?.id] || 0) + 1\n    const ultima = {}\n    for (const r of rodadas) {\n      const k = `${id(r.cardId)}:${r.camada}`\n      if (!ultima[k] || ms(r.createdAt) > ms(ultima[k].createdAt)) ultima[k] = r\n    }\n    const testes = (cid) => ['decisao', 'turno'].map((camada) => {\n      const r = ultima[`${cid}:${camada}`]\n      if (!r) return ''\n      return estado(`${camada} ${r.aprovados}/${r.total}`, r.aprovados === r.total ? 'ok' : 'bad')\n    }).join('')\n\n    const cardHtml = (c) => {\n      const cid = id(c)\n      const p = planos.find((x) => id(x) === id(c.planoId))\n      const np = perguntas[cid] || 0\n      return `<div class=\"k ${d2.state.movendo === cid ? 'movendo' : ''}\" draggable=\"${podeMover}\" data-k=\"${esc(cid)}\" data-key=\"${esc(cid)}\">\n        <div class=\"feat\">${esc(p?.titulo || 'sem plano')}</div>\n        <div class=\"tit\">${linkCard(cid, esc(c.titulo))}</div>\n        <div class=\"linha\">\n          ${tagChips(c.tags)}\n          ${np ? estado(`${np} pergunta${np > 1 ? 's' : ''}`, 'warn') : ''}\n          ${testes(cid)}\n        </div>\n        <div class=\"pessoas\">\n          <span>Responsável</span><span>${esc(nome(c.responsavel))}</span>\n          <span>Revisor</span><span>${c.revisor ? esc(nome(c.revisor)) : '—'}</span>\n          <span>Na coluna</span><span>${esc(rel(c.movidoEm || c.updatedAt))}</span>\n        </div>\n      </div>`\n    }\n\n    const colunas = ui.COLUNAS.map(([col, rot]) => {\n      const dela = cards.filter((c) => c.coluna === col).sort((a, b) => ms(b.movidoEm || b.updatedAt) - ms(a.movidoEm || a.updatedAt))\n      return `<section class=\"col\" data-col=\"${col}\" data-key=\"${col}\">\n        <header><h2>${rot}</h2><span class=\"n\">${dela.length}</span></header>\n        <div class=\"lista\">${dela.map(cardHtml).join('')}</div>\n      </section>`\n    }).join('')\n\n    return `<div class=\"root\">\n      ${ui.topo(d2, 'Kanban', projetos, projetoId)}\n      ${ui.banner(d2)}\n      <div class=\"filtros\">\n        <input name=\"busca\" placeholder=\"Buscar tarefa\" value=\"${esc(d2.state.busca || '')}\" autocomplete=\"off\">\n        <label class=\"sel\">Plano <select name=\"plano\"><option value=\"\">Todos</option>${opts(planos, d2.state.plano, (p) => `${p.titulo} (${ui.ESTADO_PLANO[p.estado] || p.estado})`)}</select></label>\n        <label class=\"sel\">Tag <select name=\"tag\"><option value=\"\">Todas</option>${tagsProjeto.map((t) => `<option ${t === d2.state.tag ? 'selected' : ''}>${esc(t)}</option>`).join('')}</select></label>\n        <label class=\"sel\">Responsável <select name=\"resp\"><option value=\"\">Todos</option>${opts(usuarios, d2.state.resp, (u) => u.nome)}</select></label>\n        <span class=\"meta\">Arraste uma tarefa para outra coluna. Pronto só sai de review e você vira o revisor; bloquear pede motivo.</span>\n      </div>\n      <div class=\"board\">${colunas}</div>\n      ${ui.avisoHtml(d2)}\n    </div>`\n  },\n}"}},"usuarios":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"usuarios"}}}},"transicao":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"transicao"}}}},"cards":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"cards"}}}},"features":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"features"}}}},"mensagens":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"mensagens"}}}},"rodadas":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"rodadas"}}}},"projetos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"projetos"}}}},"planos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"planos"}}}}}}}}}},{"_id":"6acf8942364521922264c5a9","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"extends":"data2-core-primitives@Block","component":"pm-pode-publicar","package":"gabz-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const LIB = { url: 'https://gabz-playground.data2.media/file/dPZUG5PfHXNVs-sT1YERj', css: 'https://gabz-playground.data2.media/file/qChFGH9hteWjSZxe3rSAl' }\nconst carregando = (d2) => `<div class=\"root carregando\">${d2.lib.state(LIB) === 'error' ? `Não carregou a skin: ${d2.lib.error(LIB)}` : 'Carregando…'}</div>`\nlet ui, esc, id, ms, recs, eu, rel, quando, estado, estadoPlano, travado\nconst TOM = { aprovado: 'ok', aviso: 'warn', bloqueado: 'bad', sem_projeto: 'bad' }\nconst PRONTAS = ['pronto_para_publicar', 'pronto_oculto']\n\nconst projetoAtual = (d2) => ui.projetoAtual(d2, recs(d2.data('projetos')))\n\nasync function avaliar(d2) {\n  const projetoId = projetoAtual(d2)\n  if (!projetoId) return\n  d2.setState({ avaliando: true })\n  try {\n    const res = await d2.rush('gateAvaliar').invoke({ projetoId, simular: true })\n    // resposta de um projeto que já não está na tela é descartada\n    if (projetoAtual(d2) === projetoId) d2.setState({ av: res?.data ?? res })\n  } catch (err) {\n    if (projetoAtual(d2) === projetoId) ui.avisar(d2, 'bad', `Não avaliou: ${err.message}`, 10000)\n  } finally {\n    d2.setState({ avaliando: false })\n  }\n}\n\nasync function publicar(d2) {\n  const av = d2.state.av\n  if (!av) return\n  const body = { projetoId: projetoAtual(d2), usuarioId: eu(d2) }\n  const n = (av.bloqueios || []).length\n  if (av.veredito === 'bloqueado') {\n    const motivo = await d2.dialog.prompt(`Gate bloqueado (${n} bloqueio${n === 1 ? '' : 's'}). Publicar com force exige motivo:`, '')\n    if (!motivo) return ui.avisar(d2, 'warn', 'Publish cancelado: force sem motivo.', 10000)\n    Object.assign(body, { force: true, motivo })\n  } else {\n    const pergunta = av.veredito === 'aviso' ? `Publicar mesmo com ${n} aviso${n === 1 ? '' : 's'}?` : 'Publicar o bundle?'\n    if (!(await d2.dialog.confirm(pergunta))) return\n  }\n  d2.setState({ publicando: true })\n  try {\n    const r = await ui.invocar(d2, 'publicar', body)\n    const pubs = (r.publicadas || []).join(', ') || 'nenhum plano'\n    ui.avisar(d2, 'ok', `Publicado ${r.bundleId}${r.forcado ? ' (com force)' : ''}. Viraram publicada: ${pubs}.`, 10000)\n    recarregar(d2)\n    await avaliar(d2)\n  } catch (err) {\n    ui.avisar(d2, 'bad', `Não publicou: ${err.message}`, 15000)\n  } finally {\n    d2.setState({ publicando: false })\n  }\n}\n\nasync function moverPronta(d2, planoId, nome) {\n  d2.setState({ movendo: planoId })\n  try {\n    const r = await ui.invocar(d2, 'transicao', { entidade: 'plano', entidadeId: planoId, para: 'pronto_para_publicar', atorId: eu(d2), via: 'painel', motivo: 'Movido pela aba Pode publicar?' })\n    ui.avisar(d2, 'ok', `${nome}: ${ui.ESTADO_PLANO[r.de] || r.de} → ${ui.ESTADO_PLANO[r.para] || r.para}`, 10000)\n    await avaliar(d2)\n  } catch (err) {\n    ui.avisar(d2, 'warn', `${nome} não moveu: ${err.message}`, 10000)\n  } finally {\n    d2.setState({ movendo: '' })\n  }\n}\n\n// polling só nos datasets: avaliar grava um registro em pm-gates\nfunction recarregar(d2) {\n  ui.carregar(d2, 'projetos').then(() => {\n    const projetoId = projetoAtual(d2)\n    if (projetoId) ui.carregar(d2, 'gates', { projetoId })\n  })\n}\n\nexport default {\n  css: `\n    main { padding:24px; display:grid; gap:16px; max-width:1200px; }\n    .cab { display:flex; align-items:flex-start; gap:16px; }\n    .cab h1 { font-size:16px; font-weight:600; letter-spacing:-.015em; }\n    .cab p { color:var(--tx2); margin-top:4px; }\n    .cab .sp { flex:1; }\n    .veredito { display:grid; grid-template-columns:auto repeat(4,minmax(0,1fr)); gap:16px; align-items:center; padding:16px; }\n    .veredito .grande { font-size:15px; font-weight:600; display:flex; align-items:center; gap:8px; }\n    .num span { display:block; font-size:10px; color:var(--tx3); text-transform:uppercase; letter-spacing:.06em; margin-bottom:2px; }\n    table { width:100%; border-collapse:collapse; }\n    th { text-align:left; font-size:10px; font-weight:600; color:var(--tx3); text-transform:uppercase; letter-spacing:.06em; padding:8px 16px; border-bottom:1px solid var(--line); }\n    td { padding:10px 16px; border-bottom:1px solid var(--line2); vertical-align:top; }\n    tr:last-child td { border-bottom:0; }\n    .falta { color:var(--tx2); font-size:11px; }\n    .grid2 { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:16px; align-items:start; }\n    @media (max-width:900px) { .veredito { grid-template-columns:1fr 1fr; } .grid2 { grid-template-columns:1fr; } main { padding:16px; } }\n  `,\n\n  mounted(d2) {\n    d2.on('[data-reavaliar]', 'click', () => avaliar(d2))\n    d2.on('[data-publicar]', 'click', () => publicar(d2))\n    d2.on('[data-mover]', 'click', (e, el) => {\n      const b = e.target.closest?.('[data-mover]') || el\n      moverPronta(d2, b.dataset.mover, b.dataset.nome)\n    })\n  },\n\n  updated(d2) {\n    if (!ui) return\n    if (!d2.state.iniciado) {\n      d2.state.iniciado = true\n      ui.carregarUsuarios(d2)\n      ui.ligarTopo(d2, () => { recarregar(d2); avaliar(d2) }, { av: null })\n      ui.vigiar(d2, () => recarregar(d2))\n    }\n    if (d2.state.tentou || !projetoAtual(d2)) return\n    d2.state.tentou = true\n    avaliar(d2)\n  },\n\n  render(d2) {\n    ui = d2.lib(LIB)\n    if (!ui) return carregando(d2)\n    ;({ esc, id, ms, recs, eu, rel, quando, estado, estadoPlano, travado } = ui)\n\n    const projetos = recs(d2.data('projetos'))\n    const projeto = projetos.find((p) => id(p) === projetoAtual(d2))\n    const av = d2.state.av\n    const feats = av?.planos || []\n    const bloqueios = av?.bloqueios || []\n    const trava = travado(d2)\n    const gates = recs(d2.data('gates')).filter((g) => id(g.projetoId) === id(projeto))\n      .sort((a, b) => ms(b.em) - ms(a.em)).slice(0, 10)\n\n    const linhas = feats.map((f) => {\n      const pronta = PRONTAS.includes(f.estado)\n      const entra = pronta && f.passaria\n      const podeMover = !pronta && f.passaria\n      return `<tr data-key=\"${esc(f._id)}\">\n        <td>${esc(f.nome)}</td>\n        <td>${estadoPlano(f.estado)}</td>\n        <td>${entra ? estado('entra', 'ok') : estado('bloqueia', 'bad')}</td>\n        <td class=\"falta\">${(f.faltando || []).map(esc).join('<br>') || (podeMover ? 'Nada falta; o plano ainda não foi marcado como pronto.' : '—')}</td>\n        <td>${podeMover ? `<button data-mover=\"${esc(f._id)}\" data-nome=\"${esc(f.nome)}\" ${d2.state.movendo === f._id ? 'disabled' : trava}>Marcar pronto</button>` : ''}</td>\n      </tr>`\n    }).join('')\n\n    const caminhos = []\n    for (const f of feats) {\n      if (!PRONTAS.includes(f.estado) && f.passaria) caminhos.push(`<b>${esc(f.nome)}</b>: todas as tarefas prontas. Marque o plano como pronto pra publicar (botão na tabela).`)\n      else if (!f.passaria) caminhos.push(`<b>${esc(f.nome)}</b>: ${(f.faltando || []).map(esc).join('; ')}. Resolva no ${ui.linkAba('Kanban', 'Kanban')}, ou esconda atrás de flag (flagRef) e marque como pronto (oculto).`)\n    }\n\n    const historico = gates.length ? gates.map((g) => `<tr data-key=\"${esc(id(g))}\">\n        <td class=\"mono\">${esc(quando(g.em))}</td>\n        <td>${estado(g.veredito || '—', TOM[g.veredito] || 'info')}</td>\n        <td>${g.publicado ? `${estado('publicado', 'ok')} <span class=\"mono\">${esc(g.bundleCandidato)}</span>` : '<span class=\"falta\">avaliação</span>'}</td>\n        <td class=\"falta\">${g.forcadoPor ? `force por ${esc(ui.nome(d2, g.forcadoPor) || g.forcadoPor)}: ${esc(g.motivo || '')}` : `${(g.bloqueios || []).length} bloqueio(s)`}</td>\n      </tr>`).join('') : '<tr><td colspan=\"4\" class=\"vazio\">Nenhum gate registrado.</td></tr>'\n\n    const v = av?.veredito\n    return `<div class=\"root\">\n      ${ui.topo(d2, 'Publicar', projetos, projetoAtual(d2))}\n      ${ui.banner(d2)}\n      <main>\n        <div class=\"cab\">\n          <div><h1>Pode publicar?</h1><p>O publish é do system inteiro: tudo o que mudou desde o último publish vai junto. Esta tela mostra se tudo o que vai junto está pronto. Sem adapter de publish real no projeto, o pm-publicar recusa.</p></div>\n          <span class=\"sp\"></span>\n          <button data-reavaliar ${d2.state.avaliando ? 'disabled' : ''}>${d2.state.avaliando ? 'Avaliando…' : 'Reavaliar'}</button>\n          <button class=\"pri\" data-publicar ${!av || d2.state.publicando ? 'disabled' : trava}>${d2.state.publicando ? 'Publicando…' : v === 'bloqueado' ? 'Publicar com force' : 'Publicar bundle'}</button>\n        </div>\n        <section class=\"veredito\">\n          <div class=\"grande\">${av ? estado(v, TOM[v] || 'info') : '<span class=\"falta\">avaliando…</span>'}</div>\n          <div class=\"num\"><span>Modo do gate</span>${esc(av?.modo || projeto?.gateModo || 'aviso')}</div>\n          <div class=\"num\"><span>Bundle atual</span><span class=\"mono\" style=\"display:inline;text-transform:none;letter-spacing:0;font-size:12px;color:var(--tx)\">${esc(projeto?.bundleAtual || 'nenhum')}</span></div>\n          <div class=\"num\"><span>Último publish</span>${projeto?.ultimoPublishEm ? esc(rel(projeto.ultimoPublishEm)) : 'nunca'}</div>\n          <div class=\"num\"><span>Planos no bundle</span>${feats.length}</div>\n        </section>\n        <section><header><h2>Planos no bundle</h2><span class=\"n\">${feats.length}</span></header>\n          <table><thead><tr><th>Plano</th><th>Estado</th><th>Gate</th><th>O que falta</th><th></th></tr></thead>\n          <tbody>${linhas || '<tr><td colspan=\"5\" class=\"vazio\">Nada mudou desde o último publish.</td></tr>'}</tbody></table>\n        </section>\n        <div class=\"grid2\">\n          <section><header><h2>O que bloqueia</h2><span class=\"n\">${bloqueios.length}</span></header>\n            ${bloqueios.length ? bloqueios.map((b) => `<div class=\"row\"><div class=\"txt\">${esc(b)}</div></div>`).join('') : '<div class=\"vazio\">Nada bloqueia.</div>'}\n          </section>\n          <section><header><h2>Caminhos pra destravar</h2></header>\n            ${caminhos.length ? caminhos.map((c) => `<div class=\"row\"><div class=\"txt\">${c}</div></div>`).join('') : '<div class=\"vazio\">Nada a destravar.</div>'}\n          </section>\n        </div>\n        <section><header><h2>Histórico do gate</h2></header>\n          <table><thead><tr><th>Quando</th><th>Veredito</th><th>Resultado</th><th>Detalhe</th></tr></thead><tbody>${historico}</tbody></table>\n        </section>\n      </main>\n      ${ui.avisoHtml(d2)}\n    </div>`\n  },\n}"}},"usuarios":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"usuarios"}}}},"gateAvaliar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"gateAvaliar"}}}},"publicar":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"publicar"}}}},"transicao":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"transicao"}}}},"projetos":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"projetos"}}}},"gates":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"gates"}}}}}}}}}},{"_id":"5ed9bed7b9e0891ce913e884","component":"data2-core-types@Component","params":{"package":"data2-core","component":"DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}},{"_id":"5f472ae463c680de4ff296e9","component":"data2-core-types@Component","params":{"package":"data2-core","component":"Data2TableDataSource","extends":"data2-core@DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}},{"_id":"6a4693c6bf38d382814feb4c","component":"data2-core-types@Component","system":"6863d782e78450ee0fd57fc7","params":{"component":"crm-tokens","package":"gabz-playground","definition":{"darkMode":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}},"density":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.density"}},"fontFamily":"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif","semanticsLight":{"colorPrimary":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}},"colorPrimaryHover":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 72%, white)"]}},"colorPrimaryActive":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 80%, black)"]}},"colorPrimaryBg":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 8%, white)"]}},"colorPrimaryBgHover":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 16%, white)"]}},"colorSuccess":"#22c55e","colorSuccessHover":"color-mix(in srgb, #22c55e 72%, white)","colorSuccessActive":"color-mix(in srgb, #22c55e 80%, black)","colorSuccessBg":"color-mix(in srgb, #22c55e 8%, white)","colorSuccessBgHover":"color-mix(in srgb, #22c55e 16%, white)","colorWarning":"#f59e0b","colorWarningHover":"color-mix(in srgb, #f59e0b 72%, white)","colorWarningActive":"color-mix(in srgb, #f59e0b 80%, black)","colorWarningBg":"color-mix(in srgb, #f59e0b 8%, white)","colorWarningBgHover":"color-mix(in srgb, #f59e0b 16%, white)","colorError":"#ef4444","colorErrorHover":"color-mix(in srgb, #ef4444 72%, white)","colorErrorActive":"color-mix(in srgb, #ef4444 80%, black)","colorErrorBg":"color-mix(in srgb, #ef4444 8%, white)","colorErrorBgHover":"color-mix(in srgb, #ef4444 16%, white)","colorInfo":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}},"colorInfoHover":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 72%, white)"]}},"colorInfoActive":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 80%, black)"]}},"colorInfoBg":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 8%, white)"]}},"colorInfoBgHover":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 16%, white)"]}},"colorText":"rgba(0,0,0,0.88)","colorTextSecondary":"rgba(0,0,0,0.65)","colorTextTertiary":"rgba(0,0,0,0.45)","colorTextDisabled":"rgba(0,0,0,0.25)","colorTextLightSolid":"#ffffff","colorBorder":"#d9d9d9","colorBorderSecondary":"#f0f0f0","colorBgContainer":"#ffffff","colorBgLayout":"#f5f5f5","colorBgContainerDisabled":"rgba(0,0,0,0.04)","colorBgSolid":"rgba(0,0,0,0.88)","colorBgSolidHover":"rgba(0,0,0,0.75)","colorBgSolidActive":"#000000","colorFillTertiary":"rgba(0,0,0,0.04)","colorFillSecondary":"rgba(0,0,0,0.06)","colorFill":"rgba(0,0,0,0.15)","colorBgTextHover":"rgba(0,0,0,0.06)","colorBgTextActive":"rgba(0,0,0,0.15)"},"semanticsDark":{"colorPrimary":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 86%, white)"]}},"colorPrimaryHover":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 66%, white)"]}},"colorPrimaryActive":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 78%, black)"]}},"colorPrimaryBg":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 22%, black)"]}},"colorPrimaryBgHover":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 32%, black)"]}},"colorSuccess":"color-mix(in srgb, #22c55e 86%, white)","colorSuccessHover":"color-mix(in srgb, #22c55e 66%, white)","colorSuccessActive":"color-mix(in srgb, #22c55e 78%, black)","colorSuccessBg":"color-mix(in srgb, #22c55e 22%, black)","colorSuccessBgHover":"color-mix(in srgb, #22c55e 32%, black)","colorWarning":"color-mix(in srgb, #f59e0b 86%, white)","colorWarningHover":"color-mix(in srgb, #f59e0b 66%, white)","colorWarningActive":"color-mix(in srgb, #f59e0b 78%, black)","colorWarningBg":"color-mix(in srgb, #f59e0b 22%, black)","colorWarningBgHover":"color-mix(in srgb, #f59e0b 32%, black)","colorError":"color-mix(in srgb, #ef4444 86%, white)","colorErrorHover":"color-mix(in srgb, #ef4444 66%, white)","colorErrorActive":"color-mix(in srgb, #ef4444 78%, black)","colorErrorBg":"color-mix(in srgb, #ef4444 22%, black)","colorErrorBgHover":"color-mix(in srgb, #ef4444 32%, black)","colorInfo":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 86%, white)"]}},"colorInfoHover":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 66%, white)"]}},"colorInfoActive":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 78%, black)"]}},"colorInfoBg":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 22%, black)"]}},"colorInfoBgHover":{"component":"data2-core-functions@StringConcat","params":{"portions":["","color-mix(in srgb, ",{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.accent"}}," 32%, black)"]}},"colorText":"rgba(255,255,255,0.85)","colorTextSecondary":"rgba(255,255,255,0.65)","colorTextTertiary":"rgba(255,255,255,0.45)","colorTextDisabled":"rgba(255,255,255,0.25)","colorTextLightSolid":"#ffffff","colorBorder":"#424242","colorBorderSecondary":"#303030","colorBgContainer":"#141414","colorBgLayout":"#0f0f0f","colorBgContainerDisabled":"rgba(255,255,255,0.08)","colorBgSolid":"rgba(255,255,255,0.85)","colorBgSolidHover":"rgba(255,255,255,0.95)","colorBgSolidActive":"#ffffff","colorFillTertiary":"rgba(255,255,255,0.08)","colorFillSecondary":"rgba(255,255,255,0.12)","colorFill":"rgba(255,255,255,0.18)","colorBgTextHover":"rgba(255,255,255,0.08)","colorBgTextActive":"rgba(255,255,255,0.15)"}}}}]}},{"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":{"component":"data2-core-flow@If","displayName":"management exception never picks the system","params":{"compare":{"component":"data2-core-logical-operators@Or","params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}}},{"component":"data2-core-logical-operators@Not","params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}}}}}]}},"then":{"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"else":{"system":{"component":"data2-core-primitives@String","params":{"content":"63611bdff62ab6060b8396ac"}}}}},"else":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"},"compare":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"has_access"}}}}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"sessionExpiresIn":{"component":"data2-core-primitives@Number","params":{"content":604800}},"sessionRenewal":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"identityProviders":[{"provider":{"component":"data2-core-primitives@String","params":{"content":"GOOGLE"}},"clientId":{"component":"data2-core-primitives@String","params":{"content":"55470861603-22pvfc1t49lp8cjnbfk71s5ct9hp1q1v.apps.googleusercontent.com"}}}]},"reference":"Data2BuilderAuthentication","updatedAt":"2026-10-14T16:52:02.312Z","updateMetadata":{"updatedBy":{"user":"5f1609be1ca96def427e1559"}}},{"_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"},{"_id":"5f060ee51ca96def42f3fbd1","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"UsersTableDataSource"}},"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}}},"reference":"UsersDataSet","updatedAt":"2026-03-04T21:16:40.291Z"},{"component":"data2-core@DataSet","reference":"SessionsDataSet","params":{"requiresConfirmation":false,"pk":"key","datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"data2sessionsdatasource"}}}},{"component":"data2-core@ServerSessionsDataSource","reference":"data2sessionsdatasource","params":{}},{"reference":"UsersTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"_id":"5f1600b70528b92601890f75","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ServiceComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ServiceComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:20.208Z","createdAt":"2020-07-20T20:38:15.436Z"},{"_id":"5f1602190528b92601890f7d","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":40000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentInstancesTableDataSource"}},"sort":{"_id":1},"pk":"_id","autoEdit":true,"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:07.089Z","createdAt":"2020-07-20T20:44:09.350Z"},{"_id":"5f16017f0528b92601890f7a","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"clientApplicationDomain"}}},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"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":"6a464cf2209db9c3663931ce","component":"data2-core-primitives@Router","system":"6863d782e78450ee0fd57fc7","displayName":"CRM Router","params":{"routerType":{"component":"data2-core-primitives@String","params":{"content":"browser"}},"routes":[{"component":"data2-core-primitives@Route","params":{"path":"","name":"Dashboard","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"HCqw6W4BCcQBQf5JjTKJc"}}}},{"component":"data2-core-primitives@Route","params":{"path":"/pipeline","name":"Pipeline","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"ugdNM0z8ZHI_g8A7_3Mgq"}}}},{"component":"data2-core-primitives@Route","params":{"path":"/records","name":"Records","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"RbZOaVZx40Tme4EA5JKIB"}}}},{"component":"data2-core-primitives@Route","params":{"path":"/record/:type/:id","name":"Detail","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"spI24dqM7WMOcTT3bXpWA"}}}}]},"reference":"crm-router"},{"_id":"6a85c338fbfb07f82090857e","component":"data2-core-primitives@Artboard","system":"6863d782e78450ee0fd57fc7","displayName":"Agent Chat","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Agent Chat"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":-575,"y":726,"exactX":-574.87,"exactY":726.27}}},"reference":"E06dp8enoXCBHXusuDPkP"},{"_id":"6a466f5a1035c33534235f70","component":"data2-core-primitives@Artboard","system":"6863d782e78450ee0fd57fc7","displayName":"CRM - Detail","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"CRM - Detail"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1200,"height":836}},"position":{"component":"data2-core-types@Position","params":{"x":2364,"y":799,"exactX":2363.73,"exactY":798.71}}},"reference":"spI24dqM7WMOcTT3bXpWA"},{"_id":"6a465aa0c4f6a71828529f00","component":"data2-core-primitives@Artboard","system":"6863d782e78450ee0fd57fc7","displayName":"CRM - Records","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"CRM - Records"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1200,"height":836}},"position":{"component":"data2-core-types@Position","params":{"x":1840,"y":-2806,"exactX":1840.27,"exactY":-2806.3}}},"reference":"RbZOaVZx40Tme4EA5JKIB"},{"_id":"6a465851fd69f89bce073f58","component":"data2-core-primitives@Artboard","system":"6863d782e78450ee0fd57fc7","displayName":"CRM - Pipeline","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"CRM - Pipeline"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1200,"height":836}},"position":{"component":"data2-core-types@Position","params":{"x":124,"y":-2974,"exactX":124.13,"exactY":-2973.58}}},"reference":"ugdNM0z8ZHI_g8A7_3Mgq"},{"_id":"6a4651fefb4b5485eb71b444","component":"data2-core-primitives@Artboard","system":"6863d782e78450ee0fd57fc7","displayName":"CRM - Dashboard","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"CRM - Dashboard"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1200,"height":836}},"position":{"component":"data2-core-types@Position","params":{"x":3206,"y":-836,"exactX":3205.61,"exactY":-836.5}}},"reference":"HCqw6W4BCcQBQf5JjTKJc"},{"_id":"0e4f01f19e38b768b0e0be88","parent":"6a85c338fbfb07f82090857e","component":"gabz-playground@agent-chat-shell","system":"6863d782e78450ee0fd57fc7","displayName":"AgentChatShell","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":"H1JZS2QMUE_mDODk_2mh6"},{"_id":"b81badfd5212bd46d9e49342","parent":"6a466f5a1035c33534235f70","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Detail Root","params":{"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":1200,"height":836}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#141414"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"#f4f6f8"}}}}}}]}}},"reference":"mC-q5F5bZ3rxPrXn7iH4U"},{"_id":"ec0fa8fdd46583db8630f064","parent":"6a465aa0c4f6a71828529f00","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Records Root","params":{"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":1200,"height":836}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#0f0f0f"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"#f4f6f8"}}}}}}]}}},"reference":"Qd3QPpD4wXagLaPkUX1t2"},{"_id":"74b438c6222d7521339a3076","parent":"6a465851fd69f89bce073f58","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Pipeline Root","params":{"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":1200,"height":836}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#0f0f0f"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"#f4f6f8"}}}}}}]}}},"reference":"FAWIRyMr2cAhOPrRD3cZa"},{"_id":"c949a2af9dd9491e0c3e8a66","parent":"6a4651fefb4b5485eb71b444","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Dashboard Root","params":{"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":1200,"height":836}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#0f0f0f"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"#f4f6f8"}}}}}}]}}},"index":0,"reference":"4HaEFVLA3n2nEeBWeSHd2"},{"_id":"03af2da3c708ee2becec99bd","parent":"b81badfd5212bd46d9e49342","component":"gabz-playground@ant-drawer","system":"6863d782e78450ee0fd57fc7","displayName":"Edit Drawer","params":{"title":"Edit Lead","placement":"right","width":440,"closable":true,"open":false,"tokens":{"component":"gabz-playground@crm-tokens","params":{}},"openStore":"crm-ui","openKey":"editOpen","slots":[{"type":"gabz-playground@crm-lead-form","props":{"leads":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"5oU4u3o2nj4O709bIEU03DataSet"}}}}],"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":10,"height":10}}},"onClose":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.editOpen","value":false}}]}}},"reference":"Gwd6ApB7BjHD0ERuSDe3s"},{"_id":"2f53bb183d84d6b206cb84cb","parent":"b81badfd5212bd46d9e49342","component":"gabz-playground@ant-modal","system":"6863d782e78450ee0fd57fc7","displayName":"Follow-up Modal","params":{"title":"Log Follow-up","centered":true,"closable":true,"width":460,"open":false,"openStore":"crm-ui","openKey":"followupOpen","tokens":{"component":"gabz-playground@crm-tokens","params":{}},"slots":[{"type":"gabz-playground@crm-followup-form","props":{"activities":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"aNFrXXtt76NFND6IZ3RiVDataSet"}}}}],"onCancel":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.followupOpen","value":false}}]}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":200,"height":50}}}},"reference":"jz_wzOatTNiZPrZvEB3kE"},{"_id":"654c9bcfca59b1a5ebb165a7","parent":"b81badfd5212bd46d9e49342","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Detail Panel","params":{"position":{"component":"data2-core-types@Position","params":{"x":32,"y":32,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1136,"height":772}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#1f1f1f"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"#ffffff"}}}}}}]}},"border":{"component":"data2-core-types@Border","params":{"radius":12}}},"reference":"U0w_RIiFvI4BGQTUF80TC"},{"_id":"13393138b0bfa8c64438d35c","parent":"ec0fa8fdd46583db8630f064","component":"gabz-playground@ant-modal","system":"6863d782e78450ee0fd57fc7","displayName":"Follow-up Modal","params":{"title":"Log Follow-up","centered":true,"closable":true,"width":460,"open":false,"openStore":"crm-ui","openKey":"followupOpen","tokens":{"component":"gabz-playground@crm-tokens","params":{}},"slots":[{"type":"gabz-playground@crm-followup-form","props":{"activities":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"aNFrXXtt76NFND6IZ3RiVDataSet"}}}}],"onCancel":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.followupOpen","value":false}}]}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":200,"height":50}}}},"reference":"rGrq_GiH1W5hlKQ1oP0NU"},{"_id":"17ae3d5fe1a57156e656b535","parent":"ec0fa8fdd46583db8630f064","component":"gabz-playground@ant-table","system":"6863d782e78450ee0fd57fc7","displayName":"Accounts Table","params":{"dataset":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"4TS0LqYhG0LaNTd5ucvoZDataSet"}},"searchable":true,"sortable":true,"bordered":true,"pageSize":15,"searchPlaceholder":"Search accounts…","columns":[{"key":"name","title":"Name","dataIndex":"name"},{"key":"industry","title":"Industry","dataIndex":"industry","filterable":true},{"key":"size","title":"Size","dataIndex":"size","align":"right"},{"key":"status","title":"Status","dataIndex":"status","filterable":true},{"key":"annualRevenue","title":"Annual Revenue","dataIndex":"annualRevenue","align":"right"}],"rowActions":[{"key":"edit","label":"Edit"}],"tokens":{"component":"gabz-playground@crm-tokens","params":{}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":32,"y":132,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1136,"height":688}},"hide":{"component":"data2-core-comparison-operators@Different","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}}],"comparisonSubject":"accounts"}}}},"reference":"JsJbhEQtyYtHP9_a4rmHI"},{"_id":"2309c5c5e742ae2fd1b739c9","parent":"ec0fa8fdd46583db8630f064","component":"gabz-playground@crm-convert","system":"6863d782e78450ee0fd57fc7","displayName":"Convert Watcher","params":{"leads":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"5oU4u3o2nj4O709bIEU03DataSet"}},"accounts":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"4TS0LqYhG0LaNTd5ucvoZDataSet"}},"contacts":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"arn7JIj2wlGm39IPOxXSuDataSet"}},"deals":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"4uPM8-nCj6UT29zmMAt6FDataSet"}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":32,"y":8,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":200,"height":20}}}},"reference":"vSlNloBFzEZlrWIKbquDh"},{"_id":"27839958d6e3b8cab34906e4","parent":"ec0fa8fdd46583db8630f064","component":"gabz-playground@ant-tabs","system":"6863d782e78450ee0fd57fc7","displayName":"Records Tabs","params":{"items":[{"key":"leads","label":"Leads"},{"key":"deals","label":"Deals"},{"key":"accounts","label":"Accounts"},{"key":"contacts","label":"Contacts"}],"activeKey":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}},"onChange":{"component":"data2-core-flow@Series","params":{"actions":[]}},"tokens":{"component":"gabz-playground@crm-tokens","params":{}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":32,"y":76,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1136,"height":48}}}},"reference":"OAirDEy0RcElhBGaQAnxO"},{"_id":"344bd61366b5c69b398b2d93","parent":"ec0fa8fdd46583db8630f064","component":"gabz-playground@ant-button","system":"6863d782e78450ee0fd57fc7","displayName":"New Lead Btn","params":{"label":"+ New Lead","color":"primary","variant":"solid","tokens":{"component":"gabz-playground@crm-tokens","params":{}},"super":{"hide":{"component":"data2-core-comparison-operators@Different","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}}],"comparisonSubject":"leads"}},"position":{"component":"data2-core-types@Position","params":{"x":1010,"y":24,"freeTransform":true,"left":false,"right":true,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":130,"height":36}}},"onClick":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.editId","value":""}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.draft_name","value":""}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.draft_company","value":""}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.draft_email","value":""}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.draft_phone","value":""}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.draft_source","value":""}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.draft_status","value":"New"}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.draft_score","value":""}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.draft_ownerId","value":""}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.draft_notes","value":""}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.addType","value":"leads"}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.addOpen","value":true}}]}}},"reference":"-NR-ykNoj8VUoeuwePB88"},{"_id":"40d5039d3684f8ee6f29c955","parent":"ec0fa8fdd46583db8630f064","component":"gabz-playground@ant-drawer","system":"6863d782e78450ee0fd57fc7","displayName":"Edit Drawer","params":{"title":"Edit Lead","placement":"right","width":440,"closable":true,"open":false,"tokens":{"component":"gabz-playground@crm-tokens","params":{}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":10,"height":10}}},"onClose":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.editOpen","value":false}}]}},"slots":[{"type":"gabz-playground@crm-lead-form","props":{"leads":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"5oU4u3o2nj4O709bIEU03DataSet"}}}}],"openStore":"crm-ui","openKey":"editOpen"},"reference":"_upMVQdOhWsY85uBW7lcg"},{"_id":"4f6477cb2fc363f84329bbd9","parent":"ec0fa8fdd46583db8630f064","component":"gabz-playground@ant-table","system":"6863d782e78450ee0fd57fc7","displayName":"Leads Table","params":{"dataset":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"5oU4u3o2nj4O709bIEU03DataSet"}},"searchable":true,"sortable":true,"bordered":true,"pageSize":20,"searchPlaceholder":"Search leads…","columns":[{"key":"name","title":"Name","dataIndex":"name"},{"key":"company","title":"Company","dataIndex":"company"},{"key":"status","title":"Status","dataIndex":"status","filterable":true},{"key":"score","title":"Score","dataIndex":"score","align":"right"},{"key":"source","title":"Source","dataIndex":"source","filterable":true}],"rowActions":[{"key":"edit","label":"Edit"},{"key":"followup","label":"Follow-up"},{"key":"convert","label":"Convert"}],"tokens":{"component":"gabz-playground@crm-tokens","params":{}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":32,"y":132,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1136,"height":688}},"hide":{"component":"data2-core-comparison-operators@Different","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}}],"comparisonSubject":"leads"}}},"selectionStore":"crm-ui","onAction":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.editId","value":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.actionKey"}}}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.editType","value":"leads"}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.editOpen","value":{"component":"data2-core-comparison-operators@Equal","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.actionType"}}],"comparisonSubject":"edit"}}}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.convertPending","value":{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-comparison-operators@Equal","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.actionType"}}],"comparisonSubject":"convert"}},"then":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.actionKey"}},"else":""}}}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.followupType","value":"lead"}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.followupRelatedId","value":{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-comparison-operators@Equal","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.actionType"}}],"comparisonSubject":"followup"}},"then":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.actionKey"}},"else":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.followupRelatedId"}}}}}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.followupOwnerId","value":{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-comparison-operators@Equal","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.actionType"}}],"comparisonSubject":"followup"}},"then":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.draft_ownerId"}},"else":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.followupOwnerId"}}}}}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.followupOpen","value":{"component":"data2-core-comparison-operators@Equal","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.actionType"}}],"comparisonSubject":"followup"}}}}]}}},"reference":"4rYEBuZ4cx0jPzRqkHOcR"},{"_id":"533badaf579faca82a5276bb","parent":"ec0fa8fdd46583db8630f064","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Tab Contacts","params":{"position":{"component":"data2-core-types@Position","params":{"x":230,"y":76,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":66,"height":32}},"cursor":"pointer","onClick":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab","value":"contacts"}}]}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#0f0f0f"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"#f4f6f8"}}}}}}]}},"text":{"component":"data2-core-primitives@String","params":{"content":"Contacts"}},"textSize":14,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparison-operators@Equal","params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}},"comparisonSubject":"contacts"}}],"then":600,"else":400}},"horizontalAlignment":"center","verticalAlignment":"middle"}},"textColor":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparison-operators@Equal","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}}],"comparisonSubject":"contacts"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#1677ff"}},"else":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,0.65)"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,0,0,0.88)"}}}}}},"border":{"component":"data2-core-types@Border","params":{"width":{"bottom":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparison-operators@Equal","params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}},"comparisonSubject":"contacts"}}],"then":2,"else":0}}},"color":{"component":"data2-core-types@Color","params":{"rgba":"#1677ff"}}}}},"reference":"kRAdiUIkulu0FJCIqxptR"},{"_id":"7ec287977a10551be97c4534","parent":"ec0fa8fdd46583db8630f064","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Tab Accounts","params":{"position":{"component":"data2-core-types@Position","params":{"x":148,"y":76,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":66,"height":32}},"cursor":"pointer","onClick":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab","value":"accounts"}}]}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#0f0f0f"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"#f4f6f8"}}}}}}]}},"text":{"component":"data2-core-primitives@String","params":{"content":"Accounts"}},"textSize":14,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparison-operators@Equal","params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}},"comparisonSubject":"accounts"}}],"then":600,"else":400}},"horizontalAlignment":"center","verticalAlignment":"middle"}},"textColor":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparison-operators@Equal","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}}],"comparisonSubject":"accounts"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#1677ff"}},"else":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,0.65)"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,0,0,0.88)"}}}}}},"border":{"component":"data2-core-types@Border","params":{"width":{"bottom":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparison-operators@Equal","params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}},"comparisonSubject":"accounts"}}],"then":2,"else":0}}},"color":{"component":"data2-core-types@Color","params":{"rgba":"#1677ff"}}}}},"reference":"UpOWM4Tb2pqpzWBEPrUWz"},{"_id":"93f7732e17f71560844d56f4","parent":"ec0fa8fdd46583db8630f064","component":"gabz-playground@ant-modal","system":"6863d782e78450ee0fd57fc7","displayName":"Add Modal","params":{"title":"New Lead","width":520,"centered":true,"closable":true,"open":false,"openStore":"crm-ui","openKey":"addOpen","slots":[{"type":"gabz-playground@crm-lead-form","props":{"leads":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"5oU4u3o2nj4O709bIEU03DataSet"}}}}],"tokens":{"component":"gabz-playground@crm-tokens","params":{}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":10,"height":10}}},"onCancel":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.addOpen","value":false}}]}}},"reference":"giKwMljop15gjPcYlUlBp"},{"_id":"a9a9281a7b122c405d9b4772","parent":"ec0fa8fdd46583db8630f064","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Tab Leads","params":{"position":{"component":"data2-core-types@Position","params":{"x":28,"y":76,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":56,"height":32}},"cursor":"pointer","onClick":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab","value":"leads"}}]}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#0f0f0f"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"#f4f6f8"}}}}}}]}},"text":{"component":"data2-core-primitives@String","params":{"content":"Leads"}},"textSize":14,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparison-operators@Equal","params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}},"comparisonSubject":"leads"}}],"then":600,"else":400}},"horizontalAlignment":"center","verticalAlignment":"middle"}},"textColor":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparison-operators@Equal","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}}],"comparisonSubject":"leads"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#1677ff"}},"else":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,0.65)"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,0,0,0.88)"}}}}}},"border":{"component":"data2-core-types@Border","params":{"width":{"bottom":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparison-operators@Equal","params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}},"comparisonSubject":"leads"}}],"then":2,"else":0}}},"color":{"component":"data2-core-types@Color","params":{"rgba":"#1677ff"}}}}},"reference":"N0jfMZXpbkwVQ3HvhWJ4S"},{"_id":"ac4af8d04f04ece12703a273","parent":"ec0fa8fdd46583db8630f064","component":"gabz-playground@ant-table","system":"6863d782e78450ee0fd57fc7","displayName":"Contacts Table","params":{"dataset":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"arn7JIj2wlGm39IPOxXSuDataSet"}},"searchable":true,"sortable":true,"bordered":true,"pageSize":25,"searchPlaceholder":"Search contacts…","columns":[{"key":"firstName","title":"First Name","dataIndex":"firstName"},{"key":"lastName","title":"Last Name","dataIndex":"lastName"},{"key":"title","title":"Title","dataIndex":"title"},{"key":"email","title":"Email","dataIndex":"email"},{"key":"phone","title":"Phone","dataIndex":"phone"}],"rowActions":[{"key":"edit","label":"Edit"}],"tokens":{"component":"gabz-playground@crm-tokens","params":{}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":32,"y":132,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1136,"height":688}},"hide":{"component":"data2-core-comparison-operators@Different","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}}],"comparisonSubject":"contacts"}}}},"reference":"iFL5idaDYphvphCaU2wvc"},{"_id":"ba882431e4d1dbd0f2e4a131","parent":"ec0fa8fdd46583db8630f064","component":"gabz-playground@ant-table","system":"6863d782e78450ee0fd57fc7","displayName":"Deals Table","params":{"dataset":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"4uPM8-nCj6UT29zmMAt6FDataSet"}},"searchable":true,"sortable":true,"bordered":true,"pageSize":20,"searchPlaceholder":"Search deals…","columns":[{"key":"name","title":"Name","dataIndex":"name"},{"key":"amount","title":"Amount","dataIndex":"amount","align":"right"},{"key":"stage","title":"Stage","dataIndex":"stage","filterable":true},{"key":"probability","title":"Probability","dataIndex":"probability","align":"right"},{"key":"expectedCloseDate","title":"Expected Close","dataIndex":"expectedCloseDate"}],"rowActions":[{"key":"edit","label":"Edit"},{"key":"followup","label":"Follow-up"}],"tokens":{"component":"gabz-playground@crm-tokens","params":{}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":32,"y":132,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1136,"height":688}},"hide":{"component":"data2-core-comparison-operators@Different","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}}],"comparisonSubject":"deals"}},"scroll":{"params":{"y":true},"component":"data2-core-types@Scroll"}},"selectionStore":"crm-ui","onAction":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.followupType","value":"deal"}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.followupRelatedId","value":{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-comparison-operators@Equal","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.actionType"}}],"comparisonSubject":"followup"}},"then":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.actionKey"}},"else":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.followupRelatedId"}}}}}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.followupOwnerId","value":{"component":"data2-core-flow@If","params":{"compare":{"component":"data2-core-comparison-operators@Equal","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.actionType"}}],"comparisonSubject":"followup"}},"then":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.draft_ownerId"}},"else":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.followupOwnerId"}}}}}},{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.followupOpen","value":{"component":"data2-core-comparison-operators@Equal","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.actionType"}}],"comparisonSubject":"followup"}}}}]}}},"reference":"veI8iB_nO_EhgZjap2OJD"},{"_id":"df578dbb7555de54d44c5c1f","parent":"ec0fa8fdd46583db8630f064","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Header Title","params":{"position":{"component":"data2-core-types@Position","params":{"x":32,"y":24,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":400,"height":34}},"text":{"component":"data2-core-primitives@String","params":{"content":"Records"}},"textColor":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,0.85)"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,0,0,0.88)"}}}},"textSize":26,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":700}}},"reference":"woztGoSOWj0HPgvGhO19l"},{"_id":"f85bfd065eee619acefade58","parent":"ec0fa8fdd46583db8630f064","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Tab Deals","params":{"position":{"component":"data2-core-types@Position","params":{"x":88,"y":76,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":54,"height":32}},"cursor":"pointer","onClick":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab","value":"deals"}}]}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#0f0f0f"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"#f4f6f8"}}}}}}]}},"text":{"component":"data2-core-primitives@String","params":{"content":"Deals"}},"textSize":14,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparison-operators@Equal","params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}},"comparisonSubject":"deals"}}],"then":600,"else":400}},"horizontalAlignment":"center","verticalAlignment":"middle"}},"textColor":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparison-operators@Equal","params":{"subject":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}}],"comparisonSubject":"deals"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#1677ff"}},"else":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,0.65)"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,0,0,0.88)"}}}}}},"border":{"component":"data2-core-types@Border","params":{"width":{"bottom":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-comparison-operators@Equal","params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.activeTab"}},"comparisonSubject":"deals"}}],"then":2,"else":0}}},"color":{"component":"data2-core-types@Color","params":{"rgba":"#1677ff"}}}}},"reference":"iYJZHnxvtrbfTMwlMqQZK"},{"_id":"ecbf9c3593fdba926d02a728","parent":"74b438c6222d7521339a3076","component":"gabz-playground@crm-kanban","system":"6863d782e78450ee0fd57fc7","displayName":"Kanban Board","params":{"leads":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"5oU4u3o2nj4O709bIEU03DataSet"}},"owners":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"y-Fj_8O1Q8SwET7oPpFu8DataSet"}},"tokens":{"component":"gabz-playground@crm-tokens","params":{}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":70,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1200,"height":766}}}},"index":0,"reference":"-GfMOEUt4z3GIDczJ8lQE"},{"_id":"eff44d980c048bce2cee0c62","parent":"74b438c6222d7521339a3076","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Header Title","params":{"position":{"component":"data2-core-types@Position","params":{"x":32,"y":24,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":400,"height":34}},"text":{"component":"data2-core-primitives@String","params":{"content":"Pipeline"}},"textColor":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,0.85)"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,0,0,0.88)"}}}},"textSize":26,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":700}},"tokens":{"component":"gabz-playground@crm-tokens","params":{}}},"index":0,"reference":"UphEND1gw63wvDrLP51Y_"},{"_id":"021bf16dec5d1add803b43d9","parent":"74b438c6222d7521339a3076","component":"gabz-playground@crm-convert","system":"6863d782e78450ee0fd57fc7","displayName":"Convert Watcher","params":{"leads":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"5oU4u3o2nj4O709bIEU03DataSet"}},"accounts":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"4TS0LqYhG0LaNTd5ucvoZDataSet"}},"contacts":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"arn7JIj2wlGm39IPOxXSuDataSet"}},"deals":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"4uPM8-nCj6UT29zmMAt6FDataSet"}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":8,"y":8,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":180,"height":18}}}},"reference":"3CiSTpM8RZXPsgUDBQl1I"},{"_id":"5f290aeb13a266b67a9f86e9","parent":"74b438c6222d7521339a3076","component":"gabz-playground@ant-modal","system":"6863d782e78450ee0fd57fc7","displayName":"Follow-up Modal","params":{"title":"Log Follow-up","centered":true,"closable":true,"width":460,"open":false,"openStore":"crm-ui","openKey":"followupOpen","tokens":{"component":"gabz-playground@crm-tokens","params":{}},"slots":[{"type":"gabz-playground@crm-followup-form","props":{"activities":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"aNFrXXtt76NFND6IZ3RiVDataSet"}}}}],"onCancel":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.followupOpen","value":false}}]}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":200,"height":50}}}},"reference":"hIes5RbWiUiS7GjKLcHlI"},{"_id":"e4384d9937e29c44b9792cd2","parent":"74b438c6222d7521339a3076","component":"gabz-playground@ant-drawer","system":"6863d782e78450ee0fd57fc7","displayName":"Edit Drawer","params":{"title":"Edit Lead","placement":"right","width":440,"closable":true,"open":false,"tokens":{"component":"gabz-playground@crm-tokens","params":{}},"onClose":{"component":"data2-core-flow@Series","params":{"actions":[{"component":"data2-core-types@Setter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.editOpen","value":false}}]}},"slots":[{"type":"gabz-playground@crm-lead-form","props":{"leads":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"5oU4u3o2nj4O709bIEU03DataSet"}}}}],"openStore":"crm-ui","openKey":"editOpen","super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":10,"height":10}}}},"reference":"vKkKDW5oLAEESZv5wyseA"},{"_id":"318329d718056df64f111953","parent":"c949a2af9dd9491e0c3e8a66","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Header Title","params":{"position":{"component":"data2-core-types@Position","params":{"x":32,"y":24,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":400,"height":34}},"text":{"component":"data2-core-primitives@String","params":{"content":"Dashboard"}},"textColor":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,0.85)"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,0,0,0.88)"}}}},"textSize":26,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":700}}},"index":0,"reference":"GrYNv83JnWnzut63FyRHE"},{"_id":"6decd0f57d1761a052e23b41","parent":"c949a2af9dd9491e0c3e8a66","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"KPI Card 1","params":{"position":{"component":"data2-core-types@Position","params":{"x":32,"y":76,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":272,"height":140}}},"index":1,"reference":"M_8QMJOi-jZXQp9kwkr07"},{"_id":"551a464f0294f3e1ea9c37bb","parent":"c949a2af9dd9491e0c3e8a66","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"KPI Card 2","params":{"position":{"component":"data2-core-types@Position","params":{"x":320,"y":76,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":272,"height":140}}},"index":2,"reference":"iLD0TmKYManrFmVJsijYw"},{"_id":"e3335ef796e4df922c84da84","parent":"c949a2af9dd9491e0c3e8a66","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"KPI Card 3","params":{"position":{"component":"data2-core-types@Position","params":{"x":608,"y":76,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":272,"height":140}}},"index":3,"reference":"31OI2HIdM3-BjI8suErjS"},{"_id":"9c01885bfeed8e666344a1fd","parent":"c949a2af9dd9491e0c3e8a66","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"KPI Card 4","params":{"position":{"component":"data2-core-types@Position","params":{"x":896,"y":76,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":272,"height":120}}},"index":4,"reference":"-GfC1nCfp88wZR5pp6dOU"},{"_id":"36ff1b399be2f4dca63f9783","parent":"c949a2af9dd9491e0c3e8a66","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Funnel Section","params":{"position":{"component":"data2-core-types@Position","params":{"x":32,"y":216,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":688,"height":588}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#1f1f1f"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"#ffffff"}}}}}}]}},"border":{"component":"data2-core-types@Border","params":{"radius":8,"width":1,"color":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#303030"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"#f0f0f0"}}}}}}},"index":5,"reference":"NcAXERhj0Eqv-d6XRBRd7"},{"_id":"81a8cc8b8ddb52196e79baec","parent":"c949a2af9dd9491e0c3e8a66","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Activity Section","params":{"position":{"component":"data2-core-types@Position","params":{"x":736,"y":216,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":432,"height":588}},"fill":{"component":"data2-core-types@Fill","params":{"backgrounds":[{"component":"data2-core-types@Background","params":{"color":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#1f1f1f"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"#ffffff"}}}}}}]}},"border":{"component":"data2-core-types@Border","params":{"radius":8,"width":1,"color":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"#303030"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"#f0f0f0"}}}}}}},"index":6,"reference":"9awEoBhIPeSPYyn2z3bZl"},{"_id":"70a5d353896424cc81ebaab6","parent":"654c9bcfca59b1a5ebb165a7","component":"gabz-playground@crm-detail","system":"6863d782e78450ee0fd57fc7","displayName":"Detail Instance","params":{"leads":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"5oU4u3o2nj4O709bIEU03DataSet"}},"deals":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"4uPM8-nCj6UT29zmMAt6FDataSet"}},"accounts":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"4TS0LqYhG0LaNTd5ucvoZDataSet"}},"contacts":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"arn7JIj2wlGm39IPOxXSuDataSet"}},"activities":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"aNFrXXtt76NFND6IZ3RiVDataSet"}},"tokens":{"component":"gabz-playground@crm-tokens","params":{}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":28,"y":24,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1080,"height":724}}}},"reference":"HDJbze4k4yqzN79x39NZx"},{"_id":"0251637ea865341b7ea29837","parent":"6decd0f57d1761a052e23b41","component":"gabz-playground@crm-kpi","system":"6863d782e78450ee0fd57fc7","displayName":"KPI1 OpenPipeline","params":{"super":{"position":{"component":"data2-core-types@Position","params":{"x":24,"y":66,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":240,"height":60}}},"metric":"openPipeline","title":"","prefix":"$","deals":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"4uPM8-nCj6UT29zmMAt6FDataSet"}},"tokens":{"component":"gabz-playground@crm-tokens","params":{}}},"index":0,"reference":"UMd2h3s79y4gXKkaVwHBH"},{"_id":"3c08b9f9b7ab808dcbc54598","parent":"6decd0f57d1761a052e23b41","component":"gabz-playground@ant-card","system":"6863d782e78450ee0fd57fc7","displayName":"Card1 Ant","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":272,"height":140}}},"title":"Open Pipeline","tokens":{"component":"gabz-playground@crm-tokens","params":{}}},"index":0,"reference":"_ZVjn30g2x_OzY26NZqEg"},{"_id":"1f444cae7a98f22c19c9d35b","parent":"551a464f0294f3e1ea9c37bb","component":"gabz-playground@ant-card","system":"6863d782e78450ee0fd57fc7","displayName":"Card2 Ant","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":272,"height":140}}},"title":"Deals Won","tokens":{"component":"gabz-playground@crm-tokens","params":{}}},"index":0,"reference":"S7ZYSYKMtdKjo8fHGghRp"},{"_id":"26a83ab4bd788f2c3e9d42b0","parent":"551a464f0294f3e1ea9c37bb","component":"gabz-playground@crm-kpi","system":"6863d782e78450ee0fd57fc7","displayName":"KPI2 DealsWon","params":{"super":{"position":{"component":"data2-core-types@Position","params":{"x":24,"y":66,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":240,"height":60}}},"metric":"dealsWon","title":"","deals":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"4uPM8-nCj6UT29zmMAt6FDataSet"}},"tokens":{"component":"gabz-playground@crm-tokens","params":{}}},"index":0,"reference":"ZZMzu8S8JdB2JMTmO8nAy"},{"_id":"303ad959f121d79faa861e35","parent":"e3335ef796e4df922c84da84","component":"gabz-playground@crm-kpi","system":"6863d782e78450ee0fd57fc7","displayName":"KPI3 Conversion","params":{"super":{"position":{"component":"data2-core-types@Position","params":{"x":24,"y":66,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":240,"height":60}}},"metric":"conversion","title":"","suffix":"%","deals":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"4uPM8-nCj6UT29zmMAt6FDataSet"}},"tokens":{"component":"gabz-playground@crm-tokens","params":{}}},"index":0,"reference":"o0S2nLvaK_JE34mKlXZnC"},{"_id":"d6160a2aa3bc2bde64e88309","parent":"e3335ef796e4df922c84da84","component":"gabz-playground@ant-card","system":"6863d782e78450ee0fd57fc7","displayName":"Card3 Ant","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":272,"height":140}}},"title":"Conversion Rate","tokens":{"component":"gabz-playground@crm-tokens","params":{}}},"index":0,"reference":"TmbqfzvZxmY9Fg6_F5_bQ"},{"_id":"661aeb88de491e36a4dffc5d","parent":"9c01885bfeed8e666344a1fd","component":"gabz-playground@crm-kpi","system":"6863d782e78450ee0fd57fc7","displayName":"KPI4 NewLeads","params":{"super":{"position":{"component":"data2-core-types@Position","params":{"x":24,"y":66,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":240,"height":60}}},"metric":"newLeads","title":"","leads":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"5oU4u3o2nj4O709bIEU03DataSet"}},"tokens":{"component":"gabz-playground@crm-tokens","params":{}}},"index":0,"reference":"j2VwvzYH6MufAYV8WdeA3"},{"_id":"7e256b896a5f1714bb1d2be0","parent":"9c01885bfeed8e666344a1fd","component":"gabz-playground@ant-card","system":"6863d782e78450ee0fd57fc7","displayName":"Card4 Ant","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":272,"height":140}}},"title":"New Leads","tokens":{"component":"gabz-playground@crm-tokens","params":{}}},"index":0,"reference":"oXsVlZJas_gHvPpUCLry6"},{"_id":"c18da9151ee2e5a2b917c5e0","parent":"36ff1b399be2f4dca63f9783","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Funnel Heading","params":{"position":{"component":"data2-core-types@Position","params":{"x":24,"y":20,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":400,"height":24}},"text":{"component":"data2-core-primitives@String","params":{"content":"Sales Funnel"}},"textColor":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,0.85)"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,0,0,0.88)"}}}},"textSize":16,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":600}}},"index":0,"reference":"U01KHDE33CsmTRDUXxd-v"},{"_id":"70b144055a0cff8fa1718ffc","parent":"36ff1b399be2f4dca63f9783","component":"gabz-playground@crm-funnel","system":"6863d782e78450ee0fd57fc7","displayName":"Funnel Instance","params":{"super":{"position":{"component":"data2-core-types@Position","params":{"x":24,"y":56,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":640,"height":512}}},"deals":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"4uPM8-nCj6UT29zmMAt6FDataSet"}},"tokens":{"component":"gabz-playground@crm-tokens","params":{}}},"index":1,"reference":"4SVOlJ5F6fsyfKNeYyL7A"},{"_id":"ee02eafae42c08f1fd959be0","parent":"81a8cc8b8ddb52196e79baec","component":"data2-core-primitives@Block","system":"6863d782e78450ee0fd57fc7","displayName":"Activity Heading","params":{"position":{"component":"data2-core-types@Position","params":{"x":24,"y":20,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":380,"height":24}},"text":{"component":"data2-core-primitives@String","params":{"content":"Recent Activity"}},"textColor":{"component":"data2-core-flow@If","params":{"compare":[{"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"crm-ui"}},"prop":"data.darkMode"}}],"then":{"component":"data2-core-types@Color","params":{"rgba":"rgba(255,255,255,0.85)"}},"else":{"component":"data2-core-types@Color","params":{"rgba":"rgba(0,0,0,0.88)"}}}},"textSize":16,"textFormat":{"component":"data2-core-types@TextFormat","params":{"fontWeight":600}}},"index":0,"reference":"uH7hXohzwAIY6GgBmanBy"},{"_id":"bedbfc56ddd8c10fd182aad9","parent":"81a8cc8b8ddb52196e79baec","component":"gabz-playground@crm-activity-timeline","system":"6863d782e78450ee0fd57fc7","displayName":"Timeline Instance","params":{"super":{"position":{"component":"data2-core-types@Position","params":{"x":24,"y":56,"freeTransform":true,"left":true,"right":false,"top":true,"bottom":false}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":384,"height":512}}},"activities":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"aNFrXXtt76NFND6IZ3RiVDataSet"}},"tokens":{"component":"gabz-playground@crm-tokens","params":{}}},"index":1,"reference":"cvZ-mrAtjpJPpp48WtIsN"}]}},{"_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":"6a85c3530011ba970903e2c1","displayName":"Agent Chat App","reference":"_aW9Osduf8cQBdOLatsZ2","params":{"domain":{"component":"data2-core-primitives@String","params":{"content":"agent"}},"entryPoint":{"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Artboard","reference":"E06dp8enoXCBHXusuDPkP"}}},"system":"6863d782e78450ee0fd57fc7","component":"data2-core-primitives@Application"}]}},{"reference":"DataComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a31706b56f919e52313f359","component":"data2-core@DataSet","system":"6863d782e78450ee0fd57fc7","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"admin-products"}}},"reference":"admin-productsDataSet"},{"_id":"6a3e7761913fdfe1432c2a53","component":"data2-core@Data2TableDataSource","system":"6863d782e78450ee0fd57fc7","params":{"table":"users","schema":[{"component":"data2-core-types@Field","params":{"key":"name","title":"Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"email","title":"Email","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"title":"password","key":"password","component":"data2-core-types@Password"}}]},"reference":"users"},{"_id":"6a46477eb0a857d0aa5caec9","component":"data2-core@Store","system":"6863d782e78450ee0fd57fc7","params":{"initialData":{"darkMode":false,"accent":"#4f46e5","density":"default","activeTab":"leads","actionType":"","actionKey":"","actionRow":"","editOpen":false,"editType":"leads","editId":"","addOpen":false,"addType":"leads","draft_name":"","draft_company":"","draft_email":"","draft_phone":"","draft_source":"","draft_status":"","draft_score":"","draft_ownerId":"","draft_notes":"","detailType":"","detailId":"","followupOpen":false,"followupType":"","followupRelatedId":"","followupOwnerId":"","f_type":"","f_subject":"","f_notes":"","f_dueDate":"","convertPending":"","f_name":"","f_email":"","f_phone":"","f_company":"","f_source":"","f_status":"","f_score":"","f_ownerId":"","activeNav":"/"}},"reference":"crm-ui"},{"_id":"6a669150b768b226f05adcf5","component":"data2-core@AuthenticationStrategy","system":"6863d782e78450ee0fd57fc7","params":{"credentials":[{"key":"email"},{"key":"password"}],"verifier":{"component":"data2-core-types@DataSetReference","params":{"reference":"secpplDataSet"}},"email":"email","password":"password","role":"role"},"reference":"sec-auth"},{"_id":"6a31706b9421d071c91547a2","component":"data2-core@Data2TableDataSource","system":"6863d782e78450ee0fd57fc7","params":{"table":"admin-products","schema":[{"component":"data2-core-types@Field","params":{"key":"name","title":"Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"sku","title":"SKU","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"category","title":"Category","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"price","title":"Price","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"stock","title":"Stock","component":"data2-core-primitives@Number"}}]},"reference":"admin-products"},{"_id":"6a6690a3b768b226f05adbf8","component":"data2-core@DataSet","system":"6863d782e78450ee0fd57fc7","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"secppl"}}},"reference":"secpplDataSet"},{"_id":"6a6690a3c2a2aeac4a09c14b","component":"data2-core@Data2TableDataSource","system":"6863d782e78450ee0fd57fc7","params":{"table":"secppl","schema":[{"component":"data2-core-types@Field","params":{"key":"owner","title":"owner","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"name","title":"name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"email","title":"email","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"password","title":"password","component":"data2-core-types@Password"}},{"component":"data2-core-types@Field","params":{"key":"salary","title":"salary","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"role","title":"role","component":"data2-core-primitives@String"}}]},"reference":"secppl"},{"_id":"6a45880eb0a857d0aa5b37bb","component":"data2-core@DataSet","system":"6863d782e78450ee0fd57fc7","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"5oU4u3o2nj4O709bIEU03"}}},"reference":"5oU4u3o2nj4O709bIEU03DataSet"},{"_id":"6a458b5ec53088741c501b11","component":"data2-core@DataSet","system":"6863d782e78450ee0fd57fc7","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"aNFrXXtt76NFND6IZ3RiV"}}},"reference":"aNFrXXtt76NFND6IZ3RiVDataSet"},{"_id":"6a458601209db9c36637a819","component":"data2-core@DataSet","system":"6863d782e78450ee0fd57fc7","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"4TS0LqYhG0LaNTd5ucvoZ"}}},"reference":"4TS0LqYhG0LaNTd5ucvoZDataSet"},{"_id":"6a4589568c5c69fa78eb6955","component":"data2-core@DataSet","system":"6863d782e78450ee0fd57fc7","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"4uPM8-nCj6UT29zmMAt6F"}}},"reference":"4uPM8-nCj6UT29zmMAt6FDataSet"},{"_id":"6a458752c53088741c50076c","component":"data2-core@DataSet","system":"6863d782e78450ee0fd57fc7","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"arn7JIj2wlGm39IPOxXSu"}}},"reference":"arn7JIj2wlGm39IPOxXSuDataSet"},{"_id":"6a4585668c5c69fa78eb5594","component":"data2-core@DataSet","system":"6863d782e78450ee0fd57fc7","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"y-Fj_8O1Q8SwET7oPpFu8"}}},"reference":"y-Fj_8O1Q8SwET7oPpFu8DataSet"},{"_id":"6a45880db4c0b0805461e645","component":"data2-core@Data2TableDataSource","system":"6863d782e78450ee0fd57fc7","params":{"table":"5oU4u3o2nj4O709bIEU03","schema":[{"component":"data2-core-types@Field","params":{"key":"name","title":"Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"company","title":"Company","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"email","title":"Email","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"phone","title":"Phone","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"source","title":"Source","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"status","title":"Status","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"score","title":"Score","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"ownerId","title":"Owner ID","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"notes","title":"Notes","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"createdAt","title":"Created At","component":"data2-core-primitives@Date"}}]},"reference":"5oU4u3o2nj4O709bIEU03"},{"_id":"6a458b5eb0a857d0aa5b48e1","component":"data2-core@Data2TableDataSource","system":"6863d782e78450ee0fd57fc7","params":{"table":"aNFrXXtt76NFND6IZ3RiV","schema":[{"component":"data2-core-types@Field","params":{"key":"type","title":"type","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"subject","title":"subject","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"notes","title":"notes","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"dueDate","title":"dueDate","component":"data2-core-primitives@Date"}},{"component":"data2-core-types@Field","params":{"key":"completed","title":"completed","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"relatedType","title":"relatedType","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"relatedId","title":"relatedId","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"ownerId","title":"ownerId","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"createdAt","title":"createdAt","component":"data2-core-primitives@Date"}}]},"reference":"aNFrXXtt76NFND6IZ3RiV"},{"_id":"6a458600e03c48ad27d15701","component":"data2-core@Data2TableDataSource","system":"6863d782e78450ee0fd57fc7","params":{"table":"4TS0LqYhG0LaNTd5ucvoZ","schema":[{"component":"data2-core-types@Field","params":{"key":"name","title":"Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"industry","title":"Industry","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"size","title":"Size","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"website","title":"Website","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"annualRevenue","title":"Annual Revenue","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"ownerId","title":"Owner ID","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"status","title":"Status","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"createdAt","title":"Created At","component":"data2-core-primitives@Date"}}]},"reference":"4TS0LqYhG0LaNTd5ucvoZ"},{"_id":"6a458956209db9c36637b816","component":"data2-core@Data2TableDataSource","system":"6863d782e78450ee0fd57fc7","params":{"table":"4uPM8-nCj6UT29zmMAt6F","schema":[{"component":"data2-core-types@Field","params":{"key":"name","title":"Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"accountId","title":"Account ID","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"contactId","title":"Contact ID","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"amount","title":"Amount","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"stage","title":"Stage","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"probability","title":"Probability","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"key":"expectedCloseDate","title":"Expected Close Date","component":"data2-core-primitives@Date"}},{"component":"data2-core-types@Field","params":{"key":"ownerId","title":"Owner ID","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"createdAt","title":"Created At","component":"data2-core-primitives@Date"}}]},"reference":"4uPM8-nCj6UT29zmMAt6F"},{"_id":"6a4587528c5c69fa78eb602c","component":"data2-core@Data2TableDataSource","system":"6863d782e78450ee0fd57fc7","params":{"table":"arn7JIj2wlGm39IPOxXSu","schema":[{"component":"data2-core-types@Field","params":{"key":"firstName","title":"First Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"lastName","title":"Last Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"email","title":"Email","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"phone","title":"Phone","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"title","title":"Title","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"accountId","title":"Account ID","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"isPrimary","title":"Is Primary","component":"data2-core-primitives@Boolean"}}]},"reference":"arn7JIj2wlGm39IPOxXSu"},{"_id":"6a458566022f39b9563001d5","component":"data2-core@Data2TableDataSource","system":"6863d782e78450ee0fd57fc7","params":{"table":"y-Fj_8O1Q8SwET7oPpFu8","schema":[{"component":"data2-core-types@Field","params":{"key":"name","title":"name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"email","title":"email","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"avatar","title":"avatar","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"role","title":"role","component":"data2-core-primitives@String"}}]},"reference":"y-Fj_8O1Q8SwET7oPpFu8"}]}},{"reference":"BundlesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}}],"processesParams":{}}}}