@aaqiljamal/visual-editor-runtime 0.2.0

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/Overlay.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect } from \"react\";\nimport { h, render } from \"preact\";\nimport Moveable from \"moveable\";\n\n// Spike B — verifies:\n// 1. Preact renders into a closed Shadow DOM without leaking CSS either direction.\n// 2. Vanilla `moveable` produces drag/resize handles attached to host-page elements.\n// 3. No DevTools-hook conflict with the host's React 19 (Preact does not register).\n// 4. Hover gives react-grab-style outline + source badge (data-oid + component name).\n// 5. A self-test marker on `document.body` confirms the mount worked.\n\nconst ANCHOR_TAG = \"visual-editor-anchor\";\nconst SELF_TEST_KEY = \"visualEditorMounted\";\n\ntype FiberLike = {\n type?: unknown;\n return?: FiberLike | null;\n};\n\n// Names we treat as Next.js / React framework internals rather than the\n// user's component. We don't want the hover badge to say \"<SegmentViewNode>\"\n// when the user is pointing at a Server Component in their own page.tsx.\nconst FRAMEWORK_INTERNALS = new Set([\n \"SegmentViewNode\",\n \"ClientPageRoot\",\n \"ClientSegmentRoot\",\n \"OutletBoundary\",\n \"AppRouter\",\n \"Router\",\n \"ServerInsertedHTMLProvider\",\n \"ServerInsertedMetadataProvider\",\n \"DevRootHTTPAccessFallbackBoundary\",\n \"HTTPAccessFallbackBoundary\",\n \"HTTPAccessFallbackErrorBoundary\",\n \"RenderFromTemplateContext\",\n \"LayoutRouter\",\n \"RedirectBoundary\",\n \"RedirectErrorBoundary\",\n \"NotFoundBoundary\",\n \"NotFoundErrorBoundary\",\n \"DevRootNotFoundBoundary\",\n \"ReactDevOverlay\",\n \"HotReload\",\n \"AppRouterAnnouncer\",\n \"Provider\",\n \"Overlay\",\n]);\n\nfunction getComponentName(el: HTMLElement): string | null {\n const fiberKey = Object.keys(el).find((k) => k.startsWith(\"__reactFiber$\"));\n if (!fiberKey) return null;\n let fiber = (el as unknown as Record<string, FiberLike | undefined>)[\n fiberKey\n ];\n let depth = 0;\n while (fiber && depth < 30) {\n const t = fiber.type as\n | { displayName?: string; name?: string }\n | string\n | undefined;\n if (typeof t === \"function\") {\n const fn = t as unknown as { displayName?: string; name?: string };\n const name = fn.displayName || fn.name;\n if (name && name !== \"_default\" && !FRAMEWORK_INTERNALS.has(name)) {\n return name;\n }\n }\n fiber = fiber.return ?? undefined;\n depth++;\n }\n return null;\n}\n\n// Fallback: derive a label from a data-oid like \"app/components/Card.tsx:12:4\"\n// → \"Card\". For Server Components there is no Fiber owner to walk, but the\n// `data-oid` from our Babel plugin still tells us which file rendered this DOM.\nfunction nameFromDataOid(oid: string | null): string | null {\n if (!oid) return null;\n const filePath = oid.split(\":\")[0];\n const base = filePath.split(\"/\").pop();\n if (!base) return null;\n const stem = base.replace(/\\.(tsx|ts|jsx|js)$/, \"\");\n // Capitalize the first letter so server-rendered routes like `page.tsx`\n // display as \"Page\" (matching React's PascalCase convention for components).\n return stem.charAt(0).toUpperCase() + stem.slice(1);\n}\n\n// ---------------------------------------------------------------------------\n// Snap engine (inline; mirrors packages/server/src/snap/tailwind.ts).\n// Duplicated here because the spike doesn't yet have a shared package for\n// browser+server consumption. The server's snap.test.ts covers the same logic.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_SCALE_STEPS = [\n 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 24,\n 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 96,\n];\n\ntype SnapResult = {\n step: number | null;\n suffix: string;\n resolvedPx: number;\n snapped: boolean;\n};\n\n// Theme-aware scale cache: maps step N → resolved px, honoring any\n// `--spacing-N` overrides the project added via `@theme`. Built lazily and\n// invalidated whenever the project's `--spacing` base changes.\nlet resolvedScaleCache: { spacingPx: number; map: Map<number, number> } | null =\n null;\n\nfunction getResolvedScale(spacingPx: number): Map<number, number> {\n if (resolvedScaleCache && resolvedScaleCache.spacingPx === spacingPx) {\n return resolvedScaleCache.map;\n }\n const map = new Map<number, number>();\n const cs = getComputedStyle(document.documentElement);\n for (const step of DEFAULT_SCALE_STEPS) {\n // Tailwind v4 by default sets only `--spacing` (the base); per-step\n // overrides like `--spacing-13: 3.25rem` are project-level customizations.\n // When present they win; otherwise we fall back to `step * --spacing`.\n const named = cs.getPropertyValue(`--spacing-${step}`).trim();\n let px: number;\n if (named) {\n const parsed = parseCssLengthToPx(named);\n px = parsed !== null ? parsed : step * spacingPx;\n } else {\n px = step * spacingPx;\n }\n map.set(step, px);\n }\n resolvedScaleCache = { spacingPx, map };\n return map;\n}\n\nfunction snapToTailwind(targetPx: number, spacingPx: number, tolerancePx = 1): SnapResult {\n if (!Number.isFinite(targetPx) || targetPx < 0) {\n return { step: null, suffix: `[0px]`, resolvedPx: 0, snapped: false };\n }\n const scale = getResolvedScale(spacingPx);\n let bestStep: number | null = null;\n let bestDiff = Infinity;\n let bestPx = 0;\n for (const [step, px] of scale) {\n const diff = Math.abs(px - targetPx);\n if (diff < bestDiff) {\n bestDiff = diff;\n bestStep = step;\n bestPx = px;\n }\n }\n if (bestStep !== null && bestDiff <= tolerancePx) {\n return {\n step: bestStep,\n suffix: String(bestStep),\n resolvedPx: bestPx,\n snapped: true,\n };\n }\n const intPx = Math.round(targetPx);\n return { step: null, suffix: `[${intPx}px]`, resolvedPx: intPx, snapped: false };\n}\n\nfunction parseCssLengthToPx(value: string, rootFontPx = 16): number | null {\n const v = value.trim();\n if (v.endsWith(\"px\")) {\n const n = parseFloat(v.slice(0, -2));\n return Number.isFinite(n) ? n : null;\n }\n if (v.endsWith(\"rem\")) {\n const n = parseFloat(v.slice(0, -3));\n return Number.isFinite(n) ? n * rootFontPx : null;\n }\n if (v.endsWith(\"em\")) {\n const n = parseFloat(v.slice(0, -2));\n return Number.isFinite(n) ? n * rootFontPx : null;\n }\n return null;\n}\n\nfunction pxFromClass(token: string, spacingPx: number): number | null {\n const open = token.indexOf(\"[\");\n if (open !== -1 && token.endsWith(\"]\")) {\n return parseCssLengthToPx(token.slice(open + 1, -1));\n }\n const lastDash = token.lastIndexOf(\"-\");\n if (lastDash === -1) return null;\n const stepStr = token.slice(lastDash + 1);\n if (!/^-?\\d+(?:\\.\\d+)?$/.test(stepStr)) return null;\n const step = parseFloat(stepStr);\n return Number.isFinite(step) ? step * spacingPx : null;\n}\n\n// Mirror of packages/server/src/snap/tailwind.ts:bumpStep. Uses the same\n// theme-aware scale cache as snapToTailwind, so per-step --spacing-N\n// overrides affect bump targets too.\nfunction bumpStep(\n currentToken: string,\n direction: \"up\" | \"down\",\n spacingPx: number,\n): string | null {\n const open = currentToken.indexOf(\"[\");\n let lastDash: number;\n if (open !== -1 && currentToken.endsWith(\"]\")) {\n lastDash = currentToken.lastIndexOf(\"-\", open);\n } else {\n lastDash = currentToken.lastIndexOf(\"-\");\n }\n if (lastDash <= 0) return null;\n const prefix = currentToken.slice(0, lastDash);\n\n const currentPx = pxFromClass(currentToken, spacingPx);\n if (currentPx === null) return null;\n\n const scale = Array.from(getResolvedScale(spacingPx).entries()); // [[step, px], ...]\n let currentIdx = -1;\n for (let i = 0; i < scale.length; i++) {\n if (Math.abs(scale[i]![1] - currentPx) < 0.001) {\n currentIdx = i;\n break;\n }\n }\n\n if (currentIdx === -1) {\n let nearestIdx = 0;\n let nearestDiff = Infinity;\n for (let i = 0; i < scale.length; i++) {\n const diff = Math.abs(scale[i]![1] - currentPx);\n if (diff < nearestDiff) {\n nearestDiff = diff;\n nearestIdx = i;\n }\n }\n if (direction === \"up\" && scale[nearestIdx]![1] < currentPx) {\n currentIdx = nearestIdx;\n } else if (direction === \"down\" && scale[nearestIdx]![1] > currentPx) {\n currentIdx = nearestIdx;\n } else {\n return `${prefix}-${scale[nearestIdx]![0]}`;\n }\n }\n\n const newIdx = direction === \"up\" ? currentIdx + 1 : currentIdx - 1;\n if (newIdx < 0 || newIdx >= scale.length) return null;\n return `${prefix}-${scale[newIdx]![0]}`;\n}\n\n// Prefer the shorthand (`p-*`, `m-*`) when present; otherwise fall back to\n// directional tokens (`px-*`, `pt-*`, …). The keyboard nudge bumps whichever\n// is found first in this priority order.\nconst PADDING_PREFIXES = [\"p\", \"px\", \"py\", \"pt\", \"pr\", \"pb\", \"pl\"];\nconst MARGIN_PREFIXES = [\"m\", \"mx\", \"my\", \"mt\", \"mr\", \"mb\", \"ml\"];\nconst GAP_PREFIXES = [\"gap\", \"gap-x\", \"gap-y\"];\nconst WIDTH_PREFIXES = [\"w\"];\nconst HEIGHT_PREFIXES = [\"h\"];\n\n// Mirror of the server-side swapToken used by mutateClassName. Used for the\n// optimistic DOM patch on Apply so the user sees the new state before\n// Fast Refresh fires (RSC content especially — the route segment refresh\n// takes longer than a CC HMR step).\nfunction swapClassToken(value: string, before: string, after: string): string {\n const parts = value.split(/(\\s+)/);\n let found = false;\n return parts\n .map((p) => {\n if (!found && p === before) {\n found = true;\n return after;\n }\n return p;\n })\n .join(\"\");\n}\n\nfunction findTokenByPrefix(className: string, prefixes: readonly string[]): string | null {\n const tokens = className.split(/\\s+/).filter(Boolean);\n for (const p of prefixes) {\n for (const t of tokens) {\n if (\n t.startsWith(p + \"-\") &&\n /^(?:-?\\d+(?:\\.\\d+)?|\\[[^\\]]+\\])$/.test(t.slice(p.length + 1))\n ) {\n return t;\n }\n }\n }\n return null;\n}\n\n// Read the live page's Tailwind v4 `--spacing` from :root, fall back to 4px.\n// This is the open-note from SPIKES.md note #3 — wired here so the snap\n// honors any project that customized --spacing via `@theme`.\nfunction getSpacingPx(): number {\n const rootStyle = getComputedStyle(document.documentElement);\n const rootFontPx = parseFloat(rootStyle.fontSize) || 16;\n const spacing = rootStyle.getPropertyValue(\"--spacing\").trim();\n if (!spacing) return 4;\n if (spacing.endsWith(\"rem\")) {\n const n = parseFloat(spacing);\n return Number.isFinite(n) ? n * rootFontPx : 4;\n }\n if (spacing.endsWith(\"px\")) {\n const n = parseFloat(spacing);\n return Number.isFinite(n) ? n : 4;\n }\n return 4;\n}\n\n// Match Tailwind width tokens we'd snap: `w-32`, `w-2.5`, `w-[123px]`, etc.\n// Excludes named tokens like `w-full`, `w-auto`, `w-screen`, `w-min`, `w-max`,\n// `w-fit`, and viewport-relative names — those don't map to a numeric snap.\nconst WIDTH_TOKEN_RE = /^w-(\\d+(?:\\.\\d+)?|\\[[^\\]]+\\])$/;\n\ntype PendingChange = {\n element: HTMLElement;\n file: string;\n line: number;\n col: number;\n before: string;\n after: string;\n};\n\n// Default endpoint = the Next.js Route Handler mount point from\n// @aaqiljamal/visual-editor-next. Pass a `serverUrl` prop to <VisualEditOverlay /> if\n// you're using the standalone server CLI (e.g. \"http://127.0.0.1:7790\").\n// Module-level let so the closure-bound helpers below (ensureSessionToken,\n// authedFetch) see the resolved value — works for one overlay per page.\nlet SERVER_URL: string = \"/api/visual-editor\";\nconst DRAFT_STORAGE_KEY = \"visual-editor:draft-v1\";\n\n// Persisted draft — the pending-but-not-yet-applied change. Survives page\n// reloads via localStorage. The DOM element itself can't be persisted, so\n// we store the data-oid and re-resolve the element on mount.\ntype PersistedDraft = {\n file: string;\n line: number;\n col: number;\n before: string;\n after: string;\n oid: string;\n resolvedPx: number;\n savedAt: number;\n};\n\nfunction saveDraft(d: Omit<PersistedDraft, \"savedAt\">): void {\n try {\n localStorage.setItem(\n DRAFT_STORAGE_KEY,\n JSON.stringify({ ...d, savedAt: Date.now() }),\n );\n } catch {\n /* QuotaExceeded etc — drafts are best-effort */\n }\n}\n\nfunction loadDraft(): PersistedDraft | null {\n try {\n const raw = localStorage.getItem(DRAFT_STORAGE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as PersistedDraft;\n if (\n typeof parsed.file === \"string\" &&\n typeof parsed.line === \"number\" &&\n typeof parsed.col === \"number\" &&\n typeof parsed.before === \"string\" &&\n typeof parsed.after === \"string\" &&\n typeof parsed.oid === \"string\"\n ) {\n return parsed;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nfunction clearDraft(): void {\n try {\n localStorage.removeItem(DRAFT_STORAGE_KEY);\n } catch {\n /* same */\n }\n}\n\n// Fetched once on mount via GET /token. We use a memoized promise so any\n// concurrent fetches that fire before the token resolves all queue on the\n// same in-flight request rather than racing.\nlet sessionTokenPromise: Promise<string | null> | null = null;\n\nfunction ensureSessionToken(): Promise<string | null> {\n if (sessionTokenPromise) return sessionTokenPromise;\n sessionTokenPromise = (async () => {\n try {\n const r = await fetch(`${SERVER_URL}/token`);\n if (!r.ok) return null;\n const body = (await r.json()) as { token?: string };\n return typeof body.token === \"string\" ? body.token : null;\n } catch {\n return null;\n }\n })();\n return sessionTokenPromise;\n}\n\nasync function authedFetch(\n url: string,\n init: RequestInit = {},\n): Promise<Response> {\n const token = await ensureSessionToken();\n const headers = new Headers(init.headers);\n if (init.body !== undefined && !headers.has(\"Content-Type\")) {\n headers.set(\"Content-Type\", \"application/json\");\n }\n if (token) headers.set(\"Authorization\", `Bearer ${token}`);\n return fetch(url, { ...init, headers });\n}\n\nexport type VisualEditOverlayProps = {\n /**\n * Where the overlay sends mutation requests. Defaults to\n * \"/api/visual-editor\" — the path your Next.js Route Handler is mounted\n * at via @aaqiljamal/visual-editor-next. For the standalone server (used by\n * @aaqiljamal/visual-editor-server's CLI), pass \"http://127.0.0.1:7790\".\n */\n serverUrl?: string;\n};\n\nexport default function Overlay({ serverUrl }: VisualEditOverlayProps = {}) {\n if (serverUrl) SERVER_URL = serverUrl;\n useEffect(() => {\n if (process.env.NODE_ENV !== \"development\") return;\n\n // Kick off the token fetch — every authed call awaits this promise so\n // concurrent fetches that fire on first acquire all queue cleanly.\n void ensureSessionToken();\n\n const anchor = document.createElement(ANCHOR_TAG);\n Object.assign(anchor.style, {\n position: \"fixed\",\n inset: \"0\",\n pointerEvents: \"none\",\n zIndex: \"2147483647\",\n });\n document.body.appendChild(anchor);\n const shadow = anchor.attachShadow({ mode: \"closed\" });\n\n const style = document.createElement(\"style\");\n style.textContent = `\n :host { all: initial; }\n .badge {\n position: fixed; top: 12px; right: 12px;\n background: rebeccapurple; color: white;\n font: 12px/1.2 system-ui, sans-serif;\n padding: 6px 10px; border-radius: 6px;\n pointer-events: auto;\n }\n .hover-outline {\n position: fixed; display: none;\n pointer-events: none;\n box-sizing: border-box;\n border: 1.5px solid #ec4899;\n border-radius: 2px;\n background: rgba(236, 72, 153, 0.06);\n transition: none;\n }\n .hover-tag {\n position: fixed; display: none;\n pointer-events: none;\n background: #0f172a; color: white;\n font: 11px/1.2 ui-monospace, SFMono-Regular, Menlo, monospace;\n padding: 4px 7px; border-radius: 3px;\n white-space: nowrap;\n box-shadow: 0 2px 6px rgba(0,0,0,0.2);\n }\n .hover-tag .comp { color: #fbbf24; margin-right: 6px; font-weight: 600; }\n .hover-tag .tag { color: #93c5fd; margin-right: 6px; }\n .hover-tag .src { color: #cbd5e1; }\n .moveable-container { pointer-events: auto; }\n .pending-panel {\n position: fixed; display: none;\n top: 56px; right: 12px;\n flex-direction: column; gap: 8px;\n background: #0f172a; color: white;\n font: 12px/1.3 system-ui, sans-serif;\n padding: 10px 12px; border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n pointer-events: auto;\n min-width: 240px;\n }\n .pending-header {\n font: 11px/1.2 ui-monospace, monospace;\n color: #94a3b8;\n }\n .pending-body {\n display: flex; align-items: center; gap: 8px;\n font: 12px/1.2 ui-monospace, monospace;\n }\n .pending-body .before { color: #f87171; background: rgba(248,113,113,0.1); padding: 2px 6px; border-radius: 3px; }\n .pending-body .arrow { color: #94a3b8; }\n .pending-body .after { color: #4ade80; background: rgba(74,222,128,0.1); padding: 2px 6px; border-radius: 3px; font-weight: 600; }\n .pending-body .resolved { color: #94a3b8; font-size: 11px; margin-left: auto; }\n .pending-instances {\n font: 11px/1.3 system-ui;\n color: #fbbf24;\n background: rgba(251, 191, 36, 0.1);\n padding: 6px 8px;\n border-radius: 4px;\n border-left: 3px solid #fbbf24;\n }\n .instance-outline {\n position: fixed;\n pointer-events: none;\n box-sizing: border-box;\n border: 1.5px dashed #fbbf24;\n border-radius: 2px;\n background: rgba(251, 191, 36, 0.05);\n }\n .indicator-pad {\n position: fixed; display: none;\n pointer-events: none;\n background: rgba(147, 196, 125, 0.45);\n }\n .indicator-margin {\n position: fixed; display: none;\n pointer-events: none;\n background: rgba(246, 178, 107, 0.40);\n }\n .anchor-outline {\n position: fixed; display: none;\n pointer-events: none;\n box-sizing: border-box;\n border: 1.5px solid #14b8a6;\n background: rgba(20, 184, 166, 0.06);\n border-radius: 2px;\n }\n .distance-label {\n position: fixed; display: none;\n pointer-events: none;\n background: #be185d; color: white;\n font: 11px/1.2 ui-monospace, SFMono-Regular, Menlo, monospace;\n padding: 4px 7px; border-radius: 3px;\n box-shadow: 0 2px 6px rgba(0,0,0,0.25);\n white-space: nowrap;\n }\n .distance-line {\n position: fixed; display: none;\n pointer-events: none;\n background: #ec4899;\n }\n /* Padding handles sit ON the inner edge of the padding band.\n Horizontal bars for top/bottom (you drag them vertically),\n vertical bars for left/right (you drag them horizontally).\n Subtle teal — the green padding indicator band is the\n \"what's being adjusted\" cue; the handle itself is just\n the grip. */\n .padding-handle {\n position: fixed; display: none;\n pointer-events: auto;\n background: #0d9488;\n border: 1px solid white;\n border-radius: 2px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.35);\n z-index: 2;\n touch-action: none;\n transition: background 100ms ease;\n }\n .padding-handle:hover { background: #0f766e; }\n .padding-handle-top, .padding-handle-bottom {\n width: 16px; height: 4px;\n margin-left: -8px; margin-top: -2px;\n cursor: ns-resize;\n }\n .padding-handle-left, .padding-handle-right {\n width: 4px; height: 16px;\n margin-left: -2px; margin-top: -8px;\n cursor: ew-resize;\n }\n .pending-actions { display: flex; gap: 6px; }\n .pending-actions button {\n font: 12px/1 system-ui; padding: 6px 10px; border-radius: 4px;\n border: none; cursor: pointer;\n }\n .btn-apply { background: #4ade80; color: #052e16; font-weight: 600; }\n .btn-apply:hover { background: #22c55e; }\n .btn-discard { background: #334155; color: white; }\n .btn-discard:hover { background: #475569; }\n .pending-result {\n font: 11px/1.3 system-ui;\n padding: 6px 8px; border-radius: 4px;\n }\n .pending-result.success { background: rgba(74,222,128,0.15); color: #4ade80; }\n .pending-result.error { background: rgba(248,113,113,0.15); color: #f87171; }\n .btn-undo { background: #1e293b; color: white; border: 1px solid #334155; }\n .btn-undo:hover { background: #334155; border-color: #475569; }\n /* Shortcuts hint badge — shown when a target is selected so the user\n immediately knows what's editable on this specific element. */\n .shortcuts-hint {\n position: fixed; display: none;\n bottom: 12px; left: 12px;\n background: #0f172a; color: white;\n font: 11px/1.4 system-ui, sans-serif;\n padding: 8px 12px; border-radius: 6px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n max-width: 320px;\n pointer-events: auto;\n }\n .shortcuts-hint .hint-title {\n font-weight: 600; color: #fbbf24;\n margin-bottom: 4px;\n font-size: 11px;\n }\n .shortcuts-hint kbd {\n display: inline-block;\n background: #1e293b;\n color: #e2e8f0;\n padding: 1px 5px;\n border-radius: 3px;\n font: 10px/1 ui-monospace, monospace;\n border: 1px solid #334155;\n margin: 0 1px;\n }\n .shortcuts-hint .disabled { color: #64748b; }\n .shortcuts-hint .available { color: #cbd5e1; }\n .badge { cursor: pointer; user-select: none; }\n /* B6: history panel showing recent applies. Slides in from the\n right when the user clicks the \"visual-editor on\" badge. */\n .history-panel {\n position: fixed; display: none;\n top: 52px; right: 12px;\n width: 320px;\n max-height: calc(100vh - 80px);\n background: #0f172a; color: white;\n font: 12px/1.3 system-ui, sans-serif;\n padding: 10px 12px;\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0,0,0,0.4);\n pointer-events: auto;\n flex-direction: column;\n gap: 6px;\n overflow: hidden;\n }\n .history-title {\n display: flex; align-items: center; justify-content: space-between;\n font-weight: 600; color: #fbbf24;\n font-size: 11px;\n padding-bottom: 4px;\n border-bottom: 1px solid #1e293b;\n }\n .history-list { display: flex; flex-direction: column; gap: 4px; overflow-y: auto; max-height: calc(100vh - 140px); }\n .history-row {\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: center;\n gap: 4px;\n padding: 6px 8px;\n background: #1e293b;\n border-radius: 4px;\n }\n .history-row:hover { background: #243044; }\n .history-row-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }\n .history-source {\n font: 10px/1.2 ui-monospace, monospace;\n color: #94a3b8;\n overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n }\n .history-tokens {\n font: 11px/1.2 ui-monospace, monospace;\n }\n .history-tokens .before { color: #f87171; background: rgba(248,113,113,0.1); padding: 1px 4px; border-radius: 2px; }\n .history-tokens .arrow { color: #64748b; margin: 0 4px; }\n .history-tokens .after { color: #4ade80; background: rgba(74,222,128,0.1); padding: 1px 4px; border-radius: 2px; font-weight: 600; }\n .history-time {\n font: 10px/1.2 system-ui;\n color: #64748b;\n margin-top: 2px;\n }\n .btn-undo-row {\n background: transparent;\n border: 1px solid #334155;\n color: #cbd5e1;\n font: 11px/1 system-ui;\n padding: 4px 8px;\n border-radius: 3px;\n cursor: pointer;\n }\n .btn-undo-row:hover { background: #334155; }\n .history-empty {\n color: #64748b;\n text-align: center;\n font-size: 11px;\n padding: 16px 8px;\n }\n /* B8: asset picker panel — opens on 'i' when an img is selected. */\n .asset-picker {\n position: fixed; display: none;\n top: 12px; right: 12px;\n width: 320px;\n max-height: calc(100vh - 80px);\n background: #0f172a; color: white;\n font: 12px/1.3 system-ui, sans-serif;\n padding: 10px 12px;\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0,0,0,0.4);\n pointer-events: auto;\n flex-direction: column;\n gap: 6px;\n overflow: hidden;\n z-index: 3;\n }\n .asset-picker-title {\n display: flex; align-items: center; justify-content: space-between;\n font-weight: 600; color: #fbbf24;\n font-size: 11px;\n padding-bottom: 4px;\n border-bottom: 1px solid #1e293b;\n }\n .asset-picker-list {\n display: flex; flex-direction: column; gap: 2px;\n overflow-y: auto; max-height: calc(100vh - 160px);\n }\n .asset-row {\n display: flex; align-items: center; gap: 8px;\n padding: 6px 8px;\n background: #1e293b;\n border-radius: 4px;\n cursor: pointer;\n font: 11px/1.2 ui-monospace, monospace;\n }\n .asset-row:hover { background: #334155; }\n .asset-row.current { border: 1px solid #4ade80; }\n .asset-row .current-badge { color: #4ade80; font-size: 9px; font-family: system-ui; }\n .asset-empty {\n color: #64748b; text-align: center; padding: 16px; font-size: 11px;\n }\n /* B2b: CSS Module mutation panel — opens automatically when the\n selected element has a data-css-module-class attribute (stamped\n by the Babel plugin). Distinct from the Tailwind pending panel\n because the input is a CSS property + value, not a class token. */\n .css-panel {\n position: fixed; display: none;\n top: 56px; left: 12px;\n width: 320px;\n background: #0f172a; color: white;\n font: 12px/1.3 system-ui, sans-serif;\n padding: 10px 12px;\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0,0,0,0.4);\n pointer-events: auto;\n flex-direction: column;\n gap: 8px;\n z-index: 3;\n }\n .css-panel-title {\n font-weight: 600; color: #f472b6;\n font-size: 11px;\n padding-bottom: 4px;\n border-bottom: 1px solid #1e293b;\n }\n .css-panel-meta {\n font: 10px/1.3 ui-monospace, monospace;\n color: #94a3b8;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .css-input-row {\n display: flex; gap: 6px;\n }\n .css-input-row .label {\n color: #94a3b8; font-size: 10px;\n display: flex; align-items: center;\n min-width: 56px;\n }\n .css-input-row input {\n flex: 1;\n background: #1e293b;\n color: white;\n border: 1px solid #334155;\n border-radius: 3px;\n padding: 4px 6px;\n font: 11px/1.2 ui-monospace, monospace;\n }\n .css-input-row input:focus { outline: none; border-color: #60a5fa; }\n .css-panel-actions { display: flex; gap: 6px; }\n .css-panel-actions button {\n font: 12px/1 system-ui; padding: 6px 10px; border-radius: 4px;\n border: none; cursor: pointer;\n }\n .btn-css-apply { background: #4ade80; color: #052e16; font-weight: 600; }\n .btn-css-apply:hover { background: #22c55e; }\n .btn-css-close { background: #334155; color: white; }\n .btn-css-close:hover { background: #475569; }\n .css-panel-result {\n font: 11px/1.3 system-ui;\n padding: 6px 8px; border-radius: 4px;\n word-break: break-word;\n }\n .css-panel-result.success { background: rgba(74,222,128,0.15); color: #4ade80; }\n .css-panel-result.error { background: rgba(248,113,113,0.15); color: #f87171; }\n `;\n shadow.appendChild(style);\n\n const ui = document.createElement(\"div\");\n shadow.appendChild(ui);\n render(h(\"div\", { className: \"badge\" }, \"visual-editor on\"), ui);\n\n // B6: history panel — populated lazily on first open from GET /recent.\n const historyPanel = document.createElement(\"div\");\n historyPanel.className = \"history-panel\";\n shadow.appendChild(historyPanel);\n\n type RecentApply = {\n file: string;\n line: number;\n col: number;\n before: string;\n after: string;\n appliedAt: number;\n };\n\n const relativeTime = (ms: number): string => {\n const diff = Date.now() - ms;\n if (diff < 5_000) return \"just now\";\n if (diff < 60_000) return `${Math.round(diff / 1000)}s ago`;\n if (diff < 3_600_000) return `${Math.round(diff / 60_000)}m ago`;\n if (diff < 86_400_000) return `${Math.round(diff / 3_600_000)}h ago`;\n return `${Math.round(diff / 86_400_000)}d ago`;\n };\n\n const renderHistory = async (): Promise<void> => {\n let applies: RecentApply[] = [];\n try {\n const res = await authedFetch(`${SERVER_URL}/recent`, { method: \"GET\" });\n if (res.ok) {\n const body = (await res.json()) as {\n ok: boolean;\n applies?: RecentApply[];\n };\n applies = body.applies ?? [];\n }\n } catch {\n /* server unreachable — show empty */\n }\n historyPanel.innerHTML = \"\";\n\n const title = document.createElement(\"div\");\n title.className = \"history-title\";\n title.innerHTML = `<span>Recent edits</span><span>${applies.length}</span>`;\n historyPanel.appendChild(title);\n\n if (applies.length === 0) {\n const empty = document.createElement(\"div\");\n empty.className = \"history-empty\";\n empty.textContent =\n \"No edits yet. Drag a handle, press a shortcut, or click an element to start.\";\n historyPanel.appendChild(empty);\n return;\n }\n\n const list = document.createElement(\"div\");\n list.className = \"history-list\";\n // Newest first.\n const sorted = [...applies].sort((a, b) => b.appliedAt - a.appliedAt);\n for (const a of sorted) {\n const row = document.createElement(\"div\");\n row.className = \"history-row\";\n const main = document.createElement(\"div\");\n main.className = \"history-row-main\";\n const src = document.createElement(\"div\");\n src.className = \"history-source\";\n src.textContent = `${a.file}:${a.line}:${a.col}`;\n const tokens = document.createElement(\"div\");\n tokens.className = \"history-tokens\";\n tokens.innerHTML = `<span class=\"before\">${a.before}</span><span class=\"arrow\">→</span><span class=\"after\">${a.after}</span>`;\n const time = document.createElement(\"div\");\n time.className = \"history-time\";\n time.textContent = relativeTime(a.appliedAt);\n main.appendChild(src);\n main.appendChild(tokens);\n main.appendChild(time);\n const undo = document.createElement(\"button\");\n undo.className = \"btn-undo-row\";\n undo.textContent = \"Undo\";\n undo.dataset.file = a.file;\n undo.dataset.line = String(a.line);\n undo.dataset.col = String(a.col);\n row.appendChild(main);\n row.appendChild(undo);\n list.appendChild(row);\n }\n historyPanel.appendChild(list);\n };\n\n // B8: asset picker panel\n const assetPicker = document.createElement(\"div\");\n assetPicker.className = \"asset-picker\";\n shadow.appendChild(assetPicker);\n\n // B2b: CSS Module mutation panel\n const cssPanel = document.createElement(\"div\");\n cssPanel.className = \"css-panel\";\n shadow.appendChild(cssPanel);\n\n let cssPanelTarget: HTMLElement | null = null;\n\n const hideCssPanel = () => {\n cssPanel.style.display = \"none\";\n cssPanelTarget = null;\n };\n\n // B3b: the panel is reused for two endpoints with the same shape:\n // - CSS Modules (B2b) → POST /apply-css-prop\n // - styled-components (B3b) → POST /apply-styled-prop\n // The selected element's data attributes tell us which to use.\n type CssPanelMode = \"css-module\" | \"styled-component\";\n\n const showCssPanel = (el: HTMLElement) => {\n const isCssModule = el.hasAttribute(\"data-css-module-class\");\n const isStyled = el.hasAttribute(\"data-styled-name\");\n if (!isCssModule && !isStyled) return;\n const mode: CssPanelMode = isCssModule ? \"css-module\" : \"styled-component\";\n const endpoint =\n mode === \"css-module\" ? \"/apply-css-prop\" : \"/apply-styled-prop\";\n\n const cssClass = el.getAttribute(\"data-css-module-class\");\n const cssFile = el.getAttribute(\"data-css-module-file\");\n const styledName = el.getAttribute(\"data-styled-name\");\n const styledTag = el.getAttribute(\"data-styled-tag\");\n\n const oid = el.getAttribute(\"data-oid\");\n if (!oid) return;\n const parts = oid.split(\":\");\n if (parts.length < 3) return;\n const jsxFile = parts.slice(0, -2).join(\":\");\n const line = parseInt(parts[parts.length - 2]!, 10);\n const col = parseInt(parts[parts.length - 1]!, 10);\n\n cssPanelTarget = el;\n cssPanel.innerHTML = \"\";\n\n const title = document.createElement(\"div\");\n title.className = \"css-panel-title\";\n title.textContent =\n mode === \"css-module\" ? \"CSS Module\" : \"styled-components\";\n cssPanel.appendChild(title);\n\n const meta = document.createElement(\"div\");\n meta.className = \"css-panel-meta\";\n meta.textContent =\n mode === \"css-module\"\n ? `.${cssClass} in ${cssFile}`\n : `${styledName} = styled.${styledTag}\\`…\\``;\n cssPanel.appendChild(meta);\n\n const mkRow = (\n label: string,\n placeholder: string,\n cls: string,\n ): HTMLInputElement => {\n const row = document.createElement(\"div\");\n row.className = \"css-input-row\";\n const lab = document.createElement(\"span\");\n lab.className = \"label\";\n lab.textContent = label;\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.className = cls;\n input.placeholder = placeholder;\n input.autocomplete = \"off\";\n input.spellcheck = false;\n row.appendChild(lab);\n row.appendChild(input);\n cssPanel.appendChild(row);\n return input;\n };\n const propInput = mkRow(\"property\", \"padding\", \"css-prop-input\");\n const valInput = mkRow(\"value\", \"1.5rem\", \"css-val-input\");\n\n const actions = document.createElement(\"div\");\n actions.className = \"css-panel-actions\";\n const applyBtn = document.createElement(\"button\");\n applyBtn.className = \"btn-css-apply\";\n applyBtn.textContent = \"Apply\";\n const closeBtn = document.createElement(\"button\");\n closeBtn.className = \"btn-css-close\";\n closeBtn.textContent = \"Close\";\n actions.appendChild(applyBtn);\n actions.appendChild(closeBtn);\n cssPanel.appendChild(actions);\n\n const showResultLine = (text: string, kind: \"success\" | \"error\") => {\n const existing = cssPanel.querySelector(\".css-panel-result\");\n existing?.remove();\n const r = document.createElement(\"div\");\n r.className = `css-panel-result ${kind}`;\n r.textContent = text;\n cssPanel.appendChild(r);\n };\n\n applyBtn.addEventListener(\"click\", async () => {\n const property = propInput.value.trim();\n const value = valInput.value.trim();\n if (!property || !value) {\n showResultLine(\"Both property and value are required.\", \"error\");\n return;\n }\n try {\n const res = await authedFetch(`${SERVER_URL}${endpoint}`, {\n method: \"POST\",\n body: JSON.stringify({\n file: jsxFile,\n line,\n col,\n property,\n value,\n }),\n });\n const body = (await res.json()) as\n | {\n ok: true;\n selector?: string;\n componentName?: string;\n previousValue: string | null;\n }\n | { ok: false; reason: string; details: string };\n if (res.ok && body.ok) {\n const target =\n \"selector\" in body && body.selector\n ? body.selector\n : \"componentName\" in body && body.componentName\n ? body.componentName\n : \"(target)\";\n const prev = body.previousValue\n ? `${property}: ${body.previousValue} → ${value}`\n : `${property}: ${value} (inserted)`;\n showResultLine(`Applied to ${target} — ${prev}`, \"success\");\n propInput.value = \"\";\n valInput.value = \"\";\n propInput.focus();\n } else if (!body.ok) {\n showResultLine(`Refused (${body.reason}): ${body.details}`, \"error\");\n }\n } catch (err) {\n showResultLine(`Network error: ${(err as Error).message}`, \"error\");\n }\n });\n\n closeBtn.addEventListener(\"click\", () => {\n hideCssPanel();\n });\n\n cssPanel.style.display = \"flex\";\n // Focus the property input so the user can immediately type.\n window.setTimeout(() => propInput.focus(), 0);\n };\n\n const renderAssetPicker = async (imgEl: HTMLElement): Promise<void> => {\n let assets: string[] = [];\n try {\n const res = await authedFetch(`${SERVER_URL}/assets`, { method: \"GET\" });\n if (res.ok) {\n const body = (await res.json()) as {\n ok: boolean;\n assets?: string[];\n };\n assets = body.assets ?? [];\n }\n } catch {\n /* server unreachable */\n }\n // The src on the rendered DOM may not match source (e.g. next/image\n // optimization), so we display it as informational only.\n const currentSrc = (imgEl as HTMLImageElement).getAttribute(\"src\") ?? \"\";\n\n assetPicker.innerHTML = \"\";\n const title = document.createElement(\"div\");\n title.className = \"asset-picker-title\";\n title.innerHTML = `<span>Replace image</span><span>${assets.length} available</span>`;\n assetPicker.appendChild(title);\n\n if (assets.length === 0) {\n const empty = document.createElement(\"div\");\n empty.className = \"asset-empty\";\n empty.textContent =\n \"No images found under public/. Put a .png/.jpg/.svg/.webp/.avif/.gif there.\";\n assetPicker.appendChild(empty);\n assetPicker.style.display = \"flex\";\n return;\n }\n\n const list = document.createElement(\"div\");\n list.className = \"asset-picker-list\";\n for (const a of assets) {\n const row = document.createElement(\"div\");\n row.className = \"asset-row\" + (a === currentSrc ? \" current\" : \"\");\n row.dataset.asset = a;\n row.innerHTML = `<span>${a}</span>${a === currentSrc ? \"<span class='current-badge'>current</span>\" : \"\"}`;\n list.appendChild(row);\n }\n assetPicker.appendChild(list);\n assetPicker.style.display = \"flex\";\n };\n\n const hideAssetPicker = () => {\n assetPicker.style.display = \"none\";\n };\n\n assetPicker.addEventListener(\"click\", async (e) => {\n const row = (e.target as HTMLElement | null)?.closest(\n \".asset-row\",\n ) as HTMLElement | null;\n if (!row || !lastSelected) return;\n const picked = row.dataset.asset;\n if (!picked) return;\n\n const oid = lastSelected.getAttribute(\"data-oid\");\n if (!oid) return;\n const parts = oid.split(\":\");\n if (parts.length < 3) return;\n const file = parts.slice(0, -2).join(\":\");\n const line = parseInt(parts[parts.length - 2]!, 10);\n const col = parseInt(parts[parts.length - 1]!, 10);\n\n try {\n const res = await authedFetch(`${SERVER_URL}/apply`, {\n method: \"POST\",\n body: JSON.stringify({\n file,\n line,\n col,\n attribute: \"src\",\n before: null,\n after: picked,\n }),\n });\n const body = (await res.json()) as\n | { ok: true; diff: string }\n | { ok: false; reason: string; details: string };\n if (res.ok && body.ok) {\n // Optimistic DOM swap.\n (lastSelected as HTMLImageElement).src = picked;\n hideAssetPicker();\n showResult(`Swapped image to ${picked}`, \"success\");\n } else if (!body.ok) {\n showResult(`Refused (${body.reason}): ${body.details}`, \"error\");\n }\n } catch (err) {\n showResult(\n `Network error: ${(err as Error).message}`,\n \"error\",\n );\n }\n });\n\n historyPanel.addEventListener(\"click\", async (e) => {\n const target = e.target as HTMLElement | null;\n if (!target || !target.classList.contains(\"btn-undo-row\")) return;\n const file = target.dataset.file!;\n const line = Number(target.dataset.line);\n const col = Number(target.dataset.col);\n try {\n await authedFetch(`${SERVER_URL}/revert`, {\n method: \"POST\",\n body: JSON.stringify({ file, line, col }),\n });\n await renderHistory(); // refresh list\n } catch {\n /* surface this via showResult later if needed */\n }\n });\n\n // Toggle history panel by clicking the visual-editor-on badge.\n const badgeEl = shadow.querySelector(\".badge\") as HTMLElement | null;\n if (badgeEl) {\n badgeEl.addEventListener(\"click\", async (e) => {\n e.stopPropagation();\n const isOpen = historyPanel.style.display === \"flex\";\n if (isOpen) {\n historyPanel.style.display = \"none\";\n } else {\n await renderHistory();\n historyPanel.style.display = \"flex\";\n }\n });\n }\n\n const hoverOutline = document.createElement(\"div\");\n hoverOutline.className = \"hover-outline\";\n shadow.appendChild(hoverOutline);\n\n const hoverTag = document.createElement(\"div\");\n hoverTag.className = \"hover-tag\";\n shadow.appendChild(hoverTag);\n\n // Eight box-model indicator bands (Chrome DevTools style).\n const makeIndicator = (cls: \"indicator-pad\" | \"indicator-margin\") => {\n const d = document.createElement(\"div\");\n d.className = cls;\n shadow.appendChild(d);\n return d;\n };\n const indicators = {\n padTop: makeIndicator(\"indicator-pad\"),\n padRight: makeIndicator(\"indicator-pad\"),\n padBottom: makeIndicator(\"indicator-pad\"),\n padLeft: makeIndicator(\"indicator-pad\"),\n marTop: makeIndicator(\"indicator-margin\"),\n marRight: makeIndicator(\"indicator-margin\"),\n marBottom: makeIndicator(\"indicator-margin\"),\n marLeft: makeIndicator(\"indicator-margin\"),\n };\n\n const setBand = (\n el: HTMLElement,\n visible: boolean,\n left: number,\n top: number,\n width: number,\n height: number,\n ) => {\n if (!visible || width <= 0 || height <= 0) {\n el.style.display = \"none\";\n return;\n }\n el.style.display = \"block\";\n el.style.left = `${left}px`;\n el.style.top = `${top}px`;\n el.style.width = `${width}px`;\n el.style.height = `${height}px`;\n };\n\n const clearIndicators = () => {\n for (const el of Object.values(indicators)) el.style.display = \"none\";\n };\n\n const updateIndicators = (el: HTMLElement, rect: DOMRect) => {\n const cs = getComputedStyle(el);\n const p = {\n t: parseFloat(cs.paddingTop) || 0,\n r: parseFloat(cs.paddingRight) || 0,\n b: parseFloat(cs.paddingBottom) || 0,\n l: parseFloat(cs.paddingLeft) || 0,\n };\n const m = {\n t: parseFloat(cs.marginTop) || 0,\n r: parseFloat(cs.marginRight) || 0,\n b: parseFloat(cs.marginBottom) || 0,\n l: parseFloat(cs.marginLeft) || 0,\n };\n // Padding (inside, between border and content)\n setBand(indicators.padTop, p.t > 0, rect.left, rect.top, rect.width, p.t);\n setBand(\n indicators.padBottom,\n p.b > 0,\n rect.left,\n rect.bottom - p.b,\n rect.width,\n p.b,\n );\n setBand(\n indicators.padLeft,\n p.l > 0,\n rect.left,\n rect.top + p.t,\n p.l,\n rect.height - p.t - p.b,\n );\n setBand(\n indicators.padRight,\n p.r > 0,\n rect.right - p.r,\n rect.top + p.t,\n p.r,\n rect.height - p.t - p.b,\n );\n // Margin (outside the element). Top/bottom span the full extended\n // width including side margins; left/right span only the element\n // height — avoids double-painted corners.\n setBand(\n indicators.marTop,\n m.t > 0,\n rect.left - m.l,\n rect.top - m.t,\n rect.width + m.l + m.r,\n m.t,\n );\n setBand(\n indicators.marBottom,\n m.b > 0,\n rect.left - m.l,\n rect.bottom,\n rect.width + m.l + m.r,\n m.b,\n );\n setBand(indicators.marLeft, m.l > 0, rect.left - m.l, rect.top, m.l, rect.height);\n setBand(indicators.marRight, m.r > 0, rect.right, rect.top, m.r, rect.height);\n };\n\n // Alt-hover distance measurement: show the anchor outline + a\n // labelled gap distance between the Moveable target (or last shift-\n // clicked element) and the currently hovered element.\n const anchorOutline = document.createElement(\"div\");\n anchorOutline.className = \"anchor-outline\";\n shadow.appendChild(anchorOutline);\n const distanceLabel = document.createElement(\"div\");\n distanceLabel.className = \"distance-label\";\n shadow.appendChild(distanceLabel);\n const distanceLineH = document.createElement(\"div\");\n distanceLineH.className = \"distance-line\";\n shadow.appendChild(distanceLineH);\n const distanceLineV = document.createElement(\"div\");\n distanceLineV.className = \"distance-line\";\n shadow.appendChild(distanceLineV);\n\n const measureSet: HTMLElement[] = [];\n\n const moveableContainer = document.createElement(\"div\");\n moveableContainer.className = \"moveable-container\";\n shadow.appendChild(moveableContainer);\n\n // Bottom-left shortcuts hint, populated from the selected element's\n // existing class tokens. The user immediately sees what's available\n // on this specific element instead of guessing.\n const shortcutsHint = document.createElement(\"div\");\n shortcutsHint.className = \"shortcuts-hint\";\n shadow.appendChild(shortcutsHint);\n\n const updateShortcutsHint = (el: HTMLElement) => {\n const tokens = el.className.split(/\\s+/).filter(Boolean);\n const numericSuffix = /^(-?\\d+(?:\\.\\d+)?|\\[[^\\]]+\\])$/;\n const hasPrefix = (prefixes: readonly string[]) =>\n tokens.some((t) =>\n prefixes.some(\n (p) =>\n t.startsWith(p + \"-\") &&\n numericSuffix.test(t.slice(p.length + 1)),\n ),\n );\n const hasW = hasPrefix([\"w\"]);\n const hasH = hasPrefix([\"h\"]);\n const hasPad = hasPrefix([\"p\", \"px\", \"py\", \"pt\", \"pr\", \"pb\", \"pl\"]);\n const hasMar = hasPrefix([\"m\", \"mx\", \"my\", \"mt\", \"mr\", \"mb\", \"ml\"]);\n const hasGap = hasPrefix([\"gap\", \"gap-x\", \"gap-y\"]);\n\n const line = (\n label: string,\n keys: string,\n enabled: boolean,\n ): string =>\n `<div class=\"${enabled ? \"available\" : \"disabled\"}\">${keys} → ${label}${enabled ? \"\" : \" (no class on this element)\"}</div>`;\n\n const isImg = el.tagName.toLowerCase() === \"img\";\n shortcutsHint.innerHTML =\n `<div class=\"hint-title\">This element is editable via:</div>` +\n line(\"resize width / height\", \"drag side handles\", hasW || hasH) +\n line(\"padding (per side)\", \"drag teal bars · <kbd>]</kbd> <kbd>[</kbd>\", hasPad) +\n line(\"margin\", \"<kbd>}</kbd> <kbd>{</kbd> (shift+])\", hasMar) +\n line(\"gap (flex/grid)\", \"<kbd>alt+]</kbd> <kbd>alt+[</kbd>\", hasGap) +\n line(\"width / height nudge\", \"<kbd>alt+→</kbd> <kbd>alt+↓</kbd>\", hasW || hasH) +\n line(\"replace image asset\", \"<kbd>i</kbd>\", isImg) +\n `<div class=\"disabled\" style=\"margin-top:4px;\">deselect: <kbd>esc</kbd> · alt-hover for distance · shift-click to set anchor</div>`;\n shortcutsHint.style.display = \"block\";\n };\n\n const hideShortcutsHint = () => {\n shortcutsHint.style.display = \"none\";\n };\n\n // Figma-style padding handles: 4 circles at the inner edges of the\n // padding band on the selected element. Dragging changes only that\n // side's padding; release snaps to scale and proposes a change.\n type PaddingSide = \"top\" | \"right\" | \"bottom\" | \"left\";\n const paddingHandles: Record<PaddingSide, HTMLElement> = {\n top: document.createElement(\"div\"),\n right: document.createElement(\"div\"),\n bottom: document.createElement(\"div\"),\n left: document.createElement(\"div\"),\n };\n for (const side of [\"top\", \"right\", \"bottom\", \"left\"] as const) {\n const h = paddingHandles[side];\n h.className = `padding-handle padding-handle-${side}`;\n shadow.appendChild(h);\n }\n\n const hidePaddingHandles = () => {\n for (const side of [\"top\", \"right\", \"bottom\", \"left\"] as const) {\n paddingHandles[side].style.display = \"none\";\n }\n };\n\n const positionPaddingHandles = (el: HTMLElement) => {\n const rect = el.getBoundingClientRect();\n const cs = getComputedStyle(el);\n const pt = parseFloat(cs.paddingTop) || 0;\n const pr = parseFloat(cs.paddingRight) || 0;\n const pb = parseFloat(cs.paddingBottom) || 0;\n const pl = parseFloat(cs.paddingLeft) || 0;\n const hasAnyPadding = pt > 0 || pr > 0 || pb > 0 || pl > 0;\n if (!hasAnyPadding) {\n hidePaddingHandles();\n return;\n }\n const cx = rect.left + rect.width / 2;\n const cy = rect.top + rect.height / 2;\n const showAt = (h: HTMLElement, x: number, y: number) => {\n h.style.display = \"block\";\n h.style.left = `${x}px`;\n h.style.top = `${y}px`;\n };\n // Inner edge of each padding band.\n if (pt > 0) showAt(paddingHandles.top, cx, rect.top + pt);\n else paddingHandles.top.style.display = \"none\";\n if (pb > 0) showAt(paddingHandles.bottom, cx, rect.bottom - pb);\n else paddingHandles.bottom.style.display = \"none\";\n if (pl > 0) showAt(paddingHandles.left, rect.left + pl, cy);\n else paddingHandles.left.style.display = \"none\";\n if (pr > 0) showAt(paddingHandles.right, rect.right - pr, cy);\n else paddingHandles.right.style.display = \"none\";\n };\n\n const cssSideKey = (side: PaddingSide) =>\n ({\n top: \"paddingTop\",\n right: \"paddingRight\",\n bottom: \"paddingBottom\",\n left: \"paddingLeft\",\n })[side] as \"paddingTop\" | \"paddingRight\" | \"paddingBottom\" | \"paddingLeft\";\n\n const setupPaddingDrag = (handle: HTMLElement, side: PaddingSide) => {\n handle.addEventListener(\"pointerdown\", (ev) => {\n if (!lastSelected) return;\n ev.preventDefault();\n ev.stopPropagation();\n const target = lastSelected;\n const cssKey = cssSideKey(side);\n const startX = ev.clientX;\n const startY = ev.clientY;\n const startPad =\n parseFloat(getComputedStyle(target)[cssKey] as string) || 0;\n handle.setPointerCapture(ev.pointerId);\n\n const onMove = (mv: PointerEvent) => {\n let delta = 0;\n if (side === \"top\") delta = mv.clientY - startY;\n else if (side === \"bottom\") delta = -(mv.clientY - startY);\n else if (side === \"left\") delta = mv.clientX - startX;\n else if (side === \"right\") delta = -(mv.clientX - startX);\n const next = Math.max(0, startPad + delta);\n target.style[cssKey] = `${next}px`;\n positionPaddingHandles(target);\n };\n const onUp = (mv: PointerEvent) => {\n handle.releasePointerCapture(mv.pointerId);\n document.removeEventListener(\"pointermove\", onMove);\n document.removeEventListener(\"pointerup\", onUp);\n const finalPx =\n parseFloat(getComputedStyle(target)[cssKey] as string) || 0;\n proposePaddingSideChange(target, side, finalPx);\n };\n document.addEventListener(\"pointermove\", onMove);\n document.addEventListener(\"pointerup\", onUp);\n });\n };\n for (const side of [\"top\", \"right\", \"bottom\", \"left\"] as const) {\n setupPaddingDrag(paddingHandles[side], side);\n }\n\n const SIDE_PREFIX: Record<PaddingSide, string> = {\n top: \"pt\",\n right: \"pr\",\n bottom: \"pb\",\n left: \"pl\",\n };\n const AXIS_PREFIX: Record<PaddingSide, \"px\" | \"py\"> = {\n top: \"py\",\n bottom: \"py\",\n left: \"px\",\n right: \"px\",\n };\n\n // Padding handle drag → snap → propose.\n // Priority for which token to mutate:\n // 1. side-specific (`pt-*`) — bump directly\n // 2. axis (`py-*`) or shorthand (`p-*`) — append override (`p-4` → `p-4 pt-5`)\n const proposePaddingSideChange = (\n target: HTMLElement,\n side: PaddingSide,\n newPx: number,\n ) => {\n const sidePrefix = SIDE_PREFIX[side];\n const axisPrefix = AXIS_PREFIX[side];\n const tokens = target.className.split(/\\s+/).filter(Boolean);\n const numericSuffix = /^(-?\\d+(?:\\.\\d+)?|\\[[^\\]]+\\])$/;\n\n const sideToken = tokens.find(\n (t) =>\n t.startsWith(sidePrefix + \"-\") &&\n numericSuffix.test(t.slice(sidePrefix.length + 1)),\n );\n\n const spacingPx = getSpacingPx();\n const snap = snapToTailwind(newPx, spacingPx);\n\n if (sideToken) {\n const newToken = `${sidePrefix}-${snap.suffix}`;\n if (newToken === sideToken) {\n clearInlineSizing(target);\n return;\n }\n proposeTokenChange(target, sideToken, newToken, snap.resolvedPx);\n return;\n }\n\n const axisToken = tokens.find(\n (t) =>\n t.startsWith(axisPrefix + \"-\") &&\n numericSuffix.test(t.slice(axisPrefix.length + 1)),\n );\n const shortToken = tokens.find(\n (t) =>\n t.startsWith(\"p-\") && numericSuffix.test(t.slice(\"p-\".length)),\n );\n const base = axisToken ?? shortToken;\n if (!base) {\n showResult(\n `This element has no padding class (no p-*, ${axisPrefix}-*, or ${sidePrefix}-*). Drag handles need an existing padding token to mutate.`,\n \"error\",\n );\n clearInlineSizing(target);\n return;\n }\n const overrideToken = `${sidePrefix}-${snap.suffix}`;\n // The writer's swapToken splits on whitespace. Swapping the base\n // token for \"<base> <override>\" appends the override while leaving\n // the base in place. twMerge resolves the conflict to <override>.\n proposeTokenChange(\n target,\n base,\n `${base} ${overrideToken}`,\n snap.resolvedPx,\n );\n };\n\n const pendingPanel = document.createElement(\"div\");\n pendingPanel.className = \"pending-panel\";\n shadow.appendChild(pendingPanel);\n\n let moveable: Moveable | null = null;\n let lastSelected: HTMLElement | null = null;\n let hoverTarget: HTMLElement | null = null;\n let rafId = 0;\n let lastMouseX = 0;\n let lastMouseY = 0;\n let lastResizeWidth: number | null = null;\n let pending: PendingChange | null = null;\n const instanceOutlines: HTMLElement[] = [];\n\n // Principle 11: when one source location (data-oid) renders N DOM nodes,\n // mutating its className updates all N. We surface this blast radius by\n // (a) counting matching elements, (b) outlining the *other* instances\n // with a dashed amber border so the user sees what they're about to\n // touch, and (c) showing the count in the pending panel.\n const queryInstances = (oid: string): HTMLElement[] => {\n // CSS attribute selectors need double quotes escaped; the data-oid\n // value contains `:` which is selector-safe inside quotes.\n const escaped = oid.replace(/\"/g, '\\\\\"');\n const nodes = document.querySelectorAll(`[data-oid=\"${escaped}\"]`);\n const out: HTMLElement[] = [];\n nodes.forEach((n) => {\n if (n instanceof HTMLElement) out.push(n);\n });\n return out;\n };\n\n const clearInstanceOutlines = () => {\n for (const node of instanceOutlines) node.remove();\n instanceOutlines.length = 0;\n };\n\n const drawInstanceOutlines = (instances: HTMLElement[], selected: HTMLElement) => {\n clearInstanceOutlines();\n for (const el of instances) {\n if (el === selected) continue; // Moveable already shows the selected one\n const rect = el.getBoundingClientRect();\n if (rect.width === 0 && rect.height === 0) continue;\n const outline = document.createElement(\"div\");\n outline.className = \"instance-outline\";\n outline.style.left = `${rect.left}px`;\n outline.style.top = `${rect.top}px`;\n outline.style.width = `${rect.width}px`;\n outline.style.height = `${rect.height}px`;\n shadow.appendChild(outline);\n instanceOutlines.push(outline);\n }\n };\n\n const showPending = (change: PendingChange, resolvedPx: number) => {\n pending = change;\n pendingPanel.innerHTML = \"\";\n hidePaddingHandles();\n\n const oid = change.element.getAttribute(\"data-oid\");\n\n // B5: persist the draft so a page reload doesn't blow it away. The\n // change.element reference can't be serialized — we save the\n // data-oid and re-resolve on next mount.\n if (oid) {\n saveDraft({\n file: change.file,\n line: change.line,\n col: change.col,\n before: change.before,\n after: change.after,\n oid,\n resolvedPx,\n });\n }\n\n const instances = oid ? queryInstances(oid) : [change.element];\n const instanceCount = instances.length;\n\n const header = document.createElement(\"div\");\n header.className = \"pending-header\";\n header.textContent = `${change.file}:${change.line}:${change.col}`;\n\n const body = document.createElement(\"div\");\n body.className = \"pending-body\";\n body.innerHTML =\n `<span class=\"before\">${change.before}</span>` +\n `<span class=\"arrow\">→</span>` +\n `<span class=\"after\">${change.after}</span>` +\n `<span class=\"resolved\">${Math.round(resolvedPx)}px</span>`;\n\n pendingPanel.appendChild(header);\n pendingPanel.appendChild(body);\n\n // Principle 11: surface blast radius before commit.\n if (instanceCount > 1) {\n const banner = document.createElement(\"div\");\n banner.className = \"pending-instances\";\n banner.textContent = `Edits ${instanceCount} elements rendered from this source location.`;\n pendingPanel.appendChild(banner);\n drawInstanceOutlines(instances, change.element);\n } else {\n clearInstanceOutlines();\n }\n\n const actions = document.createElement(\"div\");\n actions.className = \"pending-actions\";\n const apply = document.createElement(\"button\");\n apply.className = \"btn-apply\";\n apply.textContent = instanceCount > 1 ? `Apply to ${instanceCount}` : \"Apply\";\n const discard = document.createElement(\"button\");\n discard.className = \"btn-discard\";\n discard.textContent = \"Discard\";\n actions.appendChild(apply);\n actions.appendChild(discard);\n pendingPanel.appendChild(actions);\n pendingPanel.style.display = \"flex\";\n };\n\n const clearInlineSizing = (el: HTMLElement) => {\n el.style.width = \"\";\n el.style.height = \"\";\n el.style.transform = \"\";\n // Padding inline styles are set by the padding-handle drag — clear\n // them too so the new className paints when Fast Refresh fires.\n el.style.paddingTop = \"\";\n el.style.paddingRight = \"\";\n el.style.paddingBottom = \"\";\n el.style.paddingLeft = \"\";\n };\n\n const hidePending = () => {\n pending = null;\n pendingPanel.style.display = \"none\";\n clearInstanceOutlines();\n clearDraft();\n };\n\n let resultDismissTimer: number | null = null;\n let lastApplied: PendingChange | null = null;\n\n const showResult = (message: string, kind: \"success\" | \"error\") => {\n pendingPanel.innerHTML = \"\";\n const r = document.createElement(\"div\");\n r.className = `pending-result ${kind}`;\n r.textContent = message;\n pendingPanel.appendChild(r);\n pendingPanel.style.display = \"flex\";\n if (resultDismissTimer !== null) window.clearTimeout(resultDismissTimer);\n resultDismissTimer = window.setTimeout(() => {\n if (!pending) pendingPanel.style.display = \"none\";\n }, 3500);\n };\n\n // After a successful Apply, show \"Applied: X → Y · Undo\" with a button\n // that calls /revert. Auto-dismiss after 6s.\n const showSuccessWithUndo = (change: PendingChange) => {\n lastApplied = change;\n pendingPanel.innerHTML = \"\";\n\n const r = document.createElement(\"div\");\n r.className = \"pending-result success\";\n r.textContent = `Applied: ${change.before} → ${change.after}`;\n pendingPanel.appendChild(r);\n\n const actions = document.createElement(\"div\");\n actions.className = \"pending-actions\";\n const undo = document.createElement(\"button\");\n undo.className = \"btn-undo\";\n undo.textContent = \"Undo\";\n const dismiss = document.createElement(\"button\");\n dismiss.className = \"btn-discard\";\n dismiss.textContent = \"Dismiss\";\n actions.appendChild(undo);\n actions.appendChild(dismiss);\n pendingPanel.appendChild(actions);\n pendingPanel.style.display = \"flex\";\n\n if (resultDismissTimer !== null) window.clearTimeout(resultDismissTimer);\n resultDismissTimer = window.setTimeout(() => {\n if (!pending) pendingPanel.style.display = \"none\";\n lastApplied = null;\n }, 6000);\n };\n\n pendingPanel.addEventListener(\"click\", async (e) => {\n const target = e.target as HTMLElement | null;\n if (!target || !pending) return;\n const change = pending;\n if (target.classList.contains(\"btn-apply\")) {\n try {\n const res = await authedFetch(`${SERVER_URL}/apply`, {\n method: \"POST\",\n body: JSON.stringify({\n file: change.file,\n line: change.line,\n col: change.col,\n before: change.before,\n after: change.after,\n }),\n });\n const body = (await res.json()) as\n | { ok: true; diff: string }\n | { ok: false; reason: string; details: string };\n if (res.ok && body.ok) {\n // Optimistic DOM patch: swap the className on every instance\n // sharing this data-oid so the user sees the new state\n // immediately. For Client Components Fast Refresh quickly\n // catches up; for Server Components the route segment refresh\n // takes longer, and without this patch the user would see a\n // stale view for ~200ms. After patch, clear inline sizing so\n // the new class can paint cleanly.\n const oid = change.element.getAttribute(\"data-oid\");\n const targets = oid ? queryInstances(oid) : [change.element];\n for (const target of targets) {\n target.className = swapClassToken(\n target.className,\n change.before,\n change.after,\n );\n clearInlineSizing(target);\n }\n pending = null;\n clearInstanceOutlines();\n clearDraft();\n // The optimistic DOM patch above already paints the new state.\n // For RSC content (route segment refresh path) Fast Refresh\n // catches up within a few hundred ms; the className swap on\n // every matching DOM node keeps the view stable until then.\n showSuccessWithUndo(change);\n // Re-place the padding handles using the now-updated computed\n // styles (the className change may have grown or shrunk the\n // padding band).\n if (lastSelected) positionPaddingHandles(lastSelected);\n } else if (!body.ok) {\n showResult(`Refused (${body.reason}): ${body.details}`, \"error\");\n }\n } catch (err) {\n showResult(\n `Network error: ${(err as Error).message}. Is visual-editor server running on :7790?`,\n \"error\",\n );\n }\n } else if (target.classList.contains(\"btn-discard\")) {\n // Discard while a pending change exists; otherwise just dismiss\n // the result panel (e.g., after a successful Apply).\n if (pending) {\n clearInlineSizing(pending.element);\n hidePending();\n } else {\n pendingPanel.style.display = \"none\";\n lastApplied = null;\n }\n if (lastSelected) positionPaddingHandles(lastSelected);\n } else if (target.classList.contains(\"btn-undo\") && lastApplied) {\n const change = lastApplied;\n try {\n const res = await authedFetch(`${SERVER_URL}/revert`, {\n method: \"POST\",\n body: JSON.stringify({\n file: change.file,\n line: change.line,\n col: change.col,\n }),\n });\n const body = (await res.json()) as\n | { ok: true; diff: string }\n | { ok: false; reason: string; details: string };\n if (res.ok && body.ok) {\n lastApplied = null;\n showResult(`Reverted: ${change.after} → ${change.before}`, \"success\");\n } else if (!body.ok) {\n showResult(\n `Could not undo (${body.reason}): ${body.details}`,\n \"error\",\n );\n }\n } catch (err) {\n showResult(\n `Network error during undo: ${(err as Error).message}`,\n \"error\",\n );\n }\n }\n });\n\n const isOverlayEl = (el: Element | null): boolean => {\n if (!el) return true;\n if (el.tagName.toLowerCase() === ANCHOR_TAG) return true;\n if (el.closest(ANCHOR_TAG)) return true;\n // Don't try to select Next.js's dev-tools UI.\n if (el.closest(\"[data-nextjs-dev-tools-button]\")) return true;\n if (el.closest(\"nextjs-portal\")) return true;\n return false;\n };\n\n const clearDistanceOverlay = () => {\n anchorOutline.style.display = \"none\";\n distanceLabel.style.display = \"none\";\n distanceLineH.style.display = \"none\";\n distanceLineV.style.display = \"none\";\n };\n\n const showDistanceBetween = (anchor: HTMLElement, hovered: HTMLElement) => {\n if (anchor === hovered) {\n clearDistanceOverlay();\n return;\n }\n const a = anchor.getBoundingClientRect();\n const b = hovered.getBoundingClientRect();\n\n anchorOutline.style.display = \"block\";\n anchorOutline.style.left = `${a.left}px`;\n anchorOutline.style.top = `${a.top}px`;\n anchorOutline.style.width = `${a.width}px`;\n anchorOutline.style.height = `${a.height}px`;\n\n // Horizontal and vertical gaps between bounding boxes.\n // dx positive → hovered is to the right of the anchor; negative → overlap;\n // 0 means edges touch. Mirror for dy.\n let dx = 0;\n if (b.left >= a.right) dx = b.left - a.right;\n else if (b.right <= a.left) dx = b.right - a.left; // negative\n let dy = 0;\n if (b.top >= a.bottom) dy = b.top - a.bottom;\n else if (b.bottom <= a.top) dy = b.bottom - a.top; // negative\n\n // Position the label at the midpoint of the rectangle joining the\n // two centers. Easy and unambiguous.\n const ax = (a.left + a.right) / 2;\n const ay = (a.top + a.bottom) / 2;\n const bx = (b.left + b.right) / 2;\n const by = (b.top + b.bottom) / 2;\n const mx = (ax + bx) / 2;\n const my = (ay + by) / 2;\n distanceLabel.textContent = `↔ ${Math.round(Math.abs(dx))}px · ↕ ${Math.round(Math.abs(dy))}px`;\n distanceLabel.style.display = \"block\";\n distanceLabel.style.left = `${mx + 8}px`;\n distanceLabel.style.top = `${my + 8}px`;\n\n // Draw horizontal line from anchor's nearest x-edge to hovered's nearest x-edge,\n // at the midpoint y of the smaller element. Same for vertical.\n const drawHLine = () => {\n const y = my;\n const x1 = Math.min(a.right, b.right) > Math.max(a.left, b.left)\n ? // overlap horizontally — skip line, dx is 0/negative\n null\n : ax < bx ? a.right : a.left;\n const x2 = x1 === null ? null : ax < bx ? b.left : b.right;\n if (x1 === null || x2 === null) {\n distanceLineH.style.display = \"none\";\n return;\n }\n distanceLineH.style.display = \"block\";\n distanceLineH.style.left = `${Math.min(x1, x2)}px`;\n distanceLineH.style.top = `${y}px`;\n distanceLineH.style.width = `${Math.abs(x2 - x1)}px`;\n distanceLineH.style.height = `1px`;\n };\n const drawVLine = () => {\n const x = mx;\n const y1 = Math.min(a.bottom, b.bottom) > Math.max(a.top, b.top)\n ? null\n : ay < by ? a.bottom : a.top;\n const y2 = y1 === null ? null : ay < by ? b.top : b.bottom;\n if (y1 === null || y2 === null) {\n distanceLineV.style.display = \"none\";\n return;\n }\n distanceLineV.style.display = \"block\";\n distanceLineV.style.left = `${x}px`;\n distanceLineV.style.top = `${Math.min(y1, y2)}px`;\n distanceLineV.style.width = `1px`;\n distanceLineV.style.height = `${Math.abs(y2 - y1)}px`;\n };\n drawHLine();\n drawVLine();\n };\n\n const clearHover = () => {\n hoverOutline.style.display = \"none\";\n hoverTag.style.display = \"none\";\n clearIndicators();\n clearDistanceOverlay();\n hoverTarget = null;\n };\n\n const updateHover = (el: HTMLElement) => {\n const rect = el.getBoundingClientRect();\n if (rect.width === 0 && rect.height === 0) {\n clearHover();\n return;\n }\n hoverOutline.style.display = \"block\";\n hoverOutline.style.left = `${rect.left}px`;\n hoverOutline.style.top = `${rect.top}px`;\n hoverOutline.style.width = `${rect.width}px`;\n hoverOutline.style.height = `${rect.height}px`;\n updateIndicators(el, rect);\n\n const oid = el.getAttribute(\"data-oid\");\n // The data-oid path is the authoritative \"where did this DOM come from\"\n // because the Babel plugin stamps it at compile time, before SSR/CSR.\n // Fiber walking only adds value if it finds a user-component name *not*\n // already implied by the filename (e.g., element rendered inside a child\n // of the file's default export). For the spike, the filename label is\n // strictly better than walking into Next/React internals.\n const fiberName = getComponentName(el);\n const fileName = nameFromDataOid(oid);\n const componentName =\n fileName ||\n (fiberName && !FRAMEWORK_INTERNALS.has(fiberName) ? fiberName : null);\n const tagName = el.tagName.toLowerCase();\n const oidLabel = oid || \"(no data-oid)\";\n\n hoverTag.innerHTML = \"\";\n if (componentName) {\n const c = document.createElement(\"span\");\n c.className = \"comp\";\n c.textContent = `<${componentName}>`;\n hoverTag.appendChild(c);\n }\n const t = document.createElement(\"span\");\n t.className = \"tag\";\n t.textContent = tagName;\n hoverTag.appendChild(t);\n const s = document.createElement(\"span\");\n s.className = \"src\";\n s.textContent = oidLabel;\n hoverTag.appendChild(s);\n\n hoverTag.style.display = \"block\";\n // Position tag above element by default; flip below if near top.\n const tagH = 22;\n const above = rect.top - tagH - 4;\n const below = rect.bottom + 4;\n hoverTag.style.left = `${Math.max(4, rect.left)}px`;\n hoverTag.style.top = `${above < 0 ? below : above}px`;\n };\n\n const onMouseMove = (e: MouseEvent) => {\n lastMouseX = e.clientX;\n lastMouseY = e.clientY;\n\n // Alt+hover with an anchor (Moveable target or shift-clicked element):\n // show the gap distance instead of (or in addition to) the hover badge.\n const anchor =\n (moveable ? lastSelected : null) ?? measureSet[0] ?? null;\n if (e.altKey && anchor) {\n if (rafId) return;\n rafId = requestAnimationFrame(() => {\n rafId = 0;\n const target = document.elementFromPoint(lastMouseX, lastMouseY);\n if (!(target instanceof HTMLElement) || isOverlayEl(target)) {\n clearDistanceOverlay();\n return;\n }\n showDistanceBetween(anchor, target);\n });\n return;\n }\n clearDistanceOverlay();\n\n if (moveable) return; // selection mode — hover suspended\n if (rafId) return;\n rafId = requestAnimationFrame(() => {\n rafId = 0;\n const target = document.elementFromPoint(lastMouseX, lastMouseY);\n if (!(target instanceof HTMLElement) || isOverlayEl(target)) {\n clearHover();\n return;\n }\n if (target === hoverTarget) return;\n hoverTarget = target;\n updateHover(target);\n });\n };\n\n const onScrollOrResize = () => {\n if (pending) {\n const oid = pending.element.getAttribute(\"data-oid\");\n if (oid) {\n const instances = queryInstances(oid);\n drawInstanceOutlines(instances, pending.element);\n }\n }\n if (moveable && lastSelected) {\n positionPaddingHandles(lastSelected);\n }\n if (moveable) return;\n const target = document.elementFromPoint(lastMouseX, lastMouseY);\n if (target instanceof HTMLElement && !isOverlayEl(target)) {\n hoverTarget = target;\n updateHover(target);\n } else {\n clearHover();\n }\n };\n\n const onMouseLeave = () => clearHover();\n\n const pushSelectionToServer = (el: HTMLElement) => {\n const oid = el.getAttribute(\"data-oid\");\n if (!oid) return;\n const parts = oid.split(\":\");\n if (parts.length < 3) return;\n const file = parts.slice(0, parts.length - 2).join(\":\");\n const line = parseInt(parts[parts.length - 2]!, 10);\n const col = parseInt(parts[parts.length - 1]!, 10);\n if (!Number.isInteger(line) || !Number.isInteger(col)) return;\n\n const fiberName = getComponentName(el);\n const fileName = nameFromDataOid(oid);\n const componentName =\n fileName ||\n (fiberName && !FRAMEWORK_INTERNALS.has(fiberName) ? fiberName : null);\n\n const instances = queryInstances(oid);\n\n // Fire-and-forget — overlay must keep working even if the server isn't\n // running. MCP clients just won't see selection updates in that case.\n void authedFetch(`${SERVER_URL}/selection`, {\n method: \"POST\",\n body: JSON.stringify({\n file,\n line,\n col,\n oid,\n className: el.className,\n tagName: el.tagName.toLowerCase(),\n componentName,\n instanceCount: instances.length,\n }),\n }).catch(() => {});\n };\n\n const clearSelectionOnServer = () => {\n void authedFetch(`${SERVER_URL}/selection`, {\n method: \"DELETE\",\n }).catch(() => {});\n };\n\n const acquire = (el: HTMLElement) => {\n if (el === lastSelected) return;\n if (isOverlayEl(el)) return;\n // Switching targets discards any pending change on the previous one.\n if (pending) {\n clearInlineSizing(pending.element);\n hidePending();\n }\n lastSelected = el;\n lastResizeWidth = null;\n clearHover();\n pushSelectionToServer(el);\n\n if (moveable) moveable.destroy();\n // Sibling elements act as alignment guidelines while dragging — when\n // the target's edge gets within 4 px of a sibling's edge, Moveable\n // snaps and draws a magenta line. The 4 px matches Tailwind's base\n // spacing unit, which keeps snap behavior aligned with the snap engine.\n const parent = el.parentElement;\n const elementGuidelines: HTMLElement[] = parent\n ? Array.from(parent.children).filter(\n (c): c is HTMLElement => c instanceof HTMLElement && c !== el,\n )\n : [];\n\n moveable = new Moveable(moveableContainer, {\n target: el,\n draggable: true,\n resizable: true,\n keepRatio: false,\n origin: false,\n snappable: true,\n snapDirections: { top: true, left: true, bottom: true, right: true, center: true, middle: true },\n elementSnapDirections: { top: true, left: true, bottom: true, right: true, center: true, middle: true },\n snapThreshold: 4,\n elementGuidelines,\n });\n moveable.on(\"drag\", ({ target, transform }) => {\n const t = target as HTMLElement;\n t.style.transform = transform;\n positionPaddingHandles(t);\n updateIndicators(t, t.getBoundingClientRect());\n });\n moveable.on(\"resize\", ({ target, width, height }) => {\n const t = target as HTMLElement;\n t.style.width = `${width}px`;\n t.style.height = `${height}px`;\n lastResizeWidth = width;\n positionPaddingHandles(t);\n updateIndicators(t, t.getBoundingClientRect());\n });\n positionPaddingHandles(el);\n // Show the green padding / orange margin bands during selection too,\n // not just on hover — they're the visual answer to \"what are these\n // teal handles letting me grow?\"\n updateIndicators(el, el.getBoundingClientRect());\n updateShortcutsHint(el);\n\n // B2b / B3b: if this element comes from a CSS Module OR a styled-\n // component, the Tailwind path can't help. The shared CSS panel\n // picks the right endpoint via the element's data attributes.\n if (\n el.hasAttribute(\"data-css-module-class\") ||\n el.hasAttribute(\"data-styled-name\")\n ) {\n showCssPanel(el);\n } else {\n hideCssPanel();\n }\n moveable.on(\"resizeEnd\", ({ target }) => {\n const el = target as HTMLElement;\n if (lastResizeWidth === null) return;\n const newWidthPx = lastResizeWidth;\n lastResizeWidth = null;\n\n const tokens = el.className.split(/\\s+/).filter(Boolean);\n const widthToken = tokens.find((t) => WIDTH_TOKEN_RE.test(t));\n if (!widthToken) {\n // Check what the element DOES have so we can suggest a useful path.\n const numericSuffix = /^(-?\\d+(?:\\.\\d+)?|\\[[^\\]]+\\])$/;\n const hasPad = tokens.some((t) =>\n [\"p\", \"px\", \"py\", \"pt\", \"pr\", \"pb\", \"pl\"].some(\n (p) =>\n t.startsWith(p + \"-\") &&\n numericSuffix.test(t.slice(p.length + 1)),\n ),\n );\n const suggestion = hasPad\n ? \"Use the teal padding bars or press [ ] to adjust padding instead.\"\n : \"No editable padding either — pick a different element.\";\n showResult(`No w-* class on this element. ${suggestion}`, \"error\");\n return;\n }\n\n const spacingPx = getSpacingPx();\n const snap = snapToTailwind(newWidthPx, spacingPx);\n const newToken = `w-${snap.suffix}`;\n if (newToken === widthToken) {\n clearInlineSizing(el);\n return;\n }\n proposeTokenChange(el, widthToken, newToken, snap.resolvedPx);\n });\n };\n\n // Shared \"given a before token + after token on an element, surface\n // the pending panel\" helper. Both resizeEnd and the keyboard nudge\n // funnel through this so the data-oid parsing and error UX stay\n // consistent.\n const proposeTokenChange = (\n el: HTMLElement,\n before: string,\n after: string,\n resolvedPx: number,\n ) => {\n const oid = el.getAttribute(\"data-oid\");\n if (!oid) {\n showResult(\n \"Element has no data-oid. Is the Babel plugin loaded?\",\n \"error\",\n );\n return;\n }\n const parts = oid.split(\":\");\n if (parts.length < 3) {\n showResult(`Malformed data-oid: ${oid}`, \"error\");\n return;\n }\n const file = parts.slice(0, parts.length - 2).join(\":\");\n const line = parseInt(parts[parts.length - 2]!, 10);\n const col = parseInt(parts[parts.length - 1]!, 10);\n if (!Number.isInteger(line) || !Number.isInteger(col)) {\n showResult(`Malformed data-oid: ${oid}`, \"error\");\n return;\n }\n showPending(\n { element: el, file, line, col, before, after },\n resolvedPx,\n );\n };\n\n // Keyboard nudge for properties Moveable can't easily express by\n // dragging a corner — padding, margin, gap. Inspired by Photoshop /\n // Figma where `[` and `]` are step-down/-up.\n // ] → padding +1 step (prefer `p-*`, fall back to side-specific)\n // [ → padding −1 step\n // } → margin +1 step\n // { → margin −1 step\n // Alt+] → gap +1 step\n // Alt+[ → gap −1 step\n const handleNudgeKey = (e: KeyboardEvent): boolean => {\n if (!lastSelected) return false;\n\n let prefixes: readonly string[] | null = null;\n let direction: \"up\" | \"down\" | null = null;\n\n // Different browsers and automation tools report Shift+] as either\n // e.key === \"}\" OR e.key === \"]\" with e.shiftKey true. Handle both.\n // Arrow keys with Alt → width/height nudges.\n if (e.altKey && e.key === \"ArrowRight\") {\n prefixes = WIDTH_PREFIXES;\n direction = \"up\";\n } else if (e.altKey && e.key === \"ArrowLeft\") {\n prefixes = WIDTH_PREFIXES;\n direction = \"down\";\n } else if (e.altKey && e.key === \"ArrowDown\") {\n prefixes = HEIGHT_PREFIXES;\n direction = \"up\";\n } else if (e.altKey && e.key === \"ArrowUp\") {\n prefixes = HEIGHT_PREFIXES;\n direction = \"down\";\n } else if (e.altKey && (e.key === \"]\" || e.key === \"}\")) {\n prefixes = GAP_PREFIXES;\n direction = \"up\";\n } else if (e.altKey && (e.key === \"[\" || e.key === \"{\")) {\n prefixes = GAP_PREFIXES;\n direction = \"down\";\n } else if (e.key === \"}\" || (e.key === \"]\" && e.shiftKey)) {\n prefixes = MARGIN_PREFIXES;\n direction = \"up\";\n } else if (e.key === \"{\" || (e.key === \"[\" && e.shiftKey)) {\n prefixes = MARGIN_PREFIXES;\n direction = \"down\";\n } else if (e.key === \"]\" && !e.shiftKey) {\n prefixes = PADDING_PREFIXES;\n direction = \"up\";\n } else if (e.key === \"[\" && !e.shiftKey) {\n prefixes = PADDING_PREFIXES;\n direction = \"down\";\n }\n\n if (!prefixes || !direction) return false;\n e.preventDefault();\n\n const el = lastSelected;\n const token = findTokenByPrefix(el.className, prefixes);\n if (!token) {\n const family =\n prefixes === PADDING_PREFIXES\n ? \"padding\"\n : prefixes === MARGIN_PREFIXES\n ? \"margin\"\n : prefixes === GAP_PREFIXES\n ? \"gap\"\n : prefixes === WIDTH_PREFIXES\n ? \"width\"\n : prefixes === HEIGHT_PREFIXES\n ? \"height\"\n : `${prefixes[0]}-*`;\n showResult(\n `No ${family} class on this element to nudge. See the hint badge for what IS editable.`,\n \"error\",\n );\n return true;\n }\n\n const spacingPx = getSpacingPx();\n const newToken = bumpStep(token, direction, spacingPx);\n if (!newToken) {\n showResult(\n `${token} is already at the ${direction === \"up\" ? \"max\" : \"min\"} step. Try the arbitrary-value drag (release outside the snap window).`,\n \"error\",\n );\n return true;\n }\n\n const resolvedPx = pxFromClass(newToken, spacingPx) ?? 0;\n proposeTokenChange(el, token, newToken, resolvedPx);\n return true;\n };\n\n const onClick = (e: MouseEvent) => {\n const target = document.elementFromPoint(e.clientX, e.clientY);\n if (!(target instanceof HTMLElement)) return;\n if (isOverlayEl(target)) return;\n // Shift-click toggles membership in the measure set without\n // acquiring Moveable. The first member becomes the anchor for\n // Alt-hover distance lines.\n if (e.shiftKey) {\n const idx = measureSet.indexOf(target);\n if (idx === -1) measureSet.push(target);\n else measureSet.splice(idx, 1);\n return;\n }\n acquire(target);\n };\n\n const onKeyUp = (e: KeyboardEvent) => {\n if (e.key === \"Alt\" || e.altKey === false) {\n clearDistanceOverlay();\n }\n };\n\n const onKeyDown = (e: KeyboardEvent) => {\n // B8: `i` opens the image asset picker for the currently selected\n // <img> element.\n if (\n (e.key === \"i\" || e.key === \"I\") &&\n !e.altKey &&\n !e.metaKey &&\n !e.ctrlKey &&\n lastSelected &&\n lastSelected.tagName.toLowerCase() === \"img\"\n ) {\n e.preventDefault();\n void renderAssetPicker(lastSelected);\n return;\n }\n if (e.key === \"Escape\") {\n if (pending) {\n clearInlineSizing(pending.element);\n hidePending();\n }\n if (moveable) {\n moveable.destroy();\n moveable = null;\n lastSelected = null;\n hidePaddingHandles();\n clearIndicators();\n hideShortcutsHint();\n hideAssetPicker();\n hideCssPanel();\n clearSelectionOnServer();\n }\n return;\n }\n handleNudgeKey(e);\n };\n\n document.addEventListener(\"mousemove\", onMouseMove, { passive: true });\n document.addEventListener(\"scroll\", onScrollOrResize, { passive: true });\n window.addEventListener(\"resize\", onScrollOrResize);\n document.addEventListener(\"mouseleave\", onMouseLeave);\n document.addEventListener(\"click\", onClick);\n document.addEventListener(\"keydown\", onKeyDown);\n document.addEventListener(\"keyup\", onKeyUp);\n document.body.dataset[SELF_TEST_KEY] = \"true\";\n\n // B5: restore any persisted draft from localStorage. We re-resolve the\n // element by data-oid (the only stable handle across page reloads).\n // If the element is gone (page changed, deployed, etc.), drop the draft.\n {\n const draft = loadDraft();\n if (draft) {\n const escaped = draft.oid.replace(/\"/g, '\\\\\"');\n const restored = document.querySelector(\n `[data-oid=\"${escaped}\"]`,\n ) as HTMLElement | null;\n if (restored) {\n showPending(\n {\n element: restored,\n file: draft.file,\n line: draft.line,\n col: draft.col,\n before: draft.before,\n after: draft.after,\n },\n draft.resolvedPx,\n );\n } else {\n // Stale — DOM doesn't have the element anymore.\n clearDraft();\n }\n }\n }\n\n (window as unknown as { __visualEditorSpike?: object }).__visualEditorSpike = {\n moveableHandleCount: () =>\n moveableContainer.querySelectorAll(\".moveable-control-box\").length,\n badgeText: () =>\n (shadow.querySelector(\".badge\") as HTMLElement | null)?.textContent ??\n null,\n hostBodyColor: () => getComputedStyle(document.body).color,\n badgeColor: () => {\n const b = shadow.querySelector(\".badge\") as HTMLElement | null;\n return b ? getComputedStyle(b).backgroundColor : null;\n },\n badgeBoxSizing: () => {\n const b = shadow.querySelector(\".badge\") as HTMLElement | null;\n return b ? getComputedStyle(b).boxSizing : null;\n },\n hostBodyBoxSizing: () => getComputedStyle(document.body).boxSizing,\n hoverTagVisible: () =>\n (shadow.querySelector(\".hover-tag\") as HTMLElement | null)?.style\n .display === \"block\",\n hoverTagText: () =>\n (shadow.querySelector(\".hover-tag\") as HTMLElement | null)\n ?.textContent ?? null,\n pendingPanelVisible: () =>\n (shadow.querySelector(\".pending-panel\") as HTMLElement | null)?.style\n .display === \"flex\",\n pendingPanelText: () =>\n (shadow.querySelector(\".pending-panel\") as HTMLElement | null)\n ?.textContent ?? null,\n // Programmatic Apply trigger — clicks the .btn-apply button inside the\n // shadow so headless tests can drive the Apply flow without\n // navigating Moveable's pointer-events surface.\n clickApply: () => {\n const btn = shadow.querySelector(\".btn-apply\") as HTMLElement | null;\n if (!btn) return { error: \"no-apply-button\" };\n btn.click();\n return { clicked: true };\n },\n instanceOutlineCount: () =>\n shadow.querySelectorAll(\".instance-outline\").length,\n visiblePaddingIndicators: () =>\n Array.from(shadow.querySelectorAll(\".indicator-pad\")).filter(\n (e) => (e as HTMLElement).style.display !== \"none\",\n ).length,\n visibleMarginIndicators: () =>\n Array.from(shadow.querySelectorAll(\".indicator-margin\")).filter(\n (e) => (e as HTMLElement).style.display !== \"none\",\n ).length,\n distanceLabelText: () => {\n const el = shadow.querySelector(\".distance-label\") as HTMLElement | null;\n if (!el || el.style.display === \"none\") return null;\n return el.textContent;\n },\n measureSetSize: () => measureSet.length,\n visiblePaddingHandles: () =>\n Array.from(shadow.querySelectorAll(\".padding-handle\")).filter(\n (e) => (e as HTMLElement).style.display !== \"none\",\n ).length,\n paddingHandleRect: (side: \"top\" | \"right\" | \"bottom\" | \"left\") => {\n const h = shadow.querySelector(\n `.padding-handle-${side}`,\n ) as HTMLElement | null;\n if (!h || h.style.display === \"none\") return null;\n return {\n left: parseFloat(h.style.left),\n top: parseFloat(h.style.top),\n };\n },\n historyPanelVisible: () =>\n (shadow.querySelector(\".history-panel\") as HTMLElement | null)?.style\n .display === \"flex\",\n historyRowCount: () =>\n shadow.querySelectorAll(\".history-row\").length,\n historyRows: () =>\n Array.from(shadow.querySelectorAll(\".history-row\")).map((r) => ({\n source: (r.querySelector(\".history-source\") as HTMLElement | null)\n ?.textContent,\n tokens: (r.querySelector(\".history-tokens\") as HTMLElement | null)\n ?.textContent,\n })),\n // Open the history panel programmatically (Playwright can't reach\n // into closed shadow to click the badge directly).\n openHistory: () => {\n const badge = shadow.querySelector(\".badge\") as HTMLElement | null;\n badge?.click();\n },\n undoRowAt: (index: number) => {\n const rows = shadow.querySelectorAll(\".btn-undo-row\");\n const btn = rows[index] as HTMLElement | undefined;\n btn?.click();\n },\n assetPickerVisible: () =>\n (shadow.querySelector(\".asset-picker\") as HTMLElement | null)?.style\n .display === \"flex\",\n assetPickerOptions: () =>\n Array.from(shadow.querySelectorAll(\".asset-row\")).map(\n (r) => (r as HTMLElement).dataset.asset,\n ),\n pickAsset: (assetPath: string) => {\n const row = shadow.querySelector(\n `.asset-row[data-asset=\"${CSS.escape(assetPath)}\"]`,\n ) as HTMLElement | null;\n if (!row) return { error: \"asset-not-found\" };\n row.click();\n return { picked: assetPath };\n },\n cssPanelVisible: () =>\n (shadow.querySelector(\".css-panel\") as HTMLElement | null)?.style\n .display === \"flex\",\n cssPanelMeta: () =>\n (shadow.querySelector(\".css-panel-meta\") as HTMLElement | null)\n ?.textContent ?? null,\n cssApply: (property: string, value: string) => {\n const propInput = shadow.querySelector(\n \".css-prop-input\",\n ) as HTMLInputElement | null;\n const valInput = shadow.querySelector(\n \".css-val-input\",\n ) as HTMLInputElement | null;\n const applyBtn = shadow.querySelector(\n \".btn-css-apply\",\n ) as HTMLElement | null;\n if (!propInput || !valInput || !applyBtn) {\n return { error: \"no-css-panel\" };\n }\n propInput.value = property;\n valInput.value = value;\n applyBtn.click();\n return { clicked: true };\n },\n cssPanelResult: () =>\n (shadow.querySelector(\".css-panel-result\") as HTMLElement | null)\n ?.textContent ?? null,\n selectedTag: () => lastSelected?.tagName ?? null,\n selectedAttrs: () =>\n lastSelected\n ? {\n dataCssClass: lastSelected.getAttribute(\"data-css-module-class\"),\n dataCssFile: lastSelected.getAttribute(\"data-css-module-file\"),\n dataOid: lastSelected.getAttribute(\"data-oid\"),\n }\n : null,\n };\n\n return () => {\n document.removeEventListener(\"mousemove\", onMouseMove);\n document.removeEventListener(\"scroll\", onScrollOrResize);\n window.removeEventListener(\"resize\", onScrollOrResize);\n document.removeEventListener(\"mouseleave\", onMouseLeave);\n document.removeEventListener(\"click\", onClick);\n document.removeEventListener(\"keydown\", onKeyDown);\n document.removeEventListener(\"keyup\", onKeyUp);\n cancelAnimationFrame(rafId);\n if (resultDismissTimer !== null) window.clearTimeout(resultDismissTimer);\n moveable?.destroy();\n hidePaddingHandles();\n hideShortcutsHint();\n clearInstanceOutlines();\n anchor.remove();\n delete document.body.dataset[SELF_TEST_KEY];\n };\n }, []);\n\n return null;\n}\n"],"mappings":"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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiWpB,WAAO,YAAY,KAAK;AAExB,UAAM,KAAK,SAAS,cAAc,KAAK;AACvC,WAAO,YAAY,EAAE;AACrB,WAAO,EAAE,OAAO,EAAE,WAAW,QAAQ,GAAG,kBAAkB,GAAG,EAAE;AAG/D,UAAM,eAAe,SAAS,cAAc,KAAK;AACjD,iBAAa,YAAY;AACzB,WAAO,YAAY,YAAY;AAW/B,UAAM,eAAe,CAAC,OAAuB;AAC3C,YAAM,OAAO,KAAK,IAAI,IAAI;AAC1B,UAAI,OAAO,IAAO,QAAO;AACzB,UAAI,OAAO,IAAQ,QAAO,GAAG,KAAK,MAAM,OAAO,GAAI,CAAC;AACpD,UAAI,OAAO,KAAW,QAAO,GAAG,KAAK,MAAM,OAAO,GAAM,CAAC;AACzD,UAAI,OAAO,MAAY,QAAO,GAAG,KAAK,MAAM,OAAO,IAAS,CAAC;AAC7D,aAAO,GAAG,KAAK,MAAM,OAAO,KAAU,CAAC;AAAA,IACzC;AAEA,UAAM,gBAAgB,YAA2B;AAC/C,UAAI,UAAyB,CAAC;AAC9B,UAAI;AACF,cAAM,MAAM,MAAM,YAAY,GAAG,UAAU,WAAW,EAAE,QAAQ,MAAM,CAAC;AACvE,YAAI,IAAI,IAAI;AACV,gBAAM,OAAQ,MAAM,IAAI,KAAK;AAI7B,oBAAU,KAAK,WAAW,CAAC;AAAA,QAC7B;AAAA,MACF,QAAQ;AAAA,MAER;AACA,mBAAa,YAAY;AAEzB,YAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,YAAM,YAAY;AAClB,YAAM,YAAY,kCAAkC,QAAQ,MAAM;AAClE,mBAAa,YAAY,KAAK;AAE9B,UAAI,QAAQ,WAAW,GAAG;AACxB,cAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,cAAM,YAAY;AAClB,cAAM,cACJ;AACF,qBAAa,YAAY,KAAK;AAC9B;AAAA,MACF;AAEA,YAAM,OAAO,SAAS,cAAc,KAAK;AACzC,WAAK,YAAY;AAEjB,YAAM,SAAS,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AACpE,iBAAW,KAAK,QAAQ;AACtB,cAAM,MAAM,SAAS,cAAc,KAAK;AACxC,YAAI,YAAY;AAChB,cAAM,OAAO,SAAS,cAAc,KAAK;AACzC,aAAK,YAAY;AACjB,cAAM,MAAM,SAAS,cAAc,KAAK;AACxC,YAAI,YAAY;AAChB,YAAI,cAAc,GAAG,EAAE,IAAI,IAAI,EAAE,IAAI,IAAI,EAAE,GAAG;AAC9C,cAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,eAAO,YAAY;AACnB,eAAO,YAAY,wBAAwB,EAAE,MAAM,+DAA0D,EAAE,KAAK;AACpH,cAAM,OAAO,SAAS,cAAc,KAAK;AACzC,aAAK,YAAY;AACjB,aAAK,cAAc,aAAa,EAAE,SAAS;AAC3C,aAAK,YAAY,GAAG;AACpB,aAAK,YAAY,MAAM;AACvB,aAAK,YAAY,IAAI;AACrB,cAAM,OAAO,SAAS,cAAc,QAAQ;AAC5C,aAAK,YAAY;AACjB,aAAK,cAAc;AACnB,aAAK,QAAQ,OAAO,EAAE;AACtB,aAAK,QAAQ,OAAO,OAAO,EAAE,IAAI;AACjC,aAAK,QAAQ,MAAM,OAAO,EAAE,GAAG;AAC/B,YAAI,YAAY,IAAI;AACpB,YAAI,YAAY,IAAI;AACpB,aAAK,YAAY,GAAG;AAAA,MACtB;AACA,mBAAa,YAAY,IAAI;AAAA,IAC/B;AAGA,UAAM,cAAc,SAAS,cAAc,KAAK;AAChD,gBAAY,YAAY;AACxB,WAAO,YAAY,WAAW;AAG9B,UAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,aAAS,YAAY;AACrB,WAAO,YAAY,QAAQ;AAE3B,QAAI,iBAAqC;AAEzC,UAAM,eAAe,MAAM;AACzB,eAAS,MAAM,UAAU;AACzB,uBAAiB;AAAA,IACnB;AAQA,UAAM,eAAe,CAAC,OAAoB;AACxC,YAAM,cAAc,GAAG,aAAa,uBAAuB;AAC3D,YAAM,WAAW,GAAG,aAAa,kBAAkB;AACnD,UAAI,CAAC,eAAe,CAAC,SAAU;AAC/B,YAAM,OAAqB,cAAc,eAAe;AACxD,YAAM,WACJ,SAAS,eAAe,oBAAoB;AAE9C,YAAM,WAAW,GAAG,aAAa,uBAAuB;AACxD,YAAM,UAAU,GAAG,aAAa,sBAAsB;AACtD,YAAM,aAAa,GAAG,aAAa,kBAAkB;AACrD,YAAM,YAAY,GAAG,aAAa,iBAAiB;AAEnD,YAAM,MAAM,GAAG,aAAa,UAAU;AACtC,UAAI,CAAC,IAAK;AACV,YAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,UAAI,MAAM,SAAS,EAAG;AACtB,YAAM,UAAU,MAAM,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG;AAC3C,YAAM,OAAO,SAAS,MAAM,MAAM,SAAS,CAAC,GAAI,EAAE;AAClD,YAAM,MAAM,SAAS,MAAM,MAAM,SAAS,CAAC,GAAI,EAAE;AAEjD,uBAAiB;AACjB,eAAS,YAAY;AAErB,YAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,YAAM,YAAY;AAClB,YAAM,cACJ,SAAS,eAAe,eAAe;AACzC,eAAS,YAAY,KAAK;AAE1B,YAAM,OAAO,SAAS,cAAc,KAAK;AACzC,WAAK,YAAY;AACjB,WAAK,cACH,SAAS,eACL,IAAI,QAAQ,OAAO,OAAO,KAC1B,GAAG,UAAU,aAAa,SAAS;AACzC,eAAS,YAAY,IAAI;AAEzB,YAAM,QAAQ,CACZ,OACA,aACA,QACqB;AACrB,cAAM,MAAM,SAAS,cAAc,KAAK;AACxC,YAAI,YAAY;AAChB,cAAM,MAAM,SAAS,cAAc,MAAM;AACzC,YAAI,YAAY;AAChB,YAAI,cAAc;AAClB,cAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,cAAM,OAAO;AACb,cAAM,YAAY;AAClB,cAAM,cAAc;AACpB,cAAM,eAAe;AACrB,cAAM,aAAa;AACnB,YAAI,YAAY,GAAG;AACnB,YAAI,YAAY,KAAK;AACrB,iBAAS,YAAY,GAAG;AACxB,eAAO;AAAA,MACT;AACA,YAAM,YAAY,MAAM,YAAY,WAAW,gBAAgB;AAC/D,YAAM,WAAW,MAAM,SAAS,UAAU,eAAe;AAEzD,YAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,cAAQ,YAAY;AACpB,YAAM,WAAW,SAAS,cAAc,QAAQ;AAChD,eAAS,YAAY;AACrB,eAAS,cAAc;AACvB,YAAM,WAAW,SAAS,cAAc,QAAQ;AAChD,eAAS,YAAY;AACrB,eAAS,cAAc;AACvB,cAAQ,YAAY,QAAQ;AAC5B,cAAQ,YAAY,QAAQ;AAC5B,eAAS,YAAY,OAAO;AAE5B,YAAM,iBAAiB,CAAC,MAAc,SAA8B;AAClE,cAAM,WAAW,SAAS,cAAc,mBAAmB;AAC3D,kBAAU,OAAO;AACjB,cAAM,IAAI,SAAS,cAAc,KAAK;AACtC,UAAE,YAAY,oBAAoB,IAAI;AACtC,UAAE,cAAc;AAChB,iBAAS,YAAY,CAAC;AAAA,MACxB;AAEA,eAAS,iBAAiB,SAAS,YAAY;AAC7C,cAAM,WAAW,UAAU,MAAM,KAAK;AACtC,cAAM,QAAQ,SAAS,MAAM,KAAK;AAClC,YAAI,CAAC,YAAY,CAAC,OAAO;AACvB,yBAAe,yCAAyC,OAAO;AAC/D;AAAA,QACF;AACA,YAAI;AACF,gBAAM,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,QAAQ,IAAI;AAAA,YACxD,QAAQ;AAAA,YACR,MAAM,KAAK,UAAU;AAAA,cACnB,MAAM;AAAA,cACN;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF,CAAC;AAAA,UACH,CAAC;AACD,gBAAM,OAAQ,MAAM,IAAI,KAAK;AAQ7B,cAAI,IAAI,MAAM,KAAK,IAAI;AACrB,kBAAM,SACJ,cAAc,QAAQ,KAAK,WACvB,KAAK,WACL,mBAAmB,QAAQ,KAAK,gBAC9B,KAAK,gBACL;AACR,kBAAM,OAAO,KAAK,gBACd,GAAG,QAAQ,KAAK,KAAK,aAAa,WAAM,KAAK,KAC7C,GAAG,QAAQ,KAAK,KAAK;AACzB,2BAAe,cAAc,MAAM,WAAM,IAAI,IAAI,SAAS;AAC1D,sBAAU,QAAQ;AAClB,qBAAS,QAAQ;AACjB,sBAAU,MAAM;AAAA,UAClB,WAAW,CAAC,KAAK,IAAI;AACnB,2BAAe,YAAY,KAAK,MAAM,MAAM,KAAK,OAAO,IAAI,OAAO;AAAA,UACrE;AAAA,QACF,SAAS,KAAK;AACZ,yBAAe,kBAAmB,IAAc,OAAO,IAAI,OAAO;AAAA,QACpE;AAAA,MACF,CAAC;AAED,eAAS,iBAAiB,SAAS,MAAM;AACvC,qBAAa;AAAA,MACf,CAAC;AAED,eAAS,MAAM,UAAU;AAEzB,aAAO,WAAW,MAAM,UAAU,MAAM,GAAG,CAAC;AAAA,IAC9C;AAEA,UAAM,oBAAoB,OAAO,UAAsC;AACrE,UAAI,SAAmB,CAAC;AACxB,UAAI;AACF,cAAM,MAAM,MAAM,YAAY,GAAG,UAAU,WAAW,EAAE,QAAQ,MAAM,CAAC;AACvE,YAAI,IAAI,IAAI;AACV,gBAAM,OAAQ,MAAM,IAAI,KAAK;AAI7B,mBAAS,KAAK,UAAU,CAAC;AAAA,QAC3B;AAAA,MACF,QAAQ;AAAA,MAER;AAGA,YAAM,aAAc,MAA2B,aAAa,KAAK,KAAK;AAEtE,kBAAY,YAAY;AACxB,YAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,YAAM,YAAY;AAClB,YAAM,YAAY,mCAAmC,OAAO,MAAM;AAClE,kBAAY,YAAY,KAAK;AAE7B,UAAI,OAAO,WAAW,GAAG;AACvB,cAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,cAAM,YAAY;AAClB,cAAM,cACJ;AACF,oBAAY,YAAY,KAAK;AAC7B,oBAAY,MAAM,UAAU;AAC5B;AAAA,MACF;AAEA,YAAM,OAAO,SAAS,cAAc,KAAK;AACzC,WAAK,YAAY;AACjB,iBAAW,KAAK,QAAQ;AACtB,cAAM,MAAM,SAAS,cAAc,KAAK;AACxC,YAAI,YAAY,eAAe,MAAM,aAAa,aAAa;AAC/D,YAAI,QAAQ,QAAQ;AACpB,YAAI,YAAY,SAAS,CAAC,UAAU,MAAM,aAAa,+CAA+C,EAAE;AACxG,aAAK,YAAY,GAAG;AAAA,MACtB;AACA,kBAAY,YAAY,IAAI;AAC5B,kBAAY,MAAM,UAAU;AAAA,IAC9B;AAEA,UAAM,kBAAkB,MAAM;AAC5B,kBAAY,MAAM,UAAU;AAAA,IAC9B;AAEA,gBAAY,iBAAiB,SAAS,OAAO,MAAM;AACjD,YAAM,MAAO,EAAE,QAA+B;AAAA,QAC5C;AAAA,MACF;AACA,UAAI,CAAC,OAAO,CAAC,aAAc;AAC3B,YAAM,SAAS,IAAI,QAAQ;AAC3B,UAAI,CAAC,OAAQ;AAEb,YAAM,MAAM,aAAa,aAAa,UAAU;AAChD,UAAI,CAAC,IAAK;AACV,YAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,UAAI,MAAM,SAAS,EAAG;AACtB,YAAM,OAAO,MAAM,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG;AACxC,YAAM,OAAO,SAAS,MAAM,MAAM,SAAS,CAAC,GAAI,EAAE;AAClD,YAAM,MAAM,SAAS,MAAM,MAAM,SAAS,CAAC,GAAI,EAAE;AAEjD,UAAI;AACF,cAAM,MAAM,MAAM,YAAY,GAAG,UAAU,UAAU;AAAA,UACnD,QAAQ;AAAA,UACR,MAAM,KAAK,UAAU;AAAA,YACnB;AAAA,YACA;AAAA,YACA;AAAA,YACA,WAAW;AAAA,YACX,QAAQ;AAAA,YACR,OAAO;AAAA,UACT,CAAC;AAAA,QACH,CAAC;AACD,cAAM,OAAQ,MAAM,IAAI,KAAK;AAG7B,YAAI,IAAI,MAAM,KAAK,IAAI;AAErB,UAAC,aAAkC,MAAM;AACzC,0BAAgB;AAChB,qBAAW,oBAAoB,MAAM,IAAI,SAAS;AAAA,QACpD,WAAW,CAAC,KAAK,IAAI;AACnB,qBAAW,YAAY,KAAK,MAAM,MAAM,KAAK,OAAO,IAAI,OAAO;AAAA,QACjE;AAAA,MACF,SAAS,KAAK;AACZ;AAAA,UACE,kBAAmB,IAAc,OAAO;AAAA,UACxC;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,iBAAa,iBAAiB,SAAS,OAAO,MAAM;AAClD,YAAM,SAAS,EAAE;AACjB,UAAI,CAAC,UAAU,CAAC,OAAO,UAAU,SAAS,cAAc,EAAG;AAC3D,YAAM,OAAO,OAAO,QAAQ;AAC5B,YAAM,OAAO,OAAO,OAAO,QAAQ,IAAI;AACvC,YAAM,MAAM,OAAO,OAAO,QAAQ,GAAG;AACrC,UAAI;AACF,cAAM,YAAY,GAAG,UAAU,WAAW;AAAA,UACxC,QAAQ;AAAA,UACR,MAAM,KAAK,UAAU,EAAE,MAAM,MAAM,IAAI,CAAC;AAAA,QAC1C,CAAC;AACD,cAAM,cAAc;AAAA,MACtB,QAAQ;AAAA,MAER;AAAA,IACF,CAAC;AAGD,UAAM,UAAU,OAAO,cAAc,QAAQ;AAC7C,QAAI,SAAS;AACX,cAAQ,iBAAiB,SAAS,OAAO,MAAM;AAC7C,UAAE,gBAAgB;AAClB,cAAM,SAAS,aAAa,MAAM,YAAY;AAC9C,YAAI,QAAQ;AACV,uBAAa,MAAM,UAAU;AAAA,QAC/B,OAAO;AACL,gBAAM,cAAc;AACpB,uBAAa,MAAM,UAAU;AAAA,QAC/B;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,eAAe,SAAS,cAAc,KAAK;AACjD,iBAAa,YAAY;AACzB,WAAO,YAAY,YAAY;AAE/B,UAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,aAAS,YAAY;AACrB,WAAO,YAAY,QAAQ;AAG3B,UAAM,gBAAgB,CAAC,QAA8C;AACnE,YAAM,IAAI,SAAS,cAAc,KAAK;AACtC,QAAE,YAAY;AACd,aAAO,YAAY,CAAC;AACpB,aAAO;AAAA,IACT;AACA,UAAM,aAAa;AAAA,MACjB,QAAQ,cAAc,eAAe;AAAA,MACrC,UAAU,cAAc,eAAe;AAAA,MACvC,WAAW,cAAc,eAAe;AAAA,MACxC,SAAS,cAAc,eAAe;AAAA,MACtC,QAAQ,cAAc,kBAAkB;AAAA,MACxC,UAAU,cAAc,kBAAkB;AAAA,MAC1C,WAAW,cAAc,kBAAkB;AAAA,MAC3C,SAAS,cAAc,kBAAkB;AAAA,IAC3C;AAEA,UAAM,UAAU,CACd,IACA,SACA,MACA,KACA,OACA,WACG;AACH,UAAI,CAAC,WAAW,SAAS,KAAK,UAAU,GAAG;AACzC,WAAG,MAAM,UAAU;AACnB;AAAA,MACF;AACA,SAAG,MAAM,UAAU;AACnB,SAAG,MAAM,OAAO,GAAG,IAAI;AACvB,SAAG,MAAM,MAAM,GAAG,GAAG;AACrB,SAAG,MAAM,QAAQ,GAAG,KAAK;AACzB,SAAG,MAAM,SAAS,GAAG,MAAM;AAAA,IAC7B;AAEA,UAAM,kBAAkB,MAAM;AAC5B,iBAAW,MAAM,OAAO,OAAO,UAAU,EAAG,IAAG,MAAM,UAAU;AAAA,IACjE;AAEA,UAAM,mBAAmB,CAAC,IAAiB,SAAkB;AAC3D,YAAM,KAAK,iBAAiB,EAAE;AAC9B,YAAM,IAAI;AAAA,QACR,GAAG,WAAW,GAAG,UAAU,KAAK;AAAA,QAChC,GAAG,WAAW,GAAG,YAAY,KAAK;AAAA,QAClC,GAAG,WAAW,GAAG,aAAa,KAAK;AAAA,QACnC,GAAG,WAAW,GAAG,WAAW,KAAK;AAAA,MACnC;AACA,YAAM,IAAI;AAAA,QACR,GAAG,WAAW,GAAG,SAAS,KAAK;AAAA,QAC/B,GAAG,WAAW,GAAG,WAAW,KAAK;AAAA,QACjC,GAAG,WAAW,GAAG,YAAY,KAAK;AAAA,QAClC,GAAG,WAAW,GAAG,UAAU,KAAK;AAAA,MAClC;AAEA,cAAQ,WAAW,QAAQ,EAAE,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,KAAK,OAAO,EAAE,CAAC;AACxE;AAAA,QACE,WAAW;AAAA,QACX,EAAE,IAAI;AAAA,QACN,KAAK;AAAA,QACL,KAAK,SAAS,EAAE;AAAA,QAChB,KAAK;AAAA,QACL,EAAE;AAAA,MACJ;AACA;AAAA,QACE,WAAW;AAAA,QACX,EAAE,IAAI;AAAA,QACN,KAAK;AAAA,QACL,KAAK,MAAM,EAAE;AAAA,QACb,EAAE;AAAA,QACF,KAAK,SAAS,EAAE,IAAI,EAAE;AAAA,MACxB;AACA;AAAA,QACE,WAAW;AAAA,QACX,EAAE,IAAI;AAAA,QACN,KAAK,QAAQ,EAAE;AAAA,QACf,KAAK,MAAM,EAAE;AAAA,QACb,EAAE;AAAA,QACF,KAAK,SAAS,EAAE,IAAI,EAAE;AAAA,MACxB;AAIA;AAAA,QACE,WAAW;AAAA,QACX,EAAE,IAAI;AAAA,QACN,KAAK,OAAO,EAAE;AAAA,QACd,KAAK,MAAM,EAAE;AAAA,QACb,KAAK,QAAQ,EAAE,IAAI,EAAE;AAAA,QACrB,EAAE;AAAA,MACJ;AACA;AAAA,QACE,WAAW;AAAA,QACX,EAAE,IAAI;AAAA,QACN,KAAK,OAAO,EAAE;AAAA,QACd,KAAK;AAAA,QACL,KAAK,QAAQ,EAAE,IAAI,EAAE;AAAA,QACrB,EAAE;AAAA,MACJ;AACA,cAAQ,WAAW,SAAS,EAAE,IAAI,GAAG,KAAK,OAAO,EAAE,GAAG,KAAK,KAAK,EAAE,GAAG,KAAK,MAAM;AAChF,cAAQ,WAAW,UAAU,EAAE,IAAI,GAAG,KAAK,OAAO,KAAK,KAAK,EAAE,GAAG,KAAK,MAAM;AAAA,IAC9E;AAKA,UAAM,gBAAgB,SAAS,cAAc,KAAK;AAClD,kBAAc,YAAY;AAC1B,WAAO,YAAY,aAAa;AAChC,UAAM,gBAAgB,SAAS,cAAc,KAAK;AAClD,kBAAc,YAAY;AAC1B,WAAO,YAAY,aAAa;AAChC,UAAM,gBAAgB,SAAS,cAAc,KAAK;AAClD,kBAAc,YAAY;AAC1B,WAAO,YAAY,aAAa;AAChC,UAAM,gBAAgB,SAAS,cAAc,KAAK;AAClD,kBAAc,YAAY;AAC1B,WAAO,YAAY,aAAa;AAEhC,UAAM,aAA4B,CAAC;AAEnC,UAAM,oBAAoB,SAAS,cAAc,KAAK;AACtD,sBAAkB,YAAY;AAC9B,WAAO,YAAY,iBAAiB;AAKpC,UAAM,gBAAgB,SAAS,cAAc,KAAK;AAClD,kBAAc,YAAY;AAC1B,WAAO,YAAY,aAAa;AAEhC,UAAM,sBAAsB,CAAC,OAAoB;AAC/C,YAAM,SAAS,GAAG,UAAU,MAAM,KAAK,EAAE,OAAO,OAAO;AACvD,YAAM,gBAAgB;AACtB,YAAM,YAAY,CAAC,aACjB,OAAO;AAAA,QAAK,CAAC,MACX,SAAS;AAAA,UACP,CAAC,MACC,EAAE,WAAW,IAAI,GAAG,KACpB,cAAc,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;AAAA,QAC5C;AAAA,MACF;AACF,YAAM,OAAO,UAAU,CAAC,GAAG,CAAC;AAC5B,YAAM,OAAO,UAAU,CAAC,GAAG,CAAC;AAC5B,YAAM,SAAS,UAAU,CAAC,KAAK,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI,CAAC;AAClE,YAAM,SAAS,UAAU,CAAC,KAAK,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI,CAAC;AAClE,YAAM,SAAS,UAAU,CAAC,OAAO,SAAS,OAAO,CAAC;AAElD,YAAM,OAAO,CACX,OACA,MACA,YAEA,eAAe,UAAU,cAAc,UAAU,KAAK,IAAI,WAAM,KAAK,GAAG,UAAU,KAAK,6BAA6B;AAEtH,YAAM,QAAQ,GAAG,QAAQ,YAAY,MAAM;AAC3C,oBAAc,YACZ,gEACA,KAAK,yBAAyB,qBAAqB,QAAQ,IAAI,IAC/D,KAAK,sBAAsB,iDAA8C,MAAM,IAC/E,KAAK,UAAU,uCAAuC,MAAM,IAC5D,KAAK,mBAAmB,qCAAqC,MAAM,IACnE,KAAK,wBAAwB,+CAAqC,QAAQ,IAAI,IAC9E,KAAK,uBAAuB,gBAAgB,KAAK,IACjD;AACF,oBAAc,MAAM,UAAU;AAAA,IAChC;AAEA,UAAM,oBAAoB,MAAM;AAC9B,oBAAc,MAAM,UAAU;AAAA,IAChC;AAMA,UAAM,iBAAmD;AAAA,MACvD,KAAK,SAAS,cAAc,KAAK;AAAA,MACjC,OAAO,SAAS,cAAc,KAAK;AAAA,MACnC,QAAQ,SAAS,cAAc,KAAK;AAAA,MACpC,MAAM,SAAS,cAAc,KAAK;AAAA,IACpC;AACA,eAAW,QAAQ,CAAC,OAAO,SAAS,UAAU,MAAM,GAAY;AAC9D,YAAMA,KAAI,eAAe,IAAI;AAC7B,MAAAA,GAAE,YAAY,iCAAiC,IAAI;AACnD,aAAO,YAAYA,EAAC;AAAA,IACtB;AAEA,UAAM,qBAAqB,MAAM;AAC/B,iBAAW,QAAQ,CAAC,OAAO,SAAS,UAAU,MAAM,GAAY;AAC9D,uBAAe,IAAI,EAAE,MAAM,UAAU;AAAA,MACvC;AAAA,IACF;AAEA,UAAM,yBAAyB,CAAC,OAAoB;AAClD,YAAM,OAAO,GAAG,sBAAsB;AACtC,YAAM,KAAK,iBAAiB,EAAE;AAC9B,YAAM,KAAK,WAAW,GAAG,UAAU,KAAK;AACxC,YAAM,KAAK,WAAW,GAAG,YAAY,KAAK;AAC1C,YAAM,KAAK,WAAW,GAAG,aAAa,KAAK;AAC3C,YAAM,KAAK,WAAW,GAAG,WAAW,KAAK;AACzC,YAAM,gBAAgB,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK;AACzD,UAAI,CAAC,eAAe;AAClB,2BAAmB;AACnB;AAAA,MACF;AACA,YAAM,KAAK,KAAK,OAAO,KAAK,QAAQ;AACpC,YAAM,KAAK,KAAK,MAAM,KAAK,SAAS;AACpC,YAAM,SAAS,CAACA,IAAgB,GAAW,MAAc;AACvD,QAAAA,GAAE,MAAM,UAAU;AAClB,QAAAA,GAAE,MAAM,OAAO,GAAG,CAAC;AACnB,QAAAA,GAAE,MAAM,MAAM,GAAG,CAAC;AAAA,MACpB;AAEA,UAAI,KAAK,EAAG,QAAO,eAAe,KAAK,IAAI,KAAK,MAAM,EAAE;AAAA,UACnD,gBAAe,IAAI,MAAM,UAAU;AACxC,UAAI,KAAK,EAAG,QAAO,eAAe,QAAQ,IAAI,KAAK,SAAS,EAAE;AAAA,UACzD,gBAAe,OAAO,MAAM,UAAU;AAC3C,UAAI,KAAK,EAAG,QAAO,eAAe,MAAM,KAAK,OAAO,IAAI,EAAE;AAAA,UACrD,gBAAe,KAAK,MAAM,UAAU;AACzC,UAAI,KAAK,EAAG,QAAO,eAAe,OAAO,KAAK,QAAQ,IAAI,EAAE;AAAA,UACvD,gBAAe,MAAM,MAAM,UAAU;AAAA,IAC5C;AAEA,UAAM,aAAa,CAAC,UACjB;AAAA,MACC,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,GAAG,IAAI;AAET,UAAM,mBAAmB,CAAC,QAAqB,SAAsB;AACnE,aAAO,iBAAiB,eAAe,CAAC,OAAO;AAC7C,YAAI,CAAC,aAAc;AACnB,WAAG,eAAe;AAClB,WAAG,gBAAgB;AACnB,cAAM,SAAS;AACf,cAAM,SAAS,WAAW,IAAI;AAC9B,cAAM,SAAS,GAAG;AAClB,cAAM,SAAS,GAAG;AAClB,cAAM,WACJ,WAAW,iBAAiB,MAAM,EAAE,MAAM,CAAW,KAAK;AAC5D,eAAO,kBAAkB,GAAG,SAAS;AAErC,cAAM,SAAS,CAAC,OAAqB;AACnC,cAAI,QAAQ;AACZ,cAAI,SAAS,MAAO,SAAQ,GAAG,UAAU;AAAA,mBAChC,SAAS,SAAU,SAAQ,EAAE,GAAG,UAAU;AAAA,mBAC1C,SAAS,OAAQ,SAAQ,GAAG,UAAU;AAAA,mBACtC,SAAS,QAAS,SAAQ,EAAE,GAAG,UAAU;AAClD,gBAAM,OAAO,KAAK,IAAI,GAAG,WAAW,KAAK;AACzC,iBAAO,MAAM,MAAM,IAAI,GAAG,IAAI;AAC9B,iCAAuB,MAAM;AAAA,QAC/B;AACA,cAAM,OAAO,CAAC,OAAqB;AACjC,iBAAO,sBAAsB,GAAG,SAAS;AACzC,mBAAS,oBAAoB,eAAe,MAAM;AAClD,mBAAS,oBAAoB,aAAa,IAAI;AAC9C,gBAAM,UACJ,WAAW,iBAAiB,MAAM,EAAE,MAAM,CAAW,KAAK;AAC5D,mCAAyB,QAAQ,MAAM,OAAO;AAAA,QAChD;AACA,iBAAS,iBAAiB,eAAe,MAAM;AAC/C,iBAAS,iBAAiB,aAAa,IAAI;AAAA,MAC7C,CAAC;AAAA,IACH;AACA,eAAW,QAAQ,CAAC,OAAO,SAAS,UAAU,MAAM,GAAY;AAC9D,uBAAiB,eAAe,IAAI,GAAG,IAAI;AAAA,IAC7C;AAEA,UAAM,cAA2C;AAAA,MAC/C,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,MAAM;AAAA,IACR;AACA,UAAM,cAAgD;AAAA,MACpD,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,IACT;AAMA,UAAM,2BAA2B,CAC/B,QACA,MACA,UACG;AACH,YAAM,aAAa,YAAY,IAAI;AACnC,YAAM,aAAa,YAAY,IAAI;AACnC,YAAM,SAAS,OAAO,UAAU,MAAM,KAAK,EAAE,OAAO,OAAO;AAC3D,YAAM,gBAAgB;AAEtB,YAAM,YAAY,OAAO;AAAA,QACvB,CAAC,MACC,EAAE,WAAW,aAAa,GAAG,KAC7B,cAAc,KAAK,EAAE,MAAM,WAAW,SAAS,CAAC,CAAC;AAAA,MACrD;AAEA,YAAM,YAAY,aAAa;AAC/B,YAAM,OAAO,eAAe,OAAO,SAAS;AAE5C,UAAI,WAAW;AACb,cAAM,WAAW,GAAG,UAAU,IAAI,KAAK,MAAM;AAC7C,YAAI,aAAa,WAAW;AAC1B,4BAAkB,MAAM;AACxB;AAAA,QACF;AACA,2BAAmB,QAAQ,WAAW,UAAU,KAAK,UAAU;AAC/D;AAAA,MACF;AAEA,YAAM,YAAY,OAAO;AAAA,QACvB,CAAC,MACC,EAAE,WAAW,aAAa,GAAG,KAC7B,cAAc,KAAK,EAAE,MAAM,WAAW,SAAS,CAAC,CAAC;AAAA,MACrD;AACA,YAAM,aAAa,OAAO;AAAA,QACxB,CAAC,MACC,EAAE,WAAW,IAAI,KAAK,cAAc,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;AAAA,MACjE;AACA,YAAM,OAAO,aAAa;AAC1B,UAAI,CAAC,MAAM;AACT;AAAA,UACE,8CAA8C,UAAU,UAAU,UAAU;AAAA,UAC5E;AAAA,QACF;AACA,0BAAkB,MAAM;AACxB;AAAA,MACF;AACA,YAAM,gBAAgB,GAAG,UAAU,IAAI,KAAK,MAAM;AAIlD;AAAA,QACE;AAAA,QACA;AAAA,QACA,GAAG,IAAI,IAAI,aAAa;AAAA,QACxB,KAAK;AAAA,MACP;AAAA,IACF;AAEA,UAAM,eAAe,SAAS,cAAc,KAAK;AACjD,iBAAa,YAAY;AACzB,WAAO,YAAY,YAAY;AAE/B,QAAI,WAA4B;AAChC,QAAI,eAAmC;AACvC,QAAI,cAAkC;AACtC,QAAI,QAAQ;AACZ,QAAI,aAAa;AACjB,QAAI,aAAa;AACjB,QAAI,kBAAiC;AACrC,QAAI,UAAgC;AACpC,UAAM,mBAAkC,CAAC;AAOzC,UAAM,iBAAiB,CAAC,QAA+B;AAGrD,YAAM,UAAU,IAAI,QAAQ,MAAM,KAAK;AACvC,YAAM,QAAQ,SAAS,iBAAiB,cAAc,OAAO,IAAI;AACjE,YAAM,MAAqB,CAAC;AAC5B,YAAM,QAAQ,CAAC,MAAM;AACnB,YAAI,aAAa,YAAa,KAAI,KAAK,CAAC;AAAA,MAC1C,CAAC;AACD,aAAO;AAAA,IACT;AAEA,UAAM,wBAAwB,MAAM;AAClC,iBAAW,QAAQ,iBAAkB,MAAK,OAAO;AACjD,uBAAiB,SAAS;AAAA,IAC5B;AAEA,UAAM,uBAAuB,CAAC,WAA0B,aAA0B;AAChF,4BAAsB;AACtB,iBAAW,MAAM,WAAW;AAC1B,YAAI,OAAO,SAAU;AACrB,cAAM,OAAO,GAAG,sBAAsB;AACtC,YAAI,KAAK,UAAU,KAAK,KAAK,WAAW,EAAG;AAC3C,cAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,gBAAQ,YAAY;AACpB,gBAAQ,MAAM,OAAO,GAAG,KAAK,IAAI;AACjC,gBAAQ,MAAM,MAAM,GAAG,KAAK,GAAG;AAC/B,gBAAQ,MAAM,QAAQ,GAAG,KAAK,KAAK;AACnC,gBAAQ,MAAM,SAAS,GAAG,KAAK,MAAM;AACrC,eAAO,YAAY,OAAO;AAC1B,yBAAiB,KAAK,OAAO;AAAA,MAC/B;AAAA,IACF;AAEA,UAAM,cAAc,CAAC,QAAuB,eAAuB;AACjE,gBAAU;AACV,mBAAa,YAAY;AACzB,yBAAmB;AAEnB,YAAM,MAAM,OAAO,QAAQ,aAAa,UAAU;AAKlD,UAAI,KAAK;AACP,kBAAU;AAAA,UACR,MAAM,OAAO;AAAA,UACb,MAAM,OAAO;AAAA,UACb,KAAK,OAAO;AAAA,UACZ,QAAQ,OAAO;AAAA,UACf,OAAO,OAAO;AAAA,UACd;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAEA,YAAM,YAAY,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,OAAO;AAC7D,YAAM,gBAAgB,UAAU;AAEhC,YAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,aAAO,YAAY;AACnB,aAAO,cAAc,GAAG,OAAO,IAAI,IAAI,OAAO,IAAI,IAAI,OAAO,GAAG;AAEhE,YAAM,OAAO,SAAS,cAAc,KAAK;AACzC,WAAK,YAAY;AACjB,WAAK,YACH,wBAAwB,OAAO,MAAM,+DAEd,OAAO,KAAK,iCACT,KAAK,MAAM,UAAU,CAAC;AAElD,mBAAa,YAAY,MAAM;AAC/B,mBAAa,YAAY,IAAI;AAG7B,UAAI,gBAAgB,GAAG;AACrB,cAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,eAAO,YAAY;AACnB,eAAO,cAAc,SAAS,aAAa;AAC3C,qBAAa,YAAY,MAAM;AAC/B,6BAAqB,WAAW,OAAO,OAAO;AAAA,MAChD,OAAO;AACL,8BAAsB;AAAA,MACxB;AAEA,YAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,cAAQ,YAAY;AACpB,YAAM,QAAQ,SAAS,cAAc,QAAQ;AAC7C,YAAM,YAAY;AAClB,YAAM,cAAc,gBAAgB,IAAI,YAAY,aAAa,KAAK;AACtE,YAAM,UAAU,SAAS,cAAc,QAAQ;AAC/C,cAAQ,YAAY;AACpB,cAAQ,cAAc;AACtB,cAAQ,YAAY,KAAK;AACzB,cAAQ,YAAY,OAAO;AAC3B,mBAAa,YAAY,OAAO;AAChC,mBAAa,MAAM,UAAU;AAAA,IAC/B;AAEA,UAAM,oBAAoB,CAAC,OAAoB;AAC7C,SAAG,MAAM,QAAQ;AACjB,SAAG,MAAM,SAAS;AAClB,SAAG,MAAM,YAAY;AAGrB,SAAG,MAAM,aAAa;AACtB,SAAG,MAAM,eAAe;AACxB,SAAG,MAAM,gBAAgB;AACzB,SAAG,MAAM,cAAc;AAAA,IACzB;AAEA,UAAM,cAAc,MAAM;AACxB,gBAAU;AACV,mBAAa,MAAM,UAAU;AAC7B,4BAAsB;AACtB,iBAAW;AAAA,IACb;AAEA,QAAI,qBAAoC;AACxC,QAAI,cAAoC;AAExC,UAAM,aAAa,CAAC,SAAiB,SAA8B;AACjE,mBAAa,YAAY;AACzB,YAAM,IAAI,SAAS,cAAc,KAAK;AACtC,QAAE,YAAY,kBAAkB,IAAI;AACpC,QAAE,cAAc;AAChB,mBAAa,YAAY,CAAC;AAC1B,mBAAa,MAAM,UAAU;AAC7B,UAAI,uBAAuB,KAAM,QAAO,aAAa,kBAAkB;AACvE,2BAAqB,OAAO,WAAW,MAAM;AAC3C,YAAI,CAAC,QAAS,cAAa,MAAM,UAAU;AAAA,MAC7C,GAAG,IAAI;AAAA,IACT;AAIA,UAAM,sBAAsB,CAAC,WAA0B;AACrD,oBAAc;AACd,mBAAa,YAAY;AAEzB,YAAM,IAAI,SAAS,cAAc,KAAK;AACtC,QAAE,YAAY;AACd,QAAE,cAAc,YAAY,OAAO,MAAM,WAAM,OAAO,KAAK;AAC3D,mBAAa,YAAY,CAAC;AAE1B,YAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,cAAQ,YAAY;AACpB,YAAM,OAAO,SAAS,cAAc,QAAQ;AAC5C,WAAK,YAAY;AACjB,WAAK,cAAc;AACnB,YAAM,UAAU,SAAS,cAAc,QAAQ;AAC/C,cAAQ,YAAY;AACpB,cAAQ,cAAc;AACtB,cAAQ,YAAY,IAAI;AACxB,cAAQ,YAAY,OAAO;AAC3B,mBAAa,YAAY,OAAO;AAChC,mBAAa,MAAM,UAAU;AAE7B,UAAI,uBAAuB,KAAM,QAAO,aAAa,kBAAkB;AACvE,2BAAqB,OAAO,WAAW,MAAM;AAC3C,YAAI,CAAC,QAAS,cAAa,MAAM,UAAU;AAC3C,sBAAc;AAAA,MAChB,GAAG,GAAI;AAAA,IACT;AAEA,iBAAa,iBAAiB,SAAS,OAAO,MAAM;AAClD,YAAM,SAAS,EAAE;AACjB,UAAI,CAAC,UAAU,CAAC,QAAS;AACzB,YAAM,SAAS;AACf,UAAI,OAAO,UAAU,SAAS,WAAW,GAAG;AAC1C,YAAI;AACF,gBAAM,MAAM,MAAM,YAAY,GAAG,UAAU,UAAU;AAAA,YACnD,QAAQ;AAAA,YACR,MAAM,KAAK,UAAU;AAAA,cACnB,MAAM,OAAO;AAAA,cACb,MAAM,OAAO;AAAA,cACb,KAAK,OAAO;AAAA,cACZ,QAAQ,OAAO;AAAA,cACf,OAAO,OAAO;AAAA,YAChB,CAAC;AAAA,UACH,CAAC;AACD,gBAAM,OAAQ,MAAM,IAAI,KAAK;AAG7B,cAAI,IAAI,MAAM,KAAK,IAAI;AAQrB,kBAAM,MAAM,OAAO,QAAQ,aAAa,UAAU;AAClD,kBAAM,UAAU,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,OAAO;AAC3D,uBAAWC,WAAU,SAAS;AAC5B,cAAAA,QAAO,YAAY;AAAA,gBACjBA,QAAO;AAAA,gBACP,OAAO;AAAA,gBACP,OAAO;AAAA,cACT;AACA,gCAAkBA,OAAM;AAAA,YAC1B;AACA,sBAAU;AACV,kCAAsB;AACtB,uBAAW;AAKX,gCAAoB,MAAM;AAI1B,gBAAI,aAAc,wBAAuB,YAAY;AAAA,UACvD,WAAW,CAAC,KAAK,IAAI;AACnB,uBAAW,YAAY,KAAK,MAAM,MAAM,KAAK,OAAO,IAAI,OAAO;AAAA,UACjE;AAAA,QACF,SAAS,KAAK;AACZ;AAAA,YACE,kBAAmB,IAAc,OAAO;AAAA,YACxC;AAAA,UACF;AAAA,QACF;AAAA,MACF,WAAW,OAAO,UAAU,SAAS,aAAa,GAAG;AAGnD,YAAI,SAAS;AACX,4BAAkB,QAAQ,OAAO;AACjC,sBAAY;AAAA,QACd,OAAO;AACL,uBAAa,MAAM,UAAU;AAC7B,wBAAc;AAAA,QAChB;AACA,YAAI,aAAc,wBAAuB,YAAY;AAAA,MACvD,WAAW,OAAO,UAAU,SAAS,UAAU,KAAK,aAAa;AAC/D,cAAMC,UAAS;AACf,YAAI;AACF,gBAAM,MAAM,MAAM,YAAY,GAAG,UAAU,WAAW;AAAA,YACpD,QAAQ;AAAA,YACR,MAAM,KAAK,UAAU;AAAA,cACnB,MAAMA,QAAO;AAAA,cACb,MAAMA,QAAO;AAAA,cACb,KAAKA,QAAO;AAAA,YACd,CAAC;AAAA,UACH,CAAC;AACD,gBAAM,OAAQ,MAAM,IAAI,KAAK;AAG7B,cAAI,IAAI,MAAM,KAAK,IAAI;AACrB,0BAAc;AACd,uBAAW,aAAaA,QAAO,KAAK,WAAMA,QAAO,MAAM,IAAI,SAAS;AAAA,UACtE,WAAW,CAAC,KAAK,IAAI;AACnB;AAAA,cACE,mBAAmB,KAAK,MAAM,MAAM,KAAK,OAAO;AAAA,cAChD;AAAA,YACF;AAAA,UACF;AAAA,QACF,SAAS,KAAK;AACZ;AAAA,YACE,8BAA+B,IAAc,OAAO;AAAA,YACpD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,cAAc,CAAC,OAAgC;AACnD,UAAI,CAAC,GAAI,QAAO;AAChB,UAAI,GAAG,QAAQ,YAAY,MAAM,WAAY,QAAO;AACpD,UAAI,GAAG,QAAQ,UAAU,EAAG,QAAO;AAEnC,UAAI,GAAG,QAAQ,gCAAgC,EAAG,QAAO;AACzD,UAAI,GAAG,QAAQ,eAAe,EAAG,QAAO;AACxC,aAAO;AAAA,IACT;AAEA,UAAM,uBAAuB,MAAM;AACjC,oBAAc,MAAM,UAAU;AAC9B,oBAAc,MAAM,UAAU;AAC9B,oBAAc,MAAM,UAAU;AAC9B,oBAAc,MAAM,UAAU;AAAA,IAChC;AAEA,UAAM,sBAAsB,CAACC,SAAqB,YAAyB;AACzE,UAAIA,YAAW,SAAS;AACtB,6BAAqB;AACrB;AAAA,MACF;AACA,YAAM,IAAIA,QAAO,sBAAsB;AACvC,YAAM,IAAI,QAAQ,sBAAsB;AAExC,oBAAc,MAAM,UAAU;AAC9B,oBAAc,MAAM,OAAO,GAAG,EAAE,IAAI;AACpC,oBAAc,MAAM,MAAM,GAAG,EAAE,GAAG;AAClC,oBAAc,MAAM,QAAQ,GAAG,EAAE,KAAK;AACtC,oBAAc,MAAM,SAAS,GAAG,EAAE,MAAM;AAKxC,UAAI,KAAK;AACT,UAAI,EAAE,QAAQ,EAAE,MAAO,MAAK,EAAE,OAAO,EAAE;AAAA,eAC9B,EAAE,SAAS,EAAE,KAAM,MAAK,EAAE,QAAQ,EAAE;AAC7C,UAAI,KAAK;AACT,UAAI,EAAE,OAAO,EAAE,OAAQ,MAAK,EAAE,MAAM,EAAE;AAAA,eAC7B,EAAE,UAAU,EAAE,IAAK,MAAK,EAAE,SAAS,EAAE;AAI9C,YAAM,MAAM,EAAE,OAAO,EAAE,SAAS;AAChC,YAAM,MAAM,EAAE,MAAM,EAAE,UAAU;AAChC,YAAM,MAAM,EAAE,OAAO,EAAE,SAAS;AAChC,YAAM,MAAM,EAAE,MAAM,EAAE,UAAU;AAChC,YAAM,MAAM,KAAK,MAAM;AACvB,YAAM,MAAM,KAAK,MAAM;AACvB,oBAAc,cAAc,UAAK,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC,kBAAU,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;AAC3F,oBAAc,MAAM,UAAU;AAC9B,oBAAc,MAAM,OAAO,GAAG,KAAK,CAAC;AACpC,oBAAc,MAAM,MAAM,GAAG,KAAK,CAAC;AAInC,YAAM,YAAY,MAAM;AACtB,cAAM,IAAI;AACV,cAAM,KAAK,KAAK,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK,IAAI,EAAE,MAAM,EAAE,IAAI;AAAA;AAAA,UAE3D;AAAA,YACA,KAAK,KAAK,EAAE,QAAQ,EAAE;AAC1B,cAAM,KAAK,OAAO,OAAO,OAAO,KAAK,KAAK,EAAE,OAAO,EAAE;AACrD,YAAI,OAAO,QAAQ,OAAO,MAAM;AAC9B,wBAAc,MAAM,UAAU;AAC9B;AAAA,QACF;AACA,sBAAc,MAAM,UAAU;AAC9B,sBAAc,MAAM,OAAO,GAAG,KAAK,IAAI,IAAI,EAAE,CAAC;AAC9C,sBAAc,MAAM,MAAM,GAAG,CAAC;AAC9B,sBAAc,MAAM,QAAQ,GAAG,KAAK,IAAI,KAAK,EAAE,CAAC;AAChD,sBAAc,MAAM,SAAS;AAAA,MAC/B;AACA,YAAM,YAAY,MAAM;AACtB,cAAM,IAAI;AACV,cAAM,KAAK,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,EAAE,KAAK,EAAE,GAAG,IAC3D,OACA,KAAK,KAAK,EAAE,SAAS,EAAE;AAC3B,cAAM,KAAK,OAAO,OAAO,OAAO,KAAK,KAAK,EAAE,MAAM,EAAE;AACpD,YAAI,OAAO,QAAQ,OAAO,MAAM;AAC9B,wBAAc,MAAM,UAAU;AAC9B;AAAA,QACF;AACA,sBAAc,MAAM,UAAU;AAC9B,sBAAc,MAAM,OAAO,GAAG,CAAC;AAC/B,sBAAc,MAAM,MAAM,GAAG,KAAK,IAAI,IAAI,EAAE,CAAC;AAC7C,sBAAc,MAAM,QAAQ;AAC5B,sBAAc,MAAM,SAAS,GAAG,KAAK,IAAI,KAAK,EAAE,CAAC;AAAA,MACnD;AACA,gBAAU;AACV,gBAAU;AAAA,IACZ;AAEA,UAAM,aAAa,MAAM;AACvB,mBAAa,MAAM,UAAU;AAC7B,eAAS,MAAM,UAAU;AACzB,sBAAgB;AAChB,2BAAqB;AACrB,oBAAc;AAAA,IAChB;AAEA,UAAM,cAAc,CAAC,OAAoB;AACvC,YAAM,OAAO,GAAG,sBAAsB;AACtC,UAAI,KAAK,UAAU,KAAK,KAAK,WAAW,GAAG;AACzC,mBAAW;AACX;AAAA,MACF;AACA,mBAAa,MAAM,UAAU;AAC7B,mBAAa,MAAM,OAAO,GAAG,KAAK,IAAI;AACtC,mBAAa,MAAM,MAAM,GAAG,KAAK,GAAG;AACpC,mBAAa,MAAM,QAAQ,GAAG,KAAK,KAAK;AACxC,mBAAa,MAAM,SAAS,GAAG,KAAK,MAAM;AAC1C,uBAAiB,IAAI,IAAI;AAEzB,YAAM,MAAM,GAAG,aAAa,UAAU;AAOtC,YAAM,YAAY,iBAAiB,EAAE;AACrC,YAAM,WAAW,gBAAgB,GAAG;AACpC,YAAM,gBACJ,aACC,aAAa,CAAC,oBAAoB,IAAI,SAAS,IAAI,YAAY;AAClE,YAAM,UAAU,GAAG,QAAQ,YAAY;AACvC,YAAM,WAAW,OAAO;AAExB,eAAS,YAAY;AACrB,UAAI,eAAe;AACjB,cAAM,IAAI,SAAS,cAAc,MAAM;AACvC,UAAE,YAAY;AACd,UAAE,cAAc,IAAI,aAAa;AACjC,iBAAS,YAAY,CAAC;AAAA,MACxB;AACA,YAAM,IAAI,SAAS,cAAc,MAAM;AACvC,QAAE,YAAY;AACd,QAAE,cAAc;AAChB,eAAS,YAAY,CAAC;AACtB,YAAM,IAAI,SAAS,cAAc,MAAM;AACvC,QAAE,YAAY;AACd,QAAE,cAAc;AAChB,eAAS,YAAY,CAAC;AAEtB,eAAS,MAAM,UAAU;AAEzB,YAAM,OAAO;AACb,YAAM,QAAQ,KAAK,MAAM,OAAO;AAChC,YAAM,QAAQ,KAAK,SAAS;AAC5B,eAAS,MAAM,OAAO,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,CAAC;AAC/C,eAAS,MAAM,MAAM,GAAG,QAAQ,IAAI,QAAQ,KAAK;AAAA,IACnD;AAEA,UAAM,cAAc,CAAC,MAAkB;AACrC,mBAAa,EAAE;AACf,mBAAa,EAAE;AAIf,YAAMA,WACH,WAAW,eAAe,SAAS,WAAW,CAAC,KAAK;AACvD,UAAI,EAAE,UAAUA,SAAQ;AACtB,YAAI,MAAO;AACX,gBAAQ,sBAAsB,MAAM;AAClC,kBAAQ;AACR,gBAAM,SAAS,SAAS,iBAAiB,YAAY,UAAU;AAC/D,cAAI,EAAE,kBAAkB,gBAAgB,YAAY,MAAM,GAAG;AAC3D,iCAAqB;AACrB;AAAA,UACF;AACA,8BAAoBA,SAAQ,MAAM;AAAA,QACpC,CAAC;AACD;AAAA,MACF;AACA,2BAAqB;AAErB,UAAI,SAAU;AACd,UAAI,MAAO;AACX,cAAQ,sBAAsB,MAAM;AAClC,gBAAQ;AACR,cAAM,SAAS,SAAS,iBAAiB,YAAY,UAAU;AAC/D,YAAI,EAAE,kBAAkB,gBAAgB,YAAY,MAAM,GAAG;AAC3D,qBAAW;AACX;AAAA,QACF;AACA,YAAI,WAAW,YAAa;AAC5B,sBAAc;AACd,oBAAY,MAAM;AAAA,MACpB,CAAC;AAAA,IACH;AAEA,UAAM,mBAAmB,MAAM;AAC7B,UAAI,SAAS;AACX,cAAM,MAAM,QAAQ,QAAQ,aAAa,UAAU;AACnD,YAAI,KAAK;AACP,gBAAM,YAAY,eAAe,GAAG;AACpC,+BAAqB,WAAW,QAAQ,OAAO;AAAA,QACjD;AAAA,MACF;AACA,UAAI,YAAY,cAAc;AAC5B,+BAAuB,YAAY;AAAA,MACrC;AACA,UAAI,SAAU;AACd,YAAM,SAAS,SAAS,iBAAiB,YAAY,UAAU;AAC/D,UAAI,kBAAkB,eAAe,CAAC,YAAY,MAAM,GAAG;AACzD,sBAAc;AACd,oBAAY,MAAM;AAAA,MACpB,OAAO;AACL,mBAAW;AAAA,MACb;AAAA,IACF;AAEA,UAAM,eAAe,MAAM,WAAW;AAEtC,UAAM,wBAAwB,CAAC,OAAoB;AACjD,YAAM,MAAM,GAAG,aAAa,UAAU;AACtC,UAAI,CAAC,IAAK;AACV,YAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,UAAI,MAAM,SAAS,EAAG;AACtB,YAAM,OAAO,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,EAAE,KAAK,GAAG;AACtD,YAAM,OAAO,SAAS,MAAM,MAAM,SAAS,CAAC,GAAI,EAAE;AAClD,YAAM,MAAM,SAAS,MAAM,MAAM,SAAS,CAAC,GAAI,EAAE;AACjD,UAAI,CAAC,OAAO,UAAU,IAAI,KAAK,CAAC,OAAO,UAAU,GAAG,EAAG;AAEvD,YAAM,YAAY,iBAAiB,EAAE;AACrC,YAAM,WAAW,gBAAgB,GAAG;AACpC,YAAM,gBACJ,aACC,aAAa,CAAC,oBAAoB,IAAI,SAAS,IAAI,YAAY;AAElE,YAAM,YAAY,eAAe,GAAG;AAIpC,WAAK,YAAY,GAAG,UAAU,cAAc;AAAA,QAC1C,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW,GAAG;AAAA,UACd,SAAS,GAAG,QAAQ,YAAY;AAAA,UAChC;AAAA,UACA,eAAe,UAAU;AAAA,QAC3B,CAAC;AAAA,MACH,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACnB;AAEA,UAAM,yBAAyB,MAAM;AACnC,WAAK,YAAY,GAAG,UAAU,cAAc;AAAA,QAC1C,QAAQ;AAAA,MACV,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACnB;AAEA,UAAM,UAAU,CAAC,OAAoB;AACnC,UAAI,OAAO,aAAc;AACzB,UAAI,YAAY,EAAE,EAAG;AAErB,UAAI,SAAS;AACX,0BAAkB,QAAQ,OAAO;AACjC,oBAAY;AAAA,MACd;AACA,qBAAe;AACf,wBAAkB;AAClB,iBAAW;AACX,4BAAsB,EAAE;AAExB,UAAI,SAAU,UAAS,QAAQ;AAK/B,YAAM,SAAS,GAAG;AAClB,YAAM,oBAAmC,SACrC,MAAM,KAAK,OAAO,QAAQ,EAAE;AAAA,QAC1B,CAAC,MAAwB,aAAa,eAAe,MAAM;AAAA,MAC7D,IACA,CAAC;AAEL,iBAAW,IAAI,SAAS,mBAAmB;AAAA,QACzC,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,WAAW;AAAA,QACX,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,gBAAgB,EAAE,KAAK,MAAM,MAAM,MAAM,QAAQ,MAAM,OAAO,MAAM,QAAQ,MAAM,QAAQ,KAAK;AAAA,QAC/F,uBAAuB,EAAE,KAAK,MAAM,MAAM,MAAM,QAAQ,MAAM,OAAO,MAAM,QAAQ,MAAM,QAAQ,KAAK;AAAA,QACtG,eAAe;AAAA,QACf;AAAA,MACF,CAAC;AACD,eAAS,GAAG,QAAQ,CAAC,EAAE,QAAQ,UAAU,MAAM;AAC7C,cAAM,IAAI;AACV,UAAE,MAAM,YAAY;AACpB,+BAAuB,CAAC;AACxB,yBAAiB,GAAG,EAAE,sBAAsB,CAAC;AAAA,MAC/C,CAAC;AACD,eAAS,GAAG,UAAU,CAAC,EAAE,QAAQ,OAAO,OAAO,MAAM;AACnD,cAAM,IAAI;AACV,UAAE,MAAM,QAAQ,GAAG,KAAK;AACxB,UAAE,MAAM,SAAS,GAAG,MAAM;AAC1B,0BAAkB;AAClB,+BAAuB,CAAC;AACxB,yBAAiB,GAAG,EAAE,sBAAsB,CAAC;AAAA,MAC/C,CAAC;AACD,6BAAuB,EAAE;AAIzB,uBAAiB,IAAI,GAAG,sBAAsB,CAAC;AAC/C,0BAAoB,EAAE;AAKtB,UACE,GAAG,aAAa,uBAAuB,KACvC,GAAG,aAAa,kBAAkB,GAClC;AACA,qBAAa,EAAE;AAAA,MACjB,OAAO;AACL,qBAAa;AAAA,MACf;AACA,eAAS,GAAG,aAAa,CAAC,EAAE,OAAO,MAAM;AACvC,cAAMC,MAAK;AACX,YAAI,oBAAoB,KAAM;AAC9B,cAAM,aAAa;AACnB,0BAAkB;AAElB,cAAM,SAASA,IAAG,UAAU,MAAM,KAAK,EAAE,OAAO,OAAO;AACvD,cAAM,aAAa,OAAO,KAAK,CAAC,MAAM,eAAe,KAAK,CAAC,CAAC;AAC5D,YAAI,CAAC,YAAY;AAEf,gBAAM,gBAAgB;AACtB,gBAAM,SAAS,OAAO;AAAA,YAAK,CAAC,MAC1B,CAAC,KAAK,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI,EAAE;AAAA,cACxC,CAAC,MACC,EAAE,WAAW,IAAI,GAAG,KACpB,cAAc,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;AAAA,YAC5C;AAAA,UACF;AACA,gBAAM,aAAa,SACf,sEACA;AACJ,qBAAW,iCAAiC,UAAU,IAAI,OAAO;AACjE;AAAA,QACF;AAEA,cAAM,YAAY,aAAa;AAC/B,cAAM,OAAO,eAAe,YAAY,SAAS;AACjD,cAAM,WAAW,KAAK,KAAK,MAAM;AACjC,YAAI,aAAa,YAAY;AAC3B,4BAAkBA,GAAE;AACpB;AAAA,QACF;AACA,2BAAmBA,KAAI,YAAY,UAAU,KAAK,UAAU;AAAA,MAC9D,CAAC;AAAA,IACH;AAMA,UAAM,qBAAqB,CACzB,IACA,QACA,OACA,eACG;AACH,YAAM,MAAM,GAAG,aAAa,UAAU;AACtC,UAAI,CAAC,KAAK;AACR;AAAA,UACE;AAAA,UACA;AAAA,QACF;AACA;AAAA,MACF;AACA,YAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,UAAI,MAAM,SAAS,GAAG;AACpB,mBAAW,uBAAuB,GAAG,IAAI,OAAO;AAChD;AAAA,MACF;AACA,YAAM,OAAO,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,EAAE,KAAK,GAAG;AACtD,YAAM,OAAO,SAAS,MAAM,MAAM,SAAS,CAAC,GAAI,EAAE;AAClD,YAAM,MAAM,SAAS,MAAM,MAAM,SAAS,CAAC,GAAI,EAAE;AACjD,UAAI,CAAC,OAAO,UAAU,IAAI,KAAK,CAAC,OAAO,UAAU,GAAG,GAAG;AACrD,mBAAW,uBAAuB,GAAG,IAAI,OAAO;AAChD;AAAA,MACF;AACA;AAAA,QACE,EAAE,SAAS,IAAI,MAAM,MAAM,KAAK,QAAQ,MAAM;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAWA,UAAM,iBAAiB,CAAC,MAA8B;AACpD,UAAI,CAAC,aAAc,QAAO;AAE1B,UAAI,WAAqC;AACzC,UAAI,YAAkC;AAKtC,UAAI,EAAE,UAAU,EAAE,QAAQ,cAAc;AACtC,mBAAW;AACX,oBAAY;AAAA,MACd,WAAW,EAAE,UAAU,EAAE,QAAQ,aAAa;AAC5C,mBAAW;AACX,oBAAY;AAAA,MACd,WAAW,EAAE,UAAU,EAAE,QAAQ,aAAa;AAC5C,mBAAW;AACX,oBAAY;AAAA,MACd,WAAW,EAAE,UAAU,EAAE,QAAQ,WAAW;AAC1C,mBAAW;AACX,oBAAY;AAAA,MACd,WAAW,EAAE,WAAW,EAAE,QAAQ,OAAO,EAAE,QAAQ,MAAM;AACvD,mBAAW;AACX,oBAAY;AAAA,MACd,WAAW,EAAE,WAAW,EAAE,QAAQ,OAAO,EAAE,QAAQ,MAAM;AACvD,mBAAW;AACX,oBAAY;AAAA,MACd,WAAW,EAAE,QAAQ,OAAQ,EAAE,QAAQ,OAAO,EAAE,UAAW;AACzD,mBAAW;AACX,oBAAY;AAAA,MACd,WAAW,EAAE,QAAQ,OAAQ,EAAE,QAAQ,OAAO,EAAE,UAAW;AACzD,mBAAW;AACX,oBAAY;AAAA,MACd,WAAW,EAAE,QAAQ,OAAO,CAAC,EAAE,UAAU;AACvC,mBAAW;AACX,oBAAY;AAAA,MACd,WAAW,EAAE,QAAQ,OAAO,CAAC,EAAE,UAAU;AACvC,mBAAW;AACX,oBAAY;AAAA,MACd;AAEA,UAAI,CAAC,YAAY,CAAC,UAAW,QAAO;AACpC,QAAE,eAAe;AAEjB,YAAM,KAAK;AACX,YAAM,QAAQ,kBAAkB,GAAG,WAAW,QAAQ;AACtD,UAAI,CAAC,OAAO;AACV,cAAM,SACJ,aAAa,mBACT,YACA,aAAa,kBACX,WACA,aAAa,eACX,QACA,aAAa,iBACX,UACA,aAAa,kBACX,WACA,GAAG,SAAS,CAAC,CAAC;AAC5B;AAAA,UACE,MAAM,MAAM;AAAA,UACZ;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAEA,YAAM,YAAY,aAAa;AAC/B,YAAM,WAAW,SAAS,OAAO,WAAW,SAAS;AACrD,UAAI,CAAC,UAAU;AACb;AAAA,UACE,GAAG,KAAK,sBAAsB,cAAc,OAAO,QAAQ,KAAK;AAAA,UAChE;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAEA,YAAM,aAAa,YAAY,UAAU,SAAS,KAAK;AACvD,yBAAmB,IAAI,OAAO,UAAU,UAAU;AAClD,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,CAAC,MAAkB;AACjC,YAAM,SAAS,SAAS,iBAAiB,EAAE,SAAS,EAAE,OAAO;AAC7D,UAAI,EAAE,kBAAkB,aAAc;AACtC,UAAI,YAAY,MAAM,EAAG;AAIzB,UAAI,EAAE,UAAU;AACd,cAAM,MAAM,WAAW,QAAQ,MAAM;AACrC,YAAI,QAAQ,GAAI,YAAW,KAAK,MAAM;AAAA,YACjC,YAAW,OAAO,KAAK,CAAC;AAC7B;AAAA,MACF;AACA,cAAQ,MAAM;AAAA,IAChB;AAEA,UAAM,UAAU,CAAC,MAAqB;AACpC,UAAI,EAAE,QAAQ,SAAS,EAAE,WAAW,OAAO;AACzC,6BAAqB;AAAA,MACvB;AAAA,IACF;AAEA,UAAM,YAAY,CAAC,MAAqB;AAGtC,WACG,EAAE,QAAQ,OAAO,EAAE,QAAQ,QAC5B,CAAC,EAAE,UACH,CAAC,EAAE,WACH,CAAC,EAAE,WACH,gBACA,aAAa,QAAQ,YAAY,MAAM,OACvC;AACA,UAAE,eAAe;AACjB,aAAK,kBAAkB,YAAY;AACnC;AAAA,MACF;AACA,UAAI,EAAE,QAAQ,UAAU;AACtB,YAAI,SAAS;AACX,4BAAkB,QAAQ,OAAO;AACjC,sBAAY;AAAA,QACd;AACA,YAAI,UAAU;AACZ,mBAAS,QAAQ;AACjB,qBAAW;AACX,yBAAe;AACf,6BAAmB;AACnB,0BAAgB;AAChB,4BAAkB;AAClB,0BAAgB;AAChB,uBAAa;AACb,iCAAuB;AAAA,QACzB;AACA;AAAA,MACF;AACA,qBAAe,CAAC;AAAA,IAClB;AAEA,aAAS,iBAAiB,aAAa,aAAa,EAAE,SAAS,KAAK,CAAC;AACrE,aAAS,iBAAiB,UAAU,kBAAkB,EAAE,SAAS,KAAK,CAAC;AACvE,WAAO,iBAAiB,UAAU,gBAAgB;AAClD,aAAS,iBAAiB,cAAc,YAAY;AACpD,aAAS,iBAAiB,SAAS,OAAO;AAC1C,aAAS,iBAAiB,WAAW,SAAS;AAC9C,aAAS,iBAAiB,SAAS,OAAO;AAC1C,aAAS,KAAK,QAAQ,aAAa,IAAI;AAKvC;AACE,YAAM,QAAQ,UAAU;AACxB,UAAI,OAAO;AACT,cAAM,UAAU,MAAM,IAAI,QAAQ,MAAM,KAAK;AAC7C,cAAM,WAAW,SAAS;AAAA,UACxB,cAAc,OAAO;AAAA,QACvB;AACA,YAAI,UAAU;AACZ;AAAA,YACE;AAAA,cACE,SAAS;AAAA,cACT,MAAM,MAAM;AAAA,cACZ,MAAM,MAAM;AAAA,cACZ,KAAK,MAAM;AAAA,cACX,QAAQ,MAAM;AAAA,cACd,OAAO,MAAM;AAAA,YACf;AAAA,YACA,MAAM;AAAA,UACR;AAAA,QACF,OAAO;AAEL,qBAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAEA,IAAC,OAAuD,sBAAsB;AAAA,MAC5E,qBAAqB,MACnB,kBAAkB,iBAAiB,uBAAuB,EAAE;AAAA,MAC9D,WAAW,MACR,OAAO,cAAc,QAAQ,GAA0B,eACxD;AAAA,MACF,eAAe,MAAM,iBAAiB,SAAS,IAAI,EAAE;AAAA,MACrD,YAAY,MAAM;AAChB,cAAM,IAAI,OAAO,cAAc,QAAQ;AACvC,eAAO,IAAI,iBAAiB,CAAC,EAAE,kBAAkB;AAAA,MACnD;AAAA,MACA,gBAAgB,MAAM;AACpB,cAAM,IAAI,OAAO,cAAc,QAAQ;AACvC,eAAO,IAAI,iBAAiB,CAAC,EAAE,YAAY;AAAA,MAC7C;AAAA,MACA,mBAAmB,MAAM,iBAAiB,SAAS,IAAI,EAAE;AAAA,MACzD,iBAAiB,MACd,OAAO,cAAc,YAAY,GAA0B,MACzD,YAAY;AAAA,MACjB,cAAc,MACX,OAAO,cAAc,YAAY,GAC9B,eAAe;AAAA,MACrB,qBAAqB,MAClB,OAAO,cAAc,gBAAgB,GAA0B,MAC7D,YAAY;AAAA,MACjB,kBAAkB,MACf,OAAO,cAAc,gBAAgB,GAClC,eAAe;AAAA;AAAA;AAAA;AAAA,MAIrB,YAAY,MAAM;AAChB,cAAM,MAAM,OAAO,cAAc,YAAY;AAC7C,YAAI,CAAC,IAAK,QAAO,EAAE,OAAO,kBAAkB;AAC5C,YAAI,MAAM;AACV,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MACA,sBAAsB,MACpB,OAAO,iBAAiB,mBAAmB,EAAE;AAAA,MAC/C,0BAA0B,MACxB,MAAM,KAAK,OAAO,iBAAiB,gBAAgB,CAAC,EAAE;AAAA,QACpD,CAAC,MAAO,EAAkB,MAAM,YAAY;AAAA,MAC9C,EAAE;AAAA,MACJ,yBAAyB,MACvB,MAAM,KAAK,OAAO,iBAAiB,mBAAmB,CAAC,EAAE;AAAA,QACvD,CAAC,MAAO,EAAkB,MAAM,YAAY;AAAA,MAC9C,EAAE;AAAA,MACJ,mBAAmB,MAAM;AACvB,cAAM,KAAK,OAAO,cAAc,iBAAiB;AACjD,YAAI,CAAC,MAAM,GAAG,MAAM,YAAY,OAAQ,QAAO;AAC/C,eAAO,GAAG;AAAA,MACZ;AAAA,MACA,gBAAgB,MAAM,WAAW;AAAA,MACjC,uBAAuB,MACrB,MAAM,KAAK,OAAO,iBAAiB,iBAAiB,CAAC,EAAE;AAAA,QACrD,CAAC,MAAO,EAAkB,MAAM,YAAY;AAAA,MAC9C,EAAE;AAAA,MACJ,mBAAmB,CAAC,SAA8C;AAChE,cAAMJ,KAAI,OAAO;AAAA,UACf,mBAAmB,IAAI;AAAA,QACzB;AACA,YAAI,CAACA,MAAKA,GAAE,MAAM,YAAY,OAAQ,QAAO;AAC7C,eAAO;AAAA,UACL,MAAM,WAAWA,GAAE,MAAM,IAAI;AAAA,UAC7B,KAAK,WAAWA,GAAE,MAAM,GAAG;AAAA,QAC7B;AAAA,MACF;AAAA,MACA,qBAAqB,MAClB,OAAO,cAAc,gBAAgB,GAA0B,MAC7D,YAAY;AAAA,MACjB,iBAAiB,MACf,OAAO,iBAAiB,cAAc,EAAE;AAAA,MAC1C,aAAa,MACX,MAAM,KAAK,OAAO,iBAAiB,cAAc,CAAC,EAAE,IAAI,CAAC,OAAO;AAAA,QAC9D,QAAS,EAAE,cAAc,iBAAiB,GACtC;AAAA,QACJ,QAAS,EAAE,cAAc,iBAAiB,GACtC;AAAA,MACN,EAAE;AAAA;AAAA;AAAA,MAGJ,aAAa,MAAM;AACjB,cAAM,QAAQ,OAAO,cAAc,QAAQ;AAC3C,eAAO,MAAM;AAAA,MACf;AAAA,MACA,WAAW,CAAC,UAAkB;AAC5B,cAAM,OAAO,OAAO,iBAAiB,eAAe;AACpD,cAAM,MAAM,KAAK,KAAK;AACtB,aAAK,MAAM;AAAA,MACb;AAAA,MACA,oBAAoB,MACjB,OAAO,cAAc,eAAe,GAA0B,MAC5D,YAAY;AAAA,MACjB,oBAAoB,MAClB,MAAM,KAAK,OAAO,iBAAiB,YAAY,CAAC,EAAE;AAAA,QAChD,CAAC,MAAO,EAAkB,QAAQ;AAAA,MACpC;AAAA,MACF,WAAW,CAAC,cAAsB;AAChC,cAAM,MAAM,OAAO;AAAA,UACjB,0BAA0B,IAAI,OAAO,SAAS,CAAC;AAAA,QACjD;AACA,YAAI,CAAC,IAAK,QAAO,EAAE,OAAO,kBAAkB;AAC5C,YAAI,MAAM;AACV,eAAO,EAAE,QAAQ,UAAU;AAAA,MAC7B;AAAA,MACA,iBAAiB,MACd,OAAO,cAAc,YAAY,GAA0B,MACzD,YAAY;AAAA,MACjB,cAAc,MACX,OAAO,cAAc,iBAAiB,GACnC,eAAe;AAAA,MACrB,UAAU,CAAC,UAAkB,UAAkB;AAC7C,cAAM,YAAY,OAAO;AAAA,UACvB;AAAA,QACF;AACA,cAAM,WAAW,OAAO;AAAA,UACtB;AAAA,QACF;AACA,cAAM,WAAW,OAAO;AAAA,UACtB;AAAA,QACF;AACA,YAAI,CAAC,aAAa,CAAC,YAAY,CAAC,UAAU;AACxC,iBAAO,EAAE,OAAO,eAAe;AAAA,QACjC;AACA,kBAAU,QAAQ;AAClB,iBAAS,QAAQ;AACjB,iBAAS,MAAM;AACf,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MACA,gBAAgB,MACb,OAAO,cAAc,mBAAmB,GACrC,eAAe;AAAA,MACrB,aAAa,MAAM,cAAc,WAAW;AAAA,MAC5C,eAAe,MACb,eACI;AAAA,QACE,cAAc,aAAa,aAAa,uBAAuB;AAAA,QAC/D,aAAa,aAAa,aAAa,sBAAsB;AAAA,QAC7D,SAAS,aAAa,aAAa,UAAU;AAAA,MAC/C,IACA;AAAA,IACR;AAEA,WAAO,MAAM;AACX,eAAS,oBAAoB,aAAa,WAAW;AACrD,eAAS,oBAAoB,UAAU,gBAAgB;AACvD,aAAO,oBAAoB,UAAU,gBAAgB;AACrD,eAAS,oBAAoB,cAAc,YAAY;AACvD,eAAS,oBAAoB,SAAS,OAAO;AAC7C,eAAS,oBAAoB,WAAW,SAAS;AACjD,eAAS,oBAAoB,SAAS,OAAO;AAC7C,2BAAqB,KAAK;AAC1B,UAAI,uBAAuB,KAAM,QAAO,aAAa,kBAAkB;AACvE,gBAAU,QAAQ;AAClB,yBAAmB;AACnB,wBAAkB;AAClB,4BAAsB;AACtB,aAAO,OAAO;AACd,aAAO,SAAS,KAAK,QAAQ,aAAa;AAAA,IAC5C;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO;AACT;","names":["h","target","change","anchor","el"]}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@aaqiljamal/visual-editor-runtime",
3
+ "version": "0.2.0",
4
+ "description": "Visual-edit dev overlay. Mount in your Next.js app's layout (dev only); it talks to @aaqiljamal/visual-editor-server over localhost.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": ["dist", "README.md"],
16
+ "scripts": {
17
+ "build": "tsup",
18
+ "dev": "tsup --watch",
19
+ "typecheck": "tsc --noEmit",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "keywords": ["visual-editor", "next", "tailwind", "css-modules", "styled-components"],
23
+ "license": "MIT",
24
+ "author": "Aaqil Jamal",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/The-Design-Alchemist/visual-editor.git",
28
+ "directory": "packages/runtime"
29
+ },
30
+ "homepage": "https://github.com/The-Design-Alchemist/visual-editor#readme",
31
+ "bugs": "https://github.com/The-Design-Alchemist/visual-editor/issues",
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "engines": {
36
+ "node": ">=20"
37
+ },
38
+ "peerDependencies": {
39
+ "react": "^18.0.0 || ^19.0.0"
40
+ },
41
+ "dependencies": {
42
+ "moveable": "^0.53.0",
43
+ "preact": "^10.29.0"
44
+ },
45
+ "devDependencies": {
46
+ "@types/react": "^19.0.0",
47
+ "tsup": "^8.3.5",
48
+ "typescript": "^5.6.3"
49
+ }
50
+ }