annotask 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugin/bridge-client.ts"],"sourcesContent":["/**\n * Client bridge script injected into the user's app.\n * Communicates with the Annotask shell via postMessage.\n * Handles all DOM interactions: hover, click, style reads/writes,\n * element resolution, layout scanning, etc.\n *\n * Returned as an inline string (same pattern as toggle-button.ts).\n */\nexport function bridgeClientScript(): string {\n return `\n(function() {\n // Don't run inside the Annotask shell\n if (window.location.pathname.startsWith('/__annotask')) return;\n // Don't run if already initialized\n if (window.__ANNOTASK_BRIDGE__) return;\n window.__ANNOTASK_BRIDGE__ = true;\n\n // ── Element Registry ──────────────────────────────────\n var eidCounter = 0;\n var eidMap = new Map(); // eid string → WeakRef<Element>\n var elToEid = new WeakMap(); // Element → eid string\n\n function getEid(el) {\n if (!el) return null;\n var existing = elToEid.get(el);\n if (existing) return existing;\n eidCounter++;\n var eid = 'e-' + eidCounter;\n eidMap.set(eid, new WeakRef(el));\n elToEid.set(el, eid);\n return eid;\n }\n\n function getEl(eid) {\n var ref = eidMap.get(eid);\n return ref ? ref.deref() || null : null;\n }\n\n // ── PostMessage Helpers ───────────────────────────────\n var shellOrigin = '*'; // Will be tightened on first shell message\n\n function sendToShell(type, payload, id) {\n var msg = { type: type, payload: payload || {}, source: 'annotask-client' };\n if (id) msg.id = id;\n window.parent.postMessage(msg, shellOrigin);\n }\n\n function respond(id, payload) {\n sendToShell(null, payload, id);\n // type is not needed for responses — shell matches by id\n }\n\n // ── Source Element Resolution ─────────────────────────\n function hasSourceAttr(el) {\n return el.hasAttribute && (el.hasAttribute('data-annotask-file') || el.hasAttribute('data-astro-source-file'));\n }\n\n function findSourceElement(el) {\n var c = el;\n while (c) {\n if (hasSourceAttr(c)) return { sourceEl: c, targetEl: el };\n c = c.parentElement;\n }\n return { sourceEl: el, targetEl: el };\n }\n\n function getSourceData(el) {\n // Prefer data-annotask-* attributes, fall back to data-astro-source-* (Astro framework)\n var file = el.getAttribute('data-annotask-file') || '';\n var line = el.getAttribute('data-annotask-line') || '';\n var component = el.getAttribute('data-annotask-component') || '';\n\n if (!file && el.getAttribute('data-astro-source-file')) {\n var astroFile = el.getAttribute('data-astro-source-file') || '';\n // Convert absolute path to project-relative by finding src/ prefix\n var srcIdx = astroFile.indexOf('/src/');\n file = srcIdx !== -1 ? astroFile.slice(srcIdx + 1) : astroFile;\n }\n if ((!line || line === '0') && el.getAttribute('data-astro-source-loc')) {\n // data-astro-source-loc format: \"line:col\"\n line = (el.getAttribute('data-astro-source-loc') || '').split(':')[0];\n }\n if (!component && file) {\n // Derive component name from file path\n var parts = file.split('/');\n var fileName = parts[parts.length - 1] || '';\n component = fileName.replace(/\\.[^.]+$/, '');\n }\n\n var mfe = el.getAttribute('data-annotask-mfe') || '';\n\n return { file: file, line: line, component: component, mfe: mfe };\n }\n\n function getRect(el) {\n var r = el.getBoundingClientRect();\n return { x: r.x, y: r.y, width: r.width, height: r.height };\n }\n\n // ── Interaction Mode ──────────────────────────────────\n var storedMode = '';\n try { storedMode = localStorage.getItem('annotask:mode') || ''; } catch(e) {}\n var currentMode = storedMode || 'select';\n var inspectModes = { select: true, pin: true };\n\n // ── Event Handlers ────────────────────────────────────\n var lastHoverEid = null;\n var rafPending = false;\n var pendingHoverData = null;\n\n function onMouseOver(e) {\n if (!inspectModes[currentMode]) return;\n var el = e.target;\n if (!el || el === document.documentElement || el === document.body) return;\n var eid = getEid(el);\n if (eid === lastHoverEid) return;\n lastHoverEid = eid;\n\n var source = findSourceElement(el);\n var data = getSourceData(source.sourceEl);\n\n pendingHoverData = {\n eid: eid,\n tag: el.tagName.toLowerCase(),\n file: data.file,\n component: data.component,\n rect: getRect(el)\n };\n\n if (!rafPending) {\n rafPending = true;\n requestAnimationFrame(function() {\n rafPending = false;\n if (pendingHoverData) sendToShell('hover:enter', pendingHoverData);\n });\n }\n }\n\n function onMouseOut(e) {\n if (!inspectModes[currentMode]) return;\n // Only fire leave when truly leaving all elements\n if (e.relatedTarget && e.relatedTarget !== document.documentElement) return;\n lastHoverEid = null;\n pendingHoverData = null;\n sendToShell('hover:leave', {});\n }\n\n function onClick(e) {\n if (!inspectModes[currentMode]) return;\n e.preventDefault();\n e.stopPropagation();\n\n var el = e.target;\n if (!el) return;\n\n var source = findSourceElement(el);\n var data = getSourceData(source.sourceEl);\n var targetEl = source.targetEl;\n var classes = typeof targetEl.className === 'string' ? targetEl.className : '';\n\n sendToShell('click:element', {\n eid: getEid(targetEl),\n sourceEid: getEid(source.sourceEl),\n file: data.file,\n line: data.line,\n component: data.component,\n mfe: data.mfe,\n tag: targetEl.tagName.toLowerCase(),\n classes: classes,\n rect: getRect(targetEl),\n shiftKey: e.shiftKey,\n clientX: e.clientX,\n clientY: e.clientY\n });\n }\n\n function onMouseDown(e) {\n if (!inspectModes[currentMode]) return;\n e.stopPropagation();\n }\n\n function onMouseUp(e) {\n if (currentMode !== 'highlight') return;\n var sel = document.getSelection();\n var text = sel ? sel.toString().trim() : '';\n if (!text || text.length < 2) return;\n var anchorEl = sel.anchorNode ? sel.anchorNode.parentElement : null;\n if (!anchorEl) return;\n var source = findSourceElement(anchorEl);\n var data = getSourceData(source.sourceEl);\n\n sendToShell('selection:text', {\n text: text,\n eid: getEid(anchorEl),\n file: data.file,\n line: parseInt(data.line) || 0,\n component: data.component,\n mfe: data.mfe,\n tag: anchorEl.tagName.toLowerCase()\n });\n }\n\n function onContextMenu(e) {\n if (currentMode === 'interact') return;\n e.preventDefault();\n var el = e.target;\n if (!el) return;\n var source = findSourceElement(el);\n var data = getSourceData(source.sourceEl);\n var targetEl = source.targetEl;\n var classes = typeof targetEl.className === 'string' ? targetEl.className : '';\n\n sendToShell('contextmenu:element', {\n eid: getEid(targetEl),\n sourceEid: getEid(source.sourceEl),\n file: data.file,\n line: data.line,\n component: data.component,\n mfe: data.mfe,\n tag: targetEl.tagName.toLowerCase(),\n classes: classes,\n rect: getRect(targetEl),\n shiftKey: false,\n clientX: e.clientX,\n clientY: e.clientY\n });\n }\n\n function onKeyDown(e) {\n if ((e.ctrlKey || e.metaKey) && e.key === 'z' && !e.shiftKey) {\n e.preventDefault();\n sendToShell('keydown', { key: e.key, ctrlKey: e.ctrlKey, metaKey: e.metaKey, shiftKey: e.shiftKey });\n }\n }\n\n // Install event listeners\n document.addEventListener('mouseover', onMouseOver, { capture: true });\n document.addEventListener('mouseout', onMouseOut, { capture: true });\n document.addEventListener('mousedown', onMouseDown, { capture: true });\n document.addEventListener('click', onClick, { capture: true });\n document.addEventListener('mouseup', onMouseUp, { capture: true });\n document.addEventListener('keydown', onKeyDown, { capture: true });\n document.addEventListener('contextmenu', onContextMenu, { capture: true });\n\n // ── User Action Tracking (interact mode) ───────────────\n // Tracks meaningful page actions (link/button clicks) so the LLM\n // can understand what the user did to reach the current state.\n\n var lastActionTs = 0;\n function onUserAction(e) {\n var el = e.target;\n if (!el || !el.closest) return;\n\n // Debounce — ignore clicks within 50ms (same gesture)\n var now = Date.now();\n if (now - lastActionTs < 50) return;\n lastActionTs = now;\n\n // Find the best description of what was clicked\n var actionEl = el.closest('a, button, [role=\"button\"], [role=\"tab\"], [role=\"menuitem\"], [role=\"link\"], [type=\"submit\"], tr[class*=\"row\"], [data-pc-section=\"bodyrow\"]');\n var descEl = actionEl || el;\n\n var tag = descEl.tagName.toLowerCase();\n // Get concise text: prefer innerText of the immediate target, fall back to closest actionable\n var text = '';\n if (el.innerText) text = el.innerText.trim();\n if (!text && descEl.innerText) text = descEl.innerText.trim();\n text = text.split(String.fromCharCode(10))[0].substring(0, 60);\n\n var href = '';\n if (tag === 'a') href = descEl.getAttribute('href') || '';\n else if (el.closest('a')) href = el.closest('a').getAttribute('href') || '';\n\n // Get component context if available\n var source = findSourceElement(descEl);\n var data = getSourceData(source.sourceEl);\n\n sendToShell('user:action', {\n tag: tag,\n text: text,\n href: href,\n component: data.component || '',\n });\n }\n\n document.addEventListener('click', onUserAction, { capture: true });\n\n // ── Route Tracking ────────────────────────────────────\n var lastRoute = window.location.pathname;\n\n function checkRoute() {\n var path = window.location.pathname;\n if (path !== lastRoute) {\n lastRoute = path;\n sendToShell('route:changed', { path: path });\n }\n }\n\n window.addEventListener('popstate', checkRoute);\n window.addEventListener('hashchange', checkRoute);\n setInterval(checkRoute, 2000); // safety net for pushState\n\n // ── Message Handler ───────────────────────────────────\n window.addEventListener('message', function(event) {\n var msg = event.data;\n if (!msg || msg.source !== 'annotask-shell') return;\n // Tighten origin on first shell message\n if (shellOrigin === '*' && event.origin) shellOrigin = event.origin;\n\n var type = msg.type;\n var payload = msg.payload || {};\n var id = msg.id;\n\n // ── Mode ──\n if (type === 'mode:set') {\n currentMode = payload.mode || 'select';\n try { localStorage.setItem('annotask:mode', currentMode); } catch(e) {}\n return;\n }\n\n // ── Ping ──\n if (type === 'bridge:ping') {\n respond(id, {});\n return;\n }\n\n // ── Element Resolution ──\n if (type === 'resolve:at-point') {\n var el = document.elementFromPoint(payload.x, payload.y);\n if (!el || el === document.documentElement || el === document.body) {\n respond(id, null);\n return;\n }\n var src = findSourceElement(el);\n var srcData = getSourceData(src.sourceEl);\n respond(id, {\n eid: getEid(src.targetEl),\n file: srcData.file,\n line: srcData.line,\n component: srcData.component,\n mfe: srcData.mfe,\n tag: src.sourceEl.tagName.toLowerCase(),\n rect: getRect(src.sourceEl),\n classes: typeof src.targetEl.className === 'string' ? src.targetEl.className : ''\n });\n return;\n }\n\n if (type === 'resolve:template-group') {\n var all = document.querySelectorAll(\n '[data-annotask-file=\"' + payload.file + '\"][data-annotask-line=\"' + payload.line + '\"]'\n );\n // Also check Astro source attributes\n if (all.length === 0 && payload.file && payload.line) {\n // Try matching by astro source attributes (absolute path ends with file, loc starts with line)\n var astroAll = document.querySelectorAll('[data-astro-source-file]');\n var matched = [];\n for (var ai = 0; ai < astroAll.length; ai++) {\n var af = astroAll[ai].getAttribute('data-astro-source-file') || '';\n var al = (astroAll[ai].getAttribute('data-astro-source-loc') || '').split(':')[0];\n if (af.endsWith('/' + payload.file) && al === payload.line) matched.push(astroAll[ai]);\n }\n if (matched.length > 0) all = matched;\n }\n var eids = [];\n var rects = [];\n for (var i = 0; i < all.length; i++) {\n if (all[i].tagName.toLowerCase() === payload.tagName) {\n eids.push(getEid(all[i]));\n rects.push(getRect(all[i]));\n }\n }\n respond(id, { eids: eids, rects: rects });\n return;\n }\n\n if (type === 'resolve:rect') {\n var rEl = getEl(payload.eid);\n respond(id, rEl ? { rect: getRect(rEl) } : null);\n return;\n }\n\n if (type === 'resolve:rects') {\n var results = [];\n for (var j = 0; j < payload.eids.length; j++) {\n var re = getEl(payload.eids[j]);\n results.push(re ? getRect(re) : null);\n }\n respond(id, { rects: results });\n return;\n }\n\n // ── Style Operations ──\n if (type === 'style:get-computed') {\n var sEl = getEl(payload.eid);\n if (!sEl) { respond(id, { styles: {} }); return; }\n var cs = window.getComputedStyle(sEl);\n var styles = {};\n for (var k = 0; k < payload.properties.length; k++) {\n styles[payload.properties[k]] = cs.getPropertyValue(payload.properties[k]);\n }\n respond(id, { styles: styles });\n return;\n }\n\n if (type === 'style:apply') {\n var aEl = getEl(payload.eid);\n if (!aEl) { respond(id, { before: '' }); return; }\n var before = window.getComputedStyle(aEl).getPropertyValue(payload.property);\n aEl.style.setProperty(payload.property, payload.value);\n respond(id, { before: before });\n return;\n }\n\n if (type === 'style:apply-batch') {\n var befores = [];\n for (var m = 0; m < payload.eids.length; m++) {\n var bEl = getEl(payload.eids[m]);\n if (bEl) {\n befores.push(window.getComputedStyle(bEl).getPropertyValue(payload.property));\n bEl.style.setProperty(payload.property, payload.value);\n } else {\n befores.push('');\n }\n }\n respond(id, { befores: befores });\n return;\n }\n\n if (type === 'style:undo') {\n var uEl = getEl(payload.eid);\n if (uEl) {\n if (payload.value) uEl.style.setProperty(payload.property, payload.value);\n else uEl.style.removeProperty(payload.property);\n }\n respond(id, {});\n return;\n }\n\n if (type === 'class:get') {\n var cEl = getEl(payload.eid);\n respond(id, { classes: cEl ? (typeof cEl.className === 'string' ? cEl.className : '') : '' });\n return;\n }\n\n if (type === 'class:set') {\n var csEl = getEl(payload.eid);\n if (!csEl) { respond(id, { before: '' }); return; }\n var classBefore = typeof csEl.className === 'string' ? csEl.className : '';\n csEl.className = payload.classes;\n respond(id, { before: classBefore });\n return;\n }\n\n if (type === 'class:set-batch') {\n var classBefores = [];\n for (var n = 0; n < payload.eids.length; n++) {\n var cbEl = getEl(payload.eids[n]);\n if (cbEl) {\n classBefores.push(typeof cbEl.className === 'string' ? cbEl.className : '');\n cbEl.className = payload.classes;\n } else {\n classBefores.push('');\n }\n }\n respond(id, { befores: classBefores });\n return;\n }\n\n if (type === 'class:undo') {\n var cuEl = getEl(payload.eid);\n if (cuEl) cuEl.className = payload.classes;\n respond(id, {});\n return;\n }\n\n // ── Classification ──\n if (type === 'classify:element') {\n var clEl = getEl(payload.eid);\n if (!clEl) { respond(id, null); return; }\n var tag = clEl.tagName.toLowerCase();\n var clCs = window.getComputedStyle(clEl);\n var display = clCs.display;\n var childCount = clEl.children.length;\n var isFlex = display.includes('flex');\n var isGrid = display.includes('grid');\n var semanticContainers = ['section','main','aside','nav','header','footer','article'];\n var role = 'content';\n if (clEl.hasAttribute('data-annotask-component')) {\n var comp = clEl.getAttribute('data-annotask-component') || '';\n if (comp && comp[0] === comp[0].toUpperCase() && comp[0] !== comp[0].toLowerCase()) {\n role = 'component';\n }\n }\n if (role !== 'component' && (isFlex || isGrid) && childCount > 0) role = 'container';\n if (role !== 'component' && role !== 'container' && semanticContainers.indexOf(tag) >= 0 && childCount > 0) role = 'container';\n\n respond(id, {\n role: role,\n display: display,\n isFlexContainer: isFlex,\n isGridContainer: isGrid,\n flexDirection: isFlex ? clCs.flexDirection : undefined,\n childCount: childCount,\n isComponentUnit: role === 'component'\n });\n return;\n }\n\n if (type === 'resolve:element-context') {\n var ctxEl = getEl(payload.eid);\n if (!ctxEl) { respond(id, null); return; }\n\n // Ancestors: walk up 3 levels, capture layout-relevant styles\n var ancestors = [];\n var cur = ctxEl.parentElement;\n for (var ai = 0; ai < 3 && cur && cur !== document.body && cur !== document.documentElement; ai++) {\n var aCs = window.getComputedStyle(cur);\n var aTag = cur.tagName.toLowerCase();\n var aClasses = typeof cur.className === 'string' ? cur.className.trim() : '';\n var aData = getSourceData(cur);\n var ancestor = { tag: aTag, display: aCs.display };\n if (aClasses) ancestor.classes = aClasses;\n if (aData.component) ancestor.component = aData.component;\n if (aCs.display.includes('flex')) {\n ancestor.flexDirection = aCs.flexDirection;\n if (aCs.gap && aCs.gap !== 'normal') ancestor.gap = aCs.gap;\n ancestor.childCount = cur.children.length;\n }\n if (aCs.display.includes('grid')) {\n ancestor.gridTemplateColumns = aCs.gridTemplateColumns;\n ancestor.gridTemplateRows = aCs.gridTemplateRows;\n if (aCs.gap && aCs.gap !== 'normal') ancestor.gap = aCs.gap;\n ancestor.childCount = cur.children.length;\n }\n if (aCs.overflow && aCs.overflow !== 'visible') ancestor.overflow = aCs.overflow;\n ancestors.push(ancestor);\n cur = cur.parentElement;\n }\n\n // Subtree: simplified HTML of the element and its children (3 levels deep)\n function describeEl(el, depth) {\n var t = el.tagName.toLowerCase();\n var cl = typeof el.className === 'string' ? el.className.trim() : '';\n var txt = '';\n // Only get direct text (not from children)\n for (var ci = 0; ci < el.childNodes.length; ci++) {\n if (el.childNodes[ci].nodeType === 3) {\n var nt = el.childNodes[ci].textContent.trim();\n if (nt) { txt = nt.substring(0, 40); break; }\n }\n }\n var node = { tag: t };\n if (cl) node.classes = cl;\n if (txt) node.text = txt;\n if (depth < 3 && el.children.length > 0) {\n var kids = [];\n for (var ki = 0; ki < el.children.length && ki < 10; ki++) {\n kids.push(describeEl(el.children[ki], depth + 1));\n }\n node.children = kids;\n if (el.children.length > 10) node.childrenTruncated = el.children.length;\n }\n return node;\n }\n\n respond(id, {\n ancestors: ancestors,\n subtree: describeEl(ctxEl, 0)\n });\n return;\n }\n\n // ── Accessibility Scan ──\n if (type === 'a11y:scan') {\n var a11yEid = payload.eid;\n var a11yEl = a11yEid ? getEl(a11yEid) : document.body;\n if (!a11yEl) { respond(id, { violations: [] }); return; }\n\n function runAxeScan(target) {\n if (!window.axe) { respond(id, { violations: [], error: 'axe not loaded' }); return; }\n window.axe.run(target, { resultTypes: ['violations'] }, function(err, results) {\n if (err) { respond(id, { violations: [], error: err.message }); return; }\n var violations = [];\n for (var vi = 0; vi < results.violations.length; vi++) {\n var v = results.violations[vi];\n var nodeDetails = [];\n for (var ni = 0; ni < v.nodes.length && ni < 5; ni++) {\n var node = v.nodes[ni];\n var detail = {\n html: (node.html || '').substring(0, 200),\n target: node.target ? node.target[0] : '',\n failureSummary: node.failureSummary || ''\n };\n // Try to resolve annotask source for this element\n var selector = node.target ? node.target[0] : null;\n if (selector) {\n try {\n var domEl = document.querySelector(selector);\n if (domEl) {\n var src = findSourceElement(domEl);\n var srcData = getSourceData(src.sourceEl);\n if (srcData.file) {\n detail.file = srcData.file;\n detail.line = srcData.line;\n detail.component = srcData.component;\n }\n }\n } catch(e) {}\n }\n nodeDetails.push(detail);\n }\n violations.push({\n id: v.id,\n impact: v.impact,\n description: v.description,\n help: v.help,\n helpUrl: v.helpUrl,\n nodes: v.nodes.length,\n elements: nodeDetails\n });\n }\n respond(id, { violations: violations });\n });\n }\n\n if (window.axe) {\n runAxeScan(a11yEl);\n } else {\n var script = document.createElement('script');\n script.src = 'https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.10.2/axe.min.js';\n script.onload = function() { runAxeScan(a11yEl); };\n script.onerror = function() { respond(id, { violations: [], error: 'failed to load axe-core' }); };\n document.head.appendChild(script);\n }\n return;\n }\n\n // ── Layout Scan ──\n if (type === 'layout:scan') {\n var layoutResults = [];\n var allEls = document.querySelectorAll('*');\n for (var li = 0; li < allEls.length; li++) {\n var lEl = allEls[li];\n if (lEl.nodeType !== 1) continue;\n var lCs = window.getComputedStyle(lEl);\n var lDisplay = lCs.display;\n if (!lDisplay.includes('flex') && !lDisplay.includes('grid')) continue;\n var lRect = lEl.getBoundingClientRect();\n if (lRect.width < 20 || lRect.height < 20) continue;\n var lIsGrid = lDisplay.includes('grid');\n var entry = {\n eid: getEid(lEl),\n display: lIsGrid ? 'grid' : 'flex',\n direction: lIsGrid ? 'grid' : lCs.flexDirection,\n rect: { x: lRect.x, y: lRect.y, width: lRect.width, height: lRect.height },\n columnGap: parseFloat(lCs.columnGap) || 0,\n rowGap: parseFloat(lCs.rowGap) || 0\n };\n if (lIsGrid) {\n var cols = lCs.gridTemplateColumns;\n var rows = lCs.gridTemplateRows;\n entry.templateColumns = cols;\n entry.templateRows = rows;\n if (cols && cols !== 'none') {\n entry.columns = cols.split(/\\\\s+/).map(function(s) { return parseFloat(s) || 0; }).filter(function(v) { return v > 0; });\n }\n if (rows && rows !== 'none') {\n entry.rows = rows.split(/\\\\s+/).map(function(s) { return parseFloat(s) || 0; }).filter(function(v) { return v > 0; });\n }\n }\n layoutResults.push(entry);\n }\n respond(id, { containers: layoutResults });\n return;\n }\n\n if (type === 'layout:add-track') {\n var ltEl = getEl(payload.eid);\n if (!ltEl) { respond(id, { property: '', before: '', after: '' }); return; }\n var ltCs = window.getComputedStyle(ltEl);\n var cssProp = payload.axis === 'col' ? 'grid-template-columns' : 'grid-template-rows';\n var ltBefore = ltCs.getPropertyValue(cssProp) || '';\n var ltAfter = ltBefore && ltBefore !== 'none' ? ltBefore + ' 1fr' : '1fr';\n ltEl.style.setProperty(cssProp, ltAfter);\n respond(id, { property: cssProp, before: ltBefore, after: ltAfter });\n return;\n }\n\n if (type === 'layout:add-child') {\n var lcEl = getEl(payload.eid);\n if (!lcEl) { respond(id, { childEid: '' }); return; }\n var child = document.createElement('div');\n child.style.minWidth = '60px';\n child.style.minHeight = '40px';\n child.style.border = '2px dashed #a855f7';\n child.style.borderRadius = '4px';\n child.style.background = 'rgba(168,85,247,0.05)';\n child.setAttribute('data-annotask-placeholder', 'true');\n lcEl.appendChild(child);\n respond(id, { childEid: getEid(child) });\n return;\n }\n\n // ── Theme ──\n if (type === 'theme:inject-css') {\n var existing = document.getElementById(payload.styleId);\n if (existing) {\n existing.textContent = payload.css;\n } else {\n var style = document.createElement('style');\n style.id = payload.styleId;\n style.textContent = payload.css;\n document.head.appendChild(style);\n }\n respond(id, {});\n return;\n }\n\n if (type === 'theme:remove-css') {\n var toRemove = document.getElementById(payload.styleId);\n if (toRemove) toRemove.remove();\n respond(id, {});\n return;\n }\n\n // ── Color Palette ──\n if (type === 'palette:scan-vars') {\n var swatches = [];\n try {\n var rootStyles = window.getComputedStyle(document.documentElement);\n var sheets = document.styleSheets;\n for (var si = 0; si < sheets.length; si++) {\n try {\n var rules = sheets[si].cssRules;\n for (var ri = 0; ri < rules.length; ri++) {\n var rule = rules[ri];\n if (rule.selectorText === ':root' || rule.selectorText === ':root, :host') {\n for (var pi = 0; pi < rule.style.length; pi++) {\n var prop = rule.style[pi];\n if (prop.startsWith('--')) {\n var val = rootStyles.getPropertyValue(prop).trim();\n if (val && isColor(val)) {\n swatches.push({ name: prop, value: val });\n }\n }\n }\n }\n }\n } catch(e) { /* cross-origin stylesheet */ }\n }\n } catch(e) {}\n respond(id, { swatches: swatches });\n return;\n }\n\n // ── Source Mapping Check ──\n if (type === 'check:source-mapping') {\n respond(id, { hasMapping: !!(document.querySelector('[data-annotask-file]') || document.querySelector('[data-astro-source-file]')) });\n return;\n }\n\n // ── Insert Placeholder ──\n if (type === 'insert:placeholder') {\n var ipTarget = getEl(payload.targetEid);\n if (!ipTarget) { respond(id, { placeholderEid: '' }); return; }\n var ipEl = createPlaceholder(payload);\n var ipRef = ipTarget;\n switch (payload.position) {\n case 'before': ipRef.parentElement && ipRef.parentElement.insertBefore(ipEl, ipRef); break;\n case 'after': ipRef.parentElement && ipRef.parentElement.insertBefore(ipEl, ipRef.nextSibling); break;\n case 'append': ipRef.appendChild(ipEl); break;\n case 'prepend': ipRef.insertBefore(ipEl, ipRef.firstChild); break;\n }\n // Match sibling sizes in flex/grid\n var insertParent = (payload.position === 'append' || payload.position === 'prepend') ? ipRef : ipRef.parentElement;\n if (insertParent) {\n var pCs = window.getComputedStyle(insertParent);\n if (pCs.display.includes('flex') || pCs.display.includes('grid')) {\n if (!ipEl.style.width) {\n var isRow = pCs.flexDirection === 'row' || pCs.flexDirection === 'row-reverse' || pCs.display.includes('grid');\n if (isRow) ipEl.style.flex = '1';\n }\n }\n }\n respond(id, { placeholderEid: getEid(ipEl) });\n return;\n }\n\n if (type === 'insert:remove') {\n var irEl = getEl(payload.eid);\n if (irEl) {\n var unmount = irEl.__annotask_unmount;\n if (unmount) unmount();\n irEl.remove();\n }\n respond(id, {});\n return;\n }\n\n if (type === 'move:element') {\n var meEl = getEl(payload.eid);\n var meTarget = getEl(payload.targetEid);\n if (meEl && meTarget) {\n switch (payload.position) {\n case 'before': meTarget.parentElement && meTarget.parentElement.insertBefore(meEl, meTarget); break;\n case 'after': meTarget.parentElement && meTarget.parentElement.insertBefore(meEl, meTarget.nextSibling); break;\n case 'append': meTarget.appendChild(meEl); break;\n case 'prepend': meTarget.insertBefore(meEl, meTarget.firstChild); break;\n }\n }\n respond(id, {});\n return;\n }\n\n if (type === 'insert:vue-component' || type === 'insert:component') {\n var vcTarget = getEl(payload.targetEid);\n if (!vcTarget) { respond(id, { eid: '', mounted: false }); return; }\n var vcContainer = document.createElement('div');\n vcContainer.setAttribute('data-annotask-placeholder', 'true');\n switch (payload.position) {\n case 'before': vcTarget.parentElement && vcTarget.parentElement.insertBefore(vcContainer, vcTarget); break;\n case 'after': vcTarget.parentElement && vcTarget.parentElement.insertBefore(vcContainer, vcTarget.nextSibling); break;\n case 'append': vcTarget.appendChild(vcContainer); break;\n case 'prepend': vcTarget.insertBefore(vcContainer, vcTarget.firstChild); break;\n }\n var mounted = tryMountComponent(vcContainer, payload.componentName, payload.props);\n respond(id, { eid: getEid(vcContainer), mounted: mounted });\n return;\n }\n\n // ── Get source data for an eid ──\n if (type === 'resolve:source') {\n var rsEl = getEl(payload.eid);\n if (!rsEl) { respond(id, null); return; }\n var rsSrc = findSourceElement(rsEl);\n var rsData = getSourceData(rsSrc.sourceEl);\n respond(id, {\n sourceEid: getEid(rsSrc.sourceEl),\n file: rsData.file,\n line: rsData.line,\n component: rsData.component,\n tag: rsSrc.sourceEl.tagName.toLowerCase()\n });\n return;\n }\n\n // ── Route ──\n if (type === 'route:current') {\n respond(id, { path: window.location.pathname });\n return;\n }\n });\n\n // ── Helpers ───────────────────────────────────────────\n function isColor(val) {\n if (val.startsWith('#') || val.startsWith('rgb') || val.startsWith('hsl')) return true;\n // Named colors — quick check with canvas\n try {\n var ctx = document.createElement('canvas').getContext('2d');\n ctx.fillStyle = '#000000';\n ctx.fillStyle = val;\n return ctx.fillStyle !== '#000000' || val === 'black' || val === '#000000';\n } catch(e) { return false; }\n }\n\n function createPlaceholder(payload) {\n var el = document.createElement(payload.tag);\n el.setAttribute('data-annotask-placeholder', 'true');\n if (payload.classes) el.className = payload.classes;\n var tag = payload.tag.toLowerCase();\n var isComponent = payload.tag.includes('-') || (payload.tag[0] === payload.tag[0].toUpperCase() && payload.tag[0] !== payload.tag[0].toLowerCase());\n\n if (tag === 'button') {\n el.textContent = payload.textContent || 'Button';\n el.style.cssText = 'padding:8px 16px;border-radius:6px;font-size:14px;font-weight:500;cursor:pointer;border:1px solid currentColor;background:var(--accent,#3b82f6);color:white;';\n } else if (tag === 'input') {\n el.type = 'text'; el.placeholder = 'Input field...';\n el.style.cssText = 'padding:8px 12px;border:1px solid #ccc;border-radius:6px;font-size:14px;width:100%;max-width:300px;background:white;color:#333;';\n } else if (tag === 'textarea') {\n el.placeholder = 'Text area...';\n el.style.cssText = 'padding:8px 12px;border:1px solid #ccc;border-radius:6px;font-size:14px;width:100%;min-height:60px;background:white;color:#333;resize:vertical;';\n } else if (tag === 'img') {\n el.style.cssText = 'width:200px;height:120px;background:#e5e7eb;border-radius:8px;display:flex;align-items:center;justify-content:center;';\n } else if (['h1','h2','h3','h4','h5','h6'].indexOf(tag) >= 0) {\n el.textContent = payload.textContent || 'Heading';\n var sizes = { h1:'2em', h2:'1.5em', h3:'1.25em', h4:'1.1em', h5:'1em', h6:'0.9em' };\n el.style.cssText = 'font-size:' + (sizes[tag]||'1em') + ';font-weight:700;margin:0.5em 0;';\n } else if (tag === 'p') {\n el.textContent = payload.textContent || 'Paragraph text goes here.';\n el.style.cssText = 'margin:0.5em 0;line-height:1.5;';\n } else if (tag === 'a') {\n el.textContent = payload.textContent || 'Link';\n el.style.cssText = 'color:var(--accent,#3b82f6);text-decoration:underline;cursor:pointer;';\n } else if (tag === 'section' || tag === 'div' || tag === 'nav' || tag === 'header' || tag === 'footer' || tag === 'aside' || tag === 'main') {\n if (!payload.classes && !payload.textContent) {\n el.style.cssText = 'min-height:40px;padding:12px;border:1.5px dashed rgba(59,130,246,0.3);border-radius:6px;background:rgba(59,130,246,0.03);';\n } else if (payload.textContent) {\n el.textContent = payload.textContent;\n }\n if (payload.category === 'layout-preset') {\n el.style.minHeight = '60px';\n el.style.padding = el.style.padding || '12px';\n el.style.border = '1.5px dashed rgba(34,197,94,0.3)';\n el.style.borderRadius = '6px';\n el.style.background = 'rgba(34,197,94,0.03)';\n }\n } else if (isComponent) {\n var vcMounted = tryMountComponent(el, payload.tag, payload.defaultProps);\n if (!vcMounted) {\n el.style.cssText = 'min-height:80px;padding:16px;border:1px solid rgba(168,85,247,0.2);border-radius:8px;background:rgba(168,85,247,0.03);display:flex;flex-direction:column;gap:8px;overflow:hidden;';\n var hdr = document.createElement('div');\n hdr.style.cssText = 'display:flex;align-items:center;gap:6px;margin-bottom:4px;';\n var dot = document.createElement('span');\n dot.style.cssText = 'width:6px;height:6px;border-radius:50%;background:#a855f7;';\n hdr.appendChild(dot);\n var tagLabel = document.createElement('span');\n tagLabel.style.cssText = 'font-size:11px;font-weight:600;color:#a855f7;';\n tagLabel.textContent = payload.tag;\n hdr.appendChild(tagLabel);\n el.appendChild(hdr);\n }\n } else {\n el.textContent = payload.textContent || '';\n }\n return el;\n }\n\n function tryMountComponent(container, componentName, props) {\n // Try Vue\n if (window.__ANNOTASK_VUE__) {\n var mounted = tryMountVueComponent(container, componentName, props);\n if (mounted) return true;\n }\n // Try React\n if (window.__ANNOTASK_REACT__) {\n var mounted = tryMountReactComponent(container, componentName, props);\n if (mounted) return true;\n }\n // Try Svelte\n if (window.__ANNOTASK_SVELTE__) {\n var mounted = tryMountSvelteComponent(container, componentName, props);\n if (mounted) return true;\n }\n return false;\n }\n\n function tryMountVueComponent(container, componentName, props) {\n try {\n var appEl = document.querySelector('#app');\n var vueApp = appEl && appEl.__vue_app__;\n if (!vueApp) return false;\n var annotaskVue = window.__ANNOTASK_VUE__;\n if (!annotaskVue || !annotaskVue.createApp || !annotaskVue.h) return false;\n var component = vueApp._context.components[componentName] || (window.__ANNOTASK_COMPONENTS__ && window.__ANNOTASK_COMPONENTS__[componentName]);\n if (!component) return false;\n var mountPoint = document.createElement('div');\n container.appendChild(mountPoint);\n var miniApp = annotaskVue.createApp({\n render: function() { return annotaskVue.h(component, props || {}); }\n });\n miniApp._context = vueApp._context;\n miniApp.mount(mountPoint);\n container.setAttribute('data-annotask-mounted', 'true');\n container.__annotask_unmount = function() { try { miniApp.unmount(); } catch(e) {} };\n return true;\n } catch(e) { return false; }\n }\n\n function tryMountReactComponent(container, componentName, props) {\n try {\n var annotaskReact = window.__ANNOTASK_REACT__;\n if (!annotaskReact || !annotaskReact.createElement || !annotaskReact.createRoot) return false;\n var component = window.__ANNOTASK_COMPONENTS__ && window.__ANNOTASK_COMPONENTS__[componentName];\n if (!component) return false;\n var mountPoint = document.createElement('div');\n container.appendChild(mountPoint);\n var root = annotaskReact.createRoot(mountPoint);\n root.render(annotaskReact.createElement(component, props || {}));\n container.setAttribute('data-annotask-mounted', 'true');\n container.__annotask_unmount = function() { try { root.unmount(); } catch(e) {} };\n return true;\n } catch(e) { return false; }\n }\n\n function tryMountSvelteComponent(container, componentName, props) {\n try {\n var annotaskSvelte = window.__ANNOTASK_SVELTE__;\n if (!annotaskSvelte || !annotaskSvelte.mount) return false;\n var component = window.__ANNOTASK_COMPONENTS__ && window.__ANNOTASK_COMPONENTS__[componentName];\n if (!component) return false;\n var mountPoint = document.createElement('div');\n container.appendChild(mountPoint);\n var instance = annotaskSvelte.mount(component, { target: mountPoint, props: props || {} });\n container.setAttribute('data-annotask-mounted', 'true');\n container.__annotask_unmount = function() {\n try {\n if (annotaskSvelte.unmount) annotaskSvelte.unmount(instance);\n } catch(e) {}\n };\n return true;\n } catch(e) { return false; }\n }\n\n // ── Ready ─────────────────────────────────────────────\n sendToShell('bridge:ready', { version: '1.0' });\n})();\n`.trim()\n}\n"],"mappings":";AAQO,SAAS,qBAA6B;AAC3C,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAs+BP,KAAK;AACP;","names":[]}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  bridgeClientScript
3
- } from "./chunk-X72ZX6VB.js";
3
+ } from "./chunk-O73PGHAA.js";
4
4
  import {
5
5
  writeMfeServerInfo,
6
6
  writeServerInfo
@@ -0,0 +1 @@
1
+ .control-row[data-v-548da941]{margin-bottom:10px}.control-label[data-v-548da941]{display:block;font-size:11px;color:var(--text-muted);margin-bottom:4px;text-transform:uppercase;letter-spacing:.04em}.button-group[data-v-548da941]{display:flex;gap:2px}.seg-btn[data-v-548da941]{flex:1;padding:4px 6px;font-size:10px;background:var(--bg);border:1px solid var(--border);color:var(--text-muted);cursor:pointer;transition:all .1s;white-space:nowrap}.seg-btn[data-v-548da941]:first-child{border-radius:5px 0 0 5px}.seg-btn[data-v-548da941]:last-child{border-radius:0 5px 5px 0}.seg-btn[data-v-548da941]:hover{background:var(--surface-2);color:var(--text)}.seg-btn.active[data-v-548da941]{background:var(--accent);border-color:var(--accent);color:#fff}.icon-btn[data-v-548da941]{font-size:14px;padding:4px 8px}.num-input-group[data-v-548da941]{display:flex;align-items:center;gap:8px}.range-input[data-v-548da941]{flex:1;accent-color:var(--accent);height:4px}.num-value[data-v-548da941]{font-size:11px;color:var(--text);font-variant-numeric:tabular-nums;min-width:36px;text-align:right}.box-model[data-v-e06fb04c]{display:flex;justify-content:center}.margin-box[data-v-e06fb04c],.padding-box[data-v-e06fb04c]{position:relative;display:flex;align-items:center;justify-content:center}.margin-box[data-v-e06fb04c]{padding:20px 28px;background:#f9731614;border:1px dashed rgba(249,115,22,.3);border-radius:6px;min-width:220px}.padding-box[data-v-e06fb04c]{padding:18px 24px;background:#22c55e14;border:1px dashed rgba(34,197,94,.3);border-radius:4px;width:100%}.content-box[data-v-e06fb04c]{padding:8px 12px;background:var(--accent);border-radius:3px;color:#fff;font-size:10px;font-weight:600;text-align:center;white-space:nowrap}.box-label[data-v-e06fb04c]{position:absolute;font-size:9px;text-transform:uppercase;letter-spacing:.05em;opacity:.6}.margin-label[data-v-e06fb04c]{top:3px;left:6px;color:#f97316}.padding-label[data-v-e06fb04c]{top:2px;left:5px;color:#22c55e}.side-input[data-v-e06fb04c]{position:absolute;width:28px;padding:1px 2px;font-size:10px;text-align:center;background:transparent;border:1px solid transparent;border-radius:3px;color:var(--text);font-variant-numeric:tabular-nums;outline:none}.side-input[data-v-e06fb04c]:hover{border-color:var(--border);background:var(--bg)}.side-input[data-v-e06fb04c]:focus{border-color:var(--accent);background:var(--bg)}.margin-box>.side-input.top[data-v-e06fb04c]{top:2px;left:50%;transform:translate(-50%)}.margin-box>.side-input.bottom[data-v-e06fb04c]{bottom:2px;left:50%;transform:translate(-50%)}.margin-box>.side-input.left[data-v-e06fb04c]{left:2px;top:50%;transform:translateY(-50%)}.margin-box>.side-input.right[data-v-e06fb04c]{right:2px;top:50%;transform:translateY(-50%)}.padding-box>.side-input.top[data-v-e06fb04c]{top:1px;left:50%;transform:translate(-50%)}.padding-box>.side-input.bottom[data-v-e06fb04c]{bottom:1px;left:50%;transform:translate(-50%)}.padding-box>.side-input.left[data-v-e06fb04c]{left:2px;top:50%;transform:translateY(-50%)}.padding-box>.side-input.right[data-v-e06fb04c]{right:2px;top:50%;transform:translateY(-50%)}.size-row[data-v-c3ca7e31]{display:flex;gap:8px;margin-bottom:10px}.size-field[data-v-c3ca7e31]{flex:1}.control-row[data-v-c3ca7e31]{margin-bottom:10px}.control-label[data-v-c3ca7e31]{display:block;font-size:11px;color:var(--text-muted);margin-bottom:4px;text-transform:uppercase;letter-spacing:.04em}.size-input-group[data-v-c3ca7e31]{display:flex;align-items:center}.size-input[data-v-c3ca7e31]{width:100%;padding:5px 6px;background:var(--bg);border:1px solid var(--border);border-radius:5px 0 0 5px;color:var(--text);font-size:12px;font-variant-numeric:tabular-nums;outline:none}.size-input[data-v-c3ca7e31]:focus{border-color:var(--accent)}.size-unit[data-v-c3ca7e31]{padding:5px 6px;background:var(--surface-2);border:1px solid var(--border);border-left:none;border-radius:0 5px 5px 0;font-size:10px;color:var(--text-muted)}.button-group[data-v-c3ca7e31]{display:flex;gap:2px}.seg-btn[data-v-c3ca7e31]{flex:1;padding:4px;font-size:10px;background:var(--bg);border:1px solid var(--border);color:var(--text-muted);cursor:pointer}.seg-btn[data-v-c3ca7e31]:first-child{border-radius:5px 0 0 5px}.seg-btn[data-v-c3ca7e31]:last-child{border-radius:0 5px 5px 0}.seg-btn[data-v-c3ca7e31]:hover{background:var(--surface-2);color:var(--text)}.seg-btn.active[data-v-c3ca7e31]{background:var(--accent);border-color:var(--accent);color:#fff}.color-palette-picker[data-v-b0ade670]{position:relative}.picker-trigger[data-v-b0ade670]{display:flex;align-items:center;gap:6px}.color-swatch[data-v-b0ade670]{width:28px;height:28px;border:2px solid var(--border);border-radius:6px;cursor:pointer;padding:0;background:none}.color-swatch[data-v-b0ade670]::-webkit-color-swatch-wrapper{padding:0}.color-swatch[data-v-b0ade670]::-webkit-color-swatch{border:none;border-radius:4px}.palette-btn[data-v-b0ade670]{width:24px;height:24px;display:flex;align-items:center;justify-content:center;background:var(--surface-2);border:1px solid var(--border);border-radius:5px;color:var(--text-muted);cursor:pointer;transition:all .1s}.palette-btn[data-v-b0ade670]:hover,.palette-btn.active[data-v-b0ade670]{background:var(--border);color:var(--text)}.color-match[data-v-b0ade670]{font-size:9px;color:var(--accent);font-family:SF Mono,Fira Code,monospace}.palette-popover[data-v-b0ade670]{position:absolute;top:100%;left:0;margin-top:6px;width:280px;background:var(--surface);border:1px solid var(--border);border-radius:10px;box-shadow:0 8px 24px #00000080;z-index:200;overflow:hidden}.palette-tabs[data-v-b0ade670]{display:flex;border-bottom:1px solid var(--border)}.ptab[data-v-b0ade670]{flex:1;padding:6px 4px;font-size:10px;font-weight:500;background:none;border:none;border-bottom:2px solid transparent;color:var(--text-muted);cursor:pointer;transition:all .15s}.ptab[data-v-b0ade670]:hover{color:var(--text)}.ptab.active[data-v-b0ade670]{color:var(--accent);border-bottom-color:var(--accent)}.palette-body[data-v-b0ade670]{max-height:320px;overflow-y:auto;padding:8px}.color-family[data-v-b0ade670]{display:flex;align-items:center;gap:6px;margin-bottom:3px}.family-label[data-v-b0ade670]{font-size:8px;color:var(--text-muted);width:40px;flex-shrink:0;text-align:right;text-transform:lowercase}.swatch-row[data-v-b0ade670]{display:flex;gap:2px}.swatch[data-v-b0ade670]{width:18px;height:18px;border:1px solid rgba(255,255,255,.08);border-radius:3px;cursor:pointer;padding:0;transition:transform .1s}.swatch[data-v-b0ade670]:hover{transform:scale(1.25);z-index:1;border-color:var(--text)}.swatch.selected[data-v-b0ade670]{outline:2px solid var(--accent);outline-offset:1px}.swatch.large[data-v-b0ade670]{width:24px;height:24px;border-radius:4px}.var-grid[data-v-b0ade670]{display:flex;flex-direction:column;gap:2px}.var-swatch[data-v-b0ade670]{display:flex;align-items:center;gap:8px;padding:5px 6px;background:none;border:1px solid transparent;border-radius:6px;cursor:pointer;transition:all .1s}.var-swatch[data-v-b0ade670]:hover{background:var(--surface-2);border-color:var(--border)}.var-swatch.selected[data-v-b0ade670]{border-color:var(--accent)}.var-color[data-v-b0ade670]{width:18px;height:18px;border-radius:4px;flex-shrink:0;border:1px solid rgba(255,255,255,.08)}.var-name[data-v-b0ade670]{font-size:11px;color:var(--text);font-family:SF Mono,Fira Code,monospace;flex:1;text-align:left}.var-hex[data-v-b0ade670]{font-size:9px;color:var(--text-muted);font-family:SF Mono,Fira Code,monospace}.swatch-grid[data-v-b0ade670]{display:flex;flex-wrap:wrap;gap:4px}.empty-msg[data-v-b0ade670]{font-size:11px;color:var(--text-muted);text-align:center;padding:20px 0}.control-row[data-v-47449e0a]{margin-bottom:10px}.control-label[data-v-47449e0a]{display:block;font-size:11px;color:var(--text-muted);margin-bottom:4px;text-transform:uppercase;letter-spacing:.04em}.color-input-group[data-v-47449e0a]{display:flex;align-items:center;gap:8px}.color-value[data-v-47449e0a]{font-size:10px;color:var(--text-muted);font-family:SF Mono,Fira Code,monospace;overflow:hidden;text-overflow:ellipsis}.num-input-group[data-v-47449e0a]{display:flex;align-items:center;gap:8px}.range-input[data-v-47449e0a]{flex:1;accent-color:var(--accent);height:4px}.num-value[data-v-47449e0a]{font-size:11px;color:var(--text);font-variant-numeric:tabular-nums;min-width:36px;text-align:right}.button-group[data-v-47449e0a]{display:flex;gap:1px}.seg-btn[data-v-47449e0a]{flex:1;padding:4px 2px;font-size:9px;background:var(--bg);border:1px solid var(--border);color:var(--text-muted);cursor:pointer;transition:all .1s}.seg-btn[data-v-47449e0a]:first-child{border-radius:5px 0 0 5px}.seg-btn[data-v-47449e0a]:last-child{border-radius:0 5px 5px 0}.seg-btn[data-v-47449e0a]:hover{background:var(--surface-2);color:var(--text)}.seg-btn.active[data-v-47449e0a]{background:var(--accent);border-color:var(--accent);color:#fff}.mode-toolbar[data-v-90efa075]{display:flex;gap:2px;margin-left:4px;align-items:center}.mode-btn[data-v-90efa075]{width:28px;height:28px;display:flex;align-items:center;justify-content:center;border:1px solid var(--border);border-radius:5px;background:var(--surface-2);color:var(--text-muted);cursor:pointer;transition:all .1s}.mode-btn[data-v-90efa075]:hover{background:var(--border);color:var(--text)}.mode-btn.active[data-v-90efa075]{background:var(--accent);border-color:var(--accent);color:#fff}.mode-btn.mode-interact.active[data-v-90efa075]{background:#6366f1;border-color:#6366f1}.mode-btn.arrow.active[data-v-90efa075]{background:#ef4444;border-color:#ef4444}.mode-btn.draw.active[data-v-90efa075]{background:#22c55e;border-color:#22c55e}.mode-btn.mode-highlight.active[data-v-90efa075]{background:#f59e0b;border-color:#f59e0b}.mode-sep[data-v-90efa075]{width:1px;height:18px;background:var(--border);margin:0 2px;align-self:center}.context-menu[data-v-b4795b28]{position:fixed;z-index:20000;min-width:160px;background:var(--surface);border:1px solid var(--border);border-radius:8px;box-shadow:0 8px 24px #00000080;padding:4px;overflow:hidden}.menu-item[data-v-b4795b28]{display:flex;align-items:center;justify-content:space-between;width:100%;padding:6px 12px;background:none;border:none;border-radius:5px;color:var(--text);font-size:12px;cursor:pointer;transition:background .1s}.menu-item[data-v-b4795b28]:hover:not(.disabled){background:var(--surface-2)}.menu-item.disabled[data-v-b4795b28]{color:var(--text-muted);cursor:not-allowed;opacity:.5}.item-shortcut[data-v-b4795b28]{font-size:10px;color:var(--text-muted);font-family:SF Mono,monospace}.separator[data-v-b4795b28]{height:1px;background:var(--border);margin:4px 8px}.pin[data-v-006ef709]{position:fixed;z-index:10003;width:22px;height:22px;border-radius:50%;background:#3b82f6;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;transform:translate(-11px,-11px);box-shadow:0 2px 6px #0000004d;transition:all .15s;border:2px solid white}.pin[data-v-006ef709]:hover{transform:translate(-11px,-11px) scale(1.2)}.pin.selected[data-v-006ef709]{background:#2563eb;box-shadow:0 0 0 3px #3b82f64d,0 2px 6px #0000004d}.pin.has-action[data-v-006ef709]{background:#a855f7}.pin.has-note.has-action[data-v-006ef709]{background:#7c3aed}.pin-number[data-v-006ef709]{font-size:10px;font-weight:700}.pin-remove[data-v-006ef709]{position:absolute;top:-6px;right:-6px;width:14px;height:14px;border-radius:50%;background:var(--danger, #ef4444);color:#fff;border:1px solid white;font-size:10px;line-height:1;cursor:pointer;display:none;align-items:center;justify-content:center;padding:0}.pin:hover .pin-remove[data-v-006ef709]{display:flex}.arrow-svg[data-v-1d2c9ec9]{position:fixed;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:10003;pointer-events:none}.arrow-path[data-v-1d2c9ec9]{pointer-events:stroke;cursor:pointer}.arrow-label[data-v-1d2c9ec9]{font-size:10px;font-weight:600;fill:#ef4444;pointer-events:none;paint-order:stroke;stroke:#00000080;stroke-width:3px}.arrow-delete[data-v-1d2c9ec9]{cursor:pointer;pointer-events:auto}.section-preview[data-v-d10f1f9f]{position:fixed;z-index:10003;border:2px dashed #22c55e;background:#22c55e0f;border-radius:6px;pointer-events:none}.drawn-section[data-v-d10f1f9f]{position:fixed;z-index:10003;border:2px dashed #22c55e;background:#22c55e0a;border-radius:6px;display:flex;flex-direction:column;overflow:hidden;cursor:pointer;transition:border-color .15s}.drawn-section.selected[data-v-d10f1f9f]{border-color:#16a34a;box-shadow:0 0 0 2px #22c55e4d}.section-header[data-v-d10f1f9f]{display:flex;align-items:center;gap:6px;padding:4px 8px;background:#22c55e1a;border-bottom:1px solid rgba(34,197,94,.15)}.section-badge[data-v-d10f1f9f]{font-size:9px;font-weight:700;color:#16a34a}.section-placement[data-v-d10f1f9f]{font-size:8px;color:#22c55e;background:#22c55e1a;padding:1px 4px;border-radius:3px}.section-delete[data-v-d10f1f9f]{margin-left:auto;width:16px;height:16px;border:none;background:none;color:#22c55e;font-size:14px;cursor:pointer;padding:0;display:flex;align-items:center;justify-content:center}.section-delete[data-v-d10f1f9f]:hover{color:#ef4444}.section-prompt[data-v-d10f1f9f]{flex:1;padding:6px 8px;border:none;background:transparent;color:#166534;font-size:11px;line-height:1.4;resize:none;outline:none;font-family:inherit;min-height:40px}.section-prompt[data-v-d10f1f9f]::placeholder{color:#16653466}.section-dims[data-v-d10f1f9f]{padding:2px 8px 4px;font-size:8px;color:#16653466;text-align:right}.notes-tab[data-v-f9630085]{display:flex;flex-direction:column;gap:14px}.section-label[data-v-f9630085]{display:block;font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted);margin-bottom:6px}.action-grid[data-v-f9630085]{display:flex;flex-wrap:wrap;gap:4px}.action-btn[data-v-f9630085]{padding:4px 10px;font-size:11px;font-weight:500;background:var(--surface-2);border:1px solid var(--border);border-radius:5px;color:var(--text);cursor:pointer;transition:all .1s}.action-btn[data-v-f9630085]:hover{background:var(--border);color:var(--accent);border-color:var(--accent)}.note-input[data-v-f9630085]{width:100%;padding:8px;font-size:12px;background:var(--bg);border:1px solid var(--border);border-radius:6px;color:var(--text);resize:vertical;outline:none;font-family:inherit}.note-input[data-v-f9630085]:focus{border-color:var(--accent)}.submit-btn[data-v-f9630085]{margin-top:4px;padding:5px 12px;font-size:11px;font-weight:600;background:var(--accent);color:#fff;border:none;border-radius:5px;cursor:pointer;transition:opacity .1s}.submit-btn[data-v-f9630085]:disabled{opacity:.4;cursor:not-allowed}.submit-btn[data-v-f9630085]:hover:not(:disabled){opacity:.9}.task-toggles[data-v-f9630085]{display:flex;gap:10px;margin-top:4px}.note-actions[data-v-f9630085]{display:flex;align-items:center;gap:8px;margin-top:4px}.history-toggle[data-v-f9630085]{display:flex;align-items:center;gap:4px;font-size:10px;color:var(--text-muted);cursor:pointer;white-space:nowrap}.history-toggle input[data-v-f9630085]{margin:0}.history-toggle span[data-v-f9630085]{-webkit-user-select:none;user-select:none}.pin-item[data-v-f9630085]{display:flex;align-items:flex-start;gap:8px;padding:6px 8px;border-radius:5px;cursor:pointer;transition:background .1s}.pin-item[data-v-f9630085]:hover{background:var(--surface-2)}.pin-item.selected[data-v-f9630085]{background:var(--surface-2);border:1px solid var(--accent)}.pin-badge[data-v-f9630085]{width:18px;height:18px;border-radius:50%;background:#3b82f6;color:#fff;font-size:9px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.pin-badge.action[data-v-f9630085]{background:#a855f7}.pin-content[data-v-f9630085]{flex:1;min-width:0}.pin-file[data-v-f9630085]{font-size:10px;color:var(--accent);display:block;margin-bottom:2px}.pin-action[data-v-f9630085]{font-size:10px;color:#a855f7;font-weight:600;display:block}.pin-note[data-v-f9630085]{font-size:11px;color:var(--text);display:block;word-break:break-word}.pin-empty[data-v-f9630085]{font-size:10px;color:var(--text-muted);font-style:italic}.pin-delete[data-v-f9630085]{width:16px;height:16px;border-radius:50%;background:none;border:none;color:var(--text-muted);cursor:pointer;font-size:12px;display:none;align-items:center;justify-content:center;padding:0}.pin-item:hover .pin-delete[data-v-f9630085]{display:flex}.pin-delete[data-v-f9630085]:hover{color:var(--danger, #ef4444)}.empty-hint[data-v-f9630085]{font-size:11px;color:var(--text-muted);text-align:center;padding:12px 0}.task-review[data-v-f9630085]{border-top:1px solid var(--border, #2a2a2a);padding-top:10px}.task-item[data-v-f9630085]{padding:6px 8px;border-radius:5px;margin-bottom:4px;border:1px solid var(--border, #2a2a2a)}.task-item.review[data-v-f9630085]{border-color:#f59e0b;background:#f59e0b0d}.task-item.denied[data-v-f9630085]{border-color:#ef4444;background:#ef44440d}.task-item.pending[data-v-f9630085]{border-color:var(--border, #2a2a2a)}.task-header[data-v-f9630085]{display:flex;align-items:center;gap:6px;margin-bottom:3px}.task-status-badge[data-v-f9630085]{font-size:8px;font-weight:700;padding:1px 5px;border-radius:3px;text-transform:uppercase}.task-status-badge.pending[data-v-f9630085]{background:#71717a33;color:#71717a}.task-status-badge.review[data-v-f9630085]{background:#f59e0b33;color:#f59e0b}.task-status-badge.denied[data-v-f9630085]{background:#ef444433;color:#ef4444}.task-desc[data-v-f9630085]{font-size:11px;color:var(--text, #e4e4e7)}.task-file[data-v-f9630085]{font-size:9px;color:var(--text-muted, #71717a);display:block;margin-bottom:3px}.task-feedback[data-v-f9630085]{font-size:10px;color:#ef4444;font-style:italic;margin-bottom:3px}.task-actions[data-v-f9630085]{display:flex;gap:4px;align-items:center;margin-top:4px}.task-accept[data-v-f9630085]{padding:4px 10px;font-size:10px;font-weight:600;background:#22c55e26;color:#22c55e;border:none;border-radius:4px;cursor:pointer;transition:all .12s}.task-accept[data-v-f9630085]:hover{background:#22c55e;color:#fff}.task-deny[data-v-f9630085]{padding:4px 10px;font-size:10px;font-weight:600;background:#ef44441f;color:#ef4444;border:none;border-radius:4px;cursor:pointer;transition:all .12s}.task-deny[data-v-f9630085]:hover{background:#ef4444;color:#fff}.deny-input[data-v-f9630085]{flex:1;padding:2px 6px;font-size:10px;background:var(--bg, #0a0a0a);border:1px solid var(--border);border-radius:4px;color:var(--text);outline:none}.task-cancel[data-v-f9630085]{width:18px;height:18px;border:none;background:none;color:var(--text-muted, #71717a);font-size:14px;cursor:pointer;padding:0;display:flex;align-items:center;justify-content:center;margin-left:auto;border-radius:3px}.task-cancel[data-v-f9630085]:hover{color:#ef4444;background:#ef44441a}.highlight-prompt[data-v-b4a28a2c]{position:fixed;z-index:10005;background:var(--surface, #141414);border:1px solid #f59e0b;border-radius:8px;box-shadow:0 8px 24px #00000080;padding:8px;width:280px}.prompt-header[data-v-b4a28a2c]{margin-bottom:6px}.prompt-text-preview[data-v-b4a28a2c]{font-size:11px;color:#f59e0b;font-style:italic;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.prompt-input[data-v-b4a28a2c]{width:100%;padding:6px 8px;background:var(--bg, #0a0a0a);border:1px solid var(--border, #2a2a2a);border-radius:5px;color:var(--text, #e4e4e7);font-size:12px;outline:none}.prompt-input[data-v-b4a28a2c]:focus{border-color:#f59e0b}.prompt-hint[data-v-b4a28a2c]{font-size:9px;color:var(--text-muted, #71717a);margin-top:4px}.text-highlight-card[data-v-b4a28a2c]{position:relative;margin:4px 0;padding:6px 8px;background:#f59e0b14;border:1px solid rgba(245,158,11,.2);border-radius:6px;cursor:pointer}.text-highlight-card.selected[data-v-b4a28a2c]{border-color:#f59e0b}.hl-header[data-v-b4a28a2c]{display:flex;align-items:center;gap:6px;margin-bottom:3px}.hl-badge[data-v-b4a28a2c]{font-size:9px;font-weight:700;color:#f59e0b}.hl-file[data-v-b4a28a2c]{font-size:9px;color:var(--text-muted, #71717a)}.hl-delete[data-v-b4a28a2c]{margin-left:auto;width:14px;height:14px;border:none;background:none;color:var(--text-muted);font-size:12px;cursor:pointer;padding:0;display:none}.text-highlight-card:hover .hl-delete[data-v-b4a28a2c]{display:block}.hl-text[data-v-b4a28a2c]{font-size:11px;color:#f59e0b;font-style:italic;margin-bottom:2px}.hl-prompt[data-v-b4a28a2c]{font-size:11px;color:var(--text, #e4e4e7)}.hl-prompt-edit[data-v-b4a28a2c]{width:100%;margin-top:4px;padding:4px 6px;background:var(--bg, #0a0a0a);border:1px solid var(--border, #2a2a2a);border-radius:4px;color:var(--text);font-size:11px;outline:none}.hl-prompt-edit[data-v-b4a28a2c]:focus{border-color:#f59e0b}.layout-outline[data-v-ed4fb8a3]{position:fixed;pointer-events:none;z-index:9998;border-radius:3px}.layout-outline.flex[data-v-ed4fb8a3]{border:1.5px dashed rgba(168,85,247,.4);background:#a855f708}.layout-outline.grid[data-v-ed4fb8a3]{border:1.5px dashed rgba(34,197,94,.4);background:#22c55e08}.layout-label[data-v-ed4fb8a3]{position:absolute;top:-16px;left:4px;font-size:9px;font-weight:600;padding:1px 5px;border-radius:3px;white-space:nowrap;letter-spacing:.03em}.flex .layout-label[data-v-ed4fb8a3]{background:#a855f726;color:#a855f7}.grid .layout-label[data-v-ed4fb8a3]{background:#22c55e26;color:#22c55e}.grid-line[data-v-ed4fb8a3]{position:fixed;z-index:9999;pointer-events:auto}.grid-line.col[data-v-ed4fb8a3]{width:6px;margin-left:-3px;cursor:col-resize;background:transparent}.grid-line.col[data-v-ed4fb8a3]:hover,.grid-line.col[data-v-ed4fb8a3]:active{background:#22c55e4d}.grid-line.row[data-v-ed4fb8a3]{height:6px;margin-top:-3px;cursor:row-resize;background:transparent}.grid-line.row[data-v-ed4fb8a3]:hover,.grid-line.row[data-v-ed4fb8a3]:active{background:#22c55e4d}.add-track-btn[data-v-ed4fb8a3],.add-child-btn[data-v-ed4fb8a3]{position:fixed;z-index:9999;pointer-events:auto;border:none;border-radius:4px;font-size:9px;font-weight:700;padding:3px 6px;cursor:pointer;opacity:.7;transition:all .15s;white-space:nowrap}.add-track-btn[data-v-ed4fb8a3]:hover,.add-child-btn[data-v-ed4fb8a3]:hover{opacity:1;transform:scale(1.1)}.add-track-btn[data-v-ed4fb8a3]{background:#22c55e26;color:#22c55e;border:1px solid rgba(34,197,94,.3)}.add-track-btn[data-v-ed4fb8a3]:hover{background:#22c55e4d}.add-child-btn[data-v-ed4fb8a3]{background:#a855f726;color:#a855f7;border:1px solid rgba(168,85,247,.3);width:22px;height:22px;display:flex;align-items:center;justify-content:center;font-size:14px;padding:0}.add-child-btn[data-v-ed4fb8a3]:hover{background:#a855f74d}.theme-page[data-v-67b64182]{display:flex;flex-direction:column;height:100%;overflow:hidden}.theme-header[data-v-67b64182]{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;border-bottom:1px solid var(--border);flex-shrink:0}.theme-title[data-v-67b64182]{font-size:13px;font-weight:600;color:var(--text)}.theme-actions[data-v-67b64182]{display:flex;align-items:center;gap:8px}.theme-change-count[data-v-67b64182]{font-size:11px;color:var(--text-muted)}.theme-btn[data-v-67b64182]{padding:4px 12px;font-size:11px;font-weight:600;border:none;border-radius:5px;cursor:pointer}.theme-btn.commit[data-v-67b64182]{background:var(--accent);color:#fff}.theme-btn.commit[data-v-67b64182]:hover{opacity:.9}.theme-btn.commit[data-v-67b64182]:disabled{opacity:.4;cursor:not-allowed}.theme-btn.discard[data-v-67b64182]{background:var(--surface-2);color:var(--text-muted);border:1px solid var(--border)}.theme-btn.discard[data-v-67b64182]:hover{color:var(--text);background:var(--border)}.theme-btn.small[data-v-67b64182]{padding:3px 10px;font-size:10px}.theme-empty[data-v-67b64182]{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;color:var(--text-muted);text-align:center;padding:24px}.theme-empty p[data-v-67b64182]{font-size:13px}.theme-empty-hint[data-v-67b64182]{font-size:11px;opacity:.7}.theme-empty code[data-v-67b64182]{background:#3b82f626;padding:1px 6px;border-radius:3px;font-weight:600;color:#60a5fa}.theme-tabs[data-v-67b64182]{display:flex;border-bottom:1px solid var(--border);flex-shrink:0}.theme-tab[data-v-67b64182]{flex:1;padding:8px 4px;font-size:11px;font-weight:500;background:none;border:none;border-bottom:2px solid transparent;color:var(--text-muted);cursor:pointer;transition:all .15s}.theme-tab[data-v-67b64182]:hover{color:var(--text)}.theme-tab.active[data-v-67b64182]{color:var(--accent);border-bottom-color:var(--accent)}.theme-tab-badge[data-v-67b64182]{display:inline-flex;align-items:center;justify-content:center;min-width:14px;height:14px;padding:0 3px;font-size:9px;font-weight:700;background:var(--accent);color:#fff;border-radius:7px;margin-left:3px}.theme-content[data-v-67b64182]{flex:1;overflow-y:auto;padding:12px}.theme-section[data-v-67b64182]{display:flex;flex-direction:column;gap:2px}.theme-section-empty[data-v-67b64182]{padding:16px 0;text-align:center;font-size:11px;color:var(--text-muted);opacity:.6}.section-subtitle[data-v-67b64182]{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--text-muted);padding:6px 0 4px}.token-row[data-v-67b64182]{display:flex;align-items:center;justify-content:space-between;padding:6px 8px;border-radius:6px;gap:8px;transition:background .1s}.token-row[data-v-67b64182]:hover{background:var(--surface-2)}.token-row.new[data-v-67b64182]{background:#3b82f60f}.token-info[data-v-67b64182]{display:flex;flex-direction:column;gap:1px;min-width:0;flex-shrink:1}.token-role[data-v-67b64182]{font-size:12px;font-weight:500;color:var(--text);white-space:nowrap}.token-role.edited[data-v-67b64182]{color:var(--accent)}.token-role.new-badge[data-v-67b64182]{color:#22c55e;font-weight:600}.token-source[data-v-67b64182]{font-size:9px;color:var(--text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:160px}.token-controls[data-v-67b64182]{display:flex;align-items:center;gap:6px;flex-shrink:0}.token-value-input[data-v-67b64182]{width:80px;padding:3px 6px;font-size:11px;font-family:monospace;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--text);outline:none}.token-value-input[data-v-67b64182]:focus{border-color:var(--accent)}.token-value-input.wide[data-v-67b64182]{width:160px}.token-value-input.color-hex[data-v-67b64182]{width:72px}.token-value-ro[data-v-67b64182]{font-size:11px;color:var(--text-muted)}.token-remove[data-v-67b64182]{width:18px;height:18px;border:none;background:none;color:var(--text-muted);font-size:14px;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:3px}.token-remove[data-v-67b64182]:hover{color:#ef4444;background:#ef44441a}.no-preview-badge[data-v-67b64182]{font-size:8px;color:var(--text-muted);opacity:.6;white-space:nowrap}.color-swatch-wrapper[data-v-67b64182]{flex-shrink:0}.color-swatch-inline[data-v-67b64182]{width:20px;height:20px;border-radius:4px;border:1px solid var(--border);flex-shrink:0}.font-size-preview[data-v-67b64182]{color:var(--text);line-height:1;white-space:nowrap}.weight-chips[data-v-67b64182]{display:flex;flex-wrap:wrap;gap:4px;padding:4px 0}.weight-chip[data-v-67b64182]{font-size:10px;padding:2px 8px;background:var(--surface-2);border:1px solid var(--border);border-radius:4px;color:var(--text-muted)}.spacing-preview[data-v-67b64182]{width:60px;height:12px;background:var(--surface-2);border-radius:2px;overflow:hidden}.spacing-bar[data-v-67b64182]{height:100%;background:var(--accent);border-radius:2px;max-width:100%;transition:width .15s}.radius-preview[data-v-67b64182]{width:24px;height:24px;background:var(--accent);transition:border-radius .15s}.add-token-btn[data-v-67b64182]{padding:6px;margin-top:4px;font-size:11px;color:var(--text-muted);background:none;border:1px dashed var(--border);border-radius:6px;cursor:pointer;transition:all .1s}.add-token-btn[data-v-67b64182]:hover{color:var(--accent);border-color:var(--accent)}.add-token-form[data-v-67b64182]{display:flex;flex-direction:column;gap:4px;padding:8px;margin-top:4px;background:var(--surface-2);border:1px solid var(--border);border-radius:6px}.add-input[data-v-67b64182]{padding:4px 8px;font-size:11px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--text);outline:none;font-family:inherit}.add-input[data-v-67b64182]:focus{border-color:var(--accent)}.add-actions[data-v-67b64182]{display:flex;gap:4px;margin-top:2px}.library-card[data-v-67b64182]{display:flex;align-items:center;gap:8px;padding:8px 10px;background:var(--surface-2);border:1px solid var(--border);border-radius:6px}.library-name[data-v-67b64182]{font-size:12px;font-weight:600;color:var(--text)}.library-version[data-v-67b64182]{font-size:10px;color:var(--text-muted)}.styling-chip[data-v-67b64182]{font-size:9px;padding:1px 6px;background:#3b82f61f;color:#60a5fa;border-radius:3px;font-weight:600}.library-components[data-v-67b64182]{display:flex;flex-wrap:wrap;gap:4px;padding:6px 0}.component-chip[data-v-67b64182]{font-size:10px;padding:2px 8px;background:var(--surface-2);border:1px solid var(--border);border-radius:4px;color:var(--text-muted);font-family:monospace}.report-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50000;display:flex;justify-content:flex-end}.report-backdrop{position:absolute;top:0;right:0;bottom:0;left:0;background:#0006}.report-drawer{position:relative;width:min(720px,80vw);height:100%;background:#0d0d0d;border-left:1px solid var(--border);display:flex;flex-direction:column;animation:slide-in .15s ease-out}@keyframes slide-in{0%{transform:translate(100%)}to{transform:translate(0)}}.report-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border);background:var(--surface);flex-shrink:0}.report-title{display:flex;align-items:center;gap:10px;font-size:14px;font-weight:600;color:var(--text)}.report-badge{font-size:11px;font-weight:500;color:var(--text-muted);background:var(--surface-2);padding:2px 8px;border-radius:4px;border:1px solid var(--border)}.report-controls{display:flex;align-items:center;gap:8px}.format-toggle{display:flex;border:1px solid var(--border);border-radius:6px;overflow:hidden}.fmt-btn{padding:4px 12px;font-size:11px;font-weight:600;color:var(--text-muted);background:transparent;border:none;cursor:pointer;transition:all .1s}.fmt-btn.active{background:var(--surface-2);color:var(--text)}.fmt-btn:hover:not(.active){color:var(--text)}.copy-btn{display:flex;align-items:center;gap:5px;padding:5px 12px;font-size:12px;font-weight:500;color:var(--text);background:var(--surface-2);border:1px solid var(--border);border-radius:6px;cursor:pointer;transition:all .1s}.copy-btn:hover{background:var(--border)}.copy-btn:disabled{opacity:.4;cursor:default}.close-btn{display:flex;align-items:center;justify-content:center;width:28px;height:28px;color:var(--text-muted);background:transparent;border:none;border-radius:6px;cursor:pointer;transition:all .1s}.close-btn:hover{background:var(--surface-2);color:var(--text)}.report-body{flex:1;overflow:auto}.report-code{margin:0;padding:20px;font-size:12px;line-height:1.6;-moz-tab-size:2;tab-size:2;overflow:auto;background:transparent}.report-code code{font-family:SF Mono,Fira Code,Cascadia Code,JetBrains Mono,Consolas,monospace}.report-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--text-muted);font-size:14px}.report-empty-hint{font-size:12px;margin-top:8px;opacity:.6}.report-code .token.property{color:#7dd3fc}.report-code .token.string{color:#86efac}.report-code .token.number{color:#fbbf24}.report-code .token.boolean{color:#c084fc}.report-code .token.null{color:#f87171}.report-code .token.operator{color:#71717a}.report-code .token.punctuation{color:#52525b}.report-code .token.key,.report-code .token.atrule,.report-code .token.tag{color:#7dd3fc}.report-code .token.scalar{color:#86efac}.report-code .token.important{color:#fbbf24}.viewport-selector[data-v-0f350755]{position:relative}.vp-trigger[data-v-0f350755]{display:flex;align-items:center;gap:4px;padding:3px 8px;border:1px solid var(--border);border-radius:5px;background:var(--surface-2);color:var(--text-muted);font-size:11px;cursor:pointer;transition:all .1s;white-space:nowrap}.vp-trigger[data-v-0f350755]:hover{background:var(--border);color:var(--text)}.vp-label[data-v-0f350755]{font-family:monospace;font-size:11px}.vp-dropdown[data-v-0f350755]{position:absolute;top:100%;left:50%;transform:translate(-50%);margin-top:4px;min-width:220px;background:var(--surface);border:1px solid var(--border);border-radius:8px;box-shadow:0 8px 24px #0006;padding:4px;z-index:100;max-height:400px;overflow-y:auto}.vp-group[data-v-0f350755]{margin-top:2px}.vp-group-title[data-v-0f350755]{padding:4px 8px 2px;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--text-muted);opacity:.6}.vp-item[data-v-0f350755]{display:flex;align-items:center;justify-content:space-between;width:100%;padding:5px 8px;border:none;border-radius:4px;background:transparent;color:var(--text);font-size:11px;cursor:pointer;transition:background .1s}.vp-item[data-v-0f350755]:hover{background:var(--surface-2)}.vp-item.active[data-v-0f350755]{background:var(--accent);color:#fff}.vp-item-label[data-v-0f350755]{flex:1;text-align:left}.vp-item-dim[data-v-0f350755]{font-family:monospace;font-size:10px;color:var(--text-muted)}.vp-item.active .vp-item-dim[data-v-0f350755]{color:#ffffffb3}.vp-custom[data-v-0f350755]{margin-top:2px;border-top:1px solid var(--border);padding-top:4px}.vp-custom-row[data-v-0f350755]{display:flex;align-items:center;gap:4px;padding:4px 8px}.vp-input[data-v-0f350755]{width:56px;padding:3px 6px;border:1px solid var(--border);border-radius:4px;background:var(--surface-2);color:var(--text);font-size:11px;font-family:monospace;text-align:center}.vp-input[data-v-0f350755]:focus{outline:none;border-color:var(--accent)}.vp-x[data-v-0f350755]{color:var(--text-muted);font-size:10px}.vp-apply[data-v-0f350755]{padding:3px 8px;border:1px solid var(--accent);border-radius:4px;background:var(--accent);color:#fff;font-size:10px;font-weight:600;cursor:pointer}.vp-apply[data-v-0f350755]:hover{opacity:.9}.vp-rotate[data-v-0f350755]{margin-top:2px;border-top:1px solid var(--border);padding-top:4px;gap:6px}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}:root{--bg: #0a0a0a;--surface: #141414;--surface-2: #1e1e1e;--border: #2a2a2a;--text: #e4e4e7;--text-muted: #71717a;--accent: #3b82f6;--danger: #ef4444}html,body,#app{height:100%;overflow:hidden;background:var(--bg);color:var(--text);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:13px}.annotask-shell{display:flex;flex-direction:column;height:100%}.toolbar{display:flex;align-items:center;justify-content:space-between;height:40px;padding:0 12px;background:var(--surface);border-bottom:1px solid var(--border);flex-shrink:0}.toolbar-left,.toolbar-right{display:flex;align-items:center;gap:8px}.logo{height:20px;width:auto;margin-right:12px;color:var(--accent)}.tool-btn{display:flex;align-items:center;gap:4px;padding:4px 10px;border:1px solid var(--border);border-radius:6px;background:var(--surface-2);color:var(--text);font-size:12px;cursor:pointer}.tool-btn:hover{background:var(--border)}.tool-btn:disabled{opacity:.4;cursor:not-allowed}.tool-btn.active{background:var(--accent);border-color:var(--accent);color:#fff}.tool-btn.danger{color:var(--danger)}.panel-toggle{display:flex;border:1px solid var(--border);border-radius:6px;overflow:hidden}.toggle-btn{display:flex;align-items:center;gap:3px;padding:3px 8px;border:none;background:var(--surface-2);color:var(--text-muted);font-size:11px;cursor:pointer;transition:all .1s}.toggle-btn:first-child{border-right:1px solid var(--border)}.toggle-btn:hover{background:var(--border);color:var(--text)}.toggle-btn.active{background:var(--accent);color:#fff}.toggle-badge{display:inline-flex;align-items:center;justify-content:center;min-width:14px;height:14px;padding:0 3px;font-size:8px;font-weight:700;background:#ffffff40;color:#fff;border-radius:7px}.toggle-btn:not(.active) .toggle-badge{background:var(--accent);color:#fff}.view-toggle{display:flex;border:1px solid var(--border);border-radius:6px;overflow:hidden;margin-right:8px}.theme-panel{width:440px;background:var(--surface);border-left:1px solid var(--border);display:flex;flex-direction:column;flex-shrink:0;overflow:hidden}.visibility-toggles{display:flex;gap:1px;margin-right:4px}.vis-btn{width:20px;height:20px;border:none;border-radius:3px;background:var(--surface-2);color:var(--text-muted);font-size:9px;font-weight:700;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .1s}.vis-btn:hover{background:var(--border);color:var(--text)}.vis-btn.off{opacity:.3;text-decoration:line-through}.change-count{font-size:11px;color:var(--text-muted)}.warning-banner{padding:8px 16px;background:#eab3081a;border-bottom:1px solid rgba(234,179,8,.3);color:#eab308;font-size:12px}.warning-banner code{background:#eab30826;padding:1px 4px;border-radius:3px}.setup-banner{padding:8px 16px;background:#3b82f614;border-bottom:1px solid rgba(59,130,246,.2);color:#60a5fa;font-size:12px}.setup-banner code{background:#3b82f626;padding:1px 6px;border-radius:3px;font-weight:600}.main{display:flex;flex:1;overflow:hidden}.toolbar-center{display:flex;align-items:center;gap:8px}.route-indicator{font-size:11px;color:var(--text-muted);background:var(--surface-2);padding:2px 8px;border-radius:4px;border:1px solid var(--border)}.canvas-area{flex:1;position:relative;overflow:hidden}.canvas-area.viewport-active{display:flex;align-items:flex-start;justify-content:center;overflow:auto;background:#0a0a0a;padding:16px}.app-iframe{width:100%;height:100%;border:none}.canvas-area.viewport-active .app-iframe{flex-shrink:0;border-radius:6px;box-shadow:0 0 0 1px var(--border),0 4px 24px #00000080}.drawing-shield{position:absolute;top:0;right:0;bottom:0;left:0;z-index:9999}.drawing-shield.arrow,.drawing-shield.draw{cursor:crosshair}.highlight{position:fixed;pointer-events:none;z-index:10000;border-radius:2px}.highlight.hover{background:#3b82f61a;border:1.5px solid rgba(59,130,246,.5)}.highlight.group{background:#a855f714;border:1.5px dashed rgba(168,85,247,.4)}.highlight.select{background:#3b82f614;border:2px solid var(--accent)}.hover-label,.select-label{position:absolute;bottom:100%;left:-1px;display:flex;align-items:center;gap:6px;padding:2px 8px;font-size:11px;font-weight:500;white-space:nowrap;border-radius:4px 4px 0 0}.hover-label{background:var(--accent);color:#fff}.hover-tag{font-family:monospace}.hover-comp{opacity:.7}.select-label{background:var(--accent);color:#fff;font-family:monospace;font-size:10px}.panel{width:320px;background:var(--surface);border-left:1px solid var(--border);display:flex;flex-direction:column;flex-shrink:0;overflow:hidden}.panel.empty{justify-content:center;align-items:center}.panel-source{padding:10px 14px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:8px;flex-wrap:wrap}.source-path{font-size:12px;color:var(--accent);word-break:break-all;font-family:monospace}.component-badge{font-size:10px;padding:2px 6px;background:var(--surface-2);border:1px solid var(--border);border-radius:4px;color:var(--text-muted);white-space:nowrap}.role-badge{font-size:9px;padding:1px 5px;border-radius:3px;font-weight:600;text-transform:uppercase;letter-spacing:.03em}.role-badge.container{background:#22c55e26;color:#22c55e}.role-badge.content{background:#3b82f626;color:#3b82f6}.role-badge.component{background:#a855f726;color:#a855f7}.panel-group-bar{display:flex;align-items:center;justify-content:space-between;padding:6px 14px;border-bottom:1px solid var(--border);background:#a855f70f}.group-summary{font-size:11px;color:#a855f7}.group-toggle{display:flex;align-items:center;gap:5px;cursor:pointer}.group-toggle input{accent-color:#a855f7;width:14px;height:14px;cursor:pointer}.toggle-label{font-size:11px;color:var(--text-muted)}.panel-tabs{display:flex;border-bottom:1px solid var(--border);flex-shrink:0}.tab{flex:1;padding:8px 4px;font-size:11px;font-weight:500;background:none;border:none;border-bottom:2px solid transparent;color:var(--text-muted);cursor:pointer;transition:all .15s}.tab:hover{color:var(--text)}.tab.active{color:var(--accent);border-bottom-color:var(--accent)}.tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:14px;height:14px;padding:0 3px;font-size:9px;font-weight:700;background:var(--accent);color:#fff;border-radius:7px;margin-left:3px}.tab-content{flex:1;overflow-y:auto;padding:14px}.class-editor{width:100%;padding:8px;background:var(--bg);border:1px solid var(--border);border-radius:6px;color:var(--text);font-family:monospace;font-size:12px;resize:vertical;outline:none}.class-editor:focus{border-color:var(--accent)}.hint{font-size:10px;color:var(--text-muted);margin-top:4px}.empty-content{text-align:center;color:var(--text-muted)}.empty-content p{margin-top:8px}.empty-hint{font-size:11px;opacity:.6}.changes-footer{border-top:1px solid var(--border);flex-shrink:0;padding:8px 14px}.changes-list{max-height:120px;overflow-y:auto;margin-bottom:6px}.change-item{display:flex;align-items:center;gap:6px;padding:2px 0;font-size:11px}.change-prop{color:var(--text-muted);font-family:monospace}.change-arrow{color:var(--text-muted);font-size:10px}.change-val{color:#22c55e;font-family:monospace}.changes-actions{display:flex;align-items:center;gap:6px}.changes-count{font-size:10px;color:var(--text-muted);flex:1}.changes-commit{padding:4px 12px;font-size:11px;font-weight:600;background:var(--accent);color:#fff;border:none;border-radius:5px;cursor:pointer}.changes-commit:hover{opacity:.9}.changes-discard{padding:4px 12px;font-size:11px;background:var(--surface-2);color:var(--text-muted);border:1px solid var(--border);border-radius:5px;cursor:pointer}.changes-discard:hover{background:var(--border);color:var(--text)}.task-card{padding:8px;border:1px solid var(--border);border-radius:6px;margin-bottom:6px}.task-card.review{border-color:#f59e0b}.task-card.denied{border-color:#ef4444}.task-card-header{display:flex;align-items:center;gap:6px;margin-bottom:3px}.task-status-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}.task-status-dot.pending{background:#71717a}.task-status-dot.review{background:#f59e0b}.task-status-dot.denied{background:#ef4444}.task-card-desc{font-size:11px;color:var(--text);flex:1}.task-card-close{width:16px;height:16px;border:none;background:none;color:var(--text-muted);font-size:13px;cursor:pointer;padding:0;display:flex;align-items:center;justify-content:center;border-radius:3px}.task-card-close:hover{color:#ef4444;background:#ef44441a}.task-card-meta{display:flex;align-items:center;gap:6px}.task-card-file{font-size:9px;color:var(--text-muted)}.task-route-badge{font-size:8px;padding:1px 5px;background:#3b82f61f;color:#60a5fa;border-radius:3px;font-weight:600}.task-card-feedback{font-size:10px;color:#ef4444;font-style:italic;margin-top:3px}.new-task-toggle{margin-left:auto;padding:2px 8px;font-size:10px;font-weight:600;background:var(--accent);color:#fff;border:none;border-radius:4px;cursor:pointer}.new-task-toggle:hover{opacity:.9}.new-task-form{padding:8px 14px;border-bottom:1px solid var(--border)}.new-task-input{width:100%;padding:6px 8px;font-size:12px;background:var(--bg);border:1px solid var(--border);border-radius:5px;color:var(--text);resize:none;outline:none;font-family:inherit}.new-task-input:focus{border-color:var(--accent)}.new-task-actions{display:flex;gap:4px;margin-top:4px}.submit-btn{padding:4px 12px;font-size:11px;font-weight:600;background:var(--accent);color:#fff;border:none;border-radius:4px;cursor:pointer}.submit-btn:disabled{opacity:.4;cursor:not-allowed}.cancel-btn{padding:4px 12px;font-size:11px;background:var(--surface-2);color:var(--text-muted);border:1px solid var(--border);border-radius:4px;cursor:pointer}.task-card-actions{display:flex;gap:4px;margin-top:6px;align-items:center}.deny-feedback-input{flex:1;padding:4px 8px;font-size:10px;background:var(--bg);border:1px solid #ef4444;border-radius:4px;color:var(--text);outline:none}.deny-feedback-input:focus{box-shadow:0 0 0 2px #ef444433}.task-card-actions .task-accept,.task-card-actions .task-deny{flex:1;padding:5px 0;font-size:11px;font-weight:600;border:none;border-radius:5px;cursor:pointer;transition:all .12s;display:flex;align-items:center;justify-content:center;gap:4px}.task-card-actions .task-accept{background:#22c55e26;color:#22c55e}.task-card-actions .task-accept:hover{background:#22c55e;color:#fff}.task-card-actions .task-deny{background:#ef44441f;color:#ef4444}.task-card-actions .task-deny:hover{background:#ef4444;color:#fff}.pending-task-panel{padding:14px;display:flex;flex-direction:column;gap:12px}.pending-task-context{display:flex;flex-direction:column;gap:6px}.pending-task-kind{display:flex;align-items:center;gap:6px;font-size:12px;font-weight:600;color:var(--text)}.pending-task-kind.pin{color:var(--accent)}.pending-task-kind.pin svg{stroke:var(--accent)}.pending-task-kind.arrow{color:#ef4444}.pending-task-kind.arrow svg{stroke:#ef4444}.pending-task-file{font-size:11px;color:var(--text-muted);font-family:monospace}.pending-task-input{width:100%;padding:8px 10px;font-size:12px;background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:6px;resize:vertical;font-family:inherit;line-height:1.4}.pending-task-input:focus{border-color:var(--accent);outline:none}.pending-task-actions{display:flex;gap:6px}.pending-task-actions .submit-btn{flex:1;padding:6px 12px;font-size:11px;font-weight:600;background:var(--accent);color:#fff;border:none;border-radius:5px;cursor:pointer}.pending-task-actions .submit-btn:disabled{opacity:.4;cursor:default}.pending-task-actions .cancel-btn{padding:6px 12px;font-size:11px;background:var(--surface-2);color:var(--text-muted);border:1px solid var(--border);border-radius:5px;cursor:pointer}.pending-task-actions .cancel-btn:hover{background:var(--border);color:var(--text)}.task-toggles{display:flex;gap:10px;margin-bottom:4px}.scan-btn{padding:3px 10px;font-size:10px;font-weight:600;background:var(--accent);color:#fff;border:none;border-radius:4px;cursor:pointer}.scan-btn:disabled{opacity:.5;cursor:default}.scan-btn:hover:not(:disabled){opacity:.9}.a11y-error{font-size:11px;color:#ef4444;padding:6px 8px;background:#ef44441a;border-radius:5px;margin-bottom:6px}.a11y-pass{display:flex;align-items:center;gap:6px;padding:8px 10px;border-radius:6px;font-size:11px;font-weight:600;background:#22c55e1f;color:#22c55e;border:1px solid rgba(34,197,94,.25)}.a11y-empty{font-size:11px;color:var(--text-muted);padding:20px 0;text-align:center}.a11y-summary{font-size:11px;font-weight:600;color:#ef4444;padding:6px 8px;border-radius:5px;margin-bottom:4px;background:#ef444414;border:1px solid rgba(239,68,68,.2)}.a11y-card{padding:8px;border-radius:6px;margin-bottom:6px;background:var(--surface-2);border-left:3px solid var(--border)}.a11y-card.critical{border-left-color:#dc2626}.a11y-card.serious{border-left-color:#ef4444}.a11y-card.moderate{border-left-color:#f59e0b}.a11y-card.minor{border-left-color:#6b7280}.a11y-card-header{display:flex;align-items:center;gap:6px;font-size:11px}.a11y-impact{font-size:9px;font-weight:700;text-transform:uppercase;padding:1px 5px;border-radius:3px;color:#fff}.a11y-impact.critical{background:#dc2626}.a11y-impact.serious{background:#ef4444}.a11y-impact.moderate{background:#f59e0b}.a11y-impact.minor{background:#6b7280}.a11y-rule{font-weight:600;color:var(--text)}.a11y-count{margin-left:auto;color:var(--text-muted);font-size:10px}.a11y-help{margin:4px 0 6px;font-size:11px;color:var(--text-muted);line-height:1.4}.a11y-fix-btn{padding:3px 10px;font-size:10px;font-weight:600;background:#3b82f61f;color:#3b82f6;border:1px solid rgba(59,130,246,.25);border-radius:4px;cursor:pointer}.a11y-fix-btn:hover{background:#3b82f6;color:#fff}.a11y-tasked{font-size:10px;color:#22c55e;font-weight:600}.history-toggle{display:flex;align-items:center;gap:4px;font-size:10px;color:var(--text-muted);cursor:pointer;white-space:nowrap}.history-toggle input{margin:0}.history-toggle span{-webkit-user-select:none;user-select:none}.shortcuts-panel{padding:14px;overflow-y:auto;flex:1}.shortcut-group{margin-bottom:16px}.shortcut-group-title{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--text-muted);margin-bottom:8px;padding-bottom:4px;border-bottom:1px solid var(--border)}.shortcut-row{display:flex;align-items:center;gap:6px;padding:4px 0;font-size:12px;color:var(--text)}.shortcut-row span{margin-left:auto;color:var(--text-muted);font-size:11px}.shortcut-row kbd{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:20px;padding:0 5px;background:var(--surface-2);border:1px solid var(--border);border-radius:4px;font-family:inherit;font-size:11px;font-weight:600;color:var(--text);box-shadow:0 1px 0 var(--border)}.shortcut-row kbd.mod{font-size:10px;color:var(--text-muted)}.shortcut-hint{font-size:11px;color:var(--text-muted);padding-top:8px;border-top:1px solid var(--border);display:flex;align-items:center;gap:4px;flex-wrap:wrap}.shortcut-hint kbd{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:16px;padding:0 4px;background:var(--surface-2);border:1px solid var(--border);border-radius:3px;font-family:inherit;font-size:10px;font-weight:600;color:var(--text-muted)}