🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@cometchat/card-builder

Package Overview
Dependencies
Maintainers
14
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cometchat/card-builder - npm Package Compare versions

Comparing version
2.0.0
to
2.0.1
+1
dist/App.d.ts
export default function App(): import("react/jsx-runtime").JSX.Element;
import type { MessageData } from '../types/schema';
import type { CardVariable } from '../config/builder-config';
export interface ApiTemplate {
id: string;
name: string;
description?: string;
schemaVersion: string;
messageData: MessageData;
thumbnail?: string;
createdBy?: string;
createdAt: number;
updatedAt: number;
}
export interface ApiListMeta {
previous?: {
affix: string;
createdAt: number;
};
current: {
limit: number;
count: number;
};
next?: {
affix: string;
createdAt: number;
};
}
export interface ApiError {
code: string;
message: string;
details?: string[];
}
export declare function listTemplates(params?: {
limit?: number;
affix?: 'prepend' | 'append';
createdAt?: number;
search?: string;
}): Promise<{
data: ApiTemplate[];
meta: ApiListMeta;
}>;
export declare function getTemplate(id: string): Promise<{
data: ApiTemplate;
}>;
export declare function createTemplate(body: {
name: string;
description?: string;
messageData: MessageData;
thumbnail?: string;
createdBy?: string;
}): Promise<{
data: ApiTemplate;
}>;
export declare function updateTemplate(id: string, body: {
name?: string;
description?: string;
messageData?: MessageData;
}): Promise<{
data: ApiTemplate;
}>;
export declare function deleteTemplate(id: string): Promise<{
data: {
success: boolean;
};
}>;
export declare function listVariables(): Promise<{
data: CardVariable[];
}>;
export declare function createVariable(variable: CardVariable): Promise<{
data: CardVariable;
}>;
export declare function updateVariableApi(name: string, variable: CardVariable): Promise<{
data: CardVariable;
}>;
export declare function deleteVariable(name: string): Promise<{
data: {
success: boolean;
};
}>;
@import "https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200";.bb-root .tl-container{max-width:61.4286rem;margin:0 auto;padding:4.57143rem 1.71429rem}.bb-root .tl-header{text-align:center;margin-bottom:3.14286rem}.bb-root .tl-logo{background:var(--accent-primary);color:#fff;border-radius:.85714rem;justify-content:center;align-items:center;width:3.42857rem;height:3.42857rem;margin:0 auto 1.14286rem;font-size:1.14286rem;font-weight:800;display:flex}.bb-root .tl-title{color:var(--text-primary);font-size:1.14286rem;font-weight:700}.bb-root .tl-subtitle{color:var(--text-secondary);margin-top:.42857rem;font-size:1rem}.bb-root .tl-actions{gap:.71429rem;margin-bottom:2.57143rem;display:flex}.bb-root .tl-search{flex:1}.bb-root .tl-section{margin-bottom:2.57143rem}.bb-root .tl-section-title{color:#141414;margin-bottom:.85714rem;font-size:1rem;font-weight:600}.bb-root .tl-grid{grid-template-columns:repeat(auto-fill,minmax(13.5714rem,1fr));gap:.71429rem;display:grid}.bb-root .tl-card{text-align:left;box-shadow:none;background:#fff;border:1px solid #e9eaeb;border-radius:.57143rem;padding:1.14286rem;transition:all .15s}.bb-root .tl-card:hover{border-color:var(--accent-primary);box-shadow:var(--shadow-sm)}.bb-root .tl-card-badge{text-transform:uppercase;letter-spacing:.5px;color:var(--accent-primary);margin-bottom:.42857rem;font-size:.78571rem;font-weight:700}.bb-root .tl-card-name{color:#141414;font-size:1rem;font-weight:600}.bb-root .tl-card-desc{color:#727272;margin-top:.14286rem;font-size:.85714rem}.bb-root .tl-card-date{color:#bfbfbc;margin-top:.28571rem;font-size:.78571rem}.bb-root .tl-card{position:relative}.bb-root .tl-card-delete{width:1.57143rem;height:1.57143rem;color:var(--text-tertiary);cursor:pointer;opacity:0;background:0 0;border:none;border-radius:.28571rem;justify-content:center;align-items:center;font-size:1rem;transition:all .15s;display:flex;position:absolute;top:.57143rem;right:.57143rem}.bb-root .tl-card:hover .tl-card-delete{opacity:1}.bb-root .tl-card-delete:hover{color:#dc2626;background:#fee2e2}.bb-root .tl-pagination{justify-content:space-between;align-items:center;margin-top:1.14286rem;display:flex}.bb-root .tl-loading{text-align:center;color:var(--text-tertiary);padding:2.85714rem 1.42857rem;font-size:.92857rem}.bb-root .topbar{background:var(--bg-primary);border-bottom:1px solid var(--border-subtle);flex-shrink:0;justify-content:space-between;align-items:center;height:4rem;padding:0 1.42857rem;display:flex;position:relative}.bb-root .topbar-left{align-items:center;gap:.85714rem;display:flex}.bb-root .topbar-back{border-radius:var(--radius-sm);color:var(--text-secondary);padding:.28571rem .42857rem;font-size:1.28571rem}.bb-root .topbar-back:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .topbar-logo{align-items:center;gap:.57143rem;display:flex}.bb-root .topbar-logo-icon{background:var(--accent-primary);color:#fff;border-radius:.42857rem;justify-content:center;align-items:center;width:1.71429rem;height:1.71429rem;font-size:.64286rem;font-weight:800;display:flex}.bb-root .topbar-logo span{color:var(--text-primary);letter-spacing:-.3px;font-size:1.14286rem;font-weight:600}.bb-root .topbar-sep{background:var(--border-medium);width:1px;height:1.14286rem}.bb-root .topbar-title{color:var(--text-secondary);font-size:1rem;font-weight:500}.bb-root .topbar-name{border-radius:var(--radius-sm);min-width:10rem;max-width:14.2857rem;color:var(--text-primary);box-shadow:none;background:0 0;border:1px solid #0000;padding:.42857rem .57143rem;font-size:1rem;font-weight:500}.bb-root .topbar-name:hover{border-color:var(--border-medium)}.bb-root .topbar-name:focus{border-color:var(--accent-primary)}.bb-root .topbar-dirty{color:var(--accent-primary);font-size:.57143rem}.bb-root .topbar-right{align-items:center;gap:.57143rem;display:flex}.bb-root .topbar-btn{color:#414651;background:#fff;border-radius:.57143rem;outline:1px solid #d5d7da;align-items:center;gap:.42857rem;height:2.57143rem;padding:0 1.14286rem;font-size:1rem;font-weight:600;line-height:1.333;transition:all .15s;display:flex}.bb-root .topbar-btn:hover{background:#f5f5f5}.bb-root .topbar-toast{color:#fff;background:var(--success);z-index:2000;border-radius:.57143rem;align-items:center;gap:.57143rem;padding:.85714rem 1.42857rem;font-size:1rem;font-weight:500;display:flex;position:fixed;bottom:1.71429rem;left:50%;transform:translate(-50%);box-shadow:0 .28571rem .85714rem #00000026}.bb-root .modal-subtitle{color:var(--text-secondary);text-transform:uppercase;letter-spacing:.5px;margin:.85714rem 0 .57143rem;font-size:.78571rem;font-weight:600}.bb-root .modal-field{margin-bottom:.85714rem}.bb-root .modal-label{color:var(--text-secondary);margin-bottom:.42857rem;font-size:.85714rem;font-weight:500;display:block}.bb-root .topbar-btn-icon{border-radius:var(--radius-sm);width:2.28571rem;height:2.28571rem;color:var(--text-secondary);justify-content:center;align-items:center;font-size:1.14286rem;transition:all .15s;display:flex}.bb-root .topbar-btn-icon:hover:not(:disabled){background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .topbar-btn-icon:disabled{opacity:.3;cursor:default}.bb-root .topbar-btn-warn{color:#d97706;background:#fffbeb;border-color:#fcd34d}.bb-root .topbar-btn-warn:hover{background:#fef3c7}.bb-root .topbar-errors{border:1px solid var(--border-subtle);border-radius:var(--radius-lg);z-index:100;min-width:20rem;max-height:14.2857rem;box-shadow:var(--shadow-lg);background:#fff;margin-top:.57143rem;padding:.57143rem;font-size:.85714rem;position:absolute;top:100%;right:0;overflow-y:auto}.bb-root .topbar-error-item{border-radius:.28571rem;flex-direction:column;gap:.14286rem;padding:.42857rem .57143rem;display:flex}.bb-root .topbar-error-item:hover{background:#fef3c7}.bb-root .topbar-error-path{font-family:var(--font-mono);color:#d97706;font-size:.71429rem}.bb-root .topbar-dropdown{position:relative}.bb-root .topbar-dropdown-menu{background:var(--bg-primary);border:1px solid var(--border-subtle);border-radius:var(--radius-md);z-index:100;min-width:12.8571rem;box-shadow:var(--shadow-lg);margin-top:.42857rem;padding:.28571rem;position:absolute;top:100%;right:0}.bb-root .topbar-dropdown-item{width:100%;color:var(--text-primary);border-radius:var(--radius-sm);cursor:pointer;text-align:left;background:0 0;border:none;align-items:center;gap:.57143rem;padding:.57143rem .85714rem;font-size:.92857rem;font-weight:400;display:flex}.bb-root .topbar-dropdown-item:hover{background:var(--bg-tertiary)}.bb-root .left-panel{background:var(--bg-primary);border-right:1px solid var(--border-subtle);flex-direction:column;flex-shrink:0;width:22.8571rem;min-width:18.5714rem;max-width:28.5714rem;font-size:1rem;display:flex;overflow:hidden}.bb-root .lp-header{padding:.85714rem .85714rem .57143rem}.bb-root .lp-tabs{background:var(--bg-tertiary);border-radius:.57143rem;grid-template-columns:1fr 1fr;gap:.14286rem;padding:.21429rem;display:grid}.bb-root .lp-tab{height:2.57143rem;color:var(--text-secondary);background:0 0;border-radius:.42857rem;justify-content:center;align-items:center;gap:.42857rem;font-size:.92857rem;font-weight:500;transition:all .15s;display:flex}.bb-root .lp-tab:hover{color:var(--text-primary)}.bb-root .lp-tab.active{background:var(--bg-primary);color:var(--text-primary);box-shadow:0 1px .21429rem #00000014}.bb-root .lp-search-wrap{padding:0 .85714rem .57143rem;position:relative}.bb-root .lp-search-icon{color:var(--text-muted);pointer-events:none;margin-top:-.28571rem;position:absolute;top:50%;left:1.57143rem;transform:translateY(-50%)}.bb-root .lp-search{border:1px solid var(--border-subtle);width:100%;height:2.57143rem;color:var(--text-primary);background:#fafafa;border-radius:.57143rem;padding:0 2.28571rem 0 2.57143rem;font-size:.92857rem;transition:all .15s}.bb-root .lp-search::placeholder{color:var(--text-muted)}.bb-root .lp-search:focus{background:var(--bg-primary);border-color:var(--accent-primary);outline:none;box-shadow:0 0 0 .14286rem #6852d614}.bb-root .lp-search-clear{background:var(--border-medium);width:1.42857rem;height:1.42857rem;color:var(--text-secondary);border-radius:50%;justify-content:center;align-items:center;margin-top:-.28571rem;transition:background .15s;display:flex;position:absolute;top:50%;right:1.42857rem;transform:translateY(-50%)}.bb-root .lp-search-clear:hover{background:var(--text-muted);color:var(--text-primary)}.bb-root .lp-content{flex:1;padding:.28571rem .57143rem .85714rem;overflow-y:auto}.bb-root .lp-group{margin-bottom:.14286rem}.bb-root .lp-group-header{width:100%;color:var(--text-secondary);cursor:pointer;border-radius:.57143rem;align-items:center;gap:.57143rem;padding:.71429rem;font-size:.92857rem;font-weight:600;transition:all .15s;display:flex}.bb-root .lp-group-header:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .lp-group-header.open{color:var(--text-primary);background:var(--bg-tertiary);font-weight:600}.bb-root .lp-group-header.open .lp-group-icon{color:var(--text-primary)}.bb-root .lp-group-icon{color:var(--text-secondary);transition:color .15s}.bb-root .lp-group-label{text-align:left;flex:1}.bb-root .lp-group-count{color:var(--text-secondary);font-variant-numeric:tabular-nums;font-size:.78571rem;font-weight:500}.bb-root .lp-group-header.open .lp-group-count{color:var(--text-secondary)}.bb-root .lp-group-chevron{color:var(--text-muted);transition:transform .2s,color .15s}.bb-root .lp-group-chevron.collapsed{transform:rotate(-90deg)}.bb-root .lp-group-header.open .lp-group-chevron{color:var(--text-secondary)}.bb-root .lp-group-items{flex-direction:column;gap:.14286rem;margin-left:1.28571rem;padding:.57143rem 0 .28571rem;display:flex;position:relative}.bb-root .lp-group-items:before{content:"";background:var(--border-subtle);width:1px;position:absolute;top:0;bottom:2rem;left:0}.bb-root .lp-item{text-align:left;border:1px solid #0000;border-radius:.57143rem;align-items:center;gap:.71429rem;width:calc(100% - .85714rem);margin-left:.85714rem;padding:.57143rem .71429rem;transition:all .15s;display:flex;position:relative}.bb-root .lp-item:before{content:"";background:var(--border-subtle);width:.85714rem;height:1px;position:absolute;top:50%;left:-.85714rem}.bb-root .lp-item:hover{background:var(--bg-hover);border-color:var(--border-subtle)}.bb-root .lp-item-icon-wrap{background:var(--bg-tertiary);width:2rem;height:2rem;color:var(--text-secondary);border-radius:.42857rem;flex-shrink:0;justify-content:center;align-items:center;display:flex}.bb-root .lp-item-title{color:var(--text-primary);white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;overflow:hidden}.bb-root .lp-item--component{align-items:flex-start}.bb-root .lp-item-info{flex-direction:column;flex:1;gap:.14286rem;min-width:0;display:flex}.bb-root .lp-item-sub{color:var(--text-secondary);white-space:nowrap;text-overflow:ellipsis;font-size:12px;line-height:1.3;overflow:hidden}.bb-root .lp-empty{text-align:center;flex-direction:column;justify-content:center;align-items:center;padding:2.85714rem 1.42857rem;display:flex}.bb-root .lp-empty-icon{color:var(--border-medium);margin-bottom:.57143rem}.bb-root .lp-empty-title{color:var(--text-secondary);font-size:.92857rem;font-weight:500}.bb-root .lp-empty-sub{color:var(--text-muted);margin-top:.28571rem;font-size:.85714rem}.bb-root .lp-footer{border-top:1px dashed var(--border-subtle);padding:.71429rem}.bb-root .lp-footer-drop{border:1px dashed var(--border-subtle);color:var(--text-secondary);cursor:pointer;border-radius:.57143rem;justify-content:center;align-items:center;gap:.42857rem;padding:.71429rem;font-size:.89286rem;font-weight:500;transition:all .15s;display:flex}.bb-root .lp-footer-drop:hover{border-color:var(--border-medium);color:var(--text-primary);background:var(--bg-tertiary)}.bb-root .canvas{background:var(--bg-secondary);flex-direction:column;flex:1;display:flex;position:relative;overflow:hidden}.bb-root .canvas-area{background:radial-gradient(circle at 1px 1px,#d4d4d8 1px,#0000 0) 0 0/1rem 1rem;flex:1;justify-content:center;align-items:center;padding:2.28571rem 1.71429rem;display:flex;overflow:auto}.bb-root .phone-frame{background:#fff;border-radius:24px;flex-direction:column;flex-shrink:0;width:340px;height:700px;max-height:700px;display:flex;position:relative;overflow:hidden;box-shadow:0 0 0 1px #0000000f,0 2px 4px #0000000a,0 12px 32px #00000014,0 32px 64px #0000000f}.bb-root .phone-frame:before{content:none}.bb-root .phone-screen{background:#fafafa;flex-direction:column;height:100%;margin-top:0;display:flex;overflow:hidden}.bb-root .chat-header{background:#fff;border-bottom:1px solid #0000000f;align-items:center;padding:20px 16px 14px;display:flex}.bb-root .chat-back-btn{color:var(--text-secondary);opacity:.6;padding:2px 4px;font-size:20px}.bb-root .chat-user{flex:1;align-items:center;gap:10px;margin-left:10px;display:flex}.bb-root .chat-avatar{color:#fff;background:linear-gradient(135deg,#6852d6,#8b7ae8);border-radius:50%;justify-content:center;align-items:center;width:36px;height:36px;font-size:14px;font-weight:600;display:flex;box-shadow:0 2px 8px #6852d64d}.bb-root .chat-name{color:var(--text-primary);letter-spacing:-.01em;font-size:14px;font-weight:600}.bb-root .chat-messages{background:#fafafa;flex-direction:column;flex:1;gap:12px;min-height:0;padding:16px;display:flex;overflow:hidden auto}.bb-root .message-date{text-align:center;color:var(--text-tertiary);-webkit-backdrop-filter:blur(.57143rem);backdrop-filter:blur(.57143rem);letter-spacing:.02em;background:#fffc;border-radius:.85714rem;align-self:center;padding:.35714rem .85714rem;font-size:.78571rem;font-weight:500}.bb-root .bubble-preview{flex-shrink:0;align-self:flex-start;width:100%;min-height:50px;position:relative;overflow:visible}.bb-root .canvas-bubble{border-radius:16px 16px 16px 4px;flex-direction:column;gap:2px;display:flex;overflow:visible;box-shadow:0 1px 2px #0000000f,0 1px 3px #0000000a}.bb-root .canvas-empty{color:var(--text-tertiary);text-align:center;border:.14286rem dashed var(--border-medium);background-color:#fff;border-radius:1.14286rem;flex-direction:column;justify-content:center;align-items:center;gap:.85714rem;margin:auto .85714rem;padding:2.28571rem 1.42857rem;font-size:.92857rem;display:flex}.bb-root .canvas-empty-template-btn{background:var(--bg-tertiary);border:1px solid var(--border-subtle);color:#404040;cursor:pointer;border-radius:.57143rem;margin-top:.85714rem;padding:.57143rem 1.14286rem;font-size:.92857rem;font-weight:600;transition:all .15s}.bb-root .canvas-empty-template-btn:hover{border-color:var(--accent-primary);background:var(--accent-light);color:var(--accent-primary)}.bb-root .canvas-empty-circle{background:#f5f5f5;border-radius:50%;justify-content:center;align-items:center;width:3.42857rem;height:3.42857rem;display:flex}.bb-root .canvas-empty-plus{color:#a3a3a3;font-size:1.71429rem;font-weight:300}.bb-root .canvas-empty-title{color:var(--text-primary);font-size:1rem;font-weight:600}.bb-root .canvas-empty-sub{color:#404040;font-size:.92857rem}.bb-root .chat-input-area{background:#fff;border-top:1px solid #0000000f;align-items:center;gap:10px;padding:10px 14px;display:flex}.bb-root .chat-input{border:1px solid var(--border-subtle);color:var(--text-primary);background:#f5f6f7;border-radius:20px;flex:1;padding:9px 16px;font-size:13px}.bb-root .chat-send-btn{background:var(--accent-primary);color:#fff;border-radius:50%;justify-content:center;align-items:center;width:34px;height:34px;font-size:13px;transition:transform .15s,box-shadow .15s;display:flex;box-shadow:0 2px 8px #6852d64d}.bb-root .chat-send-btn:hover{transform:scale(1.05);box-shadow:0 4px 12px #6852d666}.bb-root .el-wrapper{cursor:pointer;border-radius:4px;width:100%;transition:all .12s;position:relative;overflow:visible}.bb-root .el-wrapper:hover{background:#6852d60a}.bb-root .el-wrapper.selected{outline:2px solid var(--accent-primary);outline-offset:-2px;background:#6852d60a}.bb-root .el-wrapper.multi-selected{outline:2px dashed var(--accent-primary);outline-offset:-2px;background:#6852d60a}.bb-root .el-controls-portal{z-index:9999;background:#fff;border-radius:.57143rem;flex-direction:row;gap:.14286rem;padding:.21429rem;display:flex;box-shadow:0 .14286rem .85714rem #0000001f,0 0 0 1px #0000000a}.bb-root .preview-mode .el-controls-portal{display:none}.bb-root .el-ctrl-btn{width:1.85714rem;height:1.85714rem;color:var(--text-secondary);border-radius:.35714rem;justify-content:center;align-items:center;font-size:.92857rem;transition:all .12s;display:flex}.bb-root .el-ctrl-btn:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .el-ctrl-btn.danger:hover{color:#dc2626;background:#fee2e2}.bb-root .el-wrap-menu{border:1px solid var(--border-subtle);z-index:1001;background:#fff;border-radius:.71429rem;min-width:10rem;margin-bottom:.28571rem;padding:.28571rem;position:absolute;bottom:100%;right:0;box-shadow:0 .57143rem 1.71429rem #0000001f}.bb-root .el-wrap-option{text-align:left;color:var(--text-secondary);white-space:nowrap;border-radius:.42857rem;width:100%;padding:.5rem .85714rem;font-size:.85714rem}.bb-root .el-wrap-option:hover{background:var(--accent-light);color:var(--accent-primary)}.bb-root .canvas-breadcrumbs{border-bottom:1px solid var(--border-subtle);background:#fff;flex-wrap:wrap;align-items:center;gap:.14286rem;padding:.42857rem 1.14286rem;font-size:.85714rem;display:flex}.bb-root .canvas-bc-sep{color:var(--text-muted);margin:0 .14286rem;font-size:.71429rem}.bb-root .canvas-bc-item{color:var(--text-secondary);font-size:.78571rem;font-family:var(--font-mono);border-radius:.28571rem;padding:.14286rem .57143rem}.bb-root .canvas-bc-item:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .canvas-bc-item.active{color:var(--accent-primary);background:var(--accent-light)}.bb-root .multi-select-bar{border:1px solid var(--border-subtle);z-index:100;background:#fff;border-radius:.85714rem;align-items:center;gap:.57143rem;padding:.57143rem 1.14286rem;font-size:.92857rem;display:flex;position:absolute;bottom:4.28571rem;left:50%;transform:translate(-50%);box-shadow:0 .57143rem 1.71429rem #0000001f}.bb-root .multi-select-bar span{color:var(--text-secondary);white-space:nowrap}.bb-root .multi-select-bar button{background:var(--accent-light);color:var(--accent-primary);white-space:nowrap;border-radius:.42857rem;padding:.42857rem .85714rem;font-size:.85714rem;font-weight:600;transition:all .15s}.bb-root .multi-select-bar button:hover{background:var(--accent-primary);color:#fff}.bb-root .canvas-bubble ::-webkit-scrollbar{height:3px}.bb-root .canvas-bubble ::-webkit-scrollbar-track{background:0 0}.bb-root .canvas-bubble ::-webkit-scrollbar-thumb{background:#00000026;border-radius:2px}.bb-root .canvas-toolbar{border-top:1px solid var(--border-subtle);background:#fff;flex-shrink:0;justify-content:center;align-items:center;gap:.28571rem;padding:.42857rem .85714rem;font-size:.85714rem;display:flex}.bb-root .canvas-tool-btn{width:2rem;height:2rem;color:var(--text-secondary);border-radius:.42857rem;justify-content:center;align-items:center;font-size:1rem;transition:all .12s;display:flex}.bb-root .canvas-tool-btn:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .canvas-tool-btn.active{background:var(--accent-light);color:var(--accent-primary)}.bb-root .canvas-tool-label{color:var(--text-secondary);text-align:center;min-width:2.57143rem;font-size:.78571rem}.bb-root .canvas-tool-sep{background:var(--border-medium);width:1px;height:1.14286rem;margin:0 .28571rem}.bb-root .preview-mode .el-wrapper{cursor:default}.bb-root .preview-mode .el-wrapper:hover{background:0 0}.bb-root .preview-mode .el-wrapper.selected,.bb-root .preview-mode .el-wrapper.multi-selected{background:0 0;outline:none}.bb-root .preview-mode .canvas-breadcrumbs,.bb-root .preview-mode .multi-select-bar{display:none}.bb-root .json-preview-panel{background:var(--bg-primary);border-left:1px solid var(--border-subtle);z-index:60;flex-direction:column;width:27.1429rem;display:flex;position:absolute;top:0;bottom:0;right:0;box-shadow:-.28571rem 0 1.71429rem #0000000f}.bb-root .json-preview-header{border-bottom:1px solid var(--border-subtle);color:var(--text-primary);background:var(--bg-secondary);align-items:center;gap:.57143rem;padding:.85714rem 1.14286rem;font-size:.92857rem;font-weight:600;display:flex}.bb-root .json-preview-header span{flex:1}.bb-root .json-preview-header button{width:2rem;height:2rem;color:var(--text-secondary);background:0 0;border:none;border-radius:.28571rem;justify-content:center;align-items:center;font-size:1rem;display:flex}.bb-root .json-preview-header button:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .json-preview-code{font-family:var(--font-mono);color:var(--text-primary);white-space:pre;tab-size:2;background:var(--bg-primary);flex:1;margin:0;padding:1.14286rem;font-size:.85714rem;line-height:1.6;overflow:auto}.bb-root .el-context-menu{background:var(--bg-primary);border:1px solid var(--border-subtle);border-radius:.71429rem;min-width:11.4286rem;padding:.28571rem;font-size:.85714rem;box-shadow:0 .57143rem 1.71429rem #0000001f}.bb-root .el-ctx-item{text-align:left;width:100%;color:var(--text-secondary);white-space:nowrap;border-radius:.42857rem;padding:.42857rem .85714rem;display:block}.bb-root .el-ctx-item:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .el-ctx-item.danger:hover{color:#dc2626;background:#fee2e2}.bb-root .el-ctx-sep{background:var(--border-subtle);height:1px;margin:.28571rem 0}.bb-root .canvas-side-toolbar{z-index:50;flex-direction:column;align-items:center;gap:1.71429rem;display:flex;position:absolute;top:50%;right:.85714rem;transform:translateY(-50%)}.bb-root .canvas-side-group{border:1px solid var(--border-subtle);background:#fff;border-radius:.85714rem;flex-direction:column;padding:.28571rem;display:flex;box-shadow:0 1px .21429rem #0000000f}.bb-root .canvas-side-btn{width:2.57143rem;height:2.57143rem;color:var(--text-secondary);border-radius:.57143rem;justify-content:center;align-items:center;transition:all .15s;display:flex}.bb-root .canvas-side-btn:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .canvas-side-btn.active{background:var(--accent-light);color:var(--accent-primary)}.bb-root .canvas.read-only .canvas-area{pointer-events:none}.bb-root .canvas.read-only .canvas-area *{pointer-events:none;-webkit-user-select:none;user-select:none;cursor:default!important}.bb-root .canvas.read-only .chat-messages{pointer-events:auto;overflow-y:auto}.bb-root .canvas.read-only .canvas-side-toolbar{display:none}.bb-root .prop-field--row{align-items:flex-start;gap:.85714rem;display:flex}.bb-root .prop-field--row>.prop-label{flex-shrink:0;width:7.14286rem;margin-bottom:0;padding-top:.57143rem}.bb-root .prop-field--row>.prop-field-input{flex:1;min-width:0}.bb-root .prop-color-row{align-items:center;gap:.71429rem;display:flex}.bb-root .prop-color-pair{align-items:center;gap:.42857rem;display:flex}.bb-root .prop-color-circle{cursor:pointer;border:1px solid var(--border-subtle);border-radius:.57143rem;flex-shrink:0;width:2.28571rem;height:2.28571rem;transition:border-color .15s;position:relative}.bb-root .prop-color-circle:hover{border-color:var(--border-medium)}.bb-root .prop-color-circle input[type=color]{cursor:pointer;opacity:0;border:none;border-radius:.57143rem;width:100%;height:100%;padding:0;position:absolute;top:0;left:0}.bb-root .prop-color-tag{-webkit-user-select:none;user-select:none;border-radius:.28571rem;padding:.21429rem .42857rem;font-size:.71429rem;font-weight:600;line-height:1}.bb-root .prop-color-tag--light{background:var(--bg-tertiary);color:var(--text-secondary);border:1px solid var(--border-subtle)}.bb-root .prop-color-tag--dark{color:#adb5bd;background:#1a1a1a;border:1px solid #495057}.bb-root .prop-color-clear{width:1.71429rem;height:1.71429rem;color:var(--text-tertiary);background:var(--bg-tertiary);border:1px solid var(--border-subtle);cursor:pointer;border-radius:.42857rem;justify-content:center;align-items:center;font-size:.85714rem;transition:all .15s;display:flex}.bb-root .prop-color-clear:hover{color:#dc2626;background:#fef2f2;border-color:#fecaca}.bb-root .prop-padding-row{align-items:center;gap:.42857rem;display:flex}.bb-root .prop-padding-row input{flex:1}.bb-root .prop-padding-toggle{border:1px solid var(--border-subtle);width:40px;height:40px;color:var(--text-muted);background:var(--bg-primary);cursor:pointer;border-radius:.57143rem;flex-shrink:0;justify-content:center;align-items:center;transition:all .15s;display:flex}.bb-root .prop-padding-toggle:hover{background:var(--bg-tertiary);color:var(--text-primary);border-color:var(--border-medium)}.bb-root .prop-padding-toggle.active{background:var(--accent-light);color:var(--accent-primary);border-color:#6852d64d}.bb-root .prop-padding-grid{grid-template-columns:1fr 1fr;gap:.57143rem;margin-top:.57143rem;display:grid}.bb-root .prop-padding-grid label{color:var(--text-secondary);text-transform:uppercase;letter-spacing:.5px;margin-bottom:.28571rem;font-size:.75rem;font-weight:500;display:block}.bb-root .prop-select-wrap{position:relative}.bb-root .prop-select-wrap select{appearance:none;padding-right:2.28571rem}.bb-root .prop-select-arrow{pointer-events:none;color:var(--text-muted);position:absolute;top:50%;right:.71429rem;transform:translateY(-50%)}.bb-root .prop-input-number{-moz-appearance:textfield}.bb-root .prop-input-number::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.bb-root .prop-input-number::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.bb-root .prop-color-section{flex-direction:column;gap:.57143rem;display:flex}.bb-root .prop-color-swatch-row{align-items:center;gap:.71429rem;display:flex}.bb-root .prop-color-swatch{cursor:pointer;border:1px solid var(--border-subtle);border-radius:.57143rem;flex-shrink:0;width:40px;height:40px;transition:border-color .15s;position:relative}.bb-root .prop-color-swatch input[type=color]{cursor:pointer;opacity:0;border:none;border-radius:.57143rem;width:100%;height:100%;padding:0;position:absolute;top:0;left:0}.bb-root .prop-input-hex{flex:1;font-size:13px}.bb-root .prop-padding-wrap{flex-direction:column;gap:.57143rem;width:100%;display:flex}.bb-root .prop-padding-wrap .prop-padding-grid{margin-left:0}.bb-root .prop-align-group{border:1px solid var(--border-subtle);border-radius:.57143rem;display:flex;overflow:hidden}.bb-root .prop-align-btn{background:var(--bg-primary);height:40px;color:var(--text-secondary);border-right:1px solid var(--border-subtle);flex:1;justify-content:center;align-items:center;transition:all .15s;display:flex}.bb-root .prop-align-btn:last-child{border-right:none}.bb-root .prop-align-btn:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .prop-align-btn.active{background:var(--accent-light);color:var(--accent-primary)}.bb-root .prop-switch{cursor:pointer;align-items:center;gap:.85714rem;padding:.42857rem 0;display:flex}.bb-root .prop-switch-track{background:var(--border-medium);border-radius:.71429rem;flex-shrink:0;width:2.57143rem;height:1.42857rem;transition:background .2s;position:relative}.bb-root .prop-switch-track.on{background:var(--accent-primary)}.bb-root .prop-switch-thumb{background:#fff;border-radius:50%;width:1.14286rem;height:1.14286rem;transition:transform .2s;position:absolute;top:.14286rem;left:.14286rem;box-shadow:0 1px .21429rem #00000026}.bb-root .prop-switch-track.on .prop-switch-thumb{transform:translate(1.14286rem)}.bb-root .prop-switch-label{width:7.14286rem;color:var(--text-tertiary);flex-shrink:0;font-size:13px;font-weight:400}.bb-root .prop-image-preview{object-fit:cover;border:1px solid var(--border-subtle);border-radius:.57143rem;width:100%;max-height:8.57143rem;margin:.28571rem 0 .57143rem}.bb-root .prop-section-header{align-items:center;gap:.57143rem;margin-top:.57143rem;padding:.57143rem 0;display:flex}.bb-root .prop-section-header .material-symbols-outlined{color:var(--text-muted)}.bb-root .prop-color-header{justify-content:space-between;align-items:center;margin-bottom:1.14286rem;display:flex}.bb-root .prop-color-field{align-items:flex-start;gap:.85714rem;margin-bottom:.85714rem;display:flex}.bb-root .prop-color-field-label{width:7.14286rem;color:var(--text-tertiary);flex-shrink:0;padding-top:.57143rem;font-size:13px;font-weight:400}.bb-root .prop-color-field-input{flex:1;align-items:center;gap:.71429rem;min-width:0;display:flex}.bb-root .prop-image-upload-placeholder{border:.14286rem dashed var(--border-medium);background:var(--bg-tertiary);cursor:pointer;border-radius:.57143rem;flex-direction:column;justify-content:center;align-items:center;width:100%;height:8.57143rem;margin-bottom:.85714rem;transition:all .15s;display:flex}.bb-root .prop-image-upload-placeholder:hover{border-color:var(--accent-primary);background:var(--accent-light)}.bb-root .prop-image-upload-icon{color:var(--text-muted);margin-bottom:.57143rem}.bb-root .prop-image-upload-placeholder:hover .prop-image-upload-icon{color:var(--accent-primary)}.bb-root .prop-image-upload-text{color:var(--text-secondary);font-size:.92857rem;font-weight:500}.bb-root .prop-image-upload-hint{color:var(--text-muted);margin-top:.14286rem;font-size:.78571rem}.bb-root .prop-image-preview-container{border:1px solid var(--border-subtle);cursor:pointer;border-radius:.57143rem;width:100%;height:12.8571rem;margin-bottom:.85714rem;position:relative;overflow:hidden}.bb-root .prop-image-preview-container:hover .prop-image-preview-overlay{opacity:1}.bb-root .prop-image-preview-img{object-fit:contain;background:var(--bg-tertiary);width:100%;height:100%}.bb-root .prop-image-preview-overlay{color:#fff;opacity:0;background:#0000004d;justify-content:center;align-items:center;gap:.42857rem;font-size:.85714rem;font-weight:500;transition:opacity .15s;display:flex;position:absolute;inset:0}.bb-root .prop-image-modal-backdrop{z-index:9999;-webkit-backdrop-filter:blur(.28571rem);backdrop-filter:blur(.28571rem);background:#000000b3;justify-content:center;align-items:center;padding:2.28571rem;display:flex;position:fixed;inset:0}.bb-root .prop-image-modal{background:#fff;border-radius:.85714rem;max-width:90vw;max-height:90vh;position:relative;overflow:hidden;box-shadow:0 1.42857rem 4.28571rem #0000004d}.bb-root .prop-image-modal-img{object-fit:contain;max-width:90vw;max-height:80vh;display:block}.bb-root .prop-image-modal-close{color:#fff;background:#00000080;border-radius:.57143rem;justify-content:center;align-items:center;width:2.57143rem;height:2.57143rem;transition:background .15s;display:flex;position:absolute;top:.85714rem;right:.85714rem}.bb-root .prop-image-modal-close:hover{background:#000000b3}.bb-root .prop-image-modal-footer{color:#fff;background:linear-gradient(#0000,#0009);justify-content:space-between;align-items:center;padding:.85714rem 1.14286rem;font-size:.85714rem;display:flex;position:absolute;bottom:0;left:0;right:0}.bb-root .prop-image-modal-close-btn{color:#fff;background:#fff3;border-radius:.57143rem;align-items:center;gap:.42857rem;padding:.42857rem .85714rem;font-size:.85714rem;font-weight:500;transition:background .15s;display:flex}.bb-root .prop-image-modal-close-btn:hover{background:#ffffff4d}.bb-root .notif-help-box{background:var(--bg-tertiary);color:var(--text-secondary);border-radius:.57143rem;align-items:flex-start;gap:.57143rem;padding:.85714rem;font-size:.89286rem;line-height:1.5;display:flex}.bb-root .notif-help-icon{color:var(--text-muted);flex-shrink:0;margin-top:1px}.bb-root .var-header{justify-content:space-between;align-items:center;display:flex}.bb-root .var-add-btn{background:var(--accent-primary);color:#fff;border-radius:.57143rem;align-items:center;gap:.28571rem;padding:.57143rem 1rem;font-size:.92857rem;font-weight:600;transition:background .15s;display:flex}.bb-root .var-add-btn:hover{background:var(--accent-secondary)}.bb-root .var-empty{text-align:center;flex-direction:column;align-items:center;padding:2.28571rem 1.14286rem;display:flex}.bb-root .var-empty-icon{background:var(--bg-tertiary);width:3.42857rem;height:3.42857rem;color:var(--text-muted);border-radius:1.71429rem;justify-content:center;align-items:center;margin-bottom:.85714rem;display:flex}.bb-root .var-empty-title{color:var(--text-secondary);font-size:.92857rem;font-weight:500}.bb-root .var-empty-sub{color:var(--text-muted);margin-top:.28571rem;font-size:.85714rem}.bb-root .var-count{text-transform:uppercase;letter-spacing:.5px;color:var(--text-secondary);margin-bottom:.85714rem;font-size:.78571rem;font-weight:600}.bb-root .var-list{flex-direction:column;gap:.71429rem;display:flex}.bb-root .var-item{border:1px solid var(--border-subtle);background:#fff;border-radius:.85714rem;transition:border-color .15s,box-shadow .15s;position:relative;overflow:hidden}.bb-root .var-item:hover{border-color:#6852d633;box-shadow:0 1px .21429rem #0000000a}.bb-root .var-item-top{align-items:center;gap:.71429rem;padding:.85714rem 1rem .57143rem;display:flex}.bb-root .var-item-icon{background:var(--accent-light);width:1.71429rem;height:1.71429rem;color:var(--accent-primary);border-radius:.42857rem;flex-shrink:0;justify-content:center;align-items:center;display:flex}.bb-root .var-item-name{color:var(--text-primary);background:#00000008;border-radius:.28571rem;flex:1;padding:.14286rem .57143rem;font-size:.92857rem;font-weight:600}.bb-root .var-item-delete{width:2rem;height:2rem;color:var(--text-muted);opacity:1;border-radius:.57143rem;flex-shrink:0;justify-content:center;align-items:center;transition:all .15s;display:flex}.bb-root .var-item:hover .var-item-delete{color:var(--text-muted)}.bb-root .var-item-delete:hover{background:#fef2f2;color:#dc2626!important}.bb-root .var-item-details{flex-direction:column;gap:.28571rem;padding:0 1rem .85714rem;display:flex}.bb-root .var-item-detail{color:var(--text-secondary);align-items:center;gap:.42857rem;font-size:.85714rem;display:flex}.bb-root .var-item-detail .material-symbols-outlined{color:var(--text-muted)}.bb-root .var-item-category{text-transform:uppercase;letter-spacing:.5px;color:var(--accent-primary);background:var(--accent-light);border-radius:.71429rem;align-self:flex-start;margin-top:.28571rem;padding:.14286rem .57143rem;font-size:.71429rem;font-weight:600}.bb-root .var-delete-overlay{z-index:10;-webkit-backdrop-filter:blur(.14286rem);backdrop-filter:blur(.14286rem);color:var(--text-primary);background:#fffffff2;border:1px solid #fecaca;border-radius:.85714rem;flex-direction:column;justify-content:center;align-items:center;gap:.57143rem;font-size:.85714rem;font-weight:500;display:flex;position:absolute;inset:0}.bb-root .var-delete-icon{color:#dc2626}.bb-root .var-delete-actions{gap:.57143rem;margin-top:.28571rem;display:flex}.bb-root .var-delete-confirm{color:#fff;background:#dc2626;border-radius:.57143rem;padding:.42857rem 1rem;font-size:.85714rem;font-weight:600}.bb-root .var-delete-confirm:hover{background:#b91c1c}.bb-root .var-delete-cancel{border:1px solid var(--border-subtle);color:var(--text-secondary);border-radius:.57143rem;padding:.42857rem 1rem;font-size:.85714rem;font-weight:500}.bb-root .var-delete-cancel:hover{background:var(--bg-tertiary)}.bb-root .var-form{background:#6852d605;border:1px solid #6852d633;border-radius:.85714rem;margin-bottom:.85714rem;padding:1.14286rem}.bb-root .var-form-title{color:var(--text-primary);margin-bottom:.85714rem;font-size:.92857rem;font-weight:600}.bb-root .var-form-actions{gap:.57143rem;margin-top:.85714rem;display:flex}.bb-root .var-form-btn-primary{background:var(--accent-primary);color:#fff;border-radius:.57143rem;padding:.57143rem 1.14286rem;font-size:.85714rem;font-weight:600;transition:background .15s}.bb-root .var-form-btn-primary:hover{background:var(--accent-secondary)}.bb-root .var-form-btn-secondary{border:1px solid var(--border-subtle);color:var(--text-secondary);border-radius:.57143rem;padding:.57143rem 1.14286rem;font-size:.85714rem;font-weight:500;transition:background .15s}.bb-root .var-form-btn-secondary:hover{background:var(--bg-tertiary)}.bb-root .tree-root{font-size:13px}.bb-root .tree-item{text-align:left;width:100%;color:var(--text-secondary);cursor:pointer;border-radius:.57143rem;align-items:center;gap:.42857rem;min-height:2.28571rem;padding:.42857rem .57143rem;transition:all .15s;display:flex;position:relative}.bb-root .tree-item:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .tree-item.selected{background:var(--bg-tertiary);color:var(--text-primary);transition:none}.bb-root .tree-item:active{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .tree-item.multi-selected{background:var(--accent-light);color:var(--accent-primary);outline:1px dashed var(--accent-primary);outline-offset:-1px}.bb-root .tree-item.drop-target{outline:.14286rem dashed var(--accent-primary);outline-offset:-.14286rem}.bb-root .tree-item.flash{background:var(--bg-tertiary)}@keyframes tree-flash{0%{background:var(--bg-tertiary)}to{background:0 0}}.bb-root .tree-chevron{width:1.14286rem;height:1.14286rem;color:var(--text-muted);cursor:pointer;border-radius:.28571rem;flex-shrink:0;justify-content:center;align-items:center;transition:color .15s;display:flex}.bb-root .tree-chevron:hover,.bb-root .tree-item.selected .tree-chevron{color:var(--text-primary)}.bb-root .tree-spacer{flex-shrink:0;width:1.14286rem}.bb-root .tree-icon-box{border:1px solid var(--border-subtle);background:var(--bg-primary);width:1.71429rem;height:1.71429rem;color:var(--text-secondary);border-radius:.28571rem;flex-shrink:0;justify-content:center;align-items:center;transition:all .15s;display:flex}.bb-root .tree-item:hover .tree-icon-box{border-color:var(--border-medium)}.bb-root .tree-item.selected .tree-icon-box,.bb-root .tree-item.flash .tree-icon-box{border-color:var(--border-medium);background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .tree-type{font-family:Satoshi,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:12px;font-weight:500}.bb-root .tree-type.is-container{font-weight:600}.bb-root .tree-item.selected .tree-type{color:var(--text-primary)}.bb-root .tree-label{color:var(--text-tertiary);text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:.78571rem;overflow:hidden}.bb-root .tree-badge{background:var(--bg-tertiary);color:var(--text-tertiary);border-radius:.57143rem;flex-shrink:0;margin-left:auto;padding:1px .35714rem;font-size:.64286rem}.bb-root .tree-item.selected .tree-badge{background:var(--border-subtle);color:var(--text-secondary)}.bb-root .tree-error-dot{background:#dc2626;border-radius:50%;flex-shrink:0;width:.42857rem;height:.42857rem;margin-left:auto}.bb-root .tree-badge+.tree-error-dot,.bb-root .tree-error-dot+.tree-badge{margin-left:.28571rem}.bb-root .tree-children{position:relative}.bb-root .tree-children:before{content:"";background:var(--border-subtle);width:1px;position:absolute;top:0;bottom:.85714rem;left:1.35714rem}.bb-root .tree-empty{color:var(--text-tertiary);flex-direction:column;align-items:center;gap:.57143rem;padding:1.71429rem;font-size:.92857rem;display:flex}.bb-root .tree-drag-overlay{background:var(--bg-primary);opacity:.9;border-radius:.57143rem;box-shadow:0 .28571rem .85714rem #00000026}.bb-root .tree-node{touch-action:none}.bb-root .tree-drop-gap{height:.28571rem;transition:height .1s;position:relative}.bb-root .tree-drop-gap.active{height:.57143rem}.bb-root .tree-drop-gap .tree-drop-line{background:0 0;border-radius:1px;height:.14286rem;transition:background .1s}.bb-root .tree-drop-gap.active .tree-drop-line{background:var(--accent-primary)}.bb-root .tree-search-wrap{margin-bottom:.57143rem;position:relative}.bb-root .tree-search-icon{color:var(--text-muted);pointer-events:none;position:absolute;top:50%;left:.71429rem;transform:translateY(-50%)}.bb-root .tree-search{border:1px solid var(--border-subtle);width:100%;color:var(--text-primary);background:#fafafa;border-radius:.57143rem;padding:.57143rem 2rem .57143rem 2.28571rem;font-size:.85714rem}.bb-root .tree-search:focus{border-color:var(--accent-primary);background:var(--bg-primary);outline:none}.bb-root .tree-search::placeholder{color:var(--text-muted)}.bb-root .tree-search-clear{width:1.42857rem;height:1.42857rem;color:var(--text-tertiary);background:var(--border-medium);border-radius:50%;justify-content:center;align-items:center;transition:all .15s;display:flex;position:absolute;top:50%;right:.57143rem;transform:translateY(-50%)}.bb-root .tree-search-clear:hover{color:var(--text-primary);background:var(--text-muted)}.bb-root .right-panel{background:var(--bg-primary);border-left:1px solid var(--border-subtle);flex-direction:column;flex-shrink:0;width:22.8571rem;min-width:18.5714rem;max-width:28.5714rem;font-size:14px;display:flex;overflow:hidden}.bb-root .rp-tabs{border-bottom:1px solid var(--border-subtle);flex-shrink:0;padding:0 .57143rem;display:flex;overflow:hidden}.bb-root .rp-tab{color:var(--text-secondary);white-space:nowrap;background:0 0;flex:1;justify-content:center;align-items:center;padding:.85714rem .57143rem;font-size:.89286rem;font-weight:500;transition:color .15s;display:flex;position:relative}.bb-root .rp-tab:hover{color:var(--text-primary)}.bb-root .rp-tab.active{color:var(--accent-primary);font-weight:500}.bb-root .rp-tab-indicator{background:var(--accent-primary);border-radius:1px;height:.14286rem;position:absolute;bottom:0;left:.57143rem;right:.57143rem}.bb-root .rp-content{flex:1;padding:1.42857rem 1.14286rem;overflow-y:auto}.bb-root .rp-empty{color:var(--text-tertiary);text-align:center;flex-direction:column;justify-content:center;align-items:center;gap:.85714rem;padding:3.42857rem 1.71429rem;display:flex}.bb-root .rp-empty-icon{color:var(--border-medium);font-size:3.42857rem}.bb-root .prop-group{margin-bottom:0;padding-bottom:0}.bb-root .prop-group:last-child{border-bottom:none}.bb-root .prop-group-title{color:var(--text-primary);margin-bottom:1.14286rem;font-size:14px;font-weight:600}.bb-root .prop-field{margin-bottom:.85714rem}.bb-root .prop-label{color:var(--text-tertiary);margin-bottom:.42857rem;font-size:13px;font-weight:400;display:block}.bb-root .prop-row{align-items:center;gap:.57143rem;display:flex}.bb-root .prop-row .prop-label{flex-shrink:0;width:7.14286rem;margin-bottom:0}.bb-root .prop-badge{background:var(--accent-light);color:var(--accent-primary);text-transform:uppercase;letter-spacing:.5px;border-radius:.28571rem;margin-bottom:1.14286rem;padding:.28571rem .71429rem;font-size:.78571rem;font-weight:600;display:inline-block}.bb-root .prop-error-summary{color:#dc2626;background:#fef2f2;border:1px solid #fecaca;border-radius:.28571rem;margin-bottom:.85714rem;padding:.42857rem .71429rem;font-size:.85714rem;font-weight:500}.bb-root .prop-field-error input,.bb-root .prop-field-error textarea,.bb-root .prop-field-error select{box-shadow:0 0 0 1px #fecaca;border-color:#dc2626!important}.bb-root .prop-field-error-hint{color:#dc2626;margin-left:.42857rem;font-size:.78571rem;font-weight:400}.bb-root .prop-color-swatch{border:1px solid var(--border-subtle);cursor:pointer;border-radius:.57143rem;flex-shrink:0;width:40px;height:40px;transition:border-color .15s}.bb-root .prop-color-swatch:hover{border-color:var(--border-medium)}.bb-root .prop-toggle-group{border:1px solid var(--border-subtle);border-radius:.57143rem;display:flex;overflow:hidden}.bb-root .prop-toggle-btn{background:var(--bg-primary);height:2.85714rem;color:var(--text-secondary);border-right:1px solid var(--border-subtle);flex:1;justify-content:center;align-items:center;transition:all .15s;display:flex}.bb-root .prop-toggle-btn:last-child{border-right:none}.bb-root .prop-toggle-btn:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .prop-toggle-btn.active{background:var(--accent-light);color:var(--accent-primary)}.bb-root .prop-mode-toggle{border:1px solid var(--border-subtle);border-radius:.57143rem;display:flex;overflow:hidden}.bb-root .prop-mode-btn{background:var(--bg-primary);width:2.57143rem;height:2.57143rem;color:var(--text-muted);border-right:1px solid var(--border-subtle);justify-content:center;align-items:center;transition:all .15s;display:flex}.bb-root .prop-mode-btn:last-child{border-right:none}.bb-root .prop-mode-btn:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .prop-mode-btn.active{background:var(--accent-light);color:var(--accent-primary)}.bb-root .prop-section-divider{background:var(--border-subtle);height:1px;margin:1.14286rem 0}.bb-root .empty-state{text-align:center;flex-direction:column;justify-content:center;align-items:center;padding:2.28571rem 1.14286rem;display:flex}.bb-root .empty-state-icon{background:var(--bg-tertiary);width:3.42857rem;height:3.42857rem;color:var(--text-muted);border-radius:50%;justify-content:center;align-items:center;margin-bottom:.85714rem;display:flex}.bb-root .empty-state-title{color:#525252;font-size:13px;font-weight:500}.bb-root .empty-state-sub{color:#a3a3a3;max-width:14.2857rem;margin-top:.28571rem;font-size:12px;line-height:1.5}.bb-root .shortcuts-overlay{z-index:10000;-webkit-backdrop-filter:blur(.28571rem);backdrop-filter:blur(.28571rem);background:#0006;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.bb-root .shortcuts-panel{background:#fff;border-radius:1.14286rem;width:22.8571rem;padding:0;overflow:hidden;box-shadow:0 1.14286rem 3.42857rem #0003}.bb-root .shortcuts-header{border-bottom:1px solid var(--border-subtle);color:var(--text-primary);justify-content:space-between;align-items:center;padding:1.14286rem 1.42857rem;font-size:1rem;font-weight:600;display:flex}.bb-root .shortcuts-close{width:1.71429rem;height:1.71429rem;color:var(--text-tertiary);border-radius:.42857rem;justify-content:center;align-items:center;font-size:1.14286rem;display:flex}.bb-root .shortcuts-close:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .shortcuts-list{padding:.85714rem 1.42857rem 1.14286rem}.bb-root .shortcut-row{border-bottom:1px solid var(--border-subtle);justify-content:space-between;align-items:center;padding:.57143rem 0;display:flex}.bb-root .shortcut-row:last-child{border-bottom:none}.bb-root .shortcut-action{color:var(--text-secondary);font-size:.92857rem}.bb-root .shortcut-keys{font-family:var(--font-mono);background:var(--bg-tertiary);color:var(--text-primary);border:1px solid var(--border-subtle);border-radius:.28571rem;padding:.21429rem .57143rem;font-size:.78571rem;font-weight:500}.bb-root .editor-root{background:var(--bg-secondary);flex-direction:column;width:100%;height:100%;font-family:Satoshi,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;display:flex}.bb-root .editor-panels{flex:1;display:flex;overflow:hidden}:root{--bg-primary:#fff;--bg-secondary:#f5f5f5;--bg-tertiary:#f5f5f5;--bg-elevated:#fff;--bg-hover:#fafafa;--bg-active:#f3f0ff;--accent-primary:#6852d6;--accent-secondary:#7c6be6;--accent-light:#f3f0ff;--accent-gradient:linear-gradient(135deg, #6852d6 0%, #7c6be6 100%);--accent-glow:#6852d633;--text-primary:#141414;--text-secondary:#727272;--text-tertiary:#414651;--text-muted:#bfbfbc;--border-subtle:#e9eaeb;--border-medium:#d5d7da;--border-accent:#6852d64d;--success:#10b981;--warning:#f59e0b;--error:#d92d20;--shadow-sm:0 1px .14286rem #0000000d;--shadow-md:0 .28571rem .42857rem #00000012;--shadow-lg:0 .71429rem 1.78571rem #0000001a;--radius-sm:.57143rem;--radius-md:.57143rem;--radius-lg:.85714rem;--radius-xl:1.14286rem;--font-sans:"Satoshi", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--font-mono:"SF Mono", "Fira Code", monospace}.bb-root .material-symbols-outlined{font-variation-settings:"FILL" 0, "wght" 400, "GRAD" 0, "opsz" 20;-webkit-user-select:none;user-select:none}.bb-root,.bb-root *{box-sizing:border-box;margin:0;padding:0}.bb-root,.bb-root,.bb-root #root{width:100%;height:100%}.bb-root,.bb-root *,.bb-root :before,.bb-root :after{font-family:Satoshi,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.bb-root{font-family:var(--font-sans);background:var(--bg-secondary);color:var(--text-primary);-webkit-font-smoothing:antialiased;font-size:clamp(14px,.95vw,28px);line-height:1.5}.bb-root ::-webkit-scrollbar{width:.42857rem;height:.42857rem}.bb-root ::-webkit-scrollbar-track{background:0 0}.bb-root ::-webkit-scrollbar-thumb{background:var(--border-medium);border-radius:.21429rem}.bb-root ::-webkit-scrollbar-thumb:hover{background:var(--text-tertiary)}.bb-root button{cursor:pointer;color:inherit;font:inherit;background:0 0;border:none}.bb-root input,.bb-root textarea,.bb-root select{box-sizing:border-box;border:1px solid var(--border-medium);width:100%;height:40px;color:var(--text-primary);background:#fff;border-radius:.57143rem;outline:none;padding:.71429rem .85714rem;font-family:inherit;font-size:13px;font-weight:500;line-height:1.5;transition:border-color .15s}.bb-root textarea{height:auto}.bb-root input:focus,.bb-root textarea:focus,.bb-root select:focus{border-color:var(--accent-primary)}.bb-root input::placeholder,.bb-root textarea::placeholder{color:var(--text-muted);font-weight:400}.bb-root select{appearance:none;cursor:pointer;padding-right:2rem}.bb-root input[type=checkbox]{width:1.14286rem;height:1.14286rem;accent-color:var(--accent-primary)}.bb-root input[type=color]{border:1px solid var(--border-medium);border-radius:var(--radius-sm);background:var(--bg-secondary);cursor:pointer;width:2.85714rem;height:2.57143rem;padding:.14286rem}.bb-root input[type=color]::-webkit-color-swatch-wrapper{padding:.14286rem}.bb-root input[type=color]::-webkit-color-swatch{border:none;border-radius:.28571rem}.bb-root textarea{resize:vertical;min-height:4.28571rem}
/*$vite$:1*/

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

import './Canvas.css';
export declare const Canvas: import("react").NamedExoticComponent<object>;
export declare const CanvasViewToggle: import("react").NamedExoticComponent<{
platform: "ios" | "android";
setPlatform: (p: "ios" | "android") => void;
darkMode: boolean;
setDarkMode: (d: boolean) => void;
}>;
interface Props {
onClose: () => void;
/** Called after credentials are saved (for Send flow) */
onSaved?: () => void;
/** Title override */
title?: string;
/** Label for the save button. Default: "Save & Continue" */
saveLabel?: string;
}
export declare const CredentialsModal: import("react").NamedExoticComponent<Props>;
export {};
import './EditorLayout.css';
export declare const EditorLayout: import("react").NamedExoticComponent<object>;
import './ElementTree.css';
export declare function ElementTree(): import("react/jsx-runtime").JSX.Element;
import './LeftPanel.css';
export declare const LeftPanel: import("react").NamedExoticComponent<object>;
export declare const NotificationPreview: import("react").NamedExoticComponent<{
platform: "ios" | "android";
}>;
import type { CardAction } from '../../types/schema';
interface Props {
action: CardAction;
onChange: (action: CardAction) => void;
}
export declare const ActionEditor: import("react").NamedExoticComponent<Props>;
export {};
import './PropertyEditors.css';
export declare const CardStyleEditor: import("react").NamedExoticComponent<object>;
import type { CardElement } from '../../types/schema';
import './PropertyEditors.css';
interface Props {
element: CardElement;
onUpdate: (updates: Partial<CardElement>) => void;
}
export declare const ElementPropertyEditor: import("react").NamedExoticComponent<Props>;
export {};
import type { IconRef } from '../../types/schema';
interface Props {
value: IconRef | string | undefined;
onChange: (v: IconRef | undefined) => void;
}
export declare const IconPicker: import("react").NamedExoticComponent<Props>;
export {};
import './PropertyEditors.css';
export declare const NotificationEditor: import("react").NamedExoticComponent<object>;
import './PropertyEditors.css';
export declare const VariableEditor: import("react").NamedExoticComponent<object>;
interface VariableInputProps {
value: string;
onChange: (v: string) => void;
placeholder?: string;
multiline?: boolean;
rows?: number;
style?: React.CSSProperties;
}
export declare const VariableInput: import("react").NamedExoticComponent<VariableInputProps>;
export {};
import type { CardElement } from '../../types/schema';
interface ElementRendererProps {
element: CardElement;
path: number[];
selectedPath: number[] | null;
selectedPaths: number[][];
onSelect: (path: number[] | null) => void;
onToggleSelect: (path: number[]) => void;
onMove: (path: number[], direction: 'up' | 'down') => void;
onRemove: (path: number[]) => void;
onWrap: (path: number[], wrapperType: 'row' | 'column' | 'grid') => void;
onUnwrap: (path: number[]) => void;
onDuplicate: (path: number[]) => void;
isFirst: boolean;
isLast: boolean;
inRow?: boolean;
colorMode?: 'light' | 'dark';
}
export declare const ElementRenderer: import("react").NamedExoticComponent<ElementRendererProps>;
export {};
import './RightPanel.css';
export declare const RightPanel: import("react").NamedExoticComponent<object>;
import './ShortcutsPanel.css';
export declare const ShortcutsPanel: import("react").NamedExoticComponent<object>;
import './TemplateLibrary.css';
export declare const TemplateLibrary: import("react").NamedExoticComponent<object>;
import './TopBar.css';
export declare const TopBar: import("react").NamedExoticComponent<object>;
import type { ReactNode, ButtonHTMLAttributes } from 'react';
type ButtonVariant = 'primary' | 'secondary' | 'danger' | 'link';
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
variant?: ButtonVariant;
children: ReactNode;
}
export declare const Button: import("react").NamedExoticComponent<ButtonProps>;
export {};
import type { ColorValue } from '../../types/schema';
/**
* Color section with light/dark toggle header + color fields.
* Usage:
* ```
* <ColorSection>
* {(mode) => (
* <>
* <ColorField label="Background" value={el.backgroundColor} onChange={(v) => onUpdate({ backgroundColor: v })} mode={mode} />
* <ColorField label="Border" value={el.borderColor} onChange={(v) => onUpdate({ borderColor: v })} mode={mode} />
* </>
* )}
* </ColorSection>
* ```
*/
export declare function ColorSection({ children }: {
children: (mode: 'light' | 'dark') => React.ReactNode;
}): import("react/jsx-runtime").JSX.Element;
/**
* Single color field: label + swatch + hex input.
* Respects light/dark mode to show/edit the correct side of a ColorValue.
*/
export declare function ColorField({ label, value, onChange, fallback, transparentValue, mode, }: {
label: string;
value: ColorValue | undefined;
onChange: (v: ColorValue | undefined) => void;
fallback?: string;
transparentValue?: ColorValue;
mode?: 'light' | 'dark';
}): import("react/jsx-runtime").JSX.Element;
interface EmptyStateProps {
icon: string;
title: string;
subtitle: string;
}
export declare const EmptyState: import("react").NamedExoticComponent<EmptyStateProps>;
export {};
interface MaterialIconProps {
icon: string;
size?: number;
filled?: boolean;
className?: string;
style?: React.CSSProperties;
}
export declare const MaterialIcon: import("react").NamedExoticComponent<MaterialIconProps>;
export {};
import type { ReactNode, CSSProperties } from 'react';
interface ModalProps {
title: string;
onClose: () => void;
children: ReactNode;
footer?: ReactNode;
width?: number;
style?: CSSProperties;
}
export declare const Modal: import("react").NamedExoticComponent<ModalProps>;
export {};
/**
* Unified app credentials state.
*
* Priority:
* 1. Props (highest) — passed via mountCardBuilder → read-only, non-editable
* 2. User-entered — set via App Credentials modal → editable (token cannot be set here)
* 3. Env vars (lowest, dev only) — from .env, set via builderConfig in App.tsx
*
* Note: `token` can only come from props or env (never user-entered).
*/
export interface AppCredentials {
appId: string;
region: string;
token: string;
apiKey: string;
}
/** Initialize credentials from mount props (highest priority, read-only) */
export declare function initCredentials(appId?: string, region?: string, token?: string, apiKey?: string, lock?: boolean): void;
/**
* Get resolved credentials (props > user-entered).
* Each field is resolved independently — props field wins if non-empty.
*/
export declare function getCredentials(): AppCredentials;
/** Whether credentials were provided via props (should be non-editable) */
export declare function isProvidedByProps(): boolean;
/** Whether we have enough credentials for template API calls (appId + token) */
export declare function hasApiCredentials(): boolean;
/** Whether we have enough credentials for sending messages (appId + region + apiKey) */
export declare function hasSendCredentials(): boolean;
/** Legacy: whether all credentials are configured */
export declare function hasCredentials(): boolean;
/** Update user-entered credentials (only works if not provided by props) */
export declare function setCredentials(creds: Partial<AppCredentials>): void;
/** Get user-entered credentials (for displaying in the modal) */
export declare function getUserCredentials(): AppCredentials;
/** Subscribe to credential changes */
export declare function subscribeCredentials(fn: () => void): () => void;
/** Reset credentials (used on destroy) */
export declare function resetCredentials(): void;
/**
* React hook: reactively reports whether template/variable (apimgmt) APIs are usable
* (appId + bearer token). Use this to hide token-requiring UI when no token is present.
*/
export declare function useHasApiCredentials(): boolean;
import type { CardMessage } from '../types/schema';
export interface CardVariable {
/** Variable name used in {{name}} tokens, e.g. 'user.name' */
name: string;
/** Human-readable label shown in the picker */
label?: string;
/** Short description */
description?: string;
/** Category for grouping in the picker */
category?: string;
}
export interface NotificationConfig {
/** App name shown in the notification preview */
appName?: string;
/** App icon URL shown in the notification preview */
appIcon?: string;
/** Show the Data key-value editor in the notification tab */
enableData?: boolean;
/** Show the push notification phone preview in the canvas. Default: true */
showPreview?: boolean;
/** Called when notification title or body changes */
onNotificationChange?: (notification: {
title: string;
body: string;
}) => void;
/** Called when notification data changes */
onNotificationDataChange?: (data: Record<string, string>) => void;
}
/** Which channels the builder supports */
export type BuilderChannels = 'inapp' | 'push' | 'both';
/** Module-level config accessible by components */
export declare const builderConfig: {
appId?: string;
region?: string;
token?: string;
onSave?: (json: CardMessage, name: string, description: string) => void;
onChange?: (json: CardMessage) => void;
hideTopBar?: boolean;
hideTemplateLibrary?: boolean;
channels?: BuilderChannels;
/** Whether channels was explicitly provided by the host app (vs defaulted to 'both') */
channelsExplicit?: boolean;
/** Show the variable editor tab for creating/managing variables. Default: true */
enableVariableEditor?: boolean;
notification?: NotificationConfig;
/** Enable the built-in variable creation/management UI. Default: false */
enableVariableManager?: boolean;
/** Show the canvas toolbar (zoom, dark mode, preview, JSON). Default: false */
showCanvasToolbar?: boolean;
/** Hide the left panel (elements & components palette). Default: false */
/** Disable all editing interactions — read-only preview mode. Default: false */
readOnly?: boolean;
hideElementPalette?: boolean;
/** Hide the right panel (tree, element properties, card settings). Default: false */
hidePropertyPanel?: boolean;
};
export interface ComponentTemplate {
name: string;
category: string;
icon: string;
description: string;
elements: Record<string, unknown>[];
}
export declare const COMPONENT_TEMPLATES: ComponentTemplate[];
export declare const COMPONENT_CATEGORIES: string[];
export declare const COMPONENT_TEMPLATE_NAMES: readonly ["Product Card", "Order Confirmation", "Announcement", "Quick Reply Buttons", "Order Tracking", "Event Card", "Feedback", "Data Table", "Carousel"];
export type ComponentTemplateName = typeof COMPONENT_TEMPLATE_NAMES[number];
import type { CardElement } from '../types/schema';
export declare const ELEMENT_DEFAULTS: Map<string, () => CardElement>;
export declare const ELEMENT_PALETTE: {
readonly Layout: readonly ["row", "column", "grid", "accordion", "tabs"];
readonly Content: readonly ["text", "image", "icon", "avatar", "badge", "divider", "spacer", "chip", "markdown", "codeBlock"];
readonly 'Data Display': readonly ["table", "progressBar"];
readonly Actions: readonly ["button", "iconButton", "link"];
};
export interface IconEntry {
name: string;
label: string;
url: string;
category: string;
}
export declare const ICON_LIBRARY: IconEntry[];
export declare const ICON_MAP: Map<string, IconEntry>;
export declare const ICON_CATEGORIES: string[];
/** Resolve an icon name to its URL. Returns the name as-is if it's already a URL. */
export declare function resolveIconUrl(nameOrUrl: string): string;
import type { UIKitColorMode } from './uikit-theme';
/** Build a flat token map from UIKit theme colors */
export declare function buildTokensFromUIKit(colors: UIKitColorMode): Record<string, string>;
export declare const THEME_TOKENS: Record<string, string>;
export declare const DARK_THEME_TOKENS: Record<string, string>;
export declare let THEME_TOKEN_NAMES: string[];
export declare function setActiveTheme(dark: boolean): void;
/** Sync active theme tokens from the UIKit theme store */
export declare function syncThemeTokens(lightColors: UIKitColorMode, darkColors: UIKitColorMode, isDark: boolean): void;
export declare function resolveColor(value: string | undefined, fallback?: string): string;
export declare const TEXT_VARIANT_STYLES: Record<string, React.CSSProperties>;
export declare function hexToRgb(hex: string): {
r: number;
g: number;
b: number;
};
export declare function rgbToHex(r: number, g: number, b: number): string;
export declare const SHADE_KEYS: readonly [50, 100, 200, 300, 400, 500, 600, 700, 800, 900];
export declare function generateExtendedPrimary(primary: string): {
light: Record<number, string>;
dark: Record<number, string>;
};
export declare function generateSpacingScale(baseUnit?: number, steps?: number): Record<string, number>;
export declare function generatePadding(scale: Record<string, number>): Record<string, number>;
export declare function generateRadius(scale: Record<string, number>): Record<string, number>;
export interface UIKitColorMode {
primary: string;
extendedPrimary: Record<number, string>;
neutral: Record<number, string>;
alert: {
info: string;
warning: string;
success: string;
error: string;
};
staticColors: {
black: string;
white: string;
};
sendBubble: {
background: string;
text: string;
textHighlight: string;
link: string;
timestamp: string;
icon: string;
};
receiveBubble: {
background: string;
text: string;
textHighlight: string;
link: string;
timestamp: string;
icon: string;
};
}
export interface UIKitTheme {
name: string;
version: string;
spacing: {
baseUnit: number;
scale: Record<string, number>;
padding: Record<string, number>;
radius: Record<string, number>;
};
typography: {
fontFamily: string;
scale: Record<string, {
size: number;
lineHeight: number;
weight?: string;
}>;
weights: {
bold: string;
medium: string;
regular: string;
};
};
colors: {
light: UIKitColorMode;
dark: UIKitColorMode;
};
}
export declare function createDefaultTheme(): UIKitTheme;
export declare function useKeyboardShortcuts(): void;
import type { CardMessage, ElementType } from './types/schema';
import type { ComponentTemplateName } from './config/component-templates';
import type { CardVariable, NotificationConfig, BuilderChannels } from './config/builder-config';
import './index.css';
export type { CardVariable } from './config/builder-config';
export type { NotificationConfig, BuilderChannels } from './config/builder-config';
export interface CardBuilderOptions {
/** CometChat app ID (required for template save/load APIs) */
appId?: string;
/** App region — us, eu, etc. (required for template save/load APIs) */
region?: string;
/** Bearer token — legacy; no longer used for template save/load auth (apiKey is). */
token?: string;
/** CometChat REST API Key (required for template save/load and sending messages) */
apiKey?: string;
/** Existing card JSON to load for editing */
card?: CardMessage;
/** Initial notification title (only used when channels includes push). */
notificationTitle?: string;
/** Initial notification body (only used when channels includes push). */
notificationBody?: string;
/** Template name */
templateName?: string;
/** Called when user clicks Save */
onSave?: (json: CardMessage, name: string, description: string) => void;
/** Called whenever the card JSON changes (any edit). Use for real-time sync. */
onChange?: (json: CardMessage) => void;
/** Available variables for {{placeholder}} insertion in text/URL fields */
variables?: CardVariable[];
/** Hide the top toolbar (save, export, import, undo/redo, template name). Default: false */
hideTopBar?: boolean;
/** Hide the template library view — go straight to editor. Default: false */
hideTemplateLibrary?: boolean;
/** Disable all editing interactions — read-only preview mode. Default: false */
readOnly?: boolean;
/** Show the variable editor tab for creating/managing variables in the builder. Default: true */
enableVariableEditor?: boolean;
/** Which channels to show: 'inapp', 'push', or 'both' (default). */
channels?: BuilderChannels;
/** Push notification preview config (app name, icon). Only used when channels is 'push' or 'both'. */
notification?: NotificationConfig;
/** Element types to hide from the palette (e.g. ['codeBlock', 'table', 'markdown']) */
hiddenElements?: ElementType[];
/** Component template names to hide from the palette (e.g. ['Product Card', 'Data Table']) */
hiddenComponents?: ComponentTemplateName[];
/** Hide the left panel (elements & components palette). Default: false */
hideElementPalette?: boolean;
/** Hide the right panel (tree, element properties, card settings). Default: false */
hidePropertyPanel?: boolean;
/** Show the canvas toolbar (zoom, dark mode, preview, JSON). Default: false */
showCanvasToolbar?: boolean;
}
export interface CardBuilderInstance {
loadCard: (card: CardMessage, name?: string) => void;
getCardJSON: () => CardMessage;
setVariables: (variables: CardVariable[]) => void;
setChannels: (channels: BuilderChannels) => void;
setCanvasView: (view: 'card' | 'notification') => void;
setReadOnly: (readOnly: boolean) => void;
/** Hide specific element types from the palette. Pass element type names (e.g. 'codeBlock', 'table'). */
setHiddenElements: (types: ElementType[]) => void;
/** Hide specific component templates from the palette. Pass template names (e.g. 'Product Card'). */
setHiddenComponents: (names: ComponentTemplateName[]) => void;
/** Show or hide the left panel at runtime. */
setHideElementPalette: (hide: boolean) => void;
/** Show or hide the right panel at runtime. */
setHidePropertyPanel: (hide: boolean) => void;
/** Show or hide the canvas toolbar at runtime. */
setShowCanvasToolbar: (show: boolean) => void;
/** Set notification title at runtime. */
setNotificationTitle: (title: string) => void;
/** Set notification body at runtime. */
setNotificationBody: (body: string) => void;
/** Set API key at runtime. */
setApiKey: (apiKey: string) => void;
destroy: () => void;
}
export { builderConfig } from './config/builder-config';
export declare function mountCardBuilder(container: HTMLElement, options: CardBuilderOptions): CardBuilderInstance;
export type { CardMessage, ElementType } from './types/schema';
export type { ComponentTemplateName } from './config/component-templates';
import type { CardElement, CardStyle, CardMessage, Template, ElementType, MessageData } from '../types/schema';
import type { ComponentTemplateName } from '../config/component-templates';
import { type CardVariable } from '../config/builder-config';
export interface BuilderState {
templateId: string | null;
templateName: string;
templateDescription: string;
body: CardElement[];
style: CardStyle;
fallbackText: string;
notificationTitle: string;
notificationBody: string;
notificationData: Array<{
key: string;
value: string;
}>;
/** Custom message type for CometChat message structure (e.g. 'product', 'order') */
messageType: string;
notificationEnabled: boolean;
/** Which view the canvas shows: card editor or notification preview */
canvasView: 'card' | 'notification';
/** Which channels are available */
channels: 'inapp' | 'push' | 'both';
/** Whether channels was explicitly set (vs default) */
channelsExplicit: boolean;
/** Read-only mode — disables all editing interactions */
readOnly: boolean;
selectedPath: number[] | null;
selectedPaths: number[][];
isDirty: boolean;
useThemePlaceholders: boolean;
/** Element types hidden from the palette */
hiddenElements: Set<ElementType>;
/** Component template names hidden from the palette */
hiddenComponents: Set<ComponentTemplateName>;
view: 'library' | 'editor';
clipboard: CardElement | null;
showTemplatePicker: boolean;
/** Hide the left panel (elements & components palette) */
hideElementPalette: boolean;
/** Hide the right panel (tree, element properties, card settings) */
hidePropertyPanel: boolean;
/** Show the canvas toolbar (zoom, dark mode, preview, JSON). Default: false */
showCanvasToolbar: boolean;
/** Show the variable editor tab. Default: true */
enableVariableEditor: boolean;
variables: CardVariable[];
history: {
body: CardElement[];
style: CardStyle;
}[];
historyIndex: number;
templates: Template[];
templatesLoading: boolean;
templatesMeta: {
previous?: {
affix: string;
createdAt: number;
};
next?: {
affix: string;
createdAt: number;
};
} | null;
setView: (view: 'library' | 'editor') => void;
setShowTemplatePicker: (show: boolean) => void;
setHideElementPalette: (hide: boolean) => void;
setHidePropertyPanel: (hide: boolean) => void;
setShowCanvasToolbar: (show: boolean) => void;
setEnableVariableEditor: (enable: boolean) => void;
selectElement: (path: number[] | null) => void;
toggleSelectElement: (path: number[]) => void;
addElement: (element: CardElement, parentPath?: number[]) => void;
updateElement: (path: number[], updates: Partial<CardElement>) => void;
removeElement: (path: number[]) => void;
moveElement: (path: number[], direction: 'up' | 'down') => void;
updateStyle: (settings: Partial<CardStyle>) => void;
setFallbackText: (text: string) => void;
setNotificationTitle: (text: string) => void;
setNotificationBody: (text: string) => void;
setMessageType: (type: string) => void;
setNotificationData: (data: Array<{
key: string;
value: string;
}>) => void;
setNotificationEnabled: (enabled: boolean) => void;
setCanvasView: (view: 'card' | 'notification') => void;
setChannels: (channels: 'inapp' | 'push' | 'both') => void;
setReadOnly: (readOnly: boolean) => void;
setHiddenElements: (types: ElementType[]) => void;
setHiddenComponents: (names: ComponentTemplateName[]) => void;
setUseThemePlaceholders: (use: boolean) => void;
setVariables: (variables: CardVariable[]) => void;
addVariable: (variable: CardVariable) => void;
updateVariable: (index: number, variable: CardVariable) => void;
removeVariable: (index: number) => void;
setTemplateName: (name: string) => void;
setTemplateDescription: (desc: string) => void;
loadCard: (card: CardMessage, templateId?: string, name?: string, desc?: string) => void;
loadTemplate: (template: Template) => void;
newCard: () => void;
getCardJSON: (opts?: {
stripEmpty?: boolean;
}) => CardMessage;
/** Get the full CometChat message structure wrapping the card (used when channels not set) */
getMessageJSON: () => MessageData;
setTemplates: (templates: Template[]) => void;
fetchTemplates: (search?: string) => Promise<void>;
fetchNextPage: () => Promise<void>;
fetchPrevPage: () => Promise<void>;
saveTemplate: () => Promise<void>;
deleteTemplate: (id: string) => Promise<void>;
reorderElement: (fromPath: number[], toPath: number[], toIndex: number) => void;
moveElementToPath: (fromPath: number[], toParentPath: number[], toIndex: number) => void;
wrapElement: (path: number[], wrapperType: 'row' | 'column' | 'grid') => void;
unwrapElement: (path: number[]) => void;
wrapSelected: (wrapperType: 'row' | 'column' | 'grid') => void;
duplicateElement: (path: number[]) => void;
copyElement: (path: number[]) => void;
pasteElement: (targetPath?: number[]) => void;
undo: () => void;
redo: () => void;
canUndo: () => boolean;
canRedo: () => boolean;
clearAll: () => void;
}
export declare const DEFAULT_STYLE: CardStyle;
export declare const useBuilderStore: import("zustand").UseBoundStore<import("zustand").StoreApi<BuilderState>>;
export type Padding = number | {
top?: number;
right?: number;
bottom?: number;
left?: number;
};
export type SizeOrPercentage = number | string;
export type ColorValue = {
light: string;
dark: string;
} | 'transparent';
/** Resolve a ColorValue to a hex string for the given mode. Returns 'transparent' for "transparent". */
export declare function resolveColor(cv: ColorValue | undefined, mode?: 'light' | 'dark'): string | undefined;
/** Create a ColorValue from a single hex (same for both modes). */
export declare function colorVal(hex: string): ColorValue;
/** Create a ColorValue with distinct light/dark values. */
export declare function colorValLD(light?: string, dark?: string): ColorValue;
export interface OpenUrlAction {
type: 'openUrl';
url: string;
openIn?: 'browser' | 'webview';
}
export interface ChatWithUserAction {
type: 'chatWithUser';
uid: string;
}
export interface ChatWithGroupAction {
type: 'chatWithGroup';
guid: string;
}
export interface SendMessageAction {
type: 'sendMessage';
text: string;
receiverUid?: string;
receiverGuid?: string;
}
export interface CopyToClipboardAction {
type: 'copyToClipboard';
value: string;
}
export interface DownloadFileAction {
type: 'downloadFile';
url: string;
filename?: string;
}
export interface InitiateCallAction {
type: 'initiateCall';
uid?: string;
guid?: string;
callType: 'audio' | 'video';
}
export interface ApiCallAction {
type: 'apiCall';
url: string;
method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
headers?: Record<string, string>;
body?: Record<string, unknown>;
}
export interface CustomCallbackAction {
type: 'customCallback';
}
export type CardAction = OpenUrlAction | ChatWithUserAction | ChatWithGroupAction | SendMessageAction | CopyToClipboardAction | DownloadFileAction | InitiateCallAction | ApiCallAction | CustomCallbackAction;
export declare const ACTION_TYPES: readonly ["openUrl", "chatWithUser", "chatWithGroup", "sendMessage", "copyToClipboard", "downloadFile", "initiateCall", "apiCall", "customCallback"];
export type ActionType = typeof ACTION_TYPES[number];
/** Reference to an icon. Use 'name' for built-in icons, 'url' for custom icon URLs. If both present, url takes precedence. */
export interface IconRef {
name?: string;
url?: string;
}
export interface TextElement {
id: string;
type: 'text';
content: string;
variant?: 'title' | 'heading1' | 'heading2' | 'heading3' | 'heading4' | 'body' | 'caption1' | 'caption2';
color?: ColorValue;
align?: 'left' | 'center' | 'right' | 'justify';
fontWeight?: 'regular' | 'medium' | 'bold';
maxLines?: number;
padding?: Padding;
}
export interface ImageElement {
id: string;
type: 'image';
url: string;
altText?: string;
fit?: 'cover' | 'contain' | 'fill';
width?: SizeOrPercentage;
height?: SizeOrPercentage;
borderRadius?: number;
padding?: Padding;
}
export interface IconElement {
id: string;
type: 'icon';
name?: string;
url?: string;
size?: number;
color?: ColorValue;
backgroundColor?: ColorValue;
borderRadius?: number;
padding?: number;
}
export interface AvatarElement {
id: string;
type: 'avatar';
imageUrl?: string;
fallbackInitials?: string;
size?: number;
borderRadius?: number;
backgroundColor?: ColorValue;
fontSize?: number;
fontWeight?: 'regular' | 'medium' | 'bold';
}
export interface BadgeElement {
id: string;
type: 'badge';
text: string;
color?: ColorValue;
size?: number;
backgroundColor?: ColorValue;
borderColor?: ColorValue;
borderWidth?: number;
borderRadius?: number;
padding?: Padding;
fontSize?: number;
}
export interface DividerElement {
id: string;
type: 'divider';
color?: ColorValue;
thickness?: number;
margin?: number;
}
export interface SpacerElement {
id: string;
type: 'spacer';
height: number;
}
export interface ChipElement {
id: string;
type: 'chip';
text: string;
color?: ColorValue;
icon?: IconRef;
backgroundColor?: ColorValue;
borderColor?: ColorValue;
borderWidth?: number;
borderRadius?: number;
padding?: Padding;
fontSize?: number;
}
export interface ProgressBarElement {
id: string;
type: 'progressBar';
value: number;
color?: ColorValue;
trackColor?: ColorValue;
height?: number;
label?: string;
borderRadius?: number;
labelFontSize?: number;
labelColor?: ColorValue;
}
export interface CodeBlockElement {
id: string;
type: 'codeBlock';
content: string;
language?: string;
backgroundColor?: ColorValue;
textColor?: ColorValue;
padding?: Padding;
borderRadius?: number;
fontSize?: number;
languageLabelFontSize?: number;
languageLabelColor?: ColorValue;
}
export interface MarkdownElement {
id: string;
type: 'markdown';
content: string;
baseFontSize?: number;
linkColor?: ColorValue;
color?: ColorValue;
lineHeight?: number;
}
export interface RowElement {
id: string;
type: 'row';
items: CardElement[];
gap?: number;
align?: 'start' | 'center' | 'end' | 'spaceBetween' | 'spaceAround';
crossAlign?: 'start' | 'center' | 'end';
wrap?: boolean;
scrollable?: boolean;
peek?: number;
snap?: 'item' | 'free';
padding?: Padding;
backgroundColor?: ColorValue;
borderRadius?: number;
borderColor?: ColorValue;
borderWidth?: number;
}
export interface ColumnElement {
id: string;
type: 'column';
items: CardElement[];
gap?: number;
align?: 'start' | 'center' | 'end' | 'stretch';
crossAlign?: 'start' | 'center' | 'end';
padding?: Padding;
backgroundColor?: ColorValue;
borderRadius?: number;
borderColor?: ColorValue;
borderWidth?: number;
}
export interface GridElement {
id: string;
type: 'grid';
items: CardElement[];
columns?: 2 | 3 | 4;
gap?: number;
padding?: Padding;
backgroundColor?: ColorValue;
borderRadius?: number;
borderColor?: ColorValue;
borderWidth?: number;
}
export interface AccordionElement {
id: string;
type: 'accordion';
header: string;
headerIcon?: IconRef;
body: CardElement[];
expandedByDefault?: boolean;
border?: boolean;
padding?: Padding;
fontSize?: number;
fontWeight?: 'regular' | 'medium' | 'bold';
borderRadius?: number;
}
export interface TabsElement {
id: string;
type: 'tabs';
tabs: {
label: string;
content: CardElement[];
}[];
defaultActiveTab?: number;
tabAlign?: 'start' | 'center' | 'stretch';
tabPadding?: Padding;
contentPadding?: Padding;
fontSize?: number;
}
export interface ButtonElement {
id: string;
type: 'button';
label: string;
action: CardAction;
backgroundColor?: ColorValue;
textColor?: ColorValue;
borderColor?: ColorValue;
borderWidth?: number;
borderRadius?: number;
icon?: IconRef;
iconPosition?: 'left' | 'right';
size?: number;
fullWidth?: boolean;
padding?: Padding;
fontSize?: number;
}
export interface IconButtonElement {
id: string;
type: 'iconButton';
icon: IconRef;
action: CardAction;
size?: number;
color?: ColorValue;
backgroundColor?: ColorValue;
borderRadius?: number;
}
export interface LinkElement {
id: string;
type: 'link';
text: string;
action: CardAction;
color?: ColorValue;
underline?: boolean;
fontSize?: number;
}
export interface TableElement {
id: string;
type: 'table';
columns: string[];
rows: string[][];
headerBackgroundColor?: ColorValue;
border?: boolean;
stripedRows?: boolean;
cellPadding?: number;
fontSize?: number;
stripedRowColor?: ColorValue;
borderColor?: ColorValue;
}
export type CardElement = TextElement | ImageElement | IconElement | AvatarElement | BadgeElement | DividerElement | SpacerElement | ChipElement | ProgressBarElement | CodeBlockElement | MarkdownElement | RowElement | ColumnElement | GridElement | AccordionElement | TabsElement | ButtonElement | IconButtonElement | LinkElement | TableElement;
export type ElementType = CardElement['type'];
export interface CardStyle {
background: ColorValue;
borderRadius?: number;
borderColor?: ColorValue;
borderWidth?: number;
padding?: Padding;
}
export interface CardMessage {
version: '1.0';
body: CardElement[];
style: CardStyle;
fallbackText: string;
}
export interface MessageData {
category: string;
type: string;
data: {
text: string;
card: CardMessage;
};
}
export interface Template {
id: string;
name: string;
description?: string;
schemaVersion?: string;
messageData: MessageData;
thumbnail?: string;
createdBy?: string;
createdAt: number;
updatedAt: number;
}
export declare function isContainerElement(el: CardElement): el is RowElement | ColumnElement | GridElement | AccordionElement;
export declare function getContainerChildren(el: CardElement): CardElement[] | null;
import type { CardElement } from '../types/schema';
export interface FieldError {
field: string;
message: string;
}
/** Returns field-level validation errors for a single element. */
export declare function getElementErrors(el: CardElement): FieldError[];
/** Quick check: does this element have any errors? Useful for tree indicators. */
export declare function hasElementErrors(el: CardElement): boolean;
export declare function generateId(type: string): string;
import type { CardElement } from '../types/schema';
/** Recursively assign IDs to all elements that don't have one */
export declare function assignIds(elements: CardElement[]): CardElement[];
export declare function setPortalRoot(el: HTMLElement): void;
export declare function getPortalRoot(): HTMLElement;
import type { CardMessage } from '../types/schema';
export interface ValidationError {
path: string;
message: string;
}
export declare function validateCard(card: CardMessage): ValidationError[];
+1
-1
{
"name": "@cometchat/card-builder",
"version": "2.0.0",
"version": "2.0.1",
"type": "module",

@@ -5,0 +5,0 @@ "main": "dist/card-builder.umd.js",

Sorry, the diff of this file is too big to display

@import "https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200";.bb-root .tl-container{max-width:61.4286rem;margin:0 auto;padding:4.57143rem 1.71429rem}.bb-root .tl-header{text-align:center;margin-bottom:3.14286rem}.bb-root .tl-logo{background:var(--accent-primary);color:#fff;border-radius:.85714rem;justify-content:center;align-items:center;width:3.42857rem;height:3.42857rem;margin:0 auto 1.14286rem;font-size:1.14286rem;font-weight:800;display:flex}.bb-root .tl-title{color:var(--text-primary);font-size:1.14286rem;font-weight:700}.bb-root .tl-subtitle{color:var(--text-secondary);margin-top:.42857rem;font-size:1rem}.bb-root .tl-actions{gap:.71429rem;margin-bottom:2.57143rem;display:flex}.bb-root .tl-search{flex:1}.bb-root .tl-section{margin-bottom:2.57143rem}.bb-root .tl-section-title{color:#141414;margin-bottom:.85714rem;font-size:1rem;font-weight:600}.bb-root .tl-grid{grid-template-columns:repeat(auto-fill,minmax(13.5714rem,1fr));gap:.71429rem;display:grid}.bb-root .tl-card{text-align:left;box-shadow:none;background:#fff;border:1px solid #e9eaeb;border-radius:.57143rem;padding:1.14286rem;transition:all .15s}.bb-root .tl-card:hover{border-color:var(--accent-primary);box-shadow:var(--shadow-sm)}.bb-root .tl-card-badge{text-transform:uppercase;letter-spacing:.5px;color:var(--accent-primary);margin-bottom:.42857rem;font-size:.78571rem;font-weight:700}.bb-root .tl-card-name{color:#141414;font-size:1rem;font-weight:600}.bb-root .tl-card-desc{color:#727272;margin-top:.14286rem;font-size:.85714rem}.bb-root .tl-card-date{color:#bfbfbc;margin-top:.28571rem;font-size:.78571rem}.bb-root .tl-card{position:relative}.bb-root .tl-card-delete{width:1.57143rem;height:1.57143rem;color:var(--text-tertiary);cursor:pointer;opacity:0;background:0 0;border:none;border-radius:.28571rem;justify-content:center;align-items:center;font-size:1rem;transition:all .15s;display:flex;position:absolute;top:.57143rem;right:.57143rem}.bb-root .tl-card:hover .tl-card-delete{opacity:1}.bb-root .tl-card-delete:hover{color:#dc2626;background:#fee2e2}.bb-root .tl-pagination{justify-content:space-between;align-items:center;margin-top:1.14286rem;display:flex}.bb-root .tl-loading{text-align:center;color:var(--text-tertiary);padding:2.85714rem 1.42857rem;font-size:.92857rem}.bb-root .topbar{background:var(--bg-primary);border-bottom:1px solid var(--border-subtle);flex-shrink:0;justify-content:space-between;align-items:center;height:4rem;padding:0 1.42857rem;display:flex;position:relative}.bb-root .topbar-left{align-items:center;gap:.85714rem;display:flex}.bb-root .topbar-back{border-radius:var(--radius-sm);color:var(--text-secondary);padding:.28571rem .42857rem;font-size:1.28571rem}.bb-root .topbar-back:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .topbar-logo{align-items:center;gap:.57143rem;display:flex}.bb-root .topbar-logo-icon{background:var(--accent-primary);color:#fff;border-radius:.42857rem;justify-content:center;align-items:center;width:1.71429rem;height:1.71429rem;font-size:.64286rem;font-weight:800;display:flex}.bb-root .topbar-logo span{color:var(--text-primary);letter-spacing:-.3px;font-size:1.14286rem;font-weight:600}.bb-root .topbar-sep{background:var(--border-medium);width:1px;height:1.14286rem}.bb-root .topbar-title{color:var(--text-secondary);font-size:1rem;font-weight:500}.bb-root .topbar-name{border-radius:var(--radius-sm);min-width:10rem;max-width:14.2857rem;color:var(--text-primary);box-shadow:none;background:0 0;border:1px solid #0000;padding:.42857rem .57143rem;font-size:1rem;font-weight:500}.bb-root .topbar-name:hover{border-color:var(--border-medium)}.bb-root .topbar-name:focus{border-color:var(--accent-primary)}.bb-root .topbar-dirty{color:var(--accent-primary);font-size:.57143rem}.bb-root .topbar-right{align-items:center;gap:.57143rem;display:flex}.bb-root .topbar-btn{color:#414651;background:#fff;border-radius:.57143rem;outline:1px solid #d5d7da;align-items:center;gap:.42857rem;height:2.57143rem;padding:0 1.14286rem;font-size:1rem;font-weight:600;line-height:1.333;transition:all .15s;display:flex}.bb-root .topbar-btn:hover{background:#f5f5f5}.bb-root .topbar-toast{color:#fff;background:var(--success);z-index:2000;border-radius:.57143rem;align-items:center;gap:.57143rem;padding:.85714rem 1.42857rem;font-size:1rem;font-weight:500;display:flex;position:fixed;bottom:1.71429rem;left:50%;transform:translate(-50%);box-shadow:0 .28571rem .85714rem #00000026}.bb-root .modal-subtitle{color:var(--text-secondary);text-transform:uppercase;letter-spacing:.5px;margin:.85714rem 0 .57143rem;font-size:.78571rem;font-weight:600}.bb-root .modal-field{margin-bottom:.85714rem}.bb-root .modal-label{color:var(--text-secondary);margin-bottom:.42857rem;font-size:.85714rem;font-weight:500;display:block}.bb-root .topbar-btn-icon{border-radius:var(--radius-sm);width:2.28571rem;height:2.28571rem;color:var(--text-secondary);justify-content:center;align-items:center;font-size:1.14286rem;transition:all .15s;display:flex}.bb-root .topbar-btn-icon:hover:not(:disabled){background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .topbar-btn-icon:disabled{opacity:.3;cursor:default}.bb-root .topbar-btn-warn{color:#d97706;background:#fffbeb;border-color:#fcd34d}.bb-root .topbar-btn-warn:hover{background:#fef3c7}.bb-root .topbar-errors{border:1px solid var(--border-subtle);border-radius:var(--radius-lg);z-index:100;min-width:20rem;max-height:14.2857rem;box-shadow:var(--shadow-lg);background:#fff;margin-top:.57143rem;padding:.57143rem;font-size:.85714rem;position:absolute;top:100%;right:0;overflow-y:auto}.bb-root .topbar-error-item{border-radius:.28571rem;flex-direction:column;gap:.14286rem;padding:.42857rem .57143rem;display:flex}.bb-root .topbar-error-item:hover{background:#fef3c7}.bb-root .topbar-error-path{font-family:var(--font-mono);color:#d97706;font-size:.71429rem}.bb-root .topbar-dropdown{position:relative}.bb-root .topbar-dropdown-menu{background:var(--bg-primary);border:1px solid var(--border-subtle);border-radius:var(--radius-md);z-index:100;min-width:12.8571rem;box-shadow:var(--shadow-lg);margin-top:.42857rem;padding:.28571rem;position:absolute;top:100%;right:0}.bb-root .topbar-dropdown-item{width:100%;color:var(--text-primary);border-radius:var(--radius-sm);cursor:pointer;text-align:left;background:0 0;border:none;align-items:center;gap:.57143rem;padding:.57143rem .85714rem;font-size:.92857rem;font-weight:400;display:flex}.bb-root .topbar-dropdown-item:hover{background:var(--bg-tertiary)}.bb-root .left-panel{background:var(--bg-primary);border-right:1px solid var(--border-subtle);flex-direction:column;flex-shrink:0;width:22.8571rem;min-width:18.5714rem;max-width:28.5714rem;font-size:1rem;display:flex;overflow:hidden}.bb-root .lp-header{padding:.85714rem .85714rem .57143rem}.bb-root .lp-tabs{background:var(--bg-tertiary);border-radius:.57143rem;grid-template-columns:1fr 1fr;gap:.14286rem;padding:.21429rem;display:grid}.bb-root .lp-tab{height:2.57143rem;color:var(--text-secondary);background:0 0;border-radius:.42857rem;justify-content:center;align-items:center;gap:.42857rem;font-size:.92857rem;font-weight:500;transition:all .15s;display:flex}.bb-root .lp-tab:hover{color:var(--text-primary)}.bb-root .lp-tab.active{background:var(--bg-primary);color:var(--text-primary);box-shadow:0 1px .21429rem #00000014}.bb-root .lp-search-wrap{padding:0 .85714rem .57143rem;position:relative}.bb-root .lp-search-icon{color:var(--text-muted);pointer-events:none;margin-top:-.28571rem;position:absolute;top:50%;left:1.57143rem;transform:translateY(-50%)}.bb-root .lp-search{border:1px solid var(--border-subtle);width:100%;height:2.57143rem;color:var(--text-primary);background:#fafafa;border-radius:.57143rem;padding:0 2.28571rem 0 2.57143rem;font-size:.92857rem;transition:all .15s}.bb-root .lp-search::placeholder{color:var(--text-muted)}.bb-root .lp-search:focus{background:var(--bg-primary);border-color:var(--accent-primary);outline:none;box-shadow:0 0 0 .14286rem #6852d614}.bb-root .lp-search-clear{background:var(--border-medium);width:1.42857rem;height:1.42857rem;color:var(--text-secondary);border-radius:50%;justify-content:center;align-items:center;margin-top:-.28571rem;transition:background .15s;display:flex;position:absolute;top:50%;right:1.42857rem;transform:translateY(-50%)}.bb-root .lp-search-clear:hover{background:var(--text-muted);color:var(--text-primary)}.bb-root .lp-content{flex:1;padding:.28571rem .57143rem .85714rem;overflow-y:auto}.bb-root .lp-group{margin-bottom:.14286rem}.bb-root .lp-group-header{width:100%;color:var(--text-secondary);cursor:pointer;border-radius:.57143rem;align-items:center;gap:.57143rem;padding:.71429rem;font-size:.92857rem;font-weight:600;transition:all .15s;display:flex}.bb-root .lp-group-header:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .lp-group-header.open{color:var(--text-primary);background:var(--bg-tertiary);font-weight:600}.bb-root .lp-group-header.open .lp-group-icon{color:var(--text-primary)}.bb-root .lp-group-icon{color:var(--text-secondary);transition:color .15s}.bb-root .lp-group-label{text-align:left;flex:1}.bb-root .lp-group-count{color:var(--text-secondary);font-variant-numeric:tabular-nums;font-size:.78571rem;font-weight:500}.bb-root .lp-group-header.open .lp-group-count{color:var(--text-secondary)}.bb-root .lp-group-chevron{color:var(--text-muted);transition:transform .2s,color .15s}.bb-root .lp-group-chevron.collapsed{transform:rotate(-90deg)}.bb-root .lp-group-header.open .lp-group-chevron{color:var(--text-secondary)}.bb-root .lp-group-items{flex-direction:column;gap:.14286rem;margin-left:1.28571rem;padding:.57143rem 0 .28571rem;display:flex;position:relative}.bb-root .lp-group-items:before{content:"";background:var(--border-subtle);width:1px;position:absolute;top:0;bottom:2rem;left:0}.bb-root .lp-item{text-align:left;border:1px solid #0000;border-radius:.57143rem;align-items:center;gap:.71429rem;width:calc(100% - .85714rem);margin-left:.85714rem;padding:.57143rem .71429rem;transition:all .15s;display:flex;position:relative}.bb-root .lp-item:before{content:"";background:var(--border-subtle);width:.85714rem;height:1px;position:absolute;top:50%;left:-.85714rem}.bb-root .lp-item:hover{background:var(--bg-hover);border-color:var(--border-subtle)}.bb-root .lp-item-icon-wrap{background:var(--bg-tertiary);width:2rem;height:2rem;color:var(--text-secondary);border-radius:.42857rem;flex-shrink:0;justify-content:center;align-items:center;display:flex}.bb-root .lp-item-title{color:var(--text-primary);white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;overflow:hidden}.bb-root .lp-item--component{align-items:flex-start}.bb-root .lp-item-info{flex-direction:column;flex:1;gap:.14286rem;min-width:0;display:flex}.bb-root .lp-item-sub{color:var(--text-secondary);white-space:nowrap;text-overflow:ellipsis;font-size:12px;line-height:1.3;overflow:hidden}.bb-root .lp-empty{text-align:center;flex-direction:column;justify-content:center;align-items:center;padding:2.85714rem 1.42857rem;display:flex}.bb-root .lp-empty-icon{color:var(--border-medium);margin-bottom:.57143rem}.bb-root .lp-empty-title{color:var(--text-secondary);font-size:.92857rem;font-weight:500}.bb-root .lp-empty-sub{color:var(--text-muted);margin-top:.28571rem;font-size:.85714rem}.bb-root .lp-footer{border-top:1px dashed var(--border-subtle);padding:.71429rem}.bb-root .lp-footer-drop{border:1px dashed var(--border-subtle);color:var(--text-secondary);cursor:pointer;border-radius:.57143rem;justify-content:center;align-items:center;gap:.42857rem;padding:.71429rem;font-size:.89286rem;font-weight:500;transition:all .15s;display:flex}.bb-root .lp-footer-drop:hover{border-color:var(--border-medium);color:var(--text-primary);background:var(--bg-tertiary)}.bb-root .canvas{background:var(--bg-secondary);flex-direction:column;flex:1;display:flex;position:relative;overflow:hidden}.bb-root .canvas-area{background:radial-gradient(circle at 1px 1px,#d4d4d8 1px,#0000 0) 0 0/1rem 1rem;flex:1;justify-content:center;align-items:center;padding:2.28571rem 1.71429rem;display:flex;overflow:auto}.bb-root .phone-frame{background:#fff;border-radius:24px;flex-direction:column;flex-shrink:0;width:340px;height:700px;max-height:700px;display:flex;position:relative;overflow:hidden;box-shadow:0 0 0 1px #0000000f,0 2px 4px #0000000a,0 12px 32px #00000014,0 32px 64px #0000000f}.bb-root .phone-frame:before{content:none}.bb-root .phone-screen{background:#fafafa;flex-direction:column;height:100%;margin-top:0;display:flex;overflow:hidden}.bb-root .chat-header{background:#fff;border-bottom:1px solid #0000000f;align-items:center;padding:20px 16px 14px;display:flex}.bb-root .chat-back-btn{color:var(--text-secondary);opacity:.6;padding:2px 4px;font-size:20px}.bb-root .chat-user{flex:1;align-items:center;gap:10px;margin-left:10px;display:flex}.bb-root .chat-avatar{color:#fff;background:linear-gradient(135deg,#6852d6,#8b7ae8);border-radius:50%;justify-content:center;align-items:center;width:36px;height:36px;font-size:14px;font-weight:600;display:flex;box-shadow:0 2px 8px #6852d64d}.bb-root .chat-name{color:var(--text-primary);letter-spacing:-.01em;font-size:14px;font-weight:600}.bb-root .chat-messages{background:#fafafa;flex-direction:column;flex:1;gap:12px;min-height:0;padding:16px;display:flex;overflow:hidden auto}.bb-root .message-date{text-align:center;color:var(--text-tertiary);-webkit-backdrop-filter:blur(.57143rem);backdrop-filter:blur(.57143rem);letter-spacing:.02em;background:#fffc;border-radius:.85714rem;align-self:center;padding:.35714rem .85714rem;font-size:.78571rem;font-weight:500}.bb-root .bubble-preview{flex-shrink:0;align-self:flex-start;width:100%;min-height:50px;position:relative;overflow:visible}.bb-root .canvas-bubble{border-radius:16px 16px 16px 4px;flex-direction:column;gap:2px;display:flex;overflow:visible;box-shadow:0 1px 2px #0000000f,0 1px 3px #0000000a}.bb-root .canvas-empty{color:var(--text-tertiary);text-align:center;border:.14286rem dashed var(--border-medium);background-color:#fff;border-radius:1.14286rem;flex-direction:column;justify-content:center;align-items:center;gap:.85714rem;margin:auto .85714rem;padding:2.28571rem 1.42857rem;font-size:.92857rem;display:flex}.bb-root .canvas-empty-template-btn{background:var(--bg-tertiary);border:1px solid var(--border-subtle);color:#404040;cursor:pointer;border-radius:.57143rem;margin-top:.85714rem;padding:.57143rem 1.14286rem;font-size:.92857rem;font-weight:600;transition:all .15s}.bb-root .canvas-empty-template-btn:hover{border-color:var(--accent-primary);background:var(--accent-light);color:var(--accent-primary)}.bb-root .canvas-empty-circle{background:#f5f5f5;border-radius:50%;justify-content:center;align-items:center;width:3.42857rem;height:3.42857rem;display:flex}.bb-root .canvas-empty-plus{color:#a3a3a3;font-size:1.71429rem;font-weight:300}.bb-root .canvas-empty-title{color:var(--text-primary);font-size:1rem;font-weight:600}.bb-root .canvas-empty-sub{color:#404040;font-size:.92857rem}.bb-root .chat-input-area{background:#fff;border-top:1px solid #0000000f;align-items:center;gap:10px;padding:10px 14px;display:flex}.bb-root .chat-input{border:1px solid var(--border-subtle);color:var(--text-primary);background:#f5f6f7;border-radius:20px;flex:1;padding:9px 16px;font-size:13px}.bb-root .chat-send-btn{background:var(--accent-primary);color:#fff;border-radius:50%;justify-content:center;align-items:center;width:34px;height:34px;font-size:13px;transition:transform .15s,box-shadow .15s;display:flex;box-shadow:0 2px 8px #6852d64d}.bb-root .chat-send-btn:hover{transform:scale(1.05);box-shadow:0 4px 12px #6852d666}.bb-root .el-wrapper{cursor:pointer;border-radius:4px;width:100%;transition:all .12s;position:relative;overflow:visible}.bb-root .el-wrapper:hover{background:#6852d60a}.bb-root .el-wrapper.selected{outline:2px solid var(--accent-primary);outline-offset:-2px;background:#6852d60a}.bb-root .el-wrapper.multi-selected{outline:2px dashed var(--accent-primary);outline-offset:-2px;background:#6852d60a}.bb-root .el-controls-portal{z-index:9999;background:#fff;border-radius:.57143rem;flex-direction:row;gap:.14286rem;padding:.21429rem;display:flex;box-shadow:0 .14286rem .85714rem #0000001f,0 0 0 1px #0000000a}.bb-root .preview-mode .el-controls-portal{display:none}.bb-root .el-ctrl-btn{width:1.85714rem;height:1.85714rem;color:var(--text-secondary);border-radius:.35714rem;justify-content:center;align-items:center;font-size:.92857rem;transition:all .12s;display:flex}.bb-root .el-ctrl-btn:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .el-ctrl-btn.danger:hover{color:#dc2626;background:#fee2e2}.bb-root .el-wrap-menu{border:1px solid var(--border-subtle);z-index:1001;background:#fff;border-radius:.71429rem;min-width:10rem;margin-bottom:.28571rem;padding:.28571rem;position:absolute;bottom:100%;right:0;box-shadow:0 .57143rem 1.71429rem #0000001f}.bb-root .el-wrap-option{text-align:left;color:var(--text-secondary);white-space:nowrap;border-radius:.42857rem;width:100%;padding:.5rem .85714rem;font-size:.85714rem}.bb-root .el-wrap-option:hover{background:var(--accent-light);color:var(--accent-primary)}.bb-root .canvas-breadcrumbs{border-bottom:1px solid var(--border-subtle);background:#fff;flex-wrap:wrap;align-items:center;gap:.14286rem;padding:.42857rem 1.14286rem;font-size:.85714rem;display:flex}.bb-root .canvas-bc-sep{color:var(--text-muted);margin:0 .14286rem;font-size:.71429rem}.bb-root .canvas-bc-item{color:var(--text-secondary);font-size:.78571rem;font-family:var(--font-mono);border-radius:.28571rem;padding:.14286rem .57143rem}.bb-root .canvas-bc-item:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .canvas-bc-item.active{color:var(--accent-primary);background:var(--accent-light)}.bb-root .multi-select-bar{border:1px solid var(--border-subtle);z-index:100;background:#fff;border-radius:.85714rem;align-items:center;gap:.57143rem;padding:.57143rem 1.14286rem;font-size:.92857rem;display:flex;position:absolute;bottom:4.28571rem;left:50%;transform:translate(-50%);box-shadow:0 .57143rem 1.71429rem #0000001f}.bb-root .multi-select-bar span{color:var(--text-secondary);white-space:nowrap}.bb-root .multi-select-bar button{background:var(--accent-light);color:var(--accent-primary);white-space:nowrap;border-radius:.42857rem;padding:.42857rem .85714rem;font-size:.85714rem;font-weight:600;transition:all .15s}.bb-root .multi-select-bar button:hover{background:var(--accent-primary);color:#fff}.bb-root .canvas-bubble ::-webkit-scrollbar{height:3px}.bb-root .canvas-bubble ::-webkit-scrollbar-track{background:0 0}.bb-root .canvas-bubble ::-webkit-scrollbar-thumb{background:#00000026;border-radius:2px}.bb-root .canvas-toolbar{border-top:1px solid var(--border-subtle);background:#fff;flex-shrink:0;justify-content:center;align-items:center;gap:.28571rem;padding:.42857rem .85714rem;font-size:.85714rem;display:flex}.bb-root .canvas-tool-btn{width:2rem;height:2rem;color:var(--text-secondary);border-radius:.42857rem;justify-content:center;align-items:center;font-size:1rem;transition:all .12s;display:flex}.bb-root .canvas-tool-btn:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .canvas-tool-btn.active{background:var(--accent-light);color:var(--accent-primary)}.bb-root .canvas-tool-label{color:var(--text-secondary);text-align:center;min-width:2.57143rem;font-size:.78571rem}.bb-root .canvas-tool-sep{background:var(--border-medium);width:1px;height:1.14286rem;margin:0 .28571rem}.bb-root .preview-mode .el-wrapper{cursor:default}.bb-root .preview-mode .el-wrapper:hover{background:0 0}.bb-root .preview-mode .el-wrapper.selected,.bb-root .preview-mode .el-wrapper.multi-selected{background:0 0;outline:none}.bb-root .preview-mode .canvas-breadcrumbs,.bb-root .preview-mode .multi-select-bar{display:none}.bb-root .json-preview-panel{background:var(--bg-primary);border-left:1px solid var(--border-subtle);z-index:60;flex-direction:column;width:27.1429rem;display:flex;position:absolute;top:0;bottom:0;right:0;box-shadow:-.28571rem 0 1.71429rem #0000000f}.bb-root .json-preview-header{border-bottom:1px solid var(--border-subtle);color:var(--text-primary);background:var(--bg-secondary);align-items:center;gap:.57143rem;padding:.85714rem 1.14286rem;font-size:.92857rem;font-weight:600;display:flex}.bb-root .json-preview-header span{flex:1}.bb-root .json-preview-header button{width:2rem;height:2rem;color:var(--text-secondary);background:0 0;border:none;border-radius:.28571rem;justify-content:center;align-items:center;font-size:1rem;display:flex}.bb-root .json-preview-header button:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .json-preview-code{font-family:var(--font-mono);color:var(--text-primary);white-space:pre;tab-size:2;background:var(--bg-primary);flex:1;margin:0;padding:1.14286rem;font-size:.85714rem;line-height:1.6;overflow:auto}.bb-root .el-context-menu{background:var(--bg-primary);border:1px solid var(--border-subtle);border-radius:.71429rem;min-width:11.4286rem;padding:.28571rem;font-size:.85714rem;box-shadow:0 .57143rem 1.71429rem #0000001f}.bb-root .el-ctx-item{text-align:left;width:100%;color:var(--text-secondary);white-space:nowrap;border-radius:.42857rem;padding:.42857rem .85714rem;display:block}.bb-root .el-ctx-item:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .el-ctx-item.danger:hover{color:#dc2626;background:#fee2e2}.bb-root .el-ctx-sep{background:var(--border-subtle);height:1px;margin:.28571rem 0}.bb-root .canvas-side-toolbar{z-index:50;flex-direction:column;align-items:center;gap:1.71429rem;display:flex;position:absolute;top:50%;right:.85714rem;transform:translateY(-50%)}.bb-root .canvas-side-group{border:1px solid var(--border-subtle);background:#fff;border-radius:.85714rem;flex-direction:column;padding:.28571rem;display:flex;box-shadow:0 1px .21429rem #0000000f}.bb-root .canvas-side-btn{width:2.57143rem;height:2.57143rem;color:var(--text-secondary);border-radius:.57143rem;justify-content:center;align-items:center;transition:all .15s;display:flex}.bb-root .canvas-side-btn:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .canvas-side-btn.active{background:var(--accent-light);color:var(--accent-primary)}.bb-root .canvas.read-only .canvas-area{pointer-events:none}.bb-root .canvas.read-only .canvas-area *{pointer-events:none;-webkit-user-select:none;user-select:none;cursor:default!important}.bb-root .canvas.read-only .chat-messages{pointer-events:auto;overflow-y:auto}.bb-root .canvas.read-only .canvas-side-toolbar{display:none}.bb-root .prop-field--row{align-items:flex-start;gap:.85714rem;display:flex}.bb-root .prop-field--row>.prop-label{flex-shrink:0;width:7.14286rem;margin-bottom:0;padding-top:.57143rem}.bb-root .prop-field--row>.prop-field-input{flex:1;min-width:0}.bb-root .prop-color-row{align-items:center;gap:.71429rem;display:flex}.bb-root .prop-color-pair{align-items:center;gap:.42857rem;display:flex}.bb-root .prop-color-circle{cursor:pointer;border:1px solid var(--border-subtle);border-radius:.57143rem;flex-shrink:0;width:2.28571rem;height:2.28571rem;transition:border-color .15s;position:relative}.bb-root .prop-color-circle:hover{border-color:var(--border-medium)}.bb-root .prop-color-circle input[type=color]{cursor:pointer;opacity:0;border:none;border-radius:.57143rem;width:100%;height:100%;padding:0;position:absolute;top:0;left:0}.bb-root .prop-color-tag{-webkit-user-select:none;user-select:none;border-radius:.28571rem;padding:.21429rem .42857rem;font-size:.71429rem;font-weight:600;line-height:1}.bb-root .prop-color-tag--light{background:var(--bg-tertiary);color:var(--text-secondary);border:1px solid var(--border-subtle)}.bb-root .prop-color-tag--dark{color:#adb5bd;background:#1a1a1a;border:1px solid #495057}.bb-root .prop-color-clear{width:1.71429rem;height:1.71429rem;color:var(--text-tertiary);background:var(--bg-tertiary);border:1px solid var(--border-subtle);cursor:pointer;border-radius:.42857rem;justify-content:center;align-items:center;font-size:.85714rem;transition:all .15s;display:flex}.bb-root .prop-color-clear:hover{color:#dc2626;background:#fef2f2;border-color:#fecaca}.bb-root .prop-padding-row{align-items:center;gap:.42857rem;display:flex}.bb-root .prop-padding-row input{flex:1}.bb-root .prop-padding-toggle{border:1px solid var(--border-subtle);width:40px;height:40px;color:var(--text-muted);background:var(--bg-primary);cursor:pointer;border-radius:.57143rem;flex-shrink:0;justify-content:center;align-items:center;transition:all .15s;display:flex}.bb-root .prop-padding-toggle:hover{background:var(--bg-tertiary);color:var(--text-primary);border-color:var(--border-medium)}.bb-root .prop-padding-toggle.active{background:var(--accent-light);color:var(--accent-primary);border-color:#6852d64d}.bb-root .prop-padding-grid{grid-template-columns:1fr 1fr;gap:.57143rem;margin-top:.57143rem;display:grid}.bb-root .prop-padding-grid label{color:var(--text-secondary);text-transform:uppercase;letter-spacing:.5px;margin-bottom:.28571rem;font-size:.75rem;font-weight:500;display:block}.bb-root .prop-select-wrap{position:relative}.bb-root .prop-select-wrap select{appearance:none;padding-right:2.28571rem}.bb-root .prop-select-arrow{pointer-events:none;color:var(--text-muted);position:absolute;top:50%;right:.71429rem;transform:translateY(-50%)}.bb-root .prop-input-number{-moz-appearance:textfield}.bb-root .prop-input-number::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.bb-root .prop-input-number::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.bb-root .prop-color-section{flex-direction:column;gap:.57143rem;display:flex}.bb-root .prop-color-swatch-row{align-items:center;gap:.71429rem;display:flex}.bb-root .prop-color-swatch{cursor:pointer;border:1px solid var(--border-subtle);border-radius:.57143rem;flex-shrink:0;width:40px;height:40px;transition:border-color .15s;position:relative}.bb-root .prop-color-swatch input[type=color]{cursor:pointer;opacity:0;border:none;border-radius:.57143rem;width:100%;height:100%;padding:0;position:absolute;top:0;left:0}.bb-root .prop-input-hex{flex:1;font-size:13px}.bb-root .prop-padding-wrap{flex-direction:column;gap:.57143rem;width:100%;display:flex}.bb-root .prop-padding-wrap .prop-padding-grid{margin-left:0}.bb-root .prop-align-group{border:1px solid var(--border-subtle);border-radius:.57143rem;display:flex;overflow:hidden}.bb-root .prop-align-btn{background:var(--bg-primary);height:40px;color:var(--text-secondary);border-right:1px solid var(--border-subtle);flex:1;justify-content:center;align-items:center;transition:all .15s;display:flex}.bb-root .prop-align-btn:last-child{border-right:none}.bb-root .prop-align-btn:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .prop-align-btn.active{background:var(--accent-light);color:var(--accent-primary)}.bb-root .prop-switch{cursor:pointer;align-items:center;gap:.85714rem;padding:.42857rem 0;display:flex}.bb-root .prop-switch-track{background:var(--border-medium);border-radius:.71429rem;flex-shrink:0;width:2.57143rem;height:1.42857rem;transition:background .2s;position:relative}.bb-root .prop-switch-track.on{background:var(--accent-primary)}.bb-root .prop-switch-thumb{background:#fff;border-radius:50%;width:1.14286rem;height:1.14286rem;transition:transform .2s;position:absolute;top:.14286rem;left:.14286rem;box-shadow:0 1px .21429rem #00000026}.bb-root .prop-switch-track.on .prop-switch-thumb{transform:translate(1.14286rem)}.bb-root .prop-switch-label{width:7.14286rem;color:var(--text-tertiary);flex-shrink:0;font-size:13px;font-weight:400}.bb-root .prop-image-preview{object-fit:cover;border:1px solid var(--border-subtle);border-radius:.57143rem;width:100%;max-height:8.57143rem;margin:.28571rem 0 .57143rem}.bb-root .prop-section-header{align-items:center;gap:.57143rem;margin-top:.57143rem;padding:.57143rem 0;display:flex}.bb-root .prop-section-header .material-symbols-outlined{color:var(--text-muted)}.bb-root .prop-color-header{justify-content:space-between;align-items:center;margin-bottom:1.14286rem;display:flex}.bb-root .prop-color-field{align-items:flex-start;gap:.85714rem;margin-bottom:.85714rem;display:flex}.bb-root .prop-color-field-label{width:7.14286rem;color:var(--text-tertiary);flex-shrink:0;padding-top:.57143rem;font-size:13px;font-weight:400}.bb-root .prop-color-field-input{flex:1;align-items:center;gap:.71429rem;min-width:0;display:flex}.bb-root .prop-image-upload-placeholder{border:.14286rem dashed var(--border-medium);background:var(--bg-tertiary);cursor:pointer;border-radius:.57143rem;flex-direction:column;justify-content:center;align-items:center;width:100%;height:8.57143rem;margin-bottom:.85714rem;transition:all .15s;display:flex}.bb-root .prop-image-upload-placeholder:hover{border-color:var(--accent-primary);background:var(--accent-light)}.bb-root .prop-image-upload-icon{color:var(--text-muted);margin-bottom:.57143rem}.bb-root .prop-image-upload-placeholder:hover .prop-image-upload-icon{color:var(--accent-primary)}.bb-root .prop-image-upload-text{color:var(--text-secondary);font-size:.92857rem;font-weight:500}.bb-root .prop-image-upload-hint{color:var(--text-muted);margin-top:.14286rem;font-size:.78571rem}.bb-root .prop-image-preview-container{border:1px solid var(--border-subtle);cursor:pointer;border-radius:.57143rem;width:100%;height:12.8571rem;margin-bottom:.85714rem;position:relative;overflow:hidden}.bb-root .prop-image-preview-container:hover .prop-image-preview-overlay{opacity:1}.bb-root .prop-image-preview-img{object-fit:contain;background:var(--bg-tertiary);width:100%;height:100%}.bb-root .prop-image-preview-overlay{color:#fff;opacity:0;background:#0000004d;justify-content:center;align-items:center;gap:.42857rem;font-size:.85714rem;font-weight:500;transition:opacity .15s;display:flex;position:absolute;inset:0}.bb-root .prop-image-modal-backdrop{z-index:9999;-webkit-backdrop-filter:blur(.28571rem);backdrop-filter:blur(.28571rem);background:#000000b3;justify-content:center;align-items:center;padding:2.28571rem;display:flex;position:fixed;inset:0}.bb-root .prop-image-modal{background:#fff;border-radius:.85714rem;max-width:90vw;max-height:90vh;position:relative;overflow:hidden;box-shadow:0 1.42857rem 4.28571rem #0000004d}.bb-root .prop-image-modal-img{object-fit:contain;max-width:90vw;max-height:80vh;display:block}.bb-root .prop-image-modal-close{color:#fff;background:#00000080;border-radius:.57143rem;justify-content:center;align-items:center;width:2.57143rem;height:2.57143rem;transition:background .15s;display:flex;position:absolute;top:.85714rem;right:.85714rem}.bb-root .prop-image-modal-close:hover{background:#000000b3}.bb-root .prop-image-modal-footer{color:#fff;background:linear-gradient(#0000,#0009);justify-content:space-between;align-items:center;padding:.85714rem 1.14286rem;font-size:.85714rem;display:flex;position:absolute;bottom:0;left:0;right:0}.bb-root .prop-image-modal-close-btn{color:#fff;background:#fff3;border-radius:.57143rem;align-items:center;gap:.42857rem;padding:.42857rem .85714rem;font-size:.85714rem;font-weight:500;transition:background .15s;display:flex}.bb-root .prop-image-modal-close-btn:hover{background:#ffffff4d}.bb-root .notif-help-box{background:var(--bg-tertiary);color:var(--text-secondary);border-radius:.57143rem;align-items:flex-start;gap:.57143rem;padding:.85714rem;font-size:.89286rem;line-height:1.5;display:flex}.bb-root .notif-help-icon{color:var(--text-muted);flex-shrink:0;margin-top:1px}.bb-root .var-header{justify-content:space-between;align-items:center;display:flex}.bb-root .var-add-btn{background:var(--accent-primary);color:#fff;border-radius:.57143rem;align-items:center;gap:.28571rem;padding:.57143rem 1rem;font-size:.92857rem;font-weight:600;transition:background .15s;display:flex}.bb-root .var-add-btn:hover{background:var(--accent-secondary)}.bb-root .var-empty{text-align:center;flex-direction:column;align-items:center;padding:2.28571rem 1.14286rem;display:flex}.bb-root .var-empty-icon{background:var(--bg-tertiary);width:3.42857rem;height:3.42857rem;color:var(--text-muted);border-radius:1.71429rem;justify-content:center;align-items:center;margin-bottom:.85714rem;display:flex}.bb-root .var-empty-title{color:var(--text-secondary);font-size:.92857rem;font-weight:500}.bb-root .var-empty-sub{color:var(--text-muted);margin-top:.28571rem;font-size:.85714rem}.bb-root .var-count{text-transform:uppercase;letter-spacing:.5px;color:var(--text-secondary);margin-bottom:.85714rem;font-size:.78571rem;font-weight:600}.bb-root .var-list{flex-direction:column;gap:.71429rem;display:flex}.bb-root .var-item{border:1px solid var(--border-subtle);background:#fff;border-radius:.85714rem;transition:border-color .15s,box-shadow .15s;position:relative;overflow:hidden}.bb-root .var-item:hover{border-color:#6852d633;box-shadow:0 1px .21429rem #0000000a}.bb-root .var-item-top{align-items:center;gap:.71429rem;padding:.85714rem 1rem .57143rem;display:flex}.bb-root .var-item-icon{background:var(--accent-light);width:1.71429rem;height:1.71429rem;color:var(--accent-primary);border-radius:.42857rem;flex-shrink:0;justify-content:center;align-items:center;display:flex}.bb-root .var-item-name{color:var(--text-primary);background:#00000008;border-radius:.28571rem;flex:1;padding:.14286rem .57143rem;font-size:.92857rem;font-weight:600}.bb-root .var-item-delete{width:2rem;height:2rem;color:var(--text-muted);opacity:1;border-radius:.57143rem;flex-shrink:0;justify-content:center;align-items:center;transition:all .15s;display:flex}.bb-root .var-item:hover .var-item-delete{color:var(--text-muted)}.bb-root .var-item-delete:hover{background:#fef2f2;color:#dc2626!important}.bb-root .var-item-details{flex-direction:column;gap:.28571rem;padding:0 1rem .85714rem;display:flex}.bb-root .var-item-detail{color:var(--text-secondary);align-items:center;gap:.42857rem;font-size:.85714rem;display:flex}.bb-root .var-item-detail .material-symbols-outlined{color:var(--text-muted)}.bb-root .var-item-category{text-transform:uppercase;letter-spacing:.5px;color:var(--accent-primary);background:var(--accent-light);border-radius:.71429rem;align-self:flex-start;margin-top:.28571rem;padding:.14286rem .57143rem;font-size:.71429rem;font-weight:600}.bb-root .var-delete-overlay{z-index:10;-webkit-backdrop-filter:blur(.14286rem);backdrop-filter:blur(.14286rem);color:var(--text-primary);background:#fffffff2;border:1px solid #fecaca;border-radius:.85714rem;flex-direction:column;justify-content:center;align-items:center;gap:.57143rem;font-size:.85714rem;font-weight:500;display:flex;position:absolute;inset:0}.bb-root .var-delete-icon{color:#dc2626}.bb-root .var-delete-actions{gap:.57143rem;margin-top:.28571rem;display:flex}.bb-root .var-delete-confirm{color:#fff;background:#dc2626;border-radius:.57143rem;padding:.42857rem 1rem;font-size:.85714rem;font-weight:600}.bb-root .var-delete-confirm:hover{background:#b91c1c}.bb-root .var-delete-cancel{border:1px solid var(--border-subtle);color:var(--text-secondary);border-radius:.57143rem;padding:.42857rem 1rem;font-size:.85714rem;font-weight:500}.bb-root .var-delete-cancel:hover{background:var(--bg-tertiary)}.bb-root .var-form{background:#6852d605;border:1px solid #6852d633;border-radius:.85714rem;margin-bottom:.85714rem;padding:1.14286rem}.bb-root .var-form-title{color:var(--text-primary);margin-bottom:.85714rem;font-size:.92857rem;font-weight:600}.bb-root .var-form-actions{gap:.57143rem;margin-top:.85714rem;display:flex}.bb-root .var-form-btn-primary{background:var(--accent-primary);color:#fff;border-radius:.57143rem;padding:.57143rem 1.14286rem;font-size:.85714rem;font-weight:600;transition:background .15s}.bb-root .var-form-btn-primary:hover{background:var(--accent-secondary)}.bb-root .var-form-btn-secondary{border:1px solid var(--border-subtle);color:var(--text-secondary);border-radius:.57143rem;padding:.57143rem 1.14286rem;font-size:.85714rem;font-weight:500;transition:background .15s}.bb-root .var-form-btn-secondary:hover{background:var(--bg-tertiary)}.bb-root .tree-root{font-size:13px}.bb-root .tree-item{text-align:left;width:100%;color:var(--text-secondary);cursor:pointer;border-radius:.57143rem;align-items:center;gap:.42857rem;min-height:2.28571rem;padding:.42857rem .57143rem;transition:all .15s;display:flex;position:relative}.bb-root .tree-item:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .tree-item.selected{background:var(--bg-tertiary);color:var(--text-primary);transition:none}.bb-root .tree-item:active{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .tree-item.multi-selected{background:var(--accent-light);color:var(--accent-primary);outline:1px dashed var(--accent-primary);outline-offset:-1px}.bb-root .tree-item.drop-target{outline:.14286rem dashed var(--accent-primary);outline-offset:-.14286rem}.bb-root .tree-item.flash{background:var(--bg-tertiary)}@keyframes tree-flash{0%{background:var(--bg-tertiary)}to{background:0 0}}.bb-root .tree-chevron{width:1.14286rem;height:1.14286rem;color:var(--text-muted);cursor:pointer;border-radius:.28571rem;flex-shrink:0;justify-content:center;align-items:center;transition:color .15s;display:flex}.bb-root .tree-chevron:hover,.bb-root .tree-item.selected .tree-chevron{color:var(--text-primary)}.bb-root .tree-spacer{flex-shrink:0;width:1.14286rem}.bb-root .tree-icon-box{border:1px solid var(--border-subtle);background:var(--bg-primary);width:1.71429rem;height:1.71429rem;color:var(--text-secondary);border-radius:.28571rem;flex-shrink:0;justify-content:center;align-items:center;transition:all .15s;display:flex}.bb-root .tree-item:hover .tree-icon-box{border-color:var(--border-medium)}.bb-root .tree-item.selected .tree-icon-box,.bb-root .tree-item.flash .tree-icon-box{border-color:var(--border-medium);background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .tree-type{font-family:Satoshi,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:12px;font-weight:500}.bb-root .tree-type.is-container{font-weight:600}.bb-root .tree-item.selected .tree-type{color:var(--text-primary)}.bb-root .tree-label{color:var(--text-tertiary);text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:.78571rem;overflow:hidden}.bb-root .tree-badge{background:var(--bg-tertiary);color:var(--text-tertiary);border-radius:.57143rem;flex-shrink:0;margin-left:auto;padding:1px .35714rem;font-size:.64286rem}.bb-root .tree-item.selected .tree-badge{background:var(--border-subtle);color:var(--text-secondary)}.bb-root .tree-error-dot{background:#dc2626;border-radius:50%;flex-shrink:0;width:.42857rem;height:.42857rem;margin-left:auto}.bb-root .tree-badge+.tree-error-dot,.bb-root .tree-error-dot+.tree-badge{margin-left:.28571rem}.bb-root .tree-children{position:relative}.bb-root .tree-children:before{content:"";background:var(--border-subtle);width:1px;position:absolute;top:0;bottom:.85714rem;left:1.35714rem}.bb-root .tree-empty{color:var(--text-tertiary);flex-direction:column;align-items:center;gap:.57143rem;padding:1.71429rem;font-size:.92857rem;display:flex}.bb-root .tree-drag-overlay{background:var(--bg-primary);opacity:.9;border-radius:.57143rem;box-shadow:0 .28571rem .85714rem #00000026}.bb-root .tree-node{touch-action:none}.bb-root .tree-drop-gap{height:.28571rem;transition:height .1s;position:relative}.bb-root .tree-drop-gap.active{height:.57143rem}.bb-root .tree-drop-gap .tree-drop-line{background:0 0;border-radius:1px;height:.14286rem;transition:background .1s}.bb-root .tree-drop-gap.active .tree-drop-line{background:var(--accent-primary)}.bb-root .tree-search-wrap{margin-bottom:.57143rem;position:relative}.bb-root .tree-search-icon{color:var(--text-muted);pointer-events:none;position:absolute;top:50%;left:.71429rem;transform:translateY(-50%)}.bb-root .tree-search{border:1px solid var(--border-subtle);width:100%;color:var(--text-primary);background:#fafafa;border-radius:.57143rem;padding:.57143rem 2rem .57143rem 2.28571rem;font-size:.85714rem}.bb-root .tree-search:focus{border-color:var(--accent-primary);background:var(--bg-primary);outline:none}.bb-root .tree-search::placeholder{color:var(--text-muted)}.bb-root .tree-search-clear{width:1.42857rem;height:1.42857rem;color:var(--text-tertiary);background:var(--border-medium);border-radius:50%;justify-content:center;align-items:center;transition:all .15s;display:flex;position:absolute;top:50%;right:.57143rem;transform:translateY(-50%)}.bb-root .tree-search-clear:hover{color:var(--text-primary);background:var(--text-muted)}.bb-root .right-panel{background:var(--bg-primary);border-left:1px solid var(--border-subtle);flex-direction:column;flex-shrink:0;width:22.8571rem;min-width:18.5714rem;max-width:28.5714rem;font-size:14px;display:flex;overflow:hidden}.bb-root .rp-tabs{border-bottom:1px solid var(--border-subtle);flex-shrink:0;padding:0 .57143rem;display:flex;overflow:hidden}.bb-root .rp-tab{color:var(--text-secondary);white-space:nowrap;background:0 0;flex:1;justify-content:center;align-items:center;padding:.85714rem .57143rem;font-size:.89286rem;font-weight:500;transition:color .15s;display:flex;position:relative}.bb-root .rp-tab:hover{color:var(--text-primary)}.bb-root .rp-tab.active{color:var(--accent-primary);font-weight:500}.bb-root .rp-tab-indicator{background:var(--accent-primary);border-radius:1px;height:.14286rem;position:absolute;bottom:0;left:.57143rem;right:.57143rem}.bb-root .rp-content{flex:1;padding:1.42857rem 1.14286rem;overflow-y:auto}.bb-root .rp-empty{color:var(--text-tertiary);text-align:center;flex-direction:column;justify-content:center;align-items:center;gap:.85714rem;padding:3.42857rem 1.71429rem;display:flex}.bb-root .rp-empty-icon{color:var(--border-medium);font-size:3.42857rem}.bb-root .prop-group{margin-bottom:0;padding-bottom:0}.bb-root .prop-group:last-child{border-bottom:none}.bb-root .prop-group-title{color:var(--text-primary);margin-bottom:1.14286rem;font-size:14px;font-weight:600}.bb-root .prop-field{margin-bottom:.85714rem}.bb-root .prop-label{color:var(--text-tertiary);margin-bottom:.42857rem;font-size:13px;font-weight:400;display:block}.bb-root .prop-row{align-items:center;gap:.57143rem;display:flex}.bb-root .prop-row .prop-label{flex-shrink:0;width:7.14286rem;margin-bottom:0}.bb-root .prop-badge{background:var(--accent-light);color:var(--accent-primary);text-transform:uppercase;letter-spacing:.5px;border-radius:.28571rem;margin-bottom:1.14286rem;padding:.28571rem .71429rem;font-size:.78571rem;font-weight:600;display:inline-block}.bb-root .prop-error-summary{color:#dc2626;background:#fef2f2;border:1px solid #fecaca;border-radius:.28571rem;margin-bottom:.85714rem;padding:.42857rem .71429rem;font-size:.85714rem;font-weight:500}.bb-root .prop-field-error input,.bb-root .prop-field-error textarea,.bb-root .prop-field-error select{box-shadow:0 0 0 1px #fecaca;border-color:#dc2626!important}.bb-root .prop-field-error-hint{color:#dc2626;margin-left:.42857rem;font-size:.78571rem;font-weight:400}.bb-root .prop-color-swatch{border:1px solid var(--border-subtle);cursor:pointer;border-radius:.57143rem;flex-shrink:0;width:40px;height:40px;transition:border-color .15s}.bb-root .prop-color-swatch:hover{border-color:var(--border-medium)}.bb-root .prop-toggle-group{border:1px solid var(--border-subtle);border-radius:.57143rem;display:flex;overflow:hidden}.bb-root .prop-toggle-btn{background:var(--bg-primary);height:2.85714rem;color:var(--text-secondary);border-right:1px solid var(--border-subtle);flex:1;justify-content:center;align-items:center;transition:all .15s;display:flex}.bb-root .prop-toggle-btn:last-child{border-right:none}.bb-root .prop-toggle-btn:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .prop-toggle-btn.active{background:var(--accent-light);color:var(--accent-primary)}.bb-root .prop-mode-toggle{border:1px solid var(--border-subtle);border-radius:.57143rem;display:flex;overflow:hidden}.bb-root .prop-mode-btn{background:var(--bg-primary);width:2.57143rem;height:2.57143rem;color:var(--text-muted);border-right:1px solid var(--border-subtle);justify-content:center;align-items:center;transition:all .15s;display:flex}.bb-root .prop-mode-btn:last-child{border-right:none}.bb-root .prop-mode-btn:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .prop-mode-btn.active{background:var(--accent-light);color:var(--accent-primary)}.bb-root .prop-section-divider{background:var(--border-subtle);height:1px;margin:1.14286rem 0}.bb-root .empty-state{text-align:center;flex-direction:column;justify-content:center;align-items:center;padding:2.28571rem 1.14286rem;display:flex}.bb-root .empty-state-icon{background:var(--bg-tertiary);width:3.42857rem;height:3.42857rem;color:var(--text-muted);border-radius:50%;justify-content:center;align-items:center;margin-bottom:.85714rem;display:flex}.bb-root .empty-state-title{color:#525252;font-size:13px;font-weight:500}.bb-root .empty-state-sub{color:#a3a3a3;max-width:14.2857rem;margin-top:.28571rem;font-size:12px;line-height:1.5}.bb-root .shortcuts-overlay{z-index:10000;-webkit-backdrop-filter:blur(.28571rem);backdrop-filter:blur(.28571rem);background:#0006;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.bb-root .shortcuts-panel{background:#fff;border-radius:1.14286rem;width:22.8571rem;padding:0;overflow:hidden;box-shadow:0 1.14286rem 3.42857rem #0003}.bb-root .shortcuts-header{border-bottom:1px solid var(--border-subtle);color:var(--text-primary);justify-content:space-between;align-items:center;padding:1.14286rem 1.42857rem;font-size:1rem;font-weight:600;display:flex}.bb-root .shortcuts-close{width:1.71429rem;height:1.71429rem;color:var(--text-tertiary);border-radius:.42857rem;justify-content:center;align-items:center;font-size:1.14286rem;display:flex}.bb-root .shortcuts-close:hover{background:var(--bg-tertiary);color:var(--text-primary)}.bb-root .shortcuts-list{padding:.85714rem 1.42857rem 1.14286rem}.bb-root .shortcut-row{border-bottom:1px solid var(--border-subtle);justify-content:space-between;align-items:center;padding:.57143rem 0;display:flex}.bb-root .shortcut-row:last-child{border-bottom:none}.bb-root .shortcut-action{color:var(--text-secondary);font-size:.92857rem}.bb-root .shortcut-keys{font-family:var(--font-mono);background:var(--bg-tertiary);color:var(--text-primary);border:1px solid var(--border-subtle);border-radius:.28571rem;padding:.21429rem .57143rem;font-size:.78571rem;font-weight:500}.bb-root .editor-root{background:var(--bg-secondary);flex-direction:column;width:100%;height:100%;font-family:Satoshi,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;display:flex}.bb-root .editor-panels{flex:1;display:flex;overflow:hidden}:root{--bg-primary:#fff;--bg-secondary:#f5f5f5;--bg-tertiary:#f5f5f5;--bg-elevated:#fff;--bg-hover:#fafafa;--bg-active:#f3f0ff;--accent-primary:#6852d6;--accent-secondary:#7c6be6;--accent-light:#f3f0ff;--accent-gradient:linear-gradient(135deg, #6852d6 0%, #7c6be6 100%);--accent-glow:#6852d633;--text-primary:#141414;--text-secondary:#727272;--text-tertiary:#414651;--text-muted:#bfbfbc;--border-subtle:#e9eaeb;--border-medium:#d5d7da;--border-accent:#6852d64d;--success:#10b981;--warning:#f59e0b;--error:#d92d20;--shadow-sm:0 1px .14286rem #0000000d;--shadow-md:0 .28571rem .42857rem #00000012;--shadow-lg:0 .71429rem 1.78571rem #0000001a;--radius-sm:.57143rem;--radius-md:.57143rem;--radius-lg:.85714rem;--radius-xl:1.14286rem;--font-sans:"Satoshi", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--font-mono:"SF Mono", "Fira Code", monospace}.bb-root .material-symbols-outlined{font-variation-settings:"FILL" 0, "wght" 400, "GRAD" 0, "opsz" 20;-webkit-user-select:none;user-select:none}.bb-root,.bb-root *{box-sizing:border-box;margin:0;padding:0}.bb-root,.bb-root,.bb-root #root{width:100%;height:100%}.bb-root,.bb-root *,.bb-root :before,.bb-root :after{font-family:Satoshi,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.bb-root{font-family:var(--font-sans);background:var(--bg-secondary);color:var(--text-primary);-webkit-font-smoothing:antialiased;font-size:clamp(14px,.95vw,28px);line-height:1.5}.bb-root ::-webkit-scrollbar{width:.42857rem;height:.42857rem}.bb-root ::-webkit-scrollbar-track{background:0 0}.bb-root ::-webkit-scrollbar-thumb{background:var(--border-medium);border-radius:.21429rem}.bb-root ::-webkit-scrollbar-thumb:hover{background:var(--text-tertiary)}.bb-root button{cursor:pointer;color:inherit;font:inherit;background:0 0;border:none}.bb-root input,.bb-root textarea,.bb-root select{box-sizing:border-box;border:1px solid var(--border-medium);width:100%;height:40px;color:var(--text-primary);background:#fff;border-radius:.57143rem;outline:none;padding:.71429rem .85714rem;font-family:inherit;font-size:13px;font-weight:500;line-height:1.5;transition:border-color .15s}.bb-root textarea{height:auto}.bb-root input:focus,.bb-root textarea:focus,.bb-root select:focus{border-color:var(--accent-primary)}.bb-root input::placeholder,.bb-root textarea::placeholder{color:var(--text-muted);font-weight:400}.bb-root select{appearance:none;cursor:pointer;padding-right:2rem}.bb-root input[type=checkbox]{width:1.14286rem;height:1.14286rem;accent-color:var(--accent-primary)}.bb-root input[type=color]{border:1px solid var(--border-medium);border-radius:var(--radius-sm);background:var(--bg-secondary);cursor:pointer;width:2.85714rem;height:2.57143rem;padding:.14286rem}.bb-root input[type=color]::-webkit-color-swatch-wrapper{padding:.14286rem}.bb-root input[type=color]::-webkit-color-swatch{border:none;border-radius:.28571rem}.bb-root textarea{resize:vertical;min-height:4.28571rem}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" rel="stylesheet" />
<link href="https://api.fontshare.com/v2/css?f[]=satoshi@300,400,500,600,700&display=swap" rel="stylesheet" />
<title>bubble-builder</title>
<style>.bb-root, .bb-root, .bb-root #root { height: 100%; width: 100%; margin: 0; padding: 0; overflow: hidden; }</style>
<script type="module" crossorigin src="/assets/index-bg5Sfjsd.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-D9-G0mBH.css">
</head>
<body>
<div id="root"></div>
</body>
</html>