1/* ============================================================ 2 * CREA ECOSYSTEM â centre de visibilité des briques vivantes. 3 * REND : dessiner 4 * 5 * Lecture seule : montre les modules frontend réellement chargés, les systèmes 6 * backend, leurs verrous et les règles de déploiement. Aucun secret ni bouton 7 * d'activation sensible n'est exposé. 8 * 9 * Chargé après CREA_API. Expose window.CREA_ECOSYSTEM. 10 * ============================================================ */ 11;(function () { 12 'use strict' 13 if (window.CREA_ECOSYSTEM) return 14 15 var MODULES = [ 16 ['CREA_IDB', 'Mémoire locale IndexedDB'], 17 ['CREA_IDENTITY', 'Identité canonique'], 18 ['CREA_SOCLE', 'Socle universel'], 19 ['CREA_NERVE', 'Système nerveux'], 20 ['CREA_ADAPT', 'Adaptation multi-support'], 21 ['CREA_ECOSYSTEM', 'Centre Ãcosystème'], 22 ['CREA_API', 'Client API partagé'], 23 ['CREA_LIVING', 'Coordinateur visuel'], 24 ['CREA_TRANSFORM', 'Transformations'], 25 ['CREA_PROPOSE', 'Propositions contextuelles'], 26 ['CREA_SMARTBAR', 'Barre intelligente'], 27 ['CREA_SOCIETY', 'Société IA, DLM et agents'], 28 ['CREA_CONTEXT', 'Contexte écosystème'],
29 ['CREA_DOC', 'Documents vivants'], 30 ['CREA_OMNIS', 'Relations et Command Center'], 31 ['CREA_PREVIEW_GUARD', 'Protection des aperçus'], 32 ['CREA_JOURNAL', 'Journal vivant'], 33 ['CREA_VIEWS', 'Vues projet et agent'], 34 ['CREA_MENTION', 'Mentions de ressources'], 35 ['CREA_GUIDE', 'Guide vivant'], 36 ['CREA_TERMINAL', 'Terminal Créa'], 37 ['CREA_BAR', 'Réglages Affiner'], 38 ['CREA_RESILIENCE', 'Résilience réseau'], 39 ['CREA_VOICE', 'Voix et dictée'], 40 ['CREA_CONNECT', 'Connecteurs'], 41 ['CREA_ACCESS', 'Niveaux d\'accès'], 42 ['CREA_CONSENT', 'Consentements'], 43 ['CREA_CONSTITUTION', 'Constitution'], 44 ['CREA_KNOWLEDGE', 'Bibliothèques'], 45 ['CREA_GUARDIAN', 'Garde-fous'], 46 ['CREA_MEDIA', 'Studio média'], 47 ['CREA_FINITION', 'Agent finition'], 48 ['CREA_EMERGENCE', 'Ãmergence'], 49 ['CREA_ROUTER', 'Routeur cognitif'], 50 ['CREA_TIME', 'Studio temps'], 51 ['CREA_RAG', 'RAG source'], 52 ['CREA_WORLD', 'Monde réel'], 53 ['CREA_SOURCES', 'Sources par domaine'], 54 ['CREA_PREMIUM', 'Finition visuelle'], 55 ['CREA_SELF', 'Connaissance de soi'], 56 ] 57 58 var latest = null 59 60 function esc(value) { 61 return String(value == null ? '' : value).replace(/[&<>"']/g, function (char) { 62 return ({ '&':'&', '<':'<', '>':'>', '"':'"', "'":''' })[char] 63 }) 64 } 65 66 function localSnapshot() { 67 var modules = MODULES.map(function (item) { 68 return { id:item[0], name:item[1], active:Boolean(window[item[0]]) } 69 }) 70 var adapt = null 71 try { adapt = window.CREA_ADAPT && window.CREA_ADAPT.current && window.CREA_ADAPT.current() } catch (e) {} 72 return { 73 modules:modules, 74 active:modules.filter(function (item) { return item.active }).length, 75 expected:modules.length, 76 profile:adapt && adapt.profile || String(window.__CREA_APP_PROFILE || 'inconnu'), 77 platform:adapt && adapt.platform || 'inconnu', 78 viewport:adapt ? adapt.width + 'x' + adapt.height : window.innerWidth + 'x' + window.innerHeight, 79 } 80 } 81 82 function activeSurface() { 83 var profile = String(window.__CREA_APP_PROFILE || '').toLowerCase() 84 if (profile.indexOf('console') >= 0) return 'console' 85 if (profile.indexOf('public') >= 0 || profile.indexOf('client') >= 0) return 'public' 86 try { 87 var adapt = window.CREA_ADAPT && window.CREA_ADAPT.current && window.CREA_ADAPT.current() 88 var surface = String(adapt && (adapt.surface || adapt.profile) || '').toLowerCase() 89 if (surface.indexOf('console') >= 0) return 'console' 90 if (surface.indexOf('public') >= 0 || surface.indexOf('client') >= 0) return 'public' 91 } catch (e) {} 92 return location.pathname.indexOf('console') >= 0 || location.pathname.indexOf('admin') >= 0 ? 'console' : 'public' 93 } 94 95 function closeNearby() { 96 [ 97 'crea-guide', 'crea-terminal', 'crea-cc', 'crea-self', 'crea-society', 98 'crea-connect', 'crea-access', 'crea-consent', 'crea-knowledge', 99 'crea-constitution', 'crea-guardian', 'crea-media', 'crea-finition', 100 'crea-emergence', 'crea-router', 'crea-time', 'crea-rag', 'crea-sources' 101 ].forEach(function (id) { 102 var node = document.getElementById(id) 103 if (node) node.remove() 104 }) 105 } 106 107 function statusLabel(status) { 108 return ({ 109 active:'Actif', 110 wired:'Branché', 111 gated:'Protégé', 112 preserved:'Conservé', 113 superseded:'Remplacé', 114 })[status] || String(status || 'Inconnu') 115 } 116 117 function statusClass(status) { 118 if (status === 'active') return 'on' 119 if (status === 'wired') return 'wired' 120 if (status === 'gated') return 'gate' 121 return 'quiet' 122 } 123 124 async function load() { 125 var backend = null 126 var files = null 127 try { 128 backend = window.CREA_API && window.CREA_API.ecosystemStatus 129 ? await window.CREA_API.ecosystemStatus() 130 : await fetch('/api/ecosystem/status', { cache:'no-store', credentials:'same-origin' }).then(function (response) { 131 if (!response.ok) throw new Error('http-' + response.status) 132 return response.json() 133 }) 134 } catch (error) { 135 backend = { ok:false, error:String(error && error.message || error), systems:[], totals:{} } 136 } 137 try { 138 var surface = activeSurface() 139 files = window.CREA_API && window.CREA_API.ecosystemFiles 140 ? await window.CREA_API.ecosystemFiles({ surface:surface, maxFiles:12000, maxDepth:10 }) 141 : await fetch('/api/ecosystem/files?surface=' + encodeURIComponent(surface) + '&maxFiles=12000&maxDepth=10', { cache:'no-store', credentials:'same-origin' }).then(function (response) { 142 if (!response.ok) throw new Error('http-' + response.status) 143 return response.json() 144 }) 145 } catch (error) { 146 files = { ok:false, error:String(error && error.message || error), files:[], directories:[], totals:{ files:0, directories:0, omitted:0 } } 147 } 148 latest = { local:localSnapshot(), backend:backend, files:files, at:Date.now() } 149 return latest 150 } 151 152 function rulesHtml(data) { 153 var rules = data.backend && data.backend.rules || {} 154 if (!data.backend || data.backend.ok !== true) { 155 return '<div class="ce-rules"><span class="unknown">Ãtat serveur non vérifié</span><span>Règles locales inchangées</span><span>Actions sensibles : validation humaine</span></div>' 156 } 157 var open = rules.openAccess === true 158 var unlimited = rules.usageQuotasEnabled === false 159 return '<div class="ce-rules">' + 160 '<span class="' + (open ? 'ok' : 'warn') + '">Accès ' + (open ? 'ouvert' : 'restreint') + '</span>' + 161 '<span class="' + (unlimited ? 'ok' : 'warn') + '">Quotas ' + (unlimited ? 'illimités' : 'actifs') + '</span>' + 162 '<span>Actions sensibles : validation humaine</span>' + 163 '</div>' 164 } 165 166 function backendRows(data) { 167 var systems = data.backend && data.backend.systems || [] 168 if (!systems.length) return '<div class="ce-empty">
168Backend indisponible. Les modules locaux restent utilisables.</div>' 169 return systems.map(function (system) { 170 var missing = (system.files || []).filter(function (file) { return !file.present }).map(function (file) { return file.path }) 171 var detail = missing.length 172 ? 'Manquant: ' + missing.join(', ') 173 : (system.gate ? 'Verrou: ' + system.gate : system.domain) 174 return '<div class="ce-row">' + 175 '<span class="ce-dot ' + statusClass(system.status) + '"></span>' + 176 '<div class="ce-main"><b>' + esc(system.name) + '</b><small>' + esc(detail) + '</small></div>' + 177 '<span class="ce-badge ' + statusClass(system.status) + '">' + esc(statusLabel(system.status)) + '</span>' + 178 '</div>' 179 }).join('') 180 } 181 182 function localRows(data) { 183 return data.local.modules.map(function (module) { 184 return '<div class="ce-module"><span class="ce-dot ' + (module.active ? 'on' : 'gate') + '"></span><span>' + 185 esc(module.name) + '</span><small>' + (module.active ? 'actif' : 'non chargé') + '</small></div>' 186 }).join('') 187 } 188 189 function statPills(map) { 190 return Object.keys(map || {}).sort().map(function (key) { 191 return '<span><b>' + esc(map[key]) + '</b> ' + esc(key) + '</span>' 192 }).join('') 193 } 194 195 function directoryRows(files) { 196 var dirs = files && files.directories || [] 197 if (!dirs.length) return '<div class="ce-empty">Aucun dossier visible pour cette surface.</div>' 198 return dirs.map(function (dir) { 199 return '<div class="ce-dir"><span>' + esc(dir.path) + '</span><b>' + esc(dir.count) + '</b></div>' 200 }).join('') 201 } 202 203 function fileRows(files) { 204 var list = files && files.files || [] 205 if (!list.length) return '<div class="ce-empty">Aucun fichier visible pour cette surface.</div>' 206 return list.map(function (file) { 207 return '<div class="ce-file">' + 208 '<span class="ce-badge quiet">' + esc(file.surface) + '</span>' + 209 '<div><b>' + esc(file.path) + '</b><small>' + esc(file.area + ' - ' + file.kind + ' - ' + Math.ceil((file.size || 0) / 1024) + ' Ko') + '</small></div>' + 210 '</div>' 211 }).join('') 212 } 213 214 function filesHtml(data) { 215 var files = data.files || {} 216 var totals = files.totals || {} 217 var omitted = files.omitted || {} 218 if (files.ok !== true) { 219 return '<section><h3>Inventaire fichiers</h3><div class="ce-empty">Inventaire indisponible : ' + esc(files.error || 'erreur') + '</div></section>' 220 } 221 return '<section><h3>Inventaire fichiers ' + esc(files.surface || activeSurface()) + '</h3>' + 222 '<div class="ce-inventory-head">' + 223 '<div><b>' + esc(totals.files || 0) + '</b><span>fichiers visibles</span></div>' + 224 '<div><b>' + esc(totals.directories || 0) + '</b><span>dossiers</span></div>' + 225 '<div><b>' + esc(totals.omitted || 0) + '</b><span>protégés/ignorés</span></div>' + 226 '</div>' + 227 '<div class="ce-pills">' + statPills(files.bySurface) + statPills(files.byArea) + '</div>' + 228 '<div class="ce-inventory-grid">' + 229 '<div><h4>Dossiers</h4><div class="ce-dir-list">' + directoryRows(files) + '</div></div>' + 230 '<div><h4>Fichiers</h4><div class="ce-file-list">' + fileRows(files) + '</div></div>' + 231 '</div>' + 232 '<p class="ce-foot">Inventaire lecture seule : chemins relatifs et métadonnées. Secrets, tokens, .env, caches lourds et node_modules restent cachés. Omission : secrets ' + esc(omitted.secret || 0) + ', dossiers ' + esc(omitted.dirs || 0) + ', lourds ' + esc(omitted.heavy || 0) + '.</p>' + 233 '</section>' 234 } 235 236 function draw(data) { 237 var root = document.getElementById('crea-ecosystem') 238 if (!root) return 239 var totals = data.backend && data.backend.totals || {} 240 root.querySelector('.ce-body').innerHTML = 241 rulesHtml(data) + 242 '<div class="ce-summary">' + 243 '<div><b>' + data.local.active + '/' + data.local.expected + '</b><span>couches navigateur</span></div>' + 244 '<div><b>' + (totals.ready || 0) + '/' + (totals.systems || 0) + '</b><span>systèmes opérationnels</span></div>' + 245 '<div><b>' + esc(data.local.profile) + '</b><span>
245' + esc(data.local.platform + ' - ' + data.local.viewport) + '</span></div>' + 246 '</div>' + 247 '<section><h3>Backend et écosystème</h3><div class="ce-list">' + backendRows(data) + '</div></section>' + 248 filesHtml(data) + 249 '<section><h3>Couches chargées sur cet appareil</h3><div class="ce-modules">' + localRows(data) + '</div></section>' + 250 '<p class="ce-foot">Les éléments protégés demandent un secret, un consentement ou un environnement adapté. Les prototypes remplacés restent conservés sans être exécutés en double.</p>' 251 } 252 253 async function refresh() { 254 var root = document.getElementById('crea-ecosystem') 255 if (root) root.classList.add('loading') 256 var data = await load() 257 if (root) { 258 root.classList.remove('loading') 259 draw(data) 260 } 261 return data 262 } 263 264 function open() { 265 var existing = document.getElementById('crea-ecosystem') 266 if (existing) { existing.remove(); return } 267 closeNearby() 268 var overlay = document.createElement('div') 269 overlay.id = 'crea-ecosystem' 270 overlay.setAttribute('role', 'dialog') 271 overlay.setAttribute('aria-modal', 'true') 272 overlay.setAttribute('aria-label', 'Centre Ãcosystème') 273 overlay.innerHTML = 274 '<div class="ce-box">' + 275 '<header><div><strong>Centre Ãcosystème</strong><span>Ãtat réel de CREA sur cet appareil et son backend</span></div>' + 276 '<button type="button" data-refresh title="Actualiser" aria-label="Actualiser">â»</button>' + 277 '<button type="button" data-close title="Fermer" aria-label="Fermer">Ã</button></header>' + 278 '<div class="ce-body"><div class="ce-loading">Lecture de l\'écosystème...</div></div>' + 279 '</div>' 280 document.body.appendChild(overlay) 281 overlay.addEventListener('mousedown', function (event) { if (event.target === overlay) overlay.remove() }) 282 overlay.addEventListener('click', function (event) { 283 if (event.target.closest('[data-close]')) overlay.remove() 284 if (event.target.closest('[data-refresh]')) refresh() 285 }) 286 document.addEventListener('keydown', function onEscape(event) { 287 if (event.key === 'Escape') { 288 overlay.remove() 289 document.removeEventListener('keydown', onEscape) 290 } 291 }) 292 refresh() 293 } 294 295 function refreshLauncher() { 296 // Bouton flottant « Eco » supprimé (épure de l'interface). 297 // Le centre reste accessible via window.CREA_ECOSYSTEM.open(). 298 var button = document.getElementById('crea-ecosystem-launch') 299 if (button) button.remove() 300 } 301 302 function css() { 303 if (document.getElementById('crea-ecosystem-css')) return 304 var style = document.createElement('style') 305 style.id = 'crea-ecosystem-css' 306 style.textContent = 307 '#crea-ecosystem{position:fixed;inset:0;z-index:90040;background:rgba(0,0,0,.56);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;padding:max(14px,env(safe-area-inset-top)) max(14px,env(safe-area-inset-right)) max(14px,env(safe-area-inset-bottom)) max(14px,env(safe-area-inset-left))}' + 308 '#crea-ecosystem .ce-box{width:min(920px,100%);max-height:min(88vh,var(--crea-vh,88vh));display:flex;flex-direction:column;overflow:hidden;background:var(--bg-secondary,#151719);border:1px solid var(--border,#34383d);border-radius:8px;box-shadow:0 24px 70px rgba(0,0,0,.55)}' + 309 '#crea-ecosystem header{display:flex;align-items:center;gap:8px;padding:13px 15px;border-bottom:1px solid var(--border,#34383d)}' + 310 '#crea-ecosystem header>div{flex:1;min-width:0;display:flex;flex-direction:column}#crea-ecosystem header strong{color:var(--t-primary,#f3f4f6);font:700 15px Inter,system-ui,sans-serif}#crea-ecosystem header span{color:var(--t-faint,#9ca3af);font:500 11.5px Inter,system-ui,sans-serif;white-space:normal}' + 311 '#crea-ecosystem header button{width:34px;height:34px;flex:0 0 34px;border:1px solid var(--border,#34383d);border-radius:6px;background:var(--bg-tertiary,#202326);color:var(--t-secondary,#d1d5db);font:600 18px Inter,system-ui,sans-serif;cursor:pointer}' + 312 '#crea-ecosystem.loading [data-refresh]{animation:ce-spin .8s linear infinite}#crea-ecosystem .ce-body{overflow:auto;padding:14px 15px 16px}' + 313 '#crea-ecosystem .ce-rules{display:flex;flex-wrap:wrap;gap:7px;margin-bottom:12px}#crea-ecosystem .ce-rules span{border:1px solid var(--border,#34383d);border-radius:999px;padding:5px 9px;color:var(--t-secondary,#d1d5db);font:600 11px Inter,system-ui,sans-serif}#crea-ecosystem .ce-rules .ok{border-color:#237a5a;color:#69d7ad;background:rgba(35,122,90,.12)}#crea-ecosystem .ce-rules .warn{border-color:#9a6b22;color:#f2c66d;background:rgba(154,107,34,.12)}#crea-ecosystem .ce-rules .unknown{border-color:#64748b;color:#94a3b8;background:rgba(100,116,139,.12)}' + 314 '#crea-ecosystem .ce-summary{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));border-top:1px solid var(--border,#34383d);border-bottom:1px solid var(--border,#34383d);margin-bottom:15px}#crea-ecosystem .ce-summary>div{min-width:0;padding:11px 12px;border-right:1px solid var(--border,#34383d);display:flex;flex-direction:column}#crea-ecosystem .ce-summary>div:last-child{border-right:0}#crea-ecosystem .ce-summary b{color:var(--t-primary,#f3f4f6);font:700 14px Inter,system-ui,sans-serif;overflow-wrap:anywhere}#crea-ecosystem .ce-summary span{color:var(--t-faint,#9ca3af);font:500 10.5px Inter,system-ui,sans-serif;margin-top:2px}' + 315 '#crea-ecosystem section+section{margin-top:17px}#crea-ecosystem h3{margin:0 0 7px;color:var(--t-secondary,#d1d5db);font:700 11px Inter,system-ui,sans-serif;text-transform:uppercase;letter-spacing:.05em}' + 316 '#crea-ecosystem .ce-list{border-top:1px solid var(--border,#34383d)}#crea-ecosystem .ce-row{display:flex;align-items:center;gap:10px;min-height:48px;padding:7px 4px;border-bottom:1px solid var(--border,#34383d)}#crea-ecosystem .ce-main{flex:1;min-width:0;display:flex;flex-direction:column}#crea-ecosystem .ce-main b{color:var(--t-primary,#f3f4f6);font:600 12.5px Inter,system-ui,sans-serif}#crea-ecosystem .ce-main small{color:var(--t-faint,#9ca3af);font:500 10.5px/1.4 Inter,system-ui,sans-serif;overflow-wrap:anywhere}' + 317 '#crea-ecosystem .ce-dot{width:8px;height:8px;border-radius:50%;flex:0 0 8px;background:#737982}#crea-ecosystem .ce-dot.on{background:#35b982}#crea-ecosystem .ce-dot.wired{background:#4ea1d3}#crea-ecosystem .ce-dot.gate{background:#d39a40}' + 318 '#crea-ecosystem .ce-badge{flex:0 0 auto;border:1px solid var(--border,#34383d);border-radius:999px;padding:4px 8px;color:var(--t-faint,#9ca3af);font:700 9.5px Inter,system-ui,sans-serif;text-transform:uppercase}#crea-ecosystem .ce-badge.on{color:#69d7ad;border-color:#237a5a}#crea-ecosystem .ce-badge.wired{color:#83c7ef;border-color:#326b8d}#crea-ecosystem .ce-badge.gate{color:#f2c66d;border-color:#9a6b22}' + 319 '#crea-ecosystem .ce-inventory-head{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));border:1px solid var(--border,#34383d);border-radius:8px;overflow:hidden;margin-bottom:9px}#crea-ecosystem .ce-inventory-head>div{min-width:0;padding:9px 10px;border-right:1px solid var(--border,#34383d);display:flex;flex-direction:column}#crea-ecosystem .ce-inventory-head>div:last-child{border-right:0}#crea-ecosystem .ce-inventory-head b{color:var(--t-primary,#f3f4f6);font:700 13px Inter,system-ui,sans-serif}#crea-ecosystem .ce-inventory-head span{color:var(--t-faint,#9ca3af);font:500 10px Inter,system-ui,sans-serif}' + 320 '#crea-ecosystem .ce-pills{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 10px}#crea-ecosystem .ce-pills span{border:1px solid var(--border,#34383d);border-radius:999px;padding:4px 8px;color:var(--t-faint,#9ca3af);font:600 10px Inter,system-ui,sans-serif}#crea-ecosystem .ce-pills b{color:var(--t-secondary,#d1d5db);font-weight:800}' + 321 '#crea-ecosystem .ce-inventory-grid{display:grid;grid-template-columns:minmax(190px,.65fr) minmax(0,1.35fr);gap:12px}#crea-ecosystem h4{margin:0 0 6px;color:var(--t-faint,#9ca3af);font:700 10px Inter,system-ui,sans-serif;text-transform:uppercase;letter-spacing:.04em}' + 322 '#crea-ecosystem .ce-dir-list,#crea-ecosystem .ce-file-list{border:1px solid var(--border,#34383d);border-radius:8px;overflow:auto;max-height:330px;background:rgba(0,0,0,.08)}#crea-ecosystem .ce-dir{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:center;padding:6px 8px;border-bottom:1px solid var(--border,#34383d)}#crea-ecosystem .ce-dir span{min-width:0;color:var(--t-secondary,#d1d5db);font:500 10.5px Inter,system-ui,sans-serif;overflow-wrap:anywhere}#crea-ecosystem .ce-dir b{color:var(--t-faint,#9ca3af);font:700 10px Inter,system-ui,sans-serif}' + 323 '#crea-ecosystem .ce-file{display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px;align-items:start;padding:7px 8px;border-bottom:1px solid var(--border,#34383d)}#crea-ecosystem .ce-file>div{min-width:0;display:flex;flex-direction:column}#crea-ecosystem .ce-file b{color:var(--t-primary,#f3f4f6);font:600 10.8px Inter,system-ui,sans-serif;overflow-wrap:anywhere}#crea-ecosystem .ce-file small{color:var(--t-faint,#9ca3af);font:500 9.5px Inter,system-ui,sans-serif;margin-top:2px}' + 324 '#crea-ecosystem .ce-modules{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:18px}#crea-ecosystem .ce-module{min-width:0;display:grid;grid-template-columns:8px minmax(0,1fr) auto;align-items:center;gap:9px;padding:7px 2px;border-bottom:1px solid var(--border,#34383d)}#crea-ecosystem .ce-module span:nth-child(2){color:var(--t-secondary,#d1d5db);font:500 11.5px Inter,system-ui,sans-serif;overflow-wrap:anywhere}#crea-ecosystem .ce-module small{color:var(--t-faint,#9ca3af);font:600 9.5px Inter,system-ui,sans-serif}' + 325 '#crea-ecosystem .ce-foot,#crea-ecosystem .ce-empty,#crea-ecosystem .ce-loading{color:var(--t-faint,#9ca3af);font:500 11px/1.5 Inter,system-ui,sans-serif}#crea-ecosystem .ce-foot{margin:14px 0 0}#crea-ecosystem .ce-empty,#crea-ecosystem .ce-loading{padding:18px 3px}' + 326 '#crea-ecosystem-launch{position:fixed;right:14px;bottom:calc(env(safe-area-inset-bottom,0px) + 142px);z-index:86010;height:38px;min-width:38px;border-radius:19px;border:1px solid var(--border,#333);background:var(--bg-secondary,#161616);color:var(--t-primary,#eee);display:flex;align-items:center;justify-content:center;gap:5px;padding:0 10px;font:700 11px Inter,system-ui,sans-serif;box-shadow:0 6px 18px rgba(0,0,0,.25);opacity:.72;cursor:pointer;transition:opacity .15s,transform .15s}' + 327 '#crea-ecosystem-launch:hover{opacity:1;transform:scale(1.05)}#crea-ecosystem-launch span{font-size:16px;line-height:1}#crea-ecosystem-launch b{font:700 10px Inter,system-ui,sans-serif;letter-spacing:0;text-transform:uppercase}' + 328 '@media(max-width:680px){#crea-ecosystem{align-items:stretch;padding:0}#crea-ecosystem .ce-box{width:100%;max-height:var(--crea-vh,100dvh);height:var(--crea-vh,100dvh);border:0;border-radius:0}#crea-ecosystem .ce-summary,#crea-ecosystem .ce-inventory-head{grid-template-columns:1fr}#crea-ecosystem .ce-summary>div,#crea-ecosystem .ce-inventory-head>div{border-right:0;border-bottom:1px solid var(--border,#34383d)}#crea-ecosystem .ce-summary>div:last-child,#crea-ecosystem .ce-inventory-head>div:last-child{border-bottom:0}#crea-ecosystem .ce-inventory-grid{grid-template-columns:1fr}#crea-ecosystem .ce-dir-list,#crea-ecosystem .ce-file-list{max-height:260px}#crea-ecosystem .ce-modules{grid-template-columns:1fr}#crea-ecosystem .ce-badge{font-size:8.5px}#crea-ecosystem-launch{right:12px;bottom:calc(env(safe-area-inset-bottom,0px) + 192px);height:34px;min-width:34px;border-radius:17px;padding:0 8px}#crea-ecosystem-launch b{display:none}}' + 329 '@keyframes ce-spin{to{transform:rotate(360deg)}}' 330 document.head.appendChild(style) 331 } 332 333 function start() { 334 css() 335 refreshLauncher() 336 } 337 338 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start) 339 else start() 340 341 window.CREA_ECOSYSTEM = { 342 open:open, 343 refresh:refresh, 344 refreshLauncher:refreshLauncher, 345 snapshot:function () { return latest || { local:localSnapshot(), backend:null } }, 346 } 347})()
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.