Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
23 kB ยท 621 lines
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622// KidLisp.com Logging Module// Beautiful multicolored headers + smart categorized logging// Inspired by aesthetic.computer's headers.mjs
const LOG_LEVELS = { NONE: 0, ERROR: 1, WARN: 2, INFO: 3, DEBUG: 4, VERBOSE: 5};
// Categories that can be individually toggledconst CATEGORIES = { boot: false, // Boot sequence splash: false, // Splash screen animation platform: true, // Platform switching (useful to see) code: true, // Code loading/saving (important) editor: false, // Monaco editor events auth: false, // Auth0/login playback: false, // Play/pause/stop controls iframe: false, // Iframe communication message: false, // PostMessage logs (very noisy) wallet: false, // Tezos wallet socket: false, // WebSocket session ui: false, // UI interactions qr: false, // QR code generation tabs: false, // Tab switching};
// Default log levellet currentLevel = LOG_LEVELS.INFO;
// Check localStorage for debug settingstry { const savedLevel = localStorage.getItem('kidlisp-log-level'); if (savedLevel && LOG_LEVELS[savedLevel.toUpperCase()] !== undefined) { currentLevel = LOG_LEVELS[savedLevel.toUpperCase()]; } const savedCategories = localStorage.getItem('kidlisp-log-categories'); if (savedCategories) { const parsed = JSON.parse(savedCategories); Object.assign(CATEGORIES, parsed); }} catch (e) { // Ignore localStorage errors}
// Day-based color schemes (matching AC client style)function getDayColorScheme() { const day = new Date().getDay(); const schemes = { 0: { // Sunday - Purple/Lavender title: ['#E8B4FF', '#D18EFF', '#B366FF', '#9544FF', '#7722FF', '#5500FF', '#7722FF', '#9544FF', '#B366FF', '#D18EFF', '#E8B4FF'], accent: '#9370db', tagline: '#b19cd9', primary: '#9370db', secondary: '#b19cd9' }, 1: { // Monday - Blue/Ocean title: ['#7DD3FC', '#60C5F8', '#43B7F4', '#26A9F0', '#099BEC', '#0284C7', '#099BEC', '#26A9F0', '#43B7F4', '#60C5F8', '#7DD3FC'], accent: '#4682b4', tagline: '#7dd3fc', primary: '#4682b4', secondary: '#7dd3fc' }, 2: { // Tuesday - Green/Forest title: ['#86EFAC', '#6AE79A', '#4EDF88', '#32D776', '#16CF64', '#059669', '#16CF64', '#32D776', '#4EDF88', '#6AE79A', '#86EFAC'], accent: '#228b22', tagline: '#6ee7b7', primary: '#228b22', secondary: '#6ee7b7' }, 3: { // Wednesday - Orange/Sunset title: ['#FED7AA', '#FDC78A', '#FCB76A', '#FBA74A', '#FA972A', '#F97316', '#FA972A', '#FBA74A', '#FCB76A', '#FDC78A', '#FED7AA'], accent: '#ff8c00', tagline: '#fed7aa', primary: '#ff8c00', secondary: '#fed7aa' }, 4: { // Thursday - Red/Ruby title: ['#FCA5A5', '#FB8585', '#FA6565', '#F94545', '#F82525', '#DC2626', '#F82525', '#F94545', '#FA6565', '#FB8585', '#FCA5A5'], accent: '#dc143c', tagline: '#fca5a5', primary: '#dc143c', secondary: '#fca5a5' }, 5: { // Friday - Pink/Rose title: ['#FBCFE8', '#F9B3DB', '#F797CE', '#F57BC1', '#F35FB4', '#EC4899', '#F35FB4', '#F57BC1', '#F797CE', '#F9B3DB', '#FBCFE8'], accent: '#ec4899', tagline: '#fbcfe8', primary: '#ec4899', secondary: '#fbcfe8' }, 6: { // Saturday - Teal/Cyan (AC signature) title: ['#5EEAD4', '#4ECDC4', '#3EBFB4', '#2EB1A4', '#1EA394', '#14B8A6', '#1EA394', '#2EB1A4', '#3EBFB4', '#4ECDC4', '#5EEAD4'], accent: '#14b8a6', tagline: '#5eead4', primary: '#4ecdc4', secondary: '#16a085' } }; return schemes[day];}
const dayColors = getDayColorScheme();
// Badge styles for different categoriesconst badges = { boot: ['๐', dayColors.accent], splash: ['๐จ', '#a855f7'], platform: ['๐ฎ', '#f43f5e'], code: ['๐พ', '#10b981'], editor: ['๐', '#f59e0b'], auth: ['๐', '#8b5cf6'], playback: ['โถ๏ธ', '#22c55e'], iframe: ['๐ผ๏ธ', '#3b82f6'], message: ['๐จ', '#6366f1'], wallet: ['๐ฐ', '#14b8a6'], socket: ['๐งฆ', '#06b6d4'], ui: ['๐๏ธ', '#64748b'], qr: ['๐ฑ', '#0ea5e9'], tabs: ['๐', '#84cc16'],};
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ// KidLisp Syntax Highlighting for Console// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// KidLisp drawing and control keywordsconst KIDLISP_KEYWORDS = { drawing: ['line', 'rect', 'circle', 'box', 'tri', 'plot', 'write', 'ink', 'paper', 'brush', 'flood', 'wipe', 'paste', 'stamp', 'scroll', 'zoom', 'contrast', 'blur', 'spin', 'jump', 'draw', 'wiggle', 'pan', 'grid', 'noise', 'shape'], control: ['if', 'when', 'unless', 'each', 'loop', 'later', 'once', 'def', 'repeat', 'tap', 'now', 'frame'], special: ['rainbow', 'zebra', 'fade', 'width', 'height', 'kidlisp'],};
// Named colors for highlightingconst CSS_COLORS = { red: '#ef4444', blue: '#3b82f6', green: '#22c55e', yellow: '#eab308', orange: '#f97316', purple: '#a855f7', pink: '#ec4899', cyan: '#06b6d4', white: '#f8fafc', black: '#0f172a', gray: '#6b7280', grey: '#6b7280', magenta: '#d946ef', lime: '#84cc16', teal: '#14b8a6', navy: '#1e3a8a', maroon: '#7f1d1d', olive: '#84cc16', aqua: '#06b6d4', silver: '#cbd5e1', gold: '#fbbf24', coral: '#fb7185', salmon: '#fca5a5', violet: '#8b5cf6', indigo: '#6366f1', crimson: '#dc2626', turquoise: '#2dd4bf', chocolate: '#92400e', tan: '#d4a574',};
// Simple tokenizer for KidLispfunction tokenizeKidLisp(code) { const tokens = []; let current = ''; let inString = false; let inComment = false; for (let i = 0; i < code.length; i++) { const char = code[i]; const next = code[i + 1]; // Handle comments if (!inString && char === ';' && next === ';') { if (current) { tokens.push(current); current = ''; } let comment = ''; while (i < code.length && code[i] !== '\n') { comment += code[i++]; } tokens.push(comment); i--; // Back up for newline continue; } // Handle strings if (char === '"') { if (inString) { current += char; tokens.push(current); current = ''; inString = false; } else { if (current) { tokens.push(current); current = ''; } current = char; inString = true; } continue; } if (inString) { current += char; continue; } // Handle parens and whitespace if (char === '(' || char === ')') { if (current) { tokens.push(current); current = ''; } tokens.push(char); continue; } if (/\s/.test(char)) { if (current) { tokens.push(current); current = ''; } tokens.push(char); continue; } current += char; } if (current) tokens.push(current); return tokens;}
// Format KidLisp code for styled console outputfunction formatKidLispForConsole(code, indent = ' ') { if (!code || typeof code !== 'string') return { text: '', styles: [] }; const tokens = tokenizeKidLisp(code); const baseStyle = 'font-family: monospace; font-size: 10px;'; let text = indent; const styles = []; for (const token of tokens) { // Whitespace - preserve as-is if (/^\s+$/.test(token)) { text += token.replace(/\n/g, '\n' + indent); continue; } // Comments if (token.startsWith(';;')) { text += `%c${token}`; styles.push(`${baseStyle} color: #6b7280; font-style: italic;`); continue; } // Strings if (token.startsWith('"') && token.endsWith('"')) { text += `%c${token}`; styles.push(`${baseStyle} color: #f472b6;`); // Pink for strings continue; } // Numbers (including time like 0.5s) if (/^-?\d+(?:\.\d+)?s?$/.test(token)) { text += `%c${token}`; styles.push(`${baseStyle} color: #4ade80; font-weight: bold;`); // Green for numbers continue; } // Parens if (token === '(' || token === ')') { text += `%c${token}`; styles.push(`${baseStyle} color: #9ca3af;`); continue; } // $codes (shortcodes) if (token.startsWith('$')) { text += `%c$%c${token.slice(1)}`; styles.push(`${baseStyle} color: #fb923c; font-weight: bold;`); // Orange $ styles.push(`${baseStyle} color: #fbbf24; font-weight: bold;`); // Yellow identifier continue; } // #codes (hashtags) if (token.startsWith('#')) { text += `%c#%c${token.slice(1)}`; styles.push(`${baseStyle} color: #818cf8; font-weight: bold;`); // Purple # styles.push(`${baseStyle} color: #a5b4fc; font-weight: bold;`); // Light purple identifier continue; } const lower = token.toLowerCase(); // Drawing commands if (KIDLISP_KEYWORDS.drawing.includes(lower)) { text += `%c${token}`; styles.push(`${baseStyle} color: #22d3ee; font-weight: bold;`); // Cyan for drawing continue; } // Control flow if (KIDLISP_KEYWORDS.control.includes(lower)) { text += `%c${token}`; styles.push(`${baseStyle} color: #c084fc; font-weight: bold;`); // Purple for control continue; } // Special keywords if (KIDLISP_KEYWORDS.special.includes(lower)) { text += `%c${token}`; styles.push(`${baseStyle} color: #f472b6; font-weight: bold;`); // Pink for special continue; } // Named colors if (CSS_COLORS[lower]) { text += `%c${token}`; styles.push(`${baseStyle} color: ${CSS_COLORS[lower]}; font-weight: bold;`); continue; } // Default - gray text text += `%c${token}`; styles.push(`${baseStyle} color: #9ca3af;`); } return { text, styles };}
// Create styled log functionsfunction createLogger(category) { const [emoji, color] = badges[category] || ['๐', '#888']; return { log: (...args) => { if (currentLevel < LOG_LEVELS.INFO || !CATEGORIES[category]) return; console.log( `%c${emoji} ${category}`, `background: ${color}; color: white; padding: 2px 6px; border-radius: 3px; font-size: 10px; font-weight: bold;`, ...args ); }, debug: (...args) => { if (currentLevel < LOG_LEVELS.DEBUG || !CATEGORIES[category]) return; console.log( `%c${emoji} ${category}`, `background: ${color}22; color: ${color}; padding: 2px 6px; border-radius: 3px; font-size: 10px; border: 1px solid ${color};`, ...args ); }, verbose: (...args) => { if (currentLevel < LOG_LEVELS.VERBOSE || !CATEGORIES[category]) return; console.log( `%c ${emoji}`, `color: ${color}; font-size: 9px; opacity: 0.6;`, ...args ); }, warn: (...args) => { if (currentLevel < LOG_LEVELS.WARN) return; console.warn( `%cโ ๏ธ ${category}`, `background: #f59e0b; color: white; padding: 2px 6px; border-radius: 3px; font-size: 10px; font-weight: bold;`, ...args ); }, error: (...args) => { if (currentLevel < LOG_LEVELS.ERROR) return; console.error( `%cโ ${category}`, `background: #ef4444; color: white; padding: 2px 6px; border-radius: 3px; font-size: 10px; font-weight: bold;`, ...args ); }, success: (...args) => { if (currentLevel < LOG_LEVELS.INFO || !CATEGORIES[category]) return; console.log( `%cโ
${category}`, `background: #22c55e; color: white; padding: 2px 6px; border-radius: 3px; font-size: 10px; font-weight: bold;`, ...args ); }, group: (label) => { if (currentLevel < LOG_LEVELS.DEBUG || !CATEGORIES[category]) return; console.groupCollapsed( `%c${emoji} ${category}%c ${label}`, `background: ${color}; color: white; padding: 2px 6px; border-radius: 3px; font-size: 10px;`, `color: ${color}; font-weight: normal; font-size: 11px;` ); }, groupEnd: () => { if (currentLevel < LOG_LEVELS.DEBUG || !CATEGORIES[category]) return; console.groupEnd(); } };}
// Create loggers for each categoryexport const log = { boot: createLogger('boot'), splash: createLogger('splash'), platform: createLogger('platform'), code: createLogger('code'), editor: createLogger('editor'), auth: createLogger('auth'), playback: createLogger('playback'), iframe: createLogger('iframe'), message: createLogger('message'), wallet: createLogger('wallet'), socket: createLogger('socket'), ui: createLogger('ui'), qr: createLogger('qr'), tabs: createLogger('tabs'),};
// Beautiful multicolored header (call once on page load)export function showHeader() { const colors = getDayColorScheme(); const title = 'KidLisp.com'; // Build the multicolored title - each character gets its own color let formatStr = ''; let styles = []; title.split('').forEach((char, i) => { formatStr += `%c${char}`; const color = colors.title[i % colors.title.length]; styles.push(`color: ${color}; font-weight: bold; font-size: 22px; font-family: 'Comic Sans MS', cursive, sans-serif; text-shadow: 1px 1px 2px rgba(0,0,0,0.3);`); }); console.log(formatStr, ...styles);}
// Log a platform switch with nice formattingexport function logPlatformSwitch(fromPlatform, toPlatform, platformInfo = {}) { if (currentLevel < LOG_LEVELS.INFO || !CATEGORIES.platform) return; const colors = getDayColorScheme(); const icons = { 'ac': '๐จ', 'ff1': '๐น', 'ableton': '๐๏ธ', 'playdate': '๐ฎ', 'gameboy': '๐พ', 'n64': '๐น๏ธ' }; const fromIcon = icons[fromPlatform] || 'โ'; const toIcon = icons[toPlatform] || 'โ'; console.log( `%c๐ฎ platform%c ${fromIcon} ${fromPlatform || 'none'} โ ${toIcon} ${toPlatform}`, `background: #f43f5e; color: white; padding: 2px 6px; border-radius: 3px; font-size: 10px; font-weight: bold;`, `color: ${colors.accent}; font-size: 11px; font-weight: bold; padding-left: 4px;` ); if (platformInfo?.comingSoon) { console.log('%c โณ Coming soon...', 'color: #f59e0b; font-size: 10px;'); } if (platformInfo?.experimental) { console.log('%c ๐งช Experimental', 'color: #8b5cf6; font-size: 10px;'); }}
// Log code operations with syntax-highlighted previewexport function logCodeOperation(operation, code, shortCode) { if (currentLevel < LOG_LEVELS.INFO || !CATEGORIES.code) return; const colors = getDayColorScheme(); const ops = { 'load': ['๐ฅ', '#3b82f6', 'Loaded'], 'save': ['๐พ', '#22c55e', 'Saved'], 'run': ['โถ๏ธ', '#22c55e', 'Running'], 'create': ['โจ', '#a855f7', 'Created'], 'fetch': ['๐', '#0ea5e9', 'Fetched'], }; const [icon, color, label] = ops[operation] || ['๐', '#666', operation]; console.log( `%c${icon} code%c ${label}${shortCode ? ` $${shortCode}` : ''}`, `background: ${color}; color: white; padding: 2px 6px; border-radius: 3px; font-size: 10px; font-weight: bold;`, `color: ${colors.accent}; font-size: 11px; padding-left: 4px;` ); // Show syntax-highlighted preview (first line or first 60 chars) if (code) { const firstLine = code.split('\n')[0] || ''; const preview = firstLine.length > 60 ? firstLine.slice(0, 60) : firstLine; const hasMore = code.includes('\n') || firstLine.length > 60; const highlighted = formatKidLispForConsole(preview + (hasMore ? 'โฆ' : '')); if (highlighted.text) { console.log(highlighted.text, ...highlighted.styles); } }}
// Log editor initializationexport function logEditorInit(editorType, options = {}) { if (currentLevel < LOG_LEVELS.INFO || !CATEGORIES.editor) return; const colors = getDayColorScheme(); console.log( `%c๐ editor%c ${editorType} initialized`, `background: #f59e0b; color: white; padding: 2px 6px; border-radius: 3px; font-size: 10px; font-weight: bold;`, `color: ${colors.accent}; font-size: 11px; padding-left: 4px;` ); if (options.theme) { console.log(`%c ๐จ Theme: ${options.theme}`, 'color: #666; font-size: 10px;'); } if (options.language) { console.log(`%c ๐ Language: ${options.language}`, 'color: #666; font-size: 10px;'); }}
// Log auth eventsexport function logAuth(event, user) { if (currentLevel < LOG_LEVELS.INFO || !CATEGORIES.auth) return; const events = { 'login': ['๐', '#22c55e', 'Logged in'], 'logout': ['๐', '#f59e0b', 'Logged out'], 'restore': ['๐', '#3b82f6', 'Session restored'], 'error': ['โ', '#ef4444', 'Auth error'], 'check': ['๐', '#6366f1', 'Checking auth'], }; const [icon, color, label] = events[event] || ['๐', '#8b5cf6', event]; console.log( `%c${icon} auth%c ${label}${user ? ` @${user}` : ''}`, `background: ${color}; color: white; padding: 2px 6px; border-radius: 3px; font-size: 10px; font-weight: bold;`, `color: #8b5cf6; font-size: 11px; font-weight: bold; padding-left: 4px;` );}
// Log boot sequence stepsexport function logBoot(step, details = '') { if (currentLevel < LOG_LEVELS.INFO || !CATEGORIES.boot) return; const colors = getDayColorScheme(); const steps = { 'start': ['๐', 'Starting'], 'config': ['โ๏ธ', 'Config loaded'], 'i18n': ['๐', 'Translations loaded'], 'auth': ['๐', 'Auth initialized'], 'editor': ['๐', 'Editor ready'], 'iframe': ['๐ผ๏ธ', 'Iframe loaded'], 'complete': ['โ
', 'Boot complete'], }; const [icon, label] = steps[step] || ['๐', step]; console.log( `%c${icon} boot%c ${label}${details ? ` โข ${details}` : ''}`, `background: ${colors.accent}; color: white; padding: 2px 6px; border-radius: 3px; font-size: 10px; font-weight: bold;`, `color: ${colors.primary}; font-size: 11px; padding-left: 4px;` );}
// Global debug controls (attach to window for console access)export const debug = { // Set log level level: (level) => { if (typeof level === 'string') { level = LOG_LEVELS[level.toUpperCase()]; } if (level !== undefined) { currentLevel = level; const levelName = Object.keys(LOG_LEVELS).find(k => LOG_LEVELS[k] === level); localStorage.setItem('kidlisp-log-level', levelName); console.log(`%c๐ Log level: ${levelName}`, `color: ${dayColors.accent}; font-weight: bold;`); } return currentLevel; }, // Quick presets quiet: () => { debug.level(LOG_LEVELS.WARN); console.log('%c๐คซ Quiet mode - warnings & errors only', 'color: #666;'); }, normal: () => { debug.level(LOG_LEVELS.INFO); console.log('%c๐ข Normal mode', 'color: #666;'); }, verbose: () => { debug.level(LOG_LEVELS.VERBOSE); console.log('%c๐ฃ Verbose mode - everything!', 'color: #666;'); }, // Toggle category toggle: (category) => { if (category && CATEGORIES[category] !== undefined) { CATEGORIES[category] = !CATEGORIES[category]; localStorage.setItem('kidlisp-log-categories', JSON.stringify(CATEGORIES)); const status = CATEGORIES[category] ? 'โ
enabled' : 'โ disabled'; const [emoji] = badges[category] || ['๐']; console.log(`%c${emoji} ${category}: ${status}`, `color: ${dayColors.accent};`); } else { console.log('%c๐ Available categories:', 'color: #888; font-weight: bold;'); Object.entries(CATEGORIES).forEach(([k, v]) => { const [emoji] = badges[k] || ['๐']; console.log(` ${emoji} ${k}: ${v ? 'โ
' : 'โ'}`); }); } }, // Enable all categories all: () => { Object.keys(CATEGORIES).forEach(k => CATEGORIES[k] = true); localStorage.setItem('kidlisp-log-categories', JSON.stringify(CATEGORIES)); debug.level(LOG_LEVELS.VERBOSE); console.log('%c๐ All logging enabled!', `color: ${dayColors.accent}; font-weight: bold;`); }, // Minimal logging (only important stuff) minimal: () => { Object.keys(CATEGORIES).forEach(k => CATEGORIES[k] = false); CATEGORIES.boot = true; CATEGORIES.code = true; CATEGORIES.auth = true; localStorage.setItem('kidlisp-log-categories', JSON.stringify(CATEGORIES)); debug.level(LOG_LEVELS.INFO); console.log('%c๐คซ Minimal logging - just the essentials', `color: ${dayColors.accent}; font-weight: bold;`); }, // Show help help: () => { const colors = getDayColorScheme(); console.log('%c๐ ๏ธ KidLisp Debug Commands', `color: ${colors.accent}; font-weight: bold; font-size: 13px;`); console.log('%cโโโโโโโโโโโโโโโโโโโโโโโโโโ', `color: ${colors.accent}44;`); console.log('%ckidlispDebug.quiet()%c - Warnings & errors only', 'color: #f59e0b; font-family: monospace;', 'color: #666;'); console.log('%ckidlispDebug.normal()%c - Standard logging', 'color: #22c55e; font-family: monospace;', 'color: #666;'); console.log('%ckidlispDebug.verbose()%c - Everything!', 'color: #3b82f6; font-family: monospace;', 'color: #666;'); console.log('%ckidlispDebug.minimal()%c - Just the essentials', 'color: #8b5cf6; font-family: monospace;', 'color: #666;'); console.log('%ckidlispDebug.all()%c - Enable all categories', 'color: #ec4899; font-family: monospace;', 'color: #666;'); console.log('%ckidlispDebug.toggle(cat)%c- Toggle a category', 'color: #14b8a6; font-family: monospace;', 'color: #666;'); console.log('%ckidlispDebug.toggle()%c - Show all categories', 'color: #0ea5e9; font-family: monospace;', 'color: #666;'); console.log('%ckidlispDebug.status()%c - Show current settings', 'color: #f43f5e; font-family: monospace;', 'color: #666;'); }, // Show current settings status: () => { const colors = getDayColorScheme(); const levelName = Object.keys(LOG_LEVELS).find(k => LOG_LEVELS[k] === currentLevel); console.log('%c๐ KidLisp Logger Status', `color: ${colors.accent}; font-weight: bold;`); console.log(`%c Level: ${levelName}`, 'color: #666;'); console.log('%c Categories:', 'color: #666;'); Object.entries(CATEGORIES).forEach(([k, v]) => { const [emoji] = badges[k] || ['๐']; console.log(` ${emoji} ${k}: ${v ? 'โ
' : 'โ'}`); }); }};
// Attach to window for console accessif (typeof window !== 'undefined') { window.kidlispDebug = debug; window.kidlispLog = log;}