{
  "version": 3,
  "sources": ["../src/services/identity.ts", "../src/services/activeEditorBrand.ts", "../src/services/devEnv.ts", "../src/services/wizardApiClient.ts", "../src/services/imageService.ts", "../src/services/text/generateService.ts", "../src/services/aiEngine.ts", "../src/utils/videoCanvasSize.ts", "../src/utils/previewHitTest.ts", "../src/lib/persistence/projectPersistence.ts", "../src/i18n/setupPresetNames.es.ts", "../src/i18n/es.ts", "../src/i18n/setupPresetNames.en.ts", "../src/i18n/en.ts", "../src/i18n/index.tsx", "../src/utils/cloudSaveStatus.ts", "../src/lib/audio/transcriptEdit.ts", "../src/utils/userFacingError.ts", "../src/lib/audio/dsp/gain.ts", "../src/lib/audio/effects/createEffectChain.ts", "../src/lib/audio/automation.ts", "../src/lib/audio/crossfade.ts", "../src/lib/audio/scheduler.ts", "../src/lib/audio/timeStretch.ts", "../src/lib/audio/loudness.ts", "../src/lib/audio/AudioEngine.ts", "../src/lib/audio/peaks.ts", "../src/store/useAudioStore.ts", "../src/lib/text/readability.ts", "../src/lib/text/outline.ts", "../src/lib/text/clarity.ts", "../src/store/useTextStore.ts", "../src/types/slides.types.ts", "../src/lib/slides/themes.ts", "../src/lib/slides/layouts.ts", "../src/lib/slides/restyle.ts", "../src/lib/slides/autofit.ts", "../src/lib/slides/a11y.ts", "../src/lib/slides/designFixes.ts", "../src/lib/slides/magicLayout.ts", "../src/services/stockService.ts", "../src/utils/chartUtils.ts", "../src/lib/slides/chartBridge.ts", "../src/lib/slides/mediaAssets.ts", "../src/lib/slides/applyGeneratedDeck.ts", "../src/services/slides/deckService.ts", "../src/utils/slidesThumbnail.ts", "../src/store/useSlidesStore.ts", "../src/services/editableService.ts", "../src/utils/audioProjectFile.ts", "../src/utils/textProjectFile.ts", "../src/utils/slidesProjectFile.ts", "../src/utils/projectExtensions.ts", "../src/utils/videoPreviewThumbnail.ts", "../src/utils/compressImageForEditor.ts", "../src/utils/projectCloudSerializer.ts", "../src/utils/cloudAutosaveToast.ts", "../src/utils/timelineUtils.ts", "../src/store/useVideoStore.ts", "../src/utils/videoAiPresetMap.ts", "../src/utils/videoEditPlan.ts", "../src/services/textService.ts", "../src/services/voiceoverService.ts", "../src/utils/transcribeUploadFile.ts", "../src/services/transcriptionService.ts", "../src/services/aiService.ts", "../src/utils/imageFilterPresets.ts", "../src/utils/canvasZoomRender.ts", "../src/utils/aiLoadingLayer.ts", "../src/utils/colorRgba.ts", "../src/utils/googleFonts.ts", "../src/utils/pixelLayer.ts", "../src/utils/magicWandSelection.ts", "../src/utils/fabricCustomFilters.ts", "../src/utils/applyFabricImageFilters.ts", "../src/store/useEditorStore.ts", "../src/utils/roundedRectCorners.ts", "../src/components/ui/atoms/Button/Button.tsx", "../src/components/ui/atoms/IconButton/IconButton.tsx", "../src/components/ui/atoms/HamburgerIcon/HamburgerIcon.tsx", "../src/components/ui/atoms/TextTitle/TextTitle.tsx", "../src/components/ui/atoms/TextBody/TextBody.tsx", "../src/components/ui/molecules/ExportButton/ExportButton.tsx", "../src/components/ui/molecules/PanelField/PanelField.tsx", "../src/components/ui/molecules/PanelSection/PanelSection.tsx", "../src/utils/clampFixedToViewport.ts", "../src/utils/useEyedropper.ts", "../src/theme/modeAccent.ts", "../src/components/ui/molecules/ColorInput/ColorInput.tsx", "../src/components/ui/molecules/AspectLockGroup/AspectLockGroup.tsx", "../src/utils/canvasSizePresets.ts", "../src/components/ui/Dropdown.tsx", "../src/components/ui/molecules/SelectDropdown/SelectDropdown.tsx", "../src/utils/panelLayoutReset.ts", "../src/components/DraggableToolPanel.tsx", "../src/context/BrandSelectionContext.tsx", "../src/utils/colorUtils.ts", "../src/components/editor/CurvesEditor.tsx", "../src/utils/fabricText3D.ts", "../src/components/Sidebar.tsx", "../src/components/editor/tool-panels/CanvasBgPanel.tsx", "../src/components/ui/organisms/CanvasSizeModal/CanvasSizeModal.tsx", "../src/components/ui/molecules/CanvasSizeChip/CanvasSizeChip.tsx", "../src/components/ui/organisms/MasterColorPanel/MasterColorPanel.tsx", "../src/components/ui/molecules/DropdownSubmenu/DropdownSubmenu.tsx", "../src/components/ui/molecules/FontPickerFlyout/FontPickerFlyout.tsx", "../src/components/ui/molecules/SubtitleAiLoader/SubtitleAiLoader.tsx", "../src/components/ui/molecules/ToolPanelTabs/ToolPanelTabs.tsx", "../src/components/ui/Input.tsx", "../src/components/ui/atoms/Switch/Switch.tsx", "../src/components/ui/Tooltip.tsx", "../src/components/ui/Modal.tsx", "../src/components/ui/Slider.tsx", "../src/components/ui/VariationsModal.tsx", "../src/components/ui/index.ts", "../src/components/editor/HistogramLevels.tsx", "../src/utils/loremUtils.ts", "../src/components/DialogModal.tsx", "../src/components/ui/Button.tsx", "../src/services/imageJobsService.ts", "../src/lib/effects/keyframeUtils.ts", "../src/lib/effects/transitionDefinitions.ts", "../src/lib/effects/webglRenderer.ts", "../src/lib/effects/motionUtils.ts", "../src/lib/effects/textRenderer.ts", "../src/components/editor/text/FontPicker.tsx", "../src/utils/useViewportMenuCoords.ts", "../src/utils/ViewportPortalMenu.tsx", "../src/utils/editablePreview.ts", "../src/hooks/useEditablePreview.ts", "../src/components/editor/CloudEditableCard.tsx", "../src/lib/persistence/localRecentProjects.ts", "../src/components/editor/RecentCanvasesCarousel.tsx", "../src/components/editor/EditorEmptyState.tsx", "../src/components/editor/BrandToolbarDropdown.tsx", "../src/components/editor/EditorModeToggle.tsx", "../src/components/editor/EditorShellHeader.tsx", "../src/components/editor/FileMenuSettings.tsx", "../src/components/editor/ShellFileMenu.tsx", "../src/components/editor/StudioTabBar.tsx", "../src/components/editor/ModeProjectTabs.tsx", "../src/services/ffmpegService.ts", "../src/utils/exportDownloadName.ts", "../src/utils/cloudSaveToast.ts", "../src/utils/advancedExportUtils.ts", "../src/utils/exportUtils.ts", "../src/components/VersionHistoryModal.tsx", "../src/utils/modKey.ts", "../src/components/icons/PencilSparkles.tsx", "../src/utils/fabricTransformModifiers.ts", "../src/utils/imageCrop.ts", "../src/components/editor/CropOverlay.tsx", "../src/components/editor/PenToolOverlay.tsx", "../src/components/editor/BooleanOperationsMenu.tsx", "../src/components/editor/MaskEditorPanel.tsx", "../src/utils/overlayCoords.ts", "../src/components/editor/MarqueeSelectOverlay.tsx", "../src/components/editor/CloneStampOverlay.tsx", "../src/components/editor/MagicWandOverlay.tsx", "../src/components/editor/PaintBucketOverlay.tsx", "../src/components/editor/PixelLassoOverlay.tsx", "../src/components/editor/ShapeLassoOverlay.tsx", "../src/components/editor/PolygonLassoOverlay.tsx", "../src/components/editor/PixelEraserOverlay.tsx", "../src/components/editor/MaskPaintOverlay.tsx", "../src/components/editor/PixelSelectionMarchingAnts.tsx", "../src/components/editor/BrushRadiusPopup.tsx", "../src/components/editor/BrushSizeCenterPreview.tsx", "../src/utils/frameFactory.ts", "../src/utils/customShapeFactory.ts", "../src/utils/textToPathUtils.ts", "../src/components/editor/tool-panels/CanvasGridPanel.tsx", "../src/components/editor/tool-panels/CanvasColorblindPanel.tsx", "../src/components/editor/tool-panels/CanvasUploadPanel.tsx", "../src/components/editor/tool-panels/BrushToolPanel.tsx", "../src/components/editor/tool-panels/MagicEraserToolPanel.tsx", "../src/components/editor/tool-panels/MagicWandToolPanel.tsx", "../src/components/editor/tool-panels/PaintBucketToolPanel.tsx", "../src/components/editor/tool-panels/CloneStampToolPanel.tsx", "../src/components/editor/tool-panels/EraserToolPanel.tsx", "../src/components/editor/SnapMagnetButton.tsx", "../src/components/editor/BrandKitButton.tsx", "../src/components/editor/CanvasZoomDock.tsx", "../src/components/editor/FabricCanvasHost.tsx", "../src/components/ChartDataModal.tsx", "../src/utils/fabricPointerCssZoom.ts", "../src/components/editor/SelectionControlsOverlay.tsx", "../src/components/editor/AiLoadingOverlay.tsx", "../src/components/CanvasArea.tsx", "../src/components/audio/AudioBpmControl.tsx", "../src/components/audio/AudioBottomToolbar.tsx", "../src/store/useAudioUiStore.ts", "../src/components/audio/AutomationLane.tsx", "../src/services/audio/jobPolling.ts", "../src/lib/audio/wavEncoder.ts", "../src/lib/audio/stemSplit.ts", "../src/services/audio/musicService.ts", "../src/services/audio/sfxService.ts", "../src/services/audio/voiceService.ts", "../src/services/audio/isolationService.ts", "../src/lib/audio/silenceTrim.ts", "../src/components/audio/AiAudioPanel.tsx", "../src/components/audio/AudioInspector.tsx", "../src/components/audio/EffectsRack.tsx", "../src/components/audio/LevelMeter.tsx", "../src/components/audio/Mixer.tsx", "../src/services/audio/audioAgentService.ts", "../src/lib/audio/agent/tools.ts", "../src/lib/audio/agent/executor.ts", "../src/components/audio/AudioChatPanel.tsx", "../src/lib/audio/recording.ts", "../src/components/audio/RecordingPanel.tsx", "../src/components/audio/LyricsPanel.tsx", "../src/components/audio/AudioJobsPanel.tsx", "../src/components/audio/AudioRightSidebar.tsx", "../src/components/audio/AudioTrackControls.tsx", "../src/lib/audio/timelineSnap.ts", "../src/components/audio/AudioTimeline.tsx", "../src/components/audio/AudioTimelineToolbar.tsx", "../src/lib/audio/mp3Encoder.ts", "../src/lib/audio/offlineRender.ts", "../src/components/audio/AudioExportModal.tsx", "../src/components/audio/AudioEditor.tsx", "../src/lib/text/extensions/aiSuggestion.ts", "../src/lib/text/extensions/commentMark.ts", "../src/lib/text/extensions/callout.ts", "../src/lib/text/extensions/footnote.ts", "../src/lib/text/extensions/brandHighlight.ts", "../src/lib/text/extensions/slashCommand.ts", "../src/lib/text/extensions/resizableImage.tsx", "../src/lib/text/extensions/indent.ts", "../src/lib/text/extensions/underscoreItalic.ts", "../src/lib/text/extensions/whatsappFormatting.ts", "../src/lib/text/extensions/index.ts", "../src/lib/text/extensions/pageBreak.ts", "../src/lib/text/pasteClean.ts", "../src/store/useTextUiStore.ts", "../src/services/text/textAgentService.ts", "../src/services/text/healthService.ts", "../src/services/text/index.ts", "../src/components/text/TextContextMenu.tsx", "../src/components/text/TextCommentComposer.tsx", "../src/components/text/TextFootnoteModal.tsx", "../src/lib/text/normalizeLinkUrl.ts", "../src/components/text/TextLinkModal.tsx", "../src/components/text/TextTableModal.tsx", "../src/components/text/DocumentCanvas.tsx", "../src/components/text/OutlinePanel.tsx", "../src/components/text/TextJobsPanel.tsx", "../src/components/text/TextLeftPanel.tsx", "../src/lib/text/markdown.ts", "../src/lib/text/applySuggestion.ts", "../src/lib/text/docxBridge.ts", "../src/components/text/TextAiResultModal.tsx", "../src/lib/text/complianceFeedback.ts", "../src/components/text/AiTextPanel.tsx", "../src/lib/text/agent/tools.ts", "../src/lib/text/agent/friendly.ts", "../src/lib/text/agent/executor.ts", "../src/components/text/TextChatPanel.tsx", "../src/components/text/VariantsBoard.tsx", "../src/components/text/CommentsPanel.tsx", "../src/components/text/ClaimsPanel.tsx", "../src/components/text/SuggestionsModal.tsx", "../src/components/text/TextRightSidebar.tsx", "../src/components/text/MetricsBar.tsx", "../src/lib/text/exportFormats.ts", "../src/lib/text/sectionBodies.ts", "../src/components/text/TextExportModal.tsx", "../src/components/text/TextCommandPalette.tsx", "../src/components/text/TextPageSetupModal.tsx", "../src/components/text/TextEditor.tsx", "../src/store/useSlidesUiStore.ts", "../src/components/slides/SlidesAiPanel.tsx", "../src/lib/slides/agent/tools.ts", "../src/lib/slides/agent/executor.ts", "../src/components/slides/SlidesChatPanel.tsx", "../src/components/slides/ThemePanel.tsx", "../src/components/slides/DeckOutlinePanel.tsx", "../src/components/slides/BuildsPanel.tsx", "../src/components/slides/CommentsPanel.tsx", "../src/components/slides/DesignCriticPanel.tsx", "../src/components/slides/CoachPanel.tsx", "../src/lib/slides/align.ts", "../src/components/slides/SlideCanvas.tsx", "../src/components/slides/LibraryPanel.tsx", "../src/components/slides/MasterPanel.tsx", "../src/components/slides/SlidesRightSidebar.tsx", "../src/components/slides/SlideRail.tsx", "../src/components/slides/SlidesLeftPanel.tsx", "../src/components/slides/SlidesCreationToolbar.tsx", "../src/components/slides/SlidesContextToolbar.tsx", "../src/components/slides/SlidesContextMenu.tsx", "../src/components/slides/SlidesAltTextModal.tsx", "../src/components/slides/SlidesSnapMagnetButton.tsx", "../src/components/slides/NotesPanel.tsx", "../src/lib/slides/pptx/emu.ts", "../src/lib/slides/pptx/shapeMap.ts", "../src/lib/slides/pptx/exportPptx.ts", "../src/utils/slidesExport.ts", "../src/components/slides/SlidesExportModal.tsx", "../src/lib/slides/canvasTransition.ts", "../src/lib/slides/animationRuntime.ts", "../src/lib/slides/morph.ts", "../src/components/slides/PresenterView.tsx", "../src/lib/slides/pptx/importPptx.ts", "../src/components/slides/SlidesEditor.tsx", "../src/App.tsx", "../src/components/ImageRightSidebar.tsx", "../src/components/ObjectPropertiesPanel.tsx", "../src/components/LayersPanel.tsx", "../src/components/editor/TransformPanel.tsx", "../src/components/ToastContainer.tsx", "../src/components/CloudSaveStatusStack.tsx", "../src/components/CommandPalette.tsx", "../src/components/editor/PresentationMode.tsx", "../src/components/editor/VideoEditor.tsx", "../src/components/editor/LeftPanel.tsx", "../src/components/editor/AssetPanel.tsx", "../src/components/editor/AiImageModal.tsx", "../src/components/editor/MyFilesPanel.tsx", "../src/components/editor/VideoCanvasPanel.tsx", "../src/components/editor/VideoAiToolsPanel.tsx", "../src/store/useVideoUiStore.ts", "../src/components/editor/VideoPreview.tsx", "../src/lib/effects/overlayTransition.ts", "../src/components/editor/images/CropTool.tsx", "../src/components/editor/RightSidebar.tsx", "../src/components/editor/PropertiesPanel.tsx", "../src/components/editor/images/ColorGradingPanel.tsx", "../src/components/editor/effects/ColorCurves.tsx", "../src/components/editor/effects/EffectStack.tsx", "../src/components/editor/effects/EffectsPanel.tsx", "../src/components/editor/transitions/TransitionPanel.tsx", "../src/components/editor/text/TextPanel.tsx", "../src/components/editor/transitions/TransitionJunctionModal.tsx", "../src/components/editor/TrackControls.tsx", "../src/components/editor/Timeline.tsx", "../src/utils/timelineSnap.ts", "../src/components/editor/transitions/TransitionBuilder.tsx", "../src/components/editor/TimelineToolbar.tsx", "../src/components/editor/ExportModal.tsx", "../src/components/editor/AiContentModal.tsx", "../src/components/editor/VideoAiGenerateModal.tsx", "../src/components/editor/AiVoiceoverModal.tsx", "../src/utils/projectFileHelper.ts", "../src/components/editor/ImageEditorChrome.tsx", "../src/components/ExportModal.tsx", "../src/components/video/agent-ui/QAVideo.tsx", "../src/components/video/agent-ui/VideoPlayer.tsx", "../src/components/video/agent-ui/Timeline.tsx", "../src/components/video/agent-ui/TransitionBuilder.tsx", "../src/services/hostMediaImport.ts", "../src/services/hostCookieBootstrap.ts", "../src/hooks/useProjectPersistence.ts", "../src/components/ProjectSetupModal.tsx", "../src/index.ts"],
  "sourcesContent": ["/**\n * Editor identity \u2014 the (accountId, brandId) tuple injected into every\n * AI service call.\n *\n * Dev:  setEditorIdentity({ accountId: 4, brandId: '48' }) called by the\n *       dev wrapper on mount.\n * Prod: the host sets it from its React Context (Zustand store) after the\n *       user logs in and the brand picker resolves.\n *\n * Services throw if getEditorIdentity() is called before setEditorIdentity().\n */\n\nexport interface EditorIdentity {\n  accountId: number;\n  brandId: string;\n}\n\nlet _identity: EditorIdentity | null = null;\n\nexport function setEditorIdentity(identity: EditorIdentity): void {\n  _identity = identity;\n}\n\nexport function getEditorIdentity(): EditorIdentity {\n  if (!_identity) {\n    throw new Error(\n      'Editor identity not configured. ' +\n        'Call setEditorIdentity() in the dev wrapper or in the host bootstrap before using AI services.'\n    );\n  }\n  return _identity;\n}\n\nexport function hasEditorIdentity(): boolean {\n  return _identity !== null;\n}\n\nexport function clearEditorIdentity(): void {\n  _identity = null;\n}\n", "/**\n * Active brand snapshot for AI calls (logos, colors, name).\n * Kept in sync with BrandSelectionContext / host brand props.\n * `brand_id` for requests still comes from getEditorIdentity().\n */\n\nimport type { EditorBrandOption } from '../types/brand.types';\n\nlet _brand: EditorBrandOption | null = null;\n\nexport function setActiveEditorBrand(brand: EditorBrandOption | null): void {\n  _brand = brand;\n}\n\nexport function getActiveEditorBrand(): EditorBrandOption | null {\n  return _brand;\n}\n\nexport function clearActiveEditorBrand(): void {\n  _brand = null;\n}\n\n/** Primary logo URL for image-generator `logo_url`. */\nexport function getActiveBrandLogoUrl(\n  brand: EditorBrandOption | null = _brand,\n): string | undefined {\n  if (!brand) return undefined;\n  if (brand.logoUrl) return brand.logoUrl;\n  const fromList = brand.brandLogos?.find((l) => l?.logoUrl)?.logoUrl;\n  return fromList || undefined;\n}\n\n/** Compact brand kit for AI copy prompts (name, colors, voice, samples). */\nexport function formatActiveBrandForPrompt(\n  brand: EditorBrandOption | null = _brand,\n): string {\n  if (!brand?.name) return '';\n  const parts: string[] = [`Marca: ${brand.name}`];\n  if (brand.primaryColors?.length) {\n    parts.push(\n      `Colores: ${brand.primaryColors\n        .map((c) => (c.name ? `${c.name} (${c.hex})` : c.hex))\n        .join(', ')}`,\n    );\n  }\n  if (brand.voice?.name) {\n    parts.push(`Tono de voz: ${brand.voice.name}`);\n  }\n  const samples = (brand.textBank ?? [])\n    .map((e) => e.text?.trim())\n    .filter((t): t is string => Boolean(t))\n    .slice(0, 3);\n  if (samples.length > 0) {\n    parts.push(`Ejemplos de voz: ${samples.map((s) => `\"${s}\"`).join('; ')}`);\n  }\n  return parts.join('. ');\n}\n", "/**\n * Single source of truth for reading Vite-injected env vars at runtime.\n *\n * Why this exists:\n *   - In Vite dev / ESM bundles, `import.meta.env` is populated by the\n *     bundler with `VITE_*` values. Reading it is free and typed via\n *     `vite/client` (see `src/vite-env.d.ts`).\n *   - In the esbuild `format: 'cjs'` bundle (used for legacy consumers like\n *     Webpack) `import.meta` is empty, so accessing `.env` returns\n *     `undefined`. We guard with try/catch once, here, instead of\n *     duplicating defensive casts across every call site.\n *\n * Behavior:\n *   - Vite/ESM: returns the real `import.meta.env` typed object.\n *   - CJS / non-Vite / when `import.meta.env` is just `undefined` (the\n *     common case in Next.js / Webpack that strip Vite's env injection):\n *     returns `{}`. The host is expected to call\n *     `configureWizardApiClient({ baseUrl, devToken })` and\n *     `setEditorIdentity({ accountId, brandId })` from its bootstrap, so\n *     empty dev defaults are a no-op in production.\n *\n * Reads at module top-level are fine \u2014 this helper performs no I/O.\n */\nconst EMPTY_ENV = {} as unknown as ImportMetaEnv;\n\nexport function readDevEnv(): ImportMetaEnv {\n  try {\n    // Two failure modes here:\n    //   1. `import.meta` exists but `.env` is `undefined` (Next.js, Webpack,\n    //      Vite library build without VITE_* at build time). No throw.\n    //   2. `import.meta.env` itself throws (some CJS runtimes).\n    // The `?? EMPTY_ENV` covers (1); the catch covers (2). Without (1),\n    // callers see `undefined.VITE_X` and get \"Cannot read properties of\n    // undefined\" at module load \u2014 the symptom we hit in wizard-ai.\n    return import.meta.env ?? EMPTY_ENV;\n  } catch {\n    return EMPTY_ENV;\n  }\n}\n", "/**\n * Wizard API Client \u2014 HTTP client for the .NET backend (wizard-ai-api.com).\n *\n * Modes:\n *  - getForJson          \u2014 query params, JSON response\n *  - postJson            \u2014 application/json body, binary image response\n *  - postJsonForJson     \u2014 application/json body, JSON response\n *  - postMultipart       \u2014 multipart/form-data body, binary image response\n *  - postMultipartForJson \u2014 multipart/form-data body, JSON response\n *  - patchMultipartForJson \u2014 multipart/form-data body (PATCH), JSON or empty\n *  - deleteForJson       \u2014 query params, JSON or empty response\n *\n * The \"ForJson\" suffix exists for endpoints that don't follow the dominant\n * \"JSON request \u2192 image bytes response\" pattern: text presets, audio\n * transcription, stock search, etc.\n *\n * Auth strategy:\n *  - Dev:  caller passes `devToken` (JWT) \u2192 sent as Authorization: Bearer\n *  - Prod: caller omits `devToken` \u2192 relies on wizard_session cookie via\n *          credentials: 'include'. The browser attaches the cookie automatically.\n *\n * Errors are typed so the host can map them to UX consistently:\n *  - AuthError            \u2192 401/403, session expired or missing\n *  - NotImplementedError  \u2192 404/501, feature not exposed by .NET\n *  - ApiError             \u2192 other 4xx/5xx with diagnostic detail\n *  - NetworkError         \u2192 fetch failed (offline, CORS, timeout, abort)\n */\n\nimport { readDevEnv } from './devEnv';\n\nexport class NotImplementedError extends Error {\n  readonly feature: string;\n  readonly status?: number;\n  readonly upstreamText?: string;\n  constructor(feature: string, status?: number, upstreamText?: string) {\n    super(\n      `Feature \"${feature}\" is not yet supported by the host backend${\n        status ? ` (HTTP ${status})` : ''\n      }`\n    );\n    this.name = 'NotImplementedError';\n    this.feature = feature;\n    this.status = status;\n    this.upstreamText = upstreamText;\n  }\n}\n\nexport class AuthError extends Error {\n  constructor(message = 'No session or session expired') {\n    super(message);\n    this.name = 'AuthError';\n  }\n}\n\nexport class NetworkError extends Error {\n  readonly cause?: unknown;\n  constructor(message: string, cause?: unknown) {\n    super(message);\n    this.name = 'NetworkError';\n    this.cause = cause;\n  }\n}\n\nexport class ApiError extends Error {\n  readonly status: number;\n  readonly detail: string;\n  constructor(status: number, detail: string) {\n    super(`HTTP ${status}: ${detail}`);\n    this.name = 'ApiError';\n    this.status = status;\n    this.detail = detail;\n  }\n}\n\nexport type FieldValue = string | number | boolean | Blob | Blob[];\n\nexport interface WizardApiClientConfig {\n  /** Base URL of the .NET backend, no trailing slash. */\n  baseUrl: string;\n  /** Optional JWT for dev. In prod, omit and let the cookie carry auth. */\n  devToken?: string;\n}\n\nexport class WizardApiClient {\n  private baseUrl: string;\n  private devToken?: string;\n\n  constructor(config: WizardApiClientConfig) {\n    this.baseUrl = config.baseUrl.replace(/\\/+$/, '');\n    this.devToken = config.devToken;\n  }\n\n  /**\n   * GET with optional query string params. Response is expected to be a JSON\n   * object \u2014 parsed and returned as `T`. Use this for endpoints that fetch\n   * data with no request body (stock image search, paginated lists, etc.).\n   *\n   * Query values are coerced to strings. Numbers, booleans, and strings are\n   * the supported types. `undefined` / `null` values are dropped so the URL\n   * doesn't end up with `?foo=undefined`.\n   */\n  async getForJson<T = unknown>(\n    path: string,\n    query?: Record<string, string | number | boolean | undefined | null>,\n    opts?: { signal?: AbortSignal }\n  ): Promise<T> {\n    let fullPath = path;\n    if (query) {\n      const params = new URLSearchParams();\n      for (const [key, value] of Object.entries(query)) {\n        if (value === undefined || value === null) continue;\n        params.append(key, String(value));\n      }\n      const qs = params.toString();\n      if (qs) fullPath = `${path}?${qs}`;\n    }\n    const res = await this.rawFetch(fullPath, {\n      method: 'GET',\n      signal: opts?.signal,\n    });\n    await this.raiseForStatus(res);\n    return (await res.json()) as T;\n  }\n\n  /** GET binary response (images, audio, etc.). */\n  async getForBlob(\n    path: string,\n    query?: Record<string, string | number | boolean | undefined | null>,\n    opts?: { signal?: AbortSignal }\n  ): Promise<Blob> {\n    let fullPath = path;\n    if (query) {\n      const params = new URLSearchParams();\n      for (const [key, value] of Object.entries(query)) {\n        if (value === undefined || value === null) continue;\n        params.append(key, String(value));\n      }\n      const qs = params.toString();\n      if (qs) fullPath = `${path}?${qs}`;\n    }\n    const res = await this.rawFetch(fullPath, {\n      method: 'GET',\n      signal: opts?.signal,\n    });\n    return this.extractBlob(res);\n  }\n\n  /**\n   * POST a JSON body. Response is expected to be binary image data\n   * (image/* or application/octet-stream) \u2014 returned as a Blob.\n   */\n  async postJson(\n    path: string,\n    body: unknown,\n    opts?: { signal?: AbortSignal }\n  ): Promise<Blob> {\n    const res = await this.rawFetch(path, {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify(body),\n      signal: opts?.signal,\n    });\n    return this.extractBlob(res);\n  }\n\n  /**\n   * POST a JSON body. Response is expected to be a JSON object \u2014 parsed and\n   * returned as `T`. Use this for endpoints that return structured data\n   * (text translation, subtitle presets, color grading, etc.) instead of\n   * binary image bytes.\n   */\n  async postJsonForJson<T = unknown>(\n    path: string,\n    body: unknown,\n    opts?: { signal?: AbortSignal }\n  ): Promise<T> {\n    const res = await this.rawFetch(path, {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify(body),\n      signal: opts?.signal,\n    });\n    await this.raiseForStatus(res);\n    return (await res.json()) as T;\n  }\n\n  /**\n   * POST a multipart/form-data body. Fields can be strings, numbers, booleans,\n   * or Blobs (attached as binary file parts). File field NAMES are passed\n   * through as-is \u2014 endpoints disagree on naming (some use \"image\", some\n   * \"sketch\", some accept \"image\" + \"mask\").\n   */\n  async postMultipart(\n    path: string,\n    fields: Record<string, FieldValue>,\n    opts?: { signal?: AbortSignal }\n  ): Promise<Blob> {\n    const res = await this.rawFetch(path, {\n      method: 'POST',\n      body: buildMultipartBody(fields),\n      signal: opts?.signal,\n    });\n    return this.extractBlob(res);\n  }\n\n  /**\n   * POST a multipart/form-data body. Response is expected to be a JSON object\n   * \u2014 parsed and returned as `T`. Use this for endpoints that take a binary\n   * file (audio, video) but return structured data (transcript segments,\n   * detection results) instead of binary bytes.\n   */\n  async postMultipartForJson<T = unknown>(\n    path: string,\n    fields: Record<string, FieldValue>,\n    opts?: { signal?: AbortSignal }\n  ): Promise<T> {\n    const res = await this.rawFetch(path, {\n      method: 'POST',\n      body: buildMultipartBody(fields),\n      signal: opts?.signal,\n    });\n    await this.raiseForStatus(res);\n    return (await res.json()) as T;\n  }\n\n  /**\n   * PATCH a multipart/form-data body. Used to update existing resources\n   * (e.g. `/api/kaiman/editables/{id}`) without creating a duplicate.\n   * Tolerates 204 / empty body like `deleteForJson`.\n   */\n  async patchMultipartForJson<T = unknown>(\n    path: string,\n    fields: Record<string, FieldValue>,\n    opts?: { signal?: AbortSignal }\n  ): Promise<T> {\n    const res = await this.rawFetch(path, {\n      method: 'PATCH',\n      body: buildMultipartBody(fields),\n      signal: opts?.signal,\n    });\n    await this.raiseForStatus(res);\n    if (res.status === 204) return undefined as T;\n    const text = await res.text();\n    if (!text) return undefined as T;\n    return JSON.parse(text) as T;\n  }\n\n  /**\n   * DELETE with optional query string params. Response is expected to be a\n   * JSON object \u2014 parsed and returned as `T`. Use this for endpoints that\n   * delete a resource by id and return a small confirmation body\n   * (`{success: true}` etc.) or `void` for empty 200/204.\n   *\n   * Query values follow the same coercion rules as `getForJson`.\n   */\n  async deleteForJson<T = unknown>(\n    path: string,\n    query?: Record<string, string | number | boolean | undefined | null>,\n    opts?: { signal?: AbortSignal }\n  ): Promise<T> {\n    let fullPath = path;\n    if (query) {\n      const params = new URLSearchParams();\n      for (const [key, value] of Object.entries(query)) {\n        if (value === undefined || value === null) continue;\n        params.append(key, String(value));\n      }\n      const qs = params.toString();\n      if (qs) fullPath = `${path}?${qs}`;\n    }\n    const res = await this.rawFetch(fullPath, {\n      method: 'DELETE',\n      signal: opts?.signal,\n    });\n    await this.raiseForStatus(res);\n    // 204 No Content: return undefined cast to T.\n    if (res.status === 204) return undefined as T;\n    // Some backends send an empty body with 200; guard the parse.\n    const text = await res.text();\n    if (!text) return undefined as T;\n    return JSON.parse(text) as T;\n  }\n\n  // \u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n  private async rawFetch(path: string, init: RequestInit): Promise<Response> {\n    const headers = new Headers(init.headers);\n    if (this.devToken) {\n      headers.set('Authorization', `Bearer ${this.devToken}`);\n    }\n    // For FormData, the browser must set Content-Type with the boundary.\n    // If we leave any Content-Type the browser will not add the boundary.\n    if (init.body instanceof FormData) {\n      headers.delete('Content-Type');\n    }\n\n    // Build RequestInit explicitly (no `...init` spread) so we control each\n    // property the browser sees. `mode: 'cors'` is intentionally omitted:\n    // the Vite dev proxy makes the request same-origin, and some browser\n    // builds behave differently when 'cors' is set with FormData bodies.\n    const fetchInit: RequestInit = {\n      method: init.method ?? 'POST',\n      body: init.body,\n      headers,\n      credentials: 'include',\n    };\n    // Only attach a signal if it's a *valid* AbortSignal. We saw a browser\n    // that returns values from `AbortSignal.timeout()` (and possibly from\n    // cross-realm AbortControllers) that fail the fetch() internal type\n    // check, surfacing as \"Failed to convert value to 'AbortSignal'\".\n    const validSignal = pickValidAbortSignal(init.signal);\n    if (validSignal) {\n      fetchInit.signal = validSignal;\n    } else if (init.signal != null) {\n      console.warn(`[wizardApiClient] Signal for ${path} was not a valid AbortSignal; sending without one.`);\n    }\n\n    try {\n      return await fetch(`${this.baseUrl}${path}`, fetchInit);\n    } catch (err) {\n      if ((err as Error).name === 'AbortError') {\n        throw new NetworkError(`Request to ${path} was aborted (user cancel or timeout)`, err);\n      }\n      throw new NetworkError(`Fetch to ${path} failed: ${(err as Error).message}`, err);\n    }\n  }\n\n  private async extractBlob(res: Response): Promise<Blob> {\n    await this.raiseForStatus(res);\n    return res.blob();\n  }\n\n  /**\n   * Inspects a non-2xx response, extracts a human-readable diagnostic\n   * (`detail` / `message` / `title` field if JSON, body text otherwise)\n   * and throws the appropriate typed error. 2xx responses return silently.\n   */\n  private async raiseForStatus(res: Response): Promise<void> {\n    if (res.ok) return;\n\n    const ct = res.headers.get('content-type') ?? '';\n    let rawDetail = '';\n    let featureFromBody: string | undefined;\n    try {\n      if (ct.includes('application/json')) {\n        const json: unknown = await res.json();\n        if (json && typeof json === 'object') {\n          const j = json as Record<string, unknown>;\n          if (typeof j.feature === 'string' && j.feature.trim()) {\n            featureFromBody = j.feature.trim();\n          }\n          rawDetail =\n            (typeof j.detail === 'string' && j.detail) ||\n            (typeof j.message === 'string' && j.message) ||\n            (typeof j.error === 'string' && j.error) ||\n            (typeof j.title === 'string' && j.title) ||\n            JSON.stringify(json);\n        } else {\n          rawDetail = String(json);\n        }\n      } else {\n        rawDetail = await res.text();\n      }\n    } catch {\n      rawDetail = res.statusText;\n    }\n    const detail = (rawDetail ?? '').trim() || res.statusText;\n\n    if (res.status === 401 || res.status === 403) {\n      throw new AuthError(`Auth failed for ${res.url}: ${detail}`);\n    }\n    if (res.status === 404 || res.status === 501) {\n      const feature =\n        featureFromBody ||\n        detail.match(/Unknown AI action:\\s*([^\\s\"'}]+)/i)?.[1] ||\n        detail.match(/Feature \"([^\"]+)\"/i)?.[1] ||\n        actionNameFromUrl(res.url) ||\n        `Operation at ${res.url}`;\n      throw new NotImplementedError(feature, res.status, detail);\n    }\n    throw new ApiError(res.status, detail);\n  }\n}\n\n/** Last path segment of `/api/ai/<action>` when the body omitted `feature`. */\nfunction actionNameFromUrl(url: string): string | undefined {\n  try {\n    const path = new URL(url).pathname;\n    const parts = path.split('/').filter(Boolean);\n    const aiIdx = parts.indexOf('ai');\n    if (aiIdx >= 0 && parts[aiIdx + 1]) return parts[aiIdx + 1];\n    return parts[parts.length - 1];\n  } catch {\n    return undefined;\n  }\n}\n\n/** Build a FormData body for a multipart POST. Field NAMES are passed\n *  through as-is. Blobs become file parts; if the Blob is a File, its\n *  original name is preserved (important for audio endpoints where the\n *  extension tells the server which decoder to use \u2014 mp3 vs wav vs m4a).\n *  Booleans are stringified as \"true\"/\"false\" because .NET multipart DTOs\n *  don't accept native bools.\n */\n/** Map MIME subtype quirks to a filename extension (never bare `bin`). */\nfunction blobFilename(blob: Blob, fallbackStem: string): string {\n  if (blob instanceof File && blob.name.trim()) return blob.name;\n  const mime = (blob.type || '').toLowerCase().split(';')[0]?.trim() ?? '';\n  const mimeExt: Record<string, string> = {\n    'audio/mpeg': 'mp3',\n    'audio/mp3': 'mp3',\n    'audio/mp4': 'm4a',\n    'audio/x-m4a': 'm4a',\n    'audio/wav': 'wav',\n    'audio/webm': 'webm',\n    'audio/ogg': 'ogg',\n    'video/mp4': 'mp4',\n    'video/webm': 'webm',\n    'video/quicktime': 'mp4',\n    'image/png': 'png',\n    'image/jpeg': 'jpg',\n    'image/webp': 'webp',\n  };\n  const ext =\n    mimeExt[mime] ||\n    (mime.split('/')[1] || 'bin').replace(/[^a-z0-9]/gi, '') ||\n    'bin';\n  return `${fallbackStem}.${ext === 'mpeg' ? 'mp3' : ext}`;\n}\n\nfunction buildMultipartBody(fields: Record<string, FieldValue>): FormData {\n  const form = new FormData();\n  for (const [key, value] of Object.entries(fields)) {\n    if (Array.isArray(value)) {\n      value.forEach((item, index) => {\n        if (!(item instanceof Blob)) return;\n        form.append(key, item, blobFilename(item, `file-${index}`));\n      });\n    } else if (value instanceof Blob) {\n      form.append(key, value, blobFilename(value, key === 'file' ? 'media' : key));\n    } else if (typeof value === 'boolean') {\n      form.append(key, value ? 'true' : 'false');\n    } else {\n      form.append(key, String(value));\n    }\n  }\n  return form;\n}\n\n/** Returns the signal if it looks like a real AbortSignal, otherwise null.\n *  Some browser/polyfill environments produce values whose `[[Prototype]]`\n *  is not `AbortSignal.prototype`, and fetch() rejects those with\n *  \"Failed to convert value to 'AbortSignal'\". The duck-type check\n *  (`aborted` + `addEventListener` + `reason`) is good enough for our needs.\n */\nfunction pickValidAbortSignal(s: unknown): AbortSignal | null {\n  if (s == null) return null;\n  if (typeof s !== 'object') return null;\n  const obj = s as Record<string, unknown>;\n  if (typeof obj.aborted !== 'boolean') return null;\n  if (typeof obj.addEventListener !== 'function') return null;\n  if (!('reason' in obj)) return null;\n  return s as AbortSignal;\n}\n\n// \u2500\u2500 singleton + configuration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nlet _client: WizardApiClient | null = null;\n\nexport function configureWizardApiClient(config: WizardApiClientConfig): void {\n  _client = new WizardApiClient(config);\n}\n\nexport function getWizardApiClient(): WizardApiClient {\n  if (!_client) {\n    // Lazy default: read dev defaults from Vite env. The dev wrapper should\n    // call configureWizardApiClient() explicitly on mount.\n    const env = readDevEnv();\n    _client = new WizardApiClient({\n      baseUrl: env.VITE_BACKEND_URL ?? 'https://wizard-ai-api.com',\n      devToken: env.VITE_DEV_JWT,\n    });\n  }\n  return _client;\n}\n\nexport function resetWizardApiClient(): void {\n  _client = null;\n}\n", "/**\n * Image service \u2014 AI image ops via Wizard BFF \u2192 .NET.\n *\n * Generate uses `/api/ai/generate-image`, which the BFF maps to\n * `POST /api/image-generator/generate` (multipart). Brand guidelines\n * require a real `brand_id` plus optional logo fields from the active brand.\n */\n\nimport { getEditorIdentity } from './identity';\nimport { getActiveEditorBrand } from './activeEditorBrand';\nimport { getWizardApiClient, type FieldValue } from './wizardApiClient';\n\n/** .NET image_purpose enum (Swagger). */\nexport type ImageGeneratorPurpose =\n  | 'Ad'\n  | 'Social Post'\n  | 'Brand Asset'\n  | 'Blog'\n  | 'Product Showcase';\n\nexport type ImageGeneratorAspectRatio =\n  | '1:1'\n  | '4:5'\n  | '9:16'\n  | '16:9'\n  | '3:2';\n\nexport const IMAGE_GENERATOR_ASPECT_RATIOS: readonly ImageGeneratorAspectRatio[] =\n  ['1:1', '4:5', '9:16', '16:9', '3:2'] as const;\n\n/** Editor UI: 1K / 2K only (OMNI doc \u2014 4K is clamped to 2K). */\nexport type ImageGeneratorResolution = '1K' | '2K';\n\nexport const IMAGE_GENERATOR_RESOLUTIONS: readonly ImageGeneratorResolution[] =\n  ['1K', '2K'] as const;\n\nexport const DEFAULT_IMAGE_GENERATOR_RESOLUTION: ImageGeneratorResolution = '2K';\n\n/** Clamp upstream `1K`/`2K`/`4K` to what the editor may send. */\nexport function clampEditorImageResolution(\n  value?: string | null,\n): ImageGeneratorResolution {\n  return value === '1K' ? '1K' : DEFAULT_IMAGE_GENERATOR_RESOLUTION;\n}\n\n// \u2500\u2500 POST /api/ai/generate-image \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface GenerateImageOptions {\n  prompt: string;\n  /** Override purpose; default Brand Asset when a brand is selected. */\n  imagePurpose?: ImageGeneratorPurpose;\n  aspectRatio?: ImageGeneratorAspectRatio;\n  /** Nano Banana resolution; default 2K (4K \u2192 2K in editor). */\n  resolution?: ImageGeneratorResolution | '4K';\n  /** Reference images for the generator (`uploaded_elements`). */\n  references?: Blob[];\n  /** Always false for AI Studio generate (user request). */\n  includeLogo?: boolean;\n  signal?: AbortSignal;\n}\n\n/** Map canvas W\u00D7H to the closest supported aspect_ratio enum. */\nexport function aspectRatioFromPageSize(\n  width: number,\n  height: number,\n): ImageGeneratorAspectRatio {\n  const w = Math.max(1, width);\n  const h = Math.max(1, height);\n  const ratio = w / h;\n  const candidates: { label: ImageGeneratorAspectRatio; value: number }[] = [\n    { label: '1:1', value: 1 },\n    { label: '4:5', value: 4 / 5 },\n    { label: '9:16', value: 9 / 16 },\n    { label: '16:9', value: 16 / 9 },\n    { label: '3:2', value: 3 / 2 },\n  ];\n  let best = candidates[0]!;\n  let bestDist = Math.abs(ratio - best.value);\n  for (const c of candidates) {\n    const d = Math.abs(ratio - c.value);\n    if (d < bestDist) {\n      best = c;\n      bestDist = d;\n    }\n  }\n  return best.label;\n}\n\nexport function generateImage(opts: GenerateImageOptions): Promise<Blob> {\n  const prompt = (opts.prompt ?? '').trim();\n  if (!prompt) {\n    return Promise.reject(new Error('prompt is required'));\n  }\n\n  const { accountId, brandId } = getEditorIdentity();\n  const brand = getActiveEditorBrand();\n  const effectiveBrandId = brand?.id || brandId || '';\n  const hasBrand = Boolean(effectiveBrandId);\n  const imagePurpose =\n    opts.imagePurpose ?? (hasBrand ? 'Brand Asset' : 'Ad');\n  const includeLogo = opts.includeLogo === true;\n  const aspectRatio = opts.aspectRatio ?? '1:1';\n  const resolution = clampEditorImageResolution(opts.resolution);\n  const references =\n    opts.references?.filter((b) => b && b.size > 0) ?? [];\n\n  // Prefer JSON when there are no reference files. Some host/proxy paths\n  // mishandle multipart text fields and the BFF then returns\n  // {\"error\":\"prompt is required\"}. JSON keeps `prompt` reliable.\n  // Always send both `prompt` and `image_prompt` (BFF + .NET aliases).\n  // No artistic `style` field \u2014 purpose only via `image_purpose`.\n  if (references.length === 0) {\n    return getWizardApiClient().postJson(\n      '/api/ai/generate-image',\n      {\n        prompt,\n        image_prompt: prompt,\n        image_purpose: imagePurpose,\n        aspect_ratio: aspectRatio,\n        resolution,\n        account_id: accountId,\n        brand_id: effectiveBrandId,\n        include_logo: includeLogo,\n      },\n      { signal: opts.signal },\n    );\n  }\n\n  const fields: Record<string, FieldValue> = {\n    prompt,\n    image_prompt: prompt,\n    image_purpose: imagePurpose,\n    aspect_ratio: aspectRatio,\n    resolution,\n    account_id: accountId,\n    brand_id: effectiveBrandId,\n    include_logo: includeLogo,\n    uploaded_elements: references,\n  };\n\n  return getWizardApiClient().postMultipart(\n    '/api/ai/generate-image',\n    fields,\n    { signal: opts.signal },\n  );\n}\n\n// \u2500\u2500 POST /api/ai/generate-image-gemini \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface GenerateImageWithGeminiOptions {\n  prompt: string;\n  resolution?: ImageGeneratorResolution | '4K';\n  signal?: AbortSignal;\n}\n\nexport function generateImageWithGemini(\n  opts: GenerateImageWithGeminiOptions\n): Promise<Blob> {\n  const prompt = (opts.prompt ?? '').trim();\n  if (!prompt) {\n    return Promise.reject(new Error('prompt is required'));\n  }\n  const { accountId, brandId } = getEditorIdentity();\n  const brand = getActiveEditorBrand();\n  return getWizardApiClient().postJson(\n    '/api/ai/generate-image-gemini',\n    {\n      prompt,\n      image_prompt: prompt,\n      account_id: accountId,\n      brand_id: brand?.id || brandId || '',\n      image_purpose: 'Brand Asset',\n      aspect_ratio: '1:1',\n      resolution: clampEditorImageResolution(opts.resolution),\n      include_logo: false,\n    },\n    { signal: opts.signal },\n  );\n}\n\n// \u2500\u2500 POST /api/ai/remove-background \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface RemoveBackgroundOptions {\n  image: Blob;\n  signal?: AbortSignal;\n}\n\nexport function removeBackground(opts: RemoveBackgroundOptions): Promise<Blob> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postMultipart(\n    '/api/ai/remove-background',\n    {\n      image: opts.image,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n}\n\n// \u2500\u2500 POST /api/ai/modify-image \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface ModifyImageOptions {\n  image: Blob;\n  prompt: string;\n  hasTransparency: boolean;\n  wantsBackground: boolean;\n  signal?: AbortSignal;\n}\n\nexport function modifyImage(opts: ModifyImageOptions): Promise<Blob> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postMultipart(\n    '/api/ai/modify-image',\n    {\n      image: opts.image,\n      prompt: opts.prompt,\n      hasTransparency: opts.hasTransparency,\n      wantsBackground: opts.wantsBackground,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n}\n\n// \u2500\u2500 POST /api/ai/sketch-to-image \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface SketchToImageOptions {\n  /** Note: server-side field name is \"sketch\", not \"image\". */\n  sketch: Blob;\n  prompt: string;\n  hasTransparency: boolean;\n  wantsBackground: boolean;\n  signal?: AbortSignal;\n}\n\nexport function sketchToImage(opts: SketchToImageOptions): Promise<Blob> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postMultipart(\n    '/api/ai/sketch-to-image',\n    {\n      sketch: opts.sketch,\n      prompt: opts.prompt,\n      hasTransparency: opts.hasTransparency,\n      wantsBackground: opts.wantsBackground,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n}\n\n// \u2500\u2500 POST /api/ai/magic-eraser \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface MagicEraserOptions {\n  image: Blob;\n  mask: Blob;\n  /** Default 2K; 4K clamped to 2K in the editor. */\n  resolution?: ImageGeneratorResolution | '4K';\n  /** Optional fill instruction for the erased region. */\n  instruction?: string;\n  signal?: AbortSignal;\n}\n\nexport function magicEraser(opts: MagicEraserOptions): Promise<Blob> {\n  const { accountId, brandId } = getEditorIdentity();\n  const fields: Record<string, FieldValue> = {\n    image: opts.image,\n    mask: opts.mask,\n    resolution: clampEditorImageResolution(opts.resolution),\n    account_id: accountId,\n    brand_id: brandId,\n  };\n  const instruction = (opts.instruction ?? '').trim();\n  if (instruction) fields.instruction = instruction;\n  return getWizardApiClient().postMultipart(\n    '/api/ai/magic-eraser',\n    fields,\n    { signal: opts.signal },\n  );\n}\n", "/**\n * Text generation / rewrite / variants / brand-voice via /api/text/*.\n */\n\nimport { getEditorIdentity } from '../identity';\nimport { getWizardApiClient } from '../wizardApiClient';\n\nexport async function generateText(opts: {\n  prompt: string;\n  tone?: string;\n  language?: string;\n  maxWords?: number;\n  signal?: AbortSignal;\n}): Promise<{ text: string }> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postJsonForJson('/api/text/generate', {\n    prompt: opts.prompt,\n    tone: opts.tone,\n    language: opts.language ?? 'es',\n    maxWords: opts.maxWords,\n    account_id: String(accountId),\n    brand_id: String(brandId),\n  }, { signal: opts.signal });\n}\n\nexport async function rewriteText(opts: {\n  text: string;\n  instruction: string;\n  tone?: string;\n  signal?: AbortSignal;\n}): Promise<{ text: string; rationale?: string }> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postJsonForJson('/api/text/rewrite', {\n    text: opts.text,\n    instruction: opts.instruction,\n    tone: opts.tone,\n    account_id: String(accountId),\n    brand_id: String(brandId),\n  }, { signal: opts.signal });\n}\n\nexport async function generateVariants(opts: {\n  text: string;\n  channels: string[];\n  /** Optional per-channel tone overrides from Brand OS. */\n  channelTones?: Record<string, string>;\n  signal?: AbortSignal;\n}): Promise<{\n  variants: Array<{ channel: string; title?: string; content: string }>;\n}> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postJsonForJson('/api/text/variants', {\n    text: opts.text,\n    channels: opts.channels,\n    channelTones: opts.channelTones,\n    account_id: String(accountId),\n    brand_id: String(brandId),\n  }, { signal: opts.signal });\n}\n\nexport async function generateOutline(opts: {\n  topic: string;\n  docType?: string;\n  signal?: AbortSignal;\n}): Promise<{ sections: Array<{ heading: string; intent?: string; keywords?: string[] }> }> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postJsonForJson('/api/text/outline', {\n    topic: opts.topic,\n    docType: opts.docType,\n    account_id: String(accountId),\n    brand_id: String(brandId),\n  }, { signal: opts.signal });\n}\n\nexport async function scoreBrandVoice(opts: {\n  text: string;\n  preferredTerms?: string[];\n  forbiddenTerms?: string[];\n  tone?: string;\n  signal?: AbortSignal;\n}): Promise<{ score: number; notes: string[] }> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postJsonForJson('/api/text/score-brand-voice', {\n    text: opts.text,\n    preferredTerms: opts.preferredTerms,\n    forbiddenTerms: opts.forbiddenTerms,\n    tone: opts.tone,\n    account_id: String(accountId),\n    brand_id: String(brandId),\n  }, { signal: opts.signal });\n}\n\nexport type SectionOp = 'tighten' | 'elevate' | 'localize' | 'expand';\n\nexport async function runSectionOp(opts: {\n  text: string;\n  op: SectionOp;\n  locale?: string;\n  signal?: AbortSignal;\n}): Promise<{ text: string; rationale?: string }> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postJsonForJson('/api/text/section-ops', {\n    text: opts.text,\n    op: opts.op,\n    locale: opts.locale,\n    account_id: String(accountId),\n    brand_id: String(brandId),\n  }, { signal: opts.signal });\n}\n\nexport async function scoreAbVariants(opts: {\n  variants: string[];\n  signal?: AbortSignal;\n}): Promise<{\n  scores: Array<{\n    index: number;\n    clarity: number;\n    ctaStrength: number;\n    brandFit: number;\n    notes?: string;\n  }>;\n}> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postJsonForJson('/api/text/ab-score', {\n    variants: opts.variants,\n    account_id: String(accountId),\n    brand_id: String(brandId),\n  }, { signal: opts.signal });\n}\n\nexport async function runCompliancePass(opts: {\n  text: string;\n  industry?: string;\n  forbidden?: string[];\n  disclaimers?: string[];\n  signal?: AbortSignal;\n}): Promise<{ flags: Array<{ severity: 'info' | 'warn' | 'block'; message: string }> }> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postJsonForJson('/api/text/compliance', {\n    text: opts.text,\n    industry: opts.industry,\n    forbidden: opts.forbidden,\n    disclaimers: opts.disclaimers,\n    account_id: String(accountId),\n    brand_id: String(brandId),\n  }, { signal: opts.signal });\n}\n\nexport async function voiceMatchRewrite(opts: {\n  text: string;\n  samples: string[];\n  signal?: AbortSignal;\n}): Promise<{ text: string; rationale?: string }> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postJsonForJson('/api/text/voice-match', {\n    text: opts.text,\n    samples: opts.samples,\n    account_id: String(accountId),\n    brand_id: String(brandId),\n  }, { signal: opts.signal });\n}\n\nexport async function analyzeClaims(opts: {\n  text: string;\n  signal?: AbortSignal;\n}): Promise<{\n  claims: Array<{ text: string; status?: string; note?: string }>;\n}> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postJsonForJson('/api/text/analyze-claims', {\n    text: opts.text,\n    account_id: String(accountId),\n    brand_id: String(brandId),\n  }, { signal: opts.signal });\n}\n", "/**\n * Image AI engine (server-backed generation and local fallbacks)\n * Provides state-of-the-art client-side AI processing:\n * 1. window.ai (Gemini Nano) local LLM wrapper with contextual copy fallback.\n * 2. Pixel-level background removal (Color-keying with border feathering).\n * 3. Prompt-driven image styling (Sketch/Sobel, Cyberpunk glow, Polaroid retro).\n * 4. Flood-fill image segmentation (Magic Wand object slicing).\n * 5. Bezier-curve path vectorization for hand-drawn strokes.\n *\n * Image generation / editing operations (removeBackground, modifyImageByPrompt,\n * sketchToImage, magicEraser, generateImageFromPrompt) are now backed by the\n * editor's own wizardApiClient \u2192 .NET backend (wizard-ai-api.com). They take\n * a dataURL for compatibility with the rest of the editor and convert it to\n * a Blob before calling the new imageService.\n *\n * Text-only operations (generateTextCopy, generateCopywritingSuggestions)\n * still call external providers directly because their .NET endpoints have\n * not been verified yet \u2014 they keep their apiKey parameter for now.\n */\n\nimport {\n  generateImage as svcGenerateImage,\n  removeBackground as svcRemoveBackground,\n  modifyImage as svcModifyImage,\n  sketchToImage as svcSketchToImage,\n  magicEraser as svcMagicEraser,\n} from './imageService';\n\n// \u2500\u2500 dataURL \u2194 Blob bridge (internal) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function dataUrlToBlob(dataUrl: string): Promise<Blob> {\n  const res = await fetch(dataUrl);\n  return res.blob();\n}\n\nasync function blobToDataUrl(blob: Blob): Promise<string> {\n  return new Promise((resolve, reject) => {\n    const reader = new FileReader();\n    reader.onloadend = () => resolve(reader.result as string);\n    reader.onerror = () => reject(reader.error ?? new Error('FileReader failed'));\n    reader.readAsDataURL(blob);\n  });\n}\n\n// Helper to load image data URL into an HTMLImageElement\nconst loadImage = (src: string): Promise<HTMLImageElement> => {\n  return new Promise((resolve, reject) => {\n    const img = new Image();\n    img.crossOrigin = 'anonymous';\n    img.src = src;\n    img.onload = () => resolve(img);\n    img.onerror = (err) => reject(err);\n  });\n};\n\n/**\n * Checks if the browser supports local AI (Gemini Nano)\n */\nexport const checkLocalAiSupport = (): boolean => {\n  const anyWin = window as any;\n  return !!(anyWin.ai?.languageModel || anyWin.ai?.createTextSession || anyWin.chrome?.aiOriginTrial?.languageModel);\n};\n\n/**\n * 1. AI Copywriting Generator\n * Integrates with window.ai (Gemini Nano) or uses a highly contextual local generator.\n */\nexport const generateTextCopy = async (prompt: string, _apiKey?: string): Promise<string> => {\n  // Prefer /api/text/generate (dev-backend \u2192 .NET). Never call Gemini from the browser.\n  try {\n    const { generateText } = await import('./text/generateService');\n    const res = await generateText({\n      prompt: `Escribe un texto comercial corto y persuasivo (maximo 12 palabras): ${prompt}`,\n      language: 'es',\n      maxWords: 12,\n    });\n    if (res.text?.trim()) return res.text.trim().replace(/^[\"']|[\"']$/g, '');\n  } catch (err) {\n    console.warn('generateText via /api/text failed, using local fallback:', err);\n  }\n\n  const cleanPrompt = prompt.trim().toLowerCase();\n  \n  // Try to use Chrome window.ai (Gemini Nano)\n  try {\n    const anyWin = window as any;\n    let session: any = null;\n    \n    if (anyWin.ai?.languageModel) {\n      session = await anyWin.ai.languageModel.create();\n    } else if (anyWin.chrome?.aiOriginTrial?.languageModel) {\n      session = await anyWin.chrome.aiOriginTrial.languageModel.create();\n    } else if (anyWin.ai?.createTextSession) {\n      session = await anyWin.ai.createTextSession();\n    }\n    \n    if (session) {\n      const systemPrompt = \"Eres un redactor creativo experto. Escribe un texto comercial corto y persuasivo (m\u00E1ximo 12 palabras) basado en la solicitud del usuario.\";\n      const fullPrompt = `${systemPrompt}\\n\\nUsuario solicita: \"${prompt}\"\\n\\nRespuesta redactada:`;\n      const response = await session.prompt(fullPrompt);\n      if (response && response.trim()) {\n        return response.trim().replace(/^[\"']|[\"']$/g, ''); // strip outer quotes\n      }\n    }\n  } catch (err) {\n    console.warn(\"Gemini Nano window.ai call failed or was rejected, using local smart fallback engine:\", err);\n  }\n\n  // Smart Contextual Fallback Copywriting Engine\n  // Analyzes prompt keywords to match professional marketing templates in Spanish/English\n  \n  // T\u00EDtulo / Coffee / Cafeter\u00EDa\n  if (cleanPrompt.includes(\"cafe\") || cleanPrompt.includes(\"coffee\") || cleanPrompt.includes(\"caf\u00E9\")) {\n    const options = [\n      \"Despierta tus Sentidos con el Mejor Caf\u00E9 de Especialidad\",\n      \"Caf\u00E9 Reci\u00E9n Tostado: Energ\u00EDa Pura en Cada Taza\",\n      \"El Aroma que Inspira tus Ma\u00F1anas\",\n      \"Sabor Intenso, Granos Org\u00E1nicos Seleccionados\"\n    ];\n    return options[Math.floor(Math.random() * options.length)];\n  }\n  // Moda / Ropa / Zapato / Oferta\n  if (cleanPrompt.includes(\"moda\") || cleanPrompt.includes(\"ropa\") || cleanPrompt.includes(\"fashion\") || cleanPrompt.includes(\"oferta\") || cleanPrompt.includes(\"zapato\") || cleanPrompt.includes(\"shoes\")) {\n    const options = [\n      \"Colecci\u00F3n de Temporada: Renueva tu Estilo con 30% Off\",\n      \"Estilo \u00DAnico para Personas Extraordinarias\",\n      \"Viste la Tendencia: Calidad y Confort sin Excusas\",\n      \"Luce Incre\u00EDble Todos los D\u00EDas. Env\u00EDo Gratis Hoy\"\n    ];\n    return options[Math.floor(Math.random() * options.length)];\n  }\n  // Deporte / Fit / Gimnasio\n  if (cleanPrompt.includes(\"deporte\") || cleanPrompt.includes(\"gym\") || cleanPrompt.includes(\"fitness\") || cleanPrompt.includes(\"ejercicio\") || cleanPrompt.includes(\"correr\")) {\n    const options = [\n      \"Supera tus L\u00EDmites: Entrena Fuerte, Vive Sano\",\n      \"Tu Mejor Versi\u00F3n Comienza Hoy\",\n      \"Rendimiento Extremo con Calzado Pro-Run\",\n      \"Siente la Fuerza del Progreso Diario\"\n    ];\n    return options[Math.floor(Math.random() * options.length)];\n  }\n  // Comida / Pizza / Hamburguesa / Restaurante\n  if (cleanPrompt.includes(\"comida\") || cleanPrompt.includes(\"pizza\") || cleanPrompt.includes(\"hamburguesa\") || cleanPrompt.includes(\"burger\") || cleanPrompt.includes(\"restaurante\")) {\n    const options = [\n      \"Sabor Casero Hecho con Ingredientes Premium\",\n      \"La Receta Original que Todo el Mundo Ama\",\n      \"Irresistiblemente Jugosa: P\u00EDdela Ahora a Domicilio\",\n      \"Pasi\u00F3n por los Ingredientes Frescos y Sabrosos\"\n    ];\n    return options[Math.floor(Math.random() * options.length)];\n  }\n  // Tecnolog\u00EDa / Software / Startup / Celular\n  if (cleanPrompt.includes(\"tech\") || cleanPrompt.includes(\"tecnologia\") || cleanPrompt.includes(\"software\") || cleanPrompt.includes(\"app\") || cleanPrompt.includes(\"digital\")) {\n    const options = [\n      \"Simplifica tu Flujo de Trabajo con Inteligencia Artificial\",\n      \"La Revoluci\u00F3n Digital al Alcance de tu Mano\",\n      \"Seguridad, Velocidad y Conectividad sin L\u00EDmites\",\n      \"Dise\u00F1ado para Impulsar la Productividad de tu Negocio\"\n    ];\n    return options[Math.floor(Math.random() * options.length)];\n  }\n  \n  // Generic Catchy Marketing Hooks\n  const generalOptions = [\n    \"Dise\u00F1os de Calidad Profesional Creados al Instante\",\n    \"Eleva tu Marca con Contenido Visual de Alto Impacto\",\n    \"Tu Pr\u00F3xima Gran Idea Comienza en este Lienzo\",\n    \"Sencillo, R\u00E1pido y Totalmente Profesional\"\n  ];\n  return generalOptions[Math.floor(Math.random() * generalOptions.length)];\n};\n\n/**\n * 2. Background Remover\n * Detects background color (analyzing corners) and transparent-masks matched pixels.\n * Uses color-keying tolerance and alpha-feathering for professional smooth cutouts.\n */\nexport const applyChromakey = async (imageDataUrl: string, tolerance: number = 48): Promise<string> => {\n  const img = await loadImage(imageDataUrl);\n  const canvas = document.createElement('canvas');\n  canvas.width = img.naturalWidth;\n  canvas.height = img.naturalHeight;\n  \n  const ctx = canvas.getContext('2d', { willReadFrequently: true });\n  if (!ctx) return imageDataUrl;\n  \n  ctx.drawImage(img, 0, 0);\n  const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n  const data = imgData.data;\n  const width = canvas.width;\n  const height = canvas.height;\n  \n  // 1. Detect background color from corner sampling\n  const corners = [\n    { r: data[0], g: data[1], b: data[2], a: data[3] },\n    { r: data[(width - 1) * 4], g: data[(width - 1) * 4 + 1], b: data[(width - 1) * 4 + 2], a: data[(width - 1) * 4 + 3] },\n    { r: data[(height - 1) * width * 4], g: data[(height - 1) * width * 4 + 1], b: data[(height - 1) * width * 4 + 2], a: data[(height - 1) * width * 4 + 3] },\n    { r: data[(data.length - 4)], g: data[(data.length - 3)], b: data[(data.length - 2)], a: data[(data.length - 1)] }\n  ];\n  \n  let bgR = 255, bgG = 255, bgB = 255;\n  const solidCorners = corners.filter(c => c.a > 50);\n  if (solidCorners.length > 0) {\n    const sum = solidCorners.reduce((acc, c) => ({ r: acc.r + c.r, g: acc.g + c.g, b: acc.b + c.b }), { r: 0, g: 0, b: 0 });\n    bgR = sum.r / solidCorners.length;\n    bgG = sum.g / solidCorners.length;\n    bgB = sum.b / solidCorners.length;\n  }\n\n  // 2. Initialize mask: 255 is foreground (keep), 0 is background (remove)\n  const mask = new Uint8Array(width * height);\n  mask.fill(255);\n  \n  // Flood fill queue and visited set\n  const queue: number[] = [];\n  const visited = new Uint8Array(width * height);\n  \n  const isBgColor = (r: number, g: number, b: number, a: number): boolean => {\n    if (a < 10) return true; // transparent is background\n    const dist = Math.sqrt(\n      Math.pow(r - bgR, 2) +\n      Math.pow(g - bgG, 2) +\n      Math.pow(b - bgB, 2)\n    );\n    return dist < tolerance;\n  };\n  \n  // Helper to push to queue\n  const pushToQueue = (x: number, y: number) => {\n    const idx = y * width + x;\n    if (visited[idx] === 0) {\n      visited[idx] = 1;\n      const pixelStart = idx * 4;\n      if (isBgColor(data[pixelStart], data[pixelStart + 1], data[pixelStart + 2], data[pixelStart + 3])) {\n        mask[idx] = 0;\n        queue.push(idx);\n      }\n    }\n  };\n  \n  // Push all border pixels\n  for (let x = 0; x < width; x++) {\n    pushToQueue(x, 0);\n    pushToQueue(x, height - 1);\n  }\n  for (let y = 0; y < height; y++) {\n    pushToQueue(0, y);\n    pushToQueue(width - 1, y);\n  }\n  \n  // Perform flood fill\n  while (queue.length > 0) {\n    const idx = queue.shift()!;\n    const cx = idx % width;\n    const cy = Math.floor(idx / width);\n    \n    // Check 4 neighbors\n    const neighbors = [\n      { x: cx - 1, y: cy },\n      { x: cx + 1, y: cy },\n      { x: cx, y: cy - 1 },\n      { x: cx, y: cy + 1 }\n    ];\n    \n    for (const n of neighbors) {\n      if (n.x >= 0 && n.x < width && n.y >= 0 && n.y < height) {\n        pushToQueue(n.x, n.y);\n      }\n    }\n  }\n  \n  // 3. Smooth the mask edges (feathering/blur)\n  const smoothMask = new Uint8Array(width * height);\n  for (let y = 0; y < height; y++) {\n    for (let x = 0; x < width; x++) {\n      const idx = y * width + x;\n      // Border pixels keep their mask values, inner pixels get smoothed\n      if (x === 0 || x === width - 1 || y === 0 || y === height - 1) {\n        smoothMask[idx] = mask[idx];\n        continue;\n      }\n      \n      let sum = 0;\n      for (let ky = -1; ky <= 1; ky++) {\n        for (let kx = -1; kx <= 1; kx++) {\n          sum += mask[(y + ky) * width + (x + kx)];\n        }\n      }\n      smoothMask[idx] = sum / 9;\n    }\n  }\n  \n  // Apply mask values back to canvas alpha channels\n  for (let i = 0; i < data.length; i += 4) {\n    const idx = i / 4;\n    const alpha = smoothMask[idx];\n    \n    if (alpha === 0) {\n      data[i + 3] = 0; // fully transparent background\n    } else if (alpha < 255) {\n      // smooth alpha border blending\n      data[i + 3] = Math.round((data[i + 3] * alpha) / 255);\n    }\n  }\n  \n  ctx.putImageData(imgData, 0, 0);\n  return canvas.toDataURL('image/png');\n};\n\n// Helper to check if an image has any transparent pixels (Alpha < 250)\nexport const hasTransparency = async (imageDataUrl: string): Promise<boolean> => {\n  try {\n    const img = await loadImage(imageDataUrl);\n    const canvas = document.createElement('canvas');\n    canvas.width = img.naturalWidth;\n    canvas.height = img.naturalHeight;\n    const ctx = canvas.getContext('2d', { willReadFrequently: true });\n    if (!ctx) return false;\n    ctx.drawImage(img, 0, 0);\n    const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n    const data = imgData.data;\n    for (let i = 3; i < data.length; i += 4) {\n      if (data[i] < 250) {\n        return true;\n      }\n    }\n  } catch (e) {\n    console.error(\"Error checking transparency:\", e);\n  }\n  return false;\n};\n\n// Helper to composite a transparent image onto a solid white background\nexport const compositeOnWhite = async (imageDataUrl: string): Promise<string> => {\n  try {\n    const img = await loadImage(imageDataUrl);\n    const canvas = document.createElement('canvas');\n    canvas.width = img.naturalWidth;\n    canvas.height = img.naturalHeight;\n    const ctx = canvas.getContext('2d', { willReadFrequently: true });\n    if (!ctx) return imageDataUrl;\n    \n    ctx.fillStyle = '#FFFFFF';\n    ctx.fillRect(0, 0, canvas.width, canvas.height);\n    ctx.drawImage(img, 0, 0);\n    \n    return canvas.toDataURL('image/png');\n  } catch (e) {\n    console.error(\"Error compositing image on white:\", e);\n    return imageDataUrl;\n  }\n};\n\n// Helper to check if user prompt is requesting to add a background\nexport const wantsBackground = (prompt: string): boolean => {\n  const p = prompt.toLowerCase();\n  return (\n    p.includes(\"fondo\") ||\n    p.includes(\"background\") ||\n    p.includes(\"paisaje\") ||\n    p.includes(\"cielo\") ||\n    p.includes(\"sky\") ||\n    p.includes(\"beach\") ||\n    p.includes(\"playa\") ||\n    p.includes(\"escenario\") ||\n    p.includes(\"en un\") ||\n    p.includes(\"en una\") ||\n    p.includes(\"in a\") ||\n    p.includes(\"on a\") ||\n    p.includes(\"with a\") ||\n    p.includes(\"con fondo\") ||\n    p.includes(\"poner\")\n  );\n};\n\nexport const removeBackground = async (imageDataUrl: string): Promise<string> => {\n  const blob = await dataUrlToBlob(imageDataUrl);\n  const result = await svcRemoveBackground({ image: blob });\n  return blobToDataUrl(result);\n};\n\nexport const modifyImageByPrompt = async (imageDataUrl: string, prompt: string): Promise<string> => {\n  const transparent = await hasTransparency(imageDataUrl);\n  const wantsBg = wantsBackground(prompt);\n\n  // The .NET endpoint accepts hasTransparency/wantsBackground hints and\n  // handles the compositing server-side. We still need the values locally\n  // to decide whether to flatten the input onto white before sending.\n  let processedInputUrl = imageDataUrl;\n  if (transparent) {\n    processedInputUrl = await compositeOnWhite(imageDataUrl);\n  }\n\n  const blob = await dataUrlToBlob(processedInputUrl);\n  const result = await svcModifyImage({\n    image: blob,\n    prompt,\n    hasTransparency: transparent,\n    wantsBackground: wantsBg,\n  });\n  return blobToDataUrl(result);\n};\n\n/**\n * 3.1. Text-to-Image Generation\n * Delegates to the .NET backend at /api/ai/generate-image. The previous\n * direct-to-Gemini + loremflickr fallback path has been removed; if the\n * backend is unavailable, the wizardApiClient throws and the caller's\n * try/catch surfaces the error to the user.\n */\nexport const generateImageFromPrompt = async (\n  prompt: string,\n  opts?: {\n    aspectRatio?: import('./imageService').ImageGeneratorAspectRatio;\n    resolution?: import('./imageService').ImageGeneratorResolution | '4K';\n    references?: Blob[];\n    includeLogo?: boolean;\n  },\n): Promise<string> => {\n  const blob = await svcGenerateImage({\n    prompt,\n    aspectRatio: opts?.aspectRatio,\n    resolution: opts?.resolution,\n    references: opts?.references,\n    includeLogo: opts?.includeLogo ?? false,\n  });\n  // Keep backend 1K/2K pixel dimensions \u2014 do not downscale for the canvas.\n  return blobToDataUrl(blob);\n};\n\n/**\n * 4. Image Object Segmenter (Magic Wand Slicer)\n * Click-aware flood-fill algorithm. Extracts a cohesive object color segment \n * surrounding the clicked coordinate (x,y) and outputs a cropped png layer.\n */\nexport const segmentImageObject = async (imageDataUrl: string, clickX: number, clickY: number): Promise<string> => {\n  const img = await loadImage(imageDataUrl);\n  const canvas = document.createElement('canvas');\n  canvas.width = img.naturalWidth;\n  canvas.height = img.naturalHeight;\n  \n  const ctx = canvas.getContext('2d', { willReadFrequently: true });\n  if (!ctx) return imageDataUrl;\n  \n  ctx.drawImage(img, 0, 0);\n  const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n  const data = imgData.data;\n  const width = canvas.width;\n  const height = canvas.height;\n  \n  // Clamp coordinates\n  const startX = Math.min(width - 1, Math.max(0, Math.round(clickX)));\n  const startY = Math.min(height - 1, Math.max(0, Math.round(clickY)));\n  \n  // Seed pixel color\n  const seedIdx = (startY * width + startX) * 4;\n  const seedR = data[seedIdx];\n  const seedG = data[seedIdx + 1];\n  const seedB = data[seedIdx + 2];\n  const seedA = data[seedIdx + 3];\n  \n  if (seedA < 10) return imageDataUrl; // Clicked transparent area\n  \n  // Flood fill tracking structures\n  const visited = new Uint8Array(width * height);\n  const queue: number[] = [];\n  \n  queue.push(startY * width + startX);\n  visited[startY * width + startX] = 1;\n  \n  const tolerance = 32; // color boundary matching\n  \n  while (queue.length > 0) {\n    const idx = queue.shift()!;\n    const cx = idx % width;\n    const cy = Math.floor(idx / width);\n    \n    // Check 4-connected neighbors\n    const neighbors = [\n      { x: cx - 1, y: cy },\n      { x: cx + 1, y: cy },\n      { x: cx, y: cy - 1 },\n      { x: cx, y: cy + 1 }\n    ];\n    \n    for (const n of neighbors) {\n      if (n.x >= 0 && n.x < width && n.y >= 0 && n.y < height) {\n        const nIdx = n.y * width + n.x;\n        if (visited[nIdx] === 0) {\n          const pixelStart = nIdx * 4;\n          const nr = data[pixelStart];\n          const ng = data[pixelStart + 1];\n          const nb = data[pixelStart + 2];\n          const na = data[pixelStart + 3];\n          \n          if (na > 10) {\n            const dist = Math.sqrt(\n              Math.pow(nr - seedR, 2) +\n              Math.pow(ng - seedG, 2) +\n              Math.pow(nb - seedB, 2)\n            );\n            \n            if (dist < tolerance) {\n              visited[nIdx] = 1;\n              queue.push(nIdx);\n            }\n          }\n        }\n      }\n    }\n  }\n  \n  // Clear all non-segmented pixels (background masking)\n  for (let i = 0; i < data.length; i += 4) {\n    const idx = i / 4;\n    if (visited[idx] === 0) {\n      data[i + 3] = 0; // Transparent\n    }\n  }\n  \n  ctx.putImageData(imgData, 0, 0);\n  return canvas.toDataURL('image/png');\n};\n\n/**\n * 5. Bezier Curve Stroke Vectorizer\n * Smooths freehand brush drawings by calculating quadratic/cubic Bezier control points.\n * Returns a high-fidelity SVG path string.\n */\nexport const vectorizeStroke = (points: { x: number; y: number }[]): string => {\n  if (points.length < 2) return '';\n  if (points.length === 2) {\n    return `M ${points[0].x} ${points[0].y} L ${points[1].x} ${points[1].y}`;\n  }\n  \n  let pathStr = `M ${points[0].x} ${points[0].y}`;\n  \n  for (let i = 1; i < points.length - 1; i++) {\n    // Calculate control points as midpoints between current and next points\n    const xc = (points[i].x + points[i + 1].x) / 2;\n    const yc = (points[i].y + points[i + 1].y) / 2;\n    pathStr += ` Q ${points[i].x} ${points[i].y}, ${xc} ${yc}`;\n  }\n  \n  // Close curve at final point\n  pathStr += ` L ${points[points.length - 1].x} ${points[points.length - 1].y}`;\n  \n  return pathStr;\n};\n\n/**\n * Ramer-Douglas-Peucker (RDP) algorithm for point simplification.\n * Reduces the number of points in a curve while preserving its shape.\n */\nexport const simplifyPoints = (points: { x: number; y: number }[], tolerance: number): { x: number; y: number }[] => {\n  if (points.length <= 2) return points;\n\n  // Find the point with the maximum distance\n  let dmax = 0;\n  let index = 0;\n  const end = points.length - 1;\n\n  for (let i = 1; i < end; i++) {\n    const d = getPerpendicularDistance(points[i], points[0], points[end]);\n    if (d > dmax) {\n      index = i;\n      dmax = d;\n    }\n  }\n\n  // If max distance is greater than tolerance, recursively simplify\n  if (dmax > tolerance) {\n    const results1 = simplifyPoints(points.slice(0, index + 1), tolerance);\n    const results2 = simplifyPoints(points.slice(index), tolerance);\n\n    // Build the result list (exclude duplicate middle point)\n    return results1.slice(0, results1.length - 1).concat(results2);\n  } else {\n    return [points[0], points[end]];\n  }\n};\n\n// Helper for perpendicular distance from point p to line segment formed by start and end\nconst getPerpendicularDistance = (p: { x: number; y: number }, start: { x: number; y: number }, end: { x: number; y: number }): number => {\n  const dx = end.x - start.x;\n  const dy = end.y - start.y;\n\n  if (dx === 0 && dy === 0) {\n    return Math.sqrt(Math.pow(p.x - start.x, 2) + Math.pow(p.y - start.y, 2));\n  }\n\n  const numerator = Math.abs(dy * p.x - dx * p.y + end.x * start.y - end.y * start.x);\n  const denominator = Math.sqrt(dx * dx + dy * dy);\n  return numerator / denominator;\n};\n\n/**\n * Generates 3 copywriting suggestions: Comercial, Creativa, and Directa.\n * Returns a JSON structure: { comercial: string, creativa: string, directa: string }\n */\nexport const generateCopywritingSuggestions = async (prompt: string, _apiKey?: string): Promise<{ comercial: string; creativa: string; directa: string }> => {\n  // Prefer /api/text/generate \u2014 no browser-side Gemini (AGENTS.md \u00A73.1).\n  try {\n    const { generateText } = await import('./text/generateService');\n    const { formatActiveBrandForPrompt, getActiveEditorBrand } = await import('./activeEditorBrand');\n    const brand = getActiveEditorBrand();\n    const brandCtx = formatActiveBrandForPrompt(brand);\n    const brandBlock = brandCtx\n      ? ` Contexto de marca (respeta tono, estilo y personalidad): ${brandCtx}. Las tres opciones deben sonar alineadas con esa marca.`\n      : '';\n    const res = await generateText({\n      prompt:\n        `Genera 3 sugerencias cortas (max 12 palabras) en JSON {\"comercial\",\"creativa\",\"directa\"} para: ${prompt}.${brandBlock}`,\n      language: 'es',\n      maxWords: 40,\n      tone: brand?.voice?.name,\n    });\n    const raw = res.text.trim().replace(/^```json?\\n?|\\n?```$/g, '');\n    const parsed = JSON.parse(raw) as { comercial?: string; creativa?: string; directa?: string };\n    if (parsed.comercial && parsed.creativa && parsed.directa) {\n      return {\n        comercial: parsed.comercial.trim().replace(/^[\"']|[\"']$/g, ''),\n        creativa: parsed.creativa.trim().replace(/^[\"']|[\"']$/g, ''),\n        directa: parsed.directa.trim().replace(/^[\"']|[\"']$/g, ''),\n      };\n    }\n  } catch (err) {\n    console.warn('copywriting via /api/text failed, using local fallback:', err);\n  }\n\n  // Smart client-side fallback generator for 3 suggestions\n  const cleanPrompt = prompt.trim().toLowerCase();\n  \n  if (cleanPrompt.includes(\"cafe\") || cleanPrompt.includes(\"coffee\") || cleanPrompt.includes(\"caf\u00E9\")) {\n    return {\n      comercial: \"Despierta tus sentidos con el mejor caf\u00E9 de especialidad. \u00A1P\u00EDdelo hoy!\",\n      creativa: \"El aroma que inspira tus ma\u00F1anas y despierta tu creatividad.\",\n      directa: \"Caf\u00E9 reci\u00E9n tostado de alta calidad. Env\u00EDo gratis a domicilio.\"\n    };\n  }\n  if (cleanPrompt.includes(\"moda\") || cleanPrompt.includes(\"ropa\") || cleanPrompt.includes(\"fashion\") || cleanPrompt.includes(\"oferta\") || cleanPrompt.includes(\"zapato\")) {\n    return {\n      comercial: \"Renueva tu estilo con 30% de descuento. \u00A1Solo por hoy!\",\n      creativa: \"Viste la tendencia y luce tu mejor versi\u00F3n todos los d\u00EDas.\",\n      directa: \"Colecci\u00F3n exclusiva de calzado y ropa premium en nuestra tienda.\"\n    };\n  }\n  if (cleanPrompt.includes(\"deporte\") || cleanPrompt.includes(\"gym\") || cleanPrompt.includes(\"fitness\") || cleanPrompt.includes(\"ejercicio\")) {\n    return {\n      comercial: \"Supera tus l\u00EDmites y entrena con el mejor equipo. \u00A1Empieza ya!\",\n      creativa: \"El dolor de hoy es la fuerza del ma\u00F1ana. Descubre tu poder.\",\n      directa: \"Prendas deportivas de alta resistencia y flexibilidad garantizada.\"\n    };\n  }\n  if (cleanPrompt.includes(\"comida\") || cleanPrompt.includes(\"pizza\") || cleanPrompt.includes(\"hamburguesa\") || cleanPrompt.includes(\"restaurante\")) {\n    return {\n      comercial: \"\u00A1Irresistiblemente deliciosa! Pide tu hamburguesa premium ahora a domicilio.\",\n      creativa: \"Pasi\u00F3n por los ingredientes frescos y el sabor artesanal que te encanta.\",\n      directa: \"Sabor casero en minutos. Haz tu pedido y disfr\u00FAtalo caliente.\"\n    };\n  }\n  if (cleanPrompt.includes(\"tech\") || cleanPrompt.includes(\"tecnologia\") || cleanPrompt.includes(\"software\") || cleanPrompt.includes(\"app\")) {\n    return {\n      comercial: \"Acelera tu flujo de trabajo con la tecnolog\u00EDa del futuro. Pru\u00E9bala gratis.\",\n      creativa: \"La revoluci\u00F3n digital al alcance de tu mano: crea sin l\u00EDmites.\",\n      directa: \"Herramientas de software dise\u00F1adas para aumentar la productividad de tu negocio.\"\n    };\n  }\n\n  return {\n    comercial: `\u00A1Lleva tu negocio al siguiente nivel! Descubre todo sobre: ${prompt}`,\n    creativa: `Haz que tus ideas cobren vida y destaca con: ${prompt}`,\n    directa: `El mejor servicio de ${prompt} disponible para ti hoy.`\n  };\n};\n\nexport const sketchToImage = async (sketchDataUrl: string, prompt: string): Promise<string> => {\n  const transparent = await hasTransparency(sketchDataUrl);\n  const wantsBg = wantsBackground(prompt);\n\n  let processedInputUrl = sketchDataUrl;\n  if (transparent) {\n    processedInputUrl = await compositeOnWhite(sketchDataUrl);\n  }\n\n  const blob = await dataUrlToBlob(processedInputUrl);\n  const result = await svcSketchToImage({\n    sketch: blob,\n    prompt,\n    hasTransparency: transparent,\n    wantsBackground: wantsBg,\n  });\n  return blobToDataUrl(result);\n};\n\nexport const magicEraser = async (imageDataUrl: string, maskDataUrl: string): Promise<string> => {\n  const imageBlob = await dataUrlToBlob(imageDataUrl);\n  const maskBlob = await dataUrlToBlob(maskDataUrl);\n  // .NET / image-studio binders expect named image/* files (png).\n  const image = new File([imageBlob], 'image.png', {\n    type: imageBlob.type || 'image/png',\n  });\n  const mask = new File([maskBlob], 'mask.png', {\n    type: maskBlob.type || 'image/png',\n  });\n  const result = await svcMagicEraser({ image, mask });\n  return blobToDataUrl(result);\n};\n\n\nexport const upscaleImage = async (imageSrc: string, factor: number, _apiKey?: string): Promise<string> => {\n  try {\n    const img = new Image();\n    img.crossOrigin = 'anonymous';\n    img.src = imageSrc;\n    await new Promise((resolve, reject) => {\n      img.onload = resolve;\n      img.onerror = reject;\n    });\n\n    const canvas = document.createElement('canvas');\n    canvas.width = img.width * factor;\n    canvas.height = img.height * factor;\n    const ctx = canvas.getContext('2d', { willReadFrequently: true });\n    if (!ctx) throw new Error(\"Could not create canvas context for upscale.\");\n    \n    ctx.imageSmoothingEnabled = true;\n    ctx.imageSmoothingQuality = 'high';\n    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);\n    \n    await new Promise(r => setTimeout(r, 1500));\n    return canvas.toDataURL('image/png', 0.95);\n  } catch (e: any) {\n    console.error(e);\n    throw new Error(`AI Upscale fall\u00F3: ${e.message}`);\n  }\n};\n", "import type { VideoProject } from '../store/useVideoStore';\n\nexport type VideoAspect = VideoProject['aspectRatio'];\n\nexport function dimensionsForAspect(aspect: VideoAspect): { width: number; height: number } {\n  switch (aspect) {\n    case '9:16':\n      return { width: 1080, height: 1920 };\n    case '1:1':\n      return { width: 1080, height: 1080 };\n    case '4:3':\n      return { width: 1440, height: 1080 };\n    case '3:4':\n      return { width: 1080, height: 1440 };\n    case '21:9':\n      return { width: 2560, height: 1080 };\n    case '16:9':\n    default:\n      return { width: 1920, height: 1080 };\n  }\n}\n\nexport function closestAspect(width: number, height: number): VideoAspect {\n  const ratio = width / Math.max(1, height);\n  const candidates: { aspect: VideoAspect; value: number }[] = [\n    { aspect: '16:9', value: 16 / 9 },\n    { aspect: '9:16', value: 9 / 16 },\n    { aspect: '1:1', value: 1 },\n    { aspect: '4:3', value: 4 / 3 },\n    { aspect: '3:4', value: 3 / 4 },\n    { aspect: '21:9', value: 21 / 9 },\n  ];\n  let best = candidates[0]!;\n  for (const c of candidates) {\n    if (Math.abs(c.value - ratio) < Math.abs(best.value - ratio)) best = c;\n  }\n  return best.aspect;\n}\n\n/** Preview drawing buffer from project canvas size (capped for GPU, keeps aspect). */\nexport function previewBufferFromCanvas(\n  canvasWidth: number,\n  canvasHeight: number,\n  maxEdge = 1280,\n): { width: number; height: number } {\n  const w = Math.max(1, Math.round(canvasWidth));\n  const h = Math.max(1, Math.round(canvasHeight));\n  const scale = Math.min(1, maxEdge / Math.max(w, h));\n  return {\n    width: Math.max(1, Math.round(w * scale)),\n    height: Math.max(1, Math.round(h * scale)),\n  };\n}\n", "import type { Asset, Clip, Track } from '../store/useVideoStore';\n\n/** Same logical boxes WebGL / CropTool use (buffer-pixel space). */\nexport const PREVIEW_IMAGE_BOX = 200;\nexport const PREVIEW_TEXT_BOX_W = 300;\nexport const PREVIEW_TEXT_BOX_H = 100;\n\nlet measureCtx: CanvasRenderingContext2D | null = null;\n\nfunction getMeasureCtx(): CanvasRenderingContext2D | null {\n  if (measureCtx) return measureCtx;\n  if (typeof document === 'undefined') return null;\n  const canvas = document.createElement('canvas');\n  measureCtx = canvas.getContext('2d');\n  return measureCtx;\n}\n\n/**\n * Unscaled text/subtitle box in buffer pixels (matches textRenderer before ctx.scale).\n * CropTool / hit-test multiply by clip.scaleX/Y afterwards.\n */\nexport function measureTextClipUnscaledBox(clip: Clip): { w: number; h: number } {\n  let text = clip.text || '';\n  if (clip.textTransform === 'uppercase') text = text.toUpperCase();\n  else if (clip.textTransform === 'lowercase') text = text.toLowerCase();\n  else if (clip.textTransform === 'capitalize') {\n    text = text.replace(/\\b\\w/g, (c) => c.toUpperCase());\n  }\n\n  const fontSize = clip.fontSize || 48;\n  const fontWeight = clip.fontWeight || 500;\n  const fontFamily = clip.fontFamily || 'Inter';\n  const fontStyle = clip.fontStyle || 'normal';\n  const lineHeightMul = clip.lineHeight || 1.2;\n  const lineHeight = fontSize * lineHeightMul;\n  const lines = (text || ' ').split('\\n');\n\n  const ctx = getMeasureCtx();\n  let maxWidth = PREVIEW_TEXT_BOX_W * 0.5;\n  if (ctx) {\n    ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px \"${fontFamily}\"`;\n    if (ctx.letterSpacing !== undefined) {\n      ctx.letterSpacing = `${clip.letterSpacing || 0}px`;\n    }\n    maxWidth = 0;\n    for (const line of lines) {\n      maxWidth = Math.max(maxWidth, ctx.measureText(line.length ? line : ' ').width);\n    }\n  } else {\n    // SSR / no canvas: rough estimate\n    maxWidth = Math.max(...lines.map((l) => Math.max(1, l.length) * fontSize * 0.55));\n  }\n\n  const totalTextHeight = Math.max(1, lines.length) * lineHeight;\n  let pad = 8;\n  if (clip.backgroundEnabled) {\n    pad = Math.max(pad, clip.backgroundPadding ?? 8);\n  }\n  const strokePad = clip.strokeEnabled ? clip.strokeWidth || 2 : 0;\n\n  return {\n    w: Math.max(48, maxWidth + pad * 2 + strokePad * 2),\n    h: Math.max(28, totalTextHeight + pad * 2 + strokePad * 2),\n  };\n}\n\nexport function fittedImageBox(\n  srcW: number,\n  srcH: number,\n  fitMode: 'fill' | 'fit' | 'stretch' | 'crop' | undefined,\n): { w: number; h: number } {\n  if (!(srcW > 0 && srcH > 0)) return { w: PREVIEW_IMAGE_BOX, h: PREVIEW_IMAGE_BOX };\n  const imageAspect = srcW / srcH;\n  const boxAspect = 1;\n  const mode = fitMode || 'fit';\n\n  let w = PREVIEW_IMAGE_BOX;\n  let h = PREVIEW_IMAGE_BOX;\n  if (mode === 'fit') {\n    if (imageAspect > boxAspect) h = PREVIEW_IMAGE_BOX / imageAspect;\n    else w = PREVIEW_IMAGE_BOX * imageAspect;\n  } else if (mode === 'crop') {\n    if (imageAspect > boxAspect) w = PREVIEW_IMAGE_BOX * imageAspect;\n    else h = PREVIEW_IMAGE_BOX / imageAspect;\n  }\n  return { w, h };\n}\n\n/**\n * Clip scale so the media draws at native pixel size on the canvas.\n * Images use the fixed PREVIEW_IMAGE_BOX base in WebGL; video uses fit-to-canvas.\n */\nexport function nativeDisplayScale(\n  assetW: number,\n  assetH: number,\n  kind: 'image' | 'video',\n  canvasW: number,\n  canvasH: number,\n): { scaleX: number; scaleY: number } {\n  if (!(assetW > 0 && assetH > 0)) {\n    return { scaleX: 1, scaleY: 1 };\n  }\n\n  if (kind === 'image') {\n    // fittedImageBox + WebGL use a 200\u00D7200 fit box; scale maps that to native px.\n    const s = Math.max(assetW, assetH) / PREVIEW_IMAGE_BOX;\n    return { scaleX: s, scaleY: s };\n  }\n\n  const cw = canvasW > 0 ? canvasW : 1920;\n  const ch = canvasH > 0 ? canvasH : 1080;\n  const imageAspect = assetW / assetH;\n  const canvasAspect = cw / ch;\n  let baseScaleX = 1;\n  let baseScaleY = 1;\n  if (imageAspect > canvasAspect) {\n    baseScaleY = canvasAspect / imageAspect;\n  } else {\n    baseScaleX = imageAspect / canvasAspect;\n  }\n  // Avoid divide-by-zero if base collapses.\n  const scaleX = baseScaleX > 0 ? assetW / (baseScaleX * cw) : 1;\n  const scaleY = baseScaleY > 0 ? assetH / (baseScaleY * ch) : 1;\n  return { scaleX, scaleY };\n}\n\nfunction pointInRotatedRect(\n  px: number,\n  py: number,\n  cx: number,\n  cy: number,\n  w: number,\n  h: number,\n  rotationDeg: number,\n): boolean {\n  const rad = (-rotationDeg * Math.PI) / 180;\n  const dx = px - cx;\n  const dy = py - cy;\n  const lx = dx * Math.cos(rad) - dy * Math.sin(rad);\n  const ly = dx * Math.sin(rad) + dy * Math.cos(rad);\n  return Math.abs(lx) <= w / 2 && Math.abs(ly) <= h / 2;\n}\n\nfunction clipBaseBox(\n  clip: Clip,\n  asset: Asset | undefined,\n  canvasCssW: number,\n  canvasCssH: number,\n  bufferW: number,\n  bufferH: number,\n): { w: number; h: number } {\n  const bufferToCssX = bufferW > 0 ? canvasCssW / bufferW : 1;\n  const bufferToCssY = bufferH > 0 ? canvasCssH / bufferH : 1;\n\n  if (clip.type === 'text' || clip.type === 'subtitle') {\n    const box = measureTextClipUnscaledBox(clip);\n    return {\n      w: box.w * bufferToCssX,\n      h: box.h * bufferToCssY,\n    };\n  }\n\n  if (clip.type === 'image') {\n    const box = fittedImageBox(asset?.width || 0, asset?.height || 0, clip.fitMode);\n    return {\n      w: box.w * bufferToCssX,\n      h: box.h * bufferToCssY,\n    };\n  }\n\n  // Video / other: approximate visible rect in CSS space (NDC scale \u00D7 canvas).\n  let baseScaleX = 1;\n  let baseScaleY = 1;\n  const srcW = asset?.width || 0;\n  const srcH = asset?.height || 0;\n  if (srcW > 0 && srcH > 0 && canvasCssW > 0 && canvasCssH > 0) {\n    const imageAspect = srcW / srcH;\n    const canvasAspect = canvasCssW / canvasCssH;\n    const fitMode = clip.fitMode || 'fit';\n    if (fitMode === 'fit') {\n      if (imageAspect > canvasAspect) {\n        baseScaleX = 1;\n        baseScaleY = canvasAspect / imageAspect;\n      } else {\n        baseScaleX = imageAspect / canvasAspect;\n        baseScaleY = 1;\n      }\n    } else if (fitMode === 'crop') {\n      if (imageAspect > canvasAspect) {\n        baseScaleX = imageAspect / canvasAspect;\n        baseScaleY = 1;\n      } else {\n        baseScaleX = 1;\n        baseScaleY = canvasAspect / imageAspect;\n      }\n    }\n  }\n\n  return {\n    w: baseScaleX * canvasCssW,\n    h: baseScaleY * canvasCssH,\n  };\n}\n\nfunction isClipActiveAt(clip: Clip, time: number): boolean {\n  return time >= clip.startTime && time < clip.startTime + clip.duration;\n}\n\n/**\n * Topmost selectable clip under a CSS-space point in the preview canvas.\n * Matches draw order: video \u2192 image \u2192 text \u2192 subtitle (subtitle wins hits).\n */\nexport function hitTestPreviewClip(\n  tracks: Track[],\n  assets: Asset[],\n  playheadTime: number,\n  px: number,\n  py: number,\n  canvasCssW: number,\n  canvasCssH: number,\n  bufferW: number,\n  bufferH: number,\n): Clip | null {\n  const layerRank = (type: string) => {\n    if (type === 'subtitle') return 4;\n    if (type === 'text') return 3;\n    if (type === 'image') return 2;\n    if (type === 'video') return 1;\n    return 0;\n  };\n\n  const selectable = tracks\n    .filter((tr) => !tr.muted && tr.type !== 'audio')\n    .flatMap((tr, trackIndex) =>\n      tr.clips\n        .filter((c) => isClipActiveAt(c, playheadTime))\n        .map((clip) => ({ clip, trackIndex })),\n    );\n\n  selectable.sort((a, b) => {\n    const byType = layerRank(b.clip.type) - layerRank(a.clip.type);\n    if (byType !== 0) return byType;\n    return b.trackIndex - a.trackIndex;\n  });\n\n  for (const { clip } of selectable) {\n    let asset = assets.find((a) => a.id === clip.assetId);\n    // Prefer live media intrinsic size when asset metadata is missing\n    if (asset && (!(asset.width > 0) || !(asset.height > 0))) {\n      const el = document.getElementById(`preview-media-${asset.id}`);\n      if (el instanceof HTMLVideoElement && el.videoWidth > 0) {\n        asset = { ...asset, width: el.videoWidth, height: el.videoHeight };\n      } else if (el instanceof HTMLImageElement && el.naturalWidth > 0) {\n        asset = { ...asset, width: el.naturalWidth, height: el.naturalHeight };\n      }\n    }\n    const base = clipBaseBox(clip, asset, canvasCssW, canvasCssH, bufferW, bufferH);\n    const sx = clip.scaleX ?? 1;\n    const sy = clip.scaleY ?? 1;\n    const w = base.w * sx;\n    const h = base.h * sy;\n    const cx = (clip.x ?? 0.5) * canvasCssW;\n    const cy = (clip.y ?? 0.5) * canvasCssH;\n    if (pointInRotatedRect(px, py, cx, cy, w, h, clip.rotation ?? 0)) {\n      return clip;\n    }\n  }\n\n  return null;\n}\n", "/**\n * Shared project persistence \u2014 same pattern as image editor autosave:\n * 1) Debounced IndexedDB write (source of truth, always latest)\n * 2) Debounced silent cloud upload (local \u2192 Recientes) in the background\n * 3) Flush on tab hide / pagehide so close-mid-edit cannot lose work\n *\n * Concurrency rules (reload / Recientes races):\n * - Local writes are serialized; overlapping calls coalesce to one more write\n *   of the latest store state (never let an older put win).\n * - Cloud dirty uses a change epoch: a successful upload only clears dirty if\n *   no newer edit happened during the upload; no-op uploads do not clear dirty.\n *\n * Stores call `scheduleAfterChange()` after mutations and register at module init.\n * App mounts `useProjectPersistence({ hydrated })` once (heartbeat + flush on hide).\n */\n\nexport type ProjectPersistenceMode = 'image' | 'video' | 'audio' | 'text' | 'slides';\n\nexport type ProjectPersistenceOptions = {\n  mode: ProjectPersistenceMode;\n  /** IndexedDB debounce after last edit. Default 400ms (keep local always fresh). */\n  localDebounceMs?: number;\n  /** Cloud upload debounce after last edit. Default 3000ms. */\n  cloudDebounceMs?: number;\n  /** Persist to IndexedDB. Must be safe to call when there is nothing to save. */\n  saveLocal: () => Promise<void>;\n  /**\n   * Upload current project to cloud (replace previous editable when possible).\n   * Return true only when a real upload completed; false for early no-ops\n   * (still loading, no canvas, etc.) so dirty is not cleared incorrectly.\n   */\n  saveCloud: () => Promise<boolean>;\n};\n\nexport type ProjectPersistenceController = {\n  readonly mode: ProjectPersistenceMode;\n  /** After every user edit: schedule local then cloud. */\n  scheduleAfterChange: () => void;\n  /** Cancel timers and run local \u2192 cloud now. */\n  flush: () => Promise<void>;\n  /** Cancel local timer and persist IndexedDB now. */\n  flushLocal: () => Promise<void>;\n  /** Cancel cloud timer and upload now (runs local first). */\n  flushCloud: () => Promise<void>;\n  /** True when a change has not yet completed a successful cloud upload. */\n  isCloudDirty: () => boolean;\n  /**\n   * Optional: mark cloud clean after an external successful upload that used\n   * the same change epoch. Prefer letting the controller clear dirty via\n   * saveCloud returning true.\n   */\n  markCloudClean: () => void;\n};\n\nconst DEFAULT_LOCAL_MS = 400;\nconst DEFAULT_CLOUD_MS = 3000;\n\nexport function createProjectPersistence(\n  opts: ProjectPersistenceOptions\n): ProjectPersistenceController {\n  const localMs = opts.localDebounceMs ?? DEFAULT_LOCAL_MS;\n  const cloudMs = opts.cloudDebounceMs ?? DEFAULT_CLOUD_MS;\n\n  let localTimer: ReturnType<typeof setTimeout> | null = null;\n  let cloudTimer: ReturnType<typeof setTimeout> | null = null;\n\n  /** Bumps on every edit; cloud upload clears dirty only when epoch still matches. */\n  let changeEpoch = 0;\n  let lastUploadedEpoch = 0;\n\n  let localBusy = false;\n  let localNeedsResave = false;\n\n  let cloudBusy = false;\n  let cloudQueued = false;\n\n  const clearLocalTimer = () => {\n    if (localTimer) {\n      clearTimeout(localTimer);\n      localTimer = null;\n    }\n  };\n\n  const clearCloudTimer = () => {\n    if (cloudTimer) {\n      clearTimeout(cloudTimer);\n      cloudTimer = null;\n    }\n  };\n\n  const runLocal = async () => {\n    clearLocalTimer();\n    if (localBusy) {\n      localNeedsResave = true;\n      return;\n    }\n    localBusy = true;\n    try {\n      do {\n        localNeedsResave = false;\n        try {\n          // Always read latest store state inside saveLocal \u2014 coalesce overlaps.\n          await opts.saveLocal();\n        } catch (err) {\n          console.warn(`[persistence:${opts.mode}] local save failed`, err);\n        }\n      } while (localNeedsResave);\n    } finally {\n      localBusy = false;\n    }\n  };\n\n  const runCloud = async () => {\n    clearCloudTimer();\n    if (cloudBusy) {\n      cloudQueued = true;\n      return;\n    }\n    cloudBusy = true;\n    try {\n      do {\n        cloudQueued = false;\n        const epochAtStart = changeEpoch;\n        await runLocal();\n\n        let uploaded = false;\n        try {\n          uploaded = await opts.saveCloud();\n        } catch (err) {\n          console.warn(`[persistence:${opts.mode}] cloud save failed`, err);\n          // Keep dirty; do not loop forever on hard failures this tick.\n          break;\n        }\n\n        if (uploaded && changeEpoch === epochAtStart) {\n          lastUploadedEpoch = epochAtStart;\n        } else if (uploaded && changeEpoch !== epochAtStart) {\n          // Stale blob reached the server; newer edits still need another pass.\n          cloudQueued = true;\n        } else if (!uploaded && changeEpoch > lastUploadedEpoch) {\n          // No-op (loading / missing canvas): retry after cloud debounce.\n          clearCloudTimer();\n          cloudTimer = setTimeout(() => {\n            cloudTimer = null;\n            void runCloud();\n          }, cloudMs);\n        }\n      } while (cloudQueued && changeEpoch > lastUploadedEpoch);\n    } finally {\n      cloudBusy = false;\n    }\n  };\n\n  const isDirty = () =>\n    changeEpoch > lastUploadedEpoch || cloudQueued || cloudTimer != null;\n\n  return {\n    mode: opts.mode,\n\n    scheduleAfterChange: () => {\n      changeEpoch += 1;\n\n      clearLocalTimer();\n      localTimer = setTimeout(() => {\n        localTimer = null;\n        void runLocal();\n      }, localMs);\n\n      clearCloudTimer();\n      cloudTimer = setTimeout(() => {\n        cloudTimer = null;\n        void runCloud();\n      }, cloudMs);\n    },\n\n    flushLocal: () => runLocal(),\n\n    flushCloud: async () => {\n      if (!isDirty()) return;\n      await runCloud();\n    },\n\n    flush: async () => {\n      clearLocalTimer();\n      clearCloudTimer();\n      await runLocal();\n      if (isDirty()) {\n        await runCloud();\n      }\n    },\n\n    isCloudDirty: () => isDirty(),\n\n    markCloudClean: () => {\n      // Only advance if nothing newer is pending \u2014 avoids wiping dirty after\n      // a store-level success that raced with a newer edit.\n      if (!cloudQueued && cloudTimer == null) {\n        lastUploadedEpoch = changeEpoch;\n      }\n    },\n  };\n}\n\nconst _registry = new Map<ProjectPersistenceMode, ProjectPersistenceController>();\n\nexport function registerProjectPersistence(\n  controller: ProjectPersistenceController\n): void {\n  _registry.set(controller.mode, controller);\n}\n\nexport function getProjectPersistence(\n  mode: ProjectPersistenceMode\n): ProjectPersistenceController | undefined {\n  return _registry.get(mode);\n}\n\nexport function getAllProjectPersistence(): ProjectPersistenceController[] {\n  return [..._registry.values()];\n}\n\nexport async function flushAllProjectPersistence(): Promise<void> {\n  await Promise.allSettled(getAllProjectPersistence().map((c) => c.flush()));\n}\n", "/** Auto-generated preset display names \u2014 keep keys in sync with ProjectSetupModal presets. */\nexport const SETUP_PRESET_NAMES_ES = {\n  't-blank': \"Documento en blanco\",\n  't-blog': \"Art\u00EDculo de blog\",\n  't-script': \"Guion\",\n  't-news': \"Newsletter\",\n  't-landing': \"Texto de landing\",\n  't-social': \"Publicaci\u00F3n social\",\n  's-blank': \"Presentaci\u00F3n en blanco\",\n  's-pitch': \"Pitch deck\",\n  's-qbr': \"Revisi\u00F3n de negocio (QBR)\",\n  's-course': \"Curso / taller\",\n  's-report': \"Informe\",\n  's-keynote': \"Keynote\",\n  's-43': \"Cl\u00E1sico 4:3\",\n  's-916': \"Stories / Reels 9:16\",\n  's-a4': \"A4 horizontal\",\n  'ig-post': \"Instagram Post\",\n  'yt-thumb': \"YouTube Thumbnail\",\n  'a4': \"A4\",\n  'fb-cover': \"Facebook Cover\",\n  'pres-16-9': \"Presentaci\u00F3n 16:9\",\n  'twitter-post': \"Twitter Post\",\n  'photo-4x6': \"Foto 4\u00D76 pulg.\",\n  'photo-5x7': \"Foto 5\u00D77 pulg.\",\n  'photo-8x10': \"Foto 8\u00D710 pulg.\",\n  'photo-sq': \"Foto cuadrada\",\n  'photo-pan': \"Panor\u00E1mica\",\n  'photo-port': \"Retrato 2:3\",\n  'ig-story': \"Instagram Story\",\n  'ig-reel': \"Instagram Reel\",\n  'fb-post': \"Facebook Post\",\n  'tw-header': \"Twitter Header\",\n  'li-banner': \"LinkedIn Banner\",\n  'tiktok': \"TikTok Cover\",\n  'yt-banner': \"YouTube Banner\",\n  'pin-post': \"Pinterest Pin\",\n  'print-a4': \"A4\",\n  'print-a3': \"A3\",\n  'print-letter': \"Carta (EE. UU.)\",\n  'biz-card': \"Tarjeta de presentaci\u00F3n\",\n  'poster-a2': \"P\u00F3ster A2\",\n  'flyer': \"Flyer A5\",\n  'web-fhd': \"Full HD (1920\u00D71080)\",\n  'web-hd': \"HD (1280\u00D7720)\",\n  'web-banner': \"Banner web\",\n  'web-email': \"Encabezado de email\",\n  'web-blog': \"Imagen destacada de blog\",\n  'web-og': \"Imagen OG\",\n  'v-yt': \"YouTube (16:9)\",\n  'v-tiktok': \"TikTok / Reels\",\n  'v-sq': \"Cuadrado\",\n  'v-film': \"Cinemascope\",\n  'v-tv': \"TV cl\u00E1sica (4:3)\",\n  'v-portrait': \"Retrato (3:4)\",\n  'v-ig-story': \"Historia de IG\",\n  'v-ig-feed': \"Feed de IG\",\n  'v-fb-video': \"Facebook Video\",\n  'v-tw-video': \"Twitter Video\",\n  'v-cinema': \"Cine ancho\",\n  'v-std': \"Est\u00E1ndar (4:3)\",\n} as const;\nexport type SetupPresetNameId_ES = keyof typeof SETUP_PRESET_NAMES_ES;", "import { SETUP_PRESET_NAMES_ES } from './setupPresetNames.es';\n\n/**\n * Spanish locale \u2014 default fallback.\n *\n * Shape of this object is the source of truth for the i18n module. The English\n * locale (en.ts) must satisfy `Messages = typeof es`. TypeScript will catch\n * missing keys / wrong shapes at build time.\n *\n * This file only covers the strings the phase-1 demo migration touches:\n *  - Brand strings (Kaiman Studio AI rebrand)\n *  - Page metadata (index.html)\n *  - Top toolbars (image + video)\n *  - Toasts (success / error)\n *  - Command palette\n *  - Modals reached from those toolbars (load/save errors, AI voiceover, export)\n *\n * Other strings (sidebars, panels, modals) are migrated in phase 2 by concern.\n */\n\nexport const es = {\n  brand: {\n    fullName: 'Kaiman Studio AI',\n    shortName: 'Kaiman AI',\n    assistant: 'Asistente de Kaiman AI',\n  },\n  editor: {\n    back: 'Volver',\n    backTitle: 'Volver a Kaiman',\n    createNew: 'Crear nuevo lienzo',\n    closeTab: 'Cerrar pesta\u00F1a',\n    renameTab: 'Nombre del proyecto',\n    renameTabHint: 'Doble clic para renombrar (nombre del archivo)',\n    createNewHint: 'Abrir configuraci\u00F3n',\n    recentTitle: 'Lienzos recientes',\n    recentSubtitle: 'Contin\u00FAa donde lo dejaste con proyectos guardados en la nube.',\n    recentEmpty: 'A\u00FAn no tienes lienzos guardados en la nube para este modo.',\n    recentLoadError: 'No se pudieron cargar los lienzos recientes',\n    recentAuthError: 'Tu sesi\u00F3n expir\u00F3. Vuelve a iniciar sesi\u00F3n en Kaiman y abre el Studio de nuevo.',\n    recentLoading: 'Cargando lienzos recientes...',\n    recentLocal: 'Local',\n    recentLocalCloud: 'Local \u00B7 nube',\n    cloudOpen: 'Abrir',\n    cloudDelete: 'Eliminar de la nube',\n    relativeDateToday: 'Hoy',\n    relativeDateYesterday: 'Ayer',\n    relativeDateDaysAgo: (n: number) => `Hace ${n} d\u00EDas`,\n    thumbnailFallback: (name: string) => name.charAt(0).toUpperCase(),\n    brand: {\n      label: 'Marca',\n      selectLabel: 'Cambiar de marca',\n    },\n    emptyByMode: {\n      Image: {\n        title: '\u00BFQu\u00E9 vas a dise\u00F1ar hoy?',\n        subtitle: 'Crea un lienzo nuevo o retoma un proyecto guardado en la nube.',\n        createHint: 'Elige tama\u00F1o, nombre y plantilla para empezar.',\n      },\n      Video: {\n        title: 'Tu pr\u00F3ximo video empieza aqu\u00ED',\n        subtitle: 'Configura un lienzo de video o abre un proyecto reciente.',\n        createHint: 'Elige la relaci\u00F3n de aspecto, el nombre y el formato de la l\u00EDnea de tiempo.',\n      },\n      Audio: {\n        title: 'Listo para editar audio',\n        subtitle: 'Abre un proyecto de audio existente o crea uno desde cero.',\n        createHint: 'Importa pistas, mezcla y exporta en un solo flujo.',\n      },\n      Text: {\n        title: 'Escribe con tu marca',\n        subtitle: 'Inicia un documento nuevo o contin\u00FAa con copy guardado.',\n        createHint: 'Editor TipTap con IA, outline y exportaci\u00F3n.',\n      },\n      Slides: {\n        title: 'Presenta con impacto',\n        subtitle: 'Crea un deck nuevo o retoma una presentaci\u00F3n en la nube.',\n        createHint: 'Slides editables con temas, charts y export PPTX.',\n      },\n    },\n    newProject: {\n      image: 'Nuevo proyecto de imagen',\n      video: 'Nuevo proyecto de video',\n      audio: 'Nuevo proyecto de audio',\n      text: 'Nuevo documento',\n      slides: 'Nueva presentaci\u00F3n',\n    },\n    loadingProject: 'Cargando proyecto...',\n    aiProcessing: 'Procesando p\u00EDxeles y completando tu imagen...',\n    aiGenerating: 'Generando',\n    localOnly: 'Local',\n    localAndCloud: 'Local \u00B7 nube',\n  },\n  projectSetup: {\n    untitled: 'Sin t\u00EDtulo',\n    newSlidesDefault: 'Nueva presentaci\u00F3n',\n    close: 'Cerrar',\n    closeDisabled: 'Crea un proyecto para continuar',\n    recents: 'Recientes',\n    refreshList: 'Refrescar lista',\n    loadingProjects: 'Cargando proyectos\u2026',\n    noRecentFiles: 'Sin archivos recientes',\n    noProjectsForMode: (modeLabel: string) => `No tienes proyectos de ${modeLabel}`,\n    projectsInOtherModes: (n: number) =>\n      n === 1 ? 'Tienes 1 proyecto en otros modos' : `Tienes ${n} proyectos en otros modos`,\n    retry: 'Reintentar',\n    upload: {\n      verb: 'Subir',\n      hint: 'Abre de nuevo un proyecto editable descargado del editor.',\n    },\n    categoryTabs: {\n      home: 'Inicio',\n      photo: 'Foto',\n      social: 'Redes sociales',\n      print: 'Impresi\u00F3n',\n      web: 'Web',\n      cinema: 'Cine',\n    },\n    templateHeaders: {\n      slides: 'Plantillas de diapositivas',\n      text: 'Plantillas de texto',\n      audio: 'Plantillas de audio',\n    },\n    presetsTitle: (count: number) => `Plantillas (${count})`,\n    presetsHintQuick: 'Clic / doble clic',\n    presetsHintCreate: 'Doble clic para crear',\n    presetTooltipImage: (name: string, w: number, h: number) =>\n      `${name} \u2014 ${w}\u00D7${h}px\\nDoble clic para crear`,\n    presetTooltipVideo: (name: string, ratio: string) =>\n      `${name} \u2014 ${ratio}\\nDoble clic para crear`,\n    create: {\n      slides: 'Crear presentaci\u00F3n',\n      text: 'Crear documento de texto',\n      audio: 'Crear proyecto de audio',\n      image: 'Crear lienzo de imagen',\n      video: 'Crear proyecto de video',\n    },\n    form: {\n      fileName: 'Nombre del archivo',\n      projectName: 'Nombre del proyecto',\n      documentName: 'Nombre del documento',\n      deckName: 'Nombre de la presentaci\u00F3n',\n      dimensions: 'Dimensiones',\n      widthPx: 'Ancho (px)',\n      heightPx: 'Alto (px)',\n      swapOrientation: 'Intercambiar orientaci\u00F3n',\n      orientation: 'Orientaci\u00F3n',\n      portrait: 'Vertical',\n      landscape: 'Horizontal',\n      backgroundColor: 'Color de fondo',\n      resetColor: 'Restablecer color predeterminado',\n      aspectRatio: 'Relaci\u00F3n de aspecto',\n      template: 'Plantilla',\n      sampleRate: 'Frecuencia de muestreo',\n      bpm: 'BPM',\n      language: 'Idioma',\n      tone: 'Tono',\n      targetChannel: 'Canal objetivo',\n      pageSize: 'Tama\u00F1o de hoja',\n      columns: 'Columnas',\n      width: 'Ancho',\n      height: 'Alto',\n    },\n    audioTemplates: {\n      empty: { label: 'Vac\u00EDo', sub: '2 pistas' },\n      podcast: { label: 'Podcast', sub: 'Presentador / invitado' },\n      music: { label: 'M\u00FAsica', sub: '5 stems' },\n      voiceover: { label: 'Locuci\u00F3n', sub: 'Voz + cama' },\n    },\n    docTypes: {\n      blank: 'En blanco',\n      blog: 'Blog',\n      script: 'Guion',\n      newsletter: 'Newsletter',\n      landing: 'Landing',\n      social: 'Redes',\n    },\n    tones: {\n      neutral: 'Neutro',\n      formal: 'Formal',\n      casual: 'Casual',\n      persuasive: 'Persuasivo',\n      technical: 'T\u00E9cnico',\n      friendly: 'Cercano',\n    },\n    channels: {\n      blog: 'Blog',\n      instagram: 'Instagram',\n      linkedin: 'LinkedIn',\n      x: 'X (Twitter)',\n      email: 'Email',\n      ad: 'Anuncio',\n      youtube: 'YouTube',\n    },\n    pageSizes: {\n      letter: 'Carta (Letter) \u2014 21.59 \u00D7 27.94 cm',\n      legal: 'Oficio (Legal) \u2014 21.59 \u00D7 35.56 cm',\n      a4: 'A4 \u2014 21 \u00D7 29.7 cm',\n      a5: 'A5 \u2014 14.8 \u00D7 21 cm',\n    },\n    languages: {\n      es: 'Espa\u00F1ol',\n      en: 'Ingl\u00E9s',\n      pt: 'Portugu\u00E9s',\n    },\n    slidesTemplates: {\n      blank: 'En blanco',\n      pitch: 'Pitch',\n      qbr: 'QBR',\n      course: 'Curso',\n      report: 'Informe',\n      keynote: 'Keynote',\n    },\n    errors: {\n      sessionNotConfigured: 'Sesi\u00F3n no configurada. Vuelve a abrir el editor desde Wizard.',\n      sessionExpired: 'Sesi\u00F3n expirada o cookies limpiadas. Inicia sesi\u00F3n de nuevo en Wizard y recarga.',\n      openFailed: (name: string, msg: string) => `No se pudo abrir \"${name}\": ${msg}`,\n      deleteFailed: (name: string, msg: string) => `No se pudo eliminar \"${name}\": ${msg}`,\n    },\n    confirmDeleteCloud: (name: string) =>\n      `\u00BFEliminar \"${name}\" de la nube? Esta acci\u00F3n no se puede deshacer.`,\n    presetNames: SETUP_PRESET_NAMES_ES,\n  },\n  page: {\n    title: 'Kaiman Studio AI Video Editor',\n    description:\n      'Kaiman Studio AI Video Editor - Un editor web de video profesional, interactivo y offline-first. Edita videos, capas, im\u00E1genes, textos y aplica efectos en tiempo real.',\n  },\n  toast: {\n    savingToCloud: 'Guardando en la nube\u2026',\n    savedToCloud: 'Guardado en la nube \u2713',\n    saveFailed: (msg: string) => `No se pudo guardar en la nube: ${msg}`,\n    cloudPayloadTooLarge:\n      'El proyecto es demasiado grande para el l\u00EDmite del servidor. Reduce el tama\u00F1o o la cantidad de im\u00E1genes e int\u00E9ntalo de nuevo.',\n  },\n  saveStatus: {\n    saving: 'Guardando...',\n    saved: 'Guardado',\n    error: 'Error',\n    local: 'Local',\n    justNow: 'Justo ahora',\n    secondsAgo: (n: number) => `Hace ${n}s`,\n    minutesAgo: (n: number) => `Hace ${n}m`,\n  },\n  keyboardHelp: {\n    title: 'Atajos de teclado',\n    titleTooltip: 'Atajos de teclado (?)',\n    select: 'Seleccionar',\n    hand: 'Mano / Pan',\n    text: 'Texto',\n    rect: 'Rect\u00E1ngulo',\n    ellipse: 'Elipse',\n    undo: 'Deshacer',\n    redo: 'Rehacer',\n    copy: 'Copiar',\n    paste: 'Pegar',\n    delete: 'Eliminar',\n    zoomIn: 'Zoom +',\n    zoomOut: 'Zoom -',\n    fitCanvas: 'Ajustar lienzo',\n    thisPanel: 'Este panel',\n  },\n  dialog: {\n    loadError: {\n      title: 'Error al cargar',\n      message: 'Error al cargar el proyecto. El archivo puede estar da\u00F1ado.',\n    },\n    saveError: {\n      title: 'Error al guardar',\n      message: (msg: string) => `Error al guardar el proyecto: ${msg}`,\n    },\n    projectOpened: {\n      title: '\u00C9xito',\n      message: 'Proyecto abierto en una nueva pesta\u00F1a.',\n    },\n    projectLoadError: {\n      title: 'Error al cargar',\n      message: (msg: string) => `Error al cargar el proyecto: ${msg}`,\n    },\n    projectNamePrompt: {\n      message: 'Introduce el nombre del proyecto:',\n      defaultName: 'mi_proyecto',\n      fallbackName: 'proyecto_sin_titulo',\n    },\n  },\n  commandPalette: {\n    placeholder: 'Escribe un comando o busca...',\n    noResults: (query: string) => `No se encontraron comandos para \"${query}\"`,\n    navigateHint: 'Usa \u2191\u2193 para navegar, Enter para seleccionar',\n    pressEnter: 'Presiona',\n    selectImageFirst: 'Selecciona una imagen primero.',\n    noSelectionTitle: 'Sin selecci\u00F3n',\n    title: 'Command Palette',\n    categories: {\n      tools: 'Herramientas',\n      actions: 'Acciones',\n      pages: 'P\u00E1ginas',\n      settings: 'Ajustes',\n      filters: 'Filtros',\n    },\n    commands: {\n      toolSelect: 'Cambiar a herramienta de selecci\u00F3n',\n      toolPan: 'Cambiar a herramienta de mano/pan',\n      toolText: 'Insertar texto',\n      toolRect: 'Insertar rect\u00E1ngulo',\n      toolCircle: 'Insertar c\u00EDrculo',\n      toolTriangle: 'Insertar tri\u00E1ngulo',\n      toolStar: 'Insertar estrella',\n      toolCrop: 'Abrir herramienta de recorte',\n      toolPencil: 'Pincel',\n      toolFrameMobile: 'Insertar marco de iPhone',\n      actionUndo: 'Deshacer',\n      actionRedo: 'Rehacer',\n      actionDelete: 'Eliminar objeto seleccionado',\n      actionCopy: 'Copiar selecci\u00F3n',\n      actionRotate90: 'Rotar 90\u00B0 a la derecha',\n      actionExportPng: 'Exportar como PNG',\n      actionSlideshow: 'Iniciar slideshow / presentaci\u00F3n',\n      actionDuplicatePage: 'Duplicar p\u00E1gina',\n      actionDeletePage: 'Eliminar p\u00E1gina actual',\n      actionClearPage: 'Limpiar todos los objetos de la p\u00E1gina',\n      actionResize1080: 'Tama\u00F1o de lienzo 1080x1080 (IG cuadrado)',\n      actionResize1920: 'Tama\u00F1o de lienzo 1920x1080 (16:9)',\n      settingRulers: 'Alternar reglas',\n      settingGuides: 'Alternar gu\u00EDas inteligentes',\n      settingGrid: 'Alternar cuadr\u00EDcula de dise\u00F1o',\n      filterSepia: 'Aplicar filtro sepia',\n      filterVintage: 'Aplicar efecto vintage',\n      filterGrayscale: 'Aplicar escala de grises',\n      filterInvert: 'Invertir colores',\n    },\n  },\n  modal: {\n    aiVoiceover: {\n      title: 'Generador de locuci\u00F3n AI (TTS)',\n      scriptLabel: 'Texto de la locuci\u00F3n',\n      placeholder:\n        'Escribe el guion que narrar\u00E1 la voz\u2026 Ej: Bienvenidos a este nuevo video de Kaiman Studio AI\u2026',\n      voiceLabel: 'Voz',\n      playDemo: 'Escuchar demo de la voz',\n      playDemoHint: 'Reproduce una muestra corta de la voz seleccionada antes de generar.',\n      demoError: 'No se pudo reproducir la demo de la voz.',\n      speedLabel: 'Velocidad de lectura',\n      cancel: 'Cancelar',\n      generate: 'Generar audio',\n      synthesizing: 'Sintetizando\u2026',\n      successTitle: 'Locuci\u00F3n generada',\n      successHint: 'Escucha el resultado y, si te convence, a\u00F1\u00E1delo a la l\u00EDnea de tiempo.',\n      addToTimeline: 'A\u00F1adir voz en off a la l\u00EDnea de tiempo',\n      decodeError: 'Error al decodificar la duraci\u00F3n del audio.',\n      clipName: (snippet: string) => `Voz: \"${snippet}\u2026\"`,\n      trackName: 'AI Voiceovers',\n      addedToast: 'Locuci\u00F3n a\u00F1adida a la l\u00EDnea de tiempo',\n    },\n    export: {\n      filePrefix: (resolution: string, aspect: string) =>\n        `kaiman_ai_render_${resolution}_${aspect.replace(':', '_')}.mp4`,\n      filePrefixBase: (resolution: string) => `kaiman_ai_export_${resolution}`,\n    },\n    imageExport: {\n      title: 'Exportaci\u00F3n Avanzada',\n      outputFormat: 'Formato de Salida',\n      resolutionScale: 'Resoluci\u00F3n (Escala)',\n      printSettings: 'Ajustes de Impresi\u00F3n',\n      includeBleed: 'Incluir Sangr\u00EDa (Bleed)',\n      includeBleedHint: 'A\u00F1ade un margen extra alrededor del dise\u00F1o',\n      bleedSizeMm: 'Tama\u00F1o (mm):',\n      cropMarks: 'Marcas de Corte (Crop Marks)',\n      cropMarksHint: 'Marcas en esquina solo en la sangr\u00EDa (margen m\u00EDn. 8 mm)',\n      watermark: 'Marca de Agua',\n      enableWatermark: 'Activar Marca de Agua',\n      watermarkText: 'Texto',\n      watermarkLogo: 'Logo (Imagen)',\n      watermarkPlaceholder: 'Ej: Borrador, Confidencial...',\n      watermarkDefault: 'Borrador',\n      uploadLogo: 'Haz clic para subir un logo\u2026',\n      opacity: 'Opacidad',\n      cancel: 'Cancelar',\n      exporting: 'Exportando...',\n      exportProject: 'Exportar Proyecto',\n      errorTitle: 'Error de exportaci\u00F3n',\n      errorMessage: 'Error en la exportaci\u00F3n avanzada.',\n    },\n    videoExport: {\n      title: 'Renderizar y exportar proyecto',\n      doNotClose: 'No cierres esta ventana durante el render.',\n      exportFormat: 'Formato de exportaci\u00F3n',\n      multiFormat: 'Exportaci\u00F3n multi-formato',\n      multiFormatHint: 'Detecta rostros con WASM y recorta a 16:9, 9:16, 1:1',\n      aspectRatio: 'Relaci\u00F3n de aspecto',\n      resolution: 'Resoluci\u00F3n',\n      frameRate: 'Fotogramas por segundo',\n      bitrate: 'Bitrate / Calidad',\n      cancel: 'Cancelar',\n      startExport: 'Iniciar exportaci\u00F3n',\n      outputPreviews: 'Vistas previas de aspecto',\n      fit: 'Ajustar',\n      crop: 'Recortar',\n      faceTrack: 'Seguir rostro',\n      landscape: 'Horizontal (16:9)',\n      portrait: 'Vertical (9:16)',\n      square: 'Cuadrado (1:1)',\n      initCompiler: 'Inicializando compilador...',\n      demoExport: 'Sin medios en la l\u00EDnea de tiempo. Ejecutando exportaci\u00F3n de demo\u2026',\n    },\n    apiKeys: {\n      title: 'Configuraci\u00F3n de claves de IA',\n      intro:\n        'Configura tus claves API para habilitar las funciones avanzadas de IA. Las claves se guardan localmente en localStorage.',\n      openaiLabel: 'Clave de OpenAI',\n      openaiPlaceholder: 'sk-proj-...',\n      geminiLabel: 'Clave de Gemini',\n      geminiPlaceholder: 'AIzaSy...',\n    },\n    versionHistory: {\n      title: 'Historial de Versiones',\n      saveCurrentVersion: 'Guardar Versi\u00F3n Actual',\n      placeholder: \"Ej. 'Antes de cambiar el fondo'\",\n      save: 'Guardar',\n      noVersions: 'No hay versiones guardadas en este proyecto.',\n      loadConfirm: '\u00BFCargar esta versi\u00F3n? Los cambios no guardados se perder\u00E1n.',\n      loadVersion: 'Cargar versi\u00F3n',\n      load: 'Cargar',\n      deleteConfirm: '\u00BFEliminar permanentemente esta versi\u00F3n?',\n      deleteVersion: 'Eliminar versi\u00F3n',\n      delete: 'Eliminar',\n      restore: 'Restaurar',\n      pagesSuffix: (n: number) => `p\u00E1g${n !== 1 ? 's' : ''}`,\n    },\n    chartData: {\n      title: 'Configuraci\u00F3n de Gr\u00E1fico',\n      tabData: 'Datos y Valores',\n      tabDesign: 'Dise\u00F1o y Estilos',\n      chartType: 'Tipo de Gr\u00E1fico',\n      bar: 'Barras',\n      line: 'L\u00EDneas',\n      pie: 'Pastel',\n      donut: 'Dona',\n      valuesTable: 'Tabla de Valores',\n      addRow: 'A\u00F1adir Fila',\n      labelCol: 'Etiqueta',\n      valueCol: 'Valor Num\u00E9rico',\n      colorCol: 'Color',\n      rowNamePlaceholder: 'Nombre...',\n      noData: 'No hay datos en el gr\u00E1fico.',\n      themeLabel: 'Tema de Grillas',\n      dark: 'Oscuro',\n      light: 'Claro',\n      showDataLabels: 'Mostrar Datos Flotantes',\n      textColorLabel: 'Color de Textos',\n      bgColorLabel: 'Fondo del Gr\u00E1fico',\n      transparentBg: 'Sin fondo (Transparente)',\n      numericValuesLabel: 'Valores Num\u00E9ricos',\n      proTip: 'Pro Tip: Si insertaste tu gr\u00E1fico sobre un lienzo de color claro (por ejemplo, blanco), aseg\u00FArate de establecer el Tema de Grillas en \"Claro\" y cambiar el Color de Textos a un tono oscuro para que sean visibles.',\n      apply: 'Aplicar Cambios',\n      itemLabel: (n: number) => `\u00CDtem ${n}`,\n    },\n    dialog: {\n      notice: 'Aviso',\n      confirmAction: '\u00BFConfirmar acci\u00F3n?',\n      accept: 'Aceptar',\n      cancel: 'Cancelar',\n      confirm: 'Confirmar',\n    },\n    variations: {\n      title: 'Variaciones AI Generadas',\n      subtitle: 'Selecciona la variante que m\u00E1s te guste para a\u00F1adirla a tu lienzo.',\n    },\n  },\n  common: {\n    closeNotification: 'Cerrar notificaci\u00F3n',\n    fileSection: 'Archivo',\n    settingsSection: 'Preferencias',\n    language: 'Idioma',\n    spanish: 'Espa\u00F1ol',\n    english: 'English',\n    languageActive: 'Activo',\n    resetPanels: 'Restablecer paneles',\n    panelsResetToast: 'Paneles restablecidos a su posici\u00F3n por defecto',\n    apply: 'Aplicar',\n    close: 'Cerrar',\n    cancel: 'Cancelar',\n    accept: 'Aceptar',\n    reset: 'Restablecer',\n    resetPosition: 'Restablecer posici\u00F3n',\n    understood: 'Entendido',\n    fileNewHint: 'Empieza un lienzo en blanco',\n    fileOpenHint: 'Carga un archivo del equipo',\n    fileSaveHint: 'Descarga el proyecto local',\n    fileCloudHint: 'Sincroniza con tu cuenta',\n    errors: {\n      unexpected:\n        'Algo sali\u00F3 mal. Por favor, int\u00E9ntalo de nuevo m\u00E1s tarde. Nuestro equipo ya est\u00E1 revisando el problema.',\n      network: 'No pudimos conectar. Revisa tu conexi\u00F3n e int\u00E9ntalo de nuevo.',\n      sessionExpired: 'Tu sesi\u00F3n expir\u00F3. Vuelve a iniciar sesi\u00F3n e int\u00E9ntalo de nuevo.',\n      comingSoon: 'Esta funci\u00F3n estar\u00E1 disponible pronto.',\n    },\n  },\n  modes: {\n    image: 'Imagen',\n    video: 'Video',\n    audio: 'Audio',\n    text: 'Texto',\n    slides: 'Diapositivas',\n    switchTo: (label: string) => `Cambiar a ${label}`,\n    menuTitle: 'Modos del estudio',\n    description: {\n      image: 'Lienzo, capas y foto',\n      video: 'L\u00EDnea de tiempo y clips',\n      audio: 'M\u00FAsica y voz',\n      text: 'Copy y documentos',\n      slides: 'Presentaciones',\n    },\n  },\n  toolbar: {\n    image: {\n      fileMenu: 'Men\u00FA de Archivo',\n      newCanvas: 'Nuevo Lienzo',\n      openProject: 'Abrir Proyecto (.kai)',\n      saveProject: 'Guardar Proyecto (.kai)',\n      saveToCloud: 'Guardar en la nube',\n      savingToCloud: 'Guardando en la nube\u2026',\n      versionHistory: 'Historial de Versiones',\n      smartGuides: 'Gu\u00EDas Inteligentes',\n      smartGuidesOn: 'ON',\n      smartGuidesOff: 'OFF',\n      snapping: 'Ajuste magn\u00E9tico',\n      snapMaster: 'Activar ajuste',\n      snapShapes: 'Formas',\n      snapImages: 'Im\u00E1genes',\n      snapText: 'Textos',\n      snapCanvasEdges: 'Bordes del lienzo',\n      undo: 'Deshacer (\u2318Z)',\n      redo: 'Rehacer (\u2318\u21E7Z)',\n      zoomOut: 'Alejar (\u2318-)',\n      zoomIn: 'Acercar (\u2318+)',\n      fitCanvas: 'Ajustar Lienzo',\n      brandKit: 'Brand Kit & Colores',\n      export: 'Exportar',\n      presentationMode: 'Modo Presentaci\u00F3n',\n      exitPresentation: 'Cerrar presentaci\u00F3n',\n      removeBackground: 'Quitar Fondo',\n      removeBackgroundTitle: 'Quitar fondo (AI)',\n      filters: 'Filtros',\n      filtersSelectImage: 'Selecciona una imagen para aplicar filtros',\n    },\n    video: {\n      fileMenu: 'Men\u00FA de archivo',\n      newCanvas: 'Nuevo lienzo',\n      importProjectLoading: 'Cargando...',\n      importProjectIdle: 'Importar proyecto (.kaiv)',\n      saveProjectSaving: 'Guardando...',\n      saveProjectIdle: 'Guardar proyecto (.kaiv)',\n      saveToCloud: 'Guardar en la nube',\n      savingToCloud: 'Guardando en la nube\u2026',\n      apiKeys: 'API Keys',\n      apiKeysOkBadge: 'OK',\n      aiAssistant: 'Asistente AI',\n      aiAssistantHint: 'Kit viral de redes a partir del guion de la l\u00EDnea de tiempo',\n      webglActive: 'WebGL Active',\n      aspectTitle: 'Formato de lienzo',\n      aspectSection: 'Formato del lienzo',\n      aspectLandscape: '16:9 \u2014 Landscape',\n      aspectPortrait: '9:16 \u2014 Portrait',\n      aspectSquare: '1:1 \u2014 Square',\n      assetsLibrary: 'Biblioteca de Assets',\n      zoomOut: 'Alejar vista previa',\n      zoomIn: 'Acercar vista previa',\n      zoomReset: 'Restablecer zoom y posici\u00F3n',\n      zoomOutHint: 'Alejar (Ctrl+Rueda en el canvas)',\n      zoomInHint: 'Acercar (Ctrl+Rueda en el canvas)',\n      export: 'Export',\n    },\n    common: {\n      fileMenu: 'Men\u00FA de Archivo',\n      new: 'Nuevo',\n      openProject: (ext: string) => `Abrir Proyecto (.${ext})`,\n      saveProject: (ext: string) => `Guardar Proyecto (.${ext})`,\n      saveToCloud: 'Guardar en la nube',\n      savingToCloud: 'Guardando en la nube\u2026',\n      export: 'Exportar',\n      exportNotAvailable: 'Exportaci\u00F3n no disponible',\n      undo: 'Deshacer (\u2318Z)',\n      redo: 'Rehacer (\u2318\u21E7Z)',\n    },\n    brand: {\n      menuLabel: 'Cambiar brand',\n      listLabel: 'Brands',\n      placeholder: 'Sin brand',\n    },\n  },\n  leftPanel: {\n    assets: 'Assets',\n    myFiles: 'Mis archivos',\n    ai: 'IA',\n    canvas: 'Lienzo',\n  },\n  crop: {\n    activeTitle: 'Recortar imagen',\n    free: 'Libre',\n    aspect1x1: '1:1',\n    aspect16x9: '16:9',\n    aspect4x3: '4:3',\n    errorPrefix: 'Error en recorte',\n    closeError: 'Cerrar',\n    cancelTooltip: 'Cancelar recorte',\n    cancelLabel: 'Cancelar',\n    applyTooltip: 'Aplicar recorte',\n    applyLabel: 'Aplicar',\n  },\n  mask: {\n    title: 'Modo M\u00E1scara de Capa',\n    hint: 'Usa el pincel para dibujar la m\u00E1scara.',\n  },\n  transition: {\n    searchPlaceholder: 'Buscar transiciones\u2026',\n    doubleClickHint: 'Doble clic para aplicar en el corte del clip',\n    apply: 'Aplicar',\n    noClipSelected: 'Ning\u00FAn clip seleccionado',\n    noClipSelectedBody:\n      'Selecciona primero un clip en la l\u00EDnea de tiempo para poder aplicarle una transici\u00F3n.',\n    notAllowedTitle: 'Acci\u00F3n no permitida',\n    notAllowedBody:\n      'Las transiciones se aplican a pistas de video, imagen y texto.',\n    notAllowedAudioBody:\n      'Las transiciones visuales no se aplican a clips de audio. Selecciona un clip de video, imagen o texto.',\n    applyTransitionTitle: 'Aplicar transici\u00F3n',\n    applyTransitionBody: (name: string) => `\u00BFD\u00F3nde deseas aplicar la transici\u00F3n \"${name}\"?`,\n    fadeIn: 'Inicio del clip (Fade In)',\n    fadeInShort: 'Entrada',\n    fadeOut: 'Final del clip (Fade Out)',\n    fadeOutShort: 'Salida',\n    betweenPrev: 'Entre el clip anterior y este',\n    betweenNext: 'Entre este clip y el siguiente',\n    cut: 'Corte',\n    catAll: 'Todas',\n    catDissolve: 'Disolver',\n    catWipe: 'Barrido',\n    catSlide: 'Deslizar',\n    catStylized: 'Estilizado',\n    addTransition: 'A\u00F1adir transici\u00F3n',\n    junctionTitle: 'Transiciones en el corte',\n    junctionHint: 'Ajusta o quita la transici\u00F3n de cada lado del corte.',\n    junctionConflictHint:\n      'Hay un conflicto: cada clip aporta una transici\u00F3n distinta. Elige una por lado o unif\u00EDcalas.',\n    junctionLeft: 'Clip izquierdo',\n    junctionRight: 'Clip derecho',\n    junctionNone: 'Sin transici\u00F3n',\n    junctionRemoveBoth: 'Quitar ambas',\n    junctionDone: 'Listo',\n    intentBanner: 'Elige una transici\u00F3n para aplicar en el borde seleccionado.',\n    intentClear: 'Cancelar borde',\n    builderTitle: 'Transici\u00F3n',\n    builderContextStart: 'Inicio del clip (Fade In)',\n    builderContextEnd: 'Final del clip (Fade Out)',\n    builderContextBetween: 'Entre clips',\n    builderType: 'Tipo',\n    builderDuration: 'Duraci\u00F3n',\n    builderBg: 'Fondo de transici\u00F3n',\n    builderBgBlack: 'A negro',\n    builderBgWhite: 'A blanco',\n    builderBgTransparent: 'Fundido a transparente',\n    builderEasing: 'Curva',\n    builderEasingLinear: 'Lineal',\n    builderEasingIn: 'Ease In',\n    builderEasingOut: 'Ease Out',\n    builderEasingInOut: 'Ease In Out',\n    builderDirection: 'Direcci\u00F3n',\n    builderForward: 'Adelante',\n    builderReversed: 'Invertida',\n    builderDelete: 'Eliminar',\n    builderApply: 'Aplicar',\n    builderTypes: {\n      clockWipe: 'Barrido reloj',\n      zoomIn: 'Zoom in',\n      zoomPunch: 'Zoom punch',\n      spinZoom: 'Spin zoom',\n    },\n    items: {\n      crossDissolve: { name: 'Fundido cruzado', desc: 'Fundido suave entre clips' },\n      fadeBlack: { name: 'A negro', desc: 'Sale a negro y entra de nuevo' },\n      fadeWhite: { name: 'A blanco', desc: 'Sale a blanco y entra de nuevo' },\n      additiveDissolve: { name: 'Fundido aditivo', desc: 'Fundido brillante aditivo' },\n      wipeLeft: { name: 'Barrido izq.', desc: 'Revela el clip entrante hacia la izquierda' },\n      wipeRight: { name: 'Barrido der.', desc: 'Revela el clip entrante hacia la derecha' },\n      wipeUp: { name: 'Barrido arriba', desc: 'Revela hacia arriba' },\n      wipeDown: { name: 'Barrido abajo', desc: 'Revela hacia abajo' },\n      irisCircle: { name: 'Iris circular', desc: 'Iris que se abre o cierra' },\n      slideLeft: { name: 'Deslizar izq.', desc: 'Entra desde el borde derecho' },\n      slideRight: { name: 'Deslizar der.', desc: 'Entra desde el borde izquierdo' },\n      pushLeft: { name: 'Empujar izq.', desc: 'El entrante empuja al saliente' },\n      pushRight: { name: 'Empujar der.', desc: 'El entrante empuja hacia la derecha' },\n      glitch: { name: 'Glitch', desc: 'Distorsi\u00F3n digital de tracking' },\n      blurDissolve: { name: 'Fundido con blur', desc: 'Fundido con desenfoque gaussiano' },\n      pixelate: { name: 'Fundido pixelado', desc: 'Fundido con bloques de p\u00EDxeles' },\n      filmBurn: { name: 'Quemado de pel\u00EDcula', desc: 'Fuga de luz org\u00E1nica' },\n    },\n  },\n  aiImage: {\n    title: 'Generador de B-Roll con IA',\n    promptLabel: 'Describe el B-Roll o gr\u00E1fico que quieres generar',\n    promptPlaceholder:\n      'Ej.: un render 3D futurista de un producto tech flotando sobre un fondo ciberpunk, alta definici\u00F3n, estilo concept art\u2026',\n    generating: 'Generando\u2026',\n    generate: 'Generar imagen',\n    firstRenderHint: 'El primer renderizado puede tardar unos segundos',\n    saveImage: 'Guardar imagen',\n    addBroll: 'A\u00F1adir B-Roll a la l\u00EDnea de tiempo',\n    unknownError: 'Error desconocido al generar la imagen.',\n    loadingInitial: 'Preparando la generaci\u00F3n de imagen\u2026',\n    loadingSteps: [\n      'Preparando la generaci\u00F3n de imagen\u2026',\n      'Enviando tu descripci\u00F3n al servicio de IA\u2026',\n      'Procesando la composici\u00F3n\u2026',\n      'Renderizando en alta calidad\u2026',\n      'Finalizando la imagen\u2026',\n    ],\n    previewAlt: 'Vista previa generada con IA',\n  },\n  videoEditor: {\n    resizeTimeline: 'Redimensionar l\u00EDnea de tiempo',\n    openSetup: 'Abrir configuraci\u00F3n',\n    newCanvas: 'Nuevo lienzo',\n    openSetupHint: 'Abrir configuraci\u00F3n',\n    assetPanel: {\n      aiBrollTitle: 'Generar B-Roll con IA',\n      importMediaTitle: 'Importar media',\n      dragDrop: 'Arrastra y suelta archivos',\n      supports: 'Video, imagen y audio (MP4, MOV, PNG, JPG, MP3, WAV\u2026)',\n      libraryTitle: (n: number) => `Biblioteca (${n})`,\n      libraryEmpty: 'La biblioteca est\u00E1 vac\u00EDa',\n      importMediaHint: 'Sube video, imagen o audio para empezar a editar',\n      doubleClickHint: 'Doble clic para insertar en la l\u00EDnea de tiempo',\n      removeAssetTitle: 'Eliminar asset',\n      altThumbnail: 'Miniatura',\n      altAiBroll: 'B-Roll de IA',\n      filterAria: 'Filtrar assets por tipo',\n      filterAll: 'Todo',\n      filterImage: 'Imagen',\n      filterVideo: 'Video',\n      filterAudio: 'Audio',\n      emptyFilter: 'No hay assets de este tipo.',\n    },\n    myFilesPanel: {\n      jobsHeader: 'Archivos de imagen, video y audio',\n      hint: 'Archivos generados en la nube. Clic para a\u00F1adirlos a la l\u00EDnea de tiempo.',\n      loading: 'Cargando archivos\u2026',\n      empty: 'No hay archivos de imagen, video o audio.',\n      emptyFilter: 'No hay archivos de este tipo.',\n      loadError: 'No se pudieron cargar los archivos.',\n      fetchError: 'No se pudo descargar el archivo.',\n      refresh: 'Actualizar',\n      addHint: 'A\u00F1adir a la l\u00EDnea de tiempo',\n      filterAria: 'Filtrar por tipo de media',\n      filterAll: 'Todo',\n      filterImage: 'Imagen',\n      filterVideo: 'Video',\n      filterAudio: 'Audio',\n    },\n    canvasPanel: {\n      aspectSection: 'Proporci\u00F3n',\n      aspectHint: 'Define la relaci\u00F3n de aspecto del lienzo de video.',\n      aspectLabel: 'Aspecto',\n      sizeLabel: 'Tama\u00F1o',\n      previewSize: 'Vista previa',\n      canvasSize: 'Lienzo',\n      qualitySection: 'Calidad de preview',\n      qualityHint: '100% renderiza a la resoluci\u00F3n del lienzo. Baja el valor para mejorar el rendimiento.',\n      qualityLabel: 'Calidad',\n      qualityReset: 'Restablecer calidad a 100%',\n      zoomSection: 'Zoom de vista',\n      zoomHint: 'Acerca o aleja la vista previa (Ctrl + rueda sobre el canvas).',\n      zoomLabel: 'Zoom',\n      zoomIn: 'Acercar',\n      zoomOut: 'Alejar',\n      zoomReset: 'Restablecer zoom y pan',\n      snapSection: 'Ajuste magn\u00E9tico',\n      snapHint: 'Alinea clips en la l\u00EDnea de tiempo y elementos al moverlos en la vista previa.',\n      snapLabel: 'Activar ajuste',\n      size1080p: '1080p horizontal',\n      size720p: '720p horizontal',\n      sizeVertical1080: '1080p vertical',\n      sizeSquare1080: '1080 cuadrado',\n      size4x3: '4:3',\n      size3x4: '3:4',\n      sizeUltrawide: 'Ultrawide 21:9',\n      sizeCustom: 'Personalizado',\n      customWidth: 'Ancho',\n      customHeight: 'Alto',\n      aspectLabels: {\n        '16:9': '16:9 \u2014 Landscape',\n        '9:16': '9:16 \u2014 Portrait',\n        '1:1': '1:1 \u2014 Cuadrado',\n        '4:3': '4:3 \u2014 Cl\u00E1sico',\n        '3:4': '3:4 \u2014 Portrait',\n        '21:9': '21:9 \u2014 Ultrawide',\n      },\n    },\n    aiTools: {\n      hint:\n        'Herramientas de IA del editor de video. Cada una act\u00FAa sobre el clip seleccionado o inserta resultado en la l\u00EDnea de tiempo.',\n      sectionSubtitles: 'Subt\u00EDtulos y audio',\n      sectionSubtitlesHint:\n        'Convierte voz a subt\u00EDtulos, trad\u00FAcelos, estil\u00EDzalos o genera locuci\u00F3n TTS.',\n      sectionLook: 'Look y clip',\n      sectionLookHint:\n        'Ajusta color, estilo visual y propiedades (velocidad, opacidad, volumen) del clip activo.',\n      sectionCopy: 'Copy y marketing',\n      sectionCopyHint:\n        'Genera textos para overlays y un kit promocional a partir del guion de la l\u00EDnea de tiempo.',\n      sectionMedia: 'Media',\n      sectionMediaHint: 'Busca fotos stock y col\u00F3calas en la l\u00EDnea de tiempo.',\n      tools: {\n        transcribe: 'Transcribir',\n        transcribeDesc:\n          'Escucha un clip de video o audio y crea subt\u00EDtulos sincronizados en la l\u00EDnea de tiempo.',\n        translate: 'Traducir subt\u00EDtulos',\n        translateDesc:\n          'Traduce todos los subt\u00EDtulos existentes al idioma que elijas, manteniendo tiempos.',\n        subtitleStyle: 'Estilo de subt\u00EDtulos',\n        subtitleStyleDesc:\n          'Describe un look (ej. neon, cine) y aplica tipograf\u00EDa, color y fondo a los subt\u00EDtulos.',\n        voiceover: 'Voiceover',\n        voiceoverDesc:\n          'Escribe un guion, elige voz y velocidad, y a\u00F1ade la locuci\u00F3n TTS a la l\u00EDnea de tiempo.',\n        colorGrading: 'Color grading AI',\n        colorGradingDesc:\n          'Describe un look (c\u00E1lido, noir, cinematic) y aplica exposici\u00F3n, contraste y color al clip.',\n        designPreset: 'Dise\u00F1o AI',\n        designPresetDesc:\n          'Transforma el estilo visual del clip de imagen, video o texto seleccionado con un prompt.',\n        videoProperties: 'Propiedades del clip',\n        videoPropertiesDesc:\n          'Cambia opacidad, velocidad, volumen o silencio con lenguaje natural (ej. \u201Cm\u00E1s lento\u201D).',\n        generateCopy: 'Generar copy',\n        generateCopyDesc:\n          'Crea un texto corto de overlay y lo inserta autom\u00E1ticamente en el playhead.',\n        copySuggestions: 'Sugerencias de copy',\n        copySuggestionsDesc:\n          'Tres variantes de tono (comercial, creativa, directa); elige una para la l\u00EDnea de tiempo.',\n        marketing: 'Asistente de marketing',\n        marketingDesc:\n          'Analiza el guion de la l\u00EDnea de tiempo y propone t\u00EDtulos virales, ganchos y copy para redes.',\n        stock: 'Stock',\n        stockDesc:\n          'Busca fotos (Unsplash/Pexels) y a\u00F1ade la elegida como clip de imagen.',\n      },\n      modal: {\n        transcribeTitle: 'Transcribir a subt\u00EDtulos',\n        translateTitle: 'Traducir subt\u00EDtulos',\n        subtitleStyleTitle: 'Estilo de subt\u00EDtulos',\n        colorGradingTitle: 'Color grading con IA',\n        designPresetTitle: 'Dise\u00F1o con IA',\n        videoPropertiesTitle: 'Propiedades del clip',\n        generateCopyTitle: 'Generar copy para overlay',\n        copySuggestionsTitle: 'Sugerencias de copy',\n        stockTitle: 'Buscar fotos stock',\n        transcribeHint:\n          'Elige el clip de video o audio a transcribir. La IA detectar\u00E1 el habla y crear\u00E1 subt\u00EDtulos alineados con el tiempo en una pista nueva.',\n        translateHint:\n          'Se traducir\u00E1n todos los clips de subt\u00EDtulos del proyecto al idioma seleccionado. Los tiempos de inicio y duraci\u00F3n se conservan.',\n        subtitleStyleHint:\n          'Describe el estilo tipogr\u00E1fico que quieres (colores, contraste, mood). Se aplicar\u00E1 a todos los subt\u00EDtulos de la l\u00EDnea de tiempo: fuente, relleno, sombra y fondo.',\n        needSubtitlesForStyle: 'A\u00F1ade subt\u00EDtulos a la l\u00EDnea de tiempo antes de aplicar un estilo.',\n        emptyStylePreset: 'El backend no devolvi\u00F3 propiedades de estilo aplicables.',\n        emptyDesignPreset: 'El backend no devolvi\u00F3 un dise\u00F1o aplicable al clip.',\n        emptyPropertiesPreset:\n          'El backend no devolvi\u00F3 propiedades ni operaciones aplicables. Revisa la consola [video-properties].',\n        colorGradingHint:\n          'Selecciona un clip de video o imagen y describe el look deseado (ej. \u201Cc\u00E1lido dorado de atardecer\u201D o \u201Ccontraste alto noir\u201D). Se actualizar\u00E1 el color grading del clip.',\n        designPresetHint:\n          'Selecciona un clip de imagen, video o texto y describe el estilo visual. La IA ajustar\u00E1 tipograf\u00EDa, filtros o apariencia seg\u00FAn el tipo de clip.',\n        videoPropertiesHint:\n          'Con el clip de video, imagen o audio seleccionado, describe ediciones en lenguaje natural: transform, opacidad, velocidad, volumen, color, efectos, transiciones y m\u00E1s.',\n        generateCopyHint:\n          'Describe el mensaje o CTA que quieres en pantalla. Al generar, se inserta un clip de texto en el playhead actual.',\n        copySuggestionsHint:\n          'Describe el producto, audiencia o idea. Recibir\u00E1s tres tonos distintos; haz clic en una variante para a\u00F1adirla a la l\u00EDnea de tiempo.',\n        stockHint:\n          'Busca por palabra clave. Al elegir una foto se descarga y se a\u00F1ade como clip de imagen en el playhead.',\n        promptPlaceholder: 'Describe lo que necesitas\u2026',\n        subtitleStylePlaceholder:\n          'Ej: subt\u00EDtulos neon cyan con sombra fuerte y fondo semitransparente\u2026',\n        colorGradingPlaceholder:\n          'Ej: look cinematogr\u00E1fico fr\u00EDo, sombras azules y highlights suaves\u2026',\n        designPresetPlaceholder:\n          'Ej: tipograf\u00EDa bold blanca con outline negro, estilo trailer\u2026',\n        videoPropertiesPlaceholder:\n          'Ej: 1.5x m\u00E1s r\u00E1pido, opacidad al 70% y volumen bajo\u2026',\n        generateCopyPlaceholder:\n          'Ej: CTA corto para probar la app gratis durante 7 d\u00EDas\u2026',\n        copySuggestionsPlaceholder:\n          'Ej: anuncio de un caf\u00E9 de especialidad para Instagram Reels\u2026',\n        stockPlaceholder: 'Ej: oficina moderna, paisaje urbano, producto\u2026',\n        clipLabel: 'Clip de origen',\n        languageLabel: 'Idioma de destino',\n        langEnglish: 'Ingl\u00E9s',\n        langSpanish: 'Espa\u00F1ol',\n        langFrench: 'Franc\u00E9s',\n        langPortuguese: 'Portugu\u00E9s',\n        langGerman: 'Alem\u00E1n',\n        langItalian: 'Italiano',\n        run: 'Ejecutar',\n        runTranscribe: 'Generar subt\u00EDtulos',\n        runTranslate: 'Traducir subt\u00EDtulos',\n        runApplyStyle: 'Aplicar estilo',\n        runApplyGrading: 'Aplicar color',\n        runApplyDesign: 'Aplicar dise\u00F1o',\n        runApplyProperties: 'Aplicar propiedades',\n        runGenerateCopy: 'Generar e insertar',\n        runCopySuggestions: 'Generar variantes',\n        search: 'Buscar fotos',\n        cancel: 'Cerrar',\n        dismiss: 'Cerrar',\n        addAsText: 'A\u00F1adir como texto',\n        toneComercial: 'Comercial',\n        toneCreativa: 'Creativa',\n        toneDirecta: 'Directa',\n        statusWorking: 'Trabajando\u2026',\n        statusTranscribing: 'Transcribiendo\u2026',\n        statusSearching: 'Buscando\u2026',\n        statusDownloading: 'Descargando\u2026',\n        statusApplyingGrading: 'Aplicando color\u2026',\n        statusApplyingDesign: 'Aplicando dise\u00F1o\u2026',\n        statusApplyingProperties: 'Aplicando propiedades\u2026',\n        previewGeneratingHint: 'La IA est\u00E1 trabajando en el preview',\n        needMediaClip: 'A\u00F1ade un clip de video o audio a la l\u00EDnea de tiempo.',\n        needMediaFile: 'El clip no tiene archivo asociado.',\n        needSubtitles: 'No hay subt\u00EDtulos en la l\u00EDnea de tiempo.',\n        needVideoOrImage: 'Selecciona un clip de video o imagen.',\n        needDesignTarget: 'Selecciona un clip de imagen, video o texto.',\n        toastSubtitlesAdded: 'Subt\u00EDtulos a\u00F1adidos a la l\u00EDnea de tiempo',\n        toastTranslated: 'Subt\u00EDtulos traducidos',\n        toastStyleApplied: 'Estilo aplicado',\n        toastGradingApplied: 'Color grading aplicado',\n        toastDesignApplied: 'Dise\u00F1o aplicado',\n        toastPropertiesApplied: 'Propiedades aplicadas',\n        toastCopyAdded: 'Texto a\u00F1adido a la l\u00EDnea de tiempo',\n        toastImageAdded: 'Imagen a\u00F1adida a la l\u00EDnea de tiempo',\n        stockEmpty: 'No hay resultados para esa b\u00FAsqueda.',\n        unknownError: 'No se pudo completar la operaci\u00F3n.',\n        featureComingSoon: (feature: string) => `Pr\u00F3ximamente: ${feature}`,\n        featureColorGrading: 'Color grading AI',\n        featureVideoProperties: 'Propiedades del clip',\n        featureDesignPreset: 'Dise\u00F1o AI',\n        featureSubtitleStyle: 'Estilo de subt\u00EDtulos',\n        featureGenerateCopy: 'Generar copy',\n        featureCopySuggestions: 'Sugerencias de copy',\n        featureMarketing: 'Asistente de marketing',\n        featureTranslate: 'Traducir subt\u00EDtulos',\n        sessionExpired: 'Tu sesi\u00F3n expir\u00F3. Vuelve a iniciar sesi\u00F3n.',\n        networkError: 'Error de red. Reintenta.',\n        emptyGradingPreset:\n          'No se pudo interpretar el look. Prueba con \u201Cc\u00E1lido\u201D, \u201Cfr\u00EDo\u201D, \u201Cnoir\u201D o \u201Ccinem\u00E1tico\u201D.',\n      },\n      marketing: {\n        title: 'Asistente de marketing social',\n        intro:\n          'Usa el texto y los subt\u00EDtulos de la l\u00EDnea de tiempo como guion. La IA propone t\u00EDtulos virales, ganchos de apertura y un copy listo para redes; puedes copiarlos o a\u00F1adirlos a la l\u00EDnea de tiempo.',\n        scriptLabel: 'Guion detectado en la l\u00EDnea de tiempo',\n        words: 'palabras',\n        emptyScript:\n          'No hay clips de subt\u00EDtulos o texto en la l\u00EDnea de tiempo. Genera subt\u00EDtulos o a\u00F1ade texto para que el asistente pueda redactar el kit promocional.',\n        analyze: 'Generar kit viral',\n        reanalyze: 'Volver a generar',\n        analyzing: 'Analizando guion\u2026',\n        tabTitles: 'T\u00EDtulos virales',\n        tabHooks: 'Ganchos de 3s',\n        tabCopy: 'Copy de redes',\n        titlesHint: 'T\u00EDtulos cortos pensados para thumbnails, Shorts o Reels',\n        hooksHint: 'Frases de apertura para los primeros segundos del video',\n        copyHint: 'Caption y hashtags listos para publicar en redes',\n        copyAll: 'Copiar todo',\n        copied: 'Copiado',\n        copyItem: 'Copiar',\n        addToTimeline: 'A\u00F1adir a la l\u00EDnea de tiempo',\n        addCopyToTimeline: 'A\u00F1adir copy a la l\u00EDnea de tiempo',\n        toastAdded: 'Texto a\u00F1adido a la l\u00EDnea de tiempo',\n        emptyResult:\n          'El backend no devolvi\u00F3 t\u00EDtulos, ganchos ni copy. Revisa la consola [marketing-assistant].',\n      },\n    },\n    playback: {\n      toStart: 'Ir al inicio',\n      rewind: 'Retroceder 1 segundo',\n      play: 'Reproducir',\n      pause: 'Pausar',\n      forward: 'Adelantar 1 segundo',\n      toEnd: 'Ir al final',\n      loop: 'Repetir (loop)',\n      fullscreen: 'Pantalla completa',\n      exitFullscreen: 'Salir de pantalla completa',\n    },\n    imagePanel: {\n      filesTab: 'Archivos',\n      stockTab: 'Stock',\n      importOverlays: 'Importar Overlays Gr\u00E1ficos',\n      supports: 'PNG (transparente), JPG, WEBP',\n      noImages: 'No hay im\u00E1genes importadas',\n      dragHint: 'Arrastra PNG, JPG, o usa Stock',\n    },\n    propertiesPanel: {\n      noClipSelected: 'No hay clip seleccionado',\n      noClipSelectedBody:\n        'Selecciona un clip en la l\u00EDnea de tiempo o en el preview para inspeccionar y editar sus propiedades.',\n      tabLayout: 'Dise\u00F1o',\n      tabColor: 'Color',\n      tabEffects: 'Efectos',\n      sectionGeneral: 'General',\n      sectionTypography: 'Tipograf\u00EDa',\n      fontFamily: 'Fuente',\n      sectionAiBatch: 'Herramientas AI (Lote)',\n      sectionAiTextDesigner: 'Dise\u00F1ador de Texto AI',\n      sectionFill: 'Relleno',\n      sectionOutline: 'Contorno',\n      sectionShadow: 'Sombra',\n      sectionPlate: 'Placa de fondo',\n      sectionAnimations: 'Animaciones',\n      sectionImage: 'Imagen',\n      sectionAiCinematic: 'Look Cinem\u00E1tico AI',\n      sectionTransform: 'Transformar',\n      sectionFlips: 'Voltear',\n      sectionVideo: 'Video',\n      sectionEffects: 'Efectos aplicados',\n      clipName: 'Nombre del clip',\n      layer: 'Capa (pista)',\n      layerUnknown: 'Desconocida',\n      layerUp: 'Subir',\n      layerDown: 'Bajar',\n      layerUpTitle: 'Mover capa arriba',\n      layerDownTitle: 'Mover capa abajo',\n      splitAtPlayhead: 'Dividir en el playhead',\n      startSec: 'Inicio (s)',\n      duration: 'Duraci\u00F3n',\n      trimIn: 'Recorte entrada',\n      trimOut: 'Recorte salida',\n      playbackSpeed: 'Velocidad',\n      speed025: '0.25x',\n      speed05: '0.50x',\n      speed1: '1.00x (Normal)',\n      speed15: '1.50x',\n      speed2: '2.00x',\n      speed4: '4.00x',\n      volume: 'Volumen',\n      textContent: 'Contenido',\n      textPlaceholder: 'Escribe el texto\u2026',\n      weight: 'Peso',\n      weightLight: 'Light',\n      weightRegular: 'Regular',\n      weightMedium: 'Medium',\n      weightSemiBold: 'Semi-Bold',\n      weightBold: 'Bold',\n      weightExtraBold: 'Extra-Bold',\n      align: 'Alinear',\n      style: 'Estilo',\n      italic: 'Cursiva',\n      underline: 'Subrayado',\n      case: 'May\u00FAsculas',\n      fontSize: 'Tama\u00F1o',\n      letterSpacing: 'Espaciado',\n      opacity: 'Opacidad',\n      positionX: 'Posici\u00F3n X',\n      positionY: 'Posici\u00F3n Y',\n      rotation: 'Rotaci\u00F3n',\n      scale: 'Escala',\n      fillType: 'Tipo de relleno',\n      fillSolid: 'Color s\u00F3lido',\n      fillGradient: 'Degradado',\n      textColor: 'Color de texto',\n      gradientColor1: 'Color 1',\n      gradientColor2: 'Color 2',\n      gradientAngle: '\u00C1ngulo',\n      outlineEnable: 'Contorno',\n      outlineSize: 'Grosor',\n      dropShadow: 'Sombra',\n      shadowColor: 'Color de sombra',\n      shadowOpacity: 'Opacidad de sombra',\n      blurRadius: 'Desenfoque',\n      offsetX: 'Desplazamiento X',\n      offsetY: 'Desplazamiento Y',\n      backgroundPlate: 'Placa de fondo',\n      plateColor: 'Color de placa',\n      plateOpacity: 'Opacidad de placa',\n      platePadding: 'Padding',\n      borderColor: 'Color de borde',\n      borderWidth: 'Grosor de borde',\n      borderRadius: 'Radio de borde',\n      introAnimation: 'Animaci\u00F3n de entrada',\n      outroAnimation: 'Animaci\u00F3n de salida',\n      introDuration: 'Duraci\u00F3n entrada',\n      outroDuration: 'Duraci\u00F3n salida',\n      animNone: 'Ninguna',\n      animFadeIn: 'Fade In',\n      animFadeOut: 'Fade Out',\n      animSlideUp: 'Deslizar arriba',\n      animSlideDown: 'Deslizar abajo',\n      animSlideLeft: 'Deslizar izquierda',\n      animSlideRight: 'Deslizar derecha',\n      animScaleIn: 'Zoom entrada',\n      animScaleOut: 'Zoom salida',\n      animTypewriter: 'M\u00E1quina de escribir',\n      animBlurIn: 'Desenfoque entrada',\n      animBlurOut: 'Desenfoque salida',\n      animRotateIn: 'Rotar entrada',\n      sizingMode: 'Ajuste',\n      fitFrame: 'Ajustar al marco',\n      fillStretch: 'Rellenar / estirar',\n      zoomCrop: 'Recorte zoom',\n      blendMode: 'Modo de fusi\u00F3n',\n      blendNormal: 'Normal',\n      blendScreen: 'Trama (Screen)',\n      blendMultiply: 'Multiplicar',\n      blendOverlay: 'Superponer',\n      blendDifference: 'Diferencia',\n      blendLuminosity: 'Luminosidad',\n      flipHorizontal: 'Voltear horizontal',\n      flipVertical: 'Voltear vertical',\n      aiTranslate: 'Traducci\u00F3n autom\u00E1tica',\n      aiTranslateBtn: 'Traducir',\n      aiCreativeDesign: 'Dise\u00F1o creativo AI',\n      aiStylePlaceholder: 'Ej: amarillo estilo MrBeast\u2026',\n      aiTextStylePlaceholder: 'Ej: estilo retro futurista rosa ne\u00F3n\u2026',\n      aiApplyStyle: 'Aplicar estilo AI',\n      aiColorFilter: 'Filtro de color AI',\n      aiGradingPlaceholder: 'Ej: c\u00E1lido atardecer retro\u2026',\n      aiApplyPreset: 'Aplicar preset AI',\n      langEnglish: 'Ingl\u00E9s',\n      langSpanish: 'Espa\u00F1ol',\n      langPortuguese: 'Portugu\u00E9s',\n      langFrench: 'Franc\u00E9s',\n      langGerman: 'Alem\u00E1n',\n      langItalian: 'Italiano',\n      noSubtitlesError: 'No hay subt\u00EDtulos en la l\u00EDnea de tiempo.',\n      translateShapeError: 'La respuesta de traducci\u00F3n AI no tiene la estructura esperada.',\n      reset: 'Restablecer',\n    },\n    colorGrading: {\n      tabBasic: 'B\u00E1sico',\n      tabCurves: 'Curvas',\n      tabHsl: 'HSL',\n      tabVignette: 'Vi\u00F1eta',\n      aiTitle: 'Look cinematogr\u00E1fico AI',\n      aiPlaceholder: 'Ej: atardecer c\u00E1lido retro\u2026',\n      aiApply: 'Aplicar',\n      aiNeedKey: 'Configura tu sesi\u00F3n para usar grading AI.',\n      exposure: 'Exposici\u00F3n',\n      contrast: 'Contraste',\n      highlights: 'Altas luces',\n      shadows: 'Sombras',\n      temperature: 'Temperatura',\n      tint: 'Tinte',\n      vibrance: 'Intensidad',\n      saturation: 'Saturaci\u00F3n',\n      channelMaster: 'Master',\n      channelRed: 'Rojo',\n      channelGreen: 'Verde',\n      channelBlue: 'Azul',\n      hslHue: 'Tono',\n      hslSaturation: 'Saturaci\u00F3n',\n      hslLuminance: 'Luminancia',\n      enableVignette: 'Activar vi\u00F1eta',\n      vignetteAmount: 'Cantidad',\n      vignetteMidpoint: 'Punto medio',\n      vignetteFeather: 'Difuminado',\n      doubleClickDeletePoint: 'Doble clic en un punto para eliminarlo',\n    },\n    effectStack: {\n      emptyTitle: 'Sin efectos en este clip',\n      emptyHint: 'Aplica un efecto desde el panel Efectos (doble clic o Aplicar).',\n      hardwareNote: 'Este efecto se renderiza con optimizaci\u00F3n por hardware.',\n      activeRange: 'Rango activo',\n      startTime: 'Inicio',\n      endTime: 'Fin',\n      enable: 'Activar efecto',\n      disable: 'Desactivar efecto',\n      remove: 'Quitar efecto',\n      addKeyframe: 'A\u00F1adir keyframe en el playhead',\n      removeKeyframe: 'Quitar keyframe en el playhead',\n      direction: 'Direcci\u00F3n',\n      zoomIn: 'Acercar',\n      zoomOut: 'Alejar',\n      reflection: 'Reflexi\u00F3n',\n      reflectionH: 'Divisi\u00F3n horizontal',\n      reflectionV: 'Divisi\u00F3n vertical',\n      reflectionQuad: 'Cuatro cuadrantes',\n      params: {\n        exposure: 'Pasos de exposici\u00F3n',\n        brightness: 'Brillo',\n        contrast: 'Contraste',\n        saturation: 'Saturaci\u00F3n',\n        temperature: 'Temperatura',\n        tint: 'Tinte',\n        radius: 'Radio de desenfoque',\n        trackingNoise: 'Ruido de tracking',\n        colorBleed: 'Sangrado de color',\n        scanLines: 'L\u00EDneas de barrido',\n        analogBrightness: 'Brillo anal\u00F3gico',\n        amount: 'Desplazamiento',\n        blockSize: 'Tama\u00F1o de bloque',\n        sepiaIntensity: 'Intensidad sepia',\n        scratchIntensity: 'Polvo y rayones',\n        jitter: 'Temblor de fotograma',\n        startScale: 'Escala inicio',\n        endScale: 'Escala fin',\n        startX: 'Offset X inicio',\n        startY: 'Offset Y inicio',\n        endX: 'Offset X fin',\n        endY: 'Offset Y fin',\n        frequency: 'Frecuencia',\n        intensity: 'Intensidad',\n        zoomPeak: 'Zoom m\u00E1ximo',\n        centerX: 'Centro X',\n        centerY: 'Centro Y',\n      },\n      names: {\n        'brightness-contrast': 'Brillo y contraste',\n        'hue-saturation': 'Tono / Saturaci\u00F3n',\n        'color-balance': 'Balance de color',\n        curves: 'Curvas',\n        levels: 'Niveles',\n        exposure: 'Exposici\u00F3n',\n        'shadows-highlights': 'Sombras y altas luces',\n        vibrance: 'Intensidad',\n        'color-temperature': 'Temperatura y tinte',\n        'selective-color': 'Color selectivo',\n        'channel-mixer': 'Mezclador de canales',\n        'gradient-map': 'Mapa de degradado',\n        'lut-3d': 'LUT 3D',\n        'blur-gaussian': 'Desenfoque gaussiano',\n        'blur-motion': 'Desenfoque de movimiento',\n        'blur-radial': 'Desenfoque radial',\n        sharpen: 'Enfocar',\n        'unsharp-mask': 'M\u00E1scara de enfoque',\n        glow: 'Resplandor',\n        bloom: 'Bloom',\n        vignette: 'Vi\u00F1eta',\n        'film-grain': 'Grano de pel\u00EDcula',\n        'chromatic-aberration': 'Aberraci\u00F3n crom\u00E1tica',\n        scanlines: 'L\u00EDneas de barrido',\n        pixelate: 'Pixelado',\n        posterize: 'Posterizar',\n        threshold: 'Umbral',\n        emboss: 'Relieve',\n        'edge-detect': 'Detecci\u00F3n de bordes',\n        duotone: 'Duotono',\n        halftone: 'Mediotono',\n        'glitch-rgb': 'Glitch RGB',\n        noise: 'Ruido',\n        'old-film': 'Pel\u00EDcula antigua',\n        vhs: 'Filtro VHS',\n        'ken-burns': 'Ken Burns',\n        'zoom-dynamic': 'Zoom din\u00E1mico',\n        'camera-shake': 'Temblor de c\u00E1mara',\n        stabilize: 'Estabilizar',\n        'speed-ramp': 'Rampa de velocidad',\n        strobe: 'Estrobosc\u00F3pico',\n        echo: 'Eco de fotograma',\n        'time-freeze': 'Congelar fotograma',\n        transform: 'Transformar',\n        'corner-pin': 'Corner pin',\n        'lens-distortion': 'Distorsi\u00F3n de lente',\n        mirror: 'Espejo',\n        flip: 'Voltear H/V',\n        crop: 'Recortar',\n      },\n    },\n    effectsLibrary: {\n      searchPlaceholder: 'Buscar efectos\u2026',\n      createCustomTitle: 'Crear efecto personalizado',\n      apply: 'Aplicar',\n      applyHint: 'Doble clic para aplicar al clip seleccionado',\n      noResults: 'No se encontraron efectos',\n      noClipTitle: 'Sin selecci\u00F3n',\n      noClipBody: 'Selecciona un clip en la l\u00EDnea de tiempo para aplicar este efecto.',\n      deletePreset: 'Eliminar preset',\n      presetBadge: 'Preset',\n      catAll: 'Todos',\n      catColor: 'Color',\n      catStylistic: 'Estilo',\n      catMotion: 'Movimiento',\n      catTransform: 'Transformar',\n      catCustom: 'Personalizado',\n      nameRequiredTitle: 'Nombre requerido',\n      nameRequiredBody: 'Introduce un nombre para el preset.',\n      cancel: 'Cancelar',\n      createEffect: 'Crear efecto',\n      presetName: 'Nombre del preset',\n      presetNamePlaceholder: 'Ej: Calidez cinematogr\u00E1fica',\n      description: 'Descripci\u00F3n',\n      descriptionPlaceholder: 'Ej: Desenfoque suave con tinte c\u00E1lido',\n      category: 'Categor\u00EDa',\n      baseEngine: 'Motor base del efecto',\n      configureParams: 'Configurar par\u00E1metros',\n      customPresetFallback: (type: string) => `Preset personalizado (${type})`,\n      catColorFull: 'Correcci\u00F3n de color',\n      catStylisticFull: 'Filtro estilizado',\n      catMotionFull: 'Efecto de movimiento',\n      catTransformFull: 'Transformar',\n      items: {\n        exposure: { name: 'Exposici\u00F3n', desc: 'Ajusta los pasos de exposici\u00F3n' },\n        brightnessContrast: { name: 'Brillo y contraste', desc: 'Ajustes simples de luminosidad' },\n        hueSaturation: { name: 'Tono / Saturaci\u00F3n', desc: 'Corrige niveles de saturaci\u00F3n' },\n        colorTemperature: { name: 'Temperatura y tinte', desc: 'Tinte fr\u00EDo o c\u00E1lido' },\n        blurGaussian: { name: 'Desenfoque gaussiano', desc: 'Suaviza el detalle del fotograma' },\n        vhs: { name: 'Filtro VHS', desc: 'Ruido anal\u00F3gico, parpadeos y sangrado' },\n        oldFilm: { name: 'Pel\u00EDcula antigua', desc: 'Tono sepia + rayones' },\n        pixelate: { name: 'Pixelado', desc: 'Reduce el tama\u00F1o de bloque' },\n        chromaticAberration: { name: 'Aberraci\u00F3n crom\u00E1tica', desc: 'Desplazamiento RGB' },\n        kenBurns: { name: 'Ken Burns', desc: 'Paneo y zoom con keyframes' },\n        cameraShake: { name: 'Temblor de c\u00E1mara', desc: 'Simula seguimiento a mano' },\n        zoomDynamic: { name: 'Zoom din\u00E1mico', desc: 'Zoom r\u00E1pido de entrada o salida' },\n        mirror: { name: 'Espejo', desc: 'Reflejo horizontal o vertical' },\n      },\n    },\n    textPanel: {\n      addText: 'A\u00F1adir texto',\n      voiceAi: 'Voz AI',\n      presetsTitle: 'Plantillas',\n      add: 'A\u00F1adir',\n      defaultText: 'A\u00F1ade tu t\u00EDtulo aqu\u00ED',\n      trackName: 'Texto 1',\n      presets: {\n        lowerThirdClassic: { name: 'Lower third cl\u00E1sico', desc: 'Franja elegante inferior' },\n        lowerThirdModern: { name: 'Lower third moderno', desc: 'Franja sans-serif limpia' },\n        lowerThirdMinimal: { name: 'Lower third m\u00EDnimo', desc: 'L\u00EDnea de texto simple' },\n        bigTitle: { name: 'T\u00EDtulo grande', desc: 'Tarjeta de t\u00EDtulo bold' },\n        subtitlePair: { name: 'Par de subt\u00EDtulo', desc: 'Encabezado + subt\u00EDtulo' },\n        centeredMinimal: { name: 'Centrado m\u00EDnimo', desc: 'Fuente fina centrada' },\n        tiktokCaption: { name: 'Caption TikTok', desc: 'Caption amarillo centrado' },\n        youtubeChapter: { name: 'Cap\u00EDtulo YouTube', desc: 'Etiqueta esquina superior' },\n        instagramQuote: { name: 'Cita Instagram', desc: 'Bloque de cita en it\u00E1lica' },\n        callOutBox: { name: 'Caja de llamada', desc: 'Caja con marco' },\n        quoteCard: { name: 'Tarjeta de cita', desc: 'Texto sobre fondo' },\n      },\n    },\n    timeline: {\n      ripple: 'RIPPLE',\n      clipFallback: 'Clip',\n      tracksLabel: 'Pistas',\n      addLayer: 'Capa',\n      addLayerTitle: 'Agregar capa / pista',\n      addTextLayer: '+ Capa de texto',\n      addSubtitleLayer: '+ Canal de subt\u00EDtulos',\n      addImageLayer: '+ Capa de imagen',\n      addVideoLayer: '+ Capa de video',\n      addAudioLayer: '+ Capa de audio',\n      resizeTracks: 'Redimensionar panel de pistas',\n      reorderLayerUp: 'Subir capa',\n      reorderLayerDown: 'Bajar capa',\n      muteTrack: 'Silenciar pista',\n      unmuteTrack: 'Activar audio',\n      hideTrack: 'Ocultar pista',\n      showTrack: 'Mostrar pista',\n      lockTrack: 'Bloquear pista',\n      unlockTrack: 'Desbloquear pista',\n      deleteTrack: 'Eliminar pista',\n      deleteTrackTitle: 'Eliminar pista',\n      deleteTrackConfirm: (name: string) =>\n        `\u00BFEliminar la pista \"${name}\" y todos sus clips?`,\n      deleteTrackConfirmBtn: 'Eliminar',\n      deleteTrackCancel: 'Cancelar',\n      contextTitle: 'Clip',\n      moveLayerUp: 'Subir de capa',\n      moveLayerDown: 'Bajar de capa',\n      generateSubtitles: 'Generar subt\u00EDtulos',\n      transcribeUnsupportedFormat:\n        'Formato de archivo no soportado para transcribir. Usa MP4, MP3, WAV o WEBM.',\n      generatingSubtitles: 'Generando subt\u00EDtulos\u2026',\n      generatingSubtitlesHint: 'Transcribiendo el audio del clip',\n      translatingSubtitles: 'Traduciendo\u2026',\n      translatingSubtitlesHint: 'Aplicando el idioma seleccionado',\n      stylingSubtitles: 'Aplicando estilo\u2026',\n      stylingSubtitlesHint: 'Tipograf\u00EDa y look del preset AI',\n      generatingVoiceover: 'Generando locuci\u00F3n\u2026',\n      generatingVoiceoverHint: 'Sintetizando TTS en esta pista',\n      generatingCopy: 'Generando copy\u2026',\n      generatingCopyHint: 'Insertando texto en esta pista',\n      split: 'Dividir',\n    },\n    timelineToolbar: {\n      currentTimeAria: 'Tiempo actual',\n      currentTimeTitle: (tc: string) => `Tiempo: ${tc}`,\n      expandTimeline: 'Expandir l\u00EDnea de tiempo',\n      collapseTimeline: 'Colapsar l\u00EDnea de tiempo',\n      restoreSize: 'Restaurar tama\u00F1o',\n      expandFullscreen: 'Expandir a pantalla completa',\n      undo: 'Deshacer',\n      undoTitle: 'Deshacer (Ctrl+Z)',\n      undoEmpty: 'Nada que deshacer',\n      redo: 'Rehacer',\n      redoTitle: 'Rehacer (Ctrl+Shift+Z)',\n      redoEmpty: 'Nada que rehacer',\n      split: 'Cortar clip en el playhead',\n      splitTitle: 'Cortar clip en el playhead (S)',\n      splitDisabled: 'Selecciona un clip para cortar',\n      delete: 'Eliminar clip seleccionado',\n      deleteDisabled: 'Selecciona un clip para eliminarlo',\n      zoomOutVideo: 'Alejar video',\n      zoomInVideo: 'Acercar video',\n      zoomHorizontal: 'Zoom horizontal del video',\n      zoomHorizontalTitle: (n: string) => `Zoom del video: ${n} px/s`,\n      zoomOutTracks: 'Reducir altura de las pistas',\n      zoomInTracks: 'Aumentar altura de las pistas',\n      zoomVertical: 'Zoom vertical de las pistas',\n      zoomVerticalTitle: (n: number) => `Altura de pista: ${n}px`,\n      resetTrackHeight: 'Restablecer altura de las pistas',\n      deleteTitle: 'Eliminar',\n      cancel: 'Cancelar',\n      confirmDelete: 'Eliminar',\n      unnamedClip: 'Clip sin nombre',\n      deleteOne: (name: string) =>\n        `\u00BFEst\u00E1s seguro de que deseas eliminar el clip \"${name}\"? Esta acci\u00F3n no se puede deshacer.`,\n      deleteMany: (n: number, names: string) =>\n        `\u00BFEst\u00E1s seguro de que deseas eliminar ${n} clips (\"${names}\")? Esta acci\u00F3n no se puede deshacer.`,\n    },\n  },\n  draggablePanel: {\n    closeAria: 'Cerrar panel',\n    closeTitle: 'Cerrar panel',\n    resetAria: 'Restablecer posici\u00F3n',\n    resetTitle: 'Restablecer posici\u00F3n',\n  },\n  panel: {\n    assets: 'Assets',\n    overlay: 'Overlay',\n    inspector: 'Inspector',\n    transitions: 'Transiciones',\n    effects: 'Efectos',\n    text: 'Texto',\n    pin: 'Anclar panel (por encima de la l\u00EDnea de tiempo)',\n    unpin: 'Desanclar panel (por debajo de la l\u00EDnea de tiempo)',\n    resetWidth: 'Restablecer ancho',\n    resetSize: 'Restablecer tama\u00F1o',\n    closePanel: 'Cerrar panel',\n    edit: 'Edici\u00F3n',\n    layersAndPages: 'Capas y P\u00E1ginas',\n    layersShort: 'Capas',\n    resetSizeAndPosition: 'Restablecer tama\u00F1o y posici\u00F3n',\n    resizeWidth: 'Arrastrar para cambiar ancho',\n    resizeHeight: 'Arrastrar para cambiar alto',\n    selectElement: 'Selecciona un elemento',\n    selectObjectForProps: 'Selecciona un objeto en el lienzo para ver sus propiedades.',\n    color: 'Color',\n    masterFill: 'Color de relleno (primer plano)',\n    masterStroke: 'Color de borde (fondo)',\n    swapColors: 'Intercambiar relleno y borde (X)',\n    saturationBrightness: 'Saturaci\u00F3n / brillo',\n    hue: 'Tono',\n    hexInput: 'Color hexadecimal',\n    colorPicker: 'Selector de color',\n    noColor: 'Sin color',\n    transparent: 'Transparente',\n  },\n  properties: {\n    text: {\n      transformTitle: 'Transformar',\n      rotation: 'Rotaci\u00F3n',\n      typography: 'Tipograf\u00EDa',\n      searchFonts: 'Buscar fuente\u2026',\n      myFonts: 'Mis Fuentes',\n      fontSize: 'Tama\u00F1o de Fuente',\n      style: 'Estilo',\n      bold: 'Negrita',\n      italic: 'It\u00E1lica',\n      underline: 'Subrayado',\n      strikethrough: 'Tachado',\n      overline: 'Sobrelineado',\n      color: 'Color',\n      fillText: 'Texto',\n      outline: 'Contorno',\n      usesMasterColor: 'Relleno y contorno usan el panel Color (arriba).',\n      thickness: 'Grosor',\n      alignment: 'Alineaci\u00F3n',\n      lineHeight: 'Interlineado',\n      letterSpacing: 'Espaciado de Letras',\n      textCurvature: 'Curvatura del Texto',\n      textShadow: 'Sombra de Texto',\n      blur: 'Difuminado',\n      offsetX: 'Desplazamiento X',\n      offsetY: 'Desplazamiento Y',\n      noTextSelected: 'Selecciona un cuadro de texto en el lienzo para editar sus propiedades.',\n      activateTextTool: 'Activar herramienta de texto',\n      addTextToCanvas: 'A\u00F1adir Texto al Lienzo',\n      addTitle: 'A\u00F1adir un T\u00EDtulo',\n      addSubtitle: 'A\u00F1adir un Subt\u00EDtulo',\n      addBodyText: 'A\u00F1adir cuerpo de texto',\n      loremGenerator: 'Generador Lorem Ipsum',\n      loremHint: 'Genera texto de relleno. Si hay un cuadro de texto seleccionado, lo reemplaza.',\n      loremWords: 'Palabras',\n      loremSentences: 'Oraciones',\n      loremParagraphs: 'P\u00E1rrafos',\n      loremAmount: 'Cantidad',\n      loremApply: 'Insertar / Reemplazar Lorem Ipsum',\n      uploadFonts: 'Subir Fuentes Propias',\n      supportedFormats: 'Soporta archivos TTF, OTF, WOFF y WOFF2.',\n      uploadFontFile: 'Subir archivo de fuente',\n      uploadHint: 'Soporta TTF, OTF, WOFF',\n      loadedFonts: 'Fuentes Cargadas',\n      deleteFontTitle: 'Eliminar',\n      tabProperties: 'Propiedades',\n      tabInsert: 'Insertar',\n      tabLorem: 'Lorem',\n      tabFonts: 'Fuentes',\n      editorTitle: 'Editor de Texto',\n      fontCategory: {\n        sansSerif: 'Sans-Serif',\n        serif: 'Serif',\n        display: 'Display / T\u00EDtulos',\n        handwriting: 'Escritura',\n        monospace: 'Monospace',\n      },\n    },\n    image: {\n      photoFilters: 'Filtros de Foto',\n      photoFiltersSubtitle: 'Ajustes finos de imagen profesional utilizando aceleraci\u00F3n por WebGL.',\n      photoAdjustments: 'Ajustes Fotogr\u00E1ficos',\n      exposure: 'Exposici\u00F3n',\n      brightness: 'Brillo',\n      contrast: 'Contraste',\n      saturation: 'Saturaci\u00F3n',\n      hue: 'Tono (Colores)',\n      blur: 'Desenfoque (Blur)',\n      invertColors: 'Invertir Colores',\n      proAdjustments: 'Ajustes Pro',\n      levels: 'Niveles (Levels)',\n      levelsShadows: 'Sombras',\n      levelsMids: 'Medios',\n      levelsHighlights: 'Luces',\n      curves: 'Curvas (Curves)',\n      curvesRgb: 'Curva RGB',\n      curvesReset: 'Resetear',\n      curvesHint: 'Haz clic para a\u00F1adir puntos. Arr\u00E1stralos para editar.',\n      quickPresets: 'Presets de Filtros R\u00E1pidos',\n      specialEffects: 'Efectos Especiales y Modos',\n      blendMode: 'Modo de Fusi\u00F3n',\n      hsl: 'Color Selectivo (HSL)',\n      selectImageHint: 'Selecciona una imagen para aplicar filtros.',\n      preset: {\n        original: 'Original',\n        grayscale: 'B y N',\n        sepia: 'Sepia',\n        vintage: 'Vintage',\n        cyberpunk: 'Cyberpunk',\n        polar: 'Polar (Fr\u00EDo)',\n        sunset: 'Atardecer',\n        fade: 'Mate (Fade)',\n        noir: 'Noir',\n      },\n      blend: {\n        normal: 'Normal',\n        multiply: 'Multiplicar (Multiply)',\n        screen: 'Trama (Screen)',\n        overlay: 'Superponer (Overlay)',\n        darken: 'Oscurecer (Darken)',\n        lighten: 'Aclarar (Lighten)',\n        difference: 'Diferencia (Difference)',\n        exclusion: 'Exclusi\u00F3n (Exclusion)',\n        colorDodge: 'Color Dodge',\n        colorBurn: 'Color Burn',\n      },\n      effect: {\n        none: 'Ninguna',\n        softDrop: 'Soft Drop',\n        hardDrop: 'Hard Drop',\n        elevate: 'Elevate',\n        neonGlow: 'Neon Glow',\n        glassmorphism: 'Glassmorphism',\n      },\n      resetAll: 'Restablecer',\n      compareOriginal: 'Viendo Original',\n      compareHold: 'Mantener p/ Comparar',\n    },\n    shape: {\n      adjustShape: 'Ajustar Figura',\n      editShapeHint: 'Edita la figura seleccionada en el lienzo. Usa el bot\u00F3n \"Figuras\" del panel inferior para agregar nuevas.',\n      width: 'Ancho (W)',\n      height: 'Alto (H)',\n      geometry: 'Geometr\u00EDa y Posici\u00F3n',\n      positionX: 'Posici\u00F3n X',\n      positionY: 'Posici\u00F3n Y',\n      shapeFill: 'Relleno de Figura',\n      fillColor: 'Relleno',\n      fillSolid: 'S\u00F3lido',\n      fillGradient: 'Degradado',\n      fillNone: 'Ninguno',\n      fillNoneMessage: 'La figura no tiene color de relleno (transparente).',\n      usesMasterFill: 'El relleno s\u00F3lido usa el color de relleno del panel Color.',\n      usesMasterStroke: 'El contorno usa el color de borde del panel Color.',\n      imageColors: 'Colores de la Imagen',\n      start: 'Inicio',\n      end: 'Fin',\n      gradientAngle: '\u00C1ngulo del Degradado',\n      stroke: 'Contorno y L\u00EDnea',\n      strokeColor: 'Contorno',\n      strokeThickness: 'Grosor de Contorno',\n      strokeStyle: 'Estilo de Contorno',\n      strokeSolid: 'S\u00F3lido',\n      strokeDashed: 'Raya',\n      strokeDotted: 'Puntos',\n      cornerRadius: 'Radio de Esquinas',\n      cornerAll: 'Todas',\n      cornerTL: 'Sup. izq.',\n      cornerTR: 'Sup. der.',\n      cornerBL: 'Inf. izq.',\n      cornerBR: 'Inf. der.',\n      cornerLink: 'Vincular esquinas',\n      cornerUnlink: 'Desvincular esquinas',\n      objectShadow: 'Sombra de Objeto',\n      shadowColor: 'Color',\n      shadowBlur: 'Difuminado (Blur)',\n      effects: 'Efectos Especiales y Presets',\n      opacity: 'Opacidad',\n      blendMode: 'Modo de Fusi\u00F3n',\n      scale: 'Escala',\n      scale1x: '1x',\n      scale2x: '2x (Retina)',\n      scale3x: '3x (HD)',\n      format: 'Formato',\n      downloadLayer: 'Descargar Capa',\n      export: 'Export',\n      exportPreview: 'Vista previa',\n      exportSelection: 'Exportar Selecci\u00F3n (Figma Style)',\n      shapeBadge: {\n        vector: 'Vector',\n        rect: 'Rect\u00E1ngulo',\n        frame: 'Marco',\n      },\n    },\n  },\n  layers: {\n    tabLayers: 'Capas',\n    tabPages: 'P\u00E1ginas',\n    noLayers: 'No hay capas creadas.',\n    noLayersHint: 'Usa la barra lateral izquierda para agregar elementos al lienzo.',\n    layerType: {\n      group: 'Grupo',\n      text: (preview: string) => `Texto: \"${preview}\"`,\n      textTruncated: (preview: string) => `Texto: \"${preview}...\"`,\n      image: 'Imagen',\n      pixel: 'Capa de p\u00EDxeles',\n      rect: 'Rect\u00E1ngulo',\n      circle: 'C\u00EDrculo',\n      triangle: 'Tri\u00E1ngulo',\n      path: 'Trazo Libre',\n      line: 'L\u00EDnea',\n      element: 'Elemento',\n    },\n    maskBadge: 'M\u00E1scara',\n    pixelBadge: 'P\u00EDxeles',\n    pixelLayerBase: 'capa',\n    duplicatedOf: (name: string) => `duplicada de ${name}`,\n    cannotDeleteBaseLayer: 'No se puede eliminar la \u00FAnica capa restante.',\n    cannotDeleteLastLayer: 'No se puede eliminar la \u00FAnica capa restante.',\n    mustSelectLayer: 'Selecciona una capa para usar esta herramienta.',\n    alreadyRaster: 'Esta capa ya es de p\u00EDxeles.',\n    rasterizeFailed: 'No se pudo rasterizar la capa.',\n    rasterize: 'Rasterizar',\n    rasterizeTitle: 'Convertir a capa de p\u00EDxeles (bitmap)',\n    newLayer: 'Nueva capa',\n    newLayerTitle: 'Crear capa de p\u00EDxeles en blanco',\n    duplicateLayerTitle: 'Duplicar capa activa',\n    maskComingSoon: 'M\u00E1scara de capa (pr\u00F3ximamente)',\n    linkedTitle: 'Objeto Vinculado',\n    tooltip: {\n      rename: 'Doble clic para renombrar capa',\n      moveUp: 'Mover arriba',\n      moveDown: 'Mover abajo',\n      hide: 'Ocultar Capa',\n      show: 'Mostrar Capa',\n      unlock: 'Desbloquear',\n      lock: 'Bloquear',\n      addMask: 'A\u00F1adir M\u00E1scara',\n      removeMask: 'Quitar m\u00E1scara',\n      paintMask: 'Editar m\u00E1scara',\n      paintContent: 'Editar capa',\n      delete: 'Eliminar Capa',\n      rasterize: 'Rasterizar',\n    },\n    group: 'Agrupar',\n    ungroup: 'Desagrupar',\n    groupTooltip: 'Agrupar Capas (Cmd+G)',\n    ungroupTooltip: 'Desagrupar Capas (Cmd+Shift+G)',\n    pages: {\n      clearCanvasTitle: 'Limpiar lienzo',\n      clearCanvasBody: '\u00BFEst\u00E1s seguro de que deseas limpiar el lienzo de esta p\u00E1gina? Esto no se puede deshacer.',\n      clearCanvasConfirm: 'Limpiar',\n      moveUp: 'Subir',\n      moveDown: 'Bajar',\n      duplicate: 'Duplicar P\u00E1gina',\n      clear: 'Limpiar P\u00E1gina',\n      delete: 'Eliminar P\u00E1gina',\n      deleteTitle: 'Eliminar p\u00E1gina',\n      deleteBody: (name: string) =>\n        `\u00BFEliminar la p\u00E1gina \"${name}\"? Esta acci\u00F3n no se puede deshacer.`,\n      deleteConfirm: 'Eliminar',\n      addNew: 'A\u00F1adir Nueva P\u00E1gina',\n      addNewTitle: 'A\u00F1adir Nueva P\u00E1gina',\n      sizeLabel: (w: number, h: number) => `${w} x ${h} px`,\n    },\n    deleteLayerTitle: 'Eliminar capa',\n    deleteLayerBody: (name: string) =>\n      `\u00BFEliminar la capa \"${name}\"? Esta acci\u00F3n no se puede deshacer.`,\n    deleteLayerConfirm: 'Eliminar',\n    collapse: {\n      show: 'Mostrar Capas',\n      hide: 'Ocultar Capas',\n    },\n  },\n  sidebar: {\n    tab: {\n      canvas: 'Configurar Lienzo',\n      upload: 'Subir Imagen',\n      shapes: 'A\u00F1adir Formas',\n      brush: 'Dibujo / Pincel',\n      filtros: 'Filtros de Imagen',\n      brand: 'Brand Kit & Colores',\n    },\n    stock: {\n      title: 'Galer\u00EDa de Stock Premium',\n      subtitle: 'Millones de im\u00E1genes de Unsplash y Pexels \u2014 libres de derechos.',\n      searchPlaceholder: 'Buscar im\u00E1genes...',\n      emptyResults: 'Sin resultados. Intenta otra b\u00FAsqueda.',\n      poweredBy: (provider: string) => `Powered by ${provider.charAt(0).toUpperCase()}${provider.slice(1)}`,\n      noImageHint: 'Selecciona una imagen en el lienzo para ajustar sus filtros.',\n    },\n    stockCategory: {\n      trending: 'Trending',\n      naturaleza: 'Naturaleza',\n      tecnologia: 'Tecnolog\u00EDa',\n      arquitectura: 'Arquitectura',\n      personas: 'Personas',\n      abstracto: 'Abstracto',\n      ciudad: 'Ciudad',\n      espacio: 'Espacio',\n    },\n    brushPreset: {\n      calligraphy: 'Pincel Caligr\u00E1fico',\n      highlighter: 'Subrayador Amarillo',\n      chalk: 'Tiza Difuminada',\n      neonMagenta: 'Ne\u00F3n Magenta',\n      neonCyan: 'Ne\u00F3n Cian',\n    },\n    stockBgPreset: {\n      studioWhite: 'Estudio Blanco',\n      sunsetGlow: 'Atardecer',\n      oceanBlue: 'Oc\u00E9ano',\n      forestGreen: 'Bosque',\n      marble: 'M\u00E1rmol',\n      darkConcrete: 'Concreto Oscuro',\n      pastelPink: 'Rosa Pastel',\n      deepPurple: 'P\u00FArpura Profundo',\n      goldenHour: 'Hora Dorada',\n      nightSky: 'Cielo Nocturno',\n    },\n    stockLayer: {\n      product: 'Producto',\n      person: 'Persona',\n      scenery: 'Paisaje',\n    },\n    brand: {\n      title: 'Brand Kit & Colores',\n      subtitle: 'Genera armon\u00EDas de color y guarda tus paletas para mantener la consistencia de tu marca.',\n      harmonyGenerator: 'Generador de Armon\u00EDas',\n      baseColorLabel: 'Color Base (HEX)',\n      baseColorTooltip: 'Cambiar color base',\n      harmonyRuleLabel: 'Regla de Armon\u00EDa',\n      harmony: {\n        complementary: 'Complementario',\n        analogous: 'An\u00E1logo',\n        triadic: 'Tr\u00EDada',\n        splitComplementary: 'Complementario Div',\n        tetradic: 'T\u00E9trada',\n        monochromatic: 'Monocrom\u00E1tico',\n      },\n      harmonyName: {\n        complementary: 'Armon\u00EDa Complementaria',\n        analogous: 'Armon\u00EDa An\u00E1loga',\n        triadic: 'Armon\u00EDa Tr\u00EDada',\n        splitComplementary: 'Armon\u00EDa Comp. Dividida',\n        tetradic: 'Armon\u00EDa T\u00E9trada',\n        monochromatic: 'Armon\u00EDa Monocrom\u00E1tica',\n        fallback: 'Paleta Generada',\n      },\n      edit: 'EDITAR',\n      savePalette: '+ Guardar Paleta',\n      savedPalettes: 'Paletas Guardadas',\n      addPalette: 'A\u00F1adir Paleta',\n      addShort: 'A\u00F1adir',\n      newPalette: 'Nueva Paleta',\n      noPalettes: 'No has guardado paletas a\u00FAn.',\n      paletteNamePlaceholder: 'Paleta',\n      brandPaletteName: (brandName: string) =>\n        brandName?.trim() ? `Marca: ${brandName.trim()}` : 'Colores de marca',\n      tooltipAddColor: 'A\u00F1adir color',\n      tooltipDeletePalette: 'Eliminar paleta',\n      tooltipEditColor: 'Editar color',\n    },\n  },\n  canvas: {\n    toolstrip: {\n      select: 'Seleccionar (V)',\n      hand: 'Mano / Desplazar (H)',\n      text: 'Texto (T)',\n      back: 'Atr\u00E1s',\n      background: 'Fondo del lienzo',\n      paintBucket: 'Bote de pintura (G)',\n      brush: 'Pincel (B)',\n      magicEraser: 'Borrador m\u00E1gico',\n      eraserMenu: 'Herramientas de borrador',\n      eraserGroup: 'Borrador',\n      shapes: 'Figuras',\n      frames: 'Marcos y Mockups',\n      aiStudio: 'AI Studio',\n      upload: 'Subir imagen',\n      canvasSize: 'Tama\u00F1o de canvas',\n      grid: 'Cuadr\u00EDcula',\n      showRulers: 'Mostrar reglas',\n      hideRulers: 'Ocultar reglas',\n      colorblind: 'Simulador de daltonismo',\n      crop: 'Recortar imagen',\n      cropDisabled: 'Selecciona una imagen para recortar',\n      cropDisabledLastLayer: 'No se puede recortar la \u00FAnica capa',\n      cloneStamp: 'Tap\u00F3n de clonar (S)',\n      magicWand: 'Varita m\u00E1gica (W)',\n      pixelLasso: 'Lazo libre (L)',\n      polygonLasso: 'Lazo poligonal (O)',\n      eraser: 'Borrador (E)',\n      selectRect: 'Lazo rectangular',\n      selectEllipse: 'Lazo circular',\n      selectLasso: 'Lazo libre (objetos)',\n      selectMenu: 'Herramientas de selecci\u00F3n',\n      lassoMenu: 'Herramientas de lazo',\n      lassoGroup: 'Lazo',\n      selectAria: 'Seleccionar',\n      handAria: 'Mano / Desplazar',\n      textAria: 'Texto',\n      backgroundAria: 'Fondo del lienzo',\n      paintBucketAria: 'Bote de pintura',\n      sizeAria: 'Tama\u00F1o de canvas',\n      gridAria: 'Opciones de cuadr\u00EDcula',\n      rulersAriaShow: 'Mostrar reglas',\n      rulersAriaHide: 'Ocultar reglas',\n      colorblindAria: 'Simulador de daltonismo',\n      backgroundTitle: (color: string) => `Fondo: ${color}`,\n      sizeTitle: (w: number, h: number) => `${w} \u00D7 ${h} px`,\n    },\n    uploadPanel: {\n      title: 'Subir imagen',\n      tabDevice: 'Desde el equipo',\n      tabFiles: 'Mis archivos',\n      tabStock: 'Im\u00E1genes de stock',\n      dragDrop: 'Haz clic o arrastra aqu\u00ED \u2014 PNG, JPG, JPEG, SVG (M\u00E1x 25MB)',\n      dragDropActive: '\u00A1Suelte aqu\u00ED sus im\u00E1genes!',\n      urlLabel: 'URL',\n      urlPlaceholder: 'https://ejemplo.com/imagen.png',\n      urlImageName: 'Imagen URL',\n      insert: 'Insertar',\n      historyHeader: (count: number) => `Tus Im\u00E1genes (${count})`,\n      clearAll: 'Limpiar todo',\n      clearHistoryTitle: 'Vaciar historial',\n      clearHistoryBody: '\u00BFDeseas vaciar todo tu historial de subidas? Las im\u00E1genes guardadas localmente se borrar\u00E1n.',\n      clearHistoryConfirm: 'Vaciar',\n      tooltipDeleteAsset: 'Eliminar de Subidas',\n      brandImagesHeader: 'Im\u00E1genes de marca',\n      brandLogosHeader: 'Logos de marca',\n      jobsHeader: 'Generaciones y archivos',\n      filesEmpty: 'No hay im\u00E1genes remotas disponibles a\u00FAn.',\n      stockSearchPlaceholder: 'Buscar en stock\u2026',\n      stockEmpty: 'Sin resultados. Prueba otra b\u00FAsqueda.',\n      stockLoading: 'Cargando\u2026',\n      stockHeader: 'Recursos de Stock Ilustrativos',\n      stockMoreTitle: 'Explorar m\u00E1s im\u00E1genes de Stock',\n      stockMoreButton: 'M\u00E1s',\n    },\n    gridPanel: {\n      title: 'Cuadr\u00EDcula de Maquetaci\u00F3n',\n      activate: 'Activar cuadr\u00EDcula',\n      deactivate: 'Desactivar cuadr\u00EDcula',\n      type: 'Tipo',\n      columns: 'Columnas (12)',\n      modular: 'Modular (Px)',\n      columnCount: 'N\u00FAmero de Columnas',\n      gutter: 'Canal (Gutter)',\n      margin: 'Margen',\n      gridSize: 'Tama\u00F1o de Cuadr\u00EDcula',\n      gridColor: 'Color de Cuadr\u00EDcula',\n      colorPink: 'Rosa',\n      colorBlue: 'Azul',\n      colorRed: 'Rojo',\n      colorGray: 'Gris',\n    },\n    aiStudio: {\n      title: 'AI Studio',\n      processing: 'Procesando...',\n      tab: {\n        enhancements: 'Mejoras',\n        generador: 'Generador',\n        copilot: 'Copilot',\n        copywriter: 'Copywriter',\n        fondo: 'Fondos',\n      },\n      enhancements: {\n        intro: 'Mejoras autom\u00E1ticas de imagen usando IA. Requiere seleccionar una imagen en el lienzo.',\n        autoEnhance: 'Auto-Enhance M\u00E1gico',\n        upscale2x: 'Upscale 2x',\n        variations: 'Variaciones',\n        imageToolsHeader: 'Herramientas de Imagen',\n        removeBg: 'Quitar Fondo (Remove BG)',\n        separateSubject: 'Separar Sujeto en Nueva Capa',\n        modifyPlaceholder: \"Ej: 'vu\u00E9lvelo cyberpunk'\",\n        apply: 'Aplicar',\n        noImage: 'Selecciona una imagen en el lienzo para habilitar estas herramientas.',\n      },\n      generador: {\n        intro: 'Genera im\u00E1genes con IA a partir de una descripci\u00F3n de texto.',\n        promptPlaceholder: 'Describe la imagen que deseas... (ej: gato espacial cafe)',\n        aspectLabel: 'Proporci\u00F3n',\n        resolutionLabel: 'Resoluci\u00F3n',\n        referencesAdd: 'Subir referencia',\n        generate: 'Generar Imagen AI',\n        generating: 'Generando imagen...',\n        inAreaHeader: 'Generar en \u00C1rea Seleccionada',\n        inAreaPlaceholder: \"Ej: 'campo de flores en primavera'\",\n        generateInArea: 'Generar en esta \u00C1rea',\n        generatingInArea: 'Generando...',\n      },\n      copilot: {\n        title: 'AI Design Copilot',\n        intro: 'Modifica el lienzo, texto, formas o filtros de foto seleccionados usando lenguaje natural.',\n        activeObject: (type: string) => `Objeto activo: ${type.toUpperCase()}`,\n        noSelection: 'Sin selecci\u00F3n \u2014 Modificar\u00E1 el fondo del lienzo',\n        placeholder: \"Ej: 'texto neon rosa brillante gigante'...\",\n        apply: 'Aplicar Dise\u00F1o AI',\n        applying: 'Aplicando Dise\u00F1o...',\n        geminiKeyLabel: 'Gemini API Key',\n        apiActive: 'API Activa',\n        localFallback: 'Local Fallback',\n        geminiKeyPlaceholder: 'Introduce tu API Key de Google...',\n        geminiKeyHint: 'Habilita el modelo gemini para creaci\u00F3n y edici\u00F3n premium.',\n      },\n      copywriter: {\n        intro: 'Genera 3 opciones profesionales de copys con IA. Haz clic en una para aplicarla.',\n        promptPlaceholder: \"Ej: 'oferta de caf\u00E9', 'slogan creativo'\",\n        write: 'Redactar',\n        brandHint: (name: string) => `Usando estilo de marca: ${name}`,\n        brandMissing: 'Sin marca activa \u2014 el copy no usar\u00E1 tono de marca.',\n        selectHint: 'Selecciona una sugerencia:',\n        apply: 'Aplicar \u2192',\n        styles: {\n          comercial: 'Persuasiva / Comercial',\n          creativa: 'Original / Creativa',\n          directa: 'Clara / Directa',\n        },\n      },\n      fondo: {\n        intro: 'Genera fondos art\u00EDsticos con IA para tu lienzo.',\n        scenePresetLabel: 'Preset de Escena',\n        presets: {\n          empty: '-- Selecciona un estilo r\u00E1pido --',\n          studioPremium: 'Estudio Premium',\n          minimalistOffice: 'Oficina Minimalista',\n          sunsetBeach: 'Playa al Atardecer',\n          cyberpunkCity: 'Ciudad Cyberpunk de Noche',\n          fantasyForest: 'Bosque de Fantas\u00EDa',\n          elegantMarble: 'M\u00E1rmol Elegante',\n        },\n        customDescriptionLabel: 'Descripci\u00F3n Personalizada',\n        customPlaceholder: \"Ej: 'bosque m\u00E1gico atardecer'\",\n        blendWithSubject: 'Mezclar con sujeto seleccionado',\n        fill: 'Rellenar Fondo AI',\n        filling: 'Generando fondo...',\n      },\n    },\n    frames: {\n      title: 'Marcos y Mockups',\n      description: 'Haz clic en un marco para dibujarlo. Arrastra una imagen sobre \u00E9l para encajarla (Drag-to-Fit).',\n      devicesHeader: 'Dispositivos',\n      mediaHeader: 'Medios F\u00EDsicos',\n      webHeader: 'Web & Interfaz',\n      abstractHeader: 'Formas Abstractas',\n      device: {\n        mobile: 'M\u00F3vil',\n        tablet: 'Tablet',\n        laptop: 'Port\u00E1til',\n        desktop: 'Monitor',\n        watch: 'Reloj',\n      },\n      physical: {\n        polaroid: 'Polaroid',\n        gallery: 'Galer\u00EDa',\n        billboard: 'Billboard',\n        poster: 'P\u00F3ster',\n        businessCard: 'Tarjeta',\n      },\n      web: {\n        browser: 'Browser',\n        video: 'Video',\n        chat: 'Chat',\n      },\n      abstract: {\n        circle: 'C\u00EDrculo',\n        arch: 'Arco',\n        hexagon: 'Hex\u00E1gono',\n        heart: 'Coraz\u00F3n',\n        blob: 'Org\u00E1nico',\n        pill: 'P\u00EDldora',\n        diamond: 'Rombo',\n        starPro: 'Estrella',\n      },\n    },\n    brush: {\n      glowTitle: 'Efecto Resplandor',\n      glowRadius: 'Radio de Difuminado',\n      glowColor: 'Color del Resplandor',\n      configTitle: 'Configuraci\u00F3n de Pincel',\n      style: 'Estilo de pincel',\n      styleOptions: {\n        pencil: 'Cl\u00E1sico',\n        calligraphy: 'Caligraf\u00EDa',\n        highlighter: 'Destacador',\n        chalk: 'Tiza',\n        spray: 'Aerosol',\n        circle: 'Burbujas',\n        magicEraser: 'Borrador IA',\n      },\n      colorAria: 'Color y opacidad del trazo',\n      colorRgba: 'Color (RGBA)',\n      opacity: 'Opacidad (Alpha)',\n      presets: 'Presets de estilo',\n      presetDefault: 'Preset',\n      widthLabel: 'Grosor del pincel',\n      radiusPopupTitle: 'Radio del pincel',\n      radiusSlider: 'Ajustar radio',\n      radiusInput: 'Radio',\n      smoothingLabel: 'Suavizado del trazo',\n      pressure: 'Grosor din\u00E1mico',\n    },\n    booleanOps: {\n      union: 'Uni\u00F3n',\n      subtract: 'Restar',\n      intersect: 'Intersecci\u00F3n',\n    },\n    pen: {\n      pathHint:\n        'Creando path: haz clic para a\u00F1adir nodos. Haz clic en el primer nodo o pulsa Enter para terminar.',\n    },\n    magicWand: {\n      title: 'Varita m\u00E1gica',\n      hint: 'Haz clic en una imagen para seleccionar p\u00EDxeles de color similar. Ajusta la tolerancia y aplica eliminar, rellenar o extraer.',\n      properties: 'Propiedades',\n      selectionMode: 'Modo de selecci\u00F3n',\n      addMode: 'Sumar',\n      subtractMode: 'Restar',\n      addModeHint: 'Sumar a la selecci\u00F3n (Shift)',\n      subtractModeHint: 'Restar de la selecci\u00F3n (Ctrl)',\n      modifierHint: 'Atajos: Shift = sumar \u00B7 Ctrl = restar',\n      tolerance: 'Tolerancia',\n      resetTolerance: 'Restablecer tolerancia',\n      contiguous: 'Contiguos',\n      fillColor: 'Color de relleno',\n      fillUsesMaster: 'El relleno usa el color del panel Color (relleno / primer plano).',\n      noSelection: 'Sin selecci\u00F3n \u2014 haz clic en la imagen.',\n      selectedPixels: (n: number) => `${n.toLocaleString('es-ES')} p\u00EDxeles seleccionados`,\n      actions: 'Acciones',\n      delete: 'Eliminar selecci\u00F3n',\n      fill: 'Rellenar selecci\u00F3n',\n      cutToLayer: 'Extraer a nueva capa',\n      deselect: 'Deseleccionar',\n      toasts: {\n        deleted: 'Selecci\u00F3n eliminada',\n        filled: 'Selecci\u00F3n rellenada',\n        cut: 'Selecci\u00F3n extra\u00EDda a nueva capa',\n      },\n    },\n    paintBucket: {\n      title: 'Bote de pintura',\n      hint: 'Haz clic en una imagen para rellenar con el color de relleno del panel Color. Ajusta tolerancia, contiguos y suavizado.',\n      properties: 'Propiedades',\n      fillColor: 'Color de relleno',\n      opacity: 'Opacidad',\n      tolerance: 'Tolerancia',\n      resetTolerance: 'Restablecer tolerancia',\n      contiguous: 'Contiguos',\n      antiAlias: 'Suavizado',\n      noImage: 'Haz clic en una imagen para rellenar.',\n      readError: 'No se pueden leer los p\u00EDxeles de esta imagen (CORS o imagen vac\u00EDa).',\n      fillError: 'Error al rellenar con el bote de pintura.',\n    },\n    pixelLasso: {\n      title: 'Lazo libre',\n      hint: 'Arrastra sobre la imagen para seleccionar p\u00EDxeles. Usa + / \u2212 o Shift / Ctrl para sumar o restar.',\n      noSelection: 'Sin selecci\u00F3n \u2014 dibuja un lazo sobre la imagen.',\n    },\n    rectLasso: {\n      title: 'Lazo rectangular',\n      hint: 'Arrastra un rect\u00E1ngulo sobre la imagen para seleccionar p\u00EDxeles. Usa + / \u2212 o Shift / Ctrl para sumar o restar.',\n      noSelection: 'Sin selecci\u00F3n \u2014 arrastra un rect\u00E1ngulo sobre la imagen.',\n    },\n    ellipseLasso: {\n      title: 'Lazo circular',\n      hint: 'Arrastra una elipse sobre la imagen para seleccionar p\u00EDxeles. Usa + / \u2212 o Shift / Ctrl para sumar o restar.',\n      noSelection: 'Sin selecci\u00F3n \u2014 arrastra una elipse sobre la imagen.',\n    },\n    polygonLasso: {\n      title: 'Lazo poligonal',\n      hint: 'Haz clic para colocar v\u00E9rtices. Cierra clicando el primer punto, con doble clic o Enter. Escape cancela.',\n      noSelection: 'Sin selecci\u00F3n \u2014 coloca puntos sobre la imagen y cierra el pol\u00EDgono.',\n    },\n    eraser: {\n      title: 'Borrador',\n      hint: 'Pinta sobre una imagen para borrar p\u00EDxeles (transparencia).',\n      brush: 'Pincel',\n      rightClickHint: 'Clic derecho: ajustar radio del borrador.',\n    },\n    magicEraserPanel: {\n      title: 'Borrador m\u00E1gico',\n      hint: 'Marca lo que quieras quitar y confirma con el check. La X cancela las marcas.',\n      loading: 'Eliminando selecci\u00F3n',\n    },\n    cloneStamp: {\n      title: 'Tap\u00F3n de clonar',\n      hint: 'Alt + clic para fijar el origen. Luego pinta para clonar.',\n      brush: 'Pincel',\n      rightClickHint: 'Clic derecho: ajustar radio del pincel.',\n    },\n    colorblind: {\n      title: 'Simulador de Daltonismo',\n      modes: {\n        normal: 'Normal',\n        protanopia: 'Protanopia',\n        deuteranopia: 'Deuteranopia',\n        tritanopia: 'Tritanopia',\n      },\n    },\n    bgPanel: {\n      title: 'Fondo del lienzo',\n      tabSolid: 'S\u00F3lido',\n      tabGradient: 'Degradado',\n      tabTextures: 'Texturas',\n      brandColors: 'Colores de marca',\n      imageColors: 'Colores de la Imagen',\n      customColor: 'Personalizado',\n      transparent: 'Transparente',\n      gradientBuilder: 'Creador de Degradados',\n      gradientStart: 'Inicio',\n      gradientEnd: 'Fin',\n      gradientAngle: 'Direcci\u00F3n / \u00C1ngulo',\n      textureSwatch: 'Muestrario de Texturas',\n      uploadCustom: 'Subir Textura Personalizada',\n      uploadFile: 'Subir archivo de imagen',\n      urlLoad: 'Cargar desde URL',\n      urlPlaceholder: 'https://ejemplo.com/fondo.jpg',\n    },\n    sizePanel: {\n      title: 'Ajustar canvas',\n      tabDimensions: 'Dimensiones',\n      tabFormats: 'Formatos',\n      tabColor: 'Color',\n      width: 'Ancho',\n      height: 'Alto',\n      lockRatio: 'Bloquear relaci\u00F3n de aspecto',\n      unlockRatio: 'Desbloquear relaci\u00F3n de aspecto',\n      unit: 'Unidad',\n      orientation: 'Orientaci\u00F3n',\n      horizontal: 'Horizontal',\n      vertical: 'Vertical',\n      catSocial: 'Redes',\n      catWeb: 'Web',\n      catPrint: 'Imprenta',\n    },\n    shapesPanel: {\n      title: 'Figuras',\n      tabFigures: 'Figuras',\n      tabShapes: 'Formas',\n      tabCharts: 'Gr\u00E1ficos',\n      tabQrCode: 'QR & C\u00F3digo',\n      basicFigures: 'Figuras B\u00E1sicas',\n      rect: 'Rect\u00E1ngulo',\n      rounded: 'Redondeado',\n      circle: 'C\u00EDrculo',\n      ellipse: 'Elipse',\n      line: 'L\u00EDnea',\n      polygonsAndStars: 'Pol\u00EDgonos y Estrellas',\n      triangle: 'Tri\u00E1ngulo',\n      hexagon: 'Hex\u00E1gono',\n      star: 'Estrella',\n      specialFigures: 'Figuras Especiales',\n      arrow: 'Flecha',\n      heart: 'Coraz\u00F3n',\n      speechBubble: 'Bocadillo',\n      cross: 'Cruz',\n      editableCharts: 'Gr\u00E1ficos Editables',\n      editChartHint: 'Doble clic en un gr\u00E1fico del lienzo para editar sus datos.',\n      insertBarChart: 'Insertar gr\u00E1fico de barras',\n      insertLineChart: 'Insertar gr\u00E1fico de l\u00EDneas',\n      insertPieChart: 'Insertar gr\u00E1fico de pastel',\n      insertDonutChart: 'Insertar gr\u00E1fico de dona',\n      chartBar: 'Barras',\n      chartLine: 'L\u00EDneas',\n      chartPie: 'Pastel',\n      chartDonut: 'Dona',\n      qrGenerator: 'Generador de QR',\n      barcodeGenerator: 'Generador de Barras',\n      qrPlaceholder: 'URL, texto, vCard...',\n      barcodePlaceholder: 'Ej: 123456789 (CODE128)',\n      insertQr: 'Insertar C\u00F3digo QR',\n      insertBarcode: 'Insertar C\u00F3digo de Barras',\n    },\n    eyedropper: {\n      paint: 'Pintar:',\n      pageBackground: 'Fondo de la P\u00E1gina',\n      invalidImage: 'Inv\u00E1lido (Imagen)',\n      selectedText: 'Texto Seleccionado',\n      selectedShape: 'Forma Seleccionada',\n      pickColor: 'Cuenta gotas',\n      pickFillHint: 'I \u00B7 muestrear relleno',\n      pickStrokeHint: 'I + Shift \u00B7 muestrear contorno',\n      cancelSpaceHint: 'Espacio para cancelar',\n    },\n    finishCropMask: 'Terminar Recorte de M\u00E1scara',\n    magicEraserActive: 'Borrador M\u00E1gico Activo',\n    magicEraserCleaning: 'Eliminando selecci\u00F3n',\n    magicEraserApply: 'Aplicar Limpieza Inteligente',\n    magicEraserClearMarks: 'Borrar marcas',\n    contextMenu: {\n      objectActions: 'Acciones de Objeto',\n      duplicate: 'Duplicar',\n      unlock: 'Desbloquear',\n      lock: 'Bloquear',\n      organizeLayers: 'Organizar Capas',\n      bringToFront: 'Traer al Frente',\n      bringForward: 'Traer Adelante',\n      sendBackward: 'Enviar Atr\u00E1s',\n      sendToBack: 'Enviar al Fondo',\n      stylesAndMasks: 'Estilos y M\u00E1scaras',\n      copyStyle: 'Copiar Estilo',\n      pasteStyle: 'Pegar Estilo',\n      quickMask: 'M\u00E1scara R\u00E1pida (1-Clic)',\n      maskCircle: 'C\u00EDrculo',\n      maskCircleTitle: 'M\u00E1scara Circular',\n      maskRounded: 'R-Rect',\n      maskRoundedTitle: 'Rect\u00E1ngulo Redondeado',\n      maskHeart: 'Coraz\u00F3n',\n      maskHeartTitle: 'M\u00E1scara de Coraz\u00F3n',\n      maskStar: 'Estrella',\n      maskStarTitle: 'M\u00E1scara de Estrella',\n      maskTriangle: 'Tri\u00E1ng.',\n      maskTriangleTitle: 'M\u00E1scara de Tri\u00E1ngulo',\n      smartLinking: 'Vinculaci\u00F3n inteligente',\n      link: 'Vincular (Link)',\n      unlink: 'Desvincular (Unlink)',\n      createMask: 'Crear M\u00E1scara',\n      createMaskHint: 'Shift+Clic Foto + Forma',\n      createMaskTitle: 'Para crear una m\u00E1scara, selecciona una imagen y una forma geom\u00E9trica manteniendo Shift pulsado.',\n      releaseMask: 'Soltar M\u00E1scara',\n      groupLayers: 'Agrupar Capas',\n      ungroup: 'Desagrupar',\n      aiMagic: 'AI Magic',\n      maskEditing: 'Edici\u00F3n de m\u00E1scara',\n      removeBg: 'Quitar Fondo (AI)',\n      separateSubject: 'Separar Sujeto (AI)',\n      generateInArea: 'Generar en \u00C1rea (AI)',\n      generateInAreaPrompt: 'Introduce el prompt para generar la imagen en esta \u00E1rea:',\n      sketchToImage: 'Boceto a Imagen (AI)',\n      sketchToImagePrompt: 'Introduce el prompt para transformar el boceto:',\n      convertToCurves: 'Convertir a Curvas (Path)',\n      convertError: 'No se pudo convertir el texto a vector.',\n      convertErrorTitle: 'Error de conversi\u00F3n',\n      convertCustomOnly: 'La conversi\u00F3n a curvas solo est\u00E1 disponible para fuentes personalizadas (Subidas).',\n      convertCustomOnlyTitle: 'Fuentes personalizadas',\n      textOnPath: 'Colocar Texto en Path',\n      textMask: 'M\u00E1scara de Texto (Recorte)',\n      copyObject: 'Copiar Objeto',\n      exportLayer: 'Exportar Capa',\n      delete: 'Eliminar',\n      generalActions: 'Acciones Generales',\n      paste: 'Pegar',\n      showGrid: 'Mostrar Cuadr\u00EDcula',\n      clearCanvas: 'Limpiar Lienzo',\n    },\n  },\n  audio: {\n    editor: {\n      noProject: 'No hay proyecto de audio abierto',\n      newProject: 'Nuevo proyecto de audio',\n      dragHere: 'Arrastra audio aqu\u00ED',\n      dragFormatHint: 'WAV, MP3, OGG\u2026 o usa Importar / panel IA',\n      chooseFiles: 'Elegir archivos',\n      dropToImport: 'Soltar para importar',\n      shortcutsTitle: 'Atajos de teclado',\n      shortcutsClose: 'Cerrar',\n      zoomOut: 'Zoom out pista',\n      zoomIn: 'Zoom in pista',\n      snap: 'Ajuste magn\u00E9tico (snapping)',\n      bpmLabel: 'BPM',\n      bpmTitle: 'Tempo del proyecto (pulsos por minuto)',\n      bpmUp: 'Subir BPM',\n      bpmDown: 'Bajar BPM',\n      bpmHalf: 'Mitad de tempo (si el an\u00E1lisis marc\u00F3 el doble)',\n      bpmDouble: 'Doble de tempo (si el an\u00E1lisis marc\u00F3 la mitad)',\n      bpmTap: 'Tap tempo: pulsa al ritmo para medir BPM',\n      bpmTapShort: 'TAP',\n      bpmTapHint: 'Sigue pulsando TAP al ritmo\u2026',\n      bpmTapSet: (n: number) => `Tempo detectado: ${n} BPM`,\n      bpmBeatSnap: 'Alinear clips a la rejilla de beats',\n      bpmGridShort: 'GRID',\n      deleteClipConfirm: '\u00BFEliminar el clip seleccionado? Esta acci\u00F3n no se puede deshacer f\u00E1cilmente.',\n      deleteClipsConfirm: (n: number) =>\n        `\u00BFEliminar ${n} clips seleccionados? Esta acci\u00F3n no se puede deshacer f\u00E1cilmente.`,\n      deleteTrackConfirm: (name: string) =>\n        `\u00BFEliminar la pista \"${name}\" y todos sus clips?`,\n      deleteConfirmTitle: 'Confirmar eliminaci\u00F3n',\n      deleteConfirmBtn: 'Eliminar',\n      shortcuts: {\n        playPause: 'Play / pausa',\n        splitClip: 'Cortar clip en el playhead',\n        delete: 'Borrar selecci\u00F3n',\n        undo: 'Deshacer',\n        redo: 'Rehacer',\n        copyPaste: 'Copiar / pegar clips',\n        nudge: 'Nudge \u00B10.1s (Shift = 1s)',\n        loop: 'Loop = selecci\u00F3n',\n        toggleRipple: 'Alternar modo ripple',\n        createRegion: 'Crear regi\u00F3n desde selecci\u00F3n',\n        zoomSelection: 'Zoom a la selecci\u00F3n',\n        showShortcuts: 'Mostrar / ocultar atajos',\n        zoomTimeline: 'Ctrl/\u2318 + rueda = zoom \u00B7 clic rueda = pan',\n      },\n      toasts: {\n        modeNormal: 'Modo normal',\n        modeRipple: 'Modo ripple',\n        regionCreated: 'Regi\u00F3n creada',\n        regionName: (n: number) => `Regi\u00F3n ${n}`,\n        projectOpened: 'Proyecto abierto',\n        projectInvalid: 'Archivo de proyecto inv\u00E1lido',\n        savedToCloud: 'Guardado en la nube \u2713',\n        cloudSaveFailed: (msg: string) => `No se pudo guardar en la nube: ${msg}`,\n        importFailed: (name: string) => `No se pudo importar ${name}`,\n      },\n    },\n    sidebar: {\n      tabLibrary: 'Biblioteca',\n      tabClip: 'Clip',\n      tabFx: 'FX',\n      tabMixer: 'Mixer',\n      tabAi: 'IA',\n      tabChat: 'Chat',\n      tabRecord: 'Rec',\n      tabLyrics: 'Letra',\n      titleInspector: 'Inspector',\n      titleFx: 'Efectos',\n      titleMixer: 'Mezclador',\n      titleAi: 'IA de audio',\n      titleChat: 'Chat de audio',\n      titleRecord: 'Grabacion',\n      titleLyrics: 'Letra',\n      titleLibrary: 'Biblioteca',\n      unpin: 'Desanclar panel',\n      pin: 'Anclar panel',\n      resetSize: 'Restablecer tamano',\n      closePanel: 'Cerrar panel',\n      resizeHeight: 'Arrastrar para cambiar alto',\n    },\n    jobsPanel: {\n      header: 'Archivos de audio',\n      hint: 'Audios generados en la nube. Clic para a\u00F1adirlos a la l\u00EDnea de tiempo.',\n      loading: 'Cargando audios\u2026',\n      empty: 'No hay archivos de audio.',\n      loadError: 'No se pudieron cargar los archivos de audio.',\n      fetchError: 'No se pudo descargar el audio.',\n      refresh: 'Actualizar',\n      addHint: 'A\u00F1adir a la l\u00EDnea de tiempo',\n      preview: 'Escuchar',\n      previewStop: 'Detener',\n      previewError: 'No se pudo reproducir el audio',\n      defaultTrackName: 'Audio',\n      addedToast: (name: string) => `A\u00F1adido: ${name}`,\n    },\n    tracks: {\n      header: 'Pistas',\n      addTrack: 'Nueva pista',\n      deleteTrack: 'Eliminar pista',\n      mute: 'Mute',\n      solo: 'Solo',\n      arm: 'Armar grabaci\u00F3n',\n      lock: 'Bloquear',\n    },\n    tools: {\n      split: 'Dividir en playhead',\n      trimStart: 'Recortar inicio al playhead',\n      trimEnd: 'Recortar fin al playhead',\n      copy: 'Copiar',\n      paste: 'Pegar',\n    },\n    clipMenu: {\n      title: 'Clip',\n      copy: 'Copiar',\n      cut: 'Cortar',\n      paste: 'Pegar',\n      createBar: 'Duplicar',\n      joinAdjacent: 'Unir con clip adyacente',\n      joinUnavailable: 'No hay un clip adyacente del mismo audio para unir',\n      joinDone: 'Clips unidos',\n      invert: 'Invertir fase',\n      bringForward: 'Traer adelante',\n      sendBackward: 'Enviar atr\u00E1s',\n      hide: 'Ocultar',\n      show: 'Mostrar',\n      lock: 'Bloquear',\n      unlock: 'Desbloquear',\n      isolate: 'Aislar voz / audio',\n      removeNoise: 'Quitar ruido de fondo',\n      delete: 'Eliminar',\n      emptyTitle: 'L\u00EDnea de tiempo',\n      importLocal: 'Subir audio local',\n      importMyFiles: 'Subir de Mis archivos',\n    },\n    inspector: {\n      emptyHint: 'Selecciona un clip para editar ganancia, fades, pitch y velocidad.',\n      selection: 'Selecci\u00F3n',\n      selectionHint: 'Duraci\u00F3n y velocidad del clip seleccionado.',\n      selStart: 'Inicio',\n      selEnd: 'Fin',\n      playbackSpeed: 'Velocidad de reproducci\u00F3n',\n      speedHalf: '0.5x',\n      speedStandard: '1x \u2014 Est\u00E1ndar',\n      speedOneHalf: '1.5x',\n      speedDouble: '2x',\n      soundLevels: 'Niveles',\n      backgroundNoise: 'Ruido de fondo',\n      removeNoise: 'Quitar ruido de fondo',\n      name: 'Nombre',\n      gain: 'Ganancia',\n      fadeIn: 'Fade in (s)',\n      fadeOut: 'Fade out (s)',\n      pitchTimeIndependent: 'Pitch / tiempo independientes',\n      speed: 'Velocidad',\n      speedStretch: 'Velocidad (stretch)',\n      pitch: 'Pitch (semitonos)',\n      crossfadeIn: 'Crossfade in (s)',\n      crossfadeOut: 'Crossfade out (s)',\n      crossfadeEqualPower: 'Crossfade equal-power',\n      crossfadeLinear: 'Crossfade linear',\n      crossfadeExponential: 'Crossfade exponential',\n      applyCrossfade: 'Crossfade selecci\u00F3n (0.25s)',\n      fadeInCurve: 'Fade in curve',\n      fadeOutCurve: 'Fade out curve',\n      curveLinear: 'Lineal',\n      curveLog: 'Log',\n      curveSCurve: 'S-curve',\n      curveExp: 'Exp',\n      mute: 'Silenciar clip',\n      invertPhase: 'Invertir fase',\n      duplicate: 'Duplicar',\n      delete: 'Eliminar',\n    },\n    fx: {\n      noTrackHint: 'Selecciona una pista para editar efectos.',\n      fxHeader: (name: string) => `FX \u2014 ${name}`,\n      addEffect: '+ Efecto',\n      noEffectsHint: 'Sin efectos. A\u00F1ade EQ, compresor, reverb\u2026',\n      savePresetTooltip: 'Guardar preset',\n      savePresetPrompt: 'Nombre del preset',\n      defaultPresetName: (type: string) => `${type} preset`,\n      loadPreset: 'Cargar preset\u2026',\n      types: {\n        eq: 'eq',\n        compressor: 'compressor',\n        gate: 'gate',\n        reverb: 'reverb',\n        delay: 'delay',\n        chorus: 'chorus',\n        distortion: 'distortion',\n        highpass: 'highpass',\n        lowpass: 'lowpass',\n        limiter: 'limiter',\n      },\n    },\n    export: {\n      title: 'Exportar audio',\n      rangeLabel: 'Rango',\n      rangeFull: 'Proyecto completo',\n      rangeSelection: 'Selecci\u00F3n de clips',\n      rangeRegion: 'Regi\u00F3n nombrada',\n      chooseRegion: 'Elegir regi\u00F3n\u2026',\n      formatLabel: 'Formato',\n      bitDepthLabel: 'Bit depth',\n      bitDepth16: '16-bit',\n      bitDepth24: '24-bit',\n      bitDepth32: '32-bit float',\n      ditherLabel: 'Dither al exportar (recomendado a 16-bit)',\n      lufsLabel: 'Normalizaci\u00F3n LUFS',\n      lufsNone: 'Sin normalizar',\n      lufsStreaming: '-14 LUFS (streaming)',\n      lufsPodcast: '-16 LUFS (podcast)',\n      stemLabel: 'Stem (opcional)',\n      fullMix: 'Mix completo',\n      bounceInPlace: 'Bounce in place',\n      exportButton: 'Exportar',\n      exporting: 'Exportando\u2026',\n      meters: {\n        shortTerm: 'Short-term:',\n        integrated: 'Integrated:',\n        truePeak: 'True-peak:',\n      },\n      toasts: {\n        ready: 'Exportaci\u00F3n lista',\n        errorExport: 'Error al exportar',\n        bounceReady: 'Bounce in place listo',\n        bounceError: 'Error en bounce',\n      },\n    },\n    lyrics: {\n      title: 'Transcript',\n      transcribeClip: 'Transcribir clip',\n      cut: 'Cortar',\n      copyText: 'Copiar texto',\n      copyLyrics: 'Copiar letra',\n      removeFillers: 'Quitar muletillas',\n      emptyHint: 'Transcribe un clip para editar por palabras (clic = seleccionar, Shift = multi).',\n      replaceSection: 'Reemplazar selecci\u00F3n (TTS)',\n      replacePlaceholder: 'Nueva frase\u2026',\n      replaceWithVoice: 'Reemplazar con voz',\n      markersSection: 'Marcadores',\n      markerAddHere: '+ Aqu\u00ED',\n      markerName: (n: number) => `Marcador ${n}`,\n      toasts: {\n        selectVoiceClip: 'Selecciona un clip de voz primero',\n        wordsTranscribed: (n: number) => `${n} palabras transcritas`,\n        transcribeError: 'Error al transcribir',\n        selectWordsWriteReplace: 'Selecciona palabras y escribe el reemplazo',\n        replacedTts: 'Frase reemplazada con TTS',\n        ttsError: 'Error TTS',\n        nothingToCopy: 'No hay texto para copiar',\n        selectionCopied: 'Selecci\u00F3n copiada',\n        transcriptCopied: 'Texto copiado',\n        copyError: 'No se pudo copiar',\n      },\n    },\n    chat: {\n      welcome: 'Soy tu copiloto de audio. Prueba: \"genera una base lo-fi de 30 segundos a 80 BPM\" o \"sube 3 dB la pista 1\".',\n      inputPlaceholder: 'Orden en lenguaje natural\u2026',\n      confirmAction: (name: string) => `Confirmar ${name}`,\n      undoAction: 'Deshacer esta acci\u00F3n',\n      toasts: {\n        done: 'Hecho.',\n        agentError: 'Error del agente',\n        error: 'Error',\n      },\n    },\n    ai: {\n      healthOk: 'API audio: OK',\n      healthDown: 'API audio no disponible',\n      healthChecking: 'Comprobando API\u2026',\n      endpointHint: {\n        music: 'Genera una pista musical a partir de un prompt.',\n        extend: 'Extiende la m\u00FAsica actual de forma fluida.',\n        sfx: 'Genera un efecto de sonido corto.',\n        tts: 'Convierte texto en voz con la voz elegida.',\n        voice: 'Cambia la voz del clip seleccionado.',\n        isolate: 'A\u00EDsla la voz u otras capas del clip.',\n        stems: 'Separa el clip en stems (voz, bater\u00EDa, bajo\u2026).',\n        automix: 'Ajusta EQ y din\u00E1mica de las pistas autom\u00E1ticamente.',\n        cleanup: 'Limpia podcast: a\u00EDsla voz y recorta silencios.',\n        lyrics: 'Transcribe el audio a letra / subt\u00EDtulos.',\n      },\n      sectionGenerate: 'Generar',\n      sectionGenerateHint: 'M\u00FAsica, SFX y voz desde cero.',\n      sectionEdit: 'Editar clip',\n      sectionEditHint: 'Transforma el clip seleccionado en la l\u00EDnea de tiempo.',\n      sectionMix: 'Mezcla y limpieza',\n      sectionMixHint: 'Niveles autom\u00E1ticos y limpieza de podcast.',\n      catalogHint: 'Elige una herramienta AI. La acci\u00F3n se aplica al playhead o al clip seleccionado.',\n      openAgent: 'Abrir agente',\n      chooseAnotherTool: 'Elegir otra herramienta',\n      showMoreTools: 'M\u00E1s opciones',\n      showLessTools: 'Mostrar menos',\n      playVoicePreview: 'Reproducir voz',\n      pauseVoicePreview: 'Pausar voz',\n      tab: {\n        music: 'M\u00FAsica',\n        extend: 'Extend',\n        sfx: 'SFX',\n        tts: 'Voz',\n        voice: 'Cambiar',\n        isolate: 'Aislar',\n        stems: 'Stems',\n        automix: 'Auto-mix',\n        cleanup: 'Podcast',\n        lyrics: 'Letra',\n      },\n      placeholders: {\n        music: 'Describe la m\u00FAsica (ej. lo-fi chill a 80 BPM)',\n        extend: 'C\u00F3mo continuar (ej. mismo groove, m\u00E1s energ\u00EDa)',\n        sfx: 'Describe el efecto (ej. whoosh cinematogr\u00E1fico)',\n        tts: 'Texto para narrar\u2026',\n      },\n      durationLabel: 'Duraci\u00F3n (s)',\n      songStructure: 'Estructura de canci\u00F3n (marcadores)',\n      songStructureClear: 'Quitar estructura',\n      songStructureToast: 'Marcadores Intro/Verso/Estribillo creados',\n      songStructureClearedToast: 'Marcadores de estructura eliminados',\n      actionLabel: {\n        applyAutomix: 'Aplicar auto-mezcla',\n        cleanupPodcast: 'Limpiar podcast',\n        separateStems: 'Separar stems',\n        extend: 'Extender',\n        generate: 'Generar',\n      },\n      selectedClip: (name: string) => `Clip seleccionado: ${name || 'ninguno'}`,\n      hints: {\n        automix: 'Ajusta niveles, pan y a\u00F1ade highpass/compresor en pistas de voz.',\n        cleanup: 'Pipeline: isolate (denoise) + highpass + compresor en una pista nueva.',\n        stems: 'Separa vocals / drums / bass / other en pistas nuevas.',\n      },\n      generating: 'Generando\u2026',\n      toasts: {\n        autoMix: 'Auto-mezcla por loudness aplicada',\n        podcastCleanup: 'Limpieza de podcast lista',\n        musicGenerated: 'M\u00FAsica generada',\n        extendGenerated: 'Extensi\u00F3n generada',\n        sfxGenerated: 'SFX generado',\n        voiceoverGenerated: 'Voiceover generado',\n        voiceChanged: 'Voz convertida',\n        audioIsolated: 'Audio aislado',\n        stemsSeparated: 'Stems separados',\n        transcriptReady: 'Transcripci\u00F3n lista \u2014 edita en panel Letra',\n        noVoiceClip: 'Selecciona un clip de voz',\n        noAudioClip: 'Selecciona un clip con audio',\n        agentError: 'Error de IA',\n        musicPromptTooLong:\n          'El backend expandi\u00F3 el prompt de m\u00FAsica con Brand Memory (l\u00EDmite ElevenLabs). El editor solo manda prompt + brand_id \u2014 escal\u00E1 al PM si sigue pasando.',\n      },\n      status: {\n        isolating: 'Aislando / denoise\u2026',\n        removingSilence: 'Quitando silencios\u2026',\n        separatingStems: 'Separando stems\u2026',\n      },\n      trackNames: {\n        aiTrack: 'AI',\n        podcastTrack: 'Podcast limpio',\n        lyricsTrack: 'Letra',\n      },\n    },\n    timeline: {\n      ripple: 'RIPPLE',\n      clipFallback: 'Clip',\n    },\n    automation: {\n      noTrackHint: 'Selecciona una pista.',\n      header: 'Automatizaci\u00F3n',\n      property: 'Propiedad',\n      propertyVolume: 'Volumen',\n      propertyPan: 'Pan',\n      addPoint: '+ Punto en playhead',\n      noPointsHint: 'Sin puntos. A\u00F1ade keyframes.',\n    },\n    mixer: {\n      deleteBus: 'Eliminar bus',\n    },\n    recording: {\n      armedTrack: (name: string) => `Pista armada: ${name || 'ninguna'}`,\n      monitorLabel: 'Monitorizaci\u00F3n (cuidado con feedback)',\n      punchLabel: 'Punch in/out (usa el loop)',\n      punchStatus: (start: string, end: string) => `Punch ${start}s \u2013 ${end}s`,\n      recordButton: 'Grabar',\n      stopButton: 'Detener',\n      takeLanesHeader: 'Take lanes (comping)',\n      loopHint: (start: string, end: string) => `Loop activo: clic en toma = comp solo en ${start}\u2013${end}s. Shift+clic = toda la pista.`,\n      groupLabel: (id: string) => `Grupo ${id.slice(-8)}`,\n      takeLabel: (lane: number, name: string, active: boolean) => `Lane ${lane}: ${name}${active ? ' (activa)' : ''}`,\n      takeFileName: (n: number) => `Toma ${n}.webm`,\n      takeNameFallback: (n: number) => `Toma ${n}`,\n      toasts: {\n        noArmedTrack: 'Crea o arma una pista primero',\n        micError: 'No se pudo acceder al micr\u00F3fono',\n        takeRecorded: (n: number) => `Toma ${n} grabada`,\n        takeActiveInLoop: (n: number) => `Toma ${n} activa en el loop`,\n        saveError: 'Error al guardar grabaci\u00F3n',\n      },\n    },\n  },\n  text: {\n    editor: {\n      noDocument: 'No hay documento de texto abierto',\n      newDocument: 'Nuevo documento',\n      toasts: {\n        docxImported: 'DOCX importado',\n        markdownImported: 'Markdown importado',\n        projectOpened: 'Proyecto abierto',\n        projectInvalid: 'Archivo de proyecto invalido',\n        savedToCloud: 'Guardado en la nube \u2713',\n        cloudSaveFailed: (msg: string) => `No se pudo guardar en la nube: ${msg}`,\n      },\n    },\n    sidebar: {\n      tabOutline: 'Esquema',\n      tabAi: 'IA',\n      tabChat: 'Chat',\n      tabSuggestions: 'Sugerencias',\n      tabVariants: 'Canales',\n      tabVersions: 'Versiones',\n      tabBrand: 'Marca',\n      tabComments: 'Notas',\n      tabClaims: 'Afirmaciones',\n      tabSeo: 'SEO',\n      titleOutline: 'Esquema',\n      titleAi: 'IA de texto',\n      titleChat: 'Chat',\n      titleSuggestions: 'Sugerencias',\n      titleVariants: 'Variantes',\n      titleVersions: 'Versiones',\n      titleBrand: 'Voz de marca',\n      titleComments: 'Comentarios',\n      titleClaims: 'Afirmaciones',\n      titleSeo: 'SEO',\n      unpin: 'Desanclar panel',\n      pin: 'Anclar panel',\n      resetSize: 'Restablecer tama\u00F1o',\n      closePanel: 'Cerrar panel',\n      resizeHeight: 'Arrastrar para cambiar alto',\n    },\n    jobsPanel: {\n      header: 'Archivos de texto e imagen',\n      hint: 'Im\u00E1genes y textos de la marca (an\u00E1lisis / guion). Clic para insertar en el documento.',\n      loading: 'Cargando archivos\u2026',\n      empty: 'No hay archivos de imagen, an\u00E1lisis o guion.',\n      emptyFilter: 'No hay items de este tipo.',\n      loadError: 'No se pudieron cargar los archivos.',\n      insertError: 'No se pudo insertar en el documento.',\n      refresh: 'Actualizar',\n      noEditor: 'Abre el documento para insertar contenido.',\n      imageAdded: 'Imagen insertada',\n      textImported: 'Texto importado',\n      addImageHint: 'Insertar imagen',\n      addTextHint: 'Importar texto',\n      filterAria: 'Filtrar archivos',\n      filterAll: 'Todo',\n      filterImage: 'Imagen',\n      filterAnalysis: 'Analysis',\n      filterScript: 'Script',\n      filterText: 'Texto',\n      kindImage: 'Imagen',\n      kindAnalysis: 'Analysis',\n      kindScript: 'Script',\n      kindText: 'Texto',\n      importAnalysisHeading: 'Analysis',\n      importScriptHeading: 'Script',\n      importTextHeading: 'Texto importado',\n    },\n    pageToolbar: {\n      imageButtonTitle: 'Insertar imagen',\n      imageTooltip: 'Imagen',\n      marginsButtonTitle: 'M\u00E1rgenes y p\u00E1gina',\n      marginsTooltip: 'M\u00E1rgenes',\n      guidesTitle: 'Mostrar/ocultar gu\u00EDas de margen',\n      guidesTooltip: 'Gu\u00EDas',\n      pageSetupTitle: 'Configuraci\u00F3n de p\u00E1gina',\n      pageSizeLabel: 'Tama\u00F1o de p\u00E1gina',\n      orientationPortrait: 'Vertical',\n      orientationLandscape: 'Horizontal',\n      marginTop: 'Superior',\n      marginBottom: 'Inferior',\n      marginLeft: 'Izquierda',\n      marginRight: 'Derecha',\n      marginUnit: (label: string) => `${label} (mm)`,\n      reset: 'Restablecer',\n      apply: 'Aplicar',\n    },\n    contextMenu: {\n      title: 'Edici\u00F3n',\n      undo: 'Deshacer',\n      redo: 'Rehacer',\n      cut: 'Cortar',\n      copy: 'Copiar',\n      paste: 'Pegar',\n      bold: 'Negrita',\n      italic: 'Cursiva',\n      highlight: 'Resaltar',\n      link: 'Enlace',\n      heading2: 'T\u00EDtulo H2',\n      paragraph: 'P\u00E1rrafo',\n      bulletList: 'Lista con vi\u00F1etas',\n      orderedList: 'Lista numerada',\n      table: 'Insertar tabla',\n      alignLeft: 'Alinear izquierda',\n      alignCenter: 'Centrar',\n      alignRight: 'Alinear derecha',\n      comment: 'Comentar selecci\u00F3n',\n    },\n    canvas: {\n      loading: 'Cargando editor\u2026',\n      fontLabel: 'Fuente',\n      fontSizeDown: 'Reducir tama\u00F1o',\n      fontSize: 'Tama\u00F1o de fuente',\n      fontSizeUp: 'Aumentar tama\u00F1o',\n      readAloud: 'Leer',\n      readAloudTitle: 'Leer en voz alta',\n      readAloudStop: 'Detener lectura',\n      readAloudUnavailable: 'Lectura en voz no disponible en este navegador',\n      slashHint: '/ comandos',\n      paletteHint: (shortcut: string) => `${shortcut} palette`,\n      textColor: 'Color de texto',\n      highlightColor: 'Color de resaltador',\n      bold: 'Negrita',\n      italic: 'Cursiva',\n      strike: 'Tachado',\n      highlight: 'Resaltador',\n      h1: 'T\u00EDtulo H1',\n      h2: 'T\u00EDtulo H2',\n      h3: 'T\u00EDtulo H3',\n      h4: 'T\u00EDtulo H4',\n      h5: 'T\u00EDtulo H5',\n      paragraph: 'P\u00E1rrafo',\n      bulletList: 'Lista con vi\u00F1etas',\n      orderedList: 'Lista numerada',\n      indent: 'Aumentar sangr\u00EDa',\n      outdent: 'Reducir sangr\u00EDa',\n      alignLeft: 'Alinear izquierda',\n      alignCenter: 'Centrar',\n      alignRight: 'Alinear derecha',\n      alignJustify: 'Justificar',\n      clearAlign: 'Quitar alineaci\u00F3n',\n      blockquote: 'Cita',\n      link: 'Agregar enlace',\n      linkPrompt: 'URL del enlace',\n      linkPlaceholder: 'ejemplo.com',\n      linkApply: 'Aplicar',\n      linkRemove: 'Quitar enlace',\n      linkOpenHint: 'Ctrl+clic (\u2318+clic en Mac) para abrir el enlace',\n      table: 'Tabla',\n      tableInsert: 'Nueva tabla',\n      tableEdit: 'Editar tabla',\n      tableRows: 'Filas',\n      tableCols: 'Columnas',\n      tableInsertAction: 'Insertar',\n      tableInsertFailed: 'No se pudo insertar la tabla aqu\u00ED',\n      tableAddRow: 'Fila',\n      tableDelRow: 'Fila',\n      tableAddCol: 'Col',\n      tableDelCol: 'Col',\n      tableDelete: 'Eliminar tabla',\n      callout: 'Destacado',\n      calloutDefault: 'Nota destacada',\n      calloutSlashHint: 'Bloque destacado',\n      superscript: 'Super\u00EDndice',\n      comment: 'Comentar',\n      commentPrompt: 'Nota del comentario:',\n      footnote: 'Nota al pie',\n      footnotePrompt: 'Texto de la nota al pie:',\n      footnoteDefault: 'Nota',\n      suggestionReady: 'Sugerencia lista',\n      selectTextFirst: 'Selecciona texto primero',\n      imageWidth: 'Ancho imagen',\n      imageNarrower: 'M\u00E1s estrecha',\n      imageWider: 'M\u00E1s ancha',\n    },\n    comments: {\n      title: 'Comentarios',\n      openSection: 'Abiertos',\n      resolvedSection: 'Resueltos',\n      openCount: (n: number) => `Abiertos (${n})`,\n      placeholder: 'Escribe tu nota\u2026',\n      addSelection: 'Guardar nota',\n      anchorHint: 'Con texto seleccionado se ancla al documento (Ir). Sin selecci\u00F3n se guarda solo como nota.',\n      empty: 'A\u00F1ade una nota. Selecciona texto antes para anclarla al documento.',\n      jump: 'Ir',\n      resolve: 'Resolver',\n      reopen: 'Reabrir',\n      remove: 'Borrar',\n      toasts: {\n        selectText: 'Selecciona texto para comentar',\n        writeNote: 'Escribe una nota',\n        anchored: 'Comentario anclado',\n        noteSaved: 'Nota guardada',\n        markMissing: 'Marca no encontrada en el documento',\n      },\n      popoverTitle: 'Nuevo comentario',\n      popoverSave: 'Anclar',\n      popoverCancel: 'Cancelar',\n      selectionChip: 'Comentar',\n    },\n    suggestions: {\n      pendingCount: (n: number) => `Pendientes (${n})`,\n      acceptAll: 'Todos nuevos',\n      rejectAll: 'Todos anteriores',\n      filterLabel: 'Filtro',\n      filterAll: 'Todas',\n      rationales: 'Justificaciones',\n      empty:\n        'Cola de revisi\u00F3n de la IA: elige Antes o Despu\u00E9s en cada sugerencia para quedarte con una versi\u00F3n.',\n      chooseHint: 'Elige con cu\u00E1l quedarte',\n      before: 'Antes',\n      after: 'Despu\u00E9s',\n      emptyOriginal: '(documento vac\u00EDo / al final)',\n      accept: 'Aceptar',\n      reject: 'Rechazar',\n      kinds: {\n        rewrite: 'Reescritura',\n        tighten: 'Condensar',\n        expand: 'Expandir',\n        elevate: 'Elevar',\n        localize: 'Localizar',\n        tone: 'Tono',\n        brand: 'Marca',\n        claim: 'Afirmaci\u00F3n',\n        other: 'Otro',\n      },\n      toasts: {\n        accepted: 'Versi\u00F3n nueva aplicada',\n        rejected: 'Se mantuvo la versi\u00F3n anterior',\n        allAccepted: 'Todas las versiones nuevas aplicadas',\n      },\n    },\n    variants: {\n      generate: 'Generar',\n      regenerateStale: (n: number) => `Regenerar desactualizadas (${n})`,\n      staleRegen: 'Desactualizada \u00B7 regenerar',\n      addToDocument: 'Agregar al documento',\n      empty:\n        'Genera textos para Instagram, LinkedIn, X, email, anuncios y YouTube desde el documento. Al editar el doc se marcan como desactualizadas.',\n      chars: (n: number) => `${n} caracteres`,\n      toasts: {\n        writeFirst: 'Escribe contenido antes de generar variantes',\n        generated: 'Variantes generadas',\n        staleRegenerated: 'Variantes desactualizadas regeneradas',\n        addedToDocument: 'Variante agregada al documento',\n        noEditor: 'Abre el documento para insertar contenido',\n        error: 'Error al generar variantes',\n      },\n      channels: {\n        instagram: 'Instagram',\n        linkedin: 'LinkedIn',\n        x: 'X / Twitter',\n        email: 'Email',\n        ad: 'Anuncio',\n        youtube: 'YouTube',\n      },\n    },\n    versions: {\n      namePlaceholder: 'Nombre (opcional)',\n      save: 'Guardar',\n      compare: 'Comparar',\n      compareA: 'A\u2026',\n      compareB: 'B\u2026',\n      current: 'Actual',\n      restoreSection: 'Restaurar secci\u00F3n',\n      sectionPlaceholder: 'Texto exacto del H2\u2026',\n      empty: 'Snapshots nombrados del documento (independientes del undo de TipTap).',\n      words: (n: number) => `${n} palabras`,\n      restoreAll: 'Todo',\n      restoreSec: 'Secci\u00F3n',\n      restoreSelection: 'Selecci\u00F3n',\n      remove: 'Borrar',\n      toasts: {\n        needHeading: 'Indica el heading a restaurar',\n        selectText: 'Selecciona texto en el documento',\n        emptySnapshot: 'Snapshot vac\u00EDo',\n        selectionRestored: 'Selecci\u00F3n restaurada desde snapshot',\n      },\n    },\n    brandPanel: {\n      rescore: 'Volver a puntuar',\n      scoreLabel: (n: number) => `Puntuaci\u00F3n ${n}`,\n      preferredTerms: 'T\u00E9rminos preferidos',\n      forbiddenTerms: 'T\u00E9rminos prohibidos',\n      approvedCtas: 'Llamadas a la acci\u00F3n aprobadas',\n      legalDisclaimers: 'Avisos legales',\n      textBank: 'Banco de texto (muestras de voz)',\n      glossary: 'Glosario',\n      glossaryTerm: 'T\u00E9rmino',\n      glossaryPreferred: 'Preferido',\n      addGlossary: 'A\u00F1adir',\n      channelTones: 'Tono por canal',\n      toneDefault: '(predeterminado)',\n      onePerLine: 'Uno por l\u00EDnea',\n      samplesHint: 'Una muestra por l\u00EDnea (ajuste de voz)',\n      forbiddenInDoc: (t: string) => `Prohibido en el documento: ${t}`,\n      missingPreferred: (t: string) => `Falta preferido: ${t}`,\n      toasts: {\n        scored: (n: number) => `Puntuaci\u00F3n de marca: ${n}`,\n        error: 'Error',\n      },\n    },\n    claims: {\n      count: (n: number) => `Afirmaciones (${n})`,\n      analyze: 'Analizar con IA',\n      markSelection: 'Marcar selecci\u00F3n',\n      empty: 'Afirmaciones que requieren fuente o verificaci\u00F3n.',\n      remove: 'Borrar',\n      claimNeedsCitation: 'Afirmaci\u00F3n: necesita cita',\n      statuses: {\n        unverified: 'Sin verificar',\n        needs_citation: 'Necesita cita',\n        ok: 'OK',\n        flagged: 'Marcado',\n      },\n      toasts: {\n        selectClaim: 'Selecciona la afirmaci\u00F3n',\n        marked: 'Afirmaci\u00F3n marcada',\n        detected: (n: number) => `${n} afirmaciones detectadas`,\n        error: 'Error',\n      },\n    },\n    seo: {\n      titleLabel: 'Title',\n      descriptionLabel: 'Meta description',\n      slugLabel: 'Slug',\n      autoSlug: 'Auto',\n      focusKeyword: 'Focus keyword',\n      keywords: 'Keywords (coma)',\n      serpPreview: 'SERP preview',\n      titleFallback: 'Title',\n      descriptionFallback: 'Meta description\u2026',\n      checklist: {\n        titleRange: (n: number) => `Title ${n}/30-60`,\n        descRange: (n: number) => `Meta description ${n}/120-160`,\n        slugDefined: 'Slug definido',\n        focusInBody: 'Focus keyword en cuerpo',\n        focusOptional: 'Focus keyword (opcional)',\n        channelLength: (ch: string) => `Longitud canal ${ch}`,\n        charLimit: (ch: string, cur: number, lim: number) =>\n          `L\u00EDmite chars ${ch}: ${cur}/${lim}`,\n      },\n    },\n    bottomBar: {\n      pageSetup: 'P\u00E1gina',\n      insertImage: 'Imagen',\n      marginGuides: 'Gu\u00EDas',\n    },\n    metrics: {\n      words: 'palabras',\n      chars: 'chars',\n      flesch: 'Flesch',\n      clarity: 'Claridad',\n      jargon: 'Jerga',\n      forbidden: 'Prohibidos',\n      inclusive: 'Inclusivo',\n      brand: 'Marca',\n      inclusiveTips: {\n        users: 'Preferir \u00ABlas personas usuarias\u00BB o una audiencia concreta',\n        genericMasculine: 'Revisar lenguaje gen\u00E9rico masculino',\n        guys: 'Preferir \u00ABtodos\u00BB / \u00ABel equipo\u00BB',\n        ableist: 'Evitar lenguaje capacitista',\n        mentalHealth: 'Evitar estereotipos de salud mental',\n      },\n    },\n    outline: {\n      title: 'Esquema',\n      empty: 'Agrega t\u00EDtulos (H1\u2013H4) en el documento para navegar el esquema.',\n    },\n    workflow: {\n      tooltip: 'Estado del documento',\n      header: 'Estado del documento',\n      options: {\n        draft: { label: 'Borrador', description: 'El documento se est\u00E1 escribiendo' },\n        review: { label: 'Revisi\u00F3n', description: 'Listo para revisi\u00F3n por un par' },\n        approved: { label: 'Aprobado', description: 'Validado por un revisor' },\n        published: { label: 'Publicado', description: 'Exportado y publicado' },\n      },\n      workflowOptionLabel: (s: string) => `Workflow \u2192 ${s}`,\n    },\n    chat: {\n      planModeLabel: 'Modo plan',\n      planModeHint:\n        'Con plan activo, el primer mensaje solo propone pasos (sin tools). Luego pide ejecutar el plan.',\n      emptyHint:\n        'Prueba: \"escribe un p\u00E1rrafo sobre mi marca\", \"genera un outline\" o \"reescribe m\u00E1s persuasivo\". Con Modo plan, di \"ejecuta el plan\" para aplicar tools.',\n      inputPlaceholder: 'Habla con el copiloto\u2026',\n      planReadyHint: 'Plan listo. Escribe \"ejecuta el plan\" o un siguiente mensaje para aplicar tools.',\n      confirmAction: (label: string) => `Confirmar: ${label}`,\n      error: 'No se pudo completar la acci\u00F3n del copiloto.',\n      tools: {\n        generate_content: 'Generar texto',\n        rewrite_selection: 'Reescribir texto',\n        change_tone: 'Cambiar tono',\n        expand_section: 'Expandir secci\u00F3n',\n        tighten: 'Condensar texto',\n        insert_section: 'Insertar secci\u00F3n',\n        generate_variants: 'Generar variantes',\n        translate_document: 'Traducir',\n        apply_brand_voice: 'Voz de marca',\n        create_outline: 'Crear esquema',\n        summarize: 'Resumir',\n        export_document: 'Exportar',\n        handoff_to_video: 'Pasar a video',\n        handoff_to_audio: 'Pasar a audio',\n        section_op: 'Operaci\u00F3n de secci\u00F3n',\n        analyze_claims: 'Analizar afirmaciones',\n        compliance_pass: 'Revisi\u00F3n legal',\n        make_clip_script: 'Guion corto',\n      },\n      errors: {\n        auth: 'Tu sesi\u00F3n expir\u00F3. Vuelve a iniciar sesi\u00F3n.',\n        unavailable: 'Esta funci\u00F3n a\u00FAn no est\u00E1 disponible en el backend.',\n        textRequired:\n          'Necesito texto del documento o una selecci\u00F3n. Escribe algo o p\u00EDdeme generar contenido primero.',\n        promptRequired: 'Falta la instrucci\u00F3n o el tema para generar el texto.',\n        network: 'Error de red. Revisa tu conexi\u00F3n e int\u00E9ntalo de nuevo.',\n        generic: 'No se pudo completar la acci\u00F3n. Int\u00E9ntalo de nuevo.',\n        styleUnsupported:\n          'El chat a\u00FAn no puede cambiar colores o tipograf\u00EDa. Usa el formato del editor, o p\u00EDdeme reescribir el contenido.',\n        unknownTool: (name: string) => `Acci\u00F3n no reconocida: ${name}`,\n      },\n      summaries: {\n        contentInserted: 'Texto generado y agregado al documento.',\n        contentSuggested: 'Texto generado: rev\u00EDsalo en Sugerencias.',\n        rewrite: 'Sugerencia de reescritura lista en Sugerencias.',\n        tone: (tone: string) => `Tono actualizado a \u00AB${tone}\u00BB (sugerencia creada).`,\n        expand: (heading: string) => `Expansi\u00F3n sugerida para \u00AB${heading}\u00BB.`,\n        tighten: 'Sugerencia de condensaci\u00F3n lista.',\n        sectionInserted: (heading: string) => `Secci\u00F3n insertada: \u00AB${heading}\u00BB.`,\n        variants: (n: number) => `${n} variantes generadas (panel Variantes).`,\n        translate: (lang: string) => `Traducci\u00F3n sugerida (${lang}).`,\n        brandScore: (n: number) => `Puntuaci\u00F3n de voz de marca: ${n}.`,\n        outline: (n: number) => `Esquema aplicado con ${n} secciones.`,\n        summarize: 'Resumen sugerido en Sugerencias.',\n        exportOpen: 'Modal de exportaci\u00F3n abierto.',\n        handoffVideo: 'Handoff a video listo en Exportar.',\n        handoffAudio: 'Handoff a audio listo en Exportar.',\n        handoffVideoToast: 'Abre Exportar \u2192 Handoff a video.',\n        handoffAudioToast: 'Abre Exportar \u2192 Handoff a audio.',\n        sectionOp: (op: string) => `Operaci\u00F3n \u00AB${op}\u00BB sugerida.`,\n        claims: (n: number) => `${n} afirmaciones detectadas (panel Afirmaciones).`,\n        clip: (platform: string) => `Guion corto para ${platform} guardado en Variantes.`,\n      },\n    },\n    commandPalette: {\n      placeholder: 'Buscar comando\u2026',\n      emptyResult: 'Sin resultados',\n      groupNavigation: 'Navegaci\u00F3n',\n      groupFormat: 'Formato',\n      groupFile: 'Archivo',\n      groupWorkflow: 'Workflow',\n      commands: {\n        tabAi: 'Ir a panel IA',\n        tabChat: 'Ir a Chat agente',\n        tabSuggestions: 'Ir a Sugerencias',\n        tabBrand: 'Ir a Brand OS',\n        tabSeo: 'Ir a SEO',\n        tabComments: 'Ir a Comentarios',\n        tabClaims: 'Ir a Afirmaciones',\n        fmtH2: 'Formato: Heading 2',\n        fmtTable: 'Insertar tabla',\n        fmtCallout: 'Insertar destacado',\n        export: 'Abrir exportar',\n        snap: 'Crear snapshot',\n      },\n    },\n    export: {\n      title: 'Exportar / Handoff',\n      formats: {\n        md: 'Markdown',\n        html: 'HTML limpio',\n        mdx: 'MDX (CMS)',\n        txt: 'Texto',\n        json: 'JSON',\n        pdf: 'PDF',\n        docx: 'DOCX',\n      },\n      mdxHint: 'MDX/HTML son para pegar en CMS (sin publish OAuth).',\n      complianceLabel: 'Bloquear export si falla compliance',\n      bridgesHeader: 'Puentes',\n      handoffVideo: 'Handoff a Video (guion timed)',\n      handoffAudio: 'Handoff a Audio (TTS por H2)',\n      fallbackName: 'Documento',\n      fallbackFilename: 'doc',\n      toasts: {\n        noTextTrack: 'No hay pista de texto en el proyecto de video',\n        docEmpty: 'Documento vac\u00EDo',\n        noTtsContent: 'No hay contenido para TTS',\n        ttsError: 'Error TTS',\n        handoffVideoDone: (n: number) => `Handoff: ${n} clips con timing (abre Video)`,\n        handoffAudioDone: 'Handoff a audio listo (TTS por secci\u00F3n)',\n        genericError: 'Error al exportar',\n      },\n    },\n    ai: {\n      title: 'IA Texto',\n      healthOk: 'API texto: OK',\n      healthDown: 'API texto no disponible',\n      healthChecking: 'Comprobando API\u2026',\n      catalogHint:\n        'Elige una herramienta. El texto generado se muestra en un modal para insertar o revisar.',\n      chooseAnotherTool: 'Elegir otra herramienta',\n      showMoreTools: 'M\u00E1s opciones',\n      showLessTools: 'Mostrar menos',\n      endpointHint: {\n        generate: 'Genera texto nuevo a partir de una instrucci\u00F3n.',\n        rewrite: 'Reescribe la selecci\u00F3n o el documento con una instrucci\u00F3n.',\n        ops: 'Ajusta un tramo: condensar, elevar, localizar o expandir.',\n        outline: 'Crea un esquema de secciones a partir de un tema.',\n        brand: 'Punt\u00FAa alineaci\u00F3n de voz de marca y sugiere mejoras.',\n        ab: 'Compara ganchos o variantes A/B por claridad y llamada a la acci\u00F3n.',\n        compliance: 'Revisa riesgos legales y avisos del documento.',\n        voice: 'Reescribe para acercar el tono a muestras de voz.',\n        clip: 'Genera un guion corto para video vertical y lo guarda en Variantes.',\n        transcript: 'Transcribe audio o video a p\u00E1rrafos con marcas de tiempo.',\n        variants: 'Variantes por canal',\n        claims: 'An\u00E1lisis de afirmaciones',\n      },\n      toneLabel: 'Tono',\n      industryLabel: 'Industria',\n      industryOtherPlaceholder: 'Escribe la industria\u2026',\n      industryOtherRequired: 'Escribe el nombre de la industria',\n      opLabel: 'Operaci\u00F3n',\n      agentLink: 'Agente',\n      clipHint: 'Genera un guion corto para video vertical y lo guarda en Variantes.',\n      clipVariantTitle: 'Guion para video corto',\n      clipPrompt: (text: string) =>\n        `Guion corto para video vertical (gancho + 3 momentos + llamada a la acci\u00F3n), m\u00E1ximo 120 palabras:\\n\\n${text}`,\n      brandAlignInstruction: (notes: string) => `Alinea la voz de marca. ${notes}`,\n      brandScoreRationale: (n: number) => `Puntuaci\u00F3n ${n}`,\n      outlineIntent: (intent: string) => `[Intenci\u00F3n: ${intent}]`,\n      rewriteDefault: 'Mejora claridad y ritmo',\n      tab: {\n        generate: 'Generar',\n        rewrite: 'Reescribir',\n        ops: 'Operaciones',\n        outline: 'Esquema',\n        brand: 'Marca',\n        ab: 'A/B',\n        compliance: 'Legal',\n        voice: 'Voz',\n        clip: 'Guion corto',\n        transcript: 'Audio',\n        variants: 'Variantes',\n        claims: 'Afirmaciones',\n      },\n      placeholders: {\n        prompt: 'Describe lo que quieres generar\u2026',\n        outline: 'Tema del documento\u2026',\n        rewriteInstruction: 'Instrucci\u00F3n de reescritura\u2026',\n        voiceSamples: 'Muestras de voz (opcional; separa con l\u00EDnea en blanco)\u2026',\n        brandText: 'Texto a analizar\u2026',\n        preferredTerms: 'T\u00E9rminos preferidos (uno por l\u00EDnea)\u2026',\n        forbiddenTerms: 'T\u00E9rminos prohibidos (uno por l\u00EDnea)\u2026',\n      },\n      hookLabel: (letter: string) => `Gancho ${letter}`,\n      hookPlaceholder: (letter: string) => `Escribe el gancho ${letter}\u2026`,\n      addHook: 'A\u00F1adir otro gancho',\n      removeHook: 'Quitar gancho',\n      abScoreClarity: 'Claridad',\n      abScoreCta: 'Llamada a la acci\u00F3n',\n      abScoreBrand: 'Marca',\n      complianceSeverity: {\n        info: 'Informaci\u00F3n',\n        warn: 'Aviso',\n        block: 'Bloqueo',\n      },\n      complianceSummaryOk: 'Revisi\u00F3n correcta: sin avisos graves ni bloqueos.',\n      complianceSummaryWarn: 'Revisi\u00F3n con avisos: conviene corregir antes de publicar.',\n      complianceSummaryBlock: 'Revisi\u00F3n con bloqueos: corrige estos puntos antes de exportar.',\n      complianceEmpty: 'Sin hallazgos. El texto pasa la revisi\u00F3n para esta industria.',\n      complianceResultsTitle: 'Resultado de la revisi\u00F3n',\n      brandUseDoc: 'Documento completo',\n      brandUseSelection: 'Selecci\u00F3n',\n      brandSelectHint: 'Selecciona texto en el documento para usar solo esa parte.',\n      textScopeLabel: 'Texto a enviar',\n      brandPreferredLabel: 'T\u00E9rminos preferidos',\n      brandForbiddenLabel: 'T\u00E9rminos prohibidos',\n      brandScoreLabel: 'Puntuaci\u00F3n actual:',\n      resultInsert: 'Aplicar (reemplazar)',\n      resultToSuggestions: 'Enviar a sugerencias',\n      resultDiscard: 'Descartar',\n      tones: {\n        neutral: 'Neutro',\n        formal: 'Formal',\n        casual: 'Informal',\n        persuasive: 'Persuasivo',\n        technical: 'T\u00E9cnico',\n        friendly: 'Amigable',\n      },\n      ops: {\n        tighten: 'Condensar',\n        elevate: 'Elevar',\n        localize: 'Localizar',\n        expand: 'Expandir',\n      },\n      industries: {\n        general: 'General',\n        fintech: 'Finanzas digitales',\n        health: 'Salud',\n        other: 'Otro',\n      },\n      rationales: {\n        generation: 'Generaci\u00F3n',\n        voiceMatch: 'Ajuste de voz',\n      },\n      voiceWithBank: (n: number) =>\n        `Usando ${n} muestra(s) del banco de texto (Marca) si dejas esto vac\u00EDo.`,\n      voiceNoBank: 'Sin banco de texto en Marca \u2014 pega muestras abajo.',\n      audioUploadLabel: 'Subir audio/video',\n      audioTranscribing: 'Transcribiendo audio\u2026',\n      audioTranscribingHint: 'Esto puede tardar unos segundos seg\u00FAn la duraci\u00F3n del archivo.',\n      runButton: 'Ejecutar',\n      toasts: {\n        generated: 'Texto generado',\n        inserted: 'Texto aplicado (reemplaz\u00F3 el anterior)',\n        sentToSuggestions: 'Enviado a sugerencias',\n        rewriteReady: 'Reescritura lista',\n        opReady: (op: string) => `Operaci\u00F3n \u00AB${op}\u00BB lista`,\n        outlineApplied: 'Esquema aplicado',\n        brandScore: (n: number) => `Puntuaci\u00F3n de marca: ${n}`,\n        abScored: 'A/B puntuado',\n        complianceOk: 'Revisi\u00F3n legal correcta',\n        complianceWarn: 'Revisi\u00F3n legal con avisos',\n        complianceBlock: 'Revisi\u00F3n legal con bloqueos',\n        voiceMatchReady: 'Ajuste de voz listo',\n        clipInVariants: 'Guion corto guardado en Variantes',\n        segmentsImported: (n: number) => `${n} segmentos importados`,\n        selectText: 'Selecciona texto o escribe primero',\n        selectOrWrite: 'Selecciona o escribe texto',\n        pasteSamples: 'Pega muestras aqu\u00ED o configura el banco de texto en Marca',\n        separateHooks: 'Escribe al menos 2 ganchos para comparar',\n        transcribeError: 'Error al transcribir',\n        generic: 'Error',\n      },\n      sectionFallback: 'Borrador desde la transcripci\u00F3n',\n    },\n  },\n  slides: {\n    editor: {\n      noProject: 'No hay presentaci\u00F3n abierta',\n      newProject: 'Nueva presentaci\u00F3n',\n      slidesRailButtonShow: 'Mostrar diapositivas',\n      slidesRailButtonHide: 'Ocultar diapositivas',\n      slidesRailButtonLabel: 'Diapositivas',\n      gridTitle: 'Cuadr\u00EDcula',\n      zoomOutTitle: 'Alejar',\n      zoomInTitle: 'Acercar',\n      presentButton: 'Presentar',\n      masterButton: 'M\u00E1ster',\n      fallbackFilename: 'Presentaci\u00F3n',\n      toasts: {\n        savedToCloud: 'Guardado en la nube \u2713',\n        cloudSaveFailed: (msg: string) => `No se pudo guardar en la nube: ${msg}`,\n        pptxImported: 'PPTX importado',\n        pptxImportedWithWarnings: (n: number) => `Importado con ${n} avisos`,\n        projectOpened: 'Proyecto abierto',\n        fileInvalid: 'Archivo inv\u00E1lido',\n      },\n    },\n    sidebar: {\n      tabAi: 'IA',\n      tabChat: 'Chat',\n      tabTheme: 'Tema',\n      tabOutline: 'Esquema',\n      tabBuilds: 'Animaci\u00F3n',\n      tabNotes: 'Notas',\n      tabComments: 'Comentarios',\n      tabCritique: 'Cr\u00EDtica',\n      tabCoach: 'Ensayo',\n      tabLibrary: 'Biblioteca',\n      tabMaster: 'M\u00E1ster',\n      titleAi: 'IA',\n      titleChat: 'Chat',\n      titleTheme: 'Tema',\n      titleOutline: 'Esquema',\n      titleBuilds: 'Animaciones',\n      titleNotes: 'Notas',\n      titleComments: 'Comentarios',\n      titleCritique: 'Cr\u00EDtica de dise\u00F1o',\n      titleCoach: 'Ensayo del orador',\n      titleLibrary: 'Biblioteca',\n      titleMaster: 'M\u00E1ster',\n      unpin: 'Desanclar panel',\n      pin: 'Anclar panel',\n      resetSize: 'Restablecer tama\u00F1o',\n      closePanel: 'Cerrar panel',\n      resizeHeight: 'Arrastrar para cambiar alto',\n    },\n    contextMenu: {\n      title: 'Objeto',\n      snapOn: 'Ajuste activo (desactivar)',\n      snapOff: 'Activar ajuste',\n      bringForward: 'Subir',\n      sendBackward: 'Bajar',\n      bringToFront: 'Subir todo',\n      sendToBack: 'Bajar todo',\n      copy: 'Copiar',\n      delete: 'Eliminar',\n    },\n    creationToolbar: {\n      textTitle: 'Texto (T)',\n      textTooltip: 'Texto',\n      shapesTitle: 'Formas',\n      shapesTooltip: 'Formas',\n      shapesHeader: 'Formas',\n      shapes: { rect: 'Rect\u00E1ngulo', circle: 'C\u00EDrculo', triangle: 'Tri\u00E1ngulo', line: 'L\u00EDnea' },\n      imageTitle: 'Adjuntar imagen',\n      imageTooltip: 'Imagen',\n      chartsTitle: 'Crear gr\u00E1fico',\n      chartsTooltip: 'Gr\u00E1ficos',\n      chartsHeader: 'Gr\u00E1ficos',\n      charts: { bar: 'Barras', line: 'L\u00EDneas', pie: 'Pastel', donut: 'Dona' },\n      chartSeriesFallback: { s1: 'Serie 1', trend: 'Tendencia', dist: 'Distribuci\u00F3n', cats: 'Categor\u00EDas' },\n    },\n    chat: {\n      agentHeader: 'Agente',\n      planModeLabel: 'Modo plan',\n      inputPlaceholder: 'Mensaje al agente\u2026',\n      sendButton: 'Enviar',\n      emptyHint: (planMode: boolean) =>\n        planMode\n          ? 'Pide al agente que a\u00F1ada diapositivas, reescriba, restile o traduzca. Modo plan: primero propone, luego di \u00ABejecuta el plan\u00BB.'\n          : 'Pide al agente que a\u00F1ada diapositivas, reescriba, restile o traduzca la presentaci\u00F3n.',\n      done: 'Listo.',\n      error: 'Error del agente',\n      planModeOmit: (tool: string) => `(omitido en plan mode: ${tool})`,\n    },\n    ai: {\n      hint: 'Herramientas de IA para la presentaci\u00F3n. Elige una para abrir su formulario.',\n      toolsHeader: 'Herramientas',\n      backToList: 'Todas las herramientas',\n      generateHeader: 'Generar presentaci\u00F3n',\n      briefPlaceholder: 'Brief, art\u00EDculo o idea\u2026',\n      audienceLabel: 'Audiencia',\n      audiencePlaceholder: 'p. ej. ejecutivos',\n      countLabel: 'Diapositivas',\n      countPlaceholder: 'Cantidad de diapositivas',\n      generateButton: 'Generar presentaci\u00F3n',\n      generating: 'Generando\u2026',\n      activeSlideHeader: 'Diapositiva activa',\n      condense: 'Condensar',\n      lessText: 'Menos texto',\n      audience: 'Audiencia',\n      magicLayout: 'Dise\u00F1o m\u00E1gico',\n      restyleBoard: 'Restilo junta',\n      speakerNotes: 'Generar notas del orador',\n      translateHeader: 'Traducir presentaci\u00F3n',\n      languageLabel: 'Idioma',\n      langEs: 'Espa\u00F1ol',\n      langEn: 'Ingl\u00E9s',\n      langPt: 'Portugu\u00E9s',\n      translateButton: 'Traducir',\n      dataHeader: 'Datos \u2192 gr\u00E1fico / narrativa',\n      insertChart: 'Insertar gr\u00E1fico',\n      dataToNarrative: 'Datos \u2192 narrativa',\n      tools: {\n        generate: 'Generar presentaci\u00F3n',\n        generateDesc: 'Crea un deck completo a partir de un brief, audiencia y n\u00FAmero de diapositivas.',\n        rewrite: 'Reescribir diapositiva',\n        rewriteDesc: 'Condensa, reduce texto o adapta la diapositiva activa a una audiencia.',\n        layout: 'Dise\u00F1o y estilo',\n        layoutDesc: 'Aplica dise\u00F1o m\u00E1gico o un restilo sem\u00E1ntico al contenido del deck.',\n        notes: 'Notas del orador',\n        notesDesc: 'Genera notas de apoyo para todas las diapositivas del esquema.',\n        translate: 'Traducir',\n        translateDesc: 'Traduce t\u00EDtulos, cuerpo y notas de toda la presentaci\u00F3n.',\n        data: 'Datos a gr\u00E1fico',\n        dataDesc: 'Pega CSV y convierte a gr\u00E1fico o a una narrativa con vi\u00F1etas.',\n      },\n      toasts: {\n        deckGenerated: (n: number) => `Presentaci\u00F3n generada (${n} diapositivas)`,\n        deckGeneratedRich: (n: number, images: number, charts: number) =>\n          `Presentaci\u00F3n generada (${n} diapositivas${images ? `, ${images} im\u00E1genes` : ''}${charts ? `, ${charts} gr\u00E1ficos` : ''})`,\n        deckError: 'Error al generar la presentaci\u00F3n',\n        rewriteEmpty: 'La diapositiva activa no tiene texto para reescribir',\n        slideRewritten: 'Diapositiva reescrita',\n        notesGenerated: 'Notas generadas',\n        deckTranslated: 'Presentaci\u00F3n traducida',\n        deckTranslatedFallback: 'Presentaci\u00F3n traducida (v\u00EDa servicio AI de traducci\u00F3n)',\n        translateNoChange:\n          'La traducci\u00F3n no cambi\u00F3 el texto (el backend devolvi\u00F3 el mismo contenido). Revisa el servicio translate-deck.',\n        translateEmpty: 'La traducci\u00F3n no devolvi\u00F3 diapositivas',\n        chartInserted: 'Gr\u00E1fico insertado',\n        narrativeCreated: 'Narrativa de datos creada',\n        chartFallbackTitle: (chartType: string) => `Gr\u00E1fico ${chartType}`,\n        generic: 'Error',\n      },\n    },\n    export: {\n      title: 'Exportar presentaci\u00F3n',\n      hint: 'Elige un formato. Cada opci\u00F3n descarga un archivo o abre otro modo del editor.',\n      sections: {\n        office: 'PowerPoint',\n        documents: 'Documentos',\n        media: 'Im\u00E1genes, video y proyecto',\n        continueIn: 'Continuar en otro modo',\n      },\n      formats: {\n        pptxEditable: {\n          title: 'PowerPoint editable',\n          description: 'Archivo .pptx que puedes abrir y editar en PowerPoint o similar.',\n        },\n        pptxRaster: {\n          title: 'PowerPoint con im\u00E1genes',\n          description: 'Cada diapositiva va como imagen dentro de un .pptx (sin editar texto).',\n        },\n        pdfSlides: {\n          title: 'PDF de diapositivas',\n          description: 'Una p\u00E1gina por diapositiva, ideal para compartir o imprimir.',\n        },\n        pdfNotes: {\n          title: 'PDF con notas del orador',\n          description: 'Incluye las notas debajo de cada diapositiva.',\n        },\n        pdfHandout4: {\n          title: 'PDF folleto (4 por p\u00E1gina)',\n          description: 'Cuatro diapositivas por hoja para repartir en reuniones.',\n        },\n        htmlBuilds: {\n          title: 'HTML interactivo',\n          description: 'P\u00E1gina web con las diapositivas y animaciones de entrada.',\n        },\n        zipPng: {\n          title: 'Im\u00E1genes PNG (ZIP)',\n          description: 'Una imagen por diapositiva, empaquetadas en un ZIP.',\n        },\n        videoWebm: {\n          title: 'Video',\n          description: 'Reproduce el deck como video (.webm), unos segundos por slide.',\n        },\n        projectWzrds: {\n          title: 'Proyecto Kaiman',\n          description: 'Archivo .kais para volver a abrir el proyecto en este editor.',\n        },\n      },\n      handoffVideo: {\n        title: 'Abrir en Video',\n        description: 'Env\u00EDa cada diapositiva como clip al editor de video.',\n      },\n      handoffText: {\n        title: 'Abrir en Texto',\n        description: 'Convierte el esquema y las notas en un documento editable.',\n      },\n      toasts: {\n        handoffVideo: (n: number) => `Se enviaron ${n} diapositivas al editor de video`,\n        handoffText: 'Documento creado en el editor de texto',\n        noImageTrack: 'No hay pista de imagen disponible en video',\n        handoffError: 'No se pudo abrir en el otro modo',\n        ready: (label: string) => `${label} listo`,\n        exportError: 'Error al exportar',\n      },\n    },\n    master: {\n      title: (name: string) => `M\u00E1ster \u00B7 ${name || 'Principal'}`,\n      closeAria: 'Cerrar M\u00E1ster',\n      closeTitle: 'Cerrar',\n      chromeSection: 'Elementos del m\u00E1ster',\n      contentSection: 'Textos',\n      showHeader: 'Encabezado',\n      showFooter: 'Pie',\n      showPageNumber: 'N\u00FAmero de p\u00E1gina',\n      showLogo: 'Logo',\n      headerTextPlaceholder: 'Texto de encabezado',\n      footerTextPlaceholder: 'Pie / confidencial',\n      chromeHint: (bg: string) =>\n        `Fondo m\u00E1ster: ${bg}. El chrome se compone al presentar/exportar.`,\n      unpin: 'Desanclar panel (por debajo de la l\u00EDnea de tiempo)',\n      pin: 'Anclar panel (por encima de la l\u00EDnea de tiempo)',\n      resetSize: 'Restablecer tama\u00F1o',\n      resizeHeight: 'Arrastrar para cambiar alto',\n    },\n    notesPanel: {\n      noActiveSlide: 'Sin diapositiva activa',\n      label: 'Notas del orador',\n      placeholder: 'Escribe las notas para esta diapositiva...',\n      wordCount: (n: number) => `${n} palabras`,\n      estMinutes: (n: number) => `~${Math.max(1, Math.ceil(n / 130))} min`,\n      minutesSep: 'min',\n    },\n    commentsPanel: {\n      hint: 'Comentarios de la diapositiva activa. Enter agrega; Shift+Enter nueva l\u00EDnea.',\n      enterHint: 'Enter para agregar \u00B7 Shift+Enter para nueva l\u00EDnea',\n      inputPlaceholder: 'Escribe un comentario\u2026',\n      add: 'Agregar comentario',\n      resolve: 'Resolver',\n      remove: 'Eliminar',\n      empty: 'Sin comentarios en esta diapositiva',\n      noActiveSlide: 'Sin diapositiva activa',\n      listTitle: (n: number) => `Comentarios (${n})`,\n      open: 'Abierto',\n      resolved: 'Resuelto',\n    },\n    slideMasterEditor: {\n      titlePrefix: 'Master:',\n      defaultName: 'Principal',\n      close: 'Cerrar',\n      showHeader: 'Header',\n      showFooter: 'Footer',\n      showPageNumber: 'N\u00FAmero de p\u00E1gina',\n      showLogo: 'Logo',\n      uploadLogo: 'Subir logo',\n    },\n    deckOutlinePanel: {\n      extract: 'Extraer del deck',\n      apply: 'Aplicar al deck',\n      placeholder: '# T\u00EDtulo\\n- Vi\u00F1eta 1\\n- Vi\u00F1eta 2\\n\\n# Siguiente slide',\n      bulletsCount: (n: number) => `${n} vi\u00F1etas`,\n      editorTitle: 'Esquema',\n      editorHint: 'Edita el outline en markdown y apl\u00EDcalo al deck.',\n      slidesTitle: 'Diapositivas',\n      defaultSection: 'Secci\u00F3n',\n      empty: 'Sin diapositivas',\n    },\n    libraryPanel: {\n      findReplaceTitle: 'Buscar / reemplazar',\n      findPlaceholder: 'Buscar en el deck',\n      replacePlaceholder: 'Reemplazar con',\n      replaceAll: 'Reemplazar en todo el deck',\n      brandComponentsTitle: 'Componentes de marca',\n      reset: 'Restablecer',\n      libraryTitle: 'Biblioteca de diapositivas',\n      saveActive: 'Guardar activa',\n      insert: 'Insertar',\n      delete: 'Eliminar',\n      empty: 'Biblioteca vac\u00EDa',\n      slideSaved: 'Diapositiva guardada en biblioteca',\n      slideInserted: 'Diapositiva insertada',\n      selectSlide: 'Selecciona una diapositiva',\n      replacementsCount: (n: number) => `${n} reemplazos`,\n      noReplacements: '0 reemplazos',\n      brandCta: 'Bloque CTA',\n      brandQuote: 'Cita',\n      brandKpi: 'KPI grande',\n      componentInserted: (name: string) => `${name} insertado`,\n      jobsTitle: 'Mis archivos',\n      jobsHint: 'Im\u00E1genes y videos de tus jobs para insertar en la diapositiva.',\n      jobsRefresh: 'Actualizar',\n      jobsEmpty: 'No hay archivos de imagen o video',\n      jobsLoadError: 'No se pudieron cargar los archivos',\n      jobsInsertError: 'No se pudo insertar el archivo',\n      mediaInserted: (name: string) => `Insertado: ${name}`,\n      filterAll: 'Todos',\n      filterImage: 'Imagen',\n      filterVideo: 'Video',\n    },\n    themePanel: {\n      canvas: 'Lienzo',\n      canvasRatio: 'Proporci\u00F3n',\n      baseline: 'Gu\u00EDa tipogr\u00E1fica',\n      semanticRestyle: 'Restilo sem\u00E1ntico',\n      restyleMode: 'Modo',\n      restyleBoard: 'Junta',\n      restyleSales: 'Ventas',\n      restyleInternal: 'Interno',\n      brandTerms: 'T\u00E9rminos de marca',\n      importBrandTerms: 'Importar desde Texto',\n      forbiddenLabel: (n: number) => `Prohibidos: ${n}`,\n      preferredLabel: (n: number) => `Preferidos: ${n}`,\n      colors: 'Fondo de la presentaci\u00F3n',\n      colorsBackgroundOnly: 'Solo cambia el fondo del deck. El color de cada objeto se edita en la barra de propiedades al seleccionarlo.',\n      colorBackground: 'Fondo',\n      colorSurface: 'Superficie',\n      colorTitle: 'T\u00EDtulo',\n      colorBody: 'Cuerpo',\n      colorAccent: 'Acento',\n      colorMuted: 'Atenuado',\n      typography: 'Tipograf\u00EDa',\n      titleLabel: 'Fuente t\u00EDtulo',\n      bodyLabel: 'Fuente cuerpo',\n    },\n    buildsPanel: {\n      transitionLabel: 'Transici\u00F3n de entrada',\n      durationLabel: 'Duraci\u00F3n (s)',\n      buildsHeader: (n: number) => `Animaciones (${n})`,\n      addToSelected: '+ Selecci\u00F3n',\n      remove: 'Quitar',\n      triggerClick: 'Al clic',\n      triggerWithPrevious: 'Con anterior',\n      triggerAfterPrevious: 'Tras anterior',\n      empty: 'Selecciona un objeto y a\u00F1ade una animaci\u00F3n.',\n      objectLabel: (id: string) => `Objeto \u00B7 ${id.slice(0, 8)}`,\n      animationLabel: 'Animaci\u00F3n',\n      triggerLabel: 'Disparador',\n      transitionLabels: {\n        cut: 'Corte',\n        'cross-dissolve': 'Fundido cruzado',\n        'fade-black': 'Fundido a negro',\n        'slide-left': 'Deslizar izq.',\n        'slide-right': 'Deslizar der.',\n        'push-left': 'Empujar izq.',\n        'zoom-in': 'Zoom in',\n        'blur-dissolve': 'Fundido blur',\n        'morph-cut': 'Morph',\n      } as Record<string, string>,\n      presetLabels: {\n        fade: 'Fade',\n        'fade-up': 'Fade up',\n        'slide-left': 'Deslizar',\n        'scale-in': 'Escala',\n        'bounce-in': 'Rebote',\n        'blur-in': 'Blur',\n      } as Record<string, string>,\n    },\n    designCriticPanel: {\n      hint: 'Auditor\u00EDa de dise\u00F1o, Q&A y fixes r\u00E1pidos. Elige una herramienta.',\n      toolsHeader: 'Herramientas',\n      backToList: 'Todas las herramientas',\n      audit: 'Auditar',\n      qaPrep: 'Prep Q&A',\n      condense: 'Condensar',\n      contrast: 'Contraste',\n      autofit: 'Autofit',\n      magicLayout: 'Magic layout',\n      splitSlide: 'Partir slide',\n      altTexts: 'Alt texts',\n      runAudit: 'Ejecutar auditor\u00EDa',\n      runQa: 'Generar preguntas',\n      scoreLine: (score: number | null, minutes: number | null, slides: number) =>\n        `Score: ${score ?? '\u2013'}${minutes != null ? ` \u00B7 ~${minutes} min` : ''} \u00B7 ${slides} slides`,\n      applyFix: 'Aplicar',\n      fixApplied: 'Fix aplicado',\n      questionsHeader: 'Preguntas probables',\n      slidePrefix: (n: number) => `Slide ${n + 1}`,\n      severityError: 'Error',\n      severityWarn: 'Aviso',\n      severityInfo: 'Info',\n      auditDone: 'Auditor\u00EDa completada',\n      qaReady: 'Q&A preparado',\n      generating: 'Generando\u2026',\n      tools: {\n        audit: 'Auditar dise\u00F1o',\n        auditDesc: 'Revisa densidad, contraste, t\u00E9rminos de marca y problemas de layout.',\n        qa: 'Prep Q&A',\n        qaDesc: 'Genera preguntas probables por diapositiva para ensayar la presentaci\u00F3n.',\n        condense: 'Condensar texto',\n        condenseDesc: 'Reduce el texto de la diapositiva activa para mejorar claridad.',\n        contrast: 'Corregir contraste',\n        contrastDesc: 'Ajusta colores de texto para legibilidad sobre el fondo.',\n        autofit: 'Autofit',\n        autofitDesc: 'Encaja el texto seleccionado o de la slide dentro de su caja.',\n        magicLayout: 'Magic layout',\n        magicLayoutDesc: 'Reorganiza el contenido con un layout autom\u00E1tico.',\n        split: 'Partir slide',\n        splitDesc: 'Divide slides densas en varias m\u00E1s cortas.',\n        alt: 'Alt texts',\n        altDesc: 'Asegura textos alternativos en im\u00E1genes del deck.',\n      },\n    },\n    presenterView: {\n      rehearsalLabel: 'Ensayo',\n      rehearsalTotal: (s: number) => `Ensayo \u00B7 total ${Math.round(s)}s`,\n      titleRehearsal: 'Ensayo',\n      titleInk: 'Tinta',\n      titleClearInk: 'Borrar tinta',\n      next: 'Siguiente',\n      teleprompter: 'Teleprompter',\n      noNotes: 'Sin notas',\n      endOfPresentation: 'Fin de la presentaci\u00F3n',\n      slideTiming: (n: number, s: number) => `S${n + 1}: ${s.toFixed(1)}s`,\n    },\n    coachPanel: {\n      intro: 'Ensayo + tips de ritmo, pausas y preguntas. Usa Presenter View (R) para grabar tiempos.',\n      rehearsalSummary: (count: number, total: number, avg: number) =>\n        `Ensayo: ${count} slides \u00B7 total ${Math.round(total)}s \u00B7 media ${Math.round(avg)}s`,\n      clearTimings: 'Limpiar tiempos',\n      run: 'Generar coach',\n      applyToNotes: 'Agregar tips a notas del orador',\n      done: 'Coach listo',\n      appliedToNotes: (n: number) => `Tips agregados a ${n} notas del orador`,\n      slideLabel: (n: number) => `Slide ${n + 1}`,\n      pacingSeconds: (n: number) => ` \u00B7 ~${n}s`,\n    },\n    contextToolbar: {\n      alignLeft: 'Alinear izquierda',\n      alignCenter: 'Centrar',\n      alignRight: 'Alinear derecha',\n      autofitText: 'Autofit texto',\n      altText: 'Alt text',\n      fontFamily: 'Tipograf\u00EDa',\n      fontSize: 'Tama\u00F1o de fuente',\n      fontSizeDecrease: 'Reducir tama\u00F1o',\n      fontSizeIncrease: 'Aumentar tama\u00F1o',\n      fillColor: 'Color',\n      replaceUpload: 'Reemplazar (subir)',\n      replaceFromFiles: 'Reemplazar desde mis archivos',\n      bringForward: 'Subir',\n      sendBackward: 'Bajar',\n      bringToFront: 'Subir todo',\n      sendToBack: 'Bajar todo',\n      duplicate: (key: string) => `Duplicar (${key})`,\n      remove: (key: string) => `Eliminar (${key})`,\n    },\n    floatingRail: {\n      title: (n: number) => `Diapositivas (${n})`,\n      add: 'Agregar',\n      unpin: 'Desanclar panel',\n      pin: 'Anclar panel',\n      resetSize: 'Restablecer tama\u00F1o',\n      closeAria: 'Cerrar panel de diapositivas',\n    },\n    slideCanvas: {\n      selectAtLeast2: 'Selecciona al menos 2 objetos',\n      selectAtLeast3: 'Selecciona al menos 3 objetos',\n      selectTextBox: 'Selecciona un cuadro de texto',\n      selectImageOrObject: 'Selecciona una imagen u objeto',\n      selectToDelete: 'Selecciona al menos un objeto para eliminar',\n      deleteSelectionBody: (n: number) =>\n        n === 1\n          ? '\u00BFEliminar el elemento seleccionado? Esta acci\u00F3n no se puede deshacer.'\n          : `\u00BFEliminar los ${n} elementos seleccionados? Esta acci\u00F3n no se puede deshacer.`,\n      selectToDuplicate: 'Selecciona un objeto para duplicar',\n      overflowWarning: 'Texto con overflow',\n      imageAddError: 'No se pudo a\u00F1adir la imagen al lienzo',\n    },\n    altTextModal: {\n      title: 'Texto alternativo',\n      hint: 'Describe la imagen para accesibilidad (lectores de pantalla y exportaci\u00F3n).',\n      placeholder: 'p. ej. Diagrama de crecimiento Q3',\n      save: 'Guardar',\n      cancel: 'Cancelar',\n    },\n    slideRail: {\n      show: 'Mostrar',\n      hide: 'Ocultar',\n      duplicate: 'Duplicar',\n      remove: 'Eliminar',\n      deleteTitle: 'Eliminar diapositiva',\n      deleteBody: (name: string) =>\n        `\u00BFEliminar la diapositiva \"${name}\"? Esta acci\u00F3n no se puede deshacer.`,\n      deleteConfirm: 'Eliminar',\n    },\n  },\n  store: {\n    toasts: {\n      editor: {\n        objectLinked: 'Objeto vinculado. C\u00F3pialo y p\u00E9galo en otra p\u00E1gina para sincronizarlos.',\n        objectUnlinked: 'Objeto desvinculado',\n        versionLoaded: (name: string) => `Versi\u00F3n \"${name}\" cargada con \u00E9xito`,\n        fileSaved: 'Archivo cargado correctamente',\n        fileSaveError: 'Error al guardar archivo en base de datos',\n        fileDeleted: 'Archivo eliminado',\n        fileDeleteError: 'Error al eliminar archivo',\n        uploadsCleared: 'Historial de subidas vaciado',\n        uploadsClearError: 'Error al vaciar subidas',\n        fontRegistered: (name: string) => `Tipograf\u00EDa registrada: ${name}`,\n        fontRegisterError: (msg: string) => `Error al registrar tipograf\u00EDa: ${msg || 'desconocido'}`,\n        fontDeleted: 'Tipograf\u00EDa eliminada',\n        fontDeleteError: 'Error al eliminar tipograf\u00EDa',\n        bgRemoved: 'Fondo eliminado con \u00E9xito',\n        bgRemoveError: (msg: string) => msg || 'Error al quitar el fondo.',\n        imageModified: 'Imagen modificada con \u00E9xito',\n        imageModifyError: (msg: string) => msg || 'Error al modificar la imagen.',\n        sketchImageCreated: 'Imagen del boceto creada con \u00E9xito',\n        sketchImageError: (msg: string) => msg || 'Error al generar imagen desde boceto.',\n        inpaintImageCreated: 'Imagen generada en \u00E1rea con \u00E9xito',\n        inpaintImageError: (msg: string) => msg || 'Error al generar imagen en \u00E1rea.',\n        subjectSeparated: 'Sujeto separado en nueva capa',\n        subjectSeparateError: (msg: string) => msg || 'Error al separar el sujeto de la imagen.',\n        magicEraserDone: 'Borrador m\u00E1gico ejecutado con \u00E9xito',\n        magicEraserNothingFound:\n          'La IA no detect\u00F3 nada relevante para borrar en esa zona. Ajusta las marcas e int\u00E9ntalo de nuevo.',\n        magicEraserNeedMarks: 'Dibuja marcas rojas sobre la imagen antes de aplicar el borrador m\u00E1gico.',\n        magicEraserError: (msg: string) => msg || 'Error al ejecutar Borrador M\u00E1gico.',\n        aiSolidBgApplied: 'Fondo de color s\u00F3lido aplicado por AI',\n        aiSolidGradientApplied: (color: string) => `Degradado simplificado a color s\u00F3lido (${color}) aplicado`,\n        aiGenerating: 'Generando imagen de fondo AI con Gemini...',\n        aiBgGenerated: 'Imagen de fondo AI generada e insertada',\n        aiTextStyleApplied: 'Estilo de texto AI aplicado con \u00E9xito',\n        aiShapeStyleApplied: 'Estilo de figura AI aplicado con \u00E9xito',\n        aiPhotoFilterApplied: 'Filtros fotogr\u00E1ficos AI aplicados con \u00E9xito',\n        upscaleSelectImage: 'Selecciona una imagen para hacer upscale.',\n        upscaleStarted: (factor: number) => `Iniciando Upscale ${factor}x... Esto puede tardar unos segundos.`,\n        upscaleDone: (factor: number) => `Upscale ${factor}x completado con \u00E9xito.`,\n        upscaleError: (msg: string) => msg || 'Error al ejecutar Upscale AI.',\n        variationsSelectImage: 'Selecciona una imagen para generar variaciones.',\n        variationsStarted: 'Generando variaciones de la imagen...',\n        variationsDone: 'Variaciones generadas. Selecciona una.',\n        variationsError: (msg: string) => msg || 'Error al generar variaciones AI.',\n        autoEnhanceSelectImage: 'Selecciona una imagen para aplicar Auto-Enhance.',\n        autoEnhanceStarted: 'Analizando y aplicando Auto-Enhance M\u00E1gico',\n        autoEnhanceDone: 'Auto-Enhance M\u00E1gico completado',\n        autoEnhanceError: 'No se pudo aplicar el Auto-Enhance.',\n        // Generic error fallbacks for image-mode AI tools (was hardcoded Spanish).\n        aiRemoveBackgroundError: 'No se pudo quitar el fondo.',\n        aiModifyImageError: 'No se pudo modificar la imagen.',\n        aiGenerateImageError: 'No se pudo generar la imagen.',\n        aiApplyGenerativeBgError: 'No se pudo aplicar el fondo generativo.',\n        aiMagicResizeError: 'No se pudo redimensionar m\u00E1gicamente.',\n        aiAutoLayoutError: 'No se pudo aplicar el Auto Layout.',\n        aiCopySuggestionsError: 'No se pudo generar las sugerencias de copy.',\n        aiVectorizeStrokeError: 'No se pudo vectorizar el trazo.',\n        aiSketchError: 'No se pudo generar la imagen desde el boceto.',\n        aiInpaintError: 'No se pudo generar la imagen en el \u00E1rea.',\n        aiSeparateSubjectError: 'No se pudo separar el sujeto de la imagen.',\n        aiMagicEraserError: 'No se pudo ejecutar el Borrador M\u00E1gico.',\n        aiDesignError: 'No se pudo procesar el dise\u00F1o con AI.',\n        aiDesignToastError: 'No se pudo aplicar el dise\u00F1o AI.',\n        aiUpscaleError: 'No se pudo ejecutar el Upscale AI.',\n        aiVariationsError: 'No se pudo generar variaciones AI.',\n        // Component-level AI tool fallbacks (consumed via useTranslation()).\n        stockLoadError: 'No se pudieron cargar las im\u00E1genes.',\n        voiceoverUnknownError: 'Error desconocido al generar la voz.',\n        transcriptAnalysisError: 'Ocurri\u00F3 un error al analizar la transcripci\u00F3n.',\n        translateSubtitlesError: 'No se pudieron traducir los subt\u00EDtulos.',\n        aiStyleError: 'No se pudo aplicar el estilo AI.',\n        aiColorGradingError: 'No se pudo aplicar el preset de color AI.',\n        exportUnknownError: 'Error desconocido',\n        colorGradingError: 'No se pudo generar el grading de color AI.',\n        exportErrorTitle: 'Error de exportaci\u00F3n',\n        subtitlesErrorTitle: 'Error de subt\u00EDtulos',\n      },\n      audio: {\n        clipsCopied: (n: number) => `${n} clip(s) copiados`,\n        noFillers: 'No hay muletillas detectadas',\n        fillersRemoved: (n: number) => `Eliminadas ${n} muletillas`,\n        selectClipFirst: 'Selecciona un clip primero',\n        trimPlayheadMiss: 'El playhead debe estar dentro del clip',\n        trackDeleted: (name: string) => `Pista eliminada: ${name}`,\n        keepOneTrack: 'Debe quedar al menos una pista de audio',\n      },\n      slides: {\n        atLeastOneSlide: 'Debe quedar al menos una diapositiva',\n        magicLayoutApplied: 'Magic layout aplicado',\n        restyleApplied: (mode: string) => `Restyle ${mode} aplicado`,\n        chartInserted: 'Grafico insertado',\n        canvasResized: (w: number, h: number) => `Canvas ${w}x${h}`,\n        notEnoughContentToSplit: 'No hay suficiente contenido para partir',\n        denseSlideSplit: 'Slide densa partida en 2',\n        saveLocalError: 'No se pudo guardar la presentaci\u00F3n en local',\n      },\n      text: {\n        snapshotSaved: (name: string) => `Snapshot \"${name}\" guardado`,\n        snapshotRestored: (name: string) => `Restaurado: ${name}`,\n        sectionNotFound: 'Seccion no encontrada en el snapshot',\n        sectionRestored: (heading: string) => `Seccion \"${heading}\" restaurada`,\n      },\n    },\n  },\n  presets: {\n    brush: {\n      calligraphy: 'Pincel Caligr\u00E1fico',\n      highlighter: 'Subrayador Amarillo',\n      chalk: 'Tiza Difuminada',\n      neonMagenta: 'Ne\u00F3n Magenta',\n      neonCyan: 'Ne\u00F3n Cian',\n      spray: 'Graffiti Spray',\n    },\n    stockBg: {\n      neonSynthwave: 'Neon Synthwave',\n      minimalistMarble: 'Minimalist Marble',\n      cyberpunkGrid: 'Cyberpunk Grid',\n      darkBeach: 'Dark Beach',\n      cleanWorkspace: 'Clean Workspace',\n      watercolorPastel: 'Watercolor Pastel',\n    },\n    stockLayer: {\n      abstractNeon: 'Abstract Neon',\n      cyberWave: 'Cyber Wave',\n      vidrio3D: 'Vidrio 3D',\n      acuarelaPastel: 'Acuarela Pastel',\n    },\n    gradient: {\n      sunsetGlow: 'Sunset Glow',\n      oceanBreeze: 'Ocean Breeze',\n      purpleHaze: 'Purple Haze',\n      emeraldGlow: 'Emerald Glow',\n      sweetCandy: 'Sweet Candy',\n      spaceVoid: 'Space Void',\n    },\n    canvasSize: {\n      // Social\n      instagramPost: 'Instagram Post',\n      instagramStory: 'Instagram Story',\n      youtubeThumbnail: 'YouTube Thumbnail',\n      youtubeBanner: 'YouTube Banner',\n      // Web\n      fullHdDesktop: 'Full HD Desktop',\n      macbookPro: 'MacBook Pro',\n      mobileAppScreen: 'Mobile App Screen',\n      // Print\n      posterA4: 'P\u00F3ster A4',\n      cartaLetter: 'Carta / Letter',\n      businessCard: 'Business Card',\n      // Description\n      square1_1: '1:1 Cuadrado',\n      portrait9_16: '9:16 Vertical',\n      landscape16_9: '16:9 Miniatura',\n      landscape16_9Banner: '16:9 Banner',\n      monitor16_9: '16:9 Monitor',\n      laptop16_10: '16:10 Laptop',\n      iphoneScreen: 'Pantalla iPhone',\n      a4Standard: 'Papel A4 Est\u00E1ndar',\n      letterUS: 'Papel Carta USA',\n      businessCardDesc: 'Tarjeta Comercial',\n    },\n  },\n};\n", "/** Auto-generated preset display names \u2014 keep keys in sync with ProjectSetupModal presets. */\nexport const SETUP_PRESET_NAMES_EN = {\n  't-blank': \"Documento en blanco\",\n  't-blog': \"Articulo de blog\",\n  't-script': \"Guion\",\n  't-news': \"Newsletter\",\n  't-landing': \"Landing copy\",\n  't-social': \"Post social\",\n  's-blank': \"Presentacion en blanco\",\n  's-pitch': \"Pitch deck\",\n  's-qbr': \"QBR / Business review\",\n  's-course': \"Curso / Workshop\",\n  's-report': \"Informe\",\n  's-keynote': \"Keynote\",\n  's-43': \"4:3 clasico\",\n  's-916': \"Stories / Reels 9:16\",\n  's-a4': \"A4 landscape\",\n  'ig-post': \"Instagram Post\",\n  'yt-thumb': \"YouTube Thumbnail\",\n  'a4': \"A4\",\n  'fb-cover': \"Facebook Cover\",\n  'pres-16-9': \"Presentation 16:9\",\n  'twitter-post': \"Twitter Post\",\n  'photo-4x6': \"4\u00D76 in Photo\",\n  'photo-5x7': \"5\u00D77 in Photo\",\n  'photo-8x10': \"8\u00D710 in Photo\",\n  'photo-sq': \"Square Photo\",\n  'photo-pan': \"Panoramic\",\n  'photo-port': \"Portrait 2:3\",\n  'ig-story': \"Instagram Story\",\n  'ig-reel': \"Instagram Reel\",\n  'fb-post': \"Facebook Post\",\n  'tw-header': \"Twitter Header\",\n  'li-banner': \"LinkedIn Banner\",\n  'tiktok': \"TikTok Cover\",\n  'yt-banner': \"YouTube Banner\",\n  'pin-post': \"Pinterest Pin\",\n  'print-a4': \"A4\",\n  'print-a3': \"A3\",\n  'print-letter': \"Letter (US)\",\n  'biz-card': \"Business Card\",\n  'poster-a2': \"Poster A2\",\n  'flyer': \"Flyer A5\",\n  'web-fhd': \"Full HD (1920\u00D71080)\",\n  'web-hd': \"HD (1280\u00D7720)\",\n  'web-banner': \"Web Banner\",\n  'web-email': \"Email Header\",\n  'web-blog': \"Blog Featured\",\n  'web-og': \"OG Image\",\n  'v-yt': \"YouTube (16:9)\",\n  'v-tiktok': \"TikTok / Reels\",\n  'v-sq': \"Square\",\n  'v-film': \"Cinemascope\",\n  'v-tv': \"Classic TV (4:3)\",\n  'v-portrait': \"Portrait (3:4)\",\n  'v-ig-story': \"IG Story\",\n  'v-ig-feed': \"IG Feed\",\n  'v-fb-video': \"Facebook Video\",\n  'v-tw-video': \"Twitter Video\",\n  'v-cinema': \"Cinema Wide\",\n  'v-std': \"Standard (4:3)\",\n} as const;\nexport type SetupPresetNameId_EN = keyof typeof SETUP_PRESET_NAMES_EN;", "/**\n * English locale \u2014 natural translations, not literal.\n *\n * Brand name \"Kaiman Studio AI\" stays the same in every locale (brand is\n * global, not localized). UI copy is rewritten in a tone that reads naturally\n * to an English-speaking user \u2014 shorter, less verbose, idiomatic.\n *\n * Shape must match `Messages = typeof es`. TypeScript will error if a key is\n * missing or the type of a value (especially template functions) drifts.\n */\n\nimport type { es } from './es';\nimport { SETUP_PRESET_NAMES_EN } from './setupPresetNames.en';\n\ntype Messages = typeof es;\n\nexport const en: Messages = {\n  brand: {\n    fullName: 'Kaiman Studio AI',\n    shortName: 'Kaiman AI',\n    assistant: 'Kaiman AI Assistant',\n  },\n  editor: {\n    back: 'Back',\n    backTitle: 'Back to Kaiman',\n    createNew: 'Create new canvas',\n    closeTab: 'Close tab',\n    renameTab: 'Project name',\n    renameTabHint: 'Double-click to rename (file name)',\n    createNewHint: 'Open setup',\n    recentTitle: 'Recent canvases',\n    recentSubtitle: 'Pick up where you left off with cloud-saved projects.',\n    recentEmpty: 'No cloud canvases saved for this mode yet.',\n    recentLoadError: 'Could not load recent canvases',\n    recentAuthError: 'Your session expired. Sign in to Kaiman again and reopen Studio.',\n    recentLoading: 'Loading recent canvases...',\n    recentLocal: 'Local',\n    recentLocalCloud: 'Local \u00B7 cloud',\n    cloudOpen: 'Open',\n    cloudDelete: 'Remove from cloud',\n    relativeDateToday: 'Today',\n    relativeDateYesterday: 'Yesterday',\n    relativeDateDaysAgo: (n: number) => `${n} days ago`,\n    thumbnailFallback: (name: string) => name.charAt(0).toUpperCase(),\n    brand: {\n      label: 'Brand',\n      selectLabel: 'Switch brand',\n    },\n    emptyByMode: {\n      Image: {\n        title: 'What will you design today?',\n        subtitle: 'Create a new canvas or reopen a cloud-saved project.',\n        createHint: 'Pick size, name, and template to get started.',\n      },\n      Video: {\n        title: 'Your next video starts here',\n        subtitle: 'Set up a video canvas or open a recent project.',\n        createHint: 'Define format, duration, and timeline aspect ratio.',\n      },\n      Audio: {\n        title: 'Ready to edit audio',\n        subtitle: 'Open an existing audio project or start from scratch.',\n        createHint: 'Import tracks, mix, and export in one flow.',\n      },\n      Text: {\n        title: 'Write on brand',\n        subtitle: 'Start a new document or continue saved copy.',\n        createHint: 'TipTap editor with AI, outline, and export.',\n      },\n      Slides: {\n        title: 'Present with impact',\n        subtitle: 'Create a new deck or reopen a cloud presentation.',\n        createHint: 'Editable slides with themes, charts, and PPTX export.',\n      },\n    },\n    newProject: {\n      image: 'New image project',\n      video: 'New video project',\n      audio: 'New audio project',\n      text: 'New document',\n      slides: 'New presentation',\n    },\n    loadingProject: 'Loading project...',\n    aiProcessing: 'Processing pixels and finishing your image...',\n    aiGenerating: 'Generando',\n    localOnly: 'Local',\n    localAndCloud: 'Local \u00B7 cloud',\n  },\n  projectSetup: {\n    untitled: 'Untitled',\n    newSlidesDefault: 'New presentation',\n    close: 'Close',\n    closeDisabled: 'Create a project to continue',\n    recents: 'Recent',\n    refreshList: 'Refresh list',\n    loadingProjects: 'Loading projects\u2026',\n    noRecentFiles: 'No recent files',\n    noProjectsForMode: (modeLabel: string) => `No ${modeLabel} projects yet`,\n    projectsInOtherModes: (n: number) =>\n      n === 1 ? 'You have 1 project in other modes' : `You have ${n} projects in other modes`,\n    retry: 'Try again',\n    upload: {\n      verb: 'Upload',\n      hint: 'Reopen an editable project downloaded from the editor.',\n    },\n    categoryTabs: {\n      home: 'Home',\n      photo: 'Photo',\n      social: 'Social media',\n      print: 'Print',\n      web: 'Web',\n      cinema: 'Cinema',\n    },\n    templateHeaders: {\n      slides: 'Slide templates',\n      text: 'Text templates',\n      audio: 'Audio templates',\n    },\n    presetsTitle: (count: number) => `Presets (${count})`,\n    presetsHintQuick: 'Click / double-click',\n    presetsHintCreate: 'Double-click to create',\n    presetTooltipImage: (name: string, w: number, h: number) =>\n      `${name} \u2014 ${w}\u00D7${h}px\\nDouble-click to create`,\n    presetTooltipVideo: (name: string, ratio: string) =>\n      `${name} \u2014 ${ratio}\\nDouble-click to create`,\n    create: {\n      slides: 'Create presentation',\n      text: 'Create text document',\n      audio: 'Create audio project',\n      image: 'Create image canvas',\n      video: 'Create video project',\n    },\n    form: {\n      fileName: 'File name',\n      projectName: 'Project name',\n      documentName: 'Document name',\n      deckName: 'Presentation name',\n      dimensions: 'Dimensions',\n      widthPx: 'Width (px)',\n      heightPx: 'Height (px)',\n      swapOrientation: 'Swap orientation',\n      orientation: 'Orientation',\n      portrait: 'Portrait',\n      landscape: 'Landscape',\n      backgroundColor: 'Background color',\n      resetColor: 'Reset to default color',\n      aspectRatio: 'Aspect ratio',\n      template: 'Template',\n      sampleRate: 'Sample rate',\n      bpm: 'BPM',\n      language: 'Language',\n      tone: 'Tone',\n      targetChannel: 'Target channel',\n      pageSize: 'Page size',\n      columns: 'Columns',\n      width: 'Width',\n      height: 'Height',\n    },\n    audioTemplates: {\n      empty: { label: 'Empty', sub: '2 tracks' },\n      podcast: { label: 'Podcast', sub: 'Host / guest' },\n      music: { label: 'Music', sub: '5 stems' },\n      voiceover: { label: 'Voiceover', sub: 'VO + bed' },\n    },\n    docTypes: {\n      blank: 'Blank',\n      blog: 'Blog',\n      script: 'Script',\n      newsletter: 'Newsletter',\n      landing: 'Landing',\n      social: 'Social',\n    },\n    tones: {\n      neutral: 'Neutral',\n      formal: 'Formal',\n      casual: 'Casual',\n      persuasive: 'Persuasive',\n      technical: 'Technical',\n      friendly: 'Friendly',\n    },\n    channels: {\n      blog: 'Blog',\n      instagram: 'Instagram',\n      linkedin: 'LinkedIn',\n      x: 'X (Twitter)',\n      email: 'Email',\n      ad: 'Ad',\n      youtube: 'YouTube',\n    },\n    pageSizes: {\n      letter: 'Letter \u2014 8.5 \u00D7 11 in',\n      legal: 'Legal \u2014 8.5 \u00D7 14 in',\n      a4: 'A4 \u2014 21 \u00D7 29.7 cm',\n      a5: 'A5 \u2014 14.8 \u00D7 21 cm',\n    },\n    languages: {\n      es: 'Spanish',\n      en: 'English',\n      pt: 'Portuguese',\n    },\n    slidesTemplates: {\n      blank: 'Blank',\n      pitch: 'Pitch',\n      qbr: 'QBR',\n      course: 'Course',\n      report: 'Report',\n      keynote: 'Keynote',\n    },\n    errors: {\n      sessionNotConfigured: 'Session not configured. Reopen the editor from Wizard.',\n      sessionExpired: 'Session expired or cookies cleared. Sign in to Wizard again and reload.',\n      openFailed: (name: string, msg: string) => `Could not open \"${name}\": ${msg}`,\n      deleteFailed: (name: string, msg: string) => `Could not delete \"${name}\": ${msg}`,\n    },\n    confirmDeleteCloud: (name: string) =>\n      `Delete \"${name}\" from the cloud? This cannot be undone.`,\n    presetNames: SETUP_PRESET_NAMES_EN,\n  },\n  page: {\n    title: 'Kaiman Studio AI Video Editor',\n    description:\n      'Kaiman Studio AI Video Editor \u2014 a professional, interactive, offline-first video editor for the web. Edit video, layers, images, and text with real-time effects.',\n  },\n  toast: {\n    savingToCloud: 'Saving to cloud\u2026',\n    savedToCloud: 'Saved to cloud \u2713',\n    saveFailed: (msg: string) => `Couldn't save to cloud: ${msg}`,\n    cloudPayloadTooLarge:\n      'This project is too large for the server upload limit. Reduce image size or count and try again.',\n  },\n  saveStatus: {\n    saving: 'Saving...',\n    saved: 'Saved',\n    error: 'Error',\n    local: 'Local',\n    justNow: 'Just now',\n    secondsAgo: (n: number) => `${n}s ago`,\n    minutesAgo: (n: number) => `${n}m ago`,\n  },\n  keyboardHelp: {\n    title: 'Keyboard shortcuts',\n    titleTooltip: 'Keyboard shortcuts (?)',\n    select: 'Select',\n    hand: 'Hand / Pan',\n    text: 'Text',\n    rect: 'Rectangle',\n    ellipse: 'Ellipse',\n    undo: 'Undo',\n    redo: 'Redo',\n    copy: 'Copy',\n    paste: 'Paste',\n    delete: 'Delete',\n    zoomIn: 'Zoom +',\n    zoomOut: 'Zoom -',\n    fitCanvas: 'Fit canvas',\n    thisPanel: 'This panel',\n  },\n  dialog: {\n    loadError: {\n      title: 'Load failed',\n      message: 'Could not load the project. The file may be corrupt.',\n    },\n    saveError: {\n      title: 'Save failed',\n      message: (msg: string) => `Could not save the project: ${msg}`,\n    },\n    projectOpened: {\n      title: 'Done',\n      message: 'Project opened in a new tab.',\n    },\n    projectLoadError: {\n      title: 'Load failed',\n      message: (msg: string) => `Could not load the project: ${msg}`,\n    },\n    projectNamePrompt: {\n      message: 'Project name:',\n      defaultName: 'my_project',\n      fallbackName: 'untitled_project',\n    },\n  },\n  commandPalette: {\n    placeholder: 'Type a command or search\u2026',\n    noResults: (query: string) => `No commands found for \"${query}\"`,\n    navigateHint: 'Use \u2191\u2193 to navigate, Enter to select',\n    pressEnter: 'Press',\n    selectImageFirst: 'Select an image first.',\n    noSelectionTitle: 'Nothing selected',\n    title: 'Command palette',\n    categories: {\n      tools: 'Tools',\n      actions: 'Actions',\n      pages: 'Pages',\n      settings: 'Settings',\n      filters: 'Filters',\n    },\n    commands: {\n      toolSelect: 'Switch to select tool',\n      toolPan: 'Switch to hand / pan tool',\n      toolText: 'Insert text',\n      toolRect: 'Insert rectangle',\n      toolCircle: 'Insert circle',\n      toolTriangle: 'Insert triangle',\n      toolStar: 'Insert star',\n      toolCrop: 'Open crop tool',\n      toolPencil: 'Pencil brush',\n      toolFrameMobile: 'Insert iPhone frame',\n      actionUndo: 'Undo',\n      actionRedo: 'Redo',\n      actionDelete: 'Delete selected object',\n      actionCopy: 'Copy selection',\n      actionRotate90: 'Rotate 90\u00B0 clockwise',\n      actionExportPng: 'Export as PNG',\n      actionSlideshow: 'Start slideshow / presentation',\n      actionDuplicatePage: 'Duplicate page',\n      actionDeletePage: 'Delete current page',\n      actionClearPage: 'Clear all objects on page',\n      actionResize1080: 'Set canvas size 1080x1080 (IG square)',\n      actionResize1920: 'Set canvas size 1920x1080 (16:9)',\n      settingRulers: 'Toggle rulers',\n      settingGuides: 'Toggle smart guides',\n      settingGrid: 'Toggle layout grid',\n      filterSepia: 'Apply sepia filter',\n      filterVintage: 'Apply vintage effect',\n      filterGrayscale: 'Apply grayscale',\n      filterInvert: 'Invert colors',\n    },\n  },\n  modal: {\n    aiVoiceover: {\n      title: 'AI voiceover generator (TTS)',\n      scriptLabel: 'Voiceover script',\n      placeholder:\n        'Write the script the voice will narrate\u2026 e.g. Welcome to this new video from Kaiman Studio AI\u2026',\n      voiceLabel: 'Voice',\n      playDemo: 'Play voice demo',\n      playDemoHint: 'Play a short sample of the selected voice before generating.',\n      demoError: 'Could not play the voice demo.',\n      speedLabel: 'Reading speed',\n      cancel: 'Cancel',\n      generate: 'Generate audio',\n      synthesizing: 'Synthesizing\u2026',\n      successTitle: 'Voiceover ready',\n      successHint: 'Listen to the result, then add it to the timeline if you like it.',\n      addToTimeline: 'Add voiceover to timeline',\n      decodeError: 'Could not decode audio duration.',\n      clipName: (snippet: string) => `Voice: \"${snippet}\u2026\"`,\n      trackName: 'AI Voiceovers',\n      addedToast: 'Voiceover added to timeline',\n    },\n    export: {\n      filePrefix: (resolution: string, aspect: string) =>\n        `kaiman_ai_render_${resolution}_${aspect.replace(':', '_')}.mp4`,\n      filePrefixBase: (resolution: string) => `kaiman_ai_export_${resolution}`,\n    },\n    imageExport: {\n      title: 'Advanced export',\n      outputFormat: 'Output format',\n      resolutionScale: 'Resolution (scale)',\n      printSettings: 'Print settings',\n      includeBleed: 'Include bleed',\n      includeBleedHint: 'Adds an extra margin around the design',\n      bleedSizeMm: 'Size (mm):',\n      cropMarks: 'Crop marks',\n      cropMarksHint: 'Corner marks in the bleed only (min. 8 mm margin)',\n      watermark: 'Watermark',\n      enableWatermark: 'Enable watermark',\n      watermarkText: 'Text',\n      watermarkLogo: 'Logo (image)',\n      watermarkPlaceholder: 'e.g. Draft, Confidential\u2026',\n      watermarkDefault: 'Draft',\n      uploadLogo: 'Click to upload a logo\u2026',\n      opacity: 'Opacity',\n      cancel: 'Cancel',\n      exporting: 'Exporting\u2026',\n      exportProject: 'Export project',\n      errorTitle: 'Export error',\n      errorMessage: 'Advanced export failed.',\n    },\n    videoExport: {\n      title: 'Render and export project',\n      doNotClose: 'Do not close this window during render.',\n      exportFormat: 'Export format',\n      multiFormat: 'Multi-format batch export',\n      multiFormatHint: 'Detects faces with WASM and crops to 16:9, 9:16, 1:1',\n      aspectRatio: 'Aspect ratio',\n      resolution: 'Resolution',\n      frameRate: 'Frame rate',\n      bitrate: 'Bitrate / quality',\n      cancel: 'Cancel',\n      startExport: 'Start export',\n      outputPreviews: 'Output aspect previews',\n      fit: 'Fit',\n      crop: 'Crop',\n      faceTrack: 'Face track',\n      landscape: 'Landscape (16:9)',\n      portrait: 'Portrait (9:16)',\n      square: 'Square (1:1)',\n      initCompiler: 'Initializing compiler\u2026',\n      demoExport: 'No media on timeline. Running simulated demo export\u2026',\n    },\n    apiKeys: {\n      title: 'AI provider keys',\n      intro:\n        'Add your API keys to unlock the advanced AI features. Keys are stored locally in localStorage.',\n      openaiLabel: 'OpenAI API key',\n      openaiPlaceholder: 'sk-proj-\u2026',\n      geminiLabel: 'Gemini API key',\n      geminiPlaceholder: 'AIzaSy\u2026',\n    },\n    versionHistory: {\n      title: 'Version history',\n      saveCurrentVersion: 'Save current version',\n      placeholder: 'e.g. \"Before changing the background\"',\n      save: 'Save',\n      noVersions: 'No saved versions in this project yet.',\n      loadConfirm: 'Load this version? Unsaved changes will be lost.',\n      loadVersion: 'Load version',\n      load: 'Load',\n      deleteConfirm: 'Permanently delete this version?',\n      deleteVersion: 'Delete version',\n      delete: 'Delete',\n      restore: 'Restore',\n      pagesSuffix: (n: number) => `page${n !== 1 ? 's' : ''}`,\n    },\n    chartData: {\n      title: 'Chart configuration',\n      tabData: 'Data & values',\n      tabDesign: 'Design & styles',\n      chartType: 'Chart type',\n      bar: 'Bar',\n      line: 'Line',\n      pie: 'Pie',\n      donut: 'Donut',\n      valuesTable: 'Values table',\n      addRow: 'Add row',\n      labelCol: 'Label',\n      valueCol: 'Numeric value',\n      colorCol: 'Color',\n      rowNamePlaceholder: 'Name\u2026',\n      noData: 'No data in the chart yet.',\n      themeLabel: 'Grid theme',\n      dark: 'Dark',\n      light: 'Light',\n      showDataLabels: 'Show floating data labels',\n      textColorLabel: 'Text color',\n      bgColorLabel: 'Chart background',\n      transparentBg: 'No background (transparent)',\n      numericValuesLabel: 'Numeric values',\n      proTip: 'Pro tip: if you placed the chart on a light canvas (e.g. white), switch the Grid theme to \"Light\" and pick a dark text color so the values stay readable.',\n      apply: 'Apply changes',\n      itemLabel: (n: number) => `Item ${n}`,\n    },\n    dialog: {\n      notice: 'Notice',\n      confirmAction: 'Confirm action?',\n      accept: 'OK',\n      cancel: 'Cancel',\n      confirm: 'Confirm',\n    },\n    variations: {\n      title: 'AI variations',\n      subtitle: 'Pick the variant you like best to add it to your canvas.',\n    },\n  },\n  common: {\n    closeNotification: 'Dismiss notification',\n    fileSection: 'File',\n    settingsSection: 'Preferences',\n    language: 'Language',\n    spanish: 'Espa\u00F1ol',\n    english: 'English',\n    languageActive: 'Active',\n    resetPanels: 'Reset panels',\n    panelsResetToast: 'Panels restored to their default positions',\n    apply: 'Apply',\n    close: 'Close',\n    cancel: 'Cancel',\n    accept: 'OK',\n    reset: 'Reset',\n    resetPosition: 'Reset position',\n    understood: 'Got it',\n    fileNewHint: 'Start a blank canvas',\n    fileOpenHint: 'Load a file from your device',\n    fileSaveHint: 'Download the project locally',\n    fileCloudHint: 'Sync with your account',\n    errors: {\n      unexpected:\n        'Something went wrong. Please try again later. Our team is already looking into it.',\n      network: 'We could not connect. Check your connection and try again.',\n      sessionExpired: 'Your session expired. Sign in again and try once more.',\n      comingSoon: 'This feature will be available soon.',\n    },\n  },\n  modes: {\n    image: 'Image',\n    video: 'Video',\n    audio: 'Audio',\n    text: 'Text',\n    slides: 'Slides',\n    switchTo: (label: string) => `Switch to ${label}`,\n    menuTitle: 'Studio modes',\n    description: {\n      image: 'Canvas, layers and photo',\n      video: 'Timeline and clips',\n      audio: 'Music and voice',\n      text: 'Copy and documents',\n      slides: 'Presentations',\n    },\n  },\n  toolbar: {\n    image: {\n      fileMenu: 'File menu',\n      newCanvas: 'New canvas',\n      openProject: 'Open project (.kai)',\n      saveProject: 'Save project (.kai)',\n      saveToCloud: 'Save to cloud',\n      savingToCloud: 'Saving to cloud\u2026',\n      versionHistory: 'Version history',\n      smartGuides: 'Smart guides',\n      smartGuidesOn: 'ON',\n      smartGuidesOff: 'OFF',\n      snapping: 'Magnetic snap',\n      snapMaster: 'Enable snapping',\n      snapShapes: 'Shapes',\n      snapImages: 'Images',\n      snapText: 'Text',\n      snapCanvasEdges: 'Canvas edges',\n      undo: 'Undo (\u2318Z)',\n      redo: 'Redo (\u2318\u21E7Z)',\n      zoomOut: 'Zoom out (\u2318-)',\n      zoomIn: 'Zoom in (\u2318+)',\n      fitCanvas: 'Fit canvas',\n      brandKit: 'Brand kit & colors',\n      export: 'Export',\n      presentationMode: 'Presentation mode',\n      exitPresentation: 'Exit presentation',\n      removeBackground: 'Remove background',\n      removeBackgroundTitle: 'Remove background (AI)',\n      filters: 'Filters',\n      filtersSelectImage: 'Select an image to apply filters',\n    },\n    video: {\n      fileMenu: 'File menu',\n      newCanvas: 'New canvas',\n      importProjectLoading: 'Loading\u2026',\n      importProjectIdle: 'Import project (.kaiv)',\n      saveProjectSaving: 'Saving\u2026',\n      saveProjectIdle: 'Save project (.kaiv)',\n      saveToCloud: 'Save to cloud',\n      savingToCloud: 'Saving to cloud\u2026',\n      apiKeys: 'API keys',\n      apiKeysOkBadge: 'OK',\n      aiAssistant: 'AI assistant',\n      aiAssistantHint: 'Viral social kit from the timeline script',\n      webglActive: 'WebGL active',\n      aspectTitle: 'Canvas format',\n      aspectSection: 'Canvas format',\n      aspectLandscape: '16:9 \u2014 Landscape',\n      aspectPortrait: '9:16 \u2014 Portrait',\n      aspectSquare: '1:1 \u2014 Square',\n      assetsLibrary: 'Assets library',\n      zoomOut: 'Zoom out preview',\n      zoomIn: 'Zoom in preview',\n      zoomReset: 'Reset zoom and position',\n      zoomOutHint: 'Zoom out (Ctrl+wheel on canvas)',\n      zoomInHint: 'Zoom in (Ctrl+wheel on canvas)',\n      export: 'Export',\n    },\n    common: {\n      fileMenu: 'File menu',\n      new: 'New',\n      openProject: (ext: string) => `Open project (.${ext})`,\n      saveProject: (ext: string) => `Save project (.${ext})`,\n      saveToCloud: 'Save to cloud',\n      savingToCloud: 'Saving to cloud\u2026',\n      export: 'Export',\n      exportNotAvailable: 'Export unavailable',\n      undo: 'Undo (\u2318Z)',\n      redo: 'Redo (\u2318\u21E7Z)',\n    },\n    brand: {\n      menuLabel: 'Switch brand',\n      listLabel: 'Brands',\n      placeholder: 'No brand',\n    },\n  },\n  leftPanel: {\n    assets: 'Assets',\n    myFiles: 'My Files',\n    ai: 'AI',\n    canvas: 'Canvas',\n  },\n  crop: {\n    activeTitle: 'Crop image',\n    free: 'Free',\n    aspect1x1: '1:1',\n    aspect16x9: '16:9',\n    aspect4x3: '4:3',\n    errorPrefix: 'Crop error',\n    closeError: 'Close',\n    cancelTooltip: 'Cancel crop',\n    cancelLabel: 'Cancel',\n    applyTooltip: 'Apply crop',\n    applyLabel: 'Apply',\n  },\n  mask: {\n    title: 'Layer mask mode',\n    hint: 'Use the brush to paint the mask.',\n  },\n  transition: {\n    searchPlaceholder: 'Search transitions\u2026',\n    doubleClickHint: 'Double click to apply at clip cuts',\n    apply: 'Apply',\n    noClipSelected: 'No clip selected',\n    noClipSelectedBody: 'Pick a clip on the timeline first to apply a transition to it.',\n    notAllowedTitle: 'Action not allowed',\n    notAllowedBody: 'Transitions apply to video, image, and text tracks.',\n    notAllowedAudioBody:\n      'Visual transitions do not apply to audio clips. Select a video, image, or text clip.',\n    applyTransitionTitle: 'Apply transition',\n    applyTransitionBody: (name: string) => `Where do you want to apply the \"${name}\" transition?`,\n    fadeIn: 'Clip start (fade in)',\n    fadeInShort: 'Entry',\n    fadeOut: 'Clip end (fade out)',\n    fadeOutShort: 'Exit',\n    betweenPrev: 'Between the previous clip and this one',\n    betweenNext: 'Between this clip and the next one',\n    cut: 'Cut',\n    catAll: 'All',\n    catDissolve: 'Dissolve',\n    catWipe: 'Wipe',\n    catSlide: 'Slide',\n    catStylized: 'Stylized',\n    addTransition: 'Add transition',\n    junctionTitle: 'Transitions at cut',\n    junctionHint: 'Adjust or remove the transition on each side of the cut.',\n    junctionConflictHint:\n      'Conflict: each clip brings a different transition. Pick one per side or unify them.',\n    junctionLeft: 'Left clip',\n    junctionRight: 'Right clip',\n    junctionNone: 'No transition',\n    junctionRemoveBoth: 'Remove both',\n    junctionDone: 'Done',\n    intentBanner: 'Pick a transition to apply on the selected edge.',\n    intentClear: 'Cancel edge',\n    builderTitle: 'Transition',\n    builderContextStart: 'Clip start (fade in)',\n    builderContextEnd: 'Clip end (fade out)',\n    builderContextBetween: 'Between clips',\n    builderType: 'Type',\n    builderDuration: 'Duration',\n    builderBg: 'Transition background',\n    builderBgBlack: 'Dip to black',\n    builderBgWhite: 'Dip to white',\n    builderBgTransparent: 'Fade to transparent',\n    builderEasing: 'Easing',\n    builderEasingLinear: 'Linear',\n    builderEasingIn: 'Ease In',\n    builderEasingOut: 'Ease Out',\n    builderEasingInOut: 'Ease In Out',\n    builderDirection: 'Direction',\n    builderForward: 'Forward',\n    builderReversed: 'Reversed',\n    builderDelete: 'Delete',\n    builderApply: 'Apply',\n    builderTypes: {\n      clockWipe: 'Clock wipe',\n      zoomIn: 'Zoom in',\n      zoomPunch: 'Zoom punch',\n      spinZoom: 'Spin zoom',\n    },\n    items: {\n      crossDissolve: { name: 'Cross dissolve', desc: 'Smooth cross-fade overlay' },\n      fadeBlack: { name: 'Dip to black', desc: 'Fade out to black then in' },\n      fadeWhite: { name: 'Dip to white', desc: 'Fade out to white then in' },\n      additiveDissolve: { name: 'Additive dissolve', desc: 'Bright glowing additive dissolve' },\n      wipeLeft: { name: 'Wipe left', desc: 'Wipes left revealing incoming' },\n      wipeRight: { name: 'Wipe right', desc: 'Wipes right revealing incoming' },\n      wipeUp: { name: 'Wipe up', desc: 'Wipes upward revealing incoming' },\n      wipeDown: { name: 'Wipe down', desc: 'Wipes downward revealing incoming' },\n      irisCircle: { name: 'Circle iris wipe', desc: 'Circular expanding/collapsing iris' },\n      slideLeft: { name: 'Slide left', desc: 'Slides in from the right edge' },\n      slideRight: { name: 'Slide right', desc: 'Slides in from the left edge' },\n      pushLeft: { name: 'Push left', desc: 'Incoming pushes outgoing left' },\n      pushRight: { name: 'Push right', desc: 'Incoming pushes outgoing right' },\n      glitch: { name: 'Glitch', desc: 'Digital tracking distortion sweep' },\n      blurDissolve: { name: 'Blur dissolve', desc: 'Gaussian blur cross dissolve' },\n      pixelate: { name: 'Pixelate dissolve', desc: 'Blocky pixelation cross dissolve' },\n      filmBurn: { name: 'Film burn leak', desc: 'Vibrant organic light leak burn' },\n    },\n  },\n  aiImage: {\n    title: 'AI B-Roll generator',\n    promptLabel: 'Describe the B-Roll or graphic you want to generate',\n    promptPlaceholder:\n      'e.g. a futuristic 3D render of a tech product floating over a cyberpunk backdrop, high definition, concept art\u2026',\n    generating: 'Generating\u2026',\n    generate: 'Generate image',\n    firstRenderHint: 'The first render can take a few seconds',\n    saveImage: 'Save image',\n    addBroll: 'Add B-Roll to timeline',\n    unknownError: 'Unknown error while generating the image.',\n    loadingInitial: 'Preparing image generation\u2026',\n    loadingSteps: [\n      'Preparing image generation\u2026',\n      'Sending your prompt to the AI service\u2026',\n      'Processing the composition\u2026',\n      'Rendering at high quality\u2026',\n      'Finishing the image\u2026',\n    ],\n    previewAlt: 'AI-generated preview',\n  },\n  videoEditor: {\n    resizeTimeline: 'Resize timeline',\n    openSetup: 'Open setup',\n    newCanvas: 'New canvas',\n    openSetupHint: 'Open setup',\n    assetPanel: {\n      aiBrollTitle: 'Generate B-Roll with AI',\n      importMediaTitle: 'Import media',\n      dragDrop: 'Drag & drop files',\n      supports: 'Video, image, and audio (MP4, MOV, PNG, JPG, MP3, WAV\u2026)',\n      libraryTitle: (n: number) => `Library (${n})`,\n      libraryEmpty: 'Library is empty',\n      importMediaHint: 'Upload video, image, or audio to start editing',\n      doubleClickHint: 'Double-click to insert on the timeline',\n      removeAssetTitle: 'Remove asset',\n      altThumbnail: 'Thumbnail',\n      altAiBroll: 'AI B-Roll',\n      filterAria: 'Filter assets by type',\n      filterAll: 'All',\n      filterImage: 'Image',\n      filterVideo: 'Video',\n      filterAudio: 'Audio',\n      emptyFilter: 'No assets of this type.',\n    },\n    myFilesPanel: {\n      jobsHeader: 'Image, video & audio files',\n      hint: 'Cloud-generated files. Click to add them to the timeline.',\n      loading: 'Loading files\u2026',\n      empty: 'No image, video, or audio files yet.',\n      emptyFilter: 'No files of this type.',\n      loadError: 'Could not load files.',\n      fetchError: 'Could not download the file.',\n      refresh: 'Refresh',\n      addHint: 'Add to timeline',\n      filterAria: 'Filter by media type',\n      filterAll: 'All',\n      filterImage: 'Image',\n      filterVideo: 'Video',\n      filterAudio: 'Audio',\n    },\n    canvasPanel: {\n      aspectSection: 'Aspect ratio',\n      aspectHint: 'Sets the video canvas aspect ratio.',\n      aspectLabel: 'Aspect',\n      sizeLabel: 'Size',\n      previewSize: 'Preview',\n      canvasSize: 'Canvas',\n      qualitySection: 'Preview quality',\n      qualityHint: '100% renders at the canvas resolution. Lower values improve performance.',\n      qualityLabel: 'Quality',\n      qualityReset: 'Reset quality to 100%',\n      zoomSection: 'View zoom',\n      zoomHint: 'Zoom the preview (Ctrl + wheel on the canvas).',\n      zoomLabel: 'Zoom',\n      zoomIn: 'Zoom in',\n      zoomOut: 'Zoom out',\n      zoomReset: 'Reset zoom and pan',\n      snapSection: 'Magnetic snap',\n      snapHint: 'Align clips on the timeline and elements when moving them in the preview.',\n      snapLabel: 'Enable snapping',\n      size1080p: '1080p landscape',\n      size720p: '720p landscape',\n      sizeVertical1080: '1080p vertical',\n      sizeSquare1080: '1080 square',\n      size4x3: '4:3',\n      size3x4: '3:4',\n      sizeUltrawide: 'Ultrawide 21:9',\n      sizeCustom: 'Custom',\n      customWidth: 'Width',\n      customHeight: 'Height',\n      aspectLabels: {\n        '16:9': '16:9 \u2014 Landscape',\n        '9:16': '9:16 \u2014 Portrait',\n        '1:1': '1:1 \u2014 Square',\n        '4:3': '4:3 \u2014 Classic',\n        '3:4': '3:4 \u2014 Portrait',\n        '21:9': '21:9 \u2014 Ultrawide',\n      },\n    },\n    aiTools: {\n      hint:\n        'Video editor AI tools. Each one acts on the selected clip or inserts a result on the timeline.',\n      sectionSubtitles: 'Subtitles & audio',\n      sectionSubtitlesHint:\n        'Turn speech into subtitles, translate them, style them, or generate TTS voiceover.',\n      sectionLook: 'Look & clip',\n      sectionLookHint:\n        'Adjust color, visual style, and properties (speed, opacity, volume) on the active clip.',\n      sectionCopy: 'Copy & marketing',\n      sectionCopyHint:\n        'Generate overlay copy and a promo kit from the timeline script.',\n      sectionMedia: 'Media',\n      sectionMediaHint: 'Search stock photos and place them on the timeline.',\n      tools: {\n        transcribe: 'Transcribe',\n        transcribeDesc:\n          'Listen to a video or audio clip and create time-synced subtitles on the timeline.',\n        translate: 'Translate subtitles',\n        translateDesc:\n          'Translate every existing subtitle clip into the language you pick, keeping timings.',\n        subtitleStyle: 'Subtitle style',\n        subtitleStyleDesc:\n          'Describe a look (e.g. neon, cinema) and apply typography, color, and background to subtitles.',\n        voiceover: 'Voiceover',\n        voiceoverDesc:\n          'Write a script, pick voice and speed, then add the TTS narration to the timeline.',\n        colorGrading: 'AI color grading',\n        colorGradingDesc:\n          'Describe a look (warm, noir, cinematic) and apply exposure, contrast, and color to the clip.',\n        designPreset: 'AI design',\n        designPresetDesc:\n          'Transform the visual style of the selected image, video, or text clip with a prompt.',\n        videoProperties: 'Clip properties',\n        videoPropertiesDesc:\n          'Change opacity, speed, volume, or mute with natural language (e.g. \u201Cslower\u201D).',\n        generateCopy: 'Generate copy',\n        generateCopyDesc:\n          'Create short overlay text and insert it automatically at the playhead.',\n        copySuggestions: 'Copy suggestions',\n        copySuggestionsDesc:\n          'Three tone variants (commercial, creative, direct); pick one for the timeline.',\n        marketing: 'Marketing assistant',\n        marketingDesc:\n          'Analyze the timeline script and propose viral titles, hooks, and social copy.',\n        stock: 'Stock',\n        stockDesc:\n          'Search photos (Unsplash/Pexels) and add the one you pick as an image clip.',\n      },\n      modal: {\n        transcribeTitle: 'Transcribe to subtitles',\n        translateTitle: 'Translate subtitles',\n        subtitleStyleTitle: 'Subtitle style',\n        colorGradingTitle: 'AI color grading',\n        designPresetTitle: 'AI design',\n        videoPropertiesTitle: 'Clip properties',\n        generateCopyTitle: 'Generate overlay copy',\n        copySuggestionsTitle: 'Copy suggestions',\n        stockTitle: 'Search stock photos',\n        transcribeHint:\n          'Pick the video or audio clip to transcribe. AI detects speech and creates time-aligned subtitles on a new track.',\n        translateHint:\n          'Every subtitle clip in the project will be translated into the selected language. Start times and durations are preserved.',\n        subtitleStyleHint:\n          'Describe the typography look you want (colors, contrast, mood). It applies to all timeline subtitles: font, fill, shadow, and background.',\n        needSubtitlesForStyle: 'Add subtitles to the timeline before applying a style.',\n        emptyStylePreset: 'The backend returned no applicable style properties.',\n        emptyDesignPreset: 'The backend returned no design applicable to the clip.',\n        emptyPropertiesPreset:\n          'The backend returned no editable properties or ops. Check the [video-properties] console log.',\n        colorGradingHint:\n          'Select a video or image clip and describe the look you want (e.g. \u201Cwarm golden sunset\u201D or \u201Chigh-contrast noir\u201D). Updates that clip\u2019s color grading.',\n        designPresetHint:\n          'Select an image, video, or text clip and describe the visual style. AI adjusts typography, filters, or appearance based on clip type.',\n        videoPropertiesHint:\n          'With a video, image, or audio clip selected, describe edits in natural language: transform, opacity, speed, volume, color, effects, transitions, and more.',\n        generateCopyHint:\n          'Describe the on-screen message or CTA you want. On generate, a text clip is inserted at the current playhead.',\n        copySuggestionsHint:\n          'Describe the product, audience, or idea. You get three tones; click a variant to add it to the timeline.',\n        stockHint:\n          'Search by keyword. Choosing a photo downloads it and adds it as an image clip at the playhead.',\n        promptPlaceholder: 'Describe what you need\u2026',\n        subtitleStylePlaceholder:\n          'E.g. neon cyan subtitles with strong shadow and semi-transparent background\u2026',\n        colorGradingPlaceholder:\n          'E.g. cold cinematic look, blue shadows and soft highlights\u2026',\n        designPresetPlaceholder:\n          'E.g. bold white type with black outline, trailer style\u2026',\n        videoPropertiesPlaceholder:\n          'E.g. 1.5x faster, 70% opacity, and lower volume\u2026',\n        generateCopyPlaceholder:\n          'E.g. short CTA to try the app free for 7 days\u2026',\n        copySuggestionsPlaceholder:\n          'E.g. specialty coffee ad for Instagram Reels\u2026',\n        stockPlaceholder: 'E.g. modern office, cityscape, product\u2026',\n        clipLabel: 'Source clip',\n        languageLabel: 'Target language',\n        langEnglish: 'English',\n        langSpanish: 'Spanish',\n        langFrench: 'French',\n        langPortuguese: 'Portuguese',\n        langGerman: 'German',\n        langItalian: 'Italian',\n        run: 'Run',\n        runTranscribe: 'Generate subtitles',\n        runTranslate: 'Translate subtitles',\n        runApplyStyle: 'Apply style',\n        runApplyGrading: 'Apply grading',\n        runApplyDesign: 'Apply design',\n        runApplyProperties: 'Apply properties',\n        runGenerateCopy: 'Generate & insert',\n        runCopySuggestions: 'Generate variants',\n        search: 'Search photos',\n        cancel: 'Close',\n        dismiss: 'Close',\n        addAsText: 'Add as text',\n        toneComercial: 'Commercial',\n        toneCreativa: 'Creative',\n        toneDirecta: 'Direct',\n        statusWorking: 'Working\u2026',\n        statusTranscribing: 'Transcribing\u2026',\n        statusSearching: 'Searching\u2026',\n        statusDownloading: 'Downloading\u2026',\n        statusApplyingGrading: 'Applying grading\u2026',\n        statusApplyingDesign: 'Applying design\u2026',\n        statusApplyingProperties: 'Applying properties\u2026',\n        previewGeneratingHint: 'AI is working on the preview',\n        needMediaClip: 'Add a video or audio clip to the timeline first.',\n        needMediaFile: 'The clip has no associated file.',\n        needSubtitles: 'No subtitles on the timeline.',\n        needVideoOrImage: 'Select a video or image clip.',\n        needDesignTarget: 'Select an image, video, or text clip.',\n        toastSubtitlesAdded: 'Subtitles added to the timeline',\n        toastTranslated: 'Subtitles translated',\n        toastStyleApplied: 'Style applied',\n        toastGradingApplied: 'Color grading applied',\n        toastDesignApplied: 'Design applied',\n        toastPropertiesApplied: 'Properties applied',\n        toastCopyAdded: 'Text added to the timeline',\n        toastImageAdded: 'Image added to the timeline',\n        stockEmpty: 'No results for that search.',\n        unknownError: 'Could not complete the operation.',\n        featureComingSoon: (feature: string) => `Coming soon: ${feature}`,\n        featureColorGrading: 'AI color grading',\n        featureVideoProperties: 'Clip properties',\n        featureDesignPreset: 'AI design',\n        featureSubtitleStyle: 'Subtitle style',\n        featureGenerateCopy: 'Generate copy',\n        featureCopySuggestions: 'Copy suggestions',\n        featureMarketing: 'Marketing assistant',\n        featureTranslate: 'Translate subtitles',\n        sessionExpired: 'Your session expired. Sign in again.',\n        networkError: 'Network error. Try again.',\n        emptyGradingPreset:\n          'Could not interpret that look. Try \u201Cwarm\u201D, \u201Ccool\u201D, \u201Cnoir\u201D, or \u201Ccinematic\u201D.',\n      },\n      marketing: {\n        title: 'AI social marketing assistant',\n        intro:\n          'Uses timeline text and subtitles as the script. AI proposes viral titles, opening hooks, and ready-to-post social copy \u2014 copy them or add them to the timeline.',\n        scriptLabel: 'Script detected on the timeline',\n        words: 'words',\n        emptyScript:\n          'No subtitle or text clips on the timeline. Generate subtitles or add text so the assistant can draft your promo kit.',\n        analyze: 'Generate viral kit',\n        reanalyze: 'Generate again',\n        analyzing: 'Analyzing script\u2026',\n        tabTitles: 'Viral titles',\n        tabHooks: '3s hooks',\n        tabCopy: 'Social copy',\n        titlesHint: 'Short titles for thumbnails, Shorts, or Reels',\n        hooksHint: 'Opening lines for the first seconds of the video',\n        copyHint: 'Caption and hashtags ready to post',\n        copyAll: 'Copy all',\n        copied: 'Copied',\n        copyItem: 'Copy',\n        addToTimeline: 'Add to timeline',\n        addCopyToTimeline: 'Add copy to timeline',\n        toastAdded: 'Text added to the timeline',\n        emptyResult:\n          'The backend returned no titles, hooks, or copy. Check the [marketing-assistant] console log.',\n      },\n    },\n    playback: {\n      toStart: 'Go to start',\n      rewind: 'Rewind 1 second',\n      play: 'Play',\n      pause: 'Pause',\n      forward: 'Forward 1 second',\n      toEnd: 'Go to end',\n      loop: 'Loop',\n      fullscreen: 'Fullscreen',\n      exitFullscreen: 'Exit fullscreen',\n    },\n    imagePanel: {\n      filesTab: 'Files',\n      stockTab: 'Stock',\n      importOverlays: 'Import Graphic Overlays',\n      supports: 'PNG (transparent), JPG, WEBP',\n      noImages: 'No images imported',\n      dragHint: 'Drag PNG, JPG, or use Stock',\n    },\n    propertiesPanel: {\n      noClipSelected: 'No clip selected',\n      noClipSelectedBody: 'Select a clip on the timeline or in the preview to inspect and edit its properties.',\n      tabLayout: 'Layout',\n      tabColor: 'Color',\n      tabEffects: 'Effects',\n      sectionGeneral: 'General',\n      sectionTypography: 'Typography',\n      fontFamily: 'Font',\n      sectionAiBatch: 'AI Tools (Batch)',\n      sectionAiTextDesigner: 'AI Text Designer',\n      sectionFill: 'Fill',\n      sectionOutline: 'Outline',\n      sectionShadow: 'Shadow',\n      sectionPlate: 'Background plate',\n      sectionAnimations: 'Animations',\n      sectionImage: 'Image',\n      sectionAiCinematic: 'AI Cinematic Look',\n      sectionTransform: 'Transform',\n      sectionFlips: 'Flip',\n      sectionVideo: 'Video',\n      sectionEffects: 'Applied FX stack',\n      clipName: 'Clip name',\n      layer: 'Layer (track)',\n      layerUnknown: 'Unknown',\n      layerUp: 'Up',\n      layerDown: 'Down',\n      layerUpTitle: 'Move layer up',\n      layerDownTitle: 'Move layer down',\n      splitAtPlayhead: 'Split clip at playhead',\n      startSec: 'Start (sec)',\n      duration: 'Duration',\n      trimIn: 'Trim in',\n      trimOut: 'Trim out',\n      playbackSpeed: 'Playback speed',\n      speed025: '0.25x',\n      speed05: '0.50x',\n      speed1: '1.00x (Normal)',\n      speed15: '1.50x',\n      speed2: '2.00x',\n      speed4: '4.00x',\n      volume: 'Volume',\n      textContent: 'Text content',\n      textPlaceholder: 'Enter text\u2026',\n      weight: 'Weight',\n      weightLight: 'Light',\n      weightRegular: 'Regular',\n      weightMedium: 'Medium',\n      weightSemiBold: 'Semi-Bold',\n      weightBold: 'Bold',\n      weightExtraBold: 'Extra-Bold',\n      align: 'Align',\n      style: 'Style',\n      italic: 'Italic',\n      underline: 'Underline',\n      case: 'Case',\n      fontSize: 'Font size',\n      letterSpacing: 'Letter spacing',\n      opacity: 'Opacity',\n      positionX: 'Position X',\n      positionY: 'Position Y',\n      rotation: 'Rotation',\n      scale: 'Scale',\n      fillType: 'Fill type',\n      fillSolid: 'Solid color',\n      fillGradient: 'Gradient',\n      textColor: 'Text color',\n      gradientColor1: 'Gradient color 1',\n      gradientColor2: 'Gradient color 2',\n      gradientAngle: 'Gradient angle',\n      outlineEnable: 'Outline',\n      outlineSize: 'Outline size',\n      dropShadow: 'Drop shadow',\n      shadowColor: 'Shadow color',\n      shadowOpacity: 'Shadow opacity',\n      blurRadius: 'Blur radius',\n      offsetX: 'Offset X',\n      offsetY: 'Offset Y',\n      backgroundPlate: 'Background plate',\n      plateColor: 'Plate color',\n      plateOpacity: 'Plate opacity',\n      platePadding: 'Plate padding',\n      borderColor: 'Border color',\n      borderWidth: 'Border width',\n      borderRadius: 'Border radius',\n      introAnimation: 'Intro animation',\n      outroAnimation: 'Outro animation',\n      introDuration: 'Intro duration',\n      outroDuration: 'Outro duration',\n      animNone: 'None',\n      animFadeIn: 'Fade In',\n      animFadeOut: 'Fade Out',\n      animSlideUp: 'Slide Up',\n      animSlideDown: 'Slide Down',\n      animSlideLeft: 'Slide Left',\n      animSlideRight: 'Slide Right',\n      animScaleIn: 'Zoom Scale In',\n      animScaleOut: 'Zoom Scale Out',\n      animTypewriter: 'Typewriter Captions',\n      animBlurIn: 'Blur Reveal In',\n      animBlurOut: 'Blur Reveal Out',\n      animRotateIn: 'Rotate In',\n      sizingMode: 'Sizing mode',\n      fitFrame: 'Fit frame',\n      fillStretch: 'Fill / stretch',\n      zoomCrop: 'Zoom crop',\n      blendMode: 'Blend mode',\n      blendNormal: 'Normal',\n      blendScreen: 'Screen (Lighten)',\n      blendMultiply: 'Multiply (Darken)',\n      blendOverlay: 'Overlay',\n      blendDifference: 'Difference',\n      blendLuminosity: 'Luminosity',\n      flipHorizontal: 'Flip horizontal',\n      flipVertical: 'Flip vertical',\n      aiTranslate: 'Automatic translation',\n      aiTranslateBtn: 'Translate',\n      aiCreativeDesign: 'AI creative design',\n      aiStylePlaceholder: 'E.g. yellow MrBeast style\u2026',\n      aiTextStylePlaceholder: 'E.g. retro futuristic neon pink\u2026',\n      aiApplyStyle: 'Apply AI style',\n      aiColorFilter: 'AI color filter',\n      aiGradingPlaceholder: 'E.g. warm retro sunset\u2026',\n      aiApplyPreset: 'Apply AI preset',\n      langEnglish: 'English',\n      langSpanish: 'Spanish',\n      langPortuguese: 'Portuguese',\n      langFrench: 'French',\n      langGerman: 'German',\n      langItalian: 'Italian',\n      noSubtitlesError: 'No subtitles on the timeline.',\n      translateShapeError: 'AI translation response has an unexpected shape.',\n      reset: 'Reset',\n    },\n    colorGrading: {\n      tabBasic: 'Basic',\n      tabCurves: 'Curves',\n      tabHsl: 'HSL',\n      tabVignette: 'Vignette',\n      aiTitle: 'AI cinematic look',\n      aiPlaceholder: 'E.g. warm retro sunset\u2026',\n      aiApply: 'Apply',\n      aiNeedKey: 'Sign in to use AI color grading.',\n      exposure: 'Exposure',\n      contrast: 'Contrast',\n      highlights: 'Highlights',\n      shadows: 'Shadows',\n      temperature: 'Temperature',\n      tint: 'Tint',\n      vibrance: 'Vibrance',\n      saturation: 'Saturation',\n      channelMaster: 'Master',\n      channelRed: 'Red',\n      channelGreen: 'Green',\n      channelBlue: 'Blue',\n      hslHue: 'Hue',\n      hslSaturation: 'Saturation',\n      hslLuminance: 'Luminance',\n      enableVignette: 'Enable vignette',\n      vignetteAmount: 'Amount',\n      vignetteMidpoint: 'Midpoint',\n      vignetteFeather: 'Feather',\n      doubleClickDeletePoint: 'Double-click a point to delete it',\n    },\n    effectStack: {\n      emptyTitle: 'No effects on this clip',\n      emptyHint: 'Apply an effect from the Effects panel (double-click or Apply).',\n      hardwareNote: 'This effect runs with hardware rendering optimization.',\n      activeRange: 'Active range',\n      startTime: 'Start',\n      endTime: 'End',\n      enable: 'Enable effect',\n      disable: 'Disable effect',\n      remove: 'Remove effect',\n      addKeyframe: 'Add keyframe at playhead',\n      removeKeyframe: 'Remove keyframe at playhead',\n      direction: 'Direction',\n      zoomIn: 'Zoom in',\n      zoomOut: 'Zoom out',\n      reflection: 'Reflection',\n      reflectionH: 'Horizontal split',\n      reflectionV: 'Vertical split',\n      reflectionQuad: 'Four quadrant',\n      params: {\n        exposure: 'Exposure stops',\n        brightness: 'Brightness',\n        contrast: 'Contrast',\n        saturation: 'Saturation',\n        temperature: 'Temperature',\n        tint: 'Tint',\n        radius: 'Blur radius',\n        trackingNoise: 'Tracking noise',\n        colorBleed: 'Color bleed',\n        scanLines: 'Scan lines',\n        analogBrightness: 'Analog brightness',\n        amount: 'Offset',\n        blockSize: 'Block size',\n        sepiaIntensity: 'Sepia intensity',\n        scratchIntensity: 'Dust & scratches',\n        jitter: 'Frame jitter',\n        startScale: 'Start scale',\n        endScale: 'End scale',\n        startX: 'Start offset X',\n        startY: 'Start offset Y',\n        endX: 'End offset X',\n        endY: 'End offset Y',\n        frequency: 'Frequency',\n        intensity: 'Intensity',\n        zoomPeak: 'Zoom peak',\n        centerX: 'Center X',\n        centerY: 'Center Y',\n      },\n      names: {\n        'brightness-contrast': 'Brightness & contrast',\n        'hue-saturation': 'Hue / saturation',\n        'color-balance': 'Color balance',\n        curves: 'Curves',\n        levels: 'Levels',\n        exposure: 'Exposure',\n        'shadows-highlights': 'Shadows & highlights',\n        vibrance: 'Vibrance',\n        'color-temperature': 'Color temp & tint',\n        'selective-color': 'Selective color',\n        'channel-mixer': 'Channel mixer',\n        'gradient-map': 'Gradient map',\n        'lut-3d': '3D LUT',\n        'blur-gaussian': 'Gaussian blur',\n        'blur-motion': 'Motion blur',\n        'blur-radial': 'Radial blur',\n        sharpen: 'Sharpen',\n        'unsharp-mask': 'Unsharp mask',\n        glow: 'Glow',\n        bloom: 'Bloom',\n        vignette: 'Vignette',\n        'film-grain': 'Film grain',\n        'chromatic-aberration': 'Chromatic aberration',\n        scanlines: 'Scanlines',\n        pixelate: 'Pixelate',\n        posterize: 'Posterize',\n        threshold: 'Threshold',\n        emboss: 'Emboss',\n        'edge-detect': 'Edge detect',\n        duotone: 'Duotone',\n        halftone: 'Halftone',\n        'glitch-rgb': 'RGB glitch',\n        noise: 'Noise',\n        'old-film': 'Old film',\n        vhs: 'VHS filter',\n        'ken-burns': 'Ken Burns',\n        'zoom-dynamic': 'Dynamic zoom',\n        'camera-shake': 'Camera shake',\n        stabilize: 'Stabilize',\n        'speed-ramp': 'Speed ramp',\n        strobe: 'Strobe',\n        echo: 'Echo frame',\n        'time-freeze': 'Freeze frame',\n        transform: 'Transform',\n        'corner-pin': 'Corner pin',\n        'lens-distortion': 'Lens distortion',\n        mirror: 'Mirror',\n        flip: 'Flip H/V',\n        crop: 'Crop',\n      },\n    },\n    effectsLibrary: {\n      searchPlaceholder: 'Search effects\u2026',\n      createCustomTitle: 'Create custom effect',\n      apply: 'Apply',\n      applyHint: 'Double-click to apply to the selected clip',\n      noResults: 'No effects found',\n      noClipTitle: 'Nothing selected',\n      noClipBody: 'Select a timeline clip first to apply this effect.',\n      deletePreset: 'Delete preset',\n      presetBadge: 'Preset',\n      catAll: 'All',\n      catColor: 'Color',\n      catStylistic: 'Style',\n      catMotion: 'Motion',\n      catTransform: 'Transform',\n      catCustom: 'Custom',\n      nameRequiredTitle: 'Name required',\n      nameRequiredBody: 'Enter a name for the preset.',\n      cancel: 'Cancel',\n      createEffect: 'Create effect',\n      presetName: 'Preset name',\n      presetNamePlaceholder: 'e.g. My cinematic warmth',\n      description: 'Description',\n      descriptionPlaceholder: 'e.g. Soft lens blur with warm temperature tint',\n      category: 'Category',\n      baseEngine: 'Base effect engine',\n      configureParams: 'Configure preset parameters',\n      customPresetFallback: (type: string) => `Custom ${type} preset`,\n      catColorFull: 'Color correction',\n      catStylisticFull: 'Stylistic filter',\n      catMotionFull: 'Motion effect',\n      catTransformFull: 'Transform',\n      items: {\n        exposure: { name: 'Exposure', desc: 'Adjust stops of exposure' },\n        brightnessContrast: { name: 'Brightness & contrast', desc: 'Simple luminosity adjustments' },\n        hueSaturation: { name: 'Hue / saturation', desc: 'Correct saturation levels' },\n        colorTemperature: { name: 'Color temp & tint', desc: 'Cool or warm tint grading' },\n        blurGaussian: { name: 'Gaussian blur', desc: 'Smooth out frame detailing' },\n        vhs: { name: 'VHS filter', desc: 'Analog noise, flickers & bleed lines' },\n        oldFilm: { name: 'Old film', desc: 'Sepia tone + noise scratches' },\n        pixelate: { name: 'Pixelate', desc: 'Reduce pixel block sizing' },\n        chromaticAberration: { name: 'Chromatic aberration', desc: 'Chromatic glass shift' },\n        kenBurns: { name: 'Ken Burns', desc: 'Keyframeable pan & scale zoom' },\n        cameraShake: { name: 'Camera shake', desc: 'Simulate handheld tracking motion' },\n        zoomDynamic: { name: 'Dynamic zoom', desc: 'Rapid zoom punch in or out' },\n        mirror: { name: 'Mirror', desc: 'Mirror horizontally or vertically' },\n      },\n    },\n    textPanel: {\n      addText: 'Add text',\n      voiceAi: 'AI voice',\n      presetsTitle: 'Templates',\n      add: 'Add',\n      defaultText: 'Add your title here',\n      trackName: 'Text 1',\n      presets: {\n        lowerThirdClassic: { name: 'Classic lower third', desc: 'Elegant lower third' },\n        lowerThirdModern: { name: 'Modern lower third', desc: 'Clean sans-serif strip' },\n        lowerThirdMinimal: { name: 'Minimal lower third', desc: 'Simple text line' },\n        bigTitle: { name: 'Big title', desc: 'Huge bold title card' },\n        subtitlePair: { name: 'Subtitle pair', desc: 'Header + secondary subtitle' },\n        centeredMinimal: { name: 'Centered minimal', desc: 'Centered thin font' },\n        tiktokCaption: { name: 'TikTok caption', desc: 'Bright yellow centered cap' },\n        youtubeChapter: { name: 'YouTube chapter', desc: 'Top left corner chapter tag' },\n        instagramQuote: { name: 'Instagram quote', desc: 'Italic quote block' },\n        callOutBox: { name: 'Call-out box', desc: 'Framed pointer box' },\n        quoteCard: { name: 'Quote card', desc: 'Text in block backing' },\n      },\n    },\n    timeline: {\n      ripple: 'RIPPLE',\n      clipFallback: 'Clip',\n      tracksLabel: 'Tracks',\n      addLayer: 'Layer',\n      addLayerTitle: 'Add layer / track',\n      addTextLayer: '+ Text layer',\n      addSubtitleLayer: '+ Subtitle channel',\n      addImageLayer: '+ Image layer',\n      addVideoLayer: '+ Video layer',\n      addAudioLayer: '+ Audio layer',\n      resizeTracks: 'Resize tracks panel',\n      reorderLayerUp: 'Move layer up',\n      reorderLayerDown: 'Move layer down',\n      muteTrack: 'Mute track',\n      unmuteTrack: 'Unmute track',\n      hideTrack: 'Hide track',\n      showTrack: 'Show track',\n      lockTrack: 'Lock track',\n      unlockTrack: 'Unlock track',\n      deleteTrack: 'Delete track',\n      deleteTrackTitle: 'Delete track',\n      deleteTrackConfirm: (name: string) =>\n        `Delete track \"${name}\" and all its clips?`,\n      deleteTrackConfirmBtn: 'Delete',\n      deleteTrackCancel: 'Cancel',\n      contextTitle: 'Clip',\n      moveLayerUp: 'Move up a layer',\n      moveLayerDown: 'Move down a layer',\n      generateSubtitles: 'Generate subtitles',\n      transcribeUnsupportedFormat:\n        'Unsupported file format for transcription. Use MP4, MP3, WAV, or WEBM.',\n      generatingSubtitles: 'Generating subtitles\u2026',\n      generatingSubtitlesHint: 'Transcribing clip audio',\n      translatingSubtitles: 'Translating\u2026',\n      translatingSubtitlesHint: 'Applying the selected language',\n      stylingSubtitles: 'Applying style\u2026',\n      stylingSubtitlesHint: 'AI typography and look preset',\n      generatingVoiceover: 'Generating voiceover\u2026',\n      generatingVoiceoverHint: 'Synthesizing TTS on this track',\n      generatingCopy: 'Generating copy\u2026',\n      generatingCopyHint: 'Inserting text on this track',\n      split: 'Split',\n    },\n    timelineToolbar: {\n      currentTimeAria: 'Current time',\n      currentTimeTitle: (tc: string) => `Time: ${tc}`,\n      expandTimeline: 'Expand timeline',\n      collapseTimeline: 'Collapse timeline',\n      restoreSize: 'Restore size',\n      expandFullscreen: 'Expand to fullscreen',\n      undo: 'Undo',\n      undoTitle: 'Undo (Ctrl+Z)',\n      undoEmpty: 'Nothing to undo',\n      redo: 'Redo',\n      redoTitle: 'Redo (Ctrl+Shift+Z)',\n      redoEmpty: 'Nothing to redo',\n      split: 'Split clip at playhead',\n      splitTitle: 'Split clip at playhead (S)',\n      splitDisabled: 'Select a clip to split',\n      delete: 'Delete selected clip',\n      deleteDisabled: 'Select a clip to delete',\n      zoomOutVideo: 'Zoom out video',\n      zoomInVideo: 'Zoom in video',\n      zoomHorizontal: 'Horizontal video zoom',\n      zoomHorizontalTitle: (n: string) => `Video zoom: ${n} px/s`,\n      zoomOutTracks: 'Decrease track height',\n      zoomInTracks: 'Increase track height',\n      zoomVertical: 'Vertical track zoom',\n      zoomVerticalTitle: (n: number) => `Track height: ${n}px`,\n      resetTrackHeight: 'Reset track height',\n      deleteTitle: 'Delete',\n      cancel: 'Cancel',\n      confirmDelete: 'Delete',\n      unnamedClip: 'Unnamed clip',\n      deleteOne: (name: string) =>\n        `Are you sure you want to delete the clip \"${name}\"? This cannot be undone.`,\n      deleteMany: (n: number, names: string) =>\n        `Are you sure you want to delete ${n} clips (\"${names}\")? This cannot be undone.`,\n    },\n  },\n  draggablePanel: {\n    closeAria: 'Close panel',\n    closeTitle: 'Close panel',\n    resetAria: 'Reset position',\n    resetTitle: 'Reset position',\n  },\n  panel: {\n    assets: 'Assets',\n    overlay: 'Overlay',\n    inspector: 'Inspector',\n    transitions: 'Transitions',\n    effects: 'Effects',\n    text: 'Text',\n    pin: 'Pin panel (above the timeline)',\n    unpin: 'Unpin panel (below the timeline)',\n    resetWidth: 'Reset width',\n    resetSize: 'Reset size',\n    closePanel: 'Close panel',\n    edit: 'Edit',\n    layersAndPages: 'Layers & pages',\n    layersShort: 'Layers',\n    resetSizeAndPosition: 'Reset size and position',\n    resizeWidth: 'Drag to change width',\n    resizeHeight: 'Drag to change height',\n    selectElement: 'Select an element',\n    selectObjectForProps: 'Select an object on the canvas to see its properties.',\n    color: 'Color',\n    masterFill: 'Fill color (foreground)',\n    masterStroke: 'Stroke color (background)',\n    swapColors: 'Swap fill and stroke (X)',\n    saturationBrightness: 'Saturation / brightness',\n    hue: 'Hue',\n    hexInput: 'Hex color',\n    colorPicker: 'Color picker',\n    noColor: 'No color',\n    transparent: 'Transparent',\n  },\n  properties: {\n    text: {\n      transformTitle: 'Transform',\n      rotation: 'Rotation',\n      typography: 'Typography',\n      searchFonts: 'Search fonts\u2026',\n      myFonts: 'My fonts',\n      fontSize: 'Font size',\n      style: 'Style',\n      bold: 'Bold',\n      italic: 'Italic',\n      underline: 'Underline',\n      strikethrough: 'Strikethrough',\n      overline: 'Overline',\n      color: 'Color',\n      fillText: 'Text',\n      outline: 'Outline',\n      usesMasterColor: 'Fill and outline use the Color panel (above).',\n      thickness: 'Thickness',\n      alignment: 'Alignment',\n      lineHeight: 'Line height',\n      letterSpacing: 'Letter spacing',\n      textCurvature: 'Text curvature',\n      textShadow: 'Text shadow',\n      blur: 'Blur',\n      offsetX: 'Offset X',\n      offsetY: 'Offset Y',\n      noTextSelected: 'Select a text box on the canvas to edit its properties.',\n      activateTextTool: 'Activate text tool',\n      addTextToCanvas: 'Add text to canvas',\n      addTitle: 'Add a title',\n      addSubtitle: 'Add a subtitle',\n      addBodyText: 'Add body text',\n      loremGenerator: 'Lorem Ipsum generator',\n      loremHint: 'Generates placeholder text. If a text box is selected, it replaces its content.',\n      loremWords: 'Words',\n      loremSentences: 'Sentences',\n      loremParagraphs: 'Paragraphs',\n      loremAmount: 'Amount',\n      loremApply: 'Insert / replace Lorem Ipsum',\n      uploadFonts: 'Upload custom fonts',\n      supportedFormats: 'Supports TTF, OTF, WOFF and WOFF2 files.',\n      uploadFontFile: 'Upload font file',\n      uploadHint: 'Supports TTF, OTF, WOFF',\n      loadedFonts: 'Loaded fonts',\n      deleteFontTitle: 'Delete',\n      tabProperties: 'Properties',\n      tabInsert: 'Insert',\n      tabLorem: 'Lorem',\n      tabFonts: 'Fonts',\n      editorTitle: 'Text editor',\n      fontCategory: {\n        sansSerif: 'Sans-Serif',\n        serif: 'Serif',\n        display: 'Display / Titles',\n        handwriting: 'Handwriting',\n        monospace: 'Monospace',\n      },\n    },\n    image: {\n      photoFilters: 'Photo filters',\n      photoFiltersSubtitle: 'Pro-grade fine image adjustments powered by WebGL acceleration.',\n      photoAdjustments: 'Photo adjustments',\n      exposure: 'Exposure',\n      brightness: 'Brightness',\n      contrast: 'Contrast',\n      saturation: 'Saturation',\n      hue: 'Hue (Colors)',\n      blur: 'Blur',\n      invertColors: 'Invert colors',\n      proAdjustments: 'Pro adjustments',\n      levels: 'Levels',\n      levelsShadows: 'Shadows',\n      levelsMids: 'Mids',\n      levelsHighlights: 'Highlights',\n      curves: 'Curves',\n      curvesRgb: 'RGB curve',\n      curvesReset: 'Reset',\n      curvesHint: 'Click to add points. Drag them to edit.',\n      quickPresets: 'Quick filter presets',\n      specialEffects: 'Special effects & modes',\n      blendMode: 'Blend mode',\n      hsl: 'Selective color (HSL)',\n      selectImageHint: 'Select an image to apply filters.',\n      preset: {\n        original: 'Original',\n        grayscale: 'B&W',\n        sepia: 'Sepia',\n        vintage: 'Vintage',\n        cyberpunk: 'Cyberpunk',\n        polar: 'Polar (Cool)',\n        sunset: 'Sunset',\n        fade: 'Fade',\n        noir: 'Noir',\n      },\n      blend: {\n        normal: 'Normal',\n        multiply: 'Multiply',\n        screen: 'Screen',\n        overlay: 'Overlay',\n        darken: 'Darken',\n        lighten: 'Lighten',\n        difference: 'Difference',\n        exclusion: 'Exclusion',\n        colorDodge: 'Color dodge',\n        colorBurn: 'Color burn',\n      },\n      effect: {\n        none: 'None',\n        softDrop: 'Soft drop',\n        hardDrop: 'Hard drop',\n        elevate: 'Elevate',\n        neonGlow: 'Neon glow',\n        glassmorphism: 'Glassmorphism',\n      },\n      resetAll: 'Reset',\n      compareOriginal: 'Viewing original',\n      compareHold: 'Hold to compare',\n    },\n    shape: {\n      adjustShape: 'Adjust shape',\n      editShapeHint: 'Edit the selected shape on the canvas. Use the \"Shapes\" button on the bottom panel to add new ones.',\n      width: 'Width (W)',\n      height: 'Height (H)',\n      geometry: 'Geometry & position',\n      positionX: 'X position',\n      positionY: 'Y position',\n      shapeFill: 'Shape fill',\n      fillColor: 'Fill',\n      fillSolid: 'Solid',\n      fillGradient: 'Gradient',\n      fillNone: 'None',\n      fillNoneMessage: 'The shape has no fill color (transparent).',\n      usesMasterFill: 'Solid fill uses the Color panel fill color.',\n      usesMasterStroke: 'Stroke uses the Color panel border color.',\n      imageColors: 'Image colors',\n      start: 'Start',\n      end: 'End',\n      gradientAngle: 'Gradient angle',\n      stroke: 'Stroke & line',\n      strokeColor: 'Stroke',\n      strokeThickness: 'Stroke thickness',\n      strokeStyle: 'Stroke style',\n      strokeSolid: 'Solid',\n      strokeDashed: 'Dashed',\n      strokeDotted: 'Dotted',\n      cornerRadius: 'Corner radius',\n      cornerAll: 'All',\n      cornerTL: 'Top left',\n      cornerTR: 'Top right',\n      cornerBL: 'Bottom left',\n      cornerBR: 'Bottom right',\n      cornerLink: 'Link corners',\n      cornerUnlink: 'Unlink corners',\n      objectShadow: 'Object shadow',\n      shadowColor: 'Color',\n      shadowBlur: 'Blur',\n      effects: 'Special effects & presets',\n      opacity: 'Opacity',\n      blendMode: 'Blend mode',\n      scale: 'Scale',\n      scale1x: '1x',\n      scale2x: '2x (Retina)',\n      scale3x: '3x (HD)',\n      format: 'Format',\n      downloadLayer: 'Download layer',\n      export: 'Export',\n      exportPreview: 'Preview',\n      exportSelection: 'Export selection (Figma-style)',\n      shapeBadge: {\n        vector: 'Vector',\n        rect: 'Rectangle',\n        frame: 'Frame',\n      },\n    },\n  },\n  layers: {\n    tabLayers: 'Layers',\n    tabPages: 'Pages',\n    noLayers: 'No layers yet.',\n    noLayersHint: 'Use the left sidebar to add elements to the canvas.',\n    layerType: {\n      group: 'Group',\n      text: (preview: string) => `Text: \"${preview}\"`,\n      textTruncated: (preview: string) => `Text: \"${preview}...\"`,\n      image: 'Image',\n      pixel: 'Pixel layer',\n      rect: 'Rectangle',\n      circle: 'Circle',\n      triangle: 'Triangle',\n      path: 'Free stroke',\n      line: 'Line',\n      element: 'Element',\n    },\n    maskBadge: 'Mask',\n    pixelBadge: 'Pixels',\n    pixelLayerBase: 'layer',\n    duplicatedOf: (name: string) => `duplicate of ${name}`,\n    cannotDeleteBaseLayer: 'The only remaining layer cannot be deleted.',\n    cannotDeleteLastLayer: 'The only remaining layer cannot be deleted.',\n    mustSelectLayer: 'Select a layer to use this tool.',\n    alreadyRaster: 'This layer is already a pixel layer.',\n    rasterizeFailed: 'Could not rasterize the layer.',\n    rasterize: 'Rasterize',\n    rasterizeTitle: 'Convert to pixel layer (bitmap)',\n    newLayer: 'New layer',\n    newLayerTitle: 'Create blank pixel layer',\n    duplicateLayerTitle: 'Duplicate active layer',\n    maskComingSoon: 'Layer mask (coming soon)',\n    linkedTitle: 'Linked object',\n    tooltip: {\n      rename: 'Double-click to rename layer',\n      moveUp: 'Move up',\n      moveDown: 'Move down',\n      hide: 'Hide layer',\n      show: 'Show layer',\n      unlock: 'Unlock',\n      lock: 'Lock',\n      addMask: 'Add mask',\n      removeMask: 'Remove mask',\n      paintMask: 'Edit mask',\n      paintContent: 'Edit layer',\n      delete: 'Delete layer',\n      rasterize: 'Rasterize',\n    },\n    group: 'Group',\n    ungroup: 'Ungroup',\n    groupTooltip: 'Group layers (Cmd+G)',\n    ungroupTooltip: 'Ungroup layers (Cmd+Shift+G)',\n    pages: {\n      clearCanvasTitle: 'Clear canvas',\n      clearCanvasBody: 'Are you sure you want to clear the canvas on this page? This cannot be undone.',\n      clearCanvasConfirm: 'Clear',\n      moveUp: 'Move up',\n      moveDown: 'Move down',\n      duplicate: 'Duplicate page',\n      clear: 'Clear page',\n      delete: 'Delete page',\n      deleteTitle: 'Delete page',\n      deleteBody: (name: string) =>\n        `Delete page \"${name}\"? This cannot be undone.`,\n      deleteConfirm: 'Delete',\n      addNew: 'Add new page',\n      addNewTitle: 'Add new page',\n      sizeLabel: (w: number, h: number) => `${w} x ${h} px`,\n    },\n    deleteLayerTitle: 'Delete layer',\n    deleteLayerBody: (name: string) =>\n      `Delete layer \"${name}\"? This cannot be undone.`,\n    deleteLayerConfirm: 'Delete',\n    collapse: {\n      show: 'Show layers',\n      hide: 'Hide layers',\n    },\n  },\n  sidebar: {\n    tab: {\n      canvas: 'Configure canvas',\n      upload: 'Upload image',\n      shapes: 'Add shapes',\n      brush: 'Brush / draw',\n      filtros: 'Image filters',\n      brand: 'Brand kit & colors',\n    },\n    stock: {\n      title: 'Premium stock gallery',\n      subtitle: 'Millions of royalty-free images from Unsplash and Pexels.',\n      searchPlaceholder: 'Search images\u2026',\n      emptyResults: 'No results. Try another search.',\n      poweredBy: (provider: string) => `Powered by ${provider.charAt(0).toUpperCase()}${provider.slice(1)}`,\n      noImageHint: 'Select an image on the canvas to adjust its filters.',\n    },\n    stockCategory: {\n      trending: 'Trending',\n      naturaleza: 'Nature',\n      tecnologia: 'Technology',\n      arquitectura: 'Architecture',\n      personas: 'People',\n      abstracto: 'Abstract',\n      ciudad: 'City',\n      espacio: 'Space',\n    },\n    brushPreset: {\n      calligraphy: 'Calligraphy brush',\n      highlighter: 'Yellow highlighter',\n      chalk: 'Soft chalk',\n      neonMagenta: 'Neon magenta',\n      neonCyan: 'Neon cyan',\n    },\n    stockBgPreset: {\n      studioWhite: 'Studio white',\n      sunsetGlow: 'Sunset glow',\n      oceanBlue: 'Ocean blue',\n      forestGreen: 'Forest green',\n      marble: 'Marble',\n      darkConcrete: 'Dark concrete',\n      pastelPink: 'Pastel pink',\n      deepPurple: 'Deep purple',\n      goldenHour: 'Golden hour',\n      nightSky: 'Night sky',\n    },\n    stockLayer: {\n      product: 'Product',\n      person: 'Person',\n      scenery: 'Scenery',\n    },\n    brand: {\n      title: 'Brand kit & colors',\n      subtitle: 'Generate color harmonies and save your palettes to keep your brand consistent.',\n      harmonyGenerator: 'Harmony generator',\n      baseColorLabel: 'Base color (HEX)',\n      baseColorTooltip: 'Change base color',\n      harmonyRuleLabel: 'Harmony rule',\n      harmony: {\n        complementary: 'Complementary',\n        analogous: 'Analogous',\n        triadic: 'Triadic',\n        splitComplementary: 'Split complementary',\n        tetradic: 'Tetradic',\n        monochromatic: 'Monochromatic',\n      },\n      harmonyName: {\n        complementary: 'Complementary harmony',\n        analogous: 'Analogous harmony',\n        triadic: 'Triadic harmony',\n        splitComplementary: 'Split-comp. harmony',\n        tetradic: 'Tetradic harmony',\n        monochromatic: 'Monochromatic harmony',\n        fallback: 'Generated palette',\n      },\n      edit: 'EDIT',\n      savePalette: '+ Save palette',\n      savedPalettes: 'Saved palettes',\n      addPalette: 'Add palette',\n      addShort: 'Add',\n      newPalette: 'New palette',\n      noPalettes: \"You haven't saved any palettes yet.\",\n      paletteNamePlaceholder: 'Palette',\n      brandPaletteName: (brandName: string) =>\n        brandName?.trim() ? `Brand: ${brandName.trim()}` : 'Brand colors',\n      tooltipAddColor: 'Add color',\n      tooltipDeletePalette: 'Delete palette',\n      tooltipEditColor: 'Edit color',\n    },\n  },\n  canvas: {\n    toolstrip: {\n      select: 'Select (V)',\n      hand: 'Hand / pan (H)',\n      text: 'Text (T)',\n      back: 'Back',\n      background: 'Canvas background',\n      paintBucket: 'Paint bucket (G)',\n      brush: 'Brush (B)',\n      magicEraser: 'Magic eraser',\n      eraserMenu: 'Eraser tools',\n      eraserGroup: 'Eraser',\n      shapes: 'Shapes',\n      frames: 'Frames & mockups',\n      aiStudio: 'AI Studio',\n      upload: 'Upload image',\n      canvasSize: 'Canvas size',\n      grid: 'Grid',\n      showRulers: 'Show rulers',\n      hideRulers: 'Hide rulers',\n      colorblind: 'Color-blindness simulator',\n      crop: 'Crop image',\n      cropDisabled: 'Select an image to crop',\n      cropDisabledLastLayer: 'Cannot crop the only remaining layer',\n      cloneStamp: 'Clone stamp (S)',\n      magicWand: 'Magic wand (W)',\n      pixelLasso: 'Freehand lasso (L)',\n      polygonLasso: 'Polygonal lasso (O)',\n      eraser: 'Eraser (E)',\n      selectRect: 'Rectangular lasso',\n      selectEllipse: 'Circular lasso',\n      selectLasso: 'Freehand object lasso',\n      selectMenu: 'Selection tools',\n      lassoMenu: 'Lasso tools',\n      lassoGroup: 'Lasso',\n      selectAria: 'Select',\n      handAria: 'Hand / pan',\n      textAria: 'Text',\n      backgroundAria: 'Canvas background',\n      paintBucketAria: 'Paint bucket',\n      sizeAria: 'Canvas size',\n      gridAria: 'Grid options',\n      rulersAriaShow: 'Show rulers',\n      rulersAriaHide: 'Hide rulers',\n      colorblindAria: 'Color-blindness simulator',\n      backgroundTitle: (color: string) => `Background: ${color}`,\n      sizeTitle: (w: number, h: number) => `${w} \u00D7 ${h} px`,\n    },\n    uploadPanel: {\n      title: 'Upload image',\n      tabDevice: 'From device',\n      tabFiles: 'My files',\n      tabStock: 'Stock images',\n      dragDrop: 'Click or drag here \u2014 PNG, JPG, JPEG, SVG (max 25MB)',\n      dragDropActive: 'Drop your images here!',\n      urlLabel: 'URL',\n      urlPlaceholder: 'https://example.com/image.png',\n      urlImageName: 'Image URL',\n      insert: 'Insert',\n      historyHeader: (count: number) => `Your images (${count})`,\n      clearAll: 'Clear all',\n      clearHistoryTitle: 'Clear history',\n      clearHistoryBody: 'Do you want to clear your entire upload history? Locally saved images will be deleted.',\n      clearHistoryConfirm: 'Clear',\n      tooltipDeleteAsset: 'Remove from uploads',\n      brandImagesHeader: 'Brand images',\n      brandLogosHeader: 'Brand logos',\n      jobsHeader: 'Generations and files',\n      filesEmpty: 'No remote images available yet.',\n      stockSearchPlaceholder: 'Search stock\u2026',\n      stockEmpty: 'No results. Try another search.',\n      stockLoading: 'Loading\u2026',\n      stockHeader: 'Illustrative stock resources',\n      stockMoreTitle: 'Browse more stock images',\n      stockMoreButton: 'More',\n    },\n    gridPanel: {\n      title: 'Layout grid',\n      activate: 'Enable grid',\n      deactivate: 'Disable grid',\n      type: 'Type',\n      columns: 'Columns (12)',\n      modular: 'Modular (px)',\n      columnCount: 'Number of columns',\n      gutter: 'Gutter',\n      margin: 'Margin',\n      gridSize: 'Grid size',\n      gridColor: 'Grid color',\n      colorPink: 'Pink',\n      colorBlue: 'Blue',\n      colorRed: 'Red',\n      colorGray: 'Gray',\n    },\n    aiStudio: {\n      title: 'AI Studio',\n      processing: 'Processing\u2026',\n      tab: {\n        enhancements: 'Enhancements',\n        generador: 'Generator',\n        copilot: 'Copilot',\n        copywriter: 'Copywriter',\n        fondo: 'Backgrounds',\n      },\n      enhancements: {\n        intro: 'AI-powered automatic image enhancements. Requires an image to be selected on the canvas.',\n        autoEnhance: 'Magic auto-enhance',\n        upscale2x: 'Upscale 2x',\n        variations: 'Variations',\n        imageToolsHeader: 'Image tools',\n        removeBg: 'Remove background',\n        separateSubject: 'Separate subject into new layer',\n        modifyPlaceholder: \"e.g. 'make it cyberpunk'\",\n        apply: 'Apply',\n        noImage: 'Select an image on the canvas to enable these tools.',\n      },\n      generador: {\n        intro: 'Generate images with AI from a text description.',\n        promptPlaceholder: 'Describe the image you want\u2026 (e.g. space cat drinking coffee)',\n        aspectLabel: 'Aspect ratio',\n        resolutionLabel: 'Resolution',\n        referencesAdd: 'Upload reference',\n        generate: 'Generate AI image',\n        generating: 'Generating image\u2026',\n        inAreaHeader: 'Generate in selected area',\n        inAreaPlaceholder: \"e.g. 'spring flower field'\",\n        generateInArea: 'Generate in this area',\n        generatingInArea: 'Generating\u2026',\n      },\n      copilot: {\n        title: 'AI Design Copilot',\n        intro: 'Modify the canvas, text, shapes or photo filters on the active selection using natural language.',\n        activeObject: (type: string) => `Active object: ${type.toUpperCase()}`,\n        noSelection: 'No selection \u2014 will modify the canvas background',\n        placeholder: \"e.g. 'big bright pink neon text'\u2026\",\n        apply: 'Apply AI design',\n        applying: 'Applying design\u2026',\n        geminiKeyLabel: 'Gemini API key',\n        apiActive: 'API active',\n        localFallback: 'Local fallback',\n        geminiKeyPlaceholder: 'Enter your Google API key\u2026',\n        geminiKeyHint: 'Enable the Gemini model for premium creation and editing.',\n      },\n      copywriter: {\n        intro: 'Generate 3 professional copy options with AI. Click one to apply it.',\n        promptPlaceholder: \"e.g. 'coffee offer', 'creative slogan'\",\n        write: 'Write',\n        brandHint: (name: string) => `Using brand style: ${name}`,\n        brandMissing: 'No active brand \u2014 copy will not use brand tone.',\n        selectHint: 'Select a suggestion:',\n        apply: 'Apply \u2192',\n        styles: {\n          comercial: 'Persuasive / commercial',\n          creativa: 'Original / creative',\n          directa: 'Clear / direct',\n        },\n      },\n      fondo: {\n        intro: 'Generate artistic AI backgrounds for your canvas.',\n        scenePresetLabel: 'Scene preset',\n        presets: {\n          empty: '-- Pick a quick style --',\n          studioPremium: 'Premium studio',\n          minimalistOffice: 'Minimalist office',\n          sunsetBeach: 'Sunset beach',\n          cyberpunkCity: 'Cyberpunk city at night',\n          fantasyForest: 'Fantasy forest',\n          elegantMarble: 'Elegant marble',\n        },\n        customDescriptionLabel: 'Custom description',\n        customPlaceholder: \"e.g. 'magical forest at sunset'\",\n        blendWithSubject: 'Blend with selected subject',\n        fill: 'AI fill background',\n        filling: 'Generating background\u2026',\n      },\n    },\n    frames: {\n      title: 'Frames & mockups',\n      description: 'Click a frame to draw it. Drag an image onto it to fit (Drag-to-Fit).',\n      devicesHeader: 'Devices',\n      mediaHeader: 'Physical media',\n      webHeader: 'Web & interface',\n      abstractHeader: 'Abstract shapes',\n      device: {\n        mobile: 'Mobile',\n        tablet: 'Tablet',\n        laptop: 'Laptop',\n        desktop: 'Monitor',\n        watch: 'Watch',\n      },\n      physical: {\n        polaroid: 'Polaroid',\n        gallery: 'Gallery',\n        billboard: 'Billboard',\n        poster: 'Poster',\n        businessCard: 'Business card',\n      },\n      web: {\n        browser: 'Browser',\n        video: 'Video',\n        chat: 'Chat',\n      },\n      abstract: {\n        circle: 'Circle',\n        arch: 'Arch',\n        hexagon: 'Hexagon',\n        heart: 'Heart',\n        blob: 'Blob',\n        pill: 'Pill',\n        diamond: 'Diamond',\n        starPro: 'Star',\n      },\n    },\n    brush: {\n      glowTitle: 'Glow effect',\n      glowRadius: 'Glow radius',\n      glowColor: 'Glow color',\n      configTitle: 'Brush settings',\n      style: 'Brush style',\n      styleOptions: {\n        pencil: 'Classic',\n        calligraphy: 'Calligraphy',\n        highlighter: 'Highlighter',\n        chalk: 'Chalk',\n        spray: 'Spray',\n        circle: 'Bubbles',\n        magicEraser: 'AI eraser',\n      },\n      colorAria: 'Stroke color and opacity',\n      colorRgba: 'Color (RGBA)',\n      opacity: 'Opacity (alpha)',\n      presets: 'Style presets',\n      presetDefault: 'Preset',\n      widthLabel: 'Brush width',\n      radiusPopupTitle: 'Brush radius',\n      radiusSlider: 'Adjust radius',\n      radiusInput: 'Radius',\n      smoothingLabel: 'Stroke smoothing',\n      pressure: 'Pressure sensitivity',\n    },\n    booleanOps: {\n      union: 'Union',\n      subtract: 'Subtract',\n      intersect: 'Intersect',\n    },\n    pen: {\n      pathHint:\n        'Drawing path: click to add nodes. Click the first node or press Enter to finish.',\n    },\n    magicWand: {\n      title: 'Magic wand',\n      hint: 'Click an image to select similar-colored pixels. Adjust tolerance, then delete, fill, or extract.',\n      properties: 'Properties',\n      selectionMode: 'Selection mode',\n      addMode: 'Add',\n      subtractMode: 'Subtract',\n      addModeHint: 'Add to selection (Shift)',\n      subtractModeHint: 'Subtract from selection (Ctrl)',\n      modifierHint: 'Shortcuts: Shift = add \u00B7 Ctrl = subtract',\n      tolerance: 'Tolerance',\n      resetTolerance: 'Reset tolerance',\n      contiguous: 'Contiguous',\n      fillColor: 'Fill color',\n      fillUsesMaster: 'Fill uses the Color panel fill (foreground) color.',\n      noSelection: 'No selection \u2014 click the image.',\n      selectedPixels: (n: number) => `${n.toLocaleString('en-US')} pixels selected`,\n      actions: 'Actions',\n      delete: 'Delete selection',\n      fill: 'Fill selection',\n      cutToLayer: 'Extract to new layer',\n      deselect: 'Deselect',\n      toasts: {\n        deleted: 'Selection deleted',\n        filled: 'Selection filled',\n        cut: 'Selection extracted to new layer',\n      },\n    },\n    paintBucket: {\n      title: 'Paint bucket',\n      hint: 'Click an image to fill with the Color panel fill color. Adjust tolerance, contiguous, and anti-alias.',\n      properties: 'Properties',\n      fillColor: 'Fill color',\n      opacity: 'Opacity',\n      tolerance: 'Tolerance',\n      resetTolerance: 'Reset tolerance',\n      contiguous: 'Contiguous',\n      antiAlias: 'Anti-alias',\n      noImage: 'Click an image to fill.',\n      readError: 'Cannot read pixels from this image (CORS or empty image).',\n      fillError: 'Paint bucket fill failed.',\n    },\n    pixelLasso: {\n      title: 'Freehand lasso',\n      hint: 'Drag over the image to select pixels. Use + / \u2212 or Shift / Ctrl to add or subtract.',\n      noSelection: 'No selection \u2014 draw a lasso over the image.',\n    },\n    rectLasso: {\n      title: 'Rectangular lasso',\n      hint: 'Drag a rectangle over the image to select pixels. Use + / \u2212 or Shift / Ctrl to add or subtract.',\n      noSelection: 'No selection \u2014 drag a rectangle over the image.',\n    },\n    ellipseLasso: {\n      title: 'Circular lasso',\n      hint: 'Drag an ellipse over the image to select pixels. Use + / \u2212 or Shift / Ctrl to add or subtract.',\n      noSelection: 'No selection \u2014 drag an ellipse over the image.',\n    },\n    polygonLasso: {\n      title: 'Polygonal lasso',\n      hint: 'Click to place vertices. Close by clicking the first point, double-click, or Enter. Escape cancels.',\n      noSelection: 'No selection \u2014 place points on the image and close the polygon.',\n    },\n    eraser: {\n      title: 'Eraser',\n      hint: 'Paint over an image to erase pixels (transparency).',\n      brush: 'Brush',\n      rightClickHint: 'Right-click: adjust eraser radius.',\n    },\n    magicEraserPanel: {\n      title: 'Magic eraser',\n      hint: 'Mark what to remove, then confirm with the check. X cancels the marks.',\n      loading: 'Removing selection',\n    },\n    cloneStamp: {\n      title: 'Clone stamp',\n      hint: 'Alt + click to set the source. Then paint to clone.',\n      brush: 'Brush',\n      rightClickHint: 'Right-click: adjust brush radius.',\n    },\n    colorblind: {\n      title: 'Color-blindness simulator',\n      modes: {\n        normal: 'Normal',\n        protanopia: 'Protanopia',\n        deuteranopia: 'Deuteranopia',\n        tritanopia: 'Tritanopia',\n      },\n    },\n    bgPanel: {\n      title: 'Canvas background',\n      tabSolid: 'Solid',\n      tabGradient: 'Gradient',\n      tabTextures: 'Textures',\n      brandColors: 'Brand colors',\n      imageColors: 'Image colors',\n      customColor: 'Custom',\n      transparent: 'Transparent',\n      gradientBuilder: 'Gradient builder',\n      gradientStart: 'Start',\n      gradientEnd: 'End',\n      gradientAngle: 'Direction / angle',\n      textureSwatch: 'Texture swatches',\n      uploadCustom: 'Upload custom texture',\n      uploadFile: 'Upload image file',\n      urlLoad: 'Load from URL',\n      urlPlaceholder: 'https://example.com/background.jpg',\n    },\n    sizePanel: {\n      title: 'Adjust canvas',\n      tabDimensions: 'Dimensions',\n      tabFormats: 'Formats',\n      tabColor: 'Color',\n      width: 'Width',\n      height: 'Height',\n      lockRatio: 'Lock aspect ratio',\n      unlockRatio: 'Unlock aspect ratio',\n      unit: 'Unit',\n      orientation: 'Orientation',\n      horizontal: 'Horizontal',\n      vertical: 'Vertical',\n      catSocial: 'Social',\n      catWeb: 'Web',\n      catPrint: 'Print',\n    },\n    shapesPanel: {\n      title: 'Shapes',\n      tabFigures: 'Figures',\n      tabShapes: 'Shapes',\n      tabCharts: 'Charts',\n      tabQrCode: 'QR & Code',\n      basicFigures: 'Basic figures',\n      rect: 'Rectangle',\n      rounded: 'Rounded',\n      circle: 'Circle',\n      ellipse: 'Ellipse',\n      line: 'Line',\n      polygonsAndStars: 'Polygons and stars',\n      triangle: 'Triangle',\n      hexagon: 'Hexagon',\n      star: 'Star',\n      specialFigures: 'Special figures',\n      arrow: 'Arrow',\n      heart: 'Heart',\n      speechBubble: 'Speech bubble',\n      cross: 'Cross',\n      editableCharts: 'Editable charts',\n      editChartHint: 'Double-click a chart on the canvas to edit its data.',\n      insertBarChart: 'Insert bar chart',\n      insertLineChart: 'Insert line chart',\n      insertPieChart: 'Insert pie chart',\n      insertDonutChart: 'Insert donut chart',\n      chartBar: 'Bar',\n      chartLine: 'Line',\n      chartPie: 'Pie',\n      chartDonut: 'Donut',\n      qrGenerator: 'QR generator',\n      barcodeGenerator: 'Barcode generator',\n      qrPlaceholder: 'URL, text, vCard...',\n      barcodePlaceholder: 'E.g. 123456789 (CODE128)',\n      insertQr: 'Insert QR code',\n      insertBarcode: 'Insert barcode',\n    },\n    eyedropper: {\n      paint: 'Paint:',\n      pageBackground: 'Page background',\n      invalidImage: 'Invalid (Image)',\n      selectedText: 'Selected text',\n      selectedShape: 'Selected shape',\n      pickColor: 'Eyedropper',\n      pickFillHint: 'I \u00B7 sample fill',\n      pickStrokeHint: 'I + Shift \u00B7 sample stroke',\n      cancelSpaceHint: 'Space to cancel',\n    },\n    finishCropMask: 'Finish mask crop',\n    magicEraserActive: 'Magic Eraser active',\n    magicEraserCleaning: 'Removing selection',\n    magicEraserApply: 'Apply smart clean',\n    magicEraserClearMarks: 'Clear marks',\n    contextMenu: {\n      objectActions: 'Object actions',\n      duplicate: 'Duplicate',\n      unlock: 'Unlock',\n      lock: 'Lock',\n      organizeLayers: 'Arrange layers',\n      bringToFront: 'Bring to front',\n      bringForward: 'Bring forward',\n      sendBackward: 'Send backward',\n      sendToBack: 'Send to back',\n      stylesAndMasks: 'Styles & masks',\n      copyStyle: 'Copy style',\n      pasteStyle: 'Paste style',\n      quickMask: 'Quick mask (1-click)',\n      maskCircle: 'Circle',\n      maskCircleTitle: 'Circle mask',\n      maskRounded: 'R-Rect',\n      maskRoundedTitle: 'Rounded rectangle',\n      maskHeart: 'Heart',\n      maskHeartTitle: 'Heart mask',\n      maskStar: 'Star',\n      maskStarTitle: 'Star mask',\n      maskTriangle: 'Tri.',\n      maskTriangleTitle: 'Triangle mask',\n      smartLinking: 'Smart linking',\n      link: 'Link',\n      unlink: 'Unlink',\n      createMask: 'Create mask',\n      createMaskHint: 'Shift+Click photo + shape',\n      createMaskTitle: 'To create a mask, select an image and a geometric shape while holding Shift.',\n      releaseMask: 'Release mask',\n      groupLayers: 'Group layers',\n      ungroup: 'Ungroup',\n      aiMagic: 'AI Magic',\n      maskEditing: 'Edici\u00F3n de m\u00E1scara',\n      removeBg: 'Remove background (AI)',\n      separateSubject: 'Separate subject (AI)',\n      generateInArea: 'Generate in area (AI)',\n      generateInAreaPrompt: 'Enter a prompt to generate an image in this area:',\n      sketchToImage: 'Sketch to image (AI)',\n      sketchToImagePrompt: 'Enter a prompt to transform the sketch:',\n      convertToCurves: 'Convert to curves (Path)',\n      convertError: 'Could not convert text to vector.',\n      convertErrorTitle: 'Conversion error',\n      convertCustomOnly: 'Curve conversion is only available for custom (uploaded) fonts.',\n      convertCustomOnlyTitle: 'Custom fonts',\n      textOnPath: 'Place text on path',\n      textMask: 'Text mask (clip)',\n      copyObject: 'Copy object',\n      exportLayer: 'Export layer',\n      delete: 'Delete',\n      generalActions: 'General actions',\n      paste: 'Paste',\n      showGrid: 'Show grid',\n      clearCanvas: 'Clear canvas',\n    },\n  },\n  audio: {\n    editor: {\n      noProject: 'No audio project is open',\n      newProject: 'New audio project',\n      dragHere: 'Drop audio here',\n      dragFormatHint: 'WAV, MP3, OGG... or use Import / AI panel',\n      chooseFiles: 'Choose files',\n      dropToImport: 'Drop to import',\n      shortcutsTitle: 'Keyboard shortcuts',\n      shortcutsClose: 'Close',\n      zoomOut: 'Zoom out track',\n      zoomIn: 'Zoom in track',\n      snap: 'Magnetic snap',\n      bpmLabel: 'BPM',\n      bpmTitle: 'Project tempo (beats per minute)',\n      bpmUp: 'Increase BPM',\n      bpmDown: 'Decrease BPM',\n      bpmHalf: 'Halve tempo (if analysis marked double-time)',\n      bpmDouble: 'Double tempo (if analysis marked half-time)',\n      bpmTap: 'Tap tempo: tap along the beat to measure BPM',\n      bpmTapShort: 'TAP',\n      bpmTapHint: 'Keep tapping TAP on the beat\u2026',\n      bpmTapSet: (n: number) => `Detected tempo: ${n} BPM`,\n      bpmBeatSnap: 'Snap clips to the beat grid',\n      bpmGridShort: 'GRID',\n      deleteClipConfirm: 'Delete the selected clip? This cannot be easily undone.',\n      deleteClipsConfirm: (n: number) =>\n        `Delete ${n} selected clips? This cannot be easily undone.`,\n      deleteTrackConfirm: (name: string) =>\n        `Delete track \"${name}\" and all of its clips?`,\n      deleteConfirmTitle: 'Confirm delete',\n      deleteConfirmBtn: 'Delete',\n      shortcuts: {\n        playPause: 'Play / pause',\n        splitClip: 'Split clip at playhead',\n        delete: 'Delete selection',\n        undo: 'Undo',\n        redo: 'Redo',\n        copyPaste: 'Copy / paste clips',\n        nudge: 'Nudge \u00B10.1s (Shift = 1s)',\n        loop: 'Loop = selection',\n        toggleRipple: 'Toggle ripple mode',\n        createRegion: 'Create region from selection',\n        zoomSelection: 'Zoom to selection',\n        showShortcuts: 'Show / hide shortcuts',\n        zoomTimeline: 'Ctrl/\u2318 + scroll = zoom \u00B7 middle-click = pan',\n      },\n      toasts: {\n        modeNormal: 'Normal mode',\n        modeRipple: 'Ripple mode',\n        regionCreated: 'Region created',\n        regionName: (n: number) => `Region ${n}`,\n        projectOpened: 'Project opened',\n        projectInvalid: 'Invalid project file',\n        savedToCloud: 'Saved to cloud \u2713',\n        cloudSaveFailed: (msg: string) => `Could not save to cloud: ${msg}`,\n        importFailed: (name: string) => `Could not import ${name}`,\n      },\n    },\n    sidebar: {\n      tabLibrary: 'Library',\n      tabClip: 'Clip',\n      tabFx: 'FX',\n      tabMixer: 'Mixer',\n      tabAi: 'AI',\n      tabChat: 'Chat',\n      tabRecord: 'Rec',\n      tabLyrics: 'Lyrics',\n      titleInspector: 'Inspector',\n      titleFx: 'Effects',\n      titleMixer: 'Mixer',\n      titleAi: 'Audio AI',\n      titleChat: 'Audio chat',\n      titleRecord: 'Recording',\n      titleLyrics: 'Lyrics',\n      titleLibrary: 'Library',\n      unpin: 'Unpin panel',\n      pin: 'Pin panel',\n      resetSize: 'Reset size',\n      closePanel: 'Close panel',\n      resizeHeight: 'Drag to change height',\n    },\n    jobsPanel: {\n      header: 'Audio files',\n      hint: 'Cloud-generated audio. Click to add to the timeline.',\n      loading: 'Loading audio\u2026',\n      empty: 'No audio files yet.',\n      loadError: 'Could not load audio files.',\n      fetchError: 'Could not download audio.',\n      refresh: 'Refresh',\n      addHint: 'Add to timeline',\n      preview: 'Preview',\n      previewStop: 'Stop',\n      previewError: 'Could not play audio',\n      defaultTrackName: 'Audio',\n      addedToast: (name: string) => `Added: ${name}`,\n    },\n    tracks: {\n      header: 'Tracks',\n      addTrack: 'New track',\n      deleteTrack: 'Delete track',\n      mute: 'Mute',\n      solo: 'Solo',\n      arm: 'Arm recording',\n      lock: 'Lock',\n    },\n    tools: {\n      split: 'Split at playhead',\n      trimStart: 'Trim start to playhead',\n      trimEnd: 'Trim end to playhead',\n      copy: 'Copy',\n      paste: 'Paste',\n    },\n    clipMenu: {\n      title: 'Clip',\n      copy: 'Copy',\n      cut: 'Cut',\n      paste: 'Paste',\n      createBar: 'Duplicate',\n      joinAdjacent: 'Join with adjacent clip',\n      joinUnavailable: 'No adjacent clip from the same audio to join',\n      joinDone: 'Clips joined',\n      invert: 'Invert phase',\n      bringForward: 'Bring forward',\n      sendBackward: 'Send backward',\n      hide: 'Hide',\n      show: 'Show',\n      lock: 'Lock',\n      unlock: 'Unlock',\n      isolate: 'Isolate voice / audio',\n      removeNoise: 'Remove background noise',\n      delete: 'Delete',\n      emptyTitle: 'Timeline',\n      importLocal: 'Upload local audio',\n      importMyFiles: 'Add from My Files',\n    },\n    inspector: {\n      emptyHint: 'Select a clip to edit gain, fades, pitch and speed.',\n      selection: 'Selection',\n      selectionHint: 'Duration and playback speed of the selected clip.',\n      selStart: 'Start',\n      selEnd: 'End',\n      playbackSpeed: 'Playback speed',\n      speedHalf: '0.5x',\n      speedStandard: '1x \u2014 Standard',\n      speedOneHalf: '1.5x',\n      speedDouble: '2x',\n      soundLevels: 'Sound levels',\n      backgroundNoise: 'Background noise',\n      removeNoise: 'Remove background noise',\n      name: 'Name',\n      gain: 'Gain',\n      fadeIn: 'Fade in (s)',\n      fadeOut: 'Fade out (s)',\n      pitchTimeIndependent: 'Pitch / time independent',\n      speed: 'Speed',\n      speedStretch: 'Speed (stretch)',\n      pitch: 'Pitch (semitones)',\n      crossfadeIn: 'Crossfade in (s)',\n      crossfadeOut: 'Crossfade out (s)',\n      crossfadeEqualPower: 'Crossfade equal-power',\n      crossfadeLinear: 'Crossfade linear',\n      crossfadeExponential: 'Crossfade exponential',\n      applyCrossfade: 'Crossfade selection (0.25s)',\n      fadeInCurve: 'Fade in curve',\n      fadeOutCurve: 'Fade out curve',\n      curveLinear: 'Linear',\n      curveLog: 'Log',\n      curveSCurve: 'S-curve',\n      curveExp: 'Exp',\n      mute: 'Mute clip',\n      invertPhase: 'Invert phase',\n      duplicate: 'Duplicate',\n      delete: 'Delete',\n    },\n    fx: {\n      noTrackHint: 'Select a track to edit effects.',\n      fxHeader: (name: string) => `FX \u2014 ${name}`,\n      addEffect: '+ Effect',\n      noEffectsHint: 'No effects. Add EQ, compressor, reverb\u2026',\n      savePresetTooltip: 'Save preset',\n      savePresetPrompt: 'Preset name',\n      defaultPresetName: (type: string) => `${type} preset`,\n      loadPreset: 'Load preset\u2026',\n      types: {\n        eq: 'eq',\n        compressor: 'compressor',\n        gate: 'gate',\n        reverb: 'reverb',\n        delay: 'delay',\n        chorus: 'chorus',\n        distortion: 'distortion',\n        highpass: 'highpass',\n        lowpass: 'lowpass',\n        limiter: 'limiter',\n      },\n    },\n    export: {\n      title: 'Export audio',\n      rangeLabel: 'Range',\n      rangeFull: 'Full project',\n      rangeSelection: 'Clip selection',\n      rangeRegion: 'Named region',\n      chooseRegion: 'Choose region\u2026',\n      formatLabel: 'Format',\n      bitDepthLabel: 'Bit depth',\n      bitDepth16: '16-bit',\n      bitDepth24: '24-bit',\n      bitDepth32: '32-bit float',\n      ditherLabel: 'Dither on export (recommended at 16-bit)',\n      lufsLabel: 'LUFS normalization',\n      lufsNone: 'No normalization',\n      lufsStreaming: '-14 LUFS (streaming)',\n      lufsPodcast: '-16 LUFS (podcast)',\n      stemLabel: 'Stem (optional)',\n      fullMix: 'Full mix',\n      bounceInPlace: 'Bounce in place',\n      exportButton: 'Export',\n      exporting: 'Exporting\u2026',\n      meters: {\n        shortTerm: 'Short-term:',\n        integrated: 'Integrated:',\n        truePeak: 'True-peak:',\n      },\n      toasts: {\n        ready: 'Export ready',\n        errorExport: 'Export error',\n        bounceReady: 'Bounce in place ready',\n        bounceError: 'Bounce error',\n      },\n    },\n    lyrics: {\n      title: 'Transcript',\n      transcribeClip: 'Transcribe clip',\n      cut: 'Cut',\n      copyText: 'Copy text',\n      copyLyrics: 'Copy lyrics',\n      removeFillers: 'Remove filler words',\n      emptyHint: 'Transcribe a clip to edit by word (click = select, Shift = multi).',\n      replaceSection: 'Replace selection (TTS)',\n      replacePlaceholder: 'New phrase\u2026',\n      replaceWithVoice: 'Replace with voice',\n      markersSection: 'Markers',\n      markerAddHere: '+ Here',\n      markerName: (n: number) => `Marker ${n}`,\n      toasts: {\n        selectVoiceClip: 'Select a voice clip first',\n        wordsTranscribed: (n: number) => `${n} words transcribed`,\n        transcribeError: 'Transcription error',\n        selectWordsWriteReplace: 'Select words and type the replacement',\n        replacedTts: 'Phrase replaced with TTS',\n        ttsError: 'TTS error',\n        nothingToCopy: 'Nothing to copy',\n        selectionCopied: 'Selection copied',\n        transcriptCopied: 'Text copied',\n        copyError: 'Could not copy',\n      },\n    },\n    chat: {\n      welcome: 'I am your audio copilot. Try: \"generate a 30-second lo-fi beat at 80 BPM\" or \"raise track 1 by 3 dB\".',\n      inputPlaceholder: 'Command in natural language\u2026',\n      confirmAction: (name: string) => `Confirm ${name}`,\n      undoAction: 'Undo this action',\n      toasts: {\n        done: 'Done.',\n        agentError: 'Agent error',\n        error: 'Error',\n      },\n    },\n    ai: {\n      healthOk: 'Audio API: OK',\n      healthDown: 'Audio API unavailable',\n      healthChecking: 'Checking API\u2026',\n      endpointHint: {\n        music: 'Generate a music track from a prompt.',\n        extend: 'Extend the current music seamlessly.',\n        sfx: 'Generate a short sound effect.',\n        tts: 'Convert text to speech with the chosen voice.',\n        voice: 'Change the voice of the selected clip.',\n        isolate: 'Isolate voice or other layers from the clip.',\n        stems: 'Split the clip into stems (vocals, drums, bass\u2026).',\n        automix: 'Auto-balance EQ and dynamics across tracks.',\n        cleanup: 'Podcast cleanup: isolate voice and trim silence.',\n        lyrics: 'Transcribe audio to lyrics / captions.',\n      },\n      sectionGenerate: 'Generate',\n      sectionGenerateHint: 'Music, SFX and voice from scratch.',\n      sectionEdit: 'Edit clip',\n      sectionEditHint: 'Transform the clip selected on the timeline.',\n      sectionMix: 'Mix and cleanup',\n      sectionMixHint: 'Auto levels and podcast cleanup.',\n      catalogHint: 'Pick an AI tool. Actions apply at the playhead or to the selected clip.',\n      openAgent: 'Open agent',\n      chooseAnotherTool: 'Choose another tool',\n      showMoreTools: 'More options',\n      showLessTools: 'Show less',\n      playVoicePreview: 'Play voice',\n      pauseVoicePreview: 'Pause voice',\n      tab: {\n        music: 'Music',\n        extend: 'Extend',\n        sfx: 'SFX',\n        tts: 'Voice',\n        voice: 'Change',\n        isolate: 'Isolate',\n        stems: 'Stems',\n        automix: 'Auto-mix',\n        cleanup: 'Podcast',\n        lyrics: 'Lyrics',\n      },\n      placeholders: {\n        music: 'Describe the music (e.g. lo-fi chill at 80 BPM)',\n        extend: 'How to continue (e.g. same groove, more energy)',\n        sfx: 'Describe the effect (e.g. cinematic whoosh)',\n        tts: 'Narration text\u2026',\n      },\n      durationLabel: 'Duration (s)',\n      songStructure: 'Song structure (markers)',\n      songStructureClear: 'Remove structure',\n      songStructureToast: 'Intro / verse / chorus markers created',\n      songStructureClearedToast: 'Song structure markers removed',\n      actionLabel: {\n        applyAutomix: 'Apply auto-mix',\n        cleanupPodcast: 'Clean up podcast',\n        separateStems: 'Separate stems',\n        extend: 'Extend',\n        generate: 'Generate',\n      },\n      selectedClip: (name: string) => `Selected clip: ${name || 'none'}`,\n      hints: {\n        automix: 'Adjusts levels, pan and adds highpass/compressor to voice tracks.',\n        cleanup: 'Pipeline: isolate (denoise) + highpass + compressor on a new track.',\n        stems: 'Separates vocals / drums / bass / other into new tracks.',\n      },\n      generating: 'Generating\u2026',\n      toasts: {\n        autoMix: 'Auto-mix by loudness applied',\n        podcastCleanup: 'Podcast cleanup ready',\n        musicGenerated: 'Music generated',\n        extendGenerated: 'Extension generated',\n        sfxGenerated: 'SFX generated',\n        voiceoverGenerated: 'Voiceover generated',\n        voiceChanged: 'Voice converted',\n        audioIsolated: 'Audio isolated',\n        stemsSeparated: 'Stems separated',\n        transcriptReady: 'Transcript ready \u2014 edit in Lyrics panel',\n        noVoiceClip: 'Select a voice clip',\n        noAudioClip: 'Select a clip with audio',\n        agentError: 'AI error',\n        musicPromptTooLong:\n          'Backend expanded the music prompt with Brand Memory (ElevenLabs length limit). The editor only sends prompt + brand_id \u2014 escalate to PM if it persists.',\n      },\n      status: {\n        isolating: 'Isolating / denoise\u2026',\n        removingSilence: 'Removing silences\u2026',\n        separatingStems: 'Separating stems\u2026',\n      },\n      trackNames: {\n        aiTrack: 'AI',\n        podcastTrack: 'Cleaned podcast',\n        lyricsTrack: 'Lyrics',\n      },\n    },\n    timeline: {\n      ripple: 'RIPPLE',\n      clipFallback: 'Clip',\n    },\n    automation: {\n      noTrackHint: 'Select a track.',\n      header: 'Automation',\n      property: 'Property',\n      propertyVolume: 'Volume',\n      propertyPan: 'Pan',\n      addPoint: '+ Point at playhead',\n      noPointsHint: 'No points. Add keyframes.',\n    },\n    mixer: {\n      deleteBus: 'Delete bus',\n    },\n    recording: {\n      armedTrack: (name: string) => `Armed track: ${name || 'none'}`,\n      monitorLabel: 'Monitoring (watch out for feedback)',\n      punchLabel: 'Punch in/out (use the loop)',\n      punchStatus: (start: string, end: string) => `Punch ${start}s \u2013 ${end}s`,\n      recordButton: 'Record',\n      stopButton: 'Stop',\n      takeLanesHeader: 'Take lanes (comping)',\n      loopHint: (start: string, end: string) => `Loop active: click take = comp only in ${start}\u2013${end}s. Shift+click = entire track.`,\n      groupLabel: (id: string) => `Group ${id.slice(-8)}`,\n      takeLabel: (lane: number, name: string, active: boolean) => `Lane ${lane}: ${name}${active ? ' (active)' : ''}`,\n      takeFileName: (n: number) => `Take ${n}.webm`,\n      takeNameFallback: (n: number) => `Take ${n}`,\n      toasts: {\n        noArmedTrack: 'Create or arm a track first',\n        micError: 'Could not access the microphone',\n        takeRecorded: (n: number) => `Take ${n} recorded`,\n        takeActiveInLoop: (n: number) => `Take ${n} active in the loop`,\n        saveError: 'Could not save recording',\n      },\n    },\n  },\n  text: {\n    editor: {\n      noDocument: 'No text document is open',\n      newDocument: 'New document',\n      toasts: {\n        docxImported: 'DOCX imported',\n        markdownImported: 'Markdown imported',\n        projectOpened: 'Project opened',\n        projectInvalid: 'Invalid project file',\n        savedToCloud: 'Saved to cloud \u2713',\n        cloudSaveFailed: (msg: string) => `Could not save to cloud: ${msg}`,\n      },\n    },\n    sidebar: {\n      tabOutline: 'Outline',\n      tabAi: 'AI',\n      tabChat: 'Chat',\n      tabSuggestions: 'Diffs',\n      tabVariants: 'Channels',\n      tabVersions: 'Versions',\n      tabBrand: 'Brand',\n      tabComments: 'Notes',\n      tabClaims: 'Claims',\n      tabSeo: 'SEO',\n      titleOutline: 'Outline',\n      titleAi: 'Text AI',\n      titleChat: 'Chat',\n      titleSuggestions: 'Suggestions',\n      titleVariants: 'Variants',\n      titleVersions: 'Versions',\n      titleBrand: 'Brand voice',\n      titleComments: 'Comments',\n      titleClaims: 'Claims',\n      titleSeo: 'SEO',\n      unpin: 'Unpin panel',\n      pin: 'Pin panel',\n      resetSize: 'Reset size',\n      closePanel: 'Close panel',\n      resizeHeight: 'Drag to change height',\n    },\n    jobsPanel: {\n      header: 'Text & image files',\n      hint: 'Brand images and analysis/script text. Click to insert into the document.',\n      loading: 'Loading files\u2026',\n      empty: 'No image, analysis, or script files yet.',\n      emptyFilter: 'No items of this type.',\n      loadError: 'Could not load files.',\n      insertError: 'Could not insert into the document.',\n      refresh: 'Refresh',\n      noEditor: 'Open the document to insert content.',\n      imageAdded: 'Image inserted',\n      textImported: 'Text imported',\n      addImageHint: 'Insert image',\n      addTextHint: 'Import text',\n      filterAria: 'Filter files',\n      filterAll: 'All',\n      filterImage: 'Image',\n      filterAnalysis: 'Analysis',\n      filterScript: 'Script',\n      filterText: 'Text',\n      kindImage: 'Image',\n      kindAnalysis: 'Analysis',\n      kindScript: 'Script',\n      kindText: 'Text',\n      importAnalysisHeading: 'Analysis',\n      importScriptHeading: 'Script',\n      importTextHeading: 'Imported text',\n    },\n    pageToolbar: {\n      imageButtonTitle: 'Insert image',\n      imageTooltip: 'Image',\n      marginsButtonTitle: 'Margins and page',\n      marginsTooltip: 'Margins',\n      guidesTitle: 'Show / hide margin guides',\n      guidesTooltip: 'Guides',\n      pageSetupTitle: 'Page setup',\n      pageSizeLabel: 'Page size',\n      orientationPortrait: 'Portrait',\n      orientationLandscape: 'Landscape',\n      marginTop: 'Top',\n      marginBottom: 'Bottom',\n      marginLeft: 'Left',\n      marginRight: 'Right',\n      marginUnit: (label: string) => `${label} (mm)`,\n      reset: 'Reset',\n      apply: 'Apply',\n    },\n    contextMenu: {\n      title: 'Edit',\n      undo: 'Undo',\n      redo: 'Redo',\n      cut: 'Cut',\n      copy: 'Copy',\n      paste: 'Paste',\n      bold: 'Bold',\n      italic: 'Italic',\n      highlight: 'Highlight',\n      link: 'Link',\n      heading2: 'Heading H2',\n      paragraph: 'Paragraph',\n      bulletList: 'Bullet list',\n      orderedList: 'Numbered list',\n      table: 'Insert table',\n      alignLeft: 'Align left',\n      alignCenter: 'Center',\n      alignRight: 'Align right',\n      comment: 'Comment on selection',\n    },\n    canvas: {\n      loading: 'Loading editor\u2026',\n      fontLabel: 'Font',\n      fontSizeDown: 'Decrease size',\n      fontSize: 'Font size',\n      fontSizeUp: 'Increase size',\n      readAloud: 'Read',\n      readAloudTitle: 'Read aloud',\n      readAloudStop: 'Stop reading',\n      readAloudUnavailable: 'Read aloud is not available in this browser',\n      slashHint: '/ commands',\n      paletteHint: (shortcut: string) => `${shortcut} palette`,\n      textColor: 'Text color',\n      highlightColor: 'Highlighter color',\n      bold: 'Bold',\n      italic: 'Italic',\n      strike: 'Strikethrough',\n      highlight: 'Highlighter',\n      h1: 'Heading H1',\n      h2: 'Heading H2',\n      h3: 'Heading H3',\n      h4: 'Heading H4',\n      h5: 'Heading H5',\n      paragraph: 'Paragraph',\n      bulletList: 'Bullet list',\n      orderedList: 'Numbered list',\n      indent: 'Increase indent',\n      outdent: 'Decrease indent',\n      alignLeft: 'Align left',\n      alignCenter: 'Center',\n      alignRight: 'Align right',\n      alignJustify: 'Justify',\n      clearAlign: 'Clear alignment',\n      blockquote: 'Quote',\n      link: 'Add link',\n      linkPrompt: 'Link URL',\n      linkPlaceholder: 'example.com',\n      linkApply: 'Apply',\n      linkRemove: 'Remove link',\n      linkOpenHint: 'Ctrl+click (\u2318+click on Mac) to open the link',\n      table: 'Table',\n      tableInsert: 'New table',\n      tableEdit: 'Edit table',\n      tableRows: 'Rows',\n      tableCols: 'Columns',\n      tableInsertAction: 'Insert',\n      tableInsertFailed: 'Could not insert a table here',\n      tableAddRow: 'Row',\n      tableDelRow: 'Row',\n      tableAddCol: 'Col',\n      tableDelCol: 'Col',\n      tableDelete: 'Delete table',\n      callout: 'Callout',\n      calloutDefault: 'Callout note',\n      calloutSlashHint: 'Highlighted block',\n      superscript: 'Superscript',\n      comment: 'Comment',\n      commentPrompt: 'Comment note:',\n      footnote: 'Footnote',\n      footnotePrompt: 'Footnote text:',\n      footnoteDefault: 'Note',\n      suggestionReady: 'Suggestion ready',\n      selectTextFirst: 'Select text first',\n      imageWidth: 'Image width',\n      imageNarrower: 'Narrower',\n      imageWider: 'Wider',\n    },\n    comments: {\n      title: 'Comments',\n      openSection: 'Open',\n      resolvedSection: 'Resolved',\n      openCount: (n: number) => `Open (${n})`,\n      placeholder: 'Write your note\u2026',\n      addSelection: 'Save note',\n      anchorHint: 'With a selection the note is pinned (Go). Without selection it is saved as a note only.',\n      empty: 'Add a note. Select text first to pin it to the document.',\n      jump: 'Go',\n      resolve: 'Resolve',\n      reopen: 'Reopen',\n      remove: 'Delete',\n      toasts: {\n        selectText: 'Select text to comment',\n        writeNote: 'Write a note',\n        anchored: 'Comment pinned',\n        noteSaved: 'Note saved',\n        markMissing: 'Mark not found in the document',\n      },\n      popoverTitle: 'New comment',\n      popoverSave: 'Pin',\n      popoverCancel: 'Cancel',\n      selectionChip: 'Comment',\n    },\n    suggestions: {\n      pendingCount: (n: number) => `Pending (${n})`,\n      acceptAll: 'All new',\n      rejectAll: 'All previous',\n      filterLabel: 'Filter',\n      filterAll: 'All',\n      rationales: 'Rationales',\n      empty:\n        'AI review queue: pick Before or After on each suggestion to keep one version.',\n      chooseHint: 'Choose which version to keep',\n      before: 'Before',\n      after: 'After',\n      emptyOriginal: '(empty doc / append)',\n      accept: 'Accept',\n      reject: 'Reject',\n      kinds: {\n        rewrite: 'Rewrite',\n        tighten: 'Tighten',\n        expand: 'Expand',\n        elevate: 'Elevate',\n        localize: 'Localize',\n        tone: 'Tone',\n        brand: 'Brand',\n        claim: 'Claim',\n        other: 'Other',\n      },\n      toasts: {\n        accepted: 'New version applied',\n        rejected: 'Kept the previous version',\n        allAccepted: 'All new versions applied',\n      },\n    },\n    variants: {\n      generate: 'Generate',\n      regenerateStale: (n: number) => `Regenerate stale (${n})`,\n      staleRegen: 'Stale \u00B7 regen',\n      addToDocument: 'Add to document',\n      empty:\n        'Generate IG, LinkedIn, X, email, ads, and YouTube captions from the document. Editing the doc marks them stale.',\n      chars: (n: number) => `${n} chars`,\n      toasts: {\n        writeFirst: 'Write content before generating variants',\n        generated: 'Variants generated',\n        staleRegenerated: 'Stale variants regenerated',\n        addedToDocument: 'Variant added to the document',\n        noEditor: 'Open the document to insert content',\n        error: 'Failed to generate variants',\n      },\n      channels: {\n        instagram: 'Instagram',\n        linkedin: 'LinkedIn',\n        x: 'X / Twitter',\n        email: 'Email',\n        ad: 'Ad',\n        youtube: 'YouTube',\n      },\n    },\n    versions: {\n      namePlaceholder: 'Name (optional)',\n      save: 'Save',\n      compare: 'Compare',\n      compareA: 'A\u2026',\n      compareB: 'B\u2026',\n      current: 'Current',\n      restoreSection: 'Restore section',\n      sectionPlaceholder: 'Exact H2 text\u2026',\n      empty: 'Named document snapshots (independent of TipTap undo).',\n      words: (n: number) => `${n} words`,\n      restoreAll: 'All',\n      restoreSec: 'Section',\n      restoreSelection: 'Selection',\n      remove: 'Delete',\n      toasts: {\n        needHeading: 'Enter the heading to restore',\n        selectText: 'Select text in the document',\n        emptySnapshot: 'Empty snapshot',\n        selectionRestored: 'Selection restored from snapshot',\n      },\n    },\n    brandPanel: {\n      rescore: 'Rescore',\n      scoreLabel: (n: number) => `Score ${n}`,\n      preferredTerms: 'Preferred terms',\n      forbiddenTerms: 'Forbidden terms',\n      approvedCtas: 'Approved CTAs',\n      legalDisclaimers: 'Legal disclaimers',\n      textBank: 'Text bank (voice samples)',\n      glossary: 'Glossary',\n      glossaryTerm: 'Term',\n      glossaryPreferred: 'Preferred',\n      addGlossary: 'Add',\n      channelTones: 'Tone by channel',\n      toneDefault: '(default)',\n      onePerLine: 'One per line',\n      samplesHint: 'One sample per line (voice match)',\n      forbiddenInDoc: (t: string) => `Forbidden in doc: ${t}`,\n      missingPreferred: (t: string) => `Missing preferred: ${t}`,\n      toasts: {\n        scored: (n: number) => `Brand score: ${n}`,\n        error: 'Error',\n      },\n    },\n    claims: {\n      count: (n: number) => `Claims (${n})`,\n      analyze: 'Analyze AI',\n      markSelection: 'Mark selection',\n      empty: 'Claims that need a source or verification.',\n      remove: 'Delete',\n      claimNeedsCitation: 'Claim: needs citation',\n      statuses: {\n        unverified: 'Unverified',\n        needs_citation: 'Needs citation',\n        ok: 'OK',\n        flagged: 'Flagged',\n      },\n      toasts: {\n        selectClaim: 'Select the claim',\n        marked: 'Claim marked',\n        detected: (n: number) => `${n} claims detected`,\n        error: 'Error',\n      },\n    },\n    seo: {\n      titleLabel: 'Title',\n      descriptionLabel: 'Meta description',\n      slugLabel: 'Slug',\n      autoSlug: 'Auto',\n      focusKeyword: 'Focus keyword',\n      keywords: 'Keywords (comma)',\n      serpPreview: 'SERP preview',\n      titleFallback: 'Title',\n      descriptionFallback: 'Meta description\u2026',\n      checklist: {\n        titleRange: (n: number) => `Title ${n}/30-60`,\n        descRange: (n: number) => `Meta description ${n}/120-160`,\n        slugDefined: 'Slug defined',\n        focusInBody: 'Focus keyword in body',\n        focusOptional: 'Focus keyword (optional)',\n        channelLength: (ch: string) => `Channel length ${ch}`,\n        charLimit: (ch: string, cur: number, lim: number) =>\n          `Char limit ${ch}: ${cur}/${lim}`,\n      },\n    },\n    bottomBar: {\n      pageSetup: 'Page',\n      insertImage: 'Image',\n      marginGuides: 'Guides',\n    },\n    metrics: {\n      words: 'words',\n      chars: 'chars',\n      flesch: 'Flesch',\n      clarity: 'Clarity',\n      jargon: 'Jargon',\n      forbidden: 'Forbidden',\n      inclusive: 'Inclusive',\n      brand: 'Brand',\n      inclusiveTips: {\n        users: 'Prefer \u201Cpeople who use\u2026\u201D or a concrete audience',\n        genericMasculine: 'Review generic masculine language',\n        guys: 'Prefer \u201Ceveryone\u201D / \u201Cteam\u201D',\n        ableist: 'Avoid ableist language',\n        mentalHealth: 'Avoid mental-health stereotypes',\n      },\n    },\n    outline: {\n      title: 'Outline',\n      empty: 'Add headings (H1\u2013H4) in the document to navigate the outline.',\n    },\n    workflow: {\n      tooltip: 'Document status',\n      header: 'Document status',\n      options: {\n        draft: { label: 'Draft', description: 'The document is being written' },\n        review: { label: 'Review', description: 'Ready for peer review' },\n        approved: { label: 'Approved', description: 'Validated by a reviewer' },\n        published: { label: 'Published', description: 'Exported and published' },\n      },\n      workflowOptionLabel: (s: string) => `Workflow \u2192 ${s}`,\n    },\n    chat: {\n      planModeLabel: 'Plan mode',\n      planModeHint:\n        'When on, the first message only proposes numbered steps (no costly tools). Then ask to execute the plan.',\n      emptyHint:\n        'Try: \"write a paragraph about my brand\", \"generate an outline\", or \"rewrite more persuasive\". With Plan mode, say \"execute the plan\" to apply tools.',\n      inputPlaceholder: 'Talk to the copilot\u2026',\n      planReadyHint: 'Plan ready. Type \"execute the plan\" or a follow-up message to apply tools.',\n      confirmAction: (label: string) => `Confirm: ${label}`,\n      error: 'The copilot could not complete that action.',\n      tools: {\n        generate_content: 'Generate text',\n        rewrite_selection: 'Rewrite text',\n        change_tone: 'Change tone',\n        expand_section: 'Expand section',\n        tighten: 'Tighten text',\n        insert_section: 'Insert section',\n        generate_variants: 'Generate variants',\n        translate_document: 'Translate',\n        apply_brand_voice: 'Brand voice',\n        create_outline: 'Create outline',\n        summarize: 'Summarize',\n        export_document: 'Export',\n        handoff_to_video: 'Hand off to video',\n        handoff_to_audio: 'Hand off to audio',\n        section_op: 'Section operation',\n        analyze_claims: 'Analyze claims',\n        compliance_pass: 'Legal review',\n        make_clip_script: 'Short script',\n      },\n      errors: {\n        auth: 'Your session expired. Sign in again.',\n        unavailable: 'This feature is not available on the backend yet.',\n        textRequired:\n          'I need document text or a selection. Write something first, or ask me to generate content.',\n        promptRequired: 'Missing the topic or instruction to generate text.',\n        network: 'Network error. Check your connection and try again.',\n        generic: 'Could not complete the action. Please try again.',\n        styleUnsupported:\n          'Chat cannot change colors or fonts yet. Use the editor formatting, or ask me to rewrite the content.',\n        unknownTool: (name: string) => `Unrecognized action: ${name}`,\n      },\n      summaries: {\n        contentInserted: 'Text generated and added to the document.',\n        contentSuggested: 'Text generated \u2014 review it in Suggestions.',\n        rewrite: 'Rewrite suggestion ready in Suggestions.',\n        tone: (tone: string) => `Tone updated to \u201C${tone}\u201D (suggestion created).`,\n        expand: (heading: string) => `Expansion suggested for \u201C${heading}\u201D.`,\n        tighten: 'Tighten suggestion ready.',\n        sectionInserted: (heading: string) => `Section inserted: \u201C${heading}\u201D.`,\n        variants: (n: number) => `${n} variants generated (Variants panel).`,\n        translate: (lang: string) => `Translation suggested (${lang}).`,\n        brandScore: (n: number) => `Brand voice score: ${n}.`,\n        outline: (n: number) => `Outline applied with ${n} sections.`,\n        summarize: 'Summary suggested in Suggestions.',\n        exportOpen: 'Export modal opened.',\n        handoffVideo: 'Video handoff ready in Export.',\n        handoffAudio: 'Audio handoff ready in Export.',\n        handoffVideoToast: 'Open Export \u2192 Hand off to video.',\n        handoffAudioToast: 'Open Export \u2192 Hand off to audio.',\n        sectionOp: (op: string) => `\u201C${op}\u201D operation suggested.`,\n        claims: (n: number) => `${n} claims detected (Claims panel).`,\n        clip: (platform: string) => `Short script for ${platform} saved in Variants.`,\n      },\n    },\n    commandPalette: {\n      placeholder: 'Search command\u2026',\n      emptyResult: 'No results',\n      groupNavigation: 'Navigation',\n      groupFormat: 'Format',\n      groupFile: 'File',\n      groupWorkflow: 'Workflow',\n      commands: {\n        tabAi: 'Go to AI panel',\n        tabChat: 'Go to agent Chat',\n        tabSuggestions: 'Go to Suggestions / Diffs',\n        tabBrand: 'Go to Brand OS',\n        tabSeo: 'Go to SEO',\n        tabComments: 'Go to Comments',\n        tabClaims: 'Go to Claims',\n        fmtH2: 'Format: Heading 2',\n        fmtTable: 'Insert table',\n        fmtCallout: 'Insert callout',\n        export: 'Open export',\n        snap: 'Create snapshot',\n      },\n    },\n    export: {\n      title: 'Export / Handoff',\n      formats: {\n        md: 'Markdown',\n        html: 'Clean HTML',\n        mdx: 'MDX (CMS)',\n        txt: 'Text',\n        json: 'JSON',\n        pdf: 'PDF',\n        docx: 'DOCX',\n      },\n      mdxHint: 'MDX/HTML are for pasting into a CMS (no publish OAuth).',\n      complianceLabel: 'Block export if compliance fails',\n      bridgesHeader: 'Bridges',\n      handoffVideo: 'Handoff to Video (timed script)',\n      handoffAudio: 'Handoff to Audio (TTS per H2)',\n      fallbackName: 'Document',\n      fallbackFilename: 'doc',\n      toasts: {\n        noTextTrack: 'No text track in the video project',\n        docEmpty: 'Empty document',\n        noTtsContent: 'No content for TTS',\n        ttsError: 'TTS error',\n        handoffVideoDone: (n: number) => `Handoff: ${n} timed clips (open Video)`,\n        handoffAudioDone: 'Handoff to audio ready (TTS per section)',\n        genericError: 'Export error',\n      },\n    },\n    ai: {\n      title: 'Text AI',\n      healthOk: 'Text API: OK',\n      healthDown: 'Text API unavailable',\n      healthChecking: 'Checking API\u2026',\n      catalogHint: 'Pick a tool. Generated copy opens in a modal to insert or review.',\n      chooseAnotherTool: 'Choose another tool',\n      showMoreTools: 'More options',\n      showLessTools: 'Show less',\n      endpointHint: {\n        generate: 'Generate new copy from a prompt.',\n        rewrite: 'Rewrite the selection or document with an instruction.',\n        ops: 'Tighten, elevate, localize, or expand a passage.',\n        outline: 'Build a section outline from a topic.',\n        brand: 'Score brand-voice fit and suggest improvements.',\n        ab: 'Compare A/B hooks for clarity and CTA strength.',\n        compliance: 'Review legal risks and disclaimers in the document.',\n        voice: 'Rewrite to match voice samples.',\n        clip: 'Generate a short vertical-video script into Variants.',\n        transcript: 'Transcribe audio or video into timestamped paragraphs.',\n        variants: 'Channel variants',\n        claims: 'Claims analysis',\n      },\n      toneLabel: 'Tone',\n      industryLabel: 'Industry',\n      industryOtherPlaceholder: 'Enter industry\u2026',\n      industryOtherRequired: 'Enter the industry name',\n      opLabel: 'Operation',\n      agentLink: 'Agent',\n      clipHint: 'Generate a short vertical-video script and save it in Variants.',\n      clipVariantTitle: 'Short video script',\n      clipPrompt: (text: string) =>\n        `Short vertical-video script (hook + 3 beats + CTA), max 120 words:\\n\\n${text}`,\n      brandAlignInstruction: (notes: string) => `Align brand voice. ${notes}`,\n      brandScoreRationale: (n: number) => `Score ${n}`,\n      outlineIntent: (intent: string) => `[Intent: ${intent}]`,\n      rewriteDefault: 'Improve clarity and rhythm',\n      tab: {\n        generate: 'Generate',\n        rewrite: 'Rewrite',\n        ops: 'Ops',\n        outline: 'Outline',\n        brand: 'Brand',\n        ab: 'A/B',\n        compliance: 'Legal',\n        voice: 'Voice',\n        clip: 'Short script',\n        transcript: 'Audio',\n        variants: 'Variants',\n        claims: 'Claims',\n      },\n      placeholders: {\n        prompt: 'Describe what you want to generate\u2026',\n        outline: 'Document topic\u2026',\n        rewriteInstruction: 'Rewrite instruction\u2026',\n        voiceSamples: 'Voice samples (optional; separate with a blank line)\u2026',\n        brandText: 'Text to analyze (selection or full document)\u2026',\n        preferredTerms: 'Preferred terms (one per line)\u2026',\n        forbiddenTerms: 'Forbidden terms (one per line)\u2026',\n      },\n      hookLabel: (letter: string) => `Hook ${letter}`,\n      hookPlaceholder: (letter: string) => `Write hook ${letter}\u2026`,\n      addHook: 'Add another hook',\n      removeHook: 'Remove hook',\n      abScoreClarity: 'Clarity',\n      abScoreCta: 'CTA strength',\n      abScoreBrand: 'Brand fit',\n      complianceSeverity: {\n        info: 'Info',\n        warn: 'Warning',\n        block: 'Block',\n      },\n      complianceSummaryOk: 'Looking good: no serious warnings or blockers.',\n      complianceSummaryWarn: 'Review complete with warnings \u2014 fix before publishing.',\n      complianceSummaryBlock: 'Blockers found \u2014 fix these before export.',\n      complianceEmpty: 'No findings. The copy passes review for this industry.',\n      complianceResultsTitle: 'Review results',\n      brandUseDoc: 'Whole document',\n      brandUseSelection: 'Selection',\n      brandSelectHint: 'Select text in the document to use only that passage.',\n      textScopeLabel: 'Text to send',\n      brandPreferredLabel: 'Preferred terms',\n      brandForbiddenLabel: 'Forbidden terms',\n      brandScoreLabel: 'Current score:',\n      resultInsert: 'Apply (replace)',\n      resultToSuggestions: 'Send to suggestions',\n      resultDiscard: 'Discard',\n      tones: {\n        neutral: 'Neutral',\n        formal: 'Formal',\n        casual: 'Casual',\n        persuasive: 'Persuasive',\n        technical: 'Technical',\n        friendly: 'Friendly',\n      },\n      ops: {\n        tighten: 'Tighten',\n        elevate: 'Elevate',\n        localize: 'Localize',\n        expand: 'Expand',\n      },\n      industries: {\n        general: 'General',\n        fintech: 'Fintech / digital finance',\n        health: 'Health',\n        other: 'Other',\n      },\n      rationales: {\n        generation: 'Generation',\n        voiceMatch: 'Voice match',\n      },\n      voiceWithBank: (n: number) =>\n        `Using ${n} sample(s) from the text bank (Brand) if you leave this empty.`,\n      voiceNoBank: 'No text bank in Brand \u2014 paste samples below.',\n      audioUploadLabel: 'Upload audio / video',\n      audioTranscribing: 'Transcribing audio\u2026',\n      audioTranscribingHint: 'This can take a few seconds depending on the file length.',\n      runButton: 'Run',\n      toasts: {\n        generated: 'Text generated',\n        inserted: 'Text applied (replaced the previous)',\n        sentToSuggestions: 'Sent to suggestions',\n        rewriteReady: 'Rewrite ready',\n        opReady: (op: string) => `Operation \u201C${op}\u201D ready`,\n        outlineApplied: 'Outline applied',\n        brandScore: (n: number) => `Brand score: ${n}`,\n        abScored: 'A/B scored',\n        complianceOk: 'Legal review passed',\n        complianceWarn: 'Legal review has warnings',\n        complianceBlock: 'Legal review has blockers',\n        voiceMatchReady: 'Voice match ready',\n        clipInVariants: 'Short script saved to Variants',\n        segmentsImported: (n: number) => `${n} segments imported`,\n        selectText: 'Select text or write first',\n        selectOrWrite: 'Select or write text',\n        pasteSamples: 'Paste samples here or configure the text bank in the Brand panel',\n        separateHooks: 'Enter at least 2 hooks to compare',\n        transcribeError: 'Transcription error',\n        generic: 'Error',\n      },\n      sectionFallback: 'Draft from transcript',\n    },\n  },\n  slides: {\n    editor: {\n      noProject: 'No presentation is open',\n      newProject: 'New presentation',\n      slidesRailButtonShow: 'Show slides',\n      slidesRailButtonHide: 'Hide slides',\n      slidesRailButtonLabel: 'Slides',\n      gridTitle: 'Grid',\n      zoomOutTitle: 'Zoom out',\n      zoomInTitle: 'Zoom in',\n      presentButton: 'Present',\n      masterButton: 'Master',\n      fallbackFilename: 'Presentation',\n      toasts: {\n        savedToCloud: 'Saved to cloud \u2713',\n        cloudSaveFailed: (msg: string) => `Could not save to cloud: ${msg}`,\n        pptxImported: 'PPTX imported',\n        pptxImportedWithWarnings: (n: number) => `Imported with ${n} warnings`,\n        projectOpened: 'Project opened',\n        fileInvalid: 'Invalid file',\n      },\n    },\n    sidebar: {\n      tabAi: 'AI',\n      tabChat: 'Chat',\n      tabTheme: 'Theme',\n      tabOutline: 'Outline',\n      tabBuilds: 'Builds',\n      tabNotes: 'Notes',\n      tabComments: 'Comments',\n      tabCritique: 'Critique',\n      tabCoach: 'Coach',\n      tabLibrary: 'Library',\n      tabMaster: 'Master',\n      titleAi: 'AI',\n      titleChat: 'Chat',\n      titleTheme: 'Theme',\n      titleOutline: 'Outline',\n      titleBuilds: 'Animations',\n      titleNotes: 'Notes',\n      titleComments: 'Comments',\n      titleCritique: 'Design critique',\n      titleCoach: 'Speaker Coach',\n      titleLibrary: 'Library',\n      titleMaster: 'Master',\n      unpin: 'Unpin panel (below the timeline)',\n      pin: 'Pin panel (above the timeline)',\n      resetSize: 'Reset size',\n      closePanel: 'Close panel',\n      resizeHeight: 'Drag to change height',\n    },\n    contextMenu: {\n      title: 'Object',\n      snapOn: 'Snap on (turn off)',\n      snapOff: 'Turn snap on',\n      bringForward: 'Bring forward',\n      sendBackward: 'Send backward',\n      bringToFront: 'Bring to front',\n      sendToBack: 'Send to back',\n      copy: 'Copy',\n      delete: 'Delete',\n    },\n    creationToolbar: {\n      textTitle: 'Text (T)',\n      textTooltip: 'Text',\n      shapesTitle: 'Shapes',\n      shapesTooltip: 'Shapes',\n      shapesHeader: 'Shapes',\n      shapes: { rect: 'Rectangle', circle: 'Circle', triangle: 'Triangle', line: 'Line' },\n      imageTitle: 'Attach image',\n      imageTooltip: 'Image',\n      chartsTitle: 'Create chart',\n      chartsTooltip: 'Charts',\n      chartsHeader: 'Charts',\n      charts: { bar: 'Bar', line: 'Line', pie: 'Pie', donut: 'Donut' },\n      chartSeriesFallback: { s1: 'Series 1', trend: 'Trend', dist: 'Distribution', cats: 'Categories' },\n    },\n    chat: {\n      agentHeader: 'Agent',\n      planModeLabel: 'Plan mode',\n      inputPlaceholder: 'Message to the agent...',\n      sendButton: 'Send',\n      emptyHint: (planMode: boolean) =>\n        planMode\n          ? 'Ask the agent to add slides, rewrite, restyle or translate the deck. Plan mode: first proposes, then say \"execute the plan\".'\n          : 'Ask the agent to add slides, rewrite, restyle or translate the deck.',\n      done: 'Done.',\n      error: 'Agent error',\n      planModeOmit: (tool: string) => `(omitted in plan mode: ${tool})`,\n    },\n    ai: {\n      hint: 'AI tools for the presentation. Pick one to open its form.',\n      toolsHeader: 'Tools',\n      backToList: 'All tools',\n      generateHeader: 'Generate presentation',\n      briefPlaceholder: 'Brief, article or idea\u2026',\n      audienceLabel: 'Audience',\n      audiencePlaceholder: 'e.g. executives',\n      countLabel: 'Slides',\n      countPlaceholder: 'Slide count',\n      generateButton: 'Generate presentation',\n      generating: 'Generating\u2026',\n      activeSlideHeader: 'Active slide',\n      condense: 'Condense',\n      lessText: 'Less text',\n      audience: 'Audience',\n      magicLayout: 'Magic layout',\n      restyleBoard: 'Restyle board',\n      speakerNotes: 'Generate speaker notes',\n      translateHeader: 'Translate presentation',\n      languageLabel: 'Language',\n      langEs: 'Spanish',\n      langEn: 'English',\n      langPt: 'Portuguese',\n      translateButton: 'Translate',\n      dataHeader: 'Data \u2192 chart / narrative',\n      insertChart: 'Insert chart',\n      dataToNarrative: 'Data \u2192 narrative',\n      tools: {\n        generate: 'Generate presentation',\n        generateDesc: 'Create a full deck from a brief, audience, and slide count.',\n        rewrite: 'Rewrite slide',\n        rewriteDesc: 'Condense, reduce copy, or adapt the active slide to an audience.',\n        layout: 'Layout & style',\n        layoutDesc: 'Apply magic layout or a semantic restyle to the deck content.',\n        notes: 'Speaker notes',\n        notesDesc: 'Generate speaker notes for every slide in the outline.',\n        translate: 'Translate',\n        translateDesc: 'Translate titles, body, and notes across the whole presentation.',\n        data: 'Data to chart',\n        dataDesc: 'Paste CSV and turn it into a chart or a bullet narrative.',\n      },\n      toasts: {\n        deckGenerated: (n: number) => `Presentation generated (${n} slides)`,\n        deckGeneratedRich: (n: number, images: number, charts: number) =>\n          `Presentation generated (${n} slides${images ? `, ${images} images` : ''}${charts ? `, ${charts} charts` : ''})`,\n        deckError: 'Error generating presentation',\n        rewriteEmpty: 'The active slide has no text to rewrite',\n        slideRewritten: 'Slide rewritten',\n        notesGenerated: 'Notes generated',\n        deckTranslated: 'Presentation translated',\n        deckTranslatedFallback: 'Presentation translated (via AI translate service)',\n        translateNoChange:\n          'Translation returned the same text (backend no-op or fallback). Check the translate-deck service.',\n        translateEmpty: 'Translation returned no slides',\n        chartInserted: 'Chart inserted',\n        narrativeCreated: 'Data narrative created',\n        chartFallbackTitle: (chartType: string) => `Chart ${chartType}`,\n        generic: 'Error',\n      },\n    },\n    export: {\n      title: 'Export presentation',\n      hint: 'Pick a format. Each option downloads a file or opens another editor mode.',\n      sections: {\n        office: 'PowerPoint',\n        documents: 'Documents',\n        media: 'Images, video, and project',\n        continueIn: 'Continue in another mode',\n      },\n      formats: {\n        pptxEditable: {\n          title: 'Editable PowerPoint',\n          description: 'A .pptx file you can open and edit in PowerPoint or similar apps.',\n        },\n        pptxRaster: {\n          title: 'PowerPoint with images',\n          description: 'Each slide as an image inside a .pptx (text not editable).',\n        },\n        pdfSlides: {\n          title: 'Slides PDF',\n          description: 'One page per slide \u2014 good for sharing or printing.',\n        },\n        pdfNotes: {\n          title: 'PDF with speaker notes',\n          description: 'Includes speaker notes under each slide.',\n        },\n        pdfHandout4: {\n          title: 'Handout PDF (4 per page)',\n          description: 'Four slides per sheet for meeting handouts.',\n        },\n        htmlBuilds: {\n          title: 'Interactive HTML',\n          description: 'A web page with slides and entrance animations.',\n        },\n        zipPng: {\n          title: 'PNG images (ZIP)',\n          description: 'One image per slide, packed in a ZIP archive.',\n        },\n        videoWebm: {\n          title: 'Video',\n          description: 'Play the deck as a video (.webm), a few seconds per slide.',\n        },\n        projectWzrds: {\n          title: 'Kaiman project',\n          description: 'A .kais file to reopen this project in the editor.',\n        },\n      },\n      handoffVideo: {\n        title: 'Open in Video',\n        description: 'Send each slide as a clip to the video editor.',\n      },\n      handoffText: {\n        title: 'Open in Text',\n        description: 'Turn the outline and notes into an editable document.',\n      },\n      toasts: {\n        handoffVideo: (n: number) => `Sent ${n} slides to the video editor`,\n        handoffText: 'Document created in the text editor',\n        noImageTrack: 'No image track available in video',\n        handoffError: 'Could not open in the other mode',\n        ready: (label: string) => `${label} ready`,\n        exportError: 'Export failed',\n      },\n    },\n    master: {\n      title: (name: string) => `Master \u00B7 ${name || 'Main'}`,\n      closeAria: 'Close Master',\n      closeTitle: 'Close',\n      chromeSection: 'Master chrome',\n      contentSection: 'Copy',\n      showHeader: 'Header',\n      showFooter: 'Footer',\n      showPageNumber: 'Page number',\n      showLogo: 'Logo',\n      headerTextPlaceholder: 'Header text',\n      footerTextPlaceholder: 'Footer / confidential',\n      chromeHint: (bg: string) =>\n        `Master background: ${bg}. The chrome is composed when presenting/exporting.`,\n      unpin: 'Unpin panel (below the timeline)',\n      pin: 'Pin panel (above the timeline)',\n      resetSize: 'Reset size',\n      resizeHeight: 'Drag to change height',\n    },\n    notesPanel: {\n      noActiveSlide: 'No active slide',\n      label: 'Speaker notes',\n      placeholder: 'Type the notes for this slide...',\n      wordCount: (n: number) => `${n} words`,\n      estMinutes: (n: number) => `~${Math.max(1, Math.ceil(n / 130))} min`,\n      minutesSep: 'min',\n    },\n    commentsPanel: {\n      hint: 'Comments on the active slide. Enter adds; Shift+Enter for a new line.',\n      enterHint: 'Enter to add \u00B7 Shift+Enter for a new line',\n      inputPlaceholder: 'Write a comment\u2026',\n      add: 'Add comment',\n      resolve: 'Resolve',\n      remove: 'Delete',\n      empty: 'No comments on this slide',\n      noActiveSlide: 'No active slide',\n      listTitle: (n: number) => `Comments (${n})`,\n      open: 'Open',\n      resolved: 'Resolved',\n    },\n    slideMasterEditor: {\n      titlePrefix: 'Master:',\n      defaultName: 'Main',\n      close: 'Close',\n      showHeader: 'Header',\n      showFooter: 'Footer',\n      showPageNumber: 'Page number',\n      showLogo: 'Logo',\n      uploadLogo: 'Upload logo',\n    },\n    deckOutlinePanel: {\n      extract: 'Extract from deck',\n      apply: 'Apply to deck',\n      placeholder: '# Title\\n- Bullet 1\\n- Bullet 2\\n\\n# Next slide',\n      bulletsCount: (n: number) => `${n} bullets`,\n      editorTitle: 'Outline',\n      editorHint: 'Edit the outline as markdown and apply it to the deck.',\n      slidesTitle: 'Slides',\n      defaultSection: 'Section',\n      empty: 'No slides',\n    },\n    libraryPanel: {\n      findReplaceTitle: 'Find / replace',\n      findPlaceholder: 'Find in deck',\n      replacePlaceholder: 'Replace with',\n      replaceAll: 'Replace across deck',\n      brandComponentsTitle: 'Brand components',\n      reset: 'Reset',\n      libraryTitle: 'Slide library',\n      saveActive: 'Save active',\n      insert: 'Insert',\n      delete: 'Delete',\n      empty: 'Library is empty',\n      slideSaved: 'Slide saved to library',\n      slideInserted: 'Slide inserted',\n      selectSlide: 'Select a slide first',\n      replacementsCount: (n: number) => `${n} replacements`,\n      noReplacements: '0 replacements',\n      brandCta: 'CTA block',\n      brandQuote: 'Quote',\n      brandKpi: 'Large KPI',\n      componentInserted: (name: string) => `${name} inserted`,\n      jobsTitle: 'My files',\n      jobsHint: 'Image and video jobs you can drop onto the slide.',\n      jobsRefresh: 'Refresh',\n      jobsEmpty: 'No image or video files',\n      jobsLoadError: 'Could not load files',\n      jobsInsertError: 'Could not insert file',\n      mediaInserted: (name: string) => `Inserted: ${name}`,\n      filterAll: 'All',\n      filterImage: 'Image',\n      filterVideo: 'Video',\n    },\n    themePanel: {\n      canvas: 'Canvas',\n      canvasRatio: 'Aspect ratio',\n      baseline: 'Typographic baseline',\n      semanticRestyle: 'Semantic restyle',\n      restyleMode: 'Mode',\n      restyleBoard: 'Board',\n      restyleSales: 'Sales',\n      restyleInternal: 'Internal',\n      brandTerms: 'Brand terms',\n      importBrandTerms: 'Import from Text',\n      forbiddenLabel: (n: number) => `Forbidden: ${n}`,\n      preferredLabel: (n: number) => `Preferred: ${n}`,\n      colors: 'Presentation background',\n      colorsBackgroundOnly:\n        'Only changes the deck background. Edit each object\u2019s color in the properties bar when selected.',\n      colorBackground: 'Background',\n      colorSurface: 'Surface',\n      colorTitle: 'Title',\n      colorBody: 'Body',\n      colorAccent: 'Accent',\n      colorMuted: 'Muted',\n      typography: 'Typography',\n      titleLabel: 'Title font',\n      bodyLabel: 'Body font',\n    },\n    buildsPanel: {\n      transitionLabel: 'Entrance transition',\n      durationLabel: 'Duration (s)',\n      buildsHeader: (n: number) => `Builds (${n})`,\n      addToSelected: '+ Selection',\n      remove: 'Remove',\n      triggerClick: 'On click',\n      triggerWithPrevious: 'With previous',\n      triggerAfterPrevious: 'After previous',\n      empty: 'Select an object and add an animation.',\n      objectLabel: (id: string) => `Object \u00B7 ${id.slice(0, 8)}`,\n      animationLabel: 'Animation',\n      triggerLabel: 'Trigger',\n      transitionLabels: {\n        cut: 'Cut',\n        'cross-dissolve': 'Cross dissolve',\n        'fade-black': 'Fade to black',\n        'slide-left': 'Slide left',\n        'slide-right': 'Slide right',\n        'push-left': 'Push left',\n        'zoom-in': 'Zoom in',\n        'blur-dissolve': 'Blur dissolve',\n        'morph-cut': 'Morph',\n      } as Record<string, string>,\n      presetLabels: {\n        fade: 'Fade',\n        'fade-up': 'Fade up',\n        'slide-left': 'Slide',\n        'scale-in': 'Scale',\n        'bounce-in': 'Bounce',\n        'blur-in': 'Blur',\n      } as Record<string, string>,\n    },\n    designCriticPanel: {\n      hint: 'Design audit, Q&A, and quick fixes. Pick a tool to open it.',\n      toolsHeader: 'Tools',\n      backToList: 'All tools',\n      audit: 'Audit',\n      qaPrep: 'Prep Q&A',\n      condense: 'Condense',\n      contrast: 'Contrast',\n      autofit: 'Autofit',\n      magicLayout: 'Magic layout',\n      splitSlide: 'Split slide',\n      altTexts: 'Alt texts',\n      runAudit: 'Run audit',\n      runQa: 'Generate questions',\n      scoreLine: (score: number | null, minutes: number | null, slides: number) =>\n        `Score: ${score ?? '\u2013'}${minutes != null ? ` \u00B7 ~${minutes} min` : ''} \u00B7 ${slides} slides`,\n      applyFix: 'Apply',\n      fixApplied: 'Fix applied',\n      questionsHeader: 'Likely questions',\n      slidePrefix: (n: number) => `Slide ${n + 1}`,\n      severityError: 'Error',\n      severityWarn: 'Warning',\n      severityInfo: 'Info',\n      auditDone: 'Audit complete',\n      qaReady: 'Q&A ready',\n      generating: 'Generating\u2026',\n      tools: {\n        audit: 'Design audit',\n        auditDesc: 'Check density, contrast, brand terms, and layout issues.',\n        qa: 'Prep Q&A',\n        qaDesc: 'Generate likely per-slide questions for rehearsal.',\n        condense: 'Condense text',\n        condenseDesc: 'Tighten copy on the active slide for clarity.',\n        contrast: 'Fix contrast',\n        contrastDesc: 'Adjust text colors for readability on the background.',\n        autofit: 'Autofit',\n        autofitDesc: 'Fit selected or slide text into its box.',\n        magicLayout: 'Magic layout',\n        magicLayoutDesc: 'Reorganize content with an automatic layout.',\n        split: 'Split slide',\n        splitDesc: 'Break dense slides into shorter ones.',\n        alt: 'Alt texts',\n        altDesc: 'Ensure alternative text on deck images.',\n      },\n    },\n    presenterView: {\n      rehearsalLabel: 'Rehearsal',\n      rehearsalTotal: (s: number) => `Rehearsal \u00B7 total ${Math.round(s)}s`,\n      titleRehearsal: 'Rehearsal',\n      titleInk: 'Ink',\n      titleClearInk: 'Clear ink',\n      next: 'Next',\n      teleprompter: 'Teleprompter',\n      noNotes: 'No notes',\n      endOfPresentation: 'End of presentation',\n      slideTiming: (n: number, s: number) => `S${n + 1}: ${s.toFixed(1)}s`,\n    },\n    coachPanel: {\n      intro: 'Rehearsal + pacing, pause and Q tips. Use Presenter View (R) to record timings.',\n      rehearsalSummary: (count: number, total: number, avg: number) =>\n        `Rehearsal: ${count} slides \u00B7 total ${Math.round(total)}s \u00B7 avg ${Math.round(avg)}s`,\n      clearTimings: 'Clear timings',\n      run: 'Generate coach',\n      applyToNotes: 'Add tips to speaker notes',\n      done: 'Coach ready',\n      appliedToNotes: (n: number) => `Tips added to ${n} speaker notes`,\n      slideLabel: (n: number) => `Slide ${n + 1}`,\n      pacingSeconds: (n: number) => ` \u00B7 ~${n}s`,\n    },\n    contextToolbar: {\n      alignLeft: 'Align left',\n      alignCenter: 'Center',\n      alignRight: 'Align right',\n      autofitText: 'Autofit text',\n      altText: 'Alt text',\n      fontFamily: 'Typography',\n      fontSize: 'Font size',\n      fontSizeDecrease: 'Decrease size',\n      fontSizeIncrease: 'Increase size',\n      fillColor: 'Color',\n      replaceUpload: 'Replace (upload)',\n      replaceFromFiles: 'Replace from my files',\n      bringForward: 'Bring forward',\n      sendBackward: 'Send backward',\n      bringToFront: 'Bring to front',\n      sendToBack: 'Send to back',\n      duplicate: (key: string) => `Duplicate (${key})`,\n      remove: (key: string) => `Delete (${key})`,\n    },\n    floatingRail: {\n      title: (n: number) => `Slides (${n})`,\n      add: 'Add',\n      unpin: 'Unpin panel',\n      pin: 'Pin panel',\n      resetSize: 'Reset size',\n      closeAria: 'Close slide panel',\n    },\n    slideCanvas: {\n      selectAtLeast2: 'Select at least 2 objects',\n      selectAtLeast3: 'Select at least 3 objects',\n      selectTextBox: 'Select a text box',\n      selectImageOrObject: 'Select an image or object',\n      selectToDelete: 'Select at least one object to delete',\n      deleteSelectionBody: (n: number) =>\n        n === 1\n          ? 'Delete the selected item? This cannot be undone.'\n          : `Delete the ${n} selected items? This cannot be undone.`,\n      selectToDuplicate: 'Select an object to duplicate',\n      overflowWarning: 'Text with overflow',\n      imageAddError: 'Could not add the image to the canvas',\n    },\n    altTextModal: {\n      title: 'Alternative text',\n      hint: 'Describe the image for accessibility (screen readers and export).',\n      placeholder: 'e.g. Q3 growth chart',\n      save: 'Save',\n      cancel: 'Cancel',\n    },\n    slideRail: {\n      show: 'Show',\n      hide: 'Hide',\n      duplicate: 'Duplicate',\n      remove: 'Delete',\n      deleteTitle: 'Delete slide',\n      deleteBody: (name: string) =>\n        `Delete slide \"${name}\"? This cannot be undone.`,\n      deleteConfirm: 'Delete',\n    },\n  },\n  store: {\n    toasts: {\n      editor: {\n        objectLinked: 'Object linked. Copy and paste it on another page to keep them in sync.',\n        objectUnlinked: 'Object unlinked',\n        versionLoaded: (name: string) => `Version \"${name}\" loaded successfully`,\n        fileSaved: 'File saved successfully',\n        fileSaveError: 'Error saving file to the database',\n        fileDeleted: 'File deleted',\n        fileDeleteError: 'Error deleting file',\n        uploadsCleared: 'Upload history cleared',\n        uploadsClearError: 'Error clearing uploads',\n        fontRegistered: (name: string) => `Font registered: ${name}`,\n        fontRegisterError: (msg: string) => `Error registering font: ${msg || 'unknown'}`,\n        fontDeleted: 'Font deleted',\n        fontDeleteError: 'Error deleting font',\n        bgRemoved: 'Background removed successfully',\n        bgRemoveError: (msg: string) => msg || 'Error removing the background.',\n        imageModified: 'Image modified successfully',\n        imageModifyError: (msg: string) => msg || 'Error modifying the image.',\n        sketchImageCreated: 'Sketch image created successfully',\n        sketchImageError: (msg: string) => msg || 'Error generating image from sketch.',\n        inpaintImageCreated: 'Image generated in area successfully',\n        inpaintImageError: (msg: string) => msg || 'Error generating image in area.',\n        subjectSeparated: 'Subject separated into a new layer',\n        subjectSeparateError: (msg: string) => msg || 'Error separating the subject from the image.',\n        magicEraserDone: 'Magic eraser executed successfully',\n        magicEraserNothingFound:\n          'AI did not find anything relevant to erase in that area. Adjust the marks and try again.',\n        magicEraserNeedMarks: 'Paint red marks on the image before applying the magic eraser.',\n        magicEraserError: (msg: string) => msg || 'Error running Magic Eraser.',\n        aiSolidBgApplied: 'AI solid color background applied',\n        aiSolidGradientApplied: (color: string) => `Gradient simplified to solid color (${color}) applied`,\n        aiGenerating: 'Generating AI background image with Gemini\u2026',\n        aiBgGenerated: 'AI background image generated and inserted',\n        aiTextStyleApplied: 'AI text style applied successfully',\n        aiShapeStyleApplied: 'AI shape style applied successfully',\n        aiPhotoFilterApplied: 'AI photo filters applied successfully',\n        upscaleSelectImage: 'Select an image to upscale.',\n        upscaleStarted: (factor: number) => `Starting Upscale ${factor}x... This may take a few seconds.`,\n        upscaleDone: (factor: number) => `Upscale ${factor}x completed successfully.`,\n        upscaleError: (msg: string) => msg || 'Error running Upscale AI.',\n        variationsSelectImage: 'Select an image to generate variations.',\n        variationsStarted: 'Generating image variations...',\n        variationsDone: 'Variations generated. Pick one.',\n        variationsError: (msg: string) => msg || 'Error generating AI variations.',\n        autoEnhanceSelectImage: 'Select an image to apply Auto-Enhance.',\n        autoEnhanceStarted: 'Analyzing and applying Magic Auto-Enhance',\n        autoEnhanceDone: 'Magic Auto-Enhance completed',\n        autoEnhanceError: 'Could not apply Auto-Enhance.',\n        // Generic error fallbacks for image-mode AI tools. The store\n        // catch blocks call `getActiveMessages().store.toasts.editor.<key>`\n        // when the underlying error has no message. Each value is the\n        // English counterpart of the previously-hardcoded Spanish fallback.\n        aiRemoveBackgroundError: 'Could not remove background.',\n        aiModifyImageError: 'Could not modify image.',\n        aiGenerateImageError: 'Could not generate image.',\n        aiApplyGenerativeBgError: 'Could not apply generative background.',\n        aiMagicResizeError: 'Could not magic-resize.',\n        aiAutoLayoutError: 'Could not apply Auto Layout.',\n        aiCopySuggestionsError: 'Could not generate copy suggestions.',\n        aiVectorizeStrokeError: 'Could not vectorize stroke.',\n        aiSketchError: 'Could not generate image from sketch.',\n        aiInpaintError: 'Could not generate image in area.',\n        aiSeparateSubjectError: 'Could not separate subject from image.',\n        aiMagicEraserError: 'Could not run Magic Eraser.',\n        aiDesignError: 'Could not process design with AI.',\n        aiDesignToastError: 'Could not apply AI design.',\n        aiUpscaleError: 'Could not run AI Upscale.',\n        aiVariationsError: 'Could not generate AI variations.',\n        // Component-level AI tool fallbacks (consumed via useTranslation()).\n        stockLoadError: 'Could not load images.',\n        voiceoverUnknownError: 'Unknown error while generating the voice.',\n        transcriptAnalysisError: 'Error analyzing the transcript.',\n        translateSubtitlesError: 'Could not translate subtitles.',\n        aiStyleError: 'Could not apply AI style.',\n        aiColorGradingError: 'Could not apply AI color grading preset.',\n        exportUnknownError: 'Unknown error',\n        colorGradingError: 'Could not generate AI color grading.',\n        exportErrorTitle: 'Export error',\n        subtitlesErrorTitle: 'Subtitles error',\n      },\n      audio: {\n        clipsCopied: (n: number) => `${n} clip(s) copied`,\n        noFillers: 'No filler words detected',\n        fillersRemoved: (n: number) => `Removed ${n} filler words`,\n        selectClipFirst: 'Select a clip first',\n        trimPlayheadMiss: 'Playhead must be inside the clip',\n        trackDeleted: (name: string) => `Track deleted: ${name}`,\n        keepOneTrack: 'At least one audio track is required',\n      },\n      slides: {\n        atLeastOneSlide: 'At least one slide must remain',\n        magicLayoutApplied: 'Magic layout applied',\n        restyleApplied: (mode: string) => `Restyle ${mode} applied`,\n        chartInserted: 'Chart inserted',\n        canvasResized: (w: number, h: number) => `Canvas ${w}x${h}`,\n        notEnoughContentToSplit: 'Not enough content to split',\n        denseSlideSplit: 'Dense slide split in 2',\n        saveLocalError: 'Could not save the presentation locally',\n      },\n      text: {\n        snapshotSaved: (name: string) => `Snapshot \"${name}\" saved`,\n        snapshotRestored: (name: string) => `Restored: ${name}`,\n        sectionNotFound: 'Section not found in snapshot',\n        sectionRestored: (heading: string) => `Section \"${heading}\" restored`,\n      },\n    },\n  },\n  presets: {\n    brush: {\n      calligraphy: 'Calligraphy',\n      highlighter: 'Yellow highlighter',\n      chalk: 'Soft chalk',\n      neonMagenta: 'Neon magenta',\n      neonCyan: 'Neon cyan',\n      spray: 'Spray graffiti',\n    },\n    stockBg: {\n      neonSynthwave: 'Neon synthwave',\n      minimalistMarble: 'Minimalist marble',\n      cyberpunkGrid: 'Cyberpunk grid',\n      darkBeach: 'Dark beach',\n      cleanWorkspace: 'Clean workspace',\n      watercolorPastel: 'Watercolor pastel',\n    },\n    stockLayer: {\n      abstractNeon: 'Abstract neon',\n      cyberWave: 'Cyber wave',\n      vidrio3D: '3D glass',\n      acuarelaPastel: 'Watercolor pastel',\n    },\n    gradient: {\n      sunsetGlow: 'Sunset glow',\n      oceanBreeze: 'Ocean breeze',\n      purpleHaze: 'Purple haze',\n      emeraldGlow: 'Emerald glow',\n      sweetCandy: 'Sweet candy',\n      spaceVoid: 'Space void',\n    },\n    canvasSize: {\n      // Social\n      instagramPost: 'Instagram Post',\n      instagramStory: 'Instagram Story',\n      youtubeThumbnail: 'YouTube Thumbnail',\n      youtubeBanner: 'YouTube Banner',\n      // Web\n      fullHdDesktop: 'Full HD Desktop',\n      macbookPro: 'MacBook Pro',\n      mobileAppScreen: 'Mobile App Screen',\n      // Print\n      posterA4: 'A4 Poster',\n      cartaLetter: 'Letter',\n      businessCard: 'Business Card',\n      // Description\n      square1_1: '1:1 Square',\n      portrait9_16: '9:16 Vertical',\n      landscape16_9: '16:9 Thumbnail',\n      landscape16_9Banner: '16:9 Banner',\n      monitor16_9: '16:9 Monitor',\n      laptop16_10: '16:10 Laptop',\n      iphoneScreen: 'iPhone screen',\n      a4Standard: 'Standard A4 paper',\n      letterUS: 'US Letter',\n      businessCardDesc: 'Business card',\n    },\n  },\n};\n", "/**\n * Internal i18n \u2014 single-locale-per-mount, no external library.\n *\n * The editor is consumed by exactly one host (Kaiman Studio AI).\n * That host passes the user locale to the <Editor /> component. The editor\n * picks the right dictionary and exposes `t(...)` via React context.\n *\n * The user can also override the locale from the File menu; that preference\n * is persisted in localStorage and takes precedence over the host prop.\n *\n * Why no `react-i18next` / `react-intl`?\n *  - One consumer, two locales (es, en) for now. ICU MessageFormat and plural\n *    rules are overkill.\n *  - Zero new runtime dep. Bundle size stays flat.\n *  - The `t` object is a plain nested dict, fully tree-shakeable by mode.\n *\n * Adding a locale:\n *  1. Copy `en.ts` to `xx.ts`.\n *  2. Translate each value (keep the same keys & function signatures).\n *  3. Add `'xx'` to the `Locale` union and to the `dictionaries` map.\n *  4. TypeScript will refuse to compile if any key is missing.\n */\n\nimport React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';\nimport { es } from './es';\nimport { en } from './en';\n\nexport type Locale = 'es' | 'en';\nexport type Messages = typeof es;\n\nconst dictionaries: Record<Locale, Messages> = { es, en };\n\nconst FALLBACK_LOCALE: Locale = 'es';\nconst LOCALE_STORAGE_KEY = 'wizard-editor-locale';\nconst LOCALE_CHANGE_EVENT = 'wizard:locale-change';\n\ninterface I18nContextValue {\n  locale: Locale;\n  t: Messages;\n  setLocale: (locale: Locale) => void;\n}\n\nconst I18nContext = createContext<I18nContextValue | null>(null);\n\nexport interface I18nProviderProps {\n  /** Locale from the host. Overridden by a user preference in localStorage. */\n  locale?: Locale;\n  children: React.ReactNode;\n}\n\n/**\n * Module-level \"active locale\" so that non-React call sites (Zustand store\n * actions, `addToast` from inside a service, etc.) can read the current\n * dictionary without having to thread the I18nProvider context through.\n *\n * Updated by `<I18nProvider>` whenever the resolved locale changes.\n * Initial value is the fallback so that any code that runs before the\n * provider mounts (rare, but possible) still gets a valid dictionary.\n */\nlet activeLocale: Locale = FALLBACK_LOCALE;\n\nfunction isLocale(value: unknown): value is Locale {\n  return value === 'es' || value === 'en';\n}\n\nfunction readStoredLocale(): Locale | null {\n  if (typeof window === 'undefined') return null;\n  try {\n    const raw = window.localStorage.getItem(LOCALE_STORAGE_KEY);\n    return isLocale(raw) ? raw : null;\n  } catch {\n    return null;\n  }\n}\n\nfunction writeStoredLocale(locale: Locale): void {\n  if (typeof window === 'undefined') return;\n  try {\n    window.localStorage.setItem(LOCALE_STORAGE_KEY, locale);\n  } catch {\n    // ignore quota / privacy mode\n  }\n}\n\n/** Returns the dictionary for the currently active locale. Safe to call from anywhere. */\nexport function getActiveMessages(): Messages {\n  return dictionaries[activeLocale] ?? dictionaries[FALLBACK_LOCALE];\n}\n\n/** Returns the currently active locale. */\nexport function getActiveLocale(): Locale {\n  return activeLocale;\n}\n\nexport const I18nProvider: React.FC<I18nProviderProps> = ({ locale, children }) => {\n  const [userLocale, setUserLocale] = useState<Locale | null>(() => readStoredLocale());\n\n  const resolved: Locale = userLocale\n    ?? (locale && dictionaries[locale] ? locale : FALLBACK_LOCALE);\n\n  const setLocale = useCallback((next: Locale) => {\n    if (!dictionaries[next]) return;\n    writeStoredLocale(next);\n    setUserLocale(next);\n    activeLocale = next;\n    if (typeof window !== 'undefined') {\n      window.dispatchEvent(new CustomEvent(LOCALE_CHANGE_EVENT, { detail: next }));\n    }\n  }, []);\n\n  // Keep nested / sibling providers in sync when locale changes elsewhere\n  useEffect(() => {\n    const onLocaleChange = (event: Event) => {\n      const next = (event as CustomEvent).detail;\n      if (isLocale(next)) setUserLocale(next);\n    };\n    window.addEventListener(LOCALE_CHANGE_EVENT, onLocaleChange);\n    return () => window.removeEventListener(LOCALE_CHANGE_EVENT, onLocaleChange);\n  }, []);\n\n  const value = useMemo<I18nContextValue>(\n    () => ({ locale: resolved, t: dictionaries[resolved], setLocale }),\n    [resolved, setLocale]\n  );\n\n  // Sync module-level activeLocale so non-React callers see the current\n  // dictionary on the next render cycle.\n  if (activeLocale !== resolved) activeLocale = resolved;\n\n  return <I18nContext.Provider value={value}>{children}</I18nContext.Provider>;\n};\n\n/**\n * Returns the active translation table. Falls back to Spanish if used outside\n * an <I18nProvider> (e.g. DevApp.tsx mounting the editor without a host).\n */\nexport function useTranslation(): Messages {\n  const ctx = useContext(I18nContext);\n  return ctx?.t ?? dictionaries[FALLBACK_LOCALE];\n}\n\n/** Returns the active locale. Useful for formatting dates/numbers with `Intl`. */\nexport function useLocale(): Locale {\n  const ctx = useContext(I18nContext);\n  return ctx?.locale ?? FALLBACK_LOCALE;\n}\n\n/** Change the editor locale at runtime (persisted in localStorage). */\nexport function useSetLocale(): (locale: Locale) => void {\n  const ctx = useContext(I18nContext);\n  return ctx?.setLocale ?? ((next: Locale) => {\n    if (!dictionaries[next]) return;\n    writeStoredLocale(next);\n    activeLocale = next;\n  });\n}\n", "/**\n * Compact cloud-save status chips (icon-only). Max 3 on screen.\n * Used by autosave + manual \"save to cloud\" across all modes.\n */\n\nexport type CloudSaveChipStatus = 'saving' | 'success' | 'error';\n\nexport type CloudSaveChip = {\n  id: string;\n  status: CloudSaveChipStatus;\n  /** Accessible label (not shown in UI). */\n  label: string;\n};\n\nconst MAX_CHIPS = 3;\nconst SUCCESS_MS = 2800;\nconst ERROR_MS = 5000;\n\nlet chips: CloudSaveChip[] = [];\nconst listeners = new Set<() => void>();\nconst dismissTimers = new Map<string, ReturnType<typeof setTimeout>>();\n\nfunction emit() {\n  listeners.forEach((fn) => fn());\n}\n\nfunction clearDismiss(id: string) {\n  const t = dismissTimers.get(id);\n  if (t) {\n    clearTimeout(t);\n    dismissTimers.delete(id);\n  }\n}\n\nfunction scheduleDismiss(id: string, ms: number) {\n  clearDismiss(id);\n  dismissTimers.set(\n    id,\n    setTimeout(() => {\n      dismissTimers.delete(id);\n      removeCloudSaveChip(id);\n    }, ms),\n  );\n}\n\nfunction trimToMax() {\n  while (chips.length > MAX_CHIPS) {\n    const completedIdx = chips.findIndex((c) => c.status !== 'saving');\n    const dropIdx = completedIdx >= 0 ? completedIdx : 0;\n    const dropped = chips[dropIdx];\n    if (dropped) clearDismiss(dropped.id);\n    chips = chips.filter((_, i) => i !== dropIdx);\n  }\n}\n\nexport function getCloudSaveChips(): CloudSaveChip[] {\n  return chips;\n}\n\nexport function subscribeCloudSaveChips(listener: () => void): () => void {\n  listeners.add(listener);\n  return () => listeners.delete(listener);\n}\n\n/** Start a saving chip. Returns id for later resolve/fail. */\nexport function beginCloudSaveChip(label: string): string {\n  const id = `cs_${Math.random().toString(36).slice(2, 9)}`;\n  chips = [...chips, { id, status: 'saving', label }];\n  trimToMax();\n  emit();\n  return id;\n}\n\nexport function resolveCloudSaveChip(\n  id: string,\n  status: 'success' | 'error',\n  label?: string,\n): void {\n  const exists = chips.some((c) => c.id === id);\n  if (!exists) return;\n  chips = chips.map((c) =>\n    c.id === id\n      ? { ...c, status, label: label ?? c.label }\n      : c,\n  );\n  emit();\n  scheduleDismiss(id, status === 'success' ? SUCCESS_MS : ERROR_MS);\n}\n\nexport function removeCloudSaveChip(id: string): void {\n  clearDismiss(id);\n  const next = chips.filter((c) => c.id !== id);\n  if (next.length === chips.length) return;\n  chips = next;\n  emit();\n}\n", "/**\n * Transcript-linked editing helpers (Descript-style word ranges \u2192 clip ops).\n */\n\nimport type { TranscriptionSegment } from '../../services/transcriptionService';\n\nexport interface TranscriptWord {\n  id: string;\n  clipId: string;\n  /** Absolute timeline seconds. */\n  start: number;\n  end: number;\n  text: string;\n  isFiller: boolean;\n}\n\nconst FILLER_RE =\n  /^(eh+|um+|uh+|ah+|mm+|hmm+|este|esto|o sea|like|you know|basically|literally|vale|bueno)$/i;\n\nexport function isFillerText(text: string): boolean {\n  const t = text.trim().replace(/[.,!?;:\"\"']/g, '');\n  return FILLER_RE.test(t);\n}\n\n/** Expand Whisper segments into word timings (real timestamps when available). */\nexport function segmentsToWords(\n  segments: TranscriptionSegment[],\n  clipId: string,\n  clipStartTime: number,\n  topLevelWords?: Array<{ word: string; start: number; end: number }>\n): TranscriptWord[] {\n  const words: TranscriptWord[] = [];\n  let n = 0;\n\n  if (topLevelWords?.length) {\n    for (const w of topLevelWords) {\n      const text = w.word.trim();\n      if (!text) continue;\n      words.push({\n        id: `tw_${clipId}_${n++}`,\n        clipId,\n        start: clipStartTime + w.start,\n        end: clipStartTime + w.end,\n        text,\n        isFiller: isFillerText(text),\n      });\n    }\n    return words;\n  }\n\n  for (const seg of segments) {\n    if (seg.words?.length) {\n      for (const w of seg.words) {\n        const text = w.word.trim();\n        if (!text) continue;\n        words.push({\n          id: `tw_${clipId}_${n++}`,\n          clipId,\n          start: clipStartTime + w.start,\n          end: clipStartTime + w.end,\n          text,\n          isFiller: isFillerText(text),\n        });\n      }\n      continue;\n    }\n    // Fallback: uniform split within the segment\n    const parts = seg.text.trim().split(/\\s+/).filter(Boolean);\n    if (!parts.length) continue;\n    const dur = Math.max(0.05, seg.end - seg.start);\n    const step = dur / parts.length;\n    parts.forEach((text, i) => {\n      const start = clipStartTime + seg.start + i * step;\n      const end = clipStartTime + seg.start + (i + 1) * step;\n      words.push({\n        id: `tw_${clipId}_${n++}`,\n        clipId,\n        start,\n        end,\n        text,\n        isFiller: isFillerText(text),\n      });\n    });\n  }\n  return words;\n}\n\n/** Merge selected word ids into contiguous absolute time ranges. */\nexport function wordsToRanges(\n  words: TranscriptWord[],\n  selectedIds: Set<string>\n): Array<{ start: number; end: number }> {\n  const selected = words\n    .filter((w) => selectedIds.has(w.id))\n    .sort((a, b) => a.start - b.start);\n  if (!selected.length) return [];\n  const ranges: Array<{ start: number; end: number }> = [];\n  let cur = { start: selected[0]!.start, end: selected[0]!.end };\n  for (let i = 1; i < selected.length; i++) {\n    const w = selected[i]!;\n    if (w.start <= cur.end + 0.08) {\n      cur.end = Math.max(cur.end, w.end);\n    } else {\n      ranges.push(cur);\n      cur = { start: w.start, end: w.end };\n    }\n  }\n  ranges.push(cur);\n  return ranges;\n}\n\nexport function shiftWordsAfter(\n  words: TranscriptWord[],\n  fromTime: number,\n  delta: number\n): TranscriptWord[] {\n  return words.map((w) =>\n    w.start >= fromTime - 1e-6\n      ? { ...w, start: Math.max(0, w.start + delta), end: Math.max(0, w.end + delta) }\n      : w\n  );\n}\n\nexport function removeWordsInRanges(\n  words: TranscriptWord[],\n  ranges: Array<{ start: number; end: number }>\n): TranscriptWord[] {\n  return words.filter(\n    (w) => !ranges.some((r) => w.start < r.end && w.end > r.start)\n  );\n}\n", "/**\n * User-facing error copy \u2014 never leak HTTP/JSON/stack to the UI.\n * Always `console.error` the real cause for debugging.\n */\n\nimport { AuthError, NetworkError, NotImplementedError } from '../services/wizardApiClient';\nimport { getActiveMessages } from '../i18n';\n\n/** True when a string looks like a developer / backend diagnostic. */\nexport function looksTechnical(message: string): boolean {\n  const m = (message || '').trim();\n  if (!m) return true;\n  if (m.length > 160) return true;\n  if (/^EMPTY_[A-Z0-9_]+$/.test(m)) return true;\n  return (\n    /HTTP\\s*\\d+/i.test(m) ||\n    /\\/api\\/[a-z0-9_\\-/{}.]+/i.test(m) ||\n    /\\{[\\s\\S]{0,40}\"(error|message|status|code)\"/i.test(m) ||\n    /NotImplemented|ApiError|AuthError|NetworkError|TypeError|ReferenceError|SyntaxError/i.test(\n      m,\n    ) ||\n    /Empty .+ (preset|from backend)|Expected |keys:|see console/i.test(m) ||\n    /OpenAI|Whisper|Swagger|__thought|ECONN|CORS|multipart|unsupported_value/i.test(m) ||\n    /Feature [\"'].+[\"'] is not yet/i.test(m) ||\n    /backend error|upstream|stack trace|at \\w+\\s*\\(/i.test(m) ||\n    /status:\\s*\\d+|failed to fetch|networkerror/i.test(m)\n  );\n}\n\nfunction copy() {\n  return getActiveMessages().common.errors;\n}\n\n/**\n * Log the raw error and return a short, localized message safe for toasts /\n * dialogs / inline banners. Validation UX strings that are already friendly\n * are preserved when passed as `fallback` or as a non-technical Error message.\n */\nexport function toUserFacingError(\n  err: unknown,\n  opts?: { context?: string; fallback?: string },\n): string {\n  const ctx = opts?.context ? `[${opts.context}]` : '[error]';\n  console.error(ctx, err);\n\n  const t = copy();\n\n  if (err instanceof AuthError) return t.sessionExpired;\n  if (err instanceof NetworkError) return t.network;\n  if (err instanceof NotImplementedError) return t.comingSoon;\n\n  const raw =\n    err instanceof Error\n      ? err.message\n      : typeof err === 'string'\n        ? err\n        : '';\n\n  if (raw && !looksTechnical(raw)) return raw;\n  if (opts?.fallback && !looksTechnical(opts.fallback)) return opts.fallback;\n\n  return t.unexpected;\n}\n\n/** Sanitize a toast/dialog string that may already be a technical dump. */\nexport function sanitizeUserFacingMessage(\n  message: string,\n  opts?: { log?: boolean; context?: string },\n): string {\n  if (opts?.log !== false && looksTechnical(message)) {\n    console.error(opts?.context ? `[${opts.context}]` : '[error:ui]', message);\n  }\n  if (!looksTechnical(message)) return message;\n  return copy().unexpected;\n}\n", "/** Convert linear gain to dB. */\nexport function linearToDb(linear: number): number {\n  if (linear <= 0) return -Infinity;\n  return 20 * Math.log10(linear);\n}\n\n/** Convert dB to linear gain. */\nexport function dbToLinear(db: number): number {\n  if (!Number.isFinite(db)) return 0;\n  return Math.pow(10, db / 20);\n}\n\nexport type FadeCurve = 'linear' | 'logarithmic' | 's-curve' | 'exponential';\n\n/** Evaluate a fade envelope 0\u21921 over normalized t in [0,1]. */\nexport function evaluateFade(t: number, curve: FadeCurve, direction: 'in' | 'out'): number {\n  const x = Math.max(0, Math.min(1, t));\n  let y: number;\n  switch (curve) {\n    case 'logarithmic':\n      y = Math.log10(1 + 9 * x) / 1;\n      break;\n    case 'exponential':\n      y = (Math.pow(10, x) - 1) / 9;\n      break;\n    case 's-curve':\n      y = x * x * (3 - 2 * x);\n      break;\n    case 'linear':\n    default:\n      y = x;\n  }\n  return direction === 'in' ? y : 1 - y;\n}\n", "/**\n * Build a Web Audio effect chain from AppliedAudioEffect descriptors.\n */\n\nimport type { AppliedAudioEffect } from '../../../store/useAudioStore';\nimport { dbToLinear } from '../dsp/gain';\n\nexport interface EffectChain {\n  input: AudioNode;\n  output: AudioNode;\n  nodes: AudioNode[];\n  /** Dynamics compressors/limiters in the chain (for GR metering). */\n  compressors: DynamicsCompressorNode[];\n  dispose: () => void;\n}\n\nfunction createEq(ctx: BaseAudioContext, params: Record<string, number | boolean | string>): BiquadFilterNode[] {\n  const low = ctx.createBiquadFilter();\n  low.type = 'lowshelf';\n  low.frequency.value = Number(params.lowFreq ?? 200);\n  low.gain.value = Number(params.lowGain ?? 0);\n\n  const mid = ctx.createBiquadFilter();\n  mid.type = 'peaking';\n  mid.frequency.value = Number(params.midFreq ?? 1000);\n  mid.Q.value = Number(params.midQ ?? 1);\n  mid.gain.value = Number(params.midGain ?? 0);\n\n  const high = ctx.createBiquadFilter();\n  high.type = 'highshelf';\n  high.frequency.value = Number(params.highFreq ?? 4000);\n  high.gain.value = Number(params.highGain ?? 0);\n\n  low.connect(mid);\n  mid.connect(high);\n  return [low, mid, high];\n}\n\n/**\n * Create an effect chain. Returns a no-op passthrough when effects is empty.\n */\nexport function createEffectChain(\n  ctx: BaseAudioContext,\n  effects: AppliedAudioEffect[]\n): EffectChain {\n  const input = ctx.createGain();\n  const output = ctx.createGain();\n  const nodes: AudioNode[] = [input];\n  const compressors: DynamicsCompressorNode[] = [];\n\n  let prev: AudioNode = input;\n  const enabled = [...effects]\n    .filter((e) => e.enabled)\n    .sort((a, b) => a.order - b.order);\n\n  for (const fx of enabled) {\n    switch (fx.type) {\n      case 'eq': {\n        const eqNodes = createEq(ctx, fx.params);\n        prev.connect(eqNodes[0]!);\n        prev = eqNodes[eqNodes.length - 1]!;\n        nodes.push(...eqNodes);\n        break;\n      }\n      case 'highpass':\n      case 'lowpass': {\n        const f = ctx.createBiquadFilter();\n        f.type = fx.type === 'highpass' ? 'highpass' : 'lowpass';\n        f.frequency.value = Number(fx.params.frequency ?? (fx.type === 'highpass' ? 80 : 12000));\n        f.Q.value = Number(fx.params.Q ?? 0.7);\n        prev.connect(f);\n        prev = f;\n        nodes.push(f);\n        break;\n      }\n      case 'compressor':\n      case 'limiter': {\n        const c = ctx.createDynamicsCompressor();\n        c.threshold.value = Number(fx.params.threshold ?? (fx.type === 'limiter' ? -3 : -24));\n        c.knee.value = Number(fx.params.knee ?? (fx.type === 'limiter' ? 0 : 30));\n        c.ratio.value = Number(fx.params.ratio ?? (fx.type === 'limiter' ? 20 : 4));\n        c.attack.value = Number(fx.params.attack ?? 0.003);\n        c.release.value = Number(fx.params.release ?? 0.25);\n        prev.connect(c);\n        prev = c;\n        nodes.push(c);\n        compressors.push(c);\n        break;\n      }\n      case 'delay': {\n        const delay = ctx.createDelay(5);\n        delay.delayTime.value = Number(fx.params.time ?? 0.3);\n        const feedback = ctx.createGain();\n        feedback.gain.value = Number(fx.params.feedback ?? 0.3);\n        const wet = ctx.createGain();\n        wet.gain.value = Number(fx.params.mix ?? 0.3);\n        const dry = ctx.createGain();\n        dry.gain.value = 1 - Number(fx.params.mix ?? 0.3);\n        const merge = ctx.createGain();\n        prev.connect(dry);\n        prev.connect(delay);\n        delay.connect(feedback);\n        feedback.connect(delay);\n        delay.connect(wet);\n        dry.connect(merge);\n        wet.connect(merge);\n        prev = merge;\n        nodes.push(delay, feedback, wet, dry, merge);\n        break;\n      }\n      case 'distortion': {\n        const shaper = ctx.createWaveShaper();\n        const amount = Number(fx.params.amount ?? 50);\n        const n = 44100;\n        const curve = new Float32Array(n);\n        const k = amount;\n        for (let i = 0; i < n; i++) {\n          const x = (i * 2) / n - 1;\n          curve[i] = ((Math.PI + k) * x) / (Math.PI + k * Math.abs(x));\n        }\n        shaper.curve = curve;\n        shaper.oversample = '2x';\n        prev.connect(shaper);\n        prev = shaper;\n        nodes.push(shaper);\n        break;\n      }\n      case 'reverb': {\n        // Lightweight synthetic impulse (no external IR file required)\n        const convolver = ctx.createConvolver();\n        const rate = ctx.sampleRate;\n        const length = Math.floor(rate * Number(fx.params.decay ?? 1.5));\n        const impulse = ctx.createBuffer(2, length, rate);\n        for (let ch = 0; ch < 2; ch++) {\n          const data = impulse.getChannelData(ch);\n          for (let i = 0; i < length; i++) {\n            data[i] = (Math.random() * 2 - 1) * Math.pow(1 - i / length, 2.5);\n          }\n        }\n        convolver.buffer = impulse;\n        const wet = ctx.createGain();\n        wet.gain.value = Number(fx.params.mix ?? 0.25);\n        const dry = ctx.createGain();\n        dry.gain.value = 1 - Number(fx.params.mix ?? 0.25);\n        const merge = ctx.createGain();\n        prev.connect(dry);\n        prev.connect(convolver);\n        convolver.connect(wet);\n        dry.connect(merge);\n        wet.connect(merge);\n        prev = merge;\n        nodes.push(convolver, wet, dry, merge);\n        break;\n      }\n      case 'chorus': {\n        const delay = ctx.createDelay(0.1);\n        delay.delayTime.value = 0.03;\n        const lfo = ctx.createOscillator();\n        lfo.frequency.value = Number(fx.params.rate ?? 1.5);\n        const lfoGain = ctx.createGain();\n        lfoGain.gain.value = Number(fx.params.depth ?? 0.005);\n        lfo.connect(lfoGain);\n        lfoGain.connect(delay.delayTime);\n        lfo.start();\n        const wet = ctx.createGain();\n        wet.gain.value = Number(fx.params.mix ?? 0.4);\n        const dry = ctx.createGain();\n        dry.gain.value = 0.6;\n        const merge = ctx.createGain();\n        prev.connect(dry);\n        prev.connect(delay);\n        delay.connect(wet);\n        dry.connect(merge);\n        wet.connect(merge);\n        prev = merge;\n        nodes.push(delay, lfo, lfoGain, wet, dry, merge);\n        break;\n      }\n      case 'gate': {\n        // Approximate gate with a compressor at high ratio + high threshold\n        const c = ctx.createDynamicsCompressor();\n        c.threshold.value = Number(fx.params.threshold ?? -40);\n        c.ratio.value = 20;\n        c.attack.value = 0.001;\n        c.release.value = Number(fx.params.release ?? 0.1);\n        prev.connect(c);\n        prev = c;\n        nodes.push(c);\n        break;\n      }\n      default:\n        break;\n    }\n  }\n\n  prev.connect(output);\n  nodes.push(output);\n\n  return {\n    input,\n    output,\n    nodes,\n    compressors,\n    dispose: () => {\n      for (const n of nodes) {\n        try {\n          n.disconnect();\n        } catch {\n          /* already disconnected */\n        }\n      }\n    },\n  };\n}\n\nexport function defaultEffectParams(type: AppliedAudioEffect['type']): Record<string, number | boolean | string> {\n  switch (type) {\n    case 'eq':\n      return { lowGain: 0, midGain: 0, highGain: 0, lowFreq: 200, midFreq: 1000, highFreq: 4000, midQ: 1 };\n    case 'compressor':\n      return { threshold: -24, knee: 30, ratio: 4, attack: 0.003, release: 0.25 };\n    case 'limiter':\n      return { threshold: -3, knee: 0, ratio: 20, attack: 0.001, release: 0.05 };\n    case 'delay':\n      return { time: 0.3, feedback: 0.3, mix: 0.3 };\n    case 'reverb':\n      return { decay: 1.5, mix: 0.25 };\n    case 'chorus':\n      return { rate: 1.5, depth: 0.005, mix: 0.4 };\n    case 'distortion':\n      return { amount: 50 };\n    case 'highpass':\n      return { frequency: 80, Q: 0.7 };\n    case 'lowpass':\n      return { frequency: 12000, Q: 0.7 };\n    case 'gate':\n      return { threshold: -40, release: 0.1 };\n    default:\n      return {};\n  }\n}\n\nexport { dbToLinear };\n", "/**\n * Evaluate automation lanes for volume (dB) and pan.\n */\n\nimport type { AutomationLane, AutomationPoint } from '../../store/useAudioStore';\nimport { dbToLinear } from './dsp/gain';\n\nfunction interpolate(points: AutomationPoint[], time: number): number | null {\n  if (!points.length) return null;\n  const sorted = [...points].sort((a, b) => a.time - b.time);\n  if (time <= (sorted[0]?.time ?? 0)) return sorted[0]!.value;\n  const last = sorted[sorted.length - 1]!;\n  if (time >= last.time) return last.value;\n  for (let i = 0; i < sorted.length - 1; i++) {\n    const a = sorted[i]!;\n    const b = sorted[i + 1]!;\n    if (time >= a.time && time <= b.time) {\n      const t = (time - a.time) / Math.max(1e-9, b.time - a.time);\n      return a.value + (b.value - a.value) * t;\n    }\n  }\n  return last.value;\n}\n\nexport function getLaneValue(\n  lanes: AutomationLane[],\n  property: string,\n  time: number\n): number | null {\n  const lane = lanes.find((l) => l.property === property);\n  if (!lane) return null;\n  return interpolate(lane.points, time);\n}\n\n/** Schedule volume automation (dB) onto a GainNode from playhead. */\nexport function scheduleVolumeAutomation(\n  param: AudioParam,\n  lanes: AutomationLane[],\n  baseVolumeDb: number,\n  playheadTime: number,\n  contextStartTime: number,\n  duration: number,\n  _ctx: BaseAudioContext\n) {\n  const lane = lanes.find((l) => l.property === 'volume');\n  const baseLinear = dbToLinear(baseVolumeDb);\n  param.cancelScheduledValues(contextStartTime);\n  param.setValueAtTime(baseLinear, contextStartTime);\n\n  if (!lane?.points.length) return;\n\n  const sorted = [...lane.points].sort((a, b) => a.time - b.time);\n  for (const p of sorted) {\n    if (p.time < playheadTime) continue;\n    if (p.time > playheadTime + duration) break;\n    const when = contextStartTime + (p.time - playheadTime);\n    param.linearRampToValueAtTime(dbToLinear(p.value), Math.max(contextStartTime, when));\n  }\n\n  // Ensure initial value matches automation at playhead\n  const atPlayhead = interpolate(sorted, playheadTime);\n  if (atPlayhead != null) {\n    param.setValueAtTime(dbToLinear(atPlayhead), contextStartTime);\n  }\n}\n\nexport function schedulePanAutomation(\n  param: AudioParam,\n  lanes: AutomationLane[],\n  basePan: number,\n  playheadTime: number,\n  contextStartTime: number,\n  duration: number\n) {\n  const lane = lanes.find((l) => l.property === 'pan');\n  param.cancelScheduledValues(contextStartTime);\n  param.setValueAtTime(basePan, contextStartTime);\n  if (!lane?.points.length) return;\n\n  const sorted = [...lane.points].sort((a, b) => a.time - b.time);\n  const atPlayhead = interpolate(sorted, playheadTime);\n  if (atPlayhead != null) {\n    param.setValueAtTime(Math.max(-1, Math.min(1, atPlayhead)), contextStartTime);\n  }\n  for (const p of sorted) {\n    if (p.time < playheadTime) continue;\n    if (p.time > playheadTime + duration) break;\n    const when = contextStartTime + (p.time - playheadTime);\n    param.linearRampToValueAtTime(\n      Math.max(-1, Math.min(1, p.value)),\n      Math.max(contextStartTime, when)\n    );\n  }\n}\n\nexport function automationGainAt(lanes: AutomationLane[], volumeDb: number, time: number): number {\n  const v = getLaneValue(lanes, 'volume', time);\n  return dbToLinear(v ?? volumeDb);\n}\n\nexport function automationPanAt(lanes: AutomationLane[], pan: number, time: number): number {\n  const v = getLaneValue(lanes, 'pan', time);\n  return v != null ? Math.max(-1, Math.min(1, v)) : pan;\n}\n", "/**\n * Equal-power / linear / exponential crossfade curve helpers.\n */\n\nexport type CrossfadeCurve = 'linear' | 'equal-power' | 'exponential';\n\n/** Fade-out gain 1\u21920 across t\u2208[0,1]. */\nexport function crossfadeOutGain(t: number, curve: CrossfadeCurve): number {\n  const x = Math.max(0, Math.min(1, t));\n  switch (curve) {\n    case 'equal-power':\n      return Math.cos(x * 0.5 * Math.PI);\n    case 'exponential':\n      return Math.pow(1 - x, 2);\n    default:\n      return 1 - x;\n  }\n}\n\n/** Fade-in gain 0\u21921 across t\u2208[0,1]. */\nexport function crossfadeInGain(t: number, curve: CrossfadeCurve): number {\n  const x = Math.max(0, Math.min(1, t));\n  switch (curve) {\n    case 'equal-power':\n      return Math.sin(x * 0.5 * Math.PI);\n    case 'exponential':\n      return Math.pow(x, 2);\n    default:\n      return x;\n  }\n}\n\n/**\n * Schedule a shaped fade on an AudioParam over [when, when+dur].\n * @param direction 'in' | 'out'\n */\nexport function scheduleShapedFade(\n  param: AudioParam,\n  when: number,\n  dur: number,\n  baseGain: number,\n  curve: CrossfadeCurve,\n  direction: 'in' | 'out',\n  steps = 12\n) {\n  if (dur <= 0.001) return;\n  const startG = direction === 'in' ? 0.0001 : baseGain;\n  param.setValueAtTime(startG, when);\n  for (let i = 1; i <= steps; i++) {\n    const t = i / steps;\n    const g =\n      (direction === 'in' ? crossfadeInGain(t, curve) : crossfadeOutGain(t, curve)) * baseGain;\n    param.linearRampToValueAtTime(Math.max(0.0001, g), when + dur * t);\n  }\n}\n", "/**\n * Sample-accurate clip scheduler with per-track FX, meters, buses/sends, and automation.\n */\n\nimport type { AudioClip, AudioTrack } from '../../store/useAudioStore';\nimport { dbToLinear, evaluateFade } from './dsp/gain';\nimport { createEffectChain, type EffectChain } from './effects/createEffectChain';\nimport { schedulePanAutomation, scheduleVolumeAutomation } from './automation';\nimport { scheduleShapedFade } from './crossfade';\n\nexport interface ScheduledClip {\n  clipId: string;\n  trackId: string;\n  source: AudioBufferSourceNode;\n  gainNode: GainNode;\n}\n\nexport interface TrackGraph {\n  trackId: string;\n  input: GainNode;\n  trackGain: GainNode;\n  panner: StereoPannerNode;\n  analyser: AnalyserNode;\n  chain: EffectChain | null;\n  /** Post-FX send gains keyed by bus track id. */\n  sendGains: Map<string, GainNode>;\n  fingerprint: string;\n  dispose: () => void;\n}\n\nexport interface ScheduleContext {\n  ctx: AudioContext;\n  master: AudioNode;\n  buffers: Map<string, AudioBuffer>;\n  tracks: AudioTrack[];\n  playheadTime: number;\n  contextStartTime: number;\n  trackGraphs?: Map<string, TrackGraph>;\n}\n\nexport interface ScheduleResult {\n  scheduled: ScheduledClip[];\n  trackGraphs: Map<string, TrackGraph>;\n}\n\nexport function trackGraphFingerprint(track: AudioTrack): string {\n  const fx = track.effects\n    .map((e) => `${e.id}:${e.type}:${e.enabled}:${e.order}:${JSON.stringify(e.params)}`)\n    .join('|');\n  const sends = (track.sends || []).map((s) => `${s.busId}:${s.amount}`).join('|');\n  return `${track.type}:${track.muted}:${track.solo}:${track.volumeDb}:${track.pan}:${fx}:${sends}`;\n}\n\n/**\n * Build track graph: clips \u2192 gain \u2192 FX \u2192 pan \u2192 analyser \u2192 master\n * + post-FX sends \u2192 bus.input\n */\nexport function ensureTrackGraph(\n  ctx: AudioContext,\n  track: AudioTrack,\n  master: AudioNode,\n  busInputs: Map<string, GainNode>,\n  existing?: TrackGraph\n): TrackGraph {\n  const fingerprint = trackGraphFingerprint(track);\n  if (existing && existing.fingerprint === fingerprint) {\n    existing.trackGain.gain.value = dbToLinear(track.volumeDb);\n    existing.panner.pan.value = track.pan;\n    for (const send of track.sends || []) {\n      const g = existing.sendGains.get(send.busId);\n      if (g) g.gain.value = Math.max(0, Math.min(1, send.amount));\n    }\n    return existing;\n  }\n\n  if (existing) existing.dispose();\n\n  const input = ctx.createGain();\n  input.gain.value = 1;\n  const trackGain = ctx.createGain();\n  trackGain.gain.value = dbToLinear(track.volumeDb);\n  const panner = ctx.createStereoPanner();\n  panner.pan.value = track.pan;\n  const analyser = ctx.createAnalyser();\n  analyser.fftSize = 2048;\n\n  const chain = track.effects.length ? createEffectChain(ctx, track.effects) : null;\n  const sendGains = new Map<string, GainNode>();\n\n  input.connect(trackGain);\n  const postFx: AudioNode = chain ? chain.output : trackGain;\n  if (chain) {\n    trackGain.connect(chain.input);\n  }\n  postFx.connect(panner);\n  panner.connect(analyser);\n  analyser.connect(master);\n\n  // Post-FX sends into bus inputs (audio tracks only)\n  if (track.type === 'audio') {\n    for (const send of track.sends || []) {\n      if (send.amount <= 0.001) continue;\n      const busIn = busInputs.get(send.busId);\n      if (!busIn) continue;\n      const g = ctx.createGain();\n      g.gain.value = Math.max(0, Math.min(1, send.amount));\n      postFx.connect(g);\n      g.connect(busIn);\n      sendGains.set(send.busId, g);\n    }\n  }\n\n  return {\n    trackId: track.id,\n    input,\n    trackGain,\n    panner,\n    analyser,\n    chain,\n    sendGains,\n    fingerprint,\n    dispose: () => {\n      try {\n        input.disconnect();\n        trackGain.disconnect();\n        panner.disconnect();\n        analyser.disconnect();\n        for (const g of sendGains.values()) g.disconnect();\n        chain?.dispose();\n      } catch {\n        /* ignore */\n      }\n    },\n  };\n}\n\n/** Build/update all track+bus graphs without scheduling clips (keeps meters alive). */\nexport function syncTrackGraphs(\n  ctx: AudioContext,\n  master: AudioNode,\n  tracks: AudioTrack[],\n  existing?: Map<string, TrackGraph>\n): Map<string, TrackGraph> {\n  const trackGraphs = new Map<string, TrackGraph>();\n  const busInputs = new Map<string, GainNode>();\n  const anySolo = tracks.some((t) => t.solo);\n\n  // Pass 1: bus graphs (so audio sends can connect)\n  for (const track of tracks) {\n    if (track.type !== 'bus') continue;\n    if (track.muted) continue;\n    if (anySolo && !track.solo) continue;\n    const graph = ensureTrackGraph(\n      ctx,\n      track,\n      master,\n      busInputs,\n      existing?.get(track.id)\n    );\n    trackGraphs.set(track.id, graph);\n    busInputs.set(track.id, graph.input);\n  }\n\n  // Pass 2: audio tracks\n  for (const track of tracks) {\n    if (track.type !== 'audio') continue;\n    if (track.muted) continue;\n    if (anySolo && !track.solo) continue;\n    const graph = ensureTrackGraph(\n      ctx,\n      track,\n      master,\n      busInputs,\n      existing?.get(track.id)\n    );\n    trackGraphs.set(track.id, graph);\n  }\n\n  // Dispose removed\n  if (existing) {\n    for (const [id, g] of existing) {\n      if (!trackGraphs.has(id)) g.dispose();\n    }\n  }\n\n  return trackGraphs;\n}\n\nexport function scheduleClips(opts: ScheduleContext): ScheduleResult {\n  const { ctx, master, buffers, tracks, playheadTime, contextStartTime } = opts;\n  const scheduled: ScheduledClip[] = [];\n  const trackGraphs = syncTrackGraphs(ctx, master, tracks, opts.trackGraphs);\n  const anySolo = tracks.some((t) => t.solo);\n  const horizon = 3600;\n\n  for (const track of tracks) {\n    if (track.type === 'lyrics') continue;\n    if (track.muted) continue;\n    if (anySolo && !track.solo) continue;\n\n    const graph = trackGraphs.get(track.id);\n    if (!graph) continue;\n\n    scheduleVolumeAutomation(\n      graph.trackGain.gain,\n      track.automation,\n      track.volumeDb,\n      playheadTime,\n      contextStartTime,\n      horizon,\n      ctx\n    );\n    schedulePanAutomation(\n      graph.panner.pan,\n      track.automation,\n      track.pan,\n      playheadTime,\n      contextStartTime,\n      horizon\n    );\n\n    for (const clip of track.clips) {\n      if (clip.muted || (clip.takeGroupId && clip.compActive === false)) continue;\n      // Prefer stretch-cache key when pitchSeparate\n      const bufKey =\n        clip.pitchSeparate && Math.abs(clip.speed - 1) > 0.01\n          ? `${clip.assetId}|stretch|${clip.speed.toFixed(3)}`\n          : clip.assetId;\n      const buffer = buffers.get(bufKey) ?? buffers.get(clip.assetId);\n      if (!buffer) continue;\n\n      const clipEnd = clip.startTime + clip.duration;\n      if (clipEnd <= playheadTime) continue;\n\n      const offsetIntoClip = Math.max(0, playheadTime - clip.startTime);\n      const when = contextStartTime + Math.max(0, clip.startTime - playheadTime);\n      // pitchSeparate + stretch: buffer already time-stretched \u2192 rate is pitch only.\n      // Original trimIn (source seconds) maps to trimIn/speed in the stretched buffer.\n      const useStretch = clip.pitchSeparate && Math.abs(clip.speed - 1) > 0.01;\n      const rate = clip.pitchSeparate\n        ? Math.pow(2, clip.pitch / 12)\n        : clip.speed * Math.pow(2, clip.pitch / 12);\n      const speedForOffset = clip.pitchSeparate ? 1 : clip.speed;\n      const bufferOffset = useStretch\n        ? clip.trimIn / Math.max(0.01, clip.speed) + offsetIntoClip\n        : clip.trimIn + offsetIntoClip * speedForOffset;\n      const remaining = Math.max(\n        0.01,\n        (clip.duration - offsetIntoClip) / Math.max(0.01, speedForOffset)\n      );\n\n      const source = ctx.createBufferSource();\n      source.buffer = buffer;\n      source.playbackRate.value = rate;\n\n      const gainNode = ctx.createGain();\n      applyClipEnvelope(gainNode.gain, ctx, when, clip, offsetIntoClip, remaining);\n      applyOverlapCrossfade(\n        gainNode.gain,\n        track.clips,\n        clip,\n        when,\n        playheadTime,\n        contextStartTime,\n        remaining\n      );\n\n      source.connect(gainNode);\n      gainNode.connect(graph.input);\n\n      try {\n        source.start(when, bufferOffset, remaining);\n      } catch {\n        continue;\n      }\n\n      scheduled.push({ clipId: clip.id, trackId: track.id, source, gainNode });\n    }\n  }\n\n  return { scheduled, trackGraphs };\n}\n\nfunction applyOverlapCrossfade(\n  param: AudioParam,\n  clips: AudioClip[],\n  clip: AudioClip,\n  when: number,\n  playheadTime: number,\n  contextStartTime: number,\n  _remaining: number\n) {\n  const others = clips.filter((c) => c.id !== clip.id && !c.muted);\n  for (const other of others) {\n    const overlapStart = Math.max(clip.startTime, other.startTime);\n    const overlapEnd = Math.min(\n      clip.startTime + clip.duration,\n      other.startTime + other.duration\n    );\n    if (overlapEnd - overlapStart < 0.02) continue;\n\n    const curve = clip.crossfadeCurve || 'equal-power';\n    if (clip.startTime <= other.startTime) {\n      const fadeDur = Math.min(\n        overlapEnd - overlapStart,\n        Math.max(clip.crossfadeOut || clip.fadeOut, 0.05)\n      );\n      const fadeAt = overlapEnd - fadeDur;\n      if (fadeAt + fadeDur <= playheadTime) continue;\n      const startWhen = contextStartTime + Math.max(0, fadeAt - playheadTime);\n      if (startWhen + fadeDur <= when) continue;\n      scheduleShapedFade(param, Math.max(when, startWhen), fadeDur, clip.gain, curve, 'out');\n    } else {\n      const fadeDur = Math.min(\n        overlapEnd - overlapStart,\n        Math.max(clip.crossfadeIn || clip.fadeIn, 0.05)\n      );\n      const startWhen = contextStartTime + Math.max(0, overlapStart - playheadTime);\n      if (startWhen + fadeDur <= when) continue;\n      scheduleShapedFade(param, Math.max(when, startWhen), fadeDur, clip.gain, curve, 'in');\n    }\n  }\n}\n\nfunction applyClipEnvelope(\n  param: AudioParam,\n  _ctx: BaseAudioContext,\n  when: number,\n  clip: AudioClip,\n  offsetIntoClip: number,\n  remaining: number\n) {\n  const base = clip.gain * (clip.inverted ? -1 : 1);\n  param.cancelScheduledValues(when);\n  param.setValueAtTime(0, when);\n\n  const fadeIn = Math.max(0, clip.fadeIn - offsetIntoClip);\n  const fadeOutStart = Math.max(0, clip.duration - clip.fadeOut - offsetIntoClip);\n\n  if (fadeIn > 0.001) {\n    const steps = 8;\n    for (let i = 0; i <= steps; i++) {\n      const t = i / steps;\n      const g = evaluateFade(t, clip.fadeInCurve, 'in') * base;\n      param.linearRampToValueAtTime(g, when + fadeIn * t);\n    }\n  } else {\n    param.setValueAtTime(base, when);\n  }\n\n  if (clip.fadeOut > 0.001 && fadeOutStart < remaining) {\n    const startAt = when + fadeOutStart;\n    param.setValueAtTime(base, startAt);\n    const steps = 8;\n    for (let i = 0; i <= steps; i++) {\n      const t = i / steps;\n      const g = evaluateFade(t, clip.fadeOutCurve, 'out') * base;\n      param.linearRampToValueAtTime(g, startAt + clip.fadeOut * t);\n    }\n  }\n}\n\nexport function readAnalyserLevels(analyser: AnalyserNode): {\n  peakL: number;\n  peakR: number;\n  rmsL: number;\n  rmsR: number;\n} {\n  const data = new Float32Array(analyser.fftSize);\n  analyser.getFloatTimeDomainData(data);\n  let peak = 0;\n  let sum = 0;\n  for (let i = 0; i < data.length; i++) {\n    const v = Math.abs(data[i] ?? 0);\n    if (v > peak) peak = v;\n    sum += v * v;\n  }\n  const rms = Math.sqrt(sum / data.length);\n  return { peakL: peak, peakR: peak, rmsL: rms, rmsR: rms };\n}\n", "/**\n * Lightweight overlap-add time-stretch (pitch-preserving).\n * Used when clip.pitchSeparate is true so speed \u2260 pitch.\n */\n\n/** Stretch buffer by factor (e.g. 0.5 = half duration / 2x speed content). */\nexport function timeStretchBuffer(\n  buffer: AudioBuffer,\n  /** Output duration / input duration. >1 = longer (slower). */\n  ratio: number\n): AudioBuffer {\n  const r = Math.max(0.25, Math.min(4, ratio));\n  if (Math.abs(r - 1) < 0.01) return buffer;\n\n  const channels = buffer.numberOfChannels;\n  const sr = buffer.sampleRate;\n  const inLen = buffer.length;\n  const outLen = Math.max(1, Math.floor(inLen * r));\n  const out = new AudioBuffer({ length: outLen, numberOfChannels: channels, sampleRate: sr });\n\n  // Grain OLA\n  const grain = Math.floor(sr * 0.04); // 40ms\n  const hopIn = Math.floor(grain / 2);\n  const hopOut = Math.max(1, Math.floor(hopIn * r));\n  const window = new Float32Array(grain);\n  for (let i = 0; i < grain; i++) {\n    window[i] = 0.5 - 0.5 * Math.cos((2 * Math.PI * i) / Math.max(1, grain - 1));\n  }\n\n  for (let c = 0; c < channels; c++) {\n    const input = buffer.getChannelData(c);\n    const output = out.getChannelData(c);\n    let inPos = 0;\n    let outPos = 0;\n    while (outPos + grain < outLen && inPos + grain < inLen) {\n      for (let i = 0; i < grain; i++) {\n        const idx = Math.min(inLen - 1, inPos + i);\n        output[outPos + i] =\n          (output[outPos + i] ?? 0) + (input[idx] ?? 0) * (window[i] ?? 0);\n      }\n      inPos += hopIn;\n      outPos += hopOut;\n    }\n    // Normalize OLA peaks\n    let peak = 0;\n    for (let i = 0; i < outLen; i++) {\n      const a = Math.abs(output[i] ?? 0);\n      if (a > peak) peak = a;\n    }\n    if (peak > 1) {\n      const g = 1 / peak;\n      for (let i = 0; i < outLen; i++) output[i] = (output[i] ?? 0) * g;\n    }\n  }\n\n  return out;\n}\n\n/** Cache key for stretched assets. */\nexport function stretchCacheKey(assetId: string, speed: number, pitch: number): string {\n  return `${assetId}|s${speed.toFixed(3)}|p${pitch.toFixed(2)}`;\n}\n", "/**\n * Approximate integrated loudness (LUFS) and true-peak helpers.\n * Not a full ITU-R BS.1770 implementation \u2014 good enough for normalize targets.\n */\n\nexport interface LoudnessStats {\n  /** Approximate integrated LUFS */\n  lufs: number;\n  peak: number;\n  rms: number;\n}\n\nexport function analyzeBuffer(buffer: AudioBuffer): LoudnessStats {\n  const channels = buffer.numberOfChannels;\n  let peak = 0;\n  let sumSquares = 0;\n  let count = 0;\n\n  for (let c = 0; c < channels; c++) {\n    const data = buffer.getChannelData(c);\n    for (let i = 0; i < data.length; i++) {\n      const v = data[i] ?? 0;\n      const a = Math.abs(v);\n      if (a > peak) peak = a;\n      sumSquares += v * v;\n      count++;\n    }\n  }\n\n  const rms = count ? Math.sqrt(sumSquares / count) : 0;\n  // Rough LUFS \u2248 -0.691 + 10*log10(mean square) with simple gating omitted\n  const meanSquare = count ? sumSquares / count : 0;\n  const lufs = meanSquare > 0 ? -0.691 + 10 * Math.log10(meanSquare) : -70;\n\n  return { lufs, peak, rms };\n}\n\n/**\n * Return a linear gain that brings the buffer to target LUFS.\n */\nexport function gainForTargetLufs(buffer: AudioBuffer, targetLufs: number): number {\n  const { lufs } = analyzeBuffer(buffer);\n  if (!Number.isFinite(lufs) || lufs < -70) return 1;\n  const deltaDb = targetLufs - lufs;\n  return Math.pow(10, deltaDb / 20);\n}\n\nexport function applyGainInPlace(buffer: AudioBuffer, gain: number): void {\n  for (let c = 0; c < buffer.numberOfChannels; c++) {\n    const data = buffer.getChannelData(c);\n    for (let i = 0; i < data.length; i++) {\n      data[i] = (data[i] ?? 0) * gain;\n    }\n  }\n}\n\n/** Approximate true-peak from linear peak (4x oversample estimate). */\nexport function truePeakDbFromPeak(peak: number): number {\n  const tp = Math.min(1.5, peak * 1.05);\n  if (tp <= 1e-9) return -60;\n  return 20 * Math.log10(tp);\n}\n\n/**\n * Short-term loudness window (~400ms) from analyser time-domain data.\n */\nexport function shortTermLufsFromTimeDomain(data: Float32Array): number {\n  let sum = 0;\n  for (let i = 0; i < data.length; i++) {\n    const v = data[i] ?? 0;\n    sum += v * v;\n  }\n  const ms = data.length ? sum / data.length : 0;\n  return ms > 0 ? -0.691 + 10 * Math.log10(ms) : -70;\n}\n\n/** Rolling history helper (max N samples). */\nexport function pushLufsHistory(history: number[], value: number, max = 60): number[] {\n  const next = [...history, value];\n  if (next.length > max) return next.slice(next.length - max);\n  return next;\n}\n", "/**\n * Real-time Web Audio playback engine with per-track FX, meters, buses, and master limiter.\n */\n\nimport type { AudioAsset, AudioTrack } from '../../store/useAudioStore';\nimport { dbToLinear } from './dsp/gain';\nimport {\n  readAnalyserLevels,\n  scheduleClips,\n  syncTrackGraphs,\n  type ScheduledClip,\n  type TrackGraph,\n} from './scheduler';\nimport { timeStretchBuffer } from './timeStretch';\nimport { pushLufsHistory, shortTermLufsFromTimeDomain, truePeakDbFromPeak } from './loudness';\n\nexport type MeterLevels = {\n  peakL: number;\n  peakR: number;\n  rmsL: number;\n  rmsR: number;\n  lufsApprox?: number;\n};\n\nexport class AudioEngine {\n  private ctx: AudioContext | null = null;\n  private masterGain: GainNode | null = null;\n  private masterLimiter: DynamicsCompressorNode | null = null;\n  private masterAnalyser: AnalyserNode | null = null;\n  private buffers = new Map<string, AudioBuffer>();\n  private scheduled: ScheduledClip[] = [];\n  private trackGraphs = new Map<string, TrackGraph>();\n  private playing = false;\n  private playheadAtStart = 0;\n  private contextTimeAtStart = 0;\n  private rafId = 0;\n  private onPlayhead?: (t: number) => void;\n  private loopEnabled = false;\n  private loopStart = 0;\n  private loopEnd = 8;\n  private projectDuration = 60;\n  private lastTracks: AudioTrack[] = [];\n  private lastAssets: AudioAsset[] = [];\n  private lastMasterDb = 0;\n  private meterKeepAlive: OscillatorNode | null = null;\n  private meterKeepGain: GainNode | null = null;\n  private lufsHistory: number[] = [];\n  private peakHold = 0;\n  private lufsTick = 0;\n  private integratedSumSq = 0;\n  private integratedSamples = 0;\n\n  async ensureContext(): Promise<AudioContext> {\n    if (!this.ctx) {\n      this.ctx = new AudioContext({ sampleRate: 48000 });\n      this.masterGain = this.ctx.createGain();\n      this.masterLimiter = this.ctx.createDynamicsCompressor();\n      this.masterLimiter.threshold.value = -1;\n      this.masterLimiter.knee.value = 0;\n      this.masterLimiter.ratio.value = 20;\n      this.masterLimiter.attack.value = 0.001;\n      this.masterLimiter.release.value = 0.05;\n      this.masterAnalyser = this.ctx.createAnalyser();\n      this.masterAnalyser.fftSize = 2048;\n      this.masterGain.connect(this.masterLimiter);\n      this.masterLimiter.connect(this.masterAnalyser);\n      this.masterAnalyser.connect(this.ctx.destination);\n\n      // Silent keep-alive so analysers stay active when paused (meters / GR)\n      this.meterKeepGain = this.ctx.createGain();\n      this.meterKeepGain.gain.value = 0.00001;\n      this.meterKeepAlive = this.ctx.createOscillator();\n      this.meterKeepAlive.frequency.value = 20;\n      this.meterKeepAlive.connect(this.meterKeepGain);\n      this.meterKeepGain.connect(this.masterGain);\n      this.meterKeepAlive.start();\n    }\n    if (this.ctx.state === 'suspended') await this.ctx.resume();\n    return this.ctx;\n  }\n\n  getMasterInput(): GainNode {\n    if (!this.masterGain) throw new Error('AudioEngine not initialized');\n    return this.masterGain;\n  }\n\n  setMasterVolumeDb(db: number) {\n    this.lastMasterDb = db;\n    if (this.masterGain) this.masterGain.gain.value = dbToLinear(db);\n  }\n\n  setLoop(enabled: boolean, start: number, end: number) {\n    this.loopEnabled = enabled;\n    this.loopStart = start;\n    this.loopEnd = end;\n  }\n\n  setProjectDuration(d: number) {\n    this.projectDuration = d;\n  }\n\n  setPlayheadCallback(cb: (t: number) => void) {\n    this.onPlayhead = cb;\n  }\n\n  async loadAsset(asset: AudioAsset): Promise<AudioBuffer | null> {\n    if (this.buffers.has(asset.id)) return this.buffers.get(asset.id)!;\n    if (!asset.file && !asset.url) return null;\n    const ctx = await this.ensureContext();\n    try {\n      const ab = await (asset.file?.arrayBuffer() ?? fetch(asset.url).then((r) => r.arrayBuffer()));\n      const buffer = await ctx.decodeAudioData(ab.slice(0));\n      this.buffers.set(asset.id, buffer);\n      return buffer;\n    } catch (err) {\n      console.error('Failed to decode audio asset', asset.name, err);\n      return null;\n    }\n  }\n\n  /** Bake pitch-preserving time-stretch buffers for clips with pitchSeparate. */\n  async prepareStretchBuffers(tracks: AudioTrack[], assets: AudioAsset[]) {\n    await Promise.all(assets.map((a) => this.loadAsset(a)));\n    for (const track of tracks) {\n      for (const clip of track.clips) {\n        if (!clip.pitchSeparate || Math.abs(clip.speed - 1) < 0.01) continue;\n        const key = `${clip.assetId}|stretch|${clip.speed.toFixed(3)}`;\n        if (this.buffers.has(key)) continue;\n        const src = this.buffers.get(clip.assetId);\n        if (!src) continue;\n        // speed > 1 = play faster = shorter output \u2192 ratio = 1/speed\n        const stretched = timeStretchBuffer(src, 1 / clip.speed);\n        this.buffers.set(key, stretched);\n      }\n    }\n  }\n\n  getBuffer(assetId: string): AudioBuffer | undefined {\n    return this.buffers.get(assetId);\n  }\n\n  /** Keep track graphs (and meters) in sync without (re)starting playback. */\n  async syncGraphs(tracks: AudioTrack[]) {\n    const ctx = await this.ensureContext();\n    this.lastTracks = tracks;\n    this.trackGraphs = syncTrackGraphs(ctx, this.masterGain!, tracks, this.trackGraphs);\n    // Silent keep-alive into master only (track meters read during/after play)\n    void ctx;\n  }\n\n  /**\n   * Rebuild FX graphs and, if playing, soft-reschedule from current playhead\n   * so parameter/FX changes are heard live.\n   */\n  async applyLiveGraphUpdate(tracks: AudioTrack[], assets: AudioAsset[]) {\n    this.lastTracks = tracks;\n    this.lastAssets = assets;\n    await this.syncGraphs(tracks);\n    if (!this.playing) return;\n    const playhead = this.getPlayheadTime();\n    this.stopSources(false);\n    this.playheadAtStart = playhead;\n    this.contextTimeAtStart = this.ctx!.currentTime;\n    await Promise.all(assets.map((a) => this.loadAsset(a)));\n    await this.prepareStretchBuffers(tracks, assets);\n    const result = scheduleClips({\n      ctx: this.ctx!,\n      master: this.masterGain!,\n      buffers: this.buffers,\n      tracks,\n      playheadTime: playhead,\n      contextStartTime: this.contextTimeAtStart,\n      trackGraphs: this.trackGraphs,\n    });\n    this.scheduled = result.scheduled;\n    this.trackGraphs = result.trackGraphs;\n  }\n\n  async play(opts: {\n    tracks: AudioTrack[];\n    assets: AudioAsset[];\n    playheadTime: number;\n    masterVolumeDb: number;\n  }) {\n    const ctx = await this.ensureContext();\n    this.stopSources(false);\n    this.setMasterVolumeDb(opts.masterVolumeDb);\n    this.lastTracks = opts.tracks;\n    this.lastAssets = opts.assets;\n\n    await Promise.all(opts.assets.map((a) => this.loadAsset(a)));\n    await this.prepareStretchBuffers(opts.tracks, opts.assets);\n\n    this.playheadAtStart = opts.playheadTime;\n    this.contextTimeAtStart = ctx.currentTime;\n    this.playing = true;\n    // Reset integrated loudness accumulator for this play session\n    this.integratedSumSq = 0;\n    this.integratedSamples = 0;\n    this.lufsHistory = [];\n    this.peakHold = 0;\n\n    const result = scheduleClips({\n      ctx,\n      master: this.masterGain!,\n      buffers: this.buffers,\n      tracks: opts.tracks,\n      playheadTime: opts.playheadTime,\n      contextStartTime: this.contextTimeAtStart,\n      trackGraphs: this.trackGraphs,\n    });\n    this.scheduled = result.scheduled;\n    for (const [id, g] of this.trackGraphs) {\n      if (!result.trackGraphs.has(id)) g.dispose();\n    }\n    this.trackGraphs = result.trackGraphs;\n\n    if (this.rafId) cancelAnimationFrame(this.rafId);\n    this.tick();\n  }\n\n  pause() {\n    this.playing = false;\n    this.playheadAtStart = this.getPlayheadTime();\n    this.stopSources(false);\n    // Keep track graphs for meters\n    if (this.rafId) cancelAnimationFrame(this.rafId);\n    this.rafId = 0;\n  }\n\n  stop() {\n    this.pause();\n    this.playheadAtStart = 0;\n    this.onPlayhead?.(0);\n  }\n\n  getPlayheadTime(): number {\n    if (!this.playing || !this.ctx) return this.playheadAtStart;\n    return this.playheadAtStart + (this.ctx.currentTime - this.contextTimeAtStart);\n  }\n\n  getMeterLevels(trackId?: string): MeterLevels {\n    const analyser =\n      trackId && trackId !== 'master'\n        ? this.trackGraphs.get(trackId)?.analyser\n        : this.masterAnalyser;\n    if (!analyser) return { peakL: 0, peakR: 0, rmsL: 0, rmsR: 0, lufsApprox: -70 };\n    const levels = readAnalyserLevels(analyser);\n    const meanSquare = levels.rmsL * levels.rmsL;\n    const lufsApprox = meanSquare > 0 ? -0.691 + 10 * Math.log10(meanSquare) : -70;\n    return { ...levels, lufsApprox };\n  }\n\n  /** Live gain reduction in dB (positive = reduction). */\n  getCompressorReductionDb(trackId: string): number {\n    const graph = this.trackGraphs.get(trackId);\n    if (!graph?.chain?.compressors.length) return 0;\n    let max = 0;\n    for (const c of graph.chain.compressors) {\n      // reduction is negative when compressing\n      max = Math.max(max, -c.reduction);\n    }\n    return max;\n  }\n\n  isPlaying() {\n    return this.playing;\n  }\n\n  dispose() {\n    this.pause();\n    for (const g of this.trackGraphs.values()) g.dispose();\n    this.trackGraphs.clear();\n    this.buffers.clear();\n    try {\n      this.meterKeepAlive?.stop();\n      this.meterKeepAlive?.disconnect();\n      this.meterKeepGain?.disconnect();\n    } catch {\n      /* ignore */\n    }\n    this.meterKeepAlive = null;\n    this.meterKeepGain = null;\n    void this.ctx?.close();\n    this.ctx = null;\n    this.masterGain = null;\n    this.masterLimiter = null;\n    this.masterAnalyser = null;\n  }\n\n  private stopSources(_disposeGraphs: boolean) {\n    for (const s of this.scheduled) {\n      try {\n        s.source.stop();\n      } catch {\n        /* already stopped */\n      }\n      try {\n        s.source.disconnect();\n        s.gainNode.disconnect();\n      } catch {\n        /* ignore */\n      }\n    }\n    this.scheduled = [];\n  }\n\n  private tick = () => {\n    if (!this.playing || !this.ctx) return;\n    let t = this.getPlayheadTime();\n\n    if (this.loopEnabled && t >= this.loopEnd) {\n      this.stopSources(false);\n      void this.play({\n        tracks: this.lastTracks,\n        assets: this.lastAssets,\n        playheadTime: this.loopStart,\n        masterVolumeDb: this.lastMasterDb,\n      });\n      return;\n    }\n\n    if (t >= this.projectDuration) {\n      this.playing = false;\n      this.stopSources(false);\n      this.onPlayhead?.(this.projectDuration);\n      return;\n    }\n\n    this.onPlayhead?.(t);\n\n    // Update LUFS history ~10Hz\n    this.lufsTick++;\n    if (this.lufsTick % 6 === 0 && this.masterAnalyser) {\n      const data = new Float32Array(this.masterAnalyser.fftSize);\n      this.masterAnalyser.getFloatTimeDomainData(data);\n      let peak = 0;\n      let sumSq = 0;\n      for (let i = 0; i < data.length; i++) {\n        const v = data[i] ?? 0;\n        const a = Math.abs(v);\n        if (a > peak) peak = a;\n        sumSq += v * v;\n      }\n      const st = shortTermLufsFromTimeDomain(data);\n      // Absolute-gate-ish: ignore near-silence for integrated estimate\n      const meanSq = data.length ? sumSq / data.length : 0;\n      if (meanSq > 1e-8) {\n        this.integratedSumSq += sumSq;\n        this.integratedSamples += data.length;\n      }\n      const integrated =\n        this.integratedSamples > 0\n          ? -0.691 + 10 * Math.log10(this.integratedSumSq / this.integratedSamples)\n          : -70;\n      this.peakHold = Math.max(this.peakHold * 0.98, peak);\n      this.lufsHistory = pushLufsHistory(this.lufsHistory, st, 64);\n      const tp = truePeakDbFromPeak(this.peakHold);\n      void import('../../store/useAudioStore').then(({ useAudioStore }) => {\n        useAudioStore.getState().setLufsMeter(this.lufsHistory, tp, integrated);\n      });\n    }\n\n    this.rafId = requestAnimationFrame(this.tick);\n  };\n}\n\nlet singleton: AudioEngine | null = null;\n\nexport function getAudioEngine(): AudioEngine {\n  if (!singleton) singleton = new AudioEngine();\n  return singleton;\n}\n\n/** Push store track/FX changes into the live engine. */\nexport function syncEngineFromStore(tracks: AudioTrack[], assets: AudioAsset[]) {\n  void getAudioEngine().applyLiveGraphUpdate(tracks, assets);\n}\n", "/**\n * Waveform peak extraction \u2014 prefers a Worker, falls back to main thread.\n */\n\nexport interface PeaksResult {\n  peaks: Float32Array;\n  /** Peaks per second (pairs of min/max). */\n  peaksSampleRate: number;\n}\n\n/** Default overview density; use higher for zoomed waveforms. */\nconst PEAKS_PER_SECOND = 200;\n\nfunction computePeaksFromChannel(\n  channel: Float32Array,\n  sampleRate: number\n): PeaksResult {\n  const samplesPerPeak = Math.max(1, Math.floor(sampleRate / PEAKS_PER_SECOND));\n  const peakPairs = Math.ceil(channel.length / samplesPerPeak);\n  const peaks = new Float32Array(peakPairs * 2);\n  for (let i = 0; i < peakPairs; i++) {\n    const start = i * samplesPerPeak;\n    const end = Math.min(channel.length, start + samplesPerPeak);\n    let min = 1;\n    let max = -1;\n    for (let j = start; j < end; j++) {\n      const v = channel[j] ?? 0;\n      if (v < min) min = v;\n      if (v > max) max = v;\n    }\n    peaks[i * 2] = min;\n    peaks[i * 2 + 1] = max;\n  }\n  return { peaks, peaksSampleRate: PEAKS_PER_SECOND };\n}\n\n/**\n * Decode a Blob/File into an AudioBuffer using a temporary AudioContext.\n */\nexport async function decodeAudioBlob(blob: Blob): Promise<AudioBuffer> {\n  const ctx = new AudioContext();\n  try {\n    const ab = await blob.arrayBuffer();\n    return await ctx.decodeAudioData(ab.slice(0));\n  } finally {\n    await ctx.close().catch(() => {});\n  }\n}\n\n/**\n * Extract min/max peaks for waveform rendering.\n */\nexport async function extractPeaks(\n  buffer: AudioBuffer,\n  channelIndex = 0\n): Promise<PeaksResult> {\n  const channel = buffer.getChannelData(Math.min(channelIndex, buffer.numberOfChannels - 1));\n  // Prefer worker when available\n  if (typeof Worker !== 'undefined') {\n    try {\n      return await extractPeaksInWorker(channel, buffer.sampleRate);\n    } catch {\n      // fall through\n    }\n  }\n  return computePeaksFromChannel(channel, buffer.sampleRate);\n}\n\nfunction extractPeaksInWorker(\n  channel: Float32Array,\n  sampleRate: number\n): Promise<PeaksResult> {\n  return new Promise((resolve, reject) => {\n    const workerCode = `\n      self.onmessage = (e) => {\n        const { channel, sampleRate, peaksPerSecond } = e.data;\n        const samplesPerPeak = Math.max(1, Math.floor(sampleRate / peaksPerSecond));\n        const peakPairs = Math.ceil(channel.length / samplesPerPeak);\n        const peaks = new Float32Array(peakPairs * 2);\n        for (let i = 0; i < peakPairs; i++) {\n          const start = i * samplesPerPeak;\n          const end = Math.min(channel.length, start + samplesPerPeak);\n          let min = 1, max = -1;\n          for (let j = start; j < end; j++) {\n            const v = channel[j];\n            if (v < min) min = v;\n            if (v > max) max = v;\n          }\n          peaks[i * 2] = min;\n          peaks[i * 2 + 1] = max;\n        }\n        self.postMessage({ peaks, peaksSampleRate: peaksPerSecond }, [peaks.buffer]);\n      };\n    `;\n    const blob = new Blob([workerCode], { type: 'application/javascript' });\n    const url = URL.createObjectURL(blob);\n    const worker = new Worker(url);\n    const copy = new Float32Array(channel);\n    worker.onmessage = (e: MessageEvent<PeaksResult>) => {\n      worker.terminate();\n      URL.revokeObjectURL(url);\n      resolve(e.data);\n    };\n    worker.onerror = (err) => {\n      worker.terminate();\n      URL.revokeObjectURL(url);\n      reject(err);\n    };\n    worker.postMessage(\n      { channel: copy, sampleRate, peaksPerSecond: PEAKS_PER_SECOND },\n      [copy.buffer]\n    );\n  });\n}\n\n/** Draw peaks onto a canvas 2d context (for non-Konva fallbacks). */\nexport function drawPeaks(\n  ctx: CanvasRenderingContext2D,\n  peaks: Float32Array,\n  width: number,\n  height: number,\n  color = '#6C63FF'\n) {\n  const mid = height / 2;\n  const pairs = peaks.length / 2;\n  ctx.fillStyle = color;\n  for (let x = 0; x < width; x++) {\n    const idx = Math.floor((x / width) * pairs);\n    const min = peaks[idx * 2] ?? 0;\n    const max = peaks[idx * 2 + 1] ?? 0;\n    const y1 = mid + min * mid;\n    const y2 = mid + max * mid;\n    ctx.fillRect(x, y1, 1, Math.max(1, y2 - y1));\n  }\n}\n", "import { create } from 'zustand';\nimport {\n  removeWordsInRanges,\n  shiftWordsAfter,\n  wordsToRanges,\n  type TranscriptWord,\n} from '../lib/audio/transcriptEdit';\nimport { getActiveMessages } from '../i18n';\nimport {\n  createProjectPersistence,\n  registerProjectPersistence,\n  type ProjectPersistenceController,\n} from '../lib/persistence/projectPersistence';\nimport {\n  markCloudAutosaveAnnounce,\n  withCloudAutosaveToast,\n} from '../utils/cloudAutosaveToast';\nimport { sanitizeUserFacingMessage } from '../utils/userFacingError';\n\n// \u2500\u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type FadeCurve = 'linear' | 'logarithmic' | 's-curve' | 'exponential';\nexport type CrossfadeCurve = 'linear' | 'equal-power' | 'exponential';\nexport type AudioEffectType =\n  | 'eq'\n  | 'compressor'\n  | 'gate'\n  | 'reverb'\n  | 'delay'\n  | 'chorus'\n  | 'distortion'\n  | 'highpass'\n  | 'lowpass'\n  | 'limiter';\n\nexport interface AutomationPoint {\n  id: string;\n  time: number;\n  value: number;\n}\n\nexport interface AutomationLane {\n  id: string;\n  /** e.g. 'volume' | 'pan' | 'fx:eq.gain' */\n  property: string;\n  points: AutomationPoint[];\n}\n\nexport interface AppliedAudioEffect {\n  id: string;\n  type: AudioEffectType;\n  enabled: boolean;\n  order: number;\n  params: Record<string, number | boolean | string>;\n}\n\nexport interface AudioAsset {\n  id: string;\n  name: string;\n  url: string;\n  duration: number;\n  sampleRate?: number;\n  channels?: number;\n  file: File;\n  /** Cached waveform peaks (min/max interleaved), optional. */\n  peaks?: Float32Array;\n  peaksSampleRate?: number;\n}\n\nexport interface AudioClip {\n  id: string;\n  trackId: string;\n  assetId: string;\n  name?: string;\n  startTime: number;\n  duration: number;\n  trimIn: number;\n  trimOut: number;\n  /** Playback rate (time-stretch when pitchSeparate). */\n  speed: number;\n  /** Semitones of pitch shift. */\n  pitch: number;\n  /** Linear gain 0\u20132 (1 = unity). */\n  gain: number;\n  muted: boolean;\n  inverted: boolean;\n  fadeIn: number;\n  fadeOut: number;\n  fadeInCurve: FadeCurve;\n  fadeOutCurve: FadeCurve;\n  /** Dedicated overlap crossfade at clip edges (equal-power by default). */\n  crossfadeIn: number;\n  crossfadeOut: number;\n  crossfadeCurve: CrossfadeCurve;\n  /** When true, speed stretches time without changing pitch (and pitch is independent). */\n  pitchSeparate: boolean;\n  /** Alternate take lane (0 = main). Same takeGroupId = mutually exclusive takes. */\n  takeLane: number;\n  takeGroupId?: string;\n  /** Whether this take is the audible choice for its group. */\n  compActive: boolean;\n}\n\nexport interface AudioSend {\n  busId: string;\n  /** 0\u20131 linear send amount (post-FX). */\n  amount: number;\n}\n\nexport interface AudioTrack {\n  id: string;\n  name: string;\n  /** 'audio' | 'bus' | 'lyrics' */\n  type: 'audio' | 'bus' | 'lyrics';\n  muted: boolean;\n  solo: boolean;\n  locked: boolean;\n  armed: boolean;\n  /** dB */\n  volumeDb: number;\n  /** -1 left \u2026 +1 right */\n  pan: number;\n  clips: AudioClip[];\n  effects: AppliedAudioEffect[];\n  automation: AutomationLane[];\n  /** Aux sends to bus tracks. */\n  sends: AudioSend[];\n  color?: string;\n}\n\nexport interface AudioMarker {\n  id: string;\n  time: number;\n  name: string;\n  color?: string;\n  /** Set by applySongStructureMarkers \u2014 clearable as a group. */\n  source?: 'song-structure';\n}\n\nexport interface AudioRegion {\n  id: string;\n  startTime: number;\n  endTime: number;\n  name: string;\n  source?: 'song-structure';\n}\n\nexport interface AudioSnapshot {\n  tracks: AudioTrack[];\n  markers: AudioMarker[];\n  regions: AudioRegion[];\n  bpm: number;\n  description: string;\n}\n\nexport interface AudioProject {\n  id: string;\n  name: string;\n  sampleRate: number;\n  bpm: number;\n  timeSignature: [number, number];\n  tracks: AudioTrack[];\n  assets: AudioAsset[];\n  markers: AudioMarker[];\n  regions: AudioRegion[];\n  projectDuration: number;\n  playheadTime: number;\n  zoom: number;\n  history: AudioSnapshot[];\n  historyIndex: number;\n  createdAt: number;\n  loopEnabled: boolean;\n  loopStart: number;\n  loopEnd: number;\n  /** Last cloud editable id \u2014 used to replace on silent autosave. */\n  cloudEditableId?: number;\n}\n\nexport type AudioToast = {\n  id: string;\n  message: string;\n  type: 'success' | 'error' | 'info' | 'warning';\n};\n\ninterface AudioState {\n  audioProjects: AudioProject[];\n  activeAudioProjectId: string | null;\n  isAudioSetupOpen: boolean;\n  isAudioProjectLoading: boolean;\n  setIsAudioSetupOpen: (open: boolean) => void;\n  createAudioProject: (\n    name: string,\n    opts?: { sampleRate?: number; bpm?: number; template?: 'empty' | 'podcast' | 'music' | 'voiceover' }\n  ) => void;\n  closeAudioProject: (projectId: string) => void;\n  switchAudioProject: (projectId: string) => void;\n  renameAudioProject: (projectId: string, name: string) => void;\n  saveAudioProject: () => Promise<void>;\n  loadAudioProject: () => Promise<void>;\n  /** Silent cloud upload (debounced via pushToHistory). */\n  autoSaveAudioProjectToCloud: () => Promise<boolean>;\n  importAudioProject: (data: Partial<AudioProject> & { tracks?: AudioTrack[]; assets?: AudioAsset[] }, filename?: string, opts?: { cloudEditableId?: number }) => void;\n\n  tracks: AudioTrack[];\n  assets: AudioAsset[];\n  markers: AudioMarker[];\n  regions: AudioRegion[];\n  playheadTime: number;\n  isPlaying: boolean;\n  zoom: number;\n  scrollLeft: number;\n  scrollTop: number;\n  selectedClipIds: string[];\n  selectedTrackIds: string[];\n  history: AudioSnapshot[];\n  historyIndex: number;\n  projectDuration: number;\n  sampleRate: number;\n  bpm: number;\n  timeSignature: [number, number];\n  loopEnabled: boolean;\n  loopStart: number;\n  loopEnd: number;\n  masterVolumeDb: number;\n  snapEnabled: boolean;\n  snapMode: 'time' | 'beat';\n  /** Timeline edit mode: ripple shifts later clips when deleting/trimming. */\n  editMode: 'normal' | 'ripple';\n  exportModalOpen: boolean;\n  clipboardClips: AudioClip[];\n  toasts: AudioToast[];\n  /** Word-level transcript for Descript-style editing. */\n  transcript: TranscriptWord[];\n  selectedTranscriptIds: string[];\n  /** Short-term LUFS history for master meter (updated by engine). */\n  lufsHistory: number[];\n  truePeakDb: number;\n  /** Running integrated loudness estimate (session playback). */\n  integratedLufs: number;\n\n  setPlayhead: (t: number) => void;\n  setIsPlaying: (v: boolean) => void;\n  /**\n   * Timeline zoom (px/s). When `anchor` is set, keeps that time under `viewX`\n   * (viewport pixels from left) so zoom does not jump the playhead/content.\n   */\n  setZoom: (z: number, anchor?: { timeSec: number; viewX: number }) => void;\n  setScrollLeft: (v: number) => void;\n  setScrollTop: (v: number) => void;\n  setBpm: (bpm: number) => void;\n  setProjectDuration: (d: number) => void;\n  setLoop: (enabled: boolean, start?: number, end?: number) => void;\n  setMasterVolumeDb: (db: number) => void;\n  setSnap: (enabled: boolean, mode?: 'time' | 'beat') => void;\n  setEditMode: (mode: 'normal' | 'ripple') => void;\n  setExportModalOpen: (open: boolean) => void;\n\n  addAsset: (asset: AudioAsset) => void;\n  removeAsset: (assetId: string) => void;\n  updateAssetPeaks: (assetId: string, peaks: Float32Array, peaksSampleRate: number) => void;\n  /** Recompute waveform peaks for assets that lost them (IDB race / reload). */\n  ensureAssetPeaks: () => void;\n\n  addTrack: (name: string, type?: AudioTrack['type']) => string;\n  removeTrack: (trackId: string) => void;\n  reorderTracks: (fromIndex: number, toIndex: number) => void;\n  updateTrack: (trackId: string, patch: Partial<AudioTrack>) => void;\n  toggleTrackMute: (trackId: string) => void;\n  toggleTrackSolo: (trackId: string) => void;\n  toggleTrackLock: (trackId: string) => void;\n  toggleTrackArm: (trackId: string) => void;\n\n  addClip: (clip: AudioClip) => void;\n  removeClip: (clipId: string) => void;\n  removeSelectedClips: () => void;\n  moveClip: (clipId: string, startTime: number, trackId?: string) => void;\n  /**\n   * Move clip to a track index; creates audio tracks if index is past the end,\n   * then removes empty user audio tracks (keeps at least one).\n   */\n  moveClipToTrackIndex: (clipId: string, startTime: number, trackIndex: number) => void;\n  moveSelectedClips: (deltaTime: number) => void;\n  trimClip: (clipId: string, trimIn: number, trimOut: number, duration: number) => void;\n  splitClip: (clipId: string, atTime: number) => void;\n  /** Merge a clip with an abutting neighbor from the same split (same asset). */\n  joinAdjacentClip: (clipId: string) => void;\n  duplicateClip: (clipId: string) => void;\n  updateClip: (clipId: string, patch: Partial<AudioClip>) => void;\n  selectClip: (clipId: string | null, additive?: boolean) => void;\n  selectClips: (clipIds: string[], additive?: boolean) => void;\n  selectTrack: (trackId: string | null, additive?: boolean) => void;\n  clearSelection: () => void;\n  copySelectedClips: () => void;\n  cutSelectedClips: () => void;\n  pasteClips: () => void;\n  /** Stack clips vertically on the same track (comp / take lanes). */\n  nudgeClipTakeLane: (clipId: string, delta: number) => void;\n  /** Trim selected clip(s) so the nearer edge snaps to the playhead (playhead must be inside). */\n  trimSelectedToPlayhead: (edge: 'start' | 'end') => void;\n  nudgeSelectedClips: (deltaSeconds: number) => void;\n  setLoopToSelection: () => void;\n  zoomToSelection: (viewportWidthPx: number) => void;\n  trimSelectedClips: (deltaTrimIn: number, deltaDuration: number) => void;\n  setTrackSend: (trackId: string, busId: string, amount: number) => void;\n  applySongStructureMarkers: () => void;\n  clearSongStructureMarkers: () => void;\n  setTranscript: (words: TranscriptWord[]) => void;\n  selectTranscriptWords: (ids: string[], additive?: boolean) => void;\n  /** @param opts.ripple defaults to editMode === 'ripple' */\n  deleteSelectedTranscriptWords: (opts?: { ripple?: boolean }) => void;\n  removeFillerWords: () => void;\n  applyCrossfadeBetweenSelected: (seconds: number, curve?: CrossfadeCurve) => void;\n  setActiveTake: (takeGroupId: string, takeLane: number) => void;\n  /** Activate take only inside [start,end]; splits overlapping clips at boundaries. */\n  compTakeInRegion: (\n    takeGroupId: string,\n    takeLane: number,\n    start: number,\n    end: number\n  ) => void;\n  setLufsMeter: (\n    history: number[],\n    truePeakDb: number,\n    integratedLufs?: number\n  ) => void;\n\n  addEffect: (trackId: string, effect: AppliedAudioEffect) => void;\n  updateEffect: (trackId: string, effectId: string, patch: Partial<AppliedAudioEffect>) => void;\n  removeEffect: (trackId: string, effectId: string) => void;\n  reorderEffects: (trackId: string, from: number, to: number) => void;\n\n  setAutomationLane: (trackId: string, lane: AutomationLane) => void;\n  addMarker: (marker: AudioMarker) => void;\n  removeMarker: (markerId: string) => void;\n  addRegion: (region: AudioRegion) => void;\n  removeRegion: (regionId: string) => void;\n\n  undo: () => void;\n  redo: () => void;\n  beginHistoryBatch: (description: string) => void;\n  endHistoryBatch: () => void;\n\n  addToast: (message: string, type?: AudioToast['type']) => void;\n  removeToast: (id: string) => void;\n\n  getProjectSnapshot: () => Record<string, unknown>;\n}\n\n// \u2500\u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nlet audioPersistence!: ProjectPersistenceController;\nlet _batchDepth = 0;\nlet _batchDescription = '';\n\nfunction uid(prefix: string): string {\n  return `${prefix}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction deepCloneTracks(tracks: AudioTrack[]): AudioTrack[] {\n  const cloned = JSON.parse(JSON.stringify(tracks)) as AudioTrack[];\n  return cloned.map((t) => ({ ...t, sends: t.sends ?? [] }));\n}\n\nfunction pushToHistory(\n  state: Pick<AudioState, 'tracks' | 'markers' | 'regions' | 'bpm' | 'history' | 'historyIndex'>,\n  description: string\n): { history: AudioSnapshot[]; historyIndex: number } {\n  if (_batchDepth > 0) {\n    return { history: state.history, historyIndex: state.historyIndex };\n  }\n  const snapshot: AudioSnapshot = {\n    tracks: deepCloneTracks(state.tracks),\n    markers: JSON.parse(JSON.stringify(state.markers)) as AudioMarker[],\n    regions: JSON.parse(JSON.stringify(state.regions)) as AudioRegion[],\n    bpm: state.bpm,\n    description,\n  };\n  let history = state.history.slice(0, state.historyIndex + 1);\n  history.push(snapshot);\n  if (history.length > 50) history = history.slice(history.length - 50);\n  markCloudAutosaveAnnounce('audio');\n  audioPersistence.scheduleAfterChange();\n  return { history, historyIndex: history.length - 1 };\n}\n\nfunction notifyEngine() {\n  // Lazy import avoids circular init; fire-and-forget live graph sync\n  void import('../lib/audio/AudioEngine').then(({ syncEngineFromStore }) => {\n    const s = useAudioStore.getState();\n    syncEngineFromStore(s.tracks, s.assets);\n  });\n}\n\nfunction defaultTracks(template: 'empty' | 'podcast' | 'music' | 'voiceover', projectId: string): AudioTrack[] {\n  const mk = (name: string, type: AudioTrack['type'], color: string): AudioTrack => ({\n    id: uid(`${type}-${projectId}`),\n    name,\n    type,\n    muted: false,\n    solo: false,\n    locked: false,\n    armed: false,\n    volumeDb: 0,\n    pan: 0,\n    clips: [],\n    effects: type === 'bus' ? [{\n      id: uid('fx'),\n      type: 'reverb',\n      enabled: true,\n      order: 0,\n      params: { decay: 2.2, mix: 1 },\n    }] : [],\n    automation: [],\n    sends: [],\n    color,\n  });\n\n  if (template === 'podcast') {\n    return [\n      mk('Host', 'audio', '#6C63FF'),\n      mk('Guest', 'audio', '#00BFA5'),\n      mk('Music bed', 'audio', '#FF8A65'),\n      mk('SFX', 'audio', '#FFD54F'),\n    ];\n  }\n  if (template === 'music') {\n    return [\n      mk('Vocals', 'audio', '#FF4081'),\n      mk('Drums', 'audio', '#FF8A65'),\n      mk('Bass', 'audio', '#6C63FF'),\n      mk('Instruments', 'audio', '#00BFA5'),\n      mk('FX', 'audio', '#FFD54F'),\n    ];\n  }\n  if (template === 'voiceover') {\n    return [mk('Voiceover', 'audio', '#6C63FF'), mk('Bed', 'audio', '#00BFA5')];\n  }\n  return [mk('Audio 1', 'audio', '#6C63FF'), mk('Audio 2', 'audio', '#00BFA5')];\n}\n\nfunction syncActiveIntoProjects(state: AudioState): AudioProject[] {\n  if (!state.activeAudioProjectId) return state.audioProjects;\n  return state.audioProjects.map((p) =>\n    p.id === state.activeAudioProjectId\n      ? {\n          ...p,\n          tracks: state.tracks,\n          assets: state.assets,\n          markers: state.markers,\n          regions: state.regions,\n          projectDuration: state.projectDuration,\n          playheadTime: state.playheadTime,\n          zoom: state.zoom,\n          history: state.history,\n          historyIndex: state.historyIndex,\n          bpm: state.bpm,\n          sampleRate: state.sampleRate,\n          timeSignature: state.timeSignature,\n          loopEnabled: state.loopEnabled,\n          loopStart: state.loopStart,\n          loopEnd: state.loopEnd,\n        }\n      : p\n  );\n}\n\nfunction applyProjectToRoot(project: AudioProject) {\n  return {\n    tracks: project.tracks,\n    assets: project.assets,\n    markers: project.markers,\n    regions: project.regions,\n    projectDuration: project.projectDuration,\n    playheadTime: project.playheadTime,\n    zoom: clampAudioZoom(project.zoom),\n    history: project.history,\n    historyIndex: project.historyIndex,\n    bpm: project.bpm,\n    sampleRate: project.sampleRate,\n    timeSignature: project.timeSignature,\n    loopEnabled: project.loopEnabled,\n    loopStart: project.loopStart,\n    loopEnd: project.loopEnd,\n    selectedClipIds: [] as string[],\n    selectedTrackIds: [] as string[],\n  };\n}\n\nfunction recomputeDuration(tracks: AudioTrack[]): number {\n  let max = 30;\n  for (const t of tracks) {\n    for (const c of t.clips) {\n      max = Math.max(max, c.startTime + c.duration);\n    }\n  }\n  return Math.ceil(max + 2);\n}\n\n/** Timeline zoom (px/s). Cap is intentionally low \u2014 Konva waveform cost scales with zoom. */\nexport const AUDIO_ZOOM_MIN = 16;\nexport const AUDIO_ZOOM_MAX = 140;\nexport const AUDIO_ZOOM_DEFAULT = 48;\n\nexport function clampAudioZoom(z: number): number {\n  return Math.max(AUDIO_ZOOM_MIN, Math.min(AUDIO_ZOOM_MAX, z));\n}\n\n// \u2500\u2500\u2500 Store \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const useAudioStore = create<AudioState>((set, get) => ({\n  audioProjects: [],\n  activeAudioProjectId: null,\n  isAudioSetupOpen: false,\n  isAudioProjectLoading: true,\n\n  tracks: [],\n  assets: [],\n  markers: [],\n  regions: [],\n  playheadTime: 0,\n  isPlaying: false,\n  zoom: AUDIO_ZOOM_DEFAULT,\n  scrollLeft: 0,\n  scrollTop: 0,\n  selectedClipIds: [],\n  selectedTrackIds: [],\n  history: [],\n  historyIndex: -1,\n  projectDuration: 60,\n  sampleRate: 48000,\n  bpm: 120,\n  timeSignature: [4, 4],\n  loopEnabled: false,\n  loopStart: 0,\n  loopEnd: 8,\n  masterVolumeDb: 0,\n  snapEnabled: true,\n  snapMode: 'beat',\n  editMode: 'normal',\n  exportModalOpen: false,\n  clipboardClips: [],\n  toasts: [],\n  transcript: [],\n  selectedTranscriptIds: [],\n  lufsHistory: [],\n  truePeakDb: -60,\n  integratedLufs: -70,\n\n  setIsAudioSetupOpen: (open) => set({ isAudioSetupOpen: open }),\n\n  createAudioProject: (name, opts) => {\n    const projectId = uid('ap');\n    const template = opts?.template ?? 'empty';\n    const tracks = defaultTracks(template, projectId);\n    const project: AudioProject = {\n      id: projectId,\n      name: name || 'Proyecto de audio',\n      sampleRate: opts?.sampleRate ?? 48000,\n      bpm: opts?.bpm ?? (template === 'podcast' ? 0 : 120),\n      timeSignature: [4, 4],\n      tracks,\n      assets: [],\n      markers: [],\n      regions: [],\n      projectDuration: 60,\n      playheadTime: 0,\n      zoom: AUDIO_ZOOM_DEFAULT,\n      history: [\n        {\n          tracks: deepCloneTracks(tracks),\n          markers: [],\n          regions: [],\n          bpm: opts?.bpm ?? 120,\n          description: 'Created',\n        },\n      ],\n      historyIndex: 0,\n      createdAt: Date.now(),\n      loopEnabled: false,\n      loopStart: 0,\n      loopEnd: 8,\n    };\n    set((state) => {\n      const projects = syncActiveIntoProjects(state);\n      return {\n        audioProjects: [...projects, project],\n        activeAudioProjectId: project.id,\n        isAudioSetupOpen: false,\n        ...applyProjectToRoot(project),\n      };\n    });\n    void get().saveAudioProject();\n  },\n\n  closeAudioProject: (projectId) => {\n    set((state) => {\n      const projects = syncActiveIntoProjects(state).filter((p) => p.id !== projectId);\n      const next = projects[0] ?? null;\n      return {\n        audioProjects: projects,\n        activeAudioProjectId: next?.id ?? null,\n        isAudioSetupOpen: projects.length === 0,\n        ...(next\n          ? applyProjectToRoot(next)\n          : {\n              tracks: [],\n              assets: [],\n              markers: [],\n              regions: [],\n              history: [],\n              historyIndex: -1,\n              playheadTime: 0,\n            }),\n      };\n    });\n    void get().saveAudioProject();\n  },\n\n  switchAudioProject: (projectId) => {\n    set((state) => {\n      const projects = syncActiveIntoProjects(state);\n      const next = projects.find((p) => p.id === projectId);\n      if (!next) return {};\n      return {\n        audioProjects: projects,\n        activeAudioProjectId: projectId,\n        ...applyProjectToRoot(next),\n      };\n    });\n    get().ensureAssetPeaks();\n  },\n\n  renameAudioProject: (projectId, name) => {\n    const trimmed = name.trim();\n    if (!trimmed) return;\n    set((state) => ({\n      audioProjects: state.audioProjects.map((p) =>\n        p.id === projectId ? { ...p, name: trimmed } : p,\n      ),\n    }));\n    void get().saveAudioProject().catch(() => {});\n    // Rename should show up in Recientes promptly.\n    void audioPersistence.flushCloud();\n  },\n\n  saveAudioProject: async () => {\n    const state = get();\n    // Never overwrite IDB while hydrating or with an empty project list\n    // (heartbeat used to wipe the last good deck during slow asset load).\n    if (state.isAudioProjectLoading || state.audioProjects.length === 0) return;\n    const projects = syncActiveIntoProjects(state);\n    const { openUploadsDB } = await import('./useEditorStore');\n    const db = await openUploadsDB();\n    await new Promise<void>((resolve, reject) => {\n      const tx = db.transaction('projects', 'readwrite');\n      const store = tx.objectStore('projects');\n      const serializable = projects.map((p) => ({\n        ...p,\n        assets: p.assets.map(({ file: _f, url: _u, peaks: _pk, ...meta }) => ({\n          ...meta,\n          url: '',\n        })),\n      }));\n      const req = store.put({ id: 'audio-projects', projects: serializable });\n      req.onsuccess = () => resolve();\n      req.onerror = () => reject(req.error);\n    });\n    set({ audioProjects: projects });\n  },\n\n  autoSaveAudioProjectToCloud: async () =>\n    withCloudAutosaveToast('audio', async () => {\n    const { hasEditorIdentity } = await import('../services/identity');\n    if (!hasEditorIdentity()) return false;\n\n    const state = get();\n    if (\n      state.isAudioProjectLoading ||\n      !state.activeAudioProjectId ||\n      state.audioProjects.length === 0\n    ) {\n      return false;\n    }\n\n    const projectId = state.activeAudioProjectId;\n    const cloudEditableId = state.audioProjects.find((p) => p.id === projectId)?.cloudEditableId;\n\n    try {\n      const { uploadCurrentProjectToCloud } = await import('../utils/projectCloudSerializer');\n      const editable = await uploadCurrentProjectToCloud('audio', {\n        editableId: cloudEditableId,\n      });\n\n      const stillActive = get().activeAudioProjectId === projectId;\n      if (stillActive) {\n        set((s) => ({\n          audioProjects: s.audioProjects.map((p) =>\n            p.id === projectId ? { ...p, cloudEditableId: editable.id } : p,\n          ),\n        }));\n        void get().saveAudioProject().catch(() => {});\n      }\n\n      return true;\n    } catch (err) {\n      console.warn('[autoSaveAudioProjectToCloud] failed:', err);\n      throw err;\n    }\n  }),\n\n  loadAudioProject: async () => {\n    try {\n      const { openUploadsDB } = await import('./useEditorStore');\n      const db = await openUploadsDB();\n      const record = await new Promise<{ projects?: AudioProject[] } | undefined>((resolve, reject) => {\n        const tx = db.transaction('projects', 'readonly');\n        const req = tx.objectStore('projects').get('audio-projects');\n        req.onsuccess = () => resolve(req.result as { projects?: AudioProject[] } | undefined);\n        req.onerror = () => reject(req.error);\n      });\n\n      const assetRows = await new Promise<\n        Array<{\n          id: string;\n          name: string;\n          mimeType: string;\n          buffer: ArrayBuffer;\n          duration: number;\n          sampleRate?: number;\n          channels?: number;\n          peaks?: ArrayBuffer;\n          peaksSampleRate?: number;\n        }>\n      >((resolve, reject) => {\n        const tx = db.transaction('audio-assets', 'readonly');\n        const req = tx.objectStore('audio-assets').getAll();\n        req.onsuccess = () => resolve((req.result as typeof assetRows) || []);\n        req.onerror = () => reject(req.error);\n      });\n\n      const assetMap = new Map(\n        assetRows.map((row) => {\n          const blob = new Blob([row.buffer], { type: row.mimeType || 'audio/mpeg' });\n          const url = URL.createObjectURL(blob);\n          const file = new File([blob], row.name || row.id, { type: row.mimeType || 'audio/mpeg' });\n          const asset: AudioAsset = {\n            id: row.id,\n            name: row.name,\n            url,\n            duration: row.duration || 0,\n            sampleRate: row.sampleRate,\n            channels: row.channels,\n            file,\n            peaks: row.peaks\n              ? row.peaks instanceof Float32Array\n                ? new Float32Array(row.peaks)\n                : new Float32Array(row.peaks)\n              : undefined,\n            peaksSampleRate: row.peaksSampleRate,\n          };\n          return [row.id, asset] as const;\n        })\n      );\n\n      const projects = (record?.projects || []).map((p) => ({\n        ...p,\n        assets: (p.assets || []).map((a) => assetMap.get(a.id) || { ...a, url: '', file: new File([], a.name) }),\n        history: p.history?.length\n          ? p.history\n          : [\n              {\n                tracks: deepCloneTracks(p.tracks || []),\n                markers: p.markers || [],\n                regions: p.regions || [],\n                bpm: p.bpm || 120,\n                description: 'Restored',\n              },\n            ],\n        historyIndex: p.history?.length ? p.historyIndex : 0,\n      }));\n\n      const active = projects[0] ?? null;\n      set({\n        audioProjects: projects,\n        activeAudioProjectId: active?.id ?? null,\n        isAudioProjectLoading: false,\n        isAudioSetupOpen: projects.length === 0,\n        ...(active\n          ? applyProjectToRoot(active)\n          : {\n              tracks: [],\n              assets: [],\n              markers: [],\n              regions: [],\n              history: [],\n              historyIndex: -1,\n            }),\n      });\n      get().ensureAssetPeaks();\n    } catch (err) {\n      console.error('Failed to load audio projects', err);\n      set({ isAudioProjectLoading: false, isAudioSetupOpen: true });\n    }\n  },\n\n  importAudioProject: (data, filename, opts) => {\n    const projectId = uid('ap');\n    const tracks = data.tracks || defaultTracks('empty', projectId);\n    const project: AudioProject = {\n      id: projectId,\n      name: filename?.replace(/\\.(kaia|wzrda)$/i, '') || data.name || 'Importado',\n      sampleRate: data.sampleRate ?? 48000,\n      bpm: data.bpm ?? 120,\n      timeSignature: data.timeSignature ?? [4, 4],\n      tracks,\n      assets: data.assets || [],\n      markers: data.markers || [],\n      regions: data.regions || [],\n      projectDuration: data.projectDuration ?? recomputeDuration(tracks),\n      playheadTime: 0,\n      zoom: clampAudioZoom(data.zoom ?? AUDIO_ZOOM_DEFAULT),\n      history: [\n        {\n          tracks: deepCloneTracks(tracks),\n          markers: data.markers || [],\n          regions: data.regions || [],\n          bpm: data.bpm ?? 120,\n          description: 'Imported',\n        },\n      ],\n      historyIndex: 0,\n      createdAt: Date.now(),\n      loopEnabled: false,\n      loopStart: 0,\n      loopEnd: 8,\n      cloudEditableId: opts?.cloudEditableId,\n    };\n    set((state) => {\n      const projects = syncActiveIntoProjects(state);\n      return {\n        audioProjects: [...projects, project],\n        activeAudioProjectId: project.id,\n        isAudioSetupOpen: false,\n        ...applyProjectToRoot(project),\n      };\n    });\n    for (const asset of project.assets) {\n      if (asset.file) {\n        void asset.file.arrayBuffer().then(async (buffer) => {\n          const { openUploadsDB } = await import('./useEditorStore');\n          const db = await openUploadsDB();\n          const tx = db.transaction('audio-assets', 'readwrite');\n          tx.objectStore('audio-assets').put({\n            id: asset.id,\n            name: asset.name,\n            mimeType: asset.file.type || 'audio/mpeg',\n            buffer,\n            duration: asset.duration,\n            sampleRate: asset.sampleRate,\n            channels: asset.channels,\n            peaks:\n              asset.peaks &&\n              asset.peaks.buffer.slice(\n                asset.peaks.byteOffset,\n                asset.peaks.byteOffset + asset.peaks.byteLength,\n              ),\n            peaksSampleRate: asset.peaksSampleRate,\n          });\n        });\n      }\n    }\n    void get().saveAudioProject();\n    void get().ensureAssetPeaks();\n  },\n\n  setPlayhead: (t) => set({ playheadTime: Math.max(0, t) }),\n  setIsPlaying: (v) => set({ isPlaying: v }),\n  setZoom: (z, anchor) =>\n    set(() => {\n      const zoom = clampAudioZoom(z);\n      if (!anchor) return { zoom };\n      const scrollLeft = Math.max(0, anchor.timeSec * zoom - anchor.viewX);\n      return { zoom, scrollLeft };\n    }),\n  setScrollLeft: (v) => set({ scrollLeft: Math.max(0, v) }),\n  setScrollTop: (v) => set({ scrollTop: Math.max(0, v) }),\n  setBpm: (bpm) =>\n    set((state) => ({\n      bpm: Math.max(0, Math.min(300, bpm)),\n      ...pushToHistory(state, `BPM \u2192 ${bpm}`),\n    })),\n  setProjectDuration: (d) => set({ projectDuration: Math.max(1, d) }),\n  setLoop: (enabled, start, end) =>\n    set((state) => ({\n      loopEnabled: enabled,\n      loopStart: start ?? state.loopStart,\n      loopEnd: end ?? state.loopEnd,\n    })),\n  setMasterVolumeDb: (db) => set({ masterVolumeDb: db }),\n  setSnap: (enabled, mode) =>\n    set((state) => ({\n      snapEnabled: enabled,\n      snapMode: mode ?? state.snapMode,\n    })),\n  setEditMode: (mode) => set({ editMode: mode }),\n  setExportModalOpen: (open) => set({ exportModalOpen: open }),\n\n  addAsset: (asset) => {\n    // Own a copy so transferable worker buffers cannot detach under us.\n    const peaks =\n      asset.peaks && asset.peaks.length > 0 ? new Float32Array(asset.peaks) : undefined;\n    const next: AudioAsset = { ...asset, peaks };\n    set((state) => ({ assets: [...state.assets, next] }));\n    void next.file.arrayBuffer().then(async (buffer) => {\n      try {\n        const { openUploadsDB } = await import('./useEditorStore');\n        const db = await openUploadsDB();\n        const tx = db.transaction('audio-assets', 'readwrite');\n        const peaksCopy =\n          peaks && peaks.buffer.slice(peaks.byteOffset, peaks.byteOffset + peaks.byteLength);\n        tx.objectStore('audio-assets').put({\n          id: next.id,\n          name: next.name,\n          mimeType: next.file.type || 'audio/mpeg',\n          buffer,\n          duration: next.duration,\n          sampleRate: next.sampleRate,\n          channels: next.channels,\n          peaks: peaksCopy,\n          peaksSampleRate: next.peaksSampleRate,\n        });\n      } catch (err) {\n        console.error('Failed to persist audio asset', err);\n      }\n    });\n    void get().saveAudioProject();\n    if (!peaks) get().ensureAssetPeaks();\n  },\n\n  removeAsset: (assetId) => {\n    set((state) => {\n      const tracks = state.tracks.map((t) => ({\n        ...t,\n        clips: t.clips.filter((c) => c.assetId !== assetId),\n      }));\n      return {\n        assets: state.assets.filter((a) => a.id !== assetId),\n        tracks,\n        ...pushToHistory({ ...state, tracks }, 'Remove asset'),\n        projectDuration: recomputeDuration(tracks),\n      };\n    });\n  },\n\n  updateAssetPeaks: (assetId, peaks, peaksSampleRate) => {\n    const owned = peaks.length > 0 ? new Float32Array(peaks) : peaks;\n    set((state) => ({\n      assets: state.assets.map((a) =>\n        a.id === assetId ? { ...a, peaks: owned, peaksSampleRate } : a,\n      ),\n    }));\n    // Persist peaks alongside the audio buffer so reload skips recompute\n    void (async () => {\n      try {\n        const { openUploadsDB } = await import('./useEditorStore');\n        const db = await openUploadsDB();\n        const tx = db.transaction('audio-assets', 'readwrite');\n        const store = tx.objectStore('audio-assets');\n        const existing = await new Promise<Record<string, unknown> | undefined>((resolve, reject) => {\n          const req = store.get(assetId);\n          req.onsuccess = () => resolve(req.result as Record<string, unknown> | undefined);\n          req.onerror = () => reject(req.error);\n        });\n        if (!existing) return;\n        store.put({\n          ...existing,\n          peaks: owned.buffer.slice(owned.byteOffset, owned.byteOffset + owned.byteLength),\n          peaksSampleRate,\n        });\n      } catch {\n        /* ignore */\n      }\n    })();\n  },\n\n  ensureAssetPeaks: () => {\n    const missing = get().assets.filter(\n      (a) => (!a.peaks || a.peaks.length === 0) && a.file && a.file.size > 0,\n    );\n    if (!missing.length) return;\n    void (async () => {\n      const { decodeAudioBlob, extractPeaks } = await import('../lib/audio/peaks');\n      for (const asset of missing) {\n        // Skip if another pass already filled peaks\n        const current = get().assets.find((a) => a.id === asset.id);\n        if (!current || (current.peaks && current.peaks.length > 0)) continue;\n        try {\n          const buffer = await decodeAudioBlob(asset.file);\n          const result = await extractPeaks(buffer);\n          get().updateAssetPeaks(asset.id, result.peaks, result.peaksSampleRate);\n        } catch (err) {\n          console.warn('[ensureAssetPeaks] failed for', asset.id, err);\n        }\n      }\n    })();\n  },\n\n  addTrack: (name, type = 'audio') => {\n    const id = uid('tr');\n    set((state) => {\n      const track: AudioTrack = {\n        id,\n        name,\n        type,\n        muted: false,\n        solo: false,\n        locked: false,\n        armed: false,\n        volumeDb: type === 'bus' ? 0 : 0,\n        pan: 0,\n        clips: [],\n        effects:\n          type === 'bus'\n            ? [\n                {\n                  id: uid('fx'),\n                  type: 'reverb',\n                  enabled: true,\n                  order: 0,\n                  params: { decay: 2.2, mix: 1 },\n                },\n              ]\n            : [],\n        automation: [],\n        sends: [],\n        color: type === 'bus' ? '#FFD54F' : '#6C63FF',\n      };\n      const tracks = [...state.tracks, track];\n      return { tracks, ...pushToHistory({ ...state, tracks }, `Add track ${name}`) };\n    });\n    notifyEngine();\n    return id;\n  },\n\n  removeTrack: (trackId) =>\n    set((state) => {\n      const tracks = state.tracks\n        .filter((t) => t.id !== trackId)\n        .map((t) => ({\n          ...t,\n          sends: t.sends?.filter((s) => s.busId !== trackId),\n        }));\n      return {\n        tracks,\n        selectedTrackIds: state.selectedTrackIds.filter((id) => id !== trackId),\n        projectDuration: recomputeDuration(tracks),\n        ...pushToHistory({ ...state, tracks }, 'Remove track'),\n      };\n    }),\n\n  reorderTracks: (fromIndex, toIndex) =>\n    set((state) => {\n      const tracks = [...state.tracks];\n      const [item] = tracks.splice(fromIndex, 1);\n      if (!item) return {};\n      tracks.splice(toIndex, 0, item);\n      return { tracks, ...pushToHistory({ ...state, tracks }, 'Reorder tracks') };\n    }),\n\n  updateTrack: (trackId, patch) => {\n    set((state) => {\n      const tracks = state.tracks.map((t) => (t.id === trackId ? { ...t, ...patch } : t));\n      return { tracks, ...pushToHistory({ ...state, tracks }, 'Update track') };\n    });\n    notifyEngine();\n  },\n\n  toggleTrackMute: (trackId) => {\n    set((state) => ({\n      tracks: state.tracks.map((t) => (t.id === trackId ? { ...t, muted: !t.muted } : t)),\n    }));\n    notifyEngine();\n  },\n\n  toggleTrackSolo: (trackId) => {\n    set((state) => ({\n      tracks: state.tracks.map((t) => (t.id === trackId ? { ...t, solo: !t.solo } : t)),\n    }));\n    notifyEngine();\n  },\n\n  toggleTrackLock: (trackId) =>\n    set((state) => ({\n      tracks: state.tracks.map((t) => (t.id === trackId ? { ...t, locked: !t.locked } : t)),\n    })),\n\n  toggleTrackArm: (trackId) =>\n    set((state) => ({\n      tracks: state.tracks.map((t) => (t.id === trackId ? { ...t, armed: !t.armed } : t)),\n    })),\n\n  addClip: (clip) =>\n    set((state) => {\n      const tracks = state.tracks.map((t) =>\n        t.id === clip.trackId ? { ...t, clips: [...t.clips, clip] } : t\n      );\n      return {\n        tracks,\n        projectDuration: recomputeDuration(tracks),\n        ...pushToHistory({ ...state, tracks }, 'Add clip'),\n      };\n    }),\n\n  removeClip: (clipId) => {\n    get().selectClip(clipId);\n    get().removeSelectedClips();\n  },\n\n  removeSelectedClips: () =>\n    set((state) => {\n      const ids = new Set(state.selectedClipIds);\n      if (!ids.size) return {};\n      const tracks = state.tracks.map((t) => {\n        const removed = t.clips.filter((c) => ids.has(c.id));\n        let clips = t.clips.filter((c) => !ids.has(c.id));\n        if (state.editMode === 'ripple' && removed.length) {\n          const cutEnd = Math.max(...removed.map((c) => c.startTime + c.duration));\n          const cutStart = Math.min(...removed.map((c) => c.startTime));\n          const delta = cutEnd - cutStart;\n          clips = clips.map((c) =>\n            c.startTime >= cutEnd ? { ...c, startTime: Math.max(0, c.startTime - delta) } : c\n          );\n        }\n        return { ...t, clips };\n      });\n      return {\n        tracks,\n        selectedClipIds: [],\n        projectDuration: recomputeDuration(tracks),\n        ...pushToHistory({ ...state, tracks }, 'Remove clips'),\n      };\n    }),\n\n  moveClip: (clipId, startTime, trackId) =>\n    set((state) => {\n      let clip: AudioClip | undefined;\n      for (const t of state.tracks) {\n        clip = t.clips.find((c) => c.id === clipId);\n        if (clip) break;\n      }\n      if (!clip) return {};\n      const targetTrackId = trackId ?? clip.trackId;\n      const moved: AudioClip = {\n        ...clip,\n        startTime: Math.max(0, startTime),\n        trackId: targetTrackId,\n        takeLane: 0,\n      };\n      const tracks = state.tracks.map((t) => {\n        const without = t.clips.filter((c) => c.id !== clipId);\n        if (t.id === targetTrackId) return { ...t, clips: [...without, moved] };\n        return { ...t, clips: without };\n      });\n      return {\n        tracks,\n        projectDuration: recomputeDuration(tracks),\n        ...pushToHistory({ ...state, tracks }, 'Move clip'),\n      };\n    }),\n\n  moveClipToTrackIndex: (clipId, startTime, trackIndex) => {\n    const state = get();\n    let clip: AudioClip | undefined;\n    let sourceTrackId: string | undefined;\n    let sourceTrackIndex = -1;\n    let sourceClipCount = 0;\n    state.tracks.forEach((t, i) => {\n      const found = t.clips.find((c) => c.id === clipId);\n      if (found) {\n        clip = found;\n        sourceTrackId = t.id;\n        sourceTrackIndex = i;\n        sourceClipCount = t.clips.length;\n      }\n    });\n    if (!clip || sourceTrackId == null) return;\n\n    // Alone on the last track + drop \"below\" would create a new row and then\n    // prune the emptied source \u2014 net same visual slot (ghost row). Keep the track.\n    const aloneOnLast =\n      sourceTrackIndex === state.tracks.length - 1 && sourceClipCount === 1;\n    let desiredIndex = Math.max(0, trackIndex);\n    if (aloneOnLast && desiredIndex >= state.tracks.length) {\n      desiredIndex = sourceTrackIndex;\n    }\n\n    let tracks = state.tracks.map((t) => ({\n      ...t,\n      clips: t.clips.filter((c) => c.id !== clipId),\n    }));\n\n    if (desiredIndex >= tracks.length) {\n      const id = uid('tr');\n      tracks = [\n        ...tracks,\n        {\n          id,\n          name: getActiveMessages().audio.tracks.addTrack,\n          type: 'audio' as const,\n          muted: false,\n          solo: false,\n          locked: false,\n          armed: false,\n          volumeDb: 0,\n          pan: 0,\n          clips: [],\n          effects: [],\n          automation: [],\n          sends: [],\n          color: '#6C63FF',\n        },\n      ];\n    }\n\n    const target = tracks[Math.min(desiredIndex, tracks.length - 1)];\n    if (!target) return;\n\n    const moved: AudioClip = {\n      ...clip,\n      startTime: Math.max(0, startTime),\n      trackId: target.id,\n      takeLane: 0,\n    };\n    tracks = tracks.map((t) =>\n      t.id === target.id ? { ...t, clips: [...t.clips, moved] } : t,\n    );\n\n    // Drop empty audio tracks, keep \u22651 audio track.\n    const audioTracks = tracks.filter((t) => t.type === 'audio');\n    const emptyAudio = audioTracks.filter((t) => t.clips.length === 0);\n    const nonEmptyAudio = audioTracks.length - emptyAudio.length;\n    const removable =\n      nonEmptyAudio >= 1 ? emptyAudio : emptyAudio.slice(1);\n    if (removable.length) {\n      const removeIds = new Set(removable.map((t) => t.id));\n      tracks = tracks\n        .filter((t) => !removeIds.has(t.id))\n        .map((t) => ({\n          ...t,\n          sends: t.sends?.filter((s) => !removeIds.has(s.busId)),\n        }));\n    }\n\n    set({\n      tracks,\n      selectedTrackIds: state.selectedTrackIds.filter((id) => tracks.some((t) => t.id === id)),\n      projectDuration: recomputeDuration(tracks),\n      ...pushToHistory({ ...state, tracks }, 'Move clip'),\n    });\n  },\n\n  moveSelectedClips: (deltaTime) =>\n    set((state) => {\n      const ids = new Set(state.selectedClipIds);\n      if (!ids.size) return {};\n      const tracks = state.tracks.map((t) => ({\n        ...t,\n        clips: t.clips.map((c) =>\n          ids.has(c.id) ? { ...c, startTime: Math.max(0, c.startTime + deltaTime) } : c\n        ),\n      }));\n      return {\n        tracks,\n        projectDuration: recomputeDuration(tracks),\n        ...pushToHistory({ ...state, tracks }, 'Move selection'),\n      };\n    }),\n\n  trimClip: (clipId, trimIn, trimOut, duration) =>\n    set((state) => {\n      const tracks = state.tracks.map((t) => ({\n        ...t,\n        clips: t.clips.map((c) =>\n          c.id === clipId ? { ...c, trimIn, trimOut, duration } : c\n        ),\n      }));\n      return {\n        tracks,\n        projectDuration: recomputeDuration(tracks),\n        ...pushToHistory({ ...state, tracks }, 'Trim clip'),\n      };\n    }),\n\n  splitClip: (clipId, atTime) =>\n    set((state) => {\n      const tracks = state.tracks.map((t) => {\n        const idx = t.clips.findIndex((c) => c.id === clipId);\n        if (idx < 0) return t;\n        const clip = t.clips[idx]!;\n        const rel = atTime - clip.startTime;\n        if (rel <= 0.05 || rel >= clip.duration - 0.05) return t;\n        const left: AudioClip = {\n          ...clip,\n          duration: rel,\n          trimOut: clip.trimIn + rel * clip.speed,\n        };\n        const right: AudioClip = {\n          ...clip,\n          id: uid('clip'),\n          startTime: atTime,\n          duration: clip.duration - rel,\n          trimIn: clip.trimIn + rel * clip.speed,\n        };\n        const clips = [...t.clips];\n        clips.splice(idx, 1, left, right);\n        return { ...t, clips };\n      });\n      return { tracks, ...pushToHistory({ ...state, tracks }, 'Split clip') };\n    }),\n\n  joinAdjacentClip: (clipId) => {\n    const state = get();\n    const EPS = 0.05;\n    let hostTrack: AudioTrack | undefined;\n    let clip: AudioClip | undefined;\n    for (const t of state.tracks) {\n      const found = t.clips.find((c) => c.id === clipId);\n      if (found) {\n        hostTrack = t;\n        clip = found;\n        break;\n      }\n    }\n    if (!clip || !hostTrack) return;\n\n    const canPair = (a: AudioClip, b: AudioClip) =>\n      a.assetId === b.assetId &&\n      Math.abs(a.speed - b.speed) < 1e-6 &&\n      Math.abs(a.pitch - b.pitch) < 1e-6 &&\n      Math.abs(a.startTime + a.duration - b.startTime) < EPS &&\n      Math.abs(a.trimOut - b.trimIn) < EPS;\n\n    let left: AudioClip | undefined;\n    let right: AudioClip | undefined;\n\n    const selectedOnTrack = state.selectedClipIds\n      .map((id) => hostTrack!.clips.find((c) => c.id === id))\n      .filter((c): c is AudioClip => Boolean(c));\n\n    if (selectedOnTrack.length === 2) {\n      const [a, b] = selectedOnTrack;\n      if (a && b) {\n        if (canPair(a, b)) {\n          left = a;\n          right = b;\n        } else if (canPair(b, a)) {\n          left = b;\n          right = a;\n        }\n      }\n    }\n\n    if (!left || !right) {\n      for (const other of hostTrack.clips) {\n        if (other.id === clip.id) continue;\n        if (canPair(clip, other)) {\n          left = clip;\n          right = other;\n          break;\n        }\n        if (canPair(other, clip)) {\n          left = other;\n          right = clip;\n          break;\n        }\n      }\n    }\n\n    if (!left || !right) {\n      get().addToast(getActiveMessages().audio.clipMenu.joinUnavailable, 'warning');\n      return;\n    }\n\n    const merged: AudioClip = {\n      ...left,\n      duration: left.duration + right.duration,\n      trimOut: right.trimOut,\n      fadeOut: right.fadeOut,\n      fadeOutCurve: right.fadeOutCurve,\n      crossfadeOut: right.crossfadeOut,\n      takeLane: 0,\n    };\n    const dropIds = new Set([left.id, right.id]);\n    const tracks = state.tracks.map((t) => {\n      if (t.id !== hostTrack!.id) return t;\n      return {\n        ...t,\n        clips: [...t.clips.filter((c) => !dropIds.has(c.id)), merged],\n      };\n    });\n    set({\n      tracks,\n      selectedClipIds: [merged.id],\n      projectDuration: recomputeDuration(tracks),\n      ...pushToHistory({ ...state, tracks }, 'Join clips'),\n    });\n    get().addToast(getActiveMessages().audio.clipMenu.joinDone, 'success');\n  },\n\n  duplicateClip: (clipId) =>\n    set((state) => {\n      const tracks = state.tracks.map((t) => {\n        const clip = t.clips.find((c) => c.id === clipId);\n        if (!clip) return t;\n        const dup: AudioClip = {\n          ...clip,\n          id: uid('clip'),\n          startTime: clip.startTime + clip.duration,\n          name: clip.name ? `${clip.name} copy` : undefined,\n        };\n        return { ...t, clips: [...t.clips, dup] };\n      });\n      return {\n        tracks,\n        projectDuration: recomputeDuration(tracks),\n        ...pushToHistory({ ...state, tracks }, 'Duplicate clip'),\n      };\n    }),\n\n  updateClip: (clipId, patch) =>\n    set((state) => {\n      const tracks = state.tracks.map((t) => ({\n        ...t,\n        clips: t.clips.map((c) => (c.id === clipId ? { ...c, ...patch } : c)),\n      }));\n      return {\n        tracks,\n        projectDuration: recomputeDuration(tracks),\n        ...pushToHistory({ ...state, tracks }, 'Update clip'),\n      };\n    }),\n\n  selectClip: (clipId, additive) =>\n    set((state) => {\n      if (!clipId) return { selectedClipIds: [] };\n      if (additive) {\n        const has = state.selectedClipIds.includes(clipId);\n        return {\n          selectedClipIds: has\n            ? state.selectedClipIds.filter((id) => id !== clipId)\n            : [...state.selectedClipIds, clipId],\n        };\n      }\n      return { selectedClipIds: [clipId] };\n    }),\n\n  selectClips: (clipIds, additive) =>\n    set((state) => {\n      if (!clipIds.length) {\n        return additive ? {} : { selectedClipIds: [] };\n      }\n      if (additive) {\n        const setIds = new Set(state.selectedClipIds);\n        for (const id of clipIds) setIds.add(id);\n        return { selectedClipIds: [...setIds] };\n      }\n      return { selectedClipIds: [...clipIds] };\n    }),\n\n  selectTrack: (trackId, additive) =>\n    set((state) => {\n      if (!trackId) return { selectedTrackIds: [] };\n      if (additive) {\n        const has = state.selectedTrackIds.includes(trackId);\n        return {\n          selectedTrackIds: has\n            ? state.selectedTrackIds.filter((id) => id !== trackId)\n            : [...state.selectedTrackIds, trackId],\n        };\n      }\n      return { selectedTrackIds: [trackId] };\n    }),\n\n  clearSelection: () => set({ selectedClipIds: [], selectedTrackIds: [] }),\n\n  copySelectedClips: () => {\n    const state = get();\n    const clips: AudioClip[] = [];\n    for (const t of state.tracks) {\n      for (const c of t.clips) {\n        if (state.selectedClipIds.includes(c.id)) clips.push({ ...c });\n      }\n    }\n    set({ clipboardClips: clips });\n    if (clips.length) get().addToast(getActiveMessages().store.toasts.audio.clipsCopied(clips.length), 'info');\n  },\n\n  cutSelectedClips: () => {\n    get().copySelectedClips();\n    if (get().selectedClipIds.length) get().removeSelectedClips();\n  },\n\n  nudgeClipTakeLane: (clipId, delta) =>\n    set((state) => {\n      const tracks = state.tracks.map((t) => ({\n        ...t,\n        clips: t.clips.map((c) => {\n          if (c.id !== clipId) return c;\n          const next = Math.max(0, Math.min(7, (c.takeLane || 0) + delta));\n          return next === (c.takeLane || 0) ? c : { ...c, takeLane: next };\n        }),\n      }));\n      return {\n        tracks,\n        ...pushToHistory({ ...state, tracks }, delta > 0 ? 'Bring clip forward' : 'Send clip backward'),\n      };\n    }),\n\n  pasteClips: () =>\n    set((state) => {\n      if (!state.clipboardClips.length) return {};\n      const offset = state.playheadTime;\n      const minStart = Math.min(...state.clipboardClips.map((c) => c.startTime));\n      const newIds: string[] = [];\n      const tracks = state.tracks.map((t) => {\n        const toPaste = state.clipboardClips\n          .filter((c) => c.trackId === t.id)\n          .map((c) => {\n            const id = uid('clip');\n            newIds.push(id);\n            return {\n              ...c,\n              id,\n              startTime: offset + (c.startTime - minStart),\n            };\n          });\n        // If clipboard tracks don't match, paste onto first selected / first track\n        return toPaste.length ? { ...t, clips: [...t.clips, ...toPaste] } : t;\n      });\n      let finalTracks = tracks;\n      if (newIds.length === 0 && state.clipboardClips.length) {\n        const targetId = state.selectedTrackIds[0] ?? state.tracks[0]?.id;\n        finalTracks = state.tracks.map((t) => {\n          if (t.id !== targetId) return t;\n          const pasted = state.clipboardClips.map((c) => {\n            const id = uid('clip');\n            newIds.push(id);\n            return {\n              ...c,\n              id,\n              trackId: t.id,\n              startTime: offset + (c.startTime - minStart),\n            };\n          });\n          return { ...t, clips: [...t.clips, ...pasted] };\n        });\n      }\n      return {\n        tracks: finalTracks,\n        selectedClipIds: newIds,\n        projectDuration: recomputeDuration(finalTracks),\n        ...pushToHistory({ ...state, tracks: finalTracks }, 'Paste clips'),\n      };\n    }),\n\n  trimSelectedToPlayhead: (edge) => {\n    const state = get();\n    const t = state.playheadTime;\n    const ids = new Set(state.selectedClipIds);\n    if (!ids.size) {\n      get().addToast(getActiveMessages().store.toasts.audio.selectClipFirst, 'warning');\n      return;\n    }\n    let changed = false;\n    const tracks = state.tracks.map((track) => ({\n      ...track,\n      clips: track.clips.map((c) => {\n        if (!ids.has(c.id)) return c;\n        const end = c.startTime + c.duration;\n        if (t <= c.startTime + 0.02 || t >= end - 0.02) return c;\n        if (edge === 'start') {\n          const delta = t - c.startTime;\n          changed = true;\n          const newDur = Math.max(0.05, c.duration - delta);\n          const newTrimIn = c.trimIn + delta * c.speed;\n          return {\n            ...c,\n            startTime: t,\n            duration: newDur,\n            trimIn: newTrimIn,\n            trimOut: newTrimIn + newDur * c.speed,\n          };\n        }\n        const newDur = Math.max(0.05, t - c.startTime);\n        changed = true;\n        return {\n          ...c,\n          duration: newDur,\n          trimOut: c.trimIn + newDur * c.speed,\n        };\n      }),\n    }));\n    if (!changed) {\n      get().addToast(getActiveMessages().store.toasts.audio.trimPlayheadMiss, 'warning');\n      return;\n    }\n    set({\n      tracks,\n      projectDuration: recomputeDuration(tracks),\n      ...pushToHistory({ ...state, tracks }, edge === 'start' ? 'Trim start' : 'Trim end'),\n    });\n  },\n\n  nudgeSelectedClips: (deltaSeconds) => get().moveSelectedClips(deltaSeconds),\n\n  setLoopToSelection: () => {\n    const state = get();\n    let min = Infinity;\n    let max = -Infinity;\n    for (const t of state.tracks) {\n      for (const c of t.clips) {\n        if (!state.selectedClipIds.includes(c.id)) continue;\n        min = Math.min(min, c.startTime);\n        max = Math.max(max, c.startTime + c.duration);\n      }\n    }\n    if (!Number.isFinite(min) || max <= min) return;\n    set({ loopEnabled: true, loopStart: min, loopEnd: max });\n  },\n\n  zoomToSelection: (viewportWidthPx) => {\n    const state = get();\n    let min = Infinity;\n    let max = -Infinity;\n    for (const t of state.tracks) {\n      for (const c of t.clips) {\n        if (!state.selectedClipIds.includes(c.id)) continue;\n        min = Math.min(min, c.startTime);\n        max = Math.max(max, c.startTime + c.duration);\n      }\n    }\n    if (!Number.isFinite(min) || max <= min) return;\n    const dur = max - min;\n    const pad = dur * 0.1;\n    const zoom = clampAudioZoom(viewportWidthPx / Math.max(0.1, dur + pad * 2));\n    set({\n      zoom,\n      scrollLeft: Math.max(0, (min - pad) * zoom),\n      playheadTime: min,\n    });\n  },\n\n  trimSelectedClips: (deltaTrimIn, deltaDuration) =>\n    set((state) => {\n      const ids = new Set(state.selectedClipIds);\n      if (!ids.size) return {};\n      const tracks = state.tracks.map((t) => ({\n        ...t,\n        clips: t.clips.map((c) => {\n          if (!ids.has(c.id)) return c;\n          const newDur = Math.max(0.05, c.duration + deltaDuration);\n          const newTrimIn = Math.max(0, c.trimIn + deltaTrimIn);\n          const newStart =\n            deltaTrimIn !== 0 ? Math.max(0, c.startTime + deltaTrimIn / Math.max(0.01, c.speed)) : c.startTime;\n          return {\n            ...c,\n            duration: newDur,\n            trimIn: newTrimIn,\n            trimOut: newTrimIn + newDur * c.speed,\n            startTime: newStart,\n          };\n        }),\n      }));\n      return {\n        tracks,\n        projectDuration: recomputeDuration(tracks),\n        ...pushToHistory({ ...state, tracks }, 'Trim selection'),\n      };\n    }),\n\n  setTrackSend: (trackId, busId, amount) => {\n    set((state) => {\n      const tracks = state.tracks.map((t) => {\n        if (t.id !== trackId) return t;\n        const sends = [...(t.sends || [])].filter((s) => s.busId !== busId);\n        if (amount > 0.001) sends.push({ busId, amount: Math.max(0, Math.min(1, amount)) });\n        return { ...t, sends };\n      });\n      return { tracks, ...pushToHistory({ ...state, tracks }, 'Set send') };\n    });\n    notifyEngine();\n  },\n\n  applySongStructureMarkers: () => {\n    const state = get();\n    const beat = state.bpm > 0 ? 60 / state.bpm : 0.5;\n    const bar = beat * (state.timeSignature[0] || 4);\n    const duration = Math.max(state.projectDuration, bar * 16);\n    const structure: Array<{ name: string; bars: number; color: string }> = [\n      { name: 'Intro', bars: 4, color: '#6C63FF' },\n      { name: 'Verso', bars: 8, color: '#00BFA5' },\n      { name: 'Estribillo', bars: 8, color: '#FF4081' },\n      { name: 'Verso', bars: 8, color: '#00BFA5' },\n      { name: 'Estribillo', bars: 8, color: '#FF4081' },\n      { name: 'Outro', bars: 4, color: '#FFD54F' },\n    ];\n    let t = 0;\n    const structureMarkers: AudioMarker[] = [];\n    const structureRegions: AudioRegion[] = [];\n    for (const s of structure) {\n      if (t >= duration) break;\n      const end = Math.min(duration, t + s.bars * bar);\n      structureMarkers.push({\n        id: uid('mk_ss'),\n        time: t,\n        name: s.name,\n        color: s.color,\n        source: 'song-structure',\n      });\n      structureRegions.push({\n        id: uid('reg_ss'),\n        startTime: t,\n        endTime: end,\n        name: s.name,\n        source: 'song-structure',\n      });\n      t = end;\n    }\n    const markers = [\n      ...state.markers.filter((m) => m.source !== 'song-structure'),\n      ...structureMarkers,\n    ];\n    const regions = [\n      ...state.regions.filter((r) => r.source !== 'song-structure'),\n      ...structureRegions,\n    ];\n    set((st) => ({\n      markers,\n      regions,\n      ...pushToHistory({ ...st, markers, regions }, 'Song structure'),\n    }));\n  },\n\n  clearSongStructureMarkers: () => {\n    const state = get();\n    const markers = state.markers.filter((m) => m.source !== 'song-structure');\n    const regions = state.regions.filter((r) => r.source !== 'song-structure');\n    if (\n      markers.length === state.markers.length &&\n      regions.length === state.regions.length\n    ) {\n      return;\n    }\n    set((st) => ({\n      markers,\n      regions,\n      ...pushToHistory({ ...st, markers, regions }, 'Clear song structure'),\n    }));\n  },\n\n  setTranscript: (words) => set({ transcript: words, selectedTranscriptIds: [] }),\n\n  selectTranscriptWords: (ids, additive) =>\n    set((state) => {\n      if (!additive) return { selectedTranscriptIds: ids };\n      const next = new Set(state.selectedTranscriptIds);\n      for (const id of ids) {\n        if (next.has(id)) next.delete(id);\n        else next.add(id);\n      }\n      return { selectedTranscriptIds: [...next] };\n    }),\n\n  deleteSelectedTranscriptWords: (opts) => {\n    const state = get();\n    const selected = new Set(state.selectedTranscriptIds);\n    if (!selected.size) return;\n    const ranges = wordsToRanges(state.transcript, selected);\n    if (!ranges.length) return;\n    const doRipple = opts?.ripple ?? state.editMode === 'ripple';\n\n    get().beginHistoryBatch('Cut transcript');\n    const ordered = [...ranges].sort((a, b) => b.start - a.start);\n    for (const range of ordered) {\n      const dur = range.end - range.start;\n      for (const track of get().tracks) {\n        if (track.type !== 'audio') continue;\n        for (const clip of [...track.clips]) {\n          const c0 = clip.startTime;\n          const c1 = clip.startTime + clip.duration;\n          if (c1 <= range.start || c0 >= range.end) continue;\n          if (range.start > c0 + 0.02 && range.start < c1 - 0.02) {\n            get().splitClip(clip.id, range.start);\n          }\n        }\n      }\n      // Also split at range.end so the middle can be removed cleanly\n      for (const track of get().tracks) {\n        if (track.type !== 'audio') continue;\n        for (const clip of [...track.clips]) {\n          const c0 = clip.startTime;\n          const c1 = clip.startTime + clip.duration;\n          if (range.end > c0 + 0.02 && range.end < c1 - 0.02) {\n            get().splitClip(clip.id, range.end);\n          }\n        }\n      }\n      for (const track of get().tracks) {\n        for (const clip of [...track.clips]) {\n          const c0 = clip.startTime;\n          const c1 = clip.startTime + clip.duration;\n          if (c0 >= range.start - 0.001 && c1 <= range.end + 0.001) {\n            get().removeClip(clip.id);\n          }\n        }\n      }\n      if (doRipple) {\n        for (const track of get().tracks) {\n          for (const clip of track.clips) {\n            if (clip.startTime >= range.end - 0.001) {\n              get().moveClip(clip.id, Math.max(0, clip.startTime - dur));\n            }\n          }\n        }\n      }\n    }\n    let transcript = removeWordsInRanges(state.transcript, ranges);\n    if (doRipple) {\n      for (const range of ordered) {\n        transcript = shiftWordsAfter(transcript, range.end, -(range.end - range.start));\n      }\n    }\n    set({ transcript, selectedTranscriptIds: [] });\n    get().endHistoryBatch();\n  },\n\n  removeFillerWords: () => {\n    const fillers = get().transcript.filter((w) => w.isFiller).map((w) => w.id);\n    if (!fillers.length) {\n      get().addToast(getActiveMessages().store.toasts.audio.noFillers, 'info');\n      return;\n    }\n    set({ selectedTranscriptIds: fillers });\n    get().deleteSelectedTranscriptWords();\n    get().addToast(getActiveMessages().store.toasts.audio.fillersRemoved(fillers.length), 'success');\n  },\n\n  applyCrossfadeBetweenSelected: (seconds, curve = 'equal-power') => {\n    const state = get();\n    const ids = state.selectedClipIds;\n    if (ids.length < 2) {\n      for (const id of ids) {\n        get().updateClip(id, {\n          crossfadeIn: seconds,\n          crossfadeOut: seconds,\n          crossfadeCurve: curve,\n          fadeIn: Math.max(seconds, 0),\n          fadeOut: Math.max(seconds, 0),\n        });\n      }\n      return;\n    }\n    const clips: AudioClip[] = [];\n    for (const t of state.tracks) {\n      for (const c of t.clips) {\n        if (ids.includes(c.id)) clips.push(c);\n      }\n    }\n    clips.sort((a, b) => a.startTime - b.startTime);\n    get().beginHistoryBatch('Crossfade');\n    for (let i = 0; i < clips.length - 1; i++) {\n      const a = clips[i]!;\n      const b = clips[i + 1]!;\n      const fade = Math.min(seconds, a.duration / 2, b.duration / 2);\n      const overlapStart = b.startTime - fade;\n      if (overlapStart > a.startTime) {\n        get().moveClip(b.id, Math.max(a.startTime + 0.01, overlapStart));\n      }\n      get().updateClip(a.id, {\n        crossfadeOut: fade,\n        crossfadeCurve: curve,\n        fadeOut: fade,\n      });\n      get().updateClip(b.id, {\n        crossfadeIn: fade,\n        crossfadeCurve: curve,\n        fadeIn: fade,\n      });\n    }\n    get().endHistoryBatch();\n  },\n\n  setActiveTake: (takeGroupId, takeLane) => {\n    set((state) => {\n      const tracks = state.tracks.map((t) => ({\n        ...t,\n        clips: t.clips.map((c) => {\n          if (c.takeGroupId !== takeGroupId) return c;\n          const active = c.takeLane === takeLane;\n          return { ...c, compActive: active, muted: !active };\n        }),\n      }));\n      return { tracks, ...pushToHistory({ ...state, tracks }, 'Comp take') };\n    });\n    notifyEngine();\n  },\n\n  compTakeInRegion: (takeGroupId, takeLane, start, end) => {\n    const a = Math.min(start, end);\n    const b = Math.max(start, end);\n    if (b - a < 0.05) {\n      get().setActiveTake(takeGroupId, takeLane);\n      return;\n    }\n    get().beginHistoryBatch('Comp take in region');\n    // Split all group clips at region boundaries so middle pieces can be toggled\n    for (const track of get().tracks) {\n      for (const clip of [...track.clips]) {\n        if (clip.takeGroupId !== takeGroupId) continue;\n        const c0 = clip.startTime;\n        const c1 = clip.startTime + clip.duration;\n        if (a > c0 + 0.02 && a < c1 - 0.02) get().splitClip(clip.id, a);\n      }\n    }\n    for (const track of get().tracks) {\n      for (const clip of [...track.clips]) {\n        if (clip.takeGroupId !== takeGroupId) continue;\n        const c0 = clip.startTime;\n        const c1 = clip.startTime + clip.duration;\n        if (b > c0 + 0.02 && b < c1 - 0.02) get().splitClip(clip.id, b);\n      }\n    }\n    set((state) => {\n      const tracks = state.tracks.map((t) => ({\n        ...t,\n        clips: t.clips.map((c) => {\n          if (c.takeGroupId !== takeGroupId) return c;\n          const c0 = c.startTime;\n          const c1 = c.startTime + c.duration;\n          const inside = c0 >= a - 0.001 && c1 <= b + 0.001;\n          if (!inside) return c;\n          const active = c.takeLane === takeLane;\n          return { ...c, compActive: active, muted: !active };\n        }),\n      }));\n      return { tracks };\n    });\n    get().endHistoryBatch();\n    notifyEngine();\n  },\n\n  setLufsMeter: (history, truePeakDb, integratedLufs) =>\n    set((s) => ({\n      lufsHistory: history,\n      truePeakDb,\n      integratedLufs: integratedLufs ?? s.integratedLufs,\n    })),\n\n  addEffect: (trackId, effect) => {\n    set((state) => {\n      const tracks = state.tracks.map((t) =>\n        t.id === trackId ? { ...t, effects: [...t.effects, effect] } : t\n      );\n      return { tracks, ...pushToHistory({ ...state, tracks }, `Add ${effect.type}`) };\n    });\n    notifyEngine();\n  },\n\n  updateEffect: (trackId, effectId, patch) => {\n    set((state) => {\n      const tracks = state.tracks.map((t) =>\n        t.id === trackId\n          ? {\n              ...t,\n              effects: t.effects.map((e) => (e.id === effectId ? { ...e, ...patch } : e)),\n            }\n          : t\n      );\n      return { tracks, ...pushToHistory({ ...state, tracks }, 'Update effect') };\n    });\n    notifyEngine();\n  },\n\n  removeEffect: (trackId, effectId) => {\n    set((state) => {\n      const tracks = state.tracks.map((t) =>\n        t.id === trackId\n          ? { ...t, effects: t.effects.filter((e) => e.id !== effectId) }\n          : t\n      );\n      return { tracks, ...pushToHistory({ ...state, tracks }, 'Remove effect') };\n    });\n    notifyEngine();\n  },\n\n  reorderEffects: (trackId, from, to) =>\n    set((state) => {\n      const tracks = state.tracks.map((t) => {\n        if (t.id !== trackId) return t;\n        const effects = [...t.effects];\n        const [item] = effects.splice(from, 1);\n        if (!item) return t;\n        effects.splice(to, 0, item);\n        return { ...t, effects: effects.map((e, i) => ({ ...e, order: i })) };\n      });\n      return { tracks, ...pushToHistory({ ...state, tracks }, 'Reorder effects') };\n    }),\n\n  setAutomationLane: (trackId, lane) =>\n    set((state) => {\n      const tracks = state.tracks.map((t) => {\n        if (t.id !== trackId) return t;\n        const others = t.automation.filter((a) => a.property !== lane.property);\n        return { ...t, automation: [...others, lane] };\n      });\n      return { tracks, ...pushToHistory({ ...state, tracks }, 'Automation') };\n    }),\n\n  addMarker: (marker) =>\n    set((state) => {\n      const markers = [...state.markers, marker];\n      return { markers, ...pushToHistory({ ...state, markers }, 'Add marker') };\n    }),\n\n  removeMarker: (markerId) =>\n    set((state) => {\n      const markers = state.markers.filter((m) => m.id !== markerId);\n      return { markers, ...pushToHistory({ ...state, markers }, 'Remove marker') };\n    }),\n\n  addRegion: (region) =>\n    set((state) => {\n      const regions = [...state.regions, region];\n      return { regions, ...pushToHistory({ ...state, regions }, 'Add region') };\n    }),\n\n  removeRegion: (regionId) =>\n    set((state) => {\n      const regions = state.regions.filter((r) => r.id !== regionId);\n      return { regions, ...pushToHistory({ ...state, regions }, 'Remove region') };\n    }),\n\n  undo: () =>\n    set((state) => {\n      if (state.historyIndex <= 0) return {};\n      const nextIndex = state.historyIndex - 1;\n      const snapshot = state.history[nextIndex];\n      if (!snapshot) return {};\n      return {\n        tracks: deepCloneTracks(snapshot.tracks),\n        markers: JSON.parse(JSON.stringify(snapshot.markers)) as AudioMarker[],\n        regions: JSON.parse(JSON.stringify(snapshot.regions)) as AudioRegion[],\n        bpm: snapshot.bpm,\n        historyIndex: nextIndex,\n        selectedClipIds: [],\n        projectDuration: recomputeDuration(snapshot.tracks),\n      };\n    }),\n\n  redo: () =>\n    set((state) => {\n      if (state.historyIndex >= state.history.length - 1) return {};\n      const nextIndex = state.historyIndex + 1;\n      const snapshot = state.history[nextIndex];\n      if (!snapshot) return {};\n      return {\n        tracks: deepCloneTracks(snapshot.tracks),\n        markers: JSON.parse(JSON.stringify(snapshot.markers)) as AudioMarker[],\n        regions: JSON.parse(JSON.stringify(snapshot.regions)) as AudioRegion[],\n        bpm: snapshot.bpm,\n        historyIndex: nextIndex,\n        selectedClipIds: [],\n        projectDuration: recomputeDuration(snapshot.tracks),\n      };\n    }),\n\n  beginHistoryBatch: (description) => {\n    _batchDepth += 1;\n    if (_batchDepth === 1) _batchDescription = description;\n  },\n\n  endHistoryBatch: () => {\n    if (_batchDepth === 0) return;\n    _batchDepth -= 1;\n    if (_batchDepth === 0) {\n      const state = get();\n      const hist = pushToHistory(state, _batchDescription || 'Batch');\n      // Force push even though batch flag is cleared\n      set({ ...hist });\n      _batchDescription = '';\n    }\n  },\n\n  addToast: (message, type = 'info') => {\n    const id = uid('toast');\n    const safe =\n      type === 'error'\n        ? sanitizeUserFacingMessage(message, { context: 'toast:audio' })\n        : message;\n    set((state) => ({ toasts: [...state.toasts, { id, message: safe, type }] }));\n    setTimeout(() => get().removeToast(id), 4000);\n  },\n\n  removeToast: (id) =>\n    set((state) => ({ toasts: state.toasts.filter((t) => t.id !== id) })),\n\n  getProjectSnapshot: () => {\n    const s = get();\n    return {\n      name: s.audioProjects.find((p) => p.id === s.activeAudioProjectId)?.name,\n      bpm: s.bpm,\n      sampleRate: s.sampleRate,\n      playheadTime: s.playheadTime,\n      projectDuration: s.projectDuration,\n      selectedClipIds: s.selectedClipIds,\n      selectedTrackIds: s.selectedTrackIds,\n      tracks: s.tracks.map((t) => ({\n        id: t.id,\n        name: t.name,\n        type: t.type,\n        muted: t.muted,\n        solo: t.solo,\n        volumeDb: t.volumeDb,\n        pan: t.pan,\n        effects: t.effects.map((e) => ({ type: e.type, enabled: e.enabled })),\n        clipCount: t.clips.length,\n        clips: t.clips.map((c) => ({\n          id: c.id,\n          name: c.name,\n          startTime: c.startTime,\n          duration: c.duration,\n          gain: c.gain,\n        })),\n      })),\n    };\n  },\n}));\n\naudioPersistence = createProjectPersistence({\n  mode: 'audio',\n  localDebounceMs: 400,\n  cloudDebounceMs: 3000,\n  saveLocal: async () => {\n    await useAudioStore.getState().saveAudioProject();\n  },\n  saveCloud: async () => useAudioStore.getState().autoSaveAudioProjectToCloud(),\n});\nregisterProjectPersistence(audioPersistence);\n\nexport function flushAudioPersistence(): Promise<void> {\n  return audioPersistence.flush();\n}\n\nexport function createAudioClip(partial: Partial<AudioClip> & Pick<AudioClip, 'trackId' | 'assetId' | 'duration'>): AudioClip {\n  return {\n    id: uid('clip'),\n    startTime: 0,\n    trimIn: 0,\n    trimOut: partial.duration,\n    speed: 1,\n    pitch: 0,\n    gain: 1,\n    muted: false,\n    inverted: false,\n    fadeIn: 0,\n    fadeOut: 0,\n    fadeInCurve: 'linear',\n    fadeOutCurve: 'linear',\n    crossfadeIn: 0,\n    crossfadeOut: 0,\n    crossfadeCurve: 'equal-power',\n    pitchSeparate: false,\n    takeLane: 0,\n    compActive: true,\n    ...partial,\n  };\n}\n", "/**\n * Local readability / writing metrics (no AI). Spanish-friendly Flesch approx.\n */\n\nexport interface ReadabilityMetrics {\n  words: number;\n  characters: number;\n  charactersNoSpaces: number;\n  sentences: number;\n  paragraphs: number;\n  avgSentenceLength: number;\n  flesch: number;\n  passiveApprox: number;\n  readingTimeMinutes: number;\n}\n\nexport function computeReadability(text: string): ReadabilityMetrics {\n  const trimmed = text.trim();\n  if (!trimmed) {\n    return {\n      words: 0,\n      characters: 0,\n      charactersNoSpaces: 0,\n      sentences: 0,\n      paragraphs: 0,\n      avgSentenceLength: 0,\n      flesch: 100,\n      passiveApprox: 0,\n      readingTimeMinutes: 0,\n    };\n  }\n\n  const characters = trimmed.length;\n  const charactersNoSpaces = trimmed.replace(/\\s/g, '').length;\n  const words = trimmed.split(/\\s+/).filter(Boolean).length;\n  const sentences = Math.max(1, (trimmed.match(/[.!?\u2026]+/g) || []).length);\n  const paragraphs = Math.max(1, trimmed.split(/\\n\\s*\\n/).filter((p) => p.trim()).length);\n  const avgSentenceLength = words / sentences;\n\n  // Approx syllable count for Spanish/English mix\n  const syllables = countSyllablesApprox(trimmed);\n  // Flesch Reading Ease adapted\n  const flesch = Math.max(\n    0,\n    Math.min(100, 206.835 - 1.015 * avgSentenceLength - 84.6 * (syllables / Math.max(1, words)))\n  );\n\n  const passiveHits = (trimmed.match(/\\b(fue|fueron|era|eran|sido|siendo|was|were|been|being)\\b/gi) || [])\n    .length;\n  const passiveApprox = Math.min(100, (passiveHits / Math.max(1, sentences)) * 100);\n\n  return {\n    words,\n    characters,\n    charactersNoSpaces,\n    sentences,\n    paragraphs,\n    avgSentenceLength: Math.round(avgSentenceLength * 10) / 10,\n    flesch: Math.round(flesch),\n    passiveApprox: Math.round(passiveApprox),\n    readingTimeMinutes: Math.max(1, Math.ceil(words / 200)),\n  };\n}\n\nfunction countSyllablesApprox(text: string): number {\n  const words = text.toLowerCase().match(/[a-z\u00E1\u00E9\u00ED\u00F3\u00FA\u00FC\u00F1]+/gi) || [];\n  let total = 0;\n  for (const w of words) {\n    const groups = w.match(/[aeiou\u00E1\u00E9\u00ED\u00F3\u00FA\u00FC]+/g);\n    total += groups ? groups.length : 1;\n  }\n  return Math.max(1, total);\n}\n\n/** Soft character limits by channel for MetricsBar. */\nexport const CHANNEL_LIMITS: Record<string, number> = {\n  x: 280,\n  instagram: 2200,\n  linkedin: 3000,\n  email: 90, // subject-ish when used for subject lines\n  youtube: 5000,\n  ad: 150,\n  blog: 0,\n};\n", "/**\n * Derive document outline from TipTap / ProseMirror JSON.\n */\n\nimport type { JSONContent } from '@tiptap/core';\n\nexport interface OutlineItem {\n  id: string;\n  level: 1 | 2 | 3 | 4 | 5 | 6;\n  text: string;\n  /** Index among heading nodes for scroll/nav. */\n  index: number;\n}\n\nfunction textOf(node: JSONContent): string {\n  if (node.type === 'text') return node.text || '';\n  return (node.content || []).map(textOf).join('');\n}\n\nexport function extractOutline(doc: JSONContent): OutlineItem[] {\n  const items: OutlineItem[] = [];\n  let index = 0;\n  const walk = (node: JSONContent) => {\n    if (node.type === 'heading') {\n      const level = Math.min(6, Math.max(1, Number(node.attrs?.level) || 1)) as OutlineItem['level'];\n      const text = textOf(node).trim() || `Seccion ${index + 1}`;\n      items.push({\n        id: `outline_${index}`,\n        level,\n        text,\n        index,\n      });\n      index += 1;\n    }\n    if (node.content) node.content.forEach(walk);\n  };\n  walk(doc);\n  return items;\n}\n", "/**\n * Local clarity / jargon / inclusive-language heuristics (no AI).\n * Inclusive tip ids are resolved via i18n at display time.\n */\n\nexport type InclusiveTipId =\n  | 'users'\n  | 'genericMasculine'\n  | 'guys'\n  | 'ableist'\n  | 'mentalHealth';\n\nexport interface ClarityExtras {\n  clarityScore: number;\n  jargonHits: string[];\n  /** Stable tip ids \u2014 translate with `text.metrics.inclusiveTips`. */\n  inclusiveFlags: InclusiveTipId[];\n  forbiddenHits: string[];\n  preferredMissing: string[];\n}\n\nconst JARGON_ES_EN = [\n  'sinergia',\n  'paradigma',\n  'disruptivo',\n  'leverage',\n  'synergy',\n  'bandwidth',\n  'holistico',\n  'hol\u00EDstico',\n  'ecosistema',\n  'value proposition',\n  'low-hanging fruit',\n  'circle back',\n  'deep dive',\n];\n\nconst INCLUSIVE_FLAGS: { pattern: RegExp; id: InclusiveTipId }[] = [\n  { pattern: /\\blos usuarios\\b/gi, id: 'users' },\n  { pattern: /\\bel hombre\\b/gi, id: 'genericMasculine' },\n  { pattern: /\\bguys\\b/gi, id: 'guys' },\n  { pattern: /\\bcripple\\b/gi, id: 'ableist' },\n  { pattern: /\\bmadman\\b/gi, id: 'mentalHealth' },\n];\n\nexport function computeClarityExtras(\n  text: string,\n  forbiddenTerms: string[] = [],\n  preferredTerms: string[] = []\n): ClarityExtras {\n  const lower = text.toLowerCase();\n  const words = text.trim() ? text.trim().split(/\\s+/).length : 0;\n  const sentences = Math.max(1, (text.match(/[.!?\u2026]+/g) || []).length);\n  const avg = words / sentences;\n\n  let clarityScore = 80;\n  if (avg > 28) clarityScore -= 20;\n  else if (avg > 22) clarityScore -= 10;\n  else if (avg < 8 && words > 40) clarityScore -= 5;\n\n  const jargonHits: string[] = [];\n  for (const j of JARGON_ES_EN) {\n    if (lower.includes(j.toLowerCase())) jargonHits.push(j);\n  }\n  clarityScore -= Math.min(25, jargonHits.length * 4);\n\n  const inclusiveFlags: InclusiveTipId[] = [];\n  for (const f of INCLUSIVE_FLAGS) {\n    if (f.pattern.test(text)) inclusiveFlags.push(f.id);\n    f.pattern.lastIndex = 0;\n  }\n\n  const forbiddenHits = forbiddenTerms.filter(\n    (t) => t && lower.includes(t.toLowerCase())\n  );\n  clarityScore -= Math.min(30, forbiddenHits.length * 10);\n\n  const preferredMissing = preferredTerms.filter(\n    (t) => t && !lower.includes(t.toLowerCase())\n  );\n\n  return {\n    clarityScore: Math.max(0, Math.min(100, Math.round(clarityScore))),\n    jargonHits,\n    inclusiveFlags,\n    forbiddenHits,\n    preferredMissing,\n  };\n}\n", "/**\n * Zustand store for the Text Content Studio mode.\n * Multi-project + IDB autosave + named snapshots (TipTap owns keystroke undo).\n */\n\nimport { create } from 'zustand';\nimport { openUploadsDB } from './useEditorStore';\nimport type { JSONContent } from '@tiptap/core';\nimport { computeReadability, type ReadabilityMetrics } from '../lib/text/readability';\nimport { extractOutline, type OutlineItem } from '../lib/text/outline';\nimport {\n  computeClarityExtras,\n  type ClarityExtras,\n} from '../lib/text/clarity';\nimport { getActiveMessages } from '../i18n';\nimport {\n  createProjectPersistence,\n  registerProjectPersistence,\n  type ProjectPersistenceController,\n} from '../lib/persistence/projectPersistence';\nimport { sanitizeUserFacingMessage } from '../utils/userFacingError';\nimport {\n  markCloudAutosaveAnnounce,\n  withCloudAutosaveToast,\n} from '../utils/cloudAutosaveToast';\n\nexport type TextDocType =\n  | 'blank'\n  | 'blog'\n  | 'script'\n  | 'newsletter'\n  | 'landing'\n  | 'social';\n\nexport type TextPageSizeId =\n  | 'letter'\n  | 'legal'\n  | 'a4'\n  | 'a5';\n\nexport interface TextPageSize {\n  id: TextPageSizeId;\n  name: string;\n  /** Width in millimeters. */\n  widthMm: number;\n  /** Height in millimeters. */\n  heightMm: number;\n  /** Default margins in millimeters. */\n  marginMm: { top: number; right: number; bottom: number; left: number };\n}\n\nexport const TEXT_PAGE_SIZES: ReadonlyArray<TextPageSize> = [\n  {\n    id: 'letter',\n    name: 'Carta (Letter)',\n    widthMm: 215.9,\n    heightMm: 279.4,\n    marginMm: { top: 25.4, right: 25.4, bottom: 25.4, left: 25.4 },\n  },\n  {\n    id: 'legal',\n    name: 'Oficio (Legal)',\n    widthMm: 215.9,\n    heightMm: 355.6,\n    marginMm: { top: 25.4, right: 25.4, bottom: 25.4, left: 25.4 },\n  },\n  {\n    id: 'a4',\n    name: 'A4',\n    widthMm: 210,\n    heightMm: 297,\n    marginMm: { top: 25.4, right: 25.4, bottom: 25.4, left: 25.4 },\n  },\n  {\n    id: 'a5',\n    name: 'A5',\n    widthMm: 148,\n    heightMm: 210,\n    marginMm: { top: 20, right: 20, bottom: 20, left: 20 },\n  },\n];\n\nexport const DEFAULT_PAGE_SIZE: TextPageSizeId = 'a4';\n\nexport type TextTone =\n  | 'neutral'\n  | 'formal'\n  | 'casual'\n  | 'persuasive'\n  | 'technical'\n  | 'friendly';\n\nexport type TextChannel =\n  | 'blog'\n  | 'instagram'\n  | 'linkedin'\n  | 'x'\n  | 'email'\n  | 'ad'\n  | 'youtube';\n\nexport type TextWorkflowStatus = 'draft' | 'review' | 'approved' | 'published';\n\nexport type TextSuggestionKind =\n  | 'rewrite'\n  | 'tone'\n  | 'tighten'\n  | 'expand'\n  | 'elevate'\n  | 'localize'\n  | 'brand'\n  | 'claim'\n  | 'other';\n\nexport type TextClaimStatus = 'unverified' | 'needs_citation' | 'ok' | 'flagged';\n\nexport interface TextSuggestion {\n  id: string;\n  kind: TextSuggestionKind;\n  original: string;\n  replacement: string;\n  rationale?: string;\n  status: 'pending' | 'accepted' | 'rejected';\n  createdAt: number;\n}\n\nexport interface TextVariant {\n  id: string;\n  channel: TextChannel;\n  title: string;\n  content: string;\n  stale: boolean;\n  updatedAt: number;\n}\n\nexport interface TextSnapshot {\n  id: string;\n  name: string;\n  doc: JSONContent;\n  createdAt: number;\n}\n\nexport interface BrandGlossaryEntry {\n  term: string;\n  preferred?: string;\n  definition?: string;\n}\n\nexport interface BrandVoiceProfile {\n  tone: TextTone;\n  preferredTerms: string[];\n  forbiddenTerms: string[];\n  approvedCtas: string[];\n  legalDisclaimers: string[];\n  channelTones: Partial<Record<TextChannel, TextTone>>;\n  glossary: BrandGlossaryEntry[];\n  /** Voice-match samples (local stand-in for host brand.textBank). */\n  textBankSamples: string[];\n  score: number | null;\n  notes: string[];\n}\n\nexport interface TextSeoMeta {\n  title: string;\n  description: string;\n  slug: string;\n  keywords: string[];\n  focusKeyword?: string;\n}\n\nexport interface TextComment {\n  id: string;\n  note: string;\n  resolved: boolean;\n  createdAt: number;\n  quote?: string;\n  /** True when a TipTap commentMark was applied in the document. */\n  anchored?: boolean;\n}\n\nexport interface TextClaim {\n  id: string;\n  text: string;\n  status: TextClaimStatus;\n  note?: string;\n  createdAt: number;\n}\n\nexport type TextToast = {\n  id: string;\n  message: string;\n  type: 'success' | 'error' | 'info' | 'warning';\n};\n\nexport type TextRightTab =\n  | 'ai'\n  | 'chat'\n  | 'suggestions'\n  | 'variants'\n  | 'comments'\n  | 'claims';\n\nexport interface TextProject {\n  id: string;\n  name: string;\n  docType: TextDocType;\n  pageSize: TextPageSizeId;\n  customPageSizeMm?: { width: number; height: number; margin: number };\n  customMarginsMm?: { top: number; right: number; bottom: number; left: number };\n  orientation: 'portrait' | 'landscape';\n  columns: number;\n  language: string;\n  tone: TextTone;\n  targetChannel: TextChannel;\n  doc: JSONContent;\n  outline: OutlineItem[];\n  variants: TextVariant[];\n  suggestions: TextSuggestion[];\n  snapshots: TextSnapshot[];\n  brandVoice: BrandVoiceProfile;\n  metrics: ReadabilityMetrics;\n  clarity: ClarityExtras;\n  workflowStatus: TextWorkflowStatus;\n  seoMeta: TextSeoMeta;\n  comments: TextComment[];\n  claims: TextClaim[];\n  enforceComplianceOnExport: boolean;\n  createdAt: number;\n  updatedAt: number;\n  /** Last cloud editable id \u2014 used to replace on silent autosave. */\n  cloudEditableId?: number;\n}\n\nexport const EMPTY_DOC: JSONContent = {\n  type: 'doc',\n  content: [{ type: 'paragraph' }],\n};\n\nexport function emptySeoMeta(): TextSeoMeta {\n  return { title: '', description: '', slug: '', keywords: [], focusKeyword: '' };\n}\n\nfunction uid(prefix: string): string {\n  return `${prefix}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction defaultBrandVoice(tone: TextTone): BrandVoiceProfile {\n  return {\n    tone,\n    preferredTerms: [],\n    forbiddenTerms: [],\n    approvedCtas: [],\n    legalDisclaimers: [],\n    channelTones: {},\n    glossary: [],\n    textBankSamples: [],\n    score: null,\n    notes: [],\n  };\n}\n\nfunction normalizeBrandVoice(\n  raw: Partial<BrandVoiceProfile> | undefined,\n  tone: TextTone\n): BrandVoiceProfile {\n  const base = defaultBrandVoice(tone);\n  if (!raw) return base;\n  return {\n    ...base,\n    ...raw,\n    preferredTerms: raw.preferredTerms ?? base.preferredTerms,\n    forbiddenTerms: raw.forbiddenTerms ?? base.forbiddenTerms,\n    approvedCtas: raw.approvedCtas ?? base.approvedCtas,\n    legalDisclaimers: raw.legalDisclaimers ?? base.legalDisclaimers,\n    channelTones: raw.channelTones ?? base.channelTones,\n    glossary: raw.glossary ?? base.glossary,\n    textBankSamples: raw.textBankSamples ?? base.textBankSamples,\n    notes: raw.notes ?? base.notes,\n    tone: raw.tone ?? tone,\n  };\n}\n\nfunction templateDoc(docType: TextDocType, name: string): JSONContent {\n  switch (docType) {\n    case 'blog':\n      return {\n        type: 'doc',\n        content: [\n          { type: 'heading', attrs: { level: 1 }, content: [{ type: 'text', text: name }] },\n          {\n            type: 'paragraph',\n            content: [\n              {\n                type: 'text',\n                text: 'Escribe la introduccion. Usa el panel de IA para expandir cada seccion.',\n              },\n            ],\n          },\n          {\n            type: 'heading',\n            attrs: { level: 2 },\n            content: [{ type: 'text', text: 'Contexto' }],\n          },\n          { type: 'paragraph' },\n          {\n            type: 'heading',\n            attrs: { level: 2 },\n            content: [{ type: 'text', text: 'Puntos clave' }],\n          },\n          { type: 'paragraph' },\n          {\n            type: 'heading',\n            attrs: { level: 2 },\n            content: [{ type: 'text', text: 'Conclusion' }],\n          },\n          { type: 'paragraph' },\n        ],\n      };\n    case 'script':\n      return {\n        type: 'doc',\n        content: [\n          { type: 'heading', attrs: { level: 1 }, content: [{ type: 'text', text: name }] },\n          {\n            type: 'heading',\n            attrs: { level: 2 },\n            content: [{ type: 'text', text: 'Escena 1' }],\n          },\n          {\n            type: 'paragraph',\n            content: [{ type: 'text', text: 'VO: ' }],\n          },\n          {\n            type: 'heading',\n            attrs: { level: 2 },\n            content: [{ type: 'text', text: 'Escena 2' }],\n          },\n          { type: 'paragraph' },\n        ],\n      };\n    case 'newsletter':\n      return {\n        type: 'doc',\n        content: [\n          { type: 'heading', attrs: { level: 1 }, content: [{ type: 'text', text: name }] },\n          {\n            type: 'paragraph',\n            content: [{ type: 'text', text: 'Asunto: ' }],\n          },\n          {\n            type: 'heading',\n            attrs: { level: 2 },\n            content: [{ type: 'text', text: 'Apertura' }],\n          },\n          { type: 'paragraph' },\n          {\n            type: 'heading',\n            attrs: { level: 2 },\n            content: [{ type: 'text', text: 'CTA' }],\n          },\n          { type: 'paragraph' },\n        ],\n      };\n    case 'landing':\n      return {\n        type: 'doc',\n        content: [\n          { type: 'heading', attrs: { level: 1 }, content: [{ type: 'text', text: name }] },\n          {\n            type: 'paragraph',\n            content: [{ type: 'text', text: 'Headline secundario / subhead' }],\n          },\n          {\n            type: 'heading',\n            attrs: { level: 2 },\n            content: [{ type: 'text', text: 'Beneficios' }],\n          },\n          {\n            type: 'bulletList',\n            content: [\n              {\n                type: 'listItem',\n                content: [{ type: 'paragraph', content: [{ type: 'text', text: 'Beneficio 1' }] }],\n              },\n            ],\n          },\n          {\n            type: 'heading',\n            attrs: { level: 2 },\n            content: [{ type: 'text', text: 'CTA' }],\n          },\n          { type: 'paragraph' },\n        ],\n      };\n    case 'social':\n      return {\n        type: 'doc',\n        content: [\n          {\n            type: 'paragraph',\n            content: [\n              {\n                type: 'text',\n                text: 'Borrador de post. Genera variantes por canal desde el panel de IA.',\n              },\n            ],\n          },\n        ],\n      };\n    default:\n      return {\n        type: 'doc',\n        content: [\n          { type: 'heading', attrs: { level: 1 }, content: [{ type: 'text', text: name }] },\n          { type: 'paragraph' },\n        ],\n      };\n  }\n}\n\nfunction docToPlainText(doc: JSONContent): string {\n  const parts: string[] = [];\n  const walk = (node: JSONContent) => {\n    if (node.type === 'text' && node.text) parts.push(node.text);\n    if (node.content) node.content.forEach(walk);\n  };\n  walk(doc);\n  return parts.join(' ');\n}\n\nfunction metricsBundle(doc: JSONContent, brand: BrandVoiceProfile) {\n  const plain = docToPlainText(doc);\n  return {\n    metrics: computeReadability(plain),\n    clarity: computeClarityExtras(plain, brand.forbiddenTerms, brand.preferredTerms),\n  };\n}\n\ninterface TextState {\n  textProjects: TextProject[];\n  activeTextProjectId: string | null;\n  isTextSetupOpen: boolean;\n  isTextProjectLoading: boolean;\n  exportModalOpen: boolean;\n  toasts: TextToast[];\n  rightTab: TextRightTab;\n  agentPlanMode: boolean;\n\n  doc: JSONContent;\n  outline: OutlineItem[];\n  variants: TextVariant[];\n  suggestions: TextSuggestion[];\n  snapshots: TextSnapshot[];\n  brandVoice: BrandVoiceProfile;\n  metrics: ReadabilityMetrics;\n  clarity: ClarityExtras;\n  docType: TextDocType;\n  language: string;\n  tone: TextTone;\n  targetChannel: TextChannel;\n  projectName: string;\n  workflowStatus: TextWorkflowStatus;\n  seoMeta: TextSeoMeta;\n  comments: TextComment[];\n  claims: TextClaim[];\n  enforceComplianceOnExport: boolean;\n\n  setIsTextSetupOpen: (open: boolean) => void;\n  setExportModalOpen: (open: boolean) => void;\n  setRightTab: (tab: TextRightTab) => void;\n  setAgentPlanMode: (on: boolean) => void;\n  createTextProject: (\n    name: string,\n    opts?: {\n      docType?: TextDocType;\n      pageSize?: TextPageSizeId;\n      orientation?: 'portrait' | 'landscape';\n      columns?: number;\n      language?: string;\n      tone?: TextTone;\n      targetChannel?: TextChannel;\n    }\n  ) => void;\n  closeTextProject: (projectId: string) => void;\n  switchTextProject: (projectId: string) => void;\n  saveTextProject: () => Promise<void>;\n  loadTextProject: () => Promise<void>;\n  autoSaveTextProjectToCloud: () => Promise<boolean>;\n  importTextProject: (\n    data: Partial<TextProject> & { doc?: JSONContent },\n    filename?: string,\n    opts?: { cloudEditableId?: number },\n  ) => void;\n\n  setDoc: (doc: JSONContent) => void;\n  setDocFromEditor: (doc: JSONContent) => void;\n  setTone: (tone: TextTone) => void;\n  setTargetChannel: (channel: TextChannel) => void;\n  setProjectName: (name: string) => void;\n  setProjectPageSize: (pageSize: TextPageSizeId) => void;\n  setProjectOrientation: (orientation: 'portrait' | 'landscape') => void;\n  setProjectMargins: (margins: { top: number; right: number; bottom: number; left: number }) => void;\n  setWorkflowStatus: (status: TextWorkflowStatus) => void;\n  setSeoMeta: (patch: Partial<TextSeoMeta>) => void;\n  setEnforceComplianceOnExport: (on: boolean) => void;\n\n  addSuggestion: (s: Omit<TextSuggestion, 'id' | 'status' | 'createdAt'>) => string;\n  acceptSuggestion: (id: string) => void;\n  rejectSuggestion: (id: string) => void;\n  acceptAllSuggestions: () => void;\n  rejectAllSuggestions: () => void;\n  clearSuggestions: () => void;\n\n  setVariants: (variants: TextVariant[]) => void;\n  markVariantsStale: () => void;\n  updateVariant: (id: string, patch: Partial<TextVariant>) => void;\n\n  createNamedSnapshot: (name?: string) => void;\n  restoreSnapshot: (id: string) => void;\n  restoreSnapshotSection: (id: string, headingText: string) => void;\n  removeSnapshot: (id: string) => void;\n  /** Plain text of a named snapshot (for selection restore in UI). */\n  getSnapshotPlainText: (id: string) => string | null;\n\n  setBrandVoice: (patch: Partial<BrandVoiceProfile>) => void;\n\n  addComment: (note: string, quote?: string, anchored?: boolean) => string;\n  resolveComment: (id: string, resolved?: boolean) => void;\n  removeComment: (id: string) => void;\n\n  addClaim: (text: string, status?: TextClaimStatus, note?: string) => string;\n  updateClaim: (id: string, patch: Partial<TextClaim>) => void;\n  removeClaim: (id: string) => void;\n  setClaims: (claims: TextClaim[]) => void;\n\n  recomputeMetrics: () => void;\n  canExport: () => { ok: boolean; blockers: string[] };\n\n  addToast: (message: string, type?: TextToast['type']) => void;\n  removeToast: (id: string) => void;\n\n  getProjectSnapshot: () => Record<string, unknown>;\n}\n\nlet textPersistence!: ProjectPersistenceController;\nlet _staleTimer: ReturnType<typeof setTimeout> | null = null;\n\nfunction syncActiveIntoProjects(state: TextState): TextProject[] {\n  if (!state.activeTextProjectId) return state.textProjects;\n  return state.textProjects.map((p) =>\n    p.id === state.activeTextProjectId\n      ? {\n          ...p,\n          name: state.projectName || p.name,\n          doc: state.doc,\n          outline: state.outline,\n          variants: state.variants,\n          suggestions: state.suggestions,\n          snapshots: state.snapshots,\n          brandVoice: state.brandVoice,\n          metrics: state.metrics,\n          clarity: state.clarity,\n          docType: state.docType,\n          language: state.language,\n          tone: state.tone,\n          targetChannel: state.targetChannel,\n          workflowStatus: state.workflowStatus,\n          seoMeta: state.seoMeta,\n          comments: state.comments,\n          claims: state.claims,\n          enforceComplianceOnExport: state.enforceComplianceOnExport,\n          updatedAt: Date.now(),\n        }\n      : p\n  );\n}\n\nfunction applyProjectToRoot(project: TextProject) {\n  return {\n    doc: project.doc,\n    outline: project.outline,\n    variants: project.variants,\n    suggestions: project.suggestions,\n    snapshots: project.snapshots,\n    brandVoice: project.brandVoice,\n    metrics: project.metrics,\n    clarity: project.clarity ?? computeClarityExtras('', []),\n    docType: project.docType,\n    language: project.language,\n    tone: project.tone,\n    targetChannel: project.targetChannel,\n    projectName: project.name,\n    workflowStatus: project.workflowStatus ?? 'draft',\n    seoMeta: project.seoMeta ?? emptySeoMeta(),\n    comments: project.comments ?? [],\n    claims: project.claims ?? [],\n    enforceComplianceOnExport: project.enforceComplianceOnExport ?? false,\n  };\n}\n\nfunction scheduleAutosave() {\n  markCloudAutosaveAnnounce('text');\n  textPersistence.scheduleAfterChange();\n}\n\nfunction scheduleMarkStale() {\n  if (_staleTimer) clearTimeout(_staleTimer);\n  _staleTimer = setTimeout(() => {\n    useTextStore.getState().markVariantsStale();\n  }, 800);\n}\n\nfunction extractSectionByHeading(doc: JSONContent, headingText: string): JSONContent[] {\n  const content = doc.content || [];\n  const out: JSONContent[] = [];\n  let capturing = false;\n  for (const node of content) {\n    if (node.type === 'heading') {\n      const text =\n        node.content?.map((c) => c.text || '').join('') || '';\n      if (capturing) break;\n      if (text.trim().toLowerCase() === headingText.trim().toLowerCase()) {\n        capturing = true;\n        out.push(node);\n        continue;\n      }\n    } else if (capturing) {\n      out.push(node);\n    }\n  }\n  return out;\n}\n\nfunction replaceSectionByHeading(\n  doc: JSONContent,\n  headingText: string,\n  sectionNodes: JSONContent[]\n): JSONContent {\n  const content = doc.content || [];\n  const result: JSONContent[] = [];\n  let i = 0;\n  while (i < content.length) {\n    const node = content[i]!;\n    if (node.type === 'heading') {\n      const text = node.content?.map((c) => c.text || '').join('') || '';\n      if (text.trim().toLowerCase() === headingText.trim().toLowerCase()) {\n        result.push(...sectionNodes);\n        i += 1;\n        while (i < content.length && content[i]!.type !== 'heading') i += 1;\n        continue;\n      }\n    }\n    result.push(node);\n    i += 1;\n  }\n  return { type: 'doc', content: result };\n}\n\nexport const useTextStore = create<TextState>((set, get) => ({\n  textProjects: [],\n  activeTextProjectId: null,\n  isTextSetupOpen: false,\n  isTextProjectLoading: true,\n  exportModalOpen: false,\n  toasts: [],\n  rightTab: 'ai',\n  agentPlanMode: false,\n\n  doc: EMPTY_DOC,\n  outline: [],\n  variants: [],\n  suggestions: [],\n  snapshots: [],\n  brandVoice: defaultBrandVoice('neutral'),\n  metrics: computeReadability(''),\n  clarity: computeClarityExtras('', []),\n  docType: 'blank',\n  language: 'es',\n  tone: 'neutral',\n  targetChannel: 'blog',\n  projectName: '',\n  workflowStatus: 'draft',\n  seoMeta: emptySeoMeta(),\n  comments: [],\n  claims: [],\n  enforceComplianceOnExport: false,\n\n  setIsTextSetupOpen: (open) => set({ isTextSetupOpen: open }),\n  setExportModalOpen: (open) => set({ exportModalOpen: open }),\n  setRightTab: (tab) => set({ rightTab: tab }),\n  setAgentPlanMode: (on) => set({ agentPlanMode: on }),\n\n  createTextProject: (name, opts) => {\n    const docType = opts?.docType ?? 'blank';\n    const tone = opts?.tone ?? 'neutral';\n    const language = opts?.language ?? 'es';\n    const targetChannel = opts?.targetChannel ?? 'blog';\n    const doc = templateDoc(docType, name);\n    const pageSize = opts?.pageSize ?? DEFAULT_PAGE_SIZE;\n    const orientation = opts?.orientation ?? 'portrait';\n    const columns = opts?.columns ?? 1;\n    const brandVoice = defaultBrandVoice(tone);\n    const { metrics, clarity } = metricsBundle(doc, brandVoice);\n    const project: TextProject = {\n      id: uid('txt'),\n      name,\n      docType,\n      pageSize,\n      orientation,\n      columns,\n      language,\n      tone,\n      targetChannel,\n      doc,\n      outline: extractOutline(doc),\n      variants: [],\n      suggestions: [],\n      snapshots: [],\n      brandVoice,\n      metrics,\n      clarity,\n      workflowStatus: 'draft',\n      seoMeta: { ...emptySeoMeta(), title: name },\n      comments: [],\n      claims: [],\n      enforceComplianceOnExport: false,\n      createdAt: Date.now(),\n      updatedAt: Date.now(),\n    };\n    set((state) => {\n      const synced = syncActiveIntoProjects(state);\n      return {\n        textProjects: [...synced, project],\n        activeTextProjectId: project.id,\n        isTextSetupOpen: false,\n        ...applyProjectToRoot(project),\n      };\n    });\n    scheduleAutosave();\n  },\n\n  closeTextProject: (projectId) => {\n    set((state) => {\n      const synced = syncActiveIntoProjects(state);\n      const remaining = synced.filter((p) => p.id !== projectId);\n      const next = remaining[0] ?? null;\n      return {\n        textProjects: remaining,\n        activeTextProjectId: next?.id ?? null,\n        ...(next\n          ? applyProjectToRoot(next)\n          : {\n              doc: EMPTY_DOC,\n              outline: [],\n              variants: [],\n              suggestions: [],\n              snapshots: [],\n              brandVoice: defaultBrandVoice('neutral'),\n              metrics: computeReadability(''),\n              clarity: computeClarityExtras('', []),\n              projectName: '',\n              workflowStatus: 'draft' as const,\n              seoMeta: emptySeoMeta(),\n              comments: [],\n              claims: [],\n            }),\n      };\n    });\n    scheduleAutosave();\n  },\n\n  switchTextProject: (projectId) => {\n    set((state) => {\n      const synced = syncActiveIntoProjects(state);\n      const next = synced.find((p) => p.id === projectId);\n      if (!next) return state;\n      return {\n        textProjects: synced,\n        activeTextProjectId: projectId,\n        ...applyProjectToRoot(next),\n      };\n    });\n  },\n\n  saveTextProject: async () => {\n    const state = get();\n    if (state.isTextProjectLoading) return;\n    const projects = syncActiveIntoProjects(state);\n    try {\n      const db = await openUploadsDB();\n      // Same in-line-key pattern as useAudioStore/saveAudioProject and\n      // useSlidesStore/saveSlidesProject: the 'projects' object store has\n      // keyPath: \"id\", so we must pass a value with an `id` field. Only\n      // one row per project family lives in this store (audio/slides/text),\n      // keyed by the family id.\n      const serializable = projects.map((p) => ({ ...p }));\n      await new Promise<void>((resolve, reject) => {\n        const tx = db.transaction('projects', 'readwrite');\n        tx.objectStore('projects').put({ id: 'text-projects', projects: serializable });\n        tx.oncomplete = () => resolve();\n        tx.onerror = () => reject(tx.error);\n      });\n      set({ textProjects: projects });\n    } catch (err) {\n      console.error('[text] save failed', err);\n    }\n  },\n\n  autoSaveTextProjectToCloud: async () =>\n    withCloudAutosaveToast('text', async () => {\n    const { hasEditorIdentity } = await import('../services/identity');\n    if (!hasEditorIdentity()) return false;\n\n    const state = get();\n    if (\n      state.isTextProjectLoading ||\n      !state.activeTextProjectId ||\n      state.textProjects.length === 0\n    ) {\n      return false;\n    }\n\n    const projectId = state.activeTextProjectId;\n    const cloudEditableId = state.textProjects.find((p) => p.id === projectId)?.cloudEditableId;\n\n    try {\n      const { uploadCurrentProjectToCloud } = await import('../utils/projectCloudSerializer');\n      const editable = await uploadCurrentProjectToCloud('text', {\n        editableId: cloudEditableId,\n      });\n\n      const stillActive = get().activeTextProjectId === projectId;\n      if (stillActive) {\n        set((s) => ({\n          textProjects: s.textProjects.map((p) =>\n            p.id === projectId ? { ...p, cloudEditableId: editable.id } : p,\n          ),\n        }));\n        void get().saveTextProject().catch(() => {});\n      }\n\n      return true;\n    } catch (err) {\n      console.warn('[autoSaveTextProjectToCloud] failed:', err);\n      throw err;\n    }\n  }),\n\n  loadTextProject: async () => {\n    try {\n      const db = await openUploadsDB();\n      const record = await new Promise<{ id: string; projects: TextProject[] } | undefined>(\n        (resolve, reject) => {\n          const tx = db.transaction('projects', 'readonly');\n          const req = tx.objectStore('projects').get('text-projects');\n          req.onsuccess = () =>\n            resolve(req.result as { id: string; projects: TextProject[] } | undefined);\n          req.onerror = () => reject(req.error);\n        }\n      );\n      const projects = record?.projects || [];\n      if (projects.length) {\n        const active = projects[0]!;\n        const normalized: TextProject = {\n          ...active,\n          brandVoice: normalizeBrandVoice(active.brandVoice, active.tone || 'neutral'),\n          clarity:\n            active.clarity ??\n            computeClarityExtras(\n              docToPlainText(active.doc),\n              active.brandVoice?.forbiddenTerms || []\n            ),\n          workflowStatus: active.workflowStatus ?? 'draft',\n          seoMeta: active.seoMeta ?? emptySeoMeta(),\n          comments: active.comments ?? [],\n          claims: active.claims ?? [],\n          enforceComplianceOnExport: active.enforceComplianceOnExport ?? false,\n        };\n        set({\n          textProjects: projects.map((p) =>\n            p.id === normalized.id ? normalized : p\n          ),\n          activeTextProjectId: normalized.id,\n          isTextProjectLoading: false,\n          ...applyProjectToRoot(normalized),\n        });\n      } else {\n        set({ isTextProjectLoading: false, isTextSetupOpen: true });\n      }\n    } catch {\n      set({ isTextProjectLoading: false, isTextSetupOpen: true });\n    }\n  },\n\n  importTextProject: (data, filename, opts) => {\n    const name =\n      data.name ||\n      (filename ? filename.replace(/\\.(kait|wzrdt|json|md|docx)$/i, '') : 'Documento importado');\n    const doc = data.doc || EMPTY_DOC;\n    const tone = data.tone || 'neutral';\n    const brandVoice = normalizeBrandVoice(data.brandVoice, tone);\n    const { metrics, clarity } = metricsBundle(doc, brandVoice);\n    const project: TextProject = {\n      id: uid('txt'),\n      name,\n      docType: data.docType || 'blank',\n      pageSize: data.pageSize || DEFAULT_PAGE_SIZE,\n      customPageSizeMm: data.customPageSizeMm,\n      customMarginsMm: data.customMarginsMm,\n      orientation: data.orientation || 'portrait',\n      columns: data.columns ?? 1,\n      language: data.language || 'es',\n      tone,\n      targetChannel: data.targetChannel || 'blog',\n      doc,\n      outline: data.outline || extractOutline(doc),\n      variants: data.variants || [],\n      suggestions: data.suggestions || [],\n      snapshots: data.snapshots || [],\n      brandVoice,\n      metrics: data.metrics || metrics,\n      clarity: data.clarity || clarity,\n      workflowStatus: data.workflowStatus || 'draft',\n      seoMeta: data.seoMeta || { ...emptySeoMeta(), title: name },\n      comments: data.comments || [],\n      claims: data.claims || [],\n      enforceComplianceOnExport: data.enforceComplianceOnExport ?? false,\n      createdAt: Date.now(),\n      updatedAt: Date.now(),\n      cloudEditableId: opts?.cloudEditableId,\n    };\n    set((state) => {\n      const synced = syncActiveIntoProjects(state);\n      return {\n        textProjects: [...synced, project],\n        activeTextProjectId: project.id,\n        isTextSetupOpen: false,\n        ...applyProjectToRoot(project),\n      };\n    });\n    scheduleAutosave();\n  },\n\n  setDoc: (doc) => {\n    const brand = get().brandVoice;\n    const { metrics, clarity } = metricsBundle(doc, brand);\n    set({\n      doc,\n      outline: extractOutline(doc),\n      metrics,\n      clarity,\n    });\n    get().markVariantsStale();\n    scheduleAutosave();\n  },\n\n  setDocFromEditor: (doc) => {\n    const brand = get().brandVoice;\n    const { metrics, clarity } = metricsBundle(doc, brand);\n    set({\n      doc,\n      outline: extractOutline(doc),\n      metrics,\n      clarity,\n    });\n    if (get().variants.length) scheduleMarkStale();\n    scheduleAutosave();\n  },\n\n  setTone: (tone) => set((s) => ({ tone, brandVoice: { ...s.brandVoice, tone } })),\n  setTargetChannel: (channel) => set({ targetChannel: channel }),\n  setProjectName: (name) => {\n    const trimmed = name.trim();\n    if (!trimmed) return;\n    set((s) => ({\n      projectName: trimmed,\n      textProjects: s.textProjects.map((p) =>\n        p.id === s.activeTextProjectId ? { ...p, name: trimmed } : p,\n      ),\n    }));\n    scheduleAutosave();\n  },\n  setProjectPageSize: (pageSize) => {\n    const { activeTextProjectId } = get();\n    if (!activeTextProjectId) return;\n    set((s) => ({\n      textProjects: s.textProjects.map((p) =>\n        p.id === activeTextProjectId ? { ...p, pageSize } : p\n      ),\n    }));\n    scheduleAutosave();\n  },\n  setProjectOrientation: (orientation) => {\n    const { activeTextProjectId } = get();\n    if (!activeTextProjectId) return;\n    set((s) => ({\n      textProjects: s.textProjects.map((p) =>\n        p.id === activeTextProjectId ? { ...p, orientation } : p\n      ),\n    }));\n    scheduleAutosave();\n  },\n  setProjectMargins: (margins) => {\n    const { activeTextProjectId } = get();\n    if (!activeTextProjectId) return;\n    // Store custom margins on the active project by overriding the pageSize's marginMm\n    set((s) => ({\n      textProjects: s.textProjects.map((p) =>\n        p.id === activeTextProjectId\n          ? { ...p, customMarginsMm: margins }\n          : p\n      ),\n    }));\n    scheduleAutosave();\n  },\n  setWorkflowStatus: (status) => {\n    set({ workflowStatus: status });\n    scheduleAutosave();\n  },\n  setSeoMeta: (patch) => {\n    set((s) => ({ seoMeta: { ...s.seoMeta, ...patch } }));\n    scheduleAutosave();\n  },\n  setEnforceComplianceOnExport: (on) => {\n    set({ enforceComplianceOnExport: on });\n    scheduleAutosave();\n  },\n\n  addSuggestion: (s) => {\n    const id = uid('sug');\n    const suggestion: TextSuggestion = {\n      ...s,\n      id,\n      status: 'pending',\n      createdAt: Date.now(),\n    };\n    set((state) => ({ suggestions: [...state.suggestions, suggestion] }));\n    return id;\n  },\n\n  acceptSuggestion: (id) => {\n    set((state) => ({\n      suggestions: state.suggestions.map((s) =>\n        s.id === id ? { ...s, status: 'accepted' as const } : s\n      ),\n    }));\n  },\n\n  rejectSuggestion: (id) => {\n    set((state) => ({\n      suggestions: state.suggestions.map((s) =>\n        s.id === id ? { ...s, status: 'rejected' as const } : s\n      ),\n    }));\n  },\n\n  acceptAllSuggestions: () => {\n    set((state) => ({\n      suggestions: state.suggestions.map((s) =>\n        s.status === 'pending' ? { ...s, status: 'accepted' as const } : s\n      ),\n    }));\n  },\n\n  rejectAllSuggestions: () => {\n    set((state) => ({\n      suggestions: state.suggestions.map((s) =>\n        s.status === 'pending' ? { ...s, status: 'rejected' as const } : s\n      ),\n    }));\n  },\n\n  clearSuggestions: () => set({ suggestions: [] }),\n\n  setVariants: (variants) => {\n    set({ variants });\n    scheduleAutosave();\n  },\n\n  markVariantsStale: () => {\n    set((state) => {\n      if (!state.variants.length) return state;\n      if (state.variants.every((v) => v.stale)) return state;\n      return {\n        variants: state.variants.map((v) => ({ ...v, stale: true })),\n      };\n    });\n  },\n\n  updateVariant: (id, patch) => {\n    set((state) => ({\n      variants: state.variants.map((v) => (v.id === id ? { ...v, ...patch } : v)),\n    }));\n    scheduleAutosave();\n  },\n\n  createNamedSnapshot: (name) => {\n    const state = get();\n    const snap: TextSnapshot = {\n      id: uid('snap'),\n      name: name || `Version ${state.snapshots.length + 1}`,\n      doc: structuredClone(state.doc),\n      createdAt: Date.now(),\n    };\n    set({ snapshots: [...state.snapshots, snap] });\n    get().addToast(getActiveMessages().store.toasts.text.snapshotSaved(snap.name), 'success');\n    scheduleAutosave();\n  },\n\n  restoreSnapshot: (id) => {\n    const snap = get().snapshots.find((s) => s.id === id);\n    if (!snap) return;\n    get().setDoc(structuredClone(snap.doc));\n    get().addToast(getActiveMessages().store.toasts.text.snapshotRestored(snap.name), 'info');\n  },\n\n  restoreSnapshotSection: (id, headingText) => {\n    const snap = get().snapshots.find((s) => s.id === id);\n    if (!snap) return;\n    const section = extractSectionByHeading(snap.doc, headingText);\n    if (!section.length) {\n      get().addToast(getActiveMessages().store.toasts.text.sectionNotFound, 'warning');\n      return;\n    }\n    const next = replaceSectionByHeading(get().doc, headingText, section);\n    get().setDoc(next);\n    get().addToast(getActiveMessages().store.toasts.text.sectionRestored(headingText), 'info');\n  },\n\n  getSnapshotPlainText: (id) => {\n    const snap = get().snapshots.find((s) => s.id === id);\n    if (!snap) return null;\n    return docToPlainText(snap.doc).trim() || null;\n  },\n\n  removeSnapshot: (id) => {\n    set((state) => ({ snapshots: state.snapshots.filter((s) => s.id !== id) }));\n    scheduleAutosave();\n  },\n\n  setBrandVoice: (patch) => {\n    set((state) => {\n      const brandVoice = { ...state.brandVoice, ...patch };\n      const plain = docToPlainText(state.doc);\n      return {\n        brandVoice,\n        clarity: computeClarityExtras(\n          plain,\n          brandVoice.forbiddenTerms,\n          brandVoice.preferredTerms\n        ),\n      };\n    });\n    scheduleAutosave();\n  },\n\n  addComment: (note, quote, anchored = false) => {\n    const id = uid('cmt');\n    const comment: TextComment = {\n      id,\n      note,\n      quote,\n      anchored,\n      resolved: false,\n      createdAt: Date.now(),\n    };\n    set((state) => ({ comments: [...state.comments, comment] }));\n    scheduleAutosave();\n    return id;\n  },\n\n  resolveComment: (id, resolved = true) => {\n    set((state) => ({\n      comments: state.comments.map((c) =>\n        c.id === id ? { ...c, resolved } : c\n      ),\n    }));\n    scheduleAutosave();\n  },\n\n  removeComment: (id) => {\n    set((state) => ({ comments: state.comments.filter((c) => c.id !== id) }));\n    scheduleAutosave();\n  },\n\n  addClaim: (text, status = 'unverified', note) => {\n    const id = uid('claim');\n    const claim: TextClaim = {\n      id,\n      text,\n      status,\n      note,\n      createdAt: Date.now(),\n    };\n    set((state) => ({ claims: [...state.claims, claim] }));\n    scheduleAutosave();\n    return id;\n  },\n\n  updateClaim: (id, patch) => {\n    set((state) => ({\n      claims: state.claims.map((c) => (c.id === id ? { ...c, ...patch } : c)),\n    }));\n    scheduleAutosave();\n  },\n\n  removeClaim: (id) => {\n    set((state) => ({ claims: state.claims.filter((c) => c.id !== id) }));\n    scheduleAutosave();\n  },\n\n  setClaims: (claims) => {\n    set({ claims });\n    scheduleAutosave();\n  },\n\n  recomputeMetrics: () => {\n    const state = get();\n    const { metrics, clarity } = metricsBundle(state.doc, state.brandVoice);\n    set({ metrics, clarity });\n  },\n\n  canExport: () => {\n    const state = get();\n    const blockers: string[] = [];\n    if (!state.enforceComplianceOnExport) {\n      return { ok: true, blockers };\n    }\n    const plain = docToPlainText(state.doc).toLowerCase();\n    for (const term of state.brandVoice.forbiddenTerms) {\n      if (term && plain.includes(term.toLowerCase())) {\n        blockers.push(`Termino prohibido: ${term}`);\n      }\n    }\n    const flagged = state.claims.filter((c) => c.status === 'flagged');\n    if (flagged.length) {\n      blockers.push(`${flagged.length} claim(s) marcados`);\n    }\n    // Draft alone is a soft warning (not a hard block)\n    if (state.workflowStatus === 'draft' && blockers.length === 0) {\n      return {\n        ok: true,\n        blockers: ['Aviso: workflow sigue en borrador'],\n      };\n    }\n    return { ok: blockers.length === 0, blockers };\n  },\n\n  addToast: (message, type = 'info') => {\n    const id = uid('toast');\n    const safe =\n      type === 'error'\n        ? sanitizeUserFacingMessage(message, { context: 'toast:text' })\n        : message;\n    set((state) => ({ toasts: [...state.toasts, { id, message: safe, type }] }));\n    setTimeout(() => get().removeToast(id), 4000);\n  },\n\n  removeToast: (id) =>\n    set((state) => ({ toasts: state.toasts.filter((t) => t.id !== id) })),\n\n  getProjectSnapshot: () => {\n    const s = get();\n    return {\n      name: s.projectName,\n      docType: s.docType,\n      language: s.language,\n      tone: s.tone,\n      targetChannel: s.targetChannel,\n      workflowStatus: s.workflowStatus,\n      seoMeta: s.seoMeta,\n      outline: s.outline,\n      metrics: s.metrics,\n      clarity: s.clarity,\n      brandVoice: s.brandVoice,\n      variantChannels: s.variants.map((v) => v.channel),\n      pendingSuggestions: s.suggestions.filter((x) => x.status === 'pending').length,\n      openComments: s.comments.filter((c) => !c.resolved).length,\n      claims: s.claims.length,\n      plainText: docToPlainText(s.doc).slice(0, 6000),\n    };\n  },\n}));\n\ntextPersistence = createProjectPersistence({\n  mode: 'text',\n  localDebounceMs: 400,\n  cloudDebounceMs: 3000,\n  saveLocal: async () => {\n    await useTextStore.getState().saveTextProject();\n  },\n  saveCloud: async () => useTextStore.getState().autoSaveTextProjectToCloud(),\n});\nregisterProjectPersistence(textPersistence);\n\nexport function flushTextPersistence(): Promise<void> {\n  return textPersistence.flush();\n}\n\nexport function getDocPlainText(doc: JSONContent): string {\n  return docToPlainText(doc);\n}\n", "/**\n * Slides Studio Pro \u2014 deck data model.\n * Theme + masters + slides with typed placeholders (not a bare page list).\n */\n\nimport type { TextAnimationPreset, TransitionType } from '../store/useVideoStore';\n\nexport const SLIDES_SCHEMA_VERSION = 2;\n\nexport type SlideLayoutId =\n  | 'blank'\n  | 'title'\n  | 'title-subtitle'\n  | 'section'\n  | 'title-body'\n  | 'two-column'\n  | 'image-left'\n  | 'image-right'\n  | 'quote'\n  | 'bullets'\n  | 'comparison'\n  | 'agenda'\n  | 'closing'\n  | 'chart'\n  | 'big-number';\n\nexport type ThemeRole =\n  | 'title'\n  | 'subtitle'\n  | 'body'\n  | 'caption'\n  | 'accent'\n  | 'muted'\n  | 'background'\n  | 'surface';\n\nexport type PlaceholderRole =\n  | 'title'\n  | 'subtitle'\n  | 'body'\n  | 'bullets'\n  | 'image'\n  | 'chart'\n  | 'quote'\n  | 'caption'\n  | 'number'\n  | 'footer'\n  | 'logo'\n  | 'table-cell';\n\nexport interface DeckTheme {\n  id: string;\n  name: string;\n  colors: {\n    background: string;\n    surface: string;\n    title: string;\n    body: string;\n    accent: string;\n    muted: string;\n  };\n  fonts: {\n    title: string;\n    body: string;\n  };\n  typeScale: {\n    title: number;\n    subtitle: number;\n    body: number;\n    caption: number;\n  };\n  radii: { sm: number; md: number; lg: number };\n  shadow: string;\n}\n\nexport interface PlaceholderDef {\n  id: string;\n  role: PlaceholderRole;\n  themeRole?: ThemeRole;\n  left: number;\n  top: number;\n  width: number;\n  height: number;\n  defaultText?: string;\n}\n\nexport interface SlideLayoutDef {\n  id: SlideLayoutId;\n  name: string;\n  placeholders: PlaceholderDef[];\n}\n\nexport interface MasterChrome {\n  showFooter: boolean;\n  footerText: string;\n  showPageNumber: boolean;\n  showLogo: boolean;\n  logoAssetId?: string;\n  logoDataUrl?: string;\n  headerText?: string;\n  showHeader: boolean;\n}\n\nexport interface SlideMaster {\n  id: string;\n  name: string;\n  /** Fabric JSON for master chrome (logo, footer, bg shapes). */\n  json: unknown;\n  backgroundColor: string;\n  layouts: SlideLayoutDef[];\n  chrome: MasterChrome;\n}\n\nexport interface ElementBuild {\n  objectId: string;\n  order: number;\n  trigger: 'click' | 'with-previous' | 'after-previous';\n  animation: TextAnimationPreset;\n  durationMs: number;\n  delayMs: number;\n}\n\nexport interface SlideTransition {\n  type: TransitionType;\n  duration: number;\n}\n\nexport interface SlideNarration {\n  text: string;\n  voiceId?: string;\n  audioAssetId?: string;\n}\n\nexport interface SlideComment {\n  id: string;\n  note: string;\n  resolved: boolean;\n  createdAt: number;\n  quote?: string;\n  objectId?: string;\n}\n\nexport interface Slide {\n  id: string;\n  name: string;\n  masterId: string;\n  layoutId: SlideLayoutId;\n  /** Fabric canvas JSON for slide content. */\n  json: unknown;\n  notes: string;\n  hidden: boolean;\n  transition: SlideTransition;\n  builds: ElementBuild[];\n  estimatedSeconds?: number;\n  narration?: SlideNarration;\n  comments: SlideComment[];\n  thumbnail?: string;\n  history: string[];\n  historyIndex: number;\n}\n\nexport interface DeckSection {\n  id: string;\n  name: string;\n  slideIds: string[];\n  collapsed?: boolean;\n}\n\nexport interface SlidesAsset {\n  id: string;\n  name: string;\n  mimeType: string;\n  url: string;\n  file?: File;\n  width?: number;\n  height?: number;\n  duration?: number;\n}\n\nexport interface SlideDeck {\n  id: string;\n  name: string;\n  size: { width: number; height: number };\n  theme: DeckTheme;\n  masters: SlideMaster[];\n  slides: Slide[];\n  sections: DeckSection[];\n  assets: SlidesAsset[];\n  activeSlideId: string | null;\n  schemaVersion: number;\n  createdAt: number;\n  updatedAt: number;\n  template?: SlidesTemplateId;\n  /** Last cloud editable id \u2014 used to replace on silent autosave. */\n  cloudEditableId?: number;\n  /** True when a cloud upload failed/was interrupted \u2014 retry on next load. */\n  cloudSavePending?: boolean;\n}\n\nexport type SlidesTemplateId =\n  | 'blank'\n  | 'pitch'\n  | 'qbr'\n  | 'course'\n  | 'report'\n  | 'keynote';\n\nexport type SlidesRightTab =\n  | 'ai'\n  | 'chat'\n  | 'theme'\n  | 'outline'\n  | 'builds'\n  | 'notes'\n  | 'comments'\n  | 'critique'\n  | 'library'\n  | 'coach'\n  | 'master';\n\nexport type SemanticRestyleMode = 'board' | 'sales' | 'internal';\n\nexport type SlidesToast = {\n  id: string;\n  message: string;\n  type: 'success' | 'error' | 'info' | 'warning';\n};\n\nexport interface SlidesCanvasConfig {\n  name: string;\n  width: number;\n  height: number;\n  template: SlidesTemplateId;\n  backgroundColor?: string;\n}\n", "import type { DeckTheme } from '../../types/slides.types';\n\nexport const DEFAULT_THEME: DeckTheme = {\n  id: 'theme_wizard_light',\n  name: 'Kaiman Light',\n  colors: {\n    background: '#FFFFFF',\n    surface: '#F5F5F8',\n    title: '#12121A',\n    body: '#3A3A4A',\n    accent: '#A204CA',\n    muted: '#8888A0',\n  },\n  fonts: {\n    title: 'Inter',\n    body: 'Inter',\n  },\n  typeScale: {\n    title: 56,\n    subtitle: 28,\n    body: 22,\n    caption: 14,\n  },\n  radii: { sm: 4, md: 8, lg: 16 },\n  shadow: '0 8px 32px rgba(0,0,0,0.12)',\n};\n\nexport const DARK_THEME: DeckTheme = {\n  id: 'theme_wizard_dark',\n  name: 'Kaiman Dark',\n  colors: {\n    background: '#0F1117',\n    surface: '#1A1D27',\n    title: '#F0F0F5',\n    body: '#C8C8D4',\n    accent: '#A204CA',\n    muted: '#8888A0',\n  },\n  fonts: {\n    title: 'Inter',\n    body: 'Inter',\n  },\n  typeScale: {\n    title: 56,\n    subtitle: 28,\n    body: 22,\n    caption: 14,\n  },\n  radii: { sm: 4, md: 8, lg: 16 },\n  shadow: '0 8px 32px rgba(0,0,0,0.35)',\n};\n\n/** @deprecated Use DEFAULT_THEME (light) or DARK_THEME */\nexport const LIGHT_THEME = DEFAULT_THEME;\n\nexport const PITCH_THEME: DeckTheme = {\n  id: 'theme_pitch',\n  name: 'Pitch',\n  colors: {\n    background: '#0A0A0F',\n    surface: '#16161F',\n    title: '#FFFFFF',\n    body: '#D0D0DC',\n    accent: '#22D3EE',\n    muted: '#7A7A90',\n  },\n  fonts: {\n    title: 'Inter',\n    body: 'Inter',\n  },\n  typeScale: {\n    title: 64,\n    subtitle: 30,\n    body: 24,\n    caption: 14,\n  },\n  radii: { sm: 6, md: 12, lg: 20 },\n  shadow: '0 12px 40px rgba(34,211,238,0.15)',\n};\n\nexport const THEME_PRESETS: DeckTheme[] = [DEFAULT_THEME];\n\n\nexport function cloneTheme(theme: DeckTheme, name?: string): DeckTheme {\n  return {\n    ...theme,\n    id: `theme_${Math.random().toString(36).slice(2, 10)}`,\n    name: name || theme.name,\n    colors: { ...theme.colors },\n    fonts: { ...theme.fonts },\n    typeScale: { ...theme.typeScale },\n    radii: { ...theme.radii },\n  };\n}\n", "/**\n * Built-in slide layouts and Fabric JSON builders for placeholders.\n */\n\nimport type {\n  DeckTheme,\n  PlaceholderDef,\n  Slide,\n  SlideLayoutDef,\n  SlideLayoutId,\n  SlideMaster,\n  SlidesTemplateId,\n} from '../../types/slides.types';\nimport { DEFAULT_THEME } from './themes';\n\nfunction uid(prefix: string): string {\n  return `${prefix}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport const LAYOUT_CATALOG: SlideLayoutDef[] = [\n  { id: 'blank', name: 'En blanco', placeholders: [] },\n  {\n    id: 'title',\n    name: 'Titulo',\n    placeholders: [\n      { id: 'ph_title', role: 'title', themeRole: 'title', left: 120, top: 380, width: 1680, height: 120, defaultText: 'Titulo de la presentacion' },\n      { id: 'ph_sub', role: 'subtitle', themeRole: 'subtitle', left: 120, top: 520, width: 1680, height: 60, defaultText: 'Subtitulo' },\n    ],\n  },\n  {\n    id: 'title-subtitle',\n    name: 'Titulo + subtitulo',\n    placeholders: [\n      { id: 'ph_title', role: 'title', themeRole: 'title', left: 120, top: 200, width: 1680, height: 100, defaultText: 'Titulo' },\n      { id: 'ph_sub', role: 'subtitle', themeRole: 'subtitle', left: 120, top: 320, width: 1680, height: 80, defaultText: 'Descripcion breve' },\n    ],\n  },\n  {\n    id: 'section',\n    name: 'Seccion',\n    placeholders: [\n      { id: 'ph_title', role: 'title', themeRole: 'title', left: 120, top: 420, width: 1680, height: 100, defaultText: 'Seccion' },\n    ],\n  },\n  {\n    id: 'title-body',\n    name: 'Titulo + cuerpo',\n    placeholders: [\n      { id: 'ph_title', role: 'title', themeRole: 'title', left: 100, top: 80, width: 1720, height: 80, defaultText: 'Titulo' },\n      { id: 'ph_body', role: 'body', themeRole: 'body', left: 100, top: 200, width: 1720, height: 700, defaultText: 'Escribe el contenido aqui...' },\n    ],\n  },\n  {\n    id: 'bullets',\n    name: 'Vi\u00F1etas',\n    placeholders: [\n      { id: 'ph_title', role: 'title', themeRole: 'title', left: 100, top: 80, width: 1720, height: 80, defaultText: 'Puntos clave' },\n      { id: 'ph_bullets', role: 'bullets', themeRole: 'body', left: 100, top: 200, width: 1720, height: 700, defaultText: '\u2022 Punto uno\\n\u2022 Punto dos\\n\u2022 Punto tres' },\n    ],\n  },\n  {\n    id: 'two-column',\n    name: 'Dos columnas',\n    placeholders: [\n      { id: 'ph_title', role: 'title', themeRole: 'title', left: 100, top: 80, width: 1720, height: 70, defaultText: 'Comparacion' },\n      { id: 'ph_left', role: 'body', themeRole: 'body', left: 100, top: 200, width: 820, height: 700, defaultText: 'Columna izquierda' },\n      { id: 'ph_right', role: 'body', themeRole: 'body', left: 1000, top: 200, width: 820, height: 700, defaultText: 'Columna derecha' },\n    ],\n  },\n  {\n    id: 'image-left',\n    name: 'Imagen izquierda',\n    placeholders: [\n      { id: 'ph_image', role: 'image', left: 80, top: 120, width: 800, height: 840 },\n      { id: 'ph_title', role: 'title', themeRole: 'title', left: 960, top: 200, width: 860, height: 80, defaultText: 'Titulo' },\n      { id: 'ph_body', role: 'body', themeRole: 'body', left: 960, top: 320, width: 860, height: 500, defaultText: 'Texto a la derecha' },\n    ],\n  },\n  {\n    id: 'image-right',\n    name: 'Imagen derecha',\n    placeholders: [\n      { id: 'ph_title', role: 'title', themeRole: 'title', left: 100, top: 200, width: 860, height: 80, defaultText: 'Titulo' },\n      { id: 'ph_body', role: 'body', themeRole: 'body', left: 100, top: 320, width: 860, height: 500, defaultText: 'Texto a la izquierda' },\n      { id: 'ph_image', role: 'image', left: 1040, top: 120, width: 800, height: 840 },\n    ],\n  },\n  {\n    id: 'quote',\n    name: 'Cita',\n    placeholders: [\n      { id: 'ph_quote', role: 'quote', themeRole: 'title', left: 200, top: 320, width: 1520, height: 200, defaultText: '\"Una cita memorable.\"' },\n      { id: 'ph_cap', role: 'caption', themeRole: 'muted', left: 200, top: 560, width: 1520, height: 50, defaultText: '\u2014 Autor' },\n    ],\n  },\n  {\n    id: 'comparison',\n    name: 'Antes / Despues',\n    placeholders: [\n      { id: 'ph_title', role: 'title', themeRole: 'title', left: 100, top: 60, width: 1720, height: 70, defaultText: 'Antes vs Despues' },\n      { id: 'ph_left', role: 'body', themeRole: 'body', left: 100, top: 180, width: 820, height: 720, defaultText: 'Antes' },\n      { id: 'ph_right', role: 'body', themeRole: 'body', left: 1000, top: 180, width: 820, height: 720, defaultText: 'Despues' },\n    ],\n  },\n  {\n    id: 'agenda',\n    name: 'Agenda',\n    placeholders: [\n      { id: 'ph_title', role: 'title', themeRole: 'title', left: 100, top: 80, width: 1720, height: 80, defaultText: 'Agenda' },\n      { id: 'ph_bullets', role: 'bullets', themeRole: 'body', left: 100, top: 220, width: 1720, height: 680, defaultText: '1. Introduccion\\n2. Problema\\n3. Solucion\\n4. Cierre' },\n    ],\n  },\n  {\n    id: 'closing',\n    name: 'Cierre',\n    placeholders: [\n      { id: 'ph_title', role: 'title', themeRole: 'title', left: 120, top: 380, width: 1680, height: 100, defaultText: 'Gracias' },\n      { id: 'ph_sub', role: 'subtitle', themeRole: 'subtitle', left: 120, top: 520, width: 1680, height: 60, defaultText: 'Preguntas?' },\n    ],\n  },\n  {\n    id: 'chart',\n    name: 'Grafico',\n    placeholders: [\n      { id: 'ph_title', role: 'title', themeRole: 'title', left: 100, top: 60, width: 1720, height: 70, defaultText: 'Metricas' },\n      { id: 'ph_chart', role: 'chart', left: 200, top: 180, width: 1520, height: 720 },\n    ],\n  },\n  {\n    id: 'big-number',\n    name: 'Numero grande',\n    placeholders: [\n      { id: 'ph_number', role: 'number', themeRole: 'accent', left: 120, top: 300, width: 1680, height: 200, defaultText: '10x' },\n      { id: 'ph_cap', role: 'caption', themeRole: 'body', left: 120, top: 540, width: 1680, height: 60, defaultText: 'Crecimiento a\u00F1o a a\u00F1o' },\n    ],\n  },\n];\n\nexport function getLayout(id: SlideLayoutId): SlideLayoutDef {\n  return LAYOUT_CATALOG.find((l) => l.id === id) || LAYOUT_CATALOG[0]!;\n}\n\nfunction textObject(\n  ph: PlaceholderDef,\n  theme: DeckTheme,\n  text: string,\n  objectId: string\n): Record<string, unknown> {\n  const role = ph.themeRole || 'body';\n  const fill =\n    role === 'title'\n      ? theme.colors.title\n      : role === 'accent'\n        ? theme.colors.accent\n        : role === 'muted' || role === 'caption'\n          ? theme.colors.muted\n          : theme.colors.body;\n  const fontSize =\n    role === 'title'\n      ? theme.typeScale.title\n      : role === 'subtitle'\n        ? theme.typeScale.subtitle\n        : role === 'caption' || role === 'muted'\n          ? theme.typeScale.caption\n          : role === 'accent'\n            ? theme.typeScale.title * 1.4\n            : theme.typeScale.body;\n  const fontFamily = role === 'title' || role === 'accent' ? theme.fonts.title : theme.fonts.body;\n\n  return {\n    type: 'Textbox',\n    version: '6.0.0',\n    originX: 'left',\n    originY: 'top',\n    left: ph.left,\n    top: ph.top,\n    width: ph.width,\n    height: ph.height,\n    fill,\n    fontSize,\n    fontFamily,\n    fontWeight: role === 'title' || role === 'accent' ? 'bold' : 'normal',\n    text,\n    textAlign: ph.role === 'quote' || ph.role === 'number' || ph.role === 'title' ? 'center' : 'left',\n    editable: true,\n    id: objectId,\n    placeholderRole: ph.role,\n    themeRole: role,\n    name: ph.role,\n  };\n}\n\nfunction imagePlaceholder(ph: PlaceholderDef, theme: DeckTheme, objectId: string): Record<string, unknown> {\n  return {\n    type: 'Rect',\n    version: '6.0.0',\n    originX: 'left',\n    originY: 'top',\n    left: ph.left,\n    top: ph.top,\n    width: ph.width,\n    height: ph.height,\n    fill: theme.colors.surface,\n    stroke: theme.colors.muted,\n    strokeWidth: 1,\n    rx: theme.radii.md,\n    ry: theme.radii.md,\n    id: objectId,\n    placeholderRole: ph.role,\n    name: 'image-placeholder',\n  };\n}\n\nexport function buildSlideJsonFromLayout(\n  layoutId: SlideLayoutId,\n  theme: DeckTheme,\n  content?: Partial<Record<string, string>>\n): { json: { version: string; objects: unknown[]; background: string }; objectIds: string[] } {\n  const layout = getLayout(layoutId);\n  const objects: unknown[] = [];\n  const objectIds: string[] = [];\n\n  for (const ph of layout.placeholders) {\n    const objectId = uid('obj');\n    objectIds.push(objectId);\n    if (ph.role === 'image' || ph.role === 'chart') {\n      objects.push(imagePlaceholder(ph, theme, objectId));\n    } else {\n      const text = content?.[ph.role] ?? content?.[ph.id] ?? ph.defaultText ?? '';\n      objects.push(textObject(ph, theme, text, objectId));\n    }\n  }\n\n  return {\n    json: {\n      version: '6.0.0',\n      objects,\n      background: theme.colors.background,\n    },\n    objectIds,\n  };\n}\n\nexport function createDefaultMaster(theme: DeckTheme): SlideMaster {\n  return {\n    id: uid('master'),\n    name: 'Master principal',\n    backgroundColor: theme.colors.background,\n    json: {\n      version: '6.0.0',\n      objects: [],\n      background: theme.colors.background,\n    },\n    layouts: LAYOUT_CATALOG,\n    chrome: {\n      showFooter: true,\n      footerText: 'Confidential',\n      showPageNumber: true,\n      showLogo: false,\n      showHeader: false,\n      headerText: '',\n    },\n  };\n}\n\n/** Merge master chrome (footer/header/page#) into a slide JSON for render/export. */\nexport function composeSlideWithMaster(\n  slideJson: unknown,\n  master: SlideMaster,\n  theme: DeckTheme,\n  pageIndex: number,\n  pageCount: number,\n  size: { width: number; height: number }\n): unknown {\n  const doc = structuredClone(slideJson || { objects: [] }) as {\n    objects?: Array<Record<string, unknown>>;\n    background?: string;\n  };\n  const objects = [...(doc.objects || [])];\n  const chrome = master.chrome || createDefaultMaster(theme).chrome;\n  if (chrome.showHeader && chrome.headerText) {\n    objects.push({\n      type: 'Textbox',\n      left: 48,\n      top: 24,\n      width: size.width - 96,\n      height: 28,\n      text: chrome.headerText,\n      fontSize: theme.typeScale.caption,\n      fontFamily: theme.fonts.body,\n      fill: theme.colors.muted,\n      id: '__master_header',\n      selectable: false,\n      evented: false,\n      masterChrome: true,\n    });\n  }\n  if (chrome.showFooter || chrome.showPageNumber) {\n    const parts: string[] = [];\n    if (chrome.showFooter && chrome.footerText) parts.push(chrome.footerText);\n    if (chrome.showPageNumber) parts.push(`${pageIndex + 1} / ${pageCount}`);\n    objects.push({\n      type: 'Textbox',\n      left: 48,\n      top: size.height - 48,\n      width: size.width - 96,\n      height: 28,\n      text: parts.join('   \u00B7   '),\n      fontSize: theme.typeScale.caption,\n      fontFamily: theme.fonts.body,\n      fill: theme.colors.muted,\n      id: '__master_footer',\n      selectable: false,\n      evented: false,\n      masterChrome: true,\n    });\n  }\n  if (chrome.showLogo && chrome.logoDataUrl) {\n    objects.push({\n      type: 'Image',\n      left: size.width - 140,\n      top: 20,\n      width: 96,\n      height: 40,\n      src: chrome.logoDataUrl,\n      id: '__master_logo',\n      selectable: false,\n      evented: false,\n      masterChrome: true,\n      alt: 'Logo',\n    });\n  }\n  return { ...doc, objects, background: doc.background || theme.colors.background };\n}\n\nexport function createEmptySlide(\n  masterId: string,\n  layoutId: SlideLayoutId,\n  theme: DeckTheme,\n  name?: string,\n  content?: Partial<Record<string, string>>\n): Slide {\n  const { json } = buildSlideJsonFromLayout(layoutId, theme, content);\n  return {\n    id: uid('slide'),\n    name: name || 'Diapositiva',\n    masterId,\n    layoutId,\n    json,\n    notes: '',\n    hidden: false,\n    transition: { type: 'cross-dissolve', duration: 0.4 },\n    builds: [],\n    comments: [],\n    history: [JSON.stringify(json)],\n    historyIndex: 0,\n  };\n}\n\nexport function createDeckFromTemplate(\n  name: string,\n  size: { width: number; height: number },\n  template: SlidesTemplateId\n): {\n  theme: DeckTheme;\n  masters: SlideMaster[];\n  slides: Slide[];\n  sections: { id: string; name: string; slideIds: string[] }[];\n} {\n  const theme = { ...DEFAULT_THEME };\n  const master = createDefaultMaster(theme);\n\n  const make = (layoutId: SlideLayoutId, slideName: string, content?: Partial<Record<string, string>>) =>\n    createEmptySlide(master.id, layoutId, theme, slideName, content);\n\n  let slides: Slide[];\n  switch (template) {\n    case 'pitch':\n      slides = [\n        make('title', 'Portada', { title: name, subtitle: 'Pitch deck' }),\n        make('agenda', 'Agenda'),\n        make('problem' as SlideLayoutId, 'Problema', { title: 'El problema', body: 'Describe el dolor del cliente.' }),\n        make('title-body', 'Solucion', { title: 'Nuestra solucion', body: 'Como lo resolvemos.' }),\n        make('big-number', 'Traccion', { number: '10x', caption: 'Crecimiento' }),\n        make('closing', 'Cierre'),\n      ];\n      // Fix invalid layout used above\n      slides[2] = make('title-body', 'Problema', { title: 'El problema', body: 'Describe el dolor del cliente.' });\n      break;\n    case 'qbr':\n      slides = [\n        make('title', 'Portada', { title: name, subtitle: 'QBR' }),\n        make('agenda', 'Agenda'),\n        make('big-number', 'KPIs'),\n        make('chart', 'Tendencias'),\n        make('two-column', 'Wins / Risks'),\n        make('closing', 'Proximos pasos'),\n      ];\n      break;\n    case 'course':\n      slides = [\n        make('title', 'Portada', { title: name, subtitle: 'Curso' }),\n        make('agenda', 'Temario'),\n        make('section', 'Modulo 1'),\n        make('bullets', 'Conceptos'),\n        make('image-right', 'Ejemplo'),\n        make('closing', 'Resumen'),\n      ];\n      break;\n    case 'report':\n      slides = [\n        make('title', 'Portada', { title: name, subtitle: 'Informe' }),\n        make('agenda', 'Indice'),\n        make('title-body', 'Resumen ejecutivo'),\n        make('chart', 'Datos'),\n        make('two-column', 'Hallazgos'),\n        make('closing', 'Recomendaciones'),\n      ];\n      break;\n    case 'keynote':\n      slides = [\n        make('title', 'Portada', { title: name, subtitle: 'Keynote' }),\n        make('section', 'Acto I'),\n        make('quote', 'Idea clave'),\n        make('big-number', 'Impacto'),\n        make('image-left', 'Historia'),\n        make('closing', 'Cierre'),\n      ];\n      break;\n    default:\n      slides = [make('title', 'Portada', { title: name, subtitle: 'Nueva presentacion' })];\n  }\n\n  // Scale placeholder coords if non-default size\n  if (size.width !== 1920 || size.height !== 1080) {\n    const sx = size.width / 1920;\n    const sy = size.height / 1080;\n    slides = slides.map((s) => scaleSlideJson(s, sx, sy, theme.colors.background));\n  }\n\n  const sections = [\n    {\n      id: uid('sec'),\n      name: 'Principal',\n      slideIds: slides.map((s) => s.id),\n    },\n  ];\n\n  return { theme, masters: [master], slides, sections };\n}\n\nfunction scaleSlideJson(slide: Slide, sx: number, sy: number, bg: string): Slide {\n  const json = slide.json as { objects?: Array<Record<string, unknown>>; background?: string };\n  if (!json?.objects) return slide;\n  const objects = json.objects.map((obj) => ({\n    ...obj,\n    left: typeof obj.left === 'number' ? obj.left * sx : obj.left,\n    top: typeof obj.top === 'number' ? obj.top * sy : obj.top,\n    width: typeof obj.width === 'number' ? obj.width * sx : obj.width,\n    height: typeof obj.height === 'number' ? obj.height * sy : obj.height,\n    fontSize: typeof obj.fontSize === 'number' ? Math.round(obj.fontSize * Math.min(sx, sy)) : obj.fontSize,\n  }));\n  const next = { ...json, objects, background: bg };\n  return {\n    ...slide,\n    json: next,\n    history: [JSON.stringify(next)],\n    historyIndex: 0,\n  };\n}\n\nfunction isFabricTextObject(o: Record<string, unknown>): boolean {\n  const t = String(o.type || '').toLowerCase();\n  return t.includes('text') || typeof o.text === 'string';\n}\n\n/** Flatten top-level + nested group objects (Fabric groups hide text otherwise). */\nexport function flattenSlideObjects(\n  objects: Array<Record<string, unknown>> | undefined\n): Array<Record<string, unknown>> {\n  const out: Array<Record<string, unknown>> = [];\n  const walk = (list: Array<Record<string, unknown>>) => {\n    for (const obj of list) {\n      out.push(obj);\n      const nested = obj.objects;\n      if (Array.isArray(nested)) {\n        walk(nested as Array<Record<string, unknown>>);\n      }\n    }\n  };\n  walk(objects || []);\n  return out;\n}\n\nexport function extractOutlineFromSlides(\n  slides: Slide[]\n): Array<{ slideId: string; title: string; bullets: string[] }> {\n  return slides.map((slide) => {\n    const json = slide.json as { objects?: Array<Record<string, unknown>> };\n    const objects = flattenSlideObjects(json?.objects);\n    let title = slide.name;\n    const bullets: string[] = [];\n    let foundRoleTitle = false;\n    let foundRoleBody = false;\n\n    for (const obj of objects) {\n      if (!isFabricTextObject(obj)) continue;\n      const role = String(obj.placeholderRole || '').toLowerCase();\n      const text = typeof obj.text === 'string' ? obj.text : '';\n      if (!text.trim()) continue;\n      if (role === 'title') {\n        title = text.split('\\n')[0] || title;\n        foundRoleTitle = true;\n      }\n      if (role === 'bullets' || role === 'body' || role === 'subtitle') {\n        text.split('\\n').forEach((line) => {\n          const cleaned = line.replace(/^[\u2022\\-\\d.]+\\s*/, '').trim();\n          if (cleaned) bullets.push(cleaned);\n        });\n        foundRoleBody = true;\n      }\n    }\n\n    // Decks without placeholderRole (imported / heavily edited): visual order.\n    if (!foundRoleTitle || !foundRoleBody) {\n      const texts = objects\n        .filter(isFabricTextObject)\n        .filter((o) => typeof o.text === 'string' && String(o.text).trim())\n        .sort((a, b) => {\n          const dy = Number(a.top || 0) - Number(b.top || 0);\n          if (Math.abs(dy) > 8) return dy;\n          return Number(a.left || 0) - Number(b.left || 0);\n        });\n      if (!foundRoleTitle && texts[0] && typeof texts[0].text === 'string') {\n        title = String(texts[0].text).split('\\n')[0] || title;\n      }\n      if (!foundRoleBody && texts.length > 1) {\n        texts.slice(1).forEach((obj) => {\n          String(obj.text || '')\n            .split('\\n')\n            .forEach((line) => {\n              const cleaned = line.replace(/^[\u2022\\-\\d.]+\\s*/, '').trim();\n              if (cleaned) bullets.push(cleaned);\n            });\n        });\n      }\n    }\n\n    return { slideId: slide.id, title, bullets };\n  });\n}\n\nexport function normalizeSlide(\n  slide: Partial<Slide> & { id?: string },\n  theme: DeckTheme,\n  fallbackMasterId?: string\n): Slide {\n  const id = slide.id || uid('slide');\n  const json = slide.json ?? {\n    version: '6.0.0',\n    objects: [],\n    background: theme.colors.background,\n  };\n  const history =\n    Array.isArray(slide.history) && slide.history.length\n      ? slide.history.map((h) => String(h))\n      : [JSON.stringify(json)];\n  const historyIndex =\n    typeof slide.historyIndex === 'number'\n      ? Math.min(Math.max(0, slide.historyIndex), history.length - 1)\n      : history.length - 1;\n  return {\n    id,\n    name: slide.name || 'Diapositiva',\n    masterId: slide.masterId || fallbackMasterId || uid('master'),\n    layoutId: slide.layoutId || 'blank',\n    json,\n    notes: slide.notes || '',\n    hidden: !!slide.hidden,\n    transition: slide.transition || { type: 'cross-dissolve', duration: 0.4 },\n    builds: Array.isArray(slide.builds) ? slide.builds : [],\n    comments: Array.isArray(slide.comments) ? slide.comments : [],\n    history,\n    historyIndex,\n    narration: slide.narration,\n  };\n}\n\nexport function normalizeMasters(\n  masters: SlideMaster[] | undefined,\n  theme: DeckTheme\n): SlideMaster[] {\n  const def = createDefaultMaster(theme);\n  if (!masters?.length) return [def];\n  return masters.map((m) => ({\n    ...m,\n    chrome: { ...def.chrome, ...(m.chrome || {}) },\n    layouts: m.layouts?.length ? m.layouts : def.layouts,\n    backgroundColor: m.backgroundColor || theme.colors.background,\n    json: m.json || def.json,\n  }));\n}\n\n/** Push a new json onto per-slide history (for bulk mutations that must refresh Fabric). */\nexport function slideWithNewJson(slide: Slide, json: unknown): Slide {\n  const hist = Array.isArray(slide.history) ? slide.history : [JSON.stringify(slide.json)];\n  const idx = typeof slide.historyIndex === 'number' ? slide.historyIndex : hist.length - 1;\n  const history = [...hist.slice(0, idx + 1), JSON.stringify(json)].slice(-50);\n  return {\n    ...slide,\n    json,\n    history,\n    historyIndex: history.length - 1,\n  };\n}\n\nexport function applyOutlineToSlide(\n  slide: Slide,\n  theme: DeckTheme,\n  title: string,\n  bullets: string[],\n  layoutId?: SlideLayoutId\n): Slide {\n  const nextLayout =\n    layoutId || (slide.layoutId === 'blank' ? 'bullets' : slide.layoutId);\n  const { json } = buildSlideJsonFromLayout(nextLayout, theme, {\n    title,\n    bullets: bullets.map((b) => `\u2022 ${b}`).join('\\n'),\n    body: bullets.map((b) => `\u2022 ${b}`).join('\\n'),\n    subtitle: bullets[0] || '',\n  });\n  return {\n    ...slideWithNewJson(slide, json),\n    name: title.slice(0, 48) || slide.name,\n    layoutId: nextLayout,\n  };\n}\n\n/**\n * Patch translated title/body/notes onto existing Fabric objects.\n * Preserves images, shapes, charts, and layout \u2014 unlike applyOutlineToSlide\n * which rebuilds JSON from placeholders and wipes user media.\n *\n * `previous` (optional) enables exact string replace of the outline we sent\n * to the API \u2014 most reliable when roles are missing or duplicated.\n */\nexport function applyTranslatedTextsToSlide(\n  slide: Slide,\n  translated: { title: string; body: string; notes?: string },\n  previous?: { title?: string; body?: string }\n): Slide {\n  const titleText = (translated.title || '').trim();\n  const bodyText = (translated.body || '').trim();\n  const prevTitle = (previous?.title || '').trim();\n  const prevBody = (previous?.body || '').trim();\n  const bulletLines = bodyText\n    ? bodyText\n        .split('\\n')\n        .map((l) => l.replace(/^[\u2022\\-]\\s*/, '').trim())\n        .filter(Boolean)\n    : [];\n  const bulletsBlock =\n    bulletLines.length > 0 ? bulletLines.map((b) => `\u2022 ${b}`).join('\\n') : bodyText;\n  const prevBullets = prevBody\n    ? prevBody\n        .split('\\n')\n        .map((l) => l.replace(/^[\u2022\\-]\\s*/, '').trim())\n        .filter(Boolean)\n    : [];\n  const prevBulletsBlock =\n    prevBullets.length > 0 ? prevBullets.map((b) => `\u2022 ${b}`).join('\\n') : prevBody;\n\n  const json = structuredClone(slide.json) as {\n    version?: string;\n    objects?: Array<Record<string, unknown>>;\n    background?: unknown;\n  };\n  const objects = json.objects || [];\n  const flat = flattenSlideObjects(objects);\n\n  const roleOf = (o: Record<string, unknown>) =>\n    String(o.placeholderRole || o.name || o.themeRole || '').toLowerCase();\n\n  const textObjs = flat\n    .filter(isFabricTextObject)\n    .sort((a, b) => {\n      const dy = Number(a.top || 0) - Number(b.top || 0);\n      if (Math.abs(dy) > 8) return dy;\n      return Number(a.left || 0) - Number(b.left || 0);\n    });\n\n  let titleApplied = false;\n  let bodyApplied = false;\n\n  // 1) Exact replace of the strings we sent to translate-deck.\n  if (prevTitle && titleText && prevTitle !== titleText) {\n    for (const obj of textObjs) {\n      if (typeof obj.text !== 'string') continue;\n      if (obj.text === prevTitle || obj.text.startsWith(prevTitle)) {\n        obj.text = titleText;\n        titleApplied = true;\n      }\n    }\n  }\n  if (prevBody && bodyText && prevBody !== bodyText) {\n    for (const obj of textObjs) {\n      if (typeof obj.text !== 'string') continue;\n      const t = obj.text;\n      if (\n        t === prevBody ||\n        t === prevBulletsBlock ||\n        (prevBullets.length > 0 &&\n          prevBullets.every((b) => t.includes(b)) &&\n          t.length <= prevBulletsBlock.length + 8)\n      ) {\n        obj.text = bulletLines.length > 1 ? bulletsBlock : bodyText;\n        bodyApplied = true;\n      } else if (prevBullets.length > 0) {\n        for (let i = 0; i < prevBullets.length; i++) {\n          const pb = prevBullets[i]!;\n          if (t === pb || t === `\u2022 ${pb}` || t.replace(/^[\u2022\\-]\\s*/, '') === pb) {\n            obj.text = bulletLines[i] ? `\u2022 ${bulletLines[i]}` : t;\n            bodyApplied = true;\n          }\n        }\n      }\n    }\n  }\n\n  // 2) Role-based patch (layouts / generate-deck placeholders).\n  for (const obj of textObjs) {\n    const roleKey = roleOf(obj);\n    const themeKey = String(obj.themeRole || '').toLowerCase();\n\n    if (\n      roleKey === 'title' ||\n      themeKey === 'title' ||\n      roleKey === 'ph_title' ||\n      roleKey.endsWith('_title')\n    ) {\n      if (titleText) {\n        obj.text = titleText;\n        titleApplied = true;\n      }\n      continue;\n    }\n    if (\n      roleKey === 'subtitle' ||\n      themeKey === 'subtitle' ||\n      roleKey === 'ph_sub' ||\n      roleKey.includes('subtitle')\n    ) {\n      if (bulletLines[0]) obj.text = bulletLines[0];\n      else if (titleText && !bodyText) obj.text = titleText;\n      else if (bodyText && !bodyText.includes('\\n')) obj.text = bodyText;\n      continue;\n    }\n    if (roleKey === 'bullets' || roleKey === 'ph_bullets' || roleKey.includes('bullet')) {\n      if (bulletsBlock) {\n        obj.text = bulletsBlock;\n        bodyApplied = true;\n      }\n      continue;\n    }\n    if (\n      roleKey === 'body' ||\n      themeKey === 'body' ||\n      roleKey === 'ph_body' ||\n      roleKey === 'ph_left' ||\n      roleKey === 'ph_right'\n    ) {\n      if (bodyText) {\n        obj.text = bulletLines.length > 1 ? bulletsBlock : bodyText;\n        bodyApplied = true;\n      }\n      continue;\n    }\n    if (roleKey === 'quote' || roleKey.includes('quote')) {\n      if (bodyText || titleText) {\n        obj.text = bodyText || titleText;\n        bodyApplied = true;\n      }\n      continue;\n    }\n    if (roleKey === 'number') {\n      if (titleText) {\n        obj.text = titleText;\n        titleApplied = true;\n      }\n      continue;\n    }\n    if (roleKey === 'caption' || themeKey === 'caption' || themeKey === 'muted') {\n      if (bulletLines[0] || bodyText) obj.text = bulletLines[0] || bodyText;\n    }\n  }\n\n  // 3) Visual order fallback when roles / exact match missed.\n  if (textObjs.length > 0 && (titleText || bodyText)) {\n    if (!titleApplied && titleText && textObjs[0]) {\n      textObjs[0].text = titleText;\n      titleApplied = true;\n    }\n    if (bodyText) {\n      const rest = titleApplied ? textObjs.slice(1) : textObjs;\n      if (!bodyApplied && rest.length >= 1 && rest[0]) {\n        if (rest.length === 1) {\n          rest[0].text = bulletLines.length > 1 ? bulletsBlock : bodyText;\n        } else if (bulletLines.length > 0) {\n          rest.forEach((obj, i) => {\n            if (bulletLines[i]) obj.text = `\u2022 ${bulletLines[i]}`;\n          });\n          if (bulletLines.length > rest.length) {\n            rest[rest.length - 1]!.text = bulletLines\n              .slice(rest.length - 1)\n              .map((b) => `\u2022 ${b}`)\n              .join('\\n');\n          }\n        } else {\n          rest[0].text = bodyText;\n        }\n        bodyApplied = true;\n      }\n    }\n  }\n\n  const notes =\n    translated.notes != null && String(translated.notes).trim() !== ''\n      ? String(translated.notes)\n      : slide.notes;\n\n  return {\n    ...slideWithNewJson(slide, json),\n    name: titleText.slice(0, 48) || slide.name,\n    notes,\n  };\n}\n", "import type { DeckTheme, ThemeRole } from '../../types/slides.types';\n\nfunction colorForRole(theme: DeckTheme, role?: ThemeRole | string): string | undefined {\n  switch (role) {\n    case 'title':\n      return theme.colors.title;\n    case 'subtitle':\n    case 'body':\n      return theme.colors.body;\n    case 'caption':\n    case 'muted':\n      return theme.colors.muted;\n    case 'accent':\n      return theme.colors.accent;\n    case 'background':\n      return theme.colors.background;\n    case 'surface':\n      return theme.colors.surface;\n    default:\n      return undefined;\n  }\n}\n\nfunction fontSizeForRole(theme: DeckTheme, role?: ThemeRole | string): number | undefined {\n  switch (role) {\n    case 'title':\n    case 'accent':\n      return theme.typeScale.title;\n    case 'subtitle':\n      return theme.typeScale.subtitle;\n    case 'caption':\n    case 'muted':\n      return theme.typeScale.caption;\n    case 'body':\n      return theme.typeScale.body;\n    default:\n      return undefined;\n  }\n}\n\n/** Re-apply theme tokens to objects that declare themeRole. */\nexport function restyleSlideJson(json: unknown, theme: DeckTheme): unknown {\n  if (!json || typeof json !== 'object') return json;\n  const doc = structuredClone(json) as {\n    background?: string;\n    objects?: Array<Record<string, unknown>>;\n  };\n  doc.background = theme.colors.background;\n  if (!doc.objects) return doc;\n\n  for (const obj of doc.objects) {\n    const role = obj.themeRole as ThemeRole | undefined;\n    const fill = colorForRole(theme, role);\n    if (fill && (obj.type === 'Textbox' || obj.type === 'IText' || obj.type === 'Text')) {\n      obj.fill = fill;\n      const size = fontSizeForRole(theme, role);\n      if (size) obj.fontSize = size;\n      obj.fontFamily =\n        role === 'title' || role === 'accent' ? theme.fonts.title : theme.fonts.body;\n    }\n    if (obj.placeholderRole === 'image' || obj.placeholderRole === 'chart') {\n      if (obj.type === 'Rect') {\n        obj.fill = theme.colors.surface;\n        obj.stroke = theme.colors.muted;\n        obj.rx = theme.radii.md;\n        obj.ry = theme.radii.md;\n      }\n    }\n  }\n  return doc;\n}\n", "/**\n * Autofit / autoshrink text inside a Fabric Textbox until it fits its box.\n */\n\nexport interface AutofitResult {\n  fontSize: number;\n  overflow: boolean;\n  lines: number;\n}\n\n/** Shrink fontSize in steps until text height fits maxHeight (approx via canvas measure). */\nexport function autofitTextbox(opts: {\n  text: string;\n  width: number;\n  maxHeight: number;\n  fontFamily: string;\n  fontWeight?: string | number;\n  minFontSize?: number;\n  maxFontSize?: number;\n  lineHeight?: number;\n}): AutofitResult {\n  const min = opts.minFontSize ?? 10;\n  const max = opts.maxFontSize ?? 96;\n  const lineHeight = opts.lineHeight ?? 1.2;\n  const canvas = document.createElement('canvas');\n  const ctx = canvas.getContext('2d');\n  if (!ctx) return { fontSize: max, overflow: false, lines: 1 };\n\n  let lo = min;\n  let hi = max;\n  let best = min;\n  let overflow = true;\n  let lines = 1;\n\n  while (lo <= hi) {\n    const mid = Math.floor((lo + hi) / 2);\n    ctx.font = `${opts.fontWeight || 'normal'} ${mid}px ${opts.fontFamily}`;\n    const words = opts.text.split(/\\s+/);\n    let line = '';\n    let lineCount = 1;\n    for (const word of words) {\n      const test = line ? `${line} ${word}` : word;\n      if (ctx.measureText(test).width > opts.width && line) {\n        lineCount += 1;\n        line = word;\n      } else {\n        line = test;\n      }\n    }\n    // Also count explicit newlines\n    lineCount += (opts.text.match(/\\n/g) || []).length;\n    const height = lineCount * mid * lineHeight;\n    if (height <= opts.maxHeight) {\n      best = mid;\n      overflow = false;\n      lines = lineCount;\n      lo = mid + 1;\n    } else {\n      hi = mid - 1;\n      lines = lineCount;\n    }\n  }\n\n  if (best <= min) {\n    ctx.font = `${opts.fontWeight || 'normal'} ${min}px ${opts.fontFamily}`;\n    const height = lines * min * lineHeight;\n    overflow = height > opts.maxHeight;\n  }\n\n  return { fontSize: best, overflow, lines };\n}\n\nexport function markOverflow(obj: Record<string, unknown>, overflow: boolean): void {\n  obj.overflow = overflow;\n  if (overflow) {\n    obj.stroke = '#EF4444';\n    obj.strokeWidth = 1;\n  }\n}\n", "/**\n * Local accessibility / design heuristics for slides.\n */\n\nexport interface ContrastIssue {\n  objectId?: string;\n  severity: 'error' | 'warn' | 'info';\n  message: string;\n  slideIndex: number;\n}\n\nfunction hexToRgb(hex: string): { r: number; g: number; b: number } | null {\n  const m = hex.replace('#', '').trim();\n  if (m.length === 3) {\n    const r = parseInt(m[0]! + m[0]!, 16);\n    const g = parseInt(m[1]! + m[1]!, 16);\n    const b = parseInt(m[2]! + m[2]!, 16);\n    return { r, g, b };\n  }\n  if (m.length !== 6) return null;\n  return {\n    r: parseInt(m.slice(0, 2), 16),\n    g: parseInt(m.slice(2, 4), 16),\n    b: parseInt(m.slice(4, 6), 16),\n  };\n}\n\nfunction relLuminance(hex: string): number {\n  const rgb = hexToRgb(hex);\n  if (!rgb) return 0;\n  const lin = [rgb.r, rgb.g, rgb.b].map((c) => {\n    const s = c / 255;\n    return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);\n  });\n  return 0.2126 * lin[0]! + 0.7152 * lin[1]! + 0.0722 * lin[2]!;\n}\n\nexport function contrastRatio(fg: string, bg: string): number {\n  const L1 = relLuminance(fg);\n  const L2 = relLuminance(bg);\n  const light = Math.max(L1, L2);\n  const dark = Math.min(L1, L2);\n  return (light + 0.05) / (dark + 0.05);\n}\n\nexport function auditSlideContrast(\n  slideIndex: number,\n  json: unknown,\n  background: string\n): ContrastIssue[] {\n  const issues: ContrastIssue[] = [];\n  const objects = (json as { objects?: Array<Record<string, unknown>> })?.objects || [];\n  for (const obj of objects) {\n    if (obj.type !== 'Textbox' && obj.type !== 'IText' && obj.type !== 'Text') continue;\n    const fill = typeof obj.fill === 'string' ? obj.fill : '';\n    if (!fill.startsWith('#')) continue;\n    const ratio = contrastRatio(fill, background);\n    const fontSize = Number(obj.fontSize || 16);\n    const need = fontSize >= 24 ? 3 : 4.5;\n    if (ratio < need) {\n      issues.push({\n        objectId: String(obj.id || ''),\n        slideIndex,\n        severity: ratio < 3 ? 'error' : 'warn',\n        message: `Contraste ${ratio.toFixed(1)}:1 (min ${need}:1 WCAG AA) en texto \"${String(obj.text || '').slice(0, 32)}\"`,\n      });\n    }\n    if (!obj.alt && obj.placeholderRole === 'image') {\n      issues.push({\n        slideIndex,\n        severity: 'warn',\n        message: 'Imagen sin texto alternativo (alt)',\n        objectId: String(obj.id || ''),\n      });\n    }\n  }\n  // Images without alt\n  for (const obj of objects) {\n    if (obj.type === 'Image' || obj.type === 'FabricImage') {\n      if (!obj.alt) {\n        issues.push({\n          slideIndex,\n          severity: 'info',\n          message: 'Imagen sin alt text',\n          objectId: String(obj.id || ''),\n        });\n      }\n    }\n  }\n  return issues;\n}\n\nexport function suggestReadableFill(bg: string): string {\n  return relLuminance(bg) > 0.5 ? '#12121A' : '#F0F0F5';\n}\n", "/**\n * Actionable design fixes applied locally to slide JSON.\n */\n\nimport { autofitTextbox, markOverflow } from './autofit';\nimport { suggestReadableFill } from './a11y';\nimport type { DeckTheme } from '../../types/slides.types';\n\nexport type DesignFixKind =\n  | 'condense-text'\n  | 'fix-contrast'\n  | 'autofit'\n  | 'split-dense'\n  | 'ensure-alt';\n\nexport function applyDesignFixToJson(\n  json: unknown,\n  kind: DesignFixKind,\n  theme: DeckTheme\n): { json: unknown; note: string } {\n  const doc = structuredClone(json) as { objects?: Array<Record<string, unknown>>; background?: string };\n  const objects = doc.objects || [];\n  let note = '';\n\n  if (kind === 'fix-contrast') {\n    const bg = typeof doc.background === 'string' ? doc.background : theme.colors.background;\n    const fill = suggestReadableFill(bg);\n    for (const obj of objects) {\n      if (obj.type === 'Textbox' || obj.type === 'IText' || obj.type === 'Text') {\n        obj.fill = fill;\n      }\n    }\n    note = 'Contraste de texto corregido';\n  }\n\n  if (kind === 'condense-text') {\n    for (const obj of objects) {\n      if (typeof obj.text !== 'string') continue;\n      const lines = obj.text\n        .split('\\n')\n        .map((l) => l.trim())\n        .filter(Boolean)\n        .slice(0, 6)\n        .map((l) => (l.length > 72 ? `${l.slice(0, 69)}...` : l));\n      obj.text = lines.join('\\n');\n    }\n    note = 'Texto condensado (max 6 lineas)';\n  }\n\n  if (kind === 'autofit') {\n    for (const obj of objects) {\n      if (typeof obj.text !== 'string') continue;\n      const width = Number(obj.width || 400) * Number(obj.scaleX || 1);\n      const height = Number(obj.height || 100) * Number(obj.scaleY || 1);\n      const result = autofitTextbox({\n        text: obj.text,\n        width,\n        maxHeight: height,\n        fontFamily: String(obj.fontFamily || theme.fonts.body),\n        maxFontSize: Number(obj.fontSize || 48),\n      });\n      obj.fontSize = result.fontSize;\n      markOverflow(obj, result.overflow);\n    }\n    note = 'Autofit aplicado';\n  }\n\n  if (kind === 'ensure-alt') {\n    let n = 0;\n    for (const obj of objects) {\n      if ((obj.type === 'Image' || obj.type === 'FabricImage' || obj.placeholderRole === 'image') && !obj.alt) {\n        obj.alt = obj.name || 'Imagen de diapositiva';\n        n += 1;\n      }\n    }\n    note = `Alt text anadido a ${n} imagenes`;\n  }\n\n  doc.objects = objects;\n  return { json: doc, note: note || kind };\n}\n\n/** Semantic restyle: board / sales / internal density + tone labels in content. */\nexport function semanticRestyleJson(\n  json: unknown,\n  mode: 'board' | 'sales' | 'internal',\n  theme: DeckTheme\n): unknown {\n  let next = json;\n  if (mode === 'board') {\n    next = applyDesignFixToJson(json, 'condense-text', theme).json;\n    next = applyDesignFixToJson(next, 'autofit', theme).json;\n  } else if (mode === 'sales') {\n    const doc = structuredClone(json) as { objects?: Array<Record<string, unknown>> };\n    for (const obj of doc.objects || []) {\n      if (obj.themeRole === 'accent' || obj.placeholderRole === 'number') {\n        obj.fill = theme.colors.accent;\n      }\n      if (obj.placeholderRole === 'title' && typeof obj.text === 'string') {\n        obj.text = obj.text.replace(/\\.$/, '');\n      }\n    }\n    next = doc;\n  } else {\n    // internal \u2014 denser body ok, muted titles\n    const doc = structuredClone(json) as { objects?: Array<Record<string, unknown>> };\n    for (const obj of doc.objects || []) {\n      if (obj.themeRole === 'title') obj.fill = theme.colors.body;\n    }\n    next = doc;\n  }\n  return next;\n}\n", "/**\n * Local magic layout \u2014 reflow elements with visual hierarchy (no backend required).\n */\n\nexport interface LayoutElement {\n  id: string;\n  type: string;\n  text?: string;\n  role?: string;\n  width: number;\n  height: number;\n  left?: number;\n  top?: number;\n}\n\nexport interface Placement {\n  id: string;\n  left: number;\n  top: number;\n  width: number;\n  height: number;\n}\n\nexport function computeMagicLayout(\n  elements: LayoutElement[],\n  canvas: { width: number; height: number },\n  margin = 80\n): Placement[] {\n  const w = canvas.width;\n  const h = canvas.height;\n  const contentW = w - margin * 2;\n\n  const title = elements.find((e) => e.role === 'title' || /title/i.test(e.type));\n  const images = elements.filter((e) => e.role === 'image' || e.type === 'Image' || e.type === 'FabricImage');\n  const charts = elements.filter((e) => e.role === 'chart');\n  const bodies = elements.filter(\n    (e) => e !== title && !images.includes(e) && !charts.includes(e)\n  );\n\n  const placements: Placement[] = [];\n  let y = margin;\n\n  if (title) {\n    placements.push({\n      id: title.id,\n      left: margin,\n      top: y,\n      width: contentW,\n      height: Math.min(title.height || 90, 120),\n    });\n    y += 140;\n  }\n\n  const media = [...images, ...charts];\n  if (media.length === 1 && bodies.length) {\n    const m = media[0]!;\n    const mediaW = Math.round(contentW * 0.48);\n    placements.push({\n      id: m.id,\n      left: margin,\n      top: y,\n      width: mediaW,\n      height: Math.min(h - y - margin, Math.round(mediaW * 0.7)),\n    });\n    const textX = margin + mediaW + 40;\n    const textW = w - textX - margin;\n    let ty = y;\n    for (const b of bodies) {\n      const bh = Math.min(b.height || 160, h - ty - margin);\n      placements.push({ id: b.id, left: textX, top: ty, width: textW, height: bh });\n      ty += bh + 24;\n    }\n    return placements;\n  }\n\n  if (media.length >= 2) {\n    const colW = (contentW - 24) / 2;\n    media.forEach((m, i) => {\n      placements.push({\n        id: m.id,\n        left: margin + (i % 2) * (colW + 24),\n        top: y + Math.floor(i / 2) * (colW * 0.65 + 24),\n        width: colW,\n        height: colW * 0.65,\n      });\n    });\n    y += Math.ceil(media.length / 2) * (colW * 0.65 + 24);\n  } else if (media.length === 1) {\n    const m = media[0]!;\n    placements.push({\n      id: m.id,\n      left: margin,\n      top: y,\n      width: contentW,\n      height: Math.min(420, h - y - margin - bodies.length * 100),\n    });\n    y += placements[placements.length - 1]!.height + 32;\n  }\n\n  const remaining = Math.max(120, h - y - margin);\n  const per = bodies.length ? remaining / bodies.length : remaining;\n  bodies.forEach((b, i) => {\n    placements.push({\n      id: b.id,\n      left: margin,\n      top: y + i * per,\n      width: contentW,\n      height: Math.min(b.height || per - 16, per - 16),\n    });\n  });\n\n  // Unmatched elements keep a safe stack\n  for (const el of elements) {\n    if (!placements.find((p) => p.id === el.id)) {\n      placements.push({\n        id: el.id,\n        left: margin,\n        top: margin,\n        width: el.width || 400,\n        height: el.height || 80,\n      });\n    }\n  }\n\n  return placements;\n}\n\n/**\n * Scale object coords when changing deck size.\n * Uses independent sx/sy so a round-trip (A\u2192B\u2192A) restores geometry;\n * fonts use geometric mean so they also invert.\n */\nexport function reflowSlideJson(\n  json: unknown,\n  from: { width: number; height: number },\n  to: { width: number; height: number }\n): unknown {\n  if (!json || typeof json !== 'object') return json;\n  const sx = to.width / Math.max(1, from.width);\n  const sy = to.height / Math.max(1, from.height);\n  if (Math.abs(sx - 1) < 1e-9 && Math.abs(sy - 1) < 1e-9) return json;\n  const fontScale = Math.sqrt(sx * sy);\n  const doc = structuredClone(json) as {\n    objects?: Array<Record<string, unknown>>;\n    background?: string;\n  };\n  if (!doc.objects) return doc;\n  doc.objects = doc.objects.map((o) => {\n    const next: Record<string, unknown> = { ...o };\n    if (typeof o.left === 'number') next.left = o.left * sx;\n    if (typeof o.top === 'number') next.top = o.top * sy;\n    if (typeof o.width === 'number') next.width = o.width * sx;\n    if (typeof o.height === 'number') next.height = o.height * sy;\n    if (typeof o.fontSize === 'number') {\n      next.fontSize = Math.max(8, Math.round(o.fontSize * fontScale));\n    }\n    // Keep object-local scale; geometry already remapped via width/height/left/top.\n    if (typeof o.scaleX === 'number') next.scaleX = o.scaleX;\n    if (typeof o.scaleY === 'number') next.scaleY = o.scaleY;\n    if (typeof o.radius === 'number') next.radius = o.radius * Math.min(sx, sy);\n    if (typeof o.rx === 'number') next.rx = o.rx * sx;\n    if (typeof o.ry === 'number') next.ry = o.ry * sy;\n    return next;\n  });\n  return doc;\n}\n", "/**\n * Stock photo service \u2014 AI image search backed by the .NET backend at\n * /api/stock/search. The .NET routes to Unsplash/Pexels server-side and\n * returns a unified shape regardless of source.\n *\n * Replaces the old client-side dual-fetch (Unsplash + Pexels APIs in\n * parallel with provider routing and download tracking). Those concerns\n * moved server-side; the editor just passes the query.\n */\n\nimport { getEditorIdentity } from './identity';\nimport { getWizardApiClient } from './wizardApiClient';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * A stock photo result. The `provider` field comes from the .NET\n * (`\"unsplash\"`, `\"pexels\"`, or whatever the backend adds later) \u2014 typed\n * as string to stay open-ended. The `downloadTrackUrl` was only relevant\n * for the old direct-Unsplash flow; the .NET handles download tracking\n * server-side, so it is no longer present in the response.\n */\nexport interface StockPhoto {\n  id: string;\n  provider: string;\n  thumbnailUrl: string;\n  regularUrl: string;\n  fullUrl: string;\n  width: number;\n  height: number;\n  alt: string;\n  photographer: string;\n  photographerUrl: string;\n  color?: string;\n}\n\nexport interface StockSearchResult {\n  photos: StockPhoto[];\n  totalResults: number;\n  page: number;\n  perPage: number;\n}\n\n// \u2500\u2500 GET /api/stock/search \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface SearchStockOptions {\n  /** Search query. Free text; empty/whitespace returns the .NET default (curated). */\n  q: string;\n  /** 1-indexed page number. .NET DTO marks it required, so we always send it. */\n  page: number;\n  /** Results per page. .NET DTO marks it required, so we always send it. */\n  perPage: number;\n  signal?: AbortSignal;\n}\n\n/**\n * Searches the .NET stock-photo backend. Returns `{ photos, totalResults, page, perPage }`.\n * The .NET itself routes to one or more providers (Unsplash, Pexels) \u2014 the\n * editor doesn't choose.\n */\nexport async function searchStock(\n  opts: SearchStockOptions\n): Promise<StockSearchResult> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().getForJson<StockSearchResult>(\n    '/api/stock/search',\n    {\n      q: opts.q,\n      page: opts.page,\n      perPage: opts.perPage,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n}\n\nexport interface StockImageBlob {\n  blob: Blob;\n  /** Original remote URL that was downloaded. */\n  sourceUrl: string;\n  objectUrl: string;\n  file: File;\n}\n\nfunction pickStockImageUrl(photo: StockPhoto): string {\n  return photo.regularUrl || photo.fullUrl || photo.thumbnailUrl;\n}\n\nasync function tryFetchBlob(\n  fetchUrl: string,\n  signal?: AbortSignal,\n  withCredentials = false,\n): Promise<Blob | null> {\n  try {\n    const res = await fetch(fetchUrl, {\n      signal,\n      credentials: withCredentials ? 'include' : 'omit',\n    });\n    if (!res.ok) return null;\n    const blob = await res.blob();\n    if (!blob || blob.size === 0) return null;\n    return blob;\n  } catch {\n    return null;\n  }\n}\n\n/**\n * Download a stock photo as a same-origin blob.\n * Direct CDN fetch often fails CORS from localhost; fall back to Wizard\n * `/api/download` BFF (same pattern as My Files).\n */\nexport async function downloadStockPhoto(\n  photo: StockPhoto,\n  opts?: { signal?: AbortSignal; filename?: string },\n): Promise<StockImageBlob> {\n  const sourceUrl = pickStockImageUrl(photo);\n  if (!sourceUrl) {\n    throw new Error('Stock photo has no downloadable URL');\n  }\n\n  const filename =\n    opts?.filename ||\n    `stock_${photo.provider || 'img'}_${String(photo.id).replace(/\\W/g, '_')}.jpg`;\n\n  // 1) Direct CDN (no credentials \u2014 include often breaks CORS preflight)\n  let blob = await tryFetchBlob(sourceUrl, opts?.signal, false);\n\n  // 2) Wizard download proxy (cookie auth, bypasses CDN CORS)\n  if (!blob) {\n    const proxy = `/api/download?mode=download&filename=${encodeURIComponent(\n      filename,\n    )}&url=${encodeURIComponent(sourceUrl)}`;\n    blob = await tryFetchBlob(proxy, opts?.signal, true);\n  }\n\n  if (!blob) {\n    throw new Error('Failed to download stock image');\n  }\n\n  const typed = blob.type.startsWith('image/')\n    ? blob\n    : new Blob([blob], { type: 'image/jpeg' });\n  const file = new File([typed], filename, { type: typed.type || 'image/jpeg' });\n  const objectUrl = URL.createObjectURL(typed);\n  return { blob: typed, sourceUrl, objectUrl, file };\n}\n", "import { Chart, registerables } from 'chart.js';\nimport ChartDataLabels from 'chartjs-plugin-datalabels';\n\nChart.register(...registerables);\n// Never register ChartDataLabels globally \u2014 pass it per-chart only.\n// Global + per-chart (or double global via HMR) paints every label twice.\ntry {\n  Chart.unregister(ChartDataLabels);\n} catch {\n  // not registered yet\n}\n\nexport type ChartType = 'bar' | 'line' | 'pie' | 'donut';\n\nexport interface ChartDataPoint {\n  label: string;\n  value: number;\n  color: string;\n}\n\nexport interface ChartOptions {\n  width: number;\n  height: number;\n  showLabels?: boolean;\n  backgroundColor?: string;\n  textColor?: string;\n  theme?: 'dark' | 'light';\n}\n\nconst defaultColors = [\n  '#6366f1',\n  '#ec4899',\n  '#14b8a6',\n  '#f59e0b',\n  '#8b5cf6',\n  '#3b82f6',\n  '#10b981',\n];\n\nexport async function generateChartImage(\n  type: ChartType,\n  data: ChartDataPoint[],\n  options: ChartOptions,\n): Promise<string> {\n  if (!data || data.length === 0) return '';\n\n  const {\n    width,\n    height,\n    showLabels = true,\n    backgroundColor = 'transparent',\n    theme = 'dark',\n    textColor: userTextColor,\n  } = options;\n\n  const isDark = theme === 'dark';\n  const textColor = userTextColor || (isDark ? '#f3f4f6' : '#1f2937');\n  const gridColor = isDark ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)';\n\n  // Manual retina: size canvas at 2x, keep Chart.js DPR at 1, scale the ctx.\n  // Avoids Chart.js resizing the canvas mid-draw (source of ghost/duplicate labels).\n  const dpr = 2;\n  const canvas = document.createElement('canvas');\n  canvas.width = Math.max(1, Math.round(width * dpr));\n  canvas.height = Math.max(1, Math.round(height * dpr));\n  canvas.style.width = `${width}px`;\n  canvas.style.height = `${height}px`;\n\n  const ctx = canvas.getContext('2d');\n  if (!ctx) return '';\n  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n  const labels = data.map((d) => d.label);\n  const values = data.map((d) => d.value);\n  const baseColors = data.map(\n    (d, i) => d.color || defaultColors[i % defaultColors.length]!,\n  );\n\n  const chartJsType: 'bar' | 'line' | 'pie' | 'doughnut' =\n    type === 'donut' ? 'doughnut' : type;\n\n  const chart = new Chart(ctx, {\n    type: chartJsType,\n    data: {\n      labels,\n      datasets: [\n        {\n          label: 'Datos',\n          data: values,\n          // Solid fills \u2014 no alpha gradients (looked like overall opacity).\n          backgroundColor: baseColors,\n          borderColor:\n            type === 'line'\n              ? baseColors[0]\n              : isDark\n                ? '#1f2937'\n                : '#ffffff',\n          borderWidth: type === 'line' ? 3 : type === 'bar' ? 0 : 2,\n          borderRadius: type === 'bar' ? 6 : 0,\n          borderSkipped: false,\n          fill: false,\n          tension: 0.35,\n          pointRadius: type === 'line' ? 5 : 0,\n          pointBackgroundColor: isDark ? '#1f2937' : '#ffffff',\n          pointBorderColor: type === 'line' ? baseColors[0] : 'transparent',\n          pointBorderWidth: 2,\n        },\n      ],\n    },\n    options: {\n      responsive: false,\n      maintainAspectRatio: false,\n      animation: false,\n      devicePixelRatio: 1,\n      layout: {\n        padding: { top: 28, right: 24, bottom: 16, left: 16 },\n      },\n      cutout: type === 'donut' ? '70%' : undefined,\n      plugins: {\n        legend: {\n          display: true,\n          position: 'bottom',\n          labels: {\n            color: textColor,\n            font: { family: \"'Inter', sans-serif\", size: 12, weight: 600 },\n            padding: 16,\n            usePointStyle: true,\n            pointStyle: 'circle',\n          },\n        },\n        tooltip: { enabled: false },\n        datalabels: {\n          display: !!showLabels,\n          color: '#ffffff',\n          backgroundColor: (ctx: { chart: { config: { type?: string } } }) => {\n            const t = ctx.chart.config.type;\n            if (t === 'pie' || t === 'doughnut') return 'transparent';\n            return 'rgba(0, 0, 0, 0.75)';\n          },\n          borderRadius: 4,\n          padding: { top: 3, bottom: 3, left: 6, right: 6 },\n          font: { weight: 'bold', family: \"'Inter', sans-serif\", size: 11 },\n          clamp: true,\n          clip: true,\n          formatter: (value: number, context: { dataset: { data: number[] } }) => {\n            if (type === 'pie' || type === 'donut') {\n              const total = context.dataset.data.reduce((a, b) => a + b, 0);\n              if (!total) return '0%';\n              const pct = (value / total) * 100;\n              return pct < 1 ? '<1%' : `${Math.round(pct)}%`;\n            }\n            return String(value);\n          },\n          anchor: type === 'bar' ? 'end' : 'center',\n          align: type === 'bar' ? 'end' : 'center',\n          offset: type === 'bar' ? 4 : 0,\n        },\n      },\n      scales:\n        type === 'pie' || type === 'donut'\n          ? {}\n          : {\n              x: {\n                grid: { display: false, drawBorder: false },\n                ticks: {\n                  color: textColor,\n                  font: { family: \"'Inter', sans-serif\", size: 11, weight: 500 },\n                  padding: 8,\n                },\n              },\n              y: {\n                beginAtZero: true,\n                grid: {\n                  color: gridColor,\n                  drawBorder: false,\n                },\n                ticks: {\n                  color: textColor,\n                  font: { family: \"'Inter', sans-serif\", size: 11, weight: 500 },\n                  padding: 10,\n                  maxTicksLimit: 6,\n                },\n              },\n            },\n    },\n    plugins: [\n      ChartDataLabels,\n      {\n        id: 'customCanvasBackgroundColor',\n        beforeDraw: (c: Chart) => {\n          if (!backgroundColor || backgroundColor === 'transparent') return;\n          const { ctx: cctx, width: w, height: h } = c;\n          cctx.save();\n          cctx.globalCompositeOperation = 'destination-over';\n          cctx.fillStyle = backgroundColor;\n          cctx.fillRect(0, 0, w, h);\n          cctx.restore();\n        },\n      },\n    ],\n  });\n\n  // Synchronous draw \u2014 no rAF/timeout (avoids a second paint pass).\n  chart.update('none');\n  const base64 = canvas.toDataURL('image/png', 1.0);\n  chart.destroy();\n  return base64;\n}\n", "/**\n * Native chart objects for slides \u2014 chart.js raster with editable chartData payload.\n */\n\nimport { Chart, registerables } from 'chart.js';\nimport { generateChartImage, type ChartType } from '../../utils/chartUtils';\nimport type { DeckTheme } from '../../types/slides.types';\n\nChart.register(...registerables);\n\nexport interface SlideChartData {\n  chartType: ChartType;\n  labels: string[];\n  series: Array<{ name: string; data: number[] }>;\n}\n\nconst SERIES_COLORS = [\n  '#6366f1',\n  '#ec4899',\n  '#14b8a6',\n  '#f59e0b',\n  '#8b5cf6',\n  '#3b82f6',\n  '#10b981',\n];\n\nfunction uid(): string {\n  return `obj_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nasync function renderMultiSeriesChart(\n  data: SlideChartData,\n  theme: DeckTheme,\n  width: number,\n  height: number\n): Promise<string> {\n  if (!data.labels.length || !data.series.length) return '';\n\n  // Single series \u2192 reuse existing helper (labels per point)\n  if (data.series.length === 1) {\n    const series0 = data.series[0]!.data;\n    const points = data.labels.map((label, i) => ({\n      label,\n      value: series0[i] ?? 0,\n      color: theme.colors.accent || SERIES_COLORS[0]!,\n    }));\n    return generateChartImage(data.chartType, points, {\n      width,\n      height,\n      backgroundColor: theme.colors.surface,\n      theme: 'dark',\n      textColor: theme.colors.body,\n      showLabels: true,\n    });\n  }\n\n  const canvas = document.createElement('canvas');\n  const scale = 2;\n  canvas.width = width * scale;\n  canvas.height = height * scale;\n  const ctx = canvas.getContext('2d');\n  if (!ctx) return '';\n\n  let chartJsType: 'bar' | 'line' | 'pie' | 'doughnut' = 'bar';\n  if (data.chartType === 'line') chartJsType = 'line';\n  else if (data.chartType === 'pie') chartJsType = 'pie';\n  else if (data.chartType === 'donut') chartJsType = 'doughnut';\n\n  const chart = new Chart(ctx, {\n    type: chartJsType,\n    data: {\n      labels: data.labels,\n      datasets: data.series.map((s, i) => ({\n        label: s.name,\n        data: s.data,\n        backgroundColor: SERIES_COLORS[i % SERIES_COLORS.length],\n        borderColor: SERIES_COLORS[i % SERIES_COLORS.length],\n        borderWidth: chartJsType === 'line' ? 3 : 0,\n        fill: false,\n        tension: 0.35,\n      })),\n    },\n    options: {\n      responsive: false,\n      animation: false,\n      devicePixelRatio: scale,\n      plugins: {\n        legend: {\n          display: true,\n          labels: { color: theme.colors.body },\n        },\n      },\n      scales:\n        chartJsType === 'pie' || chartJsType === 'doughnut'\n          ? undefined\n          : {\n              x: { ticks: { color: theme.colors.muted }, grid: { color: 'rgba(255,255,255,0.08)' } },\n              y: { ticks: { color: theme.colors.muted }, grid: { color: 'rgba(255,255,255,0.08)' } },\n            },\n    },\n  });\n  await new Promise((r) => setTimeout(r, 30));\n  const url = canvas.toDataURL('image/png');\n  chart.destroy();\n  return url;\n}\n\nexport async function buildChartFabricObject(\n  data: SlideChartData,\n  theme: DeckTheme,\n  box: { left: number; top: number; width: number; height: number }\n): Promise<Record<string, unknown>> {\n  const src = await renderMultiSeriesChart(\n    data,\n    theme,\n    Math.round(box.width),\n    Math.round(box.height)\n  );\n  return {\n    type: 'Image',\n    version: '6.0.0',\n    left: box.left,\n    top: box.top,\n    width: box.width,\n    height: box.height,\n    scaleX: 1,\n    scaleY: 1,\n    src,\n    id: uid(),\n    placeholderRole: 'chart',\n    name: 'chart',\n    alt: `Grafico ${data.chartType}: ${data.labels.join(', ')}`,\n    chartData: data,\n  };\n}\n\nexport function chartDataToPptxSeries(data: SlideChartData): {\n  chartType: 'bar' | 'line' | 'pie';\n  labels: string[];\n  series: Array<{ name: string; values: number[] }>;\n} {\n  const chartType =\n    data.chartType === 'line' ? 'line' : data.chartType === 'pie' || data.chartType === 'donut' ? 'pie' : 'bar';\n  return {\n    chartType,\n    labels: data.labels,\n    series: data.series.map((s) => ({ name: s.name, values: s.data })),\n  };\n}\n", "/**\n * Bind Fabric slide images to SlidesAsset registry so reloads survive.\n * Fabric's toObject() stores element.src (often a dead blob: URL after refresh).\n * We keep assetId on the object and rehydrate from IndexedDB blobs / data URLs.\n */\n\nimport type { FabricImage } from 'fabric';\nimport type { SlidesAsset } from '../../types/slides.types';\n\ntype FabricLikeObject = {\n  type?: string;\n  src?: string;\n  assetId?: string;\n  setSrc?: (src: string, opts?: { crossOrigin?: string | null }) => Promise<void>;\n};\n\ntype SlideJson = {\n  objects?: FabricLikeObject[];\n  [key: string]: unknown;\n};\n\nexport function isFabricImageType(type: unknown): boolean {\n  const t = String(type || '').toLowerCase();\n  return t === 'image' || t === 'fabricimage';\n}\n\nexport function fileToDataUrl(file: Blob): Promise<string> {\n  return new Promise((resolve, reject) => {\n    const reader = new FileReader();\n    reader.onload = () => resolve(String(reader.result || ''));\n    reader.onerror = () => reject(reader.error ?? new Error('FileReader failed'));\n    reader.readAsDataURL(file);\n  });\n}\n\n/**\n * Make slide JSON durable for IndexedDB: prefer data URLs from asset files\n * so loadFromJSON works even before canvas rebind. Trim nothing here \u2014 caller\n * should drop heavy history separately.\n */\nexport async function materializeSlideJsonAssets(\n  json: unknown,\n  assets: SlidesAsset[]\n): Promise<unknown> {\n  if (!json || typeof json !== 'object') return json;\n  const clone = structuredClone(json) as SlideJson;\n  const objects = clone.objects;\n  if (!Array.isArray(objects)) return clone;\n\n  const byId = new Map(assets.map((a) => [a.id, a]));\n\n  for (const obj of objects) {\n    if (!isFabricImageType(obj.type)) continue;\n    const asset = obj.assetId ? byId.get(obj.assetId) : undefined;\n    if (asset?.file) {\n      try {\n        obj.src = await fileToDataUrl(asset.file);\n        continue;\n      } catch {\n        /* fall through */\n      }\n    }\n    const src = typeof obj.src === 'string' ? obj.src : '';\n    // Still-live blob from this session: bake into data URL.\n    if (src.startsWith('blob:')) {\n      try {\n        const res = await fetch(src);\n        if (res.ok) {\n          const blob = await res.blob();\n          obj.src = await fileToDataUrl(blob);\n        }\n      } catch {\n        /* leave as-is; rebind may still recover via assetId */\n      }\n    }\n  }\n\n  return clone;\n}\n\n/** After canvas.loadFromJSON, point images at fresh asset blob URLs. */\nexport async function rebindCanvasImageAssets(\n  canvas: {\n    getObjects: () => FabricLikeObject[];\n    requestRenderAll: () => void;\n  },\n  assets: SlidesAsset[]\n): Promise<void> {\n  const byId = new Map(assets.map((a) => [a.id, a]));\n  let changed = false;\n\n  for (const obj of canvas.getObjects()) {\n    if (!isFabricImageType(obj.type)) continue;\n    const asset = obj.assetId ? byId.get(obj.assetId) : undefined;\n    const nextUrl = asset?.url;\n    if (!nextUrl || typeof obj.setSrc !== 'function') continue;\n    const current = typeof obj.src === 'string' ? obj.src : '';\n    if (current === nextUrl) continue;\n    try {\n      await obj.setSrc(nextUrl, {\n        crossOrigin:\n          nextUrl.startsWith('blob:') || nextUrl.startsWith('data:')\n            ? null\n            : 'anonymous',\n      });\n      changed = true;\n    } catch (err) {\n      console.warn('[slides] rebind asset failed', obj.assetId, err);\n    }\n  }\n\n  if (changed) canvas.requestRenderAll();\n}\n\n/** Attach assetId on a Fabric image (mutates object). */\nexport function stampImageAssetId(\n  img: FabricImage & { assetId?: string },\n  assetId: string\n): void {\n  img.assetId = assetId;\n}\n", "/**\n * Apply an enriched generate-deck response to the live slides store:\n * themeHint \u2192 DeckTheme, full copy per layout, shapes, images, charts.\n */\n\nimport { generateImage } from '../../services/imageService';\nimport { searchStock, downloadStockPhoto } from '../../services/stockService';\nimport { proxySlideImage } from '../../services/slides/deckService';\nimport type {\n  GenerateDeckBrandContext,\n  GenerateDeckVisualPolicy,\n  GeneratedSlideSpec,\n} from '../../services/slides/deckService';\nimport type { DeckTheme, Slide, SlideLayoutId, SlidesAsset } from '../../types/slides.types';\nimport { DEFAULT_THEME, DARK_THEME } from './themes';\nimport {\n  createEmptySlide,\n  getLayout,\n  slideWithNewJson,\n} from './layouts';\nimport { buildChartFabricObject, type SlideChartData } from './chartBridge';\nimport { fileToDataUrl } from './mediaAssets';\nimport type { ChartType } from '../../utils/chartUtils';\n\nexport type GenerateDeckThemeHint = {\n  background?: string;\n  surface?: string;\n  title?: string;\n  body?: string;\n  accent?: string;\n  muted?: string;\n  fonts?: { title?: string; body?: string };\n  typeScale?: {\n    title?: number;\n    subtitle?: number;\n    body?: number;\n    caption?: number;\n  };\n  mood?: string;\n};\n\nexport type GeneratedSlideShape = {\n  type?: string;\n  role?: string;\n  fillRole?: string;\n  hint?: string;\n};\n\nexport type GeneratedSlideImage = {\n  source?: string;\n  url?: string;\n  alt?: string;\n};\n\nexport type GeneratedSlideChartHint = {\n  chartType?: string;\n  labels?: string[];\n  series?: Array<{ name?: string; data?: number[] }>;\n  insight?: string;\n};\n\n/** Full slide spec from enriched generate-deck. */\nexport type EnrichedGeneratedSlide = GeneratedSlideSpec & {\n  kicker?: string;\n  quote?: string;\n  attribution?: string;\n  leftTitle?: string;\n  rightTitle?: string;\n  leftBullets?: string[];\n  rightBullets?: string[];\n  shapes?: GeneratedSlideShape[];\n  image?: GeneratedSlideImage;\n  chartHint?: string | GeneratedSlideChartHint | null;\n  visualHierarchy?: {\n    emphasis?: string;\n    density?: string;\n    align?: string;\n  };\n};\n\nexport type GenerateDeckResponse = {\n  deckTitle?: string;\n  themeHint?: GenerateDeckThemeHint | null;\n  slides: EnrichedGeneratedSlide[];\n};\n\nconst LAYOUT_IDS = new Set<string>([\n  'blank',\n  'title',\n  'title-subtitle',\n  'section',\n  'title-body',\n  'two-column',\n  'image-left',\n  'image-right',\n  'quote',\n  'bullets',\n  'comparison',\n  'agenda',\n  'closing',\n  'chart',\n  'big-number',\n]);\n\nfunction uid(prefix: string): string {\n  return `${prefix}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction asRecord(v: unknown): Record<string, unknown> | null {\n  return typeof v === 'object' && v !== null ? (v as Record<string, unknown>) : null;\n}\n\nfunction asString(v: unknown): string | undefined {\n  return typeof v === 'string' && v.trim() ? v.trim() : undefined;\n}\n\nfunction asStringArray(v: unknown): string[] | undefined {\n  if (!Array.isArray(v)) return undefined;\n  const out = v.map((x) => (typeof x === 'string' ? x.trim() : '')).filter(Boolean);\n  return out.length ? out : undefined;\n}\n\nfunction normalizeLayoutId(raw: unknown): SlideLayoutId {\n  const id = typeof raw === 'string' ? raw.trim() : '';\n  if (LAYOUT_IDS.has(id)) return id as SlideLayoutId;\n  return 'bullets';\n}\n\nfunction normalizeChartHint(\n  raw: unknown\n): GeneratedSlideChartHint | undefined {\n  if (!raw || typeof raw !== 'object') return undefined;\n  const o = raw as Record<string, unknown>;\n  const labels = Array.isArray(o.labels)\n    ? o.labels.map((x) => String(x ?? '')).filter(Boolean)\n    : [];\n  const seriesRaw = Array.isArray(o.series) ? o.series : [];\n  const series = seriesRaw\n    .map((s) => {\n      const rec = asRecord(s);\n      if (!rec) return null;\n      const data = Array.isArray(rec.data)\n        ? rec.data.map((n) => Number(n)).filter((n) => Number.isFinite(n))\n        : [];\n      if (!data.length) return null;\n      return {\n        name: asString(rec.name) || 'Serie',\n        data,\n      };\n    })\n    .filter((s): s is { name: string; data: number[] } => s != null);\n  if (!labels.length || !series.length) return undefined;\n  return {\n    chartType: asString(o.chartType) || 'bar',\n    labels,\n    series,\n    insight: asString(o.insight),\n  };\n}\n\nfunction normalizeSlide(raw: unknown): EnrichedGeneratedSlide | null {\n  const o = asRecord(raw);\n  if (!o) return null;\n  const title = asString(o.title) || asString(o.Title) || '';\n  const layoutId = normalizeLayoutId(o.layoutId ?? o.layout_id);\n  const bullets = asStringArray(o.bullets) || asStringArray(o.Bullets);\n  const body = asString(o.body) || asString(o.Body);\n  const imageRec = asRecord(o.image);\n  return {\n    layoutId,\n    title,\n    bullets,\n    body,\n    notes: asString(o.notes),\n    subtitle: asString(o.subtitle),\n    kicker: asString(o.kicker),\n    quote: asString(o.quote),\n    attribution: asString(o.attribution),\n    leftTitle: asString(o.leftTitle),\n    rightTitle: asString(o.rightTitle),\n    leftBullets: asStringArray(o.leftBullets),\n    rightBullets: asStringArray(o.rightBullets),\n    imagePrompt: asString(o.imagePrompt),\n    stockQuery: asString(o.stockQuery),\n    chartHint: normalizeChartHint(o.chartHint) ?? (typeof o.chartHint === 'string' ? o.chartHint : undefined),\n    shapes: Array.isArray(o.shapes)\n      ? (o.shapes.map((s) => {\n          const r = asRecord(s);\n          if (!r) return null;\n          return {\n            type: asString(r.type),\n            role: asString(r.role),\n            fillRole: asString(r.fillRole),\n            hint: asString(r.hint),\n          };\n        }).filter(Boolean) as GeneratedSlideShape[])\n      : undefined,\n    image: imageRec\n      ? {\n          source: asString(imageRec.source),\n          url: asString(imageRec.url),\n          alt: asString(imageRec.alt),\n        }\n      : undefined,\n    visualHierarchy: asRecord(o.visualHierarchy)\n      ? {\n          emphasis: asString(asRecord(o.visualHierarchy)!.emphasis),\n          density: asString(asRecord(o.visualHierarchy)!.density),\n          align: asString(asRecord(o.visualHierarchy)!.align),\n        }\n      : undefined,\n  };\n}\n\n/** Normalize raw API JSON (tolerant of casing / partial payloads). */\nexport function normalizeGenerateDeckResponse(raw: unknown): GenerateDeckResponse {\n  const root = asRecord(raw) || {};\n  const slidesRaw = Array.isArray(root.slides)\n    ? root.slides\n    : Array.isArray(root.Slides)\n      ? root.Slides\n      : [];\n  const slides = slidesRaw\n    .map(normalizeSlide)\n    .filter((s): s is EnrichedGeneratedSlide => s != null);\n\n  const hintRaw = asRecord(root.themeHint) || asRecord(root.theme_hint);\n  let themeHint: GenerateDeckThemeHint | undefined;\n  if (hintRaw) {\n    const fonts = asRecord(hintRaw.fonts);\n    const typeScale = asRecord(hintRaw.typeScale) || asRecord(hintRaw.type_scale);\n    themeHint = {\n      background: asString(hintRaw.background),\n      surface: asString(hintRaw.surface),\n      title: asString(hintRaw.title),\n      body: asString(hintRaw.body),\n      accent: asString(hintRaw.accent),\n      muted: asString(hintRaw.muted),\n      mood: asString(hintRaw.mood),\n      fonts: fonts\n        ? {\n            title: asString(fonts.title),\n            body: asString(fonts.body),\n          }\n        : undefined,\n      typeScale: typeScale\n        ? {\n            title: typeof typeScale.title === 'number' ? typeScale.title : undefined,\n            subtitle: typeof typeScale.subtitle === 'number' ? typeScale.subtitle : undefined,\n            body: typeof typeScale.body === 'number' ? typeScale.body : undefined,\n            caption: typeof typeScale.caption === 'number' ? typeScale.caption : undefined,\n          }\n        : undefined,\n    };\n  }\n\n  return {\n    deckTitle: asString(root.deckTitle) || asString(root.deck_title),\n    themeHint,\n    slides,\n  };\n}\n\nexport function themeFromHint(\n  hint: GenerateDeckThemeHint | null | undefined,\n  base: DeckTheme,\n  preferDark?: boolean\n): DeckTheme {\n  const fallback = preferDark ? DARK_THEME : DEFAULT_THEME;\n  const src = hint ? base : preferDark ? DARK_THEME : base;\n  return {\n    ...src,\n    id: hint?.mood ? `theme_ai_${hint.mood}` : src.id,\n    name: hint?.mood ? `AI (${hint.mood})` : src.name,\n    colors: {\n      background: hint?.background || (preferDark ? fallback.colors.background : src.colors.background),\n      surface: hint?.surface || (preferDark ? fallback.colors.surface : src.colors.surface),\n      title: hint?.title || (preferDark ? fallback.colors.title : src.colors.title),\n      body: hint?.body || (preferDark ? fallback.colors.body : src.colors.body),\n      accent: hint?.accent || src.colors.accent || fallback.colors.accent,\n      muted: hint?.muted || (preferDark ? fallback.colors.muted : src.colors.muted),\n    },\n    fonts: {\n      title: hint?.fonts?.title || src.fonts.title,\n      body: hint?.fonts?.body || src.fonts.body,\n    },\n    typeScale: {\n      title: hint?.typeScale?.title ?? src.typeScale.title,\n      subtitle: hint?.typeScale?.subtitle ?? src.typeScale.subtitle,\n      body: hint?.typeScale?.body ?? src.typeScale.body,\n      caption: hint?.typeScale?.caption ?? src.typeScale.caption,\n    },\n  };\n}\n\nfunction bulletBlock(lines: string[] | undefined): string {\n  if (!lines?.length) return '';\n  return lines.map((b) => (b.startsWith('\u2022') ? b : `\u2022 ${b}`)).join('\\n');\n}\n\n/** Map enriched slide fields onto layout placeholder content keys. */\nexport function contentFromGeneratedSlide(\n  spec: EnrichedGeneratedSlide\n): Partial<Record<string, string>> {\n  const bullets = bulletBlock(spec.bullets);\n  const layout = spec.layoutId;\n\n  if (layout === 'quote') {\n    const quote = (spec.quote || spec.body || spec.title || '').trim();\n    const attribution = (spec.attribution || '').trim();\n    return {\n      quote: quote ? (quote.startsWith('\"') ? quote : `\"${quote}\"`) : '',\n      caption: attribution ? (attribution.startsWith('\u2014') ? attribution : `\u2014 ${attribution}`) : '',\n    };\n  }\n\n  if (layout === 'big-number') {\n    return {\n      number: (spec.title || '0').trim(),\n      caption: (spec.subtitle || spec.body || bullets || '').trim(),\n    };\n  }\n\n  if (layout === 'comparison' || layout === 'two-column') {\n    const left = [\n      spec.leftTitle,\n      ...(spec.leftBullets || []).map((b) => (b.startsWith('\u2022') ? b : `\u2022 ${b}`)),\n    ]\n      .filter(Boolean)\n      .join('\\n');\n    const right = [\n      spec.rightTitle,\n      ...(spec.rightBullets || []).map((b) => (b.startsWith('\u2022') ? b : `\u2022 ${b}`)),\n    ]\n      .filter(Boolean)\n      .join('\\n');\n    return {\n      title: spec.title || '',\n      ph_left: left || spec.body || '',\n      ph_right: right || bullets || '',\n      body: bullets || spec.body || '',\n    };\n  }\n\n  if (layout === 'closing' || layout === 'title' || layout === 'title-subtitle') {\n    return {\n      title: spec.title || '',\n      subtitle: spec.subtitle || spec.kicker || spec.body || '',\n      body: spec.body || bullets || '',\n      bullets,\n    };\n  }\n\n  return {\n    title: spec.title || '',\n    subtitle: spec.subtitle || spec.kicker || '',\n    body: spec.body || bullets || '',\n    bullets: bullets || spec.body || '',\n    caption: spec.kicker || '',\n  };\n}\n\nfunction fillForRole(theme: DeckTheme, fillRole?: string): string {\n  const key = (fillRole || 'accent') as keyof DeckTheme['colors'];\n  return theme.colors[key] || theme.colors.accent;\n}\n\nfunction injectShapes(\n  json: { objects?: unknown[]; background?: string; version?: string },\n  shapes: GeneratedSlideShape[] | undefined,\n  theme: DeckTheme,\n  size: { width: number; height: number },\n  includeShapes: boolean\n): { objects: unknown[]; background?: string; version?: string } {\n  if (!includeShapes || !shapes?.length) {\n    return { ...json, objects: [...(json.objects || [])] };\n  }\n\n  const decor: Record<string, unknown>[] = [];\n  for (const shape of shapes.slice(0, 2)) {\n    const fill = fillForRole(theme, shape.fillRole);\n    const role = (shape.role || '').toLowerCase();\n    const type = (shape.type || '').toLowerCase();\n    const hint = (shape.hint || '').toLowerCase();\n\n    if (role.includes('accent-bar') || hint.includes('barra superior')) {\n      decor.push({\n        type: 'Rect',\n        version: '6.0.0',\n        left: 0,\n        top: 0,\n        width: size.width,\n        height: 10,\n        fill,\n        selectable: false,\n        evented: false,\n        id: uid('shape'),\n        name: 'ai-accent-bar',\n        aiShape: true,\n      });\n      continue;\n    }\n    if (hint.includes('barra inferior') || (role.includes('accent-bar') && hint.includes('inferior'))) {\n      decor.push({\n        type: 'Rect',\n        version: '6.0.0',\n        left: 0,\n        top: size.height - 10,\n        width: size.width,\n        height: 10,\n        fill,\n        selectable: false,\n        evented: false,\n        id: uid('shape'),\n        name: 'ai-accent-bar-bottom',\n        aiShape: true,\n      });\n      continue;\n    }\n    if (role.includes('divider') || hint.includes('vertical')) {\n      decor.push({\n        type: 'Rect',\n        version: '6.0.0',\n        left: size.width / 2 - 1,\n        top: 160,\n        width: 2,\n        height: size.height - 280,\n        fill,\n        selectable: false,\n        evented: false,\n        id: uid('shape'),\n        name: 'ai-divider',\n        aiShape: true,\n      });\n      continue;\n    }\n    if (role.includes('orb') || type === 'circle') {\n      const r = 220;\n      decor.push({\n        type: 'Circle',\n        version: '6.0.0',\n        left: size.width / 2 - r,\n        top: size.height / 2 - r - 40,\n        radius: r,\n        fill,\n        opacity: 0.18,\n        selectable: false,\n        evented: false,\n        id: uid('shape'),\n        name: 'ai-accent-orb',\n        aiShape: true,\n      });\n      continue;\n    }\n    // Default: soft surface card behind content\n    decor.push({\n      type: 'Rect',\n      version: '6.0.0',\n      left: 72,\n      top: 120,\n      width: size.width - 144,\n      height: size.height - 240,\n      fill,\n      opacity: 0.35,\n      rx: theme.radii.lg,\n      ry: theme.radii.lg,\n      selectable: false,\n      evented: false,\n      id: uid('shape'),\n      name: 'ai-surface-card',\n      aiShape: true,\n    });\n  }\n\n  return {\n    ...json,\n    objects: [...decor, ...(json.objects || [])],\n  };\n}\n\nasync function blobToAsset(\n  blob: Blob,\n  name: string\n): Promise<{ asset: Omit<SlidesAsset, 'url'> & { url: string; file: File }; dataUrl: string }> {\n  const type = blob.type.startsWith('image/') ? blob.type : 'image/jpeg';\n  const file = new File([blob], name, { type });\n  const dataUrl = await fileToDataUrl(file);\n  const url = URL.createObjectURL(file);\n  return {\n    dataUrl,\n    asset: {\n      id: uid('asset'),\n      name,\n      mimeType: type,\n      url,\n      file,\n    },\n  };\n}\n\nasync function resolveSlideImageBlob(\n  spec: EnrichedGeneratedSlide,\n  policy: GenerateDeckVisualPolicy,\n  signal?: AbortSignal\n): Promise<{ blob: Blob; alt: string; name: string } | null> {\n  const alt =\n    spec.image?.alt ||\n    spec.title ||\n    spec.stockQuery ||\n    'Slide image';\n\n  if (spec.image?.url) {\n    try {\n      const blob = await proxySlideImage({ url: spec.image.url, signal });\n      return { blob, alt, name: `deck_${Date.now()}.jpg` };\n    } catch {\n      /* fall through */\n    }\n  }\n\n  if (policy.allowGeneratedImages && spec.imagePrompt) {\n    try {\n      const blob = await generateImage({\n        prompt: spec.imagePrompt,\n        aspectRatio: '16:9',\n        imagePurpose: 'Brand Asset',\n        includeLogo: false,\n        signal,\n      });\n      return { blob, alt, name: `ai_${Date.now()}.png` };\n    } catch (err) {\n      console.warn('[slides] generate image failed', err);\n    }\n  }\n\n  if (policy.allowStockImages && (spec.stockQuery || spec.imagePrompt)) {\n    try {\n      const q = (spec.stockQuery || spec.imagePrompt || '').trim();\n      const res = await searchStock({ q, page: 1, perPage: 4, signal });\n      const photo = res.photos[0];\n      if (!photo) return null;\n      const dl = await downloadStockPhoto(photo, { signal });\n      return {\n        blob: dl.blob,\n        alt: photo.alt || alt,\n        name: `stock_${photo.id}.jpg`,\n      };\n    } catch (err) {\n      console.warn('[slides] stock image failed', err);\n    }\n  }\n\n  return null;\n}\n\nfunction replaceImagePlaceholder(\n  json: { objects?: Array<Record<string, unknown>>; background?: string; version?: string },\n  dataUrl: string,\n  assetId: string,\n  alt: string\n): typeof json {\n  const objects = [...(json.objects || [])];\n  const idx = objects.findIndex((o) => o.placeholderRole === 'image');\n  if (idx < 0) return json;\n  const ph = objects[idx]!;\n  const left = Number(ph.left) || 0;\n  const top = Number(ph.top) || 0;\n  const width = Number(ph.width) || 800;\n  const height = Number(ph.height) || 600;\n  objects[idx] = {\n    type: 'Image',\n    version: '6.0.0',\n    originX: 'left',\n    originY: 'top',\n    left,\n    top,\n    width,\n    height,\n    scaleX: 1,\n    scaleY: 1,\n    src: dataUrl,\n    id: uid('obj'),\n    placeholderRole: 'image',\n    name: 'image',\n    alt,\n    assetId,\n  };\n  return { ...json, objects };\n}\n\nfunction chartTypeOf(raw: string | undefined): ChartType {\n  const t = (raw || 'bar').toLowerCase();\n  if (t === 'line') return 'line';\n  if (t === 'pie') return 'pie';\n  if (t === 'donut' || t === 'doughnut') return 'donut';\n  return 'bar';\n}\n\nasync function replaceChartPlaceholder(\n  json: { objects?: Array<Record<string, unknown>>; background?: string; version?: string },\n  hint: GeneratedSlideChartHint,\n  theme: DeckTheme\n): Promise<typeof json> {\n  const objects = [...(json.objects || [])];\n  const idx = objects.findIndex((o) => o.placeholderRole === 'chart');\n  const box =\n    idx >= 0\n      ? {\n          left: Number(objects[idx]!.left) || 200,\n          top: Number(objects[idx]!.top) || 180,\n          width: Number(objects[idx]!.width) || 1520,\n          height: Number(objects[idx]!.height) || 720,\n        }\n      : { left: 200, top: 180, width: 1520, height: 720 };\n\n  const data: SlideChartData = {\n    chartType: chartTypeOf(hint.chartType),\n    labels: hint.labels || [],\n    series: (hint.series || []).map((s) => ({\n      name: s.name || 'Serie',\n      data: s.data || [],\n    })),\n  };\n  if (!data.labels.length || !data.series.length) return json;\n\n  const obj = await buildChartFabricObject(data, theme, box);\n  if (idx >= 0) objects[idx] = obj as Record<string, unknown>;\n  else objects.push(obj as Record<string, unknown>);\n  return { ...json, objects };\n}\n\nexport type ApplyGeneratedDeckResult = {\n  slides: Slide[];\n  theme: DeckTheme;\n  deckTitle?: string;\n  assets: SlidesAsset[];\n  imagesPlaced: number;\n  chartsPlaced: number;\n};\n\n/**\n * Build theme + slides (+ media) from an enriched generate-deck payload.\n * Caller writes into the Zustand store and flushes persistence.\n */\nexport async function buildDeckFromGeneratedResponse(\n  response: GenerateDeckResponse,\n  opts: {\n    baseTheme: DeckTheme;\n    size: { width: number; height: number };\n    masterId: string;\n    visualPolicy: GenerateDeckVisualPolicy;\n    brandContext?: GenerateDeckBrandContext;\n    signal?: AbortSignal;\n  }\n): Promise<ApplyGeneratedDeckResult> {\n  const preferDark = opts.visualPolicy.preferDarkBackground;\n  // Prefer API themeHint; else nudge accent from brand context.\n  let theme = themeFromHint(response.themeHint, opts.baseTheme, preferDark);\n  const brandAccent = opts.brandContext?.primaryColors?.[0]?.hex;\n  if (!response.themeHint?.accent && brandAccent) {\n    theme = {\n      ...theme,\n      colors: { ...theme.colors, accent: brandAccent },\n    };\n  }\n  if (!response.themeHint?.fonts?.title && opts.brandContext?.fonts?.title) {\n    theme = {\n      ...theme,\n      fonts: {\n        title: opts.brandContext.fonts.title,\n        body: opts.brandContext.fonts.body || theme.fonts.body,\n      },\n    };\n  }\n\n  const assets: SlidesAsset[] = [];\n  let imagesPlaced = 0;\n  let chartsPlaced = 0;\n  const maxImages = Math.max(0, opts.visualPolicy.maxImages);\n\n  const slides: Slide[] = [];\n  for (const spec of response.slides) {\n    const content = contentFromGeneratedSlide(spec);\n    let slide = createEmptySlide(\n      opts.masterId,\n      spec.layoutId,\n      theme,\n      (spec.title || 'Diapositiva').slice(0, 48),\n      content\n    );\n    if (spec.notes) slide = { ...slide, notes: spec.notes };\n\n    let json = injectShapes(\n      slide.json as { objects?: unknown[]; background?: string; version?: string },\n      spec.shapes,\n      theme,\n      opts.size,\n      opts.visualPolicy.includeShapes\n    );\n\n    const layout = getLayout(spec.layoutId);\n    const wantsImage = layout.placeholders.some((p) => p.role === 'image');\n    const hasImageSignal = Boolean(\n      spec.image?.url || spec.imagePrompt || spec.stockQuery\n    );\n    if (wantsImage && hasImageSignal && imagesPlaced < maxImages) {\n      const resolved = await resolveSlideImageBlob(\n        spec,\n        opts.visualPolicy,\n        opts.signal\n      );\n      if (resolved) {\n        const packed = await blobToAsset(resolved.blob, resolved.name);\n        assets.push(packed.asset);\n        json = replaceImagePlaceholder(\n          json as { objects?: Array<Record<string, unknown>>; background?: string; version?: string },\n          packed.dataUrl,\n          packed.asset.id,\n          resolved.alt\n        );\n        imagesPlaced += 1;\n      }\n    }\n\n    const chartHint =\n      typeof spec.chartHint === 'object' && spec.chartHint\n        ? spec.chartHint\n        : undefined;\n    if (chartHint || spec.layoutId === 'chart') {\n      const hint =\n        chartHint ||\n        (spec.bullets?.length\n          ? {\n              chartType: 'bar',\n              labels: spec.bullets.map((b, i) => b.slice(0, 24) || `Item ${i + 1}`),\n              series: [\n                {\n                  name: spec.title || 'Serie',\n                  data: spec.bullets.map((_, i) => 10 + i * 7),\n                },\n              ],\n            }\n          : undefined);\n      if (hint?.labels?.length && hint.series?.length) {\n        json = await replaceChartPlaceholder(\n          json as { objects?: Array<Record<string, unknown>>; background?: string; version?: string },\n          hint,\n          theme\n        );\n        chartsPlaced += 1;\n      }\n    }\n\n    slide = slideWithNewJson(slide, {\n      ...json,\n      background: theme.colors.background,\n    });\n    slides.push(slide);\n  }\n\n  return {\n    slides,\n    theme,\n    deckTitle: response.deckTitle,\n    assets,\n    imagesPlaced,\n    chartsPlaced,\n  };\n}\n", "import { getEditorIdentity } from '../identity';\nimport { getWizardApiClient } from '../wizardApiClient';\nimport { getActiveEditorBrand } from '../activeEditorBrand';\nimport type { DeckTheme, SlideLayoutId } from '../../types/slides.types';\n\nexport interface GeneratedSlideSpec {\n  layoutId: SlideLayoutId;\n  title: string;\n  bullets?: string[];\n  notes?: string;\n  imagePrompt?: string;\n  chartHint?: string;\n  body?: string;\n  subtitle?: string;\n  stockQuery?: string;\n}\n\nexport type GenerateDeckVisualPolicy = {\n  preferDarkBackground: boolean;\n  allowGeneratedImages: boolean;\n  allowStockImages: boolean;\n  maxImages: number;\n  includeShapes: boolean;\n};\n\nexport type GenerateDeckBrandContext = {\n  name: string;\n  voice?: string;\n  primaryColors: Array<{ name: string; hex: string }>;\n  secondaryColors: Array<{ name: string; hex: string }>;\n  fonts: { title: string; body: string };\n};\n\nconst DEFAULT_VISUAL_POLICY: GenerateDeckVisualPolicy = {\n  preferDarkBackground: true,\n  allowGeneratedImages: true,\n  allowStockImages: true,\n  maxImages: 4,\n  includeShapes: true,\n};\n\n/** Swagger Slides DAW identity \u2014 snake_case; content fields camelCase. */\nfunction withIdentity<T extends Record<string, unknown>>(body: T) {\n  const { accountId, brandId } = getEditorIdentity();\n  return { ...body, account_id: String(accountId), brand_id: String(brandId) };\n}\n\nfunction omitEmpty<T extends Record<string, unknown>>(obj: T): T {\n  const out: Record<string, unknown> = {};\n  for (const [k, v] of Object.entries(obj)) {\n    if (v === undefined || v === null) continue;\n    if (typeof v === 'string' && v.trim() === '') continue;\n    out[k] = v;\n  }\n  return out as T;\n}\n\nfunction hexLuminance(hex: string): number | null {\n  const raw = hex.trim().replace(/^#/, '');\n  const full =\n    raw.length === 3\n      ? raw\n          .split('')\n          .map((c) => c + c)\n          .join('')\n      : raw;\n  if (!/^[0-9a-fA-F]{6}$/.test(full)) return null;\n  const r = parseInt(full.slice(0, 2), 16);\n  const g = parseInt(full.slice(2, 4), 16);\n  const b = parseInt(full.slice(4, 6), 16);\n  return (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n}\n\nfunction isDarkBackground(hex: string | undefined): boolean {\n  if (!hex) return DEFAULT_VISUAL_POLICY.preferDarkBackground;\n  const lum = hexLuminance(hex);\n  if (lum == null) return DEFAULT_VISUAL_POLICY.preferDarkBackground;\n  return lum < 0.45;\n}\n\nfunction colorEntry(\n  name: string,\n  hex: string | undefined\n): { name: string; hex: string } | null {\n  const h = typeof hex === 'string' ? hex.trim() : '';\n  if (!h) return null;\n  return { name: name.trim() || h, hex: h };\n}\n\n/** Build ON-BRAND context from active editor brand + current deck theme. */\nexport function buildGenerateDeckBrandContext(\n  theme?: Pick<DeckTheme, 'colors' | 'fonts'> | null\n): GenerateDeckBrandContext | undefined {\n  const brand = getActiveEditorBrand();\n  const name = (brand?.name || '').trim();\n  if (!name && !theme) return undefined;\n\n  const primaryFromBrand = (brand?.primaryColors || [])\n    .map((c) => colorEntry(c.name || 'Primary', c.hex))\n    .filter((c): c is { name: string; hex: string } => c != null);\n\n  const primaryColors =\n    primaryFromBrand.length > 0\n      ? primaryFromBrand\n      : [\n          colorEntry('Title', theme?.colors.title),\n          colorEntry('Accent', theme?.colors.accent),\n        ].filter((c): c is { name: string; hex: string } => c != null);\n\n  const secondaryColors = [\n    colorEntry('Surface', theme?.colors.surface),\n    colorEntry('Body', theme?.colors.body),\n    colorEntry('Muted', theme?.colors.muted),\n    colorEntry('Background', theme?.colors.background),\n  ].filter((c): c is { name: string; hex: string } => c != null);\n\n  const fonts = {\n    title: (theme?.fonts.title || 'Space Grotesk').trim() || 'Space Grotesk',\n    body: (theme?.fonts.body || 'Quicksand').trim() || 'Quicksand',\n  };\n\n  const voice = brand?.voice?.name?.trim() || undefined;\n\n  return {\n    name: name || 'Brand',\n    ...(voice ? { voice } : {}),\n    primaryColors,\n    secondaryColors,\n    fonts,\n  };\n}\n\nfunction mergeVisualPolicy(\n  partial: Partial<GenerateDeckVisualPolicy> | undefined,\n  theme?: Pick<DeckTheme, 'colors'> | null\n): GenerateDeckVisualPolicy {\n  const preferDark =\n    partial?.preferDarkBackground ??\n    isDarkBackground(theme?.colors.background);\n\n  const maxImagesRaw = partial?.maxImages;\n  const maxImages =\n    maxImagesRaw != null && Number.isFinite(Number(maxImagesRaw))\n      ? Math.max(0, Math.round(Number(maxImagesRaw)))\n      : DEFAULT_VISUAL_POLICY.maxImages;\n\n  return {\n    preferDarkBackground: preferDark,\n    allowGeneratedImages:\n      partial?.allowGeneratedImages ?? DEFAULT_VISUAL_POLICY.allowGeneratedImages,\n    allowStockImages:\n      partial?.allowStockImages ?? DEFAULT_VISUAL_POLICY.allowStockImages,\n    maxImages,\n    includeShapes: partial?.includeShapes ?? DEFAULT_VISUAL_POLICY.includeShapes,\n  };\n}\n\nexport async function generateDeck(\n  opts: {\n    brief: string;\n    audience?: string;\n    slideCount?: number;\n    tone?: string;\n    language?: string;\n    visualPolicy?: Partial<GenerateDeckVisualPolicy>;\n    brandContext?: GenerateDeckBrandContext;\n    /** Current deck theme \u2014 used for fonts / dark preference / color fallbacks. */\n    theme?: Pick<DeckTheme, 'colors' | 'fonts'> | null;\n    signal?: AbortSignal;\n  }\n): Promise<import('../../lib/slides/applyGeneratedDeck').GenerateDeckResponse> {\n  const brief = opts.brief.trim();\n  if (!brief) {\n    throw new Error('brief is required');\n  }\n  const slideCount =\n    opts.slideCount != null && Number.isFinite(Number(opts.slideCount))\n      ? Math.round(Number(opts.slideCount))\n      : undefined;\n\n  const brandContext =\n    opts.brandContext ?? buildGenerateDeckBrandContext(opts.theme);\n  const visualPolicy = mergeVisualPolicy(opts.visualPolicy, opts.theme);\n\n  const raw = await getWizardApiClient().postJsonForJson<unknown>(\n    '/api/slides/generate-deck',\n    withIdentity(\n      omitEmpty({\n        brief,\n        audience: opts.audience?.trim() || 'general',\n        slideCount: slideCount ?? 8,\n        tone: opts.tone?.trim() || 'professional',\n        language: opts.language?.trim() || 'es',\n        visualPolicy,\n        brandContext,\n      })\n    ),\n    { signal: opts.signal }\n  );\n\n  const { normalizeGenerateDeckResponse } = await import(\n    '../../lib/slides/applyGeneratedDeck'\n  );\n  const normalized = normalizeGenerateDeckResponse(raw);\n  if (!normalized.slides.length) {\n    throw new Error('generate-deck returned no slides');\n  }\n  return normalized;\n}\n\nexport async function rewriteSlide(\n  opts: {\n    title: string;\n    body: string;\n    op: 'condense' | 'less-text' | 'audience';\n    audience?: string;\n    signal?: AbortSignal;\n  }\n): Promise<{ title: string; body: string; notes?: string }> {\n  const title = opts.title.trim() || 'Slide';\n  const body = opts.body.trim();\n  if (!body) {\n    throw new Error('No hay texto en la diapositiva para reescribir');\n  }\n  return getWizardApiClient().postJsonForJson(\n    '/api/slides/rewrite-slide',\n    withIdentity({\n      title,\n      body,\n      op: opts.op,\n      audience: opts.audience?.trim() || 'general',\n    }),\n    { signal: opts.signal }\n  );\n}\n\nexport async function generateSpeakerNotes(\n  opts: { slides: Array<{ title: string; body: string }>; signal?: AbortSignal }\n): Promise<{ notes: string[] }> {\n  const slides = opts.slides.map((s) => ({\n    title: (s.title || 'Slide').trim() || 'Slide',\n    // Schema requires body string; use title as soft fallback so LLM has context.\n    body: (s.body || '').trim() || (s.title || '').trim() || '',\n  }));\n  return getWizardApiClient().postJsonForJson(\n    '/api/slides/speaker-notes',\n    withIdentity({ slides }),\n    { signal: opts.signal }\n  );\n}\n\nexport async function suggestLayout(\n  opts: {\n    elements: Array<{ id: string; type: string; text?: string; width: number; height: number }>;\n    canvas: { width: number; height: number };\n    signal?: AbortSignal;\n  }\n): Promise<{ placements: Array<{ id: string; left: number; top: number; width: number; height: number }> }> {\n  return getWizardApiClient().postJsonForJson(\n    '/api/slides/layout-suggest',\n    withIdentity({\n      elements: opts.elements,\n      canvas: opts.canvas,\n    }),\n    { signal: opts.signal }\n  );\n}\n\nexport async function designCritique(\n  opts: {\n    slides: Array<{ title: string; body: string; wordCount: number }>;\n    signal?: AbortSignal;\n  }\n): Promise<{\n  score: number;\n  issues: Array<{ severity: 'info' | 'warn' | 'error'; slideIndex?: number; message: string }>;\n  estimatedMinutes: number;\n}> {\n  return getWizardApiClient().postJsonForJson(\n    '/api/slides/design-critique',\n    withIdentity({ slides: opts.slides }),\n    { signal: opts.signal }\n  );\n}\n\nexport async function dataToChart(\n  opts: { csv: string; signal?: AbortSignal }\n): Promise<{ chartType: string; labels: string[]; series: Array<{ name: string; data: number[] }> }> {\n  return getWizardApiClient().postJsonForJson(\n    '/api/slides/data-to-chart',\n    withIdentity({ csv: opts.csv }),\n    { signal: opts.signal }\n  );\n}\n\nexport async function translateDeck(\n  opts: {\n    slides: Array<{ title: string; body: string; notes?: string }>;\n    targetLanguage: string;\n    signal?: AbortSignal;\n  }\n): Promise<{\n  slides: Array<{ title: string; body: string; notes?: string }>;\n  /** True when translate-deck echoed / failed and we used /api/ai/translate-subtitles. */\n  usedFallback?: boolean;\n}> {\n  const input = opts.slides.map((s) => ({\n    title: s.title || '',\n    body: s.body || '',\n    notes: s.notes || '',\n  }));\n  const targetLanguage = resolveTranslateLanguage(opts.targetLanguage);\n\n  const raw = await getWizardApiClient().postJsonForJson<unknown>(\n    '/api/slides/translate-deck',\n    withIdentity({\n      slides: input,\n      targetLanguage,\n    }),\n    { signal: opts.signal }\n  );\n\n  let slides = normalizeTranslateDeckSlides(raw);\n  const echoed = isEchoTranslation(input, slides);\n\n  if (slides.length === 0 || echoed) {\n    console.warn(\n      '[slides] translate-deck empty or echo \u2014 falling back to /api/ai/translate-subtitles',\n      { echoed, got: slides.length, want: input.length, targetLanguage }\n    );\n    slides = await translateDeckViaSubtitles(input, targetLanguage, opts.signal);\n    return { slides, usedFallback: true };\n  }\n\n  // Pad / align to request length so apply never drops trailing slides.\n  if (slides.length < input.length) {\n    for (let i = slides.length; i < input.length; i++) {\n      slides.push({ ...input[i]! });\n    }\n  }\n\n  return { slides: slides.slice(0, Math.max(slides.length, input.length)) };\n}\n\n/** Map UI codes (en/es/pt) to names the translate LLM expects (same as video). */\nexport function resolveTranslateLanguage(raw: string): string {\n  const key = (raw || '').trim().toLowerCase();\n  const map: Record<string, string> = {\n    en: 'English',\n    eng: 'English',\n    english: 'English',\n    es: 'Spanish',\n    spa: 'Spanish',\n    spanish: 'Spanish',\n    espa\u00F1ol: 'Spanish',\n    espanol: 'Spanish',\n    pt: 'Portuguese',\n    por: 'Portuguese',\n    portuguese: 'Portuguese',\n    portugu\u00E9s: 'Portuguese',\n    portugues: 'Portuguese',\n  };\n  return map[key] || (raw.trim() || 'English');\n}\n\nfunction asRecord(v: unknown): Record<string, unknown> | null {\n  return typeof v === 'object' && v !== null && !Array.isArray(v)\n    ? (v as Record<string, unknown>)\n    : null;\n}\n\nfunction slideTextField(rec: Record<string, unknown>, ...keys: string[]): string {\n  for (const k of keys) {\n    const v = rec[k];\n    if (typeof v === 'string') return v;\n  }\n  return '';\n}\n\n/** Tolerant of PascalCase / nested `{ data: { slides } }` / `bullets[]` from BFF/.NET. */\nexport function normalizeTranslateDeckSlides(\n  raw: unknown\n): Array<{ title: string; body: string; notes?: string }> {\n  const root = asRecord(raw) || {};\n  const list =\n    (Array.isArray(raw) ? raw : null) ||\n    (Array.isArray(root.slides) ? root.slides : null) ||\n    (Array.isArray(root.Slides) ? root.Slides : null) ||\n    (Array.isArray(root.translatedSlides) ? root.translatedSlides : null) ||\n    (Array.isArray(root.TranslatedSlides) ? root.TranslatedSlides : null) ||\n    (Array.isArray(asRecord(root.data)?.slides) ? (asRecord(root.data)!.slides as unknown[]) : null) ||\n    (Array.isArray(asRecord(root.result)?.slides)\n      ? (asRecord(root.result)!.slides as unknown[])\n      : null) ||\n    [];\n\n  return list\n    .map((item) => {\n      const rec = asRecord(item);\n      if (!rec) return null;\n      const title = slideTextField(rec, 'title', 'Title');\n      let body = slideTextField(rec, 'body', 'Body', 'content', 'Content', 'text', 'Text');\n      if (!body.trim()) {\n        const bullets =\n          (Array.isArray(rec.bullets) ? rec.bullets : null) ||\n          (Array.isArray(rec.Bullets) ? rec.Bullets : null) ||\n          [];\n        body = bullets\n          .map((b) => (typeof b === 'string' ? b.trim() : ''))\n          .filter(Boolean)\n          .join('\\n');\n      }\n      const notesRaw = slideTextField(rec, 'notes', 'Notes', 'speakerNotes', 'SpeakerNotes');\n      return {\n        title,\n        body,\n        ...(notesRaw ? { notes: notesRaw } : {}),\n      };\n    })\n    .filter((s): s is { title: string; body: string; notes?: string } => s != null);\n}\n\nfunction isEchoTranslation(\n  input: Array<{ title: string; body: string; notes?: string }>,\n  output: Array<{ title: string; body: string; notes?: string }>\n): boolean {\n  if (!output.length || output.length !== input.length) return false;\n  return output.every(\n    (s, i) =>\n      (s.title || '') === (input[i]?.title || '') &&\n      (s.body || '') === (input[i]?.body || '') &&\n      (s.notes || '') === (input[i]?.notes || '')\n  );\n}\n\nasync function translateDeckViaSubtitles(\n  input: Array<{ title: string; body: string; notes?: string }>,\n  targetLanguage: string,\n  signal?: AbortSignal\n): Promise<Array<{ title: string; body: string; notes?: string }>> {\n  const { translateSubtitles } = await import('../textService');\n  const items: Array<{ id: string; text: string }> = [];\n  input.forEach((s, i) => {\n    if (s.title.trim()) items.push({ id: `${i}:title`, text: s.title });\n    if (s.body.trim()) items.push({ id: `${i}:body`, text: s.body });\n    if ((s.notes || '').trim()) items.push({ id: `${i}:notes`, text: s.notes || '' });\n  });\n  if (!items.length) return input.map((s) => ({ ...s }));\n\n  const translated = await translateSubtitles({\n    text: JSON.stringify(items),\n    targetLanguage,\n    signal,\n  });\n  const byId = new Map(translated.map((t) => [t.id, t.text]));\n  return input.map((s, i) => ({\n    title: byId.get(`${i}:title`) ?? s.title,\n    body: byId.get(`${i}:body`) ?? s.body,\n    notes: byId.has(`${i}:notes`) ? byId.get(`${i}:notes`) : s.notes,\n  }));\n}\n\nexport async function qaPrep(\n  opts: {\n    slides: Array<{ title: string; body: string }>;\n    signal?: AbortSignal;\n  }\n): Promise<{ questions: Array<{ slideIndex: number; question: string; tip?: string }> }> {\n  return getWizardApiClient().postJsonForJson(\n    '/api/slides/qa-prep',\n    withIdentity({\n      slides: opts.slides.map((s) => ({\n        title: s.title || '',\n        body: s.body || s.title || '',\n      })),\n    }),\n    { signal: opts.signal }\n  );\n}\n\nexport async function speakerCoach(\n  opts: {\n    slides: Array<{\n      title: string;\n      body: string;\n      notes?: string;\n      rehearsalSeconds?: number;\n    }>;\n    signal?: AbortSignal;\n  }\n): Promise<{\n  summary: string;\n  tips: Array<{ slideIndex: number; tip: string; pacingSeconds?: number }>;\n}> {\n  return getWizardApiClient().postJsonForJson(\n    '/api/slides/speaker-coach',\n    withIdentity({\n      slides: opts.slides.map((s) => ({\n        title: s.title || '',\n        body: s.body || '',\n        notes: s.notes || '',\n        rehearsalSeconds:\n          typeof s.rehearsalSeconds === 'number' && Number.isFinite(s.rehearsalSeconds)\n            ? s.rehearsalSeconds\n            : 0,\n      })),\n    }),\n    { signal: opts.signal }\n  );\n}\n\nexport async function dataNarrative(\n  opts: { csv: string; audience?: string; signal?: AbortSignal }\n): Promise<{ title: string; bullets: string[]; insight: string }> {\n  return getWizardApiClient().postJsonForJson(\n    '/api/slides/data-narrative',\n    withIdentity({\n      csv: opts.csv || '',\n      audience: opts.audience?.trim() || 'general',\n    }),\n    { signal: opts.signal }\n  );\n}\n\nexport async function runSlidesAgentTurn(\n  opts: {\n    messages: Array<{ role: string; content: string }>;\n    projectSnapshot: unknown;\n    tools: unknown[];\n    planMode?: boolean;\n    signal?: AbortSignal;\n  }\n): Promise<{ role: string; content: string; tool_calls?: Array<{ id: string; function: { name: string; arguments: string } }> }> {\n  return getWizardApiClient().postJsonForJson(\n    '/api/slides/agent',\n    withIdentity(\n      omitEmpty({\n        messages: opts.messages,\n        projectSnapshot: opts.projectSnapshot,\n        tools: opts.tools,\n        planMode: opts.planMode,\n      })\n    ),\n    { signal: opts.signal }\n  );\n}\n\n/** Same-origin proxy for remote images (CORS-safe). */\nexport async function proxySlideImage(opts: {\n  url: string;\n  signal?: AbortSignal;\n}): Promise<Blob> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().getForBlob(\n    '/api/slides/proxy-image',\n    {\n      url: opts.url,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n}\n", "/**\n * Offscreen first-slide raster for Recientes / cloud previews.\n */\n\nimport { StaticCanvas } from 'fabric';\n\nconst MAX_THUMB_W = 320;\n\nexport async function renderSlideThumbnail(\n  json: unknown,\n  size: { width: number; height: number },\n  backgroundColor: string,\n  maxW = MAX_THUMB_W,\n): Promise<string | undefined> {\n  if (typeof document === 'undefined') return undefined;\n\n  const deckW = Math.max(1, size.width || 1920);\n  const deckH = Math.max(1, size.height || 1080);\n  const scale = Math.min(1, maxW / deckW);\n  const w = Math.max(1, Math.round(deckW * scale));\n  const h = Math.max(1, Math.round(deckH * scale));\n\n  const el = document.createElement('canvas');\n  const fc = new StaticCanvas(el, {\n    width: w,\n    height: h,\n    renderOnAddRemove: false,\n    selection: false,\n  });\n\n  try {\n    fc.setZoom(scale);\n    const payload =\n      json && typeof json === 'object'\n        ? (json as Record<string, unknown>)\n        : { objects: [] };\n    const bg =\n      (typeof payload.background === 'string' && payload.background.trim()) ||\n      backgroundColor ||\n      '#FFFFFF';\n\n    await fc.loadFromJSON(payload);\n    fc.backgroundColor = bg;\n    fc.getObjects().forEach((o) => {\n      o.selectable = false;\n      o.evented = false;\n    });\n    fc.requestRenderAll();\n    return fc.toDataURL({ format: 'jpeg', quality: 0.55 });\n  } catch {\n    return undefined;\n  } finally {\n    fc.dispose();\n  }\n}\n\n/** Prefer first non-hidden slide; fall back to index 0. */\nexport function pickFirstSlideForThumbnail<T extends { hidden?: boolean }>(\n  slides: T[],\n): T | undefined {\n  return slides.find((s) => !s.hidden) ?? slides[0];\n}\n", "/**\n * Zustand store for Slides Studio Pro.\n * Multi-project + IDB autosave + per-slide history.\n */\n\nimport { create } from 'zustand';\nimport { openUploadsDB } from './useEditorStore';\nimport { getActiveMessages } from '../i18n';\nimport {\n  createProjectPersistence,\n  registerProjectPersistence,\n  type ProjectPersistenceController,\n} from '../lib/persistence/projectPersistence';\nimport {\n  markCloudAutosaveAnnounce,\n  withCloudAutosaveToast,\n} from '../utils/cloudAutosaveToast';\nimport { sanitizeUserFacingMessage } from '../utils/userFacingError';\nimport type {\n  DeckSection,\n  DeckTheme,\n  ElementBuild,\n  MasterChrome,\n  SemanticRestyleMode,\n  Slide,\n  SlideComment,\n  SlideDeck,\n  SlideLayoutId,\n  SlidesAsset,\n  SlidesCanvasConfig,\n  SlidesRightTab,\n  SlidesTemplateId,\n  SlidesToast,\n  SlideTransition,\n} from '../types/slides.types';\nimport { SLIDES_SCHEMA_VERSION } from '../types/slides.types';\nimport {\n  applyOutlineToSlide,\n  applyTranslatedTextsToSlide,\n  createDeckFromTemplate,\n  createEmptySlide,\n  extractOutlineFromSlides,\n  getLayout,\n  normalizeMasters,\n  normalizeSlide,\n  slideWithNewJson,\n} from '../lib/slides/layouts';\nimport { DEFAULT_THEME, cloneTheme } from '../lib/slides/themes';\nimport { restyleSlideJson } from '../lib/slides/restyle';\nimport { applyDesignFixToJson, semanticRestyleJson, type DesignFixKind } from '../lib/slides/designFixes';\nimport { computeMagicLayout, reflowSlideJson } from '../lib/slides/magicLayout';\nimport { suggestLayout } from '../services/slides/deckService';\nimport { buildChartFabricObject, type SlideChartData } from '../lib/slides/chartBridge';\nimport { materializeSlideJsonAssets } from '../lib/slides/mediaAssets';\n\nfunction uid(prefix: string): string {\n  return `${prefix}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport interface SlidesProject extends SlideDeck {}\n\ninterface SlidesState {\n  slidesProjects: SlidesProject[];\n  activeSlidesProjectId: string | null;\n  isSlidesSetupOpen: boolean;\n  isSlidesProjectLoading: boolean;\n  exportModalOpen: boolean;\n  isPresenting: boolean;\n  presenterWindowOpen: boolean;\n  toasts: SlidesToast[];\n  /** Local IDB save feedback for chrome / debugging. */\n  saveStatus: 'idle' | 'saving' | 'saved' | 'error';\n  rightTab: SlidesRightTab;\n  agentPlanMode: boolean;\n  selectedObjectIds: string[];\n  zoom: number;\n  showGuides: boolean;\n  /** Per-target snap (image-mode pattern). */\n  snapSettings: {\n    enabled: boolean;\n    shapes: boolean;\n    images: boolean;\n    text: boolean;\n    canvasEdges: boolean;\n  };\n  showGrid: boolean;\n  showBaseline: boolean;\n  editingMaster: boolean;\n  forbiddenTerms: string[];\n  preferredTerms: string[];\n  rehearsalTimes: Record<string, number>;\n\n  // Active project projection\n  name: string;\n  size: { width: number; height: number };\n  theme: DeckTheme;\n  masters: SlideDeck['masters'];\n  slides: Slide[];\n  sections: DeckSection[];\n  assets: SlidesAsset[];\n  activeSlideId: string | null;\n  schemaVersion: number;\n  /**\n   * Bumped on bulk deck mutations (translate, generate, \u2026) so SlideCanvas\n   * reloads even when historyIndex is capped at 49 and does not change.\n   */\n  canvasReloadEpoch: number;\n\n  setIsSlidesSetupOpen: (open: boolean) => void;\n  setExportModalOpen: (open: boolean) => void;\n  setRightTab: (tab: SlidesRightTab) => void;\n  setAgentPlanMode: (on: boolean) => void;\n  setIsPresenting: (on: boolean) => void;\n  setPresenterWindowOpen: (on: boolean) => void;\n  setSelectedObjectIds: (ids: string[]) => void;\n  setZoom: (z: number) => void;\n  setShowGuides: (on: boolean) => void;\n  setSnapSettings: (\n    partial: Partial<{\n      enabled: boolean;\n      shapes: boolean;\n      images: boolean;\n      text: boolean;\n      canvasEdges: boolean;\n    }>\n  ) => void;\n  setShowGrid: (on: boolean) => void;\n  setShowBaseline: (on: boolean) => void;\n  setEditingMaster: (on: boolean) => void;\n  setBrandTerms: (forbidden: string[], preferred: string[]) => void;\n  setRehearsalTime: (slideId: string, seconds: number) => void;\n  clearRehearsalTimes: () => void;\n  patchMasterChrome: (partial: Partial<MasterChrome>) => void;\n  applyMagicLayout: (slideId?: string) => Promise<void>;\n  applyDesignFix: (kind: DesignFixKind, slideId?: string) => void;\n  applySemanticRestyle: (mode: SemanticRestyleMode) => void;\n  insertChart: (data: SlideChartData) => Promise<void>;\n  resizeDeck: (width: number, height: number) => void;\n  setObjectAlt: (slideId: string, objectId: string, alt: string) => void;\n  splitDenseSlide: (slideId?: string) => void;\n\n  createSlidesProject: (name: string, opts?: Partial<SlidesCanvasConfig>) => void;\n  closeSlidesProject: (projectId: string) => void;\n  switchSlidesProject: (projectId: string) => void;\n  saveSlidesProject: () => Promise<void>;\n  loadSlidesProject: () => Promise<void>;\n  autoSaveSlidesProjectToCloud: () => Promise<boolean>;\n  importSlidesProject: (\n    data: Partial<SlideDeck>,\n    filename?: string,\n    opts?: { cloudEditableId?: number },\n  ) => void;\n  renameProject: (name: string) => void;\n\n  setActiveSlideId: (id: string) => void;\n  addSlide: (layoutId?: SlideLayoutId, afterId?: string) => string;\n  deleteSlide: (id: string) => void;\n  duplicateSlide: (id: string) => void;\n  moveSlide: (id: string, toIndex: number) => void;\n  renameSlide: (id: string, name: string) => void;\n  setSlideHidden: (id: string, hidden: boolean) => void;\n  updateSlideJson: (id: string, json: unknown, pushHistory?: boolean, thumbnail?: string) => void;\n  setSlideNotes: (id: string, notes: string) => void;\n  setSlideTransition: (id: string, transition: SlideTransition) => void;\n  setSlideBuilds: (id: string, builds: ElementBuild[]) => void;\n  setSlideLayout: (id: string, layoutId: SlideLayoutId) => void;\n  applyLayoutContent: (id: string, content: Partial<Record<string, string>>) => void;\n  undoSlide: (id?: string) => void;\n  redoSlide: (id?: string) => void;\n  canUndo: () => boolean;\n  canRedo: () => boolean;\n\n  setTheme: (theme: DeckTheme) => void;\n  patchTheme: (partial: Partial<DeckTheme>) => void;\n  /** Update presentation background only \u2014 does not restyle object fills. */\n  setDeckBackground: (hex: string) => void;\n  restyleDeck: () => void;\n\n  setSections: (sections: DeckSection[]) => void;\n  addSection: (name: string) => void;\n  renameSection: (id: string, name: string) => void;\n  toggleSectionCollapsed: (id: string) => void;\n\n  addComment: (slideId: string, note: string, quote?: string, objectId?: string) => void;\n  resolveComment: (slideId: string, commentId: string) => void;\n  removeComment: (slideId: string, commentId: string) => void;\n\n  addAsset: (asset: SlidesAsset) => void;\n  removeAsset: (id: string) => void;\n\n  getOutline: () => Array<{ slideId: string; title: string; bullets: string[] }>;\n  applyOutline: (\n    items: Array<{\n      slideId?: string;\n      title: string;\n      bullets: string[];\n      layoutId?: SlideLayoutId;\n    }>\n  ) => void;\n  /** Apply enriched generate-deck payload (theme, copy, shapes, images, charts). */\n  applyGeneratedDeck: (\n    response: import('../lib/slides/applyGeneratedDeck').GenerateDeckResponse,\n    opts?: {\n      visualPolicy?: import('../services/slides/deckService').GenerateDeckVisualPolicy;\n      signal?: AbortSignal;\n    }\n  ) => Promise<{ slideCount: number; imagesPlaced: number; chartsPlaced: number }>;\n  /** Translate in place \u2014 keeps images/shapes; only patches text + notes. */\n  applyDeckTranslation: (\n    items: Array<{\n      slideId: string;\n      title: string;\n      body: string;\n      notes?: string;\n      previousTitle?: string;\n      previousBody?: string;\n    }>\n  ) => void;\n  findReplace: (find: string, replace: string, caseSensitive?: boolean) => number;\n  copySlideToLibrary: (slideId: string) => Slide | null;\n  pasteSlideFromLibrary: (slide: Slide) => void;\n\n  addToast: (message: string, type?: SlidesToast['type']) => void;\n  removeToast: (id: string) => void;\n}\n\nexport type { DesignFixKind };\n\nfunction syncActiveIntoProjects(state: SlidesState): SlidesProject[] {\n  if (!state.activeSlidesProjectId) return state.slidesProjects;\n  return state.slidesProjects.map((p) =>\n    p.id === state.activeSlidesProjectId\n      ? {\n          ...p,\n          name: state.name,\n          size: state.size,\n          theme: state.theme,\n          masters: state.masters,\n          slides: state.slides,\n          sections: state.sections,\n          assets: state.assets,\n          activeSlideId: state.activeSlideId,\n          schemaVersion: state.schemaVersion,\n          updatedAt: Date.now(),\n        }\n      : p\n  );\n}\n\n/** Patch root deck fields and keep slidesProjects in lockstep (avoids save/cloud resurrecting deleted slides). */\nfunction commitActiveDeck(\n  state: SlidesState,\n  partial: Partial<\n    Pick<\n      SlidesState,\n      | 'slides'\n      | 'sections'\n      | 'activeSlideId'\n      | 'theme'\n      | 'name'\n      | 'assets'\n      | 'masters'\n      | 'size'\n    >\n  >\n): Partial<SlidesState> {\n  const merged = { ...state, ...partial };\n  return {\n    ...partial,\n    slidesProjects: syncActiveIntoProjects(merged),\n  };\n}\n\nfunction applyProjectToRoot(project: SlidesProject) {\n  return {\n    name: project.name,\n    size: project.size,\n    theme: project.theme,\n    masters: project.masters,\n    slides: project.slides,\n    sections: project.sections,\n    assets: project.assets,\n    activeSlideId: project.activeSlideId || project.slides[0]?.id || null,\n    schemaVersion: project.schemaVersion || SLIDES_SCHEMA_VERSION,\n  };\n}\n\nfunction emptyRoot() {\n  return {\n    name: '',\n    size: { width: 1920, height: 1080 },\n    theme: DEFAULT_THEME,\n    masters: [] as SlideDeck['masters'],\n    slides: [] as Slide[],\n    sections: [] as DeckSection[],\n    assets: [] as SlidesAsset[],\n    activeSlideId: null as string | null,\n    schemaVersion: SLIDES_SCHEMA_VERSION,\n  };\n}\n\nlet slidesPersistence!: ProjectPersistenceController;\n/** Bumped on every user-facing mutation; stale local saves must not clobber memory/IDB. */\nlet slidesMutationEpoch = 0;\n\nfunction scheduleAutosave() {\n  slidesMutationEpoch += 1;\n  markCloudAutosaveAnnounce('slides');\n  slidesPersistence.scheduleAfterChange();\n}\n\n/** Flush pending cloud upload immediately (tab hide / navigate away). */\nexport function flushSlidesCloudAutosave(): void {\n  void slidesPersistence?.flushCloud();\n}\n\nfunction mutateActiveSlide(\n  state: SlidesState,\n  slideId: string,\n  updater: (s: Slide) => Slide\n): Partial<SlidesState> {\n  const slides = state.slides.map((s) => (s.id === slideId ? updater(s) : s));\n  return commitActiveDeck(state, { slides });\n}\n\nexport const useSlidesStore = create<SlidesState>((set, get) => ({\n  slidesProjects: [],\n  activeSlidesProjectId: null,\n  isSlidesSetupOpen: false,\n  isSlidesProjectLoading: true,\n  exportModalOpen: false,\n  isPresenting: false,\n  presenterWindowOpen: false,\n  toasts: [],\n  saveStatus: 'idle',\n  rightTab: 'ai',\n  agentPlanMode: false,\n  selectedObjectIds: [],\n  zoom: 0.5,\n  showGuides: true,\n  snapSettings: {\n    enabled: true,\n    shapes: true,\n    images: true,\n    text: true,\n    canvasEdges: true,\n  },\n  showGrid: false,\n  showBaseline: false,\n  editingMaster: false,\n  forbiddenTerms: [],\n  preferredTerms: [],\n  rehearsalTimes: {},\n  canvasReloadEpoch: 0,\n  ...emptyRoot(),\n\n  setIsSlidesSetupOpen: (open) => set({ isSlidesSetupOpen: open }),\n  setExportModalOpen: (open) => set({ exportModalOpen: open }),\n  setRightTab: (tab) => set({ rightTab: tab === 'notes' ? 'ai' : tab }),\n  setAgentPlanMode: (on) => set({ agentPlanMode: on }),\n  setIsPresenting: (on) => set({ isPresenting: on }),\n  setPresenterWindowOpen: (on) => set({ presenterWindowOpen: on }),\n  setSelectedObjectIds: (ids) => set({ selectedObjectIds: ids }),\n  setZoom: (z) => set({ zoom: Math.max(0.15, Math.min(2, z)) }),\n  setShowGuides: (on) =>\n    set((s) => ({\n      showGuides: on,\n      snapSettings: { ...s.snapSettings, enabled: on },\n    })),\n  setSnapSettings: (partial) =>\n    set((s) => {\n      const snapSettings = { ...s.snapSettings, ...partial };\n      return { snapSettings, showGuides: snapSettings.enabled };\n    }),\n  setShowGrid: (on) => set({ showGrid: on }),\n  setShowBaseline: (on) => set({ showBaseline: on }),\n  setEditingMaster: (on) => set({ editingMaster: on }),\n  setBrandTerms: (forbidden, preferred) => set({ forbiddenTerms: forbidden, preferredTerms: preferred }),\n  setRehearsalTime: (slideId, seconds) =>\n    set((s) => ({ rehearsalTimes: { ...s.rehearsalTimes, [slideId]: seconds } })),\n  clearRehearsalTimes: () => set({ rehearsalTimes: {} }),\n\n  patchMasterChrome: (partial) => {\n    set((state) => ({\n      masters: state.masters.map((m, i) =>\n        i === 0\n          ? {\n              ...m,\n              chrome: {\n                ...(m.chrome || {\n                  showFooter: true,\n                  footerText: 'Confidential',\n                  showPageNumber: true,\n                  showLogo: false,\n                  showHeader: false,\n                }),\n                ...partial,\n              },\n            }\n          : m\n      ),\n    }));\n    scheduleAutosave();\n  },\n\n  createSlidesProject: (name, opts) => {\n    const width = opts?.width ?? 1920;\n    const height = opts?.height ?? 1080;\n    const template = (opts?.template ?? 'blank') as SlidesTemplateId;\n    const built = createDeckFromTemplate(name, { width, height }, template);\n    if (opts?.backgroundColor) {\n      built.theme = { ...built.theme, colors: { ...built.theme.colors, background: opts.backgroundColor } };\n    }\n    const project: SlidesProject = {\n      id: uid('deck'),\n      name,\n      size: { width, height },\n      theme: built.theme,\n      masters: built.masters,\n      slides: built.slides,\n      sections: built.sections,\n      assets: [],\n      activeSlideId: built.slides[0]?.id ?? null,\n      schemaVersion: SLIDES_SCHEMA_VERSION,\n      createdAt: Date.now(),\n      updatedAt: Date.now(),\n      template,\n    };\n    set((state) => {\n      const synced = syncActiveIntoProjects(state);\n      return {\n        slidesProjects: [...synced, project],\n        activeSlidesProjectId: project.id,\n        isSlidesSetupOpen: false,\n        ...applyProjectToRoot(project),\n      };\n    });\n    scheduleAutosave();\n  },\n\n  closeSlidesProject: (projectId) => {\n    set((state) => {\n      const synced = syncActiveIntoProjects(state);\n      const remaining = synced.filter((p) => p.id !== projectId);\n      const next = remaining[0] ?? null;\n      return {\n        slidesProjects: remaining,\n        activeSlidesProjectId: next?.id ?? null,\n        ...(next ? applyProjectToRoot(next) : emptyRoot()),\n      };\n    });\n    scheduleAutosave();\n  },\n\n  switchSlidesProject: (projectId) => {\n    set((state) => {\n      const synced = syncActiveIntoProjects(state);\n      const next = synced.find((p) => p.id === projectId);\n      if (!next) return state;\n      return {\n        slidesProjects: synced,\n        activeSlidesProjectId: projectId,\n        ...applyProjectToRoot(next),\n      };\n    });\n  },\n\n  saveSlidesProject: async () => {\n    const state = get();\n    if (state.isSlidesProjectLoading) return;\n    const epochAtStart = slidesMutationEpoch;\n\n    const projects = syncActiveIntoProjects(state).map((p) =>\n      p.id === state.activeSlidesProjectId && slidesPersistence?.isCloudDirty()\n        ? { ...p, cloudSavePending: true }\n        : p\n    );\n\n    try {\n      // Bake image bytes into slide JSON + keep asset blobs in slides-assets.\n      // Without this, Fabric stores blob: URLs that die on reload.\n      const durableProjects = await Promise.all(\n        projects.map(async (p) => {\n          const slides = await Promise.all(\n            p.slides.map(async (s) => {\n              const json = await materializeSlideJsonAssets(s.json, p.assets);\n              return {\n                ...s,\n                json,\n                // Drop heavy multi-step history with embedded images (quota).\n                history: [JSON.stringify(json)],\n                historyIndex: 0,\n              };\n            })\n          );\n\n          // Bake first-slide raster for Recientes when missing.\n          const { pickFirstSlideForThumbnail, renderSlideThumbnail } = await import(\n            '../utils/slidesThumbnail'\n          );\n          const first = pickFirstSlideForThumbnail(slides);\n          let withThumbs = slides;\n          if (\n            first &&\n            !(typeof first.thumbnail === 'string' && first.thumbnail.startsWith('data:'))\n          ) {\n            const thumb = await renderSlideThumbnail(\n              first.json,\n              p.size,\n              p.theme?.colors?.background || '#FFFFFF',\n            );\n            if (thumb) {\n              withThumbs = slides.map((s) =>\n                s.id === first.id ? { ...s, thumbnail: thumb } : s,\n              );\n            }\n          }\n\n          return { ...p, slides: withThumbs };\n        })\n      );\n\n      // generate-deck / outline can replace the whole deck while we were baking.\n      // Abort before IDB + set() so we never resurrect the previous slides.\n      if (epochAtStart !== slidesMutationEpoch) {\n        return;\n      }\n\n      const db = await openUploadsDB();\n      const serializable = durableProjects.map((p) => ({\n        ...p,\n        assets: p.assets.map((a) => ({\n          id: a.id,\n          name: a.name,\n          mimeType: a.mimeType,\n          width: a.width,\n          height: a.height,\n          duration: a.duration,\n          // url rebuilt from slides-assets on load\n          url: '',\n        })),\n      }));\n      await new Promise<void>((resolve, reject) => {\n        const tx = db.transaction(['projects', 'slides-assets'], 'readwrite');\n        tx.objectStore('projects').put({ id: 'slides-projects', projects: serializable });\n        const assetStore = tx.objectStore('slides-assets');\n        for (const p of durableProjects) {\n          for (const a of p.assets) {\n            if (a.file) {\n              assetStore.put({ id: a.id, name: a.name, mimeType: a.mimeType, blob: a.file });\n            }\n          }\n        }\n        tx.oncomplete = () => resolve();\n        tx.onerror = () => reject(tx.error);\n      });\n\n      if (epochAtStart !== slidesMutationEpoch) {\n        return;\n      }\n\n      // Sync durable image srcs into projects from the current root deck.\n      // Never push slidesProjects \u2192 root: root is authoritative after user edits\n      // (delete/reorder/generate). Overlay baked json/thumbs only where ids match.\n      const activeId = get().activeSlidesProjectId;\n      set((s) => {\n        if (epochAtStart !== slidesMutationEpoch) return s;\n        const nextProjects = s.slidesProjects.map((live) => {\n          const baked = durableProjects.find((d) => d.id === live.id);\n          if (!baked) return live;\n\n          if (live.id === activeId) {\n            // Active project follows root slides (deletes/adds already applied).\n            return {\n              ...live,\n              name: s.name,\n              size: s.size,\n              theme: s.theme,\n              masters: s.masters,\n              sections: s.sections,\n              assets: s.assets,\n              activeSlideId: s.activeSlideId,\n              cloudSavePending: baked.cloudSavePending,\n              slides: s.slides.map((sl) => {\n                const b = baked.slides.find((x) => x.id === sl.id);\n                return b\n                  ? {\n                      ...sl,\n                      json: b.json,\n                      thumbnail: b.thumbnail || sl.thumbnail,\n                    }\n                  : sl;\n              }),\n            };\n          }\n\n          // Inactive projects: only refresh matching slide payloads from bake.\n          const liveIds = live.slides.map((x) => x.id).join('\\0');\n          const bakedIds = baked.slides.map((x) => x.id).join('\\0');\n          if (liveIds !== bakedIds) {\n            return { ...live, cloudSavePending: baked.cloudSavePending };\n          }\n          return {\n            ...live,\n            cloudSavePending: baked.cloudSavePending,\n            slides: live.slides.map((sl) => {\n              const b = baked.slides.find((x) => x.id === sl.id);\n              return b\n                ? {\n                    ...sl,\n                    json: b.json,\n                    thumbnail: b.thumbnail || sl.thumbnail,\n                  }\n                : sl;\n            }),\n          };\n        });\n        return { slidesProjects: nextProjects };\n      });\n    } catch (err) {\n      console.error('[slides] save failed', err);\n      set({ saveStatus: 'error' });\n      get().addToast(getActiveMessages().store.toasts.slides.saveLocalError, 'error');\n      setTimeout(() => {\n        if (get().saveStatus === 'error') set({ saveStatus: 'idle' });\n      }, 4000);\n    }\n  },\n\n  autoSaveSlidesProjectToCloud: async () =>\n    withCloudAutosaveToast('slides', async () => {\n    const { hasEditorIdentity } = await import('../services/identity');\n    if (!hasEditorIdentity()) return false;\n\n    const { FEATURE_CLOUD_SLIDES } = await import('../utils/projectCloudSerializer');\n    if (!FEATURE_CLOUD_SLIDES) return false;\n\n    set((state) => ({ slidesProjects: syncActiveIntoProjects(state) }));\n\n    const state = get();\n    if (\n      state.isSlidesProjectLoading ||\n      !state.activeSlidesProjectId ||\n      state.slidesProjects.length === 0\n    ) {\n      return false;\n    }\n\n    const projectId = state.activeSlidesProjectId;\n    const cloudEditableId = state.slidesProjects.find((p) => p.id === projectId)?.cloudEditableId;\n\n    const isEditableMissing = (err: unknown): boolean => {\n      if (!err || typeof err !== 'object') return false;\n      const status = 'status' in err ? Number((err as { status?: number }).status) : undefined;\n      if (status === 404) return true;\n      return (\n        err instanceof Error &&\n        err.name === 'NotImplementedError' &&\n        /HTTP 404/.test(err.message)\n      );\n    };\n\n    try {\n      const { uploadCurrentProjectToCloud } = await import('../utils/projectCloudSerializer');\n      let editable;\n      try {\n        editable = await uploadCurrentProjectToCloud('slides', {\n          editableId: cloudEditableId,\n        });\n      } catch (err) {\n        // Stale id survived putEditableFile (race) \u2014 clear and POST once.\n        if (isEditableMissing(err) && cloudEditableId != null) {\n          set((s) => ({\n            slidesProjects: s.slidesProjects.map((p) =>\n              p.id === projectId ? { ...p, cloudEditableId: undefined } : p\n            ),\n          }));\n          editable = await uploadCurrentProjectToCloud('slides', {});\n        } else {\n          throw err;\n        }\n      }\n\n      const stillActive = get().activeSlidesProjectId === projectId;\n      if (stillActive) {\n        set((s) => ({\n          slidesProjects: s.slidesProjects.map((p) =>\n            p.id === projectId\n              ? { ...p, cloudEditableId: editable.id, cloudSavePending: false }\n              : p,\n          ),\n        }));\n        void get().saveSlidesProject().catch(() => {});\n      }\n\n      return true;\n    } catch (err) {\n      console.warn('[autoSaveSlidesProjectToCloud] failed:', err);\n      set((s) => ({\n        slidesProjects: s.slidesProjects.map((p) =>\n          p.id === projectId ? { ...p, cloudSavePending: true } : p,\n        ),\n      }));\n      void get().saveSlidesProject().catch(() => {});\n      throw err;\n    }\n  }),\n\n  loadSlidesProject: async () => {\n    try {\n      const db = await openUploadsDB();\n      const record = await new Promise<{ id: string; projects: SlidesProject[] } | undefined>(\n        (resolve, reject) => {\n          const tx = db.transaction('projects', 'readonly');\n          const req = tx.objectStore('projects').get('slides-projects');\n          req.onsuccess = () => resolve(req.result as { id: string; projects: SlidesProject[] } | undefined);\n          req.onerror = () => reject(req.error);\n        }\n      );\n      const projects = record?.projects || [];\n      if (projects.length) {\n        // Rehydrate asset blobs\n        const hydrated = await Promise.all(\n          projects.map(async (p) => {\n            const assets: SlidesAsset[] = [];\n            for (const meta of p.assets || []) {\n              try {\n                const row = await new Promise<{ blob: Blob; name: string; mimeType: string } | undefined>(\n                  (resolve, reject) => {\n                    const tx = db.transaction('slides-assets', 'readonly');\n                    const req = tx.objectStore('slides-assets').get(meta.id);\n                    req.onsuccess = () => resolve(req.result as { blob: Blob; name: string; mimeType: string } | undefined);\n                    req.onerror = () => reject(req.error);\n                  }\n                );\n                if (row?.blob) {\n                  const file = new File([row.blob], row.name || meta.name, {\n                    type: row.mimeType || meta.mimeType,\n                  });\n                  assets.push({\n                    ...meta,\n                    file,\n                    url: URL.createObjectURL(file),\n                  });\n                } else {\n                  assets.push({ ...meta, url: meta.url || '' });\n                }\n              } catch {\n                assets.push({ ...meta, url: '' });\n              }\n            }\n            const theme = p.theme || DEFAULT_THEME;\n            const masters = normalizeMasters(p.masters, theme);\n            const masterId = masters[0]?.id;\n            const slides = (p.slides || []).map((s) => normalizeSlide(s, theme, masterId));\n            return { ...p, assets, theme, masters, slides, schemaVersion: SLIDES_SCHEMA_VERSION };\n          })\n        );\n        const active = hydrated[0]!;\n        set({\n          slidesProjects: hydrated,\n          activeSlidesProjectId: active.id,\n          isSlidesProjectLoading: false,\n          ...applyProjectToRoot(active),\n        });\n        // Retry cloud upload if the previous session closed mid-save.\n        if (hydrated.some((p) => p.cloudSavePending)) {\n          void slidesPersistence.flushCloud();\n        }\n      } else {\n        set({ isSlidesProjectLoading: false, isSlidesSetupOpen: true });\n      }\n    } catch {\n      set({ isSlidesProjectLoading: false, isSlidesSetupOpen: true });\n    }\n  },\n\n  importSlidesProject: (data, filename, opts) => {\n    const name =\n      data.name ||\n      (filename ? filename.replace(/\\.(kais|wzrds|json|pptx|md)$/i, '') : 'Presentacion importada');\n    const built =\n      data.slides && data.slides.length\n        ? null\n        : createDeckFromTemplate(name, data.size || { width: 1920, height: 1080 }, 'blank');\n    const theme = data.theme || built?.theme || DEFAULT_THEME;\n    const masters = normalizeMasters(data.masters || built?.masters, theme);\n    const masterId = masters[0]?.id;\n    const rawSlides = data.slides || built?.slides || [];\n    const slides = rawSlides.map((s) => normalizeSlide(s, theme, masterId));\n    const project: SlidesProject = {\n      id: uid('deck'),\n      name,\n      size: data.size || { width: 1920, height: 1080 },\n      theme,\n      masters,\n      slides,\n      sections: data.sections || built?.sections || [],\n      assets: data.assets || [],\n      activeSlideId: data.activeSlideId || slides[0]?.id || null,\n      schemaVersion: SLIDES_SCHEMA_VERSION,\n      createdAt: Date.now(),\n      updatedAt: Date.now(),\n      template: data.template,\n      cloudEditableId: opts?.cloudEditableId,\n    };\n    set((state) => {\n      const synced = syncActiveIntoProjects(state);\n      return {\n        slidesProjects: [...synced, project],\n        activeSlidesProjectId: project.id,\n        isSlidesSetupOpen: false,\n        ...applyProjectToRoot(project),\n      };\n    });\n    scheduleAutosave();\n  },\n\n  renameProject: (name) => {\n    const trimmed = name.trim();\n    if (!trimmed) return;\n    set((s) => ({\n      name: trimmed,\n      slidesProjects: s.slidesProjects.map((p) =>\n        p.id === s.activeSlidesProjectId ? { ...p, name: trimmed } : p,\n      ),\n    }));\n    void get().saveSlidesProject().catch(() => {});\n    // Rename should show up in Recientes promptly (not wait for debounce).\n    void slidesPersistence.flushCloud();\n  },\n\n  setActiveSlideId: (id) => set({ activeSlideId: id, selectedObjectIds: [] }),\n\n  addSlide: (layoutId = 'title-body', afterId) => {\n    const state = get();\n    const masterId = state.masters[0]?.id || uid('master');\n    const slide = createEmptySlide(masterId, layoutId, state.theme);\n    const slides = [...state.slides];\n    const idx = afterId ? slides.findIndex((s) => s.id === afterId) : slides.length - 1;\n    slides.splice(idx + 1, 0, slide);\n    const sections = state.sections.map((sec, i) =>\n      i === 0 || sec.slideIds.includes(afterId || '')\n        ? { ...sec, slideIds: [...sec.slideIds, slide.id] }\n        : sec\n    );\n    set((s) => commitActiveDeck(s, { slides, sections, activeSlideId: slide.id }));\n    scheduleAutosave();\n    return slide.id;\n  },\n\n  deleteSlide: (id) => {\n    set((state) => {\n      if (state.slides.length <= 1) {\n        get().addToast(getActiveMessages().store.toasts.slides.atLeastOneSlide, 'warning');\n        return state;\n      }\n      const slides = state.slides.filter((s) => s.id !== id);\n      const sections = state.sections.map((sec) => ({\n        ...sec,\n        slideIds: sec.slideIds.filter((sid) => sid !== id),\n      }));\n      const activeSlideId =\n        state.activeSlideId === id ? slides[0]?.id ?? null : state.activeSlideId;\n      return commitActiveDeck(state, { slides, sections, activeSlideId });\n    });\n    scheduleAutosave();\n  },\n\n  duplicateSlide: (id) => {\n    set((state) => {\n      const src = state.slides.find((s) => s.id === id);\n      if (!src) return state;\n      const copy: Slide = {\n        ...structuredClone(src),\n        id: uid('slide'),\n        name: `${src.name} (copia)`,\n      };\n      // Remap object ids so morph can still match by similarity\n      const json = copy.json as { objects?: Array<Record<string, unknown>> };\n      if (json?.objects) {\n        json.objects = json.objects.map((o) => ({\n          ...o,\n          id: uid('obj'),\n          morphSourceId: o.id,\n        }));\n        copy.json = json;\n      }\n      const idx = state.slides.findIndex((s) => s.id === id);\n      const slides = [...state.slides];\n      slides.splice(idx + 1, 0, copy);\n      const sections = state.sections.map((sec) =>\n        sec.slideIds.includes(id)\n          ? { ...sec, slideIds: sec.slideIds.flatMap((sid) => (sid === id ? [sid, copy.id] : [sid])) }\n          : sec\n      );\n      return commitActiveDeck(state, { slides, sections, activeSlideId: copy.id });\n    });\n    scheduleAutosave();\n  },\n\n  moveSlide: (id, toIndex) => {\n    set((state) => {\n      const from = state.slides.findIndex((s) => s.id === id);\n      if (from < 0) return state;\n      const slides = [...state.slides];\n      const [item] = slides.splice(from, 1);\n      if (!item) return state;\n      slides.splice(Math.max(0, Math.min(toIndex, slides.length)), 0, item);\n      return commitActiveDeck(state, { slides });\n    });\n    scheduleAutosave();\n  },\n\n  renameSlide: (id, name) => {\n    set((state) => mutateActiveSlide(state, id, (s) => ({ ...s, name })));\n    scheduleAutosave();\n  },\n\n  setSlideHidden: (id, hidden) => {\n    set((state) => mutateActiveSlide(state, id, (s) => ({ ...s, hidden })));\n    scheduleAutosave();\n  },\n\n  updateSlideJson: (id, json, pushHistory = true, thumbnail) => {\n    set((state) =>\n      mutateActiveSlide(state, id, (s) => {\n        const withThumb =\n          typeof thumbnail === 'string' && thumbnail.startsWith('data:')\n            ? { thumbnail }\n            : {};\n        if (!pushHistory) return { ...s, json, ...withThumb };\n        const history = [...s.history.slice(0, s.historyIndex + 1), JSON.stringify(json)].slice(-50);\n        return {\n          ...s,\n          json,\n          history,\n          historyIndex: history.length - 1,\n          ...withThumb,\n        };\n      })\n    );\n    scheduleAutosave();\n  },\n\n  setSlideNotes: (id, notes) => {\n    set((state) => mutateActiveSlide(state, id, (s) => ({ ...s, notes })));\n    scheduleAutosave();\n  },\n\n  setSlideTransition: (id, transition) => {\n    set((state) => mutateActiveSlide(state, id, (s) => ({ ...s, transition })));\n    scheduleAutosave();\n  },\n\n  setSlideBuilds: (id, builds) => {\n    set((state) => mutateActiveSlide(state, id, (s) => ({ ...s, builds })));\n    scheduleAutosave();\n  },\n\n  setSlideLayout: (id, layoutId) => {\n    const state = get();\n    const slide = state.slides.find((s) => s.id === id);\n    if (!slide) return;\n    const layout = getLayout(layoutId);\n    const next = createEmptySlide(slide.masterId, layoutId, state.theme, slide.name);\n    set((s) =>\n      mutateActiveSlide(s, id, (sl) => ({\n        ...sl,\n        layoutId,\n        json: next.json,\n        name: layout.name,\n        history: [...sl.history.slice(0, sl.historyIndex + 1), JSON.stringify(next.json)].slice(-50),\n        historyIndex: Math.min(sl.historyIndex + 1, 49),\n      }))\n    );\n    scheduleAutosave();\n  },\n\n  applyLayoutContent: (id, content) => {\n    const state = get();\n    const slide = state.slides.find((s) => s.id === id);\n    if (!slide) return;\n    const next = createEmptySlide(slide.masterId, slide.layoutId, state.theme, slide.name, content);\n    set((s) =>\n      mutateActiveSlide(s, id, (sl) => ({\n        ...sl,\n        json: next.json,\n        history: [...sl.history.slice(0, sl.historyIndex + 1), JSON.stringify(next.json)].slice(-50),\n        historyIndex: Math.min(sl.historyIndex + 1, 49),\n      }))\n    );\n    scheduleAutosave();\n  },\n\n  undoSlide: (id) => {\n    const state = get();\n    const slideId = id || state.activeSlideId;\n    if (!slideId) return;\n    set((s) =>\n      mutateActiveSlide(s, slideId, (sl) => {\n        if (sl.historyIndex <= 0) return sl;\n        const historyIndex = sl.historyIndex - 1;\n        const json = JSON.parse(sl.history[historyIndex] || '{}');\n        return { ...sl, historyIndex, json };\n      })\n    );\n  },\n\n  redoSlide: (id) => {\n    const state = get();\n    const slideId = id || state.activeSlideId;\n    if (!slideId) return;\n    set((s) =>\n      mutateActiveSlide(s, slideId, (sl) => {\n        if (sl.historyIndex >= sl.history.length - 1) return sl;\n        const historyIndex = sl.historyIndex + 1;\n        const json = JSON.parse(sl.history[historyIndex] || '{}');\n        return { ...sl, historyIndex, json };\n      })\n    );\n  },\n\n  canUndo: () => {\n    const state = get();\n    const slide = state.slides.find((s) => s.id === state.activeSlideId);\n    return !!slide && slide.historyIndex > 0;\n  },\n\n  canRedo: () => {\n    const state = get();\n    const slide = state.slides.find((s) => s.id === state.activeSlideId);\n    return !!slide && slide.historyIndex < slide.history.length - 1;\n  },\n\n  setTheme: (theme) => {\n    set({ theme });\n    get().restyleDeck();\n  },\n\n  patchTheme: (partial) => {\n    const theme = {\n      ...get().theme,\n      ...partial,\n      colors: { ...get().theme.colors, ...(partial.colors || {}) },\n      fonts: { ...get().theme.fonts, ...(partial.fonts || {}) },\n      typeScale: { ...get().theme.typeScale, ...(partial.typeScale || {}) },\n      radii: { ...get().theme.radii, ...(partial.radii || {}) },\n    };\n    set({ theme });\n    get().restyleDeck();\n  },\n\n  setDeckBackground: (hex) => {\n    const color = hex.trim() || get().theme.colors.background;\n    const theme = {\n      ...get().theme,\n      colors: { ...get().theme.colors, background: color },\n    };\n    const slides = get().slides.map((s) => {\n      const base =\n        s.json && typeof s.json === 'object' && !Array.isArray(s.json)\n          ? structuredClone(s.json)\n          : {};\n      const doc = base as Record<string, unknown>;\n      doc.background = color;\n      return slideWithNewJson(s, doc);\n    });\n    set((s) =>\n      commitActiveDeck(s, {\n        theme,\n        slides,\n      })\n    );\n    scheduleAutosave();\n  },\n\n  restyleDeck: () => {\n    const { theme, slides } = get();\n    const next = slides.map((s) => slideWithNewJson(s, restyleSlideJson(s.json, theme)));\n    set((s) => commitActiveDeck(s, { slides: next }));\n    scheduleAutosave();\n  },\n\n  setSections: (sections) => {\n    set({ sections });\n    scheduleAutosave();\n  },\n\n  addSection: (name) => {\n    set((state) => ({\n      sections: [...state.sections, { id: uid('sec'), name, slideIds: [] }],\n    }));\n    scheduleAutosave();\n  },\n\n  renameSection: (id, name) => {\n    set((state) => ({\n      sections: state.sections.map((s) => (s.id === id ? { ...s, name } : s)),\n    }));\n    scheduleAutosave();\n  },\n\n  toggleSectionCollapsed: (id) => {\n    set((state) => ({\n      sections: state.sections.map((s) =>\n        s.id === id ? { ...s, collapsed: !s.collapsed } : s\n      ),\n    }));\n  },\n\n  addComment: (slideId, note, quote, objectId) => {\n    const comment: SlideComment = {\n      id: uid('cmt'),\n      note,\n      resolved: false,\n      createdAt: Date.now(),\n      quote,\n      objectId,\n    };\n    set((state) =>\n      mutateActiveSlide(state, slideId, (s) => ({\n        ...s,\n        comments: [...s.comments, comment],\n      }))\n    );\n    scheduleAutosave();\n  },\n\n  resolveComment: (slideId, commentId) => {\n    set((state) =>\n      mutateActiveSlide(state, slideId, (s) => ({\n        ...s,\n        comments: s.comments.map((c) =>\n          c.id === commentId ? { ...c, resolved: true } : c\n        ),\n      }))\n    );\n    scheduleAutosave();\n  },\n\n  removeComment: (slideId, commentId) => {\n    set((state) =>\n      mutateActiveSlide(state, slideId, (s) => ({\n        ...s,\n        comments: s.comments.filter((c) => c.id !== commentId),\n      }))\n    );\n    scheduleAutosave();\n  },\n\n  addAsset: (asset) => {\n    set((state) => {\n      const without = state.assets.filter((a) => a.id !== asset.id);\n      return { assets: [...without, asset] };\n    });\n    scheduleAutosave();\n  },\n\n  removeAsset: (id) => {\n    set((state) => ({ assets: state.assets.filter((a) => a.id !== id) }));\n    scheduleAutosave();\n  },\n\n  getOutline: () => extractOutlineFromSlides(get().slides),\n\n  applyOutline: (items) => {\n    const state = get();\n    const masterId = state.masters[0]?.id || uid('master');\n    const slides: Slide[] = [];\n    for (const item of items) {\n      const existing = item.slideId\n        ? state.slides.find((s) => s.id === item.slideId)\n        : undefined;\n      if (existing) {\n        slides.push(\n          applyOutlineToSlide(\n            existing,\n            state.theme,\n            item.title,\n            item.bullets,\n            item.layoutId\n          )\n        );\n      } else {\n        const slide = createEmptySlide(\n          masterId,\n          item.layoutId || 'bullets',\n          state.theme,\n          item.title,\n          {\n            title: item.title,\n            bullets: item.bullets.map((b) => `\u2022 ${b}`).join('\\n'),\n            body: item.bullets.map((b) => `\u2022 ${b}`).join('\\n'),\n          }\n        );\n        slides.push(slide);\n      }\n    }\n    if (!slides.length) return;\n    const activeSlideId = slides[0]!.id;\n    const sections: DeckSection[] = [\n      {\n        id: state.sections[0]?.id || uid('sec'),\n        name: state.sections[0]?.name || 'Principal',\n        slideIds: slides.map((s) => s.id),\n      },\n    ];\n    // Keep slidesProjects in sync immediately \u2014 otherwise an in-flight local\n    // save can write the previous deck and push it back into root state.\n    set((s) => {\n      const partial = { slides, activeSlideId, sections };\n      return {\n        ...partial,\n        slidesProjects: syncActiveIntoProjects({ ...s, ...partial }),\n      };\n    });\n    scheduleAutosave();\n  },\n\n  applyGeneratedDeck: async (response, opts) => {\n    const state = get();\n    const masterId = state.masters[0]?.id || uid('master');\n    const { buildDeckFromGeneratedResponse } = await import('../lib/slides/applyGeneratedDeck');\n    const { buildGenerateDeckBrandContext } = await import('../services/slides/deckService');\n\n    const visualPolicy = opts?.visualPolicy ?? {\n      preferDarkBackground: true,\n      allowGeneratedImages: true,\n      allowStockImages: true,\n      maxImages: 4,\n      includeShapes: true,\n    };\n\n    const built = await buildDeckFromGeneratedResponse(response, {\n      baseTheme: state.theme,\n      size: state.size,\n      masterId,\n      visualPolicy,\n      brandContext: buildGenerateDeckBrandContext(state.theme),\n      signal: opts?.signal,\n    });\n\n    if (!built.slides.length) {\n      throw new Error('No slides to apply');\n    }\n\n    const activeSlideId = built.slides[0]!.id;\n    const sections = [\n      {\n        id: state.sections[0]?.id || uid('sec'),\n        name: state.sections[0]?.name || 'Principal',\n        slideIds: built.slides.map((s) => s.id),\n      },\n    ];\n    const name = (built.deckTitle || state.name || '').trim() || state.name;\n\n    set((s) => {\n      const partial = {\n        theme: built.theme,\n        name,\n        slides: built.slides,\n        activeSlideId,\n        sections,\n        assets: [...s.assets, ...built.assets],\n        masters: s.masters.map((m, i) =>\n          i === 0\n            ? {\n                ...m,\n                backgroundColor: built.theme.colors.background,\n              }\n            : m\n        ),\n      };\n      return {\n        ...partial,\n        slidesProjects: syncActiveIntoProjects({ ...s, ...partial }),\n        canvasReloadEpoch: s.canvasReloadEpoch + 1,\n      };\n    });\n    scheduleAutosave();\n    return {\n      slideCount: built.slides.length,\n      imagesPlaced: built.imagesPlaced,\n      chartsPlaced: built.chartsPlaced,\n    };\n  },\n\n  applyDeckTranslation: (items) => {\n    if (!items.length) return;\n    set((state) => {\n      const byId = new Map(items.map((i) => [i.slideId, i]));\n      const slides = state.slides.map((slide) => {\n        const t = byId.get(slide.id);\n        if (!t) return slide;\n        return applyTranslatedTextsToSlide(\n          slide,\n          { title: t.title, body: t.body, notes: t.notes },\n          { title: t.previousTitle, body: t.previousBody }\n        );\n      });\n      return {\n        ...commitActiveDeck(state, { slides }),\n        canvasReloadEpoch: state.canvasReloadEpoch + 1,\n      };\n    });\n    scheduleAutosave();\n  },\n\n  findReplace: (find, replace, caseSensitive = false) => {\n    if (!find) return 0;\n    let count = 0;\n    const slides = get().slides.map((slide) => {\n      const json = structuredClone(slide.json) as { objects?: Array<Record<string, unknown>> };\n      if (!json.objects) return slide;\n      let changed = false;\n      for (const obj of json.objects) {\n        if (typeof obj.text !== 'string') continue;\n        const flags = caseSensitive ? 'g' : 'gi';\n        const re = new RegExp(find.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), flags);\n        const next = obj.text.replace(re, () => {\n          count += 1;\n          return replace;\n        });\n        if (next !== obj.text) {\n          obj.text = next;\n          changed = true;\n        }\n      }\n      if (!changed) return slide;\n      return {\n        ...slide,\n        json,\n        history: [...slide.history.slice(0, slide.historyIndex + 1), JSON.stringify(json)].slice(-50),\n        historyIndex: Math.min(slide.historyIndex + 1, 49),\n      };\n    });\n    set({ slides });\n    scheduleAutosave();\n    return count;\n  },\n\n  copySlideToLibrary: (slideId) => {\n    const slide = get().slides.find((s) => s.id === slideId);\n    return slide ? structuredClone(slide) : null;\n  },\n\n  pasteSlideFromLibrary: (slide) => {\n    const state = get();\n    const copy: Slide = {\n      ...structuredClone(slide),\n      id: uid('slide'),\n      masterId: state.masters[0]?.id || slide.masterId,\n      json: restyleSlideJson(slide.json, state.theme),\n    };\n    set({\n      slides: [...state.slides, copy],\n      activeSlideId: copy.id,\n    });\n    scheduleAutosave();\n  },\n\n  applyMagicLayout: async (slideId) => {\n    const state = get();\n    const id = slideId || state.activeSlideId;\n    if (!id) return;\n    const slide = state.slides.find((s) => s.id === id);\n    if (!slide) return;\n    const json = structuredClone(slide.json) as { objects?: Array<Record<string, unknown>> };\n    const objects = json.objects || [];\n    const elements = objects.map((o) => ({\n      id: String(o.id || uid('obj')),\n      type: String(o.type || ''),\n      text: typeof o.text === 'string' ? o.text : undefined,\n      role: String(o.placeholderRole || o.themeRole || ''),\n      width: Number(o.width || 200) * Number(o.scaleX || 1),\n      height: Number(o.height || 80) * Number(o.scaleY || 1),\n    }));\n    // ensure ids\n    objects.forEach((o, i) => {\n      if (!o.id) o.id = elements[i]!.id;\n    });\n\n    let placements = computeMagicLayout(elements, state.size);\n    try {\n      const remote = await suggestLayout({\n        elements: elements.map((e) => ({\n          id: e.id,\n          type: e.type,\n          text: e.text,\n          width: e.width,\n          height: e.height,\n        })),\n        canvas: { width: state.size.width, height: state.size.height },\n      });\n      if (remote.placements?.length) placements = remote.placements;\n    } catch {\n      // Fall back to local magic layout when BFF / .NET is unavailable.\n    }\n\n    for (const p of placements) {\n      const obj = objects.find((o) => o.id === p.id);\n      if (!obj) continue;\n      obj.left = p.left;\n      obj.top = p.top;\n      obj.width = p.width;\n      obj.scaleX = 1;\n      obj.scaleY = 1;\n      if (obj.type === 'Textbox' || obj.type === 'IText') obj.height = p.height;\n    }\n    get().updateSlideJson(id, { ...json, objects }, true);\n    get().addToast(getActiveMessages().store.toasts.slides.magicLayoutApplied, 'success');\n  },\n\n  applyDesignFix: (kind, slideId) => {\n    const state = get();\n    const id = slideId || state.activeSlideId;\n    if (!id) return;\n    const slide = state.slides.find((s) => s.id === id);\n    if (!slide) return;\n    const { json, note } = applyDesignFixToJson(slide.json, kind, state.theme);\n    get().updateSlideJson(id, json, true);\n    get().addToast(note, 'success');\n  },\n\n  applySemanticRestyle: (mode) => {\n    const state = get();\n    const slides = state.slides.map((s) =>\n      slideWithNewJson(s, semanticRestyleJson(s.json, mode, state.theme))\n    );\n    set((s) => commitActiveDeck(s, { slides }));\n    scheduleAutosave();\n    get().addToast(getActiveMessages().store.toasts.slides.restyleApplied(mode), 'success');\n  },\n\n  insertChart: async (data) => {\n    const state = get();\n    const id = state.activeSlideId;\n    if (!id) return;\n    const slide = state.slides.find((s) => s.id === id);\n    if (!slide) return;\n    const obj = await buildChartFabricObject(data, state.theme, {\n      left: 200,\n      top: 180,\n      width: 1520,\n      height: 720,\n    });\n    const json = structuredClone(slide.json) as { objects?: Array<Record<string, unknown>> };\n    json.objects = [...(json.objects || []).filter((o) => o.placeholderRole !== 'chart'), obj];\n    get().updateSlideJson(id, json, true);\n    get().addToast(getActiveMessages().store.toasts.slides.chartInserted, 'success');\n  },\n\n  resizeDeck: (width, height) => {\n    const state = get();\n    const from = state.size;\n    const slides = state.slides.map((s) =>\n      slideWithNewJson(s, reflowSlideJson(s.json, from, { width, height }))\n    );\n    set((s) => commitActiveDeck(s, { size: { width, height }, slides }));\n    scheduleAutosave();\n    get().addToast(getActiveMessages().store.toasts.slides.canvasResized(width, height), 'success');\n  },\n\n  setObjectAlt: (slideId, objectId, alt) => {\n    const slide = get().slides.find((s) => s.id === slideId);\n    if (!slide) return;\n    const json = structuredClone(slide.json) as { objects?: Array<Record<string, unknown>> };\n    for (const o of json.objects || []) {\n      if (o.id === objectId) o.alt = alt;\n    }\n    get().updateSlideJson(slideId, json, true);\n  },\n\n  splitDenseSlide: (slideId) => {\n    const state = get();\n    const id = slideId || state.activeSlideId;\n    if (!id) return;\n    const outline = state.getOutline().find((o) => o.slideId === id);\n    if (!outline || outline.bullets.length < 4) {\n      get().addToast(getActiveMessages().store.toasts.slides.notEnoughContentToSplit, 'info');\n      return;\n    }\n    const mid = Math.ceil(outline.bullets.length / 2);\n    const a = outline.bullets.slice(0, mid);\n    const b = outline.bullets.slice(mid);\n    get().applyLayoutContent(id, {\n      title: outline.title,\n      bullets: a.map((x) => `\u2022 ${x}`).join('\\n'),\n      body: a.map((x) => `\u2022 ${x}`).join('\\n'),\n    });\n    const newId = get().addSlide('bullets', id);\n    get().applyLayoutContent(newId, {\n      title: `${outline.title} (cont.)`,\n      bullets: b.map((x) => `\u2022 ${x}`).join('\\n'),\n      body: b.map((x) => `\u2022 ${x}`).join('\\n'),\n    });\n    get().addToast(getActiveMessages().store.toasts.slides.denseSlideSplit, 'success');\n  },\n\n  addToast: (message, type = 'info') => {\n    const id = uid('toast');\n    const safe =\n      type === 'error'\n        ? sanitizeUserFacingMessage(message, { context: 'toast:slides' })\n        : message;\n    set((state) => ({ toasts: [...state.toasts, { id, message: safe, type }] }));\n    setTimeout(() => get().removeToast(id), 4000);\n  },\n\n  removeToast: (id) => {\n    set((state) => ({ toasts: state.toasts.filter((t) => t.id !== id) }));\n  },\n}));\n\nslidesPersistence = createProjectPersistence({\n  mode: 'slides',\n  localDebounceMs: 400,\n  cloudDebounceMs: 3000,\n  saveLocal: async () => {\n    await useSlidesStore.getState().saveSlidesProject();\n  },\n  saveCloud: async () => useSlidesStore.getState().autoSaveSlidesProjectToCloud(),\n});\nregisterProjectPersistence(slidesPersistence);\n\nexport function flushSlidesPersistence(): Promise<void> {\n  return slidesPersistence.flush();\n}\n\nexport { cloneTheme };\n", "/**\n * Editable service \u2014 CRUD for user-saved editor projects (kai* / legacy wzrd*)\n * backed by the .NET at /api/kaiman/editables.\n *\n * The .NET stores the file binary in S3 and returns a metadata record with\n * the public/signed URL. The editor never constructs the URL itself \u2014 it\n * uses the `url` field returned by the API for subsequent downloads\n * (via `downloadEditableBinary`).\n *\n * Conventions to keep in sync with the .NET (verified against Swagger):\n *  - Multipart field names are camelCase: `file`, `accountId`, `brandId`,\n *    `name`, `mode` (NOT snake_case like the other editor services).\n *  - The `mode` input is an integer (0 = Image, 1 = Video); the response\n *    serializes the same field as the string \"Image\" | \"Video\".\n *  - The list endpoint returns a flat JSON array (no pagination wrapper).\n *  - `brandId` query param is optional on list: omit to list across the\n *    account, pass to scope to a single brand.\n *  - The `createdAt` from POST is `0001-01-01T00:00:00` until the next\n *    GET refresh \u2014 don't trust it from the create response.\n */\n\nimport { getEditorIdentity } from './identity';\nimport { getWizardApiClient } from './wizardApiClient';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Input `mode` for upload. 0 = Image, 1 = Video, 2 = Audio, 3 = Text, 4 = Slides.\n *  Audio/Text/Slides require .NET support \u2014 gated by FEATURE_CLOUD_* flags in the UI. */\nexport type EditableModeInput = 0 | 1 | 2 | 3 | 4;\n\n/** Response `mode` (string). */\nexport type EditableMode = 'Image' | 'Video' | 'Audio' | 'Text' | 'Slides';\n\n/** Metadata record returned by the .NET for one editable. */\nexport interface Editable {\n  id: number;\n  accountId: number;\n  brandId: number;\n  name: string;\n  /** S3 URL where the binary is stored. Fetched with `downloadEditableBinary`. */\n  url: string;\n  mode: EditableMode;\n  /** ISO timestamp. From POST this is the zero value until a GET refresh. */\n  createdAt: string;\n}\n\nconst MODE_BY_INT: Record<number, EditableMode> = {\n  0: 'Image',\n  1: 'Video',\n  2: 'Audio',\n  3: 'Text',\n  4: 'Slides',\n};\n\nconst MODE_BY_KEY: Record<string, EditableMode> = {\n  image: 'Image',\n  video: 'Video',\n  audio: 'Audio',\n  text: 'Text',\n  slides: 'Slides',\n  '0': 'Image',\n  '1': 'Video',\n  '2': 'Audio',\n  '3': 'Text',\n  '4': 'Slides',\n};\n\n/** Infer mode from kai* / wzrd* extension when API mode is missing or wrong. */\nexport function inferEditableModeFromUrl(urlOrName: string): EditableMode | null {\n  const lower = urlOrName.toLowerCase().split('?')[0] || '';\n  if (lower.endsWith('.kaiv') || lower.endsWith('.wzrdv')) return 'Video';\n  if (lower.endsWith('.kaia') || lower.endsWith('.wzrda')) return 'Audio';\n  if (lower.endsWith('.kait') || lower.endsWith('.wzrdt')) return 'Text';\n  if (lower.endsWith('.kais') || lower.endsWith('.wzrds')) return 'Slides';\n  if (lower.endsWith('.kai') || lower.endsWith('.wzrd')) return 'Image';\n  return null;\n}\n\n/**\n * .NET / BFF sometimes return mode as int (0..4), lowercase (\"image\"),\n * or the wrong enum. Recientes filters with PascalCase \u2014 normalize here.\n */\nexport function normalizeEditableMode(\n  raw: unknown,\n  urlOrName?: string\n): EditableMode {\n  if (typeof raw === 'number' && Number.isFinite(raw) && MODE_BY_INT[raw]) {\n    return MODE_BY_INT[raw]!;\n  }\n  if (typeof raw === 'string') {\n    const trimmed = raw.trim();\n    const keyed = MODE_BY_KEY[trimmed.toLowerCase()];\n    if (keyed) return keyed;\n    if (\n      trimmed === 'Image' ||\n      trimmed === 'Video' ||\n      trimmed === 'Audio' ||\n      trimmed === 'Text' ||\n      trimmed === 'Slides'\n    ) {\n      return trimmed;\n    }\n    const asNum = Number(trimmed);\n    if (Number.isFinite(asNum) && MODE_BY_INT[asNum]) return MODE_BY_INT[asNum]!;\n  }\n  const inferred = urlOrName ? inferEditableModeFromUrl(urlOrName) : null;\n  return inferred ?? 'Image';\n}\n\nexport function normalizeEditable(raw: unknown): Editable | null {\n  if (!raw || typeof raw !== 'object') return null;\n  const o = raw as Record<string, unknown>;\n\n  const idRaw =\n    o.id ?? o.Id ?? o.editableId ?? o.editable_id ?? o.EditableId;\n  const id =\n    typeof idRaw === 'number'\n      ? idRaw\n      : typeof idRaw === 'string' && /^\\d+$/.test(idRaw)\n        ? Number(idRaw)\n        : NaN;\n  if (!Number.isFinite(id)) return null;\n\n  const nameRaw = o.name ?? o.Name ?? o.fileName ?? o.FileName ?? o.title;\n  const name = typeof nameRaw === 'string' && nameRaw.trim() ? nameRaw : `editable-${id}`;\n\n  const urlRaw = o.url ?? o.Url ?? o.s3Url ?? o.s3_url ?? o.fileUrl ?? o.FileUrl;\n  const url = typeof urlRaw === 'string' ? urlRaw : '';\n\n  const mode = normalizeEditableMode(o.mode ?? o.Mode ?? o.editableMode, url || name);\n\n  const createdRaw = o.createdAt ?? o.CreatedAt ?? o.created_at ?? o.updatedAt;\n  const createdAt =\n    typeof createdRaw === 'string'\n      ? createdRaw\n      : typeof createdRaw === 'number'\n        ? new Date(createdRaw).toISOString()\n        : '';\n\n  const accountRaw = o.accountId ?? o.AccountId ?? o.account_id;\n  const brandRaw = o.brandId ?? o.BrandId ?? o.brand_id;\n\n  return {\n    id,\n    accountId: typeof accountRaw === 'number' ? accountRaw : Number(accountRaw) || 0,\n    brandId: typeof brandRaw === 'number' ? brandRaw : Number(brandRaw) || 0,\n    name,\n    url,\n    mode,\n    createdAt,\n  };\n}\n\nfunction unwrapEditableArray(raw: unknown): unknown[] {\n  if (Array.isArray(raw)) return raw;\n  if (!raw || typeof raw !== 'object') return [];\n  const obj = raw as Record<string, unknown>;\n  const candidates = [\n    obj.items,\n    obj.editables,\n    obj.data,\n    obj.result,\n    obj.results,\n    obj.value,\n    obj.Value,\n    obj.$values,\n  ];\n  for (const c of candidates) {\n    if (Array.isArray(c)) return c;\n  }\n  // Nested: { data: { items: [] } }\n  for (const c of candidates) {\n    if (c && typeof c === 'object' && !Array.isArray(c)) {\n      const nested = unwrapEditableArray(c);\n      if (nested.length) return nested;\n    }\n  }\n  return [];\n}\n\nfunction normalizeEditableList(raw: unknown): Editable[] {\n  return unwrapEditableArray(raw)\n    .map((item) => normalizeEditable(item))\n    .filter((e): e is Editable => e != null);\n}\n\n// \u2500\u2500 POST /api/kaiman/editables \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface UploadEditableOptions {\n  /** The .wzrd/.wzrdv binary as a Blob or File. */\n  file: Blob;\n  /** Display name of the project. The .NET does not append an extension. */\n  name: string;\n  /** 0 = Image, 1 = Video, 2 = Audio. */\n  mode: EditableModeInput;\n  signal?: AbortSignal;\n}\n\n/**\n * Uploads a project file to the .NET and returns the new record's metadata.\n * The response's `createdAt` is the zero value at this point \u2014 fetch the\n * list again if the caller needs the real timestamp.\n */\nexport function uploadEditable(opts: UploadEditableOptions): Promise<Editable> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient()\n    .postMultipartForJson<unknown>('/api/kaiman/editables', {\n      file: opts.file,\n      accountId,\n      brandId,\n      name: opts.name,\n      mode: opts.mode,\n    }, { signal: opts.signal })\n    .then((raw) => {\n      const normalized = normalizeEditable(raw);\n      if (!normalized) {\n        throw new Error('Upload succeeded but editable metadata was unreadable');\n      }\n      // Prefer caller mode if API omitted/mangled it.\n      return {\n        ...normalized,\n        mode: normalizeEditableMode(normalized.mode || opts.mode, opts.name),\n        name: normalized.name || opts.name,\n      };\n    });\n}\n\n// \u2500\u2500 PATCH /api/kaiman/editables/{id} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface UpdateEditableOptions {\n  id: number;\n  /** When supplied, the existing S3 file is deleted and replaced. */\n  file?: Blob;\n  /** Optional new display name. */\n  name?: string;\n  signal?: AbortSignal;\n}\n\n/**\n * Updates an existing editable in place (PATCH). Prefer this over\n * uploadEditable + delete when the project already has a `cloudEditableId`,\n * so Recientes does not accumulate duplicate canvases on every autosave.\n *\n * At least one of `file` or `name` must be provided (.NET + BFF require it).\n * A 204 / empty body is treated as success and returns a minimal Editable\n * with the same `id`.\n */\nexport async function updateEditable(\n  opts: UpdateEditableOptions\n): Promise<Editable> {\n  const name = opts.name?.trim();\n  if (!opts.file && !name) {\n    throw new Error(\"updateEditable requires at least one of 'file' or 'name'\");\n  }\n\n  const { accountId, brandId } = getEditorIdentity();\n  const fields: Record<string, string | number | Blob> = { accountId };\n  if (name) fields.name = name;\n  if (opts.file) fields.file = opts.file;\n\n  const data = await getWizardApiClient().patchMultipartForJson<\n    Partial<Editable> | undefined\n  >(`/api/kaiman/editables/${opts.id}`, fields, { signal: opts.signal });\n\n  if (data && typeof data.id === 'number') {\n    return normalizeEditable(data) ?? {\n      id: opts.id,\n      accountId,\n      brandId,\n      name: name ?? '',\n      url: typeof data.url === 'string' ? data.url : '',\n      mode: normalizeEditableMode(data.mode),\n      createdAt: typeof data.createdAt === 'string' ? data.createdAt : '',\n    };\n  }\n\n  return {\n    id: opts.id,\n    accountId,\n    brandId,\n    name: name ?? '',\n    url: typeof data?.url === 'string' ? data.url : '',\n    mode: normalizeEditableMode(data?.mode),\n    createdAt: typeof data?.createdAt === 'string' ? data.createdAt : '',\n  };\n}\n\n// \u2500\u2500 GET /api/kaiman/editables \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface ListEditablesOptions {\n  /**\n   * If set, scopes the list to a single brand. If omitted, the .NET returns\n   * every editable across the account (accountId comes from the editor's\n   * identity). Pass the editor's own brandId for the common \"mine in this\n   * brand\" case.\n   */\n  brandId?: number | string;\n  /**\n   * `account` = list across the whole account (BFF omits brandId).\n   * Useful when Recientes looks empty after brand cookie changes.\n   */\n  scope?: 'brand' | 'account';\n  signal?: AbortSignal;\n}\n\n/**\n * Lists editables. Returns a flat JSON array (no pagination wrapper).\n * Modes are normalized to PascalCase (`Image`|`Video`|\u2026) so Recientes\n * filters work even when .NET returns ints or lowercase labels.\n */\nexport async function listEditables(\n  opts: ListEditablesOptions = {}\n): Promise<Editable[]> {\n  const { accountId, brandId: identityBrandId } = getEditorIdentity();\n  const scope = opts.scope ?? 'brand';\n  const query: Record<string, string | number | boolean | undefined | null> = {\n    accountId,\n  };\n  if (scope === 'account') {\n    query.scope = 'account';\n  } else {\n    query.brandId = opts.brandId ?? identityBrandId;\n  }\n  const raw = await getWizardApiClient().getForJson<unknown>(\n    '/api/kaiman/editables',\n    query,\n    { signal: opts.signal }\n  );\n  return normalizeEditableList(raw);\n}\n\n// \u2500\u2500 GET /api/kaiman/editables/{id} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface GetEditableOptions {\n  id: number;\n  signal?: AbortSignal;\n}\n\n/** Fetches a single editable's metadata (same shape as the list items). */\nexport async function getEditable(opts: GetEditableOptions): Promise<Editable> {\n  const raw = await getWizardApiClient().getForJson<unknown>(\n    `/api/kaiman/editables/${opts.id}`,\n    undefined,\n    { signal: opts.signal }\n  );\n  const normalized = normalizeEditable(raw);\n  if (!normalized) {\n    throw new Error(`Editable ${opts.id} metadata was unreadable`);\n  }\n  return normalized;\n}\n\n// \u2500\u2500 DELETE /api/kaiman/editables/{id} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface DeleteEditableOptions {\n  id: number;\n  signal?: AbortSignal;\n}\n\n/**\n * Deletes an editable by id. The .NET requires `accountId` as a query param\n * (taken from the editor identity). Returns void on a 204/empty body.\n */\nexport function deleteEditable(opts: DeleteEditableOptions): Promise<void> {\n  const { accountId } = getEditorIdentity();\n  return getWizardApiClient().deleteForJson<void>(\n    `/api/kaiman/editables/${opts.id}`,\n    { accountId },\n    { signal: opts.signal }\n  );\n}\n\n// \u2500\u2500 Download binary (S3) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface DownloadEditableBinaryOptions {\n  /** The `url` field from a list/get/upload response. */\n  url: string;\n  signal?: AbortSignal;\n}\n\n/**\n * Downloads the .wzrd/.wzrdv binary from the S3 URL returned by the .NET.\n *\n * This is a plain `fetch` (not the wizardApiClient) because the URL points\n * at S3, not the .NET API. The browser will hit CORS for the cross-origin\n * request \u2014 if the bucket isn't configured for the editor's origin this will\n * fail at the browser level (not the .NET). CORS errors here are an S3\n * config bug, not a code bug.\n *\n * We still send the session cookie (`credentials: 'include'`) in case the\n * bucket is private and the .NET set up a signed-cookie flow \u2014 public\n * buckets ignore it.\n */\nexport async function downloadEditableBinary(\n  opts: DownloadEditableBinaryOptions\n): Promise<Blob> {\n  const res = await fetch(opts.url, {\n    signal: opts.signal,\n    credentials: 'include',\n  });\n  if (!res.ok) {\n    const detail = (await res.text().catch(() => res.statusText)) || res.statusText;\n    throw new Error(`Failed to download editable from S3: HTTP ${res.status} \u2014 ${detail}`);\n  }\n  return res.blob();\n}\n", "/**\n * .wzrda project format \u2014 same binary container as .wzrdv (WZRDPROJ magic).\n */\n\nimport type { AudioAsset, AudioMarker, AudioProject, AudioRegion, AudioTrack } from '../store/useAudioStore';\n\nexport interface AudioProjectFileData {\n  name: string;\n  sampleRate: number;\n  bpm: number;\n  timeSignature: [number, number];\n  tracks: AudioTrack[];\n  markers: AudioMarker[];\n  regions: AudioRegion[];\n  assets: AudioAsset[];\n  projectDuration: number;\n}\n\nfunction encodeString(str: string): Uint8Array {\n  return new TextEncoder().encode(str);\n}\n\n/** Ensure Uint8Array is accepted as BlobPart under strict lib DOM typings. */\nfunction toBlobPart(bytes: Uint8Array): BlobPart {\n  return Uint8Array.from(bytes);\n}\n\nfunction decodeString(bytes: Uint8Array): string {\n  return new TextDecoder().decode(bytes);\n}\n\nfunction float32ToBase64(peaks: Float32Array): string {\n  const bytes = new Uint8Array(peaks.buffer, peaks.byteOffset, peaks.byteLength);\n  let bin = '';\n  for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]!);\n  return btoa(bin);\n}\n\nfunction base64ToFloat32(b64: string): Float32Array {\n  const bin = atob(b64);\n  const bytes = new Uint8Array(bin.length);\n  for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);\n  return new Float32Array(bytes.buffer);\n}\n\nexport async function exportProjectToWzrda(project: {\n  name: string;\n  sampleRate: number;\n  bpm: number;\n  timeSignature: [number, number];\n  tracks: AudioTrack[];\n  markers: AudioMarker[];\n  regions: AudioRegion[];\n  assets: AudioAsset[];\n  projectDuration: number;\n}): Promise<Blob> {\n  const metadata = {\n    name: project.name,\n    sampleRate: project.sampleRate,\n    bpm: project.bpm,\n    timeSignature: project.timeSignature,\n    tracks: project.tracks,\n    markers: project.markers,\n    regions: project.regions,\n    projectDuration: project.projectDuration,\n    assets: project.assets.map((a) => ({\n      id: a.id,\n      name: a.name,\n      duration: a.duration,\n      sampleRate: a.sampleRate,\n      channels: a.channels,\n      peaksSampleRate: a.peaksSampleRate,\n      peaksBase64: a.peaks ? float32ToBase64(a.peaks) : undefined,\n    })),\n  };\n\n  const jsonBytes = encodeString(JSON.stringify(metadata));\n  const filesToPack: { id: string; file: File; name: string; type: string }[] = [];\n  for (const asset of project.assets) {\n    if (asset.file) {\n      filesToPack.push({\n        id: asset.id,\n        file: asset.file,\n        name: asset.name,\n        type: asset.file.type || 'audio/mpeg',\n      });\n    }\n  }\n\n  const parts: BlobPart[] = [];\n  parts.push(toBlobPart(encodeString('WZRDPROJ')));\n  const jsonLenBuf = new ArrayBuffer(4);\n  new DataView(jsonLenBuf).setUint32(0, jsonBytes.length, true);\n  parts.push(jsonLenBuf);\n  parts.push(toBlobPart(jsonBytes));\n\n  const numFilesBuf = new ArrayBuffer(4);\n  new DataView(numFilesBuf).setUint32(0, filesToPack.length, true);\n  parts.push(numFilesBuf);\n\n  const fileBlobs: Blob[] = [];\n  for (const f of filesToPack) {\n    const idBytes = encodeString(f.id);\n    const nameBytes = encodeString(f.name);\n    const typeBytes = encodeString(f.type);\n    const fileHeaderBuf = new ArrayBuffer(16);\n    const view = new DataView(fileHeaderBuf);\n    view.setUint32(0, idBytes.length, true);\n    view.setUint32(4, nameBytes.length, true);\n    view.setUint32(8, typeBytes.length, true);\n    view.setUint32(12, f.file.size, true);\n    parts.push(\n      fileHeaderBuf,\n      toBlobPart(idBytes),\n      toBlobPart(nameBytes),\n      toBlobPart(typeBytes)\n    );\n    fileBlobs.push(f.file);\n  }\n\n  return new Blob([...parts, ...fileBlobs], { type: 'application/octet-stream' });\n}\n\nexport async function importProjectFromWzrda(fileBlob: Blob): Promise<AudioProjectFileData> {\n  const arrayBuffer = await fileBlob.arrayBuffer();\n  const view = new DataView(arrayBuffer);\n  let offset = 0;\n\n  const magic = decodeString(new Uint8Array(arrayBuffer, offset, 8));\n  offset += 8;\n  if (magic !== 'WZRDPROJ') {\n    throw new Error('Invalid .wzrda file (bad magic)');\n  }\n\n  const jsonLen = view.getUint32(offset, true);\n  offset += 4;\n  const jsonStr = decodeString(new Uint8Array(arrayBuffer, offset, jsonLen));\n  offset += jsonLen;\n  const metadata = JSON.parse(jsonStr) as Omit<AudioProjectFileData, 'assets'> & {\n    assets: Array<{\n      id: string;\n      name: string;\n      duration: number;\n      sampleRate?: number;\n      channels?: number;\n      peaksSampleRate?: number;\n      peaksBase64?: string;\n    }>;\n  };\n\n  const numFiles = view.getUint32(offset, true);\n  offset += 4;\n\n  const fileMap = new Map<string, { name: string; type: string; data: Uint8Array }>();\n  const headers: Array<{ id: string; name: string; type: string; size: number }> = [];\n\n  for (let i = 0; i < numFiles; i++) {\n    const idLen = view.getUint32(offset, true);\n    const nameLen = view.getUint32(offset + 4, true);\n    const typeLen = view.getUint32(offset + 8, true);\n    const size = view.getUint32(offset + 12, true);\n    offset += 16;\n    const id = decodeString(new Uint8Array(arrayBuffer, offset, idLen));\n    offset += idLen;\n    const name = decodeString(new Uint8Array(arrayBuffer, offset, nameLen));\n    offset += nameLen;\n    const type = decodeString(new Uint8Array(arrayBuffer, offset, typeLen));\n    offset += typeLen;\n    headers.push({ id, name, type, size });\n  }\n\n  for (const h of headers) {\n    const data = new Uint8Array(arrayBuffer, offset, h.size);\n    offset += h.size;\n    fileMap.set(h.id, { name: h.name, type: h.type, data });\n  }\n\n  const assets: AudioAsset[] = (metadata.assets || []).map((meta) => {\n    const peaks = meta.peaksBase64 ? base64ToFloat32(meta.peaksBase64) : undefined;\n    const packed = fileMap.get(meta.id);\n    if (packed) {\n      const blob = new Blob([toBlobPart(packed.data)], { type: packed.type });\n      const url = URL.createObjectURL(blob);\n      const file = new File([blob], packed.name || meta.name, { type: packed.type });\n      return {\n        id: meta.id,\n        name: meta.name,\n        url,\n        duration: meta.duration,\n        sampleRate: meta.sampleRate,\n        channels: meta.channels,\n        file,\n        peaks,\n        peaksSampleRate: meta.peaksSampleRate,\n      };\n    }\n    return {\n      id: meta.id,\n      name: meta.name,\n      url: '',\n      duration: meta.duration,\n      sampleRate: meta.sampleRate,\n      channels: meta.channels,\n      file: new File([], meta.name),\n      peaks,\n      peaksSampleRate: meta.peaksSampleRate,\n    };\n  });\n\n  return {\n    name: metadata.name || 'Proyecto',\n    sampleRate: metadata.sampleRate || 48000,\n    bpm: metadata.bpm || 120,\n    timeSignature: metadata.timeSignature || [4, 4],\n    tracks: metadata.tracks || [],\n    markers: metadata.markers || [],\n    regions: metadata.regions || [],\n    assets,\n    projectDuration: metadata.projectDuration || 60,\n  };\n}\n\n/** Lightweight JSON snapshot (no media bytes). Cloud upload uses .wzrda binary instead. */\nexport function serializeAudioProjectForCloud(state: {\n  name: string;\n  sampleRate: number;\n  bpm: number;\n  timeSignature: [number, number];\n  tracks: AudioTrack[];\n  markers: AudioMarker[];\n  regions: AudioRegion[];\n  assets: AudioAsset[];\n  projectDuration: number;\n}): string {\n  return JSON.stringify({\n    name: state.name,\n    sampleRate: state.sampleRate,\n    bpm: state.bpm,\n    timeSignature: state.timeSignature,\n    tracks: state.tracks,\n    markers: state.markers,\n    regions: state.regions,\n    projectDuration: state.projectDuration,\n    assets: state.assets.map(({ file: _f, url: _u, peaks: _p, ...meta }) => meta),\n  });\n}\n\nexport type { AudioProject };\n", "/**\n * .wzrdt project format \u2014 WZRDPROJ binary container (JSON + optional embedded assets).\n * schemaVersion 2: workflow, seo, comments, claims, brand OS fields.\n */\n\nimport type { JSONContent } from '@tiptap/core';\nimport type {\n  BrandVoiceProfile,\n  TextDocType,\n  TextChannel,\n  TextProject,\n  TextSnapshot,\n  TextSuggestion,\n  TextTone,\n  TextVariant,\n  TextWorkflowStatus,\n  TextSeoMeta,\n  TextComment,\n  TextClaim,\n} from '../store/useTextStore';\nimport type { OutlineItem } from '../lib/text/outline';\nimport type { ReadabilityMetrics } from '../lib/text/readability';\nimport type { ClarityExtras } from '../lib/text/clarity';\n\nexport const TEXT_PROJECT_SCHEMA_VERSION = 2;\n\nexport interface TextProjectFileData {\n  schemaVersion?: number;\n  name: string;\n  docType: TextDocType;\n  language: string;\n  tone: TextTone;\n  targetChannel: TextChannel;\n  doc: JSONContent;\n  outline: OutlineItem[];\n  variants: TextVariant[];\n  suggestions: TextSuggestion[];\n  snapshots: TextSnapshot[];\n  brandVoice: BrandVoiceProfile;\n  metrics: ReadabilityMetrics;\n  clarity?: ClarityExtras;\n  workflowStatus?: TextWorkflowStatus;\n  seoMeta?: TextSeoMeta;\n  comments?: TextComment[];\n  claims?: TextClaim[];\n  enforceComplianceOnExport?: boolean;\n}\n\nfunction encodeString(str: string): Uint8Array {\n  return new TextEncoder().encode(str);\n}\n\nfunction decodeString(bytes: Uint8Array): string {\n  return new TextDecoder().decode(bytes);\n}\n\nexport async function exportProjectToWzrdt(project: TextProjectFileData): Promise<Blob> {\n  const metadata = {\n    schemaVersion: TEXT_PROJECT_SCHEMA_VERSION,\n    name: project.name,\n    docType: project.docType,\n    language: project.language,\n    tone: project.tone,\n    targetChannel: project.targetChannel,\n    doc: project.doc,\n    outline: project.outline,\n    variants: project.variants,\n    suggestions: project.suggestions,\n    snapshots: project.snapshots,\n    brandVoice: project.brandVoice,\n    metrics: project.metrics,\n    clarity: project.clarity,\n    workflowStatus: project.workflowStatus ?? 'draft',\n    seoMeta: project.seoMeta,\n    comments: project.comments ?? [],\n    claims: project.claims ?? [],\n    enforceComplianceOnExport: project.enforceComplianceOnExport ?? false,\n  };\n\n  const jsonBytes = encodeString(JSON.stringify(metadata));\n  const magic = encodeString('WZRDPROJ');\n  const jsonLenBuf = new ArrayBuffer(4);\n  new DataView(jsonLenBuf).setUint32(0, jsonBytes.length, true);\n  const numFilesBuf = new ArrayBuffer(4);\n  new DataView(numFilesBuf).setUint32(0, 0, true);\n\n  const toAb = (u8: Uint8Array): ArrayBuffer => {\n    const copy = new Uint8Array(u8.byteLength);\n    copy.set(u8);\n    return copy.buffer;\n  };\n  return new Blob([toAb(magic), jsonLenBuf, toAb(jsonBytes), numFilesBuf], {\n    type: 'application/octet-stream',\n  });\n}\n\nexport async function importProjectFromWzrdt(file: Blob): Promise<TextProjectFileData> {\n  const buf = await file.arrayBuffer();\n  const bytes = new Uint8Array(buf);\n  const magic = decodeString(bytes.slice(0, 8));\n  if (magic !== 'WZRDPROJ') {\n    const text = decodeString(bytes);\n    const data = JSON.parse(text) as TextProjectFileData;\n    if (!data.doc) throw new Error('Invalid text project JSON');\n    return data;\n  }\n\n  const view = new DataView(buf);\n  const jsonLen = view.getUint32(8, true);\n  const jsonBytes = bytes.slice(12, 12 + jsonLen);\n  const data = JSON.parse(decodeString(jsonBytes)) as TextProjectFileData;\n  if (!data.doc) throw new Error('Invalid .wzrdt metadata');\n  return data;\n}\n\nexport function serializeTextProjectForCloud(state: TextProjectFileData): string {\n  return JSON.stringify({\n    schemaVersion: TEXT_PROJECT_SCHEMA_VERSION,\n    name: state.name,\n    docType: state.docType,\n    language: state.language,\n    tone: state.tone,\n    targetChannel: state.targetChannel,\n    doc: state.doc,\n    outline: state.outline,\n    variants: state.variants,\n    suggestions: state.suggestions.map(({ ...s }) => s),\n    snapshots: state.snapshots,\n    brandVoice: state.brandVoice,\n    metrics: state.metrics,\n    clarity: state.clarity,\n    workflowStatus: state.workflowStatus,\n    seoMeta: state.seoMeta,\n    comments: state.comments,\n    claims: state.claims,\n    enforceComplianceOnExport: state.enforceComplianceOnExport,\n  });\n}\n\nexport function textProjectFromStore(p: TextProject): TextProjectFileData {\n  return {\n    schemaVersion: TEXT_PROJECT_SCHEMA_VERSION,\n    name: p.name,\n    docType: p.docType,\n    language: p.language,\n    tone: p.tone,\n    targetChannel: p.targetChannel,\n    doc: p.doc,\n    outline: p.outline,\n    variants: p.variants,\n    suggestions: p.suggestions,\n    snapshots: p.snapshots,\n    brandVoice: p.brandVoice,\n    metrics: p.metrics,\n    clarity: p.clarity,\n    workflowStatus: p.workflowStatus,\n    seoMeta: p.seoMeta,\n    comments: p.comments,\n    claims: p.claims,\n    enforceComplianceOnExport: p.enforceComplianceOnExport,\n  };\n}\n", "/**\n * .kais project format (legacy alias `.wzrds`) \u2014 WZRDPROJ binary container\n * with embedded media assets.\n */\n\nimport type { SlideDeck, SlidesAsset } from '../types/slides.types';\nimport { SLIDES_SCHEMA_VERSION } from '../types/slides.types';\n\nexport interface SlidesProjectFileData extends Omit<SlideDeck, 'id' | 'createdAt' | 'updatedAt'> {\n  name: string;\n}\n\nfunction encodeString(str: string): Uint8Array {\n  return new TextEncoder().encode(str);\n}\n\nfunction decodeString(bytes: Uint8Array): string {\n  return new TextDecoder().decode(bytes);\n}\n\nfunction toArrayBuffer(bytes: Uint8Array): ArrayBuffer {\n  const copy = new Uint8Array(bytes.byteLength);\n  copy.set(bytes);\n  return copy.buffer;\n}\n\nexport function slidesProjectFromStore(deck: SlideDeck): SlidesProjectFileData {\n  return {\n    name: deck.name,\n    size: deck.size,\n    theme: deck.theme,\n    masters: deck.masters,\n    slides: deck.slides.map((s) => ({\n      ...s,\n      // Drop heavy history on disk export (keep last state)\n      history: [JSON.stringify(s.json)],\n      historyIndex: 0,\n      // Keep raster thumbnails for Recientes / empty-state previews\n      thumbnail:\n        typeof s.thumbnail === 'string' && s.thumbnail.startsWith('data:')\n          ? s.thumbnail\n          : undefined,\n    })),\n    sections: deck.sections,\n    assets: deck.assets,\n    activeSlideId: deck.activeSlideId,\n    schemaVersion: deck.schemaVersion || SLIDES_SCHEMA_VERSION,\n    template: deck.template,\n  };\n}\n\nexport async function exportProjectToWzrds(project: SlidesProjectFileData): Promise<Blob> {\n  const metadata = {\n    name: project.name,\n    size: project.size,\n    theme: project.theme,\n    masters: project.masters,\n    slides: project.slides,\n    sections: project.sections,\n    activeSlideId: project.activeSlideId,\n    schemaVersion: project.schemaVersion || SLIDES_SCHEMA_VERSION,\n    template: project.template,\n    assets: project.assets.map((a) => ({\n      id: a.id,\n      name: a.name,\n      mimeType: a.mimeType,\n      width: a.width,\n      height: a.height,\n      duration: a.duration,\n    })),\n  };\n\n  const jsonBytes = encodeString(JSON.stringify(metadata));\n  const filesToPack: { id: string; file: File; name: string; type: string }[] = [];\n  for (const asset of project.assets) {\n    if (asset.file) {\n      filesToPack.push({\n        id: asset.id,\n        file: asset.file,\n        name: asset.name,\n        type: asset.mimeType || asset.file.type || 'application/octet-stream',\n      });\n    }\n  }\n\n  const parts: BlobPart[] = [];\n  parts.push(toArrayBuffer(encodeString('WZRDPROJ')));\n  const jsonLenBuf = new ArrayBuffer(4);\n  new DataView(jsonLenBuf).setUint32(0, jsonBytes.length, true);\n  parts.push(jsonLenBuf);\n  parts.push(toArrayBuffer(jsonBytes));\n\n  const numFilesBuf = new ArrayBuffer(4);\n  new DataView(numFilesBuf).setUint32(0, filesToPack.length, true);\n  parts.push(numFilesBuf);\n\n  const fileBlobs: Blob[] = [];\n  for (const f of filesToPack) {\n    const idBytes = encodeString(f.id);\n    const nameBytes = encodeString(f.name);\n    const typeBytes = encodeString(f.type);\n    const fileHeaderBuf = new ArrayBuffer(16);\n    const view = new DataView(fileHeaderBuf);\n    view.setUint32(0, idBytes.length, true);\n    view.setUint32(4, nameBytes.length, true);\n    view.setUint32(8, typeBytes.length, true);\n    view.setUint32(12, f.file.size, true);\n    parts.push(fileHeaderBuf, toArrayBuffer(idBytes), toArrayBuffer(nameBytes), toArrayBuffer(typeBytes));\n    fileBlobs.push(f.file);\n  }\n\n  return new Blob([...parts, ...fileBlobs], { type: 'application/octet-stream' });\n}\n\nexport async function importProjectFromWzrds(fileBlob: Blob): Promise<SlidesProjectFileData> {\n  const arrayBuffer = await fileBlob.arrayBuffer();\n  const view = new DataView(arrayBuffer);\n  let offset = 0;\n\n  const magic = decodeString(new Uint8Array(arrayBuffer, offset, 8));\n  offset += 8;\n\n  // Plain JSON fallback\n  if (magic !== 'WZRDPROJ') {\n    const text = await fileBlob.text();\n    const data = JSON.parse(text) as SlidesProjectFileData;\n    return {\n      ...data,\n      assets: data.assets || [],\n      schemaVersion: data.schemaVersion || SLIDES_SCHEMA_VERSION,\n    };\n  }\n\n  const jsonLen = view.getUint32(offset, true);\n  offset += 4;\n  const jsonStr = decodeString(new Uint8Array(arrayBuffer, offset, jsonLen));\n  offset += jsonLen;\n  const metadata = JSON.parse(jsonStr) as Omit<SlidesProjectFileData, 'assets'> & {\n    assets: Array<Omit<SlidesAsset, 'file' | 'url'>>;\n  };\n\n  const numFiles = view.getUint32(offset, true);\n  offset += 4;\n\n  const headers: Array<{ id: string; name: string; type: string; size: number }> = [];\n  for (let i = 0; i < numFiles; i++) {\n    const idLen = view.getUint32(offset, true);\n    const nameLen = view.getUint32(offset + 4, true);\n    const typeLen = view.getUint32(offset + 8, true);\n    const size = view.getUint32(offset + 12, true);\n    offset += 16;\n    const id = decodeString(new Uint8Array(arrayBuffer, offset, idLen));\n    offset += idLen;\n    const name = decodeString(new Uint8Array(arrayBuffer, offset, nameLen));\n    offset += nameLen;\n    const type = decodeString(new Uint8Array(arrayBuffer, offset, typeLen));\n    offset += typeLen;\n    headers.push({ id, name, type, size });\n  }\n\n  const assets: SlidesAsset[] = [];\n  for (const h of headers) {\n    const data = new Uint8Array(arrayBuffer, offset, h.size);\n    offset += h.size;\n    const copy = new Uint8Array(h.size);\n    copy.set(data);\n    const file = new File([copy.buffer], h.name, { type: h.type });\n    const meta = metadata.assets.find((a) => a.id === h.id);\n    assets.push({\n      id: h.id,\n      name: h.name,\n      mimeType: h.type,\n      file,\n      url: URL.createObjectURL(file),\n      width: meta?.width,\n      height: meta?.height,\n      duration: meta?.duration,\n    });\n  }\n\n  // Assets listed in metadata but without packed binary\n  for (const meta of metadata.assets) {\n    if (!assets.find((a) => a.id === meta.id)) {\n      assets.push({ ...meta, url: '' });\n    }\n  }\n\n  return {\n    name: metadata.name,\n    size: metadata.size,\n    theme: metadata.theme,\n    masters: metadata.masters,\n    slides: metadata.slides,\n    sections: metadata.sections,\n    assets,\n    activeSlideId: metadata.activeSlideId,\n    schemaVersion: metadata.schemaVersion || SLIDES_SCHEMA_VERSION,\n    template: metadata.template,\n  };\n}\n\nexport function serializeSlidesProjectForCloud(project: SlidesProjectFileData): string {\n  return JSON.stringify({\n    name: project.name,\n    size: project.size,\n    theme: project.theme,\n    masters: project.masters,\n    slides: project.slides.map((s) => ({\n      ...s,\n      history: [JSON.stringify(s.json)],\n      historyIndex: 0,\n      thumbnail:\n        typeof s.thumbnail === 'string' && s.thumbnail.startsWith('data:')\n          ? s.thumbnail\n          : undefined,\n    })),\n    sections: project.sections,\n    activeSlideId: project.activeSlideId,\n    schemaVersion: project.schemaVersion || SLIDES_SCHEMA_VERSION,\n    template: project.template,\n    assets: project.assets.map((a) => ({\n      id: a.id,\n      name: a.name,\n      mimeType: a.mimeType,\n      width: a.width,\n      height: a.height,\n      duration: a.duration,\n    })),\n  });\n}\n", "/**\n * Local project file extensions (kai + mode letter).\n * Legacy `wzrd*` still accepted on import for backwards compatibility.\n */\nexport const PROJECT_EXT = {\n  image: 'kai',\n  video: 'kaiv',\n  audio: 'kaia',\n  text: 'kait',\n  slides: 'kais',\n} as const;\n\nexport const PROJECT_EXT_LEGACY = {\n  image: 'wzrd',\n  video: 'wzrdv',\n  audio: 'wzrda',\n  text: 'wzrdt',\n  slides: 'wzrds',\n} as const;\n\nexport type ProjectModeExt = keyof typeof PROJECT_EXT;\n\n/** Dot-prefixed extension for downloads, e.g. `.kaiv`. */\nexport function projectExtDot(mode: ProjectModeExt): string {\n  return `.${PROJECT_EXT[mode]}`;\n}\n\n/**\n * `accept` attribute for file inputs \u2014 new + legacy extensions.\n * Extra formats (pptx, md, \u2026) can be appended by the caller.\n */\nexport function projectAccept(mode: ProjectModeExt, extra: string[] = []): string {\n  const parts = [\n    `.${PROJECT_EXT[mode]}`,\n    `.${PROJECT_EXT_LEGACY[mode]}`,\n    ...extra,\n  ];\n  return parts.join(',');\n}\n\n/** Strip known project extensions (kai* / wzrd*) from a filename. */\nexport function stripProjectExtension(fileName: string): string {\n  return fileName.replace(/\\.(kai[vadts]?|wzrd[vadts]?)$/i, '');\n}\n\n/** True if filename looks like a project file for the given mode (new or legacy). */\nexport function isProjectFileName(fileName: string, mode: ProjectModeExt): boolean {\n  const lower = fileName.toLowerCase();\n  return (\n    lower.endsWith(`.${PROJECT_EXT[mode]}`) ||\n    lower.endsWith(`.${PROJECT_EXT_LEGACY[mode]}`)\n  );\n}\n\n/** Sanitize a tab/project name for use as a download basename. */\nexport function safeProjectBasename(name: string, fallback = 'proyecto'): string {\n  const trimmed = name.trim() || fallback;\n  return trimmed.replace(/[^a-zA-Z0-9_\\-\\u00C0-\\u00FF ]/g, '_');\n}\n", "/**\n * Capture a Recientes thumbnail from the live composed video preview canvas\n * (WebGL), not a raw video element frame.\n */\n\nconst PREVIEW_CANVAS_ID = 'we-video-preview-canvas';\nconst MAX_W = 480;\n\nexport function videoPreviewCanvasId(): string {\n  return PREVIEW_CANVAS_ID;\n}\n\nfunction scaleCanvasToDataUrl(source: HTMLCanvasElement): string | undefined {\n  if (!(source.width > 0 && source.height > 0)) return undefined;\n  try {\n    const scale = Math.min(1, MAX_W / source.width);\n    const w = Math.max(1, Math.round(source.width * scale));\n    const h = Math.max(1, Math.round(source.height * scale));\n    if (w === source.width && h === source.height) {\n      return source.toDataURL('image/jpeg', 0.55);\n    }\n    const c = document.createElement('canvas');\n    c.width = w;\n    c.height = h;\n    const ctx = c.getContext('2d');\n    if (!ctx) return undefined;\n    ctx.drawImage(source, 0, 0, w, h);\n    return c.toDataURL('image/jpeg', 0.55);\n  } catch {\n    return undefined;\n  }\n}\n\nfunction captureFromVideoElement(assetId: string): string | undefined {\n  const el = document.getElementById(\n    `preview-media-${assetId}`,\n  ) as HTMLVideoElement | null;\n  if (!el || !(el.videoWidth > 0 && el.videoHeight > 0)) return undefined;\n  try {\n    const c = document.createElement('canvas');\n    const scale = Math.min(1, MAX_W / el.videoWidth);\n    c.width = Math.max(1, Math.round(el.videoWidth * scale));\n    c.height = Math.max(1, Math.round(el.videoHeight * scale));\n    const ctx = c.getContext('2d');\n    if (!ctx) return undefined;\n    ctx.drawImage(el, 0, 0, c.width, c.height);\n    return c.toDataURL('image/jpeg', 0.55);\n  } catch {\n    return undefined;\n  }\n}\n\n/**\n * Prefer the composed WebGL preview; else the first drawable timeline video;\n * else a durable asset poster data URL.\n */\nexport function captureVideoProjectThumbnail(opts?: {\n  assetIds?: string[];\n  assetPosters?: Array<{ type?: string; thumbnail?: string }>;\n}): string {\n  if (typeof document !== 'undefined') {\n    const preview = document.getElementById(\n      PREVIEW_CANVAS_ID,\n    ) as HTMLCanvasElement | null;\n    const fromPreview = preview ? scaleCanvasToDataUrl(preview) : undefined;\n    if (fromPreview) return fromPreview;\n\n    for (const id of opts?.assetIds || []) {\n      const frame = captureFromVideoElement(id);\n      if (frame) return frame;\n    }\n  }\n\n  const poster = opts?.assetPosters?.find(\n    (a) =>\n      a.type === 'video' &&\n      typeof a.thumbnail === 'string' &&\n      a.thumbnail.length > 0 &&\n      !a.thumbnail.startsWith('blob:'),\n  );\n  return poster?.thumbnail || '';\n}\n", "/**\n * Downscale / JPEG-compress images so canvas JSON and cloud uploads\n * stay under Vercel serverless body limits (~4.5MB).\n */\n\nexport type CompressImageOptions = {\n  /** Longest edge in CSS pixels. Default 2048. */\n  maxEdge?: number;\n  /** JPEG quality 0\u20131. Default 0.85. */\n  quality?: number;\n  /** Prefer PNG when source has alpha (keep transparency). Default true. */\n  preserveAlpha?: boolean;\n};\n\nfunction loadImageFromBlob(blob: Blob): Promise<HTMLImageElement> {\n  return new Promise((resolve, reject) => {\n    const url = URL.createObjectURL(blob);\n    const img = new Image();\n    img.onload = () => {\n      URL.revokeObjectURL(url);\n      resolve(img);\n    };\n    img.onerror = () => {\n      URL.revokeObjectURL(url);\n      reject(new Error('Failed to decode image for compression'));\n    };\n    img.src = url;\n  });\n}\n\nfunction loadImageFromDataUrl(dataUrl: string): Promise<HTMLImageElement> {\n  return new Promise((resolve, reject) => {\n    const img = new Image();\n    img.onload = () => resolve(img);\n    img.onerror = () => reject(new Error('Failed to decode data URL'));\n    img.src = dataUrl;\n  });\n}\n\nfunction drawScaled(\n  img: CanvasImageSource,\n  srcW: number,\n  srcH: number,\n  maxEdge: number,\n): HTMLCanvasElement {\n  const scale = Math.min(1, maxEdge / Math.max(srcW, srcH, 1));\n  const w = Math.max(1, Math.round(srcW * scale));\n  const h = Math.max(1, Math.round(srcH * scale));\n  const canvas = document.createElement('canvas');\n  canvas.width = w;\n  canvas.height = h;\n  const ctx = canvas.getContext('2d');\n  if (!ctx) throw new Error('2D context unavailable');\n  ctx.drawImage(img, 0, 0, w, h);\n  return canvas;\n}\n\nfunction canvasHasAlpha(canvas: HTMLCanvasElement): boolean {\n  const ctx = canvas.getContext('2d', { willReadFrequently: true });\n  if (!ctx) return false;\n  const stepX = Math.max(1, Math.floor(canvas.width / 48));\n  const stepY = Math.max(1, Math.floor(canvas.height / 48));\n  for (let y = 0; y < canvas.height; y += stepY) {\n    for (let x = 0; x < canvas.width; x += stepX) {\n      const a = ctx.getImageData(x, y, 1, 1).data[3] ?? 255;\n      if (a < 250) return true;\n    }\n  }\n  return false;\n}\n\nfunction canvasToBlob(\n  canvas: HTMLCanvasElement,\n  type: string,\n  quality: number,\n): Promise<Blob> {\n  return new Promise((resolve, reject) => {\n    canvas.toBlob(\n      (blob) => {\n        if (blob) resolve(blob);\n        else reject(new Error('canvas.toBlob failed'));\n      },\n      type,\n      quality,\n    );\n  });\n}\n\n/** Compress a Blob (PNG/JPEG/WebP) for editor canvas / cloud size. */\nexport async function compressImageBlob(\n  blob: Blob,\n  opts: CompressImageOptions = {},\n): Promise<Blob> {\n  const maxEdge = opts.maxEdge ?? 2048;\n  const quality = opts.quality ?? 0.85;\n  const preserveAlpha = opts.preserveAlpha !== false;\n\n  // Skip tiny payloads \u2014 not worth a decode round-trip.\n  if (blob.size < 200_000) {\n    return blob;\n  }\n\n  const img = await loadImageFromBlob(blob);\n  const canvas = drawScaled(\n    img,\n    img.naturalWidth || img.width,\n    img.naturalHeight || img.height,\n    maxEdge,\n  );\n\n  const usePng = preserveAlpha && canvasHasAlpha(canvas);\n  const out = await canvasToBlob(\n    canvas,\n    usePng ? 'image/png' : 'image/jpeg',\n    quality,\n  );\n  // Keep original if compression made it larger (rare for photo AI output).\n  return out.size < blob.size ? out : blob;\n}\n\n/** Compress a data: URL; returns a (usually shorter) data URL. */\nexport async function compressImageDataUrl(\n  dataUrl: string,\n  opts: CompressImageOptions = {},\n): Promise<string> {\n  if (!dataUrl.startsWith('data:image/')) return dataUrl;\n  // Soft skip for already-small thumbs / icons.\n  if (dataUrl.length < 240_000) return dataUrl;\n\n  const maxEdge = opts.maxEdge ?? 1600;\n  const quality = opts.quality ?? 0.82;\n  const preserveAlpha = opts.preserveAlpha !== false;\n\n  const img = await loadImageFromDataUrl(dataUrl);\n  const canvas = drawScaled(\n    img,\n    img.naturalWidth || img.width,\n    img.naturalHeight || img.height,\n    maxEdge,\n  );\n  const usePng = preserveAlpha && canvasHasAlpha(canvas);\n  const mime = usePng ? 'image/png' : 'image/jpeg';\n  const next = canvas.toDataURL(mime, quality);\n  return next.length < dataUrl.length ? next : dataUrl;\n}\n\n/**\n * Walk a Fabric `toJSON()` tree and compress large embedded `src` data URLs.\n * Mutates a deep clone \u2014 does not touch the live canvas.\n */\nexport async function compactFabricJsonImages(\n  json: unknown,\n  opts: CompressImageOptions = {},\n): Promise<unknown> {\n  if (json == null) return json;\n\n  if (typeof json === 'string') {\n    if (json.startsWith('data:image/') && json.length > 240_000) {\n      return compressImageDataUrl(json, opts);\n    }\n    return json;\n  }\n\n  if (Array.isArray(json)) {\n    const out: unknown[] = [];\n    for (const item of json) {\n      out.push(await compactFabricJsonImages(item, opts));\n    }\n    return out;\n  }\n\n  if (typeof json === 'object') {\n    const src = json as Record<string, unknown>;\n    const out: Record<string, unknown> = {};\n    for (const [key, value] of Object.entries(src)) {\n      // Fabric image objects store the raster in `src`.\n      if (\n        (key === 'src' || key === 'source') &&\n        typeof value === 'string' &&\n        value.startsWith('data:image/')\n      ) {\n        out[key] = await compressImageDataUrl(value, opts);\n      } else {\n        out[key] = await compactFabricJsonImages(value, opts);\n      }\n    }\n    return out;\n  }\n\n  return json;\n}\n", "/**\n * Cloud project serializer \u2014 converts the active editor project into the\n * JSON shape the .NET `/api/kaiman/editables` endpoint expects on upload.\n *\n * The .NET stores the file body verbatim and the `mode` field determines\n * which editor the Recientes flow dispatches to on open. The filename's\n * extension is irrelevant on the server side (it always stores as `.kai`\n * in S3); what matters is:\n *  - The JSON shape matches the corresponding `importXxxProject` action.\n *  - `mode: 0` \u2192 image editor. `mode: 1` \u2192 video editor.\n *  - `name` is the human-readable project name (no extension).\n *\n * The local \"Save\" / \"Load\" flow in the editor uses the same JSON shape\n * (just a different filename) \u2014 that's the contract `importImageProject`\n * and `importVideoProject` already accept. Roundtrip works because:\n *  - Image local save: { version, pages, activePageId, canvasJSON }\n *  - Image import:       accepts `pages` and/or `canvasJSON`\n *  - Video local save:   { aspectRatio, tracks, transitions, assets }\n *  - Video import:       accepts the same shape\n */\n\nimport { useEditorStore } from '../store/useEditorStore';\nimport { useVideoStore } from '../store/useVideoStore';\nimport { useAudioStore } from '../store/useAudioStore';\nimport { useTextStore } from '../store/useTextStore';\nimport { useSlidesStore } from '../store/useSlidesStore';\nimport {\n  uploadEditable,\n  updateEditable,\n  type Editable,\n} from '../services/editableService';\nimport { serializeAudioProjectForCloud } from './audioProjectFile';\nimport { serializeTextProjectForCloud } from './textProjectFile';\nimport { serializeSlidesProjectForCloud, slidesProjectFromStore, exportProjectToWzrds } from './slidesProjectFile';\nimport { projectExtDot } from './projectExtensions';\nimport { captureVideoProjectThumbnail } from './videoPreviewThumbnail';\nimport {\n  pickFirstSlideForThumbnail,\n  renderSlideThumbnail,\n} from './slidesThumbnail';\nimport { materializeSlideJsonAssets } from '../lib/slides/mediaAssets';\n\nexport type CloudProjectMode = 'image' | 'video' | 'audio' | 'text' | 'slides';\n\nexport interface SerializedCloudProject {\n  /** The JSON body as a string \u2014 wrap in a File/Blob for upload. */\n  json: string;\n  /** Human-readable name (no extension). */\n  name: string;\n  /** 0 = image, 1 = video, 2 = audio, 3 = text, 4 = slides. */\n  mode: 0 | 1 | 2 | 3 | 4;\n}\n\nconst DEFAULT_IMAGE_NAME = 'proyecto_imagen';\nconst DEFAULT_VIDEO_NAME = 'proyecto_video';\nconst DEFAULT_AUDIO_NAME = 'proyecto_audio';\nconst DEFAULT_TEXT_NAME = 'proyecto_texto';\nconst DEFAULT_SLIDES_NAME = 'proyecto_diapositivas';\n\n/**\n * Soft ceiling under Vercel serverless request body (~4.5MB).\n * Above this we fail client-side with a typed 413 (no host round-trip).\n */\nconst CLOUD_JSON_SOFT_MAX_CHARS = 3_500_000;\n/** Absolute refuse \u2014 multipart overhead still needs headroom under ~4.5MB. */\nconst CLOUD_JSON_HARD_MAX_CHARS = 4_000_000;\n/** Drop Recientes thumbs larger than this (base64) \u2014 they are optional. */\nconst CLOUD_THUMB_MAX_CHARS = 100_000;\n\nexport function isCloudPayloadTooLargeError(err: unknown): boolean {\n  if (!err || typeof err !== 'object') return false;\n  const status =\n    'status' in err ? Number((err as { status?: number }).status) : undefined;\n  if (status === 413) return true;\n  const msg = err instanceof Error ? err.message : String(err);\n  return /413|too large|FUNCTION_PAYLOAD_TOO_LARGE/i.test(msg);\n}\n\nfunction throwCloudPayloadTooLarge(chars: number): never {\n  const err = new Error(\n    `HTTP 413: Request Entity Too Large (project ${(chars / 1e6).toFixed(1)}MB)`,\n  );\n  (err as Error & { status: number }).status = 413;\n  err.name = 'ApiError';\n  throw err;\n}\n\nfunction compactCloudThumbnail(thumb: unknown): string | undefined {\n  if (typeof thumb !== 'string' || !thumb.startsWith('data:')) return undefined;\n  if (thumb.length > CLOUD_THUMB_MAX_CHARS) return undefined;\n  return thumb;\n}\n\n/**\n * Cloud image payload must stay small: never ship undo history (up to 50 full\n * canvas clones with embedded images) and never duplicate canvasJSON + page.json.\n */\nfunction serializeImagePagesForCloud(\n  pages: Array<{\n    id: string;\n    name: string;\n    width: number;\n    height: number;\n    backgroundColor: string;\n    json?: unknown;\n    thumbnail?: string;\n  }>,\n  activePageId: string | null | undefined,\n  liveCanvasJson: unknown,\n  liveThumb: string\n): Array<Record<string, unknown>> {\n  return pages.map((page) => {\n    const isActive = page.id === activePageId;\n    const thumb = compactCloudThumbnail(\n      isActive ? liveThumb || page.thumbnail : page.thumbnail\n    );\n    return {\n      id: page.id,\n      name: page.name,\n      width: page.width,\n      height: page.height,\n      backgroundColor: page.backgroundColor,\n      json: isActive ? liveCanvasJson : page.json,\n      ...(thumb ? { thumbnail: thumb } : {}),\n    };\n  });\n}\n\n/** Cloud save for audio (.NET EditableMode=Audio, mode=2). */\nexport const FEATURE_CLOUD_AUDIO = true;\n/** Cloud save for text (.NET EditableMode=Text, mode=3). */\nexport const FEATURE_CLOUD_TEXT = true;\n/** Cloud save for slides (.NET EditableMode=Slides, mode=4). */\nexport const FEATURE_CLOUD_SLIDES = true;\n\n/**\n * Read the active project from the appropriate store and serialize it to\n * the cloud-ready JSON. Returns `null` when there's nothing to save\n * (e.g. no active canvas, or the video store has no active project).\n */\nexport function serializeProjectToCloud(\n  mode: CloudProjectMode\n): SerializedCloudProject | null {\n  if (mode === 'image') {\n    const store = useEditorStore.getState();\n    if (!store.canvasInstance) return null;\n    const project = store.imageProjects.find(\n      (p) => p.id === store.activeImageProjectId\n    );\n    const name =\n      project?.name && project.name.trim() ? project.name : DEFAULT_IMAGE_NAME;\n\n    let liveCanvasJson: unknown;\n    try {\n      liveCanvasJson = store.canvasInstance.toJSON();\n    } catch {\n      return null;\n    }\n\n    let thumbnailDataURL = '';\n    try {\n      thumbnailDataURL = store.canvasInstance.toDataURL({\n        format: 'jpeg',\n        quality: 0.4,\n        multiplier: 0.15,\n      });\n    } catch {\n      // Canvas may be tainted or unavailable \u2014 preview falls back in recents UI.\n    }\n\n    const pages = serializeImagePagesForCloud(\n      store.pages,\n      store.activePageId,\n      liveCanvasJson,\n      thumbnailDataURL\n    );\n\n    // pages[] only \u2014 importImageProject accepts pages; canvasJSON was a duplicate\n    // of the active page and roughly doubled multipart size (\u2192 Vercel 413).\n    const data = {\n      version: '1.0.0',\n      pages,\n      activePageId: store.activePageId,\n    };\n    const json = JSON.stringify(data);\n    if (json.length > CLOUD_JSON_SOFT_MAX_CHARS) {\n      console.warn(\n        `[cloud] image project JSON is ${(json.length / 1e6).toFixed(2)}MB \u2014 may hit host 413`\n      );\n    }\n    return { json, name, mode: 0 };\n  }\n\n  if (mode === 'audio') {\n    const store = useAudioStore.getState();\n    if (!store.activeAudioProjectId) return null;\n    const project = store.audioProjects.find(\n      (p) => p.id === store.activeAudioProjectId\n    );\n    const name =\n      project?.name && project.name.trim() ? project.name : DEFAULT_AUDIO_NAME;\n    const json = serializeAudioProjectForCloud({\n      name,\n      sampleRate: store.sampleRate,\n      bpm: store.bpm,\n      timeSignature: store.timeSignature,\n      tracks: store.tracks,\n      markers: store.markers,\n      regions: store.regions,\n      assets: store.assets,\n      projectDuration: store.projectDuration,\n    });\n    return { json, name, mode: 2 };\n  }\n\n  if (mode === 'text') {\n    const store = useTextStore.getState();\n    if (!store.activeTextProjectId) return null;\n    const project = store.textProjects.find(\n      (p) => p.id === store.activeTextProjectId\n    );\n    const name =\n      project?.name && project.name.trim() ? project.name : DEFAULT_TEXT_NAME;\n    const json = serializeTextProjectForCloud({\n      name: store.projectName || name,\n      docType: store.docType,\n      language: store.language,\n      tone: store.tone,\n      targetChannel: store.targetChannel,\n      doc: store.doc,\n      outline: store.outline,\n      variants: store.variants,\n      suggestions: store.suggestions,\n      snapshots: store.snapshots,\n      brandVoice: store.brandVoice,\n      metrics: store.metrics,\n    });\n    return { json, name, mode: 3 };\n  }\n\n  if (mode === 'slides') {\n    const store = useSlidesStore.getState();\n    if (!store.activeSlidesProjectId) return null;\n    const project = store.slidesProjects.find(\n      (p) => p.id === store.activeSlidesProjectId\n    );\n    const name =\n      project?.name && project.name.trim() ? project.name : DEFAULT_SLIDES_NAME;\n    const json = serializeSlidesProjectForCloud(\n      slidesProjectFromStore({\n        id: store.activeSlidesProjectId,\n        name: store.name || name,\n        size: store.size,\n        theme: store.theme,\n        masters: store.masters,\n        slides: store.slides,\n        sections: store.sections,\n        assets: store.assets,\n        activeSlideId: store.activeSlideId,\n        schemaVersion: store.schemaVersion,\n        createdAt: project?.createdAt || Date.now(),\n        updatedAt: Date.now(),\n        template: project?.template,\n      })\n    );\n    return { json, name, mode: 4 };\n  }\n\n  // video\n  const store = useVideoStore.getState();\n  if (!store.activeVideoProjectId) return null;\n  const project = store.videoProjects.find(\n    (p) => p.id === store.activeVideoProjectId\n  );\n  const name =\n    project?.name && project.name.trim() ? project.name : DEFAULT_VIDEO_NAME;\n\n  const thumbnail = captureVideoProjectThumbnail({\n    assetIds: store.assets.filter((a) => a.type === 'video').map((a) => a.id),\n    assetPosters: store.assets,\n  });\n\n  const data = {\n    aspectRatio: store.aspectRatio,\n    tracks: store.tracks,\n    transitions: store.transitions,\n    assets: store.assets,\n    ...(thumbnail ? { thumbnail } : {}),\n  };\n  return { json: JSON.stringify(data), name, mode: 1 };\n}\n\nexport interface UploadCurrentProjectOptions {\n  /**\n   * Optional override for the project name. The user-typed name from the\n   * \"Guardar en la nube\" prompt goes here. Falls back to the active\n   * project's name if omitted.\n   */\n  nameOverride?: string;\n  /**\n   * When set, PATCH `/api/kaiman/editables/{id}` instead of POST create.\n   * Pass the project's `cloudEditableId` so autosave / re-save replace\n   * the S3 file in place and Recientes does not duplicate canvases.\n   */\n  editableId?: number;\n}\n\nasync function putEditableFile(\n  file: File,\n  name: string,\n  mode: 0 | 1 | 2 | 3 | 4,\n  editableId?: number\n): Promise<Editable> {\n  if (editableId != null) {\n    try {\n      return await updateEditable({ id: editableId, file, name });\n    } catch (err) {\n      // Stale / deleted cloud id \u2192 create a new editable instead of looping 404s.\n      const status =\n        err && typeof err === 'object' && 'status' in err\n          ? Number((err as { status?: number }).status)\n          : undefined;\n      const isMissing =\n        status === 404 ||\n        (err instanceof Error &&\n          err.name === 'NotImplementedError' &&\n          /HTTP 404/.test(err.message));\n      if (isMissing) {\n        console.warn(\n          `[cloud] editable ${editableId} missing (404) \u2014 creating a new cloud copy`\n        );\n        return uploadEditable({ file, name, mode });\n      }\n      throw err;\n    }\n  }\n  return uploadEditable({ file, name, mode });\n}\n\n/**\n * Serialize the current project and upload to `/api/kaiman/editables`.\n * Uses PATCH when `editableId` is set; otherwise POST (first cloud save).\n * The `mode` is derived from the editor type (image \u2192 0, video \u2192 1).\n *\n * Throws if there's no active project to save or the network call fails.\n * The store's `addToast` is intentionally NOT called here \u2014 each Toolbar\n * wraps this with its own toasts so error messages stay close to the\n * action that triggered them.\n */\nexport async function uploadCurrentProjectToCloud(\n  mode: CloudProjectMode,\n  opts: UploadCurrentProjectOptions = {}\n): Promise<Editable> {\n  if (mode === 'audio' && !FEATURE_CLOUD_AUDIO) {\n    throw new Error(\n      'Guardado en la nube de audio pendiente: el .NET a\u00FAn no expone EditableMode=Audio (mode=2).'\n    );\n  }\n  if (mode === 'text' && !FEATURE_CLOUD_TEXT) {\n    throw new Error(\n      'Guardado en la nube de texto pendiente: el .NET a\u00FAn no expone EditableMode=Text (mode=3).'\n    );\n  }\n  if (mode === 'slides' && !FEATURE_CLOUD_SLIDES) {\n    throw new Error(\n      'Guardado en la nube de diapositivas pendiente: el .NET a\u00FAn no expone EditableMode=Slides (mode=4).'\n    );\n  }\n\n  const nameOverride = opts.nameOverride?.trim();\n\n  if (mode === 'slides') {\n    const store = useSlidesStore.getState();\n    if (!store.activeSlidesProjectId) {\n      throw new Error('No hay un proyecto activo para guardar.');\n    }\n    const project = store.slidesProjects.find((p) => p.id === store.activeSlidesProjectId);\n    const name =\n      nameOverride ||\n      (project?.name && project.name.trim() ? project.name : DEFAULT_SLIDES_NAME);\n\n    // Ensure first slide has a raster thumbnail for Recientes.\n    let slides = store.slides;\n    const first = pickFirstSlideForThumbnail(slides);\n    if (\n      first &&\n      !(typeof first.thumbnail === 'string' && first.thumbnail.startsWith('data:'))\n    ) {\n      const bakedJson = await materializeSlideJsonAssets(first.json, store.assets);\n      const thumb = await renderSlideThumbnail(\n        bakedJson,\n        store.size,\n        store.theme?.colors?.background || '#FFFFFF',\n      );\n      if (thumb) {\n        slides = slides.map((s) =>\n          s.id === first.id ? { ...s, thumbnail: thumb, json: bakedJson } : s,\n        );\n        useSlidesStore.setState({ slides });\n      }\n    }\n\n    const blob = await exportProjectToWzrds(\n      slidesProjectFromStore({\n        id: store.activeSlidesProjectId,\n        name: store.name || name,\n        size: store.size,\n        theme: store.theme,\n        masters: store.masters,\n        slides,\n        sections: store.sections,\n        assets: store.assets,\n        activeSlideId: store.activeSlideId,\n        schemaVersion: store.schemaVersion,\n        createdAt: project?.createdAt || Date.now(),\n        updatedAt: Date.now(),\n        template: project?.template,\n      })\n    );\n    const file = new File([blob], `${name}${projectExtDot('slides')}`, {\n      type: 'application/octet-stream',\n    });\n    return putEditableFile(file, name, 4, opts.editableId);\n  }\n\n  // Audio: pack binary .wzrda (includes File blobs). JSON-only cloud saves\n  // dropped media and reopened as silent empty clips.\n  if (mode === 'audio') {\n    if (!FEATURE_CLOUD_AUDIO) {\n      throw new Error(\n        'Guardado en la nube de audio pendiente: el .NET a\u00FAn no expone EditableMode=Audio (mode=2).'\n      );\n    }\n    const store = useAudioStore.getState();\n    if (!store.activeAudioProjectId) {\n      throw new Error('No hay un proyecto activo para guardar.');\n    }\n    const project = store.audioProjects.find((p) => p.id === store.activeAudioProjectId);\n    const name =\n      nameOverride ||\n      (project?.name && project.name.trim() ? project.name : DEFAULT_AUDIO_NAME);\n    const { exportProjectToWzrda } = await import('./audioProjectFile');\n    const blob = await exportProjectToWzrda({\n      name,\n      sampleRate: store.sampleRate,\n      bpm: store.bpm,\n      timeSignature: store.timeSignature,\n      tracks: store.tracks,\n      markers: store.markers,\n      regions: store.regions,\n      assets: store.assets,\n      projectDuration: store.projectDuration,\n    });\n    const file = new File([blob], `${name}${projectExtDot('audio')}`, {\n      type: 'application/octet-stream',\n    });\n    return putEditableFile(file, name, 2, opts.editableId);\n  }\n\n  const serialized = serializeProjectToCloud(mode);\n  if (!serialized) {\n    throw new Error('No hay un proyecto activo para guardar.');\n  }\n\n  let jsonBody = serialized.json;\n\n  // Image canvases embed full rasters as data URLs \u2014 recompress before upload\n  // so AI-generated PNGs do not trip Vercel FUNCTION_PAYLOAD_TOO_LARGE.\n  if (mode === 'image') {\n    try {\n      const parsed = JSON.parse(serialized.json) as {\n        version?: string;\n        pages?: Array<Record<string, unknown>>;\n        activePageId?: string | null;\n      };\n      if (Array.isArray(parsed.pages)) {\n        const { compactFabricJsonImages } = await import(\n          './compressImageForEditor'\n        );\n        const pages: Array<Record<string, unknown>> = [];\n        for (const page of parsed.pages) {\n          const compactJson =\n            page.json != null\n              ? await compactFabricJsonImages(page.json, {\n                  maxEdge: 1600,\n                  quality: 0.8,\n                  preserveAlpha: true,\n                })\n              : page.json;\n          pages.push({ ...page, json: compactJson });\n        }\n        jsonBody = JSON.stringify({ ...parsed, pages });\n      }\n    } catch (err) {\n      console.warn('[cloud] image compact failed, uploading raw JSON', err);\n    }\n  }\n\n  if (jsonBody.length > CLOUD_JSON_HARD_MAX_CHARS) {\n    throwCloudPayloadTooLarge(jsonBody.length);\n  } else if (jsonBody.length > CLOUD_JSON_SOFT_MAX_CHARS) {\n    console.warn(\n      `[cloud] ${mode} project still ${(jsonBody.length / 1e6).toFixed(2)}MB after compact`,\n    );\n  }\n\n  const name = nameOverride || serialized.name;\n  const ext =\n    mode === 'video'\n      ? projectExtDot('video')\n      : mode === 'audio'\n        ? projectExtDot('audio')\n        : mode === 'text'\n          ? projectExtDot('text')\n          : projectExtDot('image');\n  const file = new File([jsonBody], `${name}${ext}`, {\n    type: 'application/json',\n  });\n  return putEditableFile(file, name, serialized.mode, opts.editableId);\n}\n", "import { getActiveMessages } from '../i18n';\nimport type { ProjectPersistenceMode } from '../lib/persistence/projectPersistence';\nimport {\n  beginCloudSaveChip,\n  resolveCloudSaveChip,\n} from './cloudSaveStatus';\nimport { isCloudPayloadTooLargeError } from './projectCloudSerializer';\n\nconst announceByMode: Record<ProjectPersistenceMode, boolean> = {\n  image: false,\n  video: false,\n  audio: false,\n  text: false,\n  slides: false,\n};\n\n/** Call from every user-edit \u2192 scheduleAfterChange path. */\nexport function markCloudAutosaveAnnounce(mode: ProjectPersistenceMode): void {\n  announceByMode[mode] = true;\n}\n\nfunction takeAnnounce(mode: ProjectPersistenceMode): boolean {\n  const on = announceByMode[mode];\n  announceByMode[mode] = false;\n  return on;\n}\n\nfunction cloudErrorLabel(err: unknown): string {\n  const t = getActiveMessages();\n  if (isCloudPayloadTooLargeError(err)) return t.toast.cloudPayloadTooLarge;\n  const msg = err instanceof Error ? err.message : String(err);\n  return t.toast.saveFailed(msg);\n}\n\n/**\n * Wraps a cloud autosave. When the user marked an announce, shows\n * saving \u2192 saved/error icon chip. Silent when announce is false (heartbeat).\n */\nexport async function withCloudAutosaveToast(\n  mode: ProjectPersistenceMode,\n  run: () => Promise<boolean>\n): Promise<boolean> {\n  const announce = takeAnnounce(mode);\n  const t = getActiveMessages();\n  const chipId = announce ? beginCloudSaveChip(t.toast.savingToCloud) : null;\n\n  try {\n    const ok = await run();\n    if (chipId) {\n      if (ok) {\n        resolveCloudSaveChip(chipId, 'success', t.toast.savedToCloud);\n      } else {\n        resolveCloudSaveChip(chipId, 'error', t.toast.saveFailed(''));\n      }\n    }\n    return ok;\n  } catch (err) {\n    if (chipId) {\n      resolveCloudSaveChip(chipId, 'error', cloudErrorLabel(err));\n    }\n    throw err;\n  }\n}\n", "/**\n * Formats a time in seconds to a frame-accurate timecode string (HH:MM:SS:FF).\n * @param timeInSeconds The time in seconds.\n * @param frameRate The frame rate (default is 30).\n */\nexport function formatTimecode(timeInSeconds: number, frameRate = 30): string {\n  if (isNaN(timeInSeconds) || timeInSeconds < 0) {\n    return '00:00:00:00';\n  }\n\n  const hours = Math.floor(timeInSeconds / 3600);\n  const minutes = Math.floor((timeInSeconds % 3600) / 60);\n  const seconds = Math.floor(timeInSeconds % 60);\n  const frames = Math.floor((timeInSeconds % 1) * frameRate);\n\n  const pad = (num: number) => String(num).padStart(2, '0');\n\n  return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}:${pad(frames)}`;\n}\n\n/**\n * Converts a timecode string (HH:MM:SS:FF) back to seconds.\n * Supports partial timecodes like MM:SS or SS.\n * @param timecode The timecode string.\n * @param frameRate The frame rate (default is 30).\n */\nexport function timecodeToSeconds(timecode: string, frameRate = 30): number {\n  if (!timecode) return 0;\n  \n  const parts = timecode.split(':').map(Number);\n  if (parts.some(isNaN)) return 0;\n\n  let hours = 0;\n  let minutes = 0;\n  let seconds = 0;\n  let frames = 0;\n\n  if (parts.length === 4) {\n    [hours, minutes, seconds, frames] = parts;\n  } else if (parts.length === 3) {\n    [minutes, seconds, frames] = parts;\n  } else if (parts.length === 2) {\n    [seconds, frames] = parts;\n  } else if (parts.length === 1) {\n    [seconds] = parts;\n  }\n\n  return hours * 3600 + minutes * 60 + seconds + frames / frameRate;\n}\n\n/**\n * Formats seconds into a friendly human-readable format like \"1m 15s\" or \"24s\".\n */\nexport function formatFriendlyDuration(timeInSeconds: number): string {\n  if (isNaN(timeInSeconds) || timeInSeconds < 0) return '0s';\n  if (timeInSeconds < 60) {\n    return `${timeInSeconds.toFixed(1)}s`;\n  }\n  const minutes = Math.floor(timeInSeconds / 60);\n  const seconds = timeInSeconds % 60;\n  return `${minutes}m ${seconds.toFixed(0)}s`;\n}\n\n/**\n * Formats a time in seconds to a compact timecode (MM:SS:CC).\n * CC = centiseconds (2 d\u00EDgitos, 0-99). Si la duraci\u00F3n es \u2265 60 minutos,\n * prepends hours (HH:MM:SS:CC). Para el editor ag\u00E9ntico transport pill\n * y futuros consumidores que quieran un formato de tiempo compacto.\n */\nexport function formatTimecodeShort(timeInSeconds: number): string {\n  if (isNaN(timeInSeconds) || timeInSeconds < 0) {\n    return '00:00:00';\n  }\n  const totalCs = Math.round(timeInSeconds * 100); // centiseconds\n  const totalSec = Math.floor(totalCs / 100);\n  const cs = totalCs % 100;\n  const totalMin = Math.floor(totalSec / 60);\n  const sec = totalSec % 60;\n  const pad2 = (n: number) => String(n).padStart(2, '0');\n  if (totalMin >= 60) {\n    const hours = Math.floor(totalMin / 60);\n    const min = totalMin % 60;\n    return `${pad2(hours)}:${pad2(min)}:${pad2(sec)}:${pad2(cs)}`;\n  }\n  return `${pad2(totalMin)}:${pad2(sec)}:${pad2(cs)}`;\n}\n\n/**\n * Converts seconds to frames.\n */\nexport function secondsToFrames(seconds: number, frameRate = 30): number {\n  return Math.round(seconds * frameRate);\n}\n\n/**\n * Converts frames to seconds.\n */\nexport function framesToSeconds(frames: number, frameRate = 30): number {\n  return frames / frameRate;\n}\n\n/**\n * Tracks shown in the timeline / track controls.\n * Always includes the first video lane; empty default lanes stay hidden until used.\n * User-created layers (`track_*` from addTrack) stay visible even when empty.\n */\nexport function getVisibleTimelineTracks<\n  T extends { id: string; type: string; clips: unknown[] },\n>(tracks: T[]): T[] {\n  const firstVideoId = tracks.find((t) => t.type === 'video')?.id;\n  return tracks.filter((t) => {\n    if (t.clips.length > 0) return true;\n    if (t.id.startsWith('track_')) return true;\n    if (t.type === 'video' && t.id === firstVideoId) return true;\n    return false;\n  });\n}\n\n/** Nice major step (seconds) so ticks stay ~targetPx apart at the current zoom. */\nexport function getTimelineRulerMajorStep(zoomPxPerSec: number, targetPx = 100): number {\n  const ideal = targetPx / Math.max(zoomPxPerSec, 0.001);\n  const steps = [0.1, 0.2, 0.5, 1, 2, 5, 10, 15, 30, 60, 120, 300, 600, 900, 1800, 3600];\n  for (const step of steps) {\n    if (step >= ideal) return step;\n  }\n  return steps[steps.length - 1]!;\n}\n\nexport type TimelineRulerTick = {\n  timeSec: number;\n  x: number;\n  /** Intermediate tick offsets in px from the major (empty when zoomed out). */\n  minors: number[];\n};\n\n/**\n * Viewport-culled ruler ticks. Caps node count so Alt+scroll zoom stays smooth.\n */\nexport function buildTimelineRulerTicks(opts: {\n  zoom: number;\n  scrollLeft: number;\n  viewWidth: number;\n  stageWidth: number;\n  maxMajors?: number;\n}): TimelineRulerTick[] {\n  const { zoom, scrollLeft, viewWidth, stageWidth, maxMajors = 64 } = opts;\n  if (zoom <= 0 || stageWidth <= 0 || viewWidth <= 0) return [];\n\n  const majorStep = getTimelineRulerMajorStep(zoom);\n  const padSec = majorStep * 2;\n  const viewStartSec = Math.max(0, scrollLeft / zoom - padSec);\n  const viewEndSec = Math.min(stageWidth / zoom, (scrollLeft + viewWidth) / zoom + padSec);\n\n  let first = Math.floor(viewStartSec / majorStep) * majorStep;\n  if (first < 0) first = 0;\n\n  const minorsPerMajor = (() => {\n    const division = majorStep >= 5 ? 5 : majorStep >= 1 ? 4 : majorStep >= 0.5 ? 5 : 0;\n    if (division <= 1) return 0;\n    const minorPx = (majorStep / division) * zoom;\n    return minorPx >= 8 ? division - 1 : 0;\n  })();\n\n  const ticks: TimelineRulerTick[] = [];\n  for (let t = first; t <= viewEndSec + 1e-6; t += majorStep) {\n    const x = t * zoom;\n    if (x > stageWidth + 1) break;\n    const minors: number[] = [];\n    if (minorsPerMajor > 0) {\n      const stepPx = (majorStep * zoom) / (minorsPerMajor + 1);\n      for (let j = 1; j <= minorsPerMajor; j++) {\n        const mx = j * stepPx;\n        if (x + mx <= stageWidth) minors.push(mx);\n      }\n    }\n    ticks.push({ timeSec: t, x, minors });\n    if (ticks.length >= maxMajors) break;\n  }\n  return ticks;\n}\n", "import { create } from 'zustand';\nimport {\n  closestAspect,\n  dimensionsForAspect,\n} from '../utils/videoCanvasSize';\nimport { nativeDisplayScale } from '../utils/previewHitTest';\nimport {\n  createProjectPersistence,\n  registerProjectPersistence,\n  type ProjectPersistenceController,\n} from '../lib/persistence/projectPersistence';\nimport {\n  markCloudAutosaveAnnounce,\n  withCloudAutosaveToast,\n} from '../utils/cloudAutosaveToast';\nimport { getVisibleTimelineTracks } from '../utils/timelineUtils';\n\n// \u2500\u2500\u2500 TYPES & INTERFACES \u2500\u2500\u2500\n\nexport type EasingType = 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'hold' | 'bezier';\n\nexport interface Keyframe {\n  id: string;\n  time: number; // seconds from clip start\n  value: number;\n  easing: EasingType;\n  bezierIn?: [number, number]; // control point [x, y]\n  bezierOut?: [number, number]; // control point [x, y]\n}\n\nexport interface KeyframeTrack {\n  property: string; // e.g. 'opacity', 'x', 'y', 'exposure'\n  keyframes: Keyframe[];\n}\n\nexport type TextAnimationPreset =\n  | 'fade' | 'fade-up' | 'fade-down' | 'fade-left' | 'fade-right'\n  | 'slide-up' | 'slide-down' | 'slide-left' | 'slide-right'\n  | 'scale-in' | 'scale-out' | 'bounce-in' | 'bounce-out'\n  | 'typewriter' | 'word-by-word' | 'letter-by-letter'\n  | 'blur-in' | 'blur-out' | 'glitch-in' | 'rotate-in'\n  | 'flip-x' | 'flip-y' | 'elastic-in' | 'swing-in';\n\nexport type BlendMode = \n  | 'normal' | 'multiply' | 'screen' | 'overlay'\n  | 'soft-light' | 'hard-light' | 'color-dodge' | 'color-burn'\n  | 'darken' | 'lighten' | 'difference' | 'exclusion'\n  | 'hue' | 'saturation' | 'color' | 'luminosity'\n  | 'add' | 'subtract';\n\nexport interface CurvePoint {\n  x: number;\n  y: number;\n}\n\nexport interface ColorGradingSettings {\n  exposure: number;      // -5 to +5 stops\n  contrast: number;      // -100 to +100\n  highlights: number;    // -100 to +100\n  shadows: number;       // -100 to +100\n  whites: number;        // -100 to +100\n  blacks: number;        // -100 to +100\n  temperature: number;   // -100 to +100\n  tint: number;          // -100 to +100\n  vibrance: number;      // -100 to +100\n  saturation: number;    // -100 to +100\n  hue: number;           // -180 to +180\n  sharpness: number;     // 0 to 100\n  blur: number;          // 0 to 100\n  noiseReduction: number;\n  hslAdjustments: Record<string, { hue: number; saturation: number; luminance: number }>;\n  curves: {\n    master: CurvePoint[];\n    red: CurvePoint[];\n    green: CurvePoint[];\n    blue: CurvePoint[];\n  };\n  vignetteEnabled: boolean;\n  vignetteAmount: number;\n  vignetteMidpoint: number;\n  vignetteFeather: number;\n}\n\nexport type TransitionType =\n  | 'cut' | 'fade-black' | 'fade-white' | 'cross-dissolve' | 'additive-dissolve' | 'dip-to-color'\n  | 'wipe-left' | 'wipe-right' | 'wipe-up' | 'wipe-down' | 'wipe-diagonal-tl' | 'wipe-diagonal-tr'\n  | 'iris-circle' | 'iris-diamond' | 'clock-wipe' | 'barn-doors-h' | 'barn-doors-v'\n  | 'slide-left' | 'slide-right' | 'slide-up' | 'slide-down' | 'push-left' | 'push-right' | 'push-up' | 'push-down'\n  | 'cover-left' | 'reveal-left' | 'zoom-in' | 'zoom-out' | 'zoom-punch' | 'spin-zoom'\n  | 'blur-dissolve' | 'pixelate' | 'glitch' | 'film-burn' | 'light-leak' | 'luma-fade' | 'morph-cut' | 'custom';\n\nexport interface TransitionClip {\n  id: string;\n  type: TransitionType;\n  fromClipId: string;\n  toClipId: string;\n  duration: number; // seconds\n  params: Record<string, any>;\n  easing: EasingType;\n  reverse: boolean;\n  customKeyframes?: KeyframeTrack[];\n}\n\nexport type EffectType =\n  | 'brightness-contrast' | 'hue-saturation' | 'color-balance' | 'curves' | 'levels' | 'exposure'\n  | 'shadows-highlights' | 'vibrance' | 'color-temperature' | 'selective-color' | 'channel-mixer' | 'gradient-map' | 'lut-3d'\n  | 'blur-gaussian' | 'blur-motion' | 'blur-radial' | 'sharpen' | 'unsharp-mask' | 'glow' | 'bloom' | 'vignette' | 'film-grain'\n  | 'chromatic-aberration' | 'scanlines' | 'pixelate' | 'posterize' | 'threshold' | 'emboss' | 'edge-detect' | 'duotone'\n  | 'halftone' | 'glitch-rgb' | 'noise' | 'old-film' | 'vhs'\n  | 'ken-burns' | 'zoom-dynamic' | 'camera-shake' | 'stabilize' | 'speed-ramp' | 'strobe' | 'echo' | 'time-freeze'\n  | 'transform' | 'corner-pin' | 'lens-distortion' | 'mirror' | 'flip' | 'crop';\n\nexport interface AppliedEffect {\n  id: string;\n  clipId: string;\n  effectType: EffectType;\n  enabled: boolean;\n  order: number;\n  params: Record<string, any>;\n  keyframes: KeyframeTrack[];\n  startTime?: number;\n  endTime?: number;\n}\n\nexport interface Asset {\n  id: string;\n  name: string;\n  url: string;\n  type: 'video' | 'audio' | 'image';\n  duration: number;\n  width?: number;\n  height?: number;\n  file: File;\n  thumbnail?: string;\n  /** Stable remote source (My Files / cloud). Prefer this over name when deduping. */\n  remoteUrl?: string;\n}\n\nexport interface Clip {\n  id: string;\n  trackId: string;\n  assetId: string;\n  startTime: number;\n  duration: number;\n  trimIn: number;\n  trimOut: number;\n  speed: number;\n  volume: number;\n  opacity: number;\n  muted: boolean;\n  type: 'video' | 'audio' | 'subtitle' | 'text' | 'image';\n  name?: string;\n\n  // Subtitle/Text Specifics\n  text?: string;\n  fontFamily?: string;\n  fontWeight?: number;\n  fontSize?: number;\n  fontStyle?: 'normal' | 'italic';\n  underlineEnabled?: boolean;\n  letterSpacing?: number;\n  lineHeight?: number;\n  textAlign?: 'left' | 'center' | 'right';\n  textTransform?: 'none' | 'uppercase' | 'lowercase' | 'capitalize';\n  fillType?: 'solid' | 'gradient' | 'none';\n  fillColor?: string;\n  gradientColors?: string[];\n  gradientAngle?: number;\n  strokeEnabled?: boolean;\n  strokeColor?: string;\n  strokeWidth?: number;\n  strokePosition?: 'inside' | 'outside' | 'center';\n  shadowEnabled?: boolean;\n  shadowColor?: string;\n  shadowBlur?: number;\n  shadowOffsetX?: number;\n  shadowOffsetY?: number;\n  shadowOpacity?: number;\n  backgroundEnabled?: boolean;\n  backgroundColor?: string;\n  backgroundOpacity?: number;\n  backgroundPadding?: number;\n  backgroundBorderRadius?: number;\n  backgroundBorderColor?: string;\n  backgroundBorderWidth?: number;\n  x?: number; // 0-1\n  y?: number; // 0-1\n  rotation?: number;\n  scaleX?: number;\n  scaleY?: number;\n  animationIn?: TextAnimationPreset | null;\n  animationOut?: TextAnimationPreset | null;\n  animationInDuration?: number;\n  animationOutDuration?: number;\n\n  // Image Specifics\n  cropEnabled?: boolean;\n  cropX?: number;\n  cropY?: number;\n  cropWidth?: number;\n  cropHeight?: number;\n  maskShape?: 'none' | 'rectangle' | 'circle' | 'ellipse' | 'custom';\n  maskFeather?: number;\n  flipX?: boolean;\n  flipY?: boolean;\n  blendMode?: BlendMode;\n  borderRadius?: number;\n  \n  // Grading & Fit\n  colorGrading?: ColorGradingSettings;\n  fitMode?: 'fill' | 'fit' | 'stretch' | 'crop';\n\n  // Keyframes & Effects\n  keyframes?: KeyframeTrack[];\n  effects?: AppliedEffect[];\n}\n\nexport interface Track {\n  id: string;\n  name: string;\n  type: 'video' | 'audio' | 'subtitle' | 'text' | 'image';\n  muted: boolean;\n  locked: boolean;\n  clips: Clip[];\n}\n\nexport interface EditorSnapshot {\n  tracks: Track[];\n  transitions: TransitionClip[];\n  description: string;\n}\n\n/** UI-only AI busy state for timeline / preview loaders. */\nexport type AiSubtitleJob =\n  | {\n      kind: 'generate';\n      sourceClipId: string;\n      startTime: number;\n      duration: number;\n    }\n  | {\n      kind: 'translate';\n      clipIds: string[];\n    }\n  | {\n      kind: 'style';\n      clipIds: string[];\n    }\n  | {\n      kind: 'voiceover';\n      startTime: number;\n      duration: number;\n      trackId: string;\n    }\n  | {\n      kind: 'copy';\n      startTime: number;\n      duration: number;\n      trackId: string;\n    }\n  | {\n      kind: 'clipEdit';\n      clipIds: string[];\n      /** Localized label already resolved by the caller. */\n      label: string;\n    }\n  | null;\n\n// \u2500\u2500\u2500 STATE INTERFACE \u2500\u2500\u2500\n\n/** Snapshot of a complete video project state for tab switching */\nexport interface VideoProject {\n  id: string;\n  name: string;\n  aspectRatio: '16:9' | '9:16' | '1:1' | '4:3' | '3:4' | '21:9';\n  canvasWidth: number;\n  canvasHeight: number;\n  backgroundColor: string;\n  tracks: Track[];\n  assets: Asset[];\n  transitions: TransitionClip[];\n  projectDuration: number;\n  playheadTime: number;\n  zoom: number;\n  history: EditorSnapshot[];\n  historyIndex: number;\n  createdAt: number;\n  /** Composed preview frame for Recientes (data URL). */\n  thumbnail?: string;\n  /** Last `/api/kaiman/editables` id \u2014 replaced on silent cloud autosave. */\n  cloudEditableId?: number;\n}\n\ninterface VideoState {\n  // \u2500\u2500 Multi-project state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  videoProjects: VideoProject[];\n  activeVideoProjectId: string | null;\n  isVideoSetupOpen: boolean;\n  /** True while loadVideoProject() reads IndexedDB \u2014 blocks UI until done. */\n  isVideoProjectLoading: boolean;\n  setIsVideoSetupOpen: (open: boolean) => void;\n  createVideoProject: (name: string, aspectRatio: VideoProject['aspectRatio'], backgroundColor: string) => void;\n  closeVideoProject: (projectId: string) => void;\n  switchVideoProject: (projectId: string) => void;\n  renameVideoProject: (projectId: string, name: string) => void;\n  saveVideoProject: () => Promise<void>;\n  loadVideoProject: () => Promise<void>;\n  /** Silent debounced upload to `/api/kaiman/editables` (no toast). */\n  autoSaveVideoProjectToCloud: () => Promise<boolean>;\n\n  // \u2500\u2500 Active project canvas state (proxied) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  tracks: Track[];\n  assets: Asset[];\n  transitions: TransitionClip[];\n  playheadTime: number;\n  isPlaying: boolean;\n  zoom: number;              // pixels per second\n  selectedClipIds: string[];\n  history: EditorSnapshot[];\n  historyIndex: number;\n  projectDuration: number;\n  openaiApiKey: string;\n  geminiApiKey: string;\n  unsplashApiKey: string;\n  pexelsApiKey: string;\n  scrollTop: number;\n  aspectRatio: '16:9' | '9:16' | '1:1' | '4:3' | '3:4' | '21:9';\n  canvasWidth: number;\n  canvasHeight: number;\n  /** Magnetic snap for timeline clip moves and preview element moves. */\n  snapEnabled: boolean;\n  /**\n   * In-flight AI subtitle job (generate / translate). Timeline shows loaders\n   * on the subtitle lane / clips; not persisted.\n   */\n  aiSubtitleJob: AiSubtitleJob;\n  setAiSubtitleJob: (job: AiSubtitleJob) => void;\n  /** Which AI tools-panel card is busy (shows generating overlay on the card). */\n  aiBusyToolId: string | null;\n  setAiBusyToolId: (toolId: string | null) => void;\n\n  // Actions\n  setAspectRatio: (aspectRatio: VideoProject['aspectRatio']) => void;\n  setCanvasSize: (width: number, height: number) => void;\n  setSnapEnabled: (enabled: boolean) => void;\n  setOpenaiApiKey: (key: string) => void;\n  setGeminiApiKey: (key: string) => void;\n  setUnsplashApiKey: (key: string) => void;\n  setPexelsApiKey: (key: string) => void;\n  setScrollTop: (top: number) => void;\n  addAsset: (asset: Asset) => void;\n  removeAsset: (assetId: string) => void;\n  addClip: (trackId: string, clip: Omit<Clip, 'id'>) => void;\n  removeClip: (clipId: string) => void;\n  moveClip: (clipId: string, startTime: number, trackId: string) => void;\n  /** Shift several clips by the same time delta (keep tracks). Used for multi-drag. */\n  moveClipsByDelta: (clipIds: string[], deltaSec: number) => void;\n  trimClip: (clipId: string, trimIn: number, trimOut: number, startTime?: number) => void;\n  splitClip: (clipId: string, atTime: number) => void;\n  updateClipProperties: (clipId: string, properties: Partial<Omit<Clip, 'id' | 'type' | 'trackId' | 'assetId'>>) => void;\n  setPlayhead: (time: number) => void;\n  setIsPlaying: (playing: boolean) => void;\n  setZoom: (zoom: number) => void;\n  selectClip: (clipId: string, multi: boolean) => void;\n  /** Replace or union the selection set (marquee). */\n  selectClips: (clipIds: string[], additive?: boolean) => void;\n  clearSelection: () => void;\n  toggleTrackMute: (trackId: string) => void;\n  toggleTrackLock: (trackId: string) => void;\n  undo: () => void;\n  redo: () => void;\n  setProjectDuration: (duration: number) => void;\n\n  // Track Actions\n  addTrack: (name: string, type: 'video' | 'audio' | 'text' | 'image' | 'subtitle') => void;\n  removeTrack: (trackId: string) => void;\n  /** Move clip to adjacent same-type layer (creates a new layer at the edge if needed). */\n  moveClipLayer: (clipId: string, direction: 'up' | 'down') => void;\n  /** Reorder a track among all tracks (any type). */\n  reorderTrack: (trackId: string, direction: 'up' | 'down') => void;\n\n  // Text Module Actions\n  addTextClip: (clip: Omit<Clip, 'id' | 'type'>) => void;\n  updateTextClip: (id: string, updates: Partial<Clip>) => void;\n\n  // Image Module Actions\n  addImageClip: (clip: Omit<Clip, 'id' | 'type'>) => void;\n  updateImageClip: (id: string, updates: Partial<Clip>) => void;\n  updateColorGrading: (id: string, grading: Partial<ColorGradingSettings>) => void;\n\n  // Transition Actions\n  addTransition: (transition: Omit<TransitionClip, 'id'>) => void;\n  /** `history: false` = live scrub without flooding undo stack; commit with `history: true` (default). */\n  updateTransition: (\n    id: string,\n    updates: Partial<TransitionClip>,\n    opts?: { history?: boolean },\n  ) => void;\n  removeTransition: (id: string) => void;\n\n  // Effects Actions\n  addEffect: (clipId: string, effectType: EffectType, customParams?: Record<string, any>) => void;\n  updateEffect: (clipId: string, effectId: string, params: Record<string, any>) => void;\n  removeEffect: (clipId: string, effectId: string) => void;\n  reorderEffects: (clipId: string, fromIndex: number, toIndex: number) => void;\n  toggleEffect: (clipId: string, effectId: string) => void;\n\n  // Keyframe Actions\n  addKeyframe: (clipId: string, property: string, keyframe: Omit<Keyframe, 'id'>) => void;\n  updateKeyframe: (clipId: string, property: string, keyframeId: string, updates: Partial<Keyframe>) => void;\n  removeKeyframe: (clipId: string, property: string, keyframeId: string) => void;\n  loadProjectState: (projectData: { aspectRatio: VideoProject['aspectRatio']; tracks: Track[]; transitions: TransitionClip[]; assets: Asset[] }) => void;\n  importVideoProject: (\n    projectData: { aspectRatio: VideoProject['aspectRatio']; tracks: Track[]; transitions: TransitionClip[]; assets: Asset[] },\n    fileName: string,\n    opts?: { cloudEditableId?: number },\n  ) => void;\n}\n\n// \u2500\u2500\u2500 INITIAL SYSTEM STATES \u2500\u2500\u2500\n\nexport const DEFAULT_COLOR_GRADING: ColorGradingSettings = {\n  exposure: 0,\n  contrast: 0,\n  highlights: 0,\n  shadows: 0,\n  whites: 0,\n  blacks: 0,\n  temperature: 0,\n  tint: 0,\n  vibrance: 0,\n  saturation: 0,\n  hue: 0,\n  sharpness: 0,\n  blur: 0,\n  noiseReduction: 0,\n  hslAdjustments: {\n    red: { hue: 0, saturation: 0, luminance: 0 },\n    orange: { hue: 0, saturation: 0, luminance: 0 },\n    yellow: { hue: 0, saturation: 0, luminance: 0 },\n    green: { hue: 0, saturation: 0, luminance: 0 },\n    aqua: { hue: 0, saturation: 0, luminance: 0 },\n    blue: { hue: 0, saturation: 0, luminance: 0 },\n    purple: { hue: 0, saturation: 0, luminance: 0 },\n    magenta: { hue: 0, saturation: 0, luminance: 0 },\n  },\n  curves: {\n    master: [{ x: 0, y: 0 }, { x: 1, y: 1 }],\n    red: [{ x: 0, y: 0 }, { x: 1, y: 1 }],\n    green: [{ x: 0, y: 0 }, { x: 1, y: 1 }],\n    blue: [{ x: 0, y: 0 }, { x: 1, y: 1 }],\n  },\n  vignetteEnabled: false,\n  vignetteAmount: 0,\n  vignetteMidpoint: 50,\n  vignetteFeather: 50,\n};\n\nconst INITIAL_TRACKS: Track[] = [\n  { id: 't2', name: 'Text 2', type: 'text', muted: false, locked: false, clips: [] },\n  { id: 't1', name: 'Text 1', type: 'text', muted: false, locked: false, clips: [] },\n  { id: 'sub', name: 'Subtitles', type: 'subtitle', muted: false, locked: false, clips: [] },\n  { id: 'i1', name: 'Image 1', type: 'image', muted: false, locked: false, clips: [] },\n  { id: 'v1', name: 'Video 1', type: 'video', muted: false, locked: false, clips: [] },\n  { id: 'v2', name: 'Video 2', type: 'video', muted: false, locked: false, clips: [] },\n  { id: 'a1', name: 'Audio 1', type: 'audio', muted: false, locked: false, clips: [] },\n  { id: 'a2', name: 'Audio 2', type: 'audio', muted: false, locked: false, clips: [] },\n];\n\n/**\n * Default stack for new projects only. User may freely reorder tracks of any\n * type afterward \u2014 array order is the source of truth (timeline top \u2192 bottom /\n * preview front \u2192 back for tracks[0]).\n */\nexport const VIDEO_TRACK_TYPE_ORDER = ['text', 'subtitle', 'image', 'video', 'audio'] as const;\n\n/** Stable default ordering for brand-new timelines. Do not re-apply on load. */\nexport function sortTracksByTypeOrder(tracks: Track[]): Track[] {\n  return [...tracks].sort((a, b) => {\n    const ai = VIDEO_TRACK_TYPE_ORDER.indexOf(a.type as (typeof VIDEO_TRACK_TYPE_ORDER)[number]);\n    const bi = VIDEO_TRACK_TYPE_ORDER.indexOf(b.type as (typeof VIDEO_TRACK_TYPE_ORDER)[number]);\n    const ao = ai === -1 ? 99 : ai;\n    const bo = bi === -1 ? 99 : bi;\n    if (ao !== bo) return ao - bo;\n    return 0;\n  });\n}\n\n// Debounced IndexedDB + background cloud (shared persistence controller).\nlet videoPersistence!: ProjectPersistenceController;\n\n// Helper to push state onto history stack\nfunction pushToHistory(\n  state: { tracks: Track[]; transitions: TransitionClip[]; history: EditorSnapshot[]; historyIndex: number },\n  description: string\n): EditorSnapshot[] {\n  const newSnapshot: EditorSnapshot = {\n    tracks: JSON.parse(JSON.stringify(state.tracks)),\n    transitions: JSON.parse(JSON.stringify(state.transitions)),\n    description\n  };\n  const newHistory = state.history.slice(0, state.historyIndex + 1);\n  newHistory.push(newSnapshot);\n  if (newHistory.length > 50) {\n    newHistory.shift();\n  }\n\n  markCloudAutosaveAnnounce('video');\n  videoPersistence.scheduleAfterChange();\n\n  return newHistory;\n}\n\n// Helper to validate a single transition's duration according to clip boundaries\nconst getValidatedTransitionDuration = (\n  tracks: Track[],\n  fromClipId: string,\n  toClipId: string,\n  duration: number\n): number => {\n  let fromClip: Clip | undefined;\n  let toClip: Clip | undefined;\n\n  for (const track of tracks) {\n    if (!fromClip) fromClip = track.clips.find((c) => c.id === fromClipId);\n    if (!toClip) toClip = track.clips.find((c) => c.id === toClipId);\n    if (fromClip && toClip) break;\n  }\n\n  let maxDuration = duration;\n  if (fromClipId === 'none' && toClip) {\n    maxDuration = toClip.duration;\n  } else if (toClipId === 'none' && fromClip) {\n    maxDuration = fromClip.duration;\n  } else if (fromClip && toClip) {\n    maxDuration = 2 * Math.min(fromClip.duration, toClip.duration);\n  }\n\n  return Math.max(0.1, Math.min(duration, maxDuration));\n};\n\n// Helper to validate and auto-adjust all transitions in the timeline\nconst validateAndAdjustAllTransitions = (\n  tracks: Track[],\n  transitions: TransitionClip[]\n): TransitionClip[] => {\n  const adjusted = transitions\n    .map((trans) => {\n      let fromClip: Clip | undefined;\n      let toClip: Clip | undefined;\n\n      for (const track of tracks) {\n        if (!fromClip) fromClip = track.clips.find((c) => c.id === trans.fromClipId);\n        if (!toClip) toClip = track.clips.find((c) => c.id === trans.toClipId);\n        if (fromClip && toClip) break;\n      }\n\n      const isStart = trans.fromClipId === 'none';\n      const isEnd = trans.toClipId === 'none';\n\n      if (isStart && toClip) {\n        const maxDur = toClip.duration;\n        const validDur = Math.max(0.1, Math.min(trans.duration, maxDur));\n        return { ...trans, duration: validDur };\n      } else if (isEnd && fromClip) {\n        const maxDur = fromClip.duration;\n        const validDur = Math.max(0.1, Math.min(trans.duration, maxDur));\n        return { ...trans, duration: validDur };\n      } else if (fromClip && toClip) {\n        const gap = toClip.startTime - (fromClip.startTime + fromClip.duration);\n        if (gap > 0.5) {\n          // Clips are no longer adjacent (gap > 0.5s), drop transition\n          return null;\n        }\n        const maxDur = 2 * Math.min(fromClip.duration, toClip.duration);\n        const validDur = Math.max(0.1, Math.min(trans.duration, maxDur));\n        return { ...trans, duration: validDur };\n      }\n\n      if (!isStart && !fromClip) return null;\n      if (!isEnd && !toClip) return null;\n\n      return trans;\n    })\n    .filter((t): t is TransitionClip => t !== null);\n\n  return reconcileAdjacentEdgeTransitions(tracks, adjusted);\n};\n\n/**\n * When clips become adjacent: the clip without a transition inherits the other's\n * edge transition as a between. Matching edge types merge; conflicting types stay\n * (UI conflict modal). Orphan edge fades at a junction with a between are removed.\n */\nconst reconcileAdjacentEdgeTransitions = (\n  tracks: Track[],\n  transitions: TransitionClip[],\n): TransitionClip[] => {\n  let result = [...transitions];\n\n  for (const track of tracks) {\n    const sorted = [...track.clips].sort((a, b) => a.startTime - b.startTime);\n    for (let i = 0; i < sorted.length - 1; i++) {\n      const left = sorted[i];\n      const right = sorted[i + 1];\n      if (!left || !right) continue;\n      const gap = right.startTime - (left.startTime + left.duration);\n      if (gap > 0.5) continue;\n\n      const between = result.find(\n        (t) => t.fromClipId === left.id && t.toClipId === right.id,\n      );\n      const leftEnd = result.find(\n        (t) => t.fromClipId === left.id && t.toClipId === 'none',\n      );\n      const rightStart = result.find(\n        (t) => t.fromClipId === 'none' && t.toClipId === right.id,\n      );\n\n      if (between) {\n        result = result.filter((t) => t !== leftEnd && t !== rightStart);\n        continue;\n      }\n\n      if (leftEnd && !rightStart) {\n        const duration = getValidatedTransitionDuration(\n          tracks,\n          left.id,\n          right.id,\n          leftEnd.duration,\n        );\n        result = result.map((t) =>\n          t.id === leftEnd.id\n            ? { ...t, toClipId: right.id, duration }\n            : t,\n        );\n        continue;\n      }\n\n      if (rightStart && !leftEnd) {\n        const duration = getValidatedTransitionDuration(\n          tracks,\n          left.id,\n          right.id,\n          rightStart.duration,\n        );\n        result = result.map((t) =>\n          t.id === rightStart.id\n            ? { ...t, fromClipId: left.id, duration }\n            : t,\n        );\n        continue;\n      }\n\n      if (leftEnd && rightStart && leftEnd.type === rightStart.type) {\n        const duration = getValidatedTransitionDuration(\n          tracks,\n          left.id,\n          right.id,\n          leftEnd.duration,\n        );\n        result = result\n          .filter((t) => t.id !== rightStart.id)\n          .map((t) =>\n            t.id === leftEnd.id\n              ? { ...t, toClipId: right.id, duration }\n              : t,\n          );\n      }\n    }\n  }\n\n  return result;\n};\n\n// \u2500\u2500\u2500 STORE CONFIGURATION \u2500\u2500\u2500\n\nexport const useVideoStore = create<VideoState>((set, get) => ({\n  // \u2500\u2500 Multi-project initial state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  videoProjects: [],\n  activeVideoProjectId: null,\n  // false by default \u2014 loadVideoProject() sets it to true only for first-time users.\n  isVideoSetupOpen: false,\n  // true while loadVideoProject() reads IndexedDB \u2014 App waits for this.\n  isVideoProjectLoading: true,\n\n  setIsVideoSetupOpen: (open) => set({ isVideoSetupOpen: open }),\n\n  createVideoProject: (name, aspectRatio, backgroundColor) => {\n    const projectId = `vproj-${Date.now()}`;\n    const freshTracks: Track[] = [\n      { id: `t2-${projectId}`, name: 'Text 2',    type: 'text',     muted: false, locked: false, clips: [] },\n      { id: `t1-${projectId}`, name: 'Text 1',    type: 'text',     muted: false, locked: false, clips: [] },\n      { id: `sub-${projectId}`, name: 'Subtitles', type: 'subtitle', muted: false, locked: false, clips: [] },\n      { id: `i1-${projectId}`, name: 'Image 1',   type: 'image',    muted: false, locked: false, clips: [] },\n      { id: `v1-${projectId}`, name: 'Video 1',   type: 'video',    muted: false, locked: false, clips: [] },\n      { id: `v2-${projectId}`, name: 'Video 2',   type: 'video',    muted: false, locked: false, clips: [] },\n      { id: `a1-${projectId}`, name: 'Audio 1',   type: 'audio',    muted: false, locked: false, clips: [] },\n      { id: `a2-${projectId}`, name: 'Audio 2',   type: 'audio',    muted: false, locked: false, clips: [] },\n    ];\n    const dims = dimensionsForAspect(aspectRatio);\n    const newProject: VideoProject = {\n      id: projectId,\n      name,\n      aspectRatio,\n      canvasWidth: dims.width,\n      canvasHeight: dims.height,\n      backgroundColor,\n      tracks: freshTracks,\n      assets: [],\n      transitions: [],\n      projectDuration: 300,\n      playheadTime: 0,\n      zoom: 15,\n      history: [{ tracks: freshTracks, transitions: [], description: 'Initial State' }],\n      historyIndex: 0,\n      createdAt: Date.now(),\n    };\n    set((state) => ({\n      videoProjects: [...state.videoProjects, newProject],\n      activeVideoProjectId: projectId,\n      // Sync active state\n      tracks: freshTracks,\n      assets: [],\n      transitions: [],\n      aspectRatio,\n      canvasWidth: dims.width,\n      canvasHeight: dims.height,\n      projectDuration: 300,\n      playheadTime: 0,\n      zoom: 15,\n      selectedClipIds: [],\n      history: newProject.history,\n      historyIndex: 0,\n      isVideoSetupOpen: false,\n    }));\n  },\n\n  closeVideoProject: (projectId) => {\n    const { videoProjects, activeVideoProjectId } = get();\n    const remaining = videoProjects.filter(p => p.id !== projectId);\n    if (remaining.length === 0) {\n      set({\n        videoProjects: [], activeVideoProjectId: null, isVideoSetupOpen: true,\n        tracks: INITIAL_TRACKS, assets: [], transitions: [],\n      });\n      return;\n    }\n    const newActive = activeVideoProjectId === projectId\n      ? remaining[remaining.length - 1]\n      : videoProjects.find(p => p.id === activeVideoProjectId) || remaining[0];\n    set({\n      videoProjects: remaining,\n      activeVideoProjectId: newActive.id,\n      tracks: newActive.tracks,\n      assets: newActive.assets,\n      transitions: newActive.transitions,\n      aspectRatio: newActive.aspectRatio,\n      canvasWidth: newActive.canvasWidth ?? dimensionsForAspect(newActive.aspectRatio).width,\n      canvasHeight: newActive.canvasHeight ?? dimensionsForAspect(newActive.aspectRatio).height,\n      projectDuration: newActive.projectDuration,\n      playheadTime: newActive.playheadTime,\n      zoom: newActive.zoom,\n      history: newActive.history,\n      historyIndex: newActive.historyIndex,\n    });\n  },\n\n  switchVideoProject: (projectId) => {\n    const {\n      videoProjects,\n      activeVideoProjectId,\n      tracks,\n      assets,\n      transitions,\n      aspectRatio,\n      canvasWidth,\n      canvasHeight,\n      projectDuration,\n      playheadTime,\n      zoom,\n      history,\n      historyIndex,\n    } = get();\n    if (projectId === activeVideoProjectId) return;\n    // Save current project state before switching\n    const updatedProjects = videoProjects.map((p) => {\n      if (p.id === activeVideoProjectId) {\n        return {\n          ...p,\n          tracks,\n          assets,\n          transitions,\n          aspectRatio,\n          canvasWidth,\n          canvasHeight,\n          projectDuration,\n          playheadTime,\n          zoom,\n          history,\n          historyIndex,\n        };\n      }\n      return p;\n    });\n    const target = updatedProjects.find((p) => p.id === projectId);\n    if (!target) return;\n    const dims = dimensionsForAspect(target.aspectRatio);\n    set({\n      videoProjects: updatedProjects,\n      activeVideoProjectId: projectId,\n      tracks: target.tracks ?? INITIAL_TRACKS,\n      assets: target.assets,\n      transitions: target.transitions,\n      aspectRatio: target.aspectRatio,\n      canvasWidth: target.canvasWidth ?? dims.width,\n      canvasHeight: target.canvasHeight ?? dims.height,\n      projectDuration: target.projectDuration,\n      playheadTime: target.playheadTime,\n      zoom: target.zoom,\n      history: target.history,\n      historyIndex: target.historyIndex,\n      selectedClipIds: [],\n    });\n  },\n\n  renameVideoProject: (projectId, name) => {\n    const trimmed = name.trim();\n    if (!trimmed) return;\n    set((state) => ({\n      videoProjects: state.videoProjects.map((p) =>\n        p.id === projectId ? { ...p, name: trimmed } : p,\n      ),\n    }));\n  },\n\n  // \\u2500\\u2500 Persistence \\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\n  saveVideoProject: async () => {\n    const state = get();\n    if (state.isVideoProjectLoading || state.videoProjects.length === 0) return; // never overwrite while loading\n\n    // Snapshot the current active project's live state.\n    // IMPORTANT: strip 'file' (File object \u2014 not JSON serializable) and\n    // 'url' (blob: URL \u2014 ephemeral, dies on reload) from assets before\n    // persisting.  The actual bytes are stored separately in 'video-assets'.\n    const serializableAssets = state.assets.map(({ file: _f, url: _u, thumbnail, ...rest }) => ({\n      ...rest,\n      url: '', // placeholder; recreated from video-assets on load\n      // blob: URLs die on reload \u2014 only persist durable thumbnails (data URLs)\n      thumbnail:\n        typeof thumbnail === 'string' && !thumbnail.startsWith('blob:')\n          ? thumbnail\n          : undefined,\n    }));\n\n    let projectThumb: string | undefined;\n    try {\n      const { captureVideoProjectThumbnail } = await import('../utils/videoPreviewThumbnail');\n      const captured = captureVideoProjectThumbnail({\n        assetIds: state.assets.filter((a) => a.type === 'video').map((a) => a.id),\n        assetPosters: serializableAssets,\n      });\n      if (captured) projectThumb = captured;\n    } catch {\n      projectThumb = undefined;\n    }\n\n    const syncedProjects = state.videoProjects.map((p) => {\n      if (p.id === state.activeVideoProjectId) {\n        return {\n          ...p,\n          tracks: state.tracks,\n          assets: serializableAssets,\n          transitions: state.transitions,\n          aspectRatio: state.aspectRatio,\n          canvasWidth: state.canvasWidth,\n          canvasHeight: state.canvasHeight,\n          projectDuration: state.projectDuration,\n          playheadTime: state.playheadTime,\n          zoom: state.zoom,\n          history: state.history,\n          historyIndex: state.historyIndex,\n          thumbnail: projectThumb || p.thumbnail,\n        };\n      }\n      // Also strip file/url from non-active projects\n      return {\n        ...p,\n        assets: p.assets.map(({ file: _f, url: _u, thumbnail, ...rest }: any) => ({\n          ...rest,\n          url: '',\n          thumbnail:\n            typeof thumbnail === 'string' && !thumbnail.startsWith('blob:')\n              ? thumbnail\n              : undefined,\n        })),\n      };\n    });\n\n    try {\n      const { openUploadsDB } = await import('./useEditorStore');\n      const db = await openUploadsDB();\n      await new Promise<void>((resolve, reject) => {\n        const tx = db.transaction('projects', 'readwrite');\n        const store = tx.objectStore('projects');\n        const req = store.put({\n          id: 'video-projects',\n          videoProjects: syncedProjects,\n          activeVideoProjectId: state.activeVideoProjectId,\n          savedAt: Date.now(),\n        });\n        req.onsuccess = () => resolve();\n        req.onerror = () => reject(req.error);\n      });\n\n      if (projectThumb && state.activeVideoProjectId) {\n        set({\n          videoProjects: syncedProjects,\n        });\n      }\n    } catch (err) {\n      console.error('Failed to save video projects to IndexedDB:', err);\n    }\n  },\n\n  autoSaveVideoProjectToCloud: async () =>\n    withCloudAutosaveToast('video', async () => {\n    const { hasEditorIdentity } = await import('../services/identity');\n    if (!hasEditorIdentity()) return false;\n\n    const state = get();\n    if (\n      state.isVideoProjectLoading ||\n      !state.activeVideoProjectId ||\n      state.videoProjects.length === 0\n    ) {\n      return false;\n    }\n\n    const projectId = state.activeVideoProjectId;\n    const cloudEditableId = state.videoProjects.find((p) => p.id === projectId)?.cloudEditableId;\n\n    try {\n      const { uploadCurrentProjectToCloud } = await import('../utils/projectCloudSerializer');\n      const editable = await uploadCurrentProjectToCloud('video', {\n        editableId: cloudEditableId,\n      });\n\n      const stillActive = get().activeVideoProjectId === projectId;\n      if (stillActive) {\n        set((s) => ({\n          videoProjects: s.videoProjects.map((p) =>\n            p.id === projectId ? { ...p, cloudEditableId: editable.id } : p,\n          ),\n        }));\n        void get().saveVideoProject().catch(() => {});\n      }\n\n      return true;\n    } catch (err) {\n      console.warn('[autoSaveVideoProjectToCloud] failed:', err);\n      throw err;\n    }\n  }),\n\n  loadVideoProject: async () => {\n    try {\n      const { openUploadsDB } = await import('./useEditorStore');\n      const db = await openUploadsDB();\n\n      // Load the project metadata\n      const saved: any = await new Promise((resolve, reject) => {\n        const tx = db.transaction('projects', 'readonly');\n        const store = tx.objectStore('projects');\n        const req = store.get('video-projects');\n        req.onsuccess = () => resolve(req.result || null);\n        req.onerror = () => reject(req.error);\n      });\n\n      if (!saved?.videoProjects || saved.videoProjects.length === 0) {\n        set({ isVideoSetupOpen: true, isVideoProjectLoading: false });\n        return;\n      }\n\n      // Load stored file bytes from video-assets and rebuild blob: URLs\n      const storedFiles: any[] = await new Promise((resolve, reject) => {\n        const tx = db.transaction('video-assets', 'readonly');\n        const store = tx.objectStore('video-assets');\n        const req = store.getAll();\n        req.onsuccess = () => resolve(req.result || []);\n        req.onerror = () => reject(req.error);\n      });\n\n      // Build a map: assetId \u2192 { blobUrl, file }\n      const fileMap = new Map<string, { url: string; file: File }>();\n      storedFiles.forEach((stored) => {\n        try {\n          const blob = new Blob([stored.buffer], { type: stored.mimeType || 'video/mp4' });\n          const url = URL.createObjectURL(blob);\n          // Reconstruct a File-like object for compatibility\n          const file = new File([blob], stored.name, { type: stored.mimeType || 'video/mp4' });\n          fileMap.set(stored.id, { url, file });\n        } catch (_) {}\n      });\n\n      // Patch blob: URLs back into each project's assets\n      const patchedProjects = saved.videoProjects.map((proj: any) => ({\n        ...proj,\n        tracks: proj.tracks ?? INITIAL_TRACKS,\n        assets: proj.assets.map((asset: any) => {\n          const recovered = fileMap.get(asset.id);\n          const durableThumb =\n            typeof asset.thumbnail === 'string' && !asset.thumbnail.startsWith('blob:')\n              ? asset.thumbnail\n              : undefined;\n\n          if (recovered) {\n            return {\n              ...asset,\n              url: recovered.url,\n              file: recovered.file,\n              // Images use the restored blob url as preview; videos keep data-URL thumbs\n              thumbnail:\n                durableThumb ||\n                (asset.type === 'image' ? recovered.url : durableThumb),\n            };\n          }\n\n          // Drop dead blob thumbnails when bytes were not recovered\n          if (typeof asset.thumbnail === 'string' && asset.thumbnail.startsWith('blob:')) {\n            return {\n              ...asset,\n              thumbnail: undefined,\n              url: asset.remoteUrl || '',\n            };\n          }\n          return asset;\n        }),\n      }));\n\n      const activeId = saved.activeVideoProjectId || patchedProjects[0].id;\n      const activeProj = patchedProjects.find((p: any) => p.id === activeId)\n        || patchedProjects[0];\n\n      set({\n        videoProjects: patchedProjects,\n        activeVideoProjectId: activeId,\n        tracks: activeProj.tracks ?? INITIAL_TRACKS,\n        assets: activeProj.assets ?? [],\n        transitions: activeProj.transitions ?? [],\n        aspectRatio: activeProj.aspectRatio ?? '16:9',\n        canvasWidth:\n          activeProj.canvasWidth ??\n          dimensionsForAspect(activeProj.aspectRatio ?? '16:9').width,\n        canvasHeight:\n          activeProj.canvasHeight ??\n          dimensionsForAspect(activeProj.aspectRatio ?? '16:9').height,\n        projectDuration: activeProj.projectDuration ?? 300,\n        playheadTime: activeProj.playheadTime ?? 0,\n        zoom: activeProj.zoom ?? 15,\n        selectedClipIds: [],                   // always reset \u2014 not persisted\n        // history is not persisted (too large). Seed with a single restore snapshot.\n        history: [{ tracks: activeProj.tracks ?? INITIAL_TRACKS, transitions: activeProj.transitions ?? [], description: 'Restored' }],\n        historyIndex: 0,\n        isVideoSetupOpen: false,\n        isVideoProjectLoading: false,\n      });\n    } catch (err) {\n      console.error('Failed to load video projects from IndexedDB:', err);\n      set({ isVideoSetupOpen: true, isVideoProjectLoading: false });\n    }\n  },\n\n  tracks: INITIAL_TRACKS,\n  assets: [],\n  transitions: [],\n  playheadTime: 0,\n  isPlaying: false,\n  // T-20260727-02: zoom inicial alto para que la l\u00EDnea de tiempo del\n  // editor ag\u00E9ntico muestre con detalle por defecto (80 px/s \u2248 labels\n  // cada 1s con el ruler). El usuario hace scroll horizontal para\n  // recorrer 00-30+ s de contenido. El Timeline se auto-deriva con\n  // projectDuration, pero la densidad visual inicial es esta.\n  zoom: 80,\n  selectedClipIds: [],\n  history: [{ tracks: INITIAL_TRACKS, transitions: [], description: 'Initial State' }],\n  historyIndex: 0,\n  projectDuration: 300,\n  openaiApiKey: typeof window !== 'undefined' ? localStorage.getItem('cutflow_openai_api_key') || '' : '',\n  geminiApiKey: typeof window !== 'undefined' ? localStorage.getItem('wizard_ai_gemini_api_key') || '' : '',\n  unsplashApiKey: typeof window !== 'undefined' ? localStorage.getItem('wizard_ai_unsplash_api_key') || '' : '',\n  pexelsApiKey: typeof window !== 'undefined' ? localStorage.getItem('wizard_ai_pexels_api_key') || '' : '',\n  scrollTop: 0,\n  aspectRatio: '16:9',\n  canvasWidth: 1920,\n  canvasHeight: 1080,\n  snapEnabled: true,\n  aiSubtitleJob: null,\n  setAiSubtitleJob: (job) => set({ aiSubtitleJob: job }),\n  aiBusyToolId: null,\n  setAiBusyToolId: (toolId) => set({ aiBusyToolId: toolId }),\n\n  setAspectRatio: (aspect: '16:9' | '9:16' | '1:1' | '4:3' | '3:4' | '21:9') => {\n    const dims = dimensionsForAspect(aspect);\n    set({ aspectRatio: aspect, canvasWidth: dims.width, canvasHeight: dims.height });\n    markCloudAutosaveAnnounce('video');\n    videoPersistence.scheduleAfterChange();\n  },\n\n  setCanvasSize: (width: number, height: number) => {\n    const w = Math.max(16, Math.min(7680, Math.round(width)));\n    const h = Math.max(16, Math.min(7680, Math.round(height)));\n    set({\n      canvasWidth: w,\n      canvasHeight: h,\n      aspectRatio: closestAspect(w, h),\n    });\n    markCloudAutosaveAnnounce('video');\n    videoPersistence.scheduleAfterChange();\n  },\n\n  setSnapEnabled: (enabled: boolean) => {\n    set({ snapEnabled: enabled });\n  },\n\n  setOpenaiApiKey: (key: string) => {\n    if (typeof window !== 'undefined') {\n      localStorage.setItem('cutflow_openai_api_key', key);\n    }\n    set({ openaiApiKey: key });\n  },\n\n  setGeminiApiKey: (key: string) => {\n    if (typeof window !== 'undefined') {\n      localStorage.setItem('wizard_ai_gemini_api_key', key);\n    }\n    set({ geminiApiKey: key });\n  },\n\n  setUnsplashApiKey: (key: string) => {\n    if (typeof window !== 'undefined') {\n      localStorage.setItem('wizard_ai_unsplash_api_key', key);\n    }\n    set({ unsplashApiKey: key });\n  },\n\n  setPexelsApiKey: (key: string) => {\n    if (typeof window !== 'undefined') {\n      localStorage.setItem('wizard_ai_pexels_api_key', key);\n    }\n    set({ pexelsApiKey: key });\n  },\n\n  addAsset: (asset: Asset) => {\n    // 1. Add to in-memory store immediately\n    set((state) => ({ assets: [...state.assets, asset] }));\n\n    // 2. Persist the raw file bytes to IndexedDB so blob: URLs can be\n    //    recreated after a page reload (blob: URLs are ephemeral).\n    if (asset.file && asset.file instanceof File) {\n      asset.file.arrayBuffer().then(async (buffer) => {\n        try {\n          const { openUploadsDB } = await import('./useEditorStore');\n          const db = await openUploadsDB();\n          await new Promise<void>((resolve, reject) => {\n            const tx = db.transaction('video-assets', 'readwrite');\n            const store = tx.objectStore('video-assets');\n            const req = store.put({\n              id: asset.id,\n              name: asset.name,\n              mimeType: asset.file!.type || 'video/mp4',\n              buffer,\n              thumbnail: asset.thumbnail,\n              duration: asset.duration,\n              width: asset.width,\n              height: asset.height,\n              assetType: asset.type,\n            });\n            req.onsuccess = () => resolve();\n            req.onerror = () => reject(req.error);\n          });\n        } catch (err) {\n          console.error('Failed to persist video asset to IndexedDB:', err);\n        }\n      }).catch(() => {/* File may not support arrayBuffer in all contexts */});\n    }\n  },\n\n  removeAsset: (assetId: string) => {\n    set((state) => {\n      const tracks = state.tracks.map((track) => ({\n        ...track,\n        clips: track.clips.filter((clip) => clip.assetId !== assetId),\n      }));\n\n      const newHistory = pushToHistory({ ...state, tracks }, 'Remove Asset');\n      return {\n        assets: state.assets.filter((a) => a.id !== assetId),\n        tracks,\n        selectedClipIds: [],\n        history: newHistory,\n        historyIndex: newHistory.length - 1,\n      };\n    });\n  },\n\n  addClip: (trackId: string, clipData: Omit<Clip, 'id'>) => {\n    set((state) => {\n      const track = state.tracks.find((t) => t.id === trackId);\n      if (!track || track.locked) {\n        return {};\n      }\n\n      let resolvedScaleX = clipData.scaleX;\n      let resolvedScaleY = clipData.scaleY;\n      if (\n        (clipData.type === 'image' || clipData.type === 'video') &&\n        (resolvedScaleX === undefined || resolvedScaleY === undefined)\n      ) {\n        const asset = state.assets.find((a) => a.id === clipData.assetId);\n        const native = nativeDisplayScale(\n          asset?.width ?? 0,\n          asset?.height ?? 0,\n          clipData.type === 'image' ? 'image' : 'video',\n          state.canvasWidth || 1920,\n          state.canvasHeight || 1080,\n        );\n        resolvedScaleX = resolvedScaleX ?? native.scaleX;\n        resolvedScaleY = resolvedScaleY ?? native.scaleY;\n      }\n\n      const newClip: Clip = {\n        ...clipData,\n        scaleX: resolvedScaleX,\n        scaleY: resolvedScaleY,\n        id: `clip_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n        trackId,\n        keyframes: clipData.keyframes || [],\n        effects: clipData.effects || []\n      };\n\n      let startTime = clipData.startTime;\n      const sortedClips = [...track.clips].sort((a, b) => a.startTime - b.startTime);\n\n      for (const existing of sortedClips) {\n        if (startTime < existing.startTime + existing.duration && startTime + newClip.duration > existing.startTime) {\n          startTime = existing.startTime + existing.duration;\n        }\n      }\n      newClip.startTime = startTime;\n\n      const tracks = state.tracks.map((t) => {\n        if (t.id === trackId) {\n          return { ...t, clips: [...t.clips, newClip] };\n        }\n        return t;\n      });\n\n      const newHistory = pushToHistory({ ...state, tracks }, `Add Clip ${clipData.type}`);\n      return {\n        tracks,\n        selectedClipIds: [newClip.id],\n        history: newHistory,\n        historyIndex: newHistory.length - 1,\n      };\n    });\n  },\n\n  removeClip: (clipId: string) => {\n    set((state) => {\n      let removedClip: Clip | undefined;\n      const tracks = state.tracks.map((track) => {\n        if (track.locked) return track;\n        const index = track.clips.findIndex((c) => c.id === clipId);\n        if (index !== -1) {\n          removedClip = track.clips[index];\n          return {\n            ...track,\n            clips: track.clips.filter((c) => c.id !== clipId),\n          };\n        }\n        return track;\n      });\n\n      if (!removedClip) return {};\n\n      // Remove any transitions associated with this clip\n      const transitions = state.transitions.filter(\n        (t) => t.fromClipId !== clipId && t.toClipId !== clipId\n      );\n\n      const newHistory = pushToHistory({ ...state, tracks, transitions }, 'Delete Clip');\n      return {\n        tracks,\n        transitions,\n        selectedClipIds: state.selectedClipIds.filter((id) => id !== clipId),\n        history: newHistory,\n        historyIndex: newHistory.length - 1,\n      };\n    });\n  },\n\n  moveClip: (clipId: string, startTime: number, trackId: string) => {\n    set((state) => {\n      let clipToMove: Clip | undefined;\n      let sourceTrackId = '';\n      for (const track of state.tracks) {\n        const found = track.clips.find((c) => c.id === clipId);\n        if (found) {\n          clipToMove = found;\n          sourceTrackId = track.id;\n          break;\n        }\n      }\n\n      if (!clipToMove) return {};\n\n      const srcTrack = state.tracks.find((t) => t.id === sourceTrackId);\n      const dstTrack = state.tracks.find((t) => t.id === trackId);\n      if (srcTrack?.locked || dstTrack?.locked) return {};\n\n      let targetStartTime = Math.max(0, startTime);\n\n      const tracks = state.tracks.map((track) => {\n        if (track.id === sourceTrackId && sourceTrackId !== trackId) {\n          return {\n            ...track,\n            clips: track.clips.filter((c) => c.id !== clipId),\n          };\n        }\n\n        if (track.id === trackId) {\n          const otherClips = track.clips.filter((c) => c.id !== clipId);\n          const updatedClip = { ...clipToMove!, startTime: targetStartTime, trackId };\n\n          const sortedClips = [...otherClips].sort((a, b) => a.startTime - b.startTime);\n          let currentStart = targetStartTime;\n          const duration = clipToMove!.duration;\n\n          const updatedOtherClips = sortedClips.map((c) => {\n            if (c.startTime < currentStart + duration && c.startTime + c.duration > currentStart) {\n              const overlapAmount = (currentStart + duration) - c.startTime;\n              c.startTime += overlapAmount;\n            }\n            return c;\n          });\n\n          for (let i = 0; i < updatedOtherClips.length; i++) {\n            const current = updatedOtherClips[i];\n            for (let j = i + 1; j < updatedOtherClips.length; j++) {\n              const next = updatedOtherClips[j];\n              if (next.startTime < current.startTime + current.duration) {\n                next.startTime = current.startTime + current.duration;\n              }\n            }\n          }\n\n          return {\n            ...track,\n            clips: [...updatedOtherClips, updatedClip],\n          };\n        }\n\n        return track;\n      });\n\n      const transitions = validateAndAdjustAllTransitions(tracks, state.transitions);\n      const newHistory = pushToHistory({ ...state, tracks, transitions }, 'Move Clip');\n      return {\n        tracks,\n        transitions,\n        history: newHistory,\n        historyIndex: newHistory.length - 1,\n      };\n    });\n  },\n\n  moveClipsByDelta: (clipIds, deltaSec) => {\n    if (clipIds.length === 0 || !Number.isFinite(deltaSec) || deltaSec === 0) return;\n\n    set((state) => {\n      const idSet = new Set(clipIds);\n      let minStart = Infinity;\n      for (const track of state.tracks) {\n        if (track.locked) continue;\n        for (const clip of track.clips) {\n          if (!idSet.has(clip.id)) continue;\n          minStart = Math.min(minStart, clip.startTime + deltaSec);\n        }\n      }\n      if (!Number.isFinite(minStart)) return {};\n      // Keep the group from going before t=0\n      const effectiveDelta = minStart < 0 ? deltaSec - minStart : deltaSec;\n      if (effectiveDelta === 0) return {};\n\n      const tracks = state.tracks.map((track) => {\n        if (track.locked) return track;\n        const hasSelected = track.clips.some((c) => idSet.has(c.id));\n        if (!hasSelected) return track;\n\n        const moved = track.clips.map((c) =>\n          idSet.has(c.id)\n            ? { ...c, startTime: Math.max(0, c.startTime + effectiveDelta) }\n            : { ...c },\n        );\n\n        // Push non-selected clips that overlap a selected one to the right\n        const selected = moved.filter((c) => idSet.has(c.id)).sort((a, b) => a.startTime - b.startTime);\n        const others = moved.filter((c) => !idSet.has(c.id)).sort((a, b) => a.startTime - b.startTime);\n        for (const other of others) {\n          for (const sel of selected) {\n            if (\n              other.startTime < sel.startTime + sel.duration &&\n              other.startTime + other.duration > sel.startTime\n            ) {\n              other.startTime = sel.startTime + sel.duration;\n            }\n          }\n        }\n        // Resolve cascades among others\n        for (let i = 0; i < others.length; i++) {\n          const current = others[i]!;\n          for (let j = i + 1; j < others.length; j++) {\n            const next = others[j]!;\n            if (next.startTime < current.startTime + current.duration) {\n              next.startTime = current.startTime + current.duration;\n            }\n          }\n        }\n\n        return { ...track, clips: [...selected, ...others] };\n      });\n\n      const transitions = validateAndAdjustAllTransitions(tracks, state.transitions);\n      const newHistory = pushToHistory({ ...state, tracks, transitions }, 'Move Clips');\n      return {\n        tracks,\n        transitions,\n        history: newHistory,\n        historyIndex: newHistory.length - 1,\n      };\n    });\n  },\n\n  trimClip: (clipId: string, trimIn: number, trimOut: number, newStartTime?: number) => {\n    set((state) => {\n      let clipTrackId = '';\n      let targetClip: Clip | undefined;\n\n      for (const track of state.tracks) {\n        const found = track.clips.find((c) => c.id === clipId);\n        if (found) {\n          targetClip = found;\n          clipTrackId = track.id;\n          break;\n        }\n      }\n\n      const track = state.tracks.find((t) => t.id === clipTrackId);\n      if (!targetClip || !track || track.locked) return {};\n\n      const asset = state.assets.find((a) => a.id === targetClip!.assetId);\n      const maxSourceDuration = asset ? asset.duration : 9999;\n\n      const newDuration = Math.max(0.1, (maxSourceDuration - trimIn - trimOut) / targetClip.speed);\n\n      const tracks = state.tracks.map((t) => {\n        if (t.id === clipTrackId) {\n          return {\n            ...t,\n            clips: t.clips.map((c) => {\n              if (c.id === clipId) {\n                return {\n                  ...c,\n                  trimIn,\n                  trimOut,\n                  duration: newDuration,\n                  startTime: newStartTime !== undefined ? newStartTime : c.startTime,\n                };\n              }\n              return c;\n            }),\n          };\n        }\n        return t;\n      });\n\n      const transitions = validateAndAdjustAllTransitions(tracks, state.transitions);\n      const newHistory = pushToHistory({ ...state, tracks, transitions }, 'Trim Clip');\n      return {\n        tracks,\n        transitions,\n        history: newHistory,\n        historyIndex: newHistory.length - 1,\n      };\n    });\n  },\n\n  splitClip: (clipId: string, atTime: number) => {\n    set((state) => {\n      let clipTrackId = '';\n      let targetClip: Clip | undefined;\n\n      for (const track of state.tracks) {\n        const found = track.clips.find((c) => c.id === clipId);\n        if (found) {\n          targetClip = found;\n          clipTrackId = track.id;\n          break;\n        }\n      }\n\n      const track = state.tracks.find((t) => t.id === clipTrackId);\n      if (!targetClip || !track || track.locked) return {};\n\n      const clipStart = targetClip.startTime;\n      const clipEnd = targetClip.startTime + targetClip.duration;\n      if (atTime <= clipStart || atTime >= clipEnd) return {};\n\n      const splitPointSec = atTime - clipStart;\n      const sourceSplitOffset = splitPointSec * targetClip.speed;\n\n      const clip1Duration = splitPointSec;\n      const clip2Duration = targetClip.duration - splitPointSec;\n\n      const clip1: Clip = {\n        ...targetClip,\n        duration: clip1Duration,\n        trimOut: targetClip.trimOut + clip2Duration * targetClip.speed,\n      };\n\n      const clip2: Clip = {\n        ...targetClip,\n        id: `clip_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n        startTime: atTime,\n        duration: clip2Duration,\n        trimIn: targetClip.trimIn + sourceSplitOffset,\n        keyframes: JSON.parse(JSON.stringify(targetClip.keyframes || [])),\n        effects: JSON.parse(JSON.stringify(targetClip.effects || [])),\n      };\n\n      const tracks = state.tracks.map((t) => {\n        if (t.id === clipTrackId) {\n          return {\n            ...t,\n            clips: [...t.clips.filter((c) => c.id !== clipId), clip1, clip2],\n          };\n        }\n        return t;\n      });\n\n      // Reassign transitions associated with the split clip\n      const transitions = state.transitions.map((t) => {\n        const updated = { ...t };\n        if (t.fromClipId === clipId) {\n          updated.fromClipId = clip2.id;\n        }\n        if (t.toClipId === clipId) {\n          updated.toClipId = clip1.id;\n        }\n        return updated;\n      });\n\n      const validatedTransitions = validateAndAdjustAllTransitions(tracks, transitions);\n      const newHistory = pushToHistory({ ...state, tracks, transitions: validatedTransitions }, 'Split Clip');\n      return {\n        tracks,\n        transitions: validatedTransitions,\n        selectedClipIds: [clip1.id],\n        history: newHistory,\n        historyIndex: newHistory.length - 1,\n      };\n    });\n  },\n\n  updateClipProperties: (clipId: string, properties: Partial<Omit<Clip, 'id' | 'type' | 'trackId' | 'assetId'>>) => {\n    set((state) => {\n      const tracks = state.tracks.map((track) => {\n        if (track.locked) return track;\n        const exists = track.clips.some((c) => c.id === clipId);\n        if (!exists) return track;\n\n        return {\n          ...track,\n          clips: track.clips.map((c) => {\n            if (c.id === clipId) {\n              const updated = { ...c, ...properties };\n              if (properties.speed !== undefined && properties.speed !== c.speed) {\n                const asset = state.assets.find((a) => a.id === c.assetId);\n                const maxSourceDuration = asset ? asset.duration : 9999;\n                updated.duration = (maxSourceDuration - updated.trimIn - updated.trimOut) / updated.speed;\n              }\n              return updated;\n            }\n            return c;\n          }),\n        };\n      });\n\n      const transitions = validateAndAdjustAllTransitions(tracks, state.transitions);\n      const newHistory = pushToHistory({ ...state, tracks, transitions }, 'Update Clip Properties');\n      return {\n        tracks,\n        transitions,\n        history: newHistory,\n        historyIndex: newHistory.length - 1,\n      };\n    });\n  },\n\n  setPlayhead: (time: number) => {\n    set({ playheadTime: Math.max(0, time) });\n  },\n\n  setIsPlaying: (playing: boolean) => {\n    set({ isPlaying: playing });\n  },\n\n  setZoom: (zoom: number) => {\n    set({ zoom: Math.min(100, Math.max(2, zoom)) });\n  },\n\n  setScrollTop: (top: number) => {\n    set({ scrollTop: Math.max(0, top) });\n  },\n\n  selectClip: (clipId: string, multi: boolean) => {\n    set((state) => {\n      if (multi) {\n        const selected = state.selectedClipIds.includes(clipId)\n          ? state.selectedClipIds.filter((id) => id !== clipId)\n          : [...state.selectedClipIds, clipId];\n        return { selectedClipIds: selected };\n      } else {\n        return { selectedClipIds: [clipId] };\n      }\n    });\n  },\n\n  selectClips: (clipIds, additive = false) => {\n    set((state) => {\n      if (!additive) return { selectedClipIds: [...clipIds] };\n      const setIds = new Set(state.selectedClipIds);\n      for (const id of clipIds) setIds.add(id);\n      return { selectedClipIds: Array.from(setIds) };\n    });\n  },\n\n  clearSelection: () => {\n    set({ selectedClipIds: [] });\n  },\n\n  toggleTrackMute: (trackId: string) => {\n    set((state) => {\n      const tracks = state.tracks.map((t) => (t.id === trackId ? { ...t, muted: !t.muted } : t));\n      return { tracks };\n    });\n  },\n\n  toggleTrackLock: (trackId: string) => {\n    set((state) => {\n      const tracks = state.tracks.map((t) => (t.id === trackId ? { ...t, locked: !t.locked } : t));\n      return { tracks };\n    });\n  },\n\n  undo: () => {\n    set((state) => {\n      if (state.historyIndex <= 0) return {};\n      const nextIndex = state.historyIndex - 1;\n      const snapshot = state.history[nextIndex];\n      return {\n        tracks: JSON.parse(JSON.stringify(snapshot.tracks)),\n        transitions: JSON.parse(JSON.stringify(snapshot.transitions)),\n        historyIndex: nextIndex,\n        selectedClipIds: [],\n      };\n    });\n  },\n\n  redo: () => {\n    set((state) => {\n      if (state.historyIndex >= state.history.length - 1) return {};\n      const nextIndex = state.historyIndex + 1;\n      const snapshot = state.history[nextIndex];\n      return {\n        tracks: JSON.parse(JSON.stringify(snapshot.tracks)),\n        transitions: JSON.parse(JSON.stringify(snapshot.transitions)),\n        historyIndex: nextIndex,\n        selectedClipIds: [],\n      };\n    });\n  },\n\n  setProjectDuration: (duration: number) => {\n    set({ projectDuration: Math.max(10, duration) });\n  },\n\n  addTrack: (name, type) => {\n    set((state) => {\n      const newTrack: Track = {\n        id: `track_${type}_${Date.now()}`,\n        name: name,\n        type: type,\n        muted: false,\n        locked: false,\n        clips: []\n      };\n\n      // Insert after the last track of the same type when present; otherwise append.\n      // Never force type bands \u2014 user stack order is free.\n      let insertIndex = state.tracks.length;\n      for (let i = state.tracks.length - 1; i >= 0; i--) {\n        if (state.tracks[i]?.type === type) {\n          insertIndex = i + 1;\n          break;\n        }\n      }\n\n      const tracks = [...state.tracks];\n      tracks.splice(insertIndex, 0, newTrack);\n\n      const newHistory = pushToHistory({ ...state, tracks }, `Add Track ${name}`);\n      return {\n        tracks,\n        history: newHistory,\n        historyIndex: newHistory.length - 1\n      };\n    });\n  },\n\n  removeTrack: (trackId) => {\n    set((state) => {\n      const tracks = state.tracks.filter((t) => t.id !== trackId);\n      const newHistory = pushToHistory({ ...state, tracks }, 'Remove Track');\n      return {\n        tracks,\n        history: newHistory,\n        historyIndex: newHistory.length - 1\n      };\n    });\n  },\n\n  moveClipLayer: (clipId, direction) => {\n    const state = get();\n    let clip: Clip | undefined;\n    let sourceTrack: Track | undefined;\n    let sourceIndex = -1;\n\n    for (let i = 0; i < state.tracks.length; i++) {\n      const track = state.tracks[i];\n      const found = track.clips.find((c) => c.id === clipId);\n      if (found) {\n        clip = found;\n        sourceTrack = track;\n        sourceIndex = i;\n        break;\n      }\n    }\n\n    if (!clip || !sourceTrack || sourceTrack.locked) return;\n    if (sourceTrack.type === 'subtitle') return;\n\n    const type = sourceTrack.type as 'video' | 'audio' | 'text' | 'image';\n    const sameTypeIndices = state.tracks\n      .map((t, i) => (t.type === type ? i : -1))\n      .filter((i) => i >= 0);\n    const posInType = sameTypeIndices.indexOf(sourceIndex);\n    if (posInType < 0) return;\n\n    const targetPosInType = direction === 'up' ? posInType - 1 : posInType + 1;\n\n    // Existing neighbor of the same type\n    if (targetPosInType >= 0 && targetPosInType < sameTypeIndices.length) {\n      const targetTrack = state.tracks[sameTypeIndices[targetPosInType]];\n      if (!targetTrack || targetTrack.locked) return;\n      get().moveClip(clipId, clip.startTime, targetTrack.id);\n      return;\n    }\n\n    // At edge: create a new layer and move the clip into it\n    const existingCount = state.tracks.filter((t) => t.type === type).length;\n    const name = `${type.charAt(0).toUpperCase() + type.slice(1)} ${existingCount + 1}`;\n    const newTrack: Track = {\n      id: `track_${type}_${Date.now()}`,\n      name,\n      type,\n      muted: false,\n      locked: false,\n      clips: [],\n    };\n\n    const tracks = [...state.tracks];\n    const insertAt = direction === 'up' ? sourceIndex : sourceIndex + 1;\n    tracks.splice(insertAt, 0, newTrack);\n\n    // Move clip onto the new track (same start time)\n    const withClip = tracks.map((t) => {\n      if (t.id === sourceTrack!.id) {\n        return { ...t, clips: t.clips.filter((c) => c.id !== clipId) };\n      }\n      if (t.id === newTrack.id) {\n        return {\n          ...t,\n          clips: [{ ...clip!, trackId: newTrack.id }],\n        };\n      }\n      return t;\n    });\n\n    const transitions = validateAndAdjustAllTransitions(withClip, state.transitions);\n    const newHistory = pushToHistory(\n      { ...state, tracks: withClip, transitions },\n      direction === 'up' ? 'Move Clip Layer Up' : 'Move Clip Layer Down',\n    );\n    set({\n      tracks: withClip,\n      transitions,\n      history: newHistory,\n      historyIndex: newHistory.length - 1,\n    });\n  },\n\n  reorderTrack: (trackId, direction) => {\n    set((state) => {\n      // Reorder among visible timeline lanes (any type), not only same-type neighbors.\n      const visible = getVisibleTimelineTracks(state.tracks);\n      const vIdx = visible.findIndex((t) => t.id === trackId);\n      if (vIdx < 0) return {};\n      const swapVIdx = direction === 'up' ? vIdx - 1 : vIdx + 1;\n      if (swapVIdx < 0 || swapVIdx >= visible.length) return {};\n      const aId = visible[vIdx]?.id;\n      const bId = visible[swapVIdx]?.id;\n      if (!aId || !bId) return {};\n\n      const index = state.tracks.findIndex((t) => t.id === aId);\n      const swapIndex = state.tracks.findIndex((t) => t.id === bId);\n      if (index < 0 || swapIndex < 0) return {};\n\n      const tracks = [...state.tracks];\n      const a = tracks[index];\n      const b = tracks[swapIndex];\n      if (!a || !b) return {};\n      tracks[index] = b;\n      tracks[swapIndex] = a;\n\n      const newHistory = pushToHistory(\n        { ...state, tracks },\n        direction === 'up' ? 'Reorder Track Up' : 'Reorder Track Down',\n      );\n      return {\n        tracks,\n        history: newHistory,\n        historyIndex: newHistory.length - 1,\n      };\n    });\n  },\n\n  // \u2500\u2500\u2500 TEXT MODULE ACTIONS \u2500\u2500\u2500\n\n  addTextClip: (clipData) => {\n    const aspect = get().aspectRatio || '16:9';\n    let fontSize = clipData.fontSize || 48;\n    if (aspect === '9:16') {\n      fontSize = Math.round(fontSize * 0.5);\n    } else if (aspect === '1:1') {\n      fontSize = Math.round(fontSize * 0.65);\n    }\n\n    get().addClip(clipData.trackId, {\n      ...clipData,\n      type: 'text',\n      // Set defaults for text settings\n      fontFamily: clipData.fontFamily || 'Inter',\n      fontWeight: clipData.fontWeight || 500,\n      fontSize: fontSize,\n      fontStyle: clipData.fontStyle || 'normal',\n      letterSpacing: clipData.letterSpacing || 0,\n      lineHeight: clipData.lineHeight || 1.2,\n      textAlign: clipData.textAlign || 'center',\n      textTransform: clipData.textTransform || 'none',\n      fillType: clipData.fillType || 'solid',\n      fillColor: clipData.fillColor || '#FFFFFF',\n      gradientColors: clipData.gradientColors || ['#FFFFFF', '#888888'],\n      gradientAngle: clipData.gradientAngle || 90,\n      strokeEnabled: clipData.strokeEnabled || false,\n      strokeColor: clipData.strokeColor || '#000000',\n      strokeWidth: clipData.strokeWidth || 2,\n      strokePosition: clipData.strokePosition || 'center',\n      shadowEnabled: clipData.shadowEnabled || false,\n      shadowColor: clipData.shadowColor || '#000000',\n      shadowBlur: clipData.shadowBlur || 4,\n      shadowOffsetX: clipData.shadowOffsetX || 2,\n      shadowOffsetY: clipData.shadowOffsetY || 2,\n      shadowOpacity: clipData.shadowOpacity || 0.5,\n      backgroundEnabled: clipData.backgroundEnabled || false,\n      backgroundColor: clipData.backgroundColor || '#000000',\n      backgroundOpacity: clipData.backgroundOpacity || 0.6,\n      backgroundPadding: clipData.backgroundPadding || 8,\n      backgroundBorderRadius: clipData.backgroundBorderRadius || 4,\n      x: clipData.x !== undefined ? clipData.x : 0.5,\n      y: clipData.y !== undefined ? clipData.y : 0.5,\n      rotation: clipData.rotation || 0,\n      scaleX: clipData.scaleX || 1.0,\n      scaleY: clipData.scaleY || 1.0,\n      opacity: clipData.opacity !== undefined ? clipData.opacity : 1.0,\n      animationIn: clipData.animationIn || null,\n      animationOut: clipData.animationOut || null,\n      animationInDuration: clipData.animationInDuration || 0.5,\n      animationOutDuration: clipData.animationOutDuration || 0.5,\n      keyframes: clipData.keyframes || []\n    });\n  },\n\n  updateTextClip: (id, updates) => {\n    get().updateClipProperties(id, updates);\n  },\n\n  // \u2500\u2500\u2500 IMAGE MODULE ACTIONS \u2500\u2500\u2500\n\n  addImageClip: (clipData) => {\n    get().addClip(clipData.trackId, {\n      ...clipData,\n      type: 'image',\n      // Set defaults for image settings\n      x: clipData.x !== undefined ? clipData.x : 0.5,\n      y: clipData.y !== undefined ? clipData.y : 0.5,\n      // scaleX/Y: omit so addClip applies native pixel size from the asset\n      scaleX: clipData.scaleX,\n      scaleY: clipData.scaleY,\n      rotation: clipData.rotation || 0,\n      opacity: clipData.opacity !== undefined ? clipData.opacity : 1.0,\n      cropEnabled: clipData.cropEnabled || false,\n      cropX: clipData.cropX || 0,\n      cropY: clipData.cropY || 0,\n      cropWidth: clipData.cropWidth || 1.0,\n      cropHeight: clipData.cropHeight || 1.0,\n      maskShape: clipData.maskShape || 'none',\n      maskFeather: clipData.maskFeather || 0,\n      flipX: clipData.flipX || false,\n      flipY: clipData.flipY || false,\n      blendMode: clipData.blendMode || 'normal',\n      borderRadius: clipData.borderRadius || 0,\n      colorGrading: clipData.colorGrading || { ...DEFAULT_COLOR_GRADING },\n      fitMode: clipData.fitMode || 'fit',\n      animationIn: clipData.animationIn || null,\n      animationOut: clipData.animationOut || null,\n      animationInDuration: clipData.animationInDuration || 0.5,\n      animationOutDuration: clipData.animationOutDuration || 0.5,\n      keyframes: clipData.keyframes || []\n    });\n  },\n\n  updateImageClip: (id, updates) => {\n    get().updateClipProperties(id, updates);\n  },\n\n  updateColorGrading: (clipId, grading) => {\n    set((state) => {\n      const tracks = state.tracks.map((track) => {\n        if (track.locked) return track;\n        const exists = track.clips.some((c) => c.id === clipId);\n        if (!exists) return track;\n\n        return {\n          ...track,\n          clips: track.clips.map((c) => {\n            if (c.id === clipId) {\n              const currentGrading = c.colorGrading || { ...DEFAULT_COLOR_GRADING };\n              return {\n                ...c,\n                colorGrading: {\n                  ...currentGrading,\n                  ...grading\n                }\n              };\n            }\n            return c;\n          })\n        };\n      });\n\n      const newHistory = pushToHistory({ ...state, tracks }, 'Update Color Grading');\n      return {\n        tracks,\n        history: newHistory,\n        historyIndex: newHistory.length - 1\n      };\n    });\n  },\n\n  // \u2500\u2500\u2500 TRANSITION ACTIONS \u2500\u2500\u2500\n\n  addTransition: (transitionData) => {\n    set((state) => {\n      const validatedDuration = getValidatedTransitionDuration(\n        state.tracks,\n        transitionData.fromClipId,\n        transitionData.toClipId,\n        transitionData.duration\n      );\n\n      const newTransition: TransitionClip = {\n        ...transitionData,\n        duration: validatedDuration,\n        id: `trans_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`\n      };\n\n      const transitions = [...state.transitions.filter((t) => \n        !(t.fromClipId === transitionData.fromClipId && t.toClipId === transitionData.toClipId)\n      ), newTransition];\n\n      const validatedTransitions = validateAndAdjustAllTransitions(state.tracks, transitions);\n\n      const newHistory = pushToHistory({ ...state, transitions: validatedTransitions }, 'Add Transition');\n      return {\n        transitions: validatedTransitions,\n        history: newHistory,\n        historyIndex: newHistory.length - 1\n      };\n    });\n  },\n\n  updateTransition: (id, updates, opts) => {\n    set((state) => {\n      const transitions = state.transitions.map((t) => {\n        if (t.id === id) {\n          const merged = { ...t, ...updates };\n          const validatedDuration = getValidatedTransitionDuration(\n            state.tracks,\n            merged.fromClipId,\n            merged.toClipId,\n            merged.duration\n          );\n          return { ...merged, duration: validatedDuration };\n        }\n        return t;\n      });\n      \n      const validatedTransitions = validateAndAdjustAllTransitions(state.tracks, transitions);\n\n      if (opts?.history === false) {\n        return { transitions: validatedTransitions };\n      }\n\n      const newHistory = pushToHistory({ ...state, transitions: validatedTransitions }, 'Update Transition');\n      return {\n        transitions: validatedTransitions,\n        history: newHistory,\n        historyIndex: newHistory.length - 1\n      };\n    });\n  },\n\n  removeTransition: (id) => {\n    set((state) => {\n      const transitions = state.transitions.filter((t) => t.id !== id);\n      const newHistory = pushToHistory({ ...state, transitions }, 'Remove Transition');\n      return {\n        transitions,\n        history: newHistory,\n        historyIndex: newHistory.length - 1\n      };\n    });\n  },\n\n  // \u2500\u2500\u2500 EFFECTS ACTIONS \u2500\u2500\u2500\n\n  addEffect: (clipId, effectType, customParams) => {\n    set((state) => {\n      const tracks = state.tracks.map((track) => {\n        if (track.locked) return track;\n        const exists = track.clips.some((c) => c.id === clipId);\n        if (!exists) return track;\n\n        return {\n          ...track,\n          clips: track.clips.map((c) => {\n            if (c.id === clipId) {\n              const currentEffects = c.effects || [];\n              \n              // Load default parameters for selected effect with sensible visible defaults\n              let defaultParams: Record<string, any> = {};\n              if (effectType === 'blur-gaussian') {\n                defaultParams = { radius: 15, quality: 'Medium' };\n              } else if (effectType === 'vhs') {\n                defaultParams = { trackingNoise: 30, colorBleed: 40, scanLines: 50, brightness: 20 };\n              } else if (effectType === 'ken-burns') {\n                defaultParams = { startX: 0, startY: 0, startScale: 100, endX: 10, endY: 5, endScale: 130, easing: 'ease-in-out' };\n              } else if (effectType === 'camera-shake') {\n                defaultParams = { intensity: 20, frequency: 12, type: 'Random' };\n              } else if (effectType === 'zoom-dynamic') {\n                defaultParams = { direction: 'in', amount: 125, centerX: 0.5, centerY: 0.5, startTime: 0, endTime: 2 };\n              } else if (effectType === 'chromatic-aberration') {\n                defaultParams = { amount: 15 };\n              } else if (effectType === 'pixelate') {\n                defaultParams = { blockSize: 12 };\n              } else if (effectType === 'old-film') {\n                defaultParams = { sepiaIntensity: 60, scratchIntensity: 40, jitter: 20 };\n              } else if (effectType === 'mirror') {\n                defaultParams = { reflection: 'horizontal' };\n              } else if (effectType === 'exposure') {\n                defaultParams = { exposure: 1.0 };\n              } else if (effectType === 'brightness-contrast') {\n                defaultParams = { brightness: 20, contrast: 20 };\n              } else if (effectType === 'hue-saturation') {\n                defaultParams = { saturation: 40 };\n              } else if (effectType === 'color-temperature') {\n                defaultParams = { temperature: 30, tint: 10 };\n              }\n\n              const presetParams = customParams || defaultParams;\n\n              const newEffect: AppliedEffect = {\n                id: `fx_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`,\n                clipId,\n                effectType,\n                enabled: true,\n                order: currentEffects.length,\n                params: presetParams,\n                keyframes: [],\n                startTime: 0,\n                endTime: c.duration // Apply to whole duration by default\n              };\n\n              return {\n                ...c,\n                effects: [...currentEffects, newEffect]\n              };\n            }\n            return c;\n          })\n        };\n      });\n\n      const newHistory = pushToHistory({ ...state, tracks }, `Add Effect ${effectType}`);\n      return {\n        tracks,\n        history: newHistory,\n        historyIndex: newHistory.length - 1\n      };\n    });\n  },\n\n  updateEffect: (clipId, effectId, params) => {\n    set((state) => {\n      const tracks = state.tracks.map((track) => {\n        if (track.locked) return track;\n        const exists = track.clips.some((c) => c.id === clipId);\n        if (!exists) return track;\n\n        return {\n          ...track,\n          clips: track.clips.map((c) => {\n            if (c.id === clipId) {\n              const currentEffects = c.effects || [];\n              return {\n                ...c,\n                effects: currentEffects.map((fx) => \n                  fx.id === effectId \n                    ? { ...fx, params: { ...fx.params, ...params } } \n                    : fx\n                )\n              };\n            }\n            return c;\n          })\n        };\n      });\n\n      const newHistory = pushToHistory({ ...state, tracks }, 'Update Effect Parameters');\n      return {\n        tracks,\n        history: newHistory,\n        historyIndex: newHistory.length - 1\n      };\n    });\n  },\n\n  removeEffect: (clipId, effectId) => {\n    set((state) => {\n      const tracks = state.tracks.map((track) => {\n        if (track.locked) return track;\n        const exists = track.clips.some((c) => c.id === clipId);\n        if (!exists) return track;\n\n        return {\n          ...track,\n          clips: track.clips.map((c) => {\n            if (c.id === clipId) {\n              const currentEffects = c.effects || [];\n              const filtered = currentEffects.filter((fx) => fx.id !== effectId);\n              // Re-index orders\n              const reordered = filtered.map((fx, idx) => ({ ...fx, order: idx }));\n              return {\n                ...c,\n                effects: reordered\n              };\n            }\n            return c;\n          })\n        };\n      });\n\n      const newHistory = pushToHistory({ ...state, tracks }, 'Remove Effect');\n      return {\n        tracks,\n        history: newHistory,\n        historyIndex: newHistory.length - 1\n      };\n    });\n  },\n\n  reorderEffects: (clipId, fromIndex, toIndex) => {\n    set((state) => {\n      const tracks = state.tracks.map((track) => {\n        if (track.locked) return track;\n        const exists = track.clips.some((c) => c.id === clipId);\n        if (!exists) return track;\n\n        return {\n          ...track,\n          clips: track.clips.map((c) => {\n            if (c.id === clipId) {\n              const currentEffects = [...(c.effects || [])].sort((a, b) => a.order - b.order);\n              const [moved] = currentEffects.splice(fromIndex, 1);\n              currentEffects.splice(toIndex, 0, moved);\n              \n              const reordered = currentEffects.map((fx, idx) => ({\n                ...fx,\n                order: idx\n              }));\n\n              return {\n                ...c,\n                effects: reordered\n              };\n            }\n            return c;\n          })\n        };\n      });\n\n      const newHistory = pushToHistory({ ...state, tracks }, 'Reorder Effects');\n      return {\n        tracks,\n        history: newHistory,\n        historyIndex: newHistory.length - 1\n      };\n    });\n  },\n\n  toggleEffect: (clipId, effectId) => {\n    set((state) => {\n      const tracks = state.tracks.map((track) => {\n        if (track.locked) return track;\n        const exists = track.clips.some((c) => c.id === clipId);\n        if (!exists) return track;\n\n        return {\n          ...track,\n          clips: track.clips.map((c) => {\n            if (c.id === clipId) {\n              const currentEffects = c.effects || [];\n              return {\n                ...c,\n                effects: currentEffects.map((fx) => \n                  fx.id === effectId ? { ...fx, enabled: !fx.enabled } : fx\n                )\n              };\n            }\n            return c;\n          })\n        };\n      });\n\n      const newHistory = pushToHistory({ ...state, tracks }, 'Toggle Effect State');\n      return {\n        tracks,\n        history: newHistory,\n        historyIndex: newHistory.length - 1\n      };\n    });\n  },\n\n  // \u2500\u2500\u2500 KEYFRAME ACTIONS \u2500\u2500\u2500\n\n  addKeyframe: (clipId, property, keyframeData) => {\n    set((state) => {\n      const tracks = state.tracks.map((track) => {\n        if (track.locked) return track;\n        const exists = track.clips.some((c) => c.id === clipId);\n        if (!exists) return track;\n\n        return {\n          ...track,\n          clips: track.clips.map((c) => {\n            if (c.id === clipId) {\n              const keyframes = [...(c.keyframes || [])];\n              let track = keyframes.find((k) => k.property === property);\n              \n              const newKeyframe: Keyframe = {\n                ...keyframeData,\n                id: `kf_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`\n              };\n\n              if (!track) {\n                track = { property, keyframes: [newKeyframe] };\n                keyframes.push(track);\n              } else {\n                // Remove keyframe at same time if exists\n                track.keyframes = [\n                  ...track.keyframes.filter((k) => k.time !== keyframeData.time),\n                  newKeyframe\n                ].sort((a, b) => a.time - b.time);\n              }\n\n              return {\n                ...c,\n                keyframes\n              };\n            }\n            return c;\n          })\n        };\n      });\n\n      const newHistory = pushToHistory({ ...state, tracks }, `Add Keyframe for ${property}`);\n      return {\n        tracks,\n        history: newHistory,\n        historyIndex: newHistory.length - 1\n      };\n    });\n  },\n\n  updateKeyframe: (clipId, property, keyframeId, updates) => {\n    set((state) => {\n      const tracks = state.tracks.map((track) => {\n        if (track.locked) return track;\n        const exists = track.clips.some((c) => c.id === clipId);\n        if (!exists) return track;\n\n        return {\n          ...track,\n          clips: track.clips.map((c) => {\n            if (c.id === clipId) {\n              const keyframes = (c.keyframes || []).map((t) => {\n                if (t.property === property) {\n                  return {\n                    ...t,\n                    keyframes: t.keyframes.map((k) => \n                      k.id === keyframeId ? { ...k, ...updates } : k\n                    ).sort((a, b) => a.time - b.time)\n                  };\n                }\n                return t;\n              });\n\n              return {\n                ...c,\n                keyframes\n              };\n            }\n            return c;\n          })\n        };\n      });\n\n      const newHistory = pushToHistory({ ...state, tracks }, `Update Keyframe`);\n      return {\n        tracks,\n        history: newHistory,\n        historyIndex: newHistory.length - 1\n      };\n    });\n  },\n\n  removeKeyframe: (clipId, property, keyframeId) => {\n    set((state) => {\n      const tracks = state.tracks.map((track) => {\n        if (track.locked) return track;\n        const exists = track.clips.some((c) => c.id === clipId);\n        if (!exists) return track;\n\n        return {\n          ...track,\n          clips: track.clips.map((c) => {\n            if (c.id === clipId) {\n              const keyframes = (c.keyframes || []).map((t) => {\n                if (t.property === property) {\n                  return {\n                    ...t,\n                    keyframes: t.keyframes.filter((k) => k.id !== keyframeId)\n                  };\n                }\n                return t;\n              }).filter((t) => t.keyframes.length > 0); // remove empty tracks\n\n              return {\n                ...c,\n                keyframes\n              };\n            }\n            return c;\n          })\n        };\n      });\n\n      const newHistory = pushToHistory({ ...state, tracks }, `Remove Keyframe`);\n      return {\n        tracks,\n        history: newHistory,\n        historyIndex: newHistory.length - 1\n      };\n    });\n  },\n\n  loadProjectState: (projectData) => {\n    // Revoke old object URLs to prevent memory leaks\n    get().assets.forEach((a) => {\n      if (a.url && a.url.startsWith('blob:')) {\n        URL.revokeObjectURL(a.url);\n      }\n    });\n\n    const tracks = projectData.tracks ?? INITIAL_TRACKS;\n    const newSnapshot = {\n      tracks: JSON.parse(JSON.stringify(tracks)),\n      transitions: JSON.parse(JSON.stringify(projectData.transitions || [])),\n      description: 'Load Project'\n    };\n\n    const dims = dimensionsForAspect(projectData.aspectRatio);\n    set({\n      aspectRatio: projectData.aspectRatio,\n      canvasWidth: dims.width,\n      canvasHeight: dims.height,\n      tracks,\n      transitions: projectData.transitions || [],\n      assets: projectData.assets,\n      selectedClipIds: [],\n      playheadTime: 0,\n      history: [newSnapshot],\n      historyIndex: 0\n    });\n  },\n\n  importVideoProject: (projectData, fileName, opts) => {\n    const projectId = `vproj-${Date.now()}`;\n    const projectName = fileName.replace(/\\.(kaiv|wzrdv)$/i, '') || 'Proyecto importado';\n    const dims = dimensionsForAspect(projectData.aspectRatio);\n    const tracks = projectData.tracks ?? INITIAL_TRACKS;\n\n    const initialHistory = [{\n      tracks: JSON.parse(JSON.stringify(tracks)),\n      transitions: JSON.parse(JSON.stringify(projectData.transitions || [])),\n      description: 'Imported Project',\n    }];\n\n    const newProject: VideoProject = {\n      id: projectId,\n      name: projectName,\n      aspectRatio: projectData.aspectRatio,\n      canvasWidth: dims.width,\n      canvasHeight: dims.height,\n      backgroundColor: '#000000',\n      tracks,\n      assets: projectData.assets,\n      transitions: projectData.transitions || [],\n      projectDuration: 300,\n      playheadTime: 0,\n      zoom: 15,\n      history: initialHistory,\n      historyIndex: 0,\n      createdAt: Date.now(),\n      cloudEditableId: opts?.cloudEditableId,\n    };\n\n    set((state) => ({\n      videoProjects: [...state.videoProjects, newProject],\n      activeVideoProjectId: projectId,\n      tracks,\n      assets: projectData.assets,\n      transitions: projectData.transitions || [],\n      aspectRatio: projectData.aspectRatio,\n      canvasWidth: dims.width,\n      canvasHeight: dims.height,\n      projectDuration: 300,\n      playheadTime: 0,\n      zoom: 15,\n      selectedClipIds: [],\n      history: initialHistory,\n      historyIndex: 0,\n      isVideoSetupOpen: false,\n    }));\n  },\n}));\n\nvideoPersistence = createProjectPersistence({\n  mode: 'video',\n  localDebounceMs: 400,\n  cloudDebounceMs: 3000,\n  saveLocal: async () => {\n    await useVideoStore.getState().saveVideoProject();\n  },\n  saveCloud: async () => useVideoStore.getState().autoSaveVideoProjectToCloud(),\n});\nregisterProjectPersistence(videoPersistence);\n\nexport function flushVideoPersistence(): Promise<void> {\n  return videoPersistence.flush();\n}", "/**\n * Map AI design-preset / video-properties payloads onto video-editor Clip fields.\n * Fabric image filters (brightness, contrast, \u2026) become colorGrading updates.\n */\n\nimport {\n  normalizeSubtitleStylePreset,\n  type ColorGradingPreset,\n} from '../services/textService';\nimport {\n  DEFAULT_COLOR_GRADING,\n  type Clip,\n  type ColorGradingSettings,\n} from '../store/useVideoStore';\n\nconst COLOR_GRADING_KEYS: (keyof ColorGradingPreset)[] = [\n  'exposure',\n  'contrast',\n  'highlights',\n  'shadows',\n  'whites',\n  'blacks',\n  'temperature',\n  'tint',\n  'vibrance',\n  'saturation',\n  'hue',\n  'vignetteEnabled',\n  'vignetteAmount',\n];\n\n/** Keep only known color-grading fields from a backend / flat payload. */\nexport function pickColorGradingPreset(raw: unknown): ColorGradingPreset {\n  const flat = flattenAiPresetPayload(raw);\n  const out: ColorGradingPreset = {};\n  for (const key of COLOR_GRADING_KEYS) {\n    const n = pickNum(flat, [key]);\n    if (n !== undefined) {\n      (out as Record<string, number | boolean>)[key] = n;\n      continue;\n    }\n    if (key === 'vignetteEnabled') {\n      const b = pickBool(flat, ['vignetteEnabled', 'vignette', 'vignette_enabled']);\n      if (b !== undefined) out.vignetteEnabled = b;\n    }\n  }\n  return out;\n}\n\n/**\n * Map creative Spanish/English look prompts onto ColorGradingSettings when\n * `/api/ai/color-grading-preset` is missing on the host BFF.\n */\nexport function inferColorGradingFromProse(text: string): ColorGradingPreset {\n  const t = text.toLowerCase();\n  const preset: ColorGradingPreset = {};\n\n  if (/warm|c[a\u00E1]lido|golden|dorado|sunset|atardecer|naranja|orange|\u00E1mbar|ambar/.test(t)) {\n    preset.temperature = 45;\n    preset.tint = 8;\n    preset.vibrance = 12;\n  }\n  if (/cool|fr[i\u00ED]o|azul|blue|cold|cian|cyan|hielo|ice/.test(t)) {\n    preset.temperature = -40;\n    preset.tint = -8;\n  }\n  if (/noir|b\\s*&\\s*w|black\\s*and\\s*white|blanco\\s*y\\s*negro|grayscale|greyscale|desatur/.test(t)) {\n    preset.saturation = -100;\n    preset.contrast = 35;\n    preset.vignetteEnabled = true;\n    preset.vignetteAmount = 40;\n  }\n  if (/cinem|film\\b|pel[i\u00ED]cula|movie/.test(t)) {\n    preset.contrast = Math.max(preset.contrast ?? 0, 18);\n    preset.saturation = preset.saturation ?? -12;\n    preset.shadows = 12;\n    preset.highlights = -10;\n    preset.vignetteEnabled = true;\n    preset.vignetteAmount = Math.max(preset.vignetteAmount ?? 0, 22);\n  }\n  if (/vintage|retro|sepia|anal[o\u00F3]gic|analogue|analog/.test(t)) {\n    preset.temperature = Math.max(preset.temperature ?? 0, 28);\n    preset.saturation = preset.saturation ?? -22;\n    preset.contrast = Math.max(preset.contrast ?? 0, 8);\n    preset.vignetteEnabled = true;\n    preset.vignetteAmount = Math.max(preset.vignetteAmount ?? 0, 32);\n  }\n  if (/high\\s*contrast|alto\\s*contraste|contraste\\s*alto/.test(t)) {\n    preset.contrast = 45;\n  }\n  if (/soft|suave|pastel|dreamy|suaviz/.test(t)) {\n    preset.contrast = -15;\n    preset.highlights = -18;\n    preset.shadows = 18;\n    preset.saturation = Math.max(preset.saturation ?? 0, 8);\n  }\n  if (/vibrant|vibrante|saturad|pop\\b|vivid/.test(t)) {\n    preset.vibrance = 40;\n    preset.saturation = Math.max(preset.saturation ?? 0, 22);\n  }\n  if (/dark|oscuro|moody|sombr[i\u00ED]o|gloom/.test(t)) {\n    preset.exposure = -0.55;\n    preset.shadows = -18;\n    preset.blacks = -12;\n  }\n  if (/bright|brillante|luminoso|claro|airy/.test(t)) {\n    preset.exposure = 0.45;\n    preset.highlights = 12;\n  }\n  if (/vignette|vi[n\u00F1]eta/.test(t)) {\n    preset.vignetteEnabled = true;\n    preset.vignetteAmount = Math.max(preset.vignetteAmount ?? 0, 35);\n  }\n\n  return preset;\n}\n\n/** Prefer structured preset fields; if empty, infer from prose / thought process. */\nexport function normalizeColorGradingPreset(\n  raw: unknown,\n  thoughtProcess?: string,\n): ColorGradingPreset {\n  const picked = pickColorGradingPreset(raw);\n  if (Object.keys(picked).length > 0) return picked;\n\n  const proseBits: string[] = [];\n  if (thoughtProcess?.trim()) proseBits.push(thoughtProcess);\n  const root = asRecord(raw);\n  if (root) {\n    for (const key of ['creative_style', 'creativeStyle', 'description', 'content', 'summary', 'text', 'message', 'prompt']) {\n      if (typeof root[key] === 'string') proseBits.push(root[key] as string);\n    }\n  }\n  return inferColorGradingFromProse(proseBits.join('\\n'));\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n  if (value && typeof value === 'object' && !Array.isArray(value)) {\n    return value as Record<string, unknown>;\n  }\n  return null;\n}\n\nfunction tryParseJsonObject(value: unknown): Record<string, unknown> | null {\n  const direct = asRecord(value);\n  if (direct) return direct;\n  if (typeof value !== 'string') return null;\n  const trimmed = value.trim();\n  if (!trimmed) return null;\n  const fence = trimmed.match(/```(?:json)?\\s*([\\s\\S]*?)```/i);\n  const candidate = (fence?.[1] ?? trimmed).trim();\n  const first = candidate.indexOf('{');\n  const last = candidate.lastIndexOf('}');\n  if (first < 0 || last <= first) return null;\n  try {\n    const parsed: unknown = JSON.parse(candidate.slice(first, last + 1));\n    return asRecord(parsed);\n  } catch {\n    return null;\n  }\n}\n\nfunction unwrapLeaf(value: unknown): unknown {\n  if (value === null || value === undefined) return undefined;\n  const rec = asRecord(value);\n  if (!rec) return value;\n  if ('value' in rec) return rec.value;\n  if ('Value' in rec) return rec.Value;\n  if ('amount' in rec) return rec.amount;\n  if ('Amount' in rec) return rec.Amount;\n  return value;\n}\n\nfunction num(value: unknown): number | undefined {\n  const leaf = unwrapLeaf(value);\n  if (typeof leaf === 'number' && Number.isFinite(leaf)) return leaf;\n  if (typeof leaf !== 'string') return undefined;\n  const raw = leaf.trim().toLowerCase().replace(',', '.');\n  if (!raw) return undefined;\n  // \"2x\", \"1.5\u00D7\"\n  const mul = raw.match(/^(\\d+(?:\\.\\d+)?)\\s*[x\u00D7]$/);\n  if (mul) {\n    const n = Number(mul[1]);\n    return Number.isFinite(n) ? n : undefined;\n  }\n  // \"50%\"\n  const pct = raw.match(/^(\\d+(?:\\.\\d+)?)\\s*%$/);\n  if (pct) {\n    const n = Number(pct[1]);\n    return Number.isFinite(n) ? n : undefined;\n  }\n  const cleaned = raw.replace(/[^0-9.\\-]/g, '');\n  if (!cleaned || cleaned === '-' || cleaned === '.') return undefined;\n  const n = Number(cleaned);\n  return Number.isFinite(n) ? n : undefined;\n}\n\nfunction bool(value: unknown): boolean | undefined {\n  const leaf = unwrapLeaf(value);\n  if (typeof leaf === 'boolean') return leaf;\n  if (typeof leaf === 'string') {\n    const v = leaf.trim().toLowerCase();\n    if (v === 'true' || v === '1' || v === 'yes' || v === 'on' || v === 'muted') return true;\n    if (v === 'false' || v === '0' || v === 'no' || v === 'off' || v === 'unmuted') return false;\n  }\n  if (typeof leaf === 'number') return leaf !== 0;\n  return undefined;\n}\n\n/** Pick first defined number under any of the alias keys (case-insensitive). */\nfunction pickNum(source: Record<string, unknown>, aliases: string[]): number | undefined {\n  const lowerMap = new Map<string, unknown>();\n  for (const [k, v] of Object.entries(source)) {\n    lowerMap.set(k.toLowerCase().replace(/[^a-z0-9]/g, ''), v);\n  }\n  for (const alias of aliases) {\n    const key = alias.toLowerCase().replace(/[^a-z0-9]/g, '');\n    if (lowerMap.has(key)) {\n      const n = num(lowerMap.get(key));\n      if (n !== undefined) return n;\n    }\n  }\n  return undefined;\n}\n\nfunction pickBool(source: Record<string, unknown>, aliases: string[]): boolean | undefined {\n  const lowerMap = new Map<string, unknown>();\n  for (const [k, v] of Object.entries(source)) {\n    lowerMap.set(k.toLowerCase().replace(/[^a-z0-9]/g, ''), v);\n  }\n  for (const alias of aliases) {\n    const key = alias.toLowerCase().replace(/[^a-z0-9]/g, '');\n    if (lowerMap.has(key)) {\n      const b = bool(lowerMap.get(key));\n      if (b !== undefined) return b;\n    }\n  }\n  return undefined;\n}\n\n/**\n * Flatten nested design/properties payloads (filters, result, preset, JSON strings\u2026).\n */\nexport function flattenAiPresetPayload(raw: unknown): Record<string, unknown> {\n  const root = tryParseJsonObject(raw) ?? asRecord(raw) ?? {};\n  const layers: Record<string, unknown>[] = [root];\n  const queue = [root];\n\n  const wrapperKeys = new Set([\n    'filters',\n    'preset',\n    'style',\n    'result',\n    'data',\n    'properties',\n    'settings',\n    'colorgrading',\n    'color_grading',\n    'clipproperties',\n    'clip_properties',\n    'videoproperties',\n    'video_properties',\n    'changes',\n    'updates',\n    'params',\n    'parameters',\n    'payload',\n    'content',\n    'creative_style',\n    'creativestyle',\n    'description',\n    'clip',\n    'response',\n    'output',\n    'answer',\n  ]);\n\n  while (queue.length > 0) {\n    const current = queue.shift()!;\n    for (const [key, value] of Object.entries(current)) {\n      if (key.startsWith('__')) continue;\n      const nested = tryParseJsonObject(value);\n      if (!nested) continue;\n      const normKey = key.toLowerCase().replace(/[^a-z0-9_]/g, '');\n      if (wrapperKeys.has(normKey) || wrapperKeys.has(key.toLowerCase())) {\n        layers.push(nested);\n        queue.push(nested);\n      }\n    }\n  }\n\n  const flat: Record<string, unknown> = {};\n  for (const layer of layers) {\n    for (const [k, v] of Object.entries(layer)) {\n      if (k.startsWith('__')) continue;\n      const leaf = unwrapLeaf(v);\n      if (asRecord(leaf) || Array.isArray(leaf)) continue;\n      flat[k] = leaf;\n    }\n  }\n\n  const arrayWrapperKeys = new Set([\n    'properties',\n    'changes',\n    'updates',\n    'params',\n    'parameters',\n    'items',\n    'fields',\n  ]);\n  for (const layer of layers) {\n    for (const [k, v] of Object.entries(layer)) {\n      if (!Array.isArray(v)) continue;\n      const normKey = k.toLowerCase().replace(/[^a-z0-9_]/g, '');\n      if (!arrayWrapperKeys.has(normKey)) continue;\n      for (const item of v) {\n        const rec = asRecord(item);\n        if (!rec) continue;\n        const nameRaw =\n          rec.name ??\n          rec.property ??\n          rec.key ??\n          rec.field ??\n          rec.param ??\n          rec.Property ??\n          rec.Name;\n        if (typeof nameRaw !== 'string' && typeof nameRaw !== 'number') continue;\n        const propName = String(nameRaw).trim();\n        if (!propName) continue;\n        const propVal =\n          rec.value ??\n          rec.Value ??\n          rec.amount ??\n          rec.Amount ??\n          rec.val ??\n          rec.data;\n        if (propVal !== undefined) flat[propName] = propVal;\n      }\n    }\n  }\n\n  return flat;\n}\n\nfunction normalizeUnitInterval(n: number): number {\n  // 50 \u2192 0.5 (percent); 0.5 stays 0.5\n  const v = Math.abs(n) > 1.5 ? n / 100 : n;\n  return Math.max(0, Math.min(1, v));\n}\n\nfunction pickRaw(flat: Record<string, unknown>, aliases: string[]): unknown {\n  const lowerMap = new Map<string, unknown>();\n  for (const [k, v] of Object.entries(flat)) {\n    lowerMap.set(k.toLowerCase().replace(/[^a-z0-9]/g, ''), v);\n  }\n  for (const alias of aliases) {\n    const key = alias.toLowerCase().replace(/[^a-z0-9]/g, '');\n    if (lowerMap.has(key)) return lowerMap.get(key);\n  }\n  return undefined;\n}\n\n/** .NET may return enum strings like video_speed: \"slow\" instead of numeric speed. */\nconst SPEED_TOKEN_MAP: Record<string, number> = {\n  slow: 0.75,\n  slower: 0.5,\n  very_slow: 0.5,\n  veryslow: 0.5,\n  half: 0.5,\n  fast: 1.5,\n  faster: 1.75,\n  very_fast: 2,\n  veryfast: 2,\n  double: 2,\n  normal: 1,\n  default: 1,\n  regular: 1,\n  lento: 0.75,\n  lentamente: 0.75,\n  muy_lento: 0.5,\n  muylento: 0.5,\n  rapido: 1.5,\n  r\u00E1pido: 1.5,\n  muy_rapido: 2,\n  muyrapido: 2,\n};\n\nconst OPACITY_TOKEN_MAP: Record<string, number> = {\n  low: 0.35,\n  medium: 0.65,\n  high: 0.9,\n  full: 1,\n  opaque: 1,\n  transparent: 0.25,\n  semi_transparent: 0.5,\n  semitransparent: 0.5,\n  bajo: 0.35,\n  medio: 0.65,\n  alto: 0.9,\n  opaco: 1,\n  transparente: 0.25,\n};\n\nconst VOLUME_TOKEN_MAP: Record<string, number> = {\n  low: 0.35,\n  medium: 0.65,\n  high: 1,\n  quiet: 0.35,\n  loud: 1,\n  mute: 0,\n  muted: 0,\n  silent: 0,\n  bajo: 0.35,\n  medio: 0.65,\n  alto: 1,\n  silencio: 0,\n};\n\nfunction parseTokenMap(value: unknown, map: Record<string, number>): number | undefined {\n  if (typeof value !== 'string') return undefined;\n  const key = value.trim().toLowerCase().replace(/[\\s-]+/g, '_');\n  if (key in map) return map[key];\n  return undefined;\n}\n\nfunction parseSpeedValue(value: unknown): number | undefined {\n  const n = num(value);\n  if (n !== undefined && n > 0) return Math.max(0.1, Math.min(8, n));\n  return parseTokenMap(value, SPEED_TOKEN_MAP);\n}\n\nfunction parseOpacityValue(value: unknown): number | undefined {\n  const n = num(value);\n  if (n !== undefined) return normalizeUnitInterval(n);\n  return parseTokenMap(value, OPACITY_TOKEN_MAP);\n}\n\nfunction parseVolumeValue(value: unknown): number | undefined {\n  const n = num(value);\n  if (n !== undefined) return normalizeUnitInterval(n);\n  return parseTokenMap(value, VOLUME_TOKEN_MAP);\n}\n\nconst SPEED_ALIASES = [\n  'speed',\n  'videospeed',\n  'video_speed',\n  'playbackrate',\n  'playback_rate',\n  'playbackspeed',\n  'playback_speed',\n  'rate',\n  'tempo',\n  'speedmultiplier',\n  'speed_multiplier',\n  'speedfactor',\n  'speed_factor',\n];\n\nconst OPACITY_ALIASES = [\n  'opacity',\n  'alpha',\n  'opacityvalue',\n  'opacity_value',\n  'opacitypercent',\n  'opacity_percent',\n  'videoopacity',\n  'video_opacity',\n];\n\nconst VOLUME_ALIASES = [\n  'volume',\n  'gain',\n  'audiolevel',\n  'audio_level',\n  'volumelevel',\n  'volume_level',\n  'volumepercent',\n  'volume_percent',\n  'videovolume',\n  'video_volume',\n];\n\nfunction patchFromFlat(flat: Record<string, unknown>): Partial<Clip> {\n  const patch: Partial<Clip> = {};\n\n  const opacityRaw = pickRaw(flat, OPACITY_ALIASES);\n  const opacity = opacityRaw !== undefined ? parseOpacityValue(opacityRaw) : pickNum(flat, OPACITY_ALIASES);\n  if (opacity !== undefined) {\n    patch.opacity = opacity;\n  } else {\n    const transparencyRaw = pickRaw(flat, ['transparency', 'transparent']);\n    const transparency =\n      transparencyRaw !== undefined\n        ? parseOpacityValue(transparencyRaw)\n        : pickNum(flat, ['transparency', 'transparent']);\n    if (transparency !== undefined) {\n      patch.opacity = Math.max(0, Math.min(1, 1 - transparency));\n    }\n  }\n\n  const volumeRaw = pickRaw(flat, VOLUME_ALIASES);\n  const volume = volumeRaw !== undefined ? parseVolumeValue(volumeRaw) : pickNum(flat, VOLUME_ALIASES);\n  if (volume !== undefined) {\n    patch.volume = volume;\n  }\n\n  const speedRaw = pickRaw(flat, SPEED_ALIASES);\n  const speed = speedRaw !== undefined ? parseSpeedValue(speedRaw) : pickNum(flat, SPEED_ALIASES);\n  if (speed !== undefined && speed > 0) {\n    patch.speed = speed;\n  }\n\n  const muted = pickBool(flat, [\n    'muted',\n    'mute',\n    'silent',\n    'silence',\n    'ismuted',\n    'is_muted',\n    'audiomuted',\n    'audio_muted',\n    'video_muted',\n    'videomuted',\n  ]);\n  if (muted !== undefined) patch.muted = muted;\n\n  const x = pickNum(flat, ['x', 'posX', 'positionX', 'pos_x']);\n  if (x !== undefined) patch.x = x;\n  const y = pickNum(flat, ['y', 'posY', 'positionY', 'pos_y']);\n  if (y !== undefined) patch.y = y;\n\n  const scale = pickNum(flat, ['scale', 'scaleX', 'scale_x']);\n  if (scale !== undefined) {\n    patch.scaleX = scale;\n    patch.scaleY = pickNum(flat, ['scaleY', 'scale_y']) ?? scale;\n  } else {\n    const scaleY = pickNum(flat, ['scaleY', 'scale_y']);\n    if (scaleY !== undefined) patch.scaleY = scaleY;\n  }\n\n  const rotation = pickNum(flat, ['rotation', 'angle', 'rotate']);\n  if (rotation !== undefined) patch.rotation = rotation;\n\n  const flipX = pickBool(flat, ['flipX', 'flip_x', 'mirrorX', 'mirror_x']);\n  if (flipX !== undefined) patch.flipX = flipX;\n  const flipY = pickBool(flat, ['flipY', 'flip_y', 'mirrorY', 'mirror_y']);\n  if (flipY !== undefined) patch.flipY = flipY;\n\n  return patch;\n}\n\nfunction collectVideoPropertySources(raw: unknown): Record<string, unknown>[] {\n  const sources: Record<string, unknown>[] = [];\n  const root = tryParseJsonObject(raw) ?? asRecord(raw);\n  if (root) sources.push(root);\n\n  for (const candidate of [...sources]) {\n    for (const key of [\n      'preset',\n      'properties',\n      'settings',\n      'data',\n      'result',\n      'clip',\n      'clip_properties',\n      'clipProperties',\n      'video_properties',\n      'videoProperties',\n      'creative_style',\n      'creativeStyle',\n      'response',\n      'output',\n      'content',\n      'payload',\n    ]) {\n      if (!(key in candidate)) continue;\n      const nested = tryParseJsonObject(candidate[key]);\n      if (nested) sources.push(nested);\n    }\n  }\n\n  return sources;\n}\n\n/** Infer opacity/speed/volume/mute from Spanish/English prose when .NET returns creative_style. */\nfunction inferVideoPropertiesFromProse(\n  text: string,\n): Partial<Pick<Clip, 'opacity' | 'volume' | 'speed' | 'muted'>> {\n  const t = text.toLowerCase();\n  const patch: Partial<Pick<Clip, 'opacity' | 'volume' | 'speed' | 'muted'>> = {};\n\n  const speedX = t.match(/(\\d+(?:[.,]\\d+)?)\\s*[x\u00D7]/);\n  if (speedX) {\n    const n = Number(speedX[1]!.replace(',', '.'));\n    if (Number.isFinite(n) && n > 0) patch.speed = Math.max(0.1, Math.min(8, n));\n  } else if (/double\\s+speed|twice\\s+as\\s+fast|doble\\s+velocidad|el\\s+doble/.test(t)) {\n    patch.speed = 2;\n  } else if (/half\\s+speed|mitad\\s+de\\s+velocidad|a\\s+mitad/.test(t)) {\n    patch.speed = 0.5;\n  } else if (/faster|m[a\u00E1]s\\s+r[a\u00E1]pido|aceler/.test(t)) {\n    patch.speed = 1.5;\n  } else if (/\\bslow\\b|\\bslower\\b|m[a\u00E1]s\\s+lento|ralent/.test(t)) {\n    patch.speed = 0.75;\n  } else if (/\\bfast\\b/.test(t)) {\n    patch.speed = 1.5;\n  }\n\n  const opacityPct =\n    t.match(/(\\d+(?:[.,]\\d+)?)\\s*%\\s*(?:de\\s+)?(?:opacidad|opacity|transparent)/) ||\n    t.match(/(?:opacidad|opacity|transparent[ea]*)\\s*(?:de|of|:)?\\s*(\\d+(?:[.,]\\d+)?)\\s*%/);\n  if (opacityPct) {\n    const n = Number(opacityPct[1]!.replace(',', '.'));\n    if (Number.isFinite(n)) patch.opacity = Math.max(0, Math.min(1, n / 100));\n  } else {\n    const opacityFrac = t.match(\n      /(?:opacidad|opacity)\\s*(?:de|of|:)?\\s*(0?\\.\\d+|\\d+(?:[.,]\\d+)?)/,\n    );\n    if (opacityFrac) {\n      let n = Number(opacityFrac[1]!.replace(',', '.'));\n      if (Number.isFinite(n)) {\n        if (n > 1.5) n = n / 100;\n        patch.opacity = Math.max(0, Math.min(1, n));\n      }\n    } else if (/semi[-\\s]?transparent|medio\\s+transparent|un\\s+poco\\s+transparent/.test(t)) {\n      patch.opacity = 0.5;\n    } else if (/m[a\u00E1]s\\s+transparent|more\\s+transparent|fade\\s+out/.test(t)) {\n      patch.opacity = 0.35;\n    } else if (/fully\\s+opaque|opaco|sin\\s+transparent/.test(t)) {\n      patch.opacity = 1;\n    }\n  }\n\n  if (/mute[d]?|silenci|sin\\s+audio|no\\s+sound|quiet/.test(t)) {\n    patch.muted = true;\n  } else if (/unmute|con\\s+audio|activar\\s+audio/.test(t)) {\n    patch.muted = false;\n  }\n\n  const volPct = t.match(/(?:volume|volumen)\\s*(?:to|a|de|:)?\\s*(\\d+(?:[.,]\\d+)?)\\s*%/);\n  if (volPct) {\n    const n = Number(volPct[1]!.replace(',', '.'));\n    if (Number.isFinite(n)) patch.volume = Math.max(0, Math.min(1, n / 100));\n  } else if (/quieter|m[a\u00E1]s\\s+bajo|bajar\\s+volumen|lower\\s+volume/.test(t)) {\n    patch.volume = 0.4;\n  } else if (/louder|m[a\u00E1]s\\s+alto|subir\\s+volumen|raise\\s+volume/.test(t)) {\n    patch.volume = 1;\n  }\n\n  return patch;\n}\n\n/** Scale Fabric-like -1..1 values into color-grading ranges. */\nfunction toGradingUnit(value: number, fabricMaxAbs: number, gradingMaxAbs: number): number {\n  if (Math.abs(value) <= fabricMaxAbs + 1e-6) {\n    return (value / fabricMaxAbs) * gradingMaxAbs;\n  }\n  return value;\n}\n\nexport function mapDesignPresetToClipPatch(\n  raw: unknown,\n  clip: Clip,\n): Partial<Clip> {\n  const flat = flattenAiPresetPayload(raw);\n\n  if (clip.type === 'text' || clip.type === 'subtitle') {\n    return normalizeSubtitleStylePreset(raw);\n  }\n\n  const grading: ColorGradingSettings = {\n    ...(clip.colorGrading ?? DEFAULT_COLOR_GRADING),\n  };\n  let gradingTouched = false;\n\n  const setGrading = (key: keyof ColorGradingSettings, value: number | undefined) => {\n    if (value === undefined) return;\n    (grading as Record<string, unknown>)[key] = value;\n    gradingTouched = true;\n  };\n\n  setGrading(\n    'exposure',\n    (() => {\n      const exposure = pickNum(flat, ['exposure']);\n      if (exposure !== undefined) return toGradingUnit(exposure, 1, 2);\n      const brightness = pickNum(flat, ['brightness']);\n      if (brightness !== undefined) return toGradingUnit(brightness, 1, 2);\n      return undefined;\n    })(),\n  );\n  setGrading(\n    'contrast',\n    (() => {\n      const c = pickNum(flat, ['contrast']);\n      return c === undefined ? undefined : toGradingUnit(c, 1, 100);\n    })(),\n  );\n  setGrading(\n    'saturation',\n    (() => {\n      const s = pickNum(flat, ['saturation']);\n      return s === undefined ? undefined : toGradingUnit(s, 1, 100);\n    })(),\n  );\n  setGrading(\n    'vibrance',\n    (() => {\n      const v = pickNum(flat, ['vibrance']);\n      return v === undefined ? undefined : toGradingUnit(v, 1, 100);\n    })(),\n  );\n  setGrading(\n    'temperature',\n    (() => {\n      const t = pickNum(flat, ['temperature', 'temp', 'warmth']);\n      return t === undefined ? undefined : toGradingUnit(t, 1, 100);\n    })(),\n  );\n  setGrading(\n    'tint',\n    (() => {\n      const t = pickNum(flat, ['tint']);\n      return t === undefined ? undefined : toGradingUnit(t, 1, 100);\n    })(),\n  );\n  setGrading(\n    'hue',\n    (() => {\n      const h = pickNum(flat, ['hue']);\n      return h === undefined ? undefined : toGradingUnit(h, 1, 180);\n    })(),\n  );\n  setGrading(\n    'blur',\n    (() => {\n      const b = pickNum(flat, ['blur']);\n      return b === undefined ? undefined : toGradingUnit(b, 1, 100);\n    })(),\n  );\n  setGrading('highlights', pickNum(flat, ['highlights']));\n  setGrading('shadows', pickNum(flat, ['shadows']));\n  setGrading('whites', pickNum(flat, ['whites']));\n  setGrading('blacks', pickNum(flat, ['blacks']));\n\n  const grayscale = pickBool(flat, ['grayscale', 'greyscale']);\n  if (grayscale) {\n    grading.saturation = -100;\n    gradingTouched = true;\n  }\n  const sepia = pickBool(flat, ['sepia']);\n  if (sepia) {\n    grading.temperature = Math.max(grading.temperature, 35);\n    grading.saturation = Math.min(grading.saturation, -20);\n    gradingTouched = true;\n  }\n\n  const patch: Partial<Clip> = {};\n  if (gradingTouched) patch.colorGrading = grading;\n\n  const opacity = pickNum(flat, ['opacity']);\n  if (opacity !== undefined) {\n    patch.opacity = Math.abs(opacity) <= 1 ? opacity : opacity / 100;\n  }\n  const scale = pickNum(flat, ['scale', 'scaleX']);\n  if (scale !== undefined) {\n    patch.scaleX = scale;\n    patch.scaleY = pickNum(flat, ['scaleY']) ?? scale;\n  }\n  const rotation = pickNum(flat, ['rotation', 'angle']);\n  if (rotation !== undefined) patch.rotation = rotation;\n\n  return patch;\n}\n\nexport function normalizeVideoPropertiesPreset(\n  raw: unknown,\n  thoughtProcess?: string,\n): Partial<Clip> {\n  const flat = flattenAiPresetPayload(raw);\n  let patch = patchFromFlat(flat);\n\n  if (Object.keys(patch).length === 0) {\n    for (const source of collectVideoPropertySources(raw)) {\n      const nestedPatch = patchFromFlat(flattenAiPresetPayload(source));\n      patch = { ...patch, ...nestedPatch };\n      if (Object.keys(patch).length >= 4) break;\n    }\n  }\n\n  // Nested patch object from schemaVersion plans (ignore ops here \u2014 parseVideoEditPlan owns that)\n  const root = asRecord(raw);\n  if (root?.patch && typeof root.patch === 'object') {\n    patch = { ...patch, ...patchFromFlat(flattenAiPresetPayload(root.patch)) };\n  }\n\n  const grading = pickColorGradingPreset(raw);\n  if (Object.keys(grading).length > 0) {\n    patch.colorGrading = {\n      ...(patch.colorGrading ?? DEFAULT_COLOR_GRADING),\n      ...grading,\n    } as ColorGradingSettings;\n  }\n\n  if (Object.keys(patch).length === 0) {\n    for (const v of Object.values(flat)) {\n      if (typeof v === 'string' && v.trim()) {\n        Object.assign(patch, inferVideoPropertiesFromProse(v));\n        if (Object.keys(patch).length > 0) break;\n      }\n    }\n  }\n\n  if (Object.keys(patch).length === 0) {\n    const proseBits: string[] = [];\n    if (thoughtProcess?.trim()) proseBits.push(thoughtProcess);\n    for (const v of Object.values(flat)) {\n      if (typeof v === 'string' && v.trim()) proseBits.push(v);\n    }\n    for (const source of collectVideoPropertySources(raw)) {\n      for (const v of Object.values(source)) {\n        if (typeof v === 'string' && v.trim()) proseBits.push(v);\n      }\n    }\n    if (root) {\n      for (const key of [\n        'creative_style',\n        'creativeStyle',\n        'description',\n        'content',\n        'summary',\n        'text',\n        'message',\n        'response',\n        'output',\n      ]) {\n        if (typeof root[key] === 'string') proseBits.push(root[key] as string);\n      }\n    }\n    Object.assign(patch, inferVideoPropertiesFromProse(proseBits.join('\\n')));\n  }\n\n  return patch;\n}\n", "/**\n * Apply expanded `/api/ai/video-properties` responses (ticket schemaVersion + ops).\n * Unknown ops are skipped with a console warning (forward compatible).\n */\n\nimport {\n  useVideoStore,\n  type Clip,\n  type ColorGradingSettings,\n  type EasingType,\n  type EffectType,\n  type TransitionType,\n} from '../store/useVideoStore';\n\nexport type VideoEditorProjectSnapshot = {\n  aspectRatio?: string;\n  playheadTime?: number;\n  selectedClipIds?: string[];\n  clips?: Array<{\n    id: string;\n    type: string;\n    trackId: string;\n    startTime: number;\n    duration: number;\n    speed: number;\n    opacity: number;\n    volume: number;\n    muted: boolean;\n    trimIn: number;\n    trimOut: number;\n  }>;\n  tracks?: Array<{ id: string; type: string; name: string }>;\n  transitions?: Array<{\n    id: string;\n    type: string;\n    fromClipId: string;\n    toClipId: string;\n    duration: number;\n  }>;\n};\n\nexport type VideoEditOp = {\n  op: string;\n  clipId?: string;\n  patch?: Partial<Clip> & Record<string, unknown>;\n  grading?: Partial<ColorGradingSettings> & Record<string, unknown>;\n  effectType?: string;\n  effectId?: string;\n  params?: Record<string, unknown>;\n  fromClipId?: string;\n  toClipId?: string;\n  type?: string;\n  duration?: number;\n  property?: string;\n  keyframe?: { time: number; value: number; easing?: string };\n  text?: string;\n  trackId?: string;\n  startTime?: number;\n  name?: string;\n  [key: string]: unknown;\n};\n\nexport type VideoEditPlan = {\n  schemaVersion?: number;\n  summary?: string;\n  ops?: VideoEditOp[];\n  /** Flat legacy / Phase A fields applied to the selected clip when `ops` is empty. */\n  patch?: Partial<Clip>;\n  grading?: Partial<ColorGradingSettings>;\n};\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n  if (value && typeof value === 'object' && !Array.isArray(value)) {\n    return value as Record<string, unknown>;\n  }\n  return null;\n}\n\n/** Compact snapshot for VideoPropertiesRequestDto.projectSnapshot. */\nexport function buildVideoProjectSnapshot(): VideoEditorProjectSnapshot {\n  const state = useVideoStore.getState();\n  const clips: NonNullable<VideoEditorProjectSnapshot['clips']> = [];\n  for (const track of state.tracks) {\n    for (const clip of track.clips) {\n      clips.push({\n        id: clip.id,\n        type: clip.type,\n        trackId: clip.trackId,\n        startTime: clip.startTime,\n        duration: clip.duration,\n        speed: clip.speed ?? 1,\n        opacity: clip.opacity ?? 1,\n        volume: clip.volume ?? 1,\n        muted: !!clip.muted,\n        trimIn: clip.trimIn ?? 0,\n        trimOut: clip.trimOut ?? 0,\n      });\n    }\n  }\n  return {\n    aspectRatio: state.aspectRatio,\n    playheadTime: state.playheadTime,\n    selectedClipIds: [...state.selectedClipIds],\n    clips,\n    tracks: state.tracks.map((t) => ({ id: t.id, type: t.type, name: t.name })),\n    transitions: state.transitions.map((t) => ({\n      id: t.id,\n      type: t.type,\n      fromClipId: t.fromClipId,\n      toClipId: t.toClipId,\n      duration: t.duration,\n    })),\n  };\n}\n\nfunction resolveClipIds(\n  ref: string | undefined,\n  selectedClipIds: string[],\n): string[] {\n  if (!ref || ref === '$selected') {\n    return selectedClipIds.length > 0 ? [selectedClipIds[0]!] : [];\n  }\n  if (ref === '$selectedAll') return [...selectedClipIds];\n  return [ref];\n}\n\nconst CLIP_PATCH_KEYS = new Set<string>([\n  'startTime',\n  'duration',\n  'trimIn',\n  'trimOut',\n  'speed',\n  'volume',\n  'opacity',\n  'muted',\n  'name',\n  'x',\n  'y',\n  'scaleX',\n  'scaleY',\n  'rotation',\n  'flipX',\n  'flipY',\n  'fitMode',\n  'blendMode',\n  'borderRadius',\n  'cropEnabled',\n  'cropX',\n  'cropY',\n  'cropWidth',\n  'cropHeight',\n  'maskShape',\n  'maskFeather',\n  'text',\n  'fontFamily',\n  'fontWeight',\n  'fontSize',\n  'fontStyle',\n  'letterSpacing',\n  'lineHeight',\n  'textAlign',\n  'textTransform',\n  'underlineEnabled',\n  'fillType',\n  'fillColor',\n  'gradientColors',\n  'gradientAngle',\n  'strokeEnabled',\n  'strokeColor',\n  'strokeWidth',\n  'strokePosition',\n  'shadowEnabled',\n  'shadowColor',\n  'shadowBlur',\n  'shadowOffsetX',\n  'shadowOffsetY',\n  'shadowOpacity',\n  'backgroundEnabled',\n  'backgroundColor',\n  'backgroundOpacity',\n  'backgroundPadding',\n  'backgroundBorderRadius',\n  'backgroundBorderColor',\n  'backgroundBorderWidth',\n  'animationIn',\n  'animationOut',\n  'animationInDuration',\n  'animationOutDuration',\n]);\n\nfunction pickClipPatch(raw: Record<string, unknown> | null | undefined): Partial<Clip> {\n  if (!raw) return {};\n  const out: Partial<Clip> = {};\n  for (const key of CLIP_PATCH_KEYS) {\n    if (key in raw && raw[key] !== undefined) {\n      (out as Record<string, unknown>)[key] = raw[key];\n    }\n  }\n  // Nested colorGrading inside patch\n  if (raw.colorGrading && typeof raw.colorGrading === 'object') {\n    out.colorGrading = raw.colorGrading as ColorGradingSettings;\n  }\n  return out;\n}\n\n/**\n * Detect `ops` / `schemaVersion` plan, or fall back to a flat clip patch.\n */\nexport function parseVideoEditPlan(\n  raw: unknown,\n  flatPatch: Partial<Clip>,\n  grading?: Partial<ColorGradingSettings>,\n): VideoEditPlan {\n  const root = asRecord(raw) ?? {};\n  const summary =\n    typeof root.summary === 'string'\n      ? root.summary\n      : typeof root.message === 'string'\n        ? root.message\n        : undefined;\n\n  let ops: VideoEditOp[] | undefined;\n  if (Array.isArray(root.ops)) {\n    ops = root.ops\n      .map((item) => asRecord(item))\n      .filter((item): item is Record<string, unknown> => !!item)\n      .map((item) => ({ ...(item as VideoEditOp), op: String(item.op ?? '') }));\n  }\n\n  const schemaVersion =\n    typeof root.schemaVersion === 'number'\n      ? root.schemaVersion\n      : typeof root.schema_version === 'number'\n        ? root.schema_version\n        : undefined;\n\n  const nestedPatch = pickClipPatch(asRecord(root.patch) ?? undefined);\n  const mergedPatch = { ...flatPatch, ...nestedPatch };\n  const nestedGrading =\n    (asRecord(root.grading) as Partial<ColorGradingSettings> | null) ||\n    (asRecord(root.colorGrading) as Partial<ColorGradingSettings> | null) ||\n    grading;\n\n  return {\n    schemaVersion,\n    summary,\n    ops: ops && ops.length > 0 ? ops : undefined,\n    patch: Object.keys(mergedPatch).length > 0 ? mergedPatch : undefined,\n    grading: nestedGrading && Object.keys(nestedGrading).length > 0 ? nestedGrading : undefined,\n  };\n}\n\nexport function applyVideoEditPlan(plan: VideoEditPlan): {\n  applied: number;\n  summary?: string;\n} {\n  const store = useVideoStore.getState();\n  const selected = [...store.selectedClipIds];\n  let applied = 0;\n\n  if (plan.ops && plan.ops.length > 0) {\n    for (const op of plan.ops) {\n      try {\n        if (applyOneOp(op, selected)) applied += 1;\n      } catch (err) {\n        console.warn('[video-edit-plan] op failed', op, err);\n      }\n    }\n    return { applied, summary: plan.summary };\n  }\n\n  const targets = selected.length > 0 ? selected : [];\n  if (targets.length === 0 && (plan.patch || plan.grading)) {\n    console.warn('[video-edit-plan] no selected clip to apply patch');\n    return { applied: 0, summary: plan.summary };\n  }\n\n  for (const id of targets) {\n    if (plan.patch && Object.keys(plan.patch).length > 0) {\n      const { colorGrading, ...rest } = plan.patch;\n      if (Object.keys(rest).length > 0) {\n        store.updateClipProperties(id, rest);\n        applied += 1;\n      }\n      if (colorGrading) {\n        store.updateColorGrading(id, colorGrading);\n        applied += 1;\n      }\n    }\n    if (plan.grading && Object.keys(plan.grading).length > 0) {\n      store.updateColorGrading(id, plan.grading);\n      applied += 1;\n    }\n  }\n\n  return { applied, summary: plan.summary };\n}\n\nfunction applyOneOp(op: VideoEditOp, selectedClipIds: string[]): boolean {\n  const store = useVideoStore.getState();\n  const name = (op.op || '').trim();\n  if (!name) return false;\n\n  switch (name) {\n    case 'updateClip': {\n      const ids = resolveClipIds(op.clipId, selectedClipIds);\n      const patch = pickClipPatch(asRecord(op.patch) ?? (op as Record<string, unknown>));\n      if (Object.keys(patch).length === 0) return false;\n      const { colorGrading, ...rest } = patch;\n      for (const id of ids) {\n        if (Object.keys(rest).length > 0) store.updateClipProperties(id, rest);\n        if (colorGrading) store.updateColorGrading(id, colorGrading);\n      }\n      return ids.length > 0;\n    }\n    case 'updateColorGrading': {\n      const ids = resolveClipIds(op.clipId, selectedClipIds);\n      const grading =\n        (asRecord(op.grading) as Partial<ColorGradingSettings> | null) ||\n        (asRecord(op.patch) as Partial<ColorGradingSettings> | null);\n      if (!grading || Object.keys(grading).length === 0) return false;\n      for (const id of ids) store.updateColorGrading(id, grading);\n      return ids.length > 0;\n    }\n    case 'addEffect': {\n      const ids = resolveClipIds(op.clipId, selectedClipIds);\n      const effectType = String(op.effectType || '') as EffectType;\n      if (!effectType) return false;\n      for (const id of ids) {\n        store.addEffect(id, effectType, op.params as Record<string, unknown> | undefined);\n      }\n      return ids.length > 0;\n    }\n    case 'updateEffect': {\n      const ids = resolveClipIds(op.clipId, selectedClipIds);\n      const effectId = String(op.effectId || '');\n      if (!effectId || !op.params) return false;\n      for (const id of ids) store.updateEffect(id, effectId, op.params);\n      return ids.length > 0;\n    }\n    case 'removeEffect': {\n      const ids = resolveClipIds(op.clipId, selectedClipIds);\n      const effectId = String(op.effectId || '');\n      if (!effectId) return false;\n      for (const id of ids) store.removeEffect(id, effectId);\n      return ids.length > 0;\n    }\n    case 'toggleEffect': {\n      const ids = resolveClipIds(op.clipId, selectedClipIds);\n      const effectId = String(op.effectId || '');\n      if (!effectId) return false;\n      for (const id of ids) store.toggleEffect(id, effectId);\n      return ids.length > 0;\n    }\n    case 'addTransition': {\n      const fromClipId = String(op.fromClipId || '');\n      const toClipId = String(op.toClipId || '');\n      const type = String(op.type || 'cross-dissolve') as TransitionType;\n      const duration = typeof op.duration === 'number' ? op.duration : 0.5;\n      if (!fromClipId || !toClipId) return false;\n      store.addTransition({\n        type,\n        fromClipId,\n        toClipId,\n        duration,\n        params: {},\n        easing: 'linear',\n        reverse: false,\n      });\n      return true;\n    }\n    case 'removeTransition': {\n      const id = String((op as { id?: string }).id || op.effectId || '');\n      if (!id) return false;\n      store.removeTransition(id);\n      return true;\n    }\n    case 'addKeyframe': {\n      const ids = resolveClipIds(op.clipId, selectedClipIds);\n      const property = String(op.property || '');\n      const kf = op.keyframe;\n      if (!property || !kf || typeof kf.time !== 'number') return false;\n      const easing = (kf.easing as EasingType) || 'linear';\n      for (const id of ids) {\n        store.addKeyframe(id, property, {\n          time: kf.time,\n          value: kf.value,\n          easing,\n        });\n      }\n      return ids.length > 0;\n    }\n    case 'addTextClip': {\n      let trackId = typeof op.trackId === 'string' ? op.trackId : '';\n      if (!trackId) {\n        trackId = store.tracks.find((t) => t.type === 'text')?.id ?? '';\n      }\n      if (!trackId) {\n        store.addTrack('Text AI', 'text');\n        trackId = useVideoStore.getState().tracks.find((t) => t.type === 'text')?.id ?? '';\n      }\n      if (!trackId) return false;\n      const text = String(op.text || op.patch?.text || '');\n      if (!text) return false;\n      const startTime =\n        typeof op.startTime === 'number' ? op.startTime : store.playheadTime;\n      const duration = typeof op.duration === 'number' ? op.duration : 4;\n      store.addTextClip({\n        trackId,\n        assetId: '',\n        startTime,\n        duration,\n        trimIn: 0,\n        trimOut: 0,\n        speed: 1,\n        volume: 1,\n        opacity: 1,\n        muted: false,\n        name: text.slice(0, 32),\n        text,\n        ...pickClipPatch(asRecord(op.patch) ?? undefined),\n      });\n      return true;\n    }\n    case 'setPlayhead': {\n      const time = typeof op.startTime === 'number' ? op.startTime : Number(op.patch?.startTime);\n      if (!Number.isFinite(time)) return false;\n      store.setPlayhead(time);\n      return true;\n    }\n    default:\n      console.warn('[video-edit-plan] unknown op skipped:', name, op);\n      return false;\n  }\n}\n", "/**\n * Text service \u2014 AI text operations that hit the .NET backend.\n * Currently covers:\n *  - translateSubtitles        (POST /api/ai/translate-subtitles)\n *  - generateSubtitleStylePreset (POST /api/ai/subtitle-style-preset)\n *\n * All return parsed JSON. As more JSON-returning endpoints are verified with\n * the backend, they get added here.\n */\n\nimport { getEditorIdentity } from './identity';\nimport {\n  ApiError,\n  NotImplementedError,\n  getWizardApiClient,\n} from './wizardApiClient';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface SubtitleStylePreset {\n  fontFamily?: string;\n  fontWeight?: number;\n  fontSize?: number;\n  fontStyle?: 'normal' | 'italic';\n  fillColor?: string;\n  strokeEnabled?: boolean;\n  strokeColor?: string;\n  strokeWidth?: number;\n  shadowEnabled?: boolean;\n  shadowColor?: string;\n  shadowBlur?: number;\n  shadowOffsetX?: number;\n  shadowOffsetY?: number;\n  shadowOpacity?: number;\n  backgroundEnabled?: boolean;\n  backgroundColor?: string;\n  backgroundOpacity?: number;\n  backgroundPadding?: number;\n  backgroundBorderRadius?: number;\n  letterSpacing?: number;\n  lineHeight?: number;\n  textAlign?: 'left' | 'center' | 'right';\n  textTransform?: 'none' | 'uppercase' | 'lowercase' | 'capitalize';\n}\n\nconst SUBTITLE_STYLE_KEYS = [\n  'fontFamily',\n  'fontWeight',\n  'fontSize',\n  'fontStyle',\n  'fillColor',\n  'strokeEnabled',\n  'strokeColor',\n  'strokeWidth',\n  'shadowEnabled',\n  'shadowColor',\n  'shadowBlur',\n  'shadowOffsetX',\n  'shadowOffsetY',\n  'shadowOpacity',\n  'backgroundEnabled',\n  'backgroundColor',\n  'backgroundOpacity',\n  'backgroundPadding',\n  'backgroundBorderRadius',\n  'letterSpacing',\n  'lineHeight',\n  'textAlign',\n  'textTransform',\n] as const;\n\ntype SubtitleStyleKey = (typeof SUBTITLE_STYLE_KEYS)[number];\n\n/** Alternate names the model / .NET may use for the same clip fields. */\nconst STYLE_KEY_ALIASES: Record<string, SubtitleStyleKey> = {\n  fontfamily: 'fontFamily',\n  font_family: 'fontFamily',\n  font: 'fontFamily',\n  family: 'fontFamily',\n  typeface: 'fontFamily',\n  fontweight: 'fontWeight',\n  font_weight: 'fontWeight',\n  weight: 'fontWeight',\n  fontsize: 'fontSize',\n  font_size: 'fontSize',\n  size: 'fontSize',\n  fontstyle: 'fontStyle',\n  font_style: 'fontStyle',\n  italic: 'fontStyle',\n  fillcolor: 'fillColor',\n  fill_color: 'fillColor',\n  color: 'fillColor',\n  fill: 'fillColor',\n  textcolor: 'fillColor',\n  text_color: 'fillColor',\n  foreground: 'fillColor',\n  strokecolor: 'strokeColor',\n  stroke_color: 'strokeColor',\n  outlinecolor: 'strokeColor',\n  outline_color: 'strokeColor',\n  bordercolor: 'strokeColor',\n  strokeenabled: 'strokeEnabled',\n  stroke_enabled: 'strokeEnabled',\n  outline: 'strokeEnabled',\n  outlineenabled: 'strokeEnabled',\n  strokewidth: 'strokeWidth',\n  stroke_width: 'strokeWidth',\n  outlinewidth: 'strokeWidth',\n  outline_width: 'strokeWidth',\n  borderwidth: 'strokeWidth',\n  shadowenabled: 'shadowEnabled',\n  shadow_enabled: 'shadowEnabled',\n  shadowcolor: 'shadowColor',\n  shadow_color: 'shadowColor',\n  shadowblur: 'shadowBlur',\n  shadow_blur: 'shadowBlur',\n  shadowoffsetx: 'shadowOffsetX',\n  shadow_offset_x: 'shadowOffsetX',\n  shadowoffsety: 'shadowOffsetY',\n  shadow_offset_y: 'shadowOffsetY',\n  shadowopacity: 'shadowOpacity',\n  shadow_opacity: 'shadowOpacity',\n  backgroundenabled: 'backgroundEnabled',\n  background_enabled: 'backgroundEnabled',\n  backgroundcolor: 'backgroundColor',\n  background_color: 'backgroundColor',\n  bgcolor: 'backgroundColor',\n  bg_color: 'backgroundColor',\n  platecolor: 'backgroundColor',\n  backgroundopacity: 'backgroundOpacity',\n  background_opacity: 'backgroundOpacity',\n  backgroundpadding: 'backgroundPadding',\n  background_padding: 'backgroundPadding',\n  backgroundborderradius: 'backgroundBorderRadius',\n  background_border_radius: 'backgroundBorderRadius',\n  letterspacing: 'letterSpacing',\n  letter_spacing: 'letterSpacing',\n  lineheight: 'lineHeight',\n  line_height: 'lineHeight',\n  textalign: 'textAlign',\n  text_align: 'textAlign',\n  align: 'textAlign',\n  alignment: 'textAlign',\n  texttransform: 'textTransform',\n  text_transform: 'textTransform',\n};\n\nfunction tryParseJsonObject(value: unknown): Record<string, unknown> | null {\n  if (value && typeof value === 'object' && !Array.isArray(value)) {\n    return value as Record<string, unknown>;\n  }\n  if (typeof value !== 'string') return null;\n  const trimmed = value.trim();\n  if (!trimmed) return null;\n  const fence = trimmed.match(/```(?:json)?\\s*([\\s\\S]*?)```/i);\n  const candidate = (fence?.[1] ?? trimmed).trim();\n  const first = candidate.indexOf('{');\n  const last = candidate.lastIndexOf('}');\n  if (first < 0 || last <= first) return null;\n  try {\n    const parsed: unknown = JSON.parse(candidate.slice(first, last + 1));\n    if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n      return parsed as Record<string, unknown>;\n    }\n  } catch {\n    /* ignore */\n  }\n  return null;\n}\n\nfunction resolveStyleKey(rawKey: string): SubtitleStyleKey | null {\n  if ((SUBTITLE_STYLE_KEYS as readonly string[]).includes(rawKey)) {\n    return rawKey as SubtitleStyleKey;\n  }\n  const lower = rawKey.toLowerCase().replace(/[^a-z0-9_]/g, '');\n  if (STYLE_KEY_ALIASES[lower]) return STYLE_KEY_ALIASES[lower];\n  // PascalCase \u2192 camelCase (FontFamily \u2192 fontFamily)\n  if (/^[A-Z]/.test(rawKey)) {\n    const camel = rawKey.charAt(0).toLowerCase() + rawKey.slice(1);\n    if ((SUBTITLE_STYLE_KEYS as readonly string[]).includes(camel)) {\n      return camel as SubtitleStyleKey;\n    }\n    const camelLower = camel.toLowerCase();\n    if (STYLE_KEY_ALIASES[camelLower]) return STYLE_KEY_ALIASES[camelLower];\n  }\n  return null;\n}\n\nfunction coerceStyleValue(key: SubtitleStyleKey, value: unknown): unknown {\n  if (value === undefined || value === null) return undefined;\n  if (\n    key === 'fontWeight' ||\n    key === 'fontSize' ||\n    key === 'strokeWidth' ||\n    key === 'shadowBlur' ||\n    key === 'shadowOffsetX' ||\n    key === 'shadowOffsetY' ||\n    key === 'shadowOpacity' ||\n    key === 'backgroundOpacity' ||\n    key === 'backgroundPadding' ||\n    key === 'backgroundBorderRadius' ||\n    key === 'letterSpacing' ||\n    key === 'lineHeight'\n  ) {\n    const n = typeof value === 'number' ? value : Number(value);\n    return Number.isFinite(n) ? n : undefined;\n  }\n  if (\n    key === 'strokeEnabled' ||\n    key === 'shadowEnabled' ||\n    key === 'backgroundEnabled'\n  ) {\n    if (typeof value === 'boolean') return value;\n    if (typeof value === 'string') {\n      const v = value.trim().toLowerCase();\n      if (v === 'true' || v === '1' || v === 'yes') return true;\n      if (v === 'false' || v === '0' || v === 'no') return false;\n    }\n    if (typeof value === 'number') return value !== 0;\n    return Boolean(value);\n  }\n  if (key === 'fontStyle') {\n    const s = String(value).toLowerCase();\n    return s.includes('italic') ? 'italic' : 'normal';\n  }\n  if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n    return value;\n  }\n  return undefined;\n}\n\nfunction mapStyleRecord(source: Record<string, unknown>): SubtitleStylePreset {\n  const out: SubtitleStylePreset = {};\n  for (const [key, value] of Object.entries(source)) {\n    if (key.startsWith('__') || key === 'thought_process' || key === 'ThoughtProcess') {\n      continue;\n    }\n    const camel = resolveStyleKey(key);\n    if (!camel) continue;\n    const coerced = coerceStyleValue(camel, value);\n    if (coerced === undefined) continue;\n    (out as Record<string, unknown>)[camel] = coerced;\n  }\n  return out;\n}\n\n/**\n * Normalize .NET / model payload into clip typography fields the editor understands.\n * Tolerates camelCase, snake_case, PascalCase, aliases, nested wrappers, and JSON strings.\n */\nexport function normalizeSubtitleStylePreset(raw: unknown): SubtitleStylePreset {\n  const candidates: Record<string, unknown>[] = [];\n\n  const root = tryParseJsonObject(raw);\n  if (root) candidates.push(root);\n\n  for (const candidate of [...candidates]) {\n    for (const key of [\n      'preset',\n      'style',\n      'subtitleStyle',\n      'subtitle_style',\n      'SubtitleStyle',\n      'creative_style',\n      'creativeStyle',\n      'description',\n      'data',\n      'result',\n      'Result',\n      'properties',\n      'Properties',\n      'settings',\n      'content',\n      'styleJson',\n      'style_json',\n      'presetJson',\n      'preset_json',\n    ]) {\n      if (!(key in candidate)) continue;\n      const nested = tryParseJsonObject(candidate[key]);\n      if (nested) candidates.push(nested);\n    }\n  }\n\n  let best: SubtitleStylePreset = {};\n  for (const source of candidates) {\n    const mapped = mapStyleRecord(source);\n    if (Object.keys(mapped).length > Object.keys(best).length) {\n      best = mapped;\n    }\n  }\n  return best;\n}\n\nexport interface MarketingContent {\n  titles: string[];\n  hooks: string[];\n  copy: string;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n  if (value && typeof value === 'object' && !Array.isArray(value)) {\n    return value as Record<string, unknown>;\n  }\n  return null;\n}\n\nfunction coerceStringList(value: unknown): string[] {\n  if (Array.isArray(value)) {\n    return value\n      .map((item) => {\n        if (typeof item === 'string') return item.trim();\n        const rec = asRecord(item);\n        if (!rec) return '';\n        const text = rec.text ?? rec.title ?? rec.hook ?? rec.content ?? rec.value;\n        return typeof text === 'string' ? text.trim() : '';\n      })\n      .filter(Boolean);\n  }\n  if (typeof value === 'string' && value.trim()) {\n    const lines = value\n      .split(/\\n+/)\n      .map((line) => line.replace(/^[-*\u2022\\d.)\\s]+/, '').trim())\n      .filter(Boolean);\n    return lines.length > 1 ? lines : [value.trim()];\n  }\n  return [];\n}\n\nfunction pickMarketingField(\n  source: Record<string, unknown>,\n  aliases: string[],\n): unknown {\n  const lower = new Map<string, unknown>();\n  for (const [k, v] of Object.entries(source)) {\n    lower.set(k.toLowerCase().replace(/[^a-z0-9]/g, ''), v);\n  }\n  for (const alias of aliases) {\n    const key = alias.toLowerCase().replace(/[^a-z0-9]/g, '');\n    if (lower.has(key)) return lower.get(key);\n  }\n  return undefined;\n}\n\n/** Normalize .NET / model payloads into { titles, hooks, copy }. */\nexport function normalizeMarketingContent(raw: unknown): MarketingContent {\n  const candidates: Record<string, unknown>[] = [];\n  const root = tryParseJsonObject(raw) ?? asRecord(raw);\n  if (root) candidates.push(root);\n\n  for (const candidate of [...candidates]) {\n    for (const key of [\n      'result',\n      'data',\n      'content',\n      'marketing',\n      'marketingContent',\n      'marketing_content',\n      'response',\n      'output',\n      'payload',\n      'creative_style',\n      'creativeStyle',\n    ]) {\n      if (!(key in candidate)) continue;\n      const nested = tryParseJsonObject(candidate[key]);\n      if (nested) candidates.push(nested);\n    }\n  }\n\n  let best: MarketingContent = { titles: [], hooks: [], copy: '' };\n  let bestScore = -1;\n\n  for (const source of candidates) {\n    const titles = coerceStringList(\n      pickMarketingField(source, [\n        'titles',\n        'viralTitles',\n        'viral_titles',\n        'titleIdeas',\n        'title_ideas',\n        'titulos',\n        't\u00EDtulos',\n      ]),\n    );\n    const hooks = coerceStringList(\n      pickMarketingField(source, [\n        'hooks',\n        'hookIdeas',\n        'hook_ideas',\n        'ganchos',\n        'openers',\n        'hooks3s',\n      ]),\n    );\n    const copyRaw = pickMarketingField(source, [\n      'copy',\n      'socialCopy',\n      'social_copy',\n      'caption',\n      'post',\n      'body',\n      'text',\n      'copyText',\n      'copy_text',\n    ]);\n    const copy =\n      typeof copyRaw === 'string'\n        ? copyRaw.trim()\n        : Array.isArray(copyRaw)\n          ? coerceStringList(copyRaw).join('\\n\\n')\n          : '';\n\n    const score = titles.length + hooks.length + (copy ? 2 : 0);\n    if (score > bestScore) {\n      bestScore = score;\n      best = { titles, hooks, copy };\n    }\n  }\n\n  return best;\n}\n\nexport interface ColorGradingPreset {\n  exposure?: number;\n  contrast?: number;\n  highlights?: number;\n  shadows?: number;\n  whites?: number;\n  blacks?: number;\n  temperature?: number;\n  tint?: number;\n  vibrance?: number;\n  saturation?: number;\n  hue?: number;\n  vignetteEnabled?: boolean;\n  vignetteAmount?: number;\n}\n\n// \u2500\u2500 Design preset \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * The 4 object types supported by /api/ai/design-preset. Each maps to a\n * different response shape (text vs shape vs image filters vs canvas bg).\n * The editor determines the right one from the active Fabric.js object.\n */\nexport const DESIGN_OBJECT_TYPES = ['text', 'shape', 'image', 'canvas'] as const;\nexport type DesignObjectType = (typeof DESIGN_OBJECT_TYPES)[number];\n\n/**\n * Permissive because the response shape depends on objectType. The editor\n * dispatches on the objectType it sent to know which fields are present.\n * The unknown fields let the JSON parser accept whatever the .NET returns.\n */\nexport type DesignPreset = Record<string, unknown>;\n\n// \u2500\u2500 POST /api/ai/translate-subtitles \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface TranslateSubtitlesOptions {\n  text: string;\n  targetLanguage: string;\n  signal?: AbortSignal;\n}\n\nexport type TranslatedSubtitleItem = { id: string; text: string };\n\ninterface TranslateSubtitlesResponse {\n  translatedText: string;\n  [key: string]: unknown;\n}\n\n/**\n * Models (and some BFF passthroughs) sometimes wrap the JSON array in prose\n * (\"Here's the translation: [...]\") or markdown fences. Extract a usable array.\n */\nexport function parseTranslatedSubtitlePayload(raw: string): TranslatedSubtitleItem[] {\n  const trimmed = (raw ?? '').trim();\n  if (!trimmed) {\n    throw new Error('Empty translation response');\n  }\n\n  const candidates: string[] = [trimmed];\n\n  const fence = trimmed.match(/```(?:json)?\\s*([\\s\\S]*?)```/i);\n  if (fence?.[1]) candidates.push(fence[1].trim());\n\n  const firstBracket = trimmed.indexOf('[');\n  const lastBracket = trimmed.lastIndexOf(']');\n  if (firstBracket >= 0 && lastBracket > firstBracket) {\n    candidates.push(trimmed.slice(firstBracket, lastBracket + 1));\n  }\n\n  const firstBrace = trimmed.indexOf('{');\n  const lastBrace = trimmed.lastIndexOf('}');\n  if (firstBrace >= 0 && lastBrace > firstBrace) {\n    candidates.push(trimmed.slice(firstBrace, lastBrace + 1));\n  }\n\n  const normalizeItems = (value: unknown): TranslatedSubtitleItem[] | null => {\n    if (Array.isArray(value)) {\n      const items = value\n        .map((row) => {\n          if (!row || typeof row !== 'object') return null;\n          const rec = row as Record<string, unknown>;\n          const id = typeof rec.id === 'string' ? rec.id : null;\n          const text = typeof rec.text === 'string' ? rec.text : null;\n          if (!id || text == null) return null;\n          return { id, text };\n        })\n        .filter((x): x is TranslatedSubtitleItem => x != null);\n      return items.length > 0 ? items : null;\n    }\n    if (value && typeof value === 'object') {\n      const rec = value as Record<string, unknown>;\n      for (const key of ['items', 'subtitles', 'clips', 'translations', 'data']) {\n        const nested = normalizeItems(rec[key]);\n        if (nested) return nested;\n      }\n      // Single object with id+text\n      const one = normalizeItems([value]);\n      if (one) return one;\n    }\n    return null;\n  };\n\n  let lastError: unknown;\n  for (const candidate of candidates) {\n    try {\n      const parsed: unknown = JSON.parse(candidate);\n      const items = normalizeItems(parsed);\n      if (items) return items;\n    } catch (err) {\n      lastError = err;\n    }\n  }\n\n  throw lastError instanceof Error\n    ? lastError\n    : new Error('Translation response is not valid JSON');\n}\n\nexport async function translateSubtitles(\n  opts: TranslateSubtitlesOptions\n): Promise<TranslatedSubtitleItem[]> {\n  const { accountId, brandId } = getEditorIdentity();\n  const res = await getWizardApiClient().postJsonForJson<TranslateSubtitlesResponse>(\n    '/api/ai/translate-subtitles',\n    {\n      text: opts.text,\n      targetLanguage: opts.targetLanguage,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n  return parseTranslatedSubtitlePayload(res.translatedText);\n}\n\n// \u2500\u2500 POST /api/ai/subtitle-style-preset \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface GenerateSubtitleStylePresetOptions {\n  prompt: string;\n  signal?: AbortSignal;\n}\n\n/**\n * The .NET currently leaks the AI model's `__thought_process` field in the\n * response. We declare it in the response type so the parser accepts it,\n * then strip it before returning to the caller.\n */\ninterface SubtitleStylePresetResponse extends SubtitleStylePreset {\n  __thought_process?: string;\n  [key: string]: unknown;\n}\n\nexport async function generateSubtitleStylePreset(\n  opts: GenerateSubtitleStylePresetOptions\n): Promise<SubtitleStylePreset> {\n  const { accountId, brandId } = getEditorIdentity();\n  const res = await getWizardApiClient().postJsonForJson<SubtitleStylePresetResponse>(\n    '/api/ai/subtitle-style-preset',\n    {\n      prompt: opts.prompt,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n\n  const preset = normalizeSubtitleStylePreset(res);\n\n  if (Object.keys(preset).length === 0) {\n    const record =\n      res && typeof res === 'object' ? (res as Record<string, unknown>) : null;\n    const backendError =\n      record &&\n      (typeof record.error === 'string'\n        ? record.error\n        : typeof record.message === 'string'\n          ? record.message\n          : null);\n    if (backendError) {\n      throw new Error(`Subtitle style backend error: ${backendError}`);\n    }\n    const keys = record ? Object.keys(record).join(', ') : typeof res;\n    throw new Error(\n      `Empty subtitle style preset from backend (keys: ${keys || 'none'}). ` +\n        `Expected typography fields (fontFamily, fillColor, \u2026).`,\n    );\n  }\n  return preset;\n}\n\n// \u2500\u2500 POST /api/ai/marketing-assistant \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface GenerateMarketingAssistantOptions {\n  transcript: string;\n  signal?: AbortSignal;\n}\n\n/**\n * The .NET leaks the AI model's `__thought_process` field in the response,\n * same as /api/ai/subtitle-style-preset. We declare it in the response\n * type so the parser accepts it, then strip it before returning.\n */\ninterface MarketingAssistantResponse extends MarketingContent {\n  __thought_process?: string;\n  [key: string]: unknown;\n}\n\nexport async function generateMarketingAssistant(\n  opts: GenerateMarketingAssistantOptions\n): Promise<MarketingContent> {\n  const { accountId, brandId } = getEditorIdentity();\n  const res = await getWizardApiClient().postJsonForJson<MarketingAssistantResponse>(\n    '/api/ai/marketing-assistant',\n    {\n      transcript: opts.transcript,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n\n  const { __thought_process: thoughtProcess, ...rest } = res;\n  const content = normalizeMarketingContent(rest);\n  if (\n    content.titles.length === 0 &&\n    content.hooks.length === 0 &&\n    !content.copy &&\n    thoughtProcess\n  ) {\n    // Some backends only return prose in __thought_process / creative_style.\n    const fromThought = normalizeMarketingContent({ creative_style: thoughtProcess });\n    if (\n      fromThought.titles.length ||\n      fromThought.hooks.length ||\n      fromThought.copy\n    ) {\n      Object.assign(content, fromThought);\n    }\n  }\n\n  return content;\n}\n\n// \u2500\u2500 POST /api/ai/color-grading-preset \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Host BFF may list this as not-implemented (404). When missing, we map the\n// creative prompt to grading values locally (warm/cool/noir/cinematic\u2026).\n\nexport interface GenerateColorGradingPresetOptions {\n  prompt: string;\n  signal?: AbortSignal;\n}\n\n/**\n * Same noise pattern as the other text endpoints: the .NET leaks the AI's\n * `__thought_process` field, which we declare and strip before returning.\n */\ninterface ColorGradingPresetResponse extends ColorGradingPreset {\n  __thought_process?: string;\n  [key: string]: unknown;\n}\n\nfunction isMissingColorGradingEndpoint(err: unknown): boolean {\n  if (err instanceof NotImplementedError) return true;\n  if (err instanceof ApiError && err.status === 400) {\n    return /unknown ai action/i.test(err.detail);\n  }\n  return false;\n}\n\nexport async function generateColorGradingPreset(\n  opts: GenerateColorGradingPresetOptions\n): Promise<ColorGradingPreset> {\n  const { normalizeColorGradingPreset, inferColorGradingFromProse } = await import(\n    '../utils/videoAiPresetMap'\n  );\n  const { accountId, brandId } = getEditorIdentity();\n\n  try {\n    const res = await getWizardApiClient().postJsonForJson<ColorGradingPresetResponse>(\n      '/api/ai/color-grading-preset',\n      {\n        prompt: opts.prompt,\n        account_id: accountId,\n        brand_id: brandId,\n      },\n      { signal: opts.signal }\n    );\n    const { __thought_process: thoughtProcess, ...preset } = res;\n    const normalized = normalizeColorGradingPreset(preset, thoughtProcess);\n    if (Object.keys(normalized).length > 0) return normalized;\n\n    const fromPrompt = inferColorGradingFromProse(opts.prompt);\n    if (Object.keys(fromPrompt).length > 0) return fromPrompt;\n\n    throw new Error('EMPTY_COLOR_GRADING_PRESET');\n  } catch (err) {\n    if (err instanceof Error && err.message === 'EMPTY_COLOR_GRADING_PRESET') throw err;\n    if (!isMissingColorGradingEndpoint(err)) throw err;\n\n    const fromPrompt = inferColorGradingFromProse(opts.prompt);\n    if (Object.keys(fromPrompt).length > 0) return fromPrompt;\n\n    throw new Error('EMPTY_COLOR_GRADING_PRESET');\n  }\n}\n\n// Note: EMPTY_* codes are mapped to friendly UI copy via toUserFacingError /\n// sanitizeUserFacingMessage \u2014 never shown raw to end users.\n\n// \u2500\u2500 POST /api/ai/design-preset \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface GenerateDesignPresetOptions {\n  prompt: string;\n  /**\n   * One of DESIGN_OBJECT_TYPES. If omitted/empty, the .NET defaults to\n   * 'shape'. The editor always passes the right value based on the\n   * active Fabric.js object.\n   */\n  objectType?: DesignObjectType | '';\n  signal?: AbortSignal;\n}\n\n/**\n * Same noise pattern as the other text endpoints: __thought_process\n * leaks from the .NET and gets stripped before returning.\n */\ninterface DesignPresetResponse extends DesignPreset {\n  __thought_process?: string;\n}\n\nexport async function generateDesignPreset(\n  opts: GenerateDesignPresetOptions\n): Promise<DesignPreset> {\n  const { accountId, brandId } = getEditorIdentity();\n  const res = await getWizardApiClient().postJsonForJson<DesignPresetResponse>(\n    '/api/ai/design-preset',\n    {\n      prompt: opts.prompt,\n      objectType: opts.objectType ?? '',\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n  const { __thought_process: _thoughtProcess, ...preset } = res;\n  return preset;\n}\n\n// \u2500\u2500 POST /api/ai/video-properties \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Expanded plan: schemaVersion + ops (TICKET-VIDEO-PROPERTIES-FULL-EDITOR).\n// Flat opacity/speed/volume/muted still supported. BFF miss \u2192 local prompt parse.\n\nexport type { VideoEditPlan as VideoPropertiesPreset } from '../utils/videoEditPlan';\n\nexport interface GenerateVideoPropertiesOptions {\n  prompt: string;\n  /** Optional clip kind for .NET (`video` \\| `image` \\| `audio`). */\n  clipType?: string;\n  /** When false, skip projectSnapshot (legacy callers). Default true. */\n  includeSnapshot?: boolean;\n  signal?: AbortSignal;\n}\n\ninterface VideoPropertiesResponse {\n  schemaVersion?: number;\n  summary?: string;\n  ops?: unknown[];\n  patch?: Record<string, unknown>;\n  opacity?: number;\n  volume?: number;\n  speed?: number;\n  muted?: boolean;\n  __thought_process?: string;\n  [key: string]: unknown;\n}\n\nfunction isMissingVideoPropertiesEndpoint(err: unknown): boolean {\n  if (err instanceof NotImplementedError) return true;\n  if (err instanceof ApiError && err.status === 400) {\n    return /unknown ai action/i.test(err.detail);\n  }\n  return false;\n}\n\nfunction planIsEmpty(plan: import('../utils/videoEditPlan').VideoEditPlan): boolean {\n  const hasOps = !!(plan.ops && plan.ops.length > 0);\n  const hasPatch = !!(plan.patch && Object.keys(plan.patch).length > 0);\n  const hasGrading = !!(plan.grading && Object.keys(plan.grading).length > 0);\n  return !hasOps && !hasPatch && !hasGrading;\n}\n\nexport async function generateVideoProperties(\n  opts: GenerateVideoPropertiesOptions\n): Promise<import('../utils/videoEditPlan').VideoEditPlan> {\n  const { normalizeVideoPropertiesPreset } = await import('../utils/videoAiPresetMap');\n  const { parseVideoEditPlan, buildVideoProjectSnapshot } = await import('../utils/videoEditPlan');\n  const { accountId, brandId } = getEditorIdentity();\n  const includeSnapshot = opts.includeSnapshot !== false;\n\n  const toPlan = (raw: unknown, thoughtProcess?: string) => {\n    const flatPatch = normalizeVideoPropertiesPreset(raw, thoughtProcess);\n    const { colorGrading, ...rest } = flatPatch;\n    return parseVideoEditPlan(raw, rest, colorGrading);\n  };\n\n  try {\n    const res = await getWizardApiClient().postJsonForJson<VideoPropertiesResponse>(\n      '/api/ai/video-properties',\n      {\n        prompt: opts.prompt,\n        ...(opts.clipType ? { clipType: opts.clipType } : {}),\n        account_id: accountId,\n        brand_id: brandId,\n        ...(includeSnapshot ? { projectSnapshot: buildVideoProjectSnapshot() } : {}),\n      },\n      { signal: opts.signal }\n    );\n    const { __thought_process: thoughtProcess, ...preset } = res;\n    const plan = toPlan(preset, thoughtProcess);\n\n    if (!planIsEmpty(plan)) return plan;\n\n    const fromPrompt = toPlan({}, opts.prompt);\n    if (!planIsEmpty(fromPrompt)) return fromPrompt;\n\n    const record =\n      res && typeof res === 'object' ? (res as Record<string, unknown>) : null;\n    const backendError =\n      record &&\n      (typeof record.error === 'string'\n        ? record.error\n        : typeof record.message === 'string'\n          ? record.message\n          : null);\n    if (backendError) {\n      console.error('[video-properties] backend error field:', backendError, res);\n      throw new Error('EMPTY_VIDEO_PROPERTIES_PRESET');\n    }\n    console.error('[video-properties] empty preset payload:', res);\n    throw new Error('EMPTY_VIDEO_PROPERTIES_PRESET');\n  } catch (err) {\n    if (err instanceof Error && err.message === 'EMPTY_VIDEO_PROPERTIES_PRESET') throw err;\n    if (!isMissingVideoPropertiesEndpoint(err)) throw err;\n\n    const fromPrompt = toPlan({}, opts.prompt);\n    if (!planIsEmpty(fromPrompt)) return fromPrompt;\n\n    console.error('[video-properties] endpoint missing and local parse empty', err);\n    throw new Error('EMPTY_VIDEO_PROPERTIES_PRESET');\n  }\n}\n\n// \u2500\u2500 POST /api/ai/generate-copy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface GenerateCopyOptions {\n  prompt: string;\n  signal?: AbortSignal;\n}\n\ninterface GenerateCopyResponse {\n  text?: string;\n  copy?: string;\n  content?: string;\n  __thought_process?: string;\n  [key: string]: unknown;\n}\n\nexport async function generateCopy(opts: GenerateCopyOptions): Promise<string> {\n  const { accountId, brandId } = getEditorIdentity();\n  const res = await getWizardApiClient().postJsonForJson<GenerateCopyResponse>(\n    '/api/ai/generate-copy',\n    {\n      prompt: opts.prompt,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n  const text = String(res.text ?? res.copy ?? res.content ?? '').trim();\n  if (!text) throw new Error('Empty copy response');\n  return text;\n}\n\n// \u2500\u2500 POST /api/ai/copywriting-suggestions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface CopywritingSuggestions {\n  comercial: string;\n  creativa: string;\n  directa: string;\n}\n\nexport interface GenerateCopywritingSuggestionsOptions {\n  prompt: string;\n  signal?: AbortSignal;\n}\n\ninterface CopywritingSuggestionsResponse extends CopywritingSuggestions {\n  __thought_process?: string;\n  [key: string]: unknown;\n}\n\nexport async function generateCopywritingSuggestions(\n  opts: GenerateCopywritingSuggestionsOptions\n): Promise<CopywritingSuggestions> {\n  const { accountId, brandId } = getEditorIdentity();\n  const res = await getWizardApiClient().postJsonForJson<CopywritingSuggestionsResponse>(\n    '/api/ai/copywriting-suggestions',\n    {\n      prompt: opts.prompt,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n  const comercial = String(res.comercial ?? '').trim();\n  const creativa = String(res.creativa ?? '').trim();\n  const directa = String(res.directa ?? '').trim();\n  if (!comercial || !creativa || !directa) {\n    throw new Error('Incomplete copywriting suggestions');\n  }\n  return { comercial, creativa, directa };\n}\n", "/**\n * Voiceover service \u2014 AI text-to-speech backed by the .NET / Wizard BFF at\n * POST /api/ai/voiceover. Response is audio/mpeg binary (MP3).\n *\n * Request shape (Swagger):\n *   { text, voice, speed, account_id, brand_id }\n *\n * In standalone Vite, `/api/ai/*` is proxied to the Wizard BFF (cookie auth).\n * Do NOT call `/api/audio/tts` from video voiceover \u2014 that hits .NET directly\n * and fails with 401 in dual-dev.\n */\n\nimport { getEditorIdentity } from './identity';\nimport { getWizardApiClient } from './wizardApiClient';\n\n// \u2500\u2500 Voice catalog \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Las 9 voces soportadas por el backend `/api/audio/tts` (ElevenLabs).\n *\n * ANTES: la lista eran voces de OpenAI TTS (alloy, echo, coral, etc.).\n *        El backend migr\u00F3 a ElevenLabs y el editor segu\u00EDa mandando los\n *        nombres de OpenAI \u2192 ElevenLabs devolv\u00EDa 404 \"voice_not_found\".\n *\n * `id` es el `voice_id` real de ElevenLabs (lo que se manda al backend).\n * `label` es el texto que ve el usuario en el dropdown.\n *\n * Si el backend agrega/saca voces, actualizar este array y rebuild.\n */\nexport interface TtsVoice {\n  /** ElevenLabs voice_id \u2014 se manda al backend tal cual en el campo `voice`. */\n  id: string;\n  /** Texto que se muestra en el dropdown del modal. */\n  label: string;\n  /**\n   * Optional static demo clip (Wizard hosts these under /tools/voices/).\n   * When missing, the UI synthesizes a short sample via /api/ai/voiceover.\n   */\n  previewUrl?: string;\n}\n\nexport const TTS_VOICES: readonly TtsVoice[] = [\n  {\n    id: 'pNInz6obpgDQGcFmaJgB',\n    label: 'Adam (Narrativa, masculina profunda)',\n    previewUrl: '/tools/voices/Adam - Dominant, Firm.mp3',\n  },\n  {\n    id: 'hpp4J3VqNfWAUOO0d1Us',\n    label: 'Bella (Suave, femenina)',\n    previewUrl: '/tools/voices/Bella - Professional, Bright, Warm.mp3',\n  },\n  {\n    id: 'nPczCjzI2devNBz1zQrb',\n    label: 'Brian (Brit\u00E1nica, narrativa masculina)',\n    previewUrl: '/tools/voices/Brian - Deep, Resonant and Comforting.mp3',\n  },\n  {\n    id: 'pFZP5JQG7iQjIQuC4Bku',\n    label: 'Lily (Conversacional, femenina c\u00E1lida)',\n    previewUrl: '/tools/voices/Lily - Velvety Actress.mp3',\n  },\n  {\n    id: 'iP95p4xoKVk53GoZ742B',\n    label: 'Chris (Casual, masculina amigable)',\n    previewUrl: '/tools/voices/Chris - Charming, Down-to-Earth.mp3',\n  },\n  {\n    id: 'XrExE9yKIg1WjnnlVkGX',\n    label: 'Matilda (C\u00E1lida, femenina amigable)',\n    previewUrl: '/tools/voices/Matilda - Knowledgable, Professional.mp3',\n  },\n  {\n    id: 'pqHfZKP75CvOlQylNhV4',\n    label: 'Bill (Madura, narrativa masculina)',\n    previewUrl: '/tools/voices/Bill - Wise, Mature, Balanced.mp3',\n  },\n  {\n    id: 'EXAVITQu4vr4xnSDxMaL',\n    label: 'Sarah (Suave, femenina madura)',\n    previewUrl: '/tools/voices/Sarah - Mature, Reassuring, Confident.mp3',\n  },\n  {\n    id: 'JBFqnCBsd6RMkjVDRZzb',\n    label: 'George (Brit\u00E1nica, masculina madura)',\n    previewUrl: '/tools/voices/George - Warm, Captivating Storyteller.mp3',\n  },\n] as const;\n\nexport type TtsVoiceId = (typeof TTS_VOICES)[number]['id'];\n\n// \u2500\u2500 POST /api/ai/voiceover \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface GenerateVoiceoverOptions {\n  text: string;\n  voice: TtsVoiceId | string;\n  /** Playback speed multiplier. Typical range 0.25 \u2013 4.0; default 1.0. */\n  speed: number;\n  signal?: AbortSignal;\n}\n\nexport async function generateVoiceover(\n  opts: GenerateVoiceoverOptions\n): Promise<Blob> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postJson(\n    '/api/ai/voiceover',\n    {\n      text: opts.text,\n      voice: opts.voice,\n      speed: opts.speed,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n}\n", "/**\n * Ensure a File suitable for Whisper / .NET `/api/ai/transcribe`.\n * OpenAI rejects uploads without a supported extension (e.g. bare Blobs,\n * `file.bin`, or names lost after IndexedDB round-trips).\n */\n\nconst WHISPER_EXTS = new Set([\n  'flac',\n  'm4a',\n  'mp3',\n  'mp4',\n  'mpeg',\n  'mpga',\n  'oga',\n  'ogg',\n  'wav',\n  'webm',\n]);\n\nconst MIME_TO_EXT: Record<string, string> = {\n  'audio/mpeg': 'mp3',\n  'audio/mp3': 'mp3',\n  'audio/mp4': 'm4a',\n  'audio/x-m4a': 'm4a',\n  'audio/m4a': 'm4a',\n  'audio/aac': 'm4a',\n  'audio/wav': 'wav',\n  'audio/wave': 'wav',\n  'audio/x-wav': 'wav',\n  'audio/webm': 'webm',\n  'audio/ogg': 'ogg',\n  'audio/flac': 'flac',\n  'video/mp4': 'mp4',\n  'video/webm': 'webm',\n  'video/quicktime': 'mp4',\n  'video/x-m4v': 'mp4',\n};\n\nfunction extensionOf(name: string): string | null {\n  const base = name.split(/[/\\\\]/).pop() || name;\n  const dot = base.lastIndexOf('.');\n  if (dot < 0 || dot === base.length - 1) return null;\n  return base.slice(dot + 1).toLowerCase().replace(/[^a-z0-9]/g, '');\n}\n\nfunction extFromMime(mime: string): string | null {\n  const normalized = (mime || '').toLowerCase().split(';')[0]?.trim() ?? '';\n  if (!normalized) return null;\n  if (MIME_TO_EXT[normalized]) return MIME_TO_EXT[normalized]!;\n  const subtype = normalized.split('/')[1];\n  if (!subtype) return null;\n  const clean = subtype.replace(/[^a-z0-9]/gi, '');\n  if (WHISPER_EXTS.has(clean)) return clean;\n  if (clean === 'mpeg') return 'mp3';\n  if (clean === 'xwav' || clean === 'wave') return 'wav';\n  if (clean === 'quicktime') return 'mp4';\n  return null;\n}\n\nfunction defaultExt(mime: string): string {\n  if (mime.startsWith('audio/')) return 'mp3';\n  if (mime.startsWith('video/')) return 'mp4';\n  return 'mp4';\n}\n\n/**\n * Returns a `File` whose name ends in a Whisper-supported extension.\n * Reuses the same blob bytes (no re-encode).\n */\nexport function toTranscribeUploadFile(\n  input: File | Blob,\n  hintName?: string,\n): File {\n  const mime = (input.type || '').trim() || 'application/octet-stream';\n  const rawName =\n    (input instanceof File && input.name.trim()) ||\n    (hintName || '').trim() ||\n    'media';\n\n  const fromName = extensionOf(rawName);\n  const fromMime = extFromMime(mime);\n  let ext =\n    (fromName && WHISPER_EXTS.has(fromName) ? fromName : null) ||\n    fromMime ||\n    defaultExt(mime);\n\n  if (!WHISPER_EXTS.has(ext)) {\n    ext = defaultExt(mime);\n  }\n\n  const stem = rawName.replace(/\\.[^/.]+$/, '').replace(/[^\\w.\\-]+/g, '_').slice(0, 80) || 'media';\n  const filename = `${stem}.${ext}`;\n\n  if (input instanceof File && input.name === filename) {\n    return input;\n  }\n\n  return new File([input], filename, {\n    type: mime === 'application/octet-stream' ? (ext === 'mp3' ? 'audio/mpeg' : `video/${ext}`) : mime,\n    lastModified: input instanceof File ? input.lastModified : Date.now(),\n  });\n}\n", "/**\n * Transcription service \u2014 AI speech-to-text backed by the .NET backend at\n * /api/ai/transcribe. Accepts an audio or video file (multipart upload) and\n * returns Whisper-style segments with timestamps.\n *\n * This replaces the old `whisperService.ts`, which called OpenAI's Whisper\n * API directly with the user's apiKey. The .NET now owns the transcription\n * pipeline (including any audio extraction from video containers), so the\n * editor no longer needs FFmpeg.wasm or Web Audio fallback paths.\n */\n\nimport { getEditorIdentity } from './identity';\nimport { getWizardApiClient } from './wizardApiClient';\nimport { toTranscribeUploadFile } from '../utils/transcribeUploadFile';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * A single transcription segment with word/phrase-level timestamps. Mirrors\n * the OpenAI Whisper `verbose_json` response shape (without `__thought_process`\n * noise \u2014 the .NET doesn't leak that here, unlike the text-preset endpoints).\n */\n/** Word-level timestamp when Whisper word_timestamps are available. */\nexport interface TranscriptionWordTs {\n  word: string;\n  start: number;\n  end: number;\n}\n\nexport interface TranscriptionSegment {\n  id: number;\n  seek: number;\n  /** Start time of the segment in seconds. */\n  start: number;\n  /** End time of the segment in seconds. */\n  end: number;\n  /** Transcribed text, with a leading space. */\n  text: string;\n  tokens: number[];\n  temperature: number;\n  avg_logprob: number;\n  compression_ratio: number;\n  no_speech_prob: number;\n  /** Present when backend enables Whisper word timestamps. */\n  words?: TranscriptionWordTs[];\n}\n\n/** Full verbose response. Exposed for callers that want language/duration. */\nexport interface TranscriptionResult {\n  task: 'transcribe' | 'translate';\n  language: string;\n  duration: number;\n  text: string;\n  segments: TranscriptionSegment[];\n  /** Top-level word timestamps (some Whisper responses). */\n  words?: TranscriptionWordTs[];\n  usage: {\n    type: 'duration';\n    seconds: number;\n  };\n}\n\n// \u2500\u2500 POST /api/ai/transcribe \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface TranscribeAudioOptions {\n  /** Audio or video file. Field name sent is \"file\" per the .NET Swagger DTO. */\n  file: File | Blob;\n  signal?: AbortSignal;\n}\n\n/**\n * Transcribes an audio/video file into timestamped segments.\n *\n * Server-side field name is \"file\". Pass either a `File` (preserves original\n * filename/extension) or a `Blob` (filename auto-derived from MIME type).\n * The .NET extracts audio from video containers server-side, so the editor\n * no longer needs FFmpeg.wasm preprocessing.\n */\nexport async function transcribeAudio(\n  opts: TranscribeAudioOptions\n): Promise<TranscriptionSegment[]> {\n  const { accountId, brandId } = getEditorIdentity();\n  // Whisper needs a supported filename extension; Blobs / IDB round-trips often lack one.\n  const file = toTranscribeUploadFile(opts.file);\n  const res = await getWizardApiClient().postMultipartForJson<TranscriptionResult>(\n    '/api/ai/transcribe',\n    {\n      file,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n  return res.segments;\n}\n\n/**\n * Same as `transcribeAudio` but returns the full response (including\n * language, duration, usage). Useful for analytics or progress display.\n */\nexport async function transcribeAudioVerbose(\n  opts: TranscribeAudioOptions\n): Promise<TranscriptionResult> {\n  const { accountId, brandId } = getEditorIdentity();\n  const file = toTranscribeUploadFile(opts.file);\n  return getWizardApiClient().postMultipartForJson<TranscriptionResult>(\n    '/api/ai/transcribe',\n    {\n      file,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n}\n", "/**\n * Kaiman AI Studio \u2014 AI Service\n *\n * Public fa\u00E7ade for every AI operation the editor exposes. Each function\n * delegates to a per-domain service module (imageService, textService,\n * voiceoverService, transcriptionService) which in turn calls the .NET\n * backend via the wizardApiClient. The editor no longer talks to OpenAI or\n * Google directly \u2014 every request goes through the host backend.\n */\n\nimport { generateImageWithGemini as svcGenerateImageWithGemini } from './imageService';\nimport * as textService from './textService';\nimport type {\n  SubtitleStylePreset,\n  MarketingContent,\n  ColorGradingPreset,\n  DesignPreset,\n  DesignObjectType,\n  VideoPropertiesPreset,\n  CopywritingSuggestions,\n  TranslatedSubtitleItem,\n} from './textService';\nimport * as voiceoverService from './voiceoverService';\nimport * as transcriptionService from './transcriptionService';\nimport * as stockService from './stockService';\n// Type imports para uso LOCAL en las firmas de las funciones de m\u00E1s abajo.\n// (los `export type` de abajo solo re-exportan, no importan al scope local.)\nimport type { TranscriptionSegment } from './transcriptionService';\nimport type { StockSearchResult } from './stockService';\nexport type {\n  SubtitleStylePreset,\n  MarketingContent,\n  ColorGradingPreset,\n  DesignPreset,\n  DesignObjectType,\n  VideoPropertiesPreset,\n  CopywritingSuggestions,\n  TranslatedSubtitleItem,\n};\nexport { TTS_VOICES, type TtsVoice, type TtsVoiceId } from './voiceoverService';\nexport { DESIGN_OBJECT_TYPES } from './textService';\nexport type { TranscriptionSegment, TranscriptionResult } from './transcriptionService';\nexport type { StockPhoto, StockSearchResult } from './stockService';\n\n/**\n * Helper to call OpenAI Chat Completions API (gpt-4o-mini)\n *\n * REMOVED 2026-07-10: the editor no longer calls OpenAI directly per\n * AGENTS.md \u00A73.1. All AI operations delegate to the .NET backend via\n * wizardApiClient. This helper was dead code after the migrations of\n * marketing-assistant, color-grading-preset, design-preset, and transcribe.\n */\n\n/**\n * Translates subtitles text while keeping formatting/IDs or structural placeholders.\n * Delegates to the .NET backend at /api/ai/translate-subtitles.\n * Tolerates prose/markdown wrappers around the JSON array from the model.\n */\nexport async function translateSubtitles(\n  text: string,\n  targetLanguage: string\n): Promise<TranslatedSubtitleItem[]> {\n  return textService.translateSubtitles({ text, targetLanguage });\n}\n\n/**\n * Generates subtitle styles presets based on creative descriptions.\n * Delegates to the .NET backend at /api/ai/subtitle-style-preset.\n */\nexport async function generateSubtitleStylePreset(\n  prompt: string\n): Promise<SubtitleStylePreset> {\n  return textService.generateSubtitleStylePreset({ prompt });\n}\n\n/**\n * Compiles a video transcript into marketing assets (Viral Titles, Hooks, Social Copy).\n * Delegates to the .NET backend at /api/ai/marketing-assistant.\n */\nexport async function generateMarketingAssistant(\n  transcript: string\n): Promise<MarketingContent> {\n  return textService.generateMarketingAssistant({ transcript });\n}\n\n/**\n * Generates an image using the .NET backend's /api/ai/generate-image-gemini\n * endpoint. Returns a Blob of the generated image (image/png or image/jpeg).\n */\nexport async function generateImageFromGemini(prompt: string): Promise<Blob> {\n  return svcGenerateImageWithGemini({ prompt });\n}\n\n/**\n * Generates a voiceover mp3 using the Wizard BFF / .NET at /api/ai/voiceover.\n * Response is audio/mpeg binary (MP3).\n */\nexport async function generateVoiceover(\n  text: string,\n  voice: string,\n  speed: number\n): Promise<Blob> {\n  return voiceoverService.generateVoiceover({ text, voice, speed });\n}\n\n/**\n * Translates a creative color grading prompt into ColorGradingSettings numerical parameters.\n * Delegates to the .NET backend at /api/ai/color-grading-preset.\n */\nexport async function generateColorGradingPreset(\n  prompt: string\n): Promise<ColorGradingPreset> {\n  return textService.generateColorGradingPreset({ prompt });\n}\n\n/**\n * Translates a natural language command into specific Fabric.js properties or background instructions.\n * Delegates to the .NET backend at /api/ai/design-preset.\n */\nexport async function generateImageDesignPreset(\n  prompt: string,\n  objectType: DesignObjectType | ''\n): Promise<DesignPreset> {\n  return textService.generateDesignPreset({ prompt, objectType });\n}\n\n/**\n * Maps a creative prompt to a video edit plan (flat patch and/or ops).\n * Delegates to POST /api/ai/video-properties.\n */\nexport async function generateVideoProperties(\n  prompt: string,\n  clipType?: string\n): Promise<VideoPropertiesPreset> {\n  return textService.generateVideoProperties({ prompt, clipType });\n}\n\n/**\n * Short commercial copy for text overlays.\n * Delegates to POST /api/ai/generate-copy.\n */\nexport async function generateCopy(prompt: string): Promise<string> {\n  return textService.generateCopy({ prompt });\n}\n\n/**\n * Three copywriting variants (comercial / creativa / directa).\n * Delegates to POST /api/ai/copywriting-suggestions.\n */\nexport async function generateCopywritingSuggestions(\n  prompt: string\n): Promise<CopywritingSuggestions> {\n  return textService.generateCopywritingSuggestions({ prompt });\n}\n\n/**\n * Transcribes an audio/video file into timestamped segments.\n * Delegates to the .NET backend at /api/ai/transcribe.\n * The .NET handles audio extraction from video containers server-side,\n * so the editor no longer needs FFmpeg.wasm preprocessing.\n */\nexport async function transcribeAudio(\n  file: File | Blob\n): Promise<TranscriptionSegment[]> {\n  return transcriptionService.transcribeAudio({ file });\n}\n\n/**\n * Searches the .NET stock-photo backend (Unsplash + Pexels, server-side routing).\n * Delegates to GET /api/stock/search with the new unified response shape.\n */\nexport async function searchStock(opts: {\n  q: string;\n  page: number;\n  perPage: number;\n  signal?: AbortSignal;\n}): Promise<StockSearchResult> {\n  return stockService.searchStock(opts);\n}\n", "import { filters } from 'fabric';\n\nexport const IMAGE_FILTER_PRESET_IDS = [\n  'original',\n  'grayscale',\n  'sepia',\n  'vintage',\n  'cyberpunk',\n  'polar',\n  'sunset',\n  'fade',\n  'noir',\n] as const;\n\nexport type ImageFilterPresetId = (typeof IMAGE_FILTER_PRESET_IDS)[number];\n\nexport type ImagePresetSettings = {\n  brightness: number;\n  contrast: number;\n  saturation: number;\n  blur: number;\n  hueRotation: number;\n  exposure: number;\n  invert: boolean;\n  activePreset: string;\n};\n\n/** Build Fabric filters + settings for a named quick preset. Mutates `imgObj.filters`. */\nexport function buildImageFilterPreset(\n  imgObj: { filters: unknown[] },\n  presetName: string,\n): ImagePresetSettings {\n  const newSettings: ImagePresetSettings = {\n    brightness: 0,\n    contrast: 0,\n    saturation: 0,\n    blur: 0,\n    hueRotation: 0,\n    exposure: 0,\n    invert: false,\n    activePreset: presetName,\n  };\n\n  imgObj.filters = [];\n\n  switch (presetName) {\n    case 'grayscale':\n      newSettings.saturation = -1;\n      imgObj.filters.push(new filters.Grayscale());\n      break;\n    case 'sepia':\n      imgObj.filters.push(new filters.Sepia());\n      break;\n    case 'vintage':\n      newSettings.hueRotation = 0.08;\n      newSettings.brightness = 0.05;\n      newSettings.contrast = -0.1;\n      newSettings.saturation = -0.15;\n      imgObj.filters.push(new filters.HueRotation({ rotation: 0.08 }));\n      imgObj.filters.push(new filters.Brightness({ brightness: 0.05 }));\n      imgObj.filters.push(new filters.Contrast({ contrast: -0.1 }));\n      imgObj.filters.push(new filters.Saturation({ saturation: -0.15 }));\n      break;\n    case 'cyberpunk':\n      newSettings.hueRotation = 0.55;\n      newSettings.contrast = 0.15;\n      newSettings.saturation = 0.25;\n      imgObj.filters.push(new filters.HueRotation({ rotation: 0.55 }));\n      imgObj.filters.push(new filters.Contrast({ contrast: 0.15 }));\n      imgObj.filters.push(new filters.Saturation({ saturation: 0.25 }));\n      break;\n    case 'polar':\n      newSettings.hueRotation = -0.15;\n      newSettings.brightness = -0.05;\n      newSettings.contrast = 0.1;\n      newSettings.saturation = -0.05;\n      imgObj.filters.push(new filters.HueRotation({ rotation: -0.15 }));\n      imgObj.filters.push(new filters.Brightness({ brightness: -0.05 }));\n      imgObj.filters.push(new filters.Contrast({ contrast: 0.1 }));\n      imgObj.filters.push(new filters.Saturation({ saturation: -0.05 }));\n      break;\n    case 'sunset':\n      newSettings.hueRotation = 0.05;\n      newSettings.saturation = 0.2;\n      newSettings.contrast = 0.05;\n      imgObj.filters.push(new filters.HueRotation({ rotation: 0.05 }));\n      imgObj.filters.push(new filters.Saturation({ saturation: 0.2 }));\n      imgObj.filters.push(new filters.Contrast({ contrast: 0.05 }));\n      break;\n    case 'fade':\n      newSettings.contrast = -0.15;\n      newSettings.brightness = 0.05;\n      newSettings.saturation = -0.1;\n      imgObj.filters.push(new filters.Contrast({ contrast: -0.15 }));\n      imgObj.filters.push(new filters.Brightness({ brightness: 0.05 }));\n      imgObj.filters.push(new filters.Saturation({ saturation: -0.1 }));\n      break;\n    case 'noir':\n      newSettings.saturation = -1;\n      newSettings.contrast = 0.25;\n      newSettings.brightness = -0.05;\n      imgObj.filters.push(new filters.Grayscale());\n      imgObj.filters.push(new filters.Contrast({ contrast: 0.25 }));\n      imgObj.filters.push(new filters.Brightness({ brightness: -0.05 }));\n      break;\n    default:\n      break;\n  }\n\n  return newSettings;\n}\n", "/**\n * Visual zoom without resizing the Fabric bitmap.\n *\n * Fabric stays at page \u00D7 page with setZoom(1). The page frame grows to\n * `page \u00D7 zoom` and the Fabric wrapper is CSS-scaled. That avoids\n * `setDimensions` on every wheel tick (the main zoom-in flicker source).\n *\n * Selection chrome outside the artboard is drawn by SelectionControlsOverlay\n * (DOM), not by expanding the Fabric bitmap.\n */\n\nexport type CanvasZoomRenderPlan = {\n  visualW: number;\n  visualH: number;\n  /** Always 1 \u2014 Fabric bitmap is page pixels. */\n  bitmapZoom: number;\n  bitmapW: number;\n  bitmapH: number;\n  cssScale: number;\n};\n\nexport type ZoomableFabricCanvas = {\n  setDimensions: (size: { width: number; height: number }) => unknown;\n  setZoom: (value: number) => unknown;\n  setViewportTransform?: (vpt: number[]) => unknown;\n  getZoom?: () => number;\n  getWidth?: () => number;\n  getHeight?: () => number;\n  calcOffset: () => unknown;\n  requestRenderAll?: () => unknown;\n  wrapperEl?: HTMLElement | null;\n  lowerCanvasEl?: HTMLCanvasElement | null;\n  upperCanvasEl?: HTMLCanvasElement | null;\n  width?: number;\n  height?: number;\n  clipPath?: unknown;\n  controlsAboveOverlay?: boolean;\n  skipOffscreen?: boolean;\n  /** Visual (UI) zoom \u2014 CSS scale. Not Fabric viewport zoom. */\n  weVisualZoom?: number;\n  weSelectionGutter?: number;\n};\n\nexport function planCanvasZoomRender(\n  pageW: number,\n  pageH: number,\n  zoom: number,\n): CanvasZoomRenderPlan {\n  const w = Math.max(1, pageW);\n  const h = Math.max(1, pageH);\n  const z = Math.max(0.01, zoom);\n  return {\n    visualW: w * z,\n    visualH: h * z,\n    bitmapZoom: 1,\n    bitmapW: w,\n    bitmapH: h,\n    cssScale: z,\n  };\n}\n\n/** UI / screen zoom (CSS). Falls back to Fabric zoom for non-image canvases. */\nexport function getVisualZoom(canvas: {\n  weVisualZoom?: number;\n  getZoom?: () => number;\n} | null | undefined): number {\n  if (!canvas) return 1;\n  if (typeof canvas.weVisualZoom === 'number' && canvas.weVisualZoom > 0) {\n    return canvas.weVisualZoom;\n  }\n  return canvas.getZoom?.() || 1;\n}\n\n/**\n * Keep Fabric at page size; apply visual zoom via CSS scale on the wrapper.\n * Only calls `setDimensions` when the page size changes \u2014 never on zoom.\n */\nexport function applyCanvasZoomRender(\n  canvas: ZoomableFabricCanvas,\n  pageW: number,\n  pageH: number,\n  zoom: number,\n): CanvasZoomRenderPlan {\n  const plan = planCanvasZoomRender(pageW, pageH, zoom);\n\n  // Clear leftovers from the selection-gutter experiment.\n  if (canvas.clipPath) canvas.clipPath = undefined;\n  canvas.weSelectionGutter = undefined;\n  canvas.setViewportTransform?.([1, 0, 0, 1, 0, 0]);\n\n  const curW = canvas.getWidth?.() ?? canvas.width ?? 0;\n  const curH = canvas.getHeight?.() ?? canvas.height ?? 0;\n  const pageSizeChanged =\n    Math.abs(curW - plan.bitmapW) > 0.5 || Math.abs(curH - plan.bitmapH) > 0.5;\n\n  if (pageSizeChanged) {\n    canvas.setDimensions({ width: plan.bitmapW, height: plan.bitmapH });\n  }\n\n  if (Math.abs((canvas.getZoom?.() ?? 1) - 1) > 0.0001) {\n    canvas.setZoom(1);\n  }\n  canvas.weVisualZoom = zoom;\n  canvas.controlsAboveOverlay = true;\n\n  const wrap = canvas.wrapperEl;\n  if (wrap) {\n    wrap.style.transformOrigin = '0 0';\n    wrap.style.willChange = 'transform';\n    wrap.style.position = '';\n    wrap.style.left = '';\n    wrap.style.top = '';\n    wrap.style.overflow = '';\n    const nextTransform =\n      Math.abs(plan.cssScale - 1) < 0.0001 ? '' : `scale(${plan.cssScale})`;\n    if (wrap.style.transform !== nextTransform) {\n      wrap.style.transform = nextTransform;\n    }\n  }\n\n  const lower =\n    canvas.lowerCanvasEl ||\n    (wrap?.querySelector?.('.lower-canvas') as HTMLCanvasElement | null | undefined);\n  if (lower) lower.style.clipPath = '';\n  const upper =\n    canvas.upperCanvasEl ||\n    (wrap?.querySelector?.('.upper-canvas') as HTMLCanvasElement | null | undefined);\n  if (upper) {\n    upper.style.clipPath = '';\n    upper.style.zIndex = '';\n  }\n\n  canvas.calcOffset();\n  return plan;\n}\n", "/**\n * In-canvas AI loading state: lock a layer (or placeholder) while a job runs.\n * HTML chrome for the skeleton lives in AiLoadingOverlay.\n */\n\nimport { FabricImage, Rect, type Canvas, type FabricObject } from 'fabric';\nimport type {\n  ImageGeneratorAspectRatio,\n  ImageGeneratorResolution,\n} from '../services/imageService';\nimport { clampEditorImageResolution } from '../services/imageService';\n\nexport type AiLoadingObject = FabricObject & {\n  id?: string;\n  name?: string;\n  locked?: boolean;\n  weAiLoading?: boolean;\n  weAiPlaceholder?: boolean;\n  weAiLoadingPrev?: {\n    locked: boolean;\n    selectable: boolean;\n    evented: boolean;\n    lockMovementX: boolean;\n    lockMovementY: boolean;\n    lockScalingX: boolean;\n    lockScalingY: boolean;\n    lockRotation: boolean;\n  };\n};\n\nconst ASPECT_PARTS: Record<ImageGeneratorAspectRatio, { aw: number; ah: number }> = {\n  '1:1': { aw: 1, ah: 1 },\n  '4:5': { aw: 4, ah: 5 },\n  '9:16': { aw: 9, ah: 16 },\n  '16:9': { aw: 16, ah: 9 },\n  '3:2': { aw: 3, ah: 2 },\n};\n\n/**\n * Expected generator pixel size for skeleton preview (1K \u2248 1024 long edge, 2K \u2248 2048).\n * Final placement always uses the backend image's natural width/height \u2014 not this guess.\n */\nexport function expectedGeneratorPixelSize(\n  aspect: ImageGeneratorAspectRatio,\n  resolution?: ImageGeneratorResolution | '4K' | null,\n): { w: number; h: number } {\n  const { aw, ah } = ASPECT_PARTS[aspect] ?? ASPECT_PARTS['1:1'];\n  const longEdge = clampEditorImageResolution(resolution) === '1K' ? 1024 : 2048;\n  if (aw >= ah) {\n    return { w: longEdge, h: Math.max(1, Math.round((longEdge * ah) / aw)) };\n  }\n  return { w: Math.max(1, Math.round((longEdge * aw) / ah)), h: longEdge };\n}\n\nexport function isAiLoadingObject(obj: FabricObject | null | undefined): obj is AiLoadingObject {\n  return !!(obj as AiLoadingObject | null | undefined)?.weAiLoading;\n}\n\nexport function listAiLoadingObjects(canvas: Canvas | null | undefined): AiLoadingObject[] {\n  if (!canvas) return [];\n  return canvas.getObjects().filter(isAiLoadingObject);\n}\n\n/** Lock object so the user cannot move/edit it mid-generation. */\nexport function beginAiLoading(obj: FabricObject): void {\n  const target = obj as AiLoadingObject;\n  if (target.weAiLoading) return;\n  target.weAiLoadingPrev = {\n    locked: target.locked === true,\n    selectable: target.selectable !== false,\n    evented: target.evented !== false,\n    lockMovementX: target.lockMovementX === true,\n    lockMovementY: target.lockMovementY === true,\n    lockScalingX: target.lockScalingX === true,\n    lockScalingY: target.lockScalingY === true,\n    lockRotation: target.lockRotation === true,\n  };\n  target.weAiLoading = true;\n  target.locked = true;\n  target.set({\n    selectable: false,\n    evented: false,\n    hasControls: false,\n    hasBorders: false,\n    lockMovementX: true,\n    lockMovementY: true,\n    lockScalingX: true,\n    lockScalingY: true,\n    lockRotation: true,\n  });\n  target.setCoords();\n}\n\n/** Restore lock/select flags after generation (or leave unlocked if it was a placeholder). */\nexport function endAiLoading(obj: FabricObject): void {\n  const target = obj as AiLoadingObject;\n  const prev = target.weAiLoadingPrev;\n  delete target.weAiLoading;\n  delete target.weAiLoadingPrev;\n  delete target.weAiPlaceholder;\n  if (prev) {\n    target.locked = prev.locked;\n    target.set({\n      selectable: prev.selectable,\n      evented: prev.evented,\n      lockMovementX: prev.lockMovementX,\n      lockMovementY: prev.lockMovementY,\n      lockScalingX: prev.lockScalingX,\n      lockScalingY: prev.lockScalingY,\n      lockRotation: prev.lockRotation,\n      hasControls: false,\n      hasBorders: false,\n    });\n  } else {\n    target.locked = false;\n    target.set({\n      selectable: true,\n      evented: true,\n      lockMovementX: false,\n      lockMovementY: false,\n      lockScalingX: false,\n      lockScalingY: false,\n      lockRotation: false,\n      hasControls: false,\n      hasBorders: false,\n    });\n  }\n  target.setCoords();\n}\n\ntype TransformSnapshot = {\n  left: number;\n  top: number;\n  angle: number;\n  flipX: boolean;\n  flipY: boolean;\n  originX: FabricObject['originX'];\n  originY: FabricObject['originY'];\n  skewX: number;\n  skewY: number;\n  displayW: number;\n  displayH: number;\n  id?: string;\n  name?: string;\n};\n\nfunction snapshotTransform(obj: FabricObject): TransformSnapshot {\n  return {\n    left: obj.left ?? 0,\n    top: obj.top ?? 0,\n    angle: obj.angle ?? 0,\n    flipX: obj.flipX === true,\n    flipY: obj.flipY === true,\n    originX: obj.originX ?? 'left',\n    originY: obj.originY ?? 'top',\n    skewX: obj.skewX ?? 0,\n    skewY: obj.skewY ?? 0,\n    displayW: Math.max(1, (obj.width ?? 1) * (obj.scaleX ?? 1)),\n    displayH: Math.max(1, (obj.height ?? 1) * (obj.scaleY ?? 1)),\n    id: (obj as FabricObject & { id?: string }).id,\n    name: (obj as FabricObject & { name?: string }).name,\n  };\n}\n\nfunction applyTransformPreservingDisplaySize(img: FabricImage, snap: TransformSnapshot): void {\n  const iw = Math.max(1, img.width || 1);\n  const ih = Math.max(1, img.height || 1);\n  img.set({\n    left: snap.left,\n    top: snap.top,\n    angle: snap.angle,\n    flipX: snap.flipX,\n    flipY: snap.flipY,\n    originX: snap.originX,\n    originY: snap.originY,\n    skewX: snap.skewX,\n    skewY: snap.skewY,\n    scaleX: snap.displayW / iw,\n    scaleY: snap.displayH / ih,\n    id: snap.id,\n    name: snap.name,\n  });\n  (img as FabricObject & { locked?: boolean }).locked = false;\n  img.setCoords();\n}\n\nexport function createAiPlaceholderLayer(\n  canvas: Canvas,\n  opts: {\n    aspectRatio?: ImageGeneratorAspectRatio;\n    resolution?: ImageGeneratorResolution | '4K' | null;\n    pageWidth: number;\n    pageHeight: number;\n    name?: string;\n  },\n): AiLoadingObject {\n  const aspect = opts.aspectRatio ?? '1:1';\n  // Preview at requested 1K/2K frame \u2014 not shrunk to the page.\n  const size = expectedGeneratorPixelSize(aspect, opts.resolution);\n  const id = `ai-gen-${Date.now()}`;\n  const left = (opts.pageWidth - size.w) / 2;\n  const top = (opts.pageHeight - size.h) / 2;\n  const rect = new Rect({\n    left,\n    top,\n    width: size.w,\n    height: size.h,\n    fill: '#2e2e34',\n    stroke: 'rgba(255,255,255,0.08)',\n    strokeWidth: 1,\n    rx: 16,\n    ry: 16,\n    originX: 'left',\n    originY: 'top',\n    objectCaching: false,\n  }) as AiLoadingObject;\n\n  rect.set({\n    id,\n    name: opts.name || 'AI',\n    weAiPlaceholder: true,\n  });\n  beginAiLoading(rect);\n  canvas.add(rect);\n  canvas.setActiveObject(rect);\n  canvas.requestRenderAll();\n  return rect;\n}\n\n/**\n * Place the generated image at the backend's native pixel size (scale 1).\n * Centered on the page \u2014 never stretched/shrunk to the loading placeholder.\n */\nexport async function replaceAiPlaceholderWithImage(\n  canvas: Canvas,\n  placeholder: AiLoadingObject,\n  dataUrl: string,\n  opts?: { pageWidth?: number; pageHeight?: number },\n): Promise<FabricImage> {\n  const img = await FabricImage.fromURL(dataUrl, { crossOrigin: 'anonymous' });\n  const iw = Math.max(1, img.width || 1);\n  const ih = Math.max(1, img.height || 1);\n  const pageW = opts?.pageWidth ?? canvas.getWidth();\n  const pageH = opts?.pageHeight ?? canvas.getHeight();\n  const id = placeholder.id;\n  const name = placeholder.name;\n\n  img.set({\n    left: (pageW - iw) / 2,\n    top: (pageH - ih) / 2,\n    scaleX: 1,\n    scaleY: 1,\n    angle: 0,\n    originX: 'left',\n    originY: 'top',\n    id,\n    name,\n  });\n  (img as FabricObject & { locked?: boolean }).locked = false;\n  img.setCoords();\n\n  const idx = canvas.getObjects().indexOf(placeholder);\n  canvas.remove(placeholder);\n  canvas.add(img);\n  if (idx >= 0) canvas.moveObjectTo(img, idx);\n  canvas.setActiveObject(img);\n  canvas.requestRenderAll();\n  return img;\n}\n\n/** Swap an image in place, keeping canvas position / size / rotation / flips. */\nexport async function replaceFabricImagePreservingTransform(\n  canvas: Canvas,\n  target: FabricObject,\n  dataUrl: string,\n): Promise<FabricImage> {\n  const snap = snapshotTransform(target);\n  const img = await FabricImage.fromURL(dataUrl, { crossOrigin: 'anonymous' });\n  applyTransformPreservingDisplaySize(img, snap);\n\n  const idx = canvas.getObjects().indexOf(target);\n  canvas.remove(target);\n  canvas.add(img);\n  if (idx >= 0) canvas.moveObjectTo(img, idx);\n  canvas.setActiveObject(img);\n  canvas.requestRenderAll();\n  return img;\n}\n\nexport function removeAiPlaceholder(canvas: Canvas, placeholder: AiLoadingObject): void {\n  canvas.remove(placeholder);\n  canvas.requestRenderAll();\n}\n\nexport function findObjectById(canvas: Canvas, id: string | null | undefined): FabricObject | null {\n  if (!id) return null;\n  return (\n    canvas.getObjects().find((o) => (o as FabricObject & { id?: string }).id === id) ?? null\n  );\n}\n", "/** Parse / format CSS colors with optional alpha for panel color fields. */\n\nexport type RgbaColor = { r: number; g: number; b: number; a: number };\n\nfunction clampByte(n: number): number {\n  return Math.max(0, Math.min(255, Math.round(n)));\n}\n\nfunction clamp01(n: number): number {\n  return Math.max(0, Math.min(1, n));\n}\n\nexport function rgbaToCss({ r, g, b, a }: RgbaColor): string {\n  const aa = clamp01(a);\n  if (aa >= 1) {\n    return `#${[r, g, b].map((c) => clampByte(c).toString(16).padStart(2, '0')).join('')}`.toUpperCase();\n  }\n  const aStr = Number(aa.toFixed(3)).toString();\n  return `rgba(${clampByte(r)}, ${clampByte(g)}, ${clampByte(b)}, ${aStr})`;\n}\n\n/** Hex for `<input type=\"color\">` (no alpha). */\nexport function rgbaToHex6({ r, g, b }: RgbaColor): string {\n  return `#${[r, g, b].map((c) => clampByte(c).toString(16).padStart(2, '0')).join('')}`;\n}\n\n/** Editable display: #RRGGBB or #RRGGBBAA. */\nexport function rgbaToHexDisplay({ r, g, b, a }: RgbaColor): string {\n  const rgb = [r, g, b].map((c) => clampByte(c).toString(16).padStart(2, '0')).join('');\n  if (clamp01(a) >= 1) return `#${rgb}`.toUpperCase();\n  const aa = clampByte(clamp01(a) * 255)\n    .toString(16)\n    .padStart(2, '0');\n  return `#${rgb}${aa}`.toUpperCase();\n}\n\nexport function parseCssColor(input: string, fallback: RgbaColor = { r: 0, g: 0, b: 0, a: 1 }): RgbaColor {\n  const raw = input.trim();\n  if (!raw || /^transparent$/i.test(raw) || /^transparente$/i.test(raw) || /^none$/i.test(raw)) {\n    return { ...fallback, a: 0 };\n  }\n\n  const rgbaMatch = raw.match(\n    /^rgba?\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*,\\s*([\\d.]+)(?:\\s*,\\s*([\\d.]+))?\\s*\\)$/i,\n  );\n  if (rgbaMatch) {\n    return {\n      r: clampByte(parseFloat(rgbaMatch[1]!)),\n      g: clampByte(parseFloat(rgbaMatch[2]!)),\n      b: clampByte(parseFloat(rgbaMatch[3]!)),\n      a: rgbaMatch[4] !== undefined ? clamp01(parseFloat(rgbaMatch[4]!)) : 1,\n    };\n  }\n\n  let hex = raw.replace(/^#/, '');\n  if (/^[0-9a-f]{3}$/i.test(hex)) {\n    hex = hex\n      .split('')\n      .map((c) => c + c)\n      .join('');\n  }\n  if (/^[0-9a-f]{6}$/i.test(hex)) {\n    return {\n      r: parseInt(hex.slice(0, 2), 16),\n      g: parseInt(hex.slice(2, 4), 16),\n      b: parseInt(hex.slice(4, 6), 16),\n      a: 1,\n    };\n  }\n  if (/^[0-9a-f]{8}$/i.test(hex)) {\n    return {\n      r: parseInt(hex.slice(0, 2), 16),\n      g: parseInt(hex.slice(2, 4), 16),\n      b: parseInt(hex.slice(4, 6), 16),\n      a: clampByte(parseInt(hex.slice(6, 8), 16)) / 255,\n    };\n  }\n\n  return fallback;\n}\n\nexport function isValidCssColorInput(input: string): boolean {\n  const t = input.trim();\n  if (!t) return false;\n  if (/^transparent$/i.test(t) || /^none$/i.test(t)) return true;\n  if (/^#?[0-9a-f]{3}$/i.test(t) || /^#?[0-9a-f]{6}$/i.test(t) || /^#?[0-9a-f]{8}$/i.test(t)) {\n    return true;\n  }\n  return /^rgba?\\(\\s*[\\d.]+\\s*,\\s*[\\d.]+\\s*,\\s*[\\d.]+(?:\\s*,\\s*[\\d.]+)?\\s*\\)$/i.test(t);\n}\n\n/** True for no-fill / no-stroke CSS (`transparent`, `none`, empty, Spanish transparente). */\nexport function isNoneCssColor(input: string | null | undefined): boolean {\n  const t = String(input ?? '')\n    .trim()\n    .toLowerCase();\n  return !t || t === 'transparent' || t === 'transparente' || t === 'none';\n}\n\nexport type HsvColor = { h: number; s: number; v: number };\n\nexport function rgbToHsv(r: number, g: number, b: number): HsvColor {\n  const rr = clampByte(r) / 255;\n  const gg = clampByte(g) / 255;\n  const bb = clampByte(b) / 255;\n  const max = Math.max(rr, gg, bb);\n  const min = Math.min(rr, gg, bb);\n  const d = max - min;\n  let h = 0;\n  if (d !== 0) {\n    if (max === rr) h = ((gg - bb) / d) % 6;\n    else if (max === gg) h = (bb - rr) / d + 2;\n    else h = (rr - gg) / d + 4;\n    h *= 60;\n    if (h < 0) h += 360;\n  }\n  const s = max === 0 ? 0 : d / max;\n  return { h, s, v: max };\n}\n\nexport function hsvToRgb(h: number, s: number, v: number): { r: number; g: number; b: number } {\n  const hh = ((h % 360) + 360) % 360;\n  const ss = clamp01(s);\n  const vv = clamp01(v);\n  const c = vv * ss;\n  const x = c * (1 - Math.abs(((hh / 60) % 2) - 1));\n  const m = vv - c;\n  let rp = 0;\n  let gp = 0;\n  let bp = 0;\n  if (hh < 60) {\n    rp = c;\n    gp = x;\n  } else if (hh < 120) {\n    rp = x;\n    gp = c;\n  } else if (hh < 180) {\n    gp = c;\n    bp = x;\n  } else if (hh < 240) {\n    gp = x;\n    bp = c;\n  } else if (hh < 300) {\n    rp = x;\n    bp = c;\n  } else {\n    rp = c;\n    bp = x;\n  }\n  return {\n    r: clampByte((rp + m) * 255),\n    g: clampByte((gp + m) * 255),\n    b: clampByte((bp + m) * 255),\n  };\n}\n", "/** System / bundled faces that do not need a Google Fonts stylesheet. */\nconst SAFE_FONTS = new Set([\n  'Arial',\n  'Helvetica',\n  'Georgia',\n  'Courier New',\n  'Impact',\n  'Times New Roman',\n  'Verdana',\n  'Inter',\n]);\n\n/** Nonsense family so canvas measureText falls through when the face is missing. */\nconst MISSING_FAMILY = '__we_missing_font__';\n\nconst pendingLoads = new Map<string, Promise<void>>();\n\nlet measureCtx: CanvasRenderingContext2D | null = null;\n\nconst getMeasureCtx = (): CanvasRenderingContext2D | null => {\n  if (typeof document === 'undefined') return null;\n  if (measureCtx) return measureCtx;\n  const canvas = document.createElement('canvas');\n  measureCtx = canvas.getContext('2d');\n  return measureCtx;\n};\n\nconst cleanFamily = (fontFamily: string): string =>\n  String(fontFamily || '')\n    .replace(/[\"']/g, '')\n    .trim();\n\n/** Map CSS keywords to numeric weights Google Fonts / FontFaceSet expect. */\nexport const normalizeFontWeight = (weight: string | number | undefined): string => {\n  if (weight === undefined || weight === null || weight === '') return '400';\n  const w = String(weight).toLowerCase();\n  if (w === 'normal') return '400';\n  if (w === 'bold') return '700';\n  if (w === 'lighter') return '300';\n  if (w === 'bolder') return '700';\n  return String(weight);\n};\n\nconst fontShort = (\n  family: string,\n  size: number,\n  weight: string,\n  style: string,\n  withMissingFallback = true,\n): string => {\n  const fallback = withMissingFallback ? `, ${MISSING_FAMILY}` : '';\n  return `${style} ${weight} ${size}px \"${family}\"${fallback}`;\n};\n\nconst canvasTextWidth = (fontCss: string, sample: string): number => {\n  const ctx = getMeasureCtx();\n  if (!ctx) return 0;\n  ctx.font = fontCss;\n  return ctx.measureText(sample).width;\n};\n\n/**\n * True when the face is registered AND canvas measureText is no longer using\n * the missing-fallback (Chromium often resolves fonts.load early with swap).\n */\nexport function isFontMetricsReady(\n  fontFamily: string,\n  opts: { size?: number; weight?: string | number; style?: string } = {},\n): boolean {\n  const family = cleanFamily(fontFamily);\n  if (!family) return true;\n  if (SAFE_FONTS.has(family)) return true;\n  if (typeof document === 'undefined' || !document.fonts) return true;\n\n  const size = Math.max(1, opts.size ?? 40);\n  const weight = normalizeFontWeight(opts.weight);\n  const style = opts.style || 'normal';\n  const sample = 'Hg\u00EDWm@|MWxy';\n\n  // Prefer numeric weight \u2014 matches @font-face descriptors from Google CSS.\n  const checkSpecs = [\n    `${style} ${weight} ${size}px \"${family}\"`,\n    `normal ${weight} ${size}px \"${family}\"`,\n    `${weight} ${size}px \"${family}\"`,\n  ];\n  const checked = checkSpecs.some((spec) => {\n    try {\n      return document.fonts!.check(spec);\n    } catch {\n      return false;\n    }\n  });\n  if (!checked) return false;\n\n  const withFace = canvasTextWidth(fontShort(family, size, weight, style, true), sample);\n  const missingOnly = canvasTextWidth(\n    `${style} ${weight} ${size}px ${MISSING_FAMILY}`,\n    sample,\n  );\n  // Real face must diverge from the missing-only measurement.\n  return Math.abs(withFace - missingOnly) > 0.5;\n}\n\nconst injectGoogleStylesheet = (family: string): Promise<void> => {\n  const fontId = `google-font-${family.replace(/\\s+/g, '-').toLowerCase()}`;\n  const existing = document.getElementById(fontId) as HTMLLinkElement | null;\n  if (existing) {\n    // Link may still be downloading \u2014 wait for load if not complete.\n    if (existing.dataset.weLoaded === '1') return Promise.resolve();\n    return new Promise<void>((resolve) => {\n      const done = () => {\n        existing.dataset.weLoaded = '1';\n        resolve();\n      };\n      existing.addEventListener('load', done, { once: true });\n      existing.addEventListener('error', done, { once: true });\n      // Already cached / previously fired load before we attached listeners.\n      if (existing.sheet) done();\n      else setTimeout(done, 80);\n    });\n  }\n\n  return new Promise<void>((resolve) => {\n    const link = document.createElement('link');\n    link.id = fontId;\n    link.rel = 'stylesheet';\n    link.href = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(family).replace(/%20/g, '+')}:wght@300;400;500;600;700;800;900&display=swap`;\n    const done = () => {\n      link.dataset.weLoaded = '1';\n      resolve();\n    };\n    link.onload = done;\n    link.onerror = done;\n    document.head.appendChild(link);\n  });\n};\n\nconst loadFaceVariants = async (\n  family: string,\n  size: number,\n  weight: string,\n  style: string,\n): Promise<void> => {\n  if (!document.fonts?.load) return;\n  // Request both keyword and numeric forms \u2014 browsers disagree which matches\n  // the @font-face from Google (Poppins and others are especially picky).\n  const specs = Array.from(\n    new Set([\n      `${style} ${weight} ${size}px \"${family}\"`,\n      `${style} ${normalizeFontWeight(weight)} ${size}px \"${family}\"`,\n      `normal ${normalizeFontWeight(weight)} ${size}px \"${family}\"`,\n      `400 ${size}px \"${family}\"`,\n      `700 ${size}px \"${family}\"`,\n      `normal 400 ${size}px \"${family}\"`,\n    ]),\n  );\n  await Promise.all(\n    specs.map((spec) => document.fonts!.load(spec).catch(() => undefined)),\n  );\n  try {\n    await document.fonts.ready;\n  } catch {\n    /* ignore */\n  }\n};\n\nexport type EnsureFontOptions = {\n  size?: number;\n  weight?: string | number;\n  style?: string;\n  /** Max wait for real canvas metrics (ms). */\n  timeoutMs?: number;\n};\n\n/**\n * Inject the Google Fonts stylesheet (if needed) and wait until canvas\n * measureText uses the real face \u2014 not merely until fonts.load resolves.\n * Works for any remote family (Poppins, display faces, etc.), not one-offs.\n */\nexport async function ensureFontReady(\n  fontFamily: string,\n  opts: EnsureFontOptions = {},\n): Promise<void> {\n  const family = cleanFamily(fontFamily);\n  if (!family || SAFE_FONTS.has(family)) return;\n  if (typeof document === 'undefined') return;\n\n  const size = Math.max(1, opts.size ?? 40);\n  const weight = normalizeFontWeight(opts.weight);\n  const style = opts.style || 'normal';\n  const timeoutMs = opts.timeoutMs ?? 4000;\n\n  const cacheKey = `${family}::${style}::${weight}::${size}`;\n  let pending = pendingLoads.get(cacheKey);\n  if (!pending) {\n    pending = (async () => {\n      await injectGoogleStylesheet(family);\n      await loadFaceVariants(family, size, weight, style);\n\n      if (isFontMetricsReady(family, { size, weight, style })) return;\n\n      const deadline = Date.now() + timeoutMs;\n      while (Date.now() < deadline) {\n        await loadFaceVariants(family, size, weight, style);\n        if (isFontMetricsReady(family, { size, weight, style })) return;\n        await new Promise<void>((r) => setTimeout(r, 32));\n      }\n    })().finally(() => {\n      pendingLoads.delete(cacheKey);\n    });\n    pendingLoads.set(cacheKey, pending);\n  }\n  await pending;\n}\n\n/** @deprecated Prefer ensureFontReady \u2014 kept for call sites that only know the family. */\nexport async function ensureGoogleFontLoaded(fontFamily: string): Promise<void> {\n  await ensureFontReady(fontFamily);\n}\n\nexport function isSystemFontFamily(fontFamily: string): boolean {\n  return SAFE_FONTS.has(cleanFamily(fontFamily));\n}\n", "import { FabricImage, Point, type Canvas, type FabricObject } from 'fabric';\nimport { parseCssColor } from './colorRgba';\n\n/**\n * Fabric custom props that must survive toJSON / loadFromJSON.\n * Keep CanvasArea + useEditorStore assignments in sync via this list.\n */\nexport const WE_FABRIC_CUSTOM_PROPERTIES = [\n  'id',\n  'name',\n  'locked',\n  'selectable',\n  'evented',\n  'curvature',\n  'globalCompositeOperation',\n  'eraserPaths',\n  'clippedToLayerId',\n  'isClipPathMask',\n  'linkId',\n  'chartData',\n  'chartType',\n  'chartOptions',\n  'weCornerRadii',\n  'weCornersLinked',\n  'weTextAutoWidth',\n  'wePixelLayer',\n  'weBaseLayer',\n] as const;\n\nexport type PixelLayerImage = FabricImage & {\n  wePixelLayer?: boolean;\n  /** @deprecated No longer used \u2014 file layer = bottom-most pixel layer. */\n  weBaseLayer?: boolean;\n  /** True content buffer when a layer mask is present (Fabric element is composited). */\n  weContentCanvas?: HTMLCanvasElement;\n  /** Grayscale mask: white = visible, black = hidden. */\n  weMaskCanvas?: HTMLCanvasElement | null;\n  /** Composited content\u00D7mask shown on the Fabric object (reused across refreshes). */\n  weDisplayCanvas?: HTMLCanvasElement;\n  /** Chain link between layer and mask (mask follows layer). */\n  weMaskLinked?: boolean;\n  /**\n   * Opaque content AABB in layer-buffer pixels (not page size).\n   * Selection chrome uses this \u2014 never the full page buffer.\n   */\n  weOpaqueBounds?: { x: number; y: number; w: number; h: number } | null;\n  name?: string;\n  id?: string;\n  locked?: boolean;\n};\n\nexport function isPixelLayer(obj: FabricObject | null | undefined): obj is PixelLayerImage {\n  if (!obj) return false;\n  const layer = obj as PixelLayerImage;\n  return layer.wePixelLayer === true || layer.weContentCanvas instanceof HTMLCanvasElement;\n}\n\nexport function hasLayerMask(layer: PixelLayerImage): boolean {\n  return !!layer.weMaskCanvas;\n}\n\n/** @deprecated Use isFileLayer(canvas, obj) \u2014 bottom pixel layer is the file layer. */\nexport function isBaseLayer(obj: FabricObject | null | undefined): obj is PixelLayerImage {\n  return isPixelLayer(obj) && (obj as PixelLayerImage).weBaseLayer === true;\n}\n\nexport function isFabricImage(obj: FabricObject | null | undefined): obj is FabricImage {\n  return !!obj && (obj.type || '').toLowerCase() === 'image';\n}\n\n/** Bottom-most pixel layer on the canvas (file layer / last in the stack). */\nexport function getBottomPixelLayer(canvas: Canvas): PixelLayerImage | null {\n  for (const o of canvas.getObjects()) {\n    if (isPixelLayer(o as FabricObject)) return o as PixelLayerImage;\n  }\n  return null;\n}\n\nexport function isFileLayer(canvas: Canvas, obj: FabricObject | null | undefined): boolean {\n  if (!obj || !isPixelLayer(obj)) return false;\n  return getBottomPixelLayer(canvas) === obj;\n}\n\nexport function pixelLayerHasContent(layer: PixelLayerImage): boolean {\n  if (layer.weOpaqueBounds !== undefined) return layer.weOpaqueBounds !== null;\n  const el = ensurePixelLayerCanvas(layer);\n  const bounds = getOpaqueBounds(el);\n  layer.weOpaqueBounds = bounds;\n  return bounds !== null;\n}\n\n/**\n * Hit-test the opaque CONTENT AABB (selection chrome box), not the full\n * page-sized buffer and not per-pixel alpha. Transparent holes inside the\n * box stay draggable; padding outside does not steal clicks from layers below.\n */\nfunction pointInPixelLayerContent(layer: PixelLayerImage, sceneX: number, sceneY: number): boolean {\n  let bounds = layer.weOpaqueBounds;\n  if (bounds === undefined) {\n    bounds = getOpaqueBounds(ensurePixelLayerCanvas(layer));\n    layer.weOpaqueBounds = bounds;\n  }\n  if (!bounds || bounds.w < 1 || bounds.h < 1) return false;\n  const local = sceneToLayerPixel(layer, sceneX, sceneY);\n  const pad = 3;\n  return (\n    local.x >= bounds.x - pad &&\n    local.x <= bounds.x + bounds.w + pad &&\n    local.y >= bounds.y - pad &&\n    local.y <= bounds.y + bounds.h + pad\n  );\n}\n\n/** Empty layers: selectable but no move/scale/rotate. Chrome is DOM-only. */\nexport function syncPixelLayerInteraction(layer: PixelLayerImage): void {\n  const empty = !pixelLayerHasContent(layer);\n  layer.set({\n    selectable: true,\n    evented: true,\n    objectCaching: false,\n    // SelectionControlsOverlay draws chrome; keep Fabric native handles off.\n    hasControls: false,\n    hasBorders: false,\n    lockMovementX: empty,\n    lockMovementY: empty,\n    lockScalingX: empty,\n    lockScalingY: empty,\n    lockRotation: empty,\n    lockSkewingX: empty,\n    lockSkewingY: empty,\n  });\n  // perPixelTargetFind / containsPoint set below based on empty vs content.\n  if (typeof layer.setControlsVisibility === 'function') {\n    layer.setControlsVisibility({\n      tl: false,\n      tr: false,\n      bl: false,\n      br: false,\n      ml: false,\n      mt: false,\n      mr: false,\n      mb: false,\n      mtr: false,\n    });\n  }\n\n  if (empty) {\n    // Full buffer hit so blank layers stay clickable; no opaque content to hug.\n    layer.containsPoint = FabricImage.prototype.containsPoint;\n    layer.set({ perPixelTargetFind: false });\n  } else {\n    // Geometric hit on content AABB only \u2014 never per-pixel alpha, so empty\n    // pixels inside the selection box still start a move drag.\n    layer.set({ perPixelTargetFind: false });\n    layer.containsPoint = function (\n      this: PixelLayerImage,\n      point: Point,\n      _absolute?: boolean,\n      _calculate?: boolean,\n    ) {\n      return pointInPixelLayerContent(this, point.x, point.y);\n    };\n  }\n  layer.setCoords();\n}\n\n/** Clear all pixels; keep the Fabric object at page size (file-layer delete). */\nexport function clearPixelLayerContent(\n  layer: PixelLayerImage,\n  pageW?: number,\n  pageH?: number,\n): void {\n  const w = Math.max(1, Math.round(pageW ?? layer.width ?? 1));\n  const h = Math.max(1, Math.round(pageH ?? layer.height ?? 1));\n  const el = document.createElement('canvas');\n  el.width = w;\n  el.height = h;\n  layer.weContentCanvas = el;\n  if (layer.weMaskCanvas) {\n    const mask = document.createElement('canvas');\n    mask.width = w;\n    mask.height = h;\n    fillWhite(mask);\n    layer.weMaskCanvas = mask;\n  }\n  const patch: Record<string, unknown> = {\n    scaleX: 1,\n    scaleY: 1,\n    dirty: true,\n  };\n  if (pageW != null && pageH != null) {\n    patch.left = pageW / 2;\n    patch.top = pageH / 2;\n    patch.originX = 'center';\n    patch.originY = 'center';\n    patch.angle = 0;\n  }\n  layer.set(patch);\n  refreshPixelLayerDisplay(layer);\n  syncPixelLayerInteraction(layer);\n}\n\n/**\n * Layer name from a file name / URL / upload label.\n * Strips paths, \"Imagen:\" prefixes, and trailing ellipsis.\n */\nexport function layerNameFromFileName(raw: string): string {\n  let s = (raw || '').trim();\n  if (!s) return 'capa';\n  s = s.replace(/^imagen:\\s*/i, '');\n  s = s.replace(/\\.\\.\\.\\s*$/, '');\n  s = s.replace(/^.*[\\\\/]/, '');\n  // Drop query string from URLs used as names\n  s = s.split('?')[0] || s;\n  s = s.trim();\n  return s || 'capa';\n}\n\n/** Photoshop-style pixel layer: selectable and movable when it has content. */\nexport function configurePixelLayer(img: PixelLayerImage): void {\n  syncPixelLayerInteraction(img);\n}\n\n/** After history/JSON load, keep wePixelLayer objects interactive (movable). */\nexport function reconfigureAllPixelLayers(canvas: Canvas): void {\n  hydratePixelLayersAfterLoad(canvas);\n}\n\n/** @deprecated Use configurePixelLayer \u2014 layers are movable. */\nexport const applyPixelLayerLocks = (\n  img: PixelLayerImage,\n  _pageW?: number,\n  _pageH?: number,\n): void => {\n  configurePixelLayer(img);\n};\n\n/** @deprecated Use reconfigureAllPixelLayers */\nexport const reapplyAllPixelLayerLocks = (\n  canvas: Canvas,\n  _pageW?: number,\n  _pageH?: number,\n): void => {\n  reconfigureAllPixelLayers(canvas);\n};\n\n/** Next name: `capa` then `capa-1`, `capa-2`, \u2026 (or `layer` / `layer-1` in EN). */\nexport function nextPixelLayerName(existing: FabricObject[], base: string): string {\n  const prefix = base.toLowerCase();\n  const names = existing\n    .filter((o) => isPixelLayer(o))\n    .map((o) => ((o as { name?: string }).name || '').toLowerCase());\n\n  if (!names.some((n) => n === prefix || n.startsWith(`${prefix}-`))) {\n    return base;\n  }\n\n  let max = 0;\n  for (const n of names) {\n    if (n === prefix) {\n      max = Math.max(max, 0);\n      continue;\n    }\n    const m = n.match(new RegExp(`^${escapeRegExp(prefix)}-(\\\\d+)$`));\n    if (m?.[1]) max = Math.max(max, parseInt(m[1], 10));\n  }\n  return `${base}-${max + 1}`;\n}\n\nfunction escapeRegExp(s: string): string {\n  return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction layerOriginFractions(layer: PixelLayerImage): { ox: number; oy: number } {\n  const ox = layer.originX === 'center' ? 0.5 : layer.originX === 'right' ? 1 : 0;\n  const oy = layer.originY === 'center' ? 0.5 : layer.originY === 'bottom' ? 1 : 0;\n  return { ox, oy };\n}\n\n/** Ensure the layer content buffer is a mutable HTMLCanvasElement. */\nexport function ensurePixelLayerCanvas(layer: PixelLayerImage): HTMLCanvasElement {\n  if (layer.weContentCanvas instanceof HTMLCanvasElement) {\n    return layer.weContentCanvas;\n  }\n\n  const el = layer.getElement();\n  if (el instanceof HTMLCanvasElement) {\n    layer.weContentCanvas = el;\n    return el;\n  }\n\n  // Prefer the element's natural pixel size after JSON reload (data-URL images),\n  // not Fabric's possibly-stale width/height \u2014 mismatch inflates selection chrome.\n  const natW = Math.round(\n    (el as HTMLImageElement).naturalWidth ||\n      (el as HTMLImageElement).width ||\n      layer.width ||\n      1,\n  );\n  const natH = Math.round(\n    (el as HTMLImageElement).naturalHeight ||\n      (el as HTMLImageElement).height ||\n      layer.height ||\n      1,\n  );\n  const w = Math.max(1, natW);\n  const h = Math.max(1, natH);\n  const canvas = document.createElement('canvas');\n  canvas.width = w;\n  canvas.height = h;\n  const ctx = canvas.getContext('2d');\n  if (ctx && el) ctx.drawImage(el as CanvasImageSource, 0, 0, w, h);\n  layer.weContentCanvas = canvas;\n  if (!layer.weMaskCanvas) layer.setElement(canvas);\n  // Keep Fabric object space 1:1 with the content buffer.\n  if (layer.width !== w || layer.height !== h) {\n    layer.set({ width: w, height: h });\n  }\n  return canvas;\n}\n\n/**\n * After loadFromJSON / undo: rebuild content buffers and sync Fabric size so\n * selection chrome matches opaque content (avoids slightly oversized boxes).\n * Also re-promotes plain Fabric images that lost `wePixelLayer` on serialize.\n */\nexport function hydratePixelLayersAfterLoad(canvas: Canvas): void {\n  for (const obj of canvas.getObjects()) {\n    if (!isFabricImage(obj as FabricObject)) continue;\n    if (shouldSkipPixelLayerPromotion(obj as FabricObject)) continue;\n\n    const layer = asPixelLayer(obj as FabricImage);\n    layer.weContentCanvas = undefined;\n    layer.weDisplayCanvas = undefined;\n    layer.weOpaqueBounds = undefined;\n    const el = ensurePixelLayerCanvas(layer);\n    if (layer.width !== el.width || layer.height !== el.height) {\n      layer.set({ width: el.width, height: el.height });\n    }\n    refreshPixelLayerDisplay(layer);\n    refreshPixelLayerContentBounds(layer);\n    configurePixelLayer(layer);\n  }\n}\n\n/** Overlay / mask helpers that must stay plain Fabric images. */\nexport function shouldSkipPixelLayerPromotion(obj: FabricObject): boolean {\n  const meta = obj as FabricObject & {\n    name?: string;\n    isClipPathMask?: boolean;\n    isImageCropOverlay?: boolean;\n  };\n  if (meta.isClipPathMask || meta.isImageCropOverlay) return true;\n  const name = meta.name || '';\n  return (\n    name === 'clone-stamp-layer' ||\n    name === 'eraser-mark' ||\n    name === 'canva-frame' ||\n    name === 'frame-placeholder'\n  );\n}\n\n/** Composite content \u00D7 mask luminance into the Fabric display element. */\nfunction ensureDisplayCanvas(layer: PixelLayerImage, w: number, h: number): HTMLCanvasElement {\n  let out = layer.weDisplayCanvas;\n  if (!out || out.width !== w || out.height !== h) {\n    out = document.createElement('canvas');\n    out.width = w;\n    out.height = h;\n    layer.weDisplayCanvas = out;\n  }\n  return out;\n}\n\nfunction applyMaskAlphaToImageData(img: ImageData, maskPixels: Uint8ClampedArray): void {\n  const d = img.data;\n  for (let i = 0; i < d.length; i += 4) {\n    const lum = (maskPixels[i]! + maskPixels[i + 1]! + maskPixels[i + 2]!) / (3 * 255);\n    d[i + 3] = Math.round(d[i + 3]! * lum);\n  }\n}\n\n/**\n * Recomposite content \u00D7 mask into the Fabric display element.\n * Pass `region` (layer-local px) while painting so only the dab area is updated.\n */\nexport function refreshPixelLayerDisplay(\n  layer: PixelLayerImage,\n  region?: { x: number; y: number; w: number; h: number },\n): void {\n  // Content pixels changed \u2014 drop AABB cache used by selection chrome.\n  layer.weOpaqueBounds = undefined;\n  const content = ensurePixelLayerCanvas(layer);\n  const mask = layer.weMaskCanvas;\n  if (!mask) {\n    layer.weDisplayCanvas = undefined;\n    if (layer.getElement?.() !== content) layer.setElement(content);\n    layer.set({ dirty: true });\n    layer.setCoords();\n    return;\n  }\n\n  const w = content.width;\n  const h = content.height;\n  const prev = layer.weDisplayCanvas;\n  const sizeChanged = !prev || prev.width !== w || prev.height !== h;\n  const out = ensureDisplayCanvas(layer, w, h);\n  const ctx = out.getContext('2d', { willReadFrequently: true });\n  if (!ctx) return;\n\n  // New/resized display buffer must be filled fully before dirty-rect updates.\n  const full = sizeChanged || !region;\n  const rx = full ? 0 : Math.max(0, Math.floor(region!.x));\n  const ry = full ? 0 : Math.max(0, Math.floor(region!.y));\n  const rw = full ? w : Math.min(w - rx, Math.ceil(region!.x + region!.w) - rx);\n  const rh = full ? h : Math.min(h - ry, Math.ceil(region!.y + region!.h) - ry);\n  if (rw < 1 || rh < 1) return;\n\n  try {\n    const cctx = content.getContext('2d', { willReadFrequently: true });\n    const mctx = mask.getContext('2d', { willReadFrequently: true });\n    if (!cctx || !mctx) {\n      ctx.drawImage(content, rx, ry, rw, rh, rx, ry, rw, rh);\n    } else if (mask.width === w && mask.height === h) {\n      const img = cctx.getImageData(rx, ry, rw, rh);\n      applyMaskAlphaToImageData(img, mctx.getImageData(rx, ry, rw, rh).data);\n      ctx.putImageData(img, rx, ry);\n    } else {\n      ctx.drawImage(content, 0, 0);\n      const img = ctx.getImageData(0, 0, w, h);\n      const tmp = document.createElement('canvas');\n      tmp.width = w;\n      tmp.height = h;\n      const tctx = tmp.getContext('2d');\n      if (tctx) {\n        tctx.drawImage(mask, 0, 0, w, h);\n        applyMaskAlphaToImageData(img, tctx.getImageData(0, 0, w, h).data);\n        ctx.putImageData(img, 0, 0);\n      }\n    }\n  } catch {\n    ctx.drawImage(content, rx, ry, rw, rh, rx, ry, rw, rh);\n  }\n\n  if (layer.getElement?.() !== out) layer.setElement(out);\n  layer.set({ dirty: true });\n  if (full) layer.setCoords();\n}\n\nfunction fillWhite(canvas: HTMLCanvasElement): void {\n  const ctx = canvas.getContext('2d');\n  if (!ctx) return;\n  ctx.fillStyle = '#ffffff';\n  ctx.fillRect(0, 0, canvas.width, canvas.height);\n}\n\n/** Add a white (fully visible) layer mask linked to the layer. */\nexport function addLayerMask(layer: PixelLayerImage): void {\n  const content = ensurePixelLayerCanvas(layer);\n  if (layer.weMaskCanvas) return;\n  const mask = document.createElement('canvas');\n  mask.width = content.width;\n  mask.height = content.height;\n  fillWhite(mask);\n  layer.weMaskCanvas = mask;\n  layer.weMaskLinked = true;\n  refreshPixelLayerDisplay(layer);\n  syncPixelLayerInteraction(layer);\n}\n\n/** Remove the layer mask and restore content as the display element. */\nexport function removeLayerMask(layer: PixelLayerImage): void {\n  if (!layer.weMaskCanvas) return;\n  layer.weMaskCanvas = null;\n  layer.weMaskLinked = false;\n  layer.weDisplayCanvas = undefined;\n  const content = ensurePixelLayerCanvas(layer);\n  layer.setElement(content);\n  layer.set({ dirty: true });\n  syncPixelLayerInteraction(layer);\n}\n\n/** Thumbnail of the grayscale mask (checker under empty). */\nexport function getLayerMaskThumbnailDataUrl(\n  layer: PixelLayerImage,\n  size = 40,\n): string | null {\n  const mask = layer.weMaskCanvas;\n  if (!mask || mask.width < 1 || mask.height < 1) return null;\n  try {\n    const thumb = document.createElement('canvas');\n    thumb.width = size;\n    thumb.height = size;\n    const ctx = thumb.getContext('2d');\n    if (!ctx) return null;\n    const scale = Math.min(size / mask.width, size / mask.height);\n    const dw = Math.max(1, Math.round(mask.width * scale));\n    const dh = Math.max(1, Math.round(mask.height * scale));\n    const dx = Math.floor((size - dw) / 2);\n    const dy = Math.floor((size - dh) / 2);\n    ctx.fillStyle = '#27272a';\n    ctx.fillRect(0, 0, size, size);\n    ctx.drawImage(mask, dx, dy, dw, dh);\n    return thumb.toDataURL('image/png');\n  } catch {\n    return null;\n  }\n}\n\n/** Map any CSS color to opaque grayscale (mask painting). */\nexport function cssColorToMaskGray(css: string): string {\n  const { r, g, b } = parseCssColor(css || '#ffffff');\n  const lum = Math.round(0.2126 * r + 0.7152 * g + 0.0722 * b);\n  const hex = lum.toString(16).padStart(2, '0');\n  return `#${hex}${hex}${hex}`;\n}\n\n/**\n * Grow the layer content (and mask) so `rect` (layer-local px) fits inside.\n * Returns how much existing pixels were shifted (dx, dy) in the new canvas.\n */\nexport function expandPixelLayerToIncludeRect(\n  layer: PixelLayerImage,\n  rect: { x: number; y: number; w: number; h: number },\n): { dx: number; dy: number } {\n  const el = ensurePixelLayerCanvas(layer);\n  const pad = 1;\n  const x0 = Math.floor(Math.min(0, rect.x) - (rect.x < 0 ? pad : 0));\n  const y0 = Math.floor(Math.min(0, rect.y) - (rect.y < 0 ? pad : 0));\n  const x1 = Math.ceil(Math.max(el.width, rect.x + rect.w) + (rect.x + rect.w > el.width ? pad : 0));\n  const y1 = Math.ceil(Math.max(el.height, rect.y + rect.h) + (rect.y + rect.h > el.height ? pad : 0));\n\n  if (x0 === 0 && y0 === 0 && x1 === el.width && y1 === el.height) {\n    return { dx: 0, dy: 0 };\n  }\n\n  const nw = Math.max(1, x1 - x0);\n  const nh = Math.max(1, y1 - y0);\n  const next = document.createElement('canvas');\n  next.width = nw;\n  next.height = nh;\n  const ctx = next.getContext('2d');\n  if (ctx) ctx.drawImage(el, -x0, -y0);\n\n  if (layer.weMaskCanvas) {\n    const nextMask = document.createElement('canvas');\n    nextMask.width = nw;\n    nextMask.height = nh;\n    fillWhite(nextMask);\n    const mctx = nextMask.getContext('2d');\n    if (mctx) mctx.drawImage(layer.weMaskCanvas, -x0, -y0);\n    layer.weMaskCanvas = nextMask;\n  }\n\n  const sx = layer.scaleX || 1;\n  const sy = layer.scaleY || 1;\n  const { ox, oy } = layerOriginFractions(layer);\n  const oldW = el.width * sx;\n  const oldH = el.height * sy;\n  const tlX = (layer.left || 0) - oldW * ox;\n  const tlY = (layer.top || 0) - oldH * oy;\n  const newTlX = tlX + x0 * sx;\n  const newTlY = tlY + y0 * sy;\n  const newW = nw * sx;\n  const newH = nh * sy;\n\n  layer.weContentCanvas = next;\n  refreshPixelLayerDisplay(layer);\n  layer.set({\n    left: newTlX + newW * ox,\n    top: newTlY + newH * oy,\n    dirty: true,\n  });\n  layer.setCoords();\n  return { dx: -x0, dy: -y0 };\n}\n\n/** Opaque pixel AABB, or null if fully transparent / unreadable.\n * Never returns the full canvas on failure \u2014 that made selection chrome\n * hug the page instead of the layer content.\n */\nexport function getOpaqueBounds(\n  el: HTMLCanvasElement,\n  alphaThreshold = 12,\n): { x: number; y: number; w: number; h: number } | null {\n  const ctx = el.getContext('2d', { willReadFrequently: true });\n  if (!ctx) return null;\n  const { width, height } = el;\n  if (width < 1 || height < 1) return null;\n  let data: ImageData;\n  try {\n    data = ctx.getImageData(0, 0, width, height);\n  } catch {\n    // Tainted canvas \u2014 caller must use stamped weOpaqueBounds instead.\n    return null;\n  }\n  const px = data.data;\n  const thr = Math.max(1, Math.min(255, alphaThreshold));\n  let minX = width;\n  let minY = height;\n  let maxX = -1;\n  let maxY = -1;\n  for (let y = 0; y < height; y++) {\n    for (let x = 0; x < width; x++) {\n      if (px[(y * width + x) * 4 + 3]! >= thr) {\n        if (x < minX) minX = x;\n        if (y < minY) minY = y;\n        if (x > maxX) maxX = x;\n        if (y > maxY) maxY = y;\n      }\n    }\n  }\n  if (maxX < 0) return null;\n  return { x: minX, y: minY, w: maxX - minX + 1, h: maxY - minY + 1 };\n}\n\nexport function unionOpaqueBounds(\n  a: { x: number; y: number; w: number; h: number } | null | undefined,\n  b: { x: number; y: number; w: number; h: number } | null | undefined,\n): { x: number; y: number; w: number; h: number } | null {\n  if (!a) return b ?? null;\n  if (!b) return a;\n  const x0 = Math.min(a.x, b.x);\n  const y0 = Math.min(a.y, b.y);\n  const x1 = Math.max(a.x + a.w, b.x + b.w);\n  const y1 = Math.max(a.y + a.h, b.y + b.h);\n  return { x: x0, y: y0, w: Math.max(1, x1 - x0), h: Math.max(1, y1 - y0) };\n}\n\n/** Recompute or keep stamped content bounds after buffer edits. */\nexport function refreshPixelLayerContentBounds(\n  layer: PixelLayerImage,\n  fallback?: { x: number; y: number; w: number; h: number } | null,\n): void {\n  const el = ensurePixelLayerCanvas(layer);\n  const existing = fallback ?? (layer.weOpaqueBounds !== undefined ? layer.weOpaqueBounds : null);\n  const scanned = getOpaqueBounds(el);\n\n  // Prefer a real pixel scan. Fall back to stamped bounds when the canvas is\n  // tainted or empty after a rebake.\n  if (scanned) {\n    layer.weOpaqueBounds = scanned;\n    return;\n  }\n  if (existing && existing.w >= 1 && existing.h >= 1) {\n    layer.weOpaqueBounds = existing;\n    return;\n  }\n  layer.weOpaqueBounds = null;\n}\n\n/** True when the canvas has at most one object. */\nexport function isSoleCanvasLayer(canvas: Canvas): boolean {\n  return canvas.getObjects().length <= 1;\n}\n\nexport type DeleteLayerOrClearResult = 'removed' | 'cleared' | 'blocked';\n\n/**\n * Remove a layer, or clear its content when it is the only remaining layer.\n * Empty layers are allowed \u2014 sole-layer delete clears pixels / replaces non-images\n * with a blank page-sized pixel layer instead of blocking.\n */\nexport function deleteLayerOrClearContent(\n  canvas: Canvas,\n  obj: FabricObject,\n  pageW: number,\n  pageH: number,\n  blankLayerName = 'capa',\n): DeleteLayerOrClearResult {\n  if (!isSoleCanvasLayer(canvas)) {\n    canvas.remove(obj);\n    return 'removed';\n  }\n\n  if (isPixelLayer(obj)) {\n    const layer = obj as PixelLayerImage;\n    if (!pixelLayerHasContent(layer)) return 'blocked';\n    clearPixelLayerContent(layer, pageW, pageH);\n    canvas.setActiveObject(layer);\n    return 'cleared';\n  }\n\n  const type = (obj.type || '').toLowerCase();\n  if (obj instanceof FabricImage || type === 'image') {\n    const layer = asPixelLayer(obj as FabricImage);\n    clearPixelLayerContent(layer, pageW, pageH);\n    canvas.setActiveObject(layer);\n    return 'cleared';\n  }\n\n  // Text / shape as sole object: replace with an empty pixel layer.\n  const name = (typeof (obj as { name?: unknown }).name === 'string' && (obj as { name: string }).name)\n    || blankLayerName;\n  canvas.remove(obj);\n  const blank = createBlankPixelLayer(pageW, pageH, name, {\n    centerX: pageW / 2,\n    centerY: pageH / 2,\n  });\n  canvas.add(blank);\n  canvas.setActiveObject(blank);\n  return 'cleared';\n}\n\n/** Sole layer can be deleted only when it still has content to clear. */\nexport function canClearOrDeleteLayer(canvas: Canvas, obj: FabricObject | null | undefined): boolean {\n  if (!obj) return false;\n  if (!isSoleCanvasLayer(canvas)) return true;\n  if (isPixelLayer(obj)) return pixelLayerHasContent(obj as PixelLayerImage);\n  return true;\n}\n\nfunction isFullBufferBounds(\n  b: { x: number; y: number; w: number; h: number },\n  bufW: number,\n  bufH: number,\n): boolean {\n  return b.x <= 1 && b.y <= 1 && b.w >= bufW - 2 && b.h >= bufH - 2;\n}\n\n/**\n * Rebake the layer into an exact page-sized buffer at 1:1 scale, centered on\n * the page. Content stays visually in place (drawn via the current transform).\n * Call before paint tools so clicks on empty artboard hit transparent pixels.\n */\nexport function ensurePixelLayerCoversPage(\n  layer: PixelLayerImage,\n  pageW: number,\n  pageH: number,\n): void {\n  const pw = Math.max(1, Math.round(pageW));\n  const ph = Math.max(1, Math.round(pageH));\n  const el = ensurePixelLayerCanvas(layer);\n  const sx = layer.scaleX || 1;\n  const sy = layer.scaleY || 1;\n  const angle = layer.angle || 0;\n  const atPage =\n    el.width === pw &&\n    el.height === ph &&\n    Math.abs(sx - 1) < 0.001 &&\n    Math.abs(sy - 1) < 0.001 &&\n    Math.abs(angle) < 0.001 &&\n    layer.originX === 'center' &&\n    layer.originY === 'center' &&\n    Math.abs((layer.left || 0) - pw / 2) < 0.5 &&\n    Math.abs((layer.top || 0) - ph / 2) < 0.5;\n\n  if (atPage) {\n    syncPixelLayerInteraction(layer);\n    return;\n  }\n\n  const page = document.createElement('canvas');\n  page.width = pw;\n  page.height = ph;\n  const ctx = page.getContext('2d');\n  if (!ctx) return;\n\n  const { ox, oy } = layerOriginFractions(layer);\n  const fw = Math.max(1, layer.width || el.width);\n  const fh = Math.max(1, layer.height || el.height);\n  const rad = (angle * Math.PI) / 180;\n  const flipX = layer.flipX ? -1 : 1;\n  const flipY = layer.flipY ? -1 : 1;\n\n  ctx.save();\n  ctx.translate(layer.left || 0, layer.top || 0);\n  ctx.rotate(rad);\n  ctx.scale(sx * flipX, sy * flipY);\n  ctx.drawImage(el, -fw * ox, -fh * oy, fw, fh);\n  ctx.restore();\n\n  if (layer.weMaskCanvas) {\n    const nextMask = document.createElement('canvas');\n    nextMask.width = pw;\n    nextMask.height = ph;\n    fillWhite(nextMask);\n    const mctx = nextMask.getContext('2d');\n    if (mctx) {\n      mctx.save();\n      mctx.translate(layer.left || 0, layer.top || 0);\n      mctx.rotate(rad);\n      mctx.scale(sx * flipX, sy * flipY);\n      mctx.drawImage(layer.weMaskCanvas, -fw * ox, -fh * oy, fw, fh);\n      mctx.restore();\n    }\n    layer.weMaskCanvas = nextMask;\n  }\n\n  layer.weContentCanvas = page;\n  layer.weDisplayCanvas = undefined;\n  layer.setElement(page);\n  layer.set({\n    left: pw / 2,\n    top: ph / 2,\n    originX: 'center',\n    originY: 'center',\n    scaleX: 1,\n    scaleY: 1,\n    angle: 0,\n    flipX: false,\n    flipY: false,\n    width: pw,\n    height: ph,\n    dirty: true,\n  });\n  refreshPixelLayerDisplay(layer);\n  refreshPixelLayerContentBounds(layer);\n  layer.setCoords();\n  syncPixelLayerInteraction(layer);\n}\n\n/** Promote a FabricImage to a pixel layer (mutates in place). */\nexport function asPixelLayer(img: FabricImage): PixelLayerImage {\n  const layer = img as PixelLayerImage;\n  if (!layer.wePixelLayer) {\n    layer.wePixelLayer = true;\n    layer.set('wePixelLayer', true);\n    ensurePixelLayerCanvas(layer);\n    configurePixelLayer(layer);\n  } else {\n    // Ensure Fabric serializes the flag even if only the JS property was set.\n    layer.set('wePixelLayer', true);\n  }\n  return layer;\n}\n\n/** Axis-aligned scene box of opaque content (null if empty). */\nexport function getPixelLayerContentSceneAabb(\n  layer: PixelLayerImage,\n): {\n  left: number;\n  right: number;\n  top: number;\n  bottom: number;\n  centerX: number;\n  centerY: number;\n  width: number;\n  height: number;\n} | null {\n  const corners = getPixelLayerContentSceneCorners(layer);\n  if (!corners || corners.length < 4) return null;\n  const xs = corners.map((p) => p.x);\n  const ys = corners.map((p) => p.y);\n  const left = Math.min(...xs);\n  const right = Math.max(...xs);\n  const top = Math.min(...ys);\n  const bottom = Math.max(...ys);\n  return {\n    left,\n    right,\n    top,\n    bottom,\n    centerX: (left + right) / 2,\n    centerY: (top + bottom) / 2,\n    width: Math.max(1, right - left),\n    height: Math.max(1, bottom - top),\n  };\n}\n\n/**\n * Map opaque CONTENT corners into scene space (for selection chrome).\n * Uses weOpaqueBounds when set; otherwise scans opaque pixels.\n * Content-sized layers (buffer === image) legitimately use full-buffer bounds.\n */\nexport function getPixelLayerContentSceneCorners(\n  layer: PixelLayerImage,\n): { x: number; y: number }[] | null {\n  const el = ensurePixelLayerCanvas(layer);\n  const bufW = Math.max(1, el.width);\n  const bufH = Math.max(1, el.height);\n\n  if (Math.abs((layer.width || 0) - bufW) > 0.5 || Math.abs((layer.height || 0) - bufH) > 0.5) {\n    layer.set({ width: bufW, height: bufH });\n  }\n\n  let bounds = layer.weOpaqueBounds;\n  if (bounds === undefined) {\n    bounds = getOpaqueBounds(el);\n    layer.weOpaqueBounds = bounds;\n  }\n  if (!bounds || bounds.w < 1 || bounds.h < 1) return null;\n\n  const sx = layer.scaleX || 1;\n  const sy = layer.scaleY || 1;\n  const angleDeg = layer.angle || 0;\n  const { ox, oy } = layerOriginFractions(layer);\n  // Top-left of the full buffer in scene space (axis-aligned).\n  const baseLeft = (layer.left || 0) - bufW * sx * ox;\n  const baseTop = (layer.top || 0) - bufH * sy * oy;\n  const cos = Math.cos((angleDeg * Math.PI) / 180);\n  const sin = Math.sin((angleDeg * Math.PI) / 180);\n  const cx = layer.left || 0;\n  const cy = layer.top || 0;\n\n  const local = [\n    { x: bounds.x, y: bounds.y },\n    { x: bounds.x + bounds.w, y: bounds.y },\n    { x: bounds.x + bounds.w, y: bounds.y + bounds.h },\n    { x: bounds.x, y: bounds.y + bounds.h },\n  ];\n\n  return local.map((p) => {\n    let x = baseLeft + p.x * sx;\n    let y = baseTop + p.y * sy;\n    if (angleDeg !== 0) {\n      const dx = x - cx;\n      const dy = y - cy;\n      x = cx + dx * cos - dy * sin;\n      y = cy + dx * sin + dy * cos;\n    }\n    return { x, y };\n  });\n}\n\n/** Content-center origin fractions (0\u20131) within the layer bitmap, or null if empty. */\nexport function getPixelLayerContentOriginFractions(\n  layer: PixelLayerImage,\n): { ox: number; oy: number; contentW: number; contentH: number } | null {\n  const el = ensurePixelLayerCanvas(layer);\n  const bufW = Math.max(1, el.width);\n  const bufH = Math.max(1, el.height);\n  if (Math.abs((layer.width || 0) - bufW) > 0.5 || Math.abs((layer.height || 0) - bufH) > 0.5) {\n    layer.set({ width: bufW, height: bufH });\n  }\n  let bounds = layer.weOpaqueBounds;\n  if (bounds === undefined) {\n    bounds = getOpaqueBounds(el);\n    layer.weOpaqueBounds = bounds;\n  }\n  if (!bounds) return null;\n  return {\n    ox: (bounds.x + bounds.w / 2) / bufW,\n    oy: (bounds.y + bounds.h / 2) / bufH,\n    contentW: bounds.w,\n    contentH: bounds.h,\n  };\n}\n\n/**\n * Shrink the layer bitmap to its opaque content bounds (keeps scene position).\n * Skips empty layers. Prefer page-sized buffers for paint tools \u2014 only use when\n * explicitly trimming is required.\n */\nexport function fitPixelLayerToContent(layer: PixelLayerImage): void {\n  const el = ensurePixelLayerCanvas(layer);\n  const bounds = getOpaqueBounds(el);\n  if (!bounds) {\n    refreshPixelLayerDisplay(layer);\n    syncPixelLayerInteraction(layer);\n    return;\n  }\n  if (bounds.x === 0 && bounds.y === 0 && bounds.w === el.width && bounds.h === el.height) {\n    refreshPixelLayerDisplay(layer);\n    layer.weOpaqueBounds = { x: 0, y: 0, w: el.width, h: el.height };\n    syncPixelLayerInteraction(layer);\n    return;\n  }\n\n  const next = document.createElement('canvas');\n  next.width = Math.max(1, bounds.w);\n  next.height = Math.max(1, bounds.h);\n  const ctx = next.getContext('2d');\n  if (!ctx) return;\n  ctx.drawImage(el, bounds.x, bounds.y, bounds.w, bounds.h, 0, 0, bounds.w, bounds.h);\n\n  if (layer.weMaskCanvas) {\n    const nextMask = document.createElement('canvas');\n    nextMask.width = next.width;\n    nextMask.height = next.height;\n    fillWhite(nextMask);\n    const mctx = nextMask.getContext('2d');\n    if (mctx) {\n      mctx.drawImage(\n        layer.weMaskCanvas,\n        bounds.x,\n        bounds.y,\n        bounds.w,\n        bounds.h,\n        0,\n        0,\n        bounds.w,\n        bounds.h,\n      );\n    }\n    layer.weMaskCanvas = nextMask;\n  }\n\n  const sx = layer.scaleX || 1;\n  const sy = layer.scaleY || 1;\n  const { ox, oy } = layerOriginFractions(layer);\n  const oldW = el.width * sx;\n  const oldH = el.height * sy;\n  const tlX = (layer.left || 0) - oldW * ox;\n  const tlY = (layer.top || 0) - oldH * oy;\n  const newTlX = tlX + bounds.x * sx;\n  const newTlY = tlY + bounds.y * sy;\n  const newW = bounds.w * sx;\n  const newH = bounds.h * sy;\n\n  layer.weContentCanvas = next;\n  refreshPixelLayerDisplay(layer);\n  layer.set({\n    left: newTlX + newW * ox,\n    top: newTlY + newH * oy,\n    width: next.width,\n    height: next.height,\n    dirty: true,\n  });\n  layer.weOpaqueBounds = { x: 0, y: 0, w: next.width, h: next.height };\n  layer.setCoords();\n  syncPixelLayerInteraction(layer);\n}\n\n/** Rasterize any Fabric object into a new pixel layer (same scene bounds). */\nexport function rasterizeObjectToPixelLayer(\n  canvas: Canvas,\n  obj: FabricObject,\n  name?: string,\n): PixelLayerImage | null {\n  const toCanvas = (\n    obj as FabricObject & {\n      toCanvasElement?: (opts?: Record<string, unknown>) => HTMLCanvasElement;\n    }\n  ).toCanvasElement?.({\n    enableRetinaScaling: false,\n    multiplier: 1,\n  });\n  if (!toCanvas || toCanvas.width < 1 || toCanvas.height < 1) return null;\n\n  const center = obj.getCenterPoint();\n  const layer = createBlankPixelLayer(toCanvas.width, toCanvas.height, name || 'capa', {\n    centerX: center.x,\n    centerY: center.y,\n  });\n  layer.set({\n    angle: 0,\n    scaleX: 1,\n    scaleY: 1,\n    flipX: false,\n    flipY: false,\n  });\n  const el = ensurePixelLayerCanvas(layer);\n  const ctx = el.getContext('2d');\n  if (!ctx) return null;\n  ctx.drawImage(toCanvas, 0, 0);\n  layer.weContentCanvas = el;\n  refreshPixelLayerDisplay(layer);\n  layer.weOpaqueBounds = { x: 0, y: 0, w: el.width, h: el.height };\n  syncPixelLayerInteraction(layer);\n\n  const idx = canvas.getObjects().indexOf(obj);\n  canvas.remove(obj);\n  if (idx >= 0) canvas.insertAt(idx, layer);\n  else canvas.add(layer);\n  return layer;\n}\n\n/** Create a transparent raster layer of the given pixel size. */\nexport function createBlankPixelLayer(\n  width: number,\n  height: number,\n  name: string,\n  opts?: { centerX?: number; centerY?: number },\n): PixelLayerImage {\n  const w = Math.max(1, Math.round(width));\n  const h = Math.max(1, Math.round(height));\n  const el = document.createElement('canvas');\n  el.width = w;\n  el.height = h;\n  const cx = opts?.centerX ?? w / 2;\n  const cy = opts?.centerY ?? h / 2;\n  const img = new FabricImage(el, {\n    left: cx,\n    top: cy,\n    originX: 'center',\n    originY: 'center',\n    objectCaching: false,\n  }) as PixelLayerImage;\n  img.wePixelLayer = true;\n  img.weContentCanvas = el;\n  img.weOpaqueBounds = null;\n  img.set('wePixelLayer', true);\n  img.name = name;\n  img.id = `pixel-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n  configurePixelLayer(img);\n  return img;\n}\n\n/** Deep-clone a FabricImage so raster buffers are not shared. */\nexport function cloneFabricImageElement(src: FabricImage): HTMLCanvasElement {\n  const srcEl = src.getElement() as HTMLImageElement | HTMLCanvasElement;\n  const w = Math.max(1, srcEl.width || Math.round(src.width || 1));\n  const h = Math.max(1, srcEl.height || Math.round(src.height || 1));\n  const el = document.createElement('canvas');\n  el.width = w;\n  el.height = h;\n  const ctx = el.getContext('2d');\n  if (ctx) ctx.drawImage(srcEl, 0, 0, w, h);\n  return el;\n}\n\n/** Small PNG data-URL preview for the layers list (checkerboard under transparency).\n * Crops to opaque content so page-sized buffers don't look like a blank canvas.\n */\nexport function getPixelLayerThumbnailDataUrl(\n  layer: PixelLayerImage,\n  size = 40,\n): string | null {\n  try {\n    const el = ensurePixelLayerCanvas(layer);\n    const bounds =\n      (layer.weOpaqueBounds && layer.weOpaqueBounds.w >= 1 && layer.weOpaqueBounds.h >= 1\n        ? layer.weOpaqueBounds\n        : null) ?? getOpaqueBounds(el);\n    if (!bounds) return null;\n\n    const thumb = document.createElement('canvas');\n    thumb.width = size;\n    thumb.height = size;\n    const ctx = thumb.getContext('2d');\n    if (!ctx) return null;\n    const cell = 4;\n    for (let y = 0; y < size; y += cell) {\n      for (let x = 0; x < size; x += cell) {\n        ctx.fillStyle = (x / cell + y / cell) % 2 === 0 ? '#3f3f46' : '#27272a';\n        ctx.fillRect(x, y, cell, cell);\n      }\n    }\n    const scale = Math.min(size / bounds.w, size / bounds.h);\n    const dw = Math.max(1, bounds.w * scale);\n    const dh = Math.max(1, bounds.h * scale);\n    const dx = (size - dw) / 2;\n    const dy = (size - dh) / 2;\n    ctx.drawImage(el, bounds.x, bounds.y, bounds.w, bounds.h, dx, dy, dw, dh);\n    return thumb.toDataURL('image/png');\n  } catch {\n    return null;\n  }\n}\n\n/** Draw a raster source into a pixel layer; expands the layer if needed. */\nexport function stampSourceIntoPixelLayer(\n  layer: PixelLayerImage,\n  source: CanvasImageSource,\n  dest: { x: number; y: number; w: number; h: number },\n): void {\n  const prevBounds =\n    layer.weOpaqueBounds &&\n    !isFullBufferBounds(layer.weOpaqueBounds, ensurePixelLayerCanvas(layer).width, ensurePixelLayerCanvas(layer).height)\n      ? layer.weOpaqueBounds\n      : null;\n  const { dx, dy } = expandPixelLayerToIncludeRect(layer, dest);\n  const el = ensurePixelLayerCanvas(layer);\n  const ctx = el.getContext('2d');\n  if (!ctx) return;\n  ctx.drawImage(source, dest.x + dx, dest.y + dy, dest.w, dest.h);\n  layer.weContentCanvas = el;\n  const stamped = {\n    x: Math.round(dest.x + dx),\n    y: Math.round(dest.y + dy),\n    w: Math.max(1, Math.round(dest.w)),\n    h: Math.max(1, Math.round(dest.h)),\n  };\n  const shiftedPrev =\n    prevBounds && (dx !== 0 || dy !== 0)\n      ? { ...prevBounds, x: prevBounds.x + dx, y: prevBounds.y + dy }\n      : prevBounds;\n  refreshPixelLayerDisplay(layer);\n  // Stamp rect is the source of truth for content chrome (not page buffer size).\n  layer.weOpaqueBounds = unionOpaqueBounds(shiftedPrev, stamped);\n  layer.set({ dirty: true });\n  layer.setCoords();\n  syncPixelLayerInteraction(layer);\n}\n\n/** Map a scene (page) point into the pixel layer's canvas pixel coords. */\nexport function sceneToLayerPixel(\n  layer: PixelLayerImage,\n  sceneX: number,\n  sceneY: number,\n): { x: number; y: number } {\n  const el = ensurePixelLayerCanvas(layer);\n  const sx = layer.scaleX || 1;\n  const sy = layer.scaleY || 1;\n  const w = (layer.width || el.width) * sx;\n  const h = (layer.height || el.height) * sy;\n  const { ox, oy } = layerOriginFractions(layer);\n  const left = (layer.left || 0) - w * ox;\n  const top = (layer.top || 0) - h * oy;\n  return {\n    x: (sceneX - left) / sx,\n    y: (sceneY - top) / sy,\n  };\n}\n\n/** Stamp a free-draw Path into a pixel layer content or mask. */\nexport function bakePathIntoPixelLayer(\n  canvas: Canvas,\n  path: FabricObject,\n  layer: PixelLayerImage,\n  opts?: { erase?: boolean; multiply?: boolean; target?: 'content' | 'mask' },\n): void {\n  const pathCanvas = (\n    path as FabricObject & {\n      toCanvasElement?: (opts?: Record<string, unknown>) => HTMLCanvasElement;\n    }\n  ).toCanvasElement?.({\n    enableRetinaScaling: false,\n    multiplier: 1,\n  });\n  if (!pathCanvas) return;\n\n  const paintMask = opts?.target === 'mask' && !!layer.weMaskCanvas;\n  const center = path.getCenterPoint();\n  const local = sceneToLayerPixel(layer, center.x, center.y);\n  const sx = layer.scaleX || 1;\n  const sy = layer.scaleY || 1;\n  const drawW = pathCanvas.width / sx;\n  const drawH = pathCanvas.height / sy;\n  const dest = {\n    x: local.x - drawW / 2,\n    y: local.y - drawH / 2,\n    w: drawW,\n    h: drawH,\n  };\n\n  const { dx, dy } = expandPixelLayerToIncludeRect(layer, dest);\n\n  if (paintMask && layer.weMaskCanvas) {\n    const mask = layer.weMaskCanvas;\n    const ctx = mask.getContext('2d');\n    if (!ctx) {\n      canvas.remove(path);\n      return;\n    }\n    ctx.save();\n    if (opts?.erase) {\n      // Erasing on a mask restores white (fully visible).\n      ctx.globalCompositeOperation = 'source-over';\n      ctx.fillStyle = '#ffffff';\n      // Stamp path as white via destination \u2014 draw white then clip with path alpha.\n      const tmp = document.createElement('canvas');\n      tmp.width = pathCanvas.width;\n      tmp.height = pathCanvas.height;\n      const tctx = tmp.getContext('2d');\n      if (tctx) {\n        tctx.fillStyle = '#ffffff';\n        tctx.fillRect(0, 0, tmp.width, tmp.height);\n        tctx.globalCompositeOperation = 'destination-in';\n        tctx.drawImage(pathCanvas, 0, 0);\n        ctx.drawImage(tmp, dest.x + dx, dest.y + dy, dest.w, dest.h);\n      }\n    } else {\n      ctx.globalCompositeOperation = 'source-over';\n      ctx.drawImage(pathCanvas, dest.x + dx, dest.y + dy, dest.w, dest.h);\n    }\n    ctx.restore();\n    refreshPixelLayerDisplay(layer);\n    syncPixelLayerInteraction(layer);\n  } else {\n    const el = ensurePixelLayerCanvas(layer);\n    const ctx = el.getContext('2d');\n    if (!ctx) {\n      canvas.remove(path);\n      return;\n    }\n\n    ctx.save();\n    if (opts?.erase) {\n      ctx.globalCompositeOperation = 'destination-out';\n    } else if (opts?.multiply) {\n      ctx.globalCompositeOperation = 'multiply';\n    }\n    ctx.drawImage(pathCanvas, dest.x + dx, dest.y + dy, dest.w, dest.h);\n    ctx.restore();\n\n    layer.weContentCanvas = el;\n    refreshPixelLayerDisplay(layer);\n    // Prefer opaque scan (tight to ink); fall back to stroke AABB.\n    const scanned = getOpaqueBounds(el);\n    const strokeBounds = {\n      x: Math.round(dest.x + dx),\n      y: Math.round(dest.y + dy),\n      w: Math.max(1, Math.round(dest.w)),\n      h: Math.max(1, Math.round(dest.h)),\n    };\n    layer.weOpaqueBounds = scanned ?? strokeBounds;\n    syncPixelLayerInteraction(layer);\n  }\n\n  canvas.remove(path);\n  canvas.setActiveObject(layer);\n  canvas.requestRenderAll();\n}\n", "/**\n * Photoshop-style magic wand: select similar pixels by color + tolerance.\n */\n\nimport { Point, util } from 'fabric';\n\nexport type MagicWandMask = {\n  width: number;\n  height: number;\n  /** 1 = selected, 0 = not */\n  data: Uint8Array;\n  bounds: { minX: number; minY: number; maxX: number; maxY: number };\n  pixelCount: number;\n};\n\nexport type MagicWandSampleOptions = {\n  /** 0\u2013255 Euclidean RGB distance. Default 32. */\n  tolerance: number;\n  /** If true, only 4-connected flood fill from seed. If false, all similar pixels. */\n  contiguous: boolean;\n  /** Allow sampling transparent seeds (paint bucket fills empty areas). */\n  allowTransparentSeed?: boolean;\n};\n\nfunction colorDist(\n  r1: number,\n  g1: number,\n  b1: number,\n  r2: number,\n  g2: number,\n  b2: number,\n): number {\n  const dr = r1 - r2;\n  const dg = g1 - g2;\n  const db = b1 - b2;\n  return Math.sqrt(dr * dr + dg * dg + db * db);\n}\n\n/**\n * Build a selection mask from ImageData at (startX, startY).\n * Returns null when the seed is transparent / out of bounds / empty.\n */\nexport function computeMagicWandMask(\n  imageData: ImageData,\n  startX: number,\n  startY: number,\n  opts: MagicWandSampleOptions,\n): MagicWandMask | null {\n  const { width, height, data } = imageData;\n  const sx = Math.min(width - 1, Math.max(0, Math.round(startX)));\n  const sy = Math.min(height - 1, Math.max(0, Math.round(startY)));\n  const seedIdx = (sy * width + sx) * 4;\n  const seedR = data[seedIdx] ?? 0;\n  const seedG = data[seedIdx + 1] ?? 0;\n  const seedB = data[seedIdx + 2] ?? 0;\n  const seedA = data[seedIdx + 3] ?? 0;\n  const seedTransparent = seedA < 8;\n  if (seedTransparent && !opts.allowTransparentSeed) return null;\n\n  const tolerance = Math.max(0, Math.min(255, opts.tolerance));\n  const mask = new Uint8Array(width * height);\n  let pixelCount = 0;\n  let minX = width;\n  let minY = height;\n  let maxX = 0;\n  let maxY = 0;\n\n  const mark = (nIdx: number) => {\n    if (mask[nIdx] === 1) return;\n    mask[nIdx] = 1;\n    pixelCount += 1;\n    const x = nIdx % width;\n    const y = (nIdx / width) | 0;\n    if (x < minX) minX = x;\n    if (y < minY) minY = y;\n    if (x > maxX) maxX = x;\n    if (y > maxY) maxY = y;\n  };\n\n  const matches = (nIdx: number) => {\n    const p = nIdx * 4;\n    const a = data[p + 3] ?? 0;\n    if (seedTransparent) return a < 8;\n    if (a < 8) return false;\n    return (\n      colorDist(\n        data[p] ?? 0,\n        data[p + 1] ?? 0,\n        data[p + 2] ?? 0,\n        seedR,\n        seedG,\n        seedB,\n      ) <= tolerance\n    );\n  };\n\n  if (opts.contiguous) {\n    const queue = new Int32Array(width * height);\n    let qh = 0;\n    let qt = 0;\n    const start = sy * width + sx;\n    queue[qt++] = start;\n    mark(start);\n\n    while (qh < qt) {\n      const idx = queue[qh++]!;\n      const cx = idx % width;\n      const cy = (idx / width) | 0;\n      const neighbors = [\n        idx - 1,\n        idx + 1,\n        idx - width,\n        idx + width,\n      ];\n      const valid = [\n        cx > 0,\n        cx < width - 1,\n        cy > 0,\n        cy < height - 1,\n      ];\n      for (let i = 0; i < 4; i++) {\n        if (!valid[i]) continue;\n        const nIdx = neighbors[i]!;\n        if (mask[nIdx] === 1) continue;\n        if (!matches(nIdx)) continue;\n        mark(nIdx);\n        queue[qt++] = nIdx;\n      }\n    }\n  } else {\n    for (let i = 0; i < width * height; i++) {\n      if (matches(i)) mark(i);\n    }\n  }\n\n  if (pixelCount === 0) return null;\n\n  return {\n    width,\n    height,\n    data: mask,\n    bounds: { minX, minY, maxX, maxY },\n    pixelCount,\n  };\n}\n\nexport type SelectionCombineMode = 'new' | 'add' | 'subtract';\n\nfunction recountMask(data: Uint8Array, width: number, height: number): MagicWandMask | null {\n  let pixelCount = 0;\n  let minX = width;\n  let minY = height;\n  let maxX = 0;\n  let maxY = 0;\n  for (let i = 0; i < data.length; i++) {\n    if (data[i] !== 1) continue;\n    pixelCount += 1;\n    const x = i % width;\n    const y = (i / width) | 0;\n    if (x < minX) minX = x;\n    if (y < minY) minY = y;\n    if (x > maxX) maxX = x;\n    if (y > maxY) maxY = y;\n  }\n  if (pixelCount === 0) return null;\n  return {\n    width,\n    height,\n    data,\n    bounds: { minX, minY, maxX, maxY },\n    pixelCount,\n  };\n}\n\n/** Merge a new mask into an existing one (Photoshop add / subtract). */\nexport function combineMasks(\n  base: MagicWandMask | null,\n  next: MagicWandMask,\n  mode: SelectionCombineMode,\n): MagicWandMask | null {\n  if (!base || mode === 'new' || base.width !== next.width || base.height !== next.height) {\n    return mode === 'subtract' ? (base ?? null) : next;\n  }\n\n  const data = new Uint8Array(base.width * base.height);\n  for (let i = 0; i < data.length; i++) {\n    if (mode === 'add') {\n      data[i] = base.data[i] === 1 || next.data[i] === 1 ? 1 : 0;\n    } else {\n      data[i] = base.data[i] === 1 && next.data[i] !== 1 ? 1 : 0;\n    }\n  }\n  return recountMask(data, base.width, base.height);\n}\n\n/** Point-in-polygon (ray cast) for pixel-space lasso. */\nfunction pointInPoly(x: number, y: number, pts: { x: number; y: number }[]): boolean {\n  let inside = false;\n  for (let i = 0, j = pts.length - 1; i < pts.length; j = i++) {\n    const a = pts[i];\n    const b = pts[j];\n    if (!a || !b) continue;\n    const intersect =\n      a.y > y !== b.y > y &&\n      x < ((b.x - a.x) * (y - a.y)) / ((b.y - a.y) || 1e-6) + a.x;\n    if (intersect) inside = !inside;\n  }\n  return inside;\n}\n\n/** Build a mask from a closed polygon in image pixel coordinates. */\nexport function maskFromPolygon(\n  width: number,\n  height: number,\n  points: { x: number; y: number }[],\n): MagicWandMask | null {\n  if (points.length < 3 || width < 1 || height < 1) return null;\n\n  let minX = width;\n  let minY = height;\n  let maxX = 0;\n  let maxY = 0;\n  for (const p of points) {\n    minX = Math.min(minX, Math.floor(p.x));\n    minY = Math.min(minY, Math.floor(p.y));\n    maxX = Math.max(maxX, Math.ceil(p.x));\n    maxY = Math.max(maxY, Math.ceil(p.y));\n  }\n  minX = Math.max(0, minX);\n  minY = Math.max(0, minY);\n  maxX = Math.min(width - 1, maxX);\n  maxY = Math.min(height - 1, maxY);\n\n  const data = new Uint8Array(width * height);\n  let pixelCount = 0;\n  let bMinX = width;\n  let bMinY = height;\n  let bMaxX = 0;\n  let bMaxY = 0;\n\n  for (let y = minY; y <= maxY; y++) {\n    for (let x = minX; x <= maxX; x++) {\n      if (!pointInPoly(x + 0.5, y + 0.5, points)) continue;\n      const idx = y * width + x;\n      data[idx] = 1;\n      pixelCount += 1;\n      if (x < bMinX) bMinX = x;\n      if (y < bMinY) bMinY = y;\n      if (x > bMaxX) bMaxX = x;\n      if (y > bMaxY) bMaxY = y;\n    }\n  }\n\n  if (pixelCount === 0) return null;\n  return {\n    width,\n    height,\n    data,\n    bounds: { minX: bMinX, minY: bMinY, maxX: bMaxX, maxY: bMaxY },\n    pixelCount,\n  };\n}\n\n/** Axis-aligned rectangular lasso in image pixel coordinates. */\nexport function maskFromRect(\n  width: number,\n  height: number,\n  x0: number,\n  y0: number,\n  x1: number,\n  y1: number,\n): MagicWandMask | null {\n  if (width < 1 || height < 1) return null;\n  const left = Math.max(0, Math.floor(Math.min(x0, x1)));\n  const top = Math.max(0, Math.floor(Math.min(y0, y1)));\n  const right = Math.min(width - 1, Math.floor(Math.max(x0, x1)));\n  const bottom = Math.min(height - 1, Math.floor(Math.max(y0, y1)));\n  if (right < left || bottom < top) return null;\n\n  const data = new Uint8Array(width * height);\n  let pixelCount = 0;\n  for (let y = top; y <= bottom; y++) {\n    for (let x = left; x <= right; x++) {\n      data[y * width + x] = 1;\n      pixelCount += 1;\n    }\n  }\n  if (pixelCount === 0) return null;\n  return {\n    width,\n    height,\n    data,\n    bounds: { minX: left, minY: top, maxX: right, maxY: bottom },\n    pixelCount,\n  };\n}\n\n/** Elliptical / circular lasso in image pixel coordinates. */\nexport function maskFromEllipse(\n  width: number,\n  height: number,\n  x0: number,\n  y0: number,\n  x1: number,\n  y1: number,\n): MagicWandMask | null {\n  if (width < 1 || height < 1) return null;\n  const left = Math.min(x0, x1);\n  const top = Math.min(y0, y1);\n  const right = Math.max(x0, x1);\n  const bottom = Math.max(y0, y1);\n  const rx = (right - left) / 2;\n  const ry = (bottom - top) / 2;\n  if (rx < 0.5 || ry < 0.5) return null;\n  const cx = left + rx;\n  const cy = top + ry;\n\n  const minX = Math.max(0, Math.floor(left));\n  const minY = Math.max(0, Math.floor(top));\n  const maxX = Math.min(width - 1, Math.ceil(right));\n  const maxY = Math.min(height - 1, Math.ceil(bottom));\n\n  const data = new Uint8Array(width * height);\n  let pixelCount = 0;\n  let bMinX = width;\n  let bMinY = height;\n  let bMaxX = 0;\n  let bMaxY = 0;\n\n  for (let y = minY; y <= maxY; y++) {\n    for (let x = minX; x <= maxX; x++) {\n      const nx = (x + 0.5 - cx) / rx;\n      const ny = (y + 0.5 - cy) / ry;\n      if (nx * nx + ny * ny > 1) continue;\n      data[y * width + x] = 1;\n      pixelCount += 1;\n      if (x < bMinX) bMinX = x;\n      if (y < bMinY) bMinY = y;\n      if (x > bMaxX) bMaxX = x;\n      if (y > bMaxY) bMaxY = y;\n    }\n  }\n\n  if (pixelCount === 0) return null;\n  return {\n    width,\n    height,\n    data,\n    bounds: { minX: bMinX, minY: bMinY, maxX: bMaxX, maxY: bMaxY },\n    pixelCount,\n  };\n}\n\n/** Edge pixels of a mask (selected + has empty neighbor) \u2014 for marching-ants outline. */\nexport function extractMaskEdges(mask: Uint8Array, width: number, height: number): Uint8Array {\n  const edges = new Uint8Array(width * height);\n  for (let y = 0; y < height; y++) {\n    for (let x = 0; x < width; x++) {\n      const i = y * width + x;\n      if (mask[i] !== 1) continue;\n      const isEdge =\n        x === 0 ||\n        y === 0 ||\n        x === width - 1 ||\n        y === height - 1 ||\n        mask[i - 1] !== 1 ||\n        mask[i + 1] !== 1 ||\n        mask[i - width] !== 1 ||\n        mask[i + width] !== 1;\n      if (isEdge) edges[i] = 1;\n    }\n  }\n  return edges;\n}\n\n/**\n * Paint Photoshop-style marching ants onto a canvas context (native mask size).\n * `offset` advances each frame to animate the dash.\n */\nexport function paintMarchingAnts(\n  ctx: CanvasRenderingContext2D,\n  edges: Uint8Array,\n  width: number,\n  height: number,\n  offset: number,\n  period = 8,\n): void {\n  const img = ctx.createImageData(width, height);\n  const d = img.data;\n  const half = Math.max(1, (period / 2) | 0);\n  const periodSafe = Math.max(2, period | 0);\n  for (let i = 0; i < edges.length; i++) {\n    if (edges[i] !== 1) continue;\n    const x = i % width;\n    const y = (i / width) | 0;\n    const phase = (((x + y + offset) % periodSafe) + periodSafe) % periodSafe;\n    const isWhite = phase < half;\n    const p = i * 4;\n    const v = isWhite ? 255 : 0;\n    d[p] = v;\n    d[p + 1] = v;\n    d[p + 2] = v;\n    d[p + 3] = 255;\n  }\n  ctx.putImageData(img, 0, 0);\n}\n\n/** Semi-transparent accent preview of the mask (for overlay). */\nexport function maskToPreviewDataUrl(\n  mask: MagicWandMask,\n  rgba: [number, number, number, number] = [219, 39, 119, 120],\n): string {\n  const canvas = document.createElement('canvas');\n  canvas.width = mask.width;\n  canvas.height = mask.height;\n  const ctx = canvas.getContext('2d');\n  if (!ctx) return '';\n  const out = ctx.createImageData(mask.width, mask.height);\n  const d = out.data;\n  const [r, g, b, a] = rgba;\n  for (let i = 0; i < mask.data.length; i++) {\n    if (mask.data[i] !== 1) continue;\n    const p = i * 4;\n    d[p] = r;\n    d[p + 1] = g;\n    d[p + 2] = b;\n    d[p + 3] = a;\n  }\n  ctx.putImageData(out, 0, 0);\n  return canvas.toDataURL('image/png');\n}\n\nexport function applyMaskDelete(imageData: ImageData, mask: MagicWandMask): void {\n  const { data } = imageData;\n  for (let i = 0; i < mask.data.length; i++) {\n    if (mask.data[i] !== 1) continue;\n    const p = i * 4;\n    data[p + 3] = 0;\n  }\n}\n\nexport function applyMaskFill(\n  imageData: ImageData,\n  mask: MagicWandMask,\n  rgba: { r: number; g: number; b: number; a?: number },\n): void {\n  const { data } = imageData;\n  const a = Math.round((rgba.a ?? 1) * 255);\n  for (let i = 0; i < mask.data.length; i++) {\n    if (mask.data[i] !== 1) continue;\n    const p = i * 4;\n    data[p] = rgba.r;\n    data[p + 1] = rgba.g;\n    data[p + 2] = rgba.b;\n    data[p + 3] = a;\n  }\n}\n\n/**\n * Photoshop-style paint bucket: blend fill over matched pixels with opacity,\n * optionally softening edges (anti-alias) via a 3\u00D73 coverage blur.\n */\nexport function applyPaintBucketFill(\n  imageData: ImageData,\n  mask: MagicWandMask,\n  fill: { r: number; g: number; b: number },\n  opts: { opacity: number; antiAlias: boolean },\n): void {\n  const { width, height, data } = imageData;\n  const opacity = Math.max(0, Math.min(1, opts.opacity));\n  let coverage = new Float32Array(mask.data.length);\n  for (let i = 0; i < mask.data.length; i++) {\n    coverage[i] = mask.data[i] === 1 ? 1 : 0;\n  }\n\n  if (opts.antiAlias) {\n    const soft = new Float32Array(coverage.length);\n    for (let y = 0; y < height; y++) {\n      for (let x = 0; x < width; x++) {\n        let sum = 0;\n        let n = 0;\n        for (let dy = -1; dy <= 1; dy++) {\n          for (let dx = -1; dx <= 1; dx++) {\n            const nx = x + dx;\n            const ny = y + dy;\n            if (nx < 0 || ny < 0 || nx >= width || ny >= height) continue;\n            sum += coverage[ny * width + nx] ?? 0;\n            n += 1;\n          }\n        }\n        soft[y * width + x] = n > 0 ? sum / n : 0;\n      }\n    }\n    coverage = soft;\n  }\n\n  for (let i = 0; i < coverage.length; i++) {\n    const fa = (coverage[i] ?? 0) * opacity;\n    if (fa <= 0.001) continue;\n    const p = i * 4;\n    const sr = data[p] ?? 0;\n    const sg = data[p + 1] ?? 0;\n    const sb = data[p + 2] ?? 0;\n    const sa = (data[p + 3] ?? 0) / 255;\n    const outA = fa + sa * (1 - fa);\n    if (outA < 0.001) {\n      data[p] = 0;\n      data[p + 1] = 0;\n      data[p + 2] = 0;\n      data[p + 3] = 0;\n      continue;\n    }\n    data[p] = Math.round((fill.r * fa + sr * sa * (1 - fa)) / outA);\n    data[p + 1] = Math.round((fill.g * fa + sg * sa * (1 - fa)) / outA);\n    data[p + 2] = Math.round((fill.b * fa + sb * sa * (1 - fa)) / outA);\n    data[p + 3] = Math.round(outA * 255);\n  }\n}\n\n/** Full-size PNG with only selected pixels (rest transparent) \u2014 for cut-to-layer. */\nexport function extractMaskToFullDataUrl(\n  imageData: ImageData,\n  mask: MagicWandMask,\n): string {\n  const canvas = document.createElement('canvas');\n  canvas.width = mask.width;\n  canvas.height = mask.height;\n  const ctx = canvas.getContext('2d');\n  if (!ctx) return '';\n  const out = ctx.createImageData(mask.width, mask.height);\n  const src = imageData.data;\n  const dst = out.data;\n  for (let i = 0; i < mask.data.length; i++) {\n    if (mask.data[i] !== 1) continue;\n    const p = i * 4;\n    dst[p] = src[p] ?? 0;\n    dst[p + 1] = src[p + 1] ?? 0;\n    dst[p + 2] = src[p + 2] ?? 0;\n    dst[p + 3] = src[p + 3] ?? 0;\n  }\n  ctx.putImageData(out, 0, 0);\n  return canvas.toDataURL('image/png');\n}\n\n/** Rasterize a Fabric image element into ImageData (natural pixels). */\nexport function fabricImageToImageData(imgEl: CanvasImageSource, width: number, height: number): ImageData {\n  const canvas = document.createElement('canvas');\n  canvas.width = Math.max(1, Math.round(width));\n  canvas.height = Math.max(1, Math.round(height));\n  const ctx = canvas.getContext('2d', { willReadFrequently: true });\n  if (!ctx) return new ImageData(canvas.width, canvas.height);\n  try {\n    ctx.drawImage(imgEl, 0, 0, canvas.width, canvas.height);\n    return ctx.getImageData(0, 0, canvas.width, canvas.height);\n  } catch {\n    // Tainted canvas (missing CORS) \u2014 return empty so caller can toast.\n    return new ImageData(canvas.width, canvas.height);\n  }\n}\n\n/**\n * Read pixel data from a FabricImage, preferring untainted sources.\n * Falls back to Fabric's own rasterizer when the HTMLImageElement is CORS-tainted.\n */\nexport function fabricImageObjectToImageData(img: {\n  width?: number;\n  height?: number;\n  getElement: () => CanvasImageSource;\n  toCanvasElement?: (opts?: { multiplier?: number }) => HTMLCanvasElement;\n  toDataURL?: (opts?: { format?: string; multiplier?: number }) => string;\n}): ImageData {\n  const el = img.getElement();\n  const width = Math.max(\n    1,\n    Math.round(\n      (el as HTMLImageElement).naturalWidth ||\n        (el as HTMLCanvasElement).width ||\n        img.width ||\n        1,\n    ),\n  );\n  const height = Math.max(\n    1,\n    Math.round(\n      (el as HTMLImageElement).naturalHeight ||\n        (el as HTMLCanvasElement).height ||\n        img.height ||\n        1,\n    ),\n  );\n\n  const fromEl = fabricImageToImageData(el, width, height);\n  if (imageDataHasOpaquePixels(fromEl)) return fromEl;\n\n  // Element path failed (tainted/empty) \u2014 try Fabric raster without CSS zoom.\n  try {\n    if (typeof img.toCanvasElement === 'function') {\n      const baked = img.toCanvasElement({ multiplier: 1 });\n      const data = fabricImageToImageData(baked, baked.width, baked.height);\n      if (imageDataHasOpaquePixels(data)) {\n        if (baked.width === width && baked.height === height) return data;\n        return fabricImageToImageData(baked, width, height);\n      }\n    }\n  } catch {\n    /* keep empty fromEl */\n  }\n\n  return fromEl;\n}\n\nexport function imageDataHasOpaquePixels(imageData: ImageData): boolean {\n  const { data } = imageData;\n  for (let i = 3; i < data.length; i += 4) {\n    if ((data[i] ?? 0) > 0) return true;\n  }\n  return false;\n}\n\nexport function imageDataToCanvas(imageData: ImageData): HTMLCanvasElement {\n  const canvas = document.createElement('canvas');\n  canvas.width = imageData.width;\n  canvas.height = imageData.height;\n  const ctx = canvas.getContext('2d');\n  ctx?.putImageData(imageData, 0, 0);\n  return canvas;\n}\n\n/**\n * Map a scene-space point to natural image pixels.\n * Fabric 6 has no toLocalPoint \u2014 use sendPointToPlane + origin correction.\n * sendPointToPlane requires a real fabric.Point (plain {x,y} throws).\n */\nexport function scenePointToImagePixels(\n  img: {\n    width?: number;\n    height?: number;\n    originX?: string | number;\n    originY?: string | number;\n    calcTransformMatrix: () => number[];\n    getElement: () => CanvasImageSource;\n  },\n  sceneX: number,\n  sceneY: number,\n  opts?: { allowOutside?: boolean },\n): { px: number; py: number; width: number; height: number } | null {\n  const el = img.getElement();\n  const width = Math.max(\n    1,\n    Math.round(\n      (el as HTMLImageElement).naturalWidth ||\n        (el as HTMLCanvasElement).width ||\n        img.width ||\n        1,\n    ),\n  );\n  const height = Math.max(\n    1,\n    Math.round(\n      (el as HTMLImageElement).naturalHeight ||\n        (el as HTMLCanvasElement).height ||\n        img.height ||\n        1,\n    ),\n  );\n  const fabricW = Math.max(1, img.width || width);\n  const fabricH = Math.max(1, img.height || height);\n\n  const local = util.sendPointToPlane(\n    new Point(sceneX, sceneY),\n    undefined,\n    img.calcTransformMatrix(),\n  );\n\n  let lx = local.x;\n  let ly = local.y;\n  const ox = img.originX;\n  const oy = img.originY;\n  if (ox === 'center' || ox === 0.5) lx += fabricW / 2;\n  else if (ox === 'right' || ox === 1) lx += fabricW;\n  if (oy === 'center' || oy === 0.5) ly += fabricH / 2;\n  else if (oy === 'bottom' || oy === 1) ly += fabricH;\n\n  if (!opts?.allowOutside) {\n    if (lx < -0.5 || ly < -0.5 || lx > fabricW + 0.5 || ly > fabricH + 0.5) {\n      return null;\n    }\n  }\n\n  return {\n    px: (lx / fabricW) * width,\n    py: (ly / fabricH) * height,\n    width,\n    height,\n  };\n}\n", "import { filters, classRegistry } from 'fabric';\n\n/**\n * Levels Filter (Shadows, Midtones, Highlights)\n * Maps black, white and applies gamma correction to midtones\n */\ntype LevelsProps = {\n  black: number;\n  mid: number;\n  white: number;\n};\n\nexport class LevelsFilter extends filters.BaseFilter<'Levels', LevelsProps> {\n  declare black: number;\n  declare mid: number;\n  declare white: number;\n\n  static type = 'Levels';\n  static defaults = { black: 0, mid: 1, white: 255 };\n\n  applyTo2d({ imageData: { data } }: any) {\n    const black = this.black;\n    const white = this.white;\n    const mid = this.mid;\n    \n    if (black === 0 && white === 255 && mid === 1) return;\n\n    const gamma = mid === 1 ? 1 : 1 / mid;\n    const range = white - black || 1; // Prevent division by zero\n\n    for (let i = 0; i < data.length; i += 4) {\n      for (let j = 0; j < 3; j++) {\n        let val = data[i + j];\n        // Black and White point\n        val = (val - black) / range;\n        \n        // Clamp\n        if (val < 0) val = 0;\n        else if (val > 1) val = 1;\n        \n        // Midtone Gamma\n        if (gamma !== 1) {\n          val = Math.pow(val, gamma);\n        }\n        \n        data[i + j] = val * 255;\n      }\n    }\n  }\n\n  isNeutralState() {\n    return this.black === 0 && this.white === 255 && this.mid === 1;\n  }\n}\n\n/**\n * LUT Filter (Curves)\n * Applies a 256-value Look-Up Table to the RGB channels\n */\ntype LUTProps = {\n  lut: number[]; // Array of 256 values (0-255)\n};\n\nexport class LUTFilter extends filters.BaseFilter<'LUT', LUTProps> {\n  declare lut: number[];\n\n  static type = 'LUT';\n  static defaults = { lut: [] };\n\n  /** True when lut is missing or identity (i \u2192 i). */\n  static isIdentityLut(lut: number[] | undefined | null): boolean {\n    if (!lut || lut.length !== 256) return true;\n    for (let i = 0; i < 256; i++) {\n      if (lut[i] !== i) return false;\n    }\n    return true;\n  }\n\n  applyTo2d({ imageData: { data } }: any) {\n    const lut = this.lut;\n    if (!lut || lut.length !== 256 || LUTFilter.isIdentityLut(lut)) return;\n\n    for (let i = 0; i < data.length; i += 4) {\n      data[i] = lut[data[i]];         // R\n      data[i + 1] = lut[data[i + 1]]; // G\n      data[i + 2] = lut[data[i + 2]]; // B\n    }\n  }\n\n  // No WebGL shader \u2014 always run the 2d path (WebGL would use identity passthrough).\n  applyTo(options: any) {\n    this.applyTo2d(options);\n  }\n\n  isNeutralState() {\n    return LUTFilter.isIdentityLut(this.lut);\n  }\n}\n\n/**\n * Advanced HSL Filter\n * Targets specific hue ranges and alters their Saturation and Lightness\n */\ntype HSLRange = {\n  hueMin: number;\n  hueMax: number;\n  saturationOffset: number; // -1 to 1\n  lightnessOffset: number; // -1 to 1\n};\n\ntype HSLProps = {\n  ranges: HSLRange[];\n};\n\nexport class AdvancedHSLFilter extends filters.BaseFilter<'AdvancedHSL', HSLProps> {\n  declare ranges: HSLRange[];\n\n  static type = 'AdvancedHSL';\n  static defaults = { ranges: [] };\n\n  // Helper to convert RGB to HSL\n  rgbToHsl(r: number, g: number, b: number) {\n    r /= 255; g /= 255; b /= 255;\n    const max = Math.max(r, g, b), min = Math.min(r, g, b);\n    let h = 0, s = 0, l = (max + min) / 2;\n\n    if (max !== min) {\n      const d = max - min;\n      s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n      switch (max) {\n        case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n        case g: h = (b - r) / d + 2; break;\n        case b: h = (r - g) / d + 4; break;\n      }\n      h /= 6;\n    }\n    return [h * 360, s, l];\n  }\n\n  // Helper to convert HSL to RGB\n  hslToRgb(h: number, s: number, l: number) {\n    let r, g, b;\n    h /= 360;\n    if (s === 0) {\n      r = g = b = l; // achromatic\n    } else {\n      const hue2rgb = (p: number, q: number, t: number) => {\n        if (t < 0) t += 1;\n        if (t > 1) t -= 1;\n        if (t < 1/6) return p + (q - p) * 6 * t;\n        if (t < 1/2) return q;\n        if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;\n        return p;\n      };\n      const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n      const p = 2 * l - q;\n      r = hue2rgb(p, q, h + 1/3);\n      g = hue2rgb(p, q, h);\n      b = hue2rgb(p, q, h - 1/3);\n    }\n    return [r * 255, g * 255, b * 255];\n  }\n\n  applyTo2d({ imageData: { data } }: any) {\n    if (!this.ranges || this.ranges.length === 0) return;\n    \n    // Quick check if any range actually has changes\n    const hasActiveRanges = this.ranges.some(r => r.saturationOffset !== 0 || r.lightnessOffset !== 0);\n    if (!hasActiveRanges) return;\n\n    for (let i = 0; i < data.length; i += 4) {\n      const r = data[i];\n      const g = data[i + 1];\n      const b = data[i + 2];\n      \n      const hsl = this.rgbToHsl(r, g, b);\n      let hue = hsl[0];\n      let sat = hsl[1];\n      let lit = hsl[2];\n\n      let modified = false;\n\n      for (const range of this.ranges) {\n        // Handle wrap-around hue (e.g. Red is 345 to 15)\n        let inRange = false;\n        if (range.hueMin > range.hueMax) {\n          inRange = hue >= range.hueMin || hue <= range.hueMax;\n        } else {\n          inRange = hue >= range.hueMin && hue <= range.hueMax;\n        }\n\n        if (inRange) {\n          // Calculate falloff (smooth transition at edges of range)\n          // For simplicity we apply full effect.\n          sat += range.saturationOffset;\n          lit += range.lightnessOffset;\n          \n          if (sat < 0) sat = 0; if (sat > 1) sat = 1;\n          if (lit < 0) lit = 0; if (lit > 1) lit = 1;\n          modified = true;\n        }\n      }\n\n      if (modified) {\n        const rgb = this.hslToRgb(hue, sat, lit);\n        data[i] = rgb[0];\n        data[i + 1] = rgb[1];\n        data[i + 2] = rgb[2];\n      }\n    }\n  }\n\n  isNeutralState() {\n    return !this.ranges || this.ranges.length === 0;\n  }\n}\n\n// Register the custom filters with Fabric\nclassRegistry.setClass(LevelsFilter, 'Levels');\nclassRegistry.setClass(LUTFilter, 'LUT');\nclassRegistry.setClass(AdvancedHSLFilter, 'AdvancedHSL');\n", "import {\n  setFilterBackend,\n  getFilterBackend,\n  initFilterBackend,\n  Canvas2dFilterBackend,\n} from 'fabric';\n\n/**\n * Prefer readback-optimized 2d contexts before Fabric's applyFilters path\n * calls bare getContext('2d') (attrs are ignored after the first create).\n */\nfunction preferWillReadFrequently(target: unknown): void {\n  const el =\n    target &&\n    typeof target === 'object' &&\n    '_filteredEl' in target &&\n    (target as { _filteredEl?: unknown })._filteredEl instanceof HTMLCanvasElement\n      ? (target as { _filteredEl: HTMLCanvasElement })._filteredEl\n      : target &&\n          typeof target === 'object' &&\n          'getElement' in target &&\n          typeof (target as { getElement: () => unknown }).getElement === 'function'\n        ? (target as { getElement: () => unknown }).getElement()\n        : null;\n  if (el instanceof HTMLCanvasElement) {\n    el.getContext('2d', { willReadFrequently: true });\n  }\n}\n\n/**\n * Apply Fabric image filters. Custom 2d-only filters (Levels, LUT, HSL)\n * need the Canvas2d backend \u2014 toggling config.enableGLFiltering is a no-op\n * once a WebGL backend is already cached.\n */\nexport function applyFabricImageFilters(\n  imgObj: { applyFilters: () => void },\n  needs2dBackend: boolean,\n): void {\n  preferWillReadFrequently(imgObj);\n\n  if (!needs2dBackend) {\n    imgObj.applyFilters();\n    return;\n  }\n\n  const previous = getFilterBackend(false);\n  setFilterBackend(new Canvas2dFilterBackend());\n  try {\n    imgObj.applyFilters();\n  } finally {\n    if (previous) {\n      setFilterBackend(previous);\n    } else {\n      setFilterBackend(initFilterBackend());\n    }\n  }\n}\n", "import { create } from 'zustand';\nimport { Canvas, FabricObject, Gradient, Shadow, Path, Circle, Rect, Triangle, Polygon, Group, Point, FabricImage, Textbox, Pattern, cache } from 'fabric';\nimport * as aiEngine from '../services/aiEngine';\nimport { generateImageDesignPreset } from '../services/aiService';\nimport { getActiveMessages } from '../i18n';\nimport { buildImageFilterPreset } from '../utils/imageFilterPresets';\nimport { applyCanvasZoomRender } from '../utils/canvasZoomRender';\nimport { aspectRatioFromPageSize } from '../services/imageService';\nimport { ApiError } from '../services/wizardApiClient';\nimport { sanitizeUserFacingMessage } from '../utils/userFacingError';\nimport {\n  beginAiLoading,\n  createAiPlaceholderLayer,\n  endAiLoading,\n  findObjectById,\n  removeAiPlaceholder,\n  replaceAiPlaceholderWithImage,\n  replaceFabricImagePreservingTransform,\n  type AiLoadingObject,\n} from '../utils/aiLoadingLayer';\nimport {\n  createProjectPersistence,\n  registerProjectPersistence,\n  type ProjectPersistenceController,\n} from '../lib/persistence/projectPersistence';\nimport {\n  markCloudAutosaveAnnounce,\n  withCloudAutosaveToast,\n} from '../utils/cloudAutosaveToast';\nimport { parseCssColor, rgbaToHex6, isNoneCssColor } from '../utils/colorRgba';\nimport { ensureFontReady } from '../utils/googleFonts';\nimport {\n  addLayerMask,\n  bakePathIntoPixelLayer,\n  clearPixelLayerContent,\n  cloneFabricImageElement,\n  createBlankPixelLayer,\n  cssColorToMaskGray,\n  deleteLayerOrClearContent,\n  fitPixelLayerToContent,\n  getBottomPixelLayer,\n  hasLayerMask,\n  isFabricImage,\n  isPixelLayer,\n  layerNameFromFileName,\n  nextPixelLayerName,\n  rasterizeObjectToPixelLayer,\n  reapplyAllPixelLayerLocks,\n  removeLayerMask,\n  stampSourceIntoPixelLayer,\n  syncPixelLayerInteraction,\n  asPixelLayer,\n  shouldSkipPixelLayerPromotion,\n  WE_FABRIC_CUSTOM_PROPERTIES,\n  type PixelLayerImage,\n  type DeleteLayerOrClearResult,\n} from '../utils/pixelLayer';\n\n// Configure Fabric.js v6 to serialize our custom properties\nFabricObject.customProperties = [...WE_FABRIC_CUSTOM_PROPERTIES];\n\n/** True when obj renders as editable text (Textbox, Text, Textbox3D). */\nexport const isTextObject = (obj: any): boolean => {\n  if (!obj) return false;\n  const t = (obj.type || '').toLowerCase();\n  return t === 'textbox' || t === 'text' || t === 'textbox3d';\n};\n\n/** Visual font size including object scale (what the user sees). */\nexport const getEffectiveFontSize = (obj: any): number => {\n  if (!obj) return 40;\n  return Math.max(1, Math.round((obj.fontSize || 40) * Math.abs(obj.scaleY || 1)));\n};\n\nconst textWidthPad = (obj: any): number => {\n  const fs = obj.fontSize || 40;\n  // Side-bearings + stroke ink often paint past advance widths.\n  const italicBoost = String(obj.fontStyle || '').includes('italic') ? fs * 0.1 : 0;\n  const stroke = Number(obj.strokeWidth) || 0;\n  return Math.max(4, Math.ceil(fs * 0.15 + italicBoost + stroke));\n};\n\n/**\n * Canvas ink width for a string (advance vs actualBoundingBox).\n * Used as a floor when Fabric's advance-based calc underestimates a face.\n */\nconst measureCanvasInkWidth = (\n  text: string,\n  family: string,\n  size: number,\n  weight: string | number,\n  style: string,\n  charSpacing = 0,\n): number => {\n  if (typeof document === 'undefined' || !text) return 0;\n  const canvas = document.createElement('canvas');\n  const ctx = canvas.getContext('2d');\n  if (!ctx) return 0;\n  const clean = String(family || 'Arial').replace(/[\"']/g, '');\n  // Match Fabric's _getFontDeclaration shape (style weight size family).\n  ctx.font = `${style || 'normal'} ${weight || 'normal'} ${size}px \"${clean}\"`;\n\n  const lines = String(text).split(/\\r?\\n/);\n  let max = 0;\n  for (const line of lines) {\n    if (!line) continue;\n    let advance = 0;\n    if (charSpacing) {\n      // Fabric adds charSpacing (1/1000 em) after each grapheme including last,\n      // then subtracts one spacing in measureLine \u2014 approximate full-line advance.\n      for (const ch of line) {\n        advance += ctx.measureText(ch).width + (size * charSpacing) / 1000;\n      }\n      advance -= (size * charSpacing) / 1000;\n    } else {\n      advance = ctx.measureText(line).width;\n    }\n    const m = ctx.measureText(line);\n    const ink =\n      m.actualBoundingBoxLeft != null && m.actualBoundingBoxRight != null\n        ? Math.abs(m.actualBoundingBoxLeft) + Math.abs(m.actualBoundingBoxRight)\n        : advance;\n    max = Math.max(max, advance, ink);\n  }\n  return max;\n};\n\n/**\n * Horizontal origin Fabric uses when re-anchoring after text dimension changes\n * (see ITextBehavior.updateFromTextArea).\n */\nconst textboxAnchorX = (obj: Textbox): 'left' | 'center' | 'right' => {\n  const align = String(obj.textAlign || 'left');\n  if (align === 'justify' || align.startsWith('justify-')) {\n    return obj.direction === 'rtl' ? 'right' : 'left';\n  }\n  if (align === 'center' || align === 'right' || align === 'left') return align;\n  return 'left';\n};\n\n/**\n * Recompute wrap/height while keeping the text's top edge fixed.\n * Required because Fabric 7 defaults originY to `center`: changing height\n * without re-anchoring shifts glyphs by ~\u00BD line (often ~26px) and leaves\n * selection controls misaligned after font swaps.\n */\nconst reflowTextboxPreservingTop = (obj: Textbox, width?: number): void => {\n  const anchorX = textboxAnchorX(obj);\n  const pinned = obj.getPositionByOrigin(anchorX, 'top');\n  if (typeof obj._clearCache === 'function') obj._clearCache();\n  if (width !== undefined) {\n    obj.set({ width, dirty: true });\n  } else {\n    obj.set({ dirty: true });\n  }\n  if (typeof obj.initDimensions === 'function') obj.initDimensions();\n  obj.setPositionByOrigin(pinned, anchorX, 'top');\n};\n\n/** Apply a width change and reflow while keeping the text's top edge fixed. */\nconst setTextboxWidthPreservingTop = (obj: Textbox, width: number): void => {\n  reflowTextboxPreservingTop(obj, width);\n};\n\n/** Widest wrapped line in object-local units (Fabric measure + cache clear). */\nconst measureWrappedLinesWidth = (obj: Textbox): number => {\n  const anchorX = textboxAnchorX(obj);\n  const pinned = obj.getPositionByOrigin(anchorX, 'top');\n  if (typeof obj._clearCache === 'function') obj._clearCache();\n  if (typeof obj.initDimensions === 'function') obj.initDimensions();\n\n  let maxLineW = 0;\n  if (Array.isArray(obj._textLines) && typeof obj.measureLine === 'function') {\n    for (let i = 0; i < obj._textLines.length; i++) {\n      const measured = obj.measureLine(i);\n      if (measured?.width > maxLineW) maxLineW = measured.width;\n    }\n  }\n  if (maxLineW <= 0 && typeof obj.calcTextWidth === 'function') {\n    maxLineW = obj.calcTextWidth() || 0;\n  }\n  obj.setPositionByOrigin(pinned, anchorX, 'top');\n  return maxLineW;\n};\n\n/**\n * Natural content width (hard newlines only \u2014 no auto-wrap).\n * Measures on a detached probe so the live editing object is never\n * width-thrashed (that fought Fabric's top-edge anchor mid-keystroke).\n * Takes the max of Fabric advances and canvas ink bounds so faces that\n * paint past their advances (or after a stale Fabric font cache) still fit.\n */\nconst measureNaturalContentWidth = (obj: Textbox): number => {\n  const probe = new Textbox(obj.text ?? '', {\n    fontSize: obj.fontSize,\n    fontFamily: obj.fontFamily,\n    fontWeight: obj.fontWeight,\n    fontStyle: obj.fontStyle,\n    charSpacing: obj.charSpacing,\n    lineHeight: obj.lineHeight,\n    strokeWidth: obj.strokeWidth,\n    splitByGrapheme: obj.splitByGrapheme,\n    width: 100000,\n    // Per-char styles affect glyph metrics when present.\n    styles: obj.styles ? structuredClone(obj.styles) : undefined,\n  } as ConstructorParameters<typeof Textbox>[1]);\n\n  if (typeof probe.initDimensions === 'function') probe.initDimensions();\n  const fabricW =\n    typeof probe.calcTextWidth === 'function' ? probe.calcTextWidth() || 0 : 0;\n  const inkW = measureCanvasInkWidth(\n    obj.text ?? '',\n    String(obj.fontFamily || 'Arial'),\n    Math.max(1, obj.fontSize || 40),\n    obj.fontWeight || 'normal',\n    obj.fontStyle || 'normal',\n    obj.charSpacing || 0,\n  );\n  return Math.max(fabricW, inkW);\n};\n\n/**\n * Sync Textbox width to glyphs.\n * - Auto width (`weTextAutoWidth !== false`): box ends at the last glyph.\n * - Fixed width (user dragged ml/mr): keep column, only grow if a line overflows.\n *\n * Always re-anchors the top edge after height changes (Fabric editing model).\n */\nexport const fitTextboxToContent = (obj: any): void => {\n  if (!(obj instanceof Textbox)) return;\n\n  const minWidth = obj.minWidth || 20;\n  const pad = textWidthPad(obj);\n  const auto = obj.weTextAutoWidth !== false;\n\n  if (auto) {\n    const natural = measureNaturalContentWidth(obj);\n    const needed = Math.max(minWidth, Math.ceil(natural + pad));\n    if (Math.abs(needed - (obj.width || 0)) > 0.5) {\n      setTextboxWidthPreservingTop(obj, needed);\n    } else {\n      // Font swaps can change height without changing width \u2014 still re-pin top.\n      reflowTextboxPreservingTop(obj);\n    }\n  } else {\n    const maxLineW = measureWrappedLinesWidth(obj);\n    const floor = Math.max(minWidth, obj.dynamicMinWidth || 0, maxLineW);\n    const needed = Math.ceil(floor + pad);\n    if (needed > (obj.width || 0) + 0.5) {\n      setTextboxWidthPreservingTop(obj, needed);\n    } else {\n      reflowTextboxPreservingTop(obj);\n    }\n  }\n  obj.setCoords();\n};\n\n/**\n * Size a new Textbox to its natural single-line width (plus padding).\n * Call after the font is available so measureText matches what is painted.\n */\nexport const sizeTextboxToNaturalWidth = (obj: any): void => {\n  if (!(obj instanceof Textbox)) return;\n  obj.weTextAutoWidth = true;\n  fitTextboxToContent(obj);\n};\n\n/**\n * Flatten scale into fontSize, wait for the face to be ready, then re-fit the\n * wrap column. Prevents the common reload/move overflow where measureText ran\n * against a fallback face and the real glyphs paint wider / taller than the\n * selection controls.\n */\nexport const remeasureTextObject = async (obj: any): Promise<void> => {\n  if (!isTextObject(obj)) return;\n  bakeTextScale(obj);\n\n  const family = String(obj.fontFamily || 'Arial').replace(/[\"']/g, '');\n  const size = Math.max(1, obj.fontSize || 40);\n  const weight = obj.fontWeight || 'normal';\n  const style = obj.fontStyle || 'normal';\n\n  // Drop stale async remasures when the user arrows through fonts quickly.\n  const gen = ((obj as { _weRemeasureGen?: number })._weRemeasureGen || 0) + 1;\n  (obj as { _weRemeasureGen?: number })._weRemeasureGen = gen;\n\n  try {\n    // Wait until canvas metrics match the real face (not just fonts.load).\n    await ensureFontReady(family, { size, weight, style });\n  } catch {\n    // Keep going with whatever face the browser substitutes.\n  }\n\n  if ((obj as { _weRemeasureGen?: number })._weRemeasureGen !== gen) return;\n\n  // Fabric caches char advances per family globally. If we measured while the\n  // face was still swapping (fallback), those stale widths stick even after\n  // obj._clearCache() \u2014 painted glyphs overflow the selection box (Poppins,\n  // display faces, etc.). Always drop the family cache before re-layout.\n  try {\n    cache.clearFontCache(family);\n    cache.clearFontCache(family.toLowerCase());\n  } catch {\n    /* ignore */\n  }\n\n  const applyLayout = () => {\n    if ((obj as { _weRemeasureGen?: number })._weRemeasureGen !== gen) return;\n    if (typeof obj._clearCache === 'function') obj._clearCache();\n    obj.set({ dirty: true });\n    if (obj instanceof Textbox) {\n      fitTextboxToContent(obj);\n      fitTextboxToContent(obj);\n    } else {\n      const anchorX =\n        obj.originX === 'center' || obj.originX === 'right' ? obj.originX : 'left';\n      const pinned =\n        typeof obj.getPositionByOrigin === 'function'\n          ? obj.getPositionByOrigin(anchorX, 'top')\n          : null;\n      if (typeof obj.initDimensions === 'function') obj.initDimensions();\n      if (pinned && typeof obj.setPositionByOrigin === 'function') {\n        obj.setPositionByOrigin(pinned, anchorX, 'top');\n      }\n      if (typeof obj._clearCache === 'function') obj._clearCache();\n      if (typeof obj.initDimensions === 'function') obj.initDimensions();\n      if (pinned && typeof obj.setPositionByOrigin === 'function') {\n        obj.setPositionByOrigin(pinned, anchorX, 'top');\n      }\n      obj.setCoords();\n    }\n  };\n\n  applyLayout();\n\n  // Some faces finish swapping one frame after fonts.check \u2014 clear cache\n  // again and re-fit so controls match painted glyphs.\n  await new Promise<void>((r) => requestAnimationFrame(() => requestAnimationFrame(() => r())));\n  if ((obj as { _weRemeasureGen?: number })._weRemeasureGen !== gen) return;\n  try {\n    cache.clearFontCache(family);\n    cache.clearFontCache(family.toLowerCase());\n  } catch {\n    /* ignore */\n  }\n  applyLayout();\n};\n\n/**\n * Flatten scale into fontSize + width so local width matches painted glyphs.\n * Call after corner scaling (and when the panel sets an absolute font size).\n */\nexport const bakeTextScale = (obj: any): boolean => {\n  if (!isTextObject(obj)) return false;\n  const sx = Math.abs(obj.scaleX ?? 1);\n  const sy = Math.abs(obj.scaleY ?? 1);\n  if (!Number.isFinite(sx) || !Number.isFinite(sy)) {\n    obj.set({ scaleX: 1, scaleY: 1 });\n    return false;\n  }\n  if (Math.abs(sx - 1) < 0.001 && Math.abs(sy - 1) < 0.001) return false;\n\n  const oldFontSize = obj.fontSize || 40;\n  if (!Number.isFinite(oldFontSize) || oldFontSize < 1) return false;\n\n  if (obj instanceof Textbox) {\n    // Prefer uniform factor from the dominant axis (corners use equal scaling).\n    const factor = Math.abs(sx - sy) < 0.001 ? sy : Math.max(sx, sy);\n    obj.set({\n      fontSize: Math.max(1, oldFontSize * factor),\n      width: Math.max(obj.minWidth || 20, (obj.width || 0) * sx),\n      scaleX: 1,\n      scaleY: 1,\n      dirty: true,\n    });\n    fitTextboxToContent(obj);\n  } else {\n    const factor = Math.sqrt(sx * sy);\n    obj.set({\n      fontSize: Math.max(1, oldFontSize * factor),\n      scaleX: 1,\n      scaleY: 1,\n      dirty: true,\n    });\n  }\n\n  obj.setCoords();\n  return true;\n};\n\nexport const updateTextPath = (obj: any, curvature: number) => {\n  if (!obj) return;\n  obj.curvature = curvature;\n  if (curvature === 0) {\n    obj.set({ path: null });\n  } else {\n    // Generate curved path based on obj.width or text length\n    const textWidth = obj.width || (obj.text.length * obj.fontSize * 0.6);\n    const angle = (curvature / 100) * 180;\n    const angleRad = (angle * Math.PI) / 180;\n    const arcLength = textWidth;\n    const radius = arcLength / angleRad;\n    const rx = Math.abs(radius);\n    const ry = Math.abs(radius);\n    const largeArcFlag = Math.abs(angle) > 180 ? 1 : 0;\n    const chordLength = 2 * rx * Math.sin(Math.abs(angleRad) / 2);\n    const h = rx * (1 - Math.cos(Math.abs(angleRad) / 2));\n    \n    const pathStr = curvature > 0\n      ? `M 0,0 A ${rx},${ry} 0 ${largeArcFlag},1 ${chordLength},0`\n      : `M 0,${h} A ${rx},${ry} 0 ${largeArcFlag},0 ${chordLength},${h}`;\n    \n    const pathObj = new Path(pathStr, {\n      fill: 'transparent',\n      stroke: 'transparent',\n      visible: false,\n    } as any);\n    obj.set({ path: pathObj });\n  }\n};\n\nexport const applyMaskOverrides = (maskObj: any, canvas: any) => {\n  maskObj.isClipPathMask = true;\n  if (!maskObj._originalRender) {\n    maskObj._originalRender = maskObj.render;\n    maskObj.render = function(ctx: CanvasRenderingContext2D, noTransform?: boolean) {\n      if (this.isClipPathMask && !this.isCurrentClipPath) {\n        const activeObj = canvas?.getActiveObject();\n        const isInSelection = activeObj && (\n          activeObj === this || \n          (activeObj.type?.toLowerCase() === 'activeselection' && (activeObj as any).getObjects().includes(this))\n        );\n        if (isInSelection) {\n          ctx.save();\n          ctx.strokeStyle = '#a855f7';\n          ctx.lineWidth = 1.5;\n          ctx.setLineDash([4, 4]);\n          const w = this.width;\n          const h = this.height;\n          ctx.strokeRect(-w / 2, -h / 2, w, h);\n          ctx.restore();\n        }\n        return;\n      }\n      this._originalRender(ctx, noTransform);\n    };\n  }\n};\n\nexport const applyClippedOverrides = (clippedObj: any) => {\n  if (!clippedObj._originalRender) {\n    clippedObj._originalRender = clippedObj.render;\n    clippedObj.render = function(ctx: CanvasRenderingContext2D, noTransform?: boolean) {\n      if (this.clipPath) {\n        this.clipPath.isCurrentClipPath = true;\n      }\n      this._originalRender(ctx, noTransform);\n      if (this.clipPath) {\n        this.clipPath.isCurrentClipPath = false;\n      }\n    };\n  }\n};\n\nexport const reconstructClippingMasks = (canvas: any) => {\n  if (!canvas) return;\n  const objects = canvas.getObjects();\n  \n  objects.forEach((obj: any) => {\n    if (obj.isClipPathMask) {\n      applyMaskOverrides(obj, canvas);\n    }\n  });\n\n  objects.forEach((obj: any) => {\n    if (obj.clippedToLayerId) {\n      const parent = objects.find((o: any) => o.id === obj.clippedToLayerId);\n      if (parent) {\n        obj.clipPath = parent;\n        applyClippedOverrides(obj);\n      }\n    }\n  });\n};\n\n\nexport interface Page {\n  id: string;\n  name: string;\n  width: number;\n  height: number;\n  backgroundColor: string;\n  json: any; // Serialized fabric state\n  history: string[]; // History stack of JSON states\n  historyIndex: number;\n  thumbnail?: string; // Optional low-res cached thumbnail dataURL\n}\n\n/** A single image project (one tab in the tab bar) */\nexport interface ImageProject {\n  id: string;\n  name: string;\n  pages: Page[];\n  activePageId: string;\n  createdAt: number;\n  /** Last `/api/kaiman/editables` id \u2014 replaced on silent cloud autosave. */\n  cloudEditableId?: number;\n}\n\nexport type ToolType = 'select' | 'select-rect' | 'select-ellipse' | 'select-lasso' | 'magic-wand' | 'pixel-lasso' | 'polygon-lasso' | 'eraser' | 'paint-bucket' | 'pan' | 'move-only' | 'rotate-only' | 'text' | 'rect' | 'circle' | 'triangle' | 'line' | 'brush' | 'magic-eraser' | 'clone-stamp' | 'rounded-rect' | 'ellipse' | 'star' | 'polygon' | 'arrow' | 'speech-bubble' | 'heart' | 'cross' | 'frame-polaroid' | 'frame-mobile' | 'frame-laptop' | 'frame-circle-double' | 'frame-star-pro' | 'frame-blob' | 'frame-desktop' | 'frame-ipad' | 'frame-watch' | 'frame-browser' | 'frame-billboard' | 'frame-polaroid-scatter' | 'frame-poster' | 'frame-business-card' | 'frame-video-player' | 'frame-chat' | 'frame-arch' | 'frame-hexagon' | 'frame-heart' | 'frame-circle' | 'frame-pill' | 'frame-diamond' | 'crop' | 'eyedropper' | 'pen' | 'custom-shape';\n\n/** Freehand object marquee only \u2014 rect/ellipse are pixel shape lassos. */\nexport const MARQUEE_TOOLS = ['select-lasso'] as const;\nexport type MarqueeTool = (typeof MARQUEE_TOOLS)[number];\n\n/** Shape/pixel selection tools (lasso flyout) \u2014 not the pointer cursor. */\nexport const LASSO_GROUP_TOOLS = [\n  'select-rect',\n  'select-ellipse',\n  'select-lasso',\n  'pixel-lasso',\n  'polygon-lasso',\n] as const;\nexport type LassoGroupTool = (typeof LASSO_GROUP_TOOLS)[number];\n\n/** Pixel eraser + AI magic eraser (eraser flyout). */\nexport const ERASER_GROUP_TOOLS = ['eraser', 'magic-eraser'] as const;\nexport type EraserGroupTool = (typeof ERASER_GROUP_TOOLS)[number];\n\nexport function isMarqueeTool(tool: string): tool is MarqueeTool {\n  return (MARQUEE_TOOLS as readonly string[]).includes(tool);\n}\n\nexport function isLassoGroupTool(tool: string): tool is LassoGroupTool {\n  return (LASSO_GROUP_TOOLS as readonly string[]).includes(tool);\n}\n\nexport function isEraserGroupTool(tool: string): tool is EraserGroupTool {\n  return (ERASER_GROUP_TOOLS as readonly string[]).includes(tool);\n}\n\nexport function isBrushRadiusTool(tool: string): boolean {\n  return tool === 'brush' || tool === 'magic-eraser' || tool === 'clone-stamp' || tool === 'eraser';\n}\n\nexport function isPixelSelectionTool(tool: string): boolean {\n  return (\n    tool === 'magic-wand' ||\n    tool === 'select-rect' ||\n    tool === 'select-ellipse' ||\n    tool === 'pixel-lasso' ||\n    tool === 'polygon-lasso'\n  );\n}\n\n/** Rectangular / elliptical pixel lassos (drag shape on an image). */\nexport function isShapeLassoTool(tool: string): boolean {\n  return tool === 'select-rect' || tool === 'select-ellipse';\n}\n\nexport type SelectionCombineMode = 'new' | 'add' | 'subtract';\n\nexport interface MagicWandSettings {\n  /** 0\u2013255 RGB distance. */\n  tolerance: number;\n  /** Contiguous flood-fill when true; all similar pixels when false. */\n  contiguous: boolean;\n  /** Fill color for \u201CRellenar selecci\u00F3n\u201D. */\n  fillColor: string;\n  /** How new samples combine with the current mask. Shift/Ctrl override while clicking. */\n  selectionMode: SelectionCombineMode;\n}\n\nexport interface PaintBucketSettings {\n  /** 0\u2013255 RGB distance. */\n  tolerance: number;\n  /** Contiguous flood-fill when true; all similar pixels when false. */\n  contiguous: boolean;\n  /** Soften fill edges (Photoshop anti-alias). */\n  antiAlias: boolean;\n}\n\nexport type MasterColorChannel = 'fill' | 'stroke';\n\n/** Photoshop-style tool colors: fill (foreground) + stroke (border). */\nexport interface MasterColors {\n  fill: string;\n  stroke: string;\n  activeChannel: MasterColorChannel;\n}\n\nexport type MagicWandSelectionState = {\n  objectId: string;\n  previewUrl: string;\n  width: number;\n  height: number;\n  pixelCount: number;\n  /** Serialized mask (0/1) \u2014 kept for apply ops. */\n  maskData: Uint8Array;\n};\n\nexport interface BrushSettings {\n  type: 'pencil' | 'spray' | 'circle' | 'calligraphy' | 'highlighter' | 'chalk';\n  color: string;\n  width: number;\n  opacity: number;\n  shadowColor: string;\n  shadowBlur: number;\n  shadowEnabled: boolean;\n  stabilization: number; // 0 to 1 (suavizado)\n  pressureSensitivity: boolean;\n  capType: 'round' | 'square' | 'butt';\n}\n\nexport interface TextSettings {\n  fontFamily: string;\n  fontSize: number;\n  fill: string;\n  fontWeight: string;\n  fontStyle: string;\n  underline: boolean;\n  textAlign: string;\n  charSpacing: number;\n  lineHeight: number;\n  linethrough: boolean;\n  overline: boolean;\n  stroke: string;\n  strokeWidth: number;\n  textShadowEnabled: boolean;\n  textShadowColor: string;\n  textShadowBlur: number;\n  textShadowOffsetX: number;\n  textShadowOffsetY: number;\n  curvature: number;\n}\n\nexport interface ImageSettings {\n  exposure?: number;\n  brightness?: number;\n  contrast?: number;\n  saturation?: number;\n  blur?: number;\n  hueRotation?: number;\n  invert?: boolean;\n  activePreset?: string;\n  cropScale?: number;\n  levelsBlack?: number;\n  levelsMid?: number;\n  levelsWhite?: number;\n  lut?: number[] | null;\n}\n\nexport interface UploadedAsset {\n  id: string;\n  name: string;\n  url: string;\n  size: string;\n  type: string;\n  width: number;\n  height: number;\n  timestamp: number;\n}\n\nexport interface UploadedFont {\n  name: string;\n  dataUrl: string;\n  timestamp: number;\n}\n\nexport interface ProjectVersion {\n  id: string;\n  name: string;\n  timestamp: number;\n  pages: any[]; // we use any to avoid circular dependencies with Page\n}\n\nexport interface SavedProject {\n  id: string;\n  name: string;\n  pages: any[]; // legacy single-project pages (kept for backward compat)\n  versions: ProjectVersion[];\n  lastSaved: number;\n  // Multi-project state\n  imageProjects?: any[];\n  activeImageProjectId?: string | null;\n}\n\nexport const openUploadsDB = (): Promise<IDBDatabase> => {\n  return new Promise((resolve, reject) => {\n    // v7: slides-assets store for the standalone slides editor\n    const request = indexedDB.open('WizardStudioUploads', 7);\n    request.onerror = () => reject(request.error);\n    request.onsuccess = () => resolve(request.result);\n    request.onupgradeneeded = () => {\n      const db = request.result;\n      if (!db.objectStoreNames.contains('assets')) {\n        db.createObjectStore('assets', { keyPath: 'id' });\n      }\n      if (!db.objectStoreNames.contains('fonts')) {\n        db.createObjectStore('fonts', { keyPath: 'name' });\n      }\n      if (!db.objectStoreNames.contains('projects')) {\n        db.createObjectStore('projects', { keyPath: 'id' });\n      }\n      // Stores raw file bytes for video/audio assets (blob: URLs die on reload)\n      if (!db.objectStoreNames.contains('video-assets')) {\n        db.createObjectStore('video-assets', { keyPath: 'id' });\n      }\n      // Standalone audio editor assets (peaks cache lives in memory / separate keys)\n      if (!db.objectStoreNames.contains('audio-assets')) {\n        db.createObjectStore('audio-assets', { keyPath: 'id' });\n      }\n      // Slides Studio media (images, narration audio, fonts)\n      if (!db.objectStoreNames.contains('slides-assets')) {\n        db.createObjectStore('slides-assets', { keyPath: 'id' });\n      }\n    };\n  });\n};\n\nexport const saveAssetToDB = async (asset: UploadedAsset): Promise<void> => {\n  try {\n    const db = await openUploadsDB();\n    return new Promise((resolve, reject) => {\n      const tx = db.transaction('assets', 'readwrite');\n      const store = tx.objectStore('assets');\n      const req = store.put(asset);\n      req.onsuccess = () => resolve();\n      req.onerror = () => reject(req.error);\n    });\n  } catch (err) {\n    console.error('Failed to save asset to IndexedDB:', err);\n  }\n};\n\nexport const getAllAssetsFromDB = async (): Promise<UploadedAsset[]> => {\n  try {\n    const db = await openUploadsDB();\n    return new Promise((resolve, reject) => {\n      const tx = db.transaction('assets', 'readonly');\n      const store = tx.objectStore('assets');\n      const req = store.getAll();\n      req.onsuccess = () => resolve(req.result || []);\n      req.onerror = () => reject(req.error);\n    });\n  } catch (err) {\n    console.error('Failed to get assets from IndexedDB:', err);\n    return [];\n  }\n};\n\nexport const deleteAssetFromDB = async (id: string): Promise<void> => {\n  try {\n    const db = await openUploadsDB();\n    return new Promise((resolve, reject) => {\n      const tx = db.transaction('assets', 'readwrite');\n      const store = tx.objectStore('assets');\n      const req = store.delete(id);\n      req.onsuccess = () => resolve();\n      req.onerror = () => reject(req.error);\n    });\n  } catch (err) {\n    console.error('Failed to delete asset from IndexedDB:', err);\n  }\n};\n\nexport const clearAllAssetsFromDB = async (): Promise<void> => {\n  try {\n    const db = await openUploadsDB();\n    return new Promise((resolve, reject) => {\n      const tx = db.transaction('assets', 'readwrite');\n      const store = tx.objectStore('assets');\n      const req = store.clear();\n      req.onsuccess = () => resolve();\n      req.onerror = () => reject(req.error);\n    });\n  } catch (err) {\n    console.error('Failed to clear assets from IndexedDB:', err);\n  }\n};\n\nexport const saveFontToDB = async (font: UploadedFont): Promise<void> => {\n  try {\n    const db = await openUploadsDB();\n    return new Promise((resolve, reject) => {\n      const tx = db.transaction('fonts', 'readwrite');\n      const store = tx.objectStore('fonts');\n      const req = store.put(font);\n      req.onsuccess = () => resolve();\n      req.onerror = () => reject(req.error);\n    });\n  } catch (err) {\n    console.error('Failed to save font to IndexedDB:', err);\n  }\n};\n\nexport const getAllFontsFromDB = async (): Promise<UploadedFont[]> => {\n  try {\n    const db = await openUploadsDB();\n    if (!db.objectStoreNames.contains('fonts')) return [];\n    return new Promise((resolve, reject) => {\n      const tx = db.transaction('fonts', 'readonly');\n      const store = tx.objectStore('fonts');\n      const req = store.getAll();\n      req.onsuccess = () => resolve(req.result || []);\n      req.onerror = () => reject(req.error);\n    });\n  } catch (err) {\n    console.error('Failed to get fonts from IndexedDB:', err);\n    return [];\n  }\n};\n\nexport const deleteFontFromDB = async (name: string): Promise<void> => {\n  try {\n    const db = await openUploadsDB();\n    return new Promise((resolve, reject) => {\n      const tx = db.transaction('fonts', 'readwrite');\n      const store = tx.objectStore('fonts');\n      const req = store.delete(name);\n      req.onsuccess = () => resolve();\n      req.onerror = () => reject(req.error);\n    });\n  } catch (err) {\n    console.error('Failed to delete font from IndexedDB:', err);\n  }\n};\n\nexport const saveProjectToDB = async (project: SavedProject): Promise<void> => {\n  try {\n    const db = await openUploadsDB();\n    return new Promise((resolve, reject) => {\n      const tx = db.transaction('projects', 'readwrite');\n      const store = tx.objectStore('projects');\n      const req = store.put(project);\n      req.onsuccess = () => resolve();\n      req.onerror = () => reject(req.error);\n    });\n  } catch (err) {\n    console.error('Failed to save project to IndexedDB:', err);\n  }\n};\n\nexport const getProjectFromDB = async (id: string): Promise<SavedProject | null> => {\n  try {\n    const db = await openUploadsDB();\n    return new Promise((resolve, reject) => {\n      if (!db.objectStoreNames.contains('projects')) return resolve(null);\n      const tx = db.transaction('projects', 'readonly');\n      const store = tx.objectStore('projects');\n      const req = store.get(id);\n      req.onsuccess = () => resolve(req.result || null);\n      req.onerror = () => reject(req.error);\n    });\n  } catch (err) {\n    console.error('Failed to get project from IndexedDB:', err);\n    return null;\n  }\n};\n\nexport interface ColorPalette {\n  id: string;\n  name: string;\n  colors: string[];\n}\n\nexport type SnapSettings = {\n  enabled: boolean;\n  shapes: boolean;\n  images: boolean;\n  text: boolean;\n  canvasEdges: boolean;\n};\n\nexport interface EditorState {\n  // \u2500\u2500 Multi-project State \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  imageProjects: ImageProject[];\n  activeImageProjectId: string | null;\n  isImageSetupOpen: boolean;\n  /** True while loadProject() is reading from IndexedDB \u2014 prevents flashing the\n   *  setup modal before we know whether a saved project exists. */\n  isProjectLoading: boolean;\n  setIsImageSetupOpen: (open: boolean) => void;\n  createImageProject: (name: string, width: number, height: number, backgroundColor: string) => void;\n  importImageProject: (fileData: any, fileName: string, opts?: { cloudEditableId?: number }) => void;\n  closeImageProject: (projectId: string) => void;\n  switchImageProject: (projectId: string) => void;\n  renameImageProject: (projectId: string, name: string) => void;\n\n  // Canvas State (proxied from the active project)\n  pages: Page[];\n  activePageId: string;\n  activeTool: ToolType;\n  zoom: number;\n  canvasInstance: Canvas | null;\n  activeObject: FabricObject | null;\n  /** Last selected layer id \u2014 keeps Layers panel highlight when canvas selection is cleared. */\n  lastSelectedObjectId: string | null;\n  /** Pixel layer id targeted by brush/clone while drawing mode clears Fabric selection. */\n  paintTargetLayerId: string | null;\n  /** Paint into layer pixels or into the linked grayscale mask. */\n  layerPaintTarget: 'content' | 'mask';\n  setLayerPaintTarget: (target: 'content' | 'mask') => void;\n  layers: FabricObject[];\n  isHistoryAction: boolean;\n  /** >0 while ephemeral UI (e.g. crop overlay) must not push undo steps. */\n  historyPauseCount: number;\n  sidebarCollapsed: boolean;\n  layersPanelCollapsed: boolean;\n  setSidebarCollapsed: (collapsed: boolean) => void;\n  setLayersPanelCollapsed: (collapsed: boolean) => void;\n  \n  // Settings State\n  brushSettings: BrushSettings;\n  textSettings: TextSettings;\n  imageSettings: ImageSettings;\n  magicWandSettings: MagicWandSettings;\n  magicWandSelection: MagicWandSelectionState | null;\n  updateMagicWandSettings: (settings: Partial<MagicWandSettings>) => void;\n  setMagicWandSelection: (selection: MagicWandSelectionState | null) => void;\n  clearMagicWandSelection: () => void;\n  applyMagicWandDelete: () => Promise<void>;\n  applyMagicWandFill: () => Promise<void>;\n  applyMagicWandCutToLayer: () => Promise<void>;\n  /** Cut selection to a movable layer (no toast) \u2014 used when switching to Move/Select (V). */\n  floatPixelSelection: () => Promise<boolean>;\n\n  paintBucketSettings: PaintBucketSettings;\n  updatePaintBucketSettings: (settings: Partial<PaintBucketSettings>) => void;\n\n  /** Master tool colors (fill / stroke) shared by brush, bucket, shapes, text, \u2026 */\n  masterColors: MasterColors;\n  setMasterColorChannel: (channel: MasterColorChannel) => void;\n  setMasterColorValue: (channel: MasterColorChannel, css: string) => void;\n  updateMasterColors: (partial: Partial<MasterColors>) => void;\n  swapMasterColors: () => void;\n  /** Copy solid fill/stroke from the selection into masterColors (no re-apply). */\n  hydrateMasterColorsFromSelection: () => void;\n\n  // Rules, Guides & Dropper State\n  rulersEnabled: boolean;\n  guidesEnabled: boolean;\n  snapSettings: SnapSettings;\n  copiedStyle: any | null;\n\n  // Layout Grid State\n  layoutGridEnabled: boolean;\n  layoutGridType: 'columns' | 'grid';\n  layoutGridColumns: number;\n  layoutGridGutter: number;\n  layoutGridMargin: number;\n  layoutGridSize: number;\n  layoutGridColor: string;\n\n\n  // Uploads State\n  uploadedAssets: UploadedAsset[];\n  loadUploadedAssets: () => Promise<void>;\n  addUploadedAsset: (name: string, url: string, size: string, type: string, width: number, height: number) => Promise<void>;\n  deleteUploadedAsset: (id: string) => Promise<void>;\n  clearUploadedAssets: () => Promise<void>;\n\n  // Fonts State\n  customFonts: UploadedFont[];\n  loadCustomFonts: () => Promise<void>;\n  addCustomFont: (name: string, dataUrl: string) => Promise<void>;\n  deleteCustomFont: (name: string) => Promise<void>;\n\n  // Canvas Actions\n  // Canvas Actions\n  setCanvasInstance: (canvas: Canvas | null) => void;\n  canvasSyncTrigger: number;\n  triggerCanvasSync: () => void;\n  setActiveTool: (tool: ToolType | ((prev: ToolType) => ToolType)) => void;\n  setZoom: (zoom: number) => void;\n  setActiveObject: (obj: FabricObject | null) => void;\n  setLayers: (layers: FabricObject[]) => void;\n  activeCustomShape: string | null;\n  setActiveCustomShape: (shapeId: string | null) => void;\n  \n  // Brush Settings Actions\n  updateBrushSettings: (settings: Partial<BrushSettings>) => void;\n  \n  // Text Settings Actions\n  updateTextSettings: (settings: Partial<TextSettings>) => void;\n\n  // Image Settings Actions\n  updateImageSettings: (settings: Partial<ImageSettings>) => void;\n  /** Quick filter preset (Original, B&W, Sepia, \u2026) on the active image. */\n  applyImagePreset: (presetName: string) => void;\n\n  // Rules, Guides & Dropper Actions\n  setRulersEnabled: (enabled: boolean) => void;\n  setGuidesEnabled: (enabled: boolean) => void;\n  setSnapSettings: (settings: Partial<SnapSettings>) => void;\n  setCopiedStyle: (style: any | null) => void;\n  /** When using the canvas eyedropper: apply sample to fill or stroke. */\n  eyedropperApplyChannel: 'fill' | 'stroke';\n  setEyedropperApplyChannel: (channel: 'fill' | 'stroke') => void;\n  /** Image mode: canvas size chip \u2194 floating size panel. */\n  isCanvasSizePanelOpen: boolean;\n  setCanvasSizePanelOpen: (open: boolean) => void;\n  /** Display/edit unit for canvas dimensions (chip + size modal). */\n  canvasSizeUnit: 'px' | 'in' | 'cm' | 'mm';\n  setCanvasSizeUnit: (unit: 'px' | 'in' | 'cm' | 'mm') => void;\n\n  // Layout Grid Actions\n  setLayoutGridEnabled: (enabled: boolean) => void;\n  setLayoutGridType: (type: 'columns' | 'grid') => void;\n  setLayoutGridColumns: (cols: number) => void;\n  setLayoutGridGutter: (gutter: number) => void;\n  setLayoutGridMargin: (margin: number) => void;\n  setLayoutGridSize: (size: number) => void;\n  setLayoutGridColor: (color: string) => void;\n\n  // Page Actions\n  addPage: (width?: number, height?: number) => void;\n  deletePage: (id: string) => void;\n  duplicatePage: (id: string) => void;\n  clearPage: (id: string) => void;\n  movePage: (id: string, direction: 'up' | 'down') => void;\n  renamePage: (id: string, name: string) => void;\n  setActivePageId: (id: string) => void;\n  updatePageDimensions: (id: string, width: number, height: number) => void;\n  updatePageBgColor: (id: string, color: string) => void;\n  \n  // History Actions\n  saveHistoryState: () => void;\n  undo: () => void;\n  redo: () => void;\n  canUndo: () => boolean;\n  canRedo: () => boolean;\n  /** Suspend undo snapshots (nestable). Pair with resumeHistory. */\n  pauseHistory: () => void;\n  resumeHistory: () => void;\n  \n  // Sync\n  syncLayers: () => void;\n\n  /** Blank pixel layer (page-sized, empty \u2014 no transform chrome until painted). */\n  addBlankRasterLayer: () => FabricObject | null;\n  /** Ensure at least one pixel layer exists (bottom = file layer). No weBaseLayer flag. */\n  ensureFileBaseLayer: () => PixelLayerImage | null;\n  /** Clear content of a pixel layer (used when \"deleting\" the file/bottom layer). */\n  clearPixelLayer: (layer: FabricObject) => void;\n  /**\n   * Delete a layer, or clear its content when it is the only remaining layer.\n   * Empty layers are allowed \u2014 returns 'blocked' only if the sole layer is already empty.\n   */\n  deleteLayerOrClear: (layer: FabricObject) => DeleteLayerOrClearResult;\n  /** Clone the active layer (deep-clones raster buffers for images). */\n  duplicateActiveLayer: () => Promise<FabricObject | null>;\n  /** Add a white linked layer mask to a pixel layer. */\n  addPixelLayerMask: (layer: FabricObject) => void;\n  /** Remove the layer mask from a pixel layer. */\n  removePixelLayerMask: (layer: FabricObject) => void;\n  /** Convert a vector/text object into a non-editable pixel layer (in place). */\n  rasterizeLayer: (layer: FabricObject) => void;\n  /** Reorder a top-level layer in the Layers list (top \u2192 bottom visual order). */\n  reorderLayer: (dragId: string, dropId: string) => void;\n  /**\n   * Resolve the pixel layer for paint tools. Never auto-creates.\n   * Uses active selection or paintTargetLayerId (survives drawing mode).\n   */\n  resolvePaintTargetLayer: () => PixelLayerImage | null;\n  /** @deprecated Use resolvePaintTargetLayer */\n  ensurePixelLayerForBrush: () => PixelLayerImage | null;\n  /** Bake a free-draw Path into the selected paint target (toast if none). */\n  commitBrushPathToPixelLayer: (path: FabricObject) => void;\n  /**\n   * Stamp an image into the selected pixel layer, or create an image-sized\n   * pixel layer when none is selected (never a floating FabricImage).\n   */\n  stampImageOntoActivePixelLayer: (\n    dataUrl: string,\n    opts?: { name?: string; centerX?: number; centerY?: number },\n  ) => Promise<PixelLayerImage | null>;\n\n  // Mask Actions\n  activeMaskTarget: FabricObject | null;\n  setActiveMaskTarget: (obj: FabricObject | null) => void;\n  showAiObjectEraser: boolean;\n  setShowAiObjectEraser: (show: boolean) => void;\n  \n  isVariationsModalOpen: boolean;\n  setVariationsModalOpen: (open: boolean) => void;\n  aiVariations: string[];\n  setAiVariations: (vars: string[]) => void;\n  maskMode: boolean;\n  setMaskMode: (mode: boolean) => void;\n  applyInstantMask: (image: any, shapeType: 'circle' | 'heart' | 'star' | 'triangle' | 'rounded-rect' | 'none') => void;\n  applyCustomMask: (image: any, shapeObj: any) => void;\n  releaseClippingMask: () => void;\n  createClippingMask: () => void;\n  isMaskCreationPossible: () => boolean;\n\n  // Group Actions\n  groupSelectedObjects: () => void;\n  ungroupObjects: () => void;\n\n  // AI State & Actions\n  isAiGenerating: boolean;\n  /** Image id targeted by mask-edit (magic eraser); survives brush selection clears. */\n  magicEraserTargetId: string | null;\n  setMagicEraserTargetId: (id: string | null) => void;\n  aiError: string | null;\n  /** Errors for AI Studio Generador only \u2014 never shared with magic eraser / other tools. */\n  aiStudioError: string | null;\n  setAiGenerating: (generating: boolean) => void;\n  setAiError: (error: string | null) => void;\n  setAiStudioError: (error: string | null) => void;\n  runRemoveBg: () => Promise<void>;\n  runModifyImageByPrompt: (prompt: string) => Promise<void>;\n  runTextToImage: (opts: {\n    prompt: string;\n    aspectRatio?: import('../services/imageService').ImageGeneratorAspectRatio;\n    resolution?: import('../services/imageService').ImageGeneratorResolution | '4K';\n    references?: Blob[];\n  }) => Promise<boolean>;\n  runGenerativeFill: (prompt: string, blendWithSubject?: boolean) => Promise<void>;\n  runMagicResize: (targetWidth: number, targetHeight: number) => Promise<void>;\n  runAiAutoLayout: (direction: 'row' | 'column' | 'grid', gap?: number, alignment?: 'top' | 'center' | 'bottom' | 'left' | 'right') => Promise<void>;\n  runAiCopywrite: (prompt: string) => Promise<void>;\n  runVectorizeStroke: (tolerance?: number) => Promise<void>;\n  runSketchToImage: (prompt: string) => Promise<void>;\n  runGenerateInArea: (prompt: string) => Promise<void>;\n  runSelectSubject: () => Promise<void>;\n  runAiMagicEraser: () => Promise<void>;\n  runAiDesignCopilot: (prompt: string) => Promise<void>;\n  runAiUpscale: (factor: 2) => Promise<void>;\n  runAiVariations: () => Promise<void>;\n  runAiAutoEnhance: () => Promise<void>;\n  geminiApiKey: string;\n  setGeminiApiKey: (key: string) => void;\n  aiCopywritingSuggestions: { comercial: string; creativa: string; directa: string } | null;\n  setAiCopywritingSuggestions: (suggestions: { comercial: string; creativa: string; directa: string } | null) => void;\n  applyAiCopywritingSuggestion: (text: string) => void;\n  \n  // System State\n  isCommandPaletteOpen: boolean;\n  setCommandPaletteOpen: (open: boolean) => void;\n  isPlayingSlideshow: boolean;\n  setPlayingSlideshow: (playing: boolean) => void;\n  \n  // Smart Linking\n  linkSelectedObjects: () => void;\n  unlinkSelectedObjects: () => void;\n  propagateLinkedObject: (modifiedObj: any) => void;\n  \n  // Persistence\n  saveStatus: 'idle' | 'saving' | 'saved' | 'error';\n  setSaveStatus: (status: 'idle' | 'saving' | 'saved' | 'error') => void;\n  lastSaved: number | null;\n  projectVersions: ProjectVersion[];\n  saveCurrentProject: () => Promise<void>;\n  /** Silent debounced upload to `/api/kaiman/editables` (no toast). */\n  autoSaveProjectToCloud: () => Promise<boolean>;\n  saveNamedVersion: (name: string) => Promise<void>;\n  loadProject: () => Promise<void>;\n  loadVersion: (versionId: string) => Promise<void>;\n  deleteVersion: (versionId: string) => Promise<void>;\n\n  toasts: Toast[];\n  addToast: (message: string, type?: Toast['type'], options?: AddToastOptions) => string;\n  updateToast: (id: string, patch: UpdateToastPatch) => void;\n  removeToast: (id: string) => void;\n\n\n  // Color Features\n  colorBlindnessMode: 'normal' | 'protanopia' | 'deuteranopia' | 'tritanopia';\n  setColorBlindnessMode: (mode: 'normal' | 'protanopia' | 'deuteranopia' | 'tritanopia') => void;\n  extractedColors: string[];\n  setExtractedColors: (colors: string[]) => void;\n  savedPalettes: ColorPalette[];\n  addPalette: (palette: ColorPalette) => void;\n  /** Insert or replace a palette by id (used for live brand kit sync). */\n  upsertPalette: (palette: ColorPalette) => void;\n  updatePaletteName: (id: string, name: string) => void;\n  addColorToPalette: (id: string, color: string) => void;\n  updateColorInPalette: (id: string, colorIndex: number, newColor: string) => void;\n  removeColorFromPalette: (id: string, colorIndex: number) => void;\n  reorderColorInPalette: (id: string, fromIndex: number, toIndex: number) => void;\n  deletePalette: (id: string) => void;\n}\n\nexport type ToastType = 'success' | 'error' | 'info' | 'warning';\n\nexport interface Toast {\n  id: string;\n  message: string;\n  type: ToastType;\n  /** 0\u2013100. Omit to hide the progress bar. */\n  progress?: number;\n}\n\nexport interface AddToastOptions {\n  progress?: number;\n  /** When true, the toast stays until the user closes it. Errors default to sticky. */\n  sticky?: boolean;\n  durationMs?: number;\n}\n\nexport interface UpdateToastPatch {\n  message?: string;\n  type?: ToastType;\n  /** Pass `null` to hide the progress bar. */\n  progress?: number | null;\n  sticky?: boolean;\n  durationMs?: number;\n}\n\nconst toastTimers = new Map<string, ReturnType<typeof setTimeout>>();\n\nfunction clearToastTimer(id: string) {\n  const timer = toastTimers.get(id);\n  if (timer) {\n    clearTimeout(timer);\n    toastTimers.delete(id);\n  }\n}\n\nfunction defaultToastDuration(type: ToastType): number {\n  return type === 'success' ? 5000 : 4000;\n}\n\nconst defaultPageDimensions = { width: 1080, height: 1080 };\n\nexport const applyCanvasBackground = (canvas: any | null, bg: string, width: number, height: number) => {\n  if (!canvas) return;\n\n  // \u2500\u2500 Gradiente (JSON serializado) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  if (bg && bg.startsWith('{') && bg.includes('colorStops')) {\n    try {\n      const gradData = JSON.parse(bg);\n      let coords = gradData.coords;\n\n      if (gradData.angle !== undefined) {\n        const angleRad = ((gradData.angle - 90) * Math.PI) / 180;\n        const cx = width / 2;\n        const cy = height / 2;\n        const r = Math.abs(width * Math.cos(angleRad)) + Math.abs(height * Math.sin(angleRad));\n        const halfLength = r / 2;\n        const x1 = cx - halfLength * Math.cos(angleRad);\n        const y1 = cy - halfLength * Math.sin(angleRad);\n        const x2 = cx + halfLength * Math.cos(angleRad);\n        const y2 = cy + halfLength * Math.sin(angleRad);\n        coords = { x1, y1, x2, y2 };\n      } else if (coords) {\n        coords = {\n          x1: coords.x1 * width,\n          y1: coords.y1 * height,\n          x2: coords.x2 * width,\n          y2: coords.y2 * height,\n        };\n      } else {\n        coords = { x1: 0, y1: 0, x2: width, y2: height };\n      }\n\n      const grad = new Gradient({\n        type: gradData.type || 'linear',\n        coords,\n        colorStops: gradData.colorStops,\n      });\n      canvas.backgroundColor = grad;\n      canvas.requestRenderAll();\n    } catch (e) {\n      canvas.backgroundColor = bg;\n      canvas.requestRenderAll();\n    }\n    return;\n  }\n\n  // \u2500\u2500 Textura / imagen de fondo (URL http/https o data:) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  if (bg && (bg.startsWith('http') || bg.startsWith('data:') || bg.startsWith('blob:'))) {\n    FabricImage.fromURL(bg, { crossOrigin: 'anonymous' })\n      .then((img: any) => {\n        if (!img) return;\n        // Escalar para cubrir el canvas manteniendo la proporci\u00F3n (cover)\n        const scaleX = width  / (img.width  || 1);\n        const scaleY = height / (img.height || 1);\n        const scale  = Math.max(scaleX, scaleY);\n        img.set({ scaleX: scale, scaleY: scale });\n\n        const pattern = new Pattern({ source: img.getElement(), repeat: 'no-repeat' });\n        canvas.backgroundColor = pattern;\n        canvas.requestRenderAll();\n      })\n      .catch(() => {\n        // Si falla la carga (CORS, red, etc.) pone blanco para no dejar negro\n        canvas.backgroundColor = '#ffffff';\n        canvas.requestRenderAll();\n      });\n    return;\n  }\n\n  // \u2500\u2500 Color s\u00F3lido \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  canvas.backgroundColor = bg || '#ffffff';\n  canvas.requestRenderAll();\n};\n\nconst defaultPage = (id: string, index: number): Page => {\n  const initialJSON = {\n    version: '6.0.0', // Fabric version\n    objects: [],\n    background: '#ffffff',\n  };\n  const jsonStr = JSON.stringify(initialJSON);\n  return {\n    id,\n    name: `P\u00E1gina ${index + 1}`,\n    width: defaultPageDimensions.width,\n    height: defaultPageDimensions.height,\n    backgroundColor: '#ffffff',\n    json: initialJSON,\n    history: [jsonStr],\n    historyIndex: 0,\n  };\n};\n\n// Debounced local IndexedDB + background cloud (see projectPersistence).\nlet imagePersistence!: ProjectPersistenceController;\n\ntype MagicWandOp = 'delete' | 'fill' | 'cut';\n\nasync function applyMagicWandMutation(\n  get: () => EditorState,\n  set: (partial: Partial<EditorState> | ((s: EditorState) => Partial<EditorState>)) => void,\n  op: MagicWandOp,\n): Promise<boolean> {\n  const {\n    canvasInstance,\n    magicWandSelection,\n    magicWandSettings,\n    syncLayers,\n    saveHistoryState,\n  } = get();\n  if (!canvasInstance || !magicWandSelection) return false;\n\n  const target = canvasInstance.getObjects().find(\n    (o) => (o as FabricObject & { id?: string }).id === magicWandSelection.objectId,\n  ) as FabricImage | undefined;\n  if (!target || target.type?.toLowerCase() !== 'image') {\n    set({ magicWandSelection: null });\n    return false;\n  }\n\n  const {\n    applyMaskDelete,\n    applyMaskFill,\n    extractMaskToFullDataUrl,\n    fabricImageObjectToImageData,\n    fabricImageToImageData,\n    imageDataHasOpaquePixels,\n    imageDataToCanvas,\n  } = await import('../utils/magicWandSelection');\n\n  const w = magicWandSelection.width;\n  const h = magicWandSelection.height;\n  let imageData = fabricImageObjectToImageData(target);\n  if (imageDataHasOpaquePixels(imageData) && (imageData.width !== w || imageData.height !== h)) {\n    imageData = fabricImageToImageData(imageDataToCanvas(imageData), w, h);\n  } else if (!imageDataHasOpaquePixels(imageData)) {\n    imageData = fabricImageToImageData(target.getElement(), w, h);\n  }\n  if (!imageDataHasOpaquePixels(imageData)) {\n    return false;\n  }\n  const mask = {\n    width: w,\n    height: h,\n    data: magicWandSelection.maskData,\n    bounds: { minX: 0, minY: 0, maxX: w - 1, maxY: h - 1 },\n    pixelCount: magicWandSelection.pixelCount,\n  };\n\n  if (op === 'cut') {\n    const cutUrl = extractMaskToFullDataUrl(imageData, mask);\n    applyMaskDelete(imageData, mask);\n    const edited = imageDataToCanvas(imageData);\n    target.setElement(edited);\n    target.set({ dirty: true });\n    target.setCoords();\n\n    const cutImg = await FabricImage.fromURL(cutUrl, { crossOrigin: 'anonymous' });\n    cutImg.set({\n      left: target.left,\n      top: target.top,\n      scaleX: target.scaleX,\n      scaleY: target.scaleY,\n      angle: target.angle,\n      flipX: target.flipX,\n      flipY: target.flipY,\n      originX: target.originX,\n      originY: target.originY,\n      id: `image-wand-${Date.now()}`,\n      name: `${(target as FabricObject & { name?: string }).name || 'Imagen'} (selecci\u00F3n)`,\n    });\n    const idx = canvasInstance.getObjects().indexOf(target);\n    canvasInstance.add(cutImg);\n    if (idx >= 0) canvasInstance.moveObjectTo(cutImg, idx + 1);\n    canvasInstance.setActiveObject(cutImg);\n    set({ activeObject: cutImg, magicWandSelection: null });\n  } else if (op === 'fill') {\n    const { parseCssColor } = await import('../utils/colorRgba');\n    const rgba = parseCssColor(get().masterColors.fill || magicWandSettings.fillColor || '#DB2777');\n    applyMaskFill(imageData, mask, {\n      r: rgba.r,\n      g: rgba.g,\n      b: rgba.b,\n      a: rgba.a,\n    });\n    const edited = imageDataToCanvas(imageData);\n    target.setElement(edited);\n    target.set({ dirty: true });\n    target.setCoords();\n    set({ magicWandSelection: null });\n  } else {\n    applyMaskDelete(imageData, mask);\n    const edited = imageDataToCanvas(imageData);\n    target.setElement(edited);\n    target.set({ dirty: true });\n    target.setCoords();\n    set({ magicWandSelection: null });\n  }\n\n  canvasInstance.requestRenderAll();\n  syncLayers();\n  saveHistoryState();\n  return true;\n}\n\n/** Paint master fill/stroke onto the active canvas selection (Photoshop-style). */\nfunction applyMasterColorToSelection(\n  get: () => EditorState,\n  channel: MasterColorChannel,\n  css: string,\n): void {\n  const { activeObject, canvasInstance } = get();\n  if (!activeObject || !canvasInstance) return;\n\n  const normalized =\n    !css || css === 'none' || css.toLowerCase() === 'transparent' ? 'transparent' : css;\n\n  const paintOne = (obj: FabricObject): boolean => {\n    const type = (obj.type || '').toLowerCase();\n    if (type === 'image') return false;\n    if (channel === 'fill') {\n      if (type === 'line') return false;\n      const fill = obj.fill;\n      if (fill && typeof fill === 'object') return false; // keep gradients\n      obj.set({ fill: normalized });\n      return true;\n    }\n    obj.set({ stroke: normalized });\n    return true;\n  };\n\n  let applied = false;\n  const type = (activeObject.type || '').toLowerCase();\n  if (\n    type === 'activeselection' &&\n    typeof (activeObject as { getObjects?: () => FabricObject[] }).getObjects === 'function'\n  ) {\n    for (const child of (activeObject as { getObjects: () => FabricObject[] }).getObjects()) {\n      if (paintOne(child)) applied = true;\n    }\n  } else if (paintOne(activeObject as FabricObject)) {\n    applied = true;\n  }\n\n  if (!applied) return;\n\n  if (isTextObject(activeObject)) {\n    if (channel === 'fill') {\n      get().updateTextSettings({ fill: normalized });\n    } else {\n      get().updateTextSettings({ stroke: normalized });\n    }\n  }\n\n  canvasInstance.requestRenderAll();\n}\n\nexport const useEditorStore = create<EditorState>((set, get) => ({\n  // \u2500\u2500 Multi-project initial state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  imageProjects: [],\n  activeImageProjectId: null,\n  // false by default \u2014 loadProject() sets it to true only for first-time users.\n  isImageSetupOpen: false,\n  // true while loadProject() reads IndexedDB \u2014 App waits before rendering.\n  isProjectLoading: true,\n\n  setIsImageSetupOpen: (open) => set({ isImageSetupOpen: open }),\n\n  createImageProject: (name, width, height, backgroundColor) => {\n    const projectId = `proj-${Date.now()}`;\n    const pageId = `page-${Date.now()}`;\n    const initialJSON = { version: '6.0.0', objects: [], background: backgroundColor };\n    const jsonStr = JSON.stringify(initialJSON);\n    const newPage: Page = {\n      id: pageId,\n      name: 'P\u00E1gina 1',\n      width,\n      height,\n      backgroundColor,\n      json: initialJSON,\n      history: [jsonStr],\n      historyIndex: 0,\n    };\n    const newProject: ImageProject = {\n      id: projectId,\n      name,\n      pages: [newPage],\n      activePageId: pageId,\n      createdAt: Date.now(),\n    };\n    set((state) => ({\n      imageProjects: [...state.imageProjects, newProject],\n      activeImageProjectId: projectId,\n      pages: [newPage],\n      activePageId: pageId,\n      isImageSetupOpen: false,\n      activeObject: null,\n      // Do NOT null canvasInstance here. Nulling it disconnects the real Fabric canvas\n      // from the store, causing saveHistoryState to return early (null guard) and\n      // never persist objects for projects 2+.\n      // Instead, fire canvasSyncTrigger so CanvasArea's loadFromJSON effect reloads\n      // the new blank page into the existing canvas.\n      canvasSyncTrigger: state.canvasSyncTrigger + 1,\n    }));\n  },\n\n  importImageProject: (fileData, fileName, opts) => {\n    const projectId = `proj-${Date.now()}`;\n    const projectName = fileName.replace(/\\.(kai|wzrd)$/i, '') || 'Proyecto importado';\n\n    // Build pages from the file. The .kai (legacy .wzrd) format may have a pages[] array\n    // (multi-page export) or a single canvasJSON (legacy single-page export).\n    let pages: Page[];\n    if (fileData.pages && Array.isArray(fileData.pages) && fileData.pages.length > 0) {\n      pages = fileData.pages.map((p: any, i: number) => ({\n        id: p.id || `page-${Date.now()}-${i}`,\n        name: p.name || `P\u00E1gina ${i + 1}`,\n        width: p.width || 1080,\n        height: p.height || 1080,\n        backgroundColor: p.backgroundColor || '#ffffff',\n        json: p.json || { version: '6.0.0', objects: [] },\n        history: [JSON.stringify(p.json || {})],\n        historyIndex: 0,\n      }));\n    } else if (fileData.canvasJSON) {\n      const pageId = `page-${Date.now()}`;\n      pages = [{\n        id: pageId,\n        name: 'P\u00E1gina 1',\n        width: fileData.canvasJSON.width || 1080,\n        height: fileData.canvasJSON.height || 1080,\n        backgroundColor: fileData.canvasJSON.background || '#ffffff',\n        json: fileData.canvasJSON,\n        history: [JSON.stringify(fileData.canvasJSON)],\n        historyIndex: 0,\n      }];\n    } else {\n      console.warn('importImageProject: could not parse file data');\n      return;\n    }\n\n    const newProject: ImageProject = {\n      id: projectId,\n      name: projectName,\n      pages,\n      activePageId: pages[0].id,\n      createdAt: Date.now(),\n      cloudEditableId: opts?.cloudEditableId,\n    };\n\n    set((state) => ({\n      imageProjects: [...state.imageProjects, newProject],\n      activeImageProjectId: projectId,\n      pages,\n      activePageId: pages[0].id,\n      isImageSetupOpen: false,\n      activeObject: null,\n      canvasSyncTrigger: state.canvasSyncTrigger + 1,\n    }));\n  },\n\n  closeImageProject: (projectId) => {\n    const { imageProjects, activeImageProjectId, pages, activePageId, canvasInstance } = get();\n    const remaining = imageProjects.filter(p => p.id !== projectId);\n\n    // Snapshot live canvas into closing project first (safe even if not needed)\n    let currentPages = pages;\n    if (canvasInstance && activeImageProjectId === projectId) {\n      try {\n        const liveJSON = (canvasInstance as any).toJSON();\n        currentPages = pages.map(p =>\n          p.id === activePageId ? { ...p, json: liveJSON } : p\n        );\n      } catch (_) {}\n    }\n\n    if (remaining.length === 0) {\n      set({ imageProjects: [], activeImageProjectId: null, pages: [], activePageId: '', isImageSetupOpen: true, canvasInstance: null });\n      return;\n    }\n    const newActive = activeImageProjectId === projectId\n      ? remaining[remaining.length - 1]\n      : imageProjects.find(p => p.id === activeImageProjectId) || remaining[0];\n\n    const syncedRemaining = remaining.map(p =>\n      p.id === activeImageProjectId && activeImageProjectId !== projectId\n        ? { ...p, pages: currentPages, activePageId }\n        : p\n    );\n\n    set({\n      imageProjects: syncedRemaining,\n      activeImageProjectId: newActive.id,\n      pages: newActive.pages,\n      activePageId: newActive.activePageId,\n      activeObject: null,\n      canvasSyncTrigger: get().canvasSyncTrigger + 1,\n    });\n  },\n\n  switchImageProject: (projectId) => {\n    const { imageProjects, activeImageProjectId, pages, activePageId, canvasInstance } = get();\n    if (projectId === activeImageProjectId) return;\n\n    // \u2500\u2500 Step 1: snapshot the live canvas into the outgoing project \u2500\u2500\n    // Read directly from the Fabric instance so we always get the latest painted state,\n    // not a possibly-stale store snapshot.\n    let currentPages = pages;\n    if (canvasInstance) {\n      try {\n        const liveJSON = (canvasInstance as any).toJSON();\n        currentPages = pages.map(p =>\n          p.id === activePageId ? { ...p, json: liveJSON } : p\n        );\n      } catch (_) { /* ignore serialisation errors */ }\n    }\n\n    const syncedProjects = imageProjects.map(p =>\n      p.id === activeImageProjectId\n        ? { ...p, pages: currentPages, activePageId }\n        : p\n    );\n\n    const target = syncedProjects.find(p => p.id === projectId);\n    if (!target) return;\n\n    // \u2500\u2500 Step 2: switch state WITHOUT nulling canvasInstance \u2500\u2500\n    // Keeping canvasInstance alive avoids the race where object:added fires\n    // during loadFromJSON and saveHistoryState corrupts both projects.\n    set({\n      imageProjects: syncedProjects,\n      activeImageProjectId: projectId,\n      pages: target.pages,\n      activePageId: target.activePageId,\n      activeObject: null,\n      canvasSyncTrigger: get().canvasSyncTrigger + 1, // Step 3: fire loadFromJSON\n    });\n  },\n\n  renameImageProject: (projectId, name) => {\n    const trimmed = name.trim();\n    if (!trimmed) return;\n    set((state) => ({\n      imageProjects: state.imageProjects.map((p) =>\n        p.id === projectId ? { ...p, name: trimmed } : p,\n      ),\n    }));\n  },\n\n  // \u2500\u2500 Canvas state (start empty \u2014 populated once a project is created) \u2500\u2500\n  pages: [],\n  activePageId: '',\n  activeTool: 'select',\n  paintTargetLayerId: null as string | null,\n  lastSelectedObjectId: null as string | null,\n  layerPaintTarget: 'content' as 'content' | 'mask',\n  setLayerPaintTarget: (target) => {\n    const patch: {\n      layerPaintTarget: 'content' | 'mask';\n      masterColors?: MasterColors;\n    } = { layerPaintTarget: target };\n    if (target === 'mask') {\n      const mc = get().masterColors;\n      patch.masterColors = { ...mc, fill: '#ffffff', stroke: '#000000' };\n      const canvas = get().canvasInstance;\n      if (canvas?.isDrawingMode && canvas.freeDrawingBrush) {\n        canvas.freeDrawingBrush.color = '#ffffff';\n      }\n    }\n    set(patch);\n  },\n  zoom: 1,\n  canvasInstance: null,\n  activeObject: null,\n  layers: [],\n  isHistoryAction: false,\n  historyPauseCount: 0,\n  pauseHistory: () => set((s) => ({ historyPauseCount: s.historyPauseCount + 1 })),\n  resumeHistory: () =>\n    set((s) => ({ historyPauseCount: Math.max(0, s.historyPauseCount - 1) })),\n  sidebarCollapsed: false,\n  layersPanelCollapsed: false,\n  activeMaskTarget: null,\n  activeCustomShape: null,\n  setActiveMaskTarget: (obj) => set({ activeMaskTarget: obj }),\n  setActiveCustomShape: (shapeId) => set({ activeCustomShape: shapeId }),\n  showAiObjectEraser: false,\n  setShowAiObjectEraser: (show) => set({ showAiObjectEraser: show }),\n  isVariationsModalOpen: false,\n  setVariationsModalOpen: (open) => set({ isVariationsModalOpen: open }),\n  aiVariations: [],\n  setAiVariations: (vars) => set({ aiVariations: vars }),\n  maskMode: false,\n  setMaskMode: (mode) => set({ maskMode: mode }),\n  isAiGenerating: false,\n  magicEraserTargetId: null as string | null,\n  setMagicEraserTargetId: (id) => set({ magicEraserTargetId: id }),\n  aiError: null,\n  aiStudioError: null,\n  setAiGenerating: (generating) => set({ isAiGenerating: generating }),\n  setAiError: (error) =>\n    set({\n      aiError:\n        error == null\n          ? null\n          : sanitizeUserFacingMessage(error, { context: 'aiError:image' }),\n    }),\n  setAiStudioError: (error) => set({ aiStudioError: error }),\n  geminiApiKey: localStorage.getItem('gemini_api_key') || '',\n  setGeminiApiKey: (key) => {\n    localStorage.setItem('gemini_api_key', key);\n    set({ geminiApiKey: key });\n  },\n  aiCopywritingSuggestions: null,\n  setAiCopywritingSuggestions: (suggestions) => set({ aiCopywritingSuggestions: suggestions }),\n  // System State\n  isCommandPaletteOpen: false,\n  setCommandPaletteOpen: (open) => set({ isCommandPaletteOpen: open }),\n  isPlayingSlideshow: false,\n  setPlayingSlideshow: (playing) => set({ isPlayingSlideshow: playing }),\n\n  // Smart Linking\n  linkSelectedObjects: () => {\n    const { activeObject, canvasInstance } = get();\n    if (!activeObject || !canvasInstance) return;\n    \n    const linkId = `link-${Date.now()}`;\n    let objectsToLink: any[] = [];\n    \n    if (activeObject.type === 'activeselection') {\n      objectsToLink = (activeObject as any).getObjects();\n    } else {\n      objectsToLink = [activeObject];\n    }\n    \n    objectsToLink.forEach(obj => {\n      obj.set('linkId', linkId);\n    });\n    \n    canvasInstance.requestRenderAll();\n    get().syncLayers();\n    get().saveHistoryState();\n    get().addToast(getActiveMessages().store.toasts.editor.objectLinked, 'success');\n  },\n\n  unlinkSelectedObjects: () => {\n    const { activeObject, canvasInstance } = get();\n    if (!activeObject || !canvasInstance) return;\n    \n    let objectsToUnlink: any[] = [];\n    \n    if (activeObject.type === 'activeselection') {\n      objectsToUnlink = (activeObject as any).getObjects();\n    } else {\n      objectsToUnlink = [activeObject];\n    }\n    \n    objectsToUnlink.forEach(obj => {\n      obj.set('linkId', null);\n    });\n    \n    canvasInstance.requestRenderAll();\n    get().syncLayers();\n    get().saveHistoryState();\n    get().addToast(getActiveMessages().store.toasts.editor.objectUnlinked, 'success');\n  },\n\n  propagateLinkedObject: (modifiedObj: any) => {\n    const state = get();\n    const linkId = modifiedObj.linkId;\n    if (!linkId) return;\n\n    // Serialize the modified object\n    const objJSON = modifiedObj.toJSON();\n    \n    const newPages = state.pages.map(page => {\n      if (page.id === state.activePageId) return page; // Don't propagate to the active page we just modified\n      \n      // Update the object in the page JSON\n      let updated = false;\n      const newObjects = (page.json?.objects || []).map((o: any) => {\n        if (o.linkId === linkId) {\n          updated = true;\n          return { ...objJSON, id: o.id }; // Overwrite everything (position, text, colors) but keep original UUID\n        }\n        return o;\n      });\n\n      if (updated) {\n        return {\n          ...page,\n          json: {\n            ...page.json,\n            objects: newObjects\n          }\n        };\n      }\n      return page;\n    });\n\n    set({ pages: newPages });\n  },\n\n  // Persistence\n  saveStatus: 'idle',\n  setSaveStatus: (status) => set({ saveStatus: status }),\n  lastSaved: null,\n  projectVersions: [],\n  \n  saveCurrentProject: async () => {\n    const state = get();\n\n    // CRITICAL: never overwrite IDB with empty state.\n    // The auto-save interval fires unconditionally \u2014 without this guard,\n    // it would write { imageProjects: [] } during load, destroying saved data.\n    if (state.isProjectLoading || state.imageProjects.length === 0) return;\n\n    set({ saveStatus: 'saving' });\n    try {\n      // \u2500\u2500 Snapshot the live canvas into the active page before persisting \u2500\u2500\n      let currentPages = state.pages;\n      if (state.canvasInstance) {\n        try {\n          const liveJSON = (state.canvasInstance as any).toJSON();\n          currentPages = state.pages.map((p: any) =>\n            p.id === state.activePageId ? { ...p, json: liveJSON } : p\n          );\n        } catch (_) {}\n      }\n\n      // Strip history[] / historyIndex before persisting (huge). Keep a small\n      // jpeg thumbnail for Recientes local cards.\n      const serializablePage = (p: any) => ({\n        id: p.id,\n        name: p.name,\n        width: p.width,\n        height: p.height,\n        backgroundColor: p.backgroundColor,\n        json: p.json,\n        thumbnail:\n          typeof p.thumbnail === 'string' && p.thumbnail.startsWith('data:')\n            ? p.thumbnail\n            : undefined,\n      });\n\n      // Sync live canvas state into imageProjects before saving\n      let thumb = '';\n      if (state.canvasInstance) {\n        try {\n          thumb = state.canvasInstance.toDataURL({\n            format: 'jpeg',\n            quality: 0.45,\n            multiplier: 0.18,\n          });\n        } catch {\n          /* tainted / unavailable */\n        }\n      }\n      const pagesWithThumb = currentPages.map((p: any) =>\n        p.id === state.activePageId && thumb\n          ? { ...p, thumbnail: thumb }\n          : p\n      );\n\n      const syncedProjects = state.imageProjects.map((p: any) =>\n        p.id === state.activeImageProjectId\n          ? { ...p, pages: pagesWithThumb, activePageId: state.activePageId }\n          : p\n      );\n\n      const project: SavedProject = {\n        id: 'default-project',\n        name: 'My Project',\n        pages: pagesWithThumb.map(serializablePage),\n        versions: state.projectVersions,\n        lastSaved: Date.now(),\n        imageProjects: syncedProjects.map((proj: any) => ({\n          ...proj,\n          pages: proj.pages.map(serializablePage),\n        })),\n        activeImageProjectId: state.activeImageProjectId,\n      };\n      await saveProjectToDB(project);\n      set({ saveStatus: 'saved', lastSaved: project.lastSaved });\n      setTimeout(() => set({ saveStatus: 'idle' }), 3000);\n    } catch (err) {\n      console.error('[saveCurrentProject] failed:', err);\n      set({ saveStatus: 'error' });\n    }\n  },\n\n  autoSaveProjectToCloud: async () =>\n    withCloudAutosaveToast('image', async () => {\n    const { hasEditorIdentity } = await import('../services/identity');\n    if (!hasEditorIdentity()) return false;\n\n    const state = get();\n    if (\n      state.isProjectLoading ||\n      !state.canvasInstance ||\n      !state.activeImageProjectId ||\n      state.imageProjects.length === 0\n    ) {\n      return false;\n    }\n\n    const projectId = state.activeImageProjectId;\n    const cloudEditableId = state.imageProjects.find((p) => p.id === projectId)?.cloudEditableId;\n\n    try {\n      set({ saveStatus: 'saving' });\n      const { uploadCurrentProjectToCloud } = await import('../utils/projectCloudSerializer');\n      const editable = await uploadCurrentProjectToCloud('image', {\n        editableId: cloudEditableId,\n      });\n\n      const stillActive = get().activeImageProjectId === projectId;\n      if (stillActive) {\n        set((s) => ({\n          imageProjects: s.imageProjects.map((p) =>\n            p.id === projectId ? { ...p, cloudEditableId: editable.id } : p\n          ),\n          saveStatus: 'saved',\n          lastSaved: Date.now(),\n        }));\n        setTimeout(() => {\n          if (get().saveStatus === 'saved') set({ saveStatus: 'idle' });\n        }, 3000);\n      }\n\n      return true;\n    } catch (err) {\n      console.warn('[autoSaveProjectToCloud] failed:', err);\n      set({ saveStatus: 'error' });\n      setTimeout(() => {\n        if (get().saveStatus === 'error') set({ saveStatus: 'idle' });\n      }, 4000);\n      throw err;\n    }\n  }),\n\n  saveNamedVersion: async (name) => {\n    const state = get();\n    const newVersion: ProjectVersion = {\n      id: `v-${Date.now()}`,\n      name,\n      timestamp: Date.now(),\n      pages: state.pages.map(p => ({ ...p, canvas: undefined }))\n    };\n    const newVersions = [newVersion, ...state.projectVersions];\n    set({ projectVersions: newVersions });\n    await get().saveCurrentProject();\n  },\n\n  loadProject: async () => {\n    try {\n      const project = await getProjectFromDB('default-project');\n\n      // \u2500\u2500 Case 1: Multi-project save found \u2500\u2500\n      if (project?.imageProjects && project.imageProjects.length > 0) {\n        const activeId = project.activeImageProjectId || project.imageProjects[0].id;\n        // Re-initialize history for each page (stripped on save to keep IDB writes small).\n        // Without this, saveHistoryState() crashes on undefined.slice().\n        const withHistory = (projs: any[]) => projs.map((proj: any) => ({\n          ...proj,\n          pages: (proj.pages || []).map((p: any) => ({\n            ...p,\n            history: Array.isArray(p.history) ? p.history : [JSON.stringify(p.json ?? {})],\n            historyIndex: typeof p.historyIndex === 'number' ? p.historyIndex : 0,\n          })),\n        }));\n        const rebuiltProjects = withHistory(project.imageProjects);\n        const rebuiltActive = rebuiltProjects.find((p: any) => p.id === activeId) || rebuiltProjects[0];\n        set({\n          imageProjects: rebuiltProjects,\n          activeImageProjectId: activeId,\n          pages: rebuiltActive.pages,\n          activePageId: rebuiltActive.activePageId || rebuiltActive.pages[0]?.id || '',\n          projectVersions: project.versions || [],\n          lastSaved: project.lastSaved,\n          isImageSetupOpen: false,  // existing projects \u2014 no setup\n          isProjectLoading: false,\n        });\n        get().triggerCanvasSync();\n        return;\n      }\n\n      // \u2500\u2500 Case 2: Legacy single-project save found \u2014 migrate into imageProjects \u2500\u2500\n      if (project?.pages && project.pages.length > 0) {\n        const projectId = `proj-migrated-${Date.now()}`;\n        const migratedProject = {\n          id: projectId,\n          name: 'Mi proyecto',\n          pages: project.pages,\n          activePageId: project.pages[0]?.id || '',\n          createdAt: Date.now(),\n        };\n        set({\n          imageProjects: [migratedProject],\n          activeImageProjectId: projectId,\n          pages: project.pages,\n          activePageId: project.pages[0]?.id || '',\n          projectVersions: project.versions || [],\n          lastSaved: project.lastSaved,\n          isImageSetupOpen: false,  // migrated project exists \u2014 no setup\n          isProjectLoading: false,\n        });\n        get().triggerCanvasSync();\n        return;\n      }\n\n      // \u2500\u2500 Case 3: No saved data \u2014 first-time user, show setup \u2500\u2500\n      set({ isImageSetupOpen: true, isProjectLoading: false });\n    } catch (err) {\n      console.error('Failed to load project from IndexedDB:', err);\n      // On error, behave as first-time user\n      set({ isImageSetupOpen: true, isProjectLoading: false });\n    }\n  },\n\n  loadVersion: async (versionId) => {\n    const state = get();\n    const version = state.projectVersions.find(v => v.id === versionId);\n    if (version) {\n      set({ \n        pages: version.pages,\n        activePageId: version.pages[0]?.id || state.activePageId\n      });\n      get().triggerCanvasSync();\n      get().addToast(getActiveMessages().store.toasts.editor.versionLoaded(version.name), 'success');\n    }\n  },\n\n  deleteVersion: async (versionId) => {\n    const state = get();\n    const newVersions = state.projectVersions.filter(v => v.id !== versionId);\n    set({ projectVersions: newVersions });\n    await get().saveCurrentProject();\n  },\n\n  toasts: [],\n  addToast: (message, type = 'info', options) => {\n    const id = Math.random().toString(36).substring(2, 9);\n    const safeMessage =\n      type === 'error'\n        ? sanitizeUserFacingMessage(message, { context: 'toast:image' })\n        : message;\n    const newToast: Toast = { id, message: safeMessage, type };\n    if (options?.progress !== undefined) newToast.progress = options.progress;\n    set((state) => ({ toasts: [...state.toasts, newToast] }));\n\n    const sticky = options?.sticky ?? type === 'error';\n    if (!sticky) {\n      clearToastTimer(id);\n      toastTimers.set(\n        id,\n        setTimeout(() => {\n          toastTimers.delete(id);\n          get().removeToast(id);\n        }, options?.durationMs ?? defaultToastDuration(type)),\n      );\n    }\n    return id;\n  },\n  updateToast: (id, patch) => {\n    const { sticky, durationMs, ...fields } = patch;\n    set((state) => ({\n      toasts: state.toasts.map((toast) => {\n        if (toast.id !== id) return toast;\n        const next: Toast = { ...toast };\n        if (fields.message !== undefined) next.message = fields.message;\n        if (fields.type !== undefined) next.type = fields.type;\n        if (fields.progress === null) {\n          delete next.progress;\n        } else if (fields.progress !== undefined) {\n          next.progress = fields.progress;\n        }\n        return next;\n      }),\n    }));\n\n    const lifecycleChanged =\n      sticky !== undefined || durationMs !== undefined || fields.type !== undefined;\n    if (!lifecycleChanged) return;\n\n    const current = get().toasts.find((toast) => toast.id === id);\n    if (!current) return;\n\n    const isSticky = sticky ?? current.type === 'error';\n    if (isSticky) {\n      clearToastTimer(id);\n      return;\n    }\n    clearToastTimer(id);\n    toastTimers.set(\n      id,\n      setTimeout(() => {\n        toastTimers.delete(id);\n        get().removeToast(id);\n      }, durationMs ?? defaultToastDuration(current.type)),\n    );\n  },\n  removeToast: (id) => {\n    clearToastTimer(id);\n    set((state) => ({ toasts: state.toasts.filter((t) => t.id !== id) }));\n  },\n  \n  colorBlindnessMode: 'normal',\n  setColorBlindnessMode: (mode) => set({ colorBlindnessMode: mode }),\n  extractedColors: [],\n  setExtractedColors: (colors) => set({ extractedColors: colors }),\n  \n  savedPalettes: (() => {\n    try {\n      const parsed = JSON.parse(localStorage.getItem('saved_palettes') || '[]');\n      // Migration from old string[][] format\n      return parsed.map((p: any, i: number) => {\n        if (Array.isArray(p) && typeof p[0] === 'string') {\n          return { id: `palette-${i}-${Date.now()}`, name: `Paleta ${i + 1}`, colors: p };\n        }\n        return p;\n      });\n    } catch {\n      return [];\n    }\n  })(),\n  addPalette: (palette) => {\n    set((state) => {\n      const newPalettes = [...state.savedPalettes, palette];\n      localStorage.setItem('saved_palettes', JSON.stringify(newPalettes));\n      return { savedPalettes: newPalettes };\n    });\n  },\n  upsertPalette: (palette) => {\n    set((state) => {\n      const idx = state.savedPalettes.findIndex((p) => p.id === palette.id);\n      const newPalettes =\n        idx >= 0\n          ? state.savedPalettes.map((p, i) => (i === idx ? palette : p))\n          : [palette, ...state.savedPalettes];\n      localStorage.setItem('saved_palettes', JSON.stringify(newPalettes));\n      return { savedPalettes: newPalettes };\n    });\n  },\n  updatePaletteName: (id, name) => {\n    set((state) => {\n      const newPalettes = state.savedPalettes.map(p => p.id === id ? { ...p, name } : p);\n      localStorage.setItem('saved_palettes', JSON.stringify(newPalettes));\n      return { savedPalettes: newPalettes };\n    });\n  },\n  addColorToPalette: (id, color) => {\n    set((state) => {\n      const newPalettes = state.savedPalettes.map(p => {\n        if (p.id === id) {\n          return { ...p, colors: [...p.colors, color] };\n        }\n        return p;\n      });\n      localStorage.setItem('saved_palettes', JSON.stringify(newPalettes));\n      return { savedPalettes: newPalettes };\n    });\n  },\n  updateColorInPalette: (id, colorIndex, newColor) => {\n    set((state) => {\n      const newPalettes = state.savedPalettes.map(p => {\n        if (p.id === id) {\n          const newColors = [...p.colors];\n          newColors[colorIndex] = newColor;\n          return { ...p, colors: newColors };\n        }\n        return p;\n      });\n      localStorage.setItem('saved_palettes', JSON.stringify(newPalettes));\n      return { savedPalettes: newPalettes };\n    });\n  },\n  removeColorFromPalette: (id, colorIndex) => {\n    set((state) => {\n      const newPalettes = state.savedPalettes.map(p => {\n        if (p.id === id) {\n          const newColors = [...p.colors];\n          newColors.splice(colorIndex, 1);\n          return { ...p, colors: newColors };\n        }\n        return p;\n      });\n      localStorage.setItem('saved_palettes', JSON.stringify(newPalettes));\n      return { savedPalettes: newPalettes };\n    });\n  },\n  reorderColorInPalette: (id, fromIndex, toIndex) => {\n    set((state) => {\n      const newPalettes = state.savedPalettes.map(p => {\n        if (p.id === id) {\n          const newColors = [...p.colors];\n          const [movedColor] = newColors.splice(fromIndex, 1);\n          newColors.splice(toIndex, 0, movedColor);\n          return { ...p, colors: newColors };\n        }\n        return p;\n      });\n      localStorage.setItem('saved_palettes', JSON.stringify(newPalettes));\n      return { savedPalettes: newPalettes };\n    });\n  },\n  deletePalette: (id) => {\n    set((state) => {\n      const newPalettes = state.savedPalettes.filter((p) => p.id !== id);\n      localStorage.setItem('saved_palettes', JSON.stringify(newPalettes));\n      return { savedPalettes: newPalettes };\n    });\n  },\n  applyAiCopywritingSuggestion: (text) => {\n    const { canvasInstance, activeObject, syncLayers, saveHistoryState, setActiveObject } = get();\n    if (!canvasInstance) return;\n\n    if (activeObject && ['textbox', 'text'].includes(activeObject.type?.toLowerCase() || '')) {\n      activeObject.set({ text });\n      canvasInstance.requestRenderAll();\n      syncLayers();\n      saveHistoryState();\n    } else {\n      const center = canvasInstance.getVpCenter();\n      const newText = new Textbox(text, {\n        left: center.x,\n        top: center.y,\n        originX: 'center',\n        originY: 'center',\n        width: 300,\n        fontSize: 32,\n        fontFamily: 'Inter',\n        fill: '#ffffff',\n        textAlign: 'center',\n        editable: true,\n        weTextAutoWidth: true,\n      } as any);\n      canvasInstance.add(newText);\n      sizeTextboxToNaturalWidth(newText);\n      canvasInstance.setActiveObject(newText);\n      setActiveObject(newText);\n      canvasInstance.requestRenderAll();\n      syncLayers();\n      saveHistoryState();\n    }\n  },\n\n  rulersEnabled: true,\n  guidesEnabled: true,\n  snapSettings: {\n    enabled: true,\n    shapes: true,\n    images: true,\n    text: true,\n    canvasEdges: true,\n  },\n  copiedStyle: null,\n  eyedropperApplyChannel: 'fill' as const,\n\n  layoutGridEnabled: false,\n  layoutGridType: 'columns',\n  layoutGridColumns: 12,\n  layoutGridGutter: 20,\n  layoutGridMargin: 20,\n  layoutGridSize: 20,\n  layoutGridColor: 'rgba(236, 72, 153, 0.08)',\n\n  uploadedAssets: [],\n\n  loadUploadedAssets: async () => {\n    const assets = await getAllAssetsFromDB();\n    assets.sort((a, b) => b.timestamp - a.timestamp);\n    set({ uploadedAssets: assets });\n  },\n\n  addUploadedAsset: async (name, url, size, type, width, height) => {\n    const newAsset: UploadedAsset = {\n      id: Math.random().toString(36).substring(2, 9) + Date.now().toString(36),\n      name,\n      url,\n      size,\n      type,\n      width,\n      height,\n      timestamp: Date.now(),\n    };\n    try {\n      await saveAssetToDB(newAsset);\n      const updated = [newAsset, ...get().uploadedAssets];\n      set({ uploadedAssets: updated });\n      get().addToast(getActiveMessages().store.toasts.editor.fileSaved, 'success');\n    } catch (err) {\n      get().addToast(getActiveMessages().store.toasts.editor.fileSaveError, 'error');\n    }\n  },\n\n  deleteUploadedAsset: async (id) => {\n    try {\n      await deleteAssetFromDB(id);\n      set({ uploadedAssets: get().uploadedAssets.filter(a => a.id !== id) });\n      get().addToast(getActiveMessages().store.toasts.editor.fileDeleted, 'info');\n    } catch (err) {\n      get().addToast(getActiveMessages().store.toasts.editor.fileDeleteError, 'error');\n    }\n  },\n\n  clearUploadedAssets: async () => {\n    try {\n      await clearAllAssetsFromDB();\n      set({ uploadedAssets: [] });\n      get().addToast(getActiveMessages().store.toasts.editor.uploadsCleared, 'info');\n    } catch (err) {\n      get().addToast(getActiveMessages().store.toasts.editor.uploadsClearError, 'error');\n    }\n  },\n\n  customFonts: [],\n\n  loadCustomFonts: async () => {\n    const fonts = await getAllFontsFromDB();\n    fonts.sort((a, b) => b.timestamp - a.timestamp);\n    set({ customFonts: fonts });\n    \n    // Register custom fonts in the browser DOM\n    let loadedAny = false;\n    for (const f of fonts) {\n      try {\n        const face = new FontFace(f.name, `url(${f.dataUrl})`);\n        const loaded = await face.load();\n        (document.fonts as any).add(loaded);\n        loadedAny = true;\n      } catch (err) {\n        console.error(`Error registering custom font ${f.name} on load:`, err);\n      }\n    }\n    if (loadedAny) {\n      const { canvasInstance } = get();\n      if (canvasInstance) {\n        canvasInstance.requestRenderAll();\n      }\n    }\n  },\n\n  addCustomFont: async (name, dataUrl) => {\n    const newFont: UploadedFont = {\n      name,\n      dataUrl,\n      timestamp: Date.now(),\n    };\n    try {\n      await saveFontToDB(newFont);\n      const updated = [newFont, ...get().customFonts];\n      set({ customFonts: updated });\n      \n      // Register immediately in the browser\n      const face = new FontFace(name, `url(${dataUrl})`);\n      const loaded = await face.load();\n      (document.fonts as any).add(loaded);\n      get().addToast(getActiveMessages().store.toasts.editor.fontRegistered(name), 'success');\n\n      const { canvasInstance } = get();\n      if (canvasInstance) {\n        canvasInstance.requestRenderAll();\n      }\n    } catch (err: any) {\n      console.error(`Error registering custom font ${name} immediately:`, err);\n      get().addToast(getActiveMessages().store.toasts.editor.fontRegisterError(err instanceof Error ? err.message : ''), 'error');\n    }\n  },\n\n  deleteCustomFont: async (name) => {\n    try {\n      await deleteFontFromDB(name);\n      set({ customFonts: get().customFonts.filter(f => f.name !== name) });\n      get().addToast(getActiveMessages().store.toasts.editor.fontDeleted, 'info');\n    } catch (err) {\n      get().addToast(getActiveMessages().store.toasts.editor.fontDeleteError, 'error');\n    }\n  },\n  \n  brushSettings: {\n    type: 'pencil',\n    color: '#FFFFFF',\n    width: 5,\n    opacity: 1.0,\n    shadowColor: '#000000',\n    shadowBlur: 0,\n    shadowEnabled: false,\n    stabilization: 0.3,\n    pressureSensitivity: false,\n    capType: 'round',\n  },\n\n  magicWandSettings: {\n    tolerance: 32,\n    contiguous: true,\n    fillColor: '#DB2777',\n    selectionMode: 'new',\n  },\n  magicWandSelection: null,\n\n  paintBucketSettings: {\n    tolerance: 32,\n    contiguous: true,\n    antiAlias: true,\n  },\n\n  masterColors: {\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    activeChannel: 'fill',\n  },\n  \n  textSettings: {\n    fontFamily: 'Inter',\n    fontSize: 40,\n    fill: '#000000',\n    fontWeight: 'normal',\n    fontStyle: 'normal',\n    underline: false,\n    textAlign: 'left',\n    charSpacing: 0,\n    lineHeight: 1.16,\n    linethrough: false,\n    overline: false,\n    stroke: 'transparent',\n    strokeWidth: 0,\n    textShadowEnabled: false,\n    textShadowColor: '#000000',\n    textShadowBlur: 0,\n    textShadowOffsetX: 0,\n    textShadowOffsetY: 0,\n    curvature: 0,\n  },\n\n  imageSettings: {\n    brightness: 0,\n    contrast: 0,\n    saturation: 0,\n    blur: 0,\n    hueRotation: 0,\n    exposure: 0,\n    invert: false,\n    activePreset: 'original',\n  },\n\n  setRulersEnabled: (enabled) => set({ rulersEnabled: enabled }),\n  setGuidesEnabled: (enabled) => set({\n    guidesEnabled: enabled,\n    snapSettings: { ...get().snapSettings, enabled },\n  }),\n  setSnapSettings: (settings) => {\n    const snapSettings = { ...get().snapSettings, ...settings };\n    set({\n      snapSettings,\n      guidesEnabled: snapSettings.enabled,\n    });\n  },\n  setEyedropperApplyChannel: (channel) => set({ eyedropperApplyChannel: channel }),\n  setCopiedStyle: (style) => set({ copiedStyle: style }),\n\n  isCanvasSizePanelOpen: false,\n  setCanvasSizePanelOpen: (open) => set({ isCanvasSizePanelOpen: open }),\n  canvasSizeUnit: 'px',\n  setCanvasSizeUnit: (unit) => set({ canvasSizeUnit: unit }),\n\n  setLayoutGridEnabled: (enabled) => {\n    set({ layoutGridEnabled: enabled });\n    get().canvasInstance?.requestRenderAll();\n  },\n  setLayoutGridType: (type) => {\n    set({ layoutGridType: type });\n    get().canvasInstance?.requestRenderAll();\n  },\n  setLayoutGridColumns: (cols) => {\n    set({ layoutGridColumns: cols });\n    get().canvasInstance?.requestRenderAll();\n  },\n  setLayoutGridGutter: (gutter) => {\n    set({ layoutGridGutter: gutter });\n    get().canvasInstance?.requestRenderAll();\n  },\n  setLayoutGridMargin: (margin) => {\n    set({ layoutGridMargin: margin });\n    get().canvasInstance?.requestRenderAll();\n  },\n  setLayoutGridSize: (size) => {\n    set({ layoutGridSize: size });\n    get().canvasInstance?.requestRenderAll();\n  },\n  setLayoutGridColor: (color) => {\n    set({ layoutGridColor: color });\n    get().canvasInstance?.requestRenderAll();\n  },\n\n  setSidebarCollapsed: (collapsed) => set({ sidebarCollapsed: collapsed }),\n  setLayersPanelCollapsed: (collapsed) => set({ layersPanelCollapsed: collapsed }),\n\n  // Canvas Actions\n  canvasSyncTrigger: 0,\n  triggerCanvasSync: () => set((state) => ({ canvasSyncTrigger: state.canvasSyncTrigger + 1 })),\n  setCanvasInstance: (canvas) => {\n    set({ canvasInstance: canvas });\n    if (canvas) {\n      set({ layers: canvas.getObjects().slice().reverse() });\n    } else {\n      set({ layers: [], activeObject: null });\n    }\n  },\n\n  setActiveTool: (tool) => {\n    const { canvasInstance, brushSettings } = get();\n    // T-20260707-14: soportar updater function (Zustand pattern). Sin esto, los callers\n    // que pasan `(prev) => next` almacenaban la funci\u00F3n como activeTool, reventando\n    // cualquier `.startsWith('frame-')` / `switch(activeTool)` que asum\u00EDa string.\n    const prevTool = get().activeTool;\n    const newTool: ToolType = typeof tool === 'function' ? tool(prevTool) : tool;\n    const paintPatch: { activeTool: ToolType; paintTargetLayerId?: string | null } = {\n      activeTool: newTool,\n    };\n    // Capture selected pixel layer before drawing mode clears Fabric selection.\n    if (\n      newTool === 'brush' ||\n      newTool === 'magic-eraser' ||\n      newTool === 'clone-stamp' ||\n      newTool === 'eraser' ||\n      newTool === 'paint-bucket'\n    ) {\n      const ao = get().activeObject;\n      if (isPixelLayer(ao)) {\n        paintPatch.paintTargetLayerId = (ao as PixelLayerImage).id || null;\n      }\n    }\n    set(paintPatch);\n\n    if (canvasInstance) {\n      if (newTool === 'brush' || newTool === 'magic-eraser') {\n        // Magic eraser: only enable free-draw when an image/pixel layer is already focused.\n        if (newTool === 'magic-eraser') {\n          const ao = get().activeObject;\n          const lastId = get().lastSelectedObjectId;\n          const lastObj = lastId ? findObjectById(canvasInstance, lastId) : null;\n          const imageTarget =\n            (ao && (ao.type || '').toLowerCase() === 'image' ? ao : null) ||\n            (lastObj && (lastObj.type || '').toLowerCase() === 'image' ? lastObj : null) ||\n            (isPixelLayer(ao) ? ao : null) ||\n            (isPixelLayer(lastObj) ? lastObj : null);\n          if (imageTarget) {\n            const id =\n              (imageTarget as { id?: string }).id || `img-${Date.now()}`;\n            if (!(imageTarget as { id?: string }).id) {\n              imageTarget.set({ id } as never);\n            }\n            set({ magicEraserTargetId: id });\n            canvasInstance.isDrawingMode = true;\n          } else {\n            set({ magicEraserTargetId: null });\n            canvasInstance.isDrawingMode = false;\n          }\n        } else {\n          canvasInstance.isDrawingMode = true;\n          // Restore drawing brush if a previous session left the legacy style key.\n          if ((brushSettings.type as string) === 'magic-eraser') {\n            set({ brushSettings: { ...brushSettings, type: 'pencil' } });\n          }\n          if (canvasInstance.freeDrawingBrush) {\n            const fillHex = rgbaToHex6(parseCssColor(get().masterColors.fill));\n            canvasInstance.freeDrawingBrush.color = fillHex;\n            canvasInstance.freeDrawingBrush.width = get().brushSettings.width;\n          }\n        }\n      } else {\n        canvasInstance.isDrawingMode = false;\n      }\n\n      // Clear selection if switching to drawing (except brush, wand, lasso, eraser, \u2026)\n      if (\n        newTool !== 'select' &&\n        newTool !== 'select-rect' &&\n        newTool !== 'select-ellipse' &&\n        newTool !== 'select-lasso' &&\n        newTool !== 'move-only' &&\n        newTool !== 'rotate-only' &&\n        newTool !== 'brush' &&\n        newTool !== 'magic-eraser' &&\n        newTool !== 'clone-stamp' &&\n        newTool !== 'magic-wand' &&\n        newTool !== 'pixel-lasso' &&\n        newTool !== 'polygon-lasso' &&\n        newTool !== 'eraser' &&\n        newTool !== 'paint-bucket' &&\n        newTool !== 'crop' &&\n        newTool !== 'eyedropper' &&\n        newTool !== 'pen'\n      ) {\n        canvasInstance.discardActiveObject();\n        canvasInstance.requestRenderAll();\n        set({ activeObject: null });\n      } else if (\n        newTool === 'magic-wand' ||\n        newTool === 'select-rect' ||\n        newTool === 'select-ellipse' ||\n        newTool === 'pixel-lasso' ||\n        newTool === 'polygon-lasso' ||\n        newTool === 'eraser' ||\n        newTool === 'paint-bucket'\n      ) {\n        // Keep / restore the current image in both Fabric and the store (panels read the store).\n        const storeAo = get().activeObject;\n        const canvasAo = canvasInstance.getActiveObject() as FabricObject | null;\n        const paintId = get().paintTargetLayerId;\n        const fromPaint = paintId\n          ? (canvasInstance.getObjects().find(\n              (o) => (o as FabricObject & { id?: string }).id === paintId,\n            ) as FabricObject | undefined) ?? null\n          : null;\n        const ao =\n          (storeAo && canvasInstance.getObjects().includes(storeAo as FabricObject)\n            ? (storeAo as FabricObject)\n            : null) ||\n          (canvasAo && canvasInstance.getObjects().includes(canvasAo) ? canvasAo : null) ||\n          fromPaint;\n        if (ao) {\n          canvasInstance.setActiveObject(ao);\n          canvasInstance.requestRenderAll();\n          set({ activeObject: ao });\n        }\n      } else if (newTool === 'select' || newTool === 'move-only') {\n        // Float pixel mask only when leaving wand/lasso \u2192 V (not when finishing object marquee).\n        const sel = get().magicWandSelection;\n        if (isPixelSelectionTool(prevTool) && sel && sel.pixelCount > 0) {\n          void get().floatPixelSelection();\n        }\n      }\n    }\n  },\n\n  setZoom: (zoom) => {\n    // State only \u2014 CanvasArea / wheel handler own Fabric zoom apply.\n    // Re-applying here + in a useEffect caused flicker on zoom-in.\n    const clampedZoom = Math.min(Math.max(zoom, 0.1), 10);\n    set({ zoom: clampedZoom });\n  },\n\n  setActiveObject: (obj) => {\n    // Empty-canvas click: clear Fabric selection chrome, keep layer focus via lastSelectedObjectId.\n    if (obj === null) {\n      set({ activeObject: null });\n      return;\n    }\n\n    const prev = get().activeObject;\n\n    const patch: {\n      activeObject: FabricObject | null;\n      paintTargetLayerId?: string | null;\n      lastSelectedObjectId?: string | null;\n      layerPaintTarget?: 'content' | 'mask';\n    } = {\n      activeObject: obj,\n      lastSelectedObjectId:\n        (obj as FabricObject & { id?: string }).id || get().lastSelectedObjectId,\n    };\n    if (isPixelLayer(obj)) {\n      syncPixelLayerInteraction(obj as PixelLayerImage);\n      patch.paintTargetLayerId = (obj as PixelLayerImage).id || null;\n      if (!hasLayerMask(obj as PixelLayerImage) && get().layerPaintTarget === 'mask') {\n        patch.layerPaintTarget = 'content';\n      }\n      get().canvasInstance?.requestRenderAll();\n    }\n    set(patch);\n    if (obj) {\n      // Sync tool settings with the selected object\n      if (isTextObject(obj)) {\n        const textObj = obj as any;\n        const nextSettings = {\n          fontFamily: textObj.fontFamily || 'Inter',\n          fontSize: getEffectiveFontSize(textObj),\n          fill: textObj.fill?.toString() || '#000000',\n          fontWeight: textObj.fontWeight || 'normal',\n          fontStyle: textObj.fontStyle || 'normal',\n          underline: textObj.underline || false,\n          textAlign: textObj.textAlign || 'left',\n          charSpacing: textObj.charSpacing || 0,\n          lineHeight: textObj.lineHeight || 1.16,\n          linethrough: textObj.linethrough || false,\n          overline: textObj.overline || false,\n          stroke: textObj.stroke || 'transparent',\n          strokeWidth: textObj.strokeWidth || 0,\n          textShadowEnabled: !!textObj.shadow,\n          textShadowColor: textObj.shadow?.color || '#000000',\n          textShadowBlur: textObj.shadow?.blur || 0,\n          textShadowOffsetX: textObj.shadow?.offsetX || 0,\n          textShadowOffsetY: textObj.shadow?.offsetY || 0,\n          curvature: textObj.curvature || 0,\n        };\n        const cur = get().textSettings;\n        const settingsChanged =\n          cur.fontFamily !== nextSettings.fontFamily ||\n          cur.fontSize !== nextSettings.fontSize ||\n          cur.fill !== nextSettings.fill ||\n          cur.fontWeight !== nextSettings.fontWeight ||\n          cur.fontStyle !== nextSettings.fontStyle ||\n          cur.underline !== nextSettings.underline ||\n          cur.textAlign !== nextSettings.textAlign ||\n          cur.charSpacing !== nextSettings.charSpacing ||\n          cur.lineHeight !== nextSettings.lineHeight ||\n          cur.linethrough !== nextSettings.linethrough ||\n          cur.overline !== nextSettings.overline ||\n          cur.stroke !== nextSettings.stroke ||\n          cur.strokeWidth !== nextSettings.strokeWidth ||\n          cur.textShadowEnabled !== nextSettings.textShadowEnabled ||\n          cur.curvature !== nextSettings.curvature;\n        if (settingsChanged) {\n          set({ textSettings: nextSettings });\n        }\n        // Remeasure only on newly selected text \u2014 re-clicking the same\n        // object was re-fitting width and fighting Fabric's hidden\n        // textarea focus (document scroll / \"body jumps\").\n        if (obj !== prev) {\n          void remeasureTextObject(textObj).then(() => {\n            get().canvasInstance?.requestRenderAll();\n          });\n        }\n      }\n      // If image object is selected, we can read filters (we'll implement this on slider adjustments)\n    }\n  },\n\n  setLayers: (layers) => set({ layers: layers.filter((l: any) => l.name !== 'eraser-mark') }),\n\n  updateBrushSettings: (settings) => {\n    const { brushSettings } = get();\n    const newSettings = { ...brushSettings, ...settings };\n    // Legacy: magic eraser used to be a brush style \u2014 coerce to pencil.\n    if ((newSettings.type as string) === 'magic-eraser') {\n      newSettings.type = 'pencil';\n    }\n    set({ brushSettings: newSettings });\n  },\n\n  updateMagicWandSettings: (settings) => {\n    set({ magicWandSettings: { ...get().magicWandSettings, ...settings } });\n  },\n\n  updatePaintBucketSettings: (settings) => {\n    set({ paintBucketSettings: { ...get().paintBucketSettings, ...settings } });\n  },\n\n  setMasterColorChannel: (channel) => {\n    set({ masterColors: { ...get().masterColors, activeChannel: channel } });\n  },\n\n  setMasterColorValue: (channel, css) => {\n    let normalized = isNoneCssColor(css) ? 'transparent' : css;\n    // Mask painting is grayscale only (luminance \u2192 white reveals / black hides).\n    if (\n      get().layerPaintTarget === 'mask' &&\n      !isNoneCssColor(normalized)\n    ) {\n      normalized = cssColorToMaskGray(normalized);\n    }\n    const masterColors = { ...get().masterColors, [channel]: normalized };\n    set({ masterColors });\n    if (channel === 'fill' && !isNoneCssColor(normalized)) {\n      const hex = rgbaToHex6(parseCssColor(normalized));\n      set({ brushSettings: { ...get().brushSettings, color: hex } });\n      const canvas = get().canvasInstance;\n      if (canvas?.freeDrawingBrush) {\n        canvas.freeDrawingBrush.color = hex;\n      }\n    }\n    applyMasterColorToSelection(get, channel, normalized);\n  },\n\n  updateMasterColors: (partial) => {\n    const normalizedPartial = { ...partial };\n    if (partial.fill !== undefined && isNoneCssColor(partial.fill)) {\n      normalizedPartial.fill = 'transparent';\n    }\n    if (partial.stroke !== undefined && isNoneCssColor(partial.stroke)) {\n      normalizedPartial.stroke = 'transparent';\n    }\n    const masterColors = { ...get().masterColors, ...normalizedPartial };\n    set({ masterColors });\n    if (normalizedPartial.fill !== undefined) {\n      if (!isNoneCssColor(normalizedPartial.fill)) {\n        const hex = rgbaToHex6(parseCssColor(normalizedPartial.fill));\n        set({ brushSettings: { ...get().brushSettings, color: hex } });\n        const canvas = get().canvasInstance;\n        if (canvas?.freeDrawingBrush) {\n          canvas.freeDrawingBrush.color = hex;\n        }\n      }\n      applyMasterColorToSelection(get, 'fill', normalizedPartial.fill);\n    }\n    if (normalizedPartial.stroke !== undefined) {\n      applyMasterColorToSelection(get, 'stroke', normalizedPartial.stroke);\n    }\n  },\n\n  swapMasterColors: () => {\n    const { fill, stroke, activeChannel } = get().masterColors;\n    get().updateMasterColors({ fill: stroke, stroke: fill, activeChannel });\n  },\n\n  /** Sync master swatches from the selected object (no re-apply loop). */\n  hydrateMasterColorsFromSelection: () => {\n    const { activeObject } = get();\n    if (!activeObject) return;\n    const type = (activeObject.type || '').toLowerCase();\n    if (type === 'activeselection') return;\n\n    const next = { ...get().masterColors };\n    let changed = false;\n\n    if (type !== 'image' && type !== 'line') {\n      const fill = activeObject.fill;\n      if (typeof fill === 'string') {\n        next.fill = isNoneCssColor(fill) ? 'transparent' : fill;\n        changed = true;\n      }\n    }\n    if (type === 'line') {\n      const stroke = activeObject.stroke;\n      if (typeof stroke === 'string') {\n        next.fill = isNoneCssColor(stroke) ? 'transparent' : stroke;\n        changed = true;\n      }\n    } else {\n      const stroke = activeObject.stroke;\n      if (typeof stroke === 'string') {\n        next.stroke = isNoneCssColor(stroke) ? 'transparent' : stroke;\n        changed = true;\n      }\n    }\n\n    if (!changed) return;\n    set({ masterColors: next });\n    if (!isNoneCssColor(next.fill) && next.fill !== get().brushSettings.color) {\n      const hex = rgbaToHex6(parseCssColor(next.fill));\n      set({ brushSettings: { ...get().brushSettings, color: hex } });\n      const canvas = get().canvasInstance;\n      if (canvas?.freeDrawingBrush) {\n        canvas.freeDrawingBrush.color = hex;\n      }\n    }\n  },\n\n  setMagicWandSelection: (selection) => set({ magicWandSelection: selection }),\n\n  clearMagicWandSelection: () => set({ magicWandSelection: null }),\n\n  applyMagicWandDelete: async () => {\n    const applied = await applyMagicWandMutation(get, set, 'delete');\n    if (applied) {\n      get().addToast(getActiveMessages().canvas.magicWand.toasts.deleted, 'success');\n    }\n  },\n\n  applyMagicWandFill: async () => {\n    const applied = await applyMagicWandMutation(get, set, 'fill');\n    if (applied) {\n      get().addToast(getActiveMessages().canvas.magicWand.toasts.filled, 'success');\n    }\n  },\n\n  applyMagicWandCutToLayer: async () => {\n    const applied = await applyMagicWandMutation(get, set, 'cut');\n    if (applied) {\n      get().addToast(getActiveMessages().canvas.magicWand.toasts.cut, 'success');\n    }\n  },\n\n  floatPixelSelection: async () => {\n    return applyMagicWandMutation(get, set, 'cut');\n  },\n\n  updateTextSettings: (settings) => {\n    const { textSettings, activeObject, canvasInstance } = get();\n    const newSettings = { ...textSettings, ...settings };\n    set({ textSettings: newSettings });\n\n    if (activeObject && isTextObject(activeObject)) {\n      const fabricSettings: any = {};\n      \n      if (settings.fontFamily !== undefined) fabricSettings.fontFamily = settings.fontFamily;\n      if (settings.fontSize !== undefined) {\n        // Flatten any live scale first so panel size maps 1:1 to glyphs + box.\n        bakeTextScale(activeObject);\n        const oldSize = Math.max(1, activeObject.fontSize || 40);\n        const ratio = settings.fontSize / oldSize;\n        fabricSettings.fontSize = settings.fontSize;\n        fabricSettings.scaleX = 1;\n        fabricSettings.scaleY = 1;\n        if (activeObject instanceof Textbox) {\n          fabricSettings.width = Math.max(\n            activeObject.minWidth || 20,\n            (activeObject.width || 0) * ratio,\n          );\n        }\n      }\n      if (settings.fill !== undefined) fabricSettings.fill = settings.fill;\n      if (settings.fontWeight !== undefined) fabricSettings.fontWeight = settings.fontWeight;\n      if (settings.fontStyle !== undefined) fabricSettings.fontStyle = settings.fontStyle;\n      if (settings.underline !== undefined) fabricSettings.underline = settings.underline;\n      if (settings.textAlign !== undefined) fabricSettings.textAlign = settings.textAlign;\n      if (settings.charSpacing !== undefined) fabricSettings.charSpacing = settings.charSpacing;\n      if (settings.lineHeight !== undefined) fabricSettings.lineHeight = settings.lineHeight;\n      if (settings.linethrough !== undefined) fabricSettings.linethrough = settings.linethrough;\n      if (settings.overline !== undefined) fabricSettings.overline = settings.overline;\n      if (settings.stroke !== undefined) fabricSettings.stroke = settings.stroke;\n      if (settings.strokeWidth !== undefined) fabricSettings.strokeWidth = settings.strokeWidth;\n      \n      if (settings.curvature !== undefined) {\n        fabricSettings.curvature = settings.curvature;\n        updateTextPath(activeObject, settings.curvature);\n      }\n      \n      const hasShadowUpdate = \n        settings.textShadowEnabled !== undefined || \n        settings.textShadowColor !== undefined || \n        settings.textShadowBlur !== undefined || \n        settings.textShadowOffsetX !== undefined || \n        settings.textShadowOffsetY !== undefined;\n        \n      if (hasShadowUpdate) {\n        const shadowEnabled = settings.textShadowEnabled !== undefined ? settings.textShadowEnabled : newSettings.textShadowEnabled;\n        if (shadowEnabled) {\n          const color = settings.textShadowColor !== undefined ? settings.textShadowColor : newSettings.textShadowColor;\n          const blur = settings.textShadowBlur !== undefined ? settings.textShadowBlur : newSettings.textShadowBlur;\n          const offsetX = settings.textShadowOffsetX !== undefined ? settings.textShadowOffsetX : newSettings.textShadowOffsetX;\n          const offsetY = settings.textShadowOffsetY !== undefined ? settings.textShadowOffsetY : newSettings.textShadowOffsetY;\n          \n          fabricSettings.shadow = new Shadow({\n            color,\n            blur,\n            offsetX,\n            offsetY,\n            affectStroke: false\n          });\n        } else {\n          fabricSettings.shadow = null;\n        }\n      }\n\n      // Font metrics can make lines wider/taller than the box after a size/family change.\n      // Assign fontFamily without Fabric `set()` so sync initDimensions does not\n      // run against the fallback face (that shrinks selection controls).\n      if (settings.fontFamily !== undefined) {\n        activeObject.fontFamily = settings.fontFamily;\n        activeObject.dirty = true;\n        delete fabricSettings.fontFamily;\n      }\n\n      if (Object.keys(fabricSettings).length > 0) {\n        activeObject.set(fabricSettings);\n      }\n\n      if (\n        settings.fontSize !== undefined ||\n        settings.fontFamily !== undefined ||\n        settings.fontWeight !== undefined ||\n        settings.fontStyle !== undefined ||\n        settings.charSpacing !== undefined ||\n        settings.strokeWidth !== undefined ||\n        settings.lineHeight !== undefined\n      ) {\n        void remeasureTextObject(activeObject).then(() => {\n          activeObject.setCoords();\n          canvasInstance?.requestRenderAll();\n        });\n      }\n\n      if (canvasInstance) {\n        canvasInstance.requestRenderAll();\n        get().saveHistoryState();\n      }\n    }\n  },\n\n  updateImageSettings: (settings) => {\n    const { imageSettings, activeObject, canvasInstance } = get();\n    const newSettings = { ...imageSettings, ...settings };\n    set({ imageSettings: newSettings });\n\n    // We'll apply filters directly in the CanvasArea components via image helpers,\n    // but saving imageSettings here allows controls to stay in sync.\n    if (activeObject && activeObject.type?.toLowerCase() === 'image') {\n      // Trigger canvas render and state save if it exists\n      if (canvasInstance) {\n        // We'll apply the filters directly to the object inside our UI interaction\n        // and trigger saveHistoryState inside the component to prevent spamming history.\n      }\n    }\n  },\n\n  applyImagePreset: (presetName) => {\n    const { canvasInstance, activeObject, updateImageSettings, saveHistoryState } = get();\n    if (!canvasInstance || !activeObject) return;\n    if ((activeObject.type || '').toLowerCase() !== 'image') return;\n\n    const imgObj = activeObject as any;\n    if (!imgObj.filters) imgObj.filters = [];\n\n    const newSettings = buildImageFilterPreset(imgObj, presetName);\n    updateImageSettings(newSettings);\n    imgObj.applyFilters();\n    canvasInstance.requestRenderAll();\n    saveHistoryState();\n  },\n\n  addPage: (width = defaultPageDimensions.width, height = defaultPageDimensions.height) => {\n    const { pages } = get();\n    const newId = `page-${Date.now()}`;\n    const newPageObj = defaultPage(newId, pages.length);\n    newPageObj.width = width;\n    newPageObj.height = height;\n    \n    set({\n      pages: [...pages, newPageObj],\n      activePageId: newId,\n    });\n  },\n\n  deletePage: (id) => {\n    const { pages, activePageId } = get();\n    if (pages.length <= 1) return; // Prevent deleting the last page\n    \n    const pageIndex = pages.findIndex(p => p.id === id);\n    const newPages = pages.filter(p => p.id !== id);\n    \n    let newActivePageId = activePageId;\n    if (activePageId === id) {\n      // Switch to the previous page or first page\n      const fallbackIndex = Math.max(0, pageIndex - 1);\n      newActivePageId = newPages[fallbackIndex].id;\n    }\n\n    set({\n      pages: newPages,\n      activePageId: newActivePageId,\n    });\n  },\n\n  duplicatePage: (id) => {\n    const { pages, canvasInstance, activePageId } = get();\n    const pageIndex = pages.findIndex(p => p.id === id);\n    if (pageIndex === -1) return;\n    \n    const pageToDuplicate = pages[pageIndex];\n    let activePageJSON = pageToDuplicate.json;\n    if (canvasInstance && activePageId === id) {\n      activePageJSON = (canvasInstance as any).toJSON();\n    }\n\n    const newId = `page-${Date.now()}`;\n    const newPage: Page = {\n      ...pageToDuplicate,\n      id: newId,\n      name: `${pageToDuplicate.name} (Copia)`,\n      json: JSON.parse(JSON.stringify(activePageJSON)),\n      history: [JSON.stringify(activePageJSON)],\n      historyIndex: 0,\n    };\n\n    const newPages = [...pages];\n    newPages.splice(pageIndex + 1, 0, newPage);\n\n    set({\n      pages: newPages,\n      activePageId: newId,\n    });\n    \n    // Trigger history saving on the newly duplicated page\n    setTimeout(() => {\n      const currentCanvas = get().canvasInstance;\n      if (currentCanvas) {\n        get().saveHistoryState();\n      }\n    }, 50);\n  },\n\n  clearPage: (id) => {\n    const { pages, canvasInstance, activePageId } = get();\n    const updatedPages = pages.map(p => {\n      if (p.id === id) {\n        const initialJSON = {\n          version: '6.0.0',\n          objects: [],\n          background: p.backgroundColor,\n        };\n        return {\n          ...p,\n          json: initialJSON,\n          history: [JSON.stringify(initialJSON)],\n          historyIndex: 0,\n        };\n      }\n      return p;\n    });\n\n    set({ pages: updatedPages });\n\n    if (canvasInstance && activePageId === id) {\n      canvasInstance.clear();\n      const activePage = updatedPages.find(p => p.id === id);\n      if (activePage) {\n        applyCanvasBackground(canvasInstance, activePage.backgroundColor, activePage.width, activePage.height);\n      }\n      canvasInstance.renderAll();\n      set({ layers: [], activeObject: null });\n      get().saveHistoryState();\n    }\n  },\n\n  movePage: (id, direction) => {\n    const { pages } = get();\n    const index = pages.findIndex(p => p.id === id);\n    if (index === -1) return;\n\n    const newIndex = direction === 'up' ? index - 1 : index + 1;\n    if (newIndex < 0 || newIndex >= pages.length) return;\n\n    const newPages = [...pages];\n    const temp = newPages[index];\n    newPages[index] = newPages[newIndex];\n    newPages[newIndex] = temp;\n\n    set({ pages: newPages });\n  },\n\n  renamePage: (id, name) => {\n    const { pages } = get();\n    const updatedPages = pages.map(p => {\n      if (p.id === id) {\n        return { ...p, name };\n      }\n      return p;\n    });\n    set({ pages: updatedPages });\n  },\n\n  setActivePageId: (id) => {\n    const { canvasInstance, pages, activePageId } = get();\n    if (id === activePageId) return;\n\n    // Snapshot the live canvas into the outgoing page, then switch in one update.\n    let nextPages = pages;\n    if (canvasInstance && activePageId) {\n      try {\n        const currentJSON = (canvasInstance as { toJSON: () => unknown }).toJSON();\n        nextPages = pages.map((p) =>\n          p.id === activePageId ? { ...p, json: currentJSON } : p,\n        );\n      } catch {\n        /* ignore serialisation errors */\n      }\n    }\n\n    set({ pages: nextPages, activePageId: id, activeObject: null });\n  },\n\n  updatePageDimensions: (id, width, height) => {\n    const { pages, canvasInstance, activePageId, zoom } = get();\n    const page = pages.find(p => p.id === id);\n    if (!page) return;\n\n    const updatedPages = pages.map(p => {\n      if (p.id === id) {\n        return { ...p, width, height };\n      }\n      return p;\n    });\n    set({ pages: updatedPages });\n\n    if (canvasInstance && activePageId === id) {\n      // Resize the artboard only \u2014 keep object left/top/scale in page pixels.\n      applyCanvasZoomRender(canvasInstance, width, height, zoom);\n      applyCanvasBackground(canvasInstance, page.backgroundColor, width, height);\n      canvasInstance.requestRenderAll();\n      get().saveHistoryState();\n    }\n  },\n\n  updatePageBgColor: (id, color) => {\n    const { pages, canvasInstance, activePageId } = get();\n    const updatedPages = pages.map(p => {\n      if (p.id === id) {\n        return { ...p, backgroundColor: color };\n      }\n      return p;\n    });\n    set({ pages: updatedPages });\n\n    if (canvasInstance && activePageId === id) {\n      const activePage = updatedPages.find(p => p.id === id);\n      if (activePage) {\n        applyCanvasBackground(canvasInstance, color, activePage.width, activePage.height);\n      }\n      get().saveHistoryState();\n    }\n  },\n\n  saveHistoryState: () => {\n    const { canvasInstance, activePageId, pages, isHistoryAction, historyPauseCount } = get();\n    if (!canvasInstance || isHistoryAction || historyPauseCount > 0) return;\n\n    // Serialize critical custom attributes along with standard fields\n    const currentJSON = (canvasInstance as any).toJSON();\n    const currentJSONStr = JSON.stringify(currentJSON);\n\n    // Capture low-res thumbnail cached dataURL in real-time\n    let thumbnailDataURL = '';\n    try {\n      thumbnailDataURL = canvasInstance.toDataURL({\n        format: 'jpeg',\n        quality: 0.15,\n        multiplier: 0.1,\n      });\n    } catch (e) {\n      // Ignore tainted canvas errors or other serialization edge cases\n    }\n\n    const updatedPages = pages.map(page => {\n      if (page.id === activePageId) {\n        // Slice history to discard any redone changes\n        const pageHistory = page.history.slice(0, page.historyIndex + 1);\n        \n        // Prevent duplicate consecutive states\n        if (pageHistory[pageHistory.length - 1] === currentJSONStr) {\n          return { ...page, thumbnail: thumbnailDataURL || page.thumbnail };\n        }\n\n        const newHistory = [...pageHistory, currentJSONStr];\n        // Cap history stack size to 50 states to conserve memory\n        if (newHistory.length > 50) {\n          newHistory.shift();\n        }\n\n        return {\n          ...page,\n          json: currentJSON,\n          history: newHistory,\n          historyIndex: newHistory.length - 1,\n          thumbnail: thumbnailDataURL || page.thumbnail,\n        };\n      }\n      return page;\n    });\n\n    // Also write the updated pages back into imageProjects so that\n    // switchImageProject can restore them correctly when the user switches tabs.\n    const { imageProjects: currentProjects, activeImageProjectId } = get();\n    const syncedProjects = currentProjects.map(p =>\n      p.id === activeImageProjectId\n        ? { ...p, pages: updatedPages, activePageId: get().activePageId }\n        : p\n    );\n\n    // Keep layers list in sync without ephemeral chrome (crop overlay, etc.).\n    get().syncLayers();\n    set({\n      pages: updatedPages,\n      imageProjects: syncedProjects,\n    });\n\n    // Debounced IndexedDB + background cloud (shared persistence controller).\n    markCloudAutosaveAnnounce('image');\n    imagePersistence.scheduleAfterChange();\n\n    // Automatically propagate changes if the active object is linked\n    const activeObj = get().activeObject;\n    if (activeObj && (activeObj as any).linkId) {\n      get().propagateLinkedObject(activeObj);\n    }\n  },\n\n  undo: () => {\n    const { canvasInstance, activePageId, pages } = get();\n    if (!canvasInstance) return;\n\n    const page = pages.find(p => p.id === activePageId);\n    if (!page || page.historyIndex <= 0) return;\n\n    const prevIndex = page.historyIndex - 1;\n    const prevStateStr = page.history[prevIndex];\n    const prevState = JSON.parse(prevStateStr);\n\n    set({ isHistoryAction: true });\n\n    canvasInstance.loadFromJSON(prevState).then(() => {\n      reconstructClippingMasks(canvasInstance);\n      // Reset background color/gradient from state\n      applyCanvasBackground(canvasInstance, page.backgroundColor, page.width, page.height);\n      \n      // Restore locked properties\n      canvasInstance.getObjects().forEach((obj) => {\n        const isLocked = (obj as any).locked === true;\n        if (isLocked && !isPixelLayer(obj as FabricObject)) {\n          obj.set({\n            lockMovementX: true,\n            lockMovementY: true,\n            lockScalingX: true,\n            lockScalingY: true,\n            lockRotation: true,\n            hasControls: true,\n            selectable: false,\n            borderColor: '#f59e0b',\n            cornerColor: '#f59e0b',\n            cornerStrokeColor: '#d97706',\n          });\n        }\n      });\n      reapplyAllPixelLayerLocks(canvasInstance, page.width, page.height);\n      get().ensureFileBaseLayer();\n\n      canvasInstance.renderAll();\n      \n      const updatedPages = pages.map(p => {\n        if (p.id === activePageId) {\n          return {\n            ...p,\n            json: prevState,\n            historyIndex: prevIndex,\n          };\n        }\n        return p;\n      });\n\n      set({\n        pages: updatedPages,\n        layers: canvasInstance.getObjects().slice().reverse(),\n        activeObject: null,\n        isHistoryAction: false,\n      });\n    });\n  },\n\n  redo: () => {\n    const { canvasInstance, activePageId, pages } = get();\n    if (!canvasInstance) return;\n\n    const page = pages.find(p => p.id === activePageId);\n    if (!page || page.historyIndex >= page.history.length - 1) return;\n\n    const nextIndex = page.historyIndex + 1;\n    const nextStateStr = page.history[nextIndex];\n    const nextState = JSON.parse(nextStateStr);\n\n    set({ isHistoryAction: true });\n\n    canvasInstance.loadFromJSON(nextState).then(() => {\n      reconstructClippingMasks(canvasInstance);\n      applyCanvasBackground(canvasInstance, page.backgroundColor, page.width, page.height);\n      \n      // Restore locked properties\n      canvasInstance.getObjects().forEach((obj) => {\n        const isLocked = (obj as any).locked === true;\n        if (isLocked && !isPixelLayer(obj as FabricObject)) {\n          obj.set({\n            lockMovementX: true,\n            lockMovementY: true,\n            lockScalingX: true,\n            lockScalingY: true,\n            lockRotation: true,\n            hasControls: true,\n            selectable: false,\n            borderColor: '#f59e0b',\n            cornerColor: '#f59e0b',\n            cornerStrokeColor: '#d97706',\n          });\n        }\n      });\n      reapplyAllPixelLayerLocks(canvasInstance, page.width, page.height);\n      get().ensureFileBaseLayer();\n\n      canvasInstance.renderAll();\n\n      const updatedPages = pages.map(p => {\n        if (p.id === activePageId) {\n          return {\n            ...p,\n            json: nextState,\n            historyIndex: nextIndex,\n          };\n        }\n        return p;\n      });\n\n      set({\n        pages: updatedPages,\n        layers: canvasInstance.getObjects().slice().reverse(),\n        activeObject: null,\n        isHistoryAction: false,\n      });\n    });\n  },\n\n  canUndo: () => {\n    const { pages, activePageId } = get();\n    const page = pages.find(p => p.id === activePageId);\n    return page ? page.historyIndex > 0 : false;\n  },\n\n  canRedo: () => {\n    const { pages, activePageId } = get();\n    const page = pages.find(p => p.id === activePageId);\n    return page ? page.historyIndex < page.history.length - 1 : false;\n  },\n\n  syncLayers: () => {\n    const { canvasInstance } = get();\n    if (canvasInstance) {\n      set({\n        layers: canvasInstance\n          .getObjects()\n          .filter((l: FabricObject & { name?: string; isImageCropOverlay?: boolean }) => {\n            if (l.name === 'eraser-mark' || l.name === 'clone-stamp-layer') return false;\n            if (l.isImageCropOverlay) return false;\n            return true;\n          })\n          .slice()\n          .reverse(),\n      });\n    }\n  },\n\n  addBlankRasterLayer: () => {\n    const { canvasInstance, pages, activePageId, syncLayers, saveHistoryState, setActiveObject } =\n      get();\n    if (!canvasInstance) return null;\n    const page = pages.find((p) => p.id === activePageId) || pages[0];\n    if (!page) return null;\n\n    const msgs = getActiveMessages();\n    const name = nextPixelLayerName(canvasInstance.getObjects(), msgs.layers.pixelLayerBase);\n    const layer = createBlankPixelLayer(page.width, page.height, name, {\n      centerX: page.width / 2,\n      centerY: page.height / 2,\n    });\n    syncPixelLayerInteraction(layer);\n    canvasInstance.add(layer);\n    canvasInstance.setActiveObject(layer);\n    setActiveObject(layer);\n    canvasInstance.requestRenderAll();\n    syncLayers();\n    saveHistoryState();\n    return layer;\n  },\n\n  ensureFileBaseLayer: () => {\n    const { canvasInstance, pages, activePageId, syncLayers } = get();\n    if (!canvasInstance) return null;\n    const page = pages.find((p) => p.id === activePageId) || pages[0];\n    if (!page) return null;\n\n    // Prefer an existing pixel layer \u2014 never invent an empty \"file\" layer when\n    // other content already exists (avoids duplicate empty + content capas).\n    const existing = getBottomPixelLayer(canvasInstance);\n    if (existing) {\n      syncPixelLayerInteraction(existing);\n      return existing;\n    }\n    if (canvasInstance.getObjects().length > 0) return null;\n\n    const msgs = getActiveMessages();\n    const layer = createBlankPixelLayer(page.width, page.height, msgs.layers.pixelLayerBase, {\n      centerX: page.width / 2,\n      centerY: page.height / 2,\n    });\n    canvasInstance.insertAt(0, layer);\n    syncPixelLayerInteraction(layer);\n    canvasInstance.requestRenderAll();\n    syncLayers();\n    return layer;\n  },\n\n  clearPixelLayer: (layerObj) => {\n    const { canvasInstance, pages, activePageId, syncLayers, saveHistoryState } = get();\n    if (!canvasInstance || !isPixelLayer(layerObj)) return;\n    const page = pages.find((p) => p.id === activePageId) || pages[0];\n    clearPixelLayerContent(layerObj, page?.width, page?.height);\n    canvasInstance.requestRenderAll();\n    syncLayers();\n    saveHistoryState();\n  },\n\n  deleteLayerOrClear: (layerObj) => {\n    const { canvasInstance, pages, activePageId, syncLayers, saveHistoryState, setActiveObject } =\n      get();\n    if (!canvasInstance || !layerObj) return 'blocked';\n    const page = pages.find((p) => p.id === activePageId) || pages[0];\n    if (!page) return 'blocked';\n    const msgs = getActiveMessages();\n    const result = deleteLayerOrClearContent(\n      canvasInstance,\n      layerObj,\n      page.width,\n      page.height,\n      msgs.layers.pixelLayerBase,\n    );\n    if (result === 'blocked') return result;\n    const active = canvasInstance.getActiveObject() || null;\n    setActiveObject(active);\n    canvasInstance.requestRenderAll();\n    syncLayers();\n    saveHistoryState();\n    return result;\n  },\n\n  addPixelLayerMask: (layerObj) => {\n    const { canvasInstance, syncLayers, saveHistoryState, setActiveObject, setLayerPaintTarget } =\n      get();\n    if (!canvasInstance || !layerObj) return;\n    if ((layerObj.type || '').toLowerCase() === 'activeselection') return;\n\n    let target: PixelLayerImage | null = isPixelLayer(layerObj)\n      ? (layerObj as PixelLayerImage)\n      : null;\n\n    if (!target) {\n      const name =\n        (layerObj as { name?: string }).name ||\n        getActiveMessages().layers.pixelLayerBase;\n      target = rasterizeObjectToPixelLayer(canvasInstance, layerObj, name);\n      if (!target) return;\n    }\n\n    addLayerMask(target);\n    setActiveObject(target);\n    setLayerPaintTarget('mask');\n    canvasInstance.setActiveObject(target);\n    canvasInstance.requestRenderAll();\n    syncLayers();\n    saveHistoryState();\n  },\n\n  removePixelLayerMask: (layerObj) => {\n    const { canvasInstance, syncLayers, saveHistoryState, setLayerPaintTarget } = get();\n    if (!canvasInstance || !isPixelLayer(layerObj)) return;\n    removeLayerMask(layerObj as PixelLayerImage);\n    setLayerPaintTarget('content');\n    canvasInstance.requestRenderAll();\n    syncLayers();\n    saveHistoryState();\n  },\n\n  rasterizeLayer: (layerObj) => {\n    const { canvasInstance, syncLayers, saveHistoryState, setActiveObject, setLayerPaintTarget, addToast } =\n      get();\n    if (!canvasInstance || !layerObj) return;\n    if ((layerObj.type || '').toLowerCase() === 'activeselection') return;\n    if (isPixelLayer(layerObj)) {\n      addToast(getActiveMessages().layers.alreadyRaster, 'info');\n      return;\n    }\n\n    const name =\n      (layerObj as { name?: string }).name ||\n      getActiveMessages().layers.pixelLayerBase;\n    const layer = rasterizeObjectToPixelLayer(canvasInstance, layerObj, name);\n    if (!layer) {\n      addToast(getActiveMessages().layers.rasterizeFailed, 'error');\n      return;\n    }\n\n    setLayerPaintTarget('content');\n    canvasInstance.setActiveObject(layer);\n    setActiveObject(layer);\n    canvasInstance.requestRenderAll();\n    syncLayers();\n    saveHistoryState();\n  },\n\n  reorderLayer: (dragId, dropId) => {\n    const { canvasInstance, syncLayers, saveHistoryState } = get();\n    if (!canvasInstance || !dragId || !dropId || dragId === dropId) return;\n    const objects = canvasInstance.getObjects();\n    // UI list is top\u2192bottom = reverse of Fabric stack (bottom\u2192top).\n    const list = [...objects].reverse();\n    const dragObj = list.find((o) => (o as FabricObject & { id?: string }).id === dragId);\n    const dropObj = list.find((o) => (o as FabricObject & { id?: string }).id === dropId);\n    if (!dragObj || !dropObj) return;\n    const from = list.indexOf(dragObj);\n    let to = list.indexOf(dropObj);\n    if (from < 0 || to < 0) return;\n    list.splice(from, 1);\n    if (from < to) to -= 1;\n    list.splice(to, 0, dragObj);\n    const bottomFirst = [...list].reverse();\n    bottomFirst.forEach((obj, i) => {\n      canvasInstance.moveObjectTo(obj, i);\n    });\n    canvasInstance.requestRenderAll();\n    syncLayers();\n    saveHistoryState();\n  },\n\n  duplicateActiveLayer: async () => {\n    const { canvasInstance, activeObject, lastSelectedObjectId, syncLayers, saveHistoryState, setActiveObject } =\n      get();\n    if (!canvasInstance) return null;\n\n    const source =\n      (activeObject &&\n      (activeObject.type || '').toLowerCase() !== 'activeselection'\n        ? activeObject\n        : null) ||\n      (lastSelectedObjectId\n        ? (canvasInstance.getObjects().find(\n            (o) => (o as FabricObject & { id?: string }).id === lastSelectedObjectId,\n          ) as FabricObject | undefined) ?? null\n        : null);\n    if (!source || (source.type || '').toLowerCase() === 'activeselection') return null;\n\n    const cloned = await source.clone();\n    if (!cloned) return null;\n\n    if (isFabricImage(source) && isFabricImage(cloned)) {\n      const el = cloneFabricImageElement(source);\n      cloned.setElement(el);\n      if (isPixelLayer(source)) {\n        (cloned as PixelLayerImage).wePixelLayer = true;\n      }\n    }\n\n    (cloned as PixelLayerImage).weBaseLayer = false;\n\n    const msgs = getActiveMessages();\n    const sourceName =\n      (source as { name?: string }).name ||\n      (isPixelLayer(source) ? msgs.layers.pixelLayerBase : 'Copia');\n    (cloned as { name?: string }).name = msgs.layers.duplicatedOf(sourceName);\n    (cloned as { id?: string }).id = `obj-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n\n    if (isPixelLayer(cloned as FabricObject)) {\n      syncPixelLayerInteraction(cloned as PixelLayerImage);\n    }\n    cloned.set({\n      left: (source.left || 0) + 16,\n      top: (source.top || 0) + 16,\n    });\n    cloned.setCoords();\n\n    canvasInstance.add(cloned);\n    canvasInstance.setActiveObject(cloned);\n    setActiveObject(cloned);\n    canvasInstance.requestRenderAll();\n    syncLayers();\n    saveHistoryState();\n    return cloned;\n  },\n\n  resolvePaintTargetLayer: () => {\n    const { canvasInstance, activeObject, paintTargetLayerId } = get();\n    if (!canvasInstance) return null;\n\n    // Active pixel layer (or promote a plain Fabric image \u2014 covers reloads that\n    // lost wePixelLayer before it was added to customProperties).\n    if (isPixelLayer(activeObject as FabricObject | null)) {\n      const layer = asPixelLayer(activeObject as PixelLayerImage);\n      set({ paintTargetLayerId: layer.id || null });\n      return layer;\n    }\n    if (isFabricImage(activeObject as FabricObject | null)) {\n      const img = activeObject as FabricImage;\n      if (!shouldSkipPixelLayerPromotion(img)) {\n        const layer = asPixelLayer(img);\n        set({ paintTargetLayerId: layer.id || null });\n        return layer;\n      }\n    }\n\n    if (paintTargetLayerId) {\n      const found = canvasInstance\n        .getObjects()\n        .find(\n          (o) =>\n            (isPixelLayer(o as FabricObject) || isFabricImage(o as FabricObject)) &&\n            (o as PixelLayerImage).id === paintTargetLayerId,\n        ) as FabricImage | undefined;\n      if (found && !shouldSkipPixelLayerPromotion(found)) {\n        return asPixelLayer(found);\n      }\n    }\n\n    return null;\n  },\n\n  ensurePixelLayerForBrush: () => get().resolvePaintTargetLayer(),\n\n  commitBrushPathToPixelLayer: (path) => {\n    const {\n      canvasInstance,\n      brushSettings,\n      syncLayers,\n      saveHistoryState,\n      setActiveObject,\n      addToast,\n      layerPaintTarget,\n      activeTool,\n    } = get();\n    if (!canvasInstance || !path) return;\n\n    // AI magic eraser tool: keep red strokes as marks (white=erase on apply).\n    // Layer-mask paint still uses bake below when layerPaintTarget === 'mask'.\n    if (activeTool === 'magic-eraser' && layerPaintTarget !== 'mask') {\n      const {\n        magicEraserTargetId,\n        lastSelectedObjectId,\n        activeObject: ao,\n      } = get();\n      const target =\n        get().resolvePaintTargetLayer() ||\n        findObjectById(canvasInstance, magicEraserTargetId) ||\n        findObjectById(canvasInstance, lastSelectedObjectId) ||\n        (ao && (ao.type || '').toLowerCase() === 'image' ? ao : null);\n      if (!target) {\n        canvasInstance.remove(path);\n        canvasInstance.requestRenderAll();\n        addToast(getActiveMessages().layers.mustSelectLayer, 'warning');\n        return;\n      }\n      const id =\n        (target as { id?: string }).id || `img-${Date.now()}`;\n      if (!(target as { id?: string }).id) {\n        target.set({ id } as never);\n      }\n      get().setMagicEraserTargetId(id);\n      path.set({\n        name: 'eraser-mark',\n        selectable: false,\n        evented: false,\n        excludeFromExport: true,\n      });\n      canvasInstance.requestRenderAll();\n      syncLayers();\n      return;\n    }\n\n    const layer = get().resolvePaintTargetLayer();\n    if (!layer) {\n      canvasInstance.remove(path);\n      canvasInstance.requestRenderAll();\n      addToast(getActiveMessages().layers.mustSelectLayer, 'warning');\n      return;\n    }\n\n    const erase = activeTool === 'magic-eraser';\n    const multiply = brushSettings.type === 'highlighter';\n    const target =\n      layerPaintTarget === 'mask' && hasLayerMask(layer) ? 'mask' : 'content';\n\n    // Force grayscale brush stamp when painting the mask (stroke only \u2014 never fill,\n    // or Fabric closes the freehand path into a filled shape).\n    if (target === 'mask' && canvasInstance.freeDrawingBrush && !erase) {\n      const gray = cssColorToMaskGray(\n        canvasInstance.freeDrawingBrush.color || get().masterColors.fill || '#ffffff',\n      );\n      canvasInstance.freeDrawingBrush.color = gray;\n      path.set({ stroke: gray, fill: '' });\n    }\n\n    bakePathIntoPixelLayer(canvasInstance, path, layer, { erase, multiply, target });\n    syncPixelLayerInteraction(layer);\n    set({ paintTargetLayerId: layer.id || null });\n    setActiveObject(layer);\n    syncLayers();\n    saveHistoryState();\n  },\n\n  stampImageOntoActivePixelLayer: async (dataUrl, opts) => {\n    const { canvasInstance, pages, activePageId, syncLayers, saveHistoryState, setActiveObject } =\n      get();\n    if (!canvasInstance || !dataUrl) return null;\n    const page = pages.find((p) => p.id === activePageId) || pages[0];\n    if (!page) return null;\n\n    const img = await FabricImage.fromURL(dataUrl, { crossOrigin: 'anonymous' }).catch(async () => {\n      return FabricImage.fromURL(dataUrl);\n    });\n    const sourceEl = img.getElement() as HTMLImageElement | HTMLCanvasElement;\n    const iw = Math.max(\n      1,\n      Math.round(\n        (sourceEl as HTMLImageElement).naturalWidth ||\n          (sourceEl as HTMLCanvasElement).width ||\n          img.width ||\n          1,\n      ),\n    );\n    const ih = Math.max(\n      1,\n      Math.round(\n        (sourceEl as HTMLImageElement).naturalHeight ||\n          (sourceEl as HTMLCanvasElement).height ||\n          img.height ||\n          1,\n      ),\n    );\n\n    // Always open uploads / My Files / stock / drops as a NEW pixel layer.\n    // Never composite into the selected layer \u2014 that left images \"stuck\" on the\n    // active layer and made the layers panel look like nothing was added.\n    const fileName = opts?.name ? layerNameFromFileName(opts.name) : '';\n    const msgs = getActiveMessages();\n    const name =\n      fileName || nextPixelLayerName(canvasInstance.getObjects(), msgs.layers.pixelLayerBase);\n    // Layer buffer = image pixel size (not page size). Paint tools expand later.\n    const layer = createBlankPixelLayer(iw, ih, name, {\n      centerX: opts?.centerX ?? page.width / 2,\n      centerY: opts?.centerY ?? page.height / 2,\n    });\n    stampSourceIntoPixelLayer(layer, sourceEl, { x: 0, y: 0, w: iw, h: ih });\n    fitPixelLayerToContent(layer);\n    syncPixelLayerInteraction(layer);\n    canvasInstance.add(layer);\n    canvasInstance.setActiveObject(layer);\n    setActiveObject(layer);\n    canvasInstance.requestRenderAll();\n    syncLayers();\n    saveHistoryState();\n    return layer;\n  },\n\n  applyInstantMask: (image: any, shapeType: 'circle' | 'heart' | 'star' | 'triangle' | 'rounded-rect' | 'none') => {\n    const { canvasInstance, syncLayers, saveHistoryState } = get();\n    if (!canvasInstance || !image) return;\n\n    if (shapeType === 'none') {\n      const clippedToId = image.clippedToLayerId;\n      if (clippedToId) {\n        const maskObj = canvasInstance.getObjects().find((o: any) => o.id === clippedToId);\n        if (maskObj) {\n          canvasInstance.remove(maskObj);\n        }\n      }\n      image.set({\n        clipPath: null,\n      });\n      image.clippedToLayerId = undefined;\n      if (image._originalRender) {\n        image.render = image._originalRender;\n        image._originalRender = undefined;\n      }\n      canvasInstance.requestRenderAll();\n      syncLayers();\n      saveHistoryState();\n      return;\n    }\n\n    // Otherwise, first remove any existing mask of this image to prevent stacking multiple masks on one image\n    const existingClippedToId = image.clippedToLayerId;\n    if (existingClippedToId) {\n      const maskObj = canvasInstance.getObjects().find((o: any) => o.id === existingClippedToId);\n      if (maskObj) {\n        canvasInstance.remove(maskObj);\n      }\n    }\n\n    const width = image.width * image.scaleX;\n    const height = image.height * image.scaleY;\n    const center = image.getCenterPoint();\n\n    let shape: any = null;\n\n    if (shapeType === 'circle') {\n      const radius = Math.min(width, height) / 2;\n      shape = new Circle({\n        left: center.x - radius,\n        top: center.y - radius,\n        radius: radius,\n        fill: '#ffffff',\n      });\n    } else if (shapeType === 'rounded-rect') {\n      shape = new Rect({\n        left: center.x - width / 2,\n        top: center.y - height / 2,\n        width: width,\n        height: height,\n        rx: Math.min(width, height) * 0.15,\n        ry: Math.min(width, height) * 0.15,\n        fill: '#ffffff',\n      });\n    } else if (shapeType === 'triangle') {\n      shape = new Triangle({\n        left: center.x - width / 2,\n        top: center.y - height / 2,\n        width: width,\n        height: height,\n        fill: '#ffffff',\n      });\n    } else if (shapeType === 'star') {\n      const points = [];\n      const spikes = 5;\n      const outerRadius = Math.min(width, height) / 2;\n      const innerRadius = outerRadius * 0.4;\n      let rot = (Math.PI / 2) * 3;\n      const step = Math.PI / spikes;\n      const cx = center.x;\n      const cy = center.y;\n\n      for (let i = 0; i < spikes; i++) {\n        points.push({\n          x: cx + Math.cos(rot) * outerRadius,\n          y: cy + Math.sin(rot) * outerRadius,\n        });\n        rot += step;\n        points.push({\n          x: cx + Math.cos(rot) * innerRadius,\n          y: cy + Math.sin(rot) * innerRadius,\n        });\n        rot += step;\n      }\n      shape = new Polygon(points, {\n        fill: '#ffffff',\n      });\n    } else if (shapeType === 'heart') {\n      const d = \"M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z\";\n      shape = new Path(d, {\n        fill: '#ffffff',\n        scaleX: width / 24,\n        scaleY: height / 24,\n      });\n      const pathCenter = shape.getCenterPoint();\n      shape.set({\n        left: center.x - pathCenter.x * (width / 24),\n        top: center.y - pathCenter.y * (height / 24),\n      });\n    }\n\n    if (shape) {\n      if (!(shape as any).id) {\n        shape.id = `mask-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n      }\n      shape.name = `M\u00E1scara ${shapeType === 'circle' ? 'Circular' : shapeType === 'rounded-rect' ? 'Redondeada' : shapeType === 'heart' ? 'Coraz\u00F3n' : shapeType === 'star' ? 'Estrella' : 'Tri\u00E1ngulo'}`;\n      \n      shape.set({\n        opacity: 1,\n        selectable: true,\n        evented: true,\n        absolutePositioned: true,\n      });\n\n      (image as any).clippedToLayerId = shape.id;\n      image.set({\n        clipPath: shape,\n      });\n\n      applyMaskOverrides(shape, canvasInstance);\n      applyClippedOverrides(image);\n\n      const imgIdx = canvasInstance.getObjects().indexOf(image);\n      canvasInstance.add(shape);\n      if (imgIdx !== -1) {\n        canvasInstance.moveObjectTo(shape, imgIdx);\n      }\n\n      canvasInstance.requestRenderAll();\n      syncLayers();\n      saveHistoryState();\n    }\n  },\n\n  applyCustomMask: (image: any, shapeObj: any) => {\n    const { canvasInstance, syncLayers, saveHistoryState } = get();\n    if (!canvasInstance || !image || !shapeObj) return;\n\n    canvasInstance.discardActiveObject();\n\n    if (!(shapeObj as any).id) {\n      (shapeObj as any).id = `shape-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n    }\n    if (!(image as any).id) {\n      (image as any).id = `img-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n    }\n\n    (shapeObj as any).isClipPathMask = true;\n    (image as any).clippedToLayerId = (shapeObj as any).id;\n\n    shapeObj.set({\n      selectable: true,\n      evented: true,\n      absolutePositioned: true,\n    });\n\n    image.set({\n      clipPath: shapeObj,\n    });\n\n    applyMaskOverrides(shapeObj, canvasInstance);\n    applyClippedOverrides(image);\n\n    const imgIdx = canvasInstance.getObjects().indexOf(image);\n    const shapeIdx = canvasInstance.getObjects().indexOf(shapeObj);\n    if (imgIdx < shapeIdx) {\n      canvasInstance.moveObjectTo(image, shapeIdx);\n    }\n\n    canvasInstance.setActiveObject(image);\n    canvasInstance.requestRenderAll();\n    syncLayers();\n    saveHistoryState();\n  },\n\n  releaseClippingMask: () => {\n    const { canvasInstance, activeObject, syncLayers, saveHistoryState } = get();\n    if (!canvasInstance || !activeObject) return;\n\n    if (activeObject.type?.toLowerCase() === 'group' && (activeObject as any).name === 'canva-frame-clipped') {\n      const frameGroup = activeObject as any;\n      const imgObj = frameGroup.getObjects().find((o: any) => o.type?.toLowerCase() === 'image');\n      const placeholder = frameGroup.clippedPlaceholder;\n\n      if (!imgObj || !placeholder) return;\n\n      canvasInstance.discardActiveObject();\n      canvasInstance.remove(frameGroup);\n\n      const bezelObjects = frameGroup.getObjects().filter((o: any) => o !== imgObj);\n\n      imgObj.set({\n        clipPath: null,\n      });\n      imgObj.clippedToLayerId = undefined;\n      if (imgObj._originalRender) {\n        imgObj.render = imgObj._originalRender;\n        imgObj._originalRender = undefined;\n      }\n\n      const groupLeft = frameGroup.left;\n      const groupTop = frameGroup.top;\n      const groupScaleX = frameGroup.scaleX;\n      const groupScaleY = frameGroup.scaleY;\n      const groupAngle = frameGroup.angle;\n\n      placeholder.set({\n        left: (placeholder.left - groupLeft) / groupScaleX,\n        top: (placeholder.top - groupTop) / groupScaleY,\n        scaleX: placeholder.scaleX / groupScaleX,\n        scaleY: placeholder.scaleY / groupScaleY,\n        angle: placeholder.angle - groupAngle,\n        opacity: 0.1,\n        selectable: true,\n        evented: true,\n      });\n\n      bezelObjects.forEach((o: any) => {\n        o.set({\n          left: (o.left - groupLeft) / groupScaleX,\n          top: (o.top - groupTop) / groupScaleY,\n          scaleX: o.scaleX / groupScaleX,\n          scaleY: o.scaleY / groupScaleY,\n          angle: o.angle - groupAngle,\n          selectable: true,\n          evented: true,\n        });\n      });\n\n      const originalFrameGroup = new Group([placeholder, ...bezelObjects], {\n        name: 'canva-frame',\n      } as any);\n\n      canvasInstance.add(originalFrameGroup);\n      canvasInstance.add(imgObj);\n\n      const selObj = new Group([imgObj, originalFrameGroup], { canvas: canvasInstance });\n      canvasInstance.setActiveObject(selObj);\n      canvasInstance.requestRenderAll();\n\n      syncLayers();\n      saveHistoryState();\n      return;\n    }\n\n    const selectedObj = activeObject as any;\n    let parent: any = null;\n    let child: any = null;\n    \n    if (selectedObj.clippedToLayerId) {\n      child = selectedObj;\n      parent = canvasInstance.getObjects().find((o: any) => (o as any).id === selectedObj.clippedToLayerId);\n    } else if (selectedObj.isClipPathMask) {\n      parent = selectedObj;\n      child = canvasInstance.getObjects().find((o: any) => (o as any).clippedToLayerId === selectedObj.id);\n    }\n\n    if (!child) return;\n\n    child.set({\n      clipPath: null,\n    });\n    child.clippedToLayerId = undefined;\n    if (child._originalRender) {\n      child.render = child._originalRender;\n      child._originalRender = undefined;\n    }\n\n    if (parent) {\n      parent.isClipPathMask = false;\n      if (parent._originalRender) {\n        parent.render = parent._originalRender;\n        parent._originalRender = undefined;\n      }\n      parent.set({\n        selectable: true,\n        evented: true,\n      });\n    }\n\n    canvasInstance.requestRenderAll();\n    syncLayers();\n    saveHistoryState();\n  },\n\n  createClippingMask: () => {\n    const { canvasInstance, activeObject, syncLayers, saveHistoryState } = get();\n    if (!canvasInstance || !activeObject || activeObject.type?.toLowerCase() !== 'activeselection') return;\n    const sel = activeObject as any;\n    const objects = sel.getObjects();\n    \n    const imgObj = objects.find((o: any) => o.type?.toLowerCase() === 'image');\n    const shapeObj = objects.find((o: any) => ['rect', 'circle', 'triangle', 'ellipse', 'polygon', 'path'].includes(o.type?.toLowerCase()));\n    const frameGroup = objects.find((o: any) => o.type?.toLowerCase() === 'group' && o.name === 'canva-frame');\n    \n    if (!imgObj) return;\n\n    if (frameGroup) {\n      const placeholder = frameGroup.getObjects().find((o: any) => o.name === 'frame-placeholder');\n      if (!placeholder) return;\n\n      canvasInstance.discardActiveObject();\n      canvasInstance.remove(frameGroup);\n\n      const bezelObjects = frameGroup.getObjects().filter((o: any) => o !== placeholder);\n      const groupLeft = frameGroup.left;\n      const groupTop = frameGroup.top;\n      const groupScaleX = frameGroup.scaleX;\n      const groupScaleY = frameGroup.scaleY;\n      const groupAngle = frameGroup.angle;\n\n      placeholder.set({\n        left: groupLeft + (placeholder.left * groupScaleX),\n        top: groupTop + (placeholder.top * groupScaleY),\n        scaleX: placeholder.scaleX * groupScaleX,\n        scaleY: placeholder.scaleY * groupScaleY,\n        angle: placeholder.angle + groupAngle,\n        opacity: 1,\n        selectable: false,\n        evented: false,\n      });\n      placeholder.absolutePositioned = true;\n\n      imgObj.set({\n        clipPath: placeholder,\n      });\n\n      bezelObjects.forEach((o: any) => {\n        o.set({\n          left: groupLeft + (o.left * groupScaleX),\n          top: groupTop + (o.top * groupScaleY),\n          scaleX: o.scaleX * groupScaleX,\n          scaleY: o.scaleY * groupScaleY,\n          angle: o.angle + groupAngle,\n          selectable: false,\n          evented: false,\n        });\n      });\n\n      const newFrameGroup = new Group([...bezelObjects, imgObj], {\n        name: 'canva-frame-clipped',\n        clippedPlaceholder: placeholder,\n      } as any);\n\n      canvasInstance.remove(imgObj);\n      canvasInstance.add(newFrameGroup);\n      canvasInstance.setActiveObject(newFrameGroup);\n      canvasInstance.requestRenderAll();\n\n      syncLayers();\n      saveHistoryState();\n      return;\n    }\n    \n    if (!shapeObj) return;\n\n    canvasInstance.discardActiveObject();\n    \n    if (!(shapeObj as any).id) {\n      (shapeObj as any).id = `shape-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n    }\n    if (!(imgObj as any).id) {\n      (imgObj as any).id = `img-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n    }\n\n    (shapeObj as any).isClipPathMask = true;\n    (imgObj as any).clippedToLayerId = (shapeObj as any).id;\n    \n    shapeObj.set({\n      selectable: true,\n      evented: true,\n      absolutePositioned: true,\n    });\n    \n    imgObj.set({\n      clipPath: shapeObj,\n    });\n    \n    applyMaskOverrides(shapeObj, canvasInstance);\n    applyClippedOverrides(imgObj);\n    \n    const imgIdx = canvasInstance.getObjects().indexOf(imgObj);\n    const shapeIdx = canvasInstance.getObjects().indexOf(shapeObj);\n    if (imgIdx < shapeIdx) {\n      canvasInstance.moveObjectTo(imgObj, shapeIdx);\n    }\n    \n    canvasInstance.setActiveObject(imgObj);\n    canvasInstance.requestRenderAll();\n    \n    syncLayers();\n    saveHistoryState();\n  },\n\n  isMaskCreationPossible: () => {\n    const { activeObject } = get();\n    if (!activeObject || activeObject.type?.toLowerCase() !== 'activeselection') return false;\n    const sel = activeObject as any;\n    const objects = sel.getObjects();\n    if (objects.length !== 2) return false;\n    \n    const hasImage = objects.some((o: any) => o.type?.toLowerCase() === 'image');\n    const hasShape = objects.some((o: any) => \n      ['rect', 'circle', 'triangle', 'ellipse', 'polygon', 'path'].includes(o.type?.toLowerCase()) ||\n      (o.type?.toLowerCase() === 'group' && o.name === 'canva-frame')\n    );\n    return hasImage && hasShape;\n  },\n\n  groupSelectedObjects: () => {\n    const { canvasInstance, activeObject, syncLayers, saveHistoryState } = get();\n    if (!canvasInstance || !activeObject || activeObject.type?.toLowerCase() !== 'activeselection') return;\n\n    const sel = activeObject as any;\n    const objects = sel.getObjects() as FabricObject[];\n    if (objects.length < 2) return;\n\n    canvasInstance.discardActiveObject();\n\n    // Remove the objects from canvas\n    objects.forEach((obj) => {\n      canvasInstance.remove(obj);\n    });\n\n    const newGroup = new Group(objects, {\n      id: `group-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n      subTargetCheck: true,\n      name: `Grupo ${Date.now().toString().slice(-4)}`,\n    } as any);\n\n    newGroup.setCoords();\n    canvasInstance.add(newGroup);\n    canvasInstance.setActiveObject(newGroup);\n    canvasInstance.requestRenderAll();\n\n    set({ activeObject: newGroup });\n    syncLayers();\n    saveHistoryState();\n  },\n\n  ungroupObjects: () => {\n    const { canvasInstance, activeObject, syncLayers, saveHistoryState } = get();\n    if (!canvasInstance || !activeObject || activeObject.type?.toLowerCase() !== 'group') return;\n\n    const group = activeObject as any;\n    \n    // Skip ungrouping frames\n    if (['canva-frame', 'canva-frame-clipped'].includes(group.name)) return;\n\n    const objects = group.getObjects() as FabricObject[];\n    canvasInstance.discardActiveObject();\n    canvasInstance.remove(group);\n\n    const matrix = group.calcTransformMatrix();\n\n    objects.forEach((obj) => {\n      // Transform coordinates back to absolute\n      const localPoint = new Point(obj.left, obj.top);\n      const absolutePoint = localPoint.transform(matrix);\n\n      obj.set({\n        left: absolutePoint.x,\n        top: absolutePoint.y,\n        scaleX: obj.scaleX * group.scaleX,\n        scaleY: obj.scaleY * group.scaleY,\n        angle: obj.angle + group.angle,\n      });\n\n      if (group.flipX) obj.set({ flipX: !obj.flipX });\n      if (group.flipY) obj.set({ flipY: !obj.flipY });\n\n      // Clean group reference\n      (obj as any).group = undefined;\n\n      canvasInstance.add(obj);\n    });\n\n    canvasInstance.requestRenderAll();\n    syncLayers();\n    saveHistoryState();\n  },\n\n  runRemoveBg: async () => {\n    const { canvasInstance, activeObject, syncLayers, saveHistoryState, setAiGenerating, setAiError } = get();\n    if (!canvasInstance || !activeObject || activeObject.type?.toLowerCase() !== 'image') {\n      setAiError('Selecciona una imagen primero para quitar el fondo.');\n      return;\n    }\n\n    const target = activeObject;\n    try {\n      setAiGenerating(true);\n      setAiError(null);\n      beginAiLoading(target);\n      canvasInstance.requestRenderAll();\n      syncLayers();\n\n      const dataUrl = target.toDataURL({ format: 'png' });\n      const newSrc = await aiEngine.removeBackground(dataUrl);\n      await replaceFabricImagePreservingTransform(canvasInstance, target, newSrc);\n\n      syncLayers();\n      saveHistoryState();\n      get().addToast(getActiveMessages().store.toasts.editor.bgRemoved, 'success');\n    } catch (err: any) {\n      console.error(err);\n      if (canvasInstance.getObjects().includes(target)) {\n        endAiLoading(target);\n        canvasInstance.requestRenderAll();\n      }\n      setAiError(err.message || getActiveMessages().store.toasts.editor.aiRemoveBackgroundError);\n      get().addToast(err.message || getActiveMessages().store.toasts.editor.aiRemoveBackgroundError, 'error');\n    } finally {\n      setAiGenerating(false);\n    }\n  },\n\n  runModifyImageByPrompt: async (prompt: string) => {\n    const { canvasInstance, activeObject, syncLayers, saveHistoryState, setAiGenerating, setAiError } = get();\n    if (!canvasInstance || !activeObject || activeObject.type?.toLowerCase() !== 'image') {\n      setAiError('Selecciona una imagen primero para modificarla con AI.');\n      return;\n    }\n\n    const target = activeObject;\n    try {\n      setAiGenerating(true);\n      setAiError(null);\n      beginAiLoading(target);\n      canvasInstance.requestRenderAll();\n      syncLayers();\n\n      const dataUrl = target.toDataURL({ format: 'png' });\n      const newSrc = await aiEngine.modifyImageByPrompt(dataUrl, prompt);\n      await replaceFabricImagePreservingTransform(canvasInstance, target, newSrc);\n\n      syncLayers();\n      saveHistoryState();\n      get().addToast(getActiveMessages().store.toasts.editor.imageModified, 'success');\n    } catch (err: any) {\n      console.error(err);\n      if (canvasInstance.getObjects().includes(target)) {\n        endAiLoading(target);\n        canvasInstance.requestRenderAll();\n      }\n      setAiError(err.message || getActiveMessages().store.toasts.editor.aiModifyImageError);\n      get().addToast(err.message || getActiveMessages().store.toasts.editor.aiModifyImageError, 'error');\n    } finally {\n      setAiGenerating(false);\n    }\n  },\n\n  runTextToImage: async ({ prompt, aspectRatio, resolution, references }) => {\n    const {\n      canvasInstance,\n      syncLayers,\n      saveHistoryState,\n      setAiGenerating,\n      setAiStudioError,\n    } = get();\n    if (!canvasInstance) return false;\n\n    let placeholder: AiLoadingObject | null = null;\n    try {\n      setAiGenerating(true);\n      setAiStudioError(null);\n\n      const activePage = get().pages.find(p => p.id === get().activePageId);\n      const width = activePage?.width || 800;\n      const height = activePage?.height || 600;\n      const resolvedAspect =\n        aspectRatio ?? aspectRatioFromPageSize(width, height);\n\n      placeholder = createAiPlaceholderLayer(canvasInstance, {\n        aspectRatio: resolvedAspect,\n        resolution,\n        pageWidth: width,\n        pageHeight: height,\n        name: getActiveMessages().editor.aiGenerating,\n      });\n      syncLayers();\n\n      const styledSrc = await aiEngine.generateImageFromPrompt(prompt, {\n        aspectRatio: resolvedAspect,\n        resolution,\n        references,\n        includeLogo: false,\n      });\n\n      await replaceAiPlaceholderWithImage(canvasInstance, placeholder, styledSrc, {\n        pageWidth: width,\n        pageHeight: height,\n      });\n      placeholder = null;\n\n      syncLayers();\n      saveHistoryState();\n      return true;\n    } catch (err: unknown) {\n      console.error(err);\n      if (placeholder && canvasInstance.getObjects().includes(placeholder)) {\n        removeAiPlaceholder(canvasInstance, placeholder);\n      }\n      const fallback = getActiveMessages().store.toasts.editor.aiGenerateImageError;\n      const message = err instanceof Error && err.message ? err.message : fallback;\n      setAiStudioError(message);\n      get().addToast(message, 'error');\n      return false;\n    } finally {\n      setAiGenerating(false);\n      syncLayers();\n    }\n  },\n\n  runGenerativeFill: async (prompt: string, blendWithSubject: boolean = false) => {\n    const { canvasInstance, activeObject, syncLayers, saveHistoryState, setAiGenerating, setAiError } = get();\n    if (!canvasInstance) return;\n\n    try {\n      setAiGenerating(true);\n      setAiError(null);\n\n      // Remove any existing background image\n      const bgImg = canvasInstance.getObjects().find(o => (o as any).name === 'Fondo: Imagen');\n      if (bgImg) {\n        canvasInstance.remove(bgImg);\n      }\n\n      const styledSrc = await aiEngine.generateImageFromPrompt(prompt);\n\n      const img = await new Promise<FabricImage>((resolve, reject) => {\n        FabricImage.fromURL(styledSrc, { crossOrigin: 'anonymous' })\n          .then((img) => resolve(img))\n          .catch((err) => reject(err));\n      });\n\n      const activePage = get().pages.find(p => p.id === get().activePageId);\n      const width = activePage?.width || 800;\n      const height = activePage?.height || 600;\n\n      const imgWidth = img.width || 1024;\n      const imgHeight = img.height || 768;\n      const s = Math.max(width / imgWidth, height / imgHeight);\n\n      img.set({\n        name: 'Fondo: Imagen',\n        left: (width - imgWidth * s) / 2,\n        top: (height - imgHeight * s) / 2,\n        scaleX: s,\n        scaleY: s,\n        selectable: true,\n        evented: true,\n      });\n\n      // Insert background at the bottom\n      canvasInstance.insertAt(0, img);\n\n      // If blend is checked and an active image is selected, isolate the subject and place it on top\n      if (blendWithSubject && activeObject && activeObject.type === 'image') {\n        const activeImg = activeObject as FabricImage;\n        const rawUrl = (activeImg as any).getElement().src || activeImg.toDataURL();\n        \n        // Remove background locally/via API\n        const isolatedSrc = await aiEngine.removeBackground(rawUrl);\n\n        // Update active image element\n        await new Promise<void>((resolve, reject) => {\n          const imgEl = new Image();\n          imgEl.crossOrigin = 'anonymous';\n          imgEl.src = isolatedSrc;\n          imgEl.onload = () => {\n            activeImg.setElement(imgEl);\n            resolve();\n          };\n          imgEl.onerror = (err) => reject(err);\n        });\n\n        // Center the isolated subject relative to the canvas\n        activeImg.set({\n          left: (width - activeImg.width * activeImg.scaleX) / 2,\n          top: (height - activeImg.height * activeImg.scaleY) / 2\n        });\n        activeImg.setCoords();\n      }\n\n      canvasInstance.requestRenderAll();\n      syncLayers();\n      saveHistoryState();\n    } catch (err: any) {\n      console.error(err);\n      setAiError(err.message || getActiveMessages().store.toasts.editor.aiApplyGenerativeBgError);\n    } finally {\n      setAiGenerating(false);\n    }\n  },\n\n  runMagicResize: async (targetWidth: number, targetHeight: number) => {\n    const { canvasInstance, pages, activePageId, syncLayers, saveHistoryState, setAiGenerating, setAiError } = get();\n    if (!canvasInstance) return;\n\n    try {\n      setAiGenerating(true);\n      setAiError(null);\n\n      const page = pages.find(p => p.id === activePageId);\n      if (!page) return;\n\n      const oldWidth = page.width;\n      const oldHeight = page.height;\n      const objects = canvasInstance.getObjects();\n\n      // Background dynamic detection helper\n      const isBackground = (obj: any) => {\n        if (obj.name === 'Fondo: Imagen') return true;\n        if (obj.type?.toLowerCase() === 'image' || obj.type?.toLowerCase() === 'rect') {\n          const canvasArea = oldWidth * oldHeight;\n          const objArea = (obj.width * obj.scaleX) * (obj.height * obj.scaleY);\n          if (canvasArea > 0 && (objArea / canvasArea) > 0.6) {\n            return true;\n          }\n        }\n        if (objects[0] === obj && (obj.type?.toLowerCase() === 'image' || obj.type?.toLowerCase() === 'rect')) {\n          return true;\n        }\n        return false;\n      };\n\n      // Update page dimensions in store\n      const updatedPages = pages.map(p => {\n        if (p.id === activePageId) {\n          return { ...p, width: targetWidth, height: targetHeight };\n        }\n        return p;\n      });\n      set({ pages: updatedPages });\n      canvasInstance.setDimensions({ width: targetWidth, height: targetHeight });\n      applyCanvasBackground(canvasInstance, page.backgroundColor, targetWidth, targetHeight);\n\n      const isVerticalStory = targetHeight > targetWidth && oldHeight <= oldWidth;\n      const margin = 32;\n\n      if (isVerticalStory) {\n        // Stack elements vertically\n        const backgrounds = objects.filter(isBackground);\n        const foregrounds = objects.filter(obj => !isBackground(obj));\n\n        foregrounds.sort((a, b) => a.top - b.top);\n\n        backgrounds.forEach(bg => {\n          const element = (bg as any).getElement() as any;\n          const imgWidth = bg.width || (element ? element.naturalWidth || element.width : 800);\n          const imgHeight = bg.height || (element ? element.naturalHeight || element.height : 600);\n          const s = Math.max(targetWidth / imgWidth, targetHeight / imgHeight);\n          bg.set({\n            scaleX: s,\n            scaleY: s,\n            left: (targetWidth - imgWidth * s) / 2,\n            top: (targetHeight - imgHeight * s) / 2,\n          });\n          bg.setCoords();\n        });\n\n        let currentTop = margin * 2;\n        const availableHeight = targetHeight - margin * 4;\n        const totalForegroundHeight = foregrounds.reduce((acc, obj) => acc + (obj.height * obj.scaleY), 0);\n        const gap = foregrounds.length > 1 ? (availableHeight - totalForegroundHeight) / (foregrounds.length - 1) : 20;\n        const safeGap = Math.max(20, Math.min(gap, 60));\n\n        foregrounds.forEach((obj) => {\n          const objWidth = obj.width * obj.scaleX;\n          const objHeight = obj.height * obj.scaleY;\n\n          let newScaleX = obj.scaleX;\n          let newScaleY = obj.scaleY;\n          if (objWidth > targetWidth - margin * 2) {\n            const shrink = (targetWidth - margin * 2) / objWidth;\n            newScaleX *= shrink;\n            newScaleY *= shrink;\n          }\n\n          let newLeft = (targetWidth - obj.width * newScaleX) / 2;\n\n          // Logo alignment helper\n          const oldCenterX = obj.left + objWidth / 2;\n          const oldCenterY = obj.top + objHeight / 2;\n          if (objWidth < 150 && objHeight < 150 && oldCenterY < oldHeight / 3) {\n            if (oldCenterX < oldWidth / 3) {\n              newLeft = margin;\n            } else if (oldCenterX > 2 * oldWidth / 3) {\n              newLeft = targetWidth - obj.width * newScaleX - margin;\n            }\n          }\n\n          obj.set({\n            left: newLeft,\n            top: currentTop,\n            scaleX: newScaleX,\n            scaleY: newScaleY,\n          });\n          obj.setCoords();\n          currentTop += (obj.height * newScaleY) + safeGap;\n        });\n      } else {\n        // Proportional reflow with bounds safety\n        const scaleX = oldWidth > 0 ? targetWidth / oldWidth : 1;\n        const scaleY = oldHeight > 0 ? targetHeight / oldHeight : 1;\n\n        objects.forEach(obj => {\n          if (isBackground(obj)) {\n            const element = (obj as any).getElement() as any;\n            const imgWidth = obj.width || (element ? element.naturalWidth || element.width : 800);\n            const imgHeight = obj.height || (element ? element.naturalHeight || element.height : 600);\n            const s = Math.max(targetWidth / imgWidth, targetHeight / imgHeight);\n            obj.set({\n              scaleX: s,\n              scaleY: s,\n              left: (targetWidth - imgWidth * s) / 2,\n              top: (targetHeight - imgHeight * s) / 2,\n            });\n          } else {\n            const oldCenterX = obj.left + (obj.width * obj.scaleX) / 2;\n            const wasCentered = Math.abs(oldCenterX - oldWidth / 2) < 25;\n\n            obj.set({\n              left: wasCentered ? (targetWidth - (obj.width * obj.scaleX * scaleX)) / 2 : obj.left * scaleX,\n              top: obj.top * scaleY,\n              scaleX: obj.scaleX * scaleX,\n              scaleY: obj.scaleY * scaleY,\n            });\n          }\n          obj.setCoords();\n        });\n      }\n\n      canvasInstance.renderAll();\n      syncLayers();\n      saveHistoryState();\n    } catch (err: any) {\n      console.error(err);\n      setAiError(err.message || getActiveMessages().store.toasts.editor.aiMagicResizeError);\n    } finally {\n      setAiGenerating(false);\n    }\n  },\n\n  runAiAutoLayout: async (direction: 'row' | 'column' | 'grid', gap: number = 24, alignment: 'top' | 'center' | 'bottom' | 'left' | 'right' = 'center') => {\n    const { canvasInstance, activeObject, syncLayers, saveHistoryState, setAiGenerating, setAiError } = get();\n    if (!canvasInstance || !activeObject) return;\n\n    try {\n      setAiGenerating(true);\n      setAiError(null);\n\n      let objects: any[] = [];\n      let activeSelectionObj: any = null;\n      if (activeObject.type?.toLowerCase() === 'activeselection') {\n        activeSelectionObj = activeObject;\n        objects = (activeObject as any).getObjects();\n      } else if (activeObject.type?.toLowerCase() === 'group') {\n        objects = (activeObject as any).getObjects();\n      }\n\n      if (objects.length < 2) {\n        setAiError('Selecciona m\u00FAltiples objetos para aplicar Auto Layout.');\n        return;\n      }\n\n      // Calculate the original bounding box of the selected objects\n      let minLeft = Infinity;\n      let maxRight = -Infinity;\n      let minTop = Infinity;\n      let maxBottom = -Infinity;\n\n      objects.forEach(obj => {\n        const left = obj.left;\n        const top = obj.top;\n        const right = left + obj.width * obj.scaleX;\n        const bottom = top + obj.height * obj.scaleY;\n        if (left < minLeft) minLeft = left;\n        if (right > maxRight) maxRight = right;\n        if (top < minTop) minTop = top;\n        if (bottom > maxBottom) maxBottom = bottom;\n      });\n\n      const groupWidth = maxRight - minLeft;\n      const groupHeight = maxBottom - minTop;\n\n      if (direction === 'row') {\n        // Sort objects from left to right based on current position\n        objects.sort((a, b) => a.left - b.left);\n        let currentLeft = minLeft;\n\n        objects.forEach((obj) => {\n          let targetTop = minTop;\n          if (alignment === 'center') {\n            targetTop = minTop + (groupHeight - obj.height * obj.scaleY) / 2;\n          } else if (alignment === 'bottom') {\n            targetTop = maxBottom - obj.height * obj.scaleY;\n          }\n\n          obj.set({\n            top: targetTop,\n            left: currentLeft,\n          });\n          obj.setCoords();\n          currentLeft += (obj.width * obj.scaleX) + gap;\n        });\n      } else if (direction === 'column') {\n        // Sort objects from top to bottom\n        objects.sort((a, b) => a.top - b.top);\n        let currentTop = minTop;\n\n        objects.forEach((obj) => {\n          let targetLeft = minLeft;\n          if (alignment === 'center') {\n            targetLeft = minLeft + (groupWidth - obj.width * obj.scaleX) / 2;\n          } else if (alignment === 'right') {\n            targetLeft = maxRight - obj.width * obj.scaleX;\n          }\n\n          obj.set({\n            left: targetLeft,\n            top: currentTop,\n          });\n          obj.setCoords();\n          currentTop += (obj.height * obj.scaleY) + gap;\n        });\n      } else if (direction === 'grid') {\n        // Grid layout\n        objects.sort((a, b) => a.top - b.top || a.left - b.left);\n        const numCols = Math.ceil(Math.sqrt(objects.length));\n        \n        let maxRowHeight = 0;\n        let currentLeft = minLeft;\n        let currentTop = minTop;\n\n        // Determine column widths to align objects in columns\n        const colWidths = new Array(numCols).fill(0);\n        objects.forEach((obj, idx) => {\n          const col = idx % numCols;\n          colWidths[col] = Math.max(colWidths[col], obj.width * obj.scaleX);\n        });\n\n        objects.forEach((obj, idx) => {\n          const col = idx % numCols;\n          if (col === 0 && idx > 0) {\n            currentLeft = minLeft;\n            currentTop += maxRowHeight + gap;\n            maxRowHeight = 0;\n          }\n\n          let targetLeft = currentLeft;\n          if (alignment === 'center') {\n            targetLeft = currentLeft + (colWidths[col] - obj.width * obj.scaleX) / 2;\n          } else if (alignment === 'right' || alignment === 'bottom') {\n            targetLeft = currentLeft + colWidths[col] - obj.width * obj.scaleX;\n          }\n\n          obj.set({\n            left: targetLeft,\n            top: currentTop,\n          });\n          obj.setCoords();\n\n          maxRowHeight = Math.max(maxRowHeight, obj.height * obj.scaleY);\n          currentLeft += colWidths[col] + gap;\n        });\n      }\n\n      if (activeSelectionObj) {\n        activeSelectionObj.setCoords();\n      }\n\n      canvasInstance.requestRenderAll();\n      syncLayers();\n      saveHistoryState();\n    } catch (err: any) {\n      console.error(err);\n      setAiError(err.message || getActiveMessages().store.toasts.editor.aiAutoLayoutError);\n    } finally {\n      setAiGenerating(false);\n    }\n  },\n\n  runAiCopywrite: async (prompt: string) => {\n    const { canvasInstance, setAiGenerating, setAiError, geminiApiKey, setAiCopywritingSuggestions } = get();\n    if (!canvasInstance) {\n      setAiError('El lienzo no est\u00E1 inicializado.');\n      return;\n    }\n\n    try {\n      setAiGenerating(true);\n      setAiError(null);\n\n      const suggestions = await aiEngine.generateCopywritingSuggestions(prompt, geminiApiKey);\n      setAiCopywritingSuggestions(suggestions);\n    } catch (err: any) {\n      console.error(err);\n      setAiError(err.message || getActiveMessages().store.toasts.editor.aiCopySuggestionsError);\n    } finally {\n      setAiGenerating(false);\n    }\n  },\n\n  runVectorizeStroke: async (tolerance: number = 2.0) => {\n    const { canvasInstance, activeObject, syncLayers, saveHistoryState, setAiGenerating, setAiError } = get();\n    if (!canvasInstance || !activeObject || activeObject.type?.toLowerCase() !== 'path') {\n      setAiError('Selecciona un trazo de pincel primero para vectorizar.');\n      return;\n    }\n\n    try {\n      setAiGenerating(true);\n      setAiError(null);\n\n      const pathCommands = (activeObject as any).path;\n      if (!pathCommands || pathCommands.length < 2) {\n        setAiError('El trazo seleccionado es demasiado corto o no tiene datos de ruta.');\n        return;\n      }\n\n      // Convert local coordinates relative to center to absolute canvas coords via transform matrix\n      const matrix = (activeObject as any).calcTransformMatrix();\n      const points = pathCommands\n        .filter((cmd: any) => cmd[0] === 'M' || cmd[0] === 'L' || cmd[0] === 'Q')\n        .map((cmd: any) => {\n          if (cmd.length >= 3) {\n            const lx = cmd[cmd.length - 2];\n            const ly = cmd[cmd.length - 1];\n            const [a, b, c, d, tx, ty] = matrix;\n            return {\n              x: a * lx + c * ly + tx,\n              y: b * lx + d * ly + ty\n            };\n          }\n          return null;\n        })\n        .filter(Boolean) as { x: number; y: number }[];\n\n      if (points.length < 2) {\n        setAiError('El trazo seleccionado no tiene suficientes coordenadas v\u00E1lidas.');\n        return;\n      }\n\n      // Simplify using RDP\n      const simplifiedPoints = aiEngine.simplifyPoints(points, tolerance);\n\n      const smoothPathData = aiEngine.vectorizeStroke(simplifiedPoints);\n      if (!smoothPathData) {\n        setAiError('No se pudo simplificar el trazo.');\n        return;\n      }\n\n      // Create Path using absolute coordinates. Do NOT pass left/top so Fabric positions it correctly.\n      const smoothPath = new Path(smoothPathData, {\n        fill: 'transparent',\n        stroke: activeObject.stroke || '#000000',\n        strokeWidth: activeObject.strokeWidth || 3,\n        strokeLineCap: activeObject.strokeLineCap || 'round',\n        strokeLineJoin: activeObject.strokeLineJoin || 'round',\n        id: (activeObject as any).id || `path-${Date.now()}`,\n      });\n\n      canvasInstance.remove(activeObject);\n      canvasInstance.add(smoothPath);\n      canvasInstance.setActiveObject(smoothPath);\n      canvasInstance.requestRenderAll();\n\n      syncLayers();\n      saveHistoryState();\n    } catch (err: any) {\n      console.error(err);\n      setAiError(err.message || getActiveMessages().store.toasts.editor.aiVectorizeStrokeError);\n    } finally {\n      setAiGenerating(false);\n    }\n  },\n\n  runSketchToImage: async (prompt: string) => {\n    const { canvasInstance, activeObject, setAiGenerating, setAiError, syncLayers, saveHistoryState } = get();\n    if (!canvasInstance || !activeObject) {\n      setAiError('Selecciona un dibujo o trazo en el lienzo primero.');\n      return;\n    }\n\n    try {\n      setAiGenerating(true);\n      setAiError(null);\n\n      const dataUrl = activeObject.toDataURL({ format: 'png' });\n      const newSrc = await aiEngine.sketchToImage(dataUrl, prompt);\n\n      const imgElement = await new Promise<HTMLImageElement>((resolve, reject) => {\n        const i = new Image();\n        i.crossOrigin = 'anonymous';\n        i.src = newSrc;\n        i.onload = () => resolve(i);\n        i.onerror = reject;\n      });\n\n      const width = activeObject.width * (activeObject.scaleX || 1);\n      const height = activeObject.height * (activeObject.scaleY || 1);\n\n      const croppedSrc = cropToAspectRatio(imgElement, width, height);\n\n      const img = await new Promise<FabricImage>((resolve, reject) => {\n        FabricImage.fromURL(croppedSrc, { crossOrigin: 'anonymous' })\n          .then(resolve)\n          .catch(reject);\n      });\n\n      img.set({\n        left: activeObject.left,\n        top: activeObject.top,\n        scaleX: width / img.width,\n        scaleY: height / img.height,\n        angle: activeObject.angle,\n        id: `image-sketch-${Date.now()}`,\n        name: `Imagen (Boceto)`,\n      });\n\n      canvasInstance.remove(activeObject);\n      canvasInstance.add(img);\n      canvasInstance.setActiveObject(img);\n      set({ activeObject: img });\n      canvasInstance.requestRenderAll();\n\n      syncLayers();\n      saveHistoryState();\n      get().addToast(getActiveMessages().store.toasts.editor.sketchImageCreated, 'success');\n    } catch (err: any) {\n      console.error(err);\n      setAiError(err.message || getActiveMessages().store.toasts.editor.aiSketchError);\n      get().addToast(err.message || getActiveMessages().store.toasts.editor.aiSketchError, 'error');\n    } finally {\n      setAiGenerating(false);\n    }\n  },\n\n  runGenerateInArea: async (prompt: string) => {\n    const { canvasInstance, activeObject, setAiGenerating, setAiError, syncLayers, saveHistoryState } = get();\n    if (!canvasInstance || !activeObject || activeObject.type?.toLowerCase() !== 'rect') {\n      setAiError('Selecciona un rect\u00E1ngulo primero para delimitar el \u00E1rea de generaci\u00F3n.');\n      return;\n    }\n\n    try {\n      setAiGenerating(true);\n      setAiError(null);\n\n      const newSrc = await aiEngine.generateImageFromPrompt(prompt);\n\n      const imgElement = await new Promise<HTMLImageElement>((resolve, reject) => {\n        const i = new Image();\n        i.crossOrigin = 'anonymous';\n        i.src = newSrc;\n        i.onload = () => resolve(i);\n        i.onerror = reject;\n      });\n\n      const width = activeObject.width * (activeObject.scaleX || 1);\n      const height = activeObject.height * (activeObject.scaleY || 1);\n\n      const croppedSrc = cropToAspectRatio(imgElement, width, height);\n\n      const img = await new Promise<FabricImage>((resolve, reject) => {\n        FabricImage.fromURL(croppedSrc, { crossOrigin: 'anonymous' })\n          .then(resolve)\n          .catch(reject);\n      });\n\n      img.set({\n        left: activeObject.left,\n        top: activeObject.top,\n        scaleX: width / img.width,\n        scaleY: height / img.height,\n        angle: activeObject.angle,\n        id: `image-area-${Date.now()}`,\n        name: `Imagen AI`,\n      });\n\n      canvasInstance.remove(activeObject);\n      canvasInstance.add(img);\n      canvasInstance.setActiveObject(img);\n      set({ activeObject: img });\n      canvasInstance.requestRenderAll();\n\n      syncLayers();\n      saveHistoryState();\n      get().addToast(getActiveMessages().store.toasts.editor.inpaintImageCreated, 'success');\n    } catch (err: any) {\n      console.error(err);\n      setAiError(err.message || getActiveMessages().store.toasts.editor.aiInpaintError);\n      get().addToast(err.message || getActiveMessages().store.toasts.editor.aiInpaintError, 'error');\n    } finally {\n      setAiGenerating(false);\n    }\n  },\n\n  runSelectSubject: async () => {\n    const { canvasInstance, activeObject, setAiGenerating, setAiError, syncLayers, saveHistoryState } = get();\n    if (!canvasInstance || !activeObject || activeObject.type?.toLowerCase() !== 'image') {\n      setAiError('Selecciona una imagen primero para separar el sujeto.');\n      return;\n    }\n\n    const target = activeObject;\n    try {\n      setAiGenerating(true);\n      setAiError(null);\n      beginAiLoading(target);\n      canvasInstance.requestRenderAll();\n      syncLayers();\n\n      const dataUrl = (target as any).toDataURL({ format: 'png' });\n      const newSrc = await aiEngine.removeBackground(dataUrl);\n\n      const displayW = Math.max(1, (target.width ?? 1) * (target.scaleX ?? 1));\n      const displayH = Math.max(1, (target.height ?? 1) * (target.scaleY ?? 1));\n      const img = await FabricImage.fromURL(newSrc, { crossOrigin: 'anonymous' });\n      const iw = Math.max(1, img.width || 1);\n      const ih = Math.max(1, img.height || 1);\n      img.set({\n        left: target.left,\n        top: target.top,\n        angle: target.angle,\n        flipX: target.flipX,\n        flipY: target.flipY,\n        originX: target.originX,\n        originY: target.originY,\n        skewX: target.skewX,\n        skewY: target.skewY,\n        scaleX: displayW / iw,\n        scaleY: displayH / ih,\n        id: `image-subject-${Date.now()}`,\n        name: `${(target as FabricObject & { name?: string }).name || 'Imagen'} (Sujeto)`,\n      });\n\n      const origIndex = canvasInstance.getObjects().indexOf(target);\n      endAiLoading(target);\n      canvasInstance.add(img);\n      if (origIndex >= 0) canvasInstance.moveObjectTo(img, origIndex + 1);\n      canvasInstance.setActiveObject(img);\n      set({ activeObject: img });\n      canvasInstance.requestRenderAll();\n\n      syncLayers();\n      saveHistoryState();\n      get().addToast(getActiveMessages().store.toasts.editor.subjectSeparated, 'success');\n    } catch (err: any) {\n      console.error(err);\n      if (canvasInstance.getObjects().includes(target)) {\n        endAiLoading(target);\n        canvasInstance.requestRenderAll();\n      }\n      setAiError(err.message || getActiveMessages().store.toasts.editor.aiSeparateSubjectError);\n      get().addToast(err.message || getActiveMessages().store.toasts.editor.aiSeparateSubjectError, 'error');\n    } finally {\n      setAiGenerating(false);\n    }\n  },\n\n  runAiMagicEraser: async () => {\n    const {\n      canvasInstance,\n      activeObject,\n      magicEraserTargetId,\n      lastSelectedObjectId,\n      setAiGenerating,\n      syncLayers,\n      saveHistoryState,\n      setMagicEraserTargetId,\n    } = get();\n    if (!canvasInstance) return;\n\n    // Prefer the id pinned when mask-edit started (brush clears Fabric selection).\n    const pinned =\n      findObjectById(canvasInstance, magicEraserTargetId) ||\n      findObjectById(canvasInstance, lastSelectedObjectId);\n    const candidate =\n      pinned ||\n      (activeObject && activeObject.type?.toLowerCase() === 'image' ? activeObject : null);\n    if (!candidate || candidate.type?.toLowerCase() !== 'image') {\n      get().addToast(getActiveMessages().layers.mustSelectLayer, 'warning');\n      return;\n    }\n    const target = candidate;\n\n    try {\n      setAiGenerating(true);\n      beginAiLoading(target);\n      canvasInstance.requestRenderAll();\n      syncLayers();\n\n      const allObjects = canvasInstance.getObjects();\n      const eraserMarks = allObjects.filter((obj: any) => obj.type?.toLowerCase() === 'path' && obj.name === 'eraser-mark');\n\n      if (eraserMarks.length === 0) {\n        endAiLoading(target);\n        get().addToast(\n          getActiveMessages().store.toasts.editor.magicEraserNeedMarks,\n          'warning',\n        );\n        return;\n      }\n\n      const imageWidth = target.width;\n      const imageHeight = target.height;\n\n      const tempCanvasElement = document.createElement('canvas');\n      tempCanvasElement.width = imageWidth;\n      tempCanvasElement.height = imageHeight;\n      const ctx = tempCanvasElement.getContext('2d');\n      if (!ctx) throw new Error('No se pudo crear contexto 2D para la m\u00E1scara.');\n\n      ctx.fillStyle = '#000000';\n      ctx.fillRect(0, 0, imageWidth, imageHeight);\n\n      const maskCanvas = new Canvas(tempCanvasElement, {\n        width: imageWidth,\n        height: imageHeight,\n      });\n\n      // Matrix math helpers for precise coordinate translation\n      const invertMatrix = (M: number[]): number[] => {\n        const [a, b, c, d, tx, ty] = M;\n        const det = a * d - b * c;\n        if (Math.abs(det) < 1e-6) {\n          return [1, 0, 0, 1, -tx, -ty];\n        }\n        const inv_a = d / det;\n        const inv_b = -b / det;\n        const inv_c = -c / det;\n        const inv_d = a / det;\n        const inv_tx = -(inv_a * tx + inv_c * ty);\n        const inv_ty = -(inv_b * tx + inv_d * ty);\n        return [inv_a, inv_b, inv_c, inv_d, inv_tx, inv_ty];\n      };\n\n      const multiplyMatrices = (A: number[], B: number[]): number[] => {\n        const [a1, b1, c1, d1, tx1, ty1] = A;\n        const [a2, b2, c2, d2, tx2, ty2] = B;\n        return [\n          a1 * a2 + c1 * b2,\n          b1 * a2 + d1 * b2,\n          a1 * c2 + c1 * d2,\n          b1 * c2 + d1 * d2,\n          a1 * tx2 + c1 * ty2 + tx1,\n          b1 * tx2 + d1 * ty2 + ty1\n        ];\n      };\n\n      const decomposeMatrix = (matrix: number[]) => {\n        const [a, b, c, d, tx, ty] = matrix;\n        const left = tx;\n        const top = ty;\n        const delta = a * d - b * c;\n        let scaleX = 0;\n        let scaleY = 0;\n        let angle = 0;\n        let skewX = 0;\n\n        if (a !== 0 || b !== 0) {\n          const r = Math.sqrt(a * a + b * b);\n          angle = b > 0 ? Math.acos(a / r) : -Math.acos(a / r);\n          scaleX = r;\n          scaleY = delta / r;\n          skewX = Math.atan((a * c + b * d) / (r * r));\n        } else if (c !== 0 || d !== 0) {\n          const s = Math.sqrt(c * c + d * d);\n          angle = Math.PI / 2 - (d > 0 ? Math.acos(-c / s) : -Math.acos(-c / s));\n          scaleX = delta / s;\n          scaleY = s;\n          skewX = Math.atan((a * c + b * d) / (s * s));\n        }\n        return {\n          left,\n          top,\n          scaleX,\n          scaleY,\n          angle: angle * (180 / Math.PI),\n          skewX: skewX * (180 / Math.PI),\n        };\n      };\n\n      const M_img = (target as any).calcTransformMatrix();\n      const inv_M_img = invertMatrix(M_img);\n      const T_half = [1, 0, 0, 1, imageWidth / 2, imageHeight / 2];\n      const M_global_to_mask = multiplyMatrices(T_half, inv_M_img);\n\n      eraserMarks.forEach((mark: any) => {\n        const M_mark = mark.calcTransformMatrix();\n        const M_mark_in_mask = multiplyMatrices(M_global_to_mask, M_mark);\n        const props = decomposeMatrix(M_mark_in_mask);\n\n        const clonedPath = new Path(mark.path, {\n          fill: 'transparent',\n          stroke: '#ffffff',\n          strokeWidth: mark.strokeWidth,\n          strokeLineCap: mark.strokeLineCap,\n          strokeLineJoin: mark.strokeLineJoin,\n          strokeUniform: false,\n          originX: 'center',\n          originY: 'center',\n        });\n\n        clonedPath.set({\n          left: props.left,\n          top: props.top,\n          scaleX: props.scaleX,\n          scaleY: props.scaleY,\n          angle: props.angle,\n          skewX: props.skewX,\n        });\n\n        maskCanvas.add(clonedPath);\n      });\n\n      maskCanvas.renderAll();\n      const maskDataUrl = maskCanvas.toDataURL({ format: 'png', multiplier: 1 });\n\n      maskCanvas.dispose();\n\n      const originalSrc = (target as any).toDataURL({ format: 'png' });\n\n      const newSrc = await aiEngine.magicEraser(originalSrc, maskDataUrl);\n\n      eraserMarks.forEach((mark) => canvasInstance.remove(mark));\n\n      const img = await replaceFabricImagePreservingTransform(canvasInstance, target, newSrc);\n      set({ activeObject: img, magicEraserTargetId: (img as FabricObject & { id?: string }).id || null });\n\n      syncLayers();\n      saveHistoryState();\n      get().addToast(getActiveMessages().store.toasts.editor.magicEraserDone, 'success');\n    } catch (err: unknown) {\n      if (canvasInstance.getObjects().includes(target)) {\n        endAiLoading(target);\n        canvasInstance.requestRenderAll();\n      }\n      // 409 = AI found nothing useful to erase \u2014 informational, not a hard failure.\n      const isNothingFound =\n        (err instanceof ApiError && err.status === 409) ||\n        (err instanceof Error && /\\bHTTP\\s*409\\b/i.test(err.message));\n      if (isNothingFound) {\n        get().addToast(\n          getActiveMessages().store.toasts.editor.magicEraserNothingFound,\n          'info',\n        );\n      } else {\n        console.error(err);\n        const fallback = getActiveMessages().store.toasts.editor.aiMagicEraserError;\n        const message = err instanceof Error && err.message ? err.message : fallback;\n        // Toast only \u2014 do not write aiError / aiStudioError (different tool).\n        get().addToast(message, 'error');\n      }\n    } finally {\n      setAiGenerating(false);\n      setMagicEraserTargetId(null);\n      syncLayers();\n    }\n  },\n\n  runAiDesignCopilot: async (prompt) => {\n    const { canvasInstance, activeObject, setAiGenerating, setAiError, syncLayers, saveHistoryState } = get();\n\n    // 1. Determinar el tipo de objeto activo\n    let objectType: 'text' | 'shape' | 'image' | 'canvas' = 'canvas';\n    if (activeObject) {\n      const type = activeObject.type?.toLowerCase();\n      if (['text', 'textbox', 'i-text'].includes(type || '')) {\n        objectType = 'text';\n      } else if (['rect', 'circle', 'triangle', 'path', 'ellipse', 'polygon', 'polyline'].includes(type || '')) {\n        objectType = 'shape';\n      } else if (type === 'image') {\n        objectType = 'image';\n      }\n    }\n\n    try {\n      setAiGenerating(true);\n      setAiError(null);\n\n      // 2. Obtener el preset JSON desde GPT\n      const preset = await generateImageDesignPreset(prompt, objectType);\n\n      if (objectType === 'canvas') {\n        // Modificar fondo del lienzo\n        if (preset.backgroundType === 'color' && preset.value) {\n          get().updatePageBgColor(get().activePageId, preset.value as string);\n          get().addToast('Fondo de color s\u00F3lido aplicado por AI', 'success');\n        } else if (preset.backgroundType === 'gradient' && (preset.gradient as { colors?: string[] })?.colors) {\n          const mainColor = (preset.gradient as { colors: string[] }).colors[0];\n          get().updatePageBgColor(get().activePageId, mainColor);\n          get().addToast(`Degradado simplificado a color s\u00F3lido (${mainColor}) aplicado`, 'success');\n        } else if (preset.backgroundType === 'image' && preset.imagePrompt) {\n          get().addToast('Generando imagen de fondo AI con Gemini...', 'info');\n          const newSrc = await aiEngine.generateImageFromPrompt(preset.imagePrompt as string);\n          \n          if (canvasInstance) {\n            const img = await new Promise<any>((resolve, reject) => {\n              FabricImage.fromURL(newSrc, { crossOrigin: 'anonymous' })\n                .then(resolve)\n                .catch(reject);\n            });\n            \n            const canvasWidth = canvasInstance.width || 800;\n            const canvasHeight = canvasInstance.height || 600;\n            img.set({\n              left: 0,\n              top: 0,\n              scaleX: canvasWidth / (img.width || 1024),\n              scaleY: canvasHeight / (img.height || 1024),\n              selectable: true,\n              name: 'AI Background Image'\n            });\n            \n            canvasInstance.add(img);\n            canvasInstance.sendObjectToBack(img);\n            canvasInstance.requestRenderAll();\n            syncLayers();\n            saveHistoryState();\n            get().addToast(getActiveMessages().store.toasts.editor.aiBgGenerated, 'success');\n          }\n        }\n      } else if (activeObject) {\n        if (objectType === 'text') {\n          const fabricSettings: any = { ...preset };\n          if (preset.shadowColor) {\n            const blur = (preset.shadowBlur as number) || 10;\n            const offX = (preset.shadowOffsetX as number) || 0;\n            const offY = (preset.shadowOffsetY as number) || 0;\n            fabricSettings.shadow = new Shadow(`${offX}px ${offY}px ${blur}px ${preset.shadowColor as string}`);\n          }\n          activeObject.set(fabricSettings);\n          get().updateTextSettings(fabricSettings);\n          canvasInstance?.requestRenderAll();\n          saveHistoryState();\n          get().addToast('Estilo de texto AI aplicado con \u00E9xito', 'success');\n        } else if (objectType === 'shape') {\n          activeObject.set(preset);\n          canvasInstance?.requestRenderAll();\n          saveHistoryState();\n          get().addToast('Estilo de figura AI aplicado con \u00E9xito', 'success');\n        } else if (objectType === 'image') {\n          // Aplicar filtros en lote\n          const imgObj = activeObject as any;\n          if (!imgObj.filters) imgObj.filters = [];\n          \n          const applyFilterHelper = (fClass: any, propName: string, value: any) => {\n            const idx = imgObj.filters.findIndex((f: any) => f instanceof fClass);\n            if (value === 0 || value === false || value === undefined) {\n              if (idx > -1) imgObj.filters.splice(idx, 1);\n            } else {\n              const filter = new fClass({ [propName]: value });\n              if (idx > -1) imgObj.filters[idx] = filter;\n              else imgObj.filters.push(filter);\n            }\n          };\n\n          const { filters } = await import('fabric');\n\n          if (preset.brightness !== undefined) applyFilterHelper(filters.Brightness, 'brightness', preset.brightness);\n          if (preset.contrast !== undefined) applyFilterHelper(filters.Contrast, 'contrast', preset.contrast);\n          if (preset.saturation !== undefined) applyFilterHelper(filters.Saturation, 'saturation', preset.saturation);\n          if (preset.blur !== undefined) applyFilterHelper(filters.Blur, 'blur', preset.blur);\n          if (preset.exposure !== undefined) {\n            const idx = imgObj.filters.findIndex((f: any) => f instanceof filters.Gamma);\n            if (preset.exposure === 0) {\n              if (idx > -1) imgObj.filters.splice(idx, 1);\n            } else {\n              const gVal = 1 / (1 + (preset.exposure as number));\n              const filter = new filters.Gamma({ gamma: [gVal, gVal, gVal] });\n              if (idx > -1) imgObj.filters[idx] = filter;\n              else imgObj.filters.push(filter);\n            }\n          }\n          if (preset.invert !== undefined) {\n            const idx = imgObj.filters.findIndex((f: any) => f instanceof filters.Invert);\n            if (!preset.invert) {\n              if (idx > -1) imgObj.filters.splice(idx, 1);\n            } else {\n              if (idx === -1) imgObj.filters.push(new filters.Invert());\n            }\n          }\n          if (preset.grayscale !== undefined) {\n            const idx = imgObj.filters.findIndex((f: any) => f instanceof filters.Grayscale);\n            if (!preset.grayscale) {\n              if (idx > -1) imgObj.filters.splice(idx, 1);\n            } else {\n              if (idx === -1) imgObj.filters.push(new filters.Grayscale());\n            }\n          }\n          if (preset.sepia !== undefined) {\n            const idx = imgObj.filters.findIndex((f: any) => f instanceof filters.Sepia);\n            if (!preset.sepia) {\n              if (idx > -1) imgObj.filters.splice(idx, 1);\n            } else {\n              if (idx === -1) imgObj.filters.push(new filters.Sepia());\n            }\n          }\n\n          // Guardar en la UI settings\n          const newSettings: any = {};\n          if (preset.brightness !== undefined) newSettings.brightness = preset.brightness;\n          if (preset.contrast !== undefined) newSettings.contrast = preset.contrast;\n          if (preset.saturation !== undefined) newSettings.saturation = preset.saturation;\n          if (preset.blur !== undefined) newSettings.blur = preset.blur;\n          if (preset.exposure !== undefined) newSettings.exposure = preset.exposure;\n          if (preset.invert !== undefined) newSettings.invert = preset.invert;\n          set({ imageSettings: { ...get().imageSettings, ...newSettings } });\n\n          imgObj.applyFilters();\n          canvasInstance?.requestRenderAll();\n          saveHistoryState();\n          get().addToast('Filtros fotogr\u00E1ficos AI aplicados con \u00E9xito', 'success');\n        }\n      }\n    } catch (err: any) {\n      console.error(err);\n      setAiError(err.message || getActiveMessages().store.toasts.editor.aiDesignError);\n      get().addToast(err.message || getActiveMessages().store.toasts.editor.aiDesignToastError, 'error');\n    } finally {\n      setAiGenerating(false);\n    }\n  },\n\n  runAiUpscale: async (factor) => {\n    const { canvasInstance, activeObject, setAiGenerating, setAiError, geminiApiKey, syncLayers, saveHistoryState } = get();\n    if (!canvasInstance || !activeObject || activeObject.type !== 'image') {\n      get().addToast(getActiveMessages().store.toasts.editor.upscaleSelectImage, 'warning');\n      return;\n    }\n    \n    if (!geminiApiKey) {\n      setAiError('Configura tu API Key en la barra de herramientas de Video.');\n      window.dispatchEvent(new CustomEvent('open-ai-keys-modal'));\n      return;\n    }\n\n    try {\n      setAiGenerating(true);\n      setAiError(null);\n      get().addToast(getActiveMessages().store.toasts.editor.upscaleStarted(factor), 'info');\n\n      // AI Upscale via API\n      const el = (activeObject as any).getElement();\n      const rawUrl = el.src || (activeObject as any).toDataURL();\n      const upscaledSrc = await aiEngine.upscaleImage(rawUrl, factor, geminiApiKey);\n\n      const { FabricImage } = await import('fabric');\n      const img = await new Promise<any>((resolve, reject) => {\n        FabricImage.fromURL(upscaledSrc, { crossOrigin: 'anonymous' })\n          .then(resolve)\n          .catch(reject);\n      });\n\n      // Maintain visual size but update data\n      img.set({\n        left: activeObject.left,\n        top: activeObject.top,\n        scaleX: ((activeObject.width || 1) * (activeObject.scaleX || 1)) / (img.width || 1),\n        scaleY: ((activeObject.height || 1) * (activeObject.scaleY || 1)) / (img.height || 1),\n        angle: activeObject.angle,\n        id: (activeObject as any).id,\n        name: `${(activeObject as any).name || 'Imagen'} (Upscaled)`,\n      });\n\n      const origIndex = canvasInstance.getObjects().indexOf(activeObject);\n      canvasInstance.remove(activeObject);\n      canvasInstance.add(img);\n      canvasInstance.moveObjectTo(img, origIndex);\n      canvasInstance.setActiveObject(img);\n      set({ activeObject: img });\n      canvasInstance.requestRenderAll();\n\n      syncLayers();\n      saveHistoryState();\n      get().addToast(getActiveMessages().store.toasts.editor.upscaleDone(factor), 'success');\n    } catch (err: any) {\n      console.error(err);\n      setAiError(err.message || getActiveMessages().store.toasts.editor.aiUpscaleError);\n      get().addToast(err.message || getActiveMessages().store.toasts.editor.aiUpscaleError, 'error');\n    } finally {\n      setAiGenerating(false);\n    }\n  },\n\n  runAiVariations: async () => {\n    const { activeObject, setAiGenerating, setAiError } = get();\n    if (!activeObject || activeObject.type !== 'image') {\n      get().addToast(getActiveMessages().store.toasts.editor.variationsSelectImage, 'warning');\n      return;\n    }\n\n    try {\n      setAiGenerating(true);\n      setAiError(null);\n      get().addToast(getActiveMessages().store.toasts.editor.variationsStarted, 'info');\n\n      // Generate 4 subtle variations\n      const prompts = [\n        \"create a highly detailed subtle variation of this image, keeping the exact same layout and subject but with slight lighting changes\",\n        \"create a highly detailed subtle variation of this image, keeping the exact same layout and subject but with slight color tone shifts\",\n        \"create a highly detailed subtle variation of this image, keeping the exact same layout and subject but with enhanced textures\",\n        \"create a highly detailed subtle variation of this image, keeping the exact same layout and subject but with a slightly softer mood\"\n      ];\n\n      const rawUrl = (activeObject as any).getElement().src || (activeObject as any).toDataURL();\n      const promises = prompts.map(prompt =>\n        aiEngine.modifyImageByPrompt(rawUrl, prompt)\n      );\n\n      const newImages = await Promise.all(promises);\n\n      set({\n        aiVariations: newImages,\n        isVariationsModalOpen: true\n      });\n\n      get().addToast(getActiveMessages().store.toasts.editor.variationsDone, 'success');\n    } catch (err: any) {\n      console.error(err);\n      setAiError(err.message || getActiveMessages().store.toasts.editor.aiVariationsError);\n      get().addToast(err.message || getActiveMessages().store.toasts.editor.aiVariationsError, 'error');\n    } finally {\n      setAiGenerating(false);\n    }\n  },\n\n  runAiAutoEnhance: async () => {\n    const { canvasInstance, activeObject, saveHistoryState } = get();\n    if (!canvasInstance || !activeObject || activeObject.type !== 'image') {\n      get().addToast(getActiveMessages().store.toasts.editor.autoEnhanceSelectImage, 'warning');\n      return;\n    }\n\n    try {\n      get().addToast(getActiveMessages().store.toasts.editor.autoEnhanceStarted, 'info');\n      \n      const imgObj = activeObject as any;\n      const el = imgObj.getElement();\n      \n      if (!el) return;\n\n      const canvas = document.createElement('canvas');\n      const ctx = canvas.getContext('2d');\n      if (!ctx) return;\n      \n      canvas.width = Math.min(el.width || 512, 512);\n      canvas.height = Math.min(el.height || 512, 512);\n      ctx.drawImage(el, 0, 0, canvas.width, canvas.height);\n      const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n      \n      // Calculate histogram\n      const hist = new Array(256).fill(0);\n      let totalPixels = 0;\n      for (let i = 0; i < imgData.data.length; i += 4) {\n        const lum = Math.round(imgData.data[i] * 0.299 + imgData.data[i+1] * 0.587 + imgData.data[i+2] * 0.114);\n        hist[lum]++;\n        totalPixels++;\n      }\n\n      // Find 0.5% and 99.5% percentiles\n      let blackPoint = 0;\n      let whitePoint = 255;\n      \n      let sum = 0;\n      for (let i = 0; i < 256; i++) {\n        sum += hist[i];\n        if (sum > totalPixels * 0.005) { blackPoint = i; break; }\n      }\n      \n      sum = 0;\n      for (let i = 255; i >= 0; i--) {\n        sum += hist[i];\n        if (sum > totalPixels * 0.005) { whitePoint = i; break; }\n      }\n\n      // Apply Levels and Saturation\n      const { filters } = await import('fabric');\n      const { LevelsFilter } = await import('../utils/fabricCustomFilters');\n      const { applyFabricImageFilters } = await import('../utils/applyFabricImageFilters');\n\n      if (!imgObj.filters) imgObj.filters = [];\n      \n      // Levels\n      let idxLevels = imgObj.filters.findIndex((f: any) => f instanceof LevelsFilter);\n      const levelsFilter = new LevelsFilter({ black: blackPoint, mid: 1.05, white: whitePoint });\n      if (idxLevels > -1) imgObj.filters[idxLevels] = levelsFilter;\n      else imgObj.filters.push(levelsFilter);\n\n      // Saturation boost\n      let idxSat = imgObj.filters.findIndex((f: any) => f instanceof filters.Saturation);\n      const satFilter = new filters.Saturation({ saturation: 0.2 }); // 20% boost\n      if (idxSat > -1) imgObj.filters[idxSat] = satFilter;\n      else imgObj.filters.push(satFilter);\n\n      // Sync settings\n      set({\n        imageSettings: {\n          ...get().imageSettings,\n          levelsBlack: blackPoint,\n          levelsWhite: whitePoint,\n          levelsMid: 1.05,\n          saturation: 0.2,\n          activePreset: 'custom'\n        }\n      });\n\n      applyFabricImageFilters(imgObj, true);\n\n      canvasInstance.requestRenderAll();\n      saveHistoryState();\n      get().addToast(getActiveMessages().store.toasts.editor.autoEnhanceDone, 'success');\n\n    } catch (err: any) {\n      console.error(err);\n      get().addToast(getActiveMessages().store.toasts.editor.autoEnhanceError, 'error');\n    }\n  }\n}));\n\nimagePersistence = createProjectPersistence({\n  mode: 'image',\n  localDebounceMs: 400,\n  cloudDebounceMs: 3000,\n  saveLocal: async () => {\n    await useEditorStore.getState().saveCurrentProject();\n  },\n  saveCloud: async () => useEditorStore.getState().autoSaveProjectToCloud(),\n});\nregisterProjectPersistence(imagePersistence);\n\nexport function flushImagePersistence(): Promise<void> {\n  return imagePersistence.flush();\n}\n\n// Helper at file-level for aspect-ratio cropping\nconst cropToAspectRatio = (img: HTMLImageElement, targetWidth: number, targetHeight: number): string => {\n  const canvas = document.createElement('canvas');\n  const imgAR = img.width / img.height;\n  const targetAR = targetWidth / targetHeight;\n\n  let sX = 0, sY = 0, sW = img.width, sH = img.height;\n\n  if (imgAR > targetAR) {\n    sW = img.height * targetAR;\n    sX = (img.width - sW) / 2;\n  } else {\n    sH = img.width / targetAR;\n    sY = (img.height - sH) / 2;\n  }\n\n  canvas.width = sW;\n  canvas.height = sH;\n\n  const ctx = canvas.getContext('2d');\n  if (ctx) {\n    ctx.drawImage(img, sX, sY, sW, sH, 0, 0, sW, sH);\n  }\n  return canvas.toDataURL('image/png');\n};\n\n", "/** Independent corner radii for Fabric Rect (native Rect only has uniform rx/ry). */\n\nexport type CornerRadii = {\n  tl: number;\n  tr: number;\n  br: number;\n  bl: number;\n};\n\nconst K = 0.4477152502;\n\nexport function uniformCornerRadii(r: number): CornerRadii {\n  const n = Math.max(0, Math.round(r));\n  return { tl: n, tr: n, br: n, bl: n };\n}\n\nexport function readCornerRadii(obj: {\n  rx?: number;\n  weCornerRadii?: CornerRadii;\n}): CornerRadii {\n  if (obj.weCornerRadii) {\n    return {\n      tl: Math.max(0, Math.round(obj.weCornerRadii.tl || 0)),\n      tr: Math.max(0, Math.round(obj.weCornerRadii.tr || 0)),\n      br: Math.max(0, Math.round(obj.weCornerRadii.br || 0)),\n      bl: Math.max(0, Math.round(obj.weCornerRadii.bl || 0)),\n    };\n  }\n  return uniformCornerRadii(obj.rx || 0);\n}\n\nexport function cornersAreLinked(obj: { weCornersLinked?: boolean }): boolean {\n  return obj.weCornersLinked !== false;\n}\n\nfunction clampCorners(w: number, h: number, c: CornerRadii): CornerRadii {\n  const maxR = Math.min(w, h) / 2;\n  let tl = Math.min(Math.max(0, c.tl), maxR);\n  let tr = Math.min(Math.max(0, c.tr), maxR);\n  let br = Math.min(Math.max(0, c.br), maxR);\n  let bl = Math.min(Math.max(0, c.bl), maxR);\n  // Adjacent corners on the same edge must fit the edge length.\n  if (tl + tr > w) {\n    const s = w / (tl + tr);\n    tl *= s;\n    tr *= s;\n  }\n  if (bl + br > w) {\n    const s = w / (bl + br);\n    bl *= s;\n    br *= s;\n  }\n  if (tl + bl > h) {\n    const s = h / (tl + bl);\n    tl *= s;\n    bl *= s;\n  }\n  if (tr + br > h) {\n    const s = h / (tr + br);\n    tr *= s;\n    br *= s;\n  }\n  return { tl, tr, br, bl };\n}\n\n/**\n * When corners are unlinked, Fabric's default Rect._render (uniform rx/ry)\n * cannot express per-corner radii \u2014 swap in a custom path draw.\n */\nexport function installIndependentCornerRender(obj: {\n  type?: string;\n  __weCornerRenderInstalled?: boolean;\n  _render?: (ctx: CanvasRenderingContext2D) => void;\n}): void {\n  if (!obj || (obj.type || '').toLowerCase() !== 'rect') return;\n  if (obj.__weCornerRenderInstalled) return;\n\n  const proto = Object.getPrototypeOf(obj) as {\n    _render: (ctx: CanvasRenderingContext2D) => void;\n  };\n  const baseRender = proto._render.bind(obj);\n\n  obj.__weCornerRenderInstalled = true;\n  obj._render = function (this: {\n    width: number;\n    height: number;\n    weCornersLinked?: boolean;\n    weCornerRadii?: CornerRadii;\n    _renderPaintInOrder: (ctx: CanvasRenderingContext2D) => void;\n  }, ctx: CanvasRenderingContext2D) {\n    if (this.weCornersLinked !== false || !this.weCornerRadii) {\n      return baseRender(ctx);\n    }\n\n    const { width: w, height: h } = this;\n    const x = -w / 2;\n    const y = -h / 2;\n    const { tl, tr, br, bl } = clampCorners(w, h, this.weCornerRadii);\n\n    ctx.beginPath();\n    ctx.moveTo(x + tl, y);\n    ctx.lineTo(x + w - tr, y);\n    if (tr > 0) {\n      ctx.bezierCurveTo(x + w - K * tr, y, x + w, y + K * tr, x + w, y + tr);\n    } else {\n      ctx.lineTo(x + w, y);\n    }\n    ctx.lineTo(x + w, y + h - br);\n    if (br > 0) {\n      ctx.bezierCurveTo(x + w, y + h - K * br, x + w - K * br, y + h, x + w - br, y + h);\n    } else {\n      ctx.lineTo(x + w, y + h);\n    }\n    ctx.lineTo(x + bl, y + h);\n    if (bl > 0) {\n      ctx.bezierCurveTo(x + K * bl, y + h, x, y + h - K * bl, x, y + h - bl);\n    } else {\n      ctx.lineTo(x, y + h);\n    }\n    ctx.lineTo(x, y + tl);\n    if (tl > 0) {\n      ctx.bezierCurveTo(x, y + K * tl, x + K * tl, y, x + tl, y);\n    } else {\n      ctx.lineTo(x, y);\n    }\n    ctx.closePath();\n    this._renderPaintInOrder(ctx);\n  };\n}\n\nexport function applyLinkedCornerRadius(\n  obj: {\n    set: (p: Record<string, unknown>) => void;\n    setCoords?: () => void;\n    dirty?: boolean;\n    type?: string;\n  },\n  radius: number,\n): void {\n  const r = Math.max(0, Math.round(radius));\n  installIndependentCornerRender(obj);\n  obj.set({\n    rx: r,\n    ry: r,\n    weCornersLinked: true,\n    weCornerRadii: uniformCornerRadii(r),\n  });\n  obj.dirty = true;\n  obj.setCoords?.();\n}\n\nexport function applyIndependentCornerRadii(\n  obj: {\n    set: (p: Record<string, unknown>) => void;\n    setCoords?: () => void;\n    dirty?: boolean;\n    type?: string;\n  },\n  radii: CornerRadii,\n): void {\n  const next = {\n    tl: Math.max(0, Math.round(radii.tl)),\n    tr: Math.max(0, Math.round(radii.tr)),\n    br: Math.max(0, Math.round(radii.br)),\n    bl: Math.max(0, Math.round(radii.bl)),\n  };\n  installIndependentCornerRender(obj);\n  // Zero rx/ry so default render path is unused while unlinked.\n  obj.set({\n    rx: 0,\n    ry: 0,\n    weCornersLinked: false,\n    weCornerRadii: next,\n  });\n  obj.dirty = true;\n  obj.setCoords?.();\n}\n", "import React from 'react';\n\nexport type ButtonVariant = 'accent' | 'primary' | 'secondary' | 'danger' | 'ghost' | 'outline';\nexport type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'icon';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n  variant?: ButtonVariant;\n  size?: ButtonSize;\n  loading?: boolean;\n  icon?: React.ReactNode;\n}\n\nconst variantCls: Record<ButtonVariant, string> = {\n  /** Feature-mode CTA \u2014 follows `--we-accent*` (never brand primary hex). */\n  accent:\n    'bg-[var(--we-accent)] text-white hover:bg-[var(--we-accent-hover)] shadow-lg shadow-[color-mix(in_srgb,var(--we-accent)_25%,transparent)]',\n  /** @deprecated use `accent` \u2014 alias kept for gradual migration */\n  primary:\n    'bg-[var(--we-accent)] text-white hover:bg-[var(--we-accent-hover)] shadow-lg shadow-[color-mix(in_srgb,var(--we-accent)_25%,transparent)]',\n  secondary:\n    'bg-surface-tertiary hover:bg-black-stroke text-ink-primary border border-panel-border',\n  danger: 'bg-red-600 hover:bg-red-500 text-white shadow-lg shadow-red-600/20',\n  ghost: 'bg-transparent hover:bg-surface-tertiary/80 text-ink-secondary hover:text-ink-primary',\n  outline:\n    'bg-transparent border border-panel-border text-ink-primary hover:bg-surface-tertiary',\n};\n\nconst sizeCls: Record<ButtonSize, string> = {\n  xs: 'h-7 px-2.5 text-xs gap-1 rounded-lg',\n  sm: 'h-8 px-3 text-xs gap-1.5 rounded-lg',\n  md: 'h-9 px-4 text-sm gap-2 rounded-lg',\n  lg: 'h-10 px-5 text-base gap-2 rounded-lg',\n  icon: 'h-8 w-8 rounded-lg',\n};\n\nexport const Button: React.FC<ButtonProps> = ({\n  children,\n  variant = 'secondary',\n  size = 'md',\n  loading = false,\n  icon,\n  className = '',\n  disabled,\n  ...props\n}) => {\n  const base =\n    'inline-flex shrink-0 items-center justify-center font-semibold transition-all duration-150 active:scale-95 disabled:opacity-50 disabled:pointer-events-none select-none';\n\n  return (\n    <button\n      type=\"button\"\n      className={`${base} ${variantCls[variant]} ${sizeCls[size]} ${className}`}\n      disabled={loading || disabled}\n      aria-busy={loading || undefined}\n      {...props}\n    >\n      {loading ? (\n        <svg\n          className=\"h-4 w-4 shrink-0 animate-spin text-current\"\n          fill=\"none\"\n          viewBox=\"0 0 24 24\"\n          aria-hidden\n        >\n          <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n          <path\n            className=\"opacity-75\"\n            fill=\"currentColor\"\n            d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n          />\n        </svg>\n      ) : icon ? (\n        <span className=\"shrink-0\">{icon}</span>\n      ) : null}\n      {children}\n    </button>\n  );\n};\n", "import React from 'react';\nimport { Button, type ButtonProps } from '../Button/Button';\n\nexport interface IconButtonProps extends Omit<ButtonProps, 'size' | 'children'> {\n  /** Accessible name (also used as title). */\n  label: string;\n  active?: boolean;\n  size?: 'sm' | 'md';\n  children: React.ReactNode;\n}\n\n/**\n * Atom \u2014 square icon-only control (back arrow, hamburger, play, +).\n * Active: solid feature DEFAULT (`--we-accent` = `feature.*.DEFAULT` in\n * tailwind.config.js) with white icon.\n */\nexport const IconButton: React.FC<IconButtonProps> = ({\n  label,\n  active = false,\n  size = 'md',\n  variant = 'ghost',\n  className = '',\n  children,\n  ...props\n}) => {\n  const dim = size === 'sm' ? 'h-7 w-7' : 'h-8 w-8';\n  // `!` beats ghost `text-ink-secondary` / transparent bg from Button variant.\n  const activeCls = active\n    ? '!bg-[var(--we-accent)] !text-white hover:!bg-[var(--we-accent-hover)] hover:!text-white'\n    : '';\n\n  return (\n    <Button\n      variant={variant}\n      size=\"icon\"\n      aria-label={label}\n      title={label}\n      aria-pressed={active}\n      className={`${dim} ${activeCls} ${className}`}\n      {...props}\n    >\n      {children}\n    </Button>\n  );\n};\n", "import React from 'react';\n\nexport interface HamburgerIconProps {\n  open: boolean;\n  className?: string;\n  size?: number;\n}\n\n/**\n * Atom \u2014 animated 3-line \u2194 X.\n * Closed bars use equal vertical rhythm (centers at 22% / 50% / 78%).\n */\nexport const HamburgerIcon: React.FC<HamburgerIconProps> = ({\n  open,\n  className = '',\n  size = 18,\n}) => {\n  const bar =\n    'absolute left-0 right-0 h-[2px]  bg-current transition-all duration-200 ease-out origin-center';\n\n  return (\n    <span\n      className={`relative inline-block ${className}`}\n      style={{ width: size, height: size }}\n      aria-hidden\n    >\n      <span\n        className={bar}\n        style={{\n          top: open ? '50%' : '22%',\n          transform: open ? 'translateY(-50%) rotate(45deg)' : 'translateY(-50%)',\n        }}\n      />\n      <span\n        className={bar}\n        style={{\n          top: '50%',\n          transform: 'translateY(-50%)',\n          opacity: open ? 0 : 1,\n        }}\n      />\n      <span\n        className={bar}\n        style={{\n          top: open ? '50%' : '78%',\n          transform: open ? 'translateY(-50%) rotate(-45deg)' : 'translateY(-50%)',\n        }}\n      />\n    </span>\n  );\n};\n", "import React from 'react';\n\nexport type TextTitleAs = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'p' | 'span' | 'label';\nexport type TextTitleSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport interface TextTitleProps {\n  children: React.ReactNode;\n  /** Semantic/HTML element. Default `h3`. */\n  as?: TextTitleAs;\n  /**\n   * Display size (Space Grotesk).\n   * xs=12 \u00B7 sm=14 \u00B7 md=16 \u00B7 lg=18 \u00B7 xl=20\n   */\n  size?: TextTitleSize;\n  /** Extra Tailwind classes (color, tracking, uppercase, truncate, \u2026). */\n  className?: string;\n  /** Allow selecting the text. Default false (chrome titles). */\n  selectable?: boolean;\n  id?: string;\n  title?: string;\n}\n\nconst sizeCls: Record<TextTitleSize, string> = {\n  xs: 'text-xs',\n  sm: 'text-sm',\n  md: 'text-base',\n  lg: 'text-lg',\n  xl: 'text-xl',\n};\n\n/**\n * Atom \u2014 chrome title / section heading.\n * Always Space Grotesk (`font-display`). Prefer this over raw `<div>`/`<h*>` text.\n */\nexport const TextTitle: React.FC<TextTitleProps> = ({\n  children,\n  as: Tag = 'h3',\n  size = 'sm',\n  className = '',\n  selectable = false,\n  id,\n  title,\n}) => (\n  <Tag\n    id={id}\n    title={title}\n    className={[\n      'font-display font-bold text-white',\n      selectable ? '' : 'select-none',\n      sizeCls[size],\n      className,\n    ]\n      .filter(Boolean)\n      .join(' ')}\n  >\n    {children}\n  </Tag>\n);\n", "import React from 'react';\n\nexport type TextBodyAs = 'p' | 'span' | 'label' | 'li' | 'div';\n/**\n * Quicksand body size \u2014 clamped to 12\u201316px (design rule).\n * sm=12 \u00B7 md=14 \u00B7 lg=16\n */\nexport type TextBodySize = 'sm' | 'md' | 'lg';\n\nexport type TextBodyProps = {\n  children?: React.ReactNode;\n  /** Semantic/HTML element. Default `p`. Prefer `span` inside buttons/rows. */\n  as?: TextBodyAs;\n  /** Body size. Default `sm` (12px). Never below 12 or above 16. */\n  size?: TextBodySize;\n  /** Extra Tailwind classes (color, truncate, leading, \u2026). Weight stays medium. */\n  className?: string;\n  /** Allow selecting the text. Default false for static chrome copy. */\n  selectable?: boolean;\n  id?: string;\n  title?: string;\n  htmlFor?: string;\n  dangerouslySetInnerHTML?: { __html: string };\n};\n\nconst sizeCls: Record<TextBodySize, string> = {\n  sm: 'text-xs', // 12px\n  md: 'text-sm', // 14px\n  lg: 'text-base', // 16px\n};\n\n/**\n * Atom \u2014 chrome body / paragraph / label copy.\n * Always Quicksand (`font-sans`) at **medium (500)**. Size clamped 12\u201316px.\n * Do not put raw UI strings inside bare `<div>` \u2014 use this (or TextTitle).\n */\nexport const TextBody: React.FC<TextBodyProps> = ({\n  children,\n  as: Tag = 'p',\n  size = 'sm',\n  className = '',\n  selectable = false,\n  id,\n  title,\n  htmlFor,\n  dangerouslySetInnerHTML,\n}) => (\n  <Tag\n    id={id}\n    title={title}\n    {...(Tag === 'label' && htmlFor ? { htmlFor } : {})}\n    {...(dangerouslySetInnerHTML ? { dangerouslySetInnerHTML } : {})}\n    className={[\n      'font-sans font-medium',\n      selectable ? '' : 'select-none',\n      sizeCls[size],\n      className,\n    ]\n      .filter(Boolean)\n      .join(' ')}\n  >\n    {dangerouslySetInnerHTML ? undefined : children}\n  </Tag>\n);\n", "import React from 'react';\nimport { Download } from 'lucide-react';\nimport { Button, type ButtonProps } from '../../atoms/Button/Button';\nimport { TextBody } from '../../atoms/TextBody/TextBody';\nimport { useTranslation } from '../../../../i18n';\n\nexport interface ExportButtonProps\n  extends Omit<ButtonProps, 'variant' | 'size' | 'icon' | 'children'> {\n  /** Override label (defaults to i18n toolbar.common.export). */\n  label?: string;\n  /** Shown as title when disabled without handler. */\n  unavailableTitle?: string;\n}\n\n/**\n * Molecule \u2014 primary Export CTA for shell / toolbars.\n * Uses the active mode feature accent (`--we-accent`).\n */\nexport const ExportButton: React.FC<ExportButtonProps> = ({\n  label,\n  unavailableTitle,\n  disabled,\n  className = '',\n  title,\n  ...props\n}) => {\n  const t = useTranslation();\n  const text = label ?? t.toolbar.common.export;\n  const tip =\n    title ??\n    (disabled\n      ? unavailableTitle ?? t.toolbar.common.exportNotAvailable\n      : text);\n\n  return (\n    <Button\n      variant=\"accent\"\n      size=\"xs\"\n      icon={<Download size={13} />}\n      disabled={disabled}\n      title={tip}\n      className={`whitespace-nowrap px-4 ${className}`}\n      {...props}\n    >\n      <TextBody as=\"span\" size=\"sm\">\n        {text}\n      </TextBody>\n    </Button>\n  );\n};\n", "import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { RotateCcw } from 'lucide-react';\nimport { IconButton } from '../../atoms/IconButton/IconButton';\nimport { TextBody } from '../../atoms/TextBody/TextBody';\n\nexport type PanelFieldVariant = 'normal' | 'slide' | 'ghost';\n\nexport interface PanelFieldProps {\n  /** Left-side label */\n  label: string;\n  variant?: PanelFieldVariant;\n  /** Displayed on the right for normal/slide (overridden by trailing in normal). */\n  value?: string | number;\n  /** normal: custom right slot (switch, swatch, chevron value). */\n  trailing?: React.ReactNode;\n  /** slide only */\n  min?: number;\n  max?: number;\n  step?: number;\n  numericValue?: number;\n  onChange?: (next: number) => void;\n  /** slide: fired once when pointer scrub ends (history commit). */\n  onCommit?: () => void;\n  /**\n   * slide: when set, shows a reset IconButton to the right of the row.\n   * Disabled while `numericValue` matches this default (within half step).\n   */\n  defaultValue?: number;\n  /** Accessible label for the reset control (required for a11y when defaultValue is set). */\n  resetLabel?: string;\n  /** Format right-hand number for slide (default String). */\n  formatValue?: (n: number) => string;\n  /** Allow typing the value on the right (slide). Default true. */\n  editable?: boolean;\n  className?: string;\n  disabled?: boolean;\n  onClick?: () => void;\n}\n\nconst rowBase =\n  'relative flex items-center w-full min-h-9 rounded-xl select-none transition-colors font-sans';\n\nfunction nearEqual(a: number, b: number, step: number): boolean {\n  const eps = Math.max(Math.abs(step) / 2, 1e-6);\n  return Math.abs(a - b) <= eps;\n}\n\n/**\n * Molecule \u2014 full-width property row for side panels.\n * Styling is Tailwind-only. The slide fill width is the sole exception\n * (runtime % cannot be expressed as a static utility).\n */\nexport const PanelField: React.FC<PanelFieldProps> = ({\n  label,\n  variant = 'normal',\n  value,\n  trailing,\n  min = 0,\n  max = 100,\n  step = 1,\n  numericValue = 0,\n  onChange,\n  onCommit,\n  defaultValue,\n  resetLabel = 'Reset',\n  formatValue,\n  editable = true,\n  className = '',\n  disabled = false,\n  onClick,\n}) => {\n  const trackRef = useRef<HTMLDivElement | null>(null);\n  const dragging = useRef(false);\n  // Local value while scrubbing so the fill tracks the pointer even if the\n  // parent onChange path (canvas/history) is heavy.\n  const [dragValue, setDragValue] = useState<number | null>(null);\n\n  const clamp = useCallback(\n    (n: number) => {\n      const snapped = Math.round(n / step) * step;\n      return Math.min(max, Math.max(min, snapped));\n    },\n    [min, max, step],\n  );\n\n  const valueFromClientX = useCallback(\n    (clientX: number) => {\n      const el = trackRef.current;\n      if (!el) return numericValue;\n      const rect = el.getBoundingClientRect();\n      const t = rect.width <= 0 ? 0 : (clientX - rect.left) / rect.width;\n      return clamp(min + t * (max - min));\n    },\n    [clamp, min, max, numericValue],\n  );\n\n  useEffect(() => {\n    if (!dragging.current) setDragValue(null);\n  }, [numericValue]);\n\n  const onPointerDown = (e: React.PointerEvent) => {\n    if (disabled || variant !== 'slide' || !onChange) return;\n    if ((e.target as HTMLElement).closest('input')) return;\n    dragging.current = true;\n    (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n    const next = valueFromClientX(e.clientX);\n    setDragValue(next);\n    onChange(next);\n  };\n\n  const onPointerMove = (e: React.PointerEvent) => {\n    if (!dragging.current || !onChange) return;\n    const next = valueFromClientX(e.clientX);\n    setDragValue(next);\n    onChange(next);\n  };\n\n  const onPointerUp = (e: React.PointerEvent) => {\n    if (!dragging.current) return;\n    dragging.current = false;\n    setDragValue(null);\n    try {\n      (e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId);\n    } catch {\n      // ignore\n    }\n    onCommit?.();\n  };\n\n  if (variant === 'slide') {\n    const shown = dragValue ?? numericValue;\n    const range = max - min || 1;\n    const pct = Math.min(100, Math.max(0, ((shown - min) / range) * 100));\n    const fillPct = pct > 0 ? Math.max(pct, 8) : 0;\n    const display = formatValue ? formatValue(shown) : String(shown);\n    const showReset = defaultValue !== undefined;\n    const isAtDefault = showReset && nearEqual(shown, defaultValue, step);\n\n    const slider = (\n      <div\n        ref={trackRef}\n        role=\"slider\"\n        aria-label={label}\n        aria-valuemin={min}\n        aria-valuemax={max}\n        aria-valuenow={shown}\n        aria-disabled={disabled}\n        onPointerDown={onPointerDown}\n        onPointerMove={onPointerMove}\n        onPointerUp={onPointerUp}\n        onPointerCancel={onPointerUp}\n        className={`${rowBase} group/slide overflow-hidden bg-black-capsule cursor-ew-resize ${\n          disabled ? 'opacity-40 pointer-events-none' : 'hover:bg-black-capsule-hover'\n        } ${showReset ? 'min-w-0 flex-1' : ''} ${className}`}\n      >\n        {/* Mid-track dots at 25 / 50 / 75% */}\n        <div aria-hidden className=\"pointer-events-none absolute top-1/2 left-[25%] z-0 size-0.5 -translate-x-1/2 -translate-y-1/2 rounded-full bg-ink-secondary/55\" />\n        <div aria-hidden className=\"pointer-events-none absolute top-1/2 left-[50%] z-0 size-0.5 -translate-x-1/2 -translate-y-1/2 rounded-full bg-ink-secondary/55\" />\n        <div aria-hidden className=\"pointer-events-none absolute top-1/2 left-[75%] z-0 size-0.5 -translate-x-1/2 -translate-y-1/2 rounded-full bg-ink-secondary/55\" />\n\n        {/* Fill width has no transition \u2014 laggy ease felt like input delay. */}\n        <div\n          aria-hidden\n          className=\"pointer-events-none absolute inset-y-0 left-0 z-1 rounded-xl bg-[var(--we-accent-capsule)] transition-colors duration-150 group-hover/slide:bg-[var(--we-accent)]\"\n          style={{ width: `${fillPct}%` }}\n        />\n\n        <div className=\"relative z-2 flex w-full items-center justify-between gap-2 px-3 py-2\">\n          <TextBody as=\"span\" size=\"sm\" className=\"truncate text-white/80\">\n            {label}\n          </TextBody>\n          {editable && onChange ? (\n            <input\n              type=\"number\"\n              value={shown}\n              min={min}\n              max={max}\n              step={step}\n              disabled={disabled}\n              onChange={(e) => onChange(clamp(parseFloat(e.target.value) || min))}\n              onBlur={() => onCommit?.()}\n              onKeyDown={(e) => {\n                if (e.key === 'Enter') {\n                  (e.target as HTMLInputElement).blur();\n                }\n              }}\n              onClick={(e) => e.stopPropagation()}\n              className=\"w-14 shrink-0 appearance-none border-0 bg-transparent p-0 text-right font-sans text-xs font-medium tabular-nums text-ink-primary focus:outline-none focus:ring-0 [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none\"\n            />\n          ) : (\n            <TextBody as=\"span\" size=\"sm\" className=\"shrink-0 tabular-nums text-ink-primary\">\n              {display}\n            </TextBody>\n          )}\n        </div>\n      </div>\n    );\n\n    if (!showReset) return slider;\n\n    return (\n      <div className=\"flex w-full items-center gap-1.5\">\n        {slider}\n        <IconButton\n          label={resetLabel}\n          size=\"sm\"\n          variant=\"ghost\"\n          disabled={disabled || isAtDefault}\n          className=\"shrink-0 text-white/80 hover:text-ink-primary disabled:text-white/25\"\n          onClick={(e) => {\n            e.stopPropagation();\n            if (defaultValue === undefined || !onChange) return;\n            onChange(clamp(defaultValue));\n            onCommit?.();\n          }}\n        >\n          <RotateCcw className=\"size-3.5\" strokeWidth={2.25} />\n        </IconButton>\n      </div>\n    );\n  }\n\n  const isGhost = variant === 'ghost';\n\n  return (\n    <div\n      role={onClick ? 'button' : undefined}\n      tabIndex={onClick && !disabled ? 0 : undefined}\n      onClick={disabled ? undefined : onClick}\n      onKeyDown={\n        onClick && !disabled\n          ? (e) => {\n              if (e.key === 'Enter' || e.key === ' ') {\n                e.preventDefault();\n                onClick();\n              }\n            }\n          : undefined\n      }\n      className={`${rowBase} gap-2 py-2 ${\n        isGhost\n          ? 'rounded-none bg-transparent px-0'\n          : 'bg-black-capsule px-3'\n      } ${\n        disabled\n          ? 'opacity-40 pointer-events-none'\n          : onClick\n            ? isGhost\n              ? 'cursor-pointer'\n              : 'cursor-pointer hover:bg-black-capsule-hover'\n            : ''\n      } ${className}`}\n    >\n      <TextBody as=\"span\" size=\"sm\" className=\"flex-1 truncate text-left text-white/80\">\n        {label}\n      </TextBody>\n      <div className=\"flex min-w-0 shrink-0 items-center gap-1.5\">\n        {trailing ??\n          (value != null ? (\n            <TextBody as=\"span\" size=\"sm\" className=\"tabular-nums text-ink-primary\">\n              {value}\n            </TextBody>\n          ) : null)}\n      </div>\n    </div>\n  );\n};\n", "import React from 'react';\nimport { TextBody } from '../../atoms/TextBody/TextBody';\nimport { TextTitle } from '../../atoms/TextTitle/TextTitle';\n\nexport interface PanelBodyProps {\n  children: React.ReactNode;\n  className?: string;\n}\n\n/**\n * Molecule \u2014 outer stack for a properties sidebar.\n * Owns the only horizontal/vertical padding (`p-3`) so nested sections\n * never double-pad.\n */\nexport const PanelBody: React.FC<PanelBodyProps> = ({ children, className = '' }) => (\n  <div className={`flex w-full flex-col gap-4 p-3 ${className}`}>{children}</div>\n);\n\nexport interface PanelSectionProps {\n  /** Section title (font-display). Omit for untitled blocks. */\n  title?: string;\n  /** Optional secondary line under the title. */\n  description?: string;\n  /** Right of the title row (badge, switch, etc.). */\n  trailing?: React.ReactNode;\n  children?: React.ReactNode;\n  /** Bottom divider between sections. */\n  divided?: boolean;\n  className?: string;\n}\n\n/**\n * Molecule \u2014 one titled block inside PanelBody.\n * No padding of its own; spacing is `gap-1.5` between title and fields.\n */\nexport const PanelSection: React.FC<PanelSectionProps> = ({\n  title,\n  description,\n  trailing,\n  children,\n  divided = false,\n  className = '',\n}) => (\n  <section\n    className={`flex flex-col gap-1.5 ${\n      divided ? 'border-b border-panel-border pb-4' : ''\n    } ${className}`}\n  >\n    {title || trailing ? (\n      <div className=\"flex items-start justify-between gap-2\">\n        <div className=\"min-w-0 flex flex-col gap-0.5\">\n          {title ? (\n            <TextTitle\n              as=\"h3\"\n              size=\"xs\"\n              className=\"mb-0 uppercase tracking-wider\"\n            >\n              {title}\n            </TextTitle>\n          ) : null}\n          {description ? (\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {description}\n            </TextBody>\n          ) : null}\n        </div>\n        {trailing ? <div className=\"shrink-0\">{trailing}</div> : null}\n      </div>\n    ) : null}\n    {children}\n  </section>\n);\n", "/**\n * Place a fixed menu inside the viewport.\n * Used by Dropdown, submenus, and shell menus (mode / brand).\n */\n\nexport type MenuPrefer = 'below' | 'above' | 'right' | 'left';\n\nexport type PlaceMenuOptions = {\n  trigger: DOMRect;\n  /** Measured menu size (offsetWidth / offsetHeight). */\n  menuWidth: number;\n  menuHeight: number;\n  gap?: number;\n  /** Preferred open direction. Default `below`. */\n  prefer?: MenuPrefer;\n  /** Horizontal align when prefer is below/above. Default `left`. */\n  align?: 'left' | 'right';\n  /** Floor for maxHeight so short menus still scroll. */\n  minMaxHeight?: number;\n};\n\nexport type PlacedMenu = {\n  top: number;\n  left: number;\n  maxHeight: number;\n  placement: MenuPrefer;\n};\n\n/**\n * Compute fixed `top`/`left`/`maxHeight` so the menu stays on-screen.\n * Prefer the requested side; flip when the opposite side has more room.\n */\nexport function placeMenuInViewport(opts: PlaceMenuOptions): PlacedMenu {\n  const gap = opts.gap ?? 8;\n  const prefer = opts.prefer ?? 'below';\n  const align = opts.align ?? 'left';\n  const minMaxHeight = opts.minMaxHeight ?? 120;\n  const vw = window.innerWidth;\n  const vh = window.innerHeight;\n  const tw = Math.max(1, opts.menuWidth);\n  const th = Math.max(1, opts.menuHeight);\n  const rect = opts.trigger;\n\n  if (prefer === 'right' || prefer === 'left') {\n    const spaceRight = vw - rect.right - gap;\n    const spaceLeft = rect.left - gap;\n    const openRight =\n      prefer === 'right'\n        ? spaceRight >= Math.min(tw, 160) || spaceRight >= spaceLeft\n        : spaceLeft < Math.min(tw, 160) && spaceRight > spaceLeft;\n    const placement: MenuPrefer = openRight ? 'right' : 'left';\n    let left = openRight ? rect.right + gap : rect.left - tw - gap;\n    left = Math.max(gap, Math.min(left, vw - tw - gap));\n\n    const maxHeight = Math.max(minMaxHeight, vh - gap * 2);\n    let top = rect.top;\n    if (top + th > vh - gap) {\n      top = Math.max(gap, vh - gap - Math.min(th, maxHeight));\n    }\n    top = Math.max(gap, Math.min(top, vh - gap - Math.min(th, maxHeight)));\n\n    return {\n      top,\n      left,\n      maxHeight: Math.min(maxHeight, vh - top - gap),\n      placement,\n    };\n  }\n\n  // below / above\n  const spaceBelow = vh - rect.bottom - gap;\n  const spaceAbove = rect.top - gap;\n  const need = Math.min(th, 240);\n  const openAbove =\n    prefer === 'above'\n      ? spaceAbove >= need || spaceAbove > spaceBelow\n      : spaceBelow < need && spaceAbove > spaceBelow;\n  const placement: MenuPrefer = openAbove ? 'above' : 'below';\n  const maxAvail = Math.max(minMaxHeight, openAbove ? spaceAbove : spaceBelow);\n  const menuH = Math.min(th, maxAvail);\n\n  let top = openAbove ? rect.top - menuH - 6 : rect.bottom + 6;\n  top = Math.max(gap, Math.min(top, vh - menuH - gap));\n\n  let left = align === 'right' ? rect.right - tw : rect.left;\n  left = Math.max(gap, Math.min(left, vw - tw - gap));\n\n  return {\n    top,\n    left,\n    maxHeight: maxAvail,\n    placement,\n  };\n}\n\n/**\n * Mutate a fixed element's left/top into the viewport (DOM path).\n * Prefer `placeMenuInViewport` when React owns the style.\n */\nexport function clampFixedToViewport(\n  el: HTMLElement,\n  preferredX: number,\n  preferredY: number,\n  margin = 8,\n): { x: number; y: number } {\n  const menuW = el.offsetWidth;\n  const menuH = el.offsetHeight;\n  let x = preferredX;\n  let y = preferredY;\n\n  if (y + menuH > window.innerHeight - margin) {\n    const above = preferredY - menuH;\n    if (above >= margin) y = above;\n  }\n  if (x + menuW > window.innerWidth - margin) {\n    const left = preferredX - menuW;\n    if (left >= margin) x = left;\n  }\n\n  x = Math.max(margin, Math.min(x, window.innerWidth - menuW - margin));\n  y = Math.max(margin, Math.min(y, window.innerHeight - menuH - margin));\n  el.style.left = `${x}px`;\n  el.style.top = `${y}px`;\n  return { x, y };\n}\n", "import { useState, useCallback } from 'react';\n\n/** Convert RGB 0\u2013255 to `#rrggbb`. */\nexport const rgbToHex = (r: number, g: number, b: number): string => {\n  return (\n    '#' +\n    [r, g, b]\n      .map((x) => {\n        const hex = x.toString(16);\n        return hex.length === 1 ? '0' + hex : hex;\n      })\n      .join('')\n  );\n};\n\n/**\n * Sample one pixel from a canvas element at a client (viewport) point.\n * Maps CSS display coords \u2192 backing-store coords (handles zoom + DPR correctly;\n * do not use `devicePixelRatio` alone \u2014 Fabric buffer size may differ).\n */\nexport function sampleCanvasHexAtClient(\n  canvasEl: HTMLCanvasElement,\n  clientX: number,\n  clientY: number,\n): string | null {\n  const rect = canvasEl.getBoundingClientRect();\n  if (rect.width <= 0 || rect.height <= 0) return null;\n\n  const cssX = clientX - rect.left;\n  const cssY = clientY - rect.top;\n  if (cssX < 0 || cssY < 0 || cssX > rect.width || cssY > rect.height) return null;\n\n  const scaleX = canvasEl.width / rect.width;\n  const scaleY = canvasEl.height / rect.height;\n  const px = Math.min(canvasEl.width - 1, Math.max(0, Math.floor(cssX * scaleX)));\n  const py = Math.min(canvasEl.height - 1, Math.max(0, Math.floor(cssY * scaleY)));\n\n  const ctx = canvasEl.getContext('2d', { willReadFrequently: true });\n  if (!ctx) return null;\n\n  try {\n    const data = ctx.getImageData(px, py, 1, 1).data;\n    return rgbToHex(data[0]!, data[1]!, data[2]!);\n  } catch {\n    return null;\n  }\n}\n\nexport const useEyedropper = () => {\n  const [isSupported] = useState(() => 'EyeDropper' in window);\n\n  const openNative = useCallback(async (): Promise<string | null> => {\n    if (isSupported) {\n      try {\n        const eyeDropper = new (window as any).EyeDropper();\n        const result = await eyeDropper.open();\n        return result.sRGBHex;\n      } catch {\n        return null;\n      }\n    }\n    return null;\n  }, [isSupported]);\n\n  return { openNative, isSupported };\n};\n", "import type { CSSProperties, ReactNode } from 'react';\nimport { createContext, createElement, useContext } from 'react';\nimport type { EditorMode } from '../components/editor/EditorModeToggle';\n\n/** Host feature keys that back each studio mode. */\nexport type FeatureKey = 'image' | 'video' | 'presentation' | 'script' | 'audio';\n\nexport const MODE_FEATURE: Record<EditorMode, FeatureKey> = {\n  image: 'image',\n  video: 'video',\n  slides: 'presentation',\n  text: 'script',\n  audio: 'audio',\n};\n\n/** Hex bases (kept in sync with tailwind.config.js feature swatches). */\nexport const FEATURE_HEX: Record<FeatureKey, string> = {\n  image: '#DB2777',\n  video: '#EA580C',\n  presentation: '#A204CA',\n  script: '#0891B2',\n  audio: '#9F1239',\n};\n\n/**\n * CSS custom properties for the active mode accent.\n * Apply on a mode root: style={modeAccentVars(mode)} data-we-mode={mode}\n */\nexport function modeAccentVars(mode: EditorMode): CSSProperties {\n  const feature = MODE_FEATURE[mode];\n  const hex = FEATURE_HEX[feature];\n  return {\n    ['--we-accent' as string]: hex,\n    ['--we-accent-hover' as string]: `color-mix(in srgb, ${hex} 78%, white)`,\n    ['--we-accent-stroke' as string]: `color-mix(in srgb, ${hex} 42%, #404040)`,\n    ['--we-accent-soft' as string]: `color-mix(in srgb, ${hex} 42%, white)`,\n    ['--we-accent-panel' as string]: `color-mix(in srgb, ${hex} 14%, #1a1a1a)`,\n    ['--we-accent-capsule' as string]: `color-mix(in srgb, ${hex} 22%, #363636)`,\n    ['--we-accent-capsule-hover' as string]: `color-mix(in srgb, ${hex} 38%, #616161)`,\n    ['--we-accent-muted' as string]: `color-mix(in srgb, ${hex} 28%, #1a1a1a)`,\n    ['--we-accent-dark' as string]: `color-mix(in srgb, ${hex} 42%, black)`,\n  };\n}\n\nconst ModeAccentContext = createContext<EditorMode>('image');\n\n/** Current studio mode for accent inheritance (portals / modals). */\nexport function useModeAccent(): EditorMode {\n  return useContext(ModeAccentContext);\n}\n\n/**\n * Provides the active mode accent to descendants.\n * Optional `className` wraps children in a node that also sets CSS vars\n * (needed for createPortal roots outside `.we-root`).\n * Uses createElement so this file can stay `.ts` (no JSX).\n */\nexport function ModeAccentProvider({\n  mode,\n  children,\n  className,\n}: {\n  mode: EditorMode;\n  children: ReactNode;\n  className?: string;\n}) {\n  if (className !== undefined) {\n    return createElement(\n      ModeAccentContext.Provider,\n      { value: mode },\n      createElement(\n        'div',\n        { 'data-we-mode': mode, style: modeAccentVars(mode), className },\n        children,\n      ),\n    );\n  }\n  return createElement(ModeAccentContext.Provider, { value: mode }, children);\n}\n\n/** Tailwind text color per mode (tab icons, chips). */\nexport const MODE_ACCENT_TEXT: Record<EditorMode, string> = {\n  image: 'text-feature-image',\n  video: 'text-feature-video',\n  slides: 'text-feature-presentation',\n  text: 'text-feature-script',\n  audio: 'text-feature-audio',\n};\n\nexport const MODE_ACCENT_BG: Record<EditorMode, string> = {\n  image: 'bg-feature-image',\n  video: 'bg-feature-video',\n  slides: 'bg-feature-presentation',\n  text: 'bg-feature-script',\n  audio: 'bg-feature-audio',\n};\n\nexport const MODE_ACCENT_BG_HOVER: Record<EditorMode, string> = {\n  image: 'hover:bg-feature-image-hover',\n  video: 'hover:bg-feature-video-hover',\n  slides: 'hover:bg-feature-presentation-hover',\n  text: 'hover:bg-feature-script-hover',\n  audio: 'hover:bg-feature-audio-hover',\n};\n\n", "import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Pipette } from 'lucide-react';\nimport {\n  hsvToRgb,\n  isNoneCssColor,\n  isValidCssColorInput,\n  parseCssColor,\n  rgbaToCss,\n  rgbaToHex6,\n  rgbToHsv,\n  type RgbaColor,\n} from '../../../../utils/colorRgba';\nimport { clampFixedToViewport } from '../../../../utils/clampFixedToViewport';\nimport { useEyedropper } from '../../../../utils/useEyedropper';\nimport { useTranslation } from '../../../../i18n';\nimport { modeAccentVars, useModeAccent } from '../../../../theme/modeAccent';\nimport { PanelField } from '../PanelField/PanelField';\nimport { TextBody } from '../../atoms/TextBody/TextBody';\n\nexport interface ColorInputProps {\n  /** Left-side property name (e.g. Relleno, Contorno). */\n  label: string;\n  /** Opacity row label (e.g. Opacidad). */\n  opacityLabel: string;\n  value: string;\n  onChange: (cssColor: string) => void;\n  /** Fired after discrete color edits and when opacity scrub ends. */\n  onCommit?: () => void;\n  disabled?: boolean;\n  className?: string;\n  /**\n   * Fallback when the native EyeDropper API is unavailable:\n   * typically activate the canvas eyedropper tool for this channel.\n   */\n  onCanvasEyedropper?: () => void;\n  /** Hide the pipette control (default: show). */\n  showEyedropper?: boolean;\n}\n\n/**\n * Molecule \u2014 labeled color row (hex + swatch \u2192 in-app picker) with\n * opacity as a PanelField slide underneath. Picker portal is clamped to\n * the viewport like the image canvas context menu.\n */\nexport const ColorInput: React.FC<ColorInputProps> = ({\n  label,\n  opacityLabel,\n  value,\n  onChange,\n  onCommit,\n  disabled = false,\n  className = '',\n  onCanvasEyedropper,\n  showEyedropper = true,\n}) => {\n  const t = useTranslation();\n  const mode = useModeAccent();\n  const isNone = isNoneCssColor(value);\n  const parsed = parseCssColor(isNone ? '#000000' : value);\n  const [text, setText] = useState(() => (isNone ? '' : rgbaToHex6(parsed).toUpperCase()));\n  const { openNative, isSupported } = useEyedropper();\n  const eyedropperLabel = t.canvas.eyedropper.pickColor;\n\n  const [pickerOpen, setPickerOpen] = useState(false);\n  const swatchRef = useRef<HTMLButtonElement | null>(null);\n  const flyoutRef = useRef<HTMLDivElement | null>(null);\n  const [anchor, setAnchor] = useState({ x: 0, y: 0 });\n\n  const hsv = rgbToHsv(parsed.r, parsed.g, parsed.b);\n  const [hue, setHue] = useState(hsv.h);\n  const [sat, setSat] = useState(hsv.s);\n  const [val, setVal] = useState(hsv.v);\n  const svRef = useRef<HTMLDivElement | null>(null);\n  const draggingSv = useRef(false);\n\n  useEffect(() => {\n    if (isNoneCssColor(value)) {\n      setText('');\n      return;\n    }\n    setText(rgbaToHex6(parseCssColor(value)).toUpperCase());\n  }, [value]);\n\n  useLayoutEffect(() => {\n    if (!pickerOpen) return;\n    const el = flyoutRef.current;\n    if (!el) return;\n    clampFixedToViewport(el, anchor.x, anchor.y, 8);\n  }, [pickerOpen, anchor.x, anchor.y, hue, sat, val]);\n\n  useEffect(() => {\n    if (!pickerOpen) return;\n    const onPointer = (e: PointerEvent) => {\n      const target = e.target as Node;\n      if (flyoutRef.current?.contains(target) || swatchRef.current?.contains(target)) return;\n      setPickerOpen(false);\n      onCommit?.();\n    };\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') {\n        setPickerOpen(false);\n        onCommit?.();\n      }\n    };\n    const onResize = () => {\n      const el = flyoutRef.current;\n      if (!el) return;\n      clampFixedToViewport(el, anchor.x, anchor.y, 8);\n    };\n    document.addEventListener('pointerdown', onPointer);\n    document.addEventListener('keydown', onKey);\n    window.addEventListener('resize', onResize);\n    return () => {\n      document.removeEventListener('pointerdown', onPointer);\n      document.removeEventListener('keydown', onKey);\n      window.removeEventListener('resize', onResize);\n    };\n  }, [pickerOpen, anchor.x, anchor.y, onCommit]);\n\n  const commitText = (raw: string) => {\n    const trimmed = raw.trim();\n    if (!trimmed || /^(none|transparent|transparente)$/i.test(trimmed)) {\n      onChange('transparent');\n      setText('');\n      onCommit?.();\n      return;\n    }\n    if (!isValidCssColorInput(trimmed)) {\n      setText(isNone ? '' : rgbaToHex6(parseCssColor(value)).toUpperCase());\n      return;\n    }\n    const next = parseCssColor(trimmed, parsed);\n    onChange(rgbaToCss({ ...next, a: parsed.a }));\n    setText(rgbaToHex6(next).toUpperCase());\n    onCommit?.();\n  };\n\n  const applyHsv = (h: number, s: number, v: number, commit = false) => {\n    const rgb = hsvToRgb(h, s, v);\n    const next: RgbaColor = { ...rgb, a: parsed.a };\n    onChange(rgbaToCss(next));\n    setText(rgbaToHex6(next).toUpperCase());\n    if (commit) onCommit?.();\n  };\n\n  const setRgb = (hex6: string) => {\n    const rgb = parseCssColor(hex6, parsed);\n    const next: RgbaColor = { ...rgb, a: parsed.a };\n    onChange(rgbaToCss(next));\n    setText(rgbaToHex6(next).toUpperCase());\n    onCommit?.();\n  };\n\n  const setAlpha = (a01: number) => {\n    onChange(rgbaToCss({ ...parsed, a: a01 }));\n  };\n\n  const pickWithEyedropper = async () => {\n    if (disabled) return;\n    if (isSupported) {\n      const hex = await openNative();\n      if (hex) setRgb(hex);\n      return;\n    }\n    onCanvasEyedropper?.();\n  };\n\n  const openPicker = () => {\n    if (disabled) return;\n    const rect = swatchRef.current?.getBoundingClientRect();\n    if (rect) {\n      setAnchor({ x: rect.left, y: rect.bottom + 8 });\n    }\n    const next = rgbToHsv(parsed.r, parsed.g, parsed.b);\n    setHue(next.h);\n    setSat(next.s);\n    setVal(next.v);\n    setPickerOpen(true);\n  };\n\n  const svFromClient = (clientX: number, clientY: number) => {\n    const el = svRef.current;\n    if (!el) return;\n    const rect = el.getBoundingClientRect();\n    const s = Math.min(1, Math.max(0, (clientX - rect.left) / Math.max(1, rect.width)));\n    const v = Math.min(1, Math.max(0, 1 - (clientY - rect.top) / Math.max(1, rect.height)));\n    setSat(s);\n    setVal(v);\n    applyHsv(hue, s, v);\n  };\n\n  const hueColor = hsvToRgb(hue, 1, 1);\n  const hueCss = `rgb(${hueColor.r}, ${hueColor.g}, ${hueColor.b})`;\n  const alphaPct = Math.round(parsed.a * 100);\n  const swatchCss = `rgba(${parsed.r}, ${parsed.g}, ${parsed.b}, ${parsed.a})`;\n  const hex6 = rgbaToHex6(parsed);\n\n  const picker =\n    pickerOpen && typeof document !== 'undefined'\n      ? createPortal(\n          <div\n            ref={flyoutRef}\n            role=\"dialog\"\n            aria-label={`${label} picker`}\n            data-we-mode={mode}\n            // Runtime position \u2014 clampFixedToViewport writes left/top before paint.\n            style={{\n              ...modeAccentVars(mode),\n              position: 'fixed',\n              left: anchor.x,\n              top: anchor.y,\n              zIndex: 220,\n            }}\n            className=\"w-[220px] rounded-2xl border border-panel-border bg-panel p-3 shadow-2xl shadow-black/60 backdrop-blur-md\"\n            onPointerDown={(e) => e.stopPropagation()}\n          >\n            <div\n              ref={svRef}\n              className=\"relative h-[140px] w-full cursor-crosshair overflow-hidden rounded-xl\"\n              // Dual-layer HSV square needs runtime hue color.\n              style={{\n                backgroundImage: `linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, ${hueCss})`,\n              }}\n              onPointerDown={(e) => {\n                draggingSv.current = true;\n                (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n                svFromClient(e.clientX, e.clientY);\n              }}\n              onPointerMove={(e) => {\n                if (!draggingSv.current) return;\n                svFromClient(e.clientX, e.clientY);\n              }}\n              onPointerUp={(e) => {\n                if (!draggingSv.current) return;\n                draggingSv.current = false;\n                try {\n                  (e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId);\n                } catch {\n                  // ignore\n                }\n                onCommit?.();\n              }}\n            >\n              <span\n                aria-hidden\n                className=\"pointer-events-none absolute size-3.5 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white shadow-md\"\n                style={{ left: `${sat * 100}%`, top: `${(1 - val) * 100}%` }}\n              />\n            </div>\n\n            <label className=\"mt-3 flex flex-col gap-1.5\">\n              <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                {t.videoEditor.colorGrading.hslHue}\n              </TextBody>\n              <input\n                type=\"range\"\n                min={0}\n                max={360}\n                step={1}\n                value={Math.round(hue)}\n                onChange={(e) => {\n                  const h = Number(e.target.value);\n                  setHue(h);\n                  applyHsv(h, sat, val);\n                }}\n                onPointerUp={() => onCommit?.()}\n                className=\"h-2 w-full cursor-pointer appearance-none rounded-full\"\n                style={{\n                  background:\n                    'linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00)',\n                }}\n              />\n            </label>\n\n            <div className=\"mt-3 flex items-center gap-2\">\n              <span\n                aria-hidden\n                className=\"size-7 shrink-0 rounded-md border border-panel-border\"\n                style={{ backgroundColor: hex6 }}\n              />\n              <input\n                type=\"text\"\n                aria-label={label}\n                value={text}\n                onChange={(e) => setText(e.target.value)}\n                onBlur={() => commitText(text)}\n                onKeyDown={(e) => {\n                  if (e.key === 'Enter') {\n                    commitText(text);\n                    (e.target as HTMLInputElement).blur();\n                  }\n                }}\n                spellCheck={false}\n                className=\"min-w-0 flex-1 rounded-lg border-0 bg-black-capsule px-2.5 py-1.5 text-[11px] font-medium uppercase tabular-nums text-ink-primary focus:outline-none focus:ring-1 focus:ring-[var(--we-accent)]\"\n              />\n            </div>\n          </div>,\n          document.body,\n        )\n      : null;\n\n  return (\n    <div className={`flex w-full flex-col gap-1.5 ${className}`}>\n      <div\n        className={`flex min-h-9 w-full items-center justify-between gap-2 rounded-xl bg-black-capsule px-3 py-2 ${\n          disabled ? 'pointer-events-none opacity-40' : ''\n        }`}\n      >\n        <TextBody as=\"span\" size=\"sm\" className=\"min-w-0 flex-1 truncate text-left text-white/80\">\n          {label}\n        </TextBody>\n        <div className=\"flex shrink-0 items-center gap-1.5\">\n          <input\n            type=\"text\"\n            aria-label={label}\n            disabled={disabled}\n            value={text}\n            placeholder={isNone ? t.panel.transparent : undefined}\n            onChange={(e) => setText(e.target.value)}\n            onBlur={() => commitText(text)}\n            onKeyDown={(e) => {\n              if (e.key === 'Enter') {\n                commitText(text);\n                (e.target as HTMLInputElement).blur();\n              }\n            }}\n            spellCheck={false}\n            className=\"w-[5.5rem] border-0 bg-transparent p-0 text-right text-[11px] font-medium uppercase tabular-nums text-ink-primary placeholder:normal-case placeholder:text-white/50 focus:outline-none focus:ring-0\"\n          />\n          {showEyedropper ? (\n            <button\n              type=\"button\"\n              title={eyedropperLabel}\n              aria-label={eyedropperLabel}\n              disabled={disabled || (!isSupported && !onCanvasEyedropper)}\n              onClick={() => void pickWithEyedropper()}\n              className=\"flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-md text-white/80 transition-colors hover:bg-black-capsule-hover hover:text-[var(--we-accent)] disabled:cursor-not-allowed disabled:opacity-40\"\n            >\n              <Pipette size={13} strokeWidth={2.25} aria-hidden />\n            </button>\n          ) : null}\n          <button\n            ref={swatchRef}\n            type=\"button\"\n            aria-label={`${label} picker`}\n            aria-expanded={pickerOpen}\n            disabled={disabled}\n            onClick={openPicker}\n            className=\"relative size-6 shrink-0 overflow-hidden rounded-md border border-panel-border\"\n          >\n            <span\n              aria-hidden\n              className=\"absolute inset-0\"\n              style={{\n                backgroundImage:\n                  'linear-gradient(45deg, #404040 25%, transparent 25%), linear-gradient(-45deg, #404040 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #404040 75%), linear-gradient(-45deg, transparent 75%, #404040 75%)',\n                backgroundSize: '8px 8px',\n                backgroundPosition: '0 0, 0 4px, 4px -4px, -4px 0',\n              }}\n            />\n            <span aria-hidden className=\"absolute inset-0\" style={{ backgroundColor: swatchCss }} />\n          </button>\n        </div>\n      </div>\n\n      <PanelField\n        variant=\"slide\"\n        label={opacityLabel}\n        min={0}\n        max={100}\n        step={1}\n        numericValue={alphaPct}\n        formatValue={(n) => `${n}%`}\n        disabled={disabled}\n        onChange={(pct) => setAlpha(pct / 100)}\n        onCommit={onCommit}\n      />\n\n      {picker}\n    </div>\n  );\n};\n", "import React from 'react';\nimport { Lock, Unlock } from 'lucide-react';\n\nexport interface AspectLockGroupProps {\n  /** Width / height (or any paired) fields \u2014 typically two PanelFields. */\n  children: React.ReactNode;\n  locked: boolean;\n  onLockedChange: (locked: boolean) => void;\n  lockLabel: string;\n  unlockLabel: string;\n  className?: string;\n}\n\n/**\n * Molecule \u2014 pairs two size rows with an aspect-ratio lock on the right.\n * L-shaped guides (\u2310 / \u231E) connect each row to the lock.\n */\nexport const AspectLockGroup: React.FC<AspectLockGroupProps> = ({\n  children,\n  locked,\n  onLockedChange,\n  lockLabel,\n  unlockLabel,\n  className = '',\n}) => {\n  const label = locked ? unlockLabel : lockLabel;\n\n  return (\n    <div className={`flex items-stretch gap-0.5 ${className}`}>\n      <div className=\"flex min-w-0 flex-1 flex-col gap-1.5\">{children}</div>\n\n      <div className=\"relative w-8 shrink-0 self-stretch\">\n        {/* Top L \u2192 lock */}\n        <div\n          aria-hidden\n          className=\"pointer-events-none absolute left-0 top-[20%] h-[28%] w-3.5 rounded-tr-[3px] border-t border-r border-white/40\"\n        />\n        {/* Bottom L \u2192 lock */}\n        <div\n          aria-hidden\n          className=\"pointer-events-none absolute bottom-[20%] left-0 h-[28%] w-3.5 rounded-br-[3px] border-b border-r border-white/40\"\n        />\n\n        <button\n          type=\"button\"\n          aria-pressed={locked}\n          aria-label={label}\n          title={label}\n          onClick={() => onLockedChange(!locked)}\n          className={`absolute left-1/2 top-1/2 z-10 flex size-6 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-md transition-colors ${\n            locked\n              ? 'bg-[var(--we-accent-capsule)] text-[var(--we-accent)] hover:bg-[var(--we-accent-capsule-hover)]'\n              : 'bg-black-capsule text-white/50 hover:bg-black-capsule-hover hover:text-white'\n          }`}\n        >\n          {locked ? <Lock size={12} strokeWidth={2.25} /> : <Unlock size={12} strokeWidth={2.25} />}\n        </button>\n      </div>\n    </div>\n  );\n};\n", "/** Shared canvas size presets (social / web / print). */\nexport const CATEGORIZED_PRESETS = {\n  social: [\n    { name: 'Instagram Post', nameKey: 'instagramPost', width: 1080, height: 1080, desc: '1:1 Cuadrado', descKey: 'square1_1', icon: 'square' },\n    { name: 'Instagram Story', nameKey: 'instagramStory', width: 1080, height: 1920, desc: '9:16 Vertical', descKey: 'portrait9_16', icon: 'portrait' },\n    { name: 'YouTube Thumbnail', nameKey: 'youtubeThumbnail', width: 1280, height: 720, desc: '16:9 Miniatura', descKey: 'landscape16_9', icon: 'landscape' },\n    { name: 'YouTube Banner', nameKey: 'youtubeBanner', width: 2560, height: 1440, desc: '16:9 Banner', descKey: 'landscape16_9Banner', icon: 'landscape' },\n  ],\n  web: [\n    { name: 'Full HD Desktop', nameKey: 'fullHdDesktop', width: 1920, height: 1080, desc: '16:9 Monitor', descKey: 'monitor16_9', icon: 'landscape' },\n    { name: 'MacBook Pro', nameKey: 'macbookPro', width: 1440, height: 900, desc: '16:10 Laptop', descKey: 'laptop16_10', icon: 'landscape' },\n    { name: 'Mobile App Screen', nameKey: 'mobileAppScreen', width: 375, height: 812, desc: 'Pantalla iPhone', descKey: 'iphoneScreen', icon: 'portrait' },\n  ],\n  print: [\n    { name: 'P\u00F3ster A4', nameKey: 'posterA4', width: 794, height: 1123, desc: 'Papel A4 Est\u00E1ndar', descKey: 'a4Standard', icon: 'portrait' },\n    { name: 'Carta / Letter', nameKey: 'cartaLetter', width: 816, height: 1056, desc: 'Papel Carta USA', descKey: 'letterUS', icon: 'portrait' },\n    { name: 'Business Card', nameKey: 'businessCard', width: 336, height: 192, desc: 'Tarjeta Comercial', descKey: 'businessCardDesc', icon: 'landscape' },\n  ],\n} as const;\n\nexport type CanvasSizeUnit = 'px' | 'in' | 'cm' | 'mm';\n\nexport function canvasSizeToPx(val: number, unit: CanvasSizeUnit): number {\n  if (unit === 'in') return Math.round(val * 96);\n  if (unit === 'cm') return Math.round(val * 37.795);\n  if (unit === 'mm') return Math.round(val * 3.7795);\n  return Math.round(val);\n}\n\nexport function canvasSizeFromPx(px: number, unit: CanvasSizeUnit): number {\n  if (unit === 'in') return parseFloat((px / 96).toFixed(2));\n  if (unit === 'cm') return parseFloat((px / 37.795).toFixed(2));\n  if (unit === 'mm') return parseFloat((px / 3.7795).toFixed(2));\n  return Math.round(px);\n}\n\n/** Chip / title label for numeric page size in the active unit. */\nexport function formatCanvasSizeLabel(\n  widthPx: number,\n  heightPx: number,\n  unit: CanvasSizeUnit,\n): string {\n  const w = canvasSizeFromPx(widthPx, unit);\n  const h = canvasSizeFromPx(heightPx, unit);\n  return `${w} \u00D7 ${h} ${unit}`;\n}\n", "import React, { useEffect, useId, useLayoutEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { modeAccentVars, useModeAccent } from '../../theme/modeAccent';\nimport { placeMenuInViewport } from '../../utils/clampFixedToViewport';\nimport { TextBody } from './atoms/TextBody/TextBody';\nimport { TextTitle } from './atoms/TextTitle/TextTitle';\n\nexport interface DropdownProps {\n  trigger: React.ReactNode;\n  children: React.ReactNode;\n  open?: boolean;\n  onOpenChange?: (open: boolean) => void;\n  align?: 'left' | 'right';\n  className?: string;\n  menuClassName?: string;\n  /** Accessible name for the menu panel */\n  label?: string;\n}\n\ntype MenuCoords = {\n  top: number;\n  left: number;\n  minWidth: number;\n  maxHeight: number;\n};\n\n/**\n * Controlled/uncontrolled dropdown with click-outside close.\n * Menu is portaled to document.body and clamped to the viewport so it\n * never clips off-screen (modals, scroll panes, narrow viewports).\n */\nexport const Dropdown: React.FC<DropdownProps> = ({\n  trigger,\n  children,\n  open: openProp,\n  onOpenChange,\n  align = 'left',\n  className = '',\n  menuClassName = '',\n  label,\n}) => {\n  const [uncontrolledOpen, setUncontrolledOpen] = useState(false);\n  const open = openProp ?? uncontrolledOpen;\n  const setOpen = (next: boolean) => {\n    onOpenChange?.(next);\n    if (openProp === undefined) setUncontrolledOpen(next);\n  };\n\n  const rootRef = useRef<HTMLDivElement | null>(null);\n  const menuRef = useRef<HTMLDivElement | null>(null);\n  const menuId = useId();\n  const mode = useModeAccent();\n  const [coords, setCoords] = useState<MenuCoords | null>(null);\n\n  useLayoutEffect(() => {\n    if (!open) {\n      setCoords(null);\n      return;\n    }\n    const update = () => {\n      const el = rootRef.current;\n      const menuEl = menuRef.current;\n      if (!el || !menuEl) return;\n      const rect = el.getBoundingClientRect();\n      // Measure real menu size (className may set min-w / content width).\n      const menuWidth = Math.max(menuEl.offsetWidth, rect.width, 160);\n      const menuHeight = Math.max(menuEl.offsetHeight, 1);\n      const placed = placeMenuInViewport({\n        trigger: rect,\n        menuWidth,\n        menuHeight,\n        prefer: 'below',\n        align,\n        gap: 8,\n      });\n      setCoords({\n        top: placed.top,\n        left: placed.left,\n        minWidth: menuWidth,\n        maxHeight: placed.maxHeight,\n      });\n    };\n    update();\n    const raf = requestAnimationFrame(() => {\n      update();\n      requestAnimationFrame(update);\n    });\n    window.addEventListener('resize', update);\n    window.addEventListener('scroll', update, true);\n    return () => {\n      cancelAnimationFrame(raf);\n      window.removeEventListener('resize', update);\n      window.removeEventListener('scroll', update, true);\n    };\n  }, [open, align, children]);\n\n  useEffect(() => {\n    if (!open) return;\n    const onPointer = (e: PointerEvent) => {\n      const t = e.target as Node;\n      if (rootRef.current?.contains(t) || menuRef.current?.contains(t)) return;\n      setOpen(false);\n    };\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') setOpen(false);\n    };\n    document.addEventListener('pointerdown', onPointer);\n    document.addEventListener('keydown', onKey);\n    return () => {\n      document.removeEventListener('pointerdown', onPointer);\n      document.removeEventListener('keydown', onKey);\n    };\n  }, [open]);\n\n  // Keep wheel inside the menu \u2014 portals bubble through the React tree and can\n  // otherwise scroll the timeline / other panels under the overlay.\n  useEffect(() => {\n    if (!open) return;\n    const el = menuRef.current;\n    if (!el) return;\n    const onWheel = (e: WheelEvent) => {\n      e.stopPropagation();\n      const { scrollTop, scrollHeight, clientHeight } = el;\n      const canScroll = scrollHeight > clientHeight + 1;\n      if (!canScroll) {\n        e.preventDefault();\n        return;\n      }\n      const atTop = scrollTop <= 0 && e.deltaY < 0;\n      const atBottom = scrollTop + clientHeight >= scrollHeight - 1 && e.deltaY > 0;\n      if (atTop || atBottom) e.preventDefault();\n    };\n    el.addEventListener('wheel', onWheel, { passive: false });\n    return () => el.removeEventListener('wheel', onWheel);\n  }, [open, coords]);\n\n  const menu =\n    open && typeof document !== 'undefined'\n      ? createPortal(\n          <div\n            ref={menuRef}\n            id={menuId}\n            role=\"menu\"\n            aria-label={label}\n            data-we-mode={mode}\n            style={{\n              ...modeAccentVars(mode),\n              position: 'fixed',\n              top: coords?.top ?? -9999,\n              left: coords?.left ?? 0,\n              minWidth: coords?.minWidth ?? 160,\n              maxHeight: coords?.maxHeight,\n              visibility: coords ? 'visible' : 'hidden',\n              overscrollBehavior: 'contain',\n            }}\n            className={`z-[200] flex max-h-[min(70vh,24rem)] flex-col gap-1 overflow-y-auto overscroll-contain rounded-2xl border border-panel-border bg-panel p-2 shadow-2xl shadow-black/60 backdrop-blur-md animate-fade-in ${menuClassName}`}\n            onWheel={(e) => e.stopPropagation()}\n          >\n            {children}\n          </div>,\n          document.body,\n        )\n      : null;\n\n  return (\n    <div ref={rootRef} className={`relative flex ${className}`}>\n      {React.isValidElement(trigger)\n        ? React.cloneElement(\n            trigger as React.ReactElement<Record<string, unknown>>,\n            {\n              onClick: (e: React.MouseEvent) => {\n                const prev = (trigger as React.ReactElement<{ onClick?: (ev: React.MouseEvent) => void }>).props\n                  .onClick;\n                prev?.(e);\n                setOpen(!open);\n              },\n              'aria-haspopup': 'menu',\n              'aria-expanded': open,\n              'aria-controls': menuId,\n            },\n          )\n        : (\n          <div\n            onClick={() => setOpen(!open)}\n            role=\"button\"\n            tabIndex={0}\n            aria-haspopup=\"menu\"\n            aria-expanded={open}\n            aria-controls={menuId}\n          >\n            {trigger}\n          </div>\n        )}\n      {menu}\n    </div>\n  );\n};\n\nexport interface DropdownItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n  icon?: React.ReactNode;\n  danger?: boolean;\n  /** Optional secondary line under the label. */\n  description?: string;\n}\n\nexport const DropdownItem: React.FC<DropdownItemProps> = ({\n  icon,\n  danger,\n  description,\n  children,\n  className = '',\n  ...props\n}) => (\n  <button\n    type=\"button\"\n    role=\"menuitem\"\n    className={`group/item flex w-full cursor-pointer items-center gap-3 rounded-xl px-2.5 py-2 text-left transition-colors disabled:cursor-not-allowed disabled:opacity-40 ${\n      danger\n        ? 'text-red-400 hover:bg-red-500/10'\n        : 'text-ink-primary hover:bg-white/8'\n    } ${className}`}\n    {...props}\n  >\n    {icon ? (\n      <span\n        className={`flex size-8 shrink-0 items-center justify-center rounded-lg ${\n          danger ? 'bg-red-500/15 text-red-400' : 'bg-black-capsule text-white/80 group-hover/item:text-white'\n        }`}\n      >\n        {icon}\n      </span>\n    ) : null}\n    <span className=\"min-w-0 flex-1\">\n      <TextBody as=\"span\" size=\"md\" className=\"block min-w-0 font-semibold\">\n        {children}\n      </TextBody>\n      {description ? (\n        <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 block truncate text-white/80\">\n          {description}\n        </TextBody>\n      ) : null}\n    </span>\n  </button>\n);\n\nexport const DropdownSection: React.FC<{ children: React.ReactNode; className?: string }> = ({\n  children,\n  className = '',\n}) => (\n  <div className={`px-2.5 pb-1 pt-1.5 ${className}`}>\n    <TextTitle as=\"p\" size=\"xs\" className=\"uppercase tracking-wider\">\n      {children}\n    </TextTitle>\n  </div>\n);\n\nexport const DropdownDivider: React.FC = () => (\n  <div className=\"my-1.5 h-px bg-panel-border\" aria-hidden />\n);\n", "import React, { useState } from 'react';\nimport { Check, ChevronDown } from 'lucide-react';\nimport { Dropdown, DropdownItem } from '../../Dropdown';\nimport { TextBody } from '../../atoms/TextBody/TextBody';\n\nexport type SelectDropdownOption = {\n  value: string;\n  label: string;\n};\n\nexport interface SelectDropdownProps {\n  value: string;\n  options: SelectDropdownOption[];\n  onChange: (value: string) => void;\n  /** Accessible name for the trigger / menu. */\n  ariaLabel?: string;\n  align?: 'left' | 'right';\n  disabled?: boolean;\n  className?: string;\n  /** Compact trigger for PanelField trailing (default). */\n  size?: 'sm' | 'md';\n}\n\n/**\n * Molecule \u2014 custom select (no native `<select>`). Trigger shows current\n * label + chevron; menu uses the shared Dropdown panel.\n */\nexport const SelectDropdown: React.FC<SelectDropdownProps> = ({\n  value,\n  options,\n  onChange,\n  ariaLabel,\n  align = 'right',\n  disabled = false,\n  className = '',\n  size = 'sm',\n}) => {\n  const [open, setOpen] = useState(false);\n  const selected = options.find((o) => o.value === value) ?? options[0];\n  const label = selected?.label ?? value;\n\n  const triggerPad = size === 'sm' ? 'px-2.5 py-1' : 'px-2.5 py-1.5';\n\n  return (\n    <Dropdown\n      open={open}\n      onOpenChange={setOpen}\n      align={align}\n      label={ariaLabel}\n      className={className}\n      menuClassName=\"max-h-64 overflow-y-auto overscroll-contain min-w-[10rem]\"\n      trigger={\n        <button\n          type=\"button\"\n          disabled={disabled}\n          aria-label={ariaLabel}\n          onClick={(e) => e.stopPropagation()}\n          className={`flex w-full items-center justify-between gap-2 ${triggerPad} select-none rounded-lg text-ink-primary transition-colors hover:text-white disabled:cursor-not-allowed disabled:opacity-40`}\n        >\n          <TextBody as=\"span\" size=\"sm\" className=\"min-w-0 flex-1 truncate text-left tabular-nums\">\n            {label}\n          </TextBody>\n          <ChevronDown\n            size={size === 'sm' ? 12 : 14}\n            strokeWidth={2.25}\n            className={`ml-0.5 shrink-0 text-white/80 transition-transform duration-150 ${open ? 'rotate-180' : ''}`}\n            aria-hidden\n          />\n        </button>\n      }\n    >\n      {options.map((opt) => {\n        const active = opt.value === value;\n        return (\n          <DropdownItem\n            key={opt.value}\n            onClick={(e) => {\n              e.stopPropagation();\n              onChange(opt.value);\n              setOpen(false);\n            }}\n            className={\n              active\n                ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)] hover:bg-[var(--we-accent-muted)]'\n                : ''\n            }\n          >\n            <span className=\"flex w-full items-center justify-between gap-2\">\n              <TextBody as=\"span\" size=\"sm\" className=\"truncate\">\n                {opt.label}\n              </TextBody>\n              {active ? <Check size={12} className=\"shrink-0\" strokeWidth={2.5} aria-hidden /> : null}\n            </span>\n          </DropdownItem>\n        );\n      })}\n    </Dropdown>\n  );\n};\n", "/**\n * Clears persisted floating-panel layouts and notifies open panels so they\n * snap back to their default positions/sizes.\n *\n * Keys covered:\n *  - wizard-draggable-panel-pos:*  (canvas toolstrip panels)\n *  - img-panels-layout-v1          (image edit / layers side panels)\n */\n\nexport const PANEL_POS_STORAGE_PREFIX = 'wizard-draggable-panel-pos:';\nexport const IMG_PANELS_LAYOUT_KEY = 'img-panels-layout-v1';\nexport const PANEL_LAYOUT_RESET_EVENT = 'wizard:reset-panel-layouts';\n\nexport function resetAllPanelLayouts(): number {\n  if (typeof window === 'undefined') return 0;\n\n  let cleared = 0;\n  try {\n    const toRemove: string[] = [];\n    for (let i = 0; i < window.localStorage.length; i++) {\n      const key = window.localStorage.key(i);\n      if (key && key.startsWith(PANEL_POS_STORAGE_PREFIX)) toRemove.push(key);\n    }\n    for (const key of toRemove) {\n      window.localStorage.removeItem(key);\n      cleared += 1;\n    }\n    if (window.localStorage.getItem(IMG_PANELS_LAYOUT_KEY) !== null) {\n      window.localStorage.removeItem(IMG_PANELS_LAYOUT_KEY);\n      cleared += 1;\n    }\n  } catch {\n    // ignore quota / privacy mode\n  }\n\n  window.dispatchEvent(new CustomEvent(PANEL_LAYOUT_RESET_EVENT));\n  return cleared;\n}\n", "import React, {\n  useCallback,\n  useEffect,\n  useLayoutEffect,\n  useRef,\n  useState,\n} from 'react';\nimport { X, RotateCcw } from 'lucide-react';\nimport { useTranslation } from '../i18n';\nimport { PANEL_LAYOUT_RESET_EVENT, PANEL_POS_STORAGE_PREFIX } from '../utils/panelLayoutReset';\nimport { TextTitle } from './ui';\n\ninterface Position {\n  x: number;\n  y: number;\n}\n\ntype DefaultPlacement = 'anchor' | 'center-left';\n\ninterface DraggableToolPanelProps {\n  /** Unique id used to (a) bind aria-labelledby and (b) persist position. */\n  panelId: string;\n  /** Title shown in the panel's draggable header. */\n  title: string;\n  /**\n   * Ref to the anchor button. Used for vertical placement when\n   * `defaultPlacement` is `anchor` (open upward from the anchor).\n   */\n  anchorRef: React.RefObject<HTMLElement | null>;\n  /** Called when the user clicks the close button. */\n  onClose: () => void;\n  /** Optional classes for the content wrapper (between header and bottom). */\n  contentClassName?: string;\n  /**\n   * First-open position when nothing is stored in localStorage.\n   * `center-left` = vertically centered, near the left edge (brush settings).\n   */\n  defaultPlacement?: DefaultPlacement;\n  children: React.ReactNode;\n}\n\nconst STORAGE_KEY_PREFIX = PANEL_POS_STORAGE_PREFIX;\nconst VIEWPORT_MARGIN = 16;\n\nconst loadStoredPos = (panelId: string): Position | null => {\n  if (typeof window === 'undefined') return null;\n  try {\n    const raw = window.localStorage.getItem(STORAGE_KEY_PREFIX + panelId);\n    if (!raw) return null;\n    const parsed = JSON.parse(raw) as Position;\n    if (\n      typeof parsed?.x === 'number' &&\n      typeof parsed?.y === 'number' &&\n      Number.isFinite(parsed.x) &&\n      Number.isFinite(parsed.y)\n    ) {\n      return parsed;\n    }\n  } catch {\n    // ignore malformed entries\n  }\n  return null;\n};\n\nconst persistPos = (panelId: string, pos: Position) => {\n  if (typeof window === 'undefined') return;\n  try {\n    window.localStorage.setItem(STORAGE_KEY_PREFIX + panelId, JSON.stringify(pos));\n  } catch {\n    // ignore quota / privacy mode errors\n  }\n};\n\nconst removeStoredPos = (panelId: string) => {\n  if (typeof window === 'undefined') return;\n  try {\n    window.localStorage.removeItem(STORAGE_KEY_PREFIX + panelId);\n  } catch {\n    // ignore\n  }\n};\n\nconst clampToViewport = (x: number, y: number, w: number, h: number): Position => {\n  const maxX = Math.max(VIEWPORT_MARGIN, window.innerWidth - w - VIEWPORT_MARGIN);\n  const maxY = Math.max(VIEWPORT_MARGIN, window.innerHeight - h - VIEWPORT_MARGIN);\n  return {\n    x: Math.min(Math.max(VIEWPORT_MARGIN, x), maxX),\n    y: Math.min(Math.max(VIEWPORT_MARGIN, y), maxY),\n  };\n};\n\nconst computeDefaultPos = (\n  panel: HTMLElement,\n  anchor: HTMLElement | null,\n  placement: DefaultPlacement,\n): Position => {\n  const pr = panel.getBoundingClientRect();\n\n  if (placement === 'center-left') {\n    const x = VIEWPORT_MARGIN + 12;\n    const y = (window.innerHeight - pr.height) / 2;\n    return clampToViewport(x, y, pr.width, pr.height);\n  }\n\n  // Horizontal: centered on the viewport (T-20260707-11) \u2014 independent of anchor.\n  const x = (window.innerWidth - pr.width) / 2;\n\n  // Vertical: open upward from the anchor. Fallback below when no room.\n  let y = VIEWPORT_MARGIN;\n  if (anchor) {\n    const ar = anchor.getBoundingClientRect();\n    y = ar.top - pr.height - 8;\n    if (y < VIEWPORT_MARGIN) {\n      y = ar.top + ar.height + 8;\n      if (y + pr.height > window.innerHeight - VIEWPORT_MARGIN) {\n        y = window.innerHeight - pr.height - VIEWPORT_MARGIN;\n      }\n    }\n  }\n\n  return clampToViewport(x, y, pr.width, pr.height);\n};\n\nexport const DraggableToolPanel: React.FC<DraggableToolPanelProps> = ({\n  panelId,\n  title,\n  anchorRef,\n  onClose,\n  contentClassName,\n  defaultPlacement = 'anchor',\n  children,\n}) => {\n  const t = useTranslation();\n  const panelRef = useRef<HTMLDivElement>(null);\n  const [pos, setPos] = useState<Position | null>(null);\n  const [isReady, setIsReady] = useState(false);\n  const [hasCustomPos, setHasCustomPos] = useState(false);\n\n  // Compute the initial position BEFORE first paint to avoid flicker.\n  useLayoutEffect(() => {\n    const stored = loadStoredPos(panelId);\n    let next: Position | null = stored;\n    const panel = panelRef.current;\n\n    if (stored && panel) {\n      const pr = panel.getBoundingClientRect();\n      next = clampToViewport(stored.x, stored.y, pr.width, pr.height);\n    } else if (panel) {\n      next = computeDefaultPos(panel, anchorRef.current, defaultPlacement);\n    }\n\n    if (next) setPos(next);\n    setHasCustomPos(!!stored);\n    setIsReady(true);\n  }, [panelId, anchorRef, defaultPlacement]);\n\n  // Persist position changes back to localStorage (only after the very first\n  // paint, so the default position computed in useLayoutEffect is not stored).\n  // Custom-position tracking happens explicitly in drag onUp / handleReset.\n  useEffect(() => {\n    if (!isReady || !pos || !hasCustomPos) return;\n    persistPos(panelId, pos);\n  }, [isReady, panelId, pos, hasCustomPos]);\n\n  const onHeaderMouseDown = useCallback((e: React.MouseEvent) => {\n    // Ignore mousedown that originates from any interactive element so dragging\n    // never steals clicks from controls.\n    if ((e.target as HTMLElement).closest('button, input, select, textarea')) {\n      return;\n    }\n    e.preventDefault();\n\n    const panelEl = panelRef.current;\n    if (!panelEl) return;\n\n    const rect = panelEl.getBoundingClientRect();\n    const startMouseX = e.clientX;\n    const startMouseY = e.clientY;\n    const startLeft = rect.left;\n    const startTop = rect.top;\n\n    const onMove = (ev: MouseEvent) => {\n      const newLeft = startLeft + (ev.clientX - startMouseX);\n      const newTop = startTop + (ev.clientY - startMouseY);\n      // Use direct style writes so dragging stays responsive (no React re-render).\n      panelEl.style.left = `${newLeft}px`;\n      panelEl.style.top = `${newTop}px`;\n      panelEl.style.right = 'auto';\n    };\n\n    const onUp = () => {\n      const final = panelEl.getBoundingClientRect();\n      const clamped = clampToViewport(final.left, final.top, final.width, final.height);\n      panelEl.style.left = `${clamped.x}px`;\n      panelEl.style.top = `${clamped.y}px`;\n      setPos(clamped);\n      // First drag end establishes the panel as \"custom-positioned\".\n      setHasCustomPos(true);\n      document.body.style.userSelect = '';\n      document.body.style.cursor = '';\n      window.removeEventListener('mousemove', onMove);\n      window.removeEventListener('mouseup', onUp);\n    };\n\n    document.body.style.userSelect = 'none';\n    document.body.style.cursor = 'grabbing';\n    window.addEventListener('mousemove', onMove);\n    window.addEventListener('mouseup', onUp);\n  }, []);\n\n  const handleReset = useCallback(() => {\n    const panelEl = panelRef.current;\n    if (!panelEl) return;\n    const next = computeDefaultPos(panelEl, anchorRef.current, defaultPlacement);\n    panelEl.style.left = `${next.x}px`;\n    panelEl.style.top = `${next.y}px`;\n    panelEl.style.right = 'auto';\n    setPos(next);\n    setHasCustomPos(false);\n    removeStoredPos(panelId);\n  }, [panelId, anchorRef, defaultPlacement]);\n\n  // Global \"reset all panels\" from the File menu\n  useEffect(() => {\n    const onGlobalReset = () => handleReset();\n    window.addEventListener(PANEL_LAYOUT_RESET_EVENT, onGlobalReset);\n    return () => window.removeEventListener(PANEL_LAYOUT_RESET_EVENT, onGlobalReset);\n  }, [handleReset]);\n\n  // Until the initial position has been computed, render hidden to avoid a\n  // flash at the top-left of the viewport.\n  const style: React.CSSProperties = pos\n    ? { left: pos.x, top: pos.y, right: 'auto' }\n    : { visibility: 'hidden', left: 0, top: 0 };\n\n  return (\n    <div\n      ref={panelRef}\n      role=\"dialog\"\n      aria-labelledby={`draggable-panel-${panelId}-title`}\n      data-panel-id={panelId}\n      className=\"fixed z-50 flex flex-col bg-panel border-el border-panel-border rounded-panel shadow-2xl shadow-black/60 backdrop-blur-md animate-fade-in\"\n      style={style}\n    >\n      {/* Draggable header \u2014 clicking inside interactive controls does not\n          initiate a drag thanks to the closest('button, input, \u2026') guard. */}\n      <div\n        onMouseDown={onHeaderMouseDown}\n        className=\"flex items-center justify-between px-3 py-1.5 border-b border-panel-border cursor-grab active:cursor-grabbing select-none\"\n      >\n        <TextTitle\n          id={`draggable-panel-${panelId}-title`}\n          as=\"span\"\n          size=\"xs\"\n          className=\"uppercase tracking-wider\"\n        >\n          {title}\n        </TextTitle>\n        <div className=\"flex items-center gap-0.5\">\n          <button\n            type=\"button\"\n            onClick={handleReset}\n            disabled={!hasCustomPos}\n            aria-label={t.draggablePanel.resetAria}\n            title={t.draggablePanel.resetTitle}\n            className={\n              hasCustomPos\n                ? 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] rounded p-0.5 transition-colors'\n                : 'text-white/40 opacity-40 cursor-not-allowed rounded p-0.5'\n            }\n          >\n            <RotateCcw size={12} />\n          </button>\n          <button\n            type=\"button\"\n            onClick={onClose}\n            aria-label={t.draggablePanel.closeAria}\n            title={t.draggablePanel.closeTitle}\n            className=\"text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] rounded p-0.5 transition-colors\"\n          >\n            <X size={13} />\n          </button>\n        </div>\n      </div>\n\n      {/* Content */}\n      <div className={contentClassName ?? ''}>{children}</div>\n    </div>\n  );\n};\n\nDraggableToolPanel.displayName = 'DraggableToolPanel';\n\nexport default DraggableToolPanel;\n\n", "import React, {\n  createContext,\n  useCallback,\n  useContext,\n  useEffect,\n  useMemo,\n  useState,\n} from 'react';\nimport type { EditorBrandOption } from '../types/brand.types';\nimport {\n  getEditorIdentity,\n  hasEditorIdentity,\n  setEditorIdentity,\n} from '../services/identity';\nimport { setActiveEditorBrand } from '../services/activeEditorBrand';\n\nexport type BrandSelectionContextValue = {\n  brand: EditorBrandOption | null;\n  brands: EditorBrandOption[];\n  selectBrand: (next: EditorBrandOption) => void;\n};\n\nconst BrandSelectionContext = createContext<BrandSelectionContextValue | null>(null);\n\nexport type BrandSelectionProviderProps = {\n  brand?: EditorBrandOption | null;\n  brands?: EditorBrandOption[];\n  onBrandChange?: (brand: EditorBrandOption) => void;\n  children: React.ReactNode;\n};\n\nfunction applyBrandToIdentity(next: EditorBrandOption): void {\n  setActiveEditorBrand(next);\n  if (!hasEditorIdentity()) return;\n  const current = getEditorIdentity();\n  if (current.brandId === next.id) return;\n  setEditorIdentity({ ...current, brandId: next.id });\n}\n\nexport function BrandSelectionProvider({\n  brand: brandProp = null,\n  brands: brandsProp = [],\n  onBrandChange,\n  children,\n}: BrandSelectionProviderProps) {\n  const [brand, setBrand] = useState<EditorBrandOption | null>(brandProp ?? null);\n  const [brands, setBrands] = useState<EditorBrandOption[]>(brandsProp);\n\n  useEffect(() => {\n    setBrands(brandsProp);\n  }, [brandsProp]);\n\n  useEffect(() => {\n    // Prefer explicit host/App brand. Never clear a valid selection just\n    // because the host briefly mounts with brand={null}.\n    if (brandProp) {\n      setBrand((prev) =>\n        prev?.id === brandProp.id &&\n        prev.name === brandProp.name &&\n        prev.logoUrl === brandProp.logoUrl\n          ? prev\n          : brandProp,\n      );\n      applyBrandToIdentity(brandProp);\n      return;\n    }\n    if (brandsProp.length === 0) return;\n    setBrand((prev) => {\n      if (!prev) return prev;\n      return brandsProp.find((b) => b.id === prev.id) ?? prev;\n    });\n  }, [brandProp, brandsProp]);\n\n  // Keep AI brand kit in sync even when brand is set only locally (standalone).\n  useEffect(() => {\n    if (brand) setActiveEditorBrand(brand);\n  }, [brand]);\n\n  const selectBrand = useCallback(\n    (next: EditorBrandOption) => {\n      setBrand(next);\n      applyBrandToIdentity(next);\n      onBrandChange?.(next);\n    },\n    [onBrandChange]\n  );\n\n  const value = useMemo(\n    () => ({ brand, brands, selectBrand }),\n    [brand, brands, selectBrand]\n  );\n\n  return (\n    <BrandSelectionContext.Provider value={value}>\n      {children}\n    </BrandSelectionContext.Provider>\n  );\n}\n\nexport function useBrandSelection(): BrandSelectionContextValue {\n  const ctx = useContext(BrandSelectionContext);\n  if (!ctx) {\n    return {\n      brand: null,\n      brands: [],\n      selectBrand: () => undefined,\n    };\n  }\n  return ctx;\n}\n", "export function hexToHsl(hex: string): { h: number; s: number; l: number } {\n  let r = 0, g = 0, b = 0;\n  if (hex.length === 4) {\n    r = parseInt(\"0x\" + hex[1] + hex[1]);\n    g = parseInt(\"0x\" + hex[2] + hex[2]);\n    b = parseInt(\"0x\" + hex[3] + hex[3]);\n  } else if (hex.length === 7) {\n    r = parseInt(\"0x\" + hex[1] + hex[2]);\n    g = parseInt(\"0x\" + hex[3] + hex[4]);\n    b = parseInt(\"0x\" + hex[5] + hex[6]);\n  }\n  r /= 255; g /= 255; b /= 255;\n  const max = Math.max(r, g, b), min = Math.min(r, g, b);\n  let h = 0, s = 0, l = (max + min) / 2;\n\n  if (max !== min) {\n    const d = max - min;\n    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n    switch (max) {\n      case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n      case g: h = (b - r) / d + 2; break;\n      case b: h = (r - g) / d + 4; break;\n    }\n    h /= 6;\n  }\n  return { h: h * 360, s: s * 100, l: l * 100 };\n}\n\nexport function hslToHex(h: number, s: number, l: number): string {\n  l /= 100;\n  const a = s * Math.min(l, 1 - l) / 100;\n  const f = (n: number) => {\n    const k = (n + h / 30) % 12;\n    const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);\n    return Math.round(255 * color).toString(16).padStart(2, '0');\n  };\n  return `#${f(0)}${f(8)}${f(4)}`;\n}\n\nexport type HarmonyType = 'complementary' | 'triadic' | 'analogous' | 'split-complementary' | 'tetradic' | 'monochromatic';\n\nexport function generateHarmony(hex: string, type: HarmonyType): string[] {\n  const { h, s, l } = hexToHsl(hex);\n  let hues: number[] = [];\n  let lightnesses: number[] = [l, l, l, l, l];\n  let saturations: number[] = [s, s, s, s, s];\n\n  switch (type) {\n    case 'complementary':\n      hues = [h, h, (h + 180) % 360, (h + 180) % 360, h];\n      lightnesses = [Math.max(0, l - 20), l, l, Math.min(100, l + 20), Math.min(100, l + 40)];\n      break;\n    case 'triadic':\n      hues = [h, (h + 120) % 360, (h + 240) % 360, (h + 120) % 360, (h + 240) % 360];\n      lightnesses = [l, l, l, Math.max(0, l - 20), Math.max(0, l - 20)];\n      break;\n    case 'analogous':\n      hues = [(h - 60 + 360) % 360, (h - 30 + 360) % 360, h, (h + 30) % 360, (h + 60) % 360];\n      break;\n    case 'split-complementary':\n      hues = [h, (h + 150) % 360, (h + 210) % 360, (h + 150) % 360, (h + 210) % 360];\n      lightnesses = [l, l, l, Math.max(0, l - 20), Math.max(0, l - 20)];\n      break;\n    case 'tetradic':\n      hues = [h, (h + 90) % 360, (h + 180) % 360, (h + 270) % 360, h];\n      lightnesses = [l, l, l, l, Math.max(0, l - 30)];\n      break;\n    case 'monochromatic':\n      hues = [h, h, h, h, h];\n      lightnesses = [\n        Math.max(0, l - 40),\n        Math.max(0, l - 20),\n        l,\n        Math.min(100, l + 20),\n        Math.min(100, l + 40)\n      ];\n      break;\n  }\n\n  return hues.map((hue, i) => hslToHex(hue, saturations[i], lightnesses[i]));\n}\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { useTranslation } from '../../i18n';\nimport { PanelField, TextBody } from '../ui';\n\ninterface Point {\n  x: number;\n  y: number;\n}\n\ninterface CurvesEditorProps {\n  onCurveChange: (lut: number[]) => void;\n  resetTrigger?: number;\n}\n\nexport const CurvesEditor: React.FC<CurvesEditorProps> = ({ onCurveChange, resetTrigger }) => {\n  const t = useTranslation();\n  const canvasRef = useRef<HTMLCanvasElement>(null);\n  const [points, setPoints] = useState<Point[]>([\n    { x: 0, y: 0 },\n    { x: 255, y: 255 },\n  ]);\n  const [draggingIdx, setDraggingIdx] = useState<number | null>(null);\n\n  useEffect(() => {\n    if (resetTrigger) {\n      setPoints([\n        { x: 0, y: 0 },\n        { x: 255, y: 255 },\n      ]);\n    }\n  }, [resetTrigger]);\n\n  const computeLUT = (pts: Point[]): number[] => {\n    const sorted = [...pts].sort((a, b) => a.x - b.x);\n    if (sorted[0].x > 0) sorted.unshift({ x: 0, y: sorted[0].y });\n    if (sorted[sorted.length - 1].x < 255) sorted.push({ x: 255, y: sorted[sorted.length - 1].y });\n\n    const lut = new Array(256).fill(0);\n\n    for (let i = 0; i < sorted.length - 1; i++) {\n      const p1 = sorted[i];\n      const p2 = sorted[i + 1];\n      const dx = p2.x - p1.x;\n      const dy = p2.y - p1.y;\n\n      for (let x = Math.round(p1.x); x <= Math.round(p2.x); x++) {\n        if (x >= 0 && x <= 255) {\n          if (dx === 0) lut[x] = p1.y;\n          else {\n            const y = p1.y + (dy / dx) * (x - p1.x);\n            lut[x] = Math.max(0, Math.min(255, Math.round(y)));\n          }\n        }\n      }\n    }\n    return lut;\n  };\n\n  useEffect(() => {\n    const lut = computeLUT(points);\n    onCurveChange(lut);\n    drawCanvas();\n  }, [points]);\n\n  const drawCanvas = () => {\n    const canvas = canvasRef.current;\n    if (!canvas) return;\n    const ctx = canvas.getContext('2d');\n    if (!ctx) return;\n\n    ctx.clearRect(0, 0, canvas.width, canvas.height);\n\n    ctx.strokeStyle = '#404040';\n    ctx.lineWidth = 1;\n    for (let i = 1; i < 4; i++) {\n      const p = (i / 4) * canvas.width;\n      ctx.beginPath();\n      ctx.moveTo(p, 0);\n      ctx.lineTo(p, canvas.height);\n      ctx.stroke();\n      ctx.beginPath();\n      ctx.moveTo(0, p);\n      ctx.lineTo(canvas.width, p);\n      ctx.stroke();\n    }\n\n    ctx.strokeStyle = '#363636';\n    ctx.beginPath();\n    ctx.moveTo(0, canvas.height);\n    ctx.lineTo(canvas.width, 0);\n    ctx.stroke();\n\n    const accent =\n      getComputedStyle(document.documentElement).getPropertyValue('--we-accent').trim() ||\n      '#DB2777';\n\n    const lut = computeLUT(points);\n    ctx.strokeStyle = accent;\n    ctx.lineWidth = 2;\n    ctx.beginPath();\n    ctx.moveTo(0, canvas.height - lut[0]);\n    for (let x = 1; x < 256; x++) {\n      ctx.lineTo(x, canvas.height - lut[x]);\n    }\n    ctx.stroke();\n\n    points.forEach((p) => {\n      ctx.fillStyle = '#F0F0F5';\n      ctx.beginPath();\n      ctx.arc(p.x, canvas.height - p.y, 4, 0, Math.PI * 2);\n      ctx.fill();\n      ctx.strokeStyle = '#212121';\n      ctx.lineWidth = 1;\n      ctx.stroke();\n    });\n  };\n\n  const getCanvasPos = (e: React.MouseEvent | React.TouchEvent) => {\n    const canvas = canvasRef.current;\n    if (!canvas) return { x: 0, y: 0 };\n    const rect = canvas.getBoundingClientRect();\n\n    let clientX: number;\n    let clientY: number;\n    if ('touches' in e) {\n      clientX = e.touches[0].clientX;\n      clientY = e.touches[0].clientY;\n    } else {\n      clientX = (e as React.MouseEvent).clientX;\n      clientY = (e as React.MouseEvent).clientY;\n    }\n\n    const scaleX = canvas.width / rect.width;\n    const scaleY = canvas.height / rect.height;\n\n    return {\n      x: Math.max(0, Math.min(255, (clientX - rect.left) * scaleX)),\n      y: Math.max(0, Math.min(255, canvas.height - (clientY - rect.top) * scaleY)),\n    };\n  };\n\n  const onPointerDown = (e: React.MouseEvent | React.TouchEvent) => {\n    const pos = getCanvasPos(e);\n    let closestIdx = -1;\n    let minDist = 15;\n\n    points.forEach((p, i) => {\n      const dist = Math.hypot(p.x - pos.x, p.y - pos.y);\n      if (dist < minDist) {\n        minDist = dist;\n        closestIdx = i;\n      }\n    });\n\n    if (closestIdx >= 0) {\n      setDraggingIdx(closestIdx);\n    } else {\n      const newPoints = [...points, pos].sort((a, b) => a.x - b.x);\n      setPoints(newPoints);\n      setDraggingIdx(newPoints.findIndex((p) => p.x === pos.x && p.y === pos.y));\n    }\n  };\n\n  const onPointerMove = (e: React.MouseEvent | React.TouchEvent) => {\n    if (draggingIdx === null) return;\n    const pos = getCanvasPos(e);\n\n    const newPoints = [...points];\n    if (draggingIdx === 0) pos.x = 0;\n    if (draggingIdx === newPoints.length - 1) pos.x = 255;\n\n    newPoints[draggingIdx] = pos;\n    setPoints(newPoints);\n  };\n\n  const onPointerUp = () => {\n    setDraggingIdx(null);\n  };\n\n  useEffect(() => {\n    const canvas = canvasRef.current;\n    if (!canvas) return;\n    const preventDefault = (e: Event) => e.preventDefault();\n    canvas.addEventListener('touchstart', preventDefault, { passive: false });\n    canvas.addEventListener('touchmove', preventDefault, { passive: false });\n    return () => {\n      canvas.removeEventListener('touchstart', preventDefault);\n      canvas.removeEventListener('touchmove', preventDefault);\n    };\n  }, []);\n\n  const resetCurve = () => {\n    const identity = [\n      { x: 0, y: 0 },\n      { x: 255, y: 255 },\n    ];\n    setPoints(identity);\n    // Apply immediately \u2014 don't wait for the points effect (preview was staying curved).\n    onCurveChange(computeLUT(identity));\n  };\n\n  return (\n    <div className=\"flex flex-col gap-1.5\">\n      <PanelField\n        label={t.properties.image.curvesRgb}\n        trailing={\n          <button\n            type=\"button\"\n            onClick={(e) => {\n              e.stopPropagation();\n              resetCurve();\n            }}\n            className=\"transition-colors hover:text-white\"\n          >\n            <TextBody as=\"span\" size=\"sm\" className=\"text-white/80 hover:text-white\">\n              {t.properties.image.curvesReset}\n            </TextBody>\n          </button>\n        }\n      />\n      <div className=\"relative aspect-square w-full cursor-crosshair overflow-hidden rounded-xl bg-black-capsule\">\n        <canvas\n          ref={canvasRef}\n          width={256}\n          height={256}\n          className=\"h-full w-full\"\n          onMouseDown={onPointerDown}\n          onMouseMove={onPointerMove}\n          onMouseUp={onPointerUp}\n          onMouseLeave={onPointerUp}\n          onTouchStart={onPointerDown}\n          onTouchMove={onPointerMove}\n          onTouchEnd={onPointerUp}\n          onTouchCancel={onPointerUp}\n        />\n      </div>\n      <TextBody as=\"p\" size=\"sm\" className=\"text-center text-white/80\">\n        {t.properties.image.curvesHint}\n      </TextBody>\n    </div>\n  );\n};\n", "import { Textbox, classRegistry, Point } from 'fabric';\n\nexport class Textbox3D extends Textbox {\n  static type = 'Textbox3D';\n  public extrudeDepth: number = 15;\n  public extrudeAngle: number = 45; // Degrees\n  public extrudeColor: string = '#000000';\n\n  constructor(text: string, options: any) {\n    super(text, options);\n    this.extrudeDepth = options.extrudeDepth ?? 15;\n    this.extrudeAngle = options.extrudeAngle ?? 45;\n    this.extrudeColor = options.extrudeColor ?? '#000000';\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  toObject(propertiesToInclude: any[] = []): any {\n    return super.toObject([...propertiesToInclude, 'extrudeDepth', 'extrudeAngle', 'extrudeColor']);\n  }\n\n  // Ensure selection bounds include the extrusion\n  _calculateCurrentDimensions(): Point {\n    const dim = super._calculateCurrentDimensions();\n    if (this.extrudeDepth > 0) {\n      const angleRad = (this.extrudeAngle * Math.PI) / 180;\n      const dx = Math.abs(Math.cos(angleRad) * this.extrudeDepth);\n      const dy = Math.abs(Math.sin(angleRad) * this.extrudeDepth);\n      // Add extra padding so the extruded part isn't clipped by caching\n      return new Point(dim.x + dx, dim.y + dy);\n    }\n    return dim;\n  }\n\n  _render(ctx: CanvasRenderingContext2D) {\n    if (!this.extrudeDepth || this.extrudeDepth <= 0) {\n      super._render(ctx);\n      return;\n    }\n\n    const angleRad = (this.extrudeAngle * Math.PI) / 180;\n    const dx = Math.cos(angleRad);\n    const dy = Math.sin(angleRad);\n    const origFill = this.fill;\n\n    // Draw the background layers\n    this.fill = this.extrudeColor;\n    for (let i = this.extrudeDepth; i > 0; i--) {\n      ctx.save();\n      ctx.translate(dx * i, dy * i);\n      super._render(ctx);\n      ctx.restore();\n    }\n\n    // Draw the top layer\n    this.fill = origFill;\n    super._render(ctx);\n  }\n}\n\n// Register the class in Fabric v6 registry\nclassRegistry.setClass(Textbox3D, 'Textbox3D');\n", "import React, { useState, useEffect, useRef } from 'react';\nimport { useEditorStore } from '../store/useEditorStore';\n\nimport {\n  Square,\n  ImageIcon, Sliders, Brush, Settings, Plus, Trash2, X, Search,\n  UploadCloud,\n  ChevronLeft, ChevronRight, Palette, Edit2,\n} from 'lucide-react';\nimport { FabricImage, filters, Gradient, Shadow } from 'fabric';\nimport { LevelsFilter, LUTFilter, AdvancedHSLFilter } from '../utils/fabricCustomFilters';\nimport { applyFabricImageFilters } from '../utils/applyFabricImageFilters';\nimport { generateHarmony, type HarmonyType } from '../utils/colorUtils';\n// customShapeCategories eliminado: ahora vive en el panel flotante de CanvasArea (T-20260706-08)\nimport { HistogramLevels } from './editor/HistogramLevels';\nimport { CurvesEditor } from './editor/CurvesEditor';\nimport { Textbox3D } from '../utils/fabricText3D';\nimport { type ChartType, type ChartDataPoint, type ChartOptions } from '../utils/chartUtils';\nimport { useTranslation } from '../i18n';\nimport { PanelField, Switch, TextBody, TextTitle } from './ui';\n\n\n// PRESET_COLORS deleted to avoid TS6133\n\nexport const SOLID_PRESETS = [\n  '#ffffff', '#f3f4f6', '#e2e8f0', '#94a3b8', '#475569', '#0f172a',\n  '#000000', '#ef4444', '#f97316', '#f59e0b', '#10b981', '#06b6d4',\n  '#3b82f6', '#6366f1', '#8b5cf6', '#d946ef', '#ec4899', '#14b8a6'\n];\n\ninterface BrushPreset {\n  name: string;\n  type: 'pencil' | 'spray' | 'circle' | 'calligraphy' | 'highlighter' | 'chalk';\n  color: string;\n  width: number;\n  opacity: number;\n  shadowEnabled: boolean;\n  shadowBlur: number;\n  shadowColor: string;\n  stabilization?: number;\n  pressureSensitivity?: boolean;\n  className: string;\n}\n\nexport const BRUSH_PRESETS: BrushPreset[] = [\n  {\n    name: 'Pincel Caligr\u00E1fico',\n    nameKey: 'calligraphy',\n    type: 'calligraphy',\n    color: '#d97706',\n    width: 15,\n    opacity: 1.0,\n    shadowEnabled: true,\n    shadowBlur: 2,\n    shadowColor: 'rgba(0,0,0,0.2)',\n    stabilization: 0.6,\n    pressureSensitivity: true,\n    className: 'from-amber-500 to-amber-700 border-amber-500 text-amber-100 font-bold'\n  },\n  {\n    name: 'Subrayador Amarillo',\n    nameKey: 'highlighter',\n    type: 'highlighter',\n    color: '#facc15',\n    width: 28,\n    opacity: 0.45,\n    shadowEnabled: false,\n    shadowBlur: 0,\n    shadowColor: '#000000',\n    stabilization: 0.4,\n    pressureSensitivity: false,\n    className: 'from-yellow-400 to-yellow-500 border-yellow-400 text-yellow-950 font-bold'\n  },\n  {\n    name: 'Tiza Difuminada',\n    nameKey: 'chalk',\n    type: 'chalk',\n    color: '#ffffff',\n    width: 8,\n    opacity: 0.8,\n    shadowEnabled: false,\n    shadowBlur: 0,\n    shadowColor: '#000000',\n    stabilization: 0.2,\n    pressureSensitivity: false,\n    className: 'from-dark-700 to-dark-600 border-dark-500 text-white font-bold'\n  },\n  {\n    name: 'Ne\u00F3n Magenta',\n    nameKey: 'neonMagenta',\n    type: 'pencil',\n    color: '#ff007f',\n    width: 12,\n    opacity: 1.0,\n    shadowEnabled: true,\n    shadowBlur: 15,\n    shadowColor: '#ff007f',\n    stabilization: 0.4,\n    pressureSensitivity: false,\n    className: 'from-pink-500 to-rose-500 border-pink-400 font-bold'\n  },\n  {\n    name: 'Ne\u00F3n Cian',\n    nameKey: 'neonCyan',\n    type: 'pencil',\n    color: '#00f3ff',\n    width: 12,\n    opacity: 1.0,\n    shadowEnabled: true,\n    shadowBlur: 15,\n    shadowColor: '#00f3ff',\n    stabilization: 0.4,\n    pressureSensitivity: false,\n    className: 'from-cyan-400 to-blue-500 border-cyan-400 font-bold'\n  },\n  {\n    name: 'Graffiti Spray',\n    nameKey: 'spray',\n    type: 'spray',\n    color: '#ef4444',\n    width: 18,\n    opacity: 0.9,\n    shadowEnabled: true,\n    shadowBlur: 4,\n    shadowColor: '#000000',\n    stabilization: 0.3,\n    pressureSensitivity: false,\n    className: 'from-red-500 to-orange-500 border-red-500 font-bold'\n  }\n];\n\nexport const GOOGLE_FONTS_CATALOG = [\n  // Sans-Serif\n  { name: 'Inter', category: 'Sans-Serif' },\n  { name: 'Roboto', category: 'Sans-Serif' },\n  { name: 'Montserrat', category: 'Sans-Serif' },\n  { name: 'Poppins', category: 'Sans-Serif' },\n  { name: 'Outfit', category: 'Sans-Serif' },\n  { name: 'Lato', category: 'Sans-Serif' },\n  { name: 'Oswald', category: 'Sans-Serif' },\n  { name: 'Raleway', category: 'Sans-Serif' },\n  // Serif\n  { name: 'Playfair Display', category: 'Serif' },\n  { name: 'Merriweather', category: 'Serif' },\n  { name: 'Lora', category: 'Serif' },\n  { name: 'Cinzel', category: 'Serif' },\n  { name: 'PT Serif', category: 'Serif' },\n  // Display / T\u00EDtulos\n  { name: 'Bebas Neue', category: 'Display / T\u00EDtulos' },\n  { name: 'Lobster', category: 'Display / T\u00EDtulos' },\n  { name: 'Pacifico', category: 'Display / T\u00EDtulos' },\n  { name: 'Abril Fatface', category: 'Display / T\u00EDtulos' },\n  { name: 'Fredoka', category: 'Display / T\u00EDtulos' },\n  { name: 'Righteous', category: 'Display / T\u00EDtulos' },\n  { name: 'Anton', category: 'Display / T\u00EDtulos' },\n  { name: 'Comfortaa', category: 'Display / T\u00EDtulos' },\n  // Escritura (Script)\n  { name: 'Caveat', category: 'Escritura' },\n  { name: 'Dancing Script', category: 'Escritura' },\n  { name: 'Permanent Marker', category: 'Escritura' },\n  { name: 'Satisfy', category: 'Escritura' },\n  { name: 'Great Vibes', category: 'Escritura' },\n  // Monospace\n  { name: 'JetBrains Mono', category: 'Monospace' },\n  { name: 'Fira Code', category: 'Monospace' }\n];\n\nexport const GRADIENT_PRESETS = [\n  { name: 'Sunset Glow', nameKey: 'sunsetGlow', start: '#FF512F', end: '#DD2476', angle: 90 },\n  { name: 'Ocean Breeze', nameKey: 'oceanBreeze', start: '#00c6ff', end: '#0072ff', angle: 90 },\n  { name: 'Purple Haze', nameKey: 'purpleHaze', start: '#8a2387', end: '#e94057', angle: 90 },\n  { name: 'Emerald Glow', nameKey: 'emeraldGlow', start: '#11998e', end: '#38ef7d', angle: 90 },\n  { name: 'Sweet Candy', nameKey: 'sweetCandy', start: '#ee9ca7', end: '#ffdde1', angle: 90 },\n  { name: 'Space Void', nameKey: 'spaceVoid', start: '#0f2027', end: '#2c5364', angle: 90 }\n];\n\nimport { CATEGORIZED_PRESETS } from '../utils/canvasSizePresets';\n\nexport { CATEGORIZED_PRESETS };\n\nexport const STOCK_BG_PRESETS = [\n  { name: 'Neon Synthwave', nameKey: 'neonSynthwave', url: 'https://images.unsplash.com/photo-1508739773434-c26b3d09e071?w=800&auto=format&fit=crop&q=60' },\n  { name: 'Minimalist Marble', nameKey: 'minimalistMarble', url: 'https://images.unsplash.com/photo-1533090161767-e6ffed986c88?w=800&auto=format&fit=crop&q=60' },\n  { name: 'Cyberpunk Grid', nameKey: 'cyberpunkGrid', url: 'https://images.unsplash.com/photo-1526374965328-7f61d4dc18c5?w=800&auto=format&fit=crop&q=60' },\n  { name: 'Dark Beach', nameKey: 'darkBeach', url: 'https://images.unsplash.com/photo-1507525428034-b723cf961d3e?w=800&auto=format&fit=crop&q=60' },\n  { name: 'Clean Workspace', nameKey: 'cleanWorkspace', url: 'https://images.unsplash.com/photo-1499951360447-b19be8fe80f5?w=800&auto=format&fit=crop&q=60' },\n  { name: 'Watercolor Pastel', nameKey: 'watercolorPastel', url: 'https://images.unsplash.com/photo-1579783902614-a3fb3927b6a5?w=800&auto=format&fit=crop&q=60' }\n];\n\nexport const STOCK_LAYERS = [\n  { name: 'Abstract Neon', nameKey: 'abstractNeon', url: 'https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=800&auto=format&fit=crop&q=80', thumb: 'https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=150&auto=format&fit=crop&q=60' },\n  { name: 'Cyber Wave', nameKey: 'cyberWave', url: 'https://images.unsplash.com/photo-1607604276583-eef5d076aa5f?w=800&auto=format&fit=crop&q=80', thumb: 'https://images.unsplash.com/photo-1607604276583-eef5d076aa5f?w=150&auto=format&fit=crop&q=60' },\n  { name: 'Vidrio 3D', nameKey: 'vidrio3D', url: 'https://images.unsplash.com/photo-1634017839464-5c339ebe3cb4?w=800&auto=format&fit=crop&q=80', thumb: 'https://images.unsplash.com/photo-1634017839464-5c339ebe3cb4?w=150&auto=format&fit=crop&q=60' },\n  { name: 'Acuarela Pastel', nameKey: 'acuarelaPastel', url: 'https://images.unsplash.com/photo-1579783900882-c0d3dad7b119?w=800&auto=format&fit=crop&q=80', thumb: 'https://images.unsplash.com/photo-1579783900882-c0d3dad7b119?w=150&auto=format&fit=crop&q=60' }\n];\n\n\n\n// STOCK_LIBRARY_IMAGES removed (unused - stock photos served via API)\n\n\n\nexport const extractColorsFromImage = (imgUrl: string): Promise<string[]> => {\n  return new Promise((resolve) => {\n    const img = new Image();\n    img.crossOrigin = 'anonymous';\n    img.src = imgUrl;\n    img.onload = () => {\n      try {\n        const canvas = document.createElement('canvas');\n        const ctx = canvas.getContext('2d', { willReadFrequently: true });\n        if (!ctx) {\n          resolve([]);\n          return;\n        }\n        canvas.width = 30;\n        canvas.height = 30;\n        ctx.drawImage(img, 0, 0, 30, 30);\n        const data = ctx.getImageData(0, 0, 30, 30).data;\n        const buckets: { [key: string]: number } = {};\n        for (let i = 0; i < data.length; i += 16) {\n          const r = data[i];\n          const g = data[i+1];\n          const b = data[i+2];\n          const a = data[i+3];\n          if (a < 128) continue;\n          const qr = Math.round(r / 30) * 30;\n          const qg = Math.round(g / 30) * 30;\n          const qb = Math.round(b / 30) * 30;\n          const hex = \"#\" + ((1 << 24) + (qr << 16) + (qg << 8) + qb).toString(16).slice(1);\n          buckets[hex] = (buckets[hex] || 0) + 1;\n        }\n        const sorted = Object.keys(buckets).sort((a, b) => buckets[b] - buckets[a]);\n        resolve(sorted.slice(0, 6)); // Top 6 colors matches grid nicely!\n      } catch (err) {\n        console.error(\"Color extraction failed:\", err);\n        resolve([]);\n      }\n    };\n    img.onerror = () => resolve([]);\n  });\n};\n\nexport const Sidebar: React.FC = () => {\n  const t = useTranslation();\n  const [activeTab, setActiveTab] = useState<TabType>('canvas');\n  const filterApplyTimeoutRef = useRef<any>(null);\n  const extractedColors = useEditorStore((s) => s.extractedColors);\n  const [isComparing, setIsComparing] = useState(false);\n  const [exportSelScale, setExportSelScale] = useState<number>(1);\n  const [exportSelFormat, setExportSelFormat] = useState<'png' | 'jpg' | 'svg'>('png');\n\n  // unit, isRatioLocked, ratio eliminados: ahora viven en el panel flotante de CanvasArea (T-20260706-07)\n\n  const handleExportSelection = () => {\n    if (!canvasInstance || !activeObject) return;\n\n    if (exportSelFormat === 'svg') {\n      try {\n        const svgCode = activeObject.toSVG();\n        const blob = new Blob([svgCode], { type: 'image/svg+xml;charset=utf-8' });\n        const url = URL.createObjectURL(blob);\n        const link = document.createElement('a');\n        link.href = url;\n        link.download = `${activeObject.type || 'layer'}-${Date.now()}.svg`;\n        link.click();\n        URL.revokeObjectURL(url);\n      } catch (err) {\n        console.error(\"Export selection to SVG failed:\", err);\n      }\n      return;\n    }\n\n    try {\n      // Use Fabric's native toDataURL on the object itself for transparent, cropped bounding box output\n      const dataUrl = activeObject.toDataURL({\n        format: exportSelFormat === 'png' ? 'png' : 'jpeg',\n        quality: 0.95,\n        multiplier: exportSelScale,\n      });\n\n      const link = document.createElement('a');\n      link.href = dataUrl;\n      link.download = `${activeObject.type || 'layer'}-${Date.now()}.${exportSelFormat}`;\n      link.click();\n    } catch (err) {\n      console.error(\"Export selection failed:\", err);\n    }\n  };\n  // presetCategory eliminado: ahora vive en el panel flotante de CanvasArea (T-20260706-07)\n  // isFontDropdownOpen removed (unused)\n  // expandedTextSection removed (unused)\n  // textToImagePrompt/Style removed (moved to CanvasArea)\n  // modifyImagePrompt removed (moved to CanvasArea)\n  // generativeFillPrompt/copywritePrompt/sketchToImagePrompt/generateInAreaPrompt removed (moved to CanvasArea)\n  \n  // Brand Kit states\n  const [baseHarmonyColor, setBaseHarmonyColor] = useState<string>('#3b82f6');\n  const [harmonyType, setHarmonyType] = useState<HarmonyType>('complementary');\n  const [generatedHarmony, setGeneratedHarmony] = useState<string[]>([]);\n\n  useEffect(() => {\n    setGeneratedHarmony(generateHarmony(baseHarmonyColor, harmonyType));\n  }, [baseHarmonyColor, harmonyType]);\n\n  // Accordion and Tool states\n  // expandedPanel removed (unused)\n  // generativeFillBlend removed (unused)\n\n  // dialog used below via barrel; store destructure follows\n  const {\n    sidebarCollapsed,\n    setSidebarCollapsed,\n    // pages/activePageId used in sub-sections\n    activeTool,\n    activeObject,\n    // activeCustomShape eliminado: ahora vive en el panel flotante de CanvasArea (T-20260706-08)\n    // brushSettings eliminado: ahora vive en el panel flotante de CanvasArea (T-20260706-09)\n    canvasInstance,\n    imageSettings,\n    updateImageSettings,\n    setActiveTool,\n    setActiveObject,\n    syncLayers,\n    saveHistoryState,\n    loadUploadedAssets,\n    savedPalettes,\n    addPalette,\n    updatePaletteName,\n    addColorToPalette,\n    updateColorInPalette,\n    removeColorFromPalette,\n    reorderColorInPalette,\n    deletePalette,\n  } = useEditorStore();\n\n\n\n  // activePage removed (unused in this scope)\n\n  // isDragging eliminado: ahora vive en el panel flotante de CanvasArea (T-20260706-10)\n  const [isStockExplorerOpen, setIsStockExplorerOpen] = useState(false);\n  // stockSearchQuery removed (unused)\n\n  // \u2500\u2500 Stock gallery state (backed by .NET /api/stock/search)\n  const [stockPhotos, setStockPhotos] = useState<import('../services/stockService').StockPhoto[]>([]);\n  const [stockPage, setStockPage] = useState(1);\n  const [stockQuery, setStockQuery] = useState('');\n  const [stockInputValue, setStockInputValue] = useState('');\n  const [stockActiveCategory, setStockActiveCategory] = useState<string | null>(null);\n  const [stockIsLoading, setStockIsLoading] = useState(false);\n  const [stockIsLoadingMore, setStockIsLoadingMore] = useState(false);\n  const [stockHasMore, setStockHasMore] = useState(true);\n  const [, setStockError] = useState<string | null>(null); // stockError read removed (unused)\n  const [stockAddingId, setStockAddingId] = useState<string | null>(null);\n\n  // --- Utilidades State ---\n  // loremLength/loremAmount/qrText/barcodeText: state values unused (handlers removed)\n  \n  // --- Chart Data Modal State ---\n  // chart modal state: setters used in edit-chart effect, values not rendered\n  const [, setIsChartModalOpen] = useState(false);\n  const [, setChartModalData] = useState<ChartDataPoint[]>([]);\n  const [, setChartModalType] = useState<ChartType>('bar');\n  const [, setChartModalOptions] = useState<Partial<ChartOptions>>({});\n  const [, setEditingChartObj] = useState<any>(null);\n\n  useEffect(() => {\n    const handleEditChart = (e: any) => {\n      const target = e.detail.target;\n      if (target && target.chartData && target.chartType) {\n        setChartModalData(target.chartData);\n        setChartModalType(target.chartType);\n        setChartModalOptions(target.chartOptions || {});\n        setEditingChartObj(target);\n        setIsChartModalOpen(true);\n      }\n    };\n    window.addEventListener('edit-chart', handleEditChart);\n    return () => window.removeEventListener('edit-chart', handleEditChart);\n  }, []);\n\n  const stockSentinelRef = React.useRef<HTMLDivElement>(null);\n  const stockScrollRef = React.useRef<HTMLDivElement>(null);\n  const stockSearchTimeout = React.useRef<ReturnType<typeof setTimeout> | null>(null);\n\n  const STOCK_CATEGORIES_REAL = [\n    { label: t.sidebar.stockCategory.trending, query: 'trending wallpaper' },\n    { label: t.sidebar.stockCategory.naturaleza, query: 'nature landscape' },\n    { label: t.sidebar.stockCategory.tecnologia, query: 'technology futuristic' },\n    { label: t.sidebar.stockCategory.arquitectura, query: 'architecture building' },\n    { label: t.sidebar.stockCategory.personas, query: 'people portrait' },\n    { label: t.sidebar.stockCategory.abstracto, query: 'abstract colorful' },\n    { label: t.sidebar.stockCategory.ciudad, query: 'city urban night' },\n    { label: t.sidebar.stockCategory.espacio, query: 'space galaxy cosmos' },\n  ];\n\n  // handleInsertLoremIpsum, handleInsertQR, handleInsertBarcode, handleInsertChart,\n  // handleSaveChartData removed (moved to CanvasArea panel, unused here)\n\n  // -------------------------\n\n  const fetchStockPage = React.useCallback(async (q: string, pg: number, reset: boolean) => {\n    if (pg === 1) setStockIsLoading(true); else setStockIsLoadingMore(true);\n    setStockError(null);\n    try {\n      const { searchStock } = await import('../services/stockService');\n      const { photos: results } = await searchStock({ q, page: pg, perPage: 18 });\n      if (reset) setStockPhotos(results); else setStockPhotos(prev => [...prev, ...results]);\n      setStockHasMore(results.length >= 18);\n      setStockPage(pg);\n    } catch (err: any) {\n      setStockError(err.message || t.store.toasts.editor.stockLoadError);\n    } finally {\n      setStockIsLoading(false);\n      setStockIsLoadingMore(false);\n    }\n  }, []);\n\n  useEffect(() => {\n    if (isStockExplorerOpen) {\n      fetchStockPage(stockQuery, 1, true);\n    }\n  }, [isStockExplorerOpen, stockQuery, fetchStockPage]);\n\n  useEffect(() => {\n    const sentinel = stockSentinelRef.current;\n    if (!sentinel || !isStockExplorerOpen) return;\n    const observer = new IntersectionObserver((entries) => {\n      if (entries[0].isIntersecting && stockHasMore && !stockIsLoading && !stockIsLoadingMore) {\n        fetchStockPage(stockQuery, stockPage + 1, false);\n      }\n    }, { threshold: 0.1, root: stockScrollRef.current });\n    observer.observe(sentinel);\n    return () => observer.disconnect();\n  }, [stockHasMore, stockIsLoading, stockIsLoadingMore, stockQuery, stockPage, fetchStockPage, isStockExplorerOpen]);\n\n  const handleStockInputChange = (val: string) => {\n    setStockInputValue(val);\n    if (stockSearchTimeout.current) clearTimeout(stockSearchTimeout.current);\n    stockSearchTimeout.current = setTimeout(() => { setStockActiveCategory(null); setStockQuery(val); }, 500);\n  };\n\n  const handleStockAddToCanvas = async (photo: import('../services/stockService').StockPhoto) => {\n    setStockAddingId(photo.id);\n    try {\n      const { downloadStockPhoto } = await import('../services/stockService');\n      const downloaded = await downloadStockPhoto(photo);\n      handleAddImageLayer(downloaded.objectUrl, photo.alt || photo.photographer);\n      setIsStockExplorerOpen(false);\n    } catch (err) {\n      console.error('Stock add error:', err);\n    } finally {\n      setStockAddingId(null);\n    }\n  };\n\n  const [sidebarUpdateTrigger, setSidebarUpdateTrigger] = useState(0);\n  const [shapeFillTab, setShapeFillTab] = useState<'solid' | 'gradient' | 'none'>('solid');\n  const [shapeGradStart, setShapeGradStart] = useState('#3b82f6');\n  const [shapeGradEnd, setShapeGradEnd] = useState('#8b5cf6');\n  const [shapeGradAngle, setShapeGradAngle] = useState(90);\n  const [shapeStrokeStyle, setShapeStrokeStyle] = useState<'solid' | 'dashed' | 'dotted'>('solid');\n  const [shapeShadowEnabled, setShapeShadowEnabled] = useState(false);\n  const [shapeShadowColor, setShapeShadowColor] = useState('#000000');\n  const [shapeShadowBlur, setShapeShadowBlur] = useState(10);\n  const [shapeShadowOffsetX, setShapeShadowOffsetX] = useState(5);\n  const [shapeShadowOffsetY, setShapeShadowOffsetY] = useState(5);\n\n  // addCreativeTextPreset removed (unused - moved to CanvasArea)\n\n\n\n\n  // Event listener to sync properties from canvas to sidebar\n  useEffect(() => {\n    if (!canvasInstance) return;\n\n    const handleObjectChange = () => {\n      setSidebarUpdateTrigger((prev) => prev + 1);\n    };\n\n    canvasInstance.on('object:moving', handleObjectChange);\n    canvasInstance.on('object:scaling', handleObjectChange);\n    canvasInstance.on('object:rotating', handleObjectChange);\n    canvasInstance.on('object:modified', handleObjectChange);\n    canvasInstance.on('selection:created', handleObjectChange);\n    canvasInstance.on('selection:updated', handleObjectChange);\n\n    return () => {\n      canvasInstance.off('object:moving', handleObjectChange);\n      canvasInstance.off('object:scaling', handleObjectChange);\n      canvasInstance.off('object:rotating', handleObjectChange);\n      canvasInstance.off('object:modified', handleObjectChange);\n      canvasInstance.off('selection:created', handleObjectChange);\n      canvasInstance.off('selection:updated', handleObjectChange);\n    };\n  }, [canvasInstance]);\n\n  // Sync state variables when activeObject is selected/modified\n  useEffect(() => {\n    if (!activeObject) return;\n\n    // 1. Fill type\n    const fill = activeObject.fill;\n    if (!fill || fill === 'transparent') {\n      setShapeFillTab('none');\n    } else if (typeof fill === 'object' && fill !== null && (fill as any).type) {\n      setShapeFillTab('gradient');\n      const grad = fill as any;\n      if (grad.colorStops && grad.colorStops.length >= 2) {\n        setShapeGradStart(grad.colorStops[0].color);\n        setShapeGradEnd(grad.colorStops[1].color);\n      }\n      if (grad.coords) {\n        const coords = grad.coords;\n        const dx = (coords.x2 || 0) - (coords.x1 || 0);\n        const dy = (coords.y2 || 0) - (coords.y1 || 0);\n        const angle = Math.round((Math.atan2(dy, dx) * 180) / Math.PI);\n        setShapeGradAngle(angle < 0 ? angle + 360 : angle);\n      }\n    } else {\n      setShapeFillTab('solid');\n    }\n\n    // 2. Stroke style (dash array)\n    const dash = activeObject.strokeDashArray;\n    if (!dash) {\n      setShapeStrokeStyle('solid');\n    } else if (dash[0] === 8) {\n      setShapeStrokeStyle('dashed');\n    } else {\n      setShapeStrokeStyle('dotted');\n    }\n\n    // 3. Shadow status\n    const shadow = activeObject.shadow as any;\n    if (shadow && (shadow.blur > 0 || shadow.offsetX !== 0 || shadow.offsetY !== 0)) {\n      setShapeShadowEnabled(true);\n      setShapeShadowColor(shadow.color || '#000000');\n      setShapeShadowBlur(shadow.blur || 10);\n      setShapeShadowOffsetX(shadow.offsetX || 5);\n      setShapeShadowOffsetY(shadow.offsetY || 5);\n    } else {\n      setShapeShadowEnabled(false);\n    }\n  }, [activeObject, sidebarUpdateTrigger]);\n\n  useEffect(() => {\n    loadUploadedAssets();\n  }, []);\n\n  // unit, isRatioLocked, ratio, convertToPx, convertFromPx, toggleRatioLock eliminados: ahora viven en el panel flotante de CanvasArea (T-20260706-07)\n\n  // Auto-switch tabs based on active canvas object selection\n  useEffect(() => {\n    if (activeObject) {\n      if (activeObject.type === 'Textbox' || activeObject.type === 'textbox' || activeObject.type === 'text' || activeObject instanceof Textbox3D) {\n        setActiveTab('texto');\n      } else if (activeObject.type === 'image') {\n        setActiveTab('filtros');\n        // Read current filters of the image to sync UI sliders\n        const img = activeObject as any;\n        const currentSettings = {\n          exposure: 0,\n          brightness: 0,\n          contrast: 0,\n          saturation: 0,\n          blur: 0,\n          hueRotation: 0,\n          invert: false,\n          activePreset: 'original',\n          cropScale: 1,\n          levelsBlack: 0,\n          levelsMid: 1,\n          levelsWhite: 255,\n          lut: null\n        };\n\n        if (img.filters) {\n          img.filters.forEach((f: any) => {\n            if (f instanceof filters.Brightness) currentSettings.brightness = f.brightness;\n            if (f instanceof filters.Contrast) currentSettings.contrast = f.contrast;\n            if (f instanceof filters.Saturation) currentSettings.saturation = f.saturation;\n            if (f instanceof filters.Blur) currentSettings.blur = f.blur;\n            if (f instanceof filters.HueRotation) currentSettings.hueRotation = f.rotation;\n            if (f instanceof filters.Gamma) {\n              const gVal = f.gamma ? f.gamma[0] : 1;\n              currentSettings.exposure = (1 / gVal) - 1;\n            }\n            if (f instanceof filters.Invert) currentSettings.invert = true;\n          });\n        }\n        updateImageSettings(currentSettings);\n      } else {\n        setActiveTab('shapes');\n      }\n    }\n  }, [activeObject]);\n\n  // Helper: stamp image into the active Photoshop-style pixel layer (no floating image object)\n  const handleAddImageLayer = (url: string, name: string) => {\n    if (!canvasInstance) return;\n    void useEditorStore.getState().stampImageOntoActivePixelLayer(url, { name });\n  };\n\n  // processUploadedFile y handleImageUpload eliminados: ahora viven en el panel flotante de CanvasArea (T-20260706-10)\n\n  // Apply real-time WebGL image filters\n  const applyImageFilter = (filterName: string, value: any) => {\n    if (!canvasInstance || !activeObject || activeObject.type !== 'image') return;\n    const imgObj = activeObject as any;\n\n    if (!imgObj.filters) imgObj.filters = [];\n\n    // Find and update or remove the filter\n    let filterIndex = -1;\n\n    switch (filterName) {\n      case 'brightness':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Brightness);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.Brightness({ brightness: value }); // range -1 to 1\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({ brightness: value, activePreset: 'custom' });\n        break;\n\n      case 'contrast':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Contrast);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.Contrast({ contrast: value }); // range -1 to 1\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({ contrast: value, activePreset: 'custom' });\n        break;\n\n      case 'saturation':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Saturation);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.Saturation({ saturation: value }); // range -1 to 1\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({ saturation: value, activePreset: 'custom' });\n        break;\n\n      case 'blur':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Blur);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.Blur({ blur: value }); // range 0 to 1\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({ blur: value, activePreset: 'custom' });\n        break;\n\n      case 'hue':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.HueRotation);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.HueRotation({ rotation: value }); // range -1 to 1\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({ hueRotation: value, activePreset: 'custom' });\n        break;\n\n      case 'exposure':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Gamma);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const gVal = 1 / (1 + value);\n          const filter = new filters.Gamma({ gamma: [gVal, gVal, gVal] });\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({ exposure: value, activePreset: 'custom' });\n        break;\n\n      case 'invert':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Invert);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.Invert();\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({ invert: value === 1, activePreset: 'custom' });\n        break;\n\n      case 'levels':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof LevelsFilter);\n        if (value.black === 0 && value.mid === 1 && value.white === 255) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new LevelsFilter(value);\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({ \n          levelsBlack: value.black, \n          levelsMid: value.mid, \n          levelsWhite: value.white, \n          activePreset: 'custom' \n        });\n        break;\n\n      case 'curves':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof LUTFilter);\n        if (!value || value.length !== 256 || LUTFilter.isIdentityLut(value)) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n          updateImageSettings({ lut: undefined, activePreset: 'custom' });\n        } else {\n          const filter = new LUTFilter({ lut: value });\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n          updateImageSettings({ lut: value, activePreset: 'custom' });\n        }\n        break;\n\n      // Existing switch statement ends around here\n\n      case 'grayscale':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Grayscale);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.Grayscale();\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        break;\n\n      case 'sepia':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Sepia);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.Sepia();\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        break;\n    }\n\n    const hasCustomFilter = imgObj.filters.some((f: any) => \n      f instanceof LevelsFilter || f instanceof LUTFilter || f instanceof AdvancedHSLFilter\n    );\n\n    if (filterApplyTimeoutRef.current) clearTimeout(filterApplyTimeoutRef.current);\n\n    const runApply = () => {\n      applyFabricImageFilters(imgObj, hasCustomFilter);\n      canvasInstance.requestRenderAll();\n    };\n\n    const flushNow =\n      filterName === 'curves' ||\n      filterName === 'levels' ||\n      filterName === 'invert' ||\n      filterName === 'grayscale' ||\n      filterName === 'sepia';\n\n    if (flushNow) {\n      runApply();\n    } else {\n      filterApplyTimeoutRef.current = setTimeout(runApply, 100);\n    }\n  };\n\n  const reapplyAllFilters = (settings: typeof imageSettings) => {\n    if (!canvasInstance || !activeObject || activeObject.type !== 'image') return;\n    const imgObj = activeObject as any;\n    imgObj.filters = [];\n\n    // Apply active preset filters first\n    if (settings.activePreset && settings.activePreset !== 'original') {\n      switch (settings.activePreset) {\n        case 'grayscale':\n          imgObj.filters.push(new filters.Grayscale());\n          break;\n        case 'sepia':\n          imgObj.filters.push(new filters.Sepia());\n          break;\n        case 'vintage':\n          imgObj.filters.push(new filters.HueRotation({ rotation: 0.08 }));\n          imgObj.filters.push(new filters.Brightness({ brightness: 0.05 }));\n          imgObj.filters.push(new filters.Contrast({ contrast: -0.1 }));\n          imgObj.filters.push(new filters.Saturation({ saturation: -0.15 }));\n          break;\n        case 'cyberpunk':\n          imgObj.filters.push(new filters.HueRotation({ rotation: 0.55 }));\n          imgObj.filters.push(new filters.Contrast({ contrast: 0.15 }));\n          imgObj.filters.push(new filters.Saturation({ saturation: 0.25 }));\n          break;\n        case 'polar':\n          imgObj.filters.push(new filters.HueRotation({ rotation: -0.15 }));\n          imgObj.filters.push(new filters.Brightness({ brightness: -0.05 }));\n          imgObj.filters.push(new filters.Contrast({ contrast: 0.1 }));\n          imgObj.filters.push(new filters.Saturation({ saturation: -0.05 }));\n          break;\n        case 'sunset':\n          imgObj.filters.push(new filters.HueRotation({ rotation: 0.05 }));\n          imgObj.filters.push(new filters.Saturation({ saturation: 0.2 }));\n          imgObj.filters.push(new filters.Contrast({ contrast: 0.05 }));\n          break;\n        case 'fade':\n          imgObj.filters.push(new filters.Contrast({ contrast: -0.15 }));\n          imgObj.filters.push(new filters.Brightness({ brightness: 0.05 }));\n          imgObj.filters.push(new filters.Saturation({ saturation: -0.1 }));\n          break;\n        case 'noir':\n          imgObj.filters.push(new filters.Grayscale());\n          imgObj.filters.push(new filters.Contrast({ contrast: 0.25 }));\n          imgObj.filters.push(new filters.Brightness({ brightness: -0.05 }));\n          break;\n      }\n    }\n\n    // Apply individual sliders (if they have non-default values)\n    if (settings.brightness !== 0) {\n      imgObj.filters.push(new filters.Brightness({ brightness: settings.brightness }));\n    }\n    if (settings.contrast !== 0) {\n      imgObj.filters.push(new filters.Contrast({ contrast: settings.contrast }));\n    }\n    if (settings.saturation !== 0) {\n      imgObj.filters.push(new filters.Saturation({ saturation: settings.saturation }));\n    }\n    if (settings.blur !== 0) {\n      imgObj.filters.push(new filters.Blur({ blur: settings.blur }));\n    }\n    if (settings.hueRotation !== 0) {\n      imgObj.filters.push(new filters.HueRotation({ rotation: settings.hueRotation }));\n    }\n    if (settings.exposure !== undefined && settings.exposure !== 0) {\n      const gVal = 1 / (1 + settings.exposure);\n      imgObj.filters.push(new filters.Gamma({ gamma: [gVal, gVal, gVal] }));\n    }\n    if (settings.invert) {\n      imgObj.filters.push(new filters.Invert());\n    }\n\n    {\n      const black = settings.levelsBlack ?? 0;\n      const mid = settings.levelsMid ?? 1;\n      const white = settings.levelsWhite ?? 255;\n      if (!(black === 0 && mid === 1 && white === 255)) {\n        imgObj.filters.push(new LevelsFilter({ black, mid, white }));\n      }\n    }\n    if (settings.lut && settings.lut.length === 256) {\n      imgObj.filters.push(new LUTFilter({ lut: settings.lut }));\n    }\n\n    const hasCustomFilter = imgObj.filters.some((f: any) => \n      f instanceof LevelsFilter || f instanceof LUTFilter || f instanceof AdvancedHSLFilter\n    );\n    applyFabricImageFilters(imgObj, hasCustomFilter);\n    canvasInstance.requestRenderAll();\n  };\n\n  const resetAllFilters = () => {\n    if (!canvasInstance || !activeObject || activeObject.type !== 'image') return;\n    const imgObj = activeObject as any;\n    \n    imgObj.filters = [];\n    \n    // Reset special effects and blend modes\n    imgObj.set({\n      shadow: null,\n      stroke: null,\n      strokeWidth: 0,\n      globalCompositeOperation: 'source-over',\n    });\n    setShapeShadowEnabled(false);\n    \n    imgObj.applyFilters();\n    canvasInstance.requestRenderAll();\n\n    updateImageSettings({\n      brightness: 0,\n      contrast: 0,\n      saturation: 0,\n      blur: 0,\n      hueRotation: 0,\n      exposure: 0,\n      invert: false,\n      activePreset: 'original',\n    });\n  };\n\n  const startComparing = () => {\n    if (!canvasInstance || !activeObject || activeObject.type !== 'image') return;\n    const imgObj = activeObject as any;\n    \n    // Store original effects\n    imgObj.__originalEffects = {\n      shadow: imgObj.shadow,\n      stroke: imgObj.stroke,\n      strokeWidth: imgObj.strokeWidth,\n      globalCompositeOperation: imgObj.globalCompositeOperation,\n    };\n    \n    // Clear effects\n    imgObj.set({\n      shadow: null,\n      stroke: null,\n      strokeWidth: 0,\n      globalCompositeOperation: 'source-over',\n    });\n    \n    imgObj.filters = [];\n    imgObj.applyFilters();\n    canvasInstance.requestRenderAll();\n    setIsComparing(true);\n  };\n\n  const stopComparing = () => {\n    if (!isComparing) return;\n    \n    if (activeObject && activeObject.type === 'image') {\n      const imgObj = activeObject as any;\n      if (imgObj.__originalEffects) {\n        imgObj.set(imgObj.__originalEffects);\n        delete imgObj.__originalEffects;\n      }\n    }\n    \n    reapplyAllFilters(imageSettings);\n    setIsComparing(false);\n  };\n\n  const saveFilterHistory = () => {\n    saveHistoryState();\n  };\n\n  // currentGradStart/End/Angle eliminados: ahora viven en el panel flotante de CanvasArea (T-20260706-05)\n\n  return (\n    <div className={`flex-shrink-0 flex text-dark-200 select-none transition-all duration-300 ease-in-out z-30 ${sidebarCollapsed ? 'w-0 md:w-16 overflow-hidden md:overflow-visible border-r-0 md:border-r md:border-r-dark-850 bg-dark-950 md:bg-dark-900' : 'w-80 border-r border-dark-850 absolute md:relative left-0 h-full shadow-2xl md:shadow-none bg-dark-900'}`}>\n      {/* Icon Navigation (Figma-style tabs) */}\n      <div className=\"w-16 flex flex-col items-center py-4 gap-4 border-r border-dark-850 bg-dark-950 flex-shrink-0 overflow-y-auto scrollbar-none relative\">\n        <button\n          onClick={() => setActiveTab('canvas')}\n          className={`p-3 rounded-lg transition-all relative group ${activeTab === 'canvas' ? 'bg-dark-800 text-brand-400' : 'text-dark-400 hover:text-dark-100'}`}\n        >\n          <Settings size={20} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble left-full top-1/2 -translate-y-1/2 ml-2 hidden group-hover:block whitespace-nowrap bg-dark-800 text-white px-2 py-1 rounded z-50\">{t.sidebar.tab.canvas}</TextBody>\n        </button>\n        <button\n          onClick={() => setActiveTab('upload')}\n          className={`p-3 rounded-lg transition-all relative group ${activeTab === 'upload' ? 'bg-dark-800 text-brand-400' : 'text-dark-400 hover:text-dark-100'}`}\n        >\n          <UploadCloud size={20} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble left-full top-1/2 -translate-y-1/2 ml-2 hidden group-hover:block whitespace-nowrap bg-dark-800 text-white px-2 py-1 rounded z-50\">{t.sidebar.tab.upload}</TextBody>\n        </button>\n        <button\n          onClick={() => {\n            setActiveTab('shapes');\n            setActiveTool('select');\n          }}\n          className={`p-3 rounded-lg transition-all relative group ${activeTab === 'shapes' ? 'bg-dark-800 text-brand-400' : 'text-dark-400 hover:text-dark-100'}`}\n        >\n          <Square size={20} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble left-full top-1/2 -translate-y-1/2 ml-2 hidden group-hover:block whitespace-nowrap bg-dark-800 text-white px-2 py-1 rounded z-50\">{t.sidebar.tab.shapes}</TextBody>\n        </button>\n        {/* TAB: FRAMES \u2014 movido al panel flotante en CanvasArea (T-20260706-12). Bot\u00F3n oculto. */}\n        <button\n          onClick={() => {\n            setActiveTab('brush');\n            setActiveTool('brush');\n          }}\n          className={`p-3 rounded-lg transition-all relative group ${activeTab === 'brush' || activeTool === 'brush' ? 'bg-dark-800 text-brand-400' : 'text-dark-400 hover:text-dark-100'}`}\n        >\n          <Brush size={20} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble left-full top-1/2 -translate-y-1/2 ml-2 hidden group-hover:block whitespace-nowrap bg-dark-800 text-white px-2 py-1 rounded z-50\">{t.sidebar.tab.brush}</TextBody>\n        </button>\n        {/* TAB: TEXTO \u2014 movido al panel flotante en CanvasArea (T-20260706-13). Bot\u00F3n oculto. */}\n        <button\n          onClick={() => setActiveTab('filtros')}\n          className={`p-3 rounded-lg transition-all relative group ${activeTab === 'filtros' ? 'bg-dark-800 text-brand-400' : 'text-dark-400 hover:text-dark-100'}`}\n          disabled={!activeObject || activeObject.type !== 'image'}\n          style={{ opacity: !activeObject || activeObject.type !== 'image' ? 0.35 : 1 }}\n        >\n          <Sliders size={20} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble left-full top-1/2 -translate-y-1/2 ml-2 hidden group-hover:block whitespace-nowrap bg-dark-800 text-white px-2 py-1 rounded z-50\">{t.sidebar.tab.filtros}</TextBody>\n        </button>\n        {/* TAB: AI STUDIO \u2014 movido al panel flotante en CanvasArea (T-20260706-14). Bot\u00F3n oculto. */}\n        <button\n          onClick={() => setActiveTab('brand')}\n          className={`p-3 rounded-lg transition-all relative group ${activeTab === 'brand' ? 'bg-dark-800 text-brand-400' : 'text-dark-400 hover:text-dark-100'}`}\n        >\n          <Palette size={20} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble left-full top-1/2 -translate-y-1/2 ml-2 hidden group-hover:block whitespace-nowrap bg-dark-800 text-white px-2 py-1 rounded z-50\">{t.sidebar.tab.brand}</TextBody>\n        </button>\n        {/* TAB: DATOS \u2014 movido al panel flotante de Figuras/Formas en CanvasArea (T-20260706-XX). Bot\u00F3n oculto. */}\n      </div>\n\n      {/* Tab Contents (Settings panels) */}\n      <div \n        className=\"flex-1 p-5 overflow-y-auto flex flex-col gap-6 bg-dark-900 transition-all duration-300 ease-in-out border-r border-dark-850\"\n        style={{\n          width: sidebarCollapsed ? '0px' : '256px',\n          padding: sidebarCollapsed ? '0px' : '20px',\n          opacity: sidebarCollapsed ? 0 : 1,\n          pointerEvents: sidebarCollapsed ? 'none' : 'auto',\n          overflow: sidebarCollapsed ? 'hidden' : 'auto'\n        }}\n      >\n        \n        {/* TAB 1: CANVAS \u2014 vaciado en T-20260706-08 (todo el contenido vive ahora en paneles flotantes del toolstrip) */}\n\n        {/* TAB 2: UPLOAD \u2014 el contenido de subida (drag&drop, URL, historial, stock) se movi\u00F3 al panel flotante del toolstrip (T-20260706-10). */}\n\n        {/* Real Stock API Explorer Modal \u2014 se mantiene en el Sidebar y se abre desde el panel flotante v\u00EDa evento personalizado */}\n        {isStockExplorerOpen && (\n              <div className=\"fixed inset-0 z-[100] flex items-center justify-center bg-black/75 backdrop-blur-sm p-4 animate-fade-in\">\n                <div className=\"fixed inset-0 cursor-default\" onClick={() => setIsStockExplorerOpen(false)} />\n                <div className=\"relative w-full max-w-4xl bg-dark-900 border border-dark-800 rounded-2xl shadow-2xl overflow-hidden flex flex-col h-[80vh] max-h-[700px] z-10\">\n                  {/* Header */}\n                  <div className=\"p-4 border-b border-dark-800 flex justify-between items-center bg-dark-950/40\">\n                    <div>\n                      <TextTitle as=\"h3\" size=\"sm\" className=\"uppercase tracking-wider\">{t.sidebar.stock.title}</TextTitle>\n                      <TextBody as=\"p\" size=\"sm\" className=\"mt-0.5 text-dark-400\">{t.sidebar.stock.subtitle}</TextBody>\n                    </div>\n                    <button onClick={() => setIsStockExplorerOpen(false)} className=\"p-1 rounded-md text-dark-400 hover:text-white hover:bg-dark-800 transition-colors cursor-pointer\">\n                      <X size={18} />\n                    </button>\n                  </div>\n\n                  {/* Controls */}\n                  <div className=\"p-3 border-b border-dark-800 bg-dark-900/60 flex flex-col gap-2\">\n                    {/* Search */}\n                    <div className=\"relative\">\n                      <Search size={12} className=\"absolute left-2.5 top-1/2 -translate-y-1/2 text-dark-500\" />\n                      <input type=\"text\" value={stockInputValue} onChange={e => handleStockInputChange(e.target.value)}\n                        placeholder={t.sidebar.stock.searchPlaceholder}\n                        className=\"w-full bg-dark-950 border border-dark-800 rounded pl-7 pr-3 py-1.5 text-xs text-white placeholder-dark-500 focus:outline-none focus:border-brand-500\" />\n                    </div>\n                    {/* Category chips */}\n                    <div className=\"flex gap-1 flex-wrap\">\n                      {STOCK_CATEGORIES_REAL.map(cat => (\n                        <button key={cat.label} onClick={() => {\n                          if (stockActiveCategory === cat.label) { setStockActiveCategory(null); setStockInputValue(''); setStockQuery(''); }\n                          else { setStockActiveCategory(cat.label); setStockInputValue(''); setStockQuery(cat.query); }\n                        }}\n                          className={`px-2 py-0.5 rounded-full text-[8px] font-semibold transition-all ${ stockActiveCategory === cat.label ? 'bg-brand-600 text-white' : 'bg-dark-850 text-dark-400 hover:text-white' }`}>\n                          {cat.label}\n                        </button>\n                      ))}\n                    </div>\n                  </div>\n\n                  {/* Photo Grid */}\n                  <div ref={stockScrollRef} className=\"flex-1 overflow-y-auto p-3 bg-dark-900/40\">\n                    {stockIsLoading && stockPhotos.length === 0 ? (\n                      <div className=\"grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 gap-2\">\n                        {Array.from({ length: 15 }).map((_, i) => <div key={i} className=\"h-24 rounded-xl bg-dark-850 animate-pulse\" style={{ animationDelay: `${i * 60}ms` }} />)}\n                      </div>\n                    ) : stockPhotos.length === 0 && !stockIsLoading ? (\n                      <div className=\"h-40 flex flex-col items-center justify-center text-dark-400 text-xs\">\n                        <Search size={22} className=\"mb-2 opacity-30\" />\n                        {t.sidebar.stock.emptyResults}\n                      </div>\n                    ) : (\n                      <div className=\"grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 gap-2\">\n                        {stockPhotos.map(photo => (\n                          <div key={photo.id} onClick={() => handleStockAddToCanvas(photo)}\n                            className=\"group relative h-24 rounded-xl overflow-hidden border border-dark-800 bg-dark-850 cursor-pointer hover:border-brand-500 hover:shadow-lg transition-all hover:-translate-y-0.5\">\n                            <img\n                              src={photo.thumbnailUrl}\n                              alt={photo.alt}\n                              onError={e => { (e.target as HTMLImageElement).style.opacity = '0'; }}\n                              className=\"w-full h-full object-cover group-hover:scale-105 transition-transform duration-300\"\n                              draggable={true}\n                              onDragStart={(e) => {\n                                e.dataTransfer.setData('text/plain', photo.regularUrl);\n                                e.dataTransfer.setData('image/name', photo.alt || 'Stock Image');\n                              }}\n                            />\n                            {/* Provider dot */}\n                            <div className=\"absolute top-1 right-1 w-2.5 h-2.5 rounded-full\" style={{ backgroundColor: photo.provider === 'unsplash' ? '#00E676' : '#05A081' }} />\n                            <div className=\"absolute inset-0 bg-gradient-to-t from-black/85 via-black/20 to-transparent flex flex-col justify-end p-2 opacity-0 group-hover:opacity-100 transition-opacity\">\n                              <TextBody as=\"span\" size=\"sm\" className=\"truncate leading-tight font-bold text-white\">{photo.alt || photo.photographer}</TextBody>\n                              <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400\">by {photo.photographer}</TextBody>\n                            </div>\n                            {stockAddingId === photo.id && (\n                              <div className=\"absolute inset-0 flex items-center justify-center bg-black/60\">\n                                <div className=\"w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin\" />\n                              </div>\n                            )}\n                          </div>\n                        ))}\n                      </div>\n                    )}\n                    {/* Infinite scroll sentinel */}\n                    <div ref={stockSentinelRef} className=\"py-4 flex justify-center\">\n                      {stockIsLoadingMore && <div className=\"w-5 h-5 border-2 border-brand-500 border-t-transparent rounded-full animate-spin\" />}\n                    </div>\n                    {/* Attribution \u2014 derived from actual result providers */}\n                    {stockPhotos.length > 0 && (\n                      <div className=\"flex justify-center gap-4 pt-2 pb-1 flex-wrap\">\n                        {Array.from(new Set(stockPhotos.map((p) => p.provider))).map((provider) => {\n                          const homeUrl =\n                            provider === 'unsplash'\n                              ? 'https://unsplash.com'\n                              : provider === 'pexels'\n                              ? 'https://www.pexels.com'\n                              : null;\n                          const label = t.sidebar.stock.poweredBy(provider);\n                          return homeUrl ? (\n                            <a key={provider} href={homeUrl} target=\"_blank\" rel=\"noreferrer\" className=\"text-[8px] text-dark-500 hover:text-white\">\n                              {label} \u2197\n                            </a>\n                          ) : (\n                            <TextBody as=\"span\" size=\"sm\" className=\"text-dark-500\">\n                              {label}\n                            </TextBody>\n                          );\n                        })}\n                      </div>\n                    )}\n                  </div>\n                 </div>\n                </div>\n              )}\n\n         {/* TAB 3: SHAPES \u2014 la galer\u00EDa de figuras/formas se movi\u00F3 al panel flotante del toolstrip (T-20260706-08). Aqu\u00ED solo queda el editor de propiedades del objeto activo. */}\n        {activeTab === 'shapes' && (\n          <div className=\"flex flex-col gap-4 p-2\">\n            <div>\n              <TextTitle as=\"h3\" size=\"sm\" className=\"mb-1 uppercase tracking-wider\">{t.properties.shape.adjustShape}</TextTitle>\n              <TextBody as=\"p\" size=\"sm\" className=\"mb-3 text-dark-400\">{t.properties.shape.editShapeHint}</TextBody>\n            </div>\n\n            {/* Premium Interactive Vector Properties Editor */}\n            {activeObject && ['rect', 'circle', 'triangle', 'line', 'ellipse', 'polygon', 'path', 'group', 'image'].includes(activeObject.type || '') && (\n              <div className=\"flex flex-col gap-4 mt-2 border-t border-dark-800 pt-4\">\n                <div className=\"flex items-center justify-between\">\n                  <TextBody as=\"label\" size=\"sm\" className=\"text-white uppercase tracking-wider\">{t.properties.shape.adjustShape}</TextBody>\n                  <TextBody as=\"span\" size=\"sm\" className=\"bg-brand-500/10 text-brand-400 border border-brand-500/20 px-1.5 py-0.5 rounded font-mono capitalize\">\n                    {activeObject.type === 'path' ? t.properties.shape.shapeBadge.vector : activeObject.type === 'rect' ? t.properties.shape.shapeBadge.rect : activeObject.type === 'group' ? t.properties.shape.shapeBadge.frame : activeObject.type}\n                  </TextBody>\n                </div>\n\n                {/* Section 2: Fill Style */}\n                {activeObject.type !== 'line' && activeObject.type !== 'image' && (\n                  <div className=\"bg-dark-950/40 border border-dark-800 rounded-lg p-2.5 flex flex-col gap-2\">\n                    <TextBody as=\"span\" size=\"sm\" className=\"uppercase text-dark-400 tracking-wider block mb-1\">{t.properties.shape.shapeFill}</TextBody>\n\n                    {/* Fill Tabs */}\n                    <div className=\"flex bg-dark-900 p-0.5 rounded border border-dark-800 mb-2\">\n                      <button\n                        onClick={() => {\n                          setShapeFillTab('solid');\n                          activeObject.set({ fill: shapeGradStart });\n                          canvasInstance?.requestRenderAll();\n                          saveHistoryState();\n                          setSidebarUpdateTrigger(t => t + 1);\n                        }}\n                        className={`flex-1 py-1 text-[10px] font-bold rounded transition-all cursor-pointer ${\n                          shapeFillTab === 'solid' ? 'bg-dark-750 text-white shadow' : 'text-dark-400 hover:text-dark-200'\n                        }`}\n                      >\n                        {t.properties.shape.fillSolid}\n                      </button>\n                      <button\n                        onClick={() => {\n                          setShapeFillTab('gradient');\n                          // Trigger gradient creation with local colors\n                          const w = activeObject.width || 100;\n                          const h = activeObject.height || 100;\n                          const rad = (shapeGradAngle * Math.PI) / 180;\n                          const coords = {\n                            x1: w / 2 - Math.cos(rad) * (w / 2),\n                            y1: h / 2 - Math.sin(rad) * (h / 2),\n                            x2: w / 2 + Math.cos(rad) * (w / 2),\n                            y2: h / 2 + Math.sin(rad) * (h / 2),\n                          };\n                          const grad = new Gradient({\n                            type: 'linear',\n                            coords,\n                            colorStops: [\n                              { offset: 0, color: shapeGradStart },\n                              { offset: 1, color: shapeGradEnd }\n                            ]\n                          });\n                          activeObject.set({ fill: grad });\n                          canvasInstance?.requestRenderAll();\n                          saveHistoryState();\n                          setSidebarUpdateTrigger(t => t + 1);\n                        }}\n                        className={`flex-1 py-1 text-[10px] font-bold rounded transition-all cursor-pointer ${\n                          shapeFillTab === 'gradient' ? 'bg-dark-750 text-white shadow' : 'text-dark-400 hover:text-dark-200'\n                        }`}\n                      >\n                        {t.properties.shape.fillGradient}\n                      </button>\n                      <button\n                        onClick={() => {\n                          setShapeFillTab('none');\n                          activeObject.set({ fill: 'transparent' });\n                          canvasInstance?.requestRenderAll();\n                          saveHistoryState();\n                          setSidebarUpdateTrigger(t => t + 1);\n                        }}\n                        className={`flex-1 py-1 text-[10px] font-bold rounded transition-all cursor-pointer ${\n                          shapeFillTab === 'none' ? 'bg-dark-750 text-white shadow' : 'text-dark-400 hover:text-dark-200'\n                        }`}\n                      >\n                        {t.properties.shape.fillNone}\n                      </button>\n                    </div>\n\n                    {/* Fill Details based on Active Tab */}\n                    {shapeFillTab === 'solid' && (\n                      <div className=\"flex flex-col gap-2 animate-fade-in\">\n                        <div className=\"flex gap-2 items-center\">\n                          <input\n                            type=\"color\"\n                            value={typeof activeObject.fill === 'string' && activeObject.fill !== 'transparent' ? activeObject.fill : '#3b82f6'}\n                            onChange={(e) => {\n                              activeObject.set({ fill: e.target.value });\n                              setShapeGradStart(e.target.value);\n                              canvasInstance?.requestRenderAll();\n                              saveHistoryState();\n                              setSidebarUpdateTrigger(t => t + 1);\n                            }}\n                            className=\"w-10 h-8 rounded border border-dark-800 bg-transparent cursor-pointer flex-shrink-0\"\n                          />\n                          <input\n                            type=\"text\"\n                            value={typeof activeObject.fill === 'string' && activeObject.fill !== 'transparent' ? activeObject.fill.toUpperCase() : t.panel.transparent}\n                            onChange={(e) => {\n                              const val = e.target.value;\n                              if (val.match(/^#[0-9A-F]{6}$/i) || val.match(/^#[0-9A-F]{3}$/i)) {\n                                activeObject.set({ fill: val });\n                                setShapeGradStart(val);\n                                canvasInstance?.requestRenderAll();\n                                saveHistoryState();\n                                setSidebarUpdateTrigger(t => t + 1);\n                              }\n                            }}\n                            placeholder=\"#FFFFFF\"\n                            className=\"bg-dark-900 border border-dark-800 text-xs font-mono font-bold text-white rounded px-2.5 py-1.5 flex-1 min-w-0 focus:outline-none focus:border-brand-500\"\n                          />\n                        </div>\n\n                        {/* Presets Grid */}\n                        <div className=\"grid grid-cols-6 gap-1 mt-1\">\n                          {SOLID_PRESETS.map((color) => (\n                            <button\n                              key={color}\n                              onClick={() => {\n                                activeObject.set({ fill: color });\n                                setShapeGradStart(color);\n                                canvasInstance?.requestRenderAll();\n                                saveHistoryState();\n                                setSidebarUpdateTrigger(t => t + 1);\n                              }}\n                              className=\"w-6 h-6 rounded border border-dark-900 shadow-sm transition-transform hover:scale-115 cursor-pointer relative\"\n                              style={{ backgroundColor: color }}\n                              title={color}\n                            >\n                              {activeObject.fill === color && (\n                                <span className=\"absolute inset-0 m-auto w-1.5 h-1.5 bg-white rounded-full mix-blend-difference\" />\n                              )}\n                            </button>\n                          ))}\n                        </div>\n\n                        {extractedColors.length > 0 && (\n                          <div className=\"flex flex-col gap-1.5 mt-2.5\">\n                            <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400 uppercase tracking-wider\">{t.properties.shape.imageColors}</TextBody>\n                            <div className=\"flex gap-1.5 flex-wrap\">\n                              {extractedColors.map((color) => (\n                                <button\n                                  key={color}\n                                  onClick={() => {\n                                    activeObject.set({ fill: color });\n                                    setShapeGradStart(color);\n                                    canvasInstance?.requestRenderAll();\n                                    saveHistoryState();\n                                    setSidebarUpdateTrigger(t => t + 1);\n                                  }}\n                                  className=\"w-6 h-6 rounded border border-dark-900 shadow-sm transition-transform hover:scale-115 cursor-pointer relative\"\n                                  style={{ backgroundColor: color }}\n                                  title={color}\n                                >\n                                  {activeObject.fill === color && (\n                                    <span className=\"absolute inset-0 m-auto w-1.5 h-1.5 bg-white rounded-full mix-blend-difference\" />\n                                  )}\n                                </button>\n                              ))}\n                            </div>\n                          </div>\n                        )}\n                      </div>\n                    )}\n\n                    {shapeFillTab === 'gradient' && (\n                      <div className=\"flex flex-col gap-2.5 animate-fade-in\">\n                        {/* Gradient Colors */}\n                        <div className=\"grid grid-cols-2 gap-2\">\n                          <div className=\"flex flex-col gap-1\">\n                            <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400\">{t.properties.shape.start}</TextBody>\n                            <div className=\"flex items-center gap-1.5 bg-dark-900 border border-dark-800 rounded px-1.5 py-1\">\n                              <input\n                                type=\"color\"\n                                value={shapeGradStart}\n                                onChange={(e) => {\n                                  const cStart = e.target.value;\n                                  setShapeGradStart(cStart);\n                                  // Reapply\n                                  const w = activeObject.width || 100;\n                                  const h = activeObject.height || 100;\n                                  const rad = (shapeGradAngle * Math.PI) / 180;\n                                  const coords = {\n                                    x1: w / 2 - Math.cos(rad) * (w / 2),\n                                    y1: h / 2 - Math.sin(rad) * (h / 2),\n                                    x2: w / 2 + Math.cos(rad) * (w / 2),\n                                    y2: h / 2 + Math.sin(rad) * (h / 2),\n                                  };\n                                  const grad = new Gradient({\n                                    type: 'linear',\n                                    coords,\n                                    colorStops: [\n                                      { offset: 0, color: cStart },\n                                      { offset: 1, color: shapeGradEnd }\n                                    ]\n                                  });\n                                  activeObject.set({ fill: grad });\n                                  canvasInstance?.requestRenderAll();\n                                  saveHistoryState();\n                                }}\n                                className=\"w-5 h-5 rounded cursor-pointer border border-dark-800 bg-transparent flex-shrink-0\"\n                              />\n                              <input\n                                type=\"text\"\n                                value={shapeGradStart.toUpperCase()}\n                                onChange={(e) => {\n                                  const val = e.target.value;\n                                  if (val.match(/^#[0-9A-F]{6}$/i)) {\n                                    setShapeGradStart(val);\n                                    // Reapply\n                                    const w = activeObject.width || 100;\n                                    const h = activeObject.height || 100;\n                                    const rad = (shapeGradAngle * Math.PI) / 180;\n                                    const coords = {\n                                      x1: w / 2 - Math.cos(rad) * (w / 2),\n                                      y1: h / 2 - Math.sin(rad) * (h / 2),\n                                      x2: w / 2 + Math.cos(rad) * (w / 2),\n                                      y2: h / 2 + Math.sin(rad) * (h / 2),\n                                    };\n                                    const grad = new Gradient({\n                                      type: 'linear',\n                                      coords,\n                                      colorStops: [\n                                        { offset: 0, color: val },\n                                        { offset: 1, color: shapeGradEnd }\n                                      ]\n                                    });\n                                    activeObject.set({ fill: grad });\n                                    canvasInstance?.requestRenderAll();\n                                    saveHistoryState();\n                                  }\n                                }}\n                                className=\"bg-transparent text-[10px] text-white font-mono focus:outline-none w-full font-bold\"\n                              />\n                            </div>\n                          </div>\n\n                          <div className=\"flex flex-col gap-1\">\n                            <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400\">{t.properties.shape.end}</TextBody>\n                            <div className=\"flex items-center gap-1.5 bg-dark-900 border border-dark-800 rounded px-1.5 py-1\">\n                              <input\n                                type=\"color\"\n                                value={shapeGradEnd}\n                                onChange={(e) => {\n                                  const cEnd = e.target.value;\n                                  setShapeGradEnd(cEnd);\n                                  // Reapply\n                                  const w = activeObject.width || 100;\n                                  const h = activeObject.height || 100;\n                                  const rad = (shapeGradAngle * Math.PI) / 180;\n                                  const coords = {\n                                    x1: w / 2 - Math.cos(rad) * (w / 2),\n                                    y1: h / 2 - Math.sin(rad) * (h / 2),\n                                    x2: w / 2 + Math.cos(rad) * (w / 2),\n                                    y2: h / 2 + Math.sin(rad) * (h / 2),\n                                  };\n                                  const grad = new Gradient({\n                                    type: 'linear',\n                                    coords,\n                                    colorStops: [\n                                      { offset: 0, color: shapeGradStart },\n                                      { offset: 1, color: cEnd }\n                                    ]\n                                  });\n                                  activeObject.set({ fill: grad });\n                                  canvasInstance?.requestRenderAll();\n                                  saveHistoryState();\n                                }}\n                                className=\"w-5 h-5 rounded cursor-pointer border border-dark-800 bg-transparent flex-shrink-0\"\n                              />\n                              <input\n                                type=\"text\"\n                                value={shapeGradEnd.toUpperCase()}\n                                onChange={(e) => {\n                                  const val = e.target.value;\n                                  if (val.match(/^#[0-9A-F]{6}$/i)) {\n                                    setShapeGradEnd(val);\n                                    // Reapply\n                                    const w = activeObject.width || 100;\n                                    const h = activeObject.height || 100;\n                                    const rad = (shapeGradAngle * Math.PI) / 180;\n                                    const coords = {\n                                      x1: w / 2 - Math.cos(rad) * (w / 2),\n                                      y1: h / 2 - Math.sin(rad) * (h / 2),\n                                      x2: w / 2 + Math.cos(rad) * (w / 2),\n                                      y2: h / 2 + Math.sin(rad) * (h / 2),\n                                    };\n                                    const grad = new Gradient({\n                                      type: 'linear',\n                                      coords,\n                                      colorStops: [\n                                        { offset: 0, color: shapeGradStart },\n                                        { offset: 1, color: val }\n                                      ]\n                                    });\n                                    activeObject.set({ fill: grad });\n                                    canvasInstance?.requestRenderAll();\n                                    saveHistoryState();\n                                  }\n                                }}\n                                className=\"bg-transparent text-[10px] text-white font-mono focus:outline-none w-full font-bold\"\n                              />\n                            </div>\n                          </div>\n                        </div>\n\n                        {/* Angle Slider */}\n                        <div className=\"flex flex-col gap-1.5 mt-1\">\n                          <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400\">{t.properties.shape.gradientAngle}</TextBody>\n                          <div className=\"flex items-center gap-2\">\n                            <input\n                              type=\"range\"\n                              min=\"0\"\n                              max=\"360\"\n                              value={shapeGradAngle}\n                              onChange={(e) => {\n                                const angle = parseInt(e.target.value);\n                                setShapeGradAngle(angle);\n                                // Reapply\n                                const w = activeObject.width || 100;\n                                const h = activeObject.height || 100;\n                                const rad = (angle * Math.PI) / 180;\n                                const coords = {\n                                  x1: w / 2 - Math.cos(rad) * (w / 2),\n                                  y1: h / 2 - Math.sin(rad) * (h / 2),\n                                  x2: w / 2 + Math.cos(rad) * (w / 2),\n                                  y2: h / 2 + Math.sin(rad) * (h / 2),\n                                };\n                                const grad = new Gradient({\n                                  type: 'linear',\n                                  coords,\n                                  colorStops: [\n                                    { offset: 0, color: shapeGradStart },\n                                    { offset: 1, color: shapeGradEnd }\n                                  ]\n                                });\n                                activeObject.set({ fill: grad });\n                                canvasInstance?.requestRenderAll();\n                                saveHistoryState();\n                              }}\n                              className=\"flex-1 accent-brand-500 bg-dark-800 h-1.5 rounded-lg appearance-none cursor-pointer\"\n                            />\n                            <span className=\"text-xs text-white font-mono font-bold w-12 text-right\">{shapeGradAngle}\u00B0</span>\n                          </div>\n                        </div>\n                      </div>\n                    )}\n\n                    {shapeFillTab === 'none' && (\n                      <div className=\"text-[10px] text-center text-dark-500 py-3 border border-dashed border-dark-800 rounded bg-dark-900/20 font-medium italic animate-fade-in\">\n                        La figura no tiene color de relleno (transparente).\n                      </div>\n                    )}\n                  </div>\n                )}\n\n                {/* Section 3: Advanced Outline / Stroke */}\n                <div className=\"bg-dark-950/40 border border-dark-800 rounded-lg p-2.5 flex flex-col gap-2.5\">\n                  <TextBody as=\"span\" size=\"sm\" className=\"uppercase text-dark-400 tracking-wider block\">{t.properties.shape.stroke}</TextBody>\n                  \n                  {/* Stroke Color */}\n                  <div className=\"flex gap-2 items-center\">\n                    <input\n                      type=\"color\"\n                      value={typeof activeObject.stroke === 'string' && activeObject.stroke !== 'transparent' ? activeObject.stroke : '#000000'}\n                      onChange={(e) => {\n                        activeObject.set({ stroke: e.target.value });\n                        canvasInstance?.requestRenderAll();\n                        saveHistoryState();\n                        setSidebarUpdateTrigger(t => t + 1);\n                      }}\n                      className=\"w-8 h-8 rounded border border-dark-800 bg-transparent cursor-pointer flex-shrink-0\"\n                    />\n                    <input\n                      type=\"text\"\n                      value={typeof activeObject.stroke === 'string' && activeObject.stroke !== 'transparent' ? activeObject.stroke.toUpperCase() : '#000000'}\n                      onChange={(e) => {\n                        const val = e.target.value;\n                        if (val.match(/^#[0-9A-F]{6}$/i) || val.match(/^#[0-9A-F]{3}$/i)) {\n                          activeObject.set({ stroke: val });\n                          canvasInstance?.requestRenderAll();\n                          saveHistoryState();\n                          setSidebarUpdateTrigger(t => t + 1);\n                        }\n                      }}\n                      placeholder=\"#000000\"\n                      className=\"bg-dark-900 border border-dark-800 text-[10px] font-mono font-bold text-white rounded px-2 py-1 flex-1 min-w-0 focus:outline-none focus:border-brand-500\"\n                    />\n                  </div>\n\n                  {/* Stroke Width */}\n                  <div className=\"flex flex-col gap-1 mt-1\">\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400\">{t.properties.shape.strokeThickness}</TextBody>\n                    <div className=\"flex items-center gap-2\">\n                      <input\n                        type=\"range\"\n                        min=\"0\"\n                        max=\"30\"\n                        value={activeObject.strokeWidth || 0}\n                        onChange={(e) => {\n                          const val = parseInt(e.target.value);\n                          activeObject.set({ strokeWidth: val });\n                          canvasInstance?.requestRenderAll();\n                          saveHistoryState();\n                          setSidebarUpdateTrigger(t => t + 1);\n                        }}\n                        className=\"flex-1 accent-brand-500 bg-dark-800 h-1.5 rounded-lg appearance-none cursor-pointer\"\n                      />\n                      <TextBody as=\"span\" size=\"sm\" className=\"w-12 text-right font-mono font-bold text-white\">\n                        {Math.round(activeObject.strokeWidth || 0)}px\n                      </TextBody>\n                    </div>\n                  </div>\n\n                  {/* Stroke Style */}\n                  <div className=\"flex flex-col gap-1.5\">\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400\">{t.properties.shape.strokeStyle}</TextBody>\n                    <div className=\"flex gap-1 bg-dark-900 p-0.5 rounded border border-dark-800\">\n                      <button\n                        onClick={() => {\n                          setShapeStrokeStyle('solid');\n                          activeObject.set({ strokeDashArray: null });\n                          canvasInstance?.requestRenderAll();\n                          saveHistoryState();\n                          setSidebarUpdateTrigger(t => t + 1);\n                        }}\n                        className={`flex-1 py-1 text-[9px] font-bold rounded cursor-pointer transition-all ${\n                          shapeStrokeStyle === 'solid' ? 'bg-dark-750 text-white shadow' : 'text-dark-400 hover:text-dark-200'\n                        }`}\n                      >\n                        {t.properties.shape.strokeSolid}\n                      </button>\n                      <button\n                        onClick={() => {\n                          setShapeStrokeStyle('dashed');\n                          activeObject.set({ strokeDashArray: [8, 8] });\n                          canvasInstance?.requestRenderAll();\n                          saveHistoryState();\n                          setSidebarUpdateTrigger(t => t + 1);\n                        }}\n                        className={`flex-1 py-1 text-[9px] font-bold rounded cursor-pointer transition-all ${\n                          shapeStrokeStyle === 'dashed' ? 'bg-dark-750 text-white shadow' : 'text-dark-400 hover:text-dark-200'\n                        }`}\n                      >\n                        {t.properties.shape.strokeDashed}\n                      </button>\n                      <button\n                        onClick={() => {\n                          setShapeStrokeStyle('dotted');\n                          activeObject.set({ strokeDashArray: [2, 6] });\n                          canvasInstance?.requestRenderAll();\n                          saveHistoryState();\n                          setSidebarUpdateTrigger(t => t + 1);\n                        }}\n                        className={`flex-1 py-1 text-[9px] font-bold rounded cursor-pointer transition-all ${\n                          shapeStrokeStyle === 'dotted' ? 'bg-dark-750 text-white shadow' : 'text-dark-400 hover:text-dark-200'\n                        }`}\n                      >\n                        {t.properties.shape.strokeDotted}\n                      </button>\n                    </div>\n                  </div>\n                </div>\n\n                {/* Section 4: Corner Radius (only for rectangle) */}\n                {activeObject.type === 'rect' && (\n                  <div className=\"bg-dark-950/40 border border-dark-800 rounded-lg p-2.5 flex flex-col gap-1.5\">\n                    <TextBody as=\"span\" size=\"sm\" className=\"uppercase text-dark-400 tracking-wider block mb-0.5\">{t.properties.shape.cornerRadius}</TextBody>\n                    <div className=\"flex items-center gap-2\">\n                      <input\n                        type=\"range\"\n                        min=\"0\"\n                        max=\"100\"\n                        value={(activeObject as any).rx || 0}\n                        onChange={(e) => {\n                          const val = parseInt(e.target.value);\n                          activeObject.set({ rx: val, ry: val });\n                          canvasInstance?.requestRenderAll();\n                          saveHistoryState();\n                          setSidebarUpdateTrigger(t => t + 1);\n                        }}\n                        className=\"flex-1 accent-brand-500 bg-dark-800 h-1.5 rounded-lg appearance-none cursor-pointer\"\n                      />\n                      <TextBody as=\"span\" size=\"sm\" className=\"w-12 text-right font-mono font-bold text-white\">\n                        {Math.round((activeObject as any).rx || 0)}px\n                      </TextBody>\n                    </div>\n                  </div>\n                )}\n\n                {/* Section 5: Drop Shadows */}\n                <div className=\"bg-dark-950/40 border border-dark-800 rounded-lg p-2.5 flex flex-col gap-2.5\">\n                  <div className=\"flex justify-between items-center\">\n                    <TextBody as=\"span\" size=\"sm\" className=\"uppercase text-dark-400 tracking-wider\">{t.properties.shape.objectShadow}</TextBody>\n                    <label className=\"relative inline-flex items-center cursor-pointer\">\n                      <input\n                        type=\"checkbox\"\n                        checked={shapeShadowEnabled}\n                        onChange={(e) => {\n                          const enabled = e.target.checked;\n                          setShapeShadowEnabled(enabled);\n                          \n                          if (enabled) {\n                            const shd = new Shadow({\n                              color: shapeShadowColor,\n                              blur: shapeShadowBlur,\n                              offsetX: shapeShadowOffsetX,\n                              offsetY: shapeShadowOffsetY\n                            });\n                            activeObject.set({ shadow: shd });\n                          } else {\n                            activeObject.set({ shadow: null });\n                          }\n                          canvasInstance?.requestRenderAll();\n                          saveHistoryState();\n                          setSidebarUpdateTrigger(t => t + 1);\n                        }}\n                        className=\"sr-only peer\"\n                      />\n                      <div className=\"w-7 h-4 bg-dark-800 rounded-full peer peer-focus:ring-0 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-3 after:w-3 after:transition-all peer-checked:bg-brand-600\"></div>\n                    </label>\n                  </div>\n\n                  {shapeShadowEnabled && (\n                    <div className=\"flex flex-col gap-2 animate-fade-in border-t border-dark-850 pt-2.5 mt-1\">\n                      {/* Shadow Color */}\n                      <div className=\"flex gap-2 items-center\">\n                        <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400 w-10 flex-shrink-0\">{t.properties.shape.shadowColor}</TextBody>\n                        <input\n                          type=\"color\"\n                          value={shapeShadowColor}\n                          onChange={(e) => {\n                            const col = e.target.value;\n                            setShapeShadowColor(col);\n                            const shd = new Shadow({\n                              color: col,\n                              blur: shapeShadowBlur,\n                              offsetX: shapeShadowOffsetX,\n                              offsetY: shapeShadowOffsetY\n                            });\n                            activeObject.set({ shadow: shd });\n                            canvasInstance?.requestRenderAll();\n                            saveHistoryState();\n                          }}\n                          className=\"w-7 h-7 rounded border border-dark-800 bg-transparent cursor-pointer flex-shrink-0\"\n                        />\n                        <input\n                          type=\"text\"\n                          value={shapeShadowColor.toUpperCase()}\n                          onChange={(e) => {\n                            const val = e.target.value;\n                            if (val.match(/^#[0-9A-F]{6}$/i)) {\n                              setShapeShadowColor(val);\n                              const shd = new Shadow({\n                                color: val,\n                                blur: shapeShadowBlur,\n                                offsetX: shapeShadowOffsetX,\n                                offsetY: shapeShadowOffsetY\n                              });\n                              activeObject.set({ shadow: shd });\n                              canvasInstance?.requestRenderAll();\n                              saveHistoryState();\n                            }\n                          }}\n                          className=\"bg-dark-900 border border-dark-800 text-[10px] font-mono font-bold text-white rounded px-2 py-0.5 flex-1 min-w-0 focus:outline-none focus:border-brand-500\"\n                        />\n                      </div>\n\n                      {/* Shadow Blur */}\n                      <div className=\"flex flex-col gap-1\">\n                        <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400\">{t.properties.shape.shadowBlur}</TextBody>\n                        <div className=\"flex items-center gap-2\">\n                          <input\n                            type=\"range\"\n                            min=\"0\"\n                            max=\"50\"\n                            value={shapeShadowBlur}\n                            onChange={(e) => {\n                              const blur = parseInt(e.target.value);\n                              setShapeShadowBlur(blur);\n                              const shd = new Shadow({\n                                color: shapeShadowColor,\n                                blur,\n                                offsetX: shapeShadowOffsetX,\n                                offsetY: shapeShadowOffsetY\n                              });\n                              activeObject.set({ shadow: shd });\n                              canvasInstance?.requestRenderAll();\n                              saveHistoryState();\n                            }}\n                            className=\"flex-1 accent-brand-500 bg-dark-800 h-1 rounded appearance-none cursor-pointer\"\n                          />\n                          <TextBody as=\"span\" size=\"sm\" className=\"text-white font-mono w-8 text-right\">{shapeShadowBlur}px</TextBody>\n                        </div>\n                      </div>\n\n                      {/* Shadow Offset X */}\n                      <div className=\"flex flex-col gap-1\">\n                        <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400\">Desplazamiento X</TextBody>\n                        <div className=\"flex items-center gap-2\">\n                          <input\n                            type=\"range\"\n                            min=\"-30\"\n                            max=\"30\"\n                            value={shapeShadowOffsetX}\n                            onChange={(e) => {\n                              const ox = parseInt(e.target.value);\n                              setShapeShadowOffsetX(ox);\n                              const shd = new Shadow({\n                                color: shapeShadowColor,\n                                blur: shapeShadowBlur,\n                                offsetX: ox,\n                                offsetY: shapeShadowOffsetY\n                              });\n                              activeObject.set({ shadow: shd });\n                              canvasInstance?.requestRenderAll();\n                              saveHistoryState();\n                            }}\n                            className=\"flex-1 accent-brand-500 bg-dark-800 h-1 appearance-none cursor-pointer\"\n                          />\n                          <TextBody as=\"span\" size=\"sm\" className=\"text-white font-mono w-8 text-right\">{shapeShadowOffsetX}px</TextBody>\n                        </div>\n                      </div>\n\n                      {/* Shadow Offset Y */}\n                      <div className=\"flex flex-col gap-1\">\n                        <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400\">Desplazamiento Y</TextBody>\n                        <div className=\"flex items-center gap-2\">\n                          <input\n                            type=\"range\"\n                            min=\"-30\"\n                            max=\"30\"\n                            value={shapeShadowOffsetY}\n                            onChange={(e) => {\n                              const oy = parseInt(e.target.value);\n                              setShapeShadowOffsetY(oy);\n                              const shd = new Shadow({\n                                color: shapeShadowColor,\n                                blur: shapeShadowBlur,\n                                offsetX: shapeShadowOffsetX,\n                                offsetY: oy\n                              });\n                              activeObject.set({ shadow: shd });\n                              canvasInstance?.requestRenderAll();\n                              saveHistoryState();\n                            }}\n                            className=\"flex-1 accent-brand-500 bg-dark-800 h-1 appearance-none cursor-pointer\"\n                          />\n                          <TextBody as=\"span\" size=\"sm\" className=\"text-white font-mono w-8 text-right\">{shapeShadowOffsetY}px</TextBody>\n                        </div>\n                      </div>\n\n                      {/* Moved Quick Presets Grid to be outside */}\n                    </div>\n                  )}\n                </div>\n\n                {/* Quick Presets Grid - Moved OUTSIDE of the toggle so it's always visible */}\n                <div className=\"bg-dark-950/40 border border-dark-800 rounded-lg p-2.5 flex flex-col gap-1.5\">\n                  <TextBody as=\"span\" size=\"sm\" className=\"uppercase text-dark-400 tracking-wider block mb-0.5\">{t.properties.shape.effects}</TextBody>\n                  <div className=\"grid grid-cols-2 gap-1.5\">\n                    <button\n                      onClick={() => {\n                        setShapeShadowEnabled(false);\n                        activeObject.set({ shadow: null });\n                        canvasInstance?.requestRenderAll();\n                        saveHistoryState();\n                        setSidebarUpdateTrigger(t => t + 1);\n                      }}\n                      className=\"py-1.5 rounded bg-dark-900 border border-dark-800 hover:border-dark-600 text-[10px] text-dark-300 font-semibold flex items-center justify-center gap-1 transition-colors\"\n                    >\n                      <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636\" /></svg>\n                      Ninguna\n                    </button>\n                    \n                    <button\n                      onClick={() => {\n                        setShapeShadowEnabled(true);\n                        setShapeShadowColor('rgba(0,0,0,0.15)');\n                        setShapeShadowBlur(15);\n                        setShapeShadowOffsetX(0);\n                        setShapeShadowOffsetY(6);\n                        const shd = new Shadow({ color: 'rgba(0,0,0,0.15)', blur: 15, offsetX: 0, offsetY: 6 });\n                        activeObject.set({ shadow: shd });\n                        canvasInstance?.requestRenderAll();\n                        saveHistoryState();\n                        setSidebarUpdateTrigger(t => t + 1);\n                      }}\n                      className=\"py-1.5 rounded bg-dark-900 border border-dark-800 hover:border-dark-600 text-[10px] text-white font-semibold flex items-center justify-center gap-1 transition-colors shadow-sm shadow-black/20\"\n                    >\n                      \u2601\uFE0F Soft Drop\n                    </button>\n\n                    <button\n                      onClick={() => {\n                        setShapeShadowEnabled(true);\n                        setShapeShadowColor('rgba(0,0,0,1)');\n                        setShapeShadowBlur(0);\n                        setShapeShadowOffsetX(6);\n                        setShapeShadowOffsetY(6);\n                        const shd = new Shadow({ color: 'rgba(0,0,0,1)', blur: 0, offsetX: 6, offsetY: 6 });\n                        activeObject.set({ shadow: shd });\n                        canvasInstance?.requestRenderAll();\n                        saveHistoryState();\n                        setSidebarUpdateTrigger(t => t + 1);\n                      }}\n                      className=\"py-1.5 rounded bg-dark-900 border border-dark-800 hover:border-dark-600 text-[10px] text-white font-semibold flex items-center justify-center gap-1 transition-colors drop-shadow-md\"\n                    >\n                      Hard Drop\n                    </button>\n\n                    <button\n                      onClick={() => {\n                        setShapeShadowEnabled(true);\n                        setShapeShadowColor('rgba(0,0,0,0.3)');\n                        setShapeShadowBlur(25);\n                        setShapeShadowOffsetX(0);\n                        setShapeShadowOffsetY(12);\n                        const shd = new Shadow({ color: 'rgba(0,0,0,0.3)', blur: 25, offsetX: 0, offsetY: 12 });\n                        activeObject.set({ shadow: shd });\n                        canvasInstance?.requestRenderAll();\n                        saveHistoryState();\n                        setSidebarUpdateTrigger(t => t + 1);\n                      }}\n                      className=\"py-1.5 rounded bg-dark-900 border border-dark-800 hover:border-brand-500 hover:text-brand-400 text-[10px] text-white font-semibold flex items-center justify-center gap-1 transition-colors\"\n                    >\n                      Elevate\n                    </button>\n\n                    <button\n                      onClick={() => {\n                        setShapeShadowEnabled(true);\n                        let baseCol = activeObject.fill;\n                        if (!baseCol || typeof baseCol !== 'string' || baseCol === 'transparent') {\n                          baseCol = activeObject.stroke;\n                          if (!baseCol || typeof baseCol !== 'string' || baseCol === 'transparent') {\n                            baseCol = '#00FFFF'; // default cyan neon\n                          }\n                        }\n                        setShapeShadowColor(baseCol as string);\n                        setShapeShadowBlur(25);\n                        setShapeShadowOffsetX(0);\n                        setShapeShadowOffsetY(0);\n                        \n                        const shd = new Shadow({ color: baseCol as string, blur: 25, offsetX: 0, offsetY: 0 });\n                        activeObject.set({ shadow: shd });\n                        \n                        if (!activeObject.stroke || activeObject.stroke === 'transparent') {\n                          activeObject.set({ stroke: baseCol as string, strokeWidth: 2 });\n                        }\n                        \n                        canvasInstance?.requestRenderAll();\n                        saveHistoryState();\n                        setSidebarUpdateTrigger(t => t + 1);\n                      }}\n                      className=\"py-1.5 rounded bg-dark-900 border border-dark-800 hover:border-pink-500 hover:text-pink-400 text-[10px] text-white font-semibold flex items-center justify-center gap-1 transition-colors\"\n                      style={{ textShadow: '0 0 5px rgba(236,72,153,0.5)' }}\n                    >\n                      \u26A1 Neon Glow\n                    </button>\n\n                    <button\n                      onClick={() => {\n                        setShapeShadowEnabled(true);\n                        setShapeShadowColor('rgba(0,0,0,0.1)');\n                        setShapeShadowBlur(15);\n                        setShapeShadowOffsetX(0);\n                        setShapeShadowOffsetY(10);\n                        \n                        // Create Glass Fill\n                        const w = activeObject.width || 100;\n                        const h = activeObject.height || 100;\n                        const grad = new Gradient({\n                          type: 'linear',\n                          coords: { x1: 0, y1: 0, x2: w, y2: h },\n                          colorStops: [\n                            { offset: 0, color: 'rgba(255,255,255,0.4)' },\n                            { offset: 1, color: 'rgba(255,255,255,0.05)' }\n                          ]\n                        });\n                        \n                        activeObject.set({ \n                          fill: grad, \n                          stroke: 'rgba(255,255,255,0.4)', \n                          strokeWidth: 1.5,\n                          shadow: new Shadow({ color: 'rgba(0,0,0,0.1)', blur: 15, offsetX: 0, offsetY: 10 })\n                        });\n                        \n                        setShapeFillTab('gradient');\n                        setShapeStrokeStyle('solid');\n                        \n                        canvasInstance?.requestRenderAll();\n                        saveHistoryState();\n                        setSidebarUpdateTrigger(t => t + 1);\n                      }}\n                      className=\"py-1.5 rounded bg-dark-900 border border-dark-800 hover:border-blue-300 hover:text-blue-200 text-[10px] text-white font-semibold flex items-center justify-center gap-1 transition-colors relative overflow-hidden group\"\n                    >\n                      <div className=\"absolute inset-0 bg-gradient-to-br from-white/20 to-white/0 opacity-50 pointer-events-none\"></div>\n                      <div className=\"absolute inset-0 border border-white/20 rounded pointer-events-none\"></div>\n                      Glassmorphism\n                    </button>\n                  </div>\n                </div>\n\n                {/* Section 6: Opacity */}\n                <div className=\"bg-dark-950/40 border border-dark-800 rounded-lg p-2.5 flex flex-col gap-1.5\">\n                  <TextBody as=\"span\" size=\"sm\" className=\"uppercase text-dark-400 tracking-wider block mb-0.5\">{t.properties.shape.opacity}</TextBody>\n                  <div className=\"flex items-center gap-2\">\n                    <input\n                      type=\"range\"\n                      min=\"0.1\"\n                      max=\"1\"\n                      step=\"0.05\"\n                      value={activeObject.opacity || 1}\n                      onChange={(e) => {\n                        const val = parseFloat(e.target.value);\n                        activeObject.set({ opacity: val });\n                        canvasInstance?.requestRenderAll();\n                        saveHistoryState();\n                        setSidebarUpdateTrigger(t => t + 1);\n                      }}\n                      className=\"flex-1 accent-brand-500 bg-dark-800 h-1.5 rounded-lg appearance-none cursor-pointer\"\n                    />\n                    <TextBody as=\"span\" size=\"sm\" className=\"w-12 text-right font-mono font-bold text-white\">\n                      {Math.round((activeObject.opacity || 1) * 100)}%\n                    </TextBody>\n                  </div>\n                </div>\n\n                {/* Section 7: Export Selection */}\n                <div className=\"bg-dark-950/40 border border-dark-800 rounded-lg p-2.5 flex flex-col gap-2\">\n                  <TextBody as=\"span\" size=\"sm\" className=\"uppercase text-dark-400 tracking-wider block\">{t.properties.shape.exportSelection}</TextBody>\n                  <div className=\"flex gap-1.5\">\n                    {/* Scale Selector */}\n                    <div className=\"flex-1 flex flex-col gap-1\">\n                      <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400\">{t.properties.shape.scale}</TextBody>\n                      <select\n                        value={exportSelScale}\n                        onChange={(e) => setExportSelScale(parseInt(e.target.value))}\n                        className=\"bg-dark-900 border border-dark-800 rounded px-2 py-1 text-xs text-white focus:outline-none focus:border-brand-500 font-semibold cursor-pointer\"\n                      >\n                        <option value=\"1\">1x</option>\n                        <option value=\"2\">2x (Retina)</option>\n                        <option value=\"3\">3x (HD)</option>\n                      </select>\n                    </div>\n                    {/* Format Selector */}\n                    <div className=\"flex-1 flex flex-col gap-1\">\n                      <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400\">{t.properties.shape.format}</TextBody>\n                      <select\n                        value={exportSelFormat}\n                        onChange={(e) => setExportSelFormat(e.target.value as any)}\n                        className=\"bg-dark-900 border border-dark-800 rounded px-2 py-1 text-xs text-white focus:outline-none focus:border-brand-500 font-semibold cursor-pointer\"\n                      >\n                        <option value=\"png\">PNG</option>\n                        <option value=\"jpg\">JPG</option>\n                        <option value=\"svg\">SVG</option>\n                      </select>\n                    </div>\n                  </div>\n                  \n                  <button\n                    onClick={handleExportSelection}\n                    className=\"w-full bg-brand-500 hover:bg-brand-600 active:scale-98 text-white text-[10px] font-bold py-1.5 px-3 rounded transition-all shadow-md cursor-pointer flex items-center justify-center gap-1.5\"\n                  >\n                    <span>{t.properties.shape.downloadLayer}</span>\n                  </button>\n                </div>\n              </div>\n            )}\n          </div>\n        )}\n\n        {/* TAB 4: FRAMES & MOCKUPS \u2014 movido al panel flotante en CanvasArea (T-20260706-12). Contenido preservado en CanvasArea.tsx */}\n\n\n        {/* TAB 5: BRUSH / DRAW \u2014 toda la configuraci\u00F3n se movi\u00F3 al panel flotante del toolstrip (T-20260706-09) */}\n\n        {/* TAB 5: TEXT & EDITOR \u2014 movido al panel flotante en CanvasArea (T-20260706-13). Contenido preservado en CanvasArea.tsx. */}\n\n\n\n        {/* TAB 6: FILTROS (Image Adjustments) */}\n        {activeTab === 'filtros' && (\n          <div className=\"flex flex-col gap-4\">\n            <div>\n              <TextTitle as=\"h3\" size=\"xs\" className=\"mb-0.5 uppercase tracking-wider text-white\">\n                {t.properties.image.photoFilters}\n              </TextTitle>\n              <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{t.properties.image.photoFiltersSubtitle}</TextBody>\n            </div>\n\n            {activeObject && activeObject.type === 'image' ? (\n              <div className=\"flex flex-col gap-4\">\n\n                <div className=\"flex flex-col gap-1.5\">\n                  <TextTitle as=\"span\" size=\"xs\" className=\"mb-0.5 uppercase tracking-wider text-white\">\n                    {t.properties.image.photoAdjustments}\n                  </TextTitle>\n\n                  <PanelField\n                    variant=\"slide\"\n                    label={t.properties.image.exposure}\n                    min={-80}\n                    max={80}\n                    step={4}\n                    numericValue={Math.round((imageSettings.exposure || 0) * 100)}\n                    defaultValue={0}\n                    resetLabel={t.common.reset}\n                    formatValue={(n) => `${n}%`}\n                    onChange={(v) => applyImageFilter('exposure', v / 100)}\n                    onCommit={saveFilterHistory}\n                  />\n                  <PanelField\n                    variant=\"slide\"\n                    label={t.properties.image.brightness}\n                    min={-50}\n                    max={50}\n                    step={2}\n                    numericValue={Math.round((imageSettings.brightness || 0) * 100)}\n                    defaultValue={0}\n                    resetLabel={t.common.reset}\n                    formatValue={(n) => `${n}%`}\n                    onChange={(v) => applyImageFilter('brightness', v / 100)}\n                    onCommit={saveFilterHistory}\n                  />\n                  <PanelField\n                    variant=\"slide\"\n                    label={t.properties.image.contrast}\n                    min={-50}\n                    max={50}\n                    step={2}\n                    numericValue={Math.round((imageSettings.contrast || 0) * 100)}\n                    defaultValue={0}\n                    resetLabel={t.common.reset}\n                    formatValue={(n) => `${n}%`}\n                    onChange={(v) => applyImageFilter('contrast', v / 100)}\n                    onCommit={saveFilterHistory}\n                  />\n                  <PanelField\n                    variant=\"slide\"\n                    label={t.properties.image.saturation}\n                    min={-80}\n                    max={80}\n                    step={4}\n                    numericValue={Math.round((imageSettings.saturation || 0) * 100)}\n                    defaultValue={0}\n                    resetLabel={t.common.reset}\n                    formatValue={(n) => `${n}%`}\n                    onChange={(v) => applyImageFilter('saturation', v / 100)}\n                    onCommit={saveFilterHistory}\n                  />\n                  <PanelField\n                    variant=\"slide\"\n                    label={t.properties.image.hue}\n                    min={-180}\n                    max={180}\n                    step={9}\n                    numericValue={Math.round((imageSettings.hueRotation || 0) * 180)}\n                    defaultValue={0}\n                    resetLabel={t.common.reset}\n                    formatValue={(n) => `${n}\u00B0`}\n                    onChange={(v) => applyImageFilter('hue', v / 180)}\n                    onCommit={saveFilterHistory}\n                  />\n                  <PanelField\n                    variant=\"slide\"\n                    label={t.properties.image.blur}\n                    min={0}\n                    max={60}\n                    step={2}\n                    numericValue={Math.round((imageSettings.blur || 0) * 100)}\n                    defaultValue={0}\n                    resetLabel={t.common.reset}\n                    formatValue={(n) => `${n}%`}\n                    onChange={(v) => applyImageFilter('blur', v / 100)}\n                    onCommit={saveFilterHistory}\n                  />\n                  <PanelField\n                    label={t.properties.image.invertColors}\n                    trailing={\n                      <Switch\n                        checked={!!imageSettings.invert}\n                        ariaLabel={t.properties.image.invertColors}\n                        onChange={(next) => {\n                          applyImageFilter('invert', next ? 1 : 0);\n                          saveFilterHistory();\n                        }}\n                      />\n                    }\n                  />\n                </div>\n\n                {/* Adjustments PRO Card */}\n                <div className=\"bg-dark-850/60 border border-white/5 rounded-2xl p-3.5 flex flex-col gap-4\">\n                  <TextBody as=\"label\" size=\"sm\" className=\"text-brand-400 uppercase tracking-wider border-b border-brand-500/20 pb-1\">{t.properties.image.proAdjustments}</TextBody>\n\n                  {/* Histogram Levels */}\n                  <div className=\"flex flex-col gap-2\">\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-dark-300\">{t.properties.image.levels}</TextBody>\n                    <HistogramLevels \n                      activeObject={activeObject} \n                      currentLevels={{\n                        black: imageSettings.levelsBlack ?? 0,\n                        mid: imageSettings.levelsMid ?? 1,\n                        white: imageSettings.levelsWhite ?? 255\n                      }}\n                      onLevelsChange={(black, mid, white) => {\n                        applyImageFilter('levels', { black, mid, white });\n                      }}\n                      onCommit={saveFilterHistory}\n                    />\n                  </div>\n\n                  {/* Curves Editor */}\n                  <div className=\"flex flex-col gap-2 border-t border-white/5 pt-3 mt-1\">\n                    <CurvesEditor \n                      onCurveChange={(lut) => {\n                        applyImageFilter('curves', lut);\n                        saveFilterHistory();\n                      }}\n                    />\n                  </div>\n                </div>\n\n              </div>\n            ) : (\n              <div className=\"flex flex-col items-center justify-center p-6 text-center bg-dark-850 rounded-lg border border-dark-750\">\n                <ImageIcon size={24} className=\"text-dark-500 mb-2\" />\n                <TextBody as=\"p\" size=\"sm\" className=\"text-dark-400\">{t.sidebar.stock.noImageHint}</TextBody>\n              </div>\n            )}\n          </div>\n        )}\n\n        {/* TAB 7: AI STUDIO \u2014 movido al panel flotante en CanvasArea (T-20260706-14). Contenido preservado en CanvasArea.tsx. */}\n\n\n\n        {/* TAB 8: BRAND KIT (COLORES) */}\n        {activeTab === 'brand' && (\n          <div className=\"flex flex-col gap-4\">\n            <div>\n              <TextTitle as=\"h3\" size=\"xs\" className=\"mb-2 flex items-center gap-1.5 uppercase tracking-wider\">\n                <Palette size={14} className=\"text-pink-500\" />\n                {t.sidebar.brand.title}\n              </TextTitle>\n              <TextBody as=\"p\" size=\"sm\" className=\"text-dark-400\">{t.sidebar.brand.subtitle}</TextBody>\n            </div>\n\n            {/* Harmony Generator */}\n            <div className=\"bg-dark-850 border border-dark-750 rounded-xl p-4 flex flex-col gap-3\">\n              <TextBody as=\"span\" size=\"sm\" className=\"text-dark-300 uppercase tracking-wider\">{t.sidebar.brand.harmonyGenerator}</TextBody>\n\n              <div className=\"flex items-center gap-3\">\n                <div className=\"flex-1 flex flex-col gap-1.5\">\n                  <TextBody as=\"label\" size=\"sm\" className=\"text-dark-400 uppercase\">{t.sidebar.brand.baseColorLabel}</TextBody>\n                  <div className=\"flex bg-dark-900 border border-dark-700 rounded-lg overflow-hidden focus-within:border-brand-500 transition-colors relative\">\n                    <label className=\"w-8 h-8 flex-shrink-0 relative cursor-pointer block\" title={t.sidebar.brand.baseColorTooltip}>\n                      <div className=\"absolute inset-0 pointer-events-none\" style={{ backgroundColor: baseHarmonyColor }} />\n                      <input\n                        type=\"color\"\n                        value={baseHarmonyColor}\n                        onChange={(e) => setBaseHarmonyColor(e.target.value)}\n                        className=\"absolute inset-0 w-full h-full opacity-0 cursor-pointer\"\n                      />\n                    </label>\n                    <input\n                      type=\"text\"\n                      value={baseHarmonyColor.toUpperCase()}\n                      onChange={(e) => {\n                        const val = e.target.value;\n                        setBaseHarmonyColor(val);\n                      }}\n                      className=\"w-full bg-transparent text-[11px] text-white font-mono font-bold px-2 focus:outline-none uppercase min-w-0\"\n                    />\n                  </div>\n                </div>\n\n                <div className=\"flex-1 flex flex-col gap-1.5\">\n                  <TextBody as=\"label\" size=\"sm\" className=\"text-dark-400 uppercase\">{t.sidebar.brand.harmonyRuleLabel}</TextBody>\n                  <select\n                    value={harmonyType}\n                    onChange={(e) => setHarmonyType(e.target.value as any)}\n                    className=\"w-full h-8 text-[10px] bg-dark-900 border border-dark-700 rounded-lg text-white font-medium focus:outline-none focus:border-brand-500 appearance-none px-2 cursor-pointer\"\n                  >\n                    <option value=\"complementary\">{t.sidebar.brand.harmony.complementary}</option>\n                    <option value=\"analogous\">{t.sidebar.brand.harmony.analogous}</option>\n                    <option value=\"triadic\">{t.sidebar.brand.harmony.triadic}</option>\n                    <option value=\"split-complementary\">{t.sidebar.brand.harmony.splitComplementary}</option>\n                    <option value=\"tetradic\">{t.sidebar.brand.harmony.tetradic}</option>\n                    <option value=\"monochromatic\">{t.sidebar.brand.harmony.monochromatic}</option>\n                  </select>\n                </div>\n              </div>\n\n              {/* Generated Palette Swatches */}\n              <div className=\"flex h-12 rounded-lg overflow-hidden border border-dark-700 shadow-sm mt-1\">\n                {generatedHarmony.map((hex, i) => (\n                  <div key={i} className=\"flex-1 relative group cursor-pointer transition-transform hover:scale-110 hover:z-10\">\n                    <div className=\"w-full h-full\" style={{ backgroundColor: hex }} />\n                    <input\n                      type=\"color\"\n                      value={hex}\n                      onChange={(e) => {\n                        const newHarmony = [...generatedHarmony];\n                        newHarmony[i] = e.target.value;\n                        setGeneratedHarmony(newHarmony);\n                      }}\n                      className=\"absolute inset-0 w-full h-full opacity-0 cursor-pointer\"\n                    />\n                    <div className=\"absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 flex flex-col items-center justify-center transition-opacity pointer-events-none\">\n                      <TextBody as=\"span\" size=\"sm\" className=\"tracking-wider font-bold text-white\">{hex.toUpperCase()}</TextBody>\n                      <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 text-dark-300\">{t.sidebar.brand.edit}</TextBody>\n                    </div>\n                  </div>\n                ))}\n              </div>\n\n              <button\n                onClick={() => {\n                  if (generatedHarmony.length === 5) {\n                    const nameKeys: Record<string, keyof typeof t.sidebar.brand.harmonyName> = {\n                      'complementary': 'complementary',\n                      'analogous': 'analogous',\n                      'triadic': 'triadic',\n                      'split-complementary': 'splitComplementary',\n                      'tetradic': 'tetradic',\n                      'monochromatic': 'monochromatic',\n                    };\n                    const key = nameKeys[harmonyType];\n                    addPalette({\n                      id: `palette-${Date.now()}`,\n                      name: key ? t.sidebar.brand.harmonyName[key] : t.sidebar.brand.harmonyName.fallback,\n                      colors: generatedHarmony\n                    });\n                  }\n                }}\n                className=\"w-full py-2 bg-dark-800 hover:bg-dark-700 border border-dark-600 text-[11px] font-bold text-white rounded-lg transition-colors shadow-sm cursor-pointer mt-1\"\n              >\n                {t.sidebar.brand.savePalette}\n              </button>\n            </div>\n\n            {/* Saved Palettes */}\n            <div className=\"flex flex-col gap-3 mt-2\">\n              <div className=\"flex items-center justify-between mt-2 mb-1\">\n                <TextBody as=\"span\" size=\"sm\" className=\"text-dark-300 uppercase tracking-wider\">{t.sidebar.brand.savedPalettes}</TextBody>\n                <button\n                  onClick={() => addPalette({ id: `palette-${Date.now()}`, name: t.sidebar.brand.paletteNamePlaceholder, colors: ['#000000', '#ffffff'] })}\n                  className=\"text-[9px] text-brand-400 hover:text-brand-300 flex items-center gap-1 font-semibold transition-colors cursor-pointer p-1\"\n                >\n                  <Plus size={10} /> {t.sidebar.brand.addPalette}\n                </button>\n              </div>\n\n              {(!savedPalettes || savedPalettes.length === 0) ? (\n                <div className=\"text-center p-6 border border-dashed border-dark-700 rounded-xl text-dark-400 text-xs\">\n                  {t.sidebar.brand.noPalettes}\n                </div>\n              ) : (\n                <div className=\"flex flex-col gap-3\">\n                  {(savedPalettes || []).map((palette) => (\n                    <div key={palette.id || Math.random()} className=\"flex flex-col gap-2 p-3 bg-dark-850 border border-dark-750 rounded-xl group relative shadow-sm\">\n                      <div className=\"flex items-center justify-between\">\n                        <input\n                          type=\"text\"\n                          value={palette.name || t.sidebar.brand.paletteNamePlaceholder}\n                          onChange={(e) => updatePaletteName(palette.id, e.target.value)}\n                          className=\"text-[11px] font-bold text-white bg-transparent border-none focus:outline-none focus:ring-1 focus:ring-brand-500/50 rounded px-1 py-0.5 w-3/4 truncate\"\n                        />\n                        <div className=\"flex items-center gap-1\">\n                          <label\n                            className=\"text-dark-500 hover:text-brand-400 transition-colors cursor-pointer p-1 relative flex items-center justify-center\"\n                            title={t.sidebar.brand.tooltipAddColor}\n                          >\n                            <Plus size={12} />\n                            <input\n                              type=\"color\"\n                              className=\"absolute inset-0 opacity-0 cursor-pointer w-full h-full\"\n                              onChange={(e) => addColorToPalette(palette.id, e.target.value)}\n                            />\n                          </label>\n                          <button\n                            onClick={() => deletePalette(palette.id)}\n                            className=\"text-dark-500 hover:text-red-400 transition-colors cursor-pointer p-1\"\n                            title={t.sidebar.brand.tooltipDeletePalette}\n                          >\n                            <Trash2 size={12} />\n                          </button>\n                        </div>\n                      </div>\n                      <div className=\"flex flex-wrap gap-1.5\">\n                        {(palette.colors || []).map((hex, i) => (\n                          <div key={`${i}-${hex}`} className=\"relative group/swatch flex-shrink-0\">\n                            <button\n                              onClick={() => {\n                                navigator.clipboard.writeText(hex.toUpperCase());\n                                if (activeObject && ['rect', 'circle', 'triangle', 'polygon', 'ellipse', 'path', 'textbox', 'text'].includes(activeObject.type?.toLowerCase() || '')) {\n                                  activeObject.set({ fill: hex });\n                                  canvasInstance?.requestRenderAll();\n                                  saveHistoryState();\n                                }\n                              }}\n                              className=\"w-7 h-7 rounded-md cursor-copy shadow-sm border border-dark-600 hover:scale-110 transition-transform flex items-center justify-center\"\n                              style={{ backgroundColor: hex }}\n                              title={hex.toUpperCase()}\n                            >\n                            </button>\n\n                            {/* Hover Controls for Color Swatch */}\n                            <div className=\"absolute bottom-full left-1/2 -translate-x-1/2 pb-1 opacity-0 group-hover/swatch:opacity-100 transition-opacity pointer-events-none group-hover/swatch:pointer-events-auto z-50\">\n                              <div className=\"bg-dark-900 border border-dark-700 rounded-md shadow-xl flex items-center relative\">\n                                <button\n                                  onClick={(e) => { e.stopPropagation(); if (i > 0) reorderColorInPalette(palette.id, i, i - 1); }}\n                                  className=\"p-1 text-dark-400 hover:text-white disabled:opacity-30 disabled:hover:text-dark-400\"\n                                  disabled={i === 0}\n                                >\n                                  <ChevronLeft size={10} />\n                                </button>\n                                <label className=\"p-1 text-dark-400 hover:text-brand-400 cursor-pointer relative\" title={t.sidebar.brand.tooltipEditColor}>\n                                  <Edit2 size={10} />\n                                  <input\n                                    type=\"color\"\n                                    value={hex}\n                                    onChange={(e) => updateColorInPalette(palette.id, i, e.target.value)}\n                                    className=\"absolute inset-0 w-0 h-0 opacity-0 cursor-pointer\"\n                                  />\n                                </label>\n                                <button\n                                  onClick={(e) => { e.stopPropagation(); removeColorFromPalette(palette.id, i); }}\n                                  className=\"p-1 text-dark-400 hover:text-red-400\"\n                                >\n                                  <X size={10} />\n                                </button>\n                                <button\n                                  onClick={(e) => { e.stopPropagation(); if (i < palette.colors.length - 1) reorderColorInPalette(palette.id, i, i + 1); }}\n                                  className=\"p-1 text-dark-400 hover:text-white disabled:opacity-30 disabled:hover:text-dark-400\"\n                                  disabled={i === palette.colors.length - 1}\n                                >\n                                  <ChevronRight size={10} />\n                                </button>\n                              </div>\n                            </div>\n                          </div>\n                        ))}\n                      </div>\n                    </div>\n                  ))}\n                </div>\n              )}\n            </div>\n\n          </div>\n        )}\n\n        {/* TAB: DATOS Y UTILIDADES \u2014 movido al panel flotante de Figuras/Formas en CanvasArea (T-20260706-XX). Contenido preservado en CanvasArea.tsx */}\n      </div>\n      {/* Collapse Handle Button */}\n      <div className=\"absolute right-[-12px] top-1/2 -translate-y-1/2 z-40\">\n        <button\n          onClick={() => setSidebarCollapsed(!sidebarCollapsed)}\n          className=\"w-6 h-12 rounded-r-lg border-y border-r border-dark-800 bg-dark-900/90 hover:bg-dark-850 hover:text-white backdrop-blur-md flex items-center justify-center text-dark-400 cursor-pointer shadow-md shadow-black/20 hover:shadow-brand-500/10 hover:border-brand-500/30 transition-all select-none group relative\"\n        >\n          {sidebarCollapsed ? (\n            <ChevronRight size={13} className=\"text-zinc-400 group-hover:text-brand-400 transition-colors animate-pulse\" />\n          ) : (\n            <ChevronLeft size={13} className=\"text-zinc-400 group-hover:text-brand-400 transition-colors\" />\n          )}\n          <TextBody as=\"span\" className=\"tooltip-bubble left-full top-1/2 -translate-y-1/2 ml-2\">\n            {sidebarCollapsed ? 'Mostrar Barra Lateral' : 'Ocultar Barra Lateral'}\n          </TextBody>\n        </button>\n      </div>\n      {/* ChartDataModal movido a CanvasArea.tsx (T-20260706-XX) */}\n    </div>\n  );\n};\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { UploadCloud } from 'lucide-react';\nimport { DraggableToolPanel } from '../../DraggableToolPanel';\nimport {\n  Button,\n  PanelField,\n  PanelSection,\n  ToolPanelTabs,\n  TextBody,\n} from '../../ui';\nimport { useBrandSelection } from '../../../context/BrandSelectionContext';\nimport { useTranslation } from '../../../i18n';\nimport { useEditorStore } from '../../../store/useEditorStore';\nimport { isNoneCssColor } from '../../../utils/colorRgba';\nimport {\n  SOLID_PRESETS,\n  GRADIENT_PRESETS,\n  STOCK_BG_PRESETS,\n} from '../../Sidebar';\n\nexport type BgTab = 'solid' | 'gradient' | 'stock';\n\nexport interface CanvasBgPanelProps {\n  /** Inline in CanvasSizeModal (no floating chrome). */\n  embedded?: boolean;\n  /** Required when not embedded. */\n  anchorRef?: React.RefObject<HTMLElement | null>;\n  onClose?: () => void;\n}\n\nfunction makeGradientString(start: string, end: string, angle: number): string {\n  return JSON.stringify({\n    type: 'linear',\n    angle,\n    colorStops: [\n      { offset: 0, color: start },\n      { offset: 1, color: end },\n    ],\n  });\n}\n\nconst swatchActive = (active: boolean) =>\n  `size-6 shrink-0 rounded border cursor-pointer hover:scale-110 active:scale-90 transition-transform ${\n    active\n      ? 'border-[var(--we-accent)] scale-105 ring-1 ring-[var(--we-accent)]/40'\n      : 'border-panel-border'\n  }`;\n\n/** Photoshop-style \u201Cno color\u201D mark: white square + red diagonal. */\nconst TransparentSwatchMark: React.FC = () => (\n  <>\n    <span aria-hidden className=\"absolute inset-0 bg-white\" />\n    <span\n      aria-hidden\n      className=\"absolute inset-0 bg-[linear-gradient(to_bottom_right,transparent_calc(50%-1px),#ef4444_calc(50%-1px),#ef4444_calc(50%+1px),transparent_calc(50%+1px))]\"\n    />\n  </>\n);\n\nexport const CanvasBgPanel: React.FC<CanvasBgPanelProps> = ({\n  embedded = false,\n  anchorRef,\n  onClose,\n}) => {\n  const t = useTranslation();\n  const { brand } = useBrandSelection();\n  const brandColors = brand?.primaryColors?.filter((c) => c?.hex) ?? [];\n\n  const pages = useEditorStore((s) => s.pages);\n  const activePageId = useEditorStore((s) => s.activePageId);\n  const updatePageBgColor = useEditorStore((s) => s.updatePageBgColor);\n  const extractedColors = useEditorStore((s) => s.extractedColors);\n  const activePage = pages.find((p) => p.id === activePageId) || pages[0];\n  const backgroundColor = activePage?.backgroundColor ?? '#ffffff';\n  const pageId = activePage?.id ?? '';\n\n  const [bgTab, setBgTab] = useState<BgTab>('solid');\n  const [localSolidHex, setLocalSolidHex] = useState('#ffffff');\n  const [currentGradStart, setCurrentGradStart] = useState('#ff7e5f');\n  const [currentGradEnd, setCurrentGradEnd] = useState('#feb47b');\n  const [currentGradAngle, setCurrentGradAngle] = useState(90);\n  const bgStockFileInputRef = useRef<HTMLInputElement>(null);\n\n  useEffect(() => {\n    const bg = backgroundColor;\n    if (typeof bg === 'string' && bg.startsWith('{')) {\n      try {\n        const g = JSON.parse(bg) as {\n          angle?: number;\n          colorStops?: { offset: number; color: string }[];\n        };\n        const start = g.colorStops?.find((s) => s.offset === 0)?.color;\n        const end = g.colorStops?.find((s) => s.offset === 1)?.color;\n        if (start) setCurrentGradStart(start);\n        if (end) setCurrentGradEnd(end);\n        if (typeof g.angle === 'number') setCurrentGradAngle(g.angle);\n        setBgTab('gradient');\n        return;\n      } catch {\n        /* fall through */\n      }\n    }\n    if (\n      typeof bg === 'string' &&\n      (bg.startsWith('http') || bg.startsWith('data:') || bg.startsWith('blob:'))\n    ) {\n      setBgTab('stock');\n      return;\n    }\n    if (typeof bg === 'string' && (bg.startsWith('#') || isNoneCssColor(bg))) {\n      setLocalSolidHex(isNoneCssColor(bg) ? 'transparent' : bg);\n      setBgTab('solid');\n    }\n  }, [pageId]); // sync when switching pages\n\n  if (!activePage) return null;\n\n  const isTransparentBg = isNoneCssColor(backgroundColor);\n  const solidHex = backgroundColor.startsWith('#') ? backgroundColor : '#ffffff';\n  const displayHex =\n    isTransparentBg || isNoneCssColor(localSolidHex)\n      ? ''\n      : localSolidHex && !localSolidHex.startsWith('{')\n        ? localSolidHex\n        : solidHex;\n\n  const handleGradientChange = (start: string, end: string, angle: number) => {\n    setCurrentGradStart(start);\n    setCurrentGradEnd(end);\n    setCurrentGradAngle(angle);\n    updatePageBgColor(pageId, makeGradientString(start, end, angle));\n  };\n\n  const applyStockBackground = (url: string) => {\n    updatePageBgColor(pageId, url);\n  };\n\n  const body = (\n    <>\n      <ToolPanelTabs\n        tabs={[\n          { id: 'solid' as const, label: t.canvas.bgPanel.tabSolid },\n          { id: 'gradient' as const, label: t.canvas.bgPanel.tabGradient },\n          { id: 'stock' as const, label: t.canvas.bgPanel.tabTextures },\n        ]}\n        value={bgTab}\n        onChange={setBgTab}\n      />\n\n      <div className={`flex flex-col gap-3 overflow-y-auto ${embedded ? 'pt-3' : 'p-3'}`}>\n        {bgTab === 'solid' && (\n          <div className=\"flex flex-col gap-3\">\n            <div className=\"flex flex-wrap gap-1.5\">\n              <button\n                type=\"button\"\n                onClick={() => {\n                  updatePageBgColor(pageId, 'transparent');\n                  setLocalSolidHex('transparent');\n                }}\n                className={`${swatchActive(isTransparentBg)} relative overflow-hidden`}\n                title={t.panel.transparent}\n                aria-label={t.panel.transparent}\n              >\n                <TransparentSwatchMark />\n              </button>\n              {SOLID_PRESETS.map((col) => (\n                <button\n                  key={col}\n                  type=\"button\"\n                  onClick={() => {\n                    updatePageBgColor(pageId, col);\n                    setLocalSolidHex(col);\n                  }}\n                  className={swatchActive(backgroundColor === col)}\n                  style={{ backgroundColor: col }}\n                  title={col}\n                />\n              ))}\n            </div>\n\n            {brandColors.length > 0 && (\n              <PanelSection title={t.canvas.bgPanel.brandColors}>\n                <div className=\"flex gap-1.5 flex-wrap\">\n                  {brandColors.map((c) => (\n                    <button\n                      key={`${c.name}-${c.hex}`}\n                      type=\"button\"\n                      onClick={() => {\n                        updatePageBgColor(pageId, c.hex);\n                        setLocalSolidHex(c.hex);\n                      }}\n                      className={swatchActive(backgroundColor === c.hex)}\n                      style={{ backgroundColor: c.hex }}\n                      title={c.name || c.hex}\n                    />\n                  ))}\n                </div>\n              </PanelSection>\n            )}\n\n            {extractedColors.length > 0 && (\n              <PanelSection title={t.canvas.bgPanel.imageColors}>\n                <div className=\"flex gap-1.5 flex-wrap\">\n                  {extractedColors.map((col) => (\n                    <button\n                      key={col}\n                      type=\"button\"\n                      onClick={() => {\n                        updatePageBgColor(pageId, col);\n                        setLocalSolidHex(col);\n                      }}\n                      className={swatchActive(backgroundColor === col)}\n                      style={{ backgroundColor: col }}\n                      title={col}\n                    />\n                  ))}\n                </div>\n              </PanelSection>\n            )}\n\n            <div className=\"flex min-h-9 w-full items-center justify-between gap-2 rounded-xl bg-black-capsule px-3 py-2\">\n              <TextBody as=\"span\" size=\"sm\" className=\"min-w-0 flex-1 truncate text-left text-white/80\">\n                {t.canvas.bgPanel.customColor}\n              </TextBody>\n              <div className=\"flex shrink-0 items-center gap-1.5\">\n                <input\n                  type=\"text\"\n                  aria-label={t.canvas.bgPanel.customColor}\n                  value={\n                    isTransparentBg\n                      ? ''\n                      : (displayHex.startsWith('#') ? displayHex : '').toUpperCase()\n                  }\n                  placeholder={isTransparentBg ? t.panel.transparent : '#FFFFFF'}\n                  onChange={(e) => {\n                    const val = e.target.value;\n                    setLocalSolidHex(val);\n                    let cleanVal = val.trim();\n                    if (/^(none|transparent|transparente)$/i.test(cleanVal)) {\n                      updatePageBgColor(pageId, 'transparent');\n                      setLocalSolidHex('transparent');\n                      return;\n                    }\n                    if (cleanVal.length > 0 && !cleanVal.startsWith('#')) {\n                      cleanVal = `#${cleanVal}`;\n                    }\n                    if (/^#[0-9A-Fa-f]{3}$|^#[0-9A-Fa-f]{6}$/.test(cleanVal)) {\n                      updatePageBgColor(pageId, cleanVal);\n                    }\n                  }}\n                  spellCheck={false}\n                  className=\"w-[5.5rem] border-0 bg-transparent p-0 text-right text-[11px] font-medium uppercase tabular-nums text-ink-primary placeholder:normal-case placeholder:text-white/50 focus:outline-none focus:ring-0\"\n                />\n                <div className=\"relative size-6 shrink-0 overflow-hidden rounded-md border border-panel-border\">\n                  {isTransparentBg ? (\n                    <TransparentSwatchMark />\n                  ) : (\n                    <span\n                      aria-hidden\n                      className=\"absolute inset-0\"\n                      style={{\n                        backgroundColor: solidHex,\n                      }}\n                    />\n                  )}\n                  <input\n                    type=\"color\"\n                    aria-label={`${t.canvas.bgPanel.customColor} picker`}\n                    value={solidHex}\n                    onChange={(e) => {\n                      setLocalSolidHex(e.target.value);\n                      updatePageBgColor(pageId, e.target.value);\n                    }}\n                    className=\"absolute inset-0 h-full w-full cursor-pointer opacity-0\"\n                  />\n                </div>\n              </div>\n            </div>\n          </div>\n        )}\n\n        {bgTab === 'gradient' && (\n          <div className=\"flex flex-col gap-3\">\n            <div className=\"grid grid-cols-6 gap-1.5\">\n              {GRADIENT_PRESETS.map((preset, idx) => {\n                const gradStr = makeGradientString(\n                  preset.start,\n                  preset.end,\n                  preset.angle,\n                );\n                const isActive = backgroundColor === gradStr;\n                return (\n                  <button\n                    key={idx}\n                    type=\"button\"\n                    onClick={() =>\n                      handleGradientChange(preset.start, preset.end, preset.angle)\n                    }\n                    className={`h-7 rounded border cursor-pointer hover:scale-105 active:scale-95 transition-transform ${\n                      isActive\n                        ? 'border-[var(--we-accent)] ring-1 ring-[var(--we-accent)]/40'\n                        : 'border-panel-border'\n                    }`}\n                    style={{\n                      background: `linear-gradient(${preset.angle}deg, ${preset.start}, ${preset.end})`,\n                    }}\n                    title={t.presets.gradient[preset.nameKey]}\n                  />\n                );\n              })}\n            </div>\n\n            <PanelSection title={t.canvas.bgPanel.gradientBuilder}>\n              <div className=\"grid grid-cols-2 gap-2\">\n                {(\n                  [\n                    {\n                      label: t.canvas.bgPanel.gradientStart,\n                      value: currentGradStart,\n                      onPick: (hex: string) =>\n                        handleGradientChange(hex, currentGradEnd, currentGradAngle),\n                    },\n                    {\n                      label: t.canvas.bgPanel.gradientEnd,\n                      value: currentGradEnd,\n                      onPick: (hex: string) =>\n                        handleGradientChange(currentGradStart, hex, currentGradAngle),\n                    },\n                  ] as const\n                ).map(({ label, value, onPick }) => (\n                  <div\n                    key={label}\n                    className=\"flex min-h-9 items-center justify-between gap-2 rounded-xl bg-black-capsule px-3 py-2\"\n                  >\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                      {label}\n                    </TextBody>\n                    <div className=\"relative size-6 shrink-0 overflow-hidden rounded-md border border-panel-border\">\n                      <span\n                        aria-hidden\n                        className=\"absolute inset-0\"\n                        style={{ backgroundColor: value }}\n                      />\n                      <input\n                        type=\"color\"\n                        aria-label={label}\n                        value={value}\n                        onChange={(e) => onPick(e.target.value)}\n                        className=\"absolute inset-0 h-full w-full cursor-pointer opacity-0\"\n                      />\n                    </div>\n                  </div>\n                ))}\n              </div>\n              <PanelField\n                variant=\"slide\"\n                label={t.canvas.bgPanel.gradientAngle}\n                min={0}\n                max={360}\n                step={1}\n                numericValue={currentGradAngle}\n                formatValue={(n) => `${n}\u00B0`}\n                onChange={(n) =>\n                  handleGradientChange(currentGradStart, currentGradEnd, n)\n                }\n              />\n            </PanelSection>\n          </div>\n        )}\n\n        {bgTab === 'stock' && (\n          <div className=\"flex flex-col gap-3\">\n            <PanelSection title={t.canvas.bgPanel.textureSwatch}>\n              <div className=\"grid grid-cols-3 gap-2 max-h-40 overflow-y-auto pr-0.5\">\n                {STOCK_BG_PRESETS.map((preset, idx) => (\n                  <button\n                    key={idx}\n                    type=\"button\"\n                    onClick={() => applyStockBackground(preset.url)}\n                    className=\"group relative h-12 rounded-md overflow-hidden border border-panel-border cursor-pointer hover:border-[var(--we-accent)] transition-all hover:scale-105\"\n                  >\n                    <img\n                      src={preset.url}\n                      alt={t.presets.stockBg[preset.nameKey]}\n                      className=\"w-full h-full object-cover group-hover:scale-110 transition-transform duration-300\"\n                    />\n                    <div className=\"absolute inset-0 flex items-end bg-black/40 p-1\">\n                      <TextBody as=\"span\" size=\"sm\" className=\"block w-full truncate text-left font-bold text-white\">\n                        {t.presets.stockBg[preset.nameKey]}\n                      </TextBody>\n                    </div>\n                  </button>\n                ))}\n              </div>\n            </PanelSection>\n\n            <PanelSection title={t.canvas.bgPanel.uploadCustom}>\n              <Button\n                type=\"button\"\n                variant=\"secondary\"\n                size=\"sm\"\n                className=\"w-full\"\n                icon={<UploadCloud size={14} />}\n                onClick={() => bgStockFileInputRef.current?.click()}\n              >\n                <TextBody as=\"span\" size=\"sm\">{t.canvas.bgPanel.uploadFile}</TextBody>\n              </Button>\n              <input\n                ref={bgStockFileInputRef}\n                type=\"file\"\n                accept=\"image/*\"\n                className=\"hidden\"\n                onChange={(e) => {\n                  const file = e.target.files?.[0];\n                  if (!file) return;\n                  const reader = new FileReader();\n                  reader.onload = (event) => {\n                    const dataUrl = event.target?.result as string;\n                    applyStockBackground(dataUrl);\n                  };\n                  reader.readAsDataURL(file);\n                  e.target.value = '';\n                }}\n                aria-hidden\n              />\n            </PanelSection>\n\n            <PanelSection title={t.canvas.bgPanel.urlLoad}>\n              <div className=\"flex gap-2\">\n                <input\n                  type=\"text\"\n                  placeholder={t.canvas.bgPanel.urlPlaceholder}\n                  id=\"bg-panel-url-input\"\n                  className=\"w-full min-w-0 bg-black-capsule border border-panel-border rounded-md px-2 py-1.5 text-xs text-ink-primary focus:outline-none focus:border-[var(--we-accent)] font-medium\"\n                  onKeyDown={(e) => {\n                    if (e.key === 'Enter') {\n                      const input = e.currentTarget;\n                      if (input.value.trim()) {\n                        applyStockBackground(input.value.trim());\n                        input.value = '';\n                      }\n                    }\n                  }}\n                />\n                <Button\n                  type=\"button\"\n                  variant=\"accent\"\n                  size=\"sm\"\n                  onClick={() => {\n                    const input = document.getElementById(\n                      'bg-panel-url-input',\n                    ) as HTMLInputElement | null;\n                    if (input && input.value.trim()) {\n                      applyStockBackground(input.value.trim());\n                      input.value = '';\n                    }\n                  }}\n                >\n                  {t.common.apply}\n                </Button>\n              </div>\n            </PanelSection>\n          </div>\n        )}\n      </div>\n    </>\n  );\n\n  if (embedded) {\n    return <div className=\"flex flex-col\">{body}</div>;\n  }\n\n  if (!anchorRef || !onClose) return null;\n\n  return (\n    <DraggableToolPanel\n      panelId=\"canvas-bg\"\n      title={t.canvas.bgPanel.title}\n      anchorRef={anchorRef}\n      onClose={onClose}\n      contentClassName=\"flex flex-col max-h-[70vh] overflow-y-auto min-w-[280px]\"\n    >\n      {body}\n    </DraggableToolPanel>\n  );\n};\n\nexport default CanvasBgPanel;\n", "import React, { useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { X } from 'lucide-react';\nimport { useEditorStore } from '../../../../store/useEditorStore';\nimport { useTranslation } from '../../../../i18n';\nimport { modeAccentVars, useModeAccent } from '../../../../theme/modeAccent';\nimport { CATEGORIZED_PRESETS, canvasSizeFromPx, canvasSizeToPx, type CanvasSizeUnit } from '../../../../utils/canvasSizePresets';\nimport { AspectLockGroup } from '../../molecules/AspectLockGroup/AspectLockGroup';\nimport { PanelField } from '../../molecules/PanelField/PanelField';\nimport { SelectDropdown } from '../../molecules/SelectDropdown/SelectDropdown';\nimport { IconButton } from '../../atoms/IconButton/IconButton';\nimport { TextBody } from '../../atoms/TextBody/TextBody';\nimport { TextTitle } from '../../atoms/TextTitle/TextTitle';\nimport { CanvasBgPanel } from '../../../editor/tool-panels/CanvasBgPanel';\n\nexport type { CanvasSizeUnit };\nexport type CanvasSizeTab = 'dimensions' | 'formats' | 'color';\nexport type CanvasSizeCategory = 'social' | 'web' | 'print';\n\nexport interface CanvasSizeModalProps {\n  open: boolean;\n  onClose: () => void;\n}\n\n/**\n * Organism \u2014 canvas size editor (dimensions + format presets).\n * Replaces the old DraggableToolPanel for the page-frame size chip.\n */\nexport const CanvasSizeModal: React.FC<CanvasSizeModalProps> = ({ open, onClose }) => {\n  const t = useTranslation();\n  const mode = useModeAccent();\n  const pages = useEditorStore((s) => s.pages);\n  const activePageId = useEditorStore((s) => s.activePageId);\n  const updatePageDimensions = useEditorStore((s) => s.updatePageDimensions);\n  const unit = useEditorStore((s) => s.canvasSizeUnit);\n  const setCanvasSizeUnit = useEditorStore((s) => s.setCanvasSizeUnit);\n  const activePage = pages.find((p) => p.id === activePageId) || pages[0];\n\n  const [tab, setTab] = useState<CanvasSizeTab>('dimensions');\n  const [ratioLocked, setRatioLocked] = useState(true);\n  const [ratio, setRatio] = useState(1);\n  const [category, setCategory] = useState<CanvasSizeCategory>('social');\n\n  useEffect(() => {\n    if (!activePage) return;\n    if (activePage.height > 0) setRatio(activePage.width / activePage.height);\n  }, [activePage?.id, activePage?.width, activePage?.height]);\n\n  useEffect(() => {\n    if (!open) return;\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') onClose();\n    };\n    document.addEventListener('keydown', onKey);\n    const prev = document.body.style.overflow;\n    document.body.style.overflow = 'hidden';\n    return () => {\n      document.removeEventListener('keydown', onKey);\n      document.body.style.overflow = prev;\n    };\n  }, [open, onClose]);\n\n  if (!open || !activePage || typeof document === 'undefined') return null;\n\n  const wDisplay = canvasSizeFromPx(activePage.width, unit);\n  const hDisplay = canvasSizeFromPx(activePage.height, unit);\n  const segmentActive = 'bg-[var(--we-accent-capsule)] text-white';\n  const segmentIdle = 'text-white/80 hover:text-white';\n\n  const setWidthPx = (pxWidth: number) => {\n    let pxHeight = activePage.height;\n    if (ratioLocked && ratio > 0) pxHeight = Math.round(pxWidth / ratio);\n    updatePageDimensions(activePage.id, Math.max(1, pxWidth), Math.max(1, pxHeight));\n  };\n\n  const setHeightPx = (pxHeight: number) => {\n    let pxWidth = activePage.width;\n    if (ratioLocked && ratio > 0) pxWidth = Math.round(pxHeight * ratio);\n    updatePageDimensions(activePage.id, Math.max(1, pxWidth), Math.max(1, pxHeight));\n  };\n\n  return createPortal(\n    // Portal leaves `.we-root` \u2014 re-apply current mode feature accent.\n    <div\n      className=\"fixed inset-0 z-[100] flex items-center justify-center bg-black/75 p-4 backdrop-blur-sm animate-fade-in-opacity\"\n      style={modeAccentVars(mode)}\n      data-we-mode={mode}\n    >\n      <div className=\"absolute inset-0 cursor-default\" onClick={onClose} aria-hidden />\n      <div\n        role=\"dialog\"\n        aria-modal\n        aria-label={t.canvas.sizePanel.title}\n        className=\"relative z-[101] flex max-h-[90vh] w-full max-w-lg flex-col overflow-hidden rounded-2xl border border-panel-border bg-panel shadow-2xl shadow-black/60 animate-slide-in\"\n      >\n        <div className=\"flex shrink-0 items-center justify-between gap-3 border-b border-panel-border px-4 py-3\">\n          <TextTitle as=\"h2\" size=\"sm\" className=\"uppercase tracking-wider\">\n            {t.canvas.sizePanel.title}\n          </TextTitle>\n          <IconButton label={t.common.close} size=\"sm\" variant=\"ghost\" onClick={onClose}>\n            <X size={16} />\n          </IconButton>\n        </div>\n\n        <div className=\"flex shrink-0 gap-1 border-b border-panel-border p-2\">\n          {([\n            { id: 'dimensions' as const, label: t.canvas.sizePanel.tabDimensions },\n            { id: 'formats' as const, label: t.canvas.sizePanel.tabFormats },\n            { id: 'color' as const, label: t.canvas.sizePanel.tabColor },\n          ]).map(({ id, label }) => (\n            <button\n              key={id}\n              type=\"button\"\n              onClick={() => setTab(id)}\n              className={`flex-1 cursor-pointer rounded-lg px-2 py-2 transition-colors ${\n                tab === id ? segmentActive : segmentIdle\n              }`}\n            >\n              <TextBody as=\"span\" size=\"sm\">\n                {label}\n              </TextBody>\n            </button>\n          ))}\n        </div>\n\n        <div className=\"min-h-0 flex-1 overflow-y-auto p-4\">\n          {tab === 'dimensions' && (\n            <div className=\"flex flex-col gap-3\">\n              <div className=\"flex items-start gap-2\">\n                <div className=\"min-w-0 flex-1\">\n                  <AspectLockGroup\n                    locked={ratioLocked}\n                    onLockedChange={(locked) => {\n                      if (locked && activePage.height > 0) {\n                        setRatio(activePage.width / activePage.height);\n                      }\n                      setRatioLocked(locked);\n                    }}\n                    lockLabel={t.canvas.sizePanel.lockRatio}\n                    unlockLabel={t.canvas.sizePanel.unlockRatio}\n                  >\n                    <PanelField\n                      variant=\"slide\"\n                      label={t.canvas.sizePanel.width}\n                      min={unit === 'px' ? 1 : 0.1}\n                      max={unit === 'px' ? 8000 : 100}\n                      step={unit === 'px' ? 1 : 0.1}\n                      numericValue={wDisplay}\n                      formatValue={(n) => String(n)}\n                      onChange={(v) => setWidthPx(canvasSizeToPx(v, unit))}\n                    />\n                    <PanelField\n                      variant=\"slide\"\n                      label={t.canvas.sizePanel.height}\n                      min={unit === 'px' ? 1 : 0.1}\n                      max={unit === 'px' ? 8000 : 100}\n                      step={unit === 'px' ? 1 : 0.1}\n                      numericValue={hDisplay}\n                      formatValue={(n) => String(n)}\n                      onChange={(v) => setHeightPx(canvasSizeToPx(v, unit))}\n                    />\n                  </AspectLockGroup>\n                </div>\n                <div className=\"w-[4.5rem] shrink-0 pt-0.5\">\n                  <SelectDropdown\n                    ariaLabel={t.canvas.sizePanel.unit}\n                    value={unit}\n                    onChange={(v) => setCanvasSizeUnit(v as CanvasSizeUnit)}\n                    className=\"w-full rounded-xl bg-black-capsule px-2 py-1.5\"\n                    options={[\n                      { value: 'px', label: 'px' },\n                      { value: 'in', label: 'in' },\n                      { value: 'cm', label: 'cm' },\n                      { value: 'mm', label: 'mm' },\n                    ]}\n                  />\n                </div>\n              </div>\n\n              <div className=\"flex flex-col gap-1.5\">\n                <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                  {t.canvas.sizePanel.orientation}\n                </TextBody>\n                <div className=\"flex gap-1 rounded-xl bg-black-capsule p-1\">\n                  <button\n                    type=\"button\"\n                    onClick={() => {\n                      if (activePage.width < activePage.height) {\n                        updatePageDimensions(activePage.id, activePage.height, activePage.width);\n                        setRatio(activePage.height / activePage.width);\n                      }\n                    }}\n                    className={`flex flex-1 cursor-pointer items-center justify-center gap-1.5 rounded-lg py-2 text-[11px] font-medium transition-colors ${\n                      activePage.width >= activePage.height ? segmentActive : segmentIdle\n                    }`}\n                  >\n                    <span className=\"inline-block h-2 w-3.5 rounded-sm border-2 border-current\" aria-hidden />\n                    {t.canvas.sizePanel.horizontal}\n                  </button>\n                  <button\n                    type=\"button\"\n                    onClick={() => {\n                      if (activePage.width > activePage.height) {\n                        updatePageDimensions(activePage.id, activePage.height, activePage.width);\n                        setRatio(activePage.height / activePage.width);\n                      }\n                    }}\n                    className={`flex flex-1 cursor-pointer items-center justify-center gap-1.5 rounded-lg py-2 text-[11px] font-medium transition-colors ${\n                      activePage.width < activePage.height ? segmentActive : segmentIdle\n                    }`}\n                  >\n                    <span className=\"inline-block h-3.5 w-2 rounded-sm border-2 border-current\" aria-hidden />\n                    {t.canvas.sizePanel.vertical}\n                  </button>\n                </div>\n              </div>\n            </div>\n          )}\n\n          {tab === 'formats' && (\n            <div className=\"flex flex-col gap-3\">\n              <div className=\"flex gap-1 rounded-xl bg-black-capsule p-1\">\n                {(['social', 'web', 'print'] as const).map((cat) => (\n                  <button\n                    key={cat}\n                    type=\"button\"\n                    onClick={() => setCategory(cat)}\n                    className={`flex-1 cursor-pointer rounded-lg py-1.5 text-[10px] font-medium transition-colors ${\n                      category === cat ? segmentActive : segmentIdle\n                    }`}\n                  >\n                    {cat === 'social'\n                      ? t.canvas.sizePanel.catSocial\n                      : cat === 'web'\n                        ? t.canvas.sizePanel.catWeb\n                        : t.canvas.sizePanel.catPrint}\n                  </button>\n                ))}\n              </div>\n\n              <div className=\"flex max-h-72 flex-col gap-1.5 overflow-y-auto\">\n                {CATEGORIZED_PRESETS[category].map((preset) => {\n                  const selected =\n                    activePage.width === preset.width && activePage.height === preset.height;\n                  return (\n                    <button\n                      key={preset.nameKey}\n                      type=\"button\"\n                      onClick={() => {\n                        updatePageDimensions(activePage.id, preset.width, preset.height);\n                        if (ratioLocked) setRatio(preset.width / preset.height);\n                      }}\n                      className={`flex cursor-pointer items-center gap-3 rounded-xl px-3 py-2.5 text-left transition-colors ${\n                        selected\n                          ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)]'\n                          : 'bg-black-capsule text-ink-primary hover:bg-black-capsule-hover'\n                      }`}\n                    >\n                      <div\n                        className={`flex size-8 items-center justify-center rounded-lg border border-panel-border ${\n                          selected ? 'text-[var(--we-accent)]' : 'text-white/80'\n                        }`}\n                      >\n                        {preset.icon === 'square' && (\n                          <span className=\"inline-block size-3.5 rounded-sm border-2 border-current\" />\n                        )}\n                        {preset.icon === 'portrait' && (\n                          <span className=\"inline-block h-4 w-3 rounded-sm border-2 border-current\" />\n                        )}\n                        {preset.icon === 'landscape' && (\n                          <span className=\"inline-block h-3 w-4 rounded-sm border-2 border-current\" />\n                        )}\n                      </div>\n                      <div className=\"min-w-0 flex-1\">\n                        <div className=\"truncate text-xs font-medium\">\n                          {t.presets.canvasSize[preset.nameKey as keyof typeof t.presets.canvasSize]}\n                        </div>\n                        <div className=\"truncate text-[10px] font-medium text-white/80\">\n                          {t.presets.canvasSize[preset.descKey as keyof typeof t.presets.canvasSize]} \u00B7{' '}\n                          {preset.width}\u00D7{preset.height}px\n                        </div>\n                      </div>\n                    </button>\n                  );\n                })}\n              </div>\n            </div>\n          )}\n\n          {tab === 'color' && <CanvasBgPanel embedded />}\n        </div>\n      </div>\n    </div>,\n    document.body,\n  );\n};\n", "import React, { useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport { ChevronDown, Proportions } from 'lucide-react';\nimport { useEditorStore } from '../../../../store/useEditorStore';\nimport { useTranslation } from '../../../../i18n';\nimport { CATEGORIZED_PRESETS, formatCanvasSizeLabel } from '../../../../utils/canvasSizePresets';\nimport { CanvasSizeModal } from '../../organisms/CanvasSizeModal/CanvasSizeModal';\nimport { TextBody } from '../../atoms/TextBody/TextBody';\n\nexport interface CanvasSizeChipProps {\n  /** Current canvas zoom (page frame is width*zoom wide). */\n  zoom: number;\n  className?: string;\n}\n\n/**\n * Molecule \u2014 white pill on the canvas page top edge.\n * Shows preset name when size matches a template, otherwise W \u00D7 H + unit.\n * Opens CanvasSizeModal (not a floating tool panel).\n */\nexport const CanvasSizeChip: React.FC<CanvasSizeChipProps> = ({\n  zoom,\n  className = '',\n}) => {\n  const t = useTranslation();\n  const pages = useEditorStore((s) => s.pages);\n  const activePageId = useEditorStore((s) => s.activePageId);\n  const isOpen = useEditorStore((s) => s.isCanvasSizePanelOpen);\n  const setCanvasSizePanelOpen = useEditorStore((s) => s.setCanvasSizePanelOpen);\n  const unit = useEditorStore((s) => s.canvasSizeUnit);\n  const innerRef = useRef<HTMLButtonElement | null>(null);\n  const [naturalWidth, setNaturalWidth] = useState(0);\n\n  const activePage = pages.find((p) => p.id === activePageId) || pages[0];\n  const width = activePage?.width ?? 0;\n  const height = activePage?.height ?? 0;\n\n  const label = useMemo(() => {\n    const all = [\n      ...CATEGORIZED_PRESETS.social,\n      ...CATEGORIZED_PRESETS.web,\n      ...CATEGORIZED_PRESETS.print,\n    ];\n    const match = all.find((p) => p.width === width && p.height === height);\n    if (match) {\n      return t.presets.canvasSize[match.nameKey as keyof typeof t.presets.canvasSize];\n    }\n    return formatCanvasSizeLabel(width, height, unit);\n  }, [width, height, unit, t]);\n\n  useLayoutEffect(() => {\n    const el = innerRef.current;\n    if (!el) return;\n    const prev = el.style.transform;\n    el.style.transform = 'none';\n    setNaturalWidth(el.offsetWidth);\n    el.style.transform = prev;\n  }, [label]);\n\n  const canvasScreenW = width * zoom;\n  const fitScale =\n    naturalWidth > 0 && canvasScreenW > 0\n      ? Math.min(1, (canvasScreenW * 0.92) / naturalWidth)\n      : 1;\n\n  if (!activePage) return null;\n\n  return (\n    <>\n      <button\n        type=\"button\"\n        ref={innerRef}\n        onClick={(e) => {\n          e.stopPropagation();\n          setCanvasSizePanelOpen(!isOpen);\n        }}\n        className={`inline-flex items-center gap-1.5 rounded-tl-xl rounded-tr-xl bg-white px-3 py-1.5 font-sans text-xs font-medium text-black shadow-md transition-[transform,colors] origin-bottom hover:bg-white/90 ${\n          isOpen ? 'ring-2 ring-[var(--we-accent)]' : ''\n        } ${className}`}\n        // Runtime scale vs zoom \u2014 Tailwind cannot express dynamic fit-to-canvas.\n        style={{ transform: `scale(${fitScale})` }}\n        aria-label={t.canvas.toolstrip.canvasSize}\n        aria-expanded={isOpen}\n        aria-haspopup=\"dialog\"\n        title={t.canvas.toolstrip.sizeTitle(width, height)}\n      >\n        <Proportions size={14} strokeWidth={2.25} className=\"shrink-0 text-black/70\" aria-hidden />\n        <TextBody as=\"span\" size=\"sm\" className=\"tabular-nums whitespace-nowrap text-black\">\n          {label}\n        </TextBody>\n        <ChevronDown\n          size={14}\n          strokeWidth={2.25}\n          className={`shrink-0 text-black/70 transition-transform ${isOpen ? 'rotate-180' : ''}`}\n          aria-hidden\n        />\n      </button>\n      <CanvasSizeModal open={isOpen} onClose={() => setCanvasSizePanelOpen(false)} />\n    </>\n  );\n};\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { ArrowLeftRight, Pipette } from 'lucide-react';\nimport {\n  hsvToRgb,\n  isNoneCssColor,\n  isValidCssColorInput,\n  parseCssColor,\n  rgbaToCss,\n  rgbaToHex6,\n  rgbToHsv,\n} from '../../../../utils/colorRgba';\nimport { useEyedropper } from '../../../../utils/useEyedropper';\nimport { useEditorStore, type MasterColorChannel } from '../../../../store/useEditorStore';\nimport { useTranslation } from '../../../../i18n';\nimport { TextTitle } from '../../atoms/TextTitle/TextTitle';\n\n/** Photoshop-style \u201Cno color\u201D mark: white square + red diagonal. */\nconst NoColorMark: React.FC<{ className?: string }> = ({ className = '' }) => (\n  <span\n    aria-hidden\n    className={`pointer-events-none absolute inset-0 overflow-hidden bg-white ${className}`}\n  >\n    {/* Diagonal via gradient \u2014 works at any swatch size without layout math. */}\n    <span className=\"absolute inset-0 bg-[linear-gradient(to_bottom_right,transparent_calc(50%-1px),#ef4444_calc(50%-1px),#ef4444_calc(50%+1px),transparent_calc(50%+1px))]\" />\n  </span>\n);\n\n/**\n * Organism \u2014 Photoshop-style master color (fill + stroke).\n * Always-visible dock: FG/BG swatches, editable hex, no-color, eyedropper, SV + hue.\n */\nexport const MasterColorPanel: React.FC = () => {\n  const t = useTranslation();\n  const masterColors = useEditorStore((s) => s.masterColors);\n  const setMasterColorChannel = useEditorStore((s) => s.setMasterColorChannel);\n  const setMasterColorValue = useEditorStore((s) => s.setMasterColorValue);\n  const swapMasterColors = useEditorStore((s) => s.swapMasterColors);\n  const hydrateMasterColorsFromSelection = useEditorStore(\n    (s) => s.hydrateMasterColorsFromSelection,\n  );\n  const setActiveTool = useEditorStore((s) => s.setActiveTool);\n  const setEyedropperApplyChannel = useEditorStore((s) => s.setEyedropperApplyChannel);\n  const activeObject = useEditorStore((s) => s.activeObject);\n  const layerPaintTarget = useEditorStore((s) => s.layerPaintTarget);\n  const saveHistoryState = useEditorStore((s) => s.saveHistoryState);\n  const { openNative, isSupported } = useEyedropper();\n\n  const maskGrayscale = layerPaintTarget === 'mask';\n\n  const activeCss =\n    masterColors.activeChannel === 'fill' ? masterColors.fill : masterColors.stroke;\n  const activeIsNone = isNoneCssColor(activeCss);\n  const fillIsNone = isNoneCssColor(masterColors.fill);\n  const strokeIsNone = isNoneCssColor(masterColors.stroke);\n  const parsed = parseCssColor(activeIsNone ? '#FFFFFF' : activeCss);\n  const hsv = rgbToHsv(parsed.r, parsed.g, parsed.b);\n  const hex6 = rgbaToHex6(parsed);\n\n  const [hue, setHue] = useState(hsv.h);\n  const [sat, setSat] = useState(hsv.s);\n  const [val, setVal] = useState(hsv.v);\n  const [hexText, setHexText] = useState(() => (activeIsNone ? '' : hex6.toUpperCase()));\n\n  const svRef = useRef<HTMLDivElement | null>(null);\n  const hueRef = useRef<HTMLDivElement | null>(null);\n  const draggingSv = useRef(false);\n  const draggingHue = useRef(false);\n  // Avoid overwriting HSV while the user is dragging.\n  const syncLock = useRef(false);\n\n  // When selection changes, mirror its solid fill/stroke into the master swatches.\n  useEffect(() => {\n    hydrateMasterColorsFromSelection();\n  }, [activeObject, hydrateMasterColorsFromSelection]);\n\n  useEffect(() => {\n    if (syncLock.current) return;\n    const raw =\n      masterColors.activeChannel === 'fill' ? masterColors.fill : masterColors.stroke;\n    if (isNoneCssColor(raw)) {\n      setHexText('');\n      return;\n    }\n    const next = parseCssColor(raw);\n    const h = rgbToHsv(next.r, next.g, next.b);\n    setHue(h.h);\n    setSat(h.s);\n    setVal(h.v);\n    setHexText(rgbaToHex6(next).toUpperCase());\n  }, [masterColors.fill, masterColors.stroke, masterColors.activeChannel]);\n\n  const commitHsv = (h: number, s: number, v: number) => {\n    const rgb = hsvToRgb(h, maskGrayscale ? 0 : s, v);\n    // Picking from the SV square restores an opaque color if channel was none.\n    const a = activeIsNone ? 1 : parseCssColor(activeCss).a || 1;\n    setMasterColorValue(masterColors.activeChannel, rgbaToCss({ ...rgb, a }));\n    setHexText(rgbaToHex6(rgb).toUpperCase());\n  };\n\n  const commitHex = (raw: string) => {\n    const trimmed = raw.trim();\n    if (!trimmed || /^(none|transparent|transparente)$/i.test(trimmed)) {\n      setMasterColorValue(masterColors.activeChannel, 'transparent');\n      setHexText('');\n      saveHistoryState();\n      return;\n    }\n    if (!isValidCssColorInput(trimmed)) {\n      setHexText(activeIsNone ? '' : hex6.toUpperCase());\n      return;\n    }\n    const next = parseCssColor(trimmed, parsed);\n    const css = rgbaToCss({ ...next, a: activeIsNone ? 1 : parsed.a || 1 });\n    setMasterColorValue(masterColors.activeChannel, css);\n    setHexText(rgbaToHex6(next).toUpperCase());\n    saveHistoryState();\n  };\n\n  const commitSampledColor = (hex: string) => {\n    const next = parseCssColor(hex, parsed);\n    setMasterColorValue(\n      masterColors.activeChannel,\n      rgbaToCss({ ...next, a: 1 }),\n    );\n    setHexText(rgbaToHex6(next).toUpperCase());\n    saveHistoryState();\n  };\n\n  const setNoColor = () => {\n    setMasterColorValue(masterColors.activeChannel, 'transparent');\n    setHexText('');\n    saveHistoryState();\n  };\n\n  /** EyeDropper API when available; otherwise activate canvas eyedropper tool. */\n  const pickWithEyedropper = async () => {\n    if (isSupported) {\n      const hex = await openNative();\n      if (hex) commitSampledColor(hex);\n      return;\n    }\n    setEyedropperApplyChannel(masterColors.activeChannel);\n    setActiveTool('eyedropper');\n  };\n\n  const svFromClient = (clientX: number, clientY: number) => {\n    const el = svRef.current;\n    if (!el) return;\n    const rect = el.getBoundingClientRect();\n    const s = maskGrayscale\n      ? 0\n      : Math.min(1, Math.max(0, (clientX - rect.left) / Math.max(1, rect.width)));\n    const v = Math.min(1, Math.max(0, 1 - (clientY - rect.top) / Math.max(1, rect.height)));\n    setSat(s);\n    setVal(v);\n    commitHsv(hue, s, v);\n  };\n\n  const hueFromClient = (clientY: number) => {\n    const el = hueRef.current;\n    if (!el) return;\n    const rect = el.getBoundingClientRect();\n    const h = Math.min(360, Math.max(0, ((clientY - rect.top) / Math.max(1, rect.height)) * 360));\n    setHue(h);\n    commitHsv(h, sat, val);\n  };\n\n  const selectChannel = (channel: MasterColorChannel) => {\n    setMasterColorChannel(channel);\n  };\n\n  const hueColor = hsvToRgb(hue, 1, 1);\n  const hueCss = `rgb(${hueColor.r}, ${hueColor.g}, ${hueColor.b})`;\n  const fillCss = parseCssColor(fillIsNone ? '#FFFFFF' : masterColors.fill);\n  const strokeCss = parseCssColor(strokeIsNone ? '#FFFFFF' : masterColors.stroke);\n  const fillSwatch = `rgba(${fillCss.r}, ${fillCss.g}, ${fillCss.b}, ${fillCss.a})`;\n  const strokeSwatch = `rgba(${strokeCss.r}, ${strokeCss.g}, ${strokeCss.b}, ${strokeCss.a})`;\n  const eyedropperLabel = t.canvas.eyedropper.pickColor;\n\n  return (\n    <div className=\"flex w-full shrink-0 flex-col bg-panel select-none\">\n      <div className=\"flex shrink-0 items-center border-b border-panel-border px-3 py-2\">\n        <TextTitle as=\"h2\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n          {t.panel.color}\n        </TextTitle>\n      </div>\n\n      <div className=\"flex flex-col gap-2.5 p-2.5\">\n        {/* FG/BG + hex + no-color + eyedropper */}\n        <div className=\"flex items-center gap-2\">\n          <div className=\"relative h-11 w-11 shrink-0\">\n            <button\n              type=\"button\"\n              title={t.panel.masterStroke}\n              aria-label={t.panel.masterStroke}\n              aria-pressed={masterColors.activeChannel === 'stroke'}\n              onClick={() => selectChannel('stroke')}\n              className={`absolute bottom-0 right-0 size-7 overflow-hidden rounded-sm border cursor-pointer transition-shadow ${\n                masterColors.activeChannel === 'stroke'\n                  ? 'z-[1] border-white ring-1 ring-white/60'\n                  : 'z-0 border-white/40 hover:border-white/70'\n              }`}\n              style={strokeIsNone ? undefined : { backgroundColor: strokeSwatch }}\n            >\n              {strokeIsNone ? <NoColorMark /> : null}\n            </button>\n            <button\n              type=\"button\"\n              title={t.panel.masterFill}\n              aria-label={t.panel.masterFill}\n              aria-pressed={masterColors.activeChannel === 'fill'}\n              onClick={() => selectChannel('fill')}\n              className={`absolute left-0 top-0 size-7 overflow-hidden rounded-sm border cursor-pointer transition-shadow ${\n                masterColors.activeChannel === 'fill'\n                  ? 'z-[2] border-white ring-1 ring-white/60'\n                  : 'z-[1] border-white/40 hover:border-white/70'\n              }`}\n              style={fillIsNone ? undefined : { backgroundColor: fillSwatch }}\n            >\n              {fillIsNone ? <NoColorMark /> : null}\n            </button>\n            <button\n              type=\"button\"\n              title={t.panel.swapColors}\n              aria-label={t.panel.swapColors}\n              onClick={() => swapMasterColors()}\n              className=\"absolute -right-1.5 -top-1.5 flex size-4 items-center justify-center rounded-sm text-white/80 hover:bg-white/10 hover:text-white\"\n            >\n              <ArrowLeftRight size={10} />\n            </button>\n          </div>\n\n          <div className=\"flex min-h-9 min-w-0 flex-1 items-center rounded-xl bg-black-capsule px-3 py-2\">\n            <input\n              type=\"text\"\n              aria-label={t.panel.hexInput}\n              value={hexText}\n              spellCheck={false}\n              placeholder={activeIsNone ? t.panel.transparent : '#FFFFFF'}\n              onChange={(e) => setHexText(e.target.value.toUpperCase())}\n              onBlur={() => commitHex(hexText)}\n              onKeyDown={(e) => {\n                if (e.key === 'Enter') {\n                  e.currentTarget.blur();\n                }\n                if (e.key === 'Escape') {\n                  setHexText(activeIsNone ? '' : hex6.toUpperCase());\n                  e.currentTarget.blur();\n                }\n              }}\n              className=\"w-full border-0 bg-transparent p-0 text-[11px] font-medium uppercase tabular-nums text-ink-primary placeholder:normal-case placeholder:text-white/50 focus:outline-none focus:ring-0\"\n            />\n          </div>\n\n          <button\n            type=\"button\"\n            title={t.panel.noColor}\n            aria-label={t.panel.noColor}\n            aria-pressed={activeIsNone}\n            onClick={setNoColor}\n            className={`relative size-6 shrink-0 overflow-hidden rounded-md border transition-shadow ${\n              activeIsNone\n                ? 'border-white ring-1 ring-white/60'\n                : 'border-panel-border hover:border-white/50'\n            }`}\n          >\n            <NoColorMark />\n          </button>\n\n          <button\n            type=\"button\"\n            title={eyedropperLabel}\n            aria-label={eyedropperLabel}\n            onClick={() => void pickWithEyedropper()}\n            className=\"flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-md text-white/80 transition-colors hover:bg-black-capsule-hover hover:text-[var(--we-accent)]\"\n          >\n            <Pipette size={13} strokeWidth={2.25} aria-hidden />\n          </button>\n        </div>\n\n        <div className=\"flex gap-1.5\">\n          <div\n            ref={svRef}\n            role=\"slider\"\n            aria-label={t.panel.saturationBrightness}\n            tabIndex={0}\n            className=\"relative h-[140px] flex-1 cursor-crosshair overflow-hidden rounded-sm border border-panel-border\"\n            // Dual-layer HSV needs runtime hue; mask mode is luminance only.\n            style={{\n              backgroundImage: maskGrayscale\n                ? 'linear-gradient(to top, #000, #fff)'\n                : `linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, ${hueCss})`,\n            }}\n            onPointerDown={(e) => {\n              syncLock.current = true;\n              draggingSv.current = true;\n              (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n              svFromClient(e.clientX, e.clientY);\n            }}\n            onPointerMove={(e) => {\n              if (!draggingSv.current) return;\n              svFromClient(e.clientX, e.clientY);\n            }}\n            onPointerUp={() => {\n              draggingSv.current = false;\n              syncLock.current = false;\n              saveHistoryState();\n            }}\n            onPointerCancel={() => {\n              draggingSv.current = false;\n              syncLock.current = false;\n            }}\n          >\n            <span\n              aria-hidden\n              className=\"pointer-events-none absolute size-2.5 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white shadow-[0_0_0_1px_rgba(0,0,0,0.55)]\"\n              style={{\n                left: `${maskGrayscale ? 0 : sat * 100}%`,\n                top: `${(1 - val) * 100}%`,\n              }}\n            />\n          </div>\n\n          {!maskGrayscale && (\n          <div\n            ref={hueRef}\n            role=\"slider\"\n            aria-label={t.panel.hue}\n            tabIndex={0}\n            className=\"relative h-[140px] w-3.5 shrink-0 cursor-ns-resize overflow-visible rounded-sm border border-panel-border\"\n            // Full-spectrum hue bar.\n            style={{\n              background:\n                'linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%)',\n            }}\n            onPointerDown={(e) => {\n              syncLock.current = true;\n              draggingHue.current = true;\n              (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n              hueFromClient(e.clientY);\n            }}\n            onPointerMove={(e) => {\n              if (!draggingHue.current) return;\n              hueFromClient(e.clientY);\n            }}\n            onPointerUp={() => {\n              draggingHue.current = false;\n              syncLock.current = false;\n              saveHistoryState();\n            }}\n            onPointerCancel={() => {\n              draggingHue.current = false;\n              syncLock.current = false;\n            }}\n          >\n            <span\n              aria-hidden\n              className=\"pointer-events-none absolute left-1/2 h-0 w-0 -translate-x-1/2 -translate-y-1/2\"\n              style={{ top: `${(hue / 360) * 100}%` }}\n            >\n              <span className=\"absolute -left-1.5 top-0 border-y-[4px] border-r-[5px] border-y-transparent border-l-white\" />\n              <span className=\"absolute -right-1.5 top-0 border-y-[4px] border-l-[5px] border-y-transparent border-l-white\" />\n            </span>\n          </div>\n          )}\n        </div>\n      </div>\n    </div>\n  );\n};\n\nexport default MasterColorPanel;\n", "import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { ChevronRight } from 'lucide-react';\nimport { modeAccentVars, useModeAccent } from '../../../../theme/modeAccent';\nimport { placeMenuInViewport } from '../../../../utils/clampFixedToViewport';\nimport { TextBody } from '../../atoms/TextBody/TextBody';\n\nexport interface DropdownSubmenuProps {\n  label: string;\n  disabled?: boolean;\n  /** Native tooltip; placed on the wrapper so it still shows when disabled. */\n  title?: string;\n  children: React.ReactNode;\n  className?: string;\n}\n\n/**\n * Molecule \u2014 menu row with a chevron that opens a flyout panel.\n * Portaled + clamped: flips left when the right edge would clip the viewport.\n * Overlap bridge (`pl-1.5`) keeps hover continuous when opening to the right.\n */\nexport const DropdownSubmenu: React.FC<DropdownSubmenuProps> = ({\n  label,\n  disabled = false,\n  title,\n  children,\n  className = '',\n}) => {\n  const [open, setOpen] = useState(false);\n  const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const triggerRef = useRef<HTMLButtonElement | null>(null);\n  const flyoutRef = useRef<HTMLDivElement | null>(null);\n  const mode = useModeAccent();\n  const [coords, setCoords] = useState<{\n    top: number;\n    left: number;\n    maxHeight: number;\n    openRight: boolean;\n  } | null>(null);\n\n  const clearCloseTimer = () => {\n    if (closeTimerRef.current != null) {\n      clearTimeout(closeTimerRef.current);\n      closeTimerRef.current = null;\n    }\n  };\n\n  const openMenu = () => {\n    if (disabled) return;\n    clearCloseTimer();\n    setOpen(true);\n  };\n\n  const scheduleClose = () => {\n    clearCloseTimer();\n    closeTimerRef.current = setTimeout(() => setOpen(false), 180);\n  };\n\n  useEffect(() => () => clearCloseTimer(), []);\n\n  useLayoutEffect(() => {\n    if (!open) {\n      setCoords(null);\n      return;\n    }\n    const update = () => {\n      const trigger = triggerRef.current;\n      const flyout = flyoutRef.current;\n      if (!trigger || !flyout) return;\n      const rect = trigger.getBoundingClientRect();\n      const menuWidth = Math.max(flyout.offsetWidth, 168);\n      const menuHeight = Math.max(flyout.offsetHeight, 1);\n      const placed = placeMenuInViewport({\n        trigger: rect,\n        menuWidth,\n        menuHeight,\n        prefer: 'right',\n        gap: 6,\n      });\n      setCoords({\n        top: placed.top,\n        left: placed.left,\n        maxHeight: Math.min(placed.maxHeight, 288),\n        openRight: placed.placement === 'right',\n      });\n    };\n    update();\n    const raf = requestAnimationFrame(() => {\n      update();\n      requestAnimationFrame(update);\n    });\n    window.addEventListener('resize', update);\n    window.addEventListener('scroll', update, true);\n    return () => {\n      cancelAnimationFrame(raf);\n      window.removeEventListener('resize', update);\n      window.removeEventListener('scroll', update, true);\n    };\n  }, [open, children]);\n\n  const flyout =\n    open && !disabled && typeof document !== 'undefined'\n      ? createPortal(\n          <div\n            role=\"menu\"\n            data-we-mode={mode}\n            onMouseEnter={openMenu}\n            onMouseLeave={scheduleClose}\n            // Bridge padding toward the trigger so the pointer doesn't \"fall in the gap\".\n            style={{\n              ...modeAccentVars(mode),\n              position: 'fixed',\n              top: coords?.top ?? -9999,\n              left: coords\n                ? coords.openRight\n                  ? coords.left - 6\n                  : coords.left\n                : 0,\n              paddingLeft: coords?.openRight ? 6 : 0,\n              paddingRight: coords && !coords.openRight ? 6 : 0,\n              maxHeight: coords?.maxHeight,\n              visibility: coords ? 'visible' : 'hidden',\n              zIndex: 220,\n            }}\n          >\n            <div\n              ref={flyoutRef}\n              className=\"flex max-h-72 min-w-[10.5rem] flex-col gap-1 overflow-y-auto rounded-xl border border-panel-border bg-panel p-2.5 shadow-2xl shadow-black/60 backdrop-blur-md animate-fade-in\"\n              style={{ maxHeight: coords?.maxHeight }}\n            >\n              {children}\n            </div>\n          </div>,\n          document.body,\n        )\n      : null;\n\n  return (\n    <div className={`relative ${className}`} title={title}>\n      <button\n        ref={triggerRef}\n        type=\"button\"\n        role=\"menuitem\"\n        disabled={disabled}\n        aria-expanded={open && !disabled}\n        aria-haspopup=\"menu\"\n        aria-disabled={disabled || undefined}\n        onMouseEnter={openMenu}\n        onMouseLeave={scheduleClose}\n        onClick={(e) => {\n          e.stopPropagation();\n          if (disabled) return;\n          clearCloseTimer();\n          setOpen((v) => !v);\n        }}\n        className={`flex w-full items-center justify-between gap-2.5 rounded-xl px-2.5 py-2 text-left transition-colors disabled:cursor-not-allowed disabled:opacity-40 ${\n          open && !disabled\n            ? 'bg-white/8 text-ink-primary'\n            : 'text-ink-primary hover:bg-white/8'\n        }`}\n      >\n        <TextBody as=\"span\" size=\"md\" className=\"min-w-0 truncate font-semibold\">\n          {label}\n        </TextBody>\n        <ChevronRight size={14} strokeWidth={2.25} className=\"shrink-0 text-white/80\" aria-hidden />\n      </button>\n      {flyout}\n    </div>\n  );\n};\n", "import React, { useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Search, Trash2 } from 'lucide-react';\nimport { modeAccentVars, useModeAccent } from '../../../../theme/modeAccent';\nimport { placeMenuInViewport } from '../../../../utils/clampFixedToViewport';\nimport { TextBody } from '../../atoms/TextBody/TextBody';\nimport { TextTitle } from '../../atoms/TextTitle/TextTitle';\n\nexport type FontPickerEntry = {\n  name: string;\n  category?: string;\n  custom?: boolean;\n};\n\nexport interface FontPickerFlyoutProps {\n  open: boolean;\n  onClose: () => void;\n  /** Anchor element for fixed positioning (opens to the right of the trigger). */\n  anchorRef: React.RefObject<HTMLElement | null>;\n  value: string;\n  fonts: FontPickerEntry[];\n  categoryLabels?: Record<string, string>;\n  customSectionLabel?: string;\n  searchPlaceholder?: string;\n  deleteLabel?: string;\n  onSelect: (fontName: string) => void;\n  /** Live preview while hovering / arrow-navigating. `null` restores the committed value. */\n  onPreview?: (fontName: string | null) => void;\n  onDeleteCustom?: (fontName: string) => void;\n}\n\ntype FlatRow =\n  | { kind: 'header'; key: string; label: string }\n  | { kind: 'font'; key: string; name: string; custom?: boolean };\n\n/**\n * Molecule \u2014 searchable font list in a fixed portal (not clipped by panel\n * overflow). Opens to the right of the anchor; arrow keys + Enter.\n */\nexport const FontPickerFlyout: React.FC<FontPickerFlyoutProps> = ({\n  open,\n  onClose,\n  anchorRef,\n  value,\n  fonts,\n  categoryLabels = {},\n  customSectionLabel = 'Custom',\n  searchPlaceholder = 'Search\u2026',\n  deleteLabel = 'Delete',\n  onSelect,\n  onPreview,\n  onDeleteCustom,\n}) => {\n  const mode = useModeAccent();\n  const listId = useId();\n  const searchRef = useRef<HTMLInputElement | null>(null);\n  const listRef = useRef<HTMLDivElement | null>(null);\n  const committedRef = useRef(false);\n  const [query, setQuery] = useState('');\n  const [highlight, setHighlight] = useState(0);\n  const [pos, setPos] = useState<{ left: number; top: number; maxH: number }>({\n    left: 0,\n    top: 0,\n    maxH: 360,\n  });\n\n  const rows: FlatRow[] = useMemo(() => {\n    const q = query.trim().toLowerCase();\n    const match = (name: string) => !q || name.toLowerCase().includes(q);\n    const custom = fonts.filter((f) => f.custom && match(f.name));\n    const byCat = new Map<string, FontPickerEntry[]>();\n    for (const f of fonts) {\n      if (f.custom || !match(f.name)) continue;\n      const cat = f.category || 'Other';\n      const list = byCat.get(cat) ?? [];\n      list.push(f);\n      byCat.set(cat, list);\n    }\n    const out: FlatRow[] = [];\n    if (custom.length > 0) {\n      out.push({ kind: 'header', key: 'custom', label: customSectionLabel });\n      for (const f of custom) out.push({ kind: 'font', key: `c:${f.name}`, name: f.name, custom: true });\n    }\n    for (const [cat, list] of byCat) {\n      out.push({\n        kind: 'header',\n        key: cat,\n        label: categoryLabels[cat] ?? cat,\n      });\n      for (const f of list) out.push({ kind: 'font', key: f.name, name: f.name });\n    }\n    return out;\n  }, [fonts, query, categoryLabels, customSectionLabel]);\n\n  const fontRows = useMemo(\n    () => rows.filter((r): r is Extract<FlatRow, { kind: 'font' }> => r.kind === 'font'),\n    [rows],\n  );\n  const fontRowsRef = useRef(fontRows);\n  fontRowsRef.current = fontRows;\n  const highlightRef = useRef(highlight);\n  highlightRef.current = highlight;\n  const onPreviewRef = useRef(onPreview);\n  onPreviewRef.current = onPreview;\n  const onSelectRef = useRef(onSelect);\n  onSelectRef.current = onSelect;\n  const onCloseRef = useRef(onClose);\n  onCloseRef.current = onClose;\n\n  useEffect(() => {\n    if (!open) {\n      setQuery('');\n      setHighlight(0);\n      committedRef.current = false;\n      return;\n    }\n    committedRef.current = false;\n    const place = () => {\n      const el = anchorRef.current;\n      if (!el) return;\n      const rect = el.getBoundingClientRect();\n      const placed = placeMenuInViewport({\n        trigger: rect,\n        menuWidth: 280,\n        menuHeight: Math.min(420, window.innerHeight - 16),\n        prefer: 'right',\n        gap: 8,\n      });\n      setPos({\n        left: placed.left,\n        top: placed.top,\n        maxH: Math.min(420, placed.maxHeight),\n      });\n    };\n    place();\n    const id = requestAnimationFrame(() => searchRef.current?.focus());\n    window.addEventListener('resize', place);\n    // Window scroll only \u2014 capture:true would re-place on the menu's own\n    // scrollIntoView while browsing fonts and make the flyout jump.\n    window.addEventListener('scroll', place);\n    return () => {\n      cancelAnimationFrame(id);\n      window.removeEventListener('resize', place);\n      window.removeEventListener('scroll', place);\n    };\n  }, [open, anchorRef]);\n\n  // Sync highlight to the current value only when opening or changing the search \u2014\n  // not when `fonts` gets a new array reference from the parent (that reset the\n  // cursor to the start / selected item mid-navigation).\n  useEffect(() => {\n    if (!open) return;\n    const idx = fontRowsRef.current.findIndex((f) => f.name === value);\n    setHighlight(idx >= 0 ? idx : 0);\n  }, [open, query, value]);\n\n  useEffect(() => {\n    if (!open || !listRef.current) return;\n    const active = listRef.current.querySelector<HTMLElement>('[data-font-active=\"true\"]');\n    active?.scrollIntoView({ block: 'nearest' });\n  }, [highlight, open]);\n\n  // Live-preview the highlighted face on the canvas text object.\n  useEffect(() => {\n    if (!open) return;\n    const row = fontRowsRef.current[highlight];\n    if (row) onPreviewRef.current?.(row.name);\n  }, [highlight, open]);\n\n  const closeMenu = () => {\n    if (!committedRef.current) onPreviewRef.current?.(null);\n    onCloseRef.current();\n  };\n\n  const selectAt = (index: number) => {\n    const row = fontRowsRef.current[index];\n    if (!row) return;\n    committedRef.current = true;\n    onSelectRef.current(row.name);\n    onCloseRef.current();\n  };\n\n  // Single keyboard path (window) so Arrow keys aren't handled twice via\n  // input bubble \u2192 listbox (that jumped highlight by 2).\n  useEffect(() => {\n    if (!open) return;\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') {\n        e.preventDefault();\n        e.stopPropagation();\n        if (!committedRef.current) onPreviewRef.current?.(null);\n        onCloseRef.current();\n        return;\n      }\n      const list = fontRowsRef.current;\n      if (list.length === 0) return;\n      if (e.key === 'ArrowDown') {\n        e.preventDefault();\n        e.stopPropagation();\n        setHighlight((h) => Math.min(list.length - 1, h + 1));\n        return;\n      }\n      if (e.key === 'ArrowUp') {\n        e.preventDefault();\n        e.stopPropagation();\n        setHighlight((h) => Math.max(0, h - 1));\n        return;\n      }\n      if (e.key === 'Enter') {\n        e.preventDefault();\n        e.stopPropagation();\n        selectAt(highlightRef.current);\n      }\n    };\n    window.addEventListener('keydown', onKey, true);\n    return () => window.removeEventListener('keydown', onKey, true);\n  }, [open]);\n\n  if (!open || typeof document === 'undefined') return null;\n\n  let fontIndex = -1;\n\n  return createPortal(\n    <>\n      <div className=\"fixed inset-0 z-[100]\" onClick={closeMenu} aria-hidden />\n      <div\n        role=\"listbox\"\n        id={listId}\n        aria-label={searchPlaceholder}\n        data-we-mode={mode}\n        className=\"fixed z-[110] flex w-[280px] flex-col gap-1 overflow-hidden rounded-xl border border-panel-border bg-panel p-2.5 font-sans shadow-2xl shadow-black/60 backdrop-blur-md animate-fade-in\"\n        // Runtime portal coords + feature accent (portal leaves mode root).\n        style={{ left: pos.left, top: pos.top, maxHeight: pos.maxH, ...modeAccentVars(mode) }}\n      >\n        <div className=\"flex shrink-0 items-center gap-2 rounded-lg bg-black-capsule px-2.5 py-2\">\n          <Search size={14} className=\"shrink-0 text-white/80\" aria-hidden />\n          <input\n            ref={searchRef}\n            type=\"search\"\n            value={query}\n            onChange={(e) => setQuery(e.target.value)}\n            placeholder={searchPlaceholder}\n            className=\"min-w-0 flex-1 border-0 bg-transparent p-0 font-sans text-xs font-medium text-ink-primary placeholder:text-white/40 focus:outline-none focus:ring-0\"\n          />\n        </div>\n        <div ref={listRef} className=\"min-h-0 flex-1 overflow-y-auto\">\n          {fontRows.length === 0 ? (\n            <TextBody as=\"p\" size=\"sm\" className=\"px-2.5 py-3 text-center text-white/80\">\n              \u2014\n            </TextBody>\n          ) : (\n            rows.map((row) => {\n              if (row.kind === 'header') {\n                return (\n                  <TextTitle\n                    key={row.key}\n                    as=\"p\"\n                    size=\"xs\"\n                    className=\"px-2.5 pb-1 pt-2 font-medium uppercase tracking-wider text-white/80 first:pt-0.5\"\n                  >\n                    {row.label}\n                  </TextTitle>\n                );\n              }\n              fontIndex += 1;\n              const idx = fontIndex;\n              const active = idx === highlight;\n              const selected = row.name === value;\n              return (\n                <div\n                  key={row.key}\n                  data-font-active={active ? 'true' : undefined}\n                  className={`group/item flex w-full items-center gap-1 rounded-lg transition-colors ${\n                    selected\n                      ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)]'\n                      : active\n                        ? 'bg-[var(--we-accent-capsule)] text-white'\n                        : 'text-ink-primary hover:bg-black-capsule-hover'\n                  }`}\n                >\n                  <button\n                    type=\"button\"\n                    role=\"option\"\n                    aria-selected={selected}\n                    onMouseEnter={() => setHighlight(idx)}\n                    onClick={() => selectAt(idx)}\n                    className=\"min-w-0 flex-1 cursor-pointer truncate px-2.5 py-2 text-left text-xs font-medium\"\n                    // Preview the typeface; chrome UI stays Quicksand via parent font-sans.\n                    style={{ fontFamily: `\"${row.name}\", sans-serif` }}\n                  >\n                    {row.name}\n                  </button>\n                  {row.custom && onDeleteCustom ? (\n                    <button\n                      type=\"button\"\n                      title={deleteLabel}\n                      onClick={(e) => {\n                        e.stopPropagation();\n                        onDeleteCustom(row.name);\n                      }}\n                      className={`mr-1 hidden shrink-0 cursor-pointer rounded-md p-1 group-hover/item:block ${\n                        selected || active\n                          ? 'text-[var(--we-accent)]/70 hover:bg-[var(--we-accent-muted)] hover:text-red-400'\n                          : 'text-white/80 hover:bg-red-500/10 hover:text-red-400'\n                      }`}\n                    >\n                      <Trash2 size={11} />\n                    </button>\n                  ) : null}\n                </div>\n              );\n            })\n          )}\n        </div>\n      </div>\n    </>,\n    document.body,\n  );\n};\n", "import React from 'react';\nimport { Loader2 } from 'lucide-react';\nimport { TextBody } from '../../atoms/TextBody/TextBody';\n\nexport type SubtitleAiLoaderProps = {\n  /** Localized status line (e.g. \"Generating\u2026\" / \"Translating\u2026\"). */\n  label: string;\n  /** Optional secondary hint under the label. */\n  hint?: string;\n  /**\n   * `clip` \u2014 fills a timeline slot (compact).\n   * `card` \u2014 larger standing placeholder (modal / dock).\n   */\n  variant?: 'clip' | 'card';\n  className?: string;\n};\n\n/**\n * Subtle AI pending surface for subtitle generate / translate.\n * Shimmer sweep + accent glow box-shadow (see `.animate-we-ai-glow`).\n */\nexport const SubtitleAiLoader: React.FC<SubtitleAiLoaderProps> = ({\n  label,\n  hint,\n  variant = 'clip',\n  className = '',\n}) => {\n  const isCard = variant === 'card';\n\n  return (\n    <div\n      role=\"status\"\n      aria-live=\"polite\"\n      aria-busy\n      className={[\n        'animate-we-ai-glow animate-ai-shimmer relative overflow-hidden rounded-lg',\n        'border border-[color-mix(in_srgb,var(--we-accent)_40%,transparent)]',\n        'bg-[color-mix(in_srgb,var(--we-accent)_14%,#13131A)]',\n        'select-none',\n        isCard\n          ? 'flex min-h-[4.5rem] w-full flex-col justify-center gap-1 px-4 py-3'\n          : 'flex h-full w-full items-center gap-2 px-2.5',\n        className,\n      ].join(' ')}\n    >\n      <div\n        className=\"we-ai-shimmer-bar pointer-events-none absolute inset-y-0 left-0 w-1/2 bg-gradient-to-r from-transparent via-[color-mix(in_srgb,var(--we-accent)_28%,transparent)] to-transparent\"\n        aria-hidden\n      />\n      <Loader2\n        size={isCard ? 16 : 12}\n        strokeWidth={2.25}\n        className=\"relative z-1 shrink-0 animate-spin text-[var(--we-accent)]\"\n        aria-hidden\n      />\n      <div className=\"relative z-1 min-w-0\">\n        <TextBody as=\"p\" size=\"sm\" className=\"truncate text-white\">\n          {label}\n        </TextBody>\n        {hint ? (\n          <TextBody as=\"p\" size=\"sm\" className=\"mt-0.5 truncate text-white/80\">\n            {hint}\n          </TextBody>\n        ) : null}\n      </div>\n    </div>\n  );\n};\n", "import React from 'react';\nimport { TextBody } from '../../atoms/TextBody/TextBody';\n\nexport type ToolPanelTabItem<T extends string = string> = {\n  id: T;\n  label: string;\n};\n\nexport interface ToolPanelTabsProps<T extends string = string> {\n  tabs: readonly ToolPanelTabItem<T>[];\n  value: T;\n  onChange: (id: T) => void;\n  className?: string;\n  /** Smaller labels for crowded panels (AI Studio). */\n  dense?: boolean;\n}\n\n/**\n * Segmented tabs for floating tool panels.\n * Active = `--we-accent-capsule` (feature accent), never brand purple.\n * Labels use TextBody (Quicksand medium, \u226512px).\n */\nexport function ToolPanelTabs<T extends string>({\n  tabs,\n  value,\n  onChange,\n  className = '',\n  dense = false,\n}: ToolPanelTabsProps<T>) {\n  return (\n    <div\n      className={`flex gap-1 border-b border-panel-border p-1.5 ${className}`}\n      role=\"tablist\"\n    >\n      {tabs.map((tab) => {\n        const active = value === tab.id;\n        return (\n          <button\n            key={tab.id}\n            type=\"button\"\n            role=\"tab\"\n            aria-selected={active}\n            onClick={() => onChange(tab.id)}\n            className={`flex-1 rounded-lg select-none transition-colors ${\n              dense ? 'px-1.5 py-2' : 'px-2 py-1.5'\n            } ${\n              active\n                ? 'bg-[var(--we-accent-capsule)] text-white'\n                : 'text-white/70 hover:bg-black-capsule hover:text-white'\n            }`}\n          >\n            <TextBody as=\"span\" size=\"sm\" className={active ? 'text-white' : 'text-inherit'}>\n              {tab.label}\n            </TextBody>\n          </button>\n        );\n      })}\n    </div>\n  );\n}\n\n/** Shared tile for shape/frame pickers. */\nexport const toolTileClass = (active: boolean) =>\n  `flex items-center justify-center rounded-lg border transition-colors ${\n    active\n      ? 'border-[var(--we-accent)] bg-[var(--we-accent)] text-white'\n      : 'border-panel-border bg-black-capsule text-white/80 hover:border-[var(--we-accent)]/50 hover:bg-black-capsule-hover hover:text-white'\n  }`;\n\nexport const toolTileCardClass = (active: boolean) =>\n  `flex flex-col items-center justify-center gap-1 rounded-xl border p-2 select-none transition-all group ${\n    active\n      ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)] text-[var(--we-accent)]'\n      : 'border-panel-border bg-black-capsule text-white/80 hover:border-[var(--we-accent)]/40 hover:bg-black-capsule-hover hover:text-white'\n  }`;\n", "import React from 'react';\nimport { TextBody } from './atoms/TextBody/TextBody';\n\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {\n  label?: string;\n  hint?: string;\n  error?: string;\n}\n\nexport const Input: React.FC<InputProps> = ({\n  label,\n  hint,\n  error,\n  className = '',\n  id,\n  ...props\n}) => {\n  const inputId = id ?? (label ? `we-input-${label.replace(/\\s+/g, '-').toLowerCase()}` : undefined);\n\n  return (\n    <label className={`flex flex-col gap-1 min-w-0 ${className}`}>\n      {label ? (\n        <TextBody as=\"span\" size=\"sm\" className=\"uppercase tracking-wider text-ink-secondary\">\n          {label}\n        </TextBody>\n      ) : null}\n      <input\n        id={inputId}\n        className={`h-8 w-full px-2.5 rounded-lg bg-surface-tertiary border text-xs text-ink-primary placeholder:text-ink-secondary/70 outline-none transition-colors ${\n          error\n            ? 'border-red-500 focus:border-red-400'\n            : 'border-panel-border focus:border-primary-500'\n        }`}\n        {...props}\n      />\n      {error ? (\n        <TextBody as=\"span\" size=\"sm\" className=\"text-red-400\">{error}</TextBody>\n      ) : hint ? (\n        <TextBody as=\"span\" size=\"sm\" className=\"text-ink-secondary\">{hint}</TextBody>\n      ) : null}\n    </label>\n  );\n};\n", "import React from 'react';\nimport { TextBody } from '../TextBody/TextBody';\n\nexport interface SwitchProps {\n  checked: boolean;\n  onChange: (next: boolean) => void;\n  label?: string;\n  /** Accessible name when label text is not shown (e.g. trailing in PanelField). */\n  ariaLabel?: string;\n  disabled?: boolean;\n  className?: string;\n  id?: string;\n}\n\n/**\n * Atom \u2014 boolean toggle. Off track is lighter than `black-capsule` so it\n * stays visible inside PanelField rows that share that surface.\n */\nexport const Switch: React.FC<SwitchProps> = ({\n  checked,\n  onChange,\n  label,\n  ariaLabel,\n  disabled = false,\n  className = '',\n  id,\n}) => {\n  const switchId = id ?? (label ? `we-switch-${label.replace(/\\s+/g, '-').toLowerCase()}` : undefined);\n\n  return (\n    <button\n      type=\"button\"\n      id={switchId}\n      role=\"switch\"\n      aria-checked={checked}\n      aria-label={ariaLabel ?? label}\n      disabled={disabled}\n      onClick={() => onChange(!checked)}\n      className={`inline-flex items-center gap-2 select-none ${\n        disabled ? 'opacity-40 cursor-not-allowed' : 'cursor-pointer'\n      } ${className}`}\n    >\n      {label ? (\n        <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n          {label}\n        </TextBody>\n      ) : null}\n      <span\n        className={`relative inline-flex h-5 w-9 shrink-0 rounded-full transition-colors ${\n          checked ? 'bg-[var(--we-accent)]' : 'bg-white/25'\n        }`}\n      >\n        <span\n          className={`absolute top-0.5 left-0.5 size-4 rounded-full bg-white shadow transition-transform ${\n            checked ? 'translate-x-4' : 'translate-x-0'\n          }`}\n        />\n      </span>\n    </button>\n  );\n};\n", "import React, { useState } from 'react';\n\ninterface TooltipProps {\n  content: string;\n  children: React.ReactNode;\n  position?: 'top' | 'bottom' | 'left' | 'right';\n}\n\nexport const Tooltip: React.FC<TooltipProps> = ({\n  content,\n  children,\n  position = 'top'\n}) => {\n  const [visible, setVisible] = useState(false);\n\n  const positionClasses = {\n    top: 'bottom-full left-1/2 -translate-x-1/2 mb-2',\n    bottom: 'top-full left-1/2 -translate-x-1/2 mt-2',\n    left: 'right-full top-1/2 -translate-y-1/2 mr-2',\n    right: 'left-full top-1/2 -translate-y-1/2 ml-2'\n  };\n\n  return (\n    <div\n      className=\"relative inline-block\"\n      onMouseEnter={() => setVisible(true)}\n      onMouseLeave={() => setVisible(false)}\n    >\n      {children}\n      {visible && (\n        <div\n          className={`absolute z-[999] px-2 py-1 text-xs font-medium text-white bg-black/95 border border-[#2A2A38] rounded shadow-lg whitespace-nowrap pointer-events-none ${positionClasses[position]}`}\n        >\n          {content}\n        </div>\n      )}\n    </div>\n  );\n};\n", "import React, { useEffect } from 'react';\nimport ReactDOM from 'react-dom';\nimport { X } from 'lucide-react';\nimport { modeAccentVars, useModeAccent } from '../../theme/modeAccent';\nimport { TextTitle } from './atoms/TextTitle/TextTitle';\n\ninterface ModalProps {\n  isOpen: boolean;\n  onClose: () => void;\n  title: string;\n  children: React.ReactNode;\n  size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full';\n  /** Extra classes on the scrollable body (e.g. flex layouts that own their scroll). */\n  bodyClassName?: string;\n}\n\nexport const Modal: React.FC<ModalProps> = ({\n  isOpen,\n  onClose,\n  title,\n  children,\n  size = 'md',\n  bodyClassName = '',\n}) => {\n  const mode = useModeAccent();\n\n  useEffect(() => {\n    const handleKeyDown = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') onClose();\n    };\n\n    if (isOpen) {\n      document.body.style.overflow = 'hidden';\n      window.addEventListener('keydown', handleKeyDown);\n    }\n\n    return () => {\n      document.body.style.overflow = '';\n      window.removeEventListener('keydown', handleKeyDown);\n    };\n  }, [isOpen, onClose]);\n\n  if (!isOpen) return null;\n\n  const sizeClasses: Record<NonNullable<ModalProps['size']>, string> = {\n    sm: 'max-w-md max-h-[90vh]',\n    md: 'max-w-lg max-h-[90vh]',\n    lg: 'max-w-2xl max-h-[90vh]',\n    xl: 'max-w-4xl max-h-[90vh]',\n    '2xl': 'max-w-5xl max-h-[90vh]',\n    '3xl': 'max-w-7xl max-h-[90vh]',\n    full: 'max-w-[min(96vw,1600px)] w-[96vw] h-[92vh] max-h-[92vh]',\n  };\n\n  // Portal escapes overflow-hidden parents; re-apply mode accent for --we-accent*.\n  return ReactDOM.createPortal(\n    <div\n      className=\"fixed inset-0 z-[100] flex items-center justify-center p-4 bg-black/75 backdrop-blur-sm animate-fade-in-opacity\"\n      data-we-mode={mode}\n      style={modeAccentVars(mode)}\n    >\n      <div className=\"absolute inset-0 cursor-default\" onClick={onClose} />\n\n      <div\n        className={`relative z-[101] flex w-full flex-col overflow-hidden rounded-2xl border border-panel-border bg-panel shadow-2xl animate-slide-in ${sizeClasses[size]}`}\n      >\n        <div className=\"flex shrink-0 items-center justify-between border-b border-panel-border px-6 py-4\">\n          <TextTitle as=\"h3\" size=\"md\" className=\"font-semibold\">\n            {title}\n          </TextTitle>\n          <button\n            type=\"button\"\n            onClick={onClose}\n            className=\"cursor-pointer rounded-lg p-1 text-white/80 transition-colors hover:bg-black-capsule hover:text-white\"\n          >\n            <X size={18} />\n          </button>\n        </div>\n\n        <div\n          className={`min-h-0 flex-1 overflow-y-auto px-6 py-6 text-sm font-medium text-white/80 ${bodyClassName}`}\n        >\n          {children}\n        </div>\n      </div>\n    </div>,\n    document.body\n  );\n};\n", "import React from 'react';\nimport { TextBody } from './atoms/TextBody/TextBody';\n\ninterface SliderProps {\n  value: number;\n  min: number;\n  max: number;\n  step?: number;\n  onChange: (value: number) => void;\n  label?: string;\n  formatValue?: (value: number) => string;\n  className?: string;\n}\n\nexport const Slider: React.FC<SliderProps> = ({\n  value,\n  min,\n  max,\n  step = 1,\n  onChange,\n  label,\n  formatValue,\n  className = '',\n}) => {\n  return (\n    <div className={`flex w-full flex-col gap-1.5 ${className}`}>\n      {label && (\n        <div className=\"flex items-center justify-between gap-2\">\n          <TextBody as=\"span\" size=\"sm\" className=\"min-w-0 truncate text-white/80\">\n            {label}\n          </TextBody>\n          <TextBody as=\"span\" size=\"sm\" className=\"shrink-0 tabular-nums text-white\">\n            {formatValue ? formatValue(value) : value}\n          </TextBody>\n        </div>\n      )}\n      <input\n        type=\"range\"\n        min={min}\n        max={max}\n        step={step}\n        value={value}\n        onChange={(e) => onChange(Number(e.target.value))}\n        className=\"h-1 w-full cursor-pointer appearance-none rounded-lg bg-black-capsule accent-[var(--we-accent)] focus:outline-none\"\n      />\n    </div>\n  );\n};\n", "import React from 'react';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { X, Check } from 'lucide-react';\nimport { useTranslation } from '../../i18n';\nimport { TextBody } from './atoms/TextBody/TextBody';\nimport { TextTitle } from './atoms/TextTitle/TextTitle';\n\nexport const VariationsModal: React.FC = () => {\n  const { \n    isVariationsModalOpen, \n    setVariationsModalOpen, \n    aiVariations, \n    setAiVariations,\n    canvasInstance,\n    activeObject,\n    syncLayers,\n    saveHistoryState\n  } = useEditorStore();\n  const t = useTranslation();\n\n  if (!isVariationsModalOpen) return null;\n\n  const handleSelect = async (src: string) => {\n    if (!canvasInstance || !activeObject) return;\n\n    try {\n      const { FabricImage } = await import('fabric');\n      const img = await new Promise<any>((resolve, reject) => {\n        FabricImage.fromURL(src, { crossOrigin: 'anonymous' })\n          .then(resolve)\n          .catch(reject);\n      });\n\n      img.set({\n        left: (activeObject.left || 0) + 20,\n        top: (activeObject.top || 0) + 20,\n        scaleX: activeObject.scaleX,\n        scaleY: activeObject.scaleY,\n        angle: activeObject.angle,\n        name: `Variaci\u00F3n AI`,\n      });\n\n      canvasInstance.add(img);\n      canvasInstance.setActiveObject(img);\n      useEditorStore.setState({ activeObject: img });\n      canvasInstance.requestRenderAll();\n\n      syncLayers();\n      saveHistoryState();\n      \n      closeModal();\n    } catch (err) {\n      console.error(err);\n    }\n  };\n\n  const closeModal = () => {\n    setVariationsModalOpen(false);\n    setAiVariations([]);\n  };\n\n  return (\n    <div className=\"fixed inset-0 z-[100] flex items-center justify-center bg-black/80 backdrop-blur-md p-4 animate-fade-in select-none\">\n      <div className=\"bg-dark-900 border border-dark-800 rounded-3xl p-6 w-full max-w-3xl shadow-2xl flex flex-col gap-6 relative animate-scale-in\">\n        \n        <div className=\"flex justify-between items-center\">\n          <div>\n            <TextTitle as=\"h2\" size=\"xl\" className=\"tracking-wide\">\n              {t.modal.variations.title}\n            </TextTitle>\n            <TextBody as=\"p\" size=\"md\" className=\"mt-1 text-white/80\">\n              {t.modal.variations.subtitle}\n            </TextBody>\n          </div>\n          <button \n            onClick={closeModal}\n            className=\"p-2 hover:bg-dark-800 rounded-full text-dark-400 hover:text-white transition-colors\"\n          >\n            <X size={20} />\n          </button>\n        </div>\n\n        <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-4\">\n          {aiVariations.map((src, idx) => (\n            <div \n              key={idx} \n              className=\"group relative aspect-square rounded-2xl overflow-hidden bg-dark-950 border-2 border-transparent hover:border-brand-500 cursor-pointer transition-all duration-300\"\n              onClick={() => handleSelect(src)}\n            >\n              <img src={src} alt={`Variacion ${idx}`} className=\"w-full h-full object-cover group-hover:scale-105 transition-transform duration-500\" />\n              \n              <div className=\"absolute inset-0 bg-brand-500/0 group-hover:bg-brand-500/20 transition-colors duration-300 flex items-center justify-center\">\n                <div className=\"w-10 h-10 rounded-full bg-brand-500 shadow-lg flex items-center justify-center text-white opacity-0 group-hover:opacity-100 transform scale-50 group-hover:scale-100 transition-all duration-300\">\n                  <Check size={24} />\n                </div>\n              </div>\n            </div>\n          ))}\n        </div>\n\n        <div className=\"flex justify-end\">\n          <button \n            onClick={closeModal}\n            className=\"px-6 py-2.5 rounded-xl bg-dark-800 hover:bg-dark-700 text-white transition-colors\"\n          >\n            <TextBody as=\"span\" size=\"md\" className=\"font-bold\">\n              {t.common.cancel}\n            </TextBody>\n          </button>\n        </div>\n\n      </div>\n    </div>\n  );\n};\n", "export { Button } from './atoms/Button/Button';\nexport type { ButtonProps, ButtonVariant, ButtonSize } from './atoms/Button/Button';\nexport { IconButton } from './atoms/IconButton/IconButton';\nexport type { IconButtonProps } from './atoms/IconButton/IconButton';\nexport { HamburgerIcon } from './atoms/HamburgerIcon/HamburgerIcon';\nexport type { HamburgerIconProps } from './atoms/HamburgerIcon/HamburgerIcon';\nexport { TextTitle } from './atoms/TextTitle/TextTitle';\nexport type {\n  TextTitleProps,\n  TextTitleAs,\n  TextTitleSize,\n} from './atoms/TextTitle/TextTitle';\nexport { TextBody } from './atoms/TextBody/TextBody';\nexport type {\n  TextBodyProps,\n  TextBodyAs,\n  TextBodySize,\n} from './atoms/TextBody/TextBody';\nexport { ExportButton } from './molecules/ExportButton/ExportButton';\nexport type { ExportButtonProps } from './molecules/ExportButton/ExportButton';\nexport { PanelField } from './molecules/PanelField/PanelField';\nexport type { PanelFieldProps, PanelFieldVariant } from './molecules/PanelField/PanelField';\nexport { PanelBody, PanelSection } from './molecules/PanelSection/PanelSection';\nexport type { PanelBodyProps, PanelSectionProps } from './molecules/PanelSection/PanelSection';\nexport { ColorInput } from './molecules/ColorInput/ColorInput';\nexport type { ColorInputProps } from './molecules/ColorInput/ColorInput';\nexport { AspectLockGroup } from './molecules/AspectLockGroup/AspectLockGroup';\nexport type { AspectLockGroupProps } from './molecules/AspectLockGroup/AspectLockGroup';\nexport { CanvasSizeChip } from './molecules/CanvasSizeChip/CanvasSizeChip';\nexport type { CanvasSizeChipProps } from './molecules/CanvasSizeChip/CanvasSizeChip';\nexport { CanvasSizeModal } from './organisms/CanvasSizeModal/CanvasSizeModal';\nexport type {\n  CanvasSizeModalProps,\n  CanvasSizeUnit,\n  CanvasSizeTab,\n  CanvasSizeCategory,\n} from './organisms/CanvasSizeModal/CanvasSizeModal';\nexport { MasterColorPanel } from './organisms/MasterColorPanel/MasterColorPanel';\nexport { SelectDropdown } from './molecules/SelectDropdown/SelectDropdown';\nexport type {\n  SelectDropdownProps,\n  SelectDropdownOption,\n} from './molecules/SelectDropdown/SelectDropdown';\nexport { DropdownSubmenu } from './molecules/DropdownSubmenu/DropdownSubmenu';\nexport type { DropdownSubmenuProps } from './molecules/DropdownSubmenu/DropdownSubmenu';\nexport { FontPickerFlyout } from './molecules/FontPickerFlyout/FontPickerFlyout';\nexport type {\n  FontPickerFlyoutProps,\n  FontPickerEntry,\n} from './molecules/FontPickerFlyout/FontPickerFlyout';\nexport { SubtitleAiLoader } from './molecules/SubtitleAiLoader/SubtitleAiLoader';\nexport type { SubtitleAiLoaderProps } from './molecules/SubtitleAiLoader/SubtitleAiLoader';\nexport {\n  ToolPanelTabs,\n  toolTileClass,\n  toolTileCardClass,\n} from './molecules/ToolPanelTabs/ToolPanelTabs';\nexport type {\n  ToolPanelTabsProps,\n  ToolPanelTabItem,\n} from './molecules/ToolPanelTabs/ToolPanelTabs';\nexport { Input } from './Input';\nexport type { InputProps } from './Input';\nexport { Switch } from './atoms/Switch/Switch';\nexport type { SwitchProps } from './atoms/Switch/Switch';\nexport {\n  Dropdown,\n  DropdownItem,\n  DropdownSection,\n  DropdownDivider,\n} from './Dropdown';\nexport type { DropdownProps, DropdownItemProps } from './Dropdown';\nexport { Tooltip } from './Tooltip';\nexport { Modal } from './Modal';\nexport { Slider } from './Slider';\nexport { VariationsModal } from './VariationsModal';\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { useTranslation } from '../../i18n';\nimport { PanelField } from '../ui';\n\ninterface HistogramLevelsProps {\n  activeObject: any;\n  onLevelsChange: (black: number, mid: number, white: number) => void;\n  currentLevels: { black: number; mid: number; white: number };\n  /** Fired when a scrub ends (history commit). */\n  onCommit?: () => void;\n}\n\n/** Map mid gamma (0.1\u20133, default 1) to 0\u20131 between black and white handles. */\nfunction midToneT(mid: number): number {\n  if (mid <= 1) return ((mid - 0.1) / (1 - 0.1)) * 0.5;\n  return 0.5 + ((mid - 1) / (3 - 1)) * 0.5;\n}\n\nexport const HistogramLevels: React.FC<HistogramLevelsProps> = ({\n  activeObject,\n  onLevelsChange,\n  currentLevels,\n  onCommit,\n}) => {\n  const t = useTranslation();\n  const canvasRef = useRef<HTMLCanvasElement>(null);\n  const [histogram, setHistogram] = useState<number[]>(new Array(256).fill(0));\n  const [maxCount, setMaxCount] = useState<number>(0);\n\n  useEffect(() => {\n    if (!activeObject || (activeObject.type || '').toLowerCase() !== 'image') return;\n\n    try {\n      const el = activeObject.getElement();\n      if (!el) return;\n\n      const canvas = document.createElement('canvas');\n      const ctx = canvas.getContext('2d', { willReadFrequently: true });\n      if (!ctx) return;\n\n      const width = Math.min(el.width || 512, 512);\n      const height = Math.min(el.height || 512, 512);\n      canvas.width = width;\n      canvas.height = height;\n\n      ctx.drawImage(el, 0, 0, width, height);\n      const imgData = ctx.getImageData(0, 0, width, height);\n      const data = imgData.data;\n\n      const hist = new Array(256).fill(0);\n      let max = 0;\n\n      for (let i = 0; i < data.length; i += 4) {\n        const lum = Math.round(data[i] * 0.299 + data[i + 1] * 0.587 + data[i + 2] * 0.114);\n        hist[lum]++;\n        if (hist[lum] > max) max = hist[lum];\n      }\n\n      setHistogram(hist);\n      setMaxCount(max);\n    } catch (err) {\n      console.error('Could not generate histogram', err);\n    }\n  }, [activeObject]);\n\n  useEffect(() => {\n    const canvas = canvasRef.current;\n    if (!canvas) return;\n\n    const ctx = canvas.getContext('2d');\n    if (!ctx) return;\n\n    const { width, height } = canvas;\n    ctx.clearRect(0, 0, width, height);\n\n    if (maxCount > 0) {\n      ctx.fillStyle = '#4B5563';\n      ctx.beginPath();\n      ctx.moveTo(0, height);\n      for (let i = 0; i < 256; i++) {\n        const x = (i / 255) * width;\n        const pct = histogram[i] / maxCount;\n        const y = height - pct * height;\n        ctx.lineTo(x, y);\n      }\n      ctx.lineTo(width, height);\n      ctx.closePath();\n      ctx.fill();\n    }\n\n    const black = Math.min(255, Math.max(0, currentLevels.black));\n    const white = Math.min(255, Math.max(0, currentLevels.white));\n    const mid = Math.min(3, Math.max(0.1, currentLevels.mid));\n    const midLevel = black + (white - black) * midToneT(mid);\n    const accent =\n      getComputedStyle(document.documentElement).getPropertyValue('--we-accent').trim() ||\n      '#DB2777';\n\n    const drawMarker = (level: number, color: string) => {\n      const x = (level / 255) * width + 0.5;\n      ctx.strokeStyle = color;\n      ctx.lineWidth = 1.5;\n      ctx.beginPath();\n      ctx.moveTo(x, 0);\n      ctx.lineTo(x, height);\n      ctx.stroke();\n    };\n\n    drawMarker(black, '#94a3b8');\n    drawMarker(midLevel, accent);\n    drawMarker(white, '#f8fafc');\n  }, [histogram, maxCount, currentLevels.black, currentLevels.mid, currentLevels.white]);\n\n  const setBlack = (val: number) => {\n    if (val < currentLevels.white) {\n      onLevelsChange(val, currentLevels.mid, currentLevels.white);\n    }\n  };\n\n  const setWhite = (val: number) => {\n    if (val > currentLevels.black) {\n      onLevelsChange(currentLevels.black, currentLevels.mid, val);\n    }\n  };\n\n  const setMid = (val: number) => {\n    onLevelsChange(currentLevels.black, val, currentLevels.white);\n  };\n\n  return (\n    <div className=\"flex flex-col gap-1.5\">\n      <div className=\"relative h-24 w-full overflow-hidden rounded-xl bg-black-capsule\">\n        <canvas ref={canvasRef} width={256} height={96} className=\"h-full w-full\" />\n      </div>\n\n      <PanelField\n        variant=\"slide\"\n        label={t.properties.image.levelsShadows}\n        min={0}\n        max={255}\n        step={1}\n        numericValue={currentLevels.black}\n        defaultValue={0}\n        resetLabel={t.common.reset}\n        onChange={setBlack}\n        onCommit={onCommit}\n      />\n      <PanelField\n        variant=\"slide\"\n        label={t.properties.image.levelsMids}\n        min={0.1}\n        max={3}\n        step={0.05}\n        numericValue={Number(currentLevels.mid.toFixed(2))}\n        defaultValue={1}\n        resetLabel={t.common.reset}\n        formatValue={(n) => n.toFixed(2)}\n        onChange={setMid}\n        onCommit={onCommit}\n      />\n      <PanelField\n        variant=\"slide\"\n        label={t.properties.image.levelsHighlights}\n        min={0}\n        max={255}\n        step={1}\n        numericValue={currentLevels.white}\n        defaultValue={255}\n        resetLabel={t.common.reset}\n        onChange={setWhite}\n        onCommit={onCommit}\n      />\n    </div>\n  );\n};\n", "export const LOREM_WORDS = [\n  'lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipiscing', 'elit', 'sed', 'do',\n  'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua', 'enim',\n  'ad', 'minim', 'veniam', 'quis', 'nostrud', 'exercitation', 'ullamco', 'laboris', 'nisi', 'ut',\n  'aliquip', 'ex', 'ea', 'commodo', 'consequat', 'duis', 'aute', 'irure', 'dolor', 'in', 'reprehenderit',\n  'voluptate', 'velit', 'esse', 'cillum', 'dolore', 'eu', 'fugiat', 'nulla', 'pariatur', 'excepteur',\n  'sint', 'occaecat', 'cupidatat', 'non', 'proident', 'sunt', 'in', 'culpa', 'qui', 'officia',\n  'deserunt', 'mollit', 'anim', 'id', 'est', 'laborum'\n];\n\nexport function generateLoremIpsum(type: 'words' | 'sentences' | 'paragraphs', amount: number): string {\n  const getRandomWord = () => LOREM_WORDS[Math.floor(Math.random() * LOREM_WORDS.length)];\n  \n  const generateSentence = (minWords = 5, maxWords = 15) => {\n    const wordCount = Math.floor(Math.random() * (maxWords - minWords + 1)) + minWords;\n    const words = Array.from({ length: wordCount }, getRandomWord);\n    words[0] = words[0].charAt(0).toUpperCase() + words[0].slice(1);\n    return words.join(' ') + '.';\n  };\n\n  const generateParagraph = (minSentences = 3, maxSentences = 7) => {\n    const sentenceCount = Math.floor(Math.random() * (maxSentences - minSentences + 1)) + minSentences;\n    return Array.from({ length: sentenceCount }, () => generateSentence()).join(' ');\n  };\n\n  if (type === 'words') {\n    const words = Array.from({ length: amount }, getRandomWord);\n    words[0] = words[0].charAt(0).toUpperCase() + words[0].slice(1);\n    return words.join(' ') + (amount > 3 ? '.' : '');\n  }\n\n  if (type === 'sentences') {\n    return Array.from({ length: amount }, () => generateSentence()).join(' ');\n  }\n\n  // paragraphs\n  return Array.from({ length: amount }, () => generateParagraph()).join('\\n\\n');\n}\n", "import React, {\n  createContext,\n  useContext,\n  useState,\n  useCallback,\n  useRef,\n  useEffect,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { AlertTriangle, Info, Sparkles, Trash2, X } from 'lucide-react';\nimport { useTranslation } from '../i18n';\nimport { modeAccentVars, useModeAccent } from '../theme/modeAccent';\nimport { sanitizeUserFacingMessage } from '../utils/userFacingError';\nimport { TextBody, TextTitle } from './ui';\n\n// \u2500\u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ntype DialogVariant = 'info' | 'warning' | 'error' | 'confirm' | 'danger';\n\ninterface DialogOptions {\n  title: string;\n  message: string;\n  variant?: DialogVariant;\n  confirmText?: string;\n  cancelText?: string;\n}\n\nexport interface PromptDialogOptions {\n  title: string;\n  message: string;\n  placeholder?: string;\n  defaultValue?: string;\n  confirmText?: string;\n  cancelText?: string;\n}\n\ntype BoolDialogState = DialogOptions & {\n  kind: 'bool';\n  id: number;\n  resolve: (val: boolean) => void;\n};\n\ntype PromptDialogState = PromptDialogOptions & {\n  kind: 'prompt';\n  id: number;\n  resolve: (val: string | null) => void;\n};\n\ntype DialogState = BoolDialogState | PromptDialogState;\n\n// \u2500\u2500\u2500 Context \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst DialogContext = createContext<{\n  openDialog: (opts: DialogOptions) => Promise<boolean>;\n  openPrompt: (opts: PromptDialogOptions) => Promise<string | null>;\n}>({\n  openDialog: async () => false,\n  openPrompt: async () => null,\n});\n\n// \u2500\u2500\u2500 Provider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport const DialogProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n  const [dialogs, setDialogs] = useState<DialogState[]>([]);\n  const counter = useRef(0);\n\n  const openDialog = useCallback((opts: DialogOptions): Promise<boolean> => {\n    return new Promise((resolve) => {\n      const id = ++counter.current;\n      const variant = opts.variant ?? 'info';\n      const message =\n        variant === 'error' || variant === 'danger'\n          ? sanitizeUserFacingMessage(opts.message, { context: 'dialog' })\n          : opts.message;\n      setDialogs((prev) => [\n        ...prev,\n        { ...opts, message, kind: 'bool', id, resolve },\n      ]);\n    });\n  }, []);\n\n  const openPrompt = useCallback((opts: PromptDialogOptions): Promise<string | null> => {\n    return new Promise((resolve) => {\n      const id = ++counter.current;\n      setDialogs((prev) => [...prev, { ...opts, kind: 'prompt', id, resolve }]);\n    });\n  }, []);\n\n  const closeBool = (id: number, val: boolean) => {\n    setDialogs((prev) => {\n      const d = prev.find((x) => x.id === id);\n      if (d?.kind === 'bool') d.resolve(val);\n      return prev.filter((x) => x.id !== id);\n    });\n  };\n\n  const closePrompt = (id: number, val: string | null) => {\n    setDialogs((prev) => {\n      const d = prev.find((x) => x.id === id);\n      if (d?.kind === 'prompt') d.resolve(val);\n      return prev.filter((x) => x.id !== id);\n    });\n  };\n\n  return (\n    <DialogContext.Provider value={{ openDialog, openPrompt }}>\n      {children}\n      {dialogs.map((d) =>\n        d.kind === 'prompt' ? (\n          <PromptDialogModal key={d.id} dialog={d} onClose={(val) => closePrompt(d.id, val)} />\n        ) : (\n          <DialogModal key={d.id} dialog={d} onClose={(val) => closeBool(d.id, val)} />\n        ),\n      )}\n    </DialogContext.Provider>\n  );\n};\n\n// \u2500\u2500\u2500 Hook \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport function useDialog() {\n  const { openDialog, openPrompt } = useContext(DialogContext);\n  const t = useTranslation();\n\n  const alert = useCallback(\n    (message: string, opts?: Partial<Omit<DialogOptions, 'message' | 'cancelText'>>) =>\n      openDialog({\n        title: opts?.title ?? t.modal.dialog.notice,\n        message,\n        variant: opts?.variant ?? 'info',\n        ...opts,\n      }),\n    [openDialog, t],\n  );\n\n  const confirm = useCallback(\n    (message: string, opts?: Partial<Omit<DialogOptions, 'message'>>) =>\n      openDialog({\n        title: opts?.title ?? t.modal.dialog.confirmAction,\n        message,\n        variant: opts?.variant ?? 'confirm',\n        confirmText: opts?.confirmText ?? t.modal.dialog.confirm,\n        cancelText: opts?.cancelText ?? t.modal.dialog.cancel,\n        ...opts,\n      }),\n    [openDialog, t],\n  );\n\n  const prompt = useCallback(\n    (message: string, opts?: Partial<Omit<PromptDialogOptions, 'message'>>) =>\n      openPrompt({\n        title: opts?.title ?? t.modal.dialog.notice,\n        message,\n        placeholder: opts?.placeholder,\n        defaultValue: opts?.defaultValue ?? '',\n        confirmText: opts?.confirmText ?? t.modal.dialog.accept,\n        cancelText: opts?.cancelText ?? t.modal.dialog.cancel,\n        ...opts,\n      }),\n    [openPrompt, t],\n  );\n\n  return { alert, confirm, prompt, openDialog, openPrompt };\n}\n\n// \u2500\u2500\u2500 Modal renderer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst VARIANT_STYLES: Record<DialogVariant, { icon: React.ReactNode; ring: string; btn: string }> = {\n  info: {\n    icon: <Info size={20} className=\"text-[var(--we-accent)]\" />,\n    ring: 'border-[var(--we-accent)]/30',\n    btn: 'bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)]',\n  },\n  warning: {\n    icon: <AlertTriangle size={20} className=\"text-amber-400\" />,\n    ring: 'border-amber-500/30',\n    btn: 'bg-amber-500 hover:bg-amber-400',\n  },\n  error: {\n    icon: <AlertTriangle size={20} className=\"text-red-400\" />,\n    ring: 'border-red-500/30',\n    btn: 'bg-red-600 hover:bg-red-500',\n  },\n  confirm: {\n    icon: <Info size={20} className=\"text-[var(--we-accent)]\" />,\n    ring: 'border-[var(--we-accent)]/30',\n    btn: 'bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)]',\n  },\n  danger: {\n    icon: <Trash2 size={20} className=\"text-red-400\" />,\n    ring: 'border-red-500/30',\n    btn: 'bg-red-600 hover:bg-red-500',\n  },\n};\n\nfunction DialogModal({\n  dialog,\n  onClose,\n}: {\n  dialog: BoolDialogState;\n  onClose: (val: boolean) => void;\n}) {\n  const t = useTranslation();\n  const mode = useModeAccent();\n  const { variant = 'info', title, message, confirmText = t.modal.dialog.accept, cancelText } =\n    dialog;\n  const styles = VARIANT_STYLES[variant];\n  const isConfirm = variant === 'confirm' || variant === 'danger' || !!cancelText;\n\n  useEffect(() => {\n    const handler = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') onClose(false);\n    };\n    window.addEventListener('keydown', handler);\n    return () => window.removeEventListener('keydown', handler);\n  }, [onClose]);\n\n  return createPortal(\n    <div\n      className=\"fixed inset-0 z-[99999] flex items-center justify-center bg-black/60 backdrop-blur-sm animate-fade-in\"\n      style={modeAccentVars(mode)}\n      data-we-mode={mode}\n      onClick={() => onClose(false)}\n    >\n      <div\n        className={`relative w-full max-w-sm mx-4 bg-dark-900 border rounded-2xl shadow-2xl shadow-black/60 overflow-hidden flex flex-col ${styles.ring}`}\n        style={{ borderWidth: 1 }}\n        onClick={(e) => e.stopPropagation()}\n      >\n        <div className=\"flex items-start gap-3 px-5 pt-5 pb-3\">\n          <div className=\"flex-shrink-0 mt-0.5\">{styles.icon}</div>\n          <div className=\"flex-1 min-w-0\">\n            <TextTitle as=\"h3\" size=\"sm\" className=\"leading-snug\">\n              {title}\n            </TextTitle>\n            <TextBody as=\"p\" size=\"sm\" className=\"mt-1 leading-relaxed whitespace-pre-wrap text-white/80\">\n              {message}\n            </TextBody>\n          </div>\n          <button\n            type=\"button\"\n            onClick={() => onClose(false)}\n            className=\"flex-shrink-0 p-1 rounded-lg text-dark-400 hover:text-white hover:bg-dark-800 transition-colors -mt-0.5\"\n          >\n            <X size={14} />\n          </button>\n        </div>\n\n        <div className=\"flex items-center justify-end gap-2 px-5 pb-5 pt-2\">\n          {isConfirm && (\n            <button\n              type=\"button\"\n              onClick={() => onClose(false)}\n              className=\"px-4 py-1.5 rounded-lg text-xs font-bold text-dark-300 hover:text-white bg-dark-800 hover:bg-dark-700 border border-dark-700 transition-colors\"\n            >\n              {cancelText ?? t.modal.dialog.cancel}\n            </button>\n          )}\n          <button\n            type=\"button\"\n            onClick={() => onClose(true)}\n            className={`px-4 py-1.5 rounded-lg text-xs font-bold text-white transition-colors ${styles.btn}`}\n          >\n            {confirmText}\n          </button>\n        </div>\n      </div>\n    </div>,\n    document.body,\n  );\n}\n\nfunction PromptDialogModal({\n  dialog,\n  onClose,\n}: {\n  dialog: PromptDialogState;\n  onClose: (val: string | null) => void;\n}) {\n  const t = useTranslation();\n  const mode = useModeAccent();\n  const [value, setValue] = useState(dialog.defaultValue ?? '');\n  const inputRef = useRef<HTMLTextAreaElement | null>(null);\n  const {\n    title,\n    message,\n    placeholder,\n    confirmText = t.modal.dialog.accept,\n    cancelText = t.modal.dialog.cancel,\n  } = dialog;\n\n  useEffect(() => {\n    const id = window.setTimeout(() => inputRef.current?.focus(), 0);\n    return () => window.clearTimeout(id);\n  }, []);\n\n  useEffect(() => {\n    const handler = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') onClose(null);\n    };\n    window.addEventListener('keydown', handler);\n    return () => window.removeEventListener('keydown', handler);\n  }, [onClose]);\n\n  const submit = () => {\n    const trimmed = value.trim();\n    if (!trimmed) return;\n    onClose(trimmed);\n  };\n\n  return createPortal(\n    <div\n      className=\"fixed inset-0 z-[99999] flex items-center justify-center bg-black/60 backdrop-blur-sm animate-fade-in\"\n      style={modeAccentVars(mode)}\n      data-we-mode={mode}\n      onClick={() => onClose(null)}\n    >\n      <div\n        className=\"relative w-full max-w-md mx-4 bg-dark-900 border border-[var(--we-accent)]/30 rounded-2xl shadow-2xl shadow-black/60 overflow-hidden flex flex-col\"\n        style={{ borderWidth: 1 }}\n        onClick={(e) => e.stopPropagation()}\n      >\n        <div className=\"flex items-start gap-3 px-5 pt-5 pb-3\">\n          <div className=\"flex-shrink-0 mt-0.5\">\n            <Sparkles size={20} className=\"text-[var(--we-accent)]\" />\n          </div>\n          <div className=\"flex-1 min-w-0\">\n            <TextTitle as=\"h3\" size=\"sm\" className=\"leading-snug\">\n              {title}\n            </TextTitle>\n            <TextBody as=\"p\" size=\"sm\" className=\"mt-1 leading-relaxed text-white/80\">\n              {message}\n            </TextBody>\n          </div>\n          <button\n            type=\"button\"\n            onClick={() => onClose(null)}\n            className=\"flex-shrink-0 p-1 rounded-lg text-dark-400 hover:text-white hover:bg-dark-800 transition-colors -mt-0.5\"\n          >\n            <X size={14} />\n          </button>\n        </div>\n\n        <div className=\"px-5 pb-3\">\n          <textarea\n            ref={inputRef}\n            value={value}\n            onChange={(e) => setValue(e.target.value)}\n            placeholder={placeholder}\n            rows={3}\n            onKeyDown={(e) => {\n              if (e.key === 'Enter' && !e.shiftKey) {\n                e.preventDefault();\n                submit();\n              }\n            }}\n            className=\"w-full resize-none rounded-xl border border-panel-border bg-black-capsule px-3 py-2.5 font-sans text-xs font-medium text-white placeholder:text-white/40 outline-none transition-colors hover:border-[var(--we-accent)]/40 focus:border-[var(--we-accent)] focus:ring-1 focus:ring-[var(--we-accent)]/50\"\n          />\n        </div>\n\n        <div className=\"flex items-center justify-end gap-2 px-5 pb-5 pt-1\">\n          <button\n            type=\"button\"\n            onClick={() => onClose(null)}\n            className=\"px-4 py-1.5 rounded-lg text-xs font-bold text-dark-300 hover:text-white bg-dark-800 hover:bg-dark-700 border border-dark-700 transition-colors\"\n          >\n            {cancelText}\n          </button>\n          <button\n            type=\"button\"\n            onClick={submit}\n            disabled={!value.trim()}\n            className=\"px-4 py-1.5 rounded-lg text-xs font-bold text-white bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] disabled:opacity-50 transition-colors\"\n          >\n            {confirmText}\n          </button>\n        </div>\n      </div>\n    </div>,\n    document.body,\n  );\n}\n", "/** @deprecated import from `atoms/Button/Button` \u2014 flat re-export for migration. */\nexport { Button } from './atoms/Button/Button';\nexport type { ButtonProps, ButtonVariant, ButtonSize } from './atoms/Button/Button';\n", "/**\n * Helpers for the upload \"Mis archivos\" tab \u2014 image jobs / remote URLs.\n *\n * Source of truth (same as Wizard Files modal): GET /api/ai-jobs on the\n * .NET, filtered to image job types that expose an HTTP asset URL\n * (`s3UrlsSavedJson`, `previewUrl`, or nested `s3_url`).\n */\n\nconst S3_HINT =\n  /amazonaws\\.com|\\.s3[.\\-/]|cloudfront\\.net|s3\\.|digitaloceanspaces\\.com|blob\\.core\\.windows\\.net/i;\n\nconst IMAGE_JOB_TYPES = new Set([\n  'ad_images',\n  'ad-image',\n  'ad-images',\n  'image',\n  'creative-suite',\n  'creative_suite',\n]);\n\nconst VIDEO_JOB_TYPES = new Set([\n  'video',\n  'ad_video',\n  'ad-video',\n  'ad-videos',\n  'ad_videos',\n  'generate-video',\n  'generate_video',\n  'video-generator',\n  'video_generator',\n]);\n\nconst AUDIO_JOB_TYPES = new Set([\n  'audio',\n  'ad_audio',\n  'ad-audio',\n  'generate-music',\n  'generate_music',\n  'generate-sfx',\n  'generate_sfx',\n  'tts',\n  'voiceover',\n  'voice-change',\n  'voice_change',\n  'isolate',\n  'separate-stems',\n  'separate_stems',\n  'music',\n  'sfx',\n]);\n\nconst VIDEO_EXT = /\\.(mp4|webm|mov|m4v)(\\?|#|$)/i;\nconst AUDIO_EXT = /\\.(mp3|wav|ogg|m4a|aac|flac)(\\?|#|$)/i;\nconst IMAGE_EXT = /\\.(png|jpe?g|gif|webp|avif|bmp|svg)(\\?|#|$)/i;\n\nexport function isRemoteImageUrl(url: string): boolean {\n  if (!url || url.startsWith('data:') || url.startsWith('blob:')) return false;\n  try {\n    const u = new URL(url);\n    return u.protocol === 'http:' || u.protocol === 'https:';\n  } catch {\n    return false;\n  }\n}\n\nexport function looksLikeS3Url(url: string): boolean {\n  return isRemoteImageUrl(url) && S3_HINT.test(url);\n}\n\nexport function isLikelyImageAssetUrl(url: string): boolean {\n  if (!isRemoteImageUrl(url)) return false;\n  if (VIDEO_EXT.test(url) || AUDIO_EXT.test(url)) return false;\n  return true;\n}\n\nexport function isLikelyVideoAssetUrl(url: string): boolean {\n  if (!isRemoteImageUrl(url)) return false;\n  return VIDEO_EXT.test(url);\n}\n\nexport function isLikelyAudioAssetUrl(url: string): boolean {\n  if (!isRemoteImageUrl(url)) return false;\n  return AUDIO_EXT.test(url);\n}\n\nexport type FileMediaKind = 'image' | 'video' | 'audio';\n\nexport type FileMediaItem = {\n  id: string;\n  url: string;\n  name: string;\n  kind: FileMediaKind;\n  source: 'job';\n  /** Raw backend job id (without multi-url suffix). */\n  jobId?: string;\n  jobType?: string;\n  status?: string;\n  category?: string;\n};\n\nexport type FileImageItem = {\n  id: string;\n  url: string;\n  name: string;\n  source: 'brand' | 'job' | 'upload';\n};\n\nfunction parseJsonLoose(raw: unknown): unknown {\n  if (raw == null) return null;\n  if (typeof raw !== 'string') return raw;\n  const trimmed = raw.trim();\n  if (!trimmed) return null;\n  try {\n    return JSON.parse(trimmed);\n  } catch {\n    return null;\n  }\n}\n\n/** Collect http(s) URLs from nested job payload JSON. */\nfunction extractHttpUrls(value: unknown, depth = 0): string[] {\n  if (depth > 8 || value == null) return [];\n  if (typeof value === 'string') {\n    const t = value.trim();\n    if (/^https?:\\/\\//i.test(t)) return [t];\n    if (t.startsWith('{') || t.startsWith('[')) {\n      return extractHttpUrls(parseJsonLoose(t), depth + 1);\n    }\n    return [];\n  }\n  if (Array.isArray(value)) {\n    return value.flatMap((v) => extractHttpUrls(v, depth + 1));\n  }\n  if (typeof value === 'object') {\n    const out: string[] = [];\n    for (const v of Object.values(value as Record<string, unknown>)) {\n      out.push(...extractHttpUrls(v, depth + 1));\n    }\n    return out;\n  }\n  return [];\n}\n\nfunction normalizeJobType(raw: unknown): string {\n  return String(raw ?? '')\n    .trim()\n    .toLowerCase();\n}\n\nfunction isImageJobType(jobType: string): boolean {\n  if (!jobType) return false;\n  if (IMAGE_JOB_TYPES.has(jobType)) return true;\n  return jobType.startsWith('image_') || jobType.startsWith('image-');\n}\n\nfunction isVideoJobType(jobType: string): boolean {\n  if (!jobType) return false;\n  if (VIDEO_JOB_TYPES.has(jobType)) return true;\n  return jobType.includes('video');\n}\n\nfunction isAudioJobType(jobType: string): boolean {\n  if (!jobType) return false;\n  if (AUDIO_JOB_TYPES.has(jobType)) return true;\n  return (\n    jobType.includes('audio') ||\n    jobType.includes('music') ||\n    jobType.includes('sfx') ||\n    jobType.includes('tts') ||\n    jobType.includes('voice')\n  );\n}\n\n/** Text-studio jobs that may carry analysis / script copy (not media URLs). */\nconst TEXT_CONTENT_JOB_TYPES = new Set([\n  'analysis',\n  'script',\n  'text_analysis',\n  'content_analysis',\n  'script_generation',\n  'script_gen',\n  'copywriting',\n  'marketing_assistant',\n  'generate_text',\n  'text_generate',\n  'outline',\n  'brief',\n]);\n\nfunction isTextContentJobType(jobType: string): boolean {\n  if (!jobType) return false;\n  if (TEXT_CONTENT_JOB_TYPES.has(jobType)) return true;\n  return (\n    jobType.includes('analysis') ||\n    jobType.includes('script') ||\n    jobType.includes('copy') ||\n    (jobType.includes('text') && !jobType.includes('texture'))\n  );\n}\n\nexport type TextJobContentKind = 'image' | 'analysis' | 'script' | 'text';\n\nexport type TextJobItem = {\n  id: string;\n  name: string;\n  kind: TextJobContentKind;\n  /** Remote image URL when kind === 'image'. */\n  url?: string;\n  /** Plain text body for analysis / script / text jobs. */\n  text?: string;\n  source: 'job';\n};\n\nfunction pickLongestString(values: unknown[]): string | null {\n  let best: string | null = null;\n  for (const v of values) {\n    if (typeof v !== 'string') continue;\n    const t = v.trim();\n    if (t.length < 8) continue;\n    if (/^https?:\\/\\//i.test(t)) continue;\n    if (!best || t.length > best.length) best = t;\n  }\n  return best;\n}\n\n/** Pull human-readable copy from nested job payloads. */\nfunction extractJobTextBody(value: unknown, depth = 0): string | null {\n  if (depth > 8 || value == null) return null;\n  if (typeof value === 'string') {\n    const trimmed = value.trim();\n    if (!trimmed) return null;\n    if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n      return extractJobTextBody(parseJsonLoose(trimmed), depth + 1);\n    }\n    if (trimmed.length >= 8 && !/^https?:\\/\\//i.test(trimmed)) return trimmed;\n    return null;\n  }\n  if (Array.isArray(value)) {\n    const parts = value\n      .map((v) => extractJobTextBody(v, depth + 1))\n      .filter((s): s is string => !!s);\n    if (!parts.length) return null;\n    return parts.join('\\n\\n');\n  }\n  if (typeof value === 'object') {\n    const rec = value as Record<string, unknown>;\n    const preferredKeys = [\n      'script',\n      'analysis',\n      'text',\n      'content',\n      'body',\n      'summary',\n      'transcript',\n      'result',\n      'output',\n      'markdown',\n      'article',\n      'copy',\n    ];\n    const preferred = pickLongestString(preferredKeys.map((k) => rec[k]));\n    if (preferred) return preferred;\n\n    const nested: string[] = [];\n    for (const v of Object.values(rec)) {\n      const t = extractJobTextBody(v, depth + 1);\n      if (t) nested.push(t);\n    }\n    return pickLongestString(nested);\n  }\n  return null;\n}\n\nfunction textKindFromJobType(jobType: string): TextJobContentKind {\n  if (jobType.includes('script')) return 'script';\n  if (jobType.includes('analysis') || jobType.includes('brief')) return 'analysis';\n  return 'text';\n}\n\nfunction isCompletedStatus(status: unknown): boolean {\n  const s = String(status ?? '')\n    .trim()\n    .toLowerCase();\n  return s === 'completed' || s === 'success' || s === 'succeeded' || s === 'done';\n}\n\nconst PROVIDER_NAME_RE =\n  /\\b(openai|open\\s*ai|elevenlabs|eleven\\s*labs|unsplash|pexels|midjourney|stability\\s*ai|stable\\s*diffusion|suno|udio|runway|kling|luma|google|gemini|anthropic|claude|dall-?e|gpt-?\\d*|whisper|huggingface|hugging\\s*face|replicate|fal\\.ai|byteplus|bytedance)\\b/gi;\n\n/** True if the string still names a third-party AI provider. */\nfunction containsProviderBrand(raw: string): boolean {\n  // Underscores/dots glue brands to tokens (\"elevenlabs_tts\") \u2014 normalize first.\n  const spaced = raw.replace(/[_\\-./\\\\]+/g, ' ');\n  PROVIDER_NAME_RE.lastIndex = 0;\n  return PROVIDER_NAME_RE.test(spaced);\n}\n\nfunction stripProviderNames(raw: string): string {\n  return raw\n    .replace(/[_\\-./\\\\]+/g, ' ')\n    .replace(PROVIDER_NAME_RE, ' ')\n    .replace(/\\s{2,}/g, ' ')\n    .replace(/^[\\s\\-\u2013\u2014:\u00B7.]+|[\\s\\-\u2013\u2014:\u00B7.]+$/g, '')\n    .trim();\n}\n\n/** Friendly category when backend `category` is empty \u2014 never a provider brand. */\nfunction categoryFromJobType(jobType: string): string {\n  const t = jobType.toLowerCase().replace(/_/g, '-');\n  const map: Record<string, string> = {\n    'ad-images': 'Imagen',\n    'ad-image': 'Imagen',\n    image: 'Imagen',\n    'creative-suite': 'Imagen',\n    'ad-video': 'Video',\n    'ad-videos': 'Video',\n    video: 'Video',\n    'generate-video': 'Video',\n    'video-generator': 'Video',\n    audio: 'Audio',\n    'ad-audio': 'Audio',\n    'generate-music': 'M\u00FAsica',\n    music: 'M\u00FAsica',\n    'generate-sfx': 'Efectos de sonido',\n    sfx: 'Efectos de sonido',\n    tts: 'Voz',\n    voiceover: 'Voz',\n    'voice-change': 'Cambio de voz',\n    isolate: 'Aislamiento',\n    'separate-stems': 'Stems',\n    analysis: 'An\u00E1lisis',\n    script: 'Guion',\n    copy: 'Copy',\n    'text-generate': 'Texto',\n  };\n  if (map[t]) return map[t]!;\n  if (t.includes('music')) return 'M\u00FAsica';\n  if (t.includes('sfx') || t.includes('sound')) return 'Efectos de sonido';\n  if (t.includes('tts') || t.includes('voice')) return 'Voz';\n  if (t.includes('audio')) return 'Audio';\n  if (t.includes('video')) return 'Video';\n  if (t.includes('image') || t.includes('creative')) return 'Imagen';\n  if (t.includes('script')) return 'Guion';\n  if (t.includes('analysis') || t.includes('brief')) return 'An\u00E1lisis';\n  if (t.includes('text') || t.includes('copy')) return 'Texto';\n  if (t.includes('slide') || t.includes('deck')) return 'Diapositivas';\n  // Humanize unknown types without brands: generate-foo \u2192 Generate foo\n  const human = stripProviderNames(t.replace(/-/g, ' '));\n  if (!human || containsProviderBrand(human)) return 'Archivo';\n  return human.charAt(0).toUpperCase() + human.slice(1);\n}\n\nfunction jobCategoryLabel(row: Record<string, unknown>): string {\n  for (const key of [\n    'category',\n    'Category',\n    'job_category',\n    'jobCategory',\n    'JobCategory',\n    'media_category',\n    'mediaCategory',\n    // Kaiman feature / tool labels from the host pipeline\n    'feature',\n    'Feature',\n    'feature_name',\n    'featureName',\n    'kaiman_feature',\n    'kaimanFeature',\n    'tool',\n    'Tool',\n    'edit_tool',\n    'editTool',\n    'operation',\n    'Operation',\n  ]) {\n    const raw = row[key];\n    if (typeof raw === 'string' && raw.trim()) {\n      const cleaned = stripProviderNames(raw.trim());\n      if (cleaned && !containsProviderBrand(cleaned)) return cleaned;\n    }\n  }\n  return '';\n}\n\nfunction jobDisplayName(row: Record<string, unknown>, fallbackId: string): string {\n  // Prefer the job category / Kaiman feature (never a provider brand).\n  const category = jobCategoryLabel(row);\n  if (category) return category.slice(0, 48);\n\n  const jobType = normalizeJobType(row.jobType ?? row.job_type);\n  if (jobType) {\n    const fromType = categoryFromJobType(jobType);\n    if (fromType && !containsProviderBrand(fromType)) return fromType.slice(0, 48);\n  }\n\n  const input = parseJsonLoose(row.inputParamsJson ?? row.input_params_json);\n  if (input && typeof input === 'object') {\n    const rec = input as Record<string, unknown>;\n    for (const key of ['image_prompt', 'prompt', 'edit_details', 'text']) {\n      const v = rec[key];\n      if (typeof v === 'string' && v.trim()) {\n        const cleaned = stripProviderNames(v.trim());\n        if (cleaned && !containsProviderBrand(cleaned)) return cleaned.slice(0, 48);\n      }\n    }\n  }\n\n  const nameRaw = typeof row.name === 'string' ? row.name.trim() : '';\n  const name = stripProviderNames(nameRaw);\n  if (name && !containsProviderBrand(name)) return name.slice(0, 48);\n\n  return jobType ? categoryFromJobType(jobType) : `Archivo ${fallbackId}`.slice(0, 48);\n}\n\n/** Audio My Files title: category/feature only \u2014 never S3/provider filenames. */\nfunction audioJobDisplayName(row: Record<string, unknown>, jobType: string): string {\n  const category = jobCategoryLabel(row);\n  if (category) return category.slice(0, 48);\n  if (jobType) {\n    const fromType = categoryFromJobType(jobType);\n    if (fromType && !containsProviderBrand(fromType)) return fromType.slice(0, 48);\n  }\n  return 'Audio';\n}\n\n/** Collect candidate media URLs from a job row (no kind filter yet). */\nfunction collectJobHttpUrls(row: Record<string, unknown>): string[] {\n  const collected: string[] = [];\n\n  const s3Raw =\n    row.s3UrlsSavedJson ??\n    row.s3_urls_saved_json ??\n    row.s3_urls_saved ??\n    row.s3UrlsSaved;\n  collected.push(...extractHttpUrls(s3Raw));\n\n  const preview =\n    (typeof row.previewUrl === 'string' && row.previewUrl) ||\n    (typeof row.preview_url === 'string' && row.preview_url) ||\n    '';\n  if (preview) collected.push(preview);\n\n  const s3Direct =\n    (typeof row.s3_url === 'string' && row.s3_url) ||\n    (typeof row.s3Url === 'string' && row.s3Url) ||\n    '';\n  if (s3Direct) collected.push(s3Direct);\n\n  if (collected.length === 0) {\n    collected.push(\n      ...extractHttpUrls(row.aiResponseJson ?? row.ai_response_json),\n    );\n  }\n\n  const seen = new Set<string>();\n  const out: string[] = [];\n  for (const url of collected) {\n    if (!isRemoteImageUrl(url) || seen.has(url)) continue;\n    seen.add(url);\n    out.push(url);\n  }\n  return out;\n}\n\nfunction classifyMediaUrl(url: string, jobType: string): FileMediaKind | null {\n  if (isLikelyAudioAssetUrl(url)) return 'audio';\n  if (isLikelyVideoAssetUrl(url)) return 'video';\n  if (IMAGE_EXT.test(url) || isLikelyImageAssetUrl(url)) return 'image';\n  // Extension-less S3 keys: lean on job type.\n  if (isAudioJobType(jobType)) return 'audio';\n  if (isVideoJobType(jobType)) return 'video';\n  if (isImageJobType(jobType) || !jobType) return 'image';\n  return null;\n}\n\nfunction urlsFromJobRow(row: Record<string, unknown>): string[] {\n  return collectJobHttpUrls(row).filter((url) => isLikelyImageAssetUrl(url));\n}\n\n/**\n * Resolve a remote image URL to a same-origin blob URL so Fabric can\n * load it without tainting the canvas (CORS).\n *\n * Order: direct fetch \u2192 Wizard `/api/download` BFF (S3 / private buckets).\n */\nexport async function resolveImageSrcForCanvas(url: string): Promise<string> {\n  if (!url || url.startsWith('data:') || url.startsWith('blob:')) return url;\n  if (!isRemoteImageUrl(url)) return url;\n\n  const fetchAsObjectUrl = async (fetchUrl: string): Promise<string | null> => {\n    try {\n      const res = await fetch(fetchUrl, { credentials: 'include' });\n      if (!res.ok) return null;\n      const blob = await res.blob();\n      if (!blob || blob.size === 0) return null;\n      const typed =\n        blob.type && blob.type.startsWith('image/')\n          ? blob\n          : new Blob([blob], { type: 'image/png' });\n      return URL.createObjectURL(typed);\n    } catch {\n      return null;\n    }\n  };\n\n  // Cross-origin (S3): proxy first \u2014 direct fetch fails CORS from localhost\n  // and still floods the console even when caught.\n  const proxy = `/api/download?mode=download&filename=${encodeURIComponent(\n    'canvas-image.png',\n  )}&url=${encodeURIComponent(url)}`;\n  const viaProxy = await fetchAsObjectUrl(proxy);\n  if (viaProxy) return viaProxy;\n\n  const direct = await fetchAsObjectUrl(url);\n  if (direct) return direct;\n\n  return url;\n}\n\n/**\n * Download a remote media URL as a File + blob URL.\n * Cross-origin (S3 jobs) goes through Wizard `/api/download` first to avoid CORS.\n */\nexport async function fetchRemoteMediaAsFile(\n  url: string,\n  name: string,\n  mimeFallback = 'application/octet-stream',\n): Promise<{ file: File; objectUrl: string } | null> {\n  if (!url) return null;\n\n  const tryFetch = async (\n    fetchUrl: string,\n    credentials: RequestCredentials,\n  ): Promise<{ file: File; objectUrl: string } | null> => {\n    try {\n      const res = await fetch(fetchUrl, { credentials });\n      if (!res.ok) return null;\n      const blob = await res.blob();\n      if (!blob || blob.size === 0) return null;\n      const mime = blob.type || mimeFallback;\n      const file = new File([blob], name, { type: mime });\n      return { file, objectUrl: URL.createObjectURL(blob) };\n    } catch {\n      return null;\n    }\n  };\n\n  const isHttp = /^https?:\\/\\//i.test(url);\n  const sameOrigin =\n    typeof window !== 'undefined' && isHttp && url.startsWith(window.location.origin);\n\n  if (isHttp && !sameOrigin) {\n    const proxy = `/api/download?mode=download&filename=${encodeURIComponent(\n      name,\n    )}&url=${encodeURIComponent(url)}`;\n    const viaProxy = await tryFetch(proxy, 'include');\n    if (viaProxy) return viaProxy;\n    // Public CDN with CORS configured \u2014 omit credentials to avoid preflight noise.\n    return tryFetch(url, 'omit');\n  }\n\n  return tryFetch(url, 'include');\n}\n\n/**\n * Lists completed image jobs that expose an HTTP asset URL.\n * Tries Wizard BFF `/api/jobs` first, then .NET `/api/ai-jobs`.\n * Returns [] when both fail so the UI can still show brand images.\n */\nexport async function listImageJobsWithS3(opts?: {\n  signal?: AbortSignal;\n}): Promise<FileImageItem[]> {\n  try {\n    const { getWizardApiClient, NotImplementedError, AuthError } = await import(\n      './wizardApiClient'\n    );\n    const { getEditorIdentity } = await import('./identity');\n    const { accountId, brandId } = getEditorIdentity();\n    const client = getWizardApiClient();\n\n    const query = {\n      account_id: accountId,\n      brand_id: brandId,\n      job_type: 'ad_images',\n      status: 'Completed',\n      page: 1,\n      page_size: 48,\n      lite: true,\n    };\n\n    let data: unknown = null;\n    for (const path of ['/api/jobs', '/api/ai-jobs'] as const) {\n      try {\n        data = await client.getForJson<unknown>(path, query, {\n          signal: opts?.signal,\n        });\n        break;\n      } catch (err) {\n        if (opts?.signal?.aborted) throw err;\n        if (err instanceof AuthError) throw err;\n        // 404/501 or network \u2014 try the other path\n        if (!(err instanceof NotImplementedError) && path === '/api/ai-jobs') {\n          // last path failed for a non-missing reason; still fall through to []\n        }\n        data = null;\n      }\n    }\n\n    if (data == null) return [];\n\n    const rows = Array.isArray(data)\n      ? data\n      : data &&\n          typeof data === 'object' &&\n          Array.isArray((data as { items?: unknown }).items)\n        ? (data as { items: unknown[] }).items\n        : data &&\n            typeof data === 'object' &&\n            Array.isArray((data as { jobs?: unknown }).jobs)\n          ? (data as { jobs: unknown[] }).jobs\n          : [];\n\n    const out: FileImageItem[] = [];\n    const seenUrls = new Set<string>();\n\n    for (const row of rows) {\n      if (!row || typeof row !== 'object') continue;\n      const r = row as Record<string, unknown>;\n      const jobType = normalizeJobType(r.jobType ?? r.job_type);\n      // Backend may ignore job_type; keep only image-like rows.\n      if (jobType && !isImageJobType(jobType)) continue;\n      if (r.status != null && !isCompletedStatus(r.status)) continue;\n\n      const id = String(r.id ?? r.job_id ?? r.jobId ?? '');\n      const urls = urlsFromJobRow(r);\n      if (urls.length === 0) continue;\n\n      const name = jobDisplayName(r, id || String(out.length + 1));\n      for (let i = 0; i < urls.length; i++) {\n        const url = urls[i]!;\n        if (seenUrls.has(url)) continue;\n        seenUrls.add(url);\n        out.push({\n          id: urls.length > 1 ? `${id || url}-${i}` : id || url,\n          url,\n          name: urls.length > 1 ? `${name} (${i + 1})` : name,\n          source: 'job',\n        });\n      }\n    }\n\n    return out;\n  } catch {\n    return [];\n  }\n}\n\nasync function fetchAiJobRows(opts?: {\n  signal?: AbortSignal;\n  jobType?: string;\n  pageSize?: number;\n  lite?: boolean;\n}): Promise<Record<string, unknown>[]> {\n  const { getWizardApiClient, NotImplementedError, AuthError } = await import(\n    './wizardApiClient'\n  );\n  const { getEditorIdentity } = await import('./identity');\n  const { accountId, brandId } = getEditorIdentity();\n  const client = getWizardApiClient();\n\n  const query: Record<string, string | number | boolean> = {\n    account_id: accountId,\n    brand_id: brandId,\n    status: 'Completed',\n    page: 1,\n    page_size: opts?.pageSize ?? 80,\n    lite: opts?.lite ?? true,\n  };\n  if (opts?.jobType) query.job_type = opts.jobType;\n\n  let data: unknown = null;\n  for (const path of ['/api/jobs', '/api/ai-jobs'] as const) {\n    try {\n      data = await client.getForJson<unknown>(path, query, {\n        signal: opts?.signal,\n      });\n      break;\n    } catch (err) {\n      if (opts?.signal?.aborted) throw err;\n      if (err instanceof AuthError) throw err;\n      if (!(err instanceof NotImplementedError) && path === '/api/ai-jobs') {\n        // last path failed\n      }\n      data = null;\n    }\n  }\n\n  if (data == null) return [];\n\n  const rows = Array.isArray(data)\n    ? data\n    : data &&\n        typeof data === 'object' &&\n        Array.isArray((data as { items?: unknown }).items)\n      ? (data as { items: unknown[] }).items\n      : data &&\n          typeof data === 'object' &&\n          Array.isArray((data as { jobs?: unknown }).jobs)\n        ? (data as { jobs: unknown[] }).jobs\n        : [];\n\n  return rows.filter(\n    (row): row is Record<string, unknown> =>\n      !!row && typeof row === 'object',\n  );\n}\n\n/**\n * Lists completed image + video + audio jobs with HTTP asset URLs for the\n * video studio \"My Files\" dock (add to timeline).\n */\nexport async function listMediaJobsWithS3(opts?: {\n  signal?: AbortSignal;\n}): Promise<FileMediaItem[]> {\n  try {\n    // Merge several queries \u2014 an unfiltered page can be full of non-media jobs\n    // and would otherwise skip the image/video fallbacks (empty gallery).\n    const batches = await Promise.all([\n      fetchAiJobRows({ signal: opts?.signal, pageSize: 80, lite: true }),\n      fetchAiJobRows({ signal: opts?.signal, jobType: 'ad_images', pageSize: 48, lite: true }),\n      fetchAiJobRows({ signal: opts?.signal, jobType: 'ad_video', pageSize: 48, lite: true }),\n      fetchAiJobRows({ signal: opts?.signal, jobType: 'video', pageSize: 48, lite: true }),\n      fetchAiJobRows({ signal: opts?.signal, jobType: 'ad_images', pageSize: 48, lite: false }),\n    ]);\n\n    const seenRows = new Set<string>();\n    const rows: Record<string, unknown>[] = [];\n    for (const batch of batches) {\n      for (const r of batch) {\n        const id = String(r.id ?? r.job_id ?? r.jobId ?? '');\n        const key = id || JSON.stringify(r).slice(0, 120);\n        if (seenRows.has(key)) continue;\n        seenRows.add(key);\n        rows.push(r);\n      }\n    }\n\n    const out: FileMediaItem[] = [];\n    const seenUrls = new Set<string>();\n\n    for (const r of rows) {\n      const jobType = normalizeJobType(r.jobType ?? r.job_type);\n      if (r.status != null && !isCompletedStatus(r.status)) continue;\n\n      // Skip rows that are clearly not image/video/audio when type is known.\n      if (\n        jobType &&\n        !isImageJobType(jobType) &&\n        !isVideoJobType(jobType) &&\n        !isAudioJobType(jobType)\n      ) {\n        continue;\n      }\n\n      const id = String(r.id ?? r.job_id ?? r.jobId ?? '');\n      const urls = collectJobHttpUrls(r);\n      if (urls.length === 0) continue;\n\n      const name = jobDisplayName(r, id || String(out.length + 1));\n      const status =\n        r.status != null ? String(r.status) : undefined;\n      const categoryLabel = jobCategoryLabel(r) || undefined;\n      for (let i = 0; i < urls.length; i++) {\n        const url = urls[i]!;\n        const kind = classifyMediaUrl(url, jobType);\n        if (!kind || seenUrls.has(url)) continue;\n        seenUrls.add(url);\n        const displayName =\n          kind === 'audio'\n            ? audioJobDisplayName(r, jobType)\n            : name;\n        out.push({\n          id: urls.length > 1 ? `${id || url}-${i}` : id || url,\n          url,\n          name: urls.length > 1 ? `${displayName} (${i + 1})` : displayName,\n          kind,\n          source: 'job',\n          jobId: id || undefined,\n          jobType: jobType || undefined,\n          status,\n          category: kind === 'audio' ? displayName : categoryLabel,\n        });\n      }\n    }\n\n    return out;\n  } catch {\n    return [];\n  }\n}\n\n/**\n * Text studio: all completed image files + analysis/script/text copy files.\n * Images reuse the same media listing as video My Files so nothing is missed.\n */\nexport async function listTextStudioJobs(opts?: {\n  signal?: AbortSignal;\n}): Promise<TextJobItem[]> {\n  try {\n    const out: TextJobItem[] = [];\n    const seen = new Set<string>();\n\n    // 1) Images \u2014 same source as video/image My Files (proven URL extraction).\n    const media = await listMediaJobsWithS3({ signal: opts?.signal });\n    for (const m of media) {\n      if (m.kind !== 'image' || !m.url || seen.has(m.url)) continue;\n      seen.add(m.url);\n      out.push({\n        id: m.id,\n        name: m.name,\n        kind: 'image',\n        url: m.url,\n        source: 'job',\n      });\n    }\n\n    // 2) Analysis / script / text bodies \u2014 wider page + full payload when possible.\n    let rows = await fetchAiJobRows({\n      signal: opts?.signal,\n      pageSize: 200,\n      lite: false,\n    });\n    if (rows.length === 0) {\n      rows = await fetchAiJobRows({ signal: opts?.signal, pageSize: 200, lite: true });\n    }\n\n    for (const r of rows) {\n      const jobType = normalizeJobType(r.jobType ?? r.job_type);\n      if (r.status != null && !isCompletedStatus(r.status)) continue;\n      if (jobType && (isAudioJobType(jobType) || isVideoJobType(jobType))) continue;\n\n      const id = String(r.id ?? r.job_id ?? r.jobId ?? '');\n      const name = jobDisplayName(r, id || String(out.length + 1));\n\n      // Catch any image URLs missed by media listing (different payload shapes).\n      const urls = collectJobHttpUrls(r);\n      for (let i = 0; i < urls.length; i++) {\n        const url = urls[i]!;\n        const mediaKind = classifyMediaUrl(url, jobType);\n        if (mediaKind !== 'image' || seen.has(url)) continue;\n        seen.add(url);\n        out.push({\n          id: urls.length > 1 ? `${id || url}-img-${i}` : `${id || url}-img`,\n          name: urls.length > 1 ? `${name} (${i + 1})` : name,\n          kind: 'image',\n          url,\n          source: 'job',\n        });\n      }\n\n      const rawText = extractJobTextBody(\n        r.aiResponseJson ??\n          r.ai_response_json ??\n          r.outputJson ??\n          r.output_json ??\n          r.resultJson ??\n          r.result_json ??\n          r.output ??\n          r.result ??\n          r.prompt ??\n          r.input,\n      );\n      const kind = textKindFromJobType(jobType);\n      const typedTextJob =\n        isTextContentJobType(jobType) || kind === 'analysis' || kind === 'script';\n\n      // Pure image jobs without copy \u2014 already covered by image cards.\n      if (isImageJobType(jobType) && !typedTextJob && !rawText) continue;\n\n      // Include typed analysis/script even with short/empty body so the file is visible.\n      if (!typedTextJob && (!rawText || rawText.length < 12)) continue;\n\n      const text = rawText?.trim() || '';\n      const key = `text:${id}:${kind}:${text.slice(0, 48) || name}`;\n      if (seen.has(key)) continue;\n      seen.add(key);\n      out.push({\n        id: `${id || key}-text`,\n        name,\n        kind: typedTextJob ? kind : textKindFromJobType(jobType),\n        text: text || undefined,\n        source: 'job',\n      });\n    }\n\n    return out;\n  } catch {\n    return [];\n  }\n}\n", "import { type Keyframe } from '../../store/useVideoStore';\n\n// Easing Bezier Curve solver\nfunction solveBezier(t: number, p1x: number, p1y: number, p2x: number, p2y: number): number {\n  // Simple approximation of cubic bezier curve\n  // B(t) = (1-t)^3 * P0 + 3(1-t)^2 * t * P1 + 3(1-t) * t^2 * P2 + t^3 * P3\n  // P0 is (0,0), P3 is (1,1)\n  const cx = 3.0 * p1x;\n  const bx = 3.0 * (p2x - p1x) - cx;\n  const ax = 1.0 - cx - bx;\n  \n  const cy = 3.0 * p1y;\n  const by = 3.0 * (p2y - p1y) - cy;\n  const ay = 1.0 - cy - by;\n\n  // Perform Newton-Raphson method to solve for t given x\n  let sampleT = t;\n  for (let i = 0; i < 5; i++) {\n    const currentX = ((ax * sampleT + bx) * sampleT + cx) * sampleT;\n    const derivativeX = (3.0 * ax * sampleT + 2.0 * bx) * sampleT + cx;\n    if (Math.abs(derivativeX) < 1e-6) break;\n    sampleT -= (currentX - t) / derivativeX;\n  }\n\n  // Calculate y for the solved t\n  return ((ay * sampleT + by) * sampleT + cy) * sampleT;\n}\n\nexport function interpolateValue(\n  time: number,\n  kfA: Keyframe,\n  kfB: Keyframe\n): number {\n  const t = (time - kfA.time) / (kfB.time - kfA.time);\n  if (t <= 0) return kfA.value;\n  if (t >= 1) return kfB.value;\n\n  switch (kfA.easing) {\n    case 'hold':\n      return kfA.value;\n    case 'ease-in':\n      return kfA.value + (kfB.value - kfA.value) * (t * t);\n    case 'ease-out':\n      return kfA.value + (kfB.value - kfA.value) * (t * (2 - t));\n    case 'ease-in-out':\n      return kfA.value + (kfB.value - kfA.value) * (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t);\n    case 'bezier': {\n      const p1x = kfA.bezierOut ? kfA.bezierOut[0] : 0.25;\n      const p1y = kfA.bezierOut ? kfA.bezierOut[1] : 0.15;\n      const p2x = kfB.bezierIn ? kfB.bezierIn[0] : 0.75;\n      const p2y = kfB.bezierIn ? kfB.bezierIn[1] : 0.85;\n      const easedT = solveBezier(t, p1x, p1y, p2x, p2y);\n      return kfA.value + (kfB.value - kfA.value) * easedT;\n    }\n    case 'linear':\n    default:\n      return kfA.value + (kfB.value - kfA.value) * t;\n  }\n}\n\nexport function getInterpolatedValue(\n  keyframes: Keyframe[],\n  time: number,\n  defaultValue: number\n): number {\n  if (!keyframes || keyframes.length === 0) return defaultValue;\n\n  // Sort keyframes by time\n  const sorted = [...keyframes].sort((a, b) => a.time - b.time);\n\n  if (time <= sorted[0].time) {\n    return sorted[0].value;\n  }\n  if (time >= sorted[sorted.length - 1].time) {\n    return sorted[sorted.length - 1].value;\n  }\n\n  // Find the boundary keyframes\n  for (let i = 0; i < sorted.length - 1; i++) {\n    const kfA = sorted[i];\n    const kfB = sorted[i + 1];\n    if (time >= kfA.time && time <= kfB.time) {\n      return interpolateValue(time, kfA, kfB);\n    }\n  }\n\n  return defaultValue;\n}\n\nexport function getInterpolatedProperty(\n  clip: any,\n  property: string,\n  defaultValue: number,\n  time: number // clip-relative time\n): number {\n  if (!clip.keyframes) return defaultValue;\n  const track = clip.keyframes.find((t: any) => t.property === property);\n  if (!track || !track.keyframes || track.keyframes.length === 0) return defaultValue;\n  return getInterpolatedValue(track.keyframes, time, defaultValue);\n}\n", "export interface TransitionShader {\n  name: string;\n  glsl: string;\n}\n\nexport const TRANSITION_SHADERS: Record<string, string> = {\n  'cross-dissolve': `\n    vec4 transition(vec2 uv, float progress) {\n      return mix(getFromColor(uv), getToColor(uv), progress);\n    }\n  `,\n  'fade-black': `\n    vec4 transition(vec2 uv, float progress) {\n      if (progress < 0.5) {\n        return mix(getFromColor(uv), vec4(0.0, 0.0, 0.0, 1.0), progress * 2.0);\n      } else {\n        return mix(vec4(0.0, 0.0, 0.0, 1.0), getToColor(uv), (progress - 0.5) * 2.0);\n      }\n    }\n  `,\n  'fade-white': `\n    vec4 transition(vec2 uv, float progress) {\n      if (progress < 0.5) {\n        return mix(getFromColor(uv), vec4(1.0, 1.0, 1.0, 1.0), progress * 2.0);\n      } else {\n        return mix(vec4(1.0, 1.0, 1.0, 1.0), getToColor(uv), (progress - 0.5) * 2.0);\n      }\n    }\n  `,\n  'wipe-left': `\n    vec4 transition(vec2 uv, float progress) {\n      return uv.x < (1.0 - progress) ? getFromColor(uv) : getToColor(uv);\n    }\n  `,\n  'wipe-right': `\n    vec4 transition(vec2 uv, float progress) {\n      return uv.x > progress ? getFromColor(uv) : getToColor(uv);\n    }\n  `,\n  'wipe-up': `\n    vec4 transition(vec2 uv, float progress) {\n      return uv.y < (1.0 - progress) ? getFromColor(uv) : getToColor(uv);\n    }\n  `,\n  'wipe-down': `\n    vec4 transition(vec2 uv, float progress) {\n      return uv.y > progress ? getFromColor(uv) : getToColor(uv);\n    }\n  `,\n  'slide-left': `\n    vec4 transition(vec2 uv, float progress) {\n      vec2 uv1 = uv + vec2(progress, 0.0);\n      vec2 uv2 = uv - vec2(1.0 - progress, 0.0);\n      if (uv1.x < 1.0) {\n        return getFromColor(uv1);\n      } else {\n        return getToColor(uv2);\n      }\n    }\n  `,\n  'slide-right': `\n    vec4 transition(vec2 uv, float progress) {\n      vec2 uv1 = uv - vec2(progress, 0.0);\n      vec2 uv2 = uv + vec2(1.0 - progress, 0.0);\n      if (uv1.x > 0.0) {\n        return getFromColor(uv1);\n      } else {\n        return getToColor(uv2);\n      }\n    }\n  `,\n  'push-left': `\n    vec4 transition(vec2 uv, float progress) {\n      vec2 uv1 = uv + vec2(progress, 0.0);\n      vec2 uv2 = uv - vec2(1.0 - progress, 0.0);\n      return uv1.x < 1.0 ? getFromColor(uv1) : getToColor(uv2);\n    }\n  `,\n  'push-right': `\n    vec4 transition(vec2 uv, float progress) {\n      vec2 uv2 = uv + vec2(1.0 - progress, 0.0);\n      return uv.x < progress ? getToColor(uv2) : getFromColor(uv - vec2(progress, 0.0));\n    }\n  `,\n  'iris-circle': `\n    vec4 transition(vec2 uv, float progress) {\n      vec2 center = vec2(0.5, 0.5);\n      float dist = distance(uv, center);\n      float radius = progress * 0.7071; // max distance is sqrt(0.5^2 + 0.5^2)\n      return dist > radius ? getFromColor(uv) : getToColor(uv);\n    }\n  `,\n  'clock-wipe': `\n    vec4 transition(vec2 uv, float progress) {\n      vec2 center = uv - vec2(0.5);\n      float angle = atan(center.y, center.x) + 3.14159265;\n      float threshold = progress * 2.0 * 3.14159265;\n      return angle < threshold ? getToColor(uv) : getFromColor(uv);\n    }\n  `,\n  'zoom-in': `\n    vec4 transition(vec2 uv, float progress) {\n      vec2 center = vec2(0.5);\n      vec2 uv1 = center + (uv - center) * (1.0 - progress);\n      vec2 uv2 = center + (uv - center) / progress;\n      if (progress < 0.01) return getFromColor(uv);\n      return mix(getFromColor(uv1), getToColor(uv), progress);\n    }\n  `,\n  'zoom-punch': `\n    vec4 transition(vec2 uv, float progress) {\n      vec2 center = vec2(0.5);\n      float zoom = 1.0 + sin(progress * 3.14159265) * 0.5;\n      vec2 zoomedUv = center + (uv - center) / zoom;\n      return mix(getFromColor(zoomedUv), getToColor(zoomedUv), progress);\n    }\n  `,\n  'spin-zoom': `\n    vec4 transition(vec2 uv, float progress) {\n      vec2 center = vec2(0.5);\n      float angle = progress * 6.283185;\n      float scale = 1.0 - progress;\n      \n      mat2 rotationMatrix = mat2(cos(angle), -sin(angle), sin(angle), cos(angle));\n      vec2 rotatedUv = center + rotationMatrix * (uv - center) / max(0.01, scale);\n      \n      if (rotatedUv.x >= 0.0 && rotatedUv.x <= 1.0 && rotatedUv.y >= 0.0 && rotatedUv.y <= 1.0) {\n        return mix(getFromColor(rotatedUv), getToColor(uv), progress);\n      } else {\n        return getToColor(uv);\n      }\n    }\n  `,\n  'blur-dissolve': `\n    vec4 blur(sampler2D tex, vec2 uv, float radius) {\n      vec4 sum = vec4(0.0);\n      float count = 0.0;\n      for (float x = -2.0; x <= 2.0; x += 1.0) {\n        for (float y = -2.0; y <= 2.0; y += 1.0) {\n          vec2 offset = vec2(x, y) * radius * 0.005;\n          sum += texture2D(tex, uv + offset);\n          count += 1.0;\n        }\n      }\n      return sum / count;\n    }\n    vec4 transition(vec2 uv, float progress) {\n      float blurRadius = sin(progress * 3.14159265) * 2.0;\n      vec4 c1 = progress < 0.5 ? blur(u_texture_from, uv, blurRadius) : getFromColor(uv);\n      vec4 c2 = progress >= 0.5 ? blur(u_texture_to, uv, blurRadius) : getToColor(uv);\n      return mix(c1, c2, progress);\n    }\n  `,\n  'pixelate': `\n    vec4 transition(vec2 uv, float progress) {\n      float size = sin(progress * 3.14159265) * 0.1;\n      if (size < 0.001) return mix(getFromColor(uv), getToColor(uv), progress);\n      vec2 pixelatedUv = floor(uv / size) * size;\n      return mix(getFromColor(pixelatedUv), getToColor(pixelatedUv), progress);\n    }\n  `,\n  'glitch': `\n    float rand(vec2 co) {\n      return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);\n    }\n    vec4 transition(vec2 uv, float progress) {\n      float strength = sin(progress * 3.14159265) * 0.1;\n      vec2 glitchOffset = vec2(rand(vec2(floor(uv.y * 30.0), progress)) - 0.5, 0.0) * strength;\n      vec4 c1 = getFromColor(uv + glitchOffset);\n      vec4 c2 = getToColor(uv - glitchOffset);\n      return mix(c1, c2, progress);\n    }\n  `,\n  'additive-dissolve': `\n    vec4 transition(vec2 uv, float progress) {\n      vec4 c1 = getFromColor(uv);\n      vec4 c2 = getToColor(uv);\n      return c1 * (1.0 - progress) + c2 * progress + c1 * c2 * sin(progress * 3.14159265);\n    }\n  `,\n  'film-burn': `\n    vec4 transition(vec2 uv, float progress) {\n      vec4 c1 = getFromColor(uv);\n      vec4 c2 = getToColor(uv);\n      float burn = sin(progress * 3.14159265);\n      vec4 burnColor = vec4(1.0, 0.45, 0.1, 1.0) * burn * 1.5;\n      return mix(c1, c2, progress) + burnColor;\n    }\n  `\n};\n\nexport const getTransitionShader = (type: string): string => {\n  return TRANSITION_SHADERS[type] || TRANSITION_SHADERS['cross-dissolve'];\n};\n", "import { type Clip, type ColorGradingSettings, type CurvePoint } from '../../store/useVideoStore';\nimport { getInterpolatedProperty } from './keyframeUtils';\nimport { getTransitionShader } from './transitionDefinitions';\n\n// Vertex shader source\nconst VERTEX_SHADER_SRC = `#version 300 es\nin vec2 position;\nout vec2 v_texCoord;\n\nuniform vec2 u_translation;\nuniform vec2 u_scale;\nuniform float u_rotation;\nuniform float u_canvasAspect; // width / height \u2014 rotate in pixel space, not skewed NDC\nuniform bool u_flipX;\nuniform bool u_flipY;\n\nvoid main() {\n  // Scale in NDC, then rotate in isotropic (pixel) space so the overlay CSS\n  // rotate() matches the drawn media on non-square canvases (e.g. 9:16).\n  vec2 scaledPosition = position * u_scale;\n  float aspect = max(u_canvasAspect, 0.0001);\n  vec2 iso = vec2(scaledPosition.x * aspect, scaledPosition.y);\n  float s = sin(u_rotation);\n  float c = cos(u_rotation);\n  vec2 rotatedIso = vec2(\n    iso.x * c - iso.y * s,\n    iso.x * s + iso.y * c\n  );\n  vec2 rotatedPosition = vec2(rotatedIso.x / aspect, rotatedIso.y);\n  vec2 finalPosition = rotatedPosition + u_translation;\n\n  vec2 tex = position * 0.5 + 0.5;\n  if (u_flipX) {\n    tex.x = 1.0 - tex.x;\n  }\n  if (u_flipY) {\n    tex.y = tex.y;\n  } else {\n    tex.y = 1.0 - tex.y;\n  }\n  v_texCoord = tex;\n\n  gl_Position = vec4(finalPosition, 0.0, 1.0);\n}\n`;\n\n// Master Fragment shader for applying all grading, curves, HSL, and filters\nconst FRAGMENT_SHADER_SRC = `#version 300 es\nprecision highp float;\nprecision highp sampler3D;\n\nin vec2 v_texCoord;\nout vec4 outColor;\n\nuniform sampler2D u_image;\nuniform float u_opacity;\nuniform vec2 u_resolution;\n\n// Grading settings\nuniform float u_exposure;\nuniform float u_contrast;\nuniform float u_highlights;\nuniform float u_shadows;\nuniform float u_temperature;\nuniform float u_tint;\nuniform float u_vibrance;\nuniform float u_saturation;\n\n// Vignette settings\nuniform bool u_vignetteEnabled;\nuniform float u_vignetteAmount;\nuniform float u_vignetteMidpoint;\nuniform float u_vignetteFeather;\n\n\n// Curves settings\nuniform sampler2D u_curvesTexture; // 256 x 1 texture\nuniform bool u_curvesEnabled;\n\n// HSL settings\nuniform bool u_hslEnabled;\nuniform vec3 u_hslAdjustments[8];\n\n// Stylistic effects parameters\nuniform bool u_fx_mirror;\nuniform int u_fx_mirror_type;\n\nuniform bool u_fx_blur;\nuniform float u_fx_blur_radius;\n\nuniform bool u_fx_vhs;\nuniform float u_fx_vhs_noise;\nuniform float u_fx_vhs_bleed;\nuniform float u_fx_vhs_lines;\n\nuniform bool u_fx_aberration;\nuniform float u_fx_aberration_amount;\n\nuniform bool u_fx_pixelate;\nuniform float u_fx_pixelate_blockSize;\n\nuniform bool u_fx_oldFilm;\nuniform float u_fx_oldFilm_sepia;\nuniform float u_fx_oldFilm_scratch;\nuniform float u_fx_oldFilm_jitter;\n\nuniform float u_time;\nuniform bool u_isImage;\n\n// Random noise helper\nfloat rand(vec2 co) {\n  return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);\n}\n\n// Convert RGB to HSL\nvec3 rgb2hsl(vec3 c) {\n  float maxVal = max(max(c.r, c.g), c.b);\n  float minVal = min(min(c.r, c.g), c.b);\n  float h = 0.0;\n  float s = 0.0;\n  float l = (maxVal + minVal) / 2.0;\n\n  if (maxVal != minVal) {\n    float d = maxVal - minVal;\n    s = l > 0.5 ? d / (2.0 - maxVal - minVal) : d / (maxVal + minVal);\n    if (maxVal == c.r) {\n      h = (c.g - c.b) / d + (c.g < c.b ? 6.0 : 0.0);\n    } else if (maxVal == c.g) {\n      h = (c.b - c.r) / d + 2.0;\n    } else if (maxVal == c.b) {\n      h = (c.r - c.g) / d + 4.0;\n    }\n    h /= 6.0;\n  }\n  return vec3(h, s, l);\n}\n\n// Convert HSL back to RGB\nfloat hue2rgb(float p, float q, float t) {\n  if (t < 0.0) t += 1.0;\n  if (t > 1.0) t -= 1.0;\n  if (t < 1.0 / 6.0) return p + (q - p) * 6.0 * t;\n  if (t < 0.5) return q;\n  if (t < 2.0 / 3.0) return p + (q - p) * (2.0 / 3.0 - t) * 6.0;\n  return p;\n}\n\nvec3 hsl2rgb(vec3 c) {\n  float h = c.x;\n  float s = c.y;\n  float l = c.z;\n  float r, g, b;\n\n  if (s == 0.0) {\n    r = g = b = l; // achromatic\n  } else {\n    float q = l < 0.5 ? l * (1.0 + s) : l + s - l * s;\n    float p = 2.0 * l - q;\n    r = hue2rgb(p, q, h + 1.0 / 3.0);\n    g = hue2rgb(p, q, h);\n    b = hue2rgb(p, q, h - 1.0 / 3.0);\n  }\n  return vec3(r, g, b);\n}\n\nvoid main() {\n  vec2 uv = v_texCoord;\n\n  // Mirror Effect (Step 0.5)\n  if (u_fx_mirror) {\n    if (u_fx_mirror_type == 1) { // horizontal\n      if (uv.x > 0.5) uv.x = 1.0 - uv.x;\n    } else if (u_fx_mirror_type == 2) { // vertical\n      if (uv.y > 0.5) uv.y = 1.0 - uv.y;\n    } else if (u_fx_mirror_type == 3) { // quad\n      if (uv.x > 0.5) uv.x = 1.0 - uv.x;\n      if (uv.y > 0.5) uv.y = 1.0 - uv.y;\n    }\n  }\n\n  // Pixelate Effect (Step 1)\n  if (u_fx_pixelate) {\n    float dx = u_fx_pixelate_blockSize / u_resolution.x;\n    float dy = u_fx_pixelate_blockSize / u_resolution.y;\n    uv = vec2(dx * floor(uv.x / dx), dy * floor(uv.y / dy));\n  }\n\n  // Texture sampling with chromatic aberration offset (Step 2)\n  vec4 color;\n  if (u_fx_aberration) {\n    float offset = u_fx_aberration_amount / u_resolution.x;\n    color.r = texture(u_image, uv + vec2(offset, 0.0)).r;\n    color.g = texture(u_image, uv).g;\n    color.b = texture(u_image, uv - vec2(offset, 0.0)).b;\n    color.a = texture(u_image, uv).a;\n  } else {\n    color = texture(u_image, uv);\n  }\n\n  // Gaussian Blur approximation (Step 3)\n  if (u_fx_blur) {\n    vec4 blurColor = vec4(0.0);\n    float totalWeight = 0.0;\n    float radius = u_fx_blur_radius;\n    for (float x = -3.0; x <= 3.0; x += 1.0) {\n      for (float y = -3.0; y <= 3.0; y += 1.0) {\n        float weight = exp(-(x*x + y*y) / (2.0 * radius * radius + 0.1));\n        vec2 offset = vec2(x, y) * (radius / 3.0) / u_resolution;\n        blurColor += texture(u_image, uv + offset) * weight;\n        totalWeight += weight;\n      }\n    }\n    color = blurColor / totalWeight;\n  }\n\n  // Basic color adjustments (Step 4)\n  vec3 rgb = color.rgb;\n\n  // Exposure\n  rgb *= pow(2.0, u_exposure);\n\n  // Contrast\n  rgb = (rgb - 0.5) * (1.0 + u_contrast / 100.0) + 0.5;\n\n  // Temperature / Tint\n  rgb.r += u_temperature * 0.002;\n  rgb.b -= u_temperature * 0.002;\n  rgb.g += u_tint * 0.002;\n\n  // Highlights and Shadows (approximated)\n  float luminance = dot(rgb, vec3(0.299, 0.587, 0.114));\n  float shadowMask = clamp(1.0 - luminance * 4.0, 0.0, 1.0);\n  float highlightMask = clamp((luminance - 0.75) * 4.0, 0.0, 1.0);\n  rgb += rgb * u_shadows * 0.003 * shadowMask;\n  rgb += rgb * u_highlights * 0.003 * highlightMask;\n\n  // Saturation & Vibrance\n  float mx = max(rgb.r, max(rgb.g, rgb.b));\n  float amt = (mx - luminance) * (u_vibrance * 0.01);\n  rgb += (mx - rgb) * amt;\n  rgb = mix(vec3(luminance), rgb, 1.0 + u_saturation / 100.0);\n\n  // HSL Adjustments (Step 4.5)\n  if (u_hslEnabled) {\n    vec3 hslColor = rgb2hsl(rgb);\n    float hDeg = hslColor.x * 360.0;\n    float w[8];\n    for (int i = 0; i < 8; i++) w[i] = 0.0;\n\n    if (hDeg < 30.0) {\n      float t = hDeg / 30.0;\n      w[0] = 1.0 - t; w[1] = t;\n    } else if (hDeg < 60.0) {\n      float t = (hDeg - 30.0) / 30.0;\n      w[1] = 1.0 - t; w[2] = t;\n    } else if (hDeg < 120.0) {\n      float t = (hDeg - 60.0) / 60.0;\n      w[2] = 1.0 - t; w[3] = t;\n    } else if (hDeg < 180.0) {\n      float t = (hDeg - 120.0) / 60.0;\n      w[3] = 1.0 - t; w[4] = t;\n    } else if (hDeg < 240.0) {\n      float t = (hDeg - 180.0) / 60.0;\n      w[4] = 1.0 - t; w[5] = t;\n    } else if (hDeg < 285.0) {\n      float t = (hDeg - 240.0) / 45.0;\n      w[5] = 1.0 - t; w[6] = t;\n    } else if (hDeg < 325.0) {\n      float t = (hDeg - 285.0) / 40.0;\n      w[6] = 1.0 - t; w[7] = t;\n    } else {\n      float t = (hDeg - 325.0) / 35.0;\n      w[7] = 1.0 - t; w[0] = t;\n    }\n\n    float shiftH = 0.0;\n    float shiftS = 0.0;\n    float shiftL = 0.0;\n    for (int i = 0; i < 8; i++) {\n      shiftH += w[i] * u_hslAdjustments[i].x;\n      shiftS += w[i] * u_hslAdjustments[i].y;\n      shiftL += w[i] * u_hslAdjustments[i].z;\n    }\n\n    hslColor.x = fract(hslColor.x + shiftH / 360.0);\n\n    if (shiftS >= 0.0) {\n      hslColor.y = mix(hslColor.y, 1.0, shiftS / 100.0);\n    } else {\n      hslColor.y = mix(hslColor.y, 0.0, -shiftS / 100.0);\n    }\n\n    if (shiftL >= 0.0) {\n      hslColor.z = mix(hslColor.z, 1.0, shiftL / 100.0);\n    } else {\n      hslColor.z = mix(hslColor.z, 0.0, -shiftL / 100.0);\n    }\n\n    rgb = hsl2rgb(hslColor);\n  }\n\n  // Curves Mapping (Step 5)\n  // Evaluate Curves Texture: R, G, B channels correspond to curve mappings\n  if (u_curvesEnabled) {\n    rgb = clamp(rgb, 0.0, 1.0);\n    // 1. Channel-specific curves (R, G, B channels of the texture)\n    rgb.r = texture(u_curvesTexture, vec2(rgb.r, 0.5)).r;\n    rgb.g = texture(u_curvesTexture, vec2(rgb.g, 0.5)).g;\n    rgb.b = texture(u_curvesTexture, vec2(rgb.b, 0.5)).b;\n    \n    // 2. Master curve (A channel of the texture)\n    rgb.r = texture(u_curvesTexture, vec2(rgb.r, 0.5)).a;\n    rgb.g = texture(u_curvesTexture, vec2(rgb.g, 0.5)).a;\n    rgb.b = texture(u_curvesTexture, vec2(rgb.b, 0.5)).a;\n  }\n\n\n  // Vignette (Step 7)\n  if (u_vignetteEnabled) {\n    float dist = length(uv - vec2(0.5)) * 1.41421356;\n    float start = u_vignetteMidpoint * 0.01;\n    float feather = max(u_vignetteFeather * 0.01, 0.01);\n    float vignetteValue = smoothstep(start, start + feather, dist);\n    float amt = u_vignetteAmount * 0.01;\n    if (amt >= 0.0) {\n      rgb = mix(rgb, vec3(0.0), vignetteValue * amt);\n    } else {\n      rgb = mix(rgb, vec3(1.0), vignetteValue * (-amt));\n    }\n  }\n\n  // Stylistic VHS Filter (Step 8)\n  if (u_fx_vhs) {\n    float scanline = sin(uv.y * 800.0 * (u_fx_vhs_lines * 0.02)) * 0.04;\n    rgb -= scanline;\n    float noise = (rand(uv + u_time) - 0.5) * (u_fx_vhs_noise * 0.005);\n    rgb += noise;\n    // Color Bleed horizontal smear\n    float bleed = u_fx_vhs_bleed * 0.005;\n    rgb.r = mix(rgb.r, texture(u_image, uv - vec2(bleed, 0.0)).r, 0.5);\n    rgb.b = mix(rgb.b, texture(u_image, uv + vec2(bleed, 0.0)).b, 0.5);\n  }\n\n  // Stylistic Retro Old Film (Step 9)\n  if (u_fx_oldFilm) {\n    // Sepia tone conversion\n    vec3 sepiaColor;\n    sepiaColor.r = dot(rgb, vec3(0.393, 0.769, 0.189));\n    sepiaColor.g = dot(rgb, vec3(0.349, 0.686, 0.168));\n    sepiaColor.b = dot(rgb, vec3(0.272, 0.534, 0.131));\n    rgb = mix(rgb, sepiaColor, u_fx_oldFilm_sepia * 0.01);\n\n    // Dynamic Dust Scratch line\n    float scratch = rand(vec2(floor(uv.x * 200.0), u_time)) > 0.98 ? 1.0 : 0.0;\n    rgb -= scratch * (u_fx_oldFilm_scratch * 0.003);\n  }\n\n  outColor = vec4(rgb, color.a * u_opacity);\n}\n`;\n\n// Helper to evaluate curve to 256 float coordinates\nfunction evaluateCurve(points: CurvePoint[]): number[] {\n  const values = new Array(256);\n  const sorted = [...points].sort((a, b) => a.x - b.x);\n\n  let ptIdx = 0;\n  for (let i = 0; i < 256; i++) {\n    const t = i / 255;\n    while (ptIdx < sorted.length - 1 && t > sorted[ptIdx + 1].x) {\n      ptIdx++;\n    }\n    const pA = sorted[ptIdx];\n    const pB = sorted[ptIdx + 1] || pA;\n    if (pA.x === pB.x) {\n      values[i] = pA.y;\n    } else {\n      const factor = (t - pA.x) / (pB.x - pA.x);\n      values[i] = pA.y + (pB.y - pA.y) * factor;\n    }\n    values[i] = Math.max(0, Math.min(1, values[i]));\n  }\n  return values;\n}\n\nexport class WebGLVideoRenderer {\n  private gl: WebGL2RenderingContext;\n  private program: WebGLProgram | null = null;\n  private quadBuffer: WebGLBuffer | null = null;\n  private curvesTexture: WebGLTexture | null = null;\n  private transitionProgramCache = new Map<string, WebGLProgram>();\n\n  constructor(gl: WebGL2RenderingContext) {\n    this.gl = gl;\n    this.initShaders();\n    this.initBuffers();\n  }\n\n  private initShaders() {\n    const gl = this.gl;\n    const vs = gl.createShader(gl.VERTEX_SHADER);\n    const fs = gl.createShader(gl.FRAGMENT_SHADER);\n    if (!vs || !fs) return;\n\n    gl.shaderSource(vs, VERTEX_SHADER_SRC);\n    gl.compileShader(vs);\n    if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {\n      console.error('VS compilation error:', gl.getShaderInfoLog(vs));\n    }\n\n    gl.shaderSource(fs, FRAGMENT_SHADER_SRC);\n    gl.compileShader(fs);\n    if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {\n      console.error('FS compilation error:', gl.getShaderInfoLog(fs));\n    }\n\n    const program = gl.createProgram();\n    if (!program) return;\n    gl.attachShader(program, vs);\n    gl.attachShader(program, fs);\n    gl.linkProgram(program);\n    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n      console.error('Program link error:', gl.getProgramInfoLog(program));\n    }\n\n    this.program = program;\n\n    // Set static texture units once during initialization to avoid type conflicts\n    gl.useProgram(program);\n    gl.uniform1i(gl.getUniformLocation(program, 'u_image'), 0);\n    gl.uniform1i(gl.getUniformLocation(program, 'u_curvesTexture'), 1);\n  }\n\n  private initBuffers() {\n    const gl = this.gl;\n    const vertices = new Float32Array([\n      -1.0, -1.0,\n       1.0, -1.0,\n      -1.0,  1.0,\n      -1.0,  1.0,\n       1.0, -1.0,\n       1.0,  1.0,\n    ]);\n    this.quadBuffer = gl.createBuffer();\n    gl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);\n    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);\n\n    // Create 1D Curves Texture\n    this.curvesTexture = gl.createTexture();\n    gl.bindTexture(gl.TEXTURE_2D, this.curvesTexture);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n  }\n\n  public updateCurvesTexture(curves: ColorGradingSettings['curves']) {\n    const gl = this.gl;\n    const rValues = evaluateCurve(curves.red);\n    const gValues = evaluateCurve(curves.green);\n    const bValues = evaluateCurve(curves.blue);\n    const mValues = evaluateCurve(curves.master);\n\n    const textureData = new Uint8Array(256 * 4);\n    for (let i = 0; i < 256; i++) {\n      textureData[i * 4] = Math.round(rValues[i] * 255);     // R channel curve\n      textureData[i * 4 + 1] = Math.round(gValues[i] * 255); // G channel curve\n      textureData[i * 4 + 2] = Math.round(bValues[i] * 255); // B channel curve\n      textureData[i * 4 + 3] = Math.round(mValues[i] * 255); // Master curve\n    }\n\n    gl.bindTexture(gl.TEXTURE_2D, this.curvesTexture);\n    gl.texImage2D(\n      gl.TEXTURE_2D,\n      0,\n      gl.RGBA,\n      256,\n      1,\n      0,\n      gl.RGBA,\n      gl.UNSIGNED_BYTE,\n      textureData\n    );\n  }\n\n\n  public drawLayer(\n    source: HTMLVideoElement | HTMLImageElement | HTMLCanvasElement,\n    clip: Clip,\n    relativeTime: number,\n    width: number,\n    height: number\n  ) {\n    const gl = this.gl;\n    const program = this.program;\n    if (!program) return;\n\n    gl.useProgram(program);\n\n    // Set custom blending based on clip.blendMode\n    const blendMode = clip.blendMode || 'normal';\n    if (blendMode === 'screen') {\n      gl.blendEquation(gl.FUNC_ADD);\n      gl.blendFunc(gl.ONE, gl.ONE);\n    } else if (blendMode === 'multiply') {\n      gl.blendEquation(gl.FUNC_ADD);\n      gl.blendFunc(gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA);\n    } else {\n      gl.blendEquation(gl.FUNC_ADD);\n      gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n    }\n\n    // Calculate transformation parameters\n    let scaleX = 1.0;\n    let scaleY = 1.0;\n    let translationX = 0.0;\n    let translationY = 0.0;\n    let rotationRad = 0.0;\n\n    // Intrinsic pixels \u2014 never CSS layout size (hidden preview cache is 1\u00D71 + Tailwind max-width).\n    const intrinsicSize = (el: HTMLVideoElement | HTMLImageElement | HTMLCanvasElement) => {\n      if (el instanceof HTMLVideoElement) {\n        return { w: el.videoWidth || 0, h: el.videoHeight || 0 };\n      }\n      if (el instanceof HTMLImageElement) {\n        return { w: el.naturalWidth || 0, h: el.naturalHeight || 0 };\n      }\n      return { w: el.width || 0, h: el.height || 0 };\n    };\n\n    if (clip.type === 'image') {\n      let baseScaleX = 200.0 / width;\n      let baseScaleY = 200.0 / height;\n\n      const { w: srcWidth, h: srcHeight } = intrinsicSize(source);\n\n      if (srcWidth > 0 && srcHeight > 0) {\n        const imageAspect = srcWidth / srcHeight;\n        const boxAspect = 1.0; // 200 / 200\n\n        const fitMode = clip.fitMode || 'fit';\n        if (fitMode === 'fit') {\n          if (imageAspect > boxAspect) {\n            baseScaleY = (200.0 / imageAspect) / height;\n          } else {\n            baseScaleX = (200.0 * imageAspect) / width;\n          }\n        } else if (fitMode === 'crop') {\n          if (imageAspect > boxAspect) {\n            baseScaleX = (200.0 * imageAspect) / width;\n          } else {\n            baseScaleY = (200.0 / imageAspect) / height;\n          }\n        }\n      }\n\n      scaleX = baseScaleX * (clip.scaleX !== undefined ? clip.scaleX : 1.0);\n      scaleY = baseScaleY * (clip.scaleY !== undefined ? clip.scaleY : 1.0);\n      translationX = ((clip.x !== undefined ? clip.x : 0.5) - 0.5) * 2;\n      translationY = (0.5 - (clip.y !== undefined ? clip.y : 0.5)) * 2;\n      rotationRad = ((clip.rotation || 0) * Math.PI) / 180;\n    } else {\n      let baseScaleX = 1.0;\n      let baseScaleY = 1.0;\n\n      const { w: srcWidth, h: srcHeight } = intrinsicSize(source);\n\n      if (srcWidth > 0 && srcHeight > 0) {\n        const imageAspect = srcWidth / srcHeight;\n        const canvasAspect = width / height;\n        const fitMode = clip.fitMode || 'fit';\n\n        if (fitMode === 'fit') {\n          if (imageAspect > canvasAspect) {\n            baseScaleX = 1.0;\n            baseScaleY = canvasAspect / imageAspect;\n          } else {\n            baseScaleX = imageAspect / canvasAspect;\n            baseScaleY = 1.0;\n          }\n        } else if (fitMode === 'crop') {\n          if (imageAspect > canvasAspect) {\n            baseScaleX = imageAspect / canvasAspect;\n            baseScaleY = 1.0;\n          } else {\n            baseScaleX = 1.0;\n            baseScaleY = canvasAspect / imageAspect;\n          }\n        }\n      }\n\n      scaleX = baseScaleX * (clip.scaleX !== undefined ? clip.scaleX : 1.0);\n      scaleY = baseScaleY * (clip.scaleY !== undefined ? clip.scaleY : 1.0);\n      translationX = ((clip.x !== undefined ? clip.x : 0.5) - 0.5) * 2;\n      translationY = (0.5 - (clip.y !== undefined ? clip.y : 0.5)) * 2;\n      rotationRad = ((clip.rotation || 0) * Math.PI) / 180;\n    }\n\n    // Set transformation & flips uniforms\n    gl.uniform2f(gl.getUniformLocation(program, 'u_translation'), translationX, translationY);\n    gl.uniform2f(gl.getUniformLocation(program, 'u_scale'), scaleX, scaleY);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_rotation'), rotationRad);\n    gl.uniform1f(\n      gl.getUniformLocation(program, 'u_canvasAspect'),\n      height > 0 ? width / height : 1,\n    );\n    gl.uniform1i(gl.getUniformLocation(program, 'u_flipX'), clip.flipX ? 1 : 0);\n    gl.uniform1i(gl.getUniformLocation(program, 'u_flipY'), clip.flipY ? 1 : 0);\n\n    // Setup coordinates quad buffers\n    const positionLoc = gl.getAttribLocation(program, 'position');\n    gl.enableVertexAttribArray(positionLoc);\n    gl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);\n    gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);\n\n    // Create and bind source texture\n    const texture = gl.createTexture();\n    gl.activeTexture(gl.TEXTURE0);\n    gl.bindTexture(gl.TEXTURE_2D, texture);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n    \n    // Upload current frame source\n    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);\n\n    // Set simple uniforms\n    gl.uniform1i(gl.getUniformLocation(program, 'u_image'), 0);\n    const isImg = source instanceof HTMLImageElement || clip.type === 'image';\n    gl.uniform1i(gl.getUniformLocation(program, 'u_isImage'), isImg ? 1 : 0);\n    \n    // Interpolate keyframe properties for opacity\n    const opacity = getInterpolatedProperty(clip, 'opacity', clip.opacity ?? 1.0, relativeTime);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_opacity'), opacity);\n    gl.uniform2f(gl.getUniformLocation(program, 'u_resolution'), width, height);\n\n    let exposureVal = 0.0;\n    let contrastVal = 0.0;\n    let highlightsVal = 0.0;\n    let shadowsVal = 0.0;\n    let temperatureVal = 0.0;\n    let tintVal = 0.0;\n    let vibranceVal = 0.0;\n    let saturationVal = 0.0;\n    let vignetteEnabled = false;\n    let vignetteAmount = 0.0;\n    let vignetteMidpoint = 50.0;\n    let vignetteFeather = 50.0;\n    let curvesEnabled = false;\n    let hslEnabled = false;\n    let hslAdjustments: any = null;\n\n    const grading = clip.colorGrading;\n    if (grading) {\n      exposureVal = grading.exposure;\n      contrastVal = grading.contrast;\n      highlightsVal = grading.highlights;\n      shadowsVal = grading.shadows;\n      temperatureVal = grading.temperature;\n      tintVal = grading.tint;\n      vibranceVal = grading.vibrance;\n      saturationVal = grading.saturation;\n      vignetteEnabled = grading.vignetteEnabled;\n      vignetteAmount = grading.vignetteAmount;\n      vignetteMidpoint = grading.vignetteMidpoint;\n      vignetteFeather = grading.vignetteFeather;\n      curvesEnabled = true;\n      hslEnabled = true;\n      hslAdjustments = grading.hslAdjustments;\n    }\n\n    // Process effects list and accumulate parameters\n    const effects = clip.effects || [];\n    let blurRadius = 0;\n    let scanLines = 0, trackingNoise = 0, colorBleed = 0;\n    let aberrationAmount = 0;\n    let pixelateBlockSize = 0;\n    let sepia = 0, scratch = 0, jitter = 0;\n    let mirrorEnabled = false;\n    let mirrorType = 1;\n\n    effects.forEach((fx) => {\n      if (!fx.enabled) return;\n\n      const start = fx.startTime !== undefined ? fx.startTime : 0.0;\n      const end = fx.endTime !== undefined ? fx.endTime : clip.duration;\n      if (relativeTime < start || relativeTime > end) return;\n      \n      const interpolateEffectParam = (paramName: string, defVal: number) => {\n        return getInterpolatedProperty(clip, `${fx.id}:${paramName}`, fx.params[paramName] ?? defVal, relativeTime);\n      };\n\n      if (fx.effectType === 'blur-gaussian') {\n        blurRadius = interpolateEffectParam('radius', 15);\n      } else if (fx.effectType === 'vhs') {\n        trackingNoise = interpolateEffectParam('trackingNoise', 30);\n        colorBleed = interpolateEffectParam('colorBleed', 40);\n        scanLines = interpolateEffectParam('scanLines', 50);\n      } else if (fx.effectType === 'chromatic-aberration') {\n        aberrationAmount = interpolateEffectParam('amount', 15);\n      } else if (fx.effectType === 'pixelate') {\n        pixelateBlockSize = interpolateEffectParam('blockSize', 12);\n      } else if (fx.effectType === 'old-film') {\n        sepia = interpolateEffectParam('sepiaIntensity', 60);\n        scratch = interpolateEffectParam('scratchIntensity', 40);\n        jitter = interpolateEffectParam('jitter', 20);\n      } else if (fx.effectType === 'mirror') {\n        mirrorEnabled = true;\n        const reflection = fx.params.reflection || 'horizontal';\n        mirrorType = reflection === 'horizontal' ? 1 : reflection === 'vertical' ? 2 : 3;\n      } else if (fx.effectType === 'exposure') {\n        exposureVal += interpolateEffectParam('exposure', 1.0);\n      } else if (fx.effectType === 'brightness-contrast') {\n        exposureVal += interpolateEffectParam('brightness', 20.0) * 0.02; // Map brightness % to exposure stops\n        contrastVal += interpolateEffectParam('contrast', 20.0);\n      } else if (fx.effectType === 'hue-saturation') {\n        saturationVal += interpolateEffectParam('saturation', 40.0);\n      } else if (fx.effectType === 'color-temperature') {\n        temperatureVal += interpolateEffectParam('temperature', 30.0);\n        tintVal += interpolateEffectParam('tint', 10.0);\n      }\n    });\n\n    // Upload color grading accumulated uniforms\n    gl.uniform1f(gl.getUniformLocation(program, 'u_exposure'), exposureVal);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_contrast'), contrastVal);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_highlights'), highlightsVal);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_shadows'), shadowsVal);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_temperature'), temperatureVal);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_tint'), tintVal);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_vibrance'), vibranceVal);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_saturation'), saturationVal);\n\n    // Vignette\n    gl.uniform1i(gl.getUniformLocation(program, 'u_vignetteEnabled'), vignetteEnabled ? 1 : 0);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_vignetteAmount'), vignetteAmount);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_vignetteMidpoint'), vignetteMidpoint);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_vignetteFeather'), vignetteFeather);\n\n    // Curves 1D texture bind\n    if (curvesEnabled && grading) {\n      gl.activeTexture(gl.TEXTURE1);\n      this.updateCurvesTexture(grading.curves);\n      gl.uniform1i(gl.getUniformLocation(program, 'u_curvesTexture'), 1);\n      gl.uniform1i(gl.getUniformLocation(program, 'u_curvesEnabled'), 1);\n    } else {\n      gl.uniform1i(gl.getUniformLocation(program, 'u_curvesEnabled'), 0);\n      gl.uniform1i(gl.getUniformLocation(program, 'u_curvesTexture'), 1);\n    }\n\n    // HSL Adjustments\n    if (hslEnabled && hslAdjustments) {\n      const hslArray = new Float32Array(8 * 3);\n      const colors = ['red', 'orange', 'yellow', 'green', 'aqua', 'blue', 'purple', 'magenta'];\n      colors.forEach((color, idx) => {\n        const adj = hslAdjustments[color] || { hue: 0, saturation: 0, luminance: 0 };\n        hslArray[idx * 3] = adj.hue;\n        hslArray[idx * 3 + 1] = adj.saturation;\n        hslArray[idx * 3 + 2] = adj.luminance;\n      });\n      gl.uniform3fv(gl.getUniformLocation(program, 'u_hslAdjustments'), hslArray);\n      gl.uniform1i(gl.getUniformLocation(program, 'u_hslEnabled'), 1);\n    } else {\n      gl.uniform1i(gl.getUniformLocation(program, 'u_hslEnabled'), 0);\n    }\n\n    // Upload filter uniform values\n    gl.uniform1i(gl.getUniformLocation(program, 'u_fx_blur'), blurRadius > 0 ? 1 : 0);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_fx_blur_radius'), blurRadius);\n\n    gl.uniform1i(gl.getUniformLocation(program, 'u_fx_vhs'), (scanLines + trackingNoise + colorBleed) > 0 ? 1 : 0);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_fx_vhs_noise'), trackingNoise);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_fx_vhs_bleed'), colorBleed);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_fx_vhs_lines'), scanLines);\n\n    gl.uniform1i(gl.getUniformLocation(program, 'u_fx_aberration'), aberrationAmount > 1 ? 1 : 0);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_fx_aberration_amount'), aberrationAmount);\n\n    gl.uniform1i(gl.getUniformLocation(program, 'u_fx_pixelate'), pixelateBlockSize > 1 ? 1 : 0);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_fx_pixelate_blockSize'), pixelateBlockSize);\n\n    gl.uniform1i(gl.getUniformLocation(program, 'u_fx_oldFilm'), (sepia + scratch + jitter) > 0 ? 1 : 0);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_fx_oldFilm_sepia'), sepia);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_fx_oldFilm_scratch'), scratch);\n    gl.uniform1f(gl.getUniformLocation(program, 'u_fx_oldFilm_jitter'), jitter);\n\n    // Upload mirror uniform values\n    gl.uniform1i(gl.getUniformLocation(program, 'u_fx_mirror'), mirrorEnabled ? 1 : 0);\n    gl.uniform1i(gl.getUniformLocation(program, 'u_fx_mirror_type'), mirrorType);\n\n    gl.uniform1f(gl.getUniformLocation(program, 'u_time'), relativeTime);\n\n    // Draw final quad\n    gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n    // Clean up texture bind\n    gl.deleteTexture(texture);\n  }\n\n  public drawTransition(\n    sourceFrom: HTMLVideoElement | HTMLImageElement | HTMLCanvasElement,\n    sourceTo: HTMLVideoElement | HTMLImageElement | HTMLCanvasElement,\n    transitionType: string,\n    progress: number,\n    _width: number,\n    _height: number\n  ) {\n    const gl = this.gl;\n    const transProgram = this.getTransitionProgram(transitionType);\n    if (!transProgram || !this.quadBuffer) return;\n\n    gl.useProgram(transProgram);\n\n    const positionLoc = gl.getAttribLocation(transProgram, 'position');\n    gl.enableVertexAttribArray(positionLoc);\n    gl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);\n    gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);\n\n    const texFrom = gl.createTexture();\n    gl.activeTexture(gl.TEXTURE0);\n    gl.bindTexture(gl.TEXTURE_2D, texFrom);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, sourceFrom);\n\n    const texTo = gl.createTexture();\n    gl.activeTexture(gl.TEXTURE1);\n    gl.bindTexture(gl.TEXTURE_2D, texTo);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, sourceTo);\n\n    gl.uniform1i(gl.getUniformLocation(transProgram, 'u_texture_from'), 0);\n    gl.uniform1i(gl.getUniformLocation(transProgram, 'u_texture_to'), 1);\n    gl.uniform1f(gl.getUniformLocation(transProgram, 'u_progress'), progress);\n\n    gl.uniform2f(gl.getUniformLocation(transProgram, 'u_translation'), 0.0, 0.0);\n    gl.uniform2f(gl.getUniformLocation(transProgram, 'u_scale'), 1.0, 1.0);\n    gl.uniform1f(gl.getUniformLocation(transProgram, 'u_rotation'), 0.0);\n    gl.uniform1f(\n      gl.getUniformLocation(transProgram, 'u_canvasAspect'),\n      this.gl.canvas.height > 0 ? this.gl.canvas.width / this.gl.canvas.height : 1,\n    );\n    gl.uniform1i(gl.getUniformLocation(transProgram, 'u_flipX'), 0);\n    gl.uniform1i(gl.getUniformLocation(transProgram, 'u_flipY'), 0);\n\n    gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n    gl.deleteTexture(texFrom);\n    gl.deleteTexture(texTo);\n  }\n\n  /** Compile once per transition type \u2014 recreating programs every frame caused paused flicker. */\n  private getTransitionProgram(transitionType: string): WebGLProgram | null {\n    const cached = this.transitionProgramCache.get(transitionType);\n    if (cached) return cached;\n\n    const gl = this.gl;\n    const transitionGLSL = getTransitionShader(transitionType);\n    const vs = gl.createShader(gl.VERTEX_SHADER);\n    const fs = gl.createShader(gl.FRAGMENT_SHADER);\n    if (!vs || !fs) return null;\n\n    gl.shaderSource(vs, VERTEX_SHADER_SRC);\n    gl.compileShader(vs);\n\n    const fsSource = `#version 300 es\n    precision highp float;\n    in vec2 v_texCoord;\n    out vec4 outColor;\n    \n    uniform sampler2D u_texture_from;\n    uniform sampler2D u_texture_to;\n    uniform float u_progress;\n    \n    vec4 getFromColor(vec2 uv) {\n      return texture(u_texture_from, uv);\n    }\n    vec4 getToColor(vec2 uv) {\n      return texture(u_texture_to, uv);\n    }\n    \n    ${transitionGLSL}\n    \n    void main() {\n      outColor = transition(v_texCoord, u_progress);\n    }\n    `;\n\n    gl.shaderSource(fs, fsSource);\n    gl.compileShader(fs);\n\n    const program = gl.createProgram();\n    if (!program) {\n      gl.deleteShader(vs);\n      gl.deleteShader(fs);\n      return null;\n    }\n    gl.attachShader(program, vs);\n    gl.attachShader(program, fs);\n    gl.linkProgram(program);\n    gl.deleteShader(vs);\n    gl.deleteShader(fs);\n\n    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n      gl.deleteProgram(program);\n      return null;\n    }\n\n    this.transitionProgramCache.set(transitionType, program);\n    return program;\n  }\n}\n", "import { type Clip } from '../../store/useVideoStore';\n\nexport interface MotionTransform {\n  xOffset: number; // in percent of frame (-1.0 to 1.0)\n  yOffset: number;\n  scale: number;    // multiplier\n  rotationOffset: number; // in degrees\n}\n\nexport function getMotionTransform(\n  clip: Clip,\n  relativeTime: number // relative to clip start\n): MotionTransform {\n  const transform: MotionTransform = {\n    xOffset: 0,\n    yOffset: 0,\n    scale: 1.0,\n    rotationOffset: 0\n  };\n\n  const duration = clip.duration || 1.0;\n  const progress = Math.max(0, Math.min(1, relativeTime / duration));\n\n  const effects = clip.effects || [];\n\n  effects.forEach((fx) => {\n    if (!fx.enabled) return;\n\n    if (fx.effectType === 'ken-burns') {\n      const params = fx.params || {};\n      const startScale = (params.startScale || 100) / 100;\n      const endScale = (params.endScale || 130) / 100;\n      const startX = (params.startX || 0) / 100;\n      const startY = (params.startY || 0) / 100;\n      const endX = (params.endX || 10) / 100;\n      const endY = (params.endY || 5) / 100;\n\n      // Linear interpolation of pan/zoom\n      const currentScale = startScale + (endScale - startScale) * progress;\n      const currentX = startX + (endX - startX) * progress;\n      const currentY = startY + (endY - startY) * progress;\n\n      transform.scale *= currentScale;\n      transform.xOffset += currentX;\n      transform.yOffset += currentY;\n    }\n\n    if (fx.effectType === 'camera-shake') {\n      const params = fx.params || {};\n      const freq = params.frequency || 10; // Hz\n      const intensity = params.intensity || 15; // pixels at 1920x1080 -> normalize to around 0-0.03\n      \n      // Calculate two offset paths using sine/cosine with slightly offset speeds\n      const shakeAmt = intensity * 0.0005; // normalize intensity\n      const dx = sinNoise(relativeTime * freq) * shakeAmt;\n      const dy = cosNoise(relativeTime * freq * 1.1) * shakeAmt;\n      const dr = sinNoise(relativeTime * freq * 0.9) * (shakeAmt * 50); // slight rotation shake\n\n      transform.xOffset += dx;\n      transform.yOffset += dy;\n      transform.rotationOffset += dr;\n    }\n\n    if (fx.effectType === 'zoom-dynamic') {\n      const params = fx.params || {};\n      const peakAmount = (params.amount || 125) / 100; // peak scale multiplier\n      const direction = params.direction || 'in';\n      const cX = params.centerX !== undefined ? params.centerX : 0.5;\n      const cY = params.centerY !== undefined ? params.centerY : 0.5;\n\n      // Pulse shape: peaks at mid-clip or fades in/out\n      // Zoom dynamic usually punches in and stays, or punches and returns.\n      // Let's do a smooth ease zoom that scales up smoothly during the clip\n      const startScale = direction === 'in' ? 1.0 : peakAmount;\n      const endScale = direction === 'in' ? peakAmount : 1.0;\n      \n      // Smooth step ease\n      const t = progress * progress * (3.0 - 2.0 * progress);\n      const currentScale = startScale + (endScale - startScale) * t;\n\n      transform.scale *= currentScale;\n      // Shift offsets so scaling is centered on the custom anchor point (cX, cY)\n      transform.xOffset += (0.5 - cX) * (currentScale - 1.0);\n      transform.yOffset += (0.5 - cY) * (currentScale - 1.0);\n    }\n  });\n\n  return transform;\n}\n\n// Simple deterministic sine/noise function\nfunction sinNoise(x: number): number {\n  return Math.sin(x) + Math.sin(x * 2.3) * 0.5 + Math.sin(x * 5.7) * 0.25;\n}\n\nfunction cosNoise(x: number): number {\n  return Math.cos(x) + Math.cos(x * 1.9) * 0.5 + Math.cos(x * 6.1) * 0.25;\n}\n", "import { type Clip } from '../../store/useVideoStore';\n\nfunction hexToRgba(hex: string, opacity: number): string {\n  let c = hex.substring(1);\n  if (c.length === 3) {\n    c = c[0] + c[0] + c[1] + c[1] + c[2] + c[2];\n  }\n  const r = parseInt(c.substring(0, 2), 16);\n  const g = parseInt(c.substring(2, 4), 16);\n  const b = parseInt(c.substring(4, 6), 16);\n  return `rgba(${r}, ${g}, ${b}, ${opacity})`;\n}\n\nexport function drawTextClipToCanvas(\n  ctx: CanvasRenderingContext2D,\n  clip: Clip,\n  relativeTime: number,\n  canvasWidth: number,\n  canvasHeight: number\n) {\n  let text = clip.text || '';\n  if (!text) return;\n\n  if (clip.textTransform === 'uppercase') {\n    text = text.toUpperCase();\n  } else if (clip.textTransform === 'lowercase') {\n    text = text.toLowerCase();\n  } else if (clip.textTransform === 'capitalize') {\n    text = text.replace(/\\b\\w/g, c => c.toUpperCase());\n  }\n\n  ctx.save();\n\n  // 1. Calculate animations offsets\n  let opacity = clip.opacity !== undefined ? clip.opacity : 1.0;\n  let offsetX = 0;\n  let offsetY = 0;\n  let scale = 1.0;\n\n  const duration = clip.duration || 5.0;\n  const progressIn = relativeTime; // time from start\n  const progressOut = duration - relativeTime; // time to end\n\n  const animIn = clip.animationIn;\n  const animInDur = clip.animationInDuration || 0.5;\n  const animOut = clip.animationOut;\n  const animOutDur = clip.animationOutDuration || 0.5;\n\n  // Intro animation\n  if (animIn && progressIn < animInDur) {\n    const t = progressIn / animInDur; // 0 to 1\n    if (animIn === 'fade') {\n      opacity *= t;\n    } else if (animIn === 'slide-up') {\n      offsetY += (1 - t) * 40;\n      opacity *= t;\n    } else if (animIn === 'scale-in') {\n      scale *= t;\n      opacity *= t;\n    } else if (animIn === 'typewriter') {\n      // Draw sub-string of text based on typewriter progress\n      const totalChars = text.length;\n      const visibleChars = Math.floor(totalChars * t);\n      ctx.restore();\n      ctx.save();\n      // Temporarily modify text clip value for subsequent drawing\n      const typewriterClip = { ...clip, text: text.substring(0, visibleChars), animationIn: null };\n      drawTextClipToCanvas(ctx, typewriterClip, relativeTime, canvasWidth, canvasHeight);\n      ctx.restore();\n      return;\n    } else if (animIn === 'blur-in') {\n      opacity *= t;\n      ctx.filter = `blur(${(1 - t) * 10}px)`;\n    }\n  }\n\n  // Outro animation\n  if (animOut && progressOut < animOutDur) {\n    const t = progressOut / animOutDur; // 1 to 0\n    if (animOut === 'fade') {\n      opacity *= t;\n    } else if (animOut === 'slide-down') {\n      offsetY += (1 - t) * 40;\n      opacity *= t;\n    } else if (animOut === 'scale-out') {\n      scale *= t;\n      opacity *= t;\n    } else if (animOut === 'blur-out') {\n      opacity *= t;\n      ctx.filter = `blur(${(1 - t) * 10}px)`;\n    }\n  }\n\n  ctx.globalAlpha = opacity;\n\n  // 2. Set Typography details\n  const fontWeight = clip.fontWeight || 500;\n  const fontSize = clip.fontSize || 48;\n  const fontFamily = clip.fontFamily || 'Inter';\n  const fontStyle = clip.fontStyle || 'normal';\n  \n  ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px \"${fontFamily}\"`;\n  if (ctx.letterSpacing !== undefined) {\n    ctx.letterSpacing = `${clip.letterSpacing || 0}px`;\n  }\n  ctx.textAlign = clip.textAlign || 'center';\n  ctx.textBaseline = 'middle';\n\n  // Normalize positions (0-1 coords)\n  const x = (clip.x !== undefined ? clip.x : 0.5) * canvasWidth + offsetX;\n  const y = (clip.y !== undefined ? clip.y : 0.5) * canvasHeight + offsetY;\n\n  // Wrap text into multiple lines if needed\n  const lines = text.split('\\n');\n  const lineHeight = fontSize * (clip.lineHeight || 1.2);\n  const totalTextHeight = lines.length * lineHeight;\n\n  ctx.translate(x, y);\n  ctx.rotate(((clip.rotation || 0) * Math.PI) / 180);\n  ctx.scale(\n    (clip.scaleX !== undefined ? clip.scaleX : 1.0) * scale,\n    (clip.scaleY !== undefined ? clip.scaleY : 1.0) * scale\n  );\n\n  // 3. Draw background plate if enabled\n  if (clip.backgroundEnabled) {\n    ctx.save();\n    const padding = clip.backgroundPadding || 8;\n    const borderRadius = clip.backgroundBorderRadius || 4;\n    const plateOpacity = clip.backgroundOpacity !== undefined ? clip.backgroundOpacity : 0.6;\n    \n    ctx.fillStyle = clip.backgroundColor || '#000000';\n    ctx.globalAlpha = opacity * plateOpacity;\n\n    // Find the max width line to size the background plate\n    let maxWidth = 0;\n    lines.forEach((line) => {\n      const w = ctx.measureText(line).width;\n      if (w > maxWidth) maxWidth = w;\n    });\n\n    const plateW = maxWidth + padding * 2;\n    const plateH = totalTextHeight + padding * 2;\n\n    let plateX = -plateW / 2;\n    if (clip.textAlign === 'left') plateX = -padding;\n    else if (clip.textAlign === 'right') plateX = -plateW + padding;\n\n    const plateY = -plateH / 2;\n\n    // Draw rounded rect\n    ctx.beginPath();\n    ctx.roundRect(plateX, plateY, plateW, plateH, borderRadius);\n    ctx.fill();\n\n    if (clip.backgroundBorderWidth && clip.backgroundBorderWidth > 0) {\n      ctx.strokeStyle = clip.backgroundBorderColor || '#FFFFFF';\n      ctx.lineWidth = clip.backgroundBorderWidth;\n      ctx.lineJoin = 'round';\n      ctx.stroke();\n    }\n    ctx.restore();\n  }\n\n  // 4. Fill text with solid or gradient\n  let textFill: string | CanvasGradient = clip.fillColor || '#FFFFFF';\n  if (clip.fillType === 'gradient' && clip.gradientColors && clip.gradientColors.length >= 2) {\n    const angle = ((clip.gradientAngle || 90) * Math.PI) / 180;\n    const r = fontSize / 2;\n    const dx = Math.cos(angle) * r;\n    const dy = Math.sin(angle) * r;\n    \n    const grad = ctx.createLinearGradient(-dx, -dy, dx, dy);\n    grad.addColorStop(0, clip.gradientColors[0]);\n    grad.addColorStop(1, clip.gradientColors[1]);\n    textFill = grad;\n  }\n\n  // Draw lines of text\n  lines.forEach((line, index) => {\n    // Center alignment Y offset offsets\n    const lineY = -totalTextHeight / 2 + index * lineHeight + lineHeight / 2;\n\n    // Outline / Stroke\n    if (clip.strokeEnabled) {\n      ctx.save();\n      ctx.strokeStyle = clip.strokeColor || '#000000';\n      ctx.lineWidth = clip.strokeWidth || 2;\n      ctx.lineJoin = 'round';\n      ctx.strokeText(line, 0, lineY);\n      ctx.restore();\n    }\n\n    // Shadow\n    if (clip.shadowEnabled) {\n      ctx.save();\n      let sColor = clip.shadowColor || '#000000';\n      if (clip.shadowOpacity !== undefined && clip.shadowOpacity !== 1.0) {\n        sColor = hexToRgba(sColor, clip.shadowOpacity);\n      }\n      ctx.shadowColor = sColor;\n      ctx.shadowBlur = clip.shadowBlur || 4;\n      ctx.shadowOffsetX = clip.shadowOffsetX || 2;\n      ctx.shadowOffsetY = clip.shadowOffsetY || 2;\n      ctx.fillStyle = textFill;\n      ctx.fillText(line, 0, lineY);\n      ctx.restore();\n    } else {\n      ctx.fillStyle = textFill;\n      ctx.fillText(line, 0, lineY);\n    }\n\n    // Underline\n    if (clip.underlineEnabled) {\n      ctx.save();\n      const lineWidth = ctx.measureText(line).width;\n      ctx.beginPath();\n      ctx.strokeStyle = typeof textFill === 'string' ? textFill : (clip.fillColor || '#FFFFFF');\n      ctx.lineWidth = Math.max(1, fontSize * 0.06);\n      ctx.lineCap = 'round';\n\n      let startX = -lineWidth / 2;\n      if (clip.textAlign === 'left') startX = 0;\n      else if (clip.textAlign === 'right') startX = -lineWidth;\n\n      const endX = startX + lineWidth;\n      const underlineY = lineY + fontSize * 0.45;\n\n      ctx.moveTo(startX, underlineY);\n      ctx.lineTo(endX, underlineY);\n      ctx.stroke();\n      ctx.restore();\n    }\n  });\n\n  ctx.restore();\n}\n", "import React, { useEffect } from 'react';\nimport { useTranslation } from '../../../i18n';\nimport { TextTitle } from '../../ui';\nimport { ensureGoogleFontLoaded } from '../../../utils/googleFonts';\n\nexport const POPULAR_FONTS = [\n  { name: 'Inter', family: 'Inter' },\n  { name: 'Roboto', family: 'Roboto' },\n  { name: 'Poppins', family: 'Poppins' },\n  { name: 'Montserrat', family: 'Montserrat' },\n  { name: 'Playfair Display', family: 'Playfair Display' },\n  { name: 'Oswald', family: 'Oswald' },\n  { name: 'Lora', family: 'Lora' },\n  { name: 'Merriweather', family: 'Merriweather' },\n  { name: 'Outfit', family: 'Outfit' },\n  { name: 'Raleway', family: 'Raleway' },\n  { name: 'Bebas Neue', family: 'Bebas Neue' },\n  { name: 'Pacifico', family: 'Pacifico' },\n  { name: 'Fredoka', family: 'Fredoka' },\n  { name: 'Caveat', family: 'Caveat' },\n  { name: 'Permanent Marker', family: 'Permanent Marker' },\n  { name: 'Lobster', family: 'Lobster' },\n];\n\nexport const loadGoogleFont = (fontFamily: string) => {\n  void ensureGoogleFontLoaded(fontFamily);\n};\n\ninterface FontPickerProps {\n  value: string;\n  onChange: (font: string) => void;\n}\n\nexport const FontPicker: React.FC<FontPickerProps> = ({ value, onChange }) => {\n  const t = useTranslation();\n\n  useEffect(() => {\n    loadGoogleFont(value);\n  }, [value]);\n\n  const handleFontChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n    const selectedFont = e.target.value;\n    loadGoogleFont(selectedFont);\n    onChange(selectedFont);\n  };\n\n  return (\n    <div className=\"space-y-1\">\n      <TextTitle as=\"label\" size=\"xs\" className=\"block uppercase tracking-wider text-[#8888A0]\">\n        {t.properties.text.typography}\n      </TextTitle>\n      <select\n        value={value}\n        onChange={handleFontChange}\n        className=\"w-full rounded border border-[#2A2A38] bg-[#0A0A0F] px-2.5 py-1.5 font-sans text-xs text-[#F0F0F5] focus:border-[var(--we-accent)] focus:outline-none\"\n        style={{ fontFamily: value }}\n      >\n        {POPULAR_FONTS.map((font) => (\n          <option key={font.family} value={font.family} style={{ fontFamily: font.family }}>\n            {font.name}\n          </option>\n        ))}\n      </select>\n    </div>\n  );\n};\n", "import { useLayoutEffect, useState, type RefObject } from 'react';\nimport {\n  placeMenuInViewport,\n  type MenuPrefer,\n  type PlacedMenu,\n} from './clampFixedToViewport';\n\nexport type ViewportMenuCoords = {\n  top: number;\n  left: number;\n  maxHeight: number;\n  minWidth: number;\n  placement: MenuPrefer;\n};\n\ntype Options = {\n  prefer?: MenuPrefer;\n  align?: 'left' | 'right';\n  gap?: number;\n  /** Extra deps that should remeasure (e.g. children length). */\n  deps?: unknown[];\n};\n\n/**\n * Measure trigger + menu and keep fixed coords inside the viewport.\n * Call only when the menu is mounted (portaled) so offsetWidth/Height are real.\n */\nexport function useViewportMenuCoords(\n  open: boolean,\n  triggerRef: RefObject<HTMLElement | null>,\n  menuRef: RefObject<HTMLElement | null>,\n  options: Options = {},\n): ViewportMenuCoords | null {\n  const { prefer = 'below', align = 'left', gap = 8, deps = [] } = options;\n  const [coords, setCoords] = useState<ViewportMenuCoords | null>(null);\n\n  useLayoutEffect(() => {\n    if (!open) {\n      setCoords(null);\n      return;\n    }\n    const update = () => {\n      const trigger = triggerRef.current;\n      const menu = menuRef.current;\n      if (!trigger || !menu) return;\n      const rect = trigger.getBoundingClientRect();\n      const menuWidth = Math.max(menu.offsetWidth, rect.width, 120);\n      const menuHeight = Math.max(menu.offsetHeight, 1);\n      const placed: PlacedMenu = placeMenuInViewport({\n        trigger: rect,\n        menuWidth,\n        menuHeight,\n        prefer,\n        align,\n        gap,\n      });\n      setCoords({\n        top: placed.top,\n        left: placed.left,\n        maxHeight: placed.maxHeight,\n        minWidth: menuWidth,\n        placement: placed.placement,\n      });\n    };\n    update();\n    const raf = requestAnimationFrame(() => {\n      update();\n      requestAnimationFrame(update);\n    });\n    window.addEventListener('resize', update);\n    window.addEventListener('scroll', update, true);\n    return () => {\n      cancelAnimationFrame(raf);\n      window.removeEventListener('resize', update);\n      window.removeEventListener('scroll', update, true);\n    };\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- deps[] is intentional caller list\n  }, [open, prefer, align, gap, triggerRef, menuRef, ...deps]);\n\n  return coords;\n}\n", "import React, { useEffect, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { modeAccentVars, useModeAccent } from '../theme/modeAccent';\nimport { useViewportMenuCoords } from './useViewportMenuCoords';\nimport type { MenuPrefer } from './clampFixedToViewport';\n\nexport type ViewportPortalMenuProps = {\n  open: boolean;\n  onClose: () => void;\n  /** Element the menu anchors to (usually the trigger button). */\n  anchorRef: React.RefObject<HTMLElement | null>;\n  children: React.ReactNode;\n  className?: string;\n  prefer?: MenuPrefer;\n  align?: 'left' | 'right';\n  gap?: number;\n  zIndex?: number;\n  role?: string;\n  'aria-label'?: string;\n};\n\n/**\n * Portals children as a fixed menu clamped to the viewport.\n * Outside click + Escape close via `onClose`.\n */\nexport const ViewportPortalMenu: React.FC<ViewportPortalMenuProps> = ({\n  open,\n  onClose,\n  anchorRef,\n  children,\n  className = '',\n  prefer = 'below',\n  align = 'left',\n  gap = 8,\n  zIndex = 200,\n  role = 'menu',\n  'aria-label': ariaLabel,\n}) => {\n  const mode = useModeAccent();\n  const menuRef = useRef<HTMLDivElement | null>(null);\n  const coords = useViewportMenuCoords(open, anchorRef, menuRef, {\n    prefer,\n    align,\n    gap,\n  });\n\n  useEffect(() => {\n    if (!open) return;\n    const onPointer = (e: PointerEvent) => {\n      const t = e.target as Node;\n      if (anchorRef.current?.contains(t) || menuRef.current?.contains(t)) return;\n      onClose();\n    };\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') onClose();\n    };\n    document.addEventListener('pointerdown', onPointer);\n    document.addEventListener('keydown', onKey);\n    return () => {\n      document.removeEventListener('pointerdown', onPointer);\n      document.removeEventListener('keydown', onKey);\n    };\n  }, [open, onClose, anchorRef]);\n\n  if (!open || typeof document === 'undefined') return null;\n\n  return createPortal(\n    <div\n      ref={menuRef}\n      role={role}\n      aria-label={ariaLabel}\n      data-we-mode={mode}\n      style={{\n        ...modeAccentVars(mode),\n        position: 'fixed',\n        top: coords?.top ?? -9999,\n        left: coords?.left ?? 0,\n        maxHeight: coords?.maxHeight,\n        minWidth: coords?.minWidth,\n        visibility: coords ? 'visible' : 'hidden',\n        zIndex,\n        overscrollBehavior: 'contain',\n      }}\n      className={`overflow-y-auto overscroll-contain animate-fade-in ${className}`}\n      onWheel={(e) => e.stopPropagation()}\n    >\n      {children}\n    </div>,\n    document.body,\n  );\n};\n", "/**\n * Extracts a lightweight preview (thumbnail or background) from a cloud-editable\n * binary without opening the full editor.\n */\n\nimport type { EditableMode } from '../services/editableService';\n\nexport interface EditablePreview {\n  /** data: URL or blob URL suitable for <img src>. */\n  thumbnail?: string;\n  /** Slide/page background when no raster thumbnail exists. */\n  backgroundColor?: string;\n  /** Short plain-text snippet (text mode). */\n  textSnippet?: string;\n}\n\nconst previewCache = new Map<number, EditablePreview | null>();\n\nexport function getCachedEditablePreview(id: number): EditablePreview | null | undefined {\n  return previewCache.get(id);\n}\n\nexport function setCachedEditablePreview(id: number, preview: EditablePreview | null): void {\n  previewCache.set(id, preview);\n}\n\nasync function parseWzrdProjMetadata(blob: Blob): Promise<Record<string, unknown> | null> {\n  const magicBuf = await blob.slice(0, 8).arrayBuffer();\n  const magic = new TextDecoder().decode(new Uint8Array(magicBuf));\n\n  if (magic !== 'WZRDPROJ') {\n    try {\n      return JSON.parse(await blob.text()) as Record<string, unknown>;\n    } catch {\n      return null;\n    }\n  }\n\n  const lenBuf = await blob.slice(8, 12).arrayBuffer();\n  const jsonLen = new DataView(lenBuf).getUint32(0, true);\n  if (jsonLen <= 0 || jsonLen > 4 * 1024 * 1024) return null;\n\n  const jsonBuf = await blob.slice(12, 12 + jsonLen).arrayBuffer();\n  try {\n    return JSON.parse(new TextDecoder().decode(new Uint8Array(jsonBuf))) as Record<string, unknown>;\n  } catch {\n    return null;\n  }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null;\n}\n\nfunction pickThumbnailFromImageJson(data: Record<string, unknown>): EditablePreview | null {\n  const pages = data.pages;\n  if (!Array.isArray(pages) || pages.length === 0) return null;\n\n  const activePageId = data.activePageId;\n  const active =\n    (typeof activePageId === 'string'\n      ? pages.find((p) => isRecord(p) && p.id === activePageId)\n      : undefined) ??\n    pages.find(isRecord);\n\n  if (!isRecord(active)) return null;\n\n  const thumbnail = active.thumbnail;\n  if (typeof thumbnail === 'string' && thumbnail.startsWith('data:')) {\n    return { thumbnail };\n  }\n\n  const backgroundColor = active.backgroundColor;\n  if (typeof backgroundColor === 'string' && backgroundColor.trim()) {\n    return { backgroundColor };\n  }\n\n  return null;\n}\n\nfunction pickThumbnailFromVideoJson(data: Record<string, unknown>): EditablePreview | null {\n  // Prefer project-level composite / export thumbnail when present\n  const projectThumb = data.thumbnail;\n  if (typeof projectThumb === 'string' && projectThumb.length > 0) {\n    return { thumbnail: projectThumb };\n  }\n\n  const assets = data.assets;\n  if (!Array.isArray(assets)) return null;\n\n  // Prefer video asset posters (not random uploaded stills / overlays)\n  for (const asset of assets) {\n    if (!isRecord(asset)) continue;\n    if (asset.type !== 'video') continue;\n    const thumb = asset.thumbnail;\n    if (typeof thumb === 'string' && thumb.length > 0) {\n      return { thumbnail: thumb };\n    }\n  }\n\n  for (const asset of assets) {\n    if (!isRecord(asset)) continue;\n    if (asset.type === 'image') continue;\n    const thumb = asset.thumbnail;\n    if (typeof thumb === 'string' && thumb.length > 0) {\n      return { thumbnail: thumb };\n    }\n  }\n\n  return null;\n}\n\nfunction pickPreviewFromTextMetadata(_data: Record<string, unknown>): EditablePreview | null {\n  // Recientes show a mode icon for Text (same as Audio), not a text snippet.\n  return null;\n}\n\nasync function pickPreviewFromSlidesMetadata(\n  data: Record<string, unknown>\n): Promise<EditablePreview | null> {\n  const slides = data.slides;\n  const list = Array.isArray(slides) ? slides.filter(isRecord) : [];\n  const first = list.find((s) => !s.hidden) ?? list[0];\n\n  if (isRecord(first)) {\n    const thumb = first.thumbnail;\n    if (typeof thumb === 'string' && thumb.startsWith('data:')) {\n      return { thumbnail: thumb };\n    }\n  }\n\n  // Deck-level thumbnail (optional)\n  if (typeof data.thumbnail === 'string' && data.thumbnail.startsWith('data:')) {\n    return { thumbnail: data.thumbnail };\n  }\n\n  // Legacy cloud files without baked thumbs \u2014 render first slide offscreen.\n  if (isRecord(first) && typeof document !== 'undefined') {\n    try {\n      const { renderSlideThumbnail } = await import('./slidesThumbnail');\n      const sizeRec = isRecord(data.size) ? data.size : null;\n      const width = typeof sizeRec?.width === 'number' ? sizeRec.width : 1920;\n      const height = typeof sizeRec?.height === 'number' ? sizeRec.height : 1080;\n      const theme = isRecord(data.theme) ? data.theme : null;\n      const colors = theme && isRecord(theme.colors) ? theme.colors : null;\n      const bg =\n        (typeof first.backgroundColor === 'string' && first.backgroundColor) ||\n        (typeof colors?.background === 'string' && colors.background) ||\n        '#FFFFFF';\n      const rendered = await renderSlideThumbnail(first.json, { width, height }, bg);\n      if (rendered) return { thumbnail: rendered };\n    } catch {\n      /* fall through */\n    }\n\n    const bg = first.backgroundColor;\n    if (typeof bg === 'string' && bg.trim()) {\n      return { backgroundColor: bg };\n    }\n  }\n\n  const theme = data.theme;\n  if (isRecord(theme)) {\n    const themeBg = theme.backgroundColor ?? theme.background;\n    if (typeof themeBg === 'string' && themeBg.trim()) {\n      return { backgroundColor: themeBg };\n    }\n    const colors = theme.colors;\n    if (isRecord(colors) && typeof colors.background === 'string') {\n      return { backgroundColor: colors.background };\n    }\n  }\n\n  return null;\n}\n\nexport async function extractEditablePreview(\n  blob: Blob,\n  mode: EditableMode\n): Promise<EditablePreview | null> {\n  try {\n    if (mode === 'Image' || mode === 'Video') {\n      const text = await blob.text();\n      const data = JSON.parse(text) as Record<string, unknown>;\n      return mode === 'Image'\n        ? pickThumbnailFromImageJson(data)\n        : pickThumbnailFromVideoJson(data);\n    }\n\n    if (mode === 'Text' || mode === 'Slides' || mode === 'Audio') {\n      const meta = await parseWzrdProjMetadata(blob);\n      if (!meta) return null;\n      if (mode === 'Text') return pickPreviewFromTextMetadata(meta);\n      if (mode === 'Slides') return pickPreviewFromSlidesMetadata(meta);\n      // Audio: icon fallback in the card UI\n      return null;\n    }\n  } catch {\n    return null;\n  }\n\n  return null;\n}\n", "import { useEffect, useRef, useState, type RefObject } from 'react';\nimport type { Editable } from '../services/editableService';\nimport { downloadEditableBinary } from '../services/editableService';\nimport {\n  extractEditablePreview,\n  getCachedEditablePreview,\n  setCachedEditablePreview,\n  type EditablePreview,\n} from '../utils/editablePreview';\n\nexport type EditablePreviewState =\n  | { kind: 'idle' }\n  | { kind: 'loading' }\n  | { kind: 'ready'; preview: EditablePreview | null }\n  | { kind: 'error' };\n\n/**\n * Lazily loads a cloud editable preview when the card enters the viewport.\n */\nexport function useEditablePreview(editable: Editable): {\n  ref: RefObject<HTMLDivElement | null>;\n  state: EditablePreviewState;\n} {\n  const ref = useRef<HTMLDivElement | null>(null);\n  const [state, setState] = useState<EditablePreviewState>({ kind: 'idle' });\n\n  useEffect(() => {\n    // Audio / Text Recientes always use mode icons \u2014 skip binary download.\n    if (editable.mode === 'Audio' || editable.mode === 'Text') {\n      setState({ kind: 'ready', preview: null });\n      return;\n    }\n\n    const cached = getCachedEditablePreview(editable.id);\n    if (cached !== undefined) {\n      setState({ kind: 'ready', preview: cached });\n      return;\n    }\n\n    const el = ref.current;\n    if (!el) return;\n\n    let cancelled = false;\n\n    const load = async () => {\n      setState({ kind: 'loading' });\n      try {\n        const blob = await downloadEditableBinary({ url: editable.url });\n        const preview = await extractEditablePreview(blob, editable.mode);\n        setCachedEditablePreview(editable.id, preview);\n        if (!cancelled) setState({ kind: 'ready', preview });\n      } catch {\n        setCachedEditablePreview(editable.id, null);\n        if (!cancelled) setState({ kind: 'error' });\n      }\n    };\n\n    const observer = new IntersectionObserver(\n      (entries) => {\n        if (entries.some((e) => e.isIntersecting)) {\n          observer.disconnect();\n          void load();\n        }\n      },\n      { rootMargin: '64px' }\n    );\n\n    observer.observe(el);\n    return () => {\n      cancelled = true;\n      observer.disconnect();\n    };\n  }, [editable.id, editable.mode, editable.url]);\n\n  return { ref, state };\n}\n", "import React from 'react';\nimport {\n  Film,\n  Image as ImageIcon,\n  Loader2,\n  Mic2,\n  Presentation,\n  Trash2,\n  Type,\n} from 'lucide-react';\nimport { useTranslation } from '../../i18n';\nimport type { Editable, EditableMode } from '../../services/editableService';\nimport { useEditablePreview, type EditablePreviewState } from '../../hooks/useEditablePreview';\nimport { TextBody, TextTitle } from '../ui';\n\ninterface CloudEditableCardProps {\n  editable: Editable;\n  formattedDate: string | null;\n  onOpen: () => void;\n  onDelete?: () => void;\n  disabled?: boolean;\n  /** Preview tile ratio. Setup uses square; empty-state carousel may use video. */\n  aspect?: 'video' | 'square';\n  className?: string;\n}\n\nfunction modeIcon(mode: EditableMode, size = 20) {\n  switch (mode) {\n    case 'Video':\n      return <Film size={size} className=\"text-[var(--we-accent)]\" />;\n    case 'Audio':\n      return <Mic2 size={size} className=\"text-[var(--we-accent)]\" />;\n    case 'Text':\n      return <Type size={size} className=\"text-[var(--we-accent)]\" />;\n    case 'Slides':\n      return <Presentation size={size} className=\"text-[var(--we-accent)]\" />;\n    default:\n      return <ImageIcon size={size} className=\"text-[var(--we-accent)]\" />;\n  }\n}\n\nfunction PreviewBody({\n  editable,\n  previewState,\n}: {\n  editable: Editable;\n  previewState: EditablePreviewState;\n}) {\n  const t = useTranslation();\n\n  if (previewState.kind === 'loading' || previewState.kind === 'idle') {\n    return (\n      <div className=\"flex h-full w-full items-center justify-center bg-[#0A0A0F]\">\n        <Loader2 size={18} className=\"animate-spin text-[#666680]\" />\n      </div>\n    );\n  }\n\n  // Audio / Text: always mode icon (no text snippet).\n  if (editable.mode === 'Audio' || editable.mode === 'Text') {\n    return (\n      <div className=\"flex h-full w-full flex-col items-center justify-center gap-1 bg-[#13131A] opacity-80\">\n        {modeIcon(editable.mode, 28)}\n      </div>\n    );\n  }\n\n  const preview = previewState.kind === 'ready' ? previewState.preview : null;\n\n  if (preview?.thumbnail) {\n    return (\n      <img\n        src={preview.thumbnail}\n        alt={editable.name}\n        className=\"h-full w-full object-cover\"\n      />\n    );\n  }\n\n  const bg = preview?.backgroundColor ?? '#13131A';\n\n  return (\n    <div\n      className=\"flex h-full w-full flex-col items-center justify-center gap-1 opacity-50\"\n      style={{ backgroundColor: bg }}\n    >\n      {modeIcon(editable.mode)}\n      <TextTitle as=\"span\" size=\"xl\" className=\"text-[var(--we-accent)]\">\n        {t.editor.thumbnailFallback(editable.name)}\n      </TextTitle>\n    </div>\n  );\n}\n\nexport const CloudEditableCard: React.FC<CloudEditableCardProps> = ({\n  editable,\n  formattedDate,\n  onOpen,\n  onDelete,\n  disabled = false,\n  aspect = 'square',\n  className = '',\n}) => {\n  const t = useTranslation();\n  const { ref, state: previewState } = useEditablePreview(editable);\n\n  return (\n    <div\n      role=\"button\"\n      tabIndex={disabled ? -1 : 0}\n      aria-disabled={disabled || undefined}\n      onClick={disabled ? undefined : onOpen}\n      onKeyDown={\n        disabled\n          ? undefined\n          : (e) => {\n              if (e.key === 'Enter' || e.key === ' ') {\n                e.preventDefault();\n                onOpen();\n              }\n            }\n      }\n      className={`group relative flex aspect-square h-full w-auto flex-shrink-0 flex-col overflow-hidden rounded-xl border border-panel-border bg-panel text-left transition-all\n        ${\n          disabled\n            ? 'cursor-not-allowed opacity-50'\n            : 'cursor-pointer hover:border-[var(--we-accent)]/50 hover:bg-black-capsule-hover active:scale-[0.98]'\n        } ${className}`}\n      title={editable.name}\n    >\n      {onDelete ? (\n        <button\n          type=\"button\"\n          onClick={(e) => {\n            e.stopPropagation();\n            onDelete();\n          }}\n          title={t.editor.cloudDelete}\n          className=\"absolute right-1.5 top-1.5 z-10 flex h-6 w-6 cursor-pointer items-center justify-center rounded-md bg-black/60 text-white/70 opacity-0 transition-all hover:bg-red-500/80 hover:text-white group-hover:opacity-100\"\n        >\n          <Trash2 size={11} />\n        </button>\n      ) : null}\n\n      {/* Preview fills remaining space above the footer (card itself is 1:1). */}\n      <div\n        ref={ref}\n        className={`relative min-h-0 w-full flex-1 overflow-hidden bg-black-capsule ${\n          aspect === 'video' ? 'aspect-video max-h-[70%]' : ''\n        }`}\n      >\n        <PreviewBody editable={editable} previewState={previewState} />\n        <div className=\"pointer-events-none absolute inset-0 flex items-end justify-center bg-gradient-to-t from-black/60 to-transparent pb-2 opacity-0 transition-opacity group-hover:opacity-100\">\n          <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-white\">\n            {t.editor.cloudOpen}\n          </TextBody>\n        </div>\n      </div>\n\n      <div className=\"flex shrink-0 flex-col gap-0.5 border-t border-panel-border px-2.5 py-2\">\n        <TextBody as=\"p\" size=\"sm\" className=\"truncate font-bold text-white\">\n          {editable.name}\n        </TextBody>\n        <TextBody as=\"p\" size=\"sm\" className=\"truncate text-white/80\">\n          {editable.mode}\n          {formattedDate ? ` \u00B7 ${formattedDate}` : ''}\n        </TextBody>\n      </div>\n    </div>\n  );\n};\n", "/**\n * Local Recientes \u2014 projects still in IndexedDB after the user closes tabs.\n * Cloud Recientes can be empty (auth/mode parse); local list keeps reopen working.\n */\n\nimport { openUploadsDB, useEditorStore } from '../../store/useEditorStore';\nimport { useVideoStore } from '../../store/useVideoStore';\nimport { useAudioStore } from '../../store/useAudioStore';\nimport { useTextStore } from '../../store/useTextStore';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport type { EditableMode } from '../../services/editableService';\n\nexport type LocalRecentProject = {\n  id: string;\n  name: string;\n  mode: EditableMode;\n  updatedAt: number;\n  cloudEditableId?: number;\n  /** data: URL when available (image page / video compose / first slide). */\n  thumbnail?: string;\n};\n\ntype IdbProjectMeta = {\n  id?: string;\n  name?: string;\n  updatedAt?: number;\n  createdAt?: number;\n  lastSaved?: number;\n  cloudEditableId?: number;\n  thumbnail?: string;\n  pages?: Array<{ thumbnail?: string; id?: string }>;\n  activePageId?: string;\n  assets?: Array<{ type?: string; thumbnail?: string }>;\n  slides?: Array<{ hidden?: boolean; thumbnail?: string }>;\n  theme?: { colors?: { background?: string } };\n};\n\nfunction durableThumb(value: unknown): string | undefined {\n  return typeof value === 'string' && value.startsWith('data:') ? value : undefined;\n}\n\nfunction mapMeta(\n  mode: EditableMode,\n  p: IdbProjectMeta\n): LocalRecentProject | null {\n  if (!p?.id) return null;\n\n  let thumbnail: string | undefined;\n  if (mode === 'Image') {\n    const pages = p.pages || [];\n    const active =\n      (p.activePageId\n        ? pages.find((pg) => pg.id === p.activePageId)\n        : undefined) ?? pages[0];\n    thumbnail = durableThumb(active?.thumbnail);\n  } else if (mode === 'Video') {\n    thumbnail =\n      durableThumb(p.thumbnail) ||\n      durableThumb(\n        p.assets?.find((a) => a.type === 'video' && durableThumb(a.thumbnail))\n          ?.thumbnail,\n      );\n  } else if (mode === 'Slides') {\n    const first =\n      p.slides?.find((s) => !s.hidden) ?? p.slides?.[0];\n    thumbnail = durableThumb(first?.thumbnail);\n  }\n\n  return {\n    id: p.id,\n    name: (p.name && p.name.trim()) || `Proyecto ${mode}`,\n    mode,\n    updatedAt: p.updatedAt || p.lastSaved || p.createdAt || 0,\n    cloudEditableId:\n      typeof p.cloudEditableId === 'number' ? p.cloudEditableId : undefined,\n    thumbnail,\n  };\n}\n\nasync function readProjectsKey(key: string): Promise<unknown> {\n  const db = await openUploadsDB();\n  return new Promise((resolve, reject) => {\n    const tx = db.transaction('projects', 'readonly');\n    const req = tx.objectStore('projects').get(key);\n    req.onsuccess = () => resolve(req.result ?? null);\n    req.onerror = () => reject(req.error);\n  });\n}\n\n/** Load local project metas for one editor mode from IndexedDB. */\nexport async function loadLocalRecentProjects(\n  mode: EditableMode\n): Promise<LocalRecentProject[]> {\n  try {\n    if (mode === 'Image') {\n      const row = (await readProjectsKey('default-project')) as {\n        imageProjects?: IdbProjectMeta[];\n      } | null;\n      const list = row?.imageProjects || [];\n      return list\n        .map((p) => mapMeta('Image', p))\n        .filter((x): x is LocalRecentProject => x != null)\n        .sort((a, b) => b.updatedAt - a.updatedAt);\n    }\n\n    if (mode === 'Video') {\n      const row = (await readProjectsKey('video-projects')) as {\n        videoProjects?: IdbProjectMeta[];\n      } | null;\n      const list = row?.videoProjects || [];\n      return list\n        .map((p) => mapMeta('Video', p))\n        .filter((x): x is LocalRecentProject => x != null)\n        .sort((a, b) => b.updatedAt - a.updatedAt);\n    }\n\n    if (mode === 'Audio') {\n      const row = (await readProjectsKey('audio-projects')) as {\n        projects?: IdbProjectMeta[];\n      } | null;\n      const list = row?.projects || [];\n      return list\n        .map((p) => mapMeta('Audio', p))\n        .filter((x): x is LocalRecentProject => x != null)\n        .sort((a, b) => b.updatedAt - a.updatedAt);\n    }\n\n    if (mode === 'Text') {\n      const row = (await readProjectsKey('text-projects')) as {\n        projects?: IdbProjectMeta[];\n      } | null;\n      const list = row?.projects || [];\n      return list\n        .map((p) => mapMeta('Text', p))\n        .filter((x): x is LocalRecentProject => x != null)\n        .sort((a, b) => b.updatedAt - a.updatedAt);\n    }\n\n    const row = (await readProjectsKey('slides-projects')) as {\n      projects?: IdbProjectMeta[];\n    } | null;\n    const list = row?.projects || [];\n    return list\n      .map((p) => mapMeta('Slides', p))\n      .filter((x): x is LocalRecentProject => x != null)\n      .sort((a, b) => b.updatedAt - a.updatedAt);\n  } catch (err) {\n    console.warn('[localRecentProjects] failed', mode, err);\n    return [];\n  }\n}\n\n/**\n * Re-open a local project after the tab was closed (reload from IDB if needed).\n */\nexport async function reopenLocalRecentProject(\n  item: LocalRecentProject\n): Promise<void> {\n  if (item.mode === 'Image') {\n    const s = useEditorStore.getState();\n    if (!s.imageProjects.some((p) => p.id === item.id)) {\n      await s.saveCurrentProject().catch(() => {});\n      await s.loadProject();\n    }\n    useEditorStore.getState().switchImageProject(item.id);\n    useEditorStore.getState().setIsImageSetupOpen(false);\n    return;\n  }\n\n  if (item.mode === 'Video') {\n    const s = useVideoStore.getState();\n    if (!s.videoProjects.some((p) => p.id === item.id)) {\n      await s.saveVideoProject().catch(() => {});\n      await s.loadVideoProject();\n    }\n    useVideoStore.getState().switchVideoProject(item.id);\n    useVideoStore.getState().setIsVideoSetupOpen(false);\n    return;\n  }\n\n  if (item.mode === 'Audio') {\n    const s = useAudioStore.getState();\n    if (!s.audioProjects.some((p) => p.id === item.id)) {\n      await s.saveAudioProject().catch(() => {});\n      await s.loadAudioProject();\n    }\n    useAudioStore.getState().switchAudioProject(item.id);\n    useAudioStore.getState().setIsAudioSetupOpen(false);\n    return;\n  }\n\n  if (item.mode === 'Text') {\n    const s = useTextStore.getState();\n    if (!s.textProjects.some((p) => p.id === item.id)) {\n      await s.saveTextProject().catch(() => {});\n      await s.loadTextProject();\n    }\n    useTextStore.getState().switchTextProject(item.id);\n    useTextStore.getState().setIsTextSetupOpen(false);\n    return;\n  }\n\n  const s = useSlidesStore.getState();\n  if (!s.slidesProjects.some((p) => p.id === item.id)) {\n    await s.saveSlidesProject().catch(() => {});\n    await s.loadSlidesProject();\n  }\n  useSlidesStore.getState().switchSlidesProject(item.id);\n  useSlidesStore.getState().setIsSlidesSetupOpen(false);\n}\n", "import React, { useEffect, useState } from 'react';\nimport {\n  Cloud,\n  AlertTriangle,\n  Film,\n  Image as ImageIcon,\n  Loader2,\n  Mic2,\n  Presentation,\n  Type,\n} from 'lucide-react';\nimport { CloudEditableCard } from './CloudEditableCard';\nimport { useTranslation } from '../../i18n';\nimport { listEditables, type Editable, type EditableMode } from '../../services/editableService';\nimport { AuthError } from '../../services/wizardApiClient';\nimport {\n  loadLocalRecentProjects,\n  reopenLocalRecentProject,\n  type LocalRecentProject,\n} from '../../lib/persistence/localRecentProjects';\nimport { TextBody } from '../ui';\n\nexport type RecentCanvasMode = 'Image' | 'Video' | 'Audio' | 'Text' | 'Slides';\n\ninterface RecentCanvasesCarouselProps {\n  mode: RecentCanvasMode;\n  limit?: number;\n  onOpen: (editable: Editable) => void;\n  /** Optional first cell (e.g. create-new tile). */\n  leading?: React.ReactNode;\n  /** Setup-style square grid (default) or legacy horizontal row. */\n  layout?: 'grid' | 'row';\n}\n\ntype FetchState =\n  | { kind: 'loading' }\n  | {\n      kind: 'ok';\n      cloud: Editable[];\n      local: LocalRecentProject[];\n    }\n  | { kind: 'error'; auth?: boolean; local: LocalRecentProject[] }\n  | { kind: 'empty' };\n\nfunction formatRelativeDate(\n  iso: string,\n  labels: {\n    today: string;\n    yesterday: string;\n    daysAgo: (n: number) => string;\n  },\n): string | null {\n  if (!iso || iso.startsWith('0001')) return null;\n  const date = new Date(iso);\n  if (Number.isNaN(date.getTime())) return null;\n  const diffMs = Date.now() - date.getTime();\n  const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));\n  if (diffDays <= 0) return labels.today;\n  if (diffDays === 1) return labels.yesterday;\n  if (diffDays < 7) return labels.daysAgo(diffDays);\n  return date.toLocaleDateString(undefined, { day: 'numeric', month: 'short' });\n}\n\nconst gridClass =\n  'grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 xl:grid-cols-5 gap-3';\n\nfunction modeIcon(mode: EditableMode, size = 22) {\n  switch (mode) {\n    case 'Video':\n      return <Film size={size} className=\"text-[var(--we-accent)]\" />;\n    case 'Audio':\n      return <Mic2 size={size} className=\"text-[var(--we-accent)]\" />;\n    case 'Text':\n      return <Type size={size} className=\"text-[var(--we-accent)]\" />;\n    case 'Slides':\n      return <Presentation size={size} className=\"text-[var(--we-accent)]\" />;\n    default:\n      return <ImageIcon size={size} className=\"text-[var(--we-accent)]\" />;\n  }\n}\n\nfunction LoadingSkeleton({\n  layout,\n  leading,\n}: {\n  layout: 'grid' | 'row';\n  leading?: React.ReactNode;\n}) {\n  if (layout === 'grid') {\n    return (\n      <div className={gridClass}>\n        {leading}\n        {[0, 1, 2, 3].map((i) => (\n          <div\n            key={i}\n            className=\"aspect-square w-full animate-pulse rounded-xl border border-panel-border bg-black-capsule\"\n          />\n        ))}\n      </div>\n    );\n  }\n  return (\n    <div className=\"flex gap-3 overflow-x-auto pb-1 scrollbar-none\">\n      {leading}\n      {[0, 1, 2].map((i) => (\n        <div\n          key={i}\n          className=\"h-36 w-36 flex-shrink-0 animate-pulse rounded-xl border border-panel-border bg-black-capsule\"\n        />\n      ))}\n    </div>\n  );\n}\n\nfunction LocalProjectCard({\n  item,\n  layout,\n  opening,\n  onOpen,\n}: {\n  item: LocalRecentProject;\n  layout: 'grid' | 'row';\n  opening: boolean;\n  onOpen: () => void;\n}) {\n  const t = useTranslation();\n  const showRaster =\n    Boolean(item.thumbnail) &&\n    (item.mode === 'Image' || item.mode === 'Video' || item.mode === 'Slides');\n\n  return (\n    <button\n      type=\"button\"\n      disabled={opening}\n      onClick={onOpen}\n      title={\n        item.cloudEditableId\n          ? `${item.name} (${t.editor.localAndCloud})`\n          : `${item.name} (${t.editor.localOnly})`\n      }\n      className={`group relative flex cursor-pointer flex-col overflow-hidden rounded-xl border border-panel-border bg-[#0A0A0F] text-left transition-all hover:border-[var(--we-accent)] disabled:cursor-wait disabled:opacity-60 ${\n        layout === 'grid' ? 'aspect-square h-auto w-full' : 'h-36 w-36 flex-shrink-0'\n      }`}\n    >\n      <div className=\"relative flex flex-1 items-center justify-center overflow-hidden bg-[#13131A]\">\n        {opening ? (\n          <Loader2 size={18} className=\"animate-spin text-[var(--we-accent)]\" />\n        ) : showRaster ? (\n          <img src={item.thumbnail} alt=\"\" className=\"h-full w-full object-cover\" />\n        ) : (\n          modeIcon(item.mode, 28)\n        )}\n      </div>\n      <div className=\"border-t border-panel-border px-2 py-1.5\">\n        <TextBody as=\"div\" size=\"sm\" className=\"truncate font-bold text-[#F0F0F5]\">\n          {item.name}\n        </TextBody>\n        <TextBody as=\"div\" size=\"sm\" className=\"text-[#8888A0]\">\n          {item.cloudEditableId != null ? t.editor.localAndCloud : t.editor.localOnly}\n        </TextBody>\n      </div>\n    </button>\n  );\n}\n\nexport const RecentCanvasesCarousel: React.FC<RecentCanvasesCarouselProps> = ({\n  mode,\n  limit = 12,\n  onOpen,\n  leading,\n  layout = 'grid',\n}) => {\n  const t = useTranslation();\n  const [state, setState] = useState<FetchState>({ kind: 'loading' });\n  const [openingLocalId, setOpeningLocalId] = useState<string | null>(null);\n\n  useEffect(() => {\n    let cancelled = false;\n    setState({ kind: 'loading' });\n    (async () => {\n      const locals = await loadLocalRecentProjects(mode);\n      if (cancelled) return;\n\n      try {\n        let all = await listEditables({ scope: 'account' });\n        if (all.length === 0) {\n          all = await listEditables({ scope: 'brand' });\n        }\n        if (cancelled) return;\n\n        const cloud = all\n          .filter((e) => e.mode === mode)\n          .sort((a, b) => {\n            if (a.createdAt && b.createdAt) {\n              return b.createdAt.localeCompare(a.createdAt);\n            }\n            return b.id - a.id;\n          })\n          .slice(0, limit);\n\n        const cloudIds = new Set(cloud.map((e) => e.id));\n        const local = locals\n          .filter(\n            (p) =>\n              p.cloudEditableId == null || !cloudIds.has(p.cloudEditableId),\n          )\n          .slice(0, limit);\n\n        if (cloud.length === 0 && local.length === 0) {\n          setState({ kind: 'empty' });\n        } else {\n          setState({ kind: 'ok', cloud, local });\n        }\n      } catch (err) {\n        if (cancelled) return;\n        console.error('Failed to load recent editables', err);\n        if (locals.length > 0) {\n          setState({\n            kind: 'ok',\n            cloud: [],\n            local: locals.slice(0, limit),\n          });\n        } else {\n          setState({\n            kind: 'error',\n            auth: err instanceof AuthError,\n            local: [],\n          });\n        }\n      }\n    })();\n    return () => {\n      cancelled = true;\n    };\n  }, [mode, limit]);\n\n  const openLocal = async (item: LocalRecentProject) => {\n    setOpeningLocalId(item.id);\n    try {\n      await reopenLocalRecentProject(item);\n    } catch (err) {\n      console.error('Failed to open local project', err);\n    } finally {\n      setOpeningLocalId(null);\n    }\n  };\n\n  if (state.kind === 'loading') {\n    return <LoadingSkeleton layout={layout} leading={leading} />;\n  }\n\n  if (state.kind === 'error') {\n    return (\n      <div className=\"flex flex-col gap-3\">\n        {layout === 'grid' && leading ? (\n          <div className={gridClass}>\n            {leading}\n            <div className=\"col-span-full flex items-center gap-2 rounded-xl border border-amber-500/20 bg-amber-500/5 px-4 py-3 text-amber-300/90\">\n              <AlertTriangle size={14} className=\"flex-shrink-0\" />\n              <TextBody as=\"span\" size=\"sm\" className=\"text-pretty text-amber-300/90\">\n                {state.auth ? t.editor.recentAuthError : t.editor.recentLoadError}\n              </TextBody>\n            </div>\n          </div>\n        ) : (\n          <>\n            {leading}\n            <div className=\"flex items-center gap-2 rounded-xl border border-amber-500/20 bg-amber-500/5 px-4 py-3 text-amber-300/90\">\n              <AlertTriangle size={14} className=\"flex-shrink-0\" />\n              <TextBody as=\"span\" size=\"sm\" className=\"text-pretty text-amber-300/90\">\n                {state.auth ? t.editor.recentAuthError : t.editor.recentLoadError}\n              </TextBody>\n            </div>\n          </>\n        )}\n      </div>\n    );\n  }\n\n  if (state.kind === 'empty') {\n    if (layout === 'grid') {\n      return (\n        <div className={gridClass}>\n          {leading}\n          <div className=\"flex aspect-square w-full flex-col items-center justify-center gap-2 rounded-xl border border-dashed border-panel-border bg-black-capsule px-3 text-center\">\n            <Cloud size={20} className=\"text-white/50\" />\n            <TextBody as=\"p\" size=\"sm\" className=\"text-pretty text-white/80\">\n              {t.editor.recentEmpty}\n            </TextBody>\n          </div>\n        </div>\n      );\n    }\n    return (\n      <div className=\"flex flex-col gap-3\">\n        {leading}\n        <div className=\"flex flex-col items-center justify-center gap-2 rounded-xl border border-dashed border-panel-border bg-black-capsule px-6 py-10 text-center\">\n          <Cloud size={20} className=\"text-white/50\" />\n          <TextBody as=\"p\" size=\"sm\" className=\"max-w-xs text-pretty text-white/80\">\n            {t.editor.recentEmpty}\n          </TextBody>\n        </div>\n      </div>\n    );\n  }\n\n  const dateLabels = {\n    today: t.editor.relativeDateToday,\n    yesterday: t.editor.relativeDateYesterday,\n    daysAgo: t.editor.relativeDateDaysAgo,\n  };\n\n  const localCards = state.local.map((item) => (\n    <LocalProjectCard\n      key={`local-${item.id}`}\n      item={item}\n      layout={layout}\n      opening={openingLocalId === item.id}\n      onOpen={() => void openLocal(item)}\n    />\n  ));\n\n  const cloudCards = state.cloud.map((editable) => (\n    <CloudEditableCard\n      key={editable.id}\n      editable={editable}\n      aspect=\"square\"\n      className={layout === 'grid' ? 'h-auto w-full' : 'h-36 w-36'}\n      formattedDate={formatRelativeDate(editable.createdAt, dateLabels)}\n      onOpen={() => onOpen(editable)}\n    />\n  ));\n\n  if (layout === 'grid') {\n    return (\n      <div className={gridClass}>\n        {leading}\n        {localCards}\n        {cloudCards}\n      </div>\n    );\n  }\n\n  return (\n    <div className=\"scrollbar-none -mx-1 flex gap-3 overflow-x-auto px-1 pb-1\">\n      {leading}\n      {localCards}\n      {cloudCards}\n    </div>\n  );\n};\n", "import React from 'react';\nimport {\n  Plus,\n  Film,\n  Image as ImageIcon,\n  Music2,\n  FileText,\n  Presentation,\n  type LucideIcon,\n} from 'lucide-react';\nimport { useTranslation } from '../../i18n';\nimport { RecentCanvasesCarousel, type RecentCanvasMode } from './RecentCanvasesCarousel';\nimport type { Editable } from '../../services/editableService';\nimport { TextBody, TextTitle } from '../ui';\n\ninterface EditorEmptyStateProps {\n  mode: RecentCanvasMode;\n  onCreate: () => void;\n  onOpenCloud: (editable: Editable) => void;\n  recentLimit?: number;\n}\n\ntype ModeMeta = {\n  accent: string;\n  accentSoft: string;\n  Icon: LucideIcon;\n  modeKey: 'image' | 'video' | 'audio' | 'text' | 'slides';\n};\n\nconst MODE_META: Record<RecentCanvasMode, ModeMeta> = {\n  Image: { modeKey: 'image', accent: '#DB2777', accentSoft: 'rgba(219, 39, 119, 0.14)', Icon: ImageIcon },\n  Video: { modeKey: 'video', accent: '#EA580C', accentSoft: 'rgba(234, 88, 12, 0.14)', Icon: Film },\n  Audio: { modeKey: 'audio', accent: '#9F1239', accentSoft: 'rgba(159, 18, 57, 0.14)', Icon: Music2 },\n  Text: { modeKey: 'text', accent: '#0891B2', accentSoft: 'rgba(8, 145, 178, 0.14)', Icon: FileText },\n  Slides: { modeKey: 'slides', accent: '#A204CA', accentSoft: 'rgba(162, 4, 202, 0.14)', Icon: Presentation },\n};\n\n/**\n * Landing surface when a studio mode has no open local project.\n * Setup-aligned: square grid with create tile + cloud editables.\n */\nexport const EditorEmptyState: React.FC<EditorEmptyStateProps> = ({\n  mode,\n  onCreate,\n  onOpenCloud,\n  recentLimit,\n}) => {\n  const t = useTranslation();\n  const meta = MODE_META[mode];\n  const copy = t.editor.emptyByMode[mode];\n  const ModeIcon = meta.Icon;\n  const modeLabel = t.modes[meta.modeKey];\n\n  const createTile = (\n    <button\n      type=\"button\"\n      onClick={onCreate}\n      title={t.editor.createNew}\n      className=\"group flex aspect-square w-full cursor-pointer flex-col items-center justify-center gap-2 rounded-xl border border-[var(--we-accent)] bg-[var(--we-accent)] transition-all hover:opacity-80 active:scale-95\"\n    >\n      <Plus size={28} className=\"text-[var(--we-accent-dark)]\" strokeWidth={2.5} />\n      <TextBody as=\"span\" size=\"sm\" className=\"px-3 text-center font-bold text-[var(--we-accent-dark)]\">\n        {t.editor.createNew}\n      </TextBody>\n      <TextBody as=\"span\" size=\"sm\" className=\"px-3 text-center text-[var(--we-accent-dark)]/80\">\n        {copy.createHint}\n      </TextBody>\n    </button>\n  );\n\n  return (\n    <div className=\"min-h-0 flex-1 overflow-y-auto bg-dark-950\">\n      <div className=\"mx-auto flex max-w-5xl flex-col gap-6 px-6 py-8\">\n        <header className=\"flex flex-col gap-3 pt-12\">\n          <div className=\"flex items-center gap-2\">\n            <span\n              className=\"inline-flex h-8 w-8 items-center justify-center rounded-lg border border-panel-border\"\n              style={{ backgroundColor: meta.accentSoft, color: meta.accent }}\n            >\n              <ModeIcon size={16} strokeWidth={2} />\n            </span>\n            <TextBody as=\"span\" size=\"sm\" className=\"tracking-wider text-white/80 uppercase font-bold\">\n              {modeLabel}\n            </TextBody>\n          </div>\n          <TextTitle as=\"h1\" size=\"xl\" className=\"text-balance text-2xl\">\n            {copy.title}\n          </TextTitle>\n          <TextBody as=\"p\" size=\"md\" className=\"max-w-xl text-pretty text-white/80\">\n            {copy.subtitle}\n          </TextBody>\n        </header>\n\n        <section className=\"flex flex-col gap-3\">\n          <TextTitle as=\"h2\" size=\"xs\" className=\"tracking-wider text-white/80 uppercase\">\n            {t.editor.recentTitle}\n          </TextTitle>\n          <RecentCanvasesCarousel\n            mode={mode}\n            limit={recentLimit}\n            layout=\"grid\"\n            leading={createTile}\n            onOpen={onOpenCloud}\n          />\n        </section>\n      </div>\n    </div>\n  );\n};\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { ChevronDown, Check } from 'lucide-react';\nimport { useBrandSelection } from '../../context/BrandSelectionContext';\nimport { useTranslation } from '../../i18n';\nimport { modeAccentVars, useModeAccent } from '../../theme/modeAccent';\nimport { useViewportMenuCoords } from '../../utils/useViewportMenuCoords';\nimport { TextBody, TextTitle } from '../ui';\n\n/**\n * Compact brand switcher for floating toolbars.\n * Host supplies `brands` + `brand` via <Editor />; selecting updates\n * editor identity (AI brand_id) and notifies the host via onBrandChange.\n */\nexport const BrandToolbarDropdown: React.FC = () => {\n  const t = useTranslation();\n  const mode = useModeAccent();\n  const { brand, brands, selectBrand } = useBrandSelection();\n  const [open, setOpen] = useState(false);\n  const rootRef = useRef<HTMLDivElement | null>(null);\n  const triggerRef = useRef<HTMLButtonElement | null>(null);\n  const menuRef = useRef<HTMLDivElement | null>(null);\n  const coords = useViewportMenuCoords(open, triggerRef, menuRef, {\n    prefer: 'below',\n    align: 'left',\n    gap: 6,\n    deps: [brands.length],\n  });\n\n  useEffect(() => {\n    if (!open) return;\n    const onPointer = (e: PointerEvent) => {\n      const node = e.target as Node;\n      if (rootRef.current?.contains(node) || menuRef.current?.contains(node)) return;\n      setOpen(false);\n    };\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') setOpen(false);\n    };\n    document.addEventListener('pointerdown', onPointer);\n    document.addEventListener('keydown', onKey);\n    return () => {\n      document.removeEventListener('pointerdown', onPointer);\n      document.removeEventListener('keydown', onKey);\n    };\n  }, [open]);\n\n  if (!brand && brands.length === 0) return null;\n\n  const label = brand?.name ?? t.toolbar.brand.placeholder;\n  const canSwitch = brands.length > 0;\n\n  const menu =\n    open && canSwitch && typeof document !== 'undefined'\n      ? createPortal(\n          <div\n            ref={menuRef}\n            role=\"listbox\"\n            aria-label={t.toolbar.brand.listLabel}\n            data-we-mode={mode}\n            style={{\n              ...modeAccentVars(mode),\n              position: 'fixed',\n              top: coords?.top ?? -9999,\n              left: coords?.left ?? 0,\n              maxHeight: coords?.maxHeight,\n              visibility: coords ? 'visible' : 'hidden',\n              zIndex: 200,\n            }}\n            className=\"flex w-[min(18.5rem,calc(100vw-1.5rem))] flex-col overflow-hidden rounded-2xl border border-panel-border bg-panel p-2 shadow-2xl shadow-black/60 backdrop-blur-md animate-fade-in\"\n          >\n            <div className=\"mb-1.5 shrink-0 px-2.5 pb-1 pt-1.5\">\n              <TextTitle as=\"p\" size=\"xs\" className=\"uppercase tracking-wider\">\n                {t.toolbar.brand.listLabel}\n              </TextTitle>\n            </div>\n            <div\n              className=\"flex min-h-0 flex-col gap-1 overflow-y-auto overscroll-contain\"\n              style={{ maxHeight: coords ? Math.max(80, coords.maxHeight - 48) : 240 }}\n            >\n              {brands.map((item) => {\n                const selected = brand?.id === item.id;\n                return (\n                  <button\n                    key={item.id}\n                    type=\"button\"\n                    role=\"option\"\n                    aria-selected={selected}\n                    onClick={() => {\n                      selectBrand(item);\n                      setOpen(false);\n                    }}\n                    className={`flex w-full cursor-pointer items-center gap-3 rounded-xl px-2.5 py-2.5 text-left transition-colors ${\n                      selected\n                        ? 'bg-white text-black'\n                        : 'text-ink-primary hover:bg-white/8'\n                    }`}\n                  >\n                    {item.logoUrl ? (\n                      <img\n                        src={item.logoUrl}\n                        alt=\"\"\n                        className=\"size-9 shrink-0 rounded-xl object-contain bg-white border border-black\"\n                      />\n                    ) : (\n                      <TextBody\n                        as=\"span\"\n                        size=\"md\"\n                        className={`flex size-9 shrink-0 items-center justify-center rounded-xl font-bold ${\n                          selected\n                            ? 'bg-black-capsule text-white'\n                            : 'bg-black-capsule text-white/80'\n                        }`}\n                      >\n                        {item.name.charAt(0).toUpperCase()}\n                      </TextBody>\n                    )}\n                    <TextBody\n                      as=\"span\"\n                      size=\"md\"\n                      className={`min-w-0 flex-1 truncate font-semibold ${\n                        selected ? 'text-black' : ''\n                      }`}\n                    >\n                      {item.name}\n                    </TextBody>\n                    {selected ? (\n                      <Check size={14} strokeWidth={2.5} className=\"shrink-0 text-black\" aria-hidden />\n                    ) : (\n                      <span className=\"size-3.5 shrink-0\" aria-hidden />\n                    )}\n                  </button>\n                );\n              })}\n            </div>\n          </div>,\n          document.body,\n        )\n      : null;\n\n  return (\n    <div ref={rootRef} className=\"relative shrink-0\">\n      <button\n        ref={triggerRef}\n        type=\"button\"\n        onClick={() => canSwitch && setOpen((v) => !v)}\n        disabled={!canSwitch}\n        aria-label={t.toolbar.brand.menuLabel}\n        aria-expanded={open}\n        aria-haspopup=\"listbox\"\n        title={t.toolbar.brand.menuLabel}\n        className={`flex items-center gap-1.5 h-8 max-w-[160px] px-2.5 rounded-lg transition-all active:scale-95 ${\n          open\n            ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)]'\n            : 'text-[#F0F0F5] hover:bg-[#1C1C26] hover:text-[#F0F0F5]'\n        } ${!canSwitch ? 'opacity-70 cursor-default' : 'cursor-pointer'}`}\n      >\n        {brand?.logoUrl ? (\n          <img\n            src={brand.logoUrl}\n            alt=\"\"\n            className=\"h-4 w-4 shrink-0 rounded object-contain bg-black-capsule\"\n          />\n        ) : (\n          <TextBody\n            as=\"span\"\n            size=\"sm\"\n            className=\"h-4 w-4 rounded bg-[#1C1C26] font-bold text-[#8888A0] flex items-center justify-center flex-shrink-0\"\n          >\n            {label.charAt(0).toUpperCase()}\n          </TextBody>\n        )}\n        <TextBody as=\"span\" size=\"sm\" className=\"truncate font-semibold\">\n          {label}\n        </TextBody>\n        {canSwitch && (\n          <ChevronDown\n            size={12}\n            className={`flex-shrink-0 text-[#8888A0] transition-transform duration-200 ${open ? 'rotate-180' : ''}`}\n          />\n        )}\n      </button>\n      {menu}\n    </div>\n  );\n};\n", "import React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n  Film,\n  Image as ImageIcon,\n  Music2,\n  FileText,\n  Presentation,\n  ChevronDown,\n  Check,\n} from 'lucide-react';\nimport { useTranslation } from '../../i18n';\nimport {\n  MODE_ACCENT_BG,\n  MODE_ACCENT_BG_HOVER,\n  modeAccentVars,\n  useModeAccent,\n} from '../../theme/modeAccent';\nimport { useViewportMenuCoords } from '../../utils/useViewportMenuCoords';\nimport { TextBody, TextTitle } from '../ui';\n\nexport type EditorMode = 'video' | 'image' | 'audio' | 'text' | 'slides';\n\ninterface EditorModeToggleProps {\n  activeMode?: EditorMode;\n  onSwitchToImage?: () => void;\n  onSwitchToVideo?: () => void;\n  onSwitchToAudio?: () => void;\n  onSwitchToText?: () => void;\n  onSwitchToSlides?: () => void;\n  /** Compact inline control for EditorShellHeader (no floating panel chrome). */\n  variant?: 'floating' | 'header';\n  /** @deprecated use onSwitchToImage \u2014 kept for VideoEditor callers */\n  onSwitchToImageLegacy?: () => void;\n}\n\ntype ModeDef = { mode: EditorMode; Icon: React.ComponentType<{ size?: number; strokeWidth?: number; className?: string }> };\n\nconst MODE_DEFS: ReadonlyArray<ModeDef> = [\n  { mode: 'image', Icon: ImageIcon },\n  { mode: 'video', Icon: Film },\n  { mode: 'audio', Icon: Music2 },\n  { mode: 'text', Icon: FileText },\n  { mode: 'slides', Icon: Presentation },\n];\n\n/** Solid feature DEFAULT behind each mode icon. */\nconst MODE_ICON_BG: Record<EditorMode, string> = {\n  image: 'bg-feature-image',\n  video: 'bg-feature-video',\n  audio: 'bg-feature-audio',\n  text: 'bg-feature-script',\n  slides: 'bg-feature-presentation',\n};\n\nexport const EditorModeToggle: React.FC<EditorModeToggleProps> = ({\n  activeMode = 'video',\n  onSwitchToImage,\n  onSwitchToVideo,\n  onSwitchToAudio,\n  onSwitchToText,\n  onSwitchToSlides,\n  variant = 'floating',\n}) => {\n  const t = useTranslation();\n  const modeAccent = useModeAccent();\n\n  const modes = useMemo(\n    () =>\n      MODE_DEFS.map(({ mode, Icon }) => ({\n        mode,\n        Icon,\n        label: t.modes[mode],\n        description: t.modes.description[mode],\n      })),\n    [t],\n  );\n\n  // Hover + click open paths so the menu works on desktop and touch.\n  // Keep them separate: latching click-open while hover already opened the\n  // menu sticks it after mouseleave (scheduleHoverClose bails on isClickOpen).\n  const [isHoverOpen, setIsHoverOpen] = useState(false);\n  const [isClickOpen, setIsClickOpen] = useState(false);\n  const isOpen = isHoverOpen || isClickOpen;\n  /** True while the pointer is over the chip (not the portaled menu). */\n  const pointerOnChipRef = useRef(false);\n\n  const rootRef = useRef<HTMLDivElement | null>(null);\n  const hoverCloseTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const triggerRef = useRef<HTMLButtonElement | null>(null);\n  const menuRef = useRef<HTMLDivElement | null>(null);\n  const coords = useViewportMenuCoords(isOpen, triggerRef, menuRef, {\n    prefer: 'below',\n    align: 'left',\n    gap: 6,\n  });\n\n  const clearHoverClose = () => {\n    if (hoverCloseTimer.current != null) {\n      clearTimeout(hoverCloseTimer.current);\n      hoverCloseTimer.current = null;\n    }\n  };\n\n  const openByHover = () => {\n    clearHoverClose();\n    setIsHoverOpen(true);\n  };\n\n  const scheduleHoverClose = () => {\n    if (isClickOpen) return;\n    clearHoverClose();\n    // Short grace so the cursor can cross the gap between chip and menu.\n    hoverCloseTimer.current = setTimeout(() => {\n      setIsHoverOpen(false);\n      hoverCloseTimer.current = null;\n    }, 150);\n  };\n\n  useEffect(() => () => clearHoverClose(), []);\n\n  useEffect(() => {\n    if (!isClickOpen) return;\n    const handlePointerDown = (e: PointerEvent) => {\n      const node = e.target as Node;\n      if (rootRef.current?.contains(node) || menuRef.current?.contains(node)) return;\n      setIsClickOpen(false);\n    };\n    document.addEventListener('pointerdown', handlePointerDown);\n    return () => document.removeEventListener('pointerdown', handlePointerDown);\n  }, [isClickOpen]);\n\n  const closeAll = () => {\n    clearHoverClose();\n    setIsHoverOpen(false);\n    setIsClickOpen(false);\n  };\n\n  const onTriggerClick = () => {\n    // Hover already opened the menu \u2014 ignore the click so we don't latch\n    // isClickOpen (that would keep the menu stuck after mouseleave).\n    if (isHoverOpen || pointerOnChipRef.current) {\n      return;\n    }\n    setIsClickOpen((v) => !v);\n  };\n\n  const callbacks: Record<EditorMode, (() => void) | undefined> = {\n    video: onSwitchToVideo,\n    image: onSwitchToImage,\n    audio: onSwitchToAudio,\n    text: onSwitchToText,\n    slides: onSwitchToSlides,\n  };\n\n  const active = modes.find((m) => m.mode === activeMode) ?? modes[0]!;\n  const ActiveIcon = active.Icon;\n\n  const isHeader = variant === 'header';\n  const activeBg = MODE_ACCENT_BG[activeMode];\n  const activeHover = MODE_ACCENT_BG_HOVER[activeMode];\n\n  const menu =\n    isOpen && typeof document !== 'undefined'\n      ? createPortal(\n          <div\n            ref={menuRef}\n            role=\"menu\"\n            aria-label={t.modes.menuTitle}\n            data-we-mode={modeAccent}\n            onMouseEnter={() => {\n              if (!isHeader) openByHover();\n            }}\n            onMouseLeave={() => {\n              if (!isHeader) scheduleHoverClose();\n            }}\n            style={{\n              ...modeAccentVars(modeAccent),\n              position: 'fixed',\n              top: coords?.top ?? -9999,\n              left: coords?.left ?? 0,\n              minWidth: coords?.minWidth ?? (isHeader ? 280 : 288),\n              maxHeight: coords?.maxHeight,\n              visibility: coords ? 'visible' : 'hidden',\n              zIndex: 400,\n            }}\n            className={`flex flex-col overflow-y-auto overscroll-contain rounded-2xl border border-panel-border bg-panel p-2 shadow-2xl shadow-black/60 backdrop-blur-md ${\n              isHeader ? 'w-[min(20rem,calc(100vw-1.5rem))]' : 'min-w-[18rem]'\n            }`}\n          >\n            <div className=\"mb-1.5 px-2.5 pt-1.5 pb-1\">\n              <TextTitle as=\"p\" size=\"xs\" className=\"uppercase tracking-wider\">\n                {t.modes.menuTitle}\n              </TextTitle>\n            </div>\n\n            <div className=\"flex flex-col gap-1\">\n              {modes.map(({ mode, label, description, Icon }) => {\n                const cb = callbacks[mode];\n                const isActive = mode === activeMode;\n                return (\n                  <button\n                    key={mode}\n                    type=\"button\"\n                    role=\"menuitem\"\n                    onClick={() => {\n                      if (!isActive) cb?.();\n                      closeAll();\n                    }}\n                    aria-current={isActive ? 'true' : undefined}\n                    title={t.modes.switchTo(label)}\n                    className={`group/item flex w-full cursor-pointer items-center gap-3 rounded-xl px-2.5 py-2.5 text-left transition-colors ${\n                      isActive ? 'bg-white' : 'hover:bg-white/8'\n                    }`}\n                  >\n                    <span\n                      className={`flex size-9 shrink-0 items-center justify-center rounded-xl ${MODE_ICON_BG[mode]}`}\n                    >\n                      <Icon size={16} strokeWidth={2.25} className=\"text-white\" />\n                    </span>\n                    <span className=\"min-w-0 flex-1\">\n                      <TextBody\n                        as=\"span\"\n                        size=\"md\"\n                        className={`block truncate font-semibold ${\n                          isActive ? 'text-black' : 'text-ink-primary group-hover/item:text-white'\n                        }`}\n                      >\n                        {label}\n                      </TextBody>\n                      <TextBody\n                        as=\"span\"\n                        size=\"sm\"\n                        className={`mt-0.5 block truncate ${\n                          isActive ? 'text-black/70' : 'text-white/80'\n                        }`}\n                      >\n                        {description}\n                      </TextBody>\n                    </span>\n                    {isActive ? (\n                      <Check\n                        size={14}\n                        strokeWidth={2.5}\n                        className=\"shrink-0 text-black\"\n                        aria-hidden\n                      />\n                    ) : (\n                      <span className=\"size-3.5 shrink-0\" aria-hidden />\n                    )}\n                  </button>\n                );\n              })}\n            </div>\n          </div>,\n          document.body,\n        )\n      : null;\n\n  return (\n    <div\n      ref={rootRef}\n      className={\n        isHeader\n          ? 'relative shrink-0 select-none'\n          : 'group relative flex w-full flex-col gap-1 rounded-2xl border border-panel-border bg-panel p-1 shadow-2xl shadow-black/60 backdrop-blur-md select-none'\n      }\n      onMouseEnter={() => {\n        pointerOnChipRef.current = true;\n        openByHover();\n      }}\n      onMouseLeave={() => {\n        pointerOnChipRef.current = false;\n        scheduleHoverClose();\n      }}\n    >\n      <button\n        ref={triggerRef}\n        type=\"button\"\n        onClick={onTriggerClick}\n        aria-haspopup=\"menu\"\n        aria-expanded={isOpen}\n        title={active.label}\n        className={\n          isHeader\n            ? `flex h-7 items-center justify-center gap-1.5 rounded-lg px-2.5 text-white transition-all ${activeBg} ${activeHover}`\n            : `flex h-8 items-center justify-center gap-1.5 rounded-xl px-3 text-white shadow transition-all ${activeBg} ${activeHover}`\n        }\n      >\n        <ActiveIcon size={13} strokeWidth={2.25} />\n        <TextBody as=\"span\" size=\"sm\" className={`font-bold ${isHeader ? 'hidden sm:inline' : ''}`}>\n          {active.label}\n        </TextBody>\n        <ChevronDown\n          size={12}\n          strokeWidth={2.5}\n          className={`transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`}\n        />\n      </button>\n      {menu}\n    </div>\n  );\n};\n", "import React, { useState } from 'react';\nimport { ArrowLeft, Play, Plus } from 'lucide-react';\nimport { useTranslation } from '../../i18n';\nimport { IconButton, HamburgerIcon, Dropdown, ExportButton } from '../ui';\nimport { BrandToolbarDropdown } from './BrandToolbarDropdown';\nimport { EditorModeToggle, type EditorMode } from './EditorModeToggle';\nimport { modeAccentVars } from '../../theme/modeAccent';\n\nexport interface EditorShellHeaderProps {\n  mode: EditorMode;\n  onBack?: () => void;\n  backHref?: string;\n  backLabel?: string;\n  onSwitchMode: (mode: EditorMode) => void;\n  fileMenu: React.ReactNode;\n  fileMenuLabel?: string;\n  tabs?: React.ReactNode;\n  onNewProject?: () => void;\n  newProjectTitle?: string;\n  onExport?: () => void;\n  exportDisabled?: boolean;\n  onPlay?: () => void;\n  playDisabled?: boolean;\n  className?: string;\n}\n\n/**\n * Unified 44px shell chrome for all studio modes.\n * Accent follows the mode feature palette (image/video/presentation/script/audio).\n */\nexport const EditorShellHeader: React.FC<EditorShellHeaderProps> = ({\n  mode,\n  onBack,\n  backHref,\n  backLabel,\n  onSwitchMode,\n  fileMenu,\n  fileMenuLabel,\n  tabs,\n  onNewProject,\n  newProjectTitle,\n  onExport,\n  exportDisabled,\n  onPlay,\n  playDisabled,\n  className = '',\n}) => {\n  const t = useTranslation();\n  const [menuOpen, setMenuOpen] = useState(false);\n\n  const handleBack = () => {\n    if (onBack) {\n      onBack();\n      return;\n    }\n    if (backHref) {\n      window.location.assign(backHref);\n      return;\n    }\n    window.history.back();\n  };\n\n  return (\n    <header\n      data-we-mode={mode}\n      style={{ height: 44, paddingLeft: 4, paddingRight: 4, ...modeAccentVars(mode) }}\n      className={`flex items-center gap-1.5 h-header min-h-header shrink-0 w-full bg-surface-primary border-b border-[var(--we-accent-stroke)] px-1 select-none ${className}`}\n    >\n      <IconButton\n        label={backLabel || t.editor.back}\n        size=\"sm\"\n        onClick={handleBack}\n        className=\"shrink-0\"\n      >\n        <ArrowLeft size={16} />\n      </IconButton>\n\n      <Dropdown\n        open={menuOpen}\n        onOpenChange={setMenuOpen}\n        label={fileMenuLabel || t.toolbar.common.fileMenu}\n        menuClassName=\"w-[min(17.5rem,calc(100vw-1.5rem))]\"\n        trigger={\n          <IconButton\n            label={fileMenuLabel || t.toolbar.common.fileMenu}\n            size=\"sm\"\n            active={menuOpen}\n            aria-expanded={menuOpen}\n          >\n            <HamburgerIcon open={menuOpen} size={16} />\n          </IconButton>\n        }\n      >\n        <div\n          onClick={(e) => {\n            // Keep open when toggling a submenu trigger (Filtros).\n            // Leaf items (role=menuitem without haspopup) still close the menu.\n            const target = e.target as HTMLElement | null;\n            if (target?.closest('[role=\"menuitem\"][aria-haspopup=\"menu\"]')) return;\n            setMenuOpen(false);\n          }}\n          onKeyDown={(e) => {\n            if (e.key === 'Enter') setMenuOpen(false);\n          }}\n        >\n          {fileMenu}\n        </div>\n      </Dropdown>\n\n      <EditorModeToggle\n        variant=\"header\"\n        activeMode={mode}\n        onSwitchToVideo={() => onSwitchMode('video')}\n        onSwitchToImage={() => onSwitchMode('image')}\n        onSwitchToAudio={() => onSwitchMode('audio')}\n        onSwitchToText={() => onSwitchMode('text')}\n        onSwitchToSlides={() => onSwitchMode('slides')}\n      />\n\n      <BrandToolbarDropdown />\n\n      <div className=\"flex items-center gap-1 flex-1 min-w-0 overflow-x-auto scrollbar-none ml-0.5\">\n        {tabs}\n      </div>\n\n      {onNewProject ? (\n        <IconButton\n          label={newProjectTitle || t.editor.newProject[mode]}\n          size=\"sm\"\n          onClick={onNewProject}\n          className=\"shrink-0\"\n        >\n          <Plus size={14} />\n        </IconButton>\n      ) : null}\n\n      <div className=\"flex items-center gap-1 shrink-0 pl-1\">\n        {mode === 'image' && onPlay ? (\n          <IconButton\n            label={t.toolbar.image.presentationMode}\n            size=\"sm\"\n            disabled={playDisabled}\n            onClick={onPlay}\n          >\n            <Play size={14} className=\"fill-current\" />\n          </IconButton>\n        ) : null}\n\n        <ExportButton\n          disabled={exportDisabled || !onExport}\n          onClick={() => onExport?.()}\n        />\n      </div>\n    </header>\n  );\n};\n", "import React from 'react';\nimport { Languages, LayoutTemplate, Check } from 'lucide-react';\nimport { useLocale, useSetLocale, useTranslation, type Locale } from '../../i18n';\nimport { resetAllPanelLayouts } from '../../utils/panelLayoutReset';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { DropdownDivider, DropdownItem, DropdownSection, TextBody } from '../ui';\n\ninterface FileMenuSettingsProps {\n  /** Close the parent file dropdown after an action. */\n  onDone: () => void;\n}\n\nconst LOCALES: { id: Locale; labelKey: 'spanish' | 'english' }[] = [\n  { id: 'es', labelKey: 'spanish' },\n  { id: 'en', labelKey: 'english' },\n];\n\n/**\n * Shared File-menu section: language switch + reset floating panels.\n * Used by image Toolbar, video Toolbar and CommonToolbar.\n */\nexport const FileMenuSettings: React.FC<FileMenuSettingsProps> = ({ onDone }) => {\n  const t = useTranslation();\n  const locale = useLocale();\n  const setLocale = useSetLocale();\n  const addToast = useEditorStore((s) => s.addToast);\n\n  const handleResetPanels = () => {\n    resetAllPanelLayouts();\n    addToast(t.common.panelsResetToast, 'success');\n    onDone();\n  };\n\n  return (\n    <>\n      <DropdownDivider />\n      <DropdownSection>{t.common.settingsSection}</DropdownSection>\n\n      <div className=\"flex items-center gap-1.5 px-2.5 pb-1 pt-0.5\">\n        <Languages size={11} className=\"shrink-0 text-white/80\" aria-hidden />\n        <TextBody as=\"span\" size=\"sm\" className=\"uppercase tracking-wider text-white/80 font-semibold\">\n          {t.common.language}\n        </TextBody>\n      </div>\n\n      {LOCALES.map(({ id, labelKey }) => {\n        const active = locale === id;\n        return (\n          <button\n            key={id}\n            type=\"button\"\n            role=\"menuitem\"\n            onClick={() => {\n              setLocale(id);\n              onDone();\n            }}\n            className={`flex w-full cursor-pointer items-center justify-between gap-2.5 rounded-xl px-2.5 py-2 text-left transition-colors ${\n              active\n                ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)]'\n                : 'text-ink-primary hover:bg-white/8'\n            }`}\n          >\n            <TextBody as=\"span\" size=\"md\" className=\"font-semibold\">\n              {t.common[labelKey]}\n            </TextBody>\n            {active ? (\n              <Check size={14} strokeWidth={2.5} className=\"shrink-0 text-[var(--we-accent)]\" aria-hidden />\n            ) : (\n              <span className=\"size-3.5 shrink-0\" aria-hidden />\n            )}\n          </button>\n        );\n      })}\n\n      <DropdownDivider />\n\n      <DropdownItem icon={<LayoutTemplate size={15} strokeWidth={2.25} />} onClick={handleResetPanels}>\n        {t.common.resetPanels}\n      </DropdownItem>\n    </>\n  );\n};\n", "import React from 'react';\nimport {\n  FilePlus,\n  FolderOpen,\n  Save,\n  CloudUpload,\n  Loader2,\n  Clock,\n  Sparkles,\n  Key,\n} from 'lucide-react';\nimport { DropdownItem, DropdownSection, DropdownDivider } from '../ui';\nimport { FileMenuSettings } from './FileMenuSettings';\nimport { useTranslation } from '../../i18n';\n\nexport interface ShellFileMenuProps {\n  onNew?: () => void;\n  onOpen?: () => void;\n  onSave?: () => void;\n  onSaveToCloud?: () => void;\n  isSavingCloud?: boolean;\n  /** Extra rows before settings (e.g. version history, API keys). */\n  extras?: React.ReactNode;\n  newLabel?: string;\n  openLabel?: string;\n  saveLabel?: string;\n  newDescription?: string;\n  openDescription?: string;\n  saveDescription?: string;\n}\n\n/** Shared file-menu body for EditorShellHeader hamburger. */\nexport const ShellFileMenu: React.FC<ShellFileMenuProps> = ({\n  onNew,\n  onOpen,\n  onSave,\n  onSaveToCloud,\n  isSavingCloud = false,\n  extras,\n  newLabel,\n  openLabel,\n  saveLabel,\n  newDescription,\n  openDescription,\n  saveDescription,\n}) => {\n  const t = useTranslation();\n\n  return (\n    <>\n      <DropdownSection>{t.common.fileSection}</DropdownSection>\n      {onNew ? (\n        <DropdownItem\n          icon={<FilePlus size={15} strokeWidth={2.25} />}\n          description={newDescription ?? t.common.fileNewHint}\n          onClick={onNew}\n        >\n          {newLabel || t.toolbar.common.new}\n        </DropdownItem>\n      ) : null}\n      {onOpen ? (\n        <DropdownItem\n          icon={<FolderOpen size={15} strokeWidth={2.25} />}\n          description={openDescription ?? t.common.fileOpenHint}\n          onClick={onOpen}\n        >\n          {openLabel || t.toolbar.common.openProject('kai')}\n        </DropdownItem>\n      ) : null}\n      {onSave ? (\n        <DropdownItem\n          icon={<Save size={15} strokeWidth={2.25} />}\n          description={saveDescription ?? t.common.fileSaveHint}\n          onClick={onSave}\n        >\n          {saveLabel || t.toolbar.common.saveProject('kai')}\n        </DropdownItem>\n      ) : null}\n      {onSaveToCloud ? (\n        <DropdownItem\n          icon={\n            isSavingCloud ? (\n              <Loader2 size={15} strokeWidth={2.25} className=\"animate-spin text-[var(--we-accent)]\" />\n            ) : (\n              <CloudUpload size={15} strokeWidth={2.25} />\n            )\n          }\n          description={t.common.fileCloudHint}\n          disabled={isSavingCloud}\n          onClick={onSaveToCloud}\n        >\n          {isSavingCloud ? t.toolbar.common.savingToCloud : t.toolbar.common.saveToCloud}\n        </DropdownItem>\n      ) : null}\n      {extras}\n      <FileMenuSettings onDone={() => undefined} />\n    </>\n  );\n};\n\nexport { Clock, Sparkles, Key, DropdownItem, DropdownDivider, DropdownSection };\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { Plus } from 'lucide-react';\nimport { useTranslation } from '../../i18n';\nimport { TextBody } from '../ui';\n\nexport interface StudioTabBarProps {\n  backLinkHref?: string;\n  backLinkText?: string;\n  onNewProject?: () => void;\n  newProjectTitle?: string;\n  children?: React.ReactNode;\n  className?: string;\n}\n\n/**\n * Top chrome shared by all studio modes. Always renders the back link so\n * users can return to Kaiman even when no local project tabs exist.\n */\nexport const StudioTabBar: React.FC<StudioTabBarProps> = ({\n  backLinkHref,\n  backLinkText,\n  onNewProject,\n  newProjectTitle,\n  children,\n  className = '',\n}) => {\n  const t = useTranslation();\n\n  return (\n    <div\n      className={`flex items-center gap-2 h-9 bg-[#0A0A0F] border-b border-panel-border px-3 overflow-x-auto scrollbar-none flex-shrink-0 ${className}`}\n    >\n      <a\n        href={backLinkHref || '#'}\n        className=\"flex-shrink-0 h-7 px-3 flex items-center rounded-lg bg-white text-black hover:opacity-80 transition-opacity duration-150 select-none whitespace-nowrap\"\n      >\n        <TextBody as=\"span\" size=\"sm\" className=\"font-bold\">\n          {backLinkText || t.editor.back}\n        </TextBody>\n      </a>\n\n      <div className=\"flex items-center gap-1 flex-1 min-w-0 overflow-x-auto\">\n        {children}\n      </div>\n\n      {onNewProject ? (\n        <button\n          type=\"button\"\n          onClick={onNewProject}\n          title={newProjectTitle}\n          className=\"flex-shrink-0 w-7 h-7 flex items-center justify-center rounded-lg text-[#8888A0] hover:text-[#F0F0F5] hover:bg-[#1C1C26] transition-all\"\n        >\n          <Plus size={13} />\n        </button>\n      ) : null}\n    </div>\n  );\n};\n\nexport interface StudioProjectTabProps {\n  label: string;\n  isActive: boolean;\n  icon: React.ReactNode;\n  onSelect: () => void;\n  onClose: () => void;\n  /** Double-click the label to rename; becomes the project / file name. */\n  onRename?: (nextName: string) => void;\n}\n\n/** Project tabs stay neutral \u2014 feature accent lives on the floating toolstrip. */\nexport const StudioProjectTab: React.FC<StudioProjectTabProps> = ({\n  label,\n  isActive,\n  icon,\n  onSelect,\n  onClose,\n  onRename,\n}) => {\n  const t = useTranslation();\n  const [editing, setEditing] = useState(false);\n  const [draft, setDraft] = useState(label);\n  const inputRef = useRef<HTMLInputElement | null>(null);\n\n  useEffect(() => {\n    if (!editing) setDraft(label);\n  }, [label, editing]);\n\n  useEffect(() => {\n    if (!editing) return;\n    const el = inputRef.current;\n    if (!el) return;\n    el.focus();\n    el.select();\n  }, [editing]);\n\n  const commit = () => {\n    const next = draft.trim();\n    setEditing(false);\n    if (!next || next === label) {\n      setDraft(label);\n      return;\n    }\n    onRename?.(next);\n  };\n\n  const cancel = () => {\n    setDraft(label);\n    setEditing(false);\n  };\n\n  return (\n    <div\n      role=\"tab\"\n      aria-selected={isActive}\n      onClick={() => {\n        if (!editing) onSelect();\n      }}\n      className={`group flex h-7 max-w-[160px] shrink-0 cursor-pointer items-center gap-1.5 rounded-lg border px-4 font-semibold transition-all select-none ${\n        isActive\n          ? 'border-panel-border bg-surface-tertiary text-ink-primary'\n          : 'border-transparent text-ink-secondary hover:bg-surface-tertiary/50 hover:text-ink-primary'\n      }`}\n    >\n      {icon}\n      {editing && onRename ? (\n        <input\n          ref={inputRef}\n          value={draft}\n          onChange={(e) => setDraft(e.target.value)}\n          onClick={(e) => e.stopPropagation()}\n          onDoubleClick={(e) => e.stopPropagation()}\n          onBlur={commit}\n          onKeyDown={(e) => {\n            if (e.key === 'Enter') {\n              e.preventDefault();\n              commit();\n            } else if (e.key === 'Escape') {\n              e.preventDefault();\n              cancel();\n            }\n          }}\n          className=\"min-w-0 max-w-[7rem] flex-1 rounded bg-black-capsule px-1 py-0.5 font-sans text-[11px] font-semibold text-ink-primary outline-none ring-1 ring-[var(--we-accent)]/50\"\n          aria-label={t.editor.renameTab}\n        />\n      ) : (\n        <span\n          className=\"min-w-0 truncate\"\n          title={onRename ? t.editor.renameTabHint : label}\n          onDoubleClick={(e) => {\n            if (!onRename) return;\n            e.stopPropagation();\n            e.preventDefault();\n            setDraft(label);\n            setEditing(true);\n          }}\n        >\n          <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n            {label}\n          </TextBody>\n        </span>\n      )}\n      <button\n        type=\"button\"\n        onClick={(e) => {\n          e.stopPropagation();\n          onClose();\n        }}\n        className={`ml-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded transition-all ${\n          isActive\n            ? 'opacity-60 hover:bg-black-stroke hover:opacity-100'\n            : 'opacity-0 group-hover:opacity-60 hover:!opacity-100 hover:bg-black-stroke'\n        }`}\n      >\n        <TextBody as=\"span\" size=\"sm\" className=\"sr-only\">\n          {t.editor.closeTab}\n        </TextBody>\n        <svg width=\"9\" height=\"9\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n          <path d=\"M18 6 6 18M6 6l12 12\" />\n        </svg>\n      </button>\n    </div>\n  );\n};\n", "import React from 'react';\nimport { Film, Image as ImageIcon, Music2, FileText, Presentation } from 'lucide-react';\nimport { StudioProjectTab } from './StudioTabBar';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { useVideoStore } from '../../store/useVideoStore';\nimport { useAudioStore } from '../../store/useAudioStore';\nimport { useTextStore } from '../../store/useTextStore';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport type { EditorMode } from './EditorModeToggle';\n\nfunction ImageTabs() {\n  const {\n    imageProjects,\n    activeImageProjectId,\n    switchImageProject,\n    closeImageProject,\n    renameImageProject,\n  } = useEditorStore();\n  return (\n    <>\n      {imageProjects.map((p) => (\n        <StudioProjectTab\n          key={p.id}\n          label={p.name}\n          isActive={p.id === activeImageProjectId}\n          icon={<ImageIcon size={10} className=\"text-ink-secondary\" />}\n          onSelect={() => switchImageProject(p.id)}\n          onClose={() => closeImageProject(p.id)}\n          onRename={(name) => renameImageProject(p.id, name)}\n        />\n      ))}\n    </>\n  );\n}\n\nfunction VideoTabs() {\n  const {\n    videoProjects,\n    activeVideoProjectId,\n    switchVideoProject,\n    closeVideoProject,\n    renameVideoProject,\n  } = useVideoStore();\n  return (\n    <>\n      {videoProjects.map((p) => (\n        <StudioProjectTab\n          key={p.id}\n          label={p.name}\n          isActive={p.id === activeVideoProjectId}\n          icon={<Film size={10} className=\"text-ink-secondary\" />}\n          onSelect={() => switchVideoProject(p.id)}\n          onClose={() => closeVideoProject(p.id)}\n          onRename={(name) => renameVideoProject(p.id, name)}\n        />\n      ))}\n    </>\n  );\n}\n\nfunction AudioTabs() {\n  const {\n    audioProjects,\n    activeAudioProjectId,\n    switchAudioProject,\n    closeAudioProject,\n    renameAudioProject,\n  } = useAudioStore();\n  return (\n    <>\n      {audioProjects.map((p) => (\n        <StudioProjectTab\n          key={p.id}\n          label={p.name}\n          isActive={p.id === activeAudioProjectId}\n          icon={<Music2 size={10} className=\"text-ink-secondary\" />}\n          onSelect={() => switchAudioProject(p.id)}\n          onClose={() => closeAudioProject(p.id)}\n          onRename={(name) => renameAudioProject(p.id, name)}\n        />\n      ))}\n    </>\n  );\n}\n\nfunction TextTabs() {\n  const {\n    textProjects,\n    activeTextProjectId,\n    switchTextProject,\n    closeTextProject,\n    setProjectName,\n  } = useTextStore();\n  return (\n    <>\n      {textProjects.map((p) => (\n        <StudioProjectTab\n          key={p.id}\n          label={p.name}\n          isActive={p.id === activeTextProjectId}\n          icon={<FileText size={10} className=\"text-ink-secondary\" />}\n          onSelect={() => switchTextProject(p.id)}\n          onClose={() => closeTextProject(p.id)}\n          onRename={(name) => {\n            if (p.id === activeTextProjectId) {\n              setProjectName(name);\n            } else {\n              useTextStore.setState((s) => ({\n                textProjects: s.textProjects.map((proj) =>\n                  proj.id === p.id ? { ...proj, name } : proj,\n                ),\n              }));\n            }\n          }}\n        />\n      ))}\n    </>\n  );\n}\n\nfunction SlidesTabs() {\n  const {\n    slidesProjects,\n    activeSlidesProjectId,\n    switchSlidesProject,\n    closeSlidesProject,\n    renameProject,\n  } = useSlidesStore();\n  return (\n    <>\n      {slidesProjects.map((p) => (\n        <StudioProjectTab\n          key={p.id}\n          label={p.name}\n          isActive={p.id === activeSlidesProjectId}\n          icon={<Presentation size={10} className=\"text-ink-secondary\" />}\n          onSelect={() => switchSlidesProject(p.id)}\n          onClose={() => closeSlidesProject(p.id)}\n          onRename={(name) => {\n            if (p.id === activeSlidesProjectId) {\n              renameProject(name);\n            } else {\n              useSlidesStore.setState((s) => ({\n                slidesProjects: s.slidesProjects.map((proj) =>\n                  proj.id === p.id ? { ...proj, name } : proj,\n                ),\n              }));\n            }\n          }}\n        />\n      ))}\n    </>\n  );\n}\n\n/** Project tabs for the unified shell header (per mode store). */\nexport const ModeProjectTabs: React.FC<{ mode: EditorMode }> = ({ mode }) => {\n  switch (mode) {\n    case 'image':\n      return <ImageTabs />;\n    case 'video':\n      return <VideoTabs />;\n    case 'audio':\n      return <AudioTabs />;\n    case 'text':\n      return <TextTabs />;\n    case 'slides':\n      return <SlidesTabs />;\n    default:\n      return null;\n  }\n};\n", "import { FFmpeg } from '@ffmpeg/ffmpeg';\nimport { toBlobURL } from '@ffmpeg/util';\nimport { type Track, type Asset } from '../store/useVideoStore';\nimport { WebGLVideoRenderer } from '../lib/effects/webglRenderer';\nimport { drawTextClipToCanvas } from '../lib/effects/textRenderer';\nimport { getMotionTransform } from '../lib/effects/motionUtils';\n\nlet ffmpegInstance: FFmpeg | null = null;\n\n/**\n * Returns a singleton FFmpeg instance, fully loaded and ready to use.\n *\n * Worker resolution strategy (bundler-agnostic):\n * Instead of relying on `import.meta.url` \u2014 which only works in Vite and breaks\n * in Next.js / Turbopack / Webpack environments \u2014 we explicitly provide the worker\n * via `classWorkerURL` as a Blob URL fetched from unpkg (CDN).\n * This makes the package self-contained and portable across any bundler.\n */\nexport async function getFFmpeg(): Promise<FFmpeg> {\n  if (ffmpegInstance) return ffmpegInstance;\n\n  const ffmpeg = new FFmpeg();\n\n  // All assets are loaded from unpkg CDN as Blob URLs.\n  // Using Blob URLs avoids CORS/COEP restrictions and removes any\n  // dependency on the local file system or bundler-specific asset resolution.\n  const ffmpegVersion = '0.12.15';\n  const coreVersion = '0.12.6';\n  const workerURL = `https://unpkg.com/@ffmpeg/ffmpeg@${ffmpegVersion}/dist/esm/worker.js`;\n  const coreBaseURL = `https://unpkg.com/@ffmpeg/core@${coreVersion}/dist/esm`;\n\n  await ffmpeg.load({\n    // Explicit worker URL via CDN \u2014 avoids the `import.meta.url` resolution\n    // that Vite inlines at build time and that Next.js / Turbopack cannot handle.\n    classWorkerURL: await toBlobURL(workerURL, 'text/javascript'),\n    coreURL: await toBlobURL(`${coreBaseURL}/ffmpeg-core.js`, 'text/javascript'),\n    wasmURL: await toBlobURL(`${coreBaseURL}/ffmpeg-core.wasm`, 'application/wasm'),\n  });\n\n  ffmpegInstance = ffmpeg;\n  return ffmpeg;\n}\n\nexport async function exportVideo(\n  tracks: Track[],\n  assets: Asset[],\n  projectDuration: number,\n  resolution: '720p' | '1080p' | '4k',\n  fps: number,\n  onProgress: (progress: number, step: string) => void\n): Promise<Blob> {\n  const ffmpeg = await getFFmpeg();\n  onProgress(5, 'Initializing virtual rendering canvas...');\n\n  // Setup render canvas size\n  let width = 1920;\n  let height = 1080;\n  if (resolution === '720p') {\n    width = 1280;\n    height = 720;\n  } else if (resolution === '4k') {\n    width = 3840;\n    height = 2160;\n  }\n\n  const canvas = document.createElement('canvas');\n  canvas.width = width;\n  canvas.height = height;\n  const gl = canvas.getContext('webgl2', { premultipliedAlpha: false });\n  if (!gl) {\n    throw new Error('WebGL2 is not supported by your browser.');\n  }\n\n  const renderer = new WebGLVideoRenderer(gl);\n  \n  // Offscreen canvas for rendering text overlays\n  const textCanvas = document.createElement('canvas');\n  textCanvas.width = width;\n  textCanvas.height = height;\n  const textCtx = textCanvas.getContext('2d');\n  if (!textCtx) {\n    throw new Error('Could not get 2D context for text rendering.');\n  }\n\n  // Pre-load all media assets elements for rendering\n  onProgress(10, 'Pre-caching project media elements...');\n  const mediaElements: Record<string, HTMLVideoElement | HTMLImageElement> = {};\n  \n  for (const asset of assets) {\n    if (asset.type === 'image') {\n      const img = new Image();\n      img.src = asset.url;\n      img.crossOrigin = 'anonymous';\n      await new Promise((resolve) => {\n        img.onload = resolve;\n        img.onerror = resolve;\n      });\n      mediaElements[asset.id] = img;\n    } else if (asset.type === 'video') {\n      const video = document.createElement('video');\n      video.src = asset.url;\n      video.preload = 'auto';\n      video.crossOrigin = 'anonymous';\n      video.muted = true;\n      video.playsInline = true;\n      await new Promise((resolve) => {\n        video.onloadeddata = resolve;\n        video.onerror = resolve;\n      });\n      mediaElements[asset.id] = video;\n    }\n  }\n\n  // Frame by frame stepping\n  const step = 1 / fps;\n  const totalFrames = Math.ceil(projectDuration / step);\n  \n  onProgress(15, `Rendering ${totalFrames} frames...`);\n\n  // WebGL Blending Setup\n  gl.viewport(0, 0, width, height);\n  gl.enable(gl.BLEND);\n  gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n\n  // Write frames loop\n  for (let f = 0; f < totalFrames; f++) {\n    const time = f * step;\n\n    // Clear gl canvas\n    gl.clearColor(0.04, 0.04, 0.06, 1.0);\n    gl.clear(gl.COLOR_BUFFER_BIT);\n\n    // 1. Render Video Track Layers\n    // Muted video tracks still export picture; audio is silenced separately.\n    const videoTracks = tracks.filter((t) => t.type === 'video');\n    // Gather active video clips\n    const activeVideoClips: { clip: any; videoEl: HTMLVideoElement }[] = [];\n    videoTracks.forEach((track) => {\n      track.clips.forEach((clip) => {\n        if (time >= clip.startTime && time < clip.startTime + clip.duration) {\n          const videoEl = mediaElements[clip.assetId] as HTMLVideoElement;\n          if (videoEl) {\n            activeVideoClips.push({ clip, videoEl });\n          }\n        }\n      });\n    });\n\n    // Sort by track ID\n    activeVideoClips.sort((a, b) => {\n      const trackOrder = ['v1', 'v2'];\n      return trackOrder.indexOf(a.clip.trackId) - trackOrder.indexOf(b.clip.trackId);\n    });\n\n    for (const { clip, videoEl } of activeVideoClips) {\n      const offset = (time - clip.startTime) * clip.speed + clip.trimIn;\n      videoEl.currentTime = offset;\n      \n      // Wait a microsecond for frame seek sync in browser\n      await new Promise((r) => setTimeout(r, 8));\n      \n      renderer.drawLayer(videoEl, clip, offset, width, height);\n    }\n\n    // 2. Render Image Layers\n    const imageTracks = tracks.filter((t) => t.type === 'image' && !t.muted);\n    imageTracks.forEach((track) => {\n      track.clips.forEach((clip) => {\n        if (time >= clip.startTime && time < clip.startTime + clip.duration) {\n          const imgEl = mediaElements[clip.assetId] as HTMLImageElement;\n          if (imgEl) {\n            const offset = time - clip.startTime;\n            const motion = getMotionTransform(clip, offset);\n            \n            const animatedClip = {\n              ...clip,\n              opacity: clip.opacity !== undefined ? clip.opacity * motion.scale : motion.scale,\n              x: (clip.x ?? 0.5) + motion.xOffset,\n              y: (clip.y ?? 0.5) + motion.yOffset,\n              rotation: (clip.rotation || 0) + motion.rotationOffset\n            };\n            renderer.drawLayer(imgEl, animatedClip, offset, width, height);\n          }\n        }\n      });\n    });\n\n    // 3. Render Text & Subtitle Layers\n    const textTracks = tracks.filter((t) => (t.type === 'text' || t.type === 'subtitle' || t.id === 'sub') && !t.muted);\n    textCtx.clearRect(0, 0, width, height);\n    let hasActiveText = false;\n\n    textTracks.forEach((track) => {\n      track.clips.forEach((clip) => {\n        if (time >= clip.startTime && time < clip.startTime + clip.duration) {\n          const offset = time - clip.startTime;\n          drawTextClipToCanvas(textCtx, clip, offset, width, height);\n          hasActiveText = true;\n        }\n      });\n    });\n\n    if (hasActiveText) {\n      const dummyClip = {\n        id: 'export_text',\n        trackId: '',\n        assetId: '',\n        startTime: 0,\n        duration: 9999,\n        trimIn: 0,\n        trimOut: 0,\n        speed: 1.0,\n        volume: 1.0,\n        opacity: 1.0,\n        muted: false,\n        type: 'text' as const\n      };\n      renderer.drawLayer(textCanvas, dummyClip, 0, width, height);\n    }\n\n    // 4. Capture Frame Blob & write to FFmpeg FS\n    const blob = await new Promise<Blob | null>((resolve) => canvas.toBlob(resolve, 'image/jpeg', 0.85));\n    if (blob) {\n      const frameBuffer = new Uint8Array(await blob.arrayBuffer());\n      const fileName = `frame_${f.toString().padStart(5, '0')}.jpg`;\n      await ffmpeg.writeFile(fileName, frameBuffer);\n    }\n\n    // Update progress between 15% and 80%\n    const currentProgress = 15 + Math.round((f / totalFrames) * 65);\n    if (f % 5 === 0) {\n      onProgress(currentProgress, `Baking frames (${f}/${totalFrames})...`);\n    }\n  }\n\n  // 5. Build output video command\n  onProgress(85, 'Running FFmpeg video assembler compiler...');\n  await ffmpeg.exec([\n    '-framerate', String(fps),\n    '-i', 'frame_%05d.jpg',\n    '-c:v', 'libx264',\n    '-preset', 'ultrafast',\n    '-pix_fmt', 'yuv420p',\n    'raw_output.mp4'\n  ]);\n\n  onProgress(95, 'Finalizing download blob packaging...');\n  const fileData = await ffmpeg.readFile('raw_output.mp4');\n  const finalBlob = new Blob([fileData as any], { type: 'video/mp4' });\n\n  // Clean up virtual filesystem frames\n  onProgress(98, 'Cleaning compiler cache files...');\n  for (let f = 0; f < totalFrames; f++) {\n    const fileName = `frame_${f.toString().padStart(5, '0')}.jpg`;\n    try {\n      await ffmpeg.deleteFile(fileName);\n    } catch (e) {}\n  }\n  try {\n    await ffmpeg.deleteFile('raw_output.mp4');\n  } catch (e) {}\n\n  onProgress(100, 'Export completed!');\n  return finalBlob;\n}\n", "import type { EditorMode } from '../components/editor/EditorModeToggle';\nimport { getActiveMessages } from '../i18n';\n\n/** Download basename = current-locale studio mode label (e.g. Imagen / Image). */\nexport function modeExportBasename(mode: EditorMode): string {\n  return getActiveMessages().modes[mode];\n}\n\n/** `Imagen.png`, `Video.mp4`, \u2026 */\nexport function modeExportFilename(mode: EditorMode, extension: string): string {\n  const ext = extension.replace(/^\\./, '');\n  return `${modeExportBasename(mode)}.${ext}`;\n}\n", "import { getActiveMessages } from '../i18n';\nimport { useEditorStore } from '../store/useEditorStore';\nimport { useVideoStore } from '../store/useVideoStore';\nimport { useAudioStore } from '../store/useAudioStore';\nimport { useTextStore } from '../store/useTextStore';\nimport { useSlidesStore } from '../store/useSlidesStore';\nimport {\n  uploadCurrentProjectToCloud,\n  isCloudPayloadTooLargeError,\n  type CloudProjectMode,\n} from './projectCloudSerializer';\nimport {\n  beginCloudSaveChip,\n  resolveCloudSaveChip,\n} from './cloudSaveStatus';\n\n/**\n * Uploads the active project and shows a compact save icon chip\n * (spinner \u2192 check / X). Reuses `cloudEditableId` via PATCH so Recientes\n * keeps one canvas per project.\n */\nexport async function uploadCurrentProjectToCloudWithToast(\n  mode: CloudProjectMode,\n): Promise<void> {\n  const t = getActiveMessages();\n  const chipId = beginCloudSaveChip(t.toast.savingToCloud);\n\n  try {\n    let cloudEditableId: number | undefined;\n    if (mode === 'image') {\n      const s = useEditorStore.getState();\n      cloudEditableId = s.imageProjects.find((p) => p.id === s.activeImageProjectId)?.cloudEditableId;\n    } else if (mode === 'video') {\n      const s = useVideoStore.getState();\n      cloudEditableId = s.videoProjects.find((p) => p.id === s.activeVideoProjectId)?.cloudEditableId;\n    } else if (mode === 'audio') {\n      const s = useAudioStore.getState();\n      cloudEditableId = s.audioProjects.find((p) => p.id === s.activeAudioProjectId)?.cloudEditableId;\n    } else if (mode === 'text') {\n      const s = useTextStore.getState();\n      cloudEditableId = s.textProjects.find((p) => p.id === s.activeTextProjectId)?.cloudEditableId;\n    } else if (mode === 'slides') {\n      const s = useSlidesStore.getState();\n      cloudEditableId = s.slidesProjects.find((p) => p.id === s.activeSlidesProjectId)?.cloudEditableId;\n    }\n\n    const editable = await uploadCurrentProjectToCloud(mode, {\n      editableId: cloudEditableId,\n    });\n\n    if (mode === 'image') {\n      const store = useEditorStore.getState();\n      const projectId = store.activeImageProjectId;\n      if (projectId) {\n        useEditorStore.setState({\n          imageProjects: store.imageProjects.map((p) =>\n            p.id === projectId ? { ...p, cloudEditableId: editable.id } : p,\n          ),\n        });\n        void store.saveCurrentProject().catch(() => {});\n      }\n    } else if (mode === 'video') {\n      const store = useVideoStore.getState();\n      const projectId = store.activeVideoProjectId;\n      if (projectId) {\n        useVideoStore.setState({\n          videoProjects: store.videoProjects.map((p) =>\n            p.id === projectId ? { ...p, cloudEditableId: editable.id } : p,\n          ),\n        });\n        void store.saveVideoProject().catch(() => {});\n      }\n    } else if (mode === 'audio') {\n      const store = useAudioStore.getState();\n      const projectId = store.activeAudioProjectId;\n      if (projectId) {\n        useAudioStore.setState({\n          audioProjects: store.audioProjects.map((p) =>\n            p.id === projectId ? { ...p, cloudEditableId: editable.id } : p,\n          ),\n        });\n        void store.saveAudioProject().catch(() => {});\n      }\n    } else if (mode === 'text') {\n      const store = useTextStore.getState();\n      const projectId = store.activeTextProjectId;\n      if (projectId) {\n        useTextStore.setState({\n          textProjects: store.textProjects.map((p) =>\n            p.id === projectId ? { ...p, cloudEditableId: editable.id } : p,\n          ),\n        });\n        void store.saveTextProject().catch(() => {});\n      }\n    } else if (mode === 'slides') {\n      const store = useSlidesStore.getState();\n      const projectId = store.activeSlidesProjectId;\n      if (projectId) {\n        useSlidesStore.setState({\n          slidesProjects: store.slidesProjects.map((p) =>\n            p.id === projectId ? { ...p, cloudEditableId: editable.id } : p,\n          ),\n        });\n        void store.saveSlidesProject().catch(() => {});\n      }\n    }\n\n    resolveCloudSaveChip(chipId, 'success', t.toast.savedToCloud);\n  } catch (err) {\n    const label = isCloudPayloadTooLargeError(err)\n      ? t.toast.cloudPayloadTooLarge\n      : t.toast.saveFailed(err instanceof Error ? err.message : String(err));\n    resolveCloudSaveChip(chipId, 'error', label);\n    throw err;\n  }\n}\n", "import { StaticCanvas, FabricText, FabricImage, Line } from 'fabric';\nimport { useEditorStore, applyCanvasBackground } from '../store/useEditorStore';\nimport { jsPDF } from 'jspdf';\nimport { modeExportBasename, modeExportFilename } from './exportDownloadName';\n\nexport interface AdvancedExportOptions {\n  format: 'png' | 'jpeg' | 'svg' | 'pdf' | 'pptx' | 'html';\n  scale: number;\n  bleed: number; // in mm, default 0\n  cropMarks: boolean;\n  watermark: {\n    enabled: boolean;\n    type: 'text' | 'image';\n    text?: string;\n    imageUrl?: string;\n    opacity: number;\n  };\n}\n\nconst MM_TO_PX = 3.7795275591; // Approx at 96 DPI\n/** Minimum outer margin so corner crop marks fit inside the bleed. */\nconst MIN_BLEED_FOR_CROP_MARKS_MM = 8;\n\nconst addWatermark = async (canvas: StaticCanvas, options: AdvancedExportOptions) => {\n  const { watermark } = options;\n  if (!watermark.enabled) return;\n\n  if (watermark.type === 'text' && watermark.text) {\n    const text = new FabricText(watermark.text, {\n      fontSize: Math.min(canvas.width!, canvas.height!) / 5,\n      fill: 'rgba(0,0,0,1)',\n      opacity: watermark.opacity,\n      originX: 'center',\n      originY: 'center',\n      left: canvas.width! / 2,\n      top: canvas.height! / 2,\n      angle: -45,\n      fontWeight: 'bold',\n      fontFamily: 'Inter, sans-serif',\n    });\n    canvas.add(text);\n  } else if (watermark.type === 'image' && watermark.imageUrl) {\n    const img = await FabricImage.fromURL(watermark.imageUrl);\n    const scale = Math.min(canvas.width! / img.width!, canvas.height! / img.height!) * 0.8;\n    img.set({\n      scaleX: scale,\n      scaleY: scale,\n      opacity: watermark.opacity,\n      originX: 'center',\n      originY: 'center',\n      left: canvas.width! / 2,\n      top: canvas.height! / 2,\n    });\n    canvas.add(img);\n  }\n};\n\n/**\n * Print crop marks: L-marks only in the bleed gutter (never on the artwork).\n * Sized to fit inside `bleedPx`. Dual white/black strokes for contrast.\n */\nconst addCropMarks = (canvas: StaticCanvas, bleedPx: number, originalW: number, originalH: number) => {\n  if (bleedPx < 4) return;\n\n  const left = bleedPx;\n  const top = bleedPx;\n  const right = bleedPx + originalW;\n  const bottom = bleedPx + originalH;\n\n  const gap = Math.max(2, Math.min(bleedPx * 0.2, 8));\n  const len = Math.max(6, bleedPx - gap - 1);\n  const strokeWidth = Math.max(1.25, Math.min(bleedPx / 6, 2.5));\n\n  const base = {\n    selectable: false,\n    evented: false,\n    objectCaching: false,\n  } as const;\n\n  const addLine = (coords: [number, number, number, number], stroke: string, width: number) => {\n    canvas.add(\n      new Line(coords, {\n        ...base,\n        stroke,\n        strokeWidth: width,\n        strokeLineCap: 'butt',\n      }),\n    );\n  };\n\n  const addVisibleLine = (coords: [number, number, number, number]) => {\n    addLine(coords, '#ffffff', strokeWidth + 1.75);\n    addLine(coords, '#111111', strokeWidth);\n  };\n\n  // Corner L-marks entirely inside the bleed (outside the trim box).\n  addVisibleLine([left - gap - len, top, left - gap, top]);\n  addVisibleLine([left, top - gap - len, left, top - gap]);\n  addVisibleLine([right + gap, top, right + gap + len, top]);\n  addVisibleLine([right, top - gap - len, right, top - gap]);\n  addVisibleLine([left - gap - len, bottom, left - gap, bottom]);\n  addVisibleLine([left, bottom + gap, left, bottom + gap + len]);\n  addVisibleLine([right + gap, bottom, right + gap + len, bottom]);\n  addVisibleLine([right, bottom + gap, right, bottom + gap + len]);\n};\n\nexport const advancedExport = async (options: AdvancedExportOptions) => {\n  const store = useEditorStore.getState();\n  const pages = store.pages;\n  const activePageId = store.activePageId;\n  const activePage = pages.find((p) => p.id === activePageId) || pages[0];\n\n  if (!activePage) return;\n\n  // Crop marks need outer margin; bump bleed when marks are on but margin is too small.\n  const bleedMm = options.cropMarks\n    ? Math.max(options.bleed, MIN_BLEED_FOR_CROP_MARKS_MM)\n    : options.bleed;\n  const bleedPx = bleedMm * MM_TO_PX;\n  const exportWidth = activePage.width + bleedPx * 2;\n  const exportHeight = activePage.height + bleedPx * 2;\n\n  // Single Page Export for images/HTML\n  if (['png', 'jpeg', 'svg', 'html'].includes(options.format)) {\n    const canvasEl = document.createElement('canvas');\n    const staticCanvas = new StaticCanvas(canvasEl, { renderOnAddRemove: false });\n\n    staticCanvas.setDimensions({ width: exportWidth, height: exportHeight });\n\n    await staticCanvas.loadFromJSON(activePage.json || {});\n\n    if (bleedPx > 0) {\n      staticCanvas.getObjects().forEach((obj) => {\n        obj.left = (obj.left || 0) + bleedPx;\n        obj.top = (obj.top || 0) + bleedPx;\n        obj.setCoords();\n      });\n    }\n\n    applyCanvasBackground(staticCanvas, activePage.backgroundColor, exportWidth, exportHeight);\n\n    if (options.cropMarks) {\n      addCropMarks(staticCanvas, bleedPx, activePage.width, activePage.height);\n    }\n\n    await addWatermark(staticCanvas, options);\n\n    staticCanvas.requestRenderAll();\n    await new Promise((r) => setTimeout(r, 100));\n\n    if (options.format === 'svg') {\n      const svg = staticCanvas.toSVG();\n      const blob = new Blob([svg], { type: 'image/svg+xml' });\n      const url = URL.createObjectURL(blob);\n      const a = document.createElement('a');\n      a.href = url;\n      a.download = modeExportFilename('image', 'svg');\n      a.click();\n      URL.revokeObjectURL(url);\n    } else if (options.format === 'html') {\n      // Self-contained snapshot (no CDN / Fabric). Works offline and under file://.\n      const dataUrl = staticCanvas.toDataURL({\n        format: 'png',\n        quality: 1,\n        multiplier: options.scale,\n      });\n      const displayW = Math.round(exportWidth * options.scale);\n      const displayH = Math.round(exportHeight * options.scale);\n      const title = modeExportBasename('image');\n      const htmlContent = `<!DOCTYPE html>\n<html lang=\"es\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n  <title>${title}</title>\n  <style>\n    html, body { margin: 0; min-height: 100%; }\n    body {\n      display: flex;\n      justify-content: center;\n      align-items: center;\n      min-height: 100vh;\n      background: #e5e7eb;\n      box-sizing: border-box;\n      padding: 24px;\n    }\n    img {\n      display: block;\n      max-width: 100%;\n      height: auto;\n      box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n    }\n  </style>\n</head>\n<body>\n  <img src=\"${dataUrl}\" width=\"${displayW}\" height=\"${displayH}\" alt=\"${title}\" />\n</body>\n</html>`;\n      const blob = new Blob([htmlContent], { type: 'text/html;charset=utf-8' });\n      const url = URL.createObjectURL(blob);\n      const a = document.createElement('a');\n      a.href = url;\n      a.download = modeExportFilename('image', 'html');\n      a.click();\n      URL.revokeObjectURL(url);\n    } else {\n      const dataUrl = staticCanvas.toDataURL({\n        format: options.format as 'png' | 'jpeg',\n        quality: 1,\n        multiplier: options.scale,\n      });\n      const a = document.createElement('a');\n      a.href = dataUrl;\n      a.download = modeExportFilename('image', options.format);\n      a.click();\n    }\n    staticCanvas.dispose();\n  } else if (options.format === 'pdf') {\n    const pdf = new jsPDF({\n      orientation: exportWidth > exportHeight ? 'landscape' : 'portrait',\n      unit: 'px',\n      format: [exportWidth, exportHeight],\n    });\n\n    const canvasEl = document.createElement('canvas');\n    const staticCanvas = new StaticCanvas(canvasEl, { renderOnAddRemove: false });\n\n    for (let i = 0; i < pages.length; i++) {\n      const page = pages[i]!;\n      const pageExportWidth = page.width + bleedPx * 2;\n      const pageExportHeight = page.height + bleedPx * 2;\n\n      staticCanvas.setDimensions({ width: pageExportWidth, height: pageExportHeight });\n      await staticCanvas.loadFromJSON(page.json || {});\n\n      if (bleedPx > 0) {\n        staticCanvas.getObjects().forEach((obj) => {\n          obj.left = (obj.left || 0) + bleedPx;\n          obj.top = (obj.top || 0) + bleedPx;\n          obj.setCoords();\n        });\n      }\n\n      applyCanvasBackground(staticCanvas, page.backgroundColor, pageExportWidth, pageExportHeight);\n\n      if (options.cropMarks) {\n        addCropMarks(staticCanvas, bleedPx, page.width, page.height);\n      }\n      await addWatermark(staticCanvas, options);\n\n      staticCanvas.requestRenderAll();\n      await new Promise((r) => setTimeout(r, 100));\n\n      const dataUrl = staticCanvas.toDataURL({\n        format: 'jpeg',\n        quality: 1,\n        multiplier: options.scale,\n      });\n\n      if (i > 0) {\n        pdf.addPage(\n          [pageExportWidth, pageExportHeight],\n          pageExportWidth > pageExportHeight ? 'landscape' : 'portrait',\n        );\n      }\n\n      pdf.addImage(dataUrl, 'JPEG', 0, 0, pageExportWidth, pageExportHeight);\n    }\n    staticCanvas.dispose();\n    pdf.save(modeExportFilename('image', 'pdf'));\n  } else if (options.format === 'pptx') {\n    const { exportProjectToPPTX } = await import('./exportUtils');\n    exportProjectToPPTX();\n  }\n};\n", "import { StaticCanvas } from 'fabric';\nimport { useEditorStore, applyCanvasBackground } from '../store/useEditorStore';\nimport { jsPDF } from 'jspdf';\nimport pptxgen from 'pptxgenjs';\nimport { modeExportBasename } from './exportDownloadName';\n\nexport const exportProjectToPDF = async (fileName: string = modeExportBasename('image')) => {\n  const store = useEditorStore.getState();\n  const pages = store.pages;\n  \n  if (pages.length === 0) return;\n\n  // Create a hidden canvas element\n  const canvasEl = document.createElement('canvas');\n  const staticCanvas = new StaticCanvas(canvasEl, {\n    renderOnAddRemove: false,\n  });\n\n  const pdf = new jsPDF({\n    orientation: pages[0].width > pages[0].height ? 'landscape' : 'portrait',\n    unit: 'px',\n    format: [pages[0].width, pages[0].height]\n  });\n\n  for (let i = 0; i < pages.length; i++) {\n    const page = pages[i];\n    \n    // Set dimensions\n    staticCanvas.setDimensions({ width: page.width, height: page.height });\n    \n    // Load JSON\n    await staticCanvas.loadFromJSON(page.json || {});\n    applyCanvasBackground(staticCanvas, page.backgroundColor, page.width, page.height);\n    staticCanvas.requestRenderAll();\n    \n    // Wait for render (fonts, images might need a moment, though loadFromJSON usually awaits)\n    await new Promise(r => setTimeout(r, 100));\n    \n    const dataUrl = staticCanvas.toDataURL({\n      format: 'jpeg',\n      quality: 0.95,\n      multiplier: 2 // High res\n    });\n    \n    if (i > 0) {\n      pdf.addPage([page.width, page.height], page.width > page.height ? 'landscape' : 'portrait');\n    }\n    \n    pdf.addImage(dataUrl, 'JPEG', 0, 0, page.width, page.height);\n  }\n\n  staticCanvas.dispose();\n  pdf.save(`${fileName}.pdf`);\n};\n\nexport const exportProjectToPPTX = async (fileName: string = modeExportBasename('image')) => {\n  const store = useEditorStore.getState();\n  const pages = store.pages;\n  \n  if (pages.length === 0) return;\n\n  const pres = new pptxgen();\n  \n  // Create a hidden canvas element\n  const canvasEl = document.createElement('canvas');\n  const staticCanvas = new StaticCanvas(canvasEl, {\n    renderOnAddRemove: false,\n  });\n\n  for (let i = 0; i < pages.length; i++) {\n    const page = pages[i];\n    \n    // Setup PPTX slide layout based on page size (inches)\n    // 96 PPI is standard for web to inches conversion\n    const wInches = page.width / 96;\n    const hInches = page.height / 96;\n    \n    pres.defineLayout({ name: `Layout_Page_${i}`, width: wInches, height: hInches });\n    const slide = pres.addSlide({ masterName: `Layout_Page_${i}` });\n    \n    // Set dimensions\n    staticCanvas.setDimensions({ width: page.width, height: page.height });\n    \n    // Load JSON\n    await staticCanvas.loadFromJSON(page.json || {});\n    applyCanvasBackground(staticCanvas, page.backgroundColor, page.width, page.height);\n    staticCanvas.requestRenderAll();\n    \n    // Wait for render\n    await new Promise(r => setTimeout(r, 100));\n    \n    const dataUrl = staticCanvas.toDataURL({\n      format: 'png', // PNG for better color accuracy in PPTX\n      multiplier: 2\n    });\n    \n    slide.addImage({ data: dataUrl, x: 0, y: 0, w: wInches, h: hInches });\n  }\n\n  staticCanvas.dispose();\n  pres.writeFile({ fileName: `${fileName}.pptx` });\n};\n\nexport * from './advancedExportUtils';\n", "import React, { useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Clock, Download, Trash2, X } from 'lucide-react';\nimport { useEditorStore } from '../store/useEditorStore';\nimport { useDialog } from '../components/DialogModal';\nimport { useTranslation } from '../i18n';\nimport { modeAccentVars, useModeAccent } from '../theme/modeAccent';\nimport { TextBody, TextTitle } from './ui';\n\nexport const VersionHistoryModal: React.FC<{ onClose: () => void }> = ({ onClose }) => {\n  const mode = useModeAccent();\n  const dialog = useDialog();\n  const t = useTranslation();\n  const { projectVersions, loadVersion, deleteVersion, saveNamedVersion } = useEditorStore();\n  const [newVersionName, setNewVersionName] = useState('');\n\n  const handleSave = () => {\n    if (newVersionName.trim()) {\n      saveNamedVersion(newVersionName.trim());\n      setNewVersionName('');\n    }\n  };\n\n  return createPortal(\n    <div\n      className=\"fixed w-screen h-screen inset-0 left-0 z-[10000] bg-black/60 backdrop-blur-sm flex items-center justify-center\"\n      style={modeAccentVars(mode)}\n      data-we-mode={mode}\n    >\n      <div \n        className=\"w-full max-w-lg bg-dark-900 border border-dark-700 rounded-2xl shadow-[0_0_50px_rgba(0,0,0,0.5)] overflow-hidden flex flex-col max-h-[80vh]\"\n        onClick={(e) => e.stopPropagation()}\n      >\n        <div className=\"px-5 py-4 border-b border-dark-800 flex items-center justify-between\">\n          <div className=\"flex items-center gap-2\">\n            <Clock size={18} className=\"text-[var(--we-accent)]\" />\n            <TextTitle as=\"h2\" size=\"sm\">\n              {t.modal.versionHistory.title}\n            </TextTitle>\n          </div>\n          <button \n            onClick={onClose}\n            className=\"p-1.5 hover:bg-dark-800 rounded-lg text-dark-400 hover:text-white transition-colors\"\n          >\n            <X size={18} />\n          </button>\n        </div>\n\n        <div className=\"p-5 flex flex-col gap-4 border-b border-dark-800 bg-dark-950/30\">\n          <TextBody as=\"label\" size=\"sm\" className=\"font-bold text-dark-300 uppercase tracking-wider\">\n            {t.modal.versionHistory.saveCurrentVersion}\n          </TextBody>\n          <div className=\"flex gap-2\">\n            <input\n              type=\"text\"\n              placeholder={t.modal.versionHistory.placeholder}\n              value={newVersionName}\n              onChange={(e) => setNewVersionName(e.target.value)}\n              className=\"flex-1 bg-dark-900 border border-dark-700 rounded-lg px-3 py-2 font-sans text-sm font-medium text-white focus:outline-none focus:border-[var(--we-accent)] transition-colors\"\n            />\n            <button \n              onClick={handleSave}\n              disabled={!newVersionName.trim()}\n              className=\"px-4 py-2 bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] disabled:opacity-50 disabled:cursor-not-allowed text-white rounded-lg transition-colors\"\n            >\n              <TextBody as=\"span\" size=\"md\" className=\"font-bold text-white\">\n                {t.modal.versionHistory.save}\n              </TextBody>\n            </button>\n          </div>\n        </div>\n\n        <div className=\"flex-1 overflow-y-auto p-2\">\n          {projectVersions.length === 0 ? (\n            <TextBody as=\"p\" size=\"md\" className=\"py-10 text-center text-dark-400\">\n              {t.modal.versionHistory.noVersions}\n            </TextBody>\n          ) : (\n            <div className=\"flex flex-col gap-2 p-3\">\n              {projectVersions.map((v) => (\n                <div key={v.id} className=\"flex items-center justify-between p-3 bg-dark-850 hover:bg-dark-800 border border-dark-750 rounded-xl transition-colors group\">\n                  <div className=\"flex flex-col\">\n                    <TextBody as=\"span\" size=\"md\" className=\"font-bold text-white\">\n                      {v.name}\n                    </TextBody>\n                    <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 text-dark-400\">\n                      {new Date(v.timestamp).toLocaleString()} \u2022 {v.pages.length} {t.modal.versionHistory.pagesSuffix(v.pages.length)}\n                    </TextBody>\n                  </div>\n                  <div className=\"flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity\">\n                    <button\n                      onClick={async () => {\n                        const ok = await dialog.confirm(\n                          t.modal.versionHistory.loadConfirm,\n                          { title: t.modal.versionHistory.loadVersion, variant: 'warning', confirmText: t.modal.versionHistory.load, cancelText: t.common.cancel }\n                        );\n                        if (ok) { loadVersion(v.id); onClose(); }\n                      }}\n                      className=\"flex items-center gap-1.5 px-3 py-1.5 bg-dark-700 hover:bg-[var(--we-accent)] text-white rounded-lg transition-colors\"\n                    >\n                      <Download size={14} />\n                      <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-white\">\n                        {t.modal.versionHistory.restore}\n                      </TextBody>\n                    </button>\n                    <button\n                      onClick={async () => {\n                        const ok2 = await dialog.confirm(\n                          t.modal.versionHistory.deleteConfirm,\n                          { title: t.modal.versionHistory.deleteVersion, variant: 'danger', confirmText: t.modal.versionHistory.delete, cancelText: t.common.cancel }\n                        );\n                        if (ok2) deleteVersion(v.id);\n                      }}\n                      className=\"p-1.5 hover:bg-red-500/20 text-dark-400 hover:text-red-400 rounded-lg transition-colors\"\n                      title={t.modal.versionHistory.deleteVersion}\n                    >\n                      <Trash2 size={16} />\n                    </button>\n                  </div>\n                </div>\n              ))}\n            </div>\n          )}\n        </div>\n\n      </div>\n    </div>\n  , document.body);\n};\n", "/**\n * OS modifier key for shortcut labels (Ctrl on Windows/Linux, \u2318 on macOS).\n */\nexport function isApplePlatform(): boolean {\n  if (typeof navigator === 'undefined') return false;\n  const nav = navigator as Navigator & { userAgentData?: { platform?: string } };\n  const platform = (nav.userAgentData?.platform || navigator.platform || '').toUpperCase();\n  const ua = navigator.userAgent || '';\n  return platform.includes('MAC') || platform.includes('IPHONE') || platform.includes('IPAD') || /Mac OS X|iPhone|iPad/.test(ua);\n}\n\n/** Symbol/word for the primary shortcut modifier. */\nexport function modKeyLabel(): string {\n  return isApplePlatform() ? '\u2318' : 'Ctrl';\n}\n\n/** e.g. modShortcut('C') \u2192 \"\u2318C\" or \"Ctrl+C\" */\nexport function modShortcut(key: string): string {\n  const k = key.trim();\n  return isApplePlatform() ? `\u2318${k}` : `Ctrl+${k}`;\n}\n", "import React from 'react';\n\n/** Lucide `pencil-sparkles` \u2014 not yet in the package version pinned by this editor. */\nexport function PencilSparkles({\n  size = 24,\n  className,\n  strokeWidth = 2,\n  ...rest\n}: React.SVGProps<SVGSVGElement> & { size?: number | string }) {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width={size}\n      height={size}\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth={strokeWidth}\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      className={className}\n      aria-hidden\n      {...rest}\n    >\n      <path d=\"M10 3H8\" />\n      <path d=\"m15.007 5.008 3.987 3.986\" />\n      <path d=\"M20 15v4\" />\n      <path d=\"M21.174 6.813a2.82 2.82 0 0 0-3.986-3.987L3.842 16.175a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\" />\n      <path d=\"M22 17h-4\" />\n      <path d=\"M4 5v4\" />\n      <path d=\"M6 7H2\" />\n      <path d=\"M9 2v2\" />\n    </svg>\n  );\n}\n", "import type { Canvas, FabricObject, Point } from 'fabric';\n\ntype TransformOrigin = { x: string; y: string };\n\ntype LiveTransform = {\n  action?: string;\n  corner?: string;\n  originX: string;\n  originY: string;\n  altKey?: boolean;\n  target: FabricObject;\n  scaleX?: number;\n  scaleY?: number;\n  width?: number;\n  height?: number;\n  signX?: number;\n  signY?: number;\n  original?: Record<string, unknown> & TransformOrigin;\n  /** Opposite-corner origin captured at gesture start (for Alt toggle). */\n  _weCornerOrigin?: TransformOrigin;\n  /** Scene-space center frozen at mousedown for the whole resize gesture. */\n  _weFixedCenter?: { x: number; y: number };\n};\n\nconst CENTER_ACTIONS = new Set(['scale', 'scaleX', 'scaleY', 'resizing']);\n\nfunction getLiveTransform(canvas: Canvas): LiveTransform | null {\n  return ((canvas as unknown as { _currentTransform?: LiveTransform })._currentTransform ??\n    null) as LiveTransform | null;\n}\n\nfunction originFromCorner(corner: string): TransformOrigin {\n  const origin: TransformOrigin = { x: 'center', y: 'center' };\n  if (['ml', 'tl', 'bl'].includes(corner)) origin.x = 'right';\n  else if (['mr', 'tr', 'br'].includes(corner)) origin.x = 'left';\n  if (['tl', 'mt', 'tr'].includes(corner)) origin.y = 'bottom';\n  else if (['bl', 'mb', 'br'].includes(corner)) origin.y = 'top';\n  return origin;\n}\n\nfunction isCenteredOrigin(t: LiveTransform): boolean {\n  return t.originX === 'center' && t.originY === 'center';\n}\n\nfunction rebaselineTransform(t: LiveTransform, target: FabricObject): void {\n  t.scaleX = target.scaleX;\n  t.scaleY = target.scaleY;\n  t.width = target.width;\n  t.height = target.height;\n  delete t.signX;\n  delete t.signY;\n  if (t.original) {\n    t.original.scaleX = target.scaleX;\n    t.original.scaleY = target.scaleY;\n    t.original.left = target.left;\n    t.original.top = target.top;\n    t.original.width = target.width;\n    t.original.height = target.height;\n    t.original.originX = t.originX;\n    t.original.originY = t.originY;\n  }\n}\n\n/** Keep Fabric's live transform in sync after we mutate scale/size mid-gesture (e.g. snap). */\nexport function rebaselineLiveTransform(canvas: Canvas): void {\n  const t = getLiveTransform(canvas);\n  if (!t?.target) return;\n  rebaselineTransform(t, t.target);\n}\n\n/**\n * Capture opposite-corner origin AND the object's center at gesture start.\n * Shift/Alt pins to that initial center \u2014 never re-sampled mid-drag.\n */\nexport function captureTransformCornerOrigin(canvas: Canvas): void {\n  const t = getLiveTransform(canvas);\n  if (!t || !CENTER_ACTIONS.has(String(t.action || ''))) return;\n\n  const fromCanvas = (\n    canvas as unknown as {\n      _getOriginFromCorner?: (target: FabricObject, corner: string) => TransformOrigin;\n    }\n  )._getOriginFromCorner?.bind(canvas);\n\n  t._weCornerOrigin =\n    (t.corner && fromCanvas?.(t.target, t.corner)) ||\n    (t.corner ? originFromCorner(t.corner) : { x: 'left', y: 'top' });\n\n  // Freeze center at mousedown \u2014 toggling Alt must not adopt a drifted center.\n  if (!t._weFixedCenter) {\n    const target = t.target as FabricObject & { getCenterPoint: () => Point };\n    const c = target.getCenterPoint();\n    t._weFixedCenter = { x: c.x, y: c.y };\n  }\n}\n\n/**\n * While scaling/resizing, Shift/Alt locks the object's center to the gesture-start\n * center. Releasing only switches the anchor mode \u2014 it does not adopt a\n * new base from the live position (that caused jumps when toggling mid-scale).\n */\nexport function syncTransformCenteredOrigin(\n  canvas: Canvas,\n  wantCentered: boolean,\n): boolean {\n  const t = getLiveTransform(canvas);\n  if (!t || !CENTER_ACTIONS.has(String(t.action || ''))) return false;\n\n  const target = t.target as FabricObject & {\n    getCenterPoint: () => Point;\n    getPositionByOrigin: (ox: string, oy: string) => Point;\n    setPositionByOrigin: (pos: Point, ox: string, oy: string) => void;\n  };\n\n  // Ensure gesture-start center exists even if capture ran before the object settled.\n  if (!t._weFixedCenter) {\n    const c = target.getCenterPoint();\n    t._weFixedCenter = { x: c.x, y: c.y };\n  }\n\n  if (wantCentered) {\n    const wasCentered = isCenteredOrigin(t) && t.altKey;\n    const fixed = t._weFixedCenter;\n    t.originX = 'center';\n    t.originY = 'center';\n    t.altKey = true;\n    // Neutralize sign so scaleObject won't invert center \u2192 left.\n    t.signX = 1;\n    t.signY = 1;\n    target.setPositionByOrigin(fixed as Point, 'center', 'center');\n    if (!wasCentered) rebaselineTransform(t, target);\n    target.setCoords();\n    return !wasCentered;\n  }\n\n  // Leaving Alt: keep the object where it is; only change future scale anchor.\n  if (!t.altKey && !isCenteredOrigin(t)) {\n    return false;\n  }\n\n  const cornerOrigin = t._weCornerOrigin || originFromCorner(t.corner || '');\n  t.originX = cornerOrigin.x;\n  t.originY = cornerOrigin.y;\n  t.altKey = false;\n  // Do not rewrite left/top from a freshly measured center \u2014 that drifts the base.\n  rebaselineTransform(t, target);\n  target.setCoords();\n  return true;\n}\n\nexport type CtrlDragDuplicateSession = {\n  target: FabricObject;\n  startLeft: number;\n  startTop: number;\n  moved: boolean;\n  /** Ctrl/Cmd currently held. */\n  ctrlHeld: boolean;\n  /** Ghost clone parked at the drag-start position (preview). */\n  ghost: FabricObject | null;\n  ghostPending: boolean;\n};\n\nexport function beginCtrlDragSession(\n  target: FabricObject,\n  ctrlHeld: boolean,\n): CtrlDragDuplicateSession {\n  return {\n    target,\n    startLeft: target.left ?? 0,\n    startTop: target.top ?? 0,\n    moved: false,\n    ctrlHeld,\n    ghost: null,\n    ghostPending: false,\n  };\n}\n\nfunction newObjectId(): string {\n  return `obj-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n}\n\n/** Remove the preview ghost (Ctrl released \u2192 cancel duplicate). */\nexport function cancelCtrlDragGhost(\n  canvas: Canvas,\n  session: CtrlDragDuplicateSession | null,\n): void {\n  if (!session?.ghost) return;\n  canvas.remove(session.ghost);\n  session.ghost = null;\n  session.ghostPending = false;\n  canvas.requestRenderAll();\n}\n\n/**\n * While Ctrl is held during a drag: park a same-looking clone at the\n * drag-start position; the live object keeps following the pointer.\n */\nexport async function ensureCtrlDragGhost(\n  canvas: Canvas,\n  session: CtrlDragDuplicateSession,\n  customProps: string[],\n): Promise<void> {\n  if (!session.ctrlHeld || session.ghost || session.ghostPending) return;\n  if (!canvas.getObjects().includes(session.target)) return;\n\n  session.ghostPending = true;\n  try {\n    const cloned = await session.target.clone(customProps);\n    // Ctrl may have been released while clone was building.\n    if (!session.ctrlHeld || session.ghost) {\n      session.ghostPending = false;\n      return;\n    }\n\n    cloned.set({\n      left: session.startLeft,\n      top: session.startTop,\n      evented: false,\n      selectable: false,\n    });\n    (cloned as FabricObject & { _weDupGhost?: boolean; id?: string })._weDupGhost = true;\n    (cloned as FabricObject & { id?: string }).id = newObjectId();\n\n    const type = (cloned.type || '').toLowerCase();\n    if (type === 'activeselection') {\n      // Flatten selection ghosts into individual parked objects is messy;\n      // park the selection group itself as a non-interactive preview.\n      (cloned as FabricObject & { canvas?: Canvas }).canvas = canvas;\n    }\n\n    canvas.add(cloned);\n    const idx = canvas.getObjects().indexOf(session.target);\n    if (idx > 0 && typeof (canvas as Canvas & { moveObjectTo?: (o: FabricObject, i: number) => void }).moveObjectTo === 'function') {\n      (canvas as Canvas & { moveObjectTo: (o: FabricObject, i: number) => void }).moveObjectTo(\n        cloned,\n        Math.max(0, idx),\n      );\n    }\n\n    session.ghost = cloned;\n    canvas.requestRenderAll();\n  } finally {\n    session.ghostPending = false;\n  }\n}\n\n/**\n * Mouseup while a ghost exists \u2192 promote ghost to a real object.\n * Returns the object that should stay selected (the one under the cursor).\n */\nexport function commitCtrlDragGhost(\n  canvas: Canvas,\n  session: CtrlDragDuplicateSession,\n): FabricObject | null {\n  const ghost = session.ghost;\n  if (!ghost) return null;\n\n  ghost.set({\n    evented: true,\n    selectable: true,\n  });\n  delete (ghost as FabricObject & { _weDupGhost?: boolean })._weDupGhost;\n\n  const type = (ghost.type || '').toLowerCase();\n  if (type === 'activeselection') {\n    const group = ghost as FabricObject & {\n      forEachObject: (cb: (o: FabricObject) => void) => void;\n      canvas?: Canvas;\n    };\n    group.canvas = canvas;\n    const kids: FabricObject[] = [];\n    group.forEachObject((obj) => {\n      (obj as FabricObject & { id?: string }).id = newObjectId();\n      obj.set({ evented: true, selectable: true });\n      kids.push(obj);\n    });\n    canvas.remove(ghost);\n    kids.forEach((obj) => canvas.add(obj));\n  }\n\n  session.ghost = null;\n  session.ghostPending = false;\n  // Keep the dragged original selected (follows cursor \u2192 drop position).\n  canvas.setActiveObject(session.target);\n  canvas.requestRenderAll();\n  return session.target;\n}\n", "import { FabricImage, Point, Rect, type Canvas } from 'fabric';\nimport {\n  getOpaqueBounds,\n  ensurePixelLayerCanvas,\n  isPixelLayer,\n  asPixelLayer,\n  refreshPixelLayerDisplay,\n  refreshPixelLayerContentBounds,\n  syncPixelLayerInteraction,\n  type PixelLayerImage,\n} from './pixelLayer';\n\nconst MIN_CROP_PX = 24;\n\nexport type CropOverlayRect = Rect & {\n  isImageCropOverlay?: boolean;\n  /** Id of the Fabric image being cropped (for DOM chrome clamp). */\n  weCropImageId?: string;\n};\n\nexport function isCropEligibleImage(obj: unknown): obj is FabricImage {\n  if (!obj || typeof obj !== 'object') return false;\n  return (obj as FabricImage).type === 'image';\n}\n\n/** Crop is allowed on any selected image (including the sole layer). */\nexport function canUseImageCropTool(\n  obj: unknown,\n  _canvas?: Canvas | null | undefined,\n): obj is FabricImage {\n  return isCropEligibleImage(obj);\n}\n\nfunction isCropOverlayObject(obj: unknown): obj is CropOverlayRect {\n  return Boolean(obj && typeof obj === 'object' && (obj as CropOverlayRect).isImageCropOverlay);\n}\n\nasync function loadImageSource(src: string): Promise<HTMLImageElement> {\n  return new Promise((resolve, reject) => {\n    const el = new Image();\n    el.crossOrigin = 'anonymous';\n    el.onload = () => resolve(el);\n    el.onerror = () => reject(new Error('Could not load image source'));\n    el.src = src;\n  });\n}\n\n/** Drawable raster + its pixel size (prefer canvas element \u2014 no toDataURL roundtrip). */\nasync function resolveRasterDrawable(\n  img: FabricImage,\n): Promise<{ source: CanvasImageSource; sourceW: number; sourceH: number }> {\n  if (isPixelLayer(img)) {\n    const el = ensurePixelLayerCanvas(img as PixelLayerImage);\n    return { source: el, sourceW: el.width, sourceH: el.height };\n  }\n\n  const element = img.getElement();\n  if (element instanceof HTMLCanvasElement && element.width > 0 && element.height > 0) {\n    return { source: element, sourceW: element.width, sourceH: element.height };\n  }\n\n  if (element instanceof HTMLImageElement && element.complete && element.naturalWidth > 0) {\n    return {\n      source: element,\n      sourceW: element.naturalWidth,\n      sourceH: element.naturalHeight,\n    };\n  }\n\n  const src = typeof img.getSrc === 'function' ? img.getSrc(true) : '';\n  if (src) {\n    const loaded = await loadImageSource(src);\n    return {\n      source: loaded,\n      sourceW: loaded.naturalWidth,\n      sourceH: loaded.naturalHeight,\n    };\n  }\n\n  throw new Error('Invalid image element');\n}\n\nexport function applyCropModeObjectSettings(\n  canvas: Canvas,\n  cropRect: CropOverlayRect | null,\n  targetImg: FabricImage | null,\n): void {\n  canvas.getObjects().forEach((obj) => {\n    if (cropRect && obj === cropRect) {\n      // Fabric handles stay off \u2014 SelectionControlsOverlay draws edge chrome\n      // outside the artboard clip so crop stays editable at page edges.\n      cropRect.set({\n        selectable: true,\n        evented: true,\n        hasControls: false,\n        hasBorders: false,\n        lockRotation: true,\n        lockScalingFlip: true,\n        lockMovementX: false,\n        lockMovementY: false,\n        borderColor: 'transparent',\n        cornerColor: 'transparent',\n        cornerStrokeColor: 'transparent',\n        stroke: '#3b82f6',\n        strokeDashArray: [6, 4],\n      });\n      cropRect.setControlsVisibility({\n        mt: false,\n        mb: false,\n        ml: false,\n        mr: false,\n        tl: false,\n        tr: false,\n        bl: false,\n        br: false,\n        mtr: false,\n      });\n      return;\n    }\n\n    if (targetImg && obj === targetImg) return;\n\n    if (!isCropOverlayObject(obj)) {\n      obj.set({\n        selectable: false,\n        evented: false,\n        hasControls: false,\n      });\n    }\n  });\n\n  canvas.selection = false;\n  canvas.skipTargetFind = false;\n  canvas.defaultCursor = 'default';\n  canvas.hoverCursor = 'default';\n  canvas.requestRenderAll();\n}\n\n/**\n * Display (scene) size of the cropable content.\n * Uses abs(scale) for dimensions so flipped layers still get a positive frame.\n */\nfunction imageDisplaySize(img: FabricImage): {\n  w: number;\n  h: number;\n  offsetX: number;\n  offsetY: number;\n} {\n  const sx = img.scaleX ?? 1;\n  const sy = img.scaleY ?? 1;\n  const absSx = Math.abs(sx) || 1;\n  const absSy = Math.abs(sy) || 1;\n\n  // Pixel layers are page-sized; crop chrome should hug opaque content.\n  if (isPixelLayer(img)) {\n    const layer = img as PixelLayerImage;\n    const el = ensurePixelLayerCanvas(layer);\n    const bounds = layer.weOpaqueBounds ?? getOpaqueBounds(el);\n    if (bounds) {\n      layer.weOpaqueBounds = bounds;\n      return {\n        w: bounds.w * absSx,\n        h: bounds.h * absSy,\n        offsetX: (bounds.x + bounds.w / 2 - el.width / 2) * sx,\n        offsetY: (bounds.y + bounds.h / 2 - el.height / 2) * sy,\n      };\n    }\n  }\n  return {\n    w: (img.width ?? 0) * absSx,\n    h: (img.height ?? 0) * absSy,\n    offsetX: 0,\n    offsetY: 0,\n  };\n}\n\nfunction contentCenterInScene(img: FabricImage): Point {\n  const imgAngle = img.angle ?? 0;\n  const { offsetX, offsetY } = imageDisplaySize(img);\n  const imgCenter = img.getCenterPoint();\n  const radA = (imgAngle * Math.PI) / 180;\n  return new Point(\n    imgCenter.x + offsetX * Math.cos(radA) - offsetY * Math.sin(radA),\n    imgCenter.y + offsetX * Math.sin(radA) + offsetY * Math.cos(radA),\n  );\n}\n\n/** Full-size crop frame aligned to the image \u2014 same center, angle and display size. */\nexport function createImageCropRect(img: FabricImage, canvasZoom: number): CropOverlayRect {\n  const strokeW = 2 / (canvasZoom || 1);\n  const { w, h } = imageDisplaySize(img);\n  const angle = img.angle ?? 0;\n  const center = contentCenterInScene(img);\n\n  const rect = new Rect({\n    left: center.x,\n    top: center.y,\n    originX: 'center',\n    originY: 'center',\n    width: Math.max(MIN_CROP_PX, w),\n    height: Math.max(MIN_CROP_PX, h),\n    scaleX: 1,\n    scaleY: 1,\n    angle,\n    fill: 'rgba(59, 130, 246, 0.32)',\n    stroke: '#3b82f6',\n    strokeWidth: strokeW,\n    strokeUniform: true,\n    strokeDashArray: [6, 4],\n    cornerColor: 'transparent',\n    cornerStrokeColor: 'transparent',\n    cornerSize: 10,\n    transparentCorners: false,\n    borderColor: 'transparent',\n    hasBorders: false,\n    hasControls: false,\n    lockRotation: true,\n    lockScalingFlip: true,\n    lockMovementX: false,\n    lockMovementY: false,\n    selectable: true,\n    evented: true,\n    objectCaching: false,\n  }) as CropOverlayRect;\n\n  rect.setControlsVisibility({\n    mt: false,\n    mb: false,\n    ml: false,\n    mr: false,\n    tl: false,\n    tr: false,\n    bl: false,\n    br: false,\n    mtr: false,\n  });\n\n  rect.isImageCropOverlay = true;\n  rect.hasControls = false;\n  rect.hasBorders = false;\n  return rect;\n}\n\nexport type ClampCropOptions = {\n  /**\n   * When true (default), bake scaleX/Y into width/height.\n   * During live `scaling` gestures set false so Fabric controls are not fought.\n   */\n  normalizeScale?: boolean;\n};\n\n/**\n * Keeps the crop box inside the image \u2014 uses image-local axes so it works\n * while dragging edge handles (same angle as the image).\n */\nexport function clampCropRectToImage(\n  cropRect: Rect,\n  img: FabricImage,\n  opts?: ClampCropOptions,\n): void {\n  const normalizeScale = opts?.normalizeScale !== false;\n  const imgAngle = img.angle ?? 0;\n  const { w: maxW, h: maxH } = imageDisplaySize(img);\n  if (maxW <= MIN_CROP_PX || maxH <= MIN_CROP_PX) return;\n\n  let cropW = (cropRect.width ?? 0) * (cropRect.scaleX ?? 1);\n  let cropH = (cropRect.height ?? 0) * (cropRect.scaleY ?? 1);\n  cropW = Math.max(MIN_CROP_PX, Math.min(cropW, maxW));\n  cropH = Math.max(MIN_CROP_PX, Math.min(cropH, maxH));\n\n  const contentCenter = contentCenterInScene(img);\n  // Read center BEFORE mutating origin/scale \u2014 mid-gesture Fabric may use a temporary origin.\n  const cropCenter = cropRect.getCenterPoint();\n  const rad = (-imgAngle * Math.PI) / 180;\n\n  const dx = cropCenter.x - contentCenter.x;\n  const dy = cropCenter.y - contentCenter.y;\n  let localCx = dx * Math.cos(rad) - dy * Math.sin(rad);\n  let localCy = dx * Math.sin(rad) + dy * Math.cos(rad);\n\n  const halfMaxW = maxW / 2;\n  const halfMaxH = maxH / 2;\n  const halfCropW = cropW / 2;\n  const halfCropH = cropH / 2;\n\n  localCx = Math.max(-halfMaxW + halfCropW, Math.min(halfMaxW - halfCropW, localCx));\n  localCy = Math.max(-halfMaxH + halfCropH, Math.min(halfMaxH - halfCropH, localCy));\n\n  const radFwd = (imgAngle * Math.PI) / 180;\n  const newCenter = new Point(\n    contentCenter.x + localCx * Math.cos(radFwd) - localCy * Math.sin(radFwd),\n    contentCenter.y + localCx * Math.sin(radFwd) + localCy * Math.cos(radFwd),\n  );\n\n  if (normalizeScale) {\n    cropRect.set({\n      originX: 'center',\n      originY: 'center',\n      width: cropW,\n      height: cropH,\n      scaleX: 1,\n      scaleY: 1,\n      angle: imgAngle,\n    });\n    cropRect.setPositionByOrigin(newCenter, 'center', 'center');\n  } else {\n    // Live gesture: nudge center only \u2014 do not bake scale into width (that fights Fabric handles).\n    const maxScaleX = maxW / Math.max(1e-6, cropRect.width ?? 1);\n    const maxScaleY = maxH / Math.max(1e-6, cropRect.height ?? 1);\n    const nextScaleX = Math.min(Math.abs(cropRect.scaleX ?? 1), maxScaleX);\n    const nextScaleY = Math.min(Math.abs(cropRect.scaleY ?? 1), maxScaleY);\n    cropRect.set({\n      scaleX: nextScaleX,\n      scaleY: nextScaleY,\n      angle: imgAngle,\n    });\n    cropRect.setPositionByOrigin(\n      newCenter,\n      (cropRect.originX as 'left' | 'center' | 'right') || 'center',\n      (cropRect.originY as 'top' | 'center' | 'bottom') || 'center',\n    );\n  }\n  cropRect.setCoords();\n}\n\n/**\n * Map the crop overlay (scene / display space) \u2192 source pixel rect.\n * Same scale-aware math as the clamp UI \u2014 avoids Fabric matrix/origin drift.\n */\nfunction cropRectToSourcePixels(\n  img: FabricImage,\n  cropRect: Rect,\n  sourceW: number,\n  sourceH: number,\n): { sx: number; sy: number; sw: number; sh: number; outCenter: Point } {\n  const scaleX = img.scaleX ?? 1;\n  const scaleY = img.scaleY ?? 1;\n  const absSx = Math.abs(scaleX) || 1;\n  const absSy = Math.abs(scaleY) || 1;\n  const imgAngle = img.angle ?? 0;\n\n  const contentCenter = contentCenterInScene(img);\n  const cropW = Math.max(1, (cropRect.width ?? 0) * (cropRect.scaleX ?? 1));\n  const cropH = Math.max(1, (cropRect.height ?? 0) * (cropRect.scaleY ?? 1));\n  const outCenter = cropRect.getCenterPoint();\n\n  const rad = (-imgAngle * Math.PI) / 180;\n  const dx = outCenter.x - contentCenter.x;\n  const dy = outCenter.y - contentCenter.y;\n  const localCx = dx * Math.cos(rad) - dy * Math.sin(rad);\n  const localCy = dx * Math.sin(rad) + dy * Math.cos(rad);\n\n  // Display offset \u2192 unscaled buffer/object pixels (signed scale handles flip).\n  const sw = cropW / absSx;\n  const sh = cropH / absSy;\n\n  let srcCx: number;\n  let srcCy: number;\n\n  if (isPixelLayer(img)) {\n    const layer = img as PixelLayerImage;\n    const el = ensurePixelLayerCanvas(layer);\n    const bounds =\n      layer.weOpaqueBounds ??\n      getOpaqueBounds(el) ?? { x: 0, y: 0, w: el.width, h: el.height };\n    srcCx = bounds.x + bounds.w / 2 + localCx / scaleX;\n    srcCy = bounds.y + bounds.h / 2 + localCy / scaleY;\n  } else {\n    const objW = img.width ?? sourceW;\n    const objH = img.height ?? sourceH;\n    const cropX = img.cropX ?? 0;\n    const cropY = img.cropY ?? 0;\n    // Object pixel space (0..width) may differ from natural source \u2014 callers scale.\n    srcCx = cropX + objW / 2 + localCx / scaleX;\n    srcCy = cropY + objH / 2 + localCy / scaleY;\n  }\n\n  return {\n    sx: srcCx - sw / 2,\n    sy: srcCy - sh / 2,\n    sw,\n    sh,\n    outCenter,\n  };\n}\n\nexport async function bakeImageCrop(\n  canvas: Canvas,\n  img: FabricImage,\n  cropRect: Rect,\n): Promise<FabricImage> {\n  // Finalize overlay geometry (bake scale into width) before reading.\n  clampCropRectToImage(cropRect, img, { normalizeScale: true });\n  cropRect.setCoords();\n  img.setCoords();\n\n  const { source, sourceW, sourceH } = await resolveRasterDrawable(img);\n  const wasPixel = isPixelLayer(img);\n\n  const objW = wasPixel\n    ? sourceW\n    : Math.max(1, img.width ?? sourceW);\n  const objH = wasPixel\n    ? sourceH\n    : Math.max(1, img.height ?? sourceH);\n\n  const { sx, sy, sw, sh, outCenter } = cropRectToSourcePixels(\n    img,\n    cropRect,\n    sourceW,\n    sourceH,\n  );\n\n  // Object-space \u2192 natural source pixels (no-op for pixel-layer canvases).\n  const scaleToSourceX = sourceW / objW;\n  const scaleToSourceY = sourceH / objH;\n\n  let srcX = sx * scaleToSourceX;\n  let srcY = sy * scaleToSourceY;\n  let srcW = sw * scaleToSourceX;\n  let srcH = sh * scaleToSourceY;\n\n  // Clamp to drawable bounds\n  if (srcX < 0) {\n    srcW += srcX;\n    srcX = 0;\n  }\n  if (srcY < 0) {\n    srcH += srcY;\n    srcY = 0;\n  }\n  if (srcX + srcW > sourceW) srcW = sourceW - srcX;\n  if (srcY + srcH > sourceH) srcH = sourceH - srcY;\n\n  srcW = Math.max(1, srcW);\n  srcH = Math.max(1, srcH);\n\n  const outCanvas = document.createElement('canvas');\n  outCanvas.width = Math.max(1, Math.round(srcW));\n  outCanvas.height = Math.max(1, Math.round(srcH));\n  const ctx = outCanvas.getContext('2d');\n  if (!ctx) throw new Error('Could not create crop canvas');\n\n  ctx.drawImage(\n    source,\n    Math.round(srcX),\n    Math.round(srcY),\n    Math.round(srcW),\n    Math.round(srcH),\n    0,\n    0,\n    outCanvas.width,\n    outCanvas.height,\n  );\n\n  const scaleX = img.scaleX ?? 1;\n  const scaleY = img.scaleY ?? 1;\n  const angle = img.angle ?? 0;\n  const imgName = (img as FabricImage & { name?: string }).name;\n\n  const dataUrl = outCanvas.toDataURL('image/png');\n  const newImg = await FabricImage.fromURL(dataUrl, { crossOrigin: 'anonymous' });\n  newImg.set({\n    left: outCenter.x,\n    top: outCenter.y,\n    originX: 'center',\n    originY: 'center',\n    // Keep the same visual scale the user had \u2014 bitmap is unscaled crop pixels.\n    scaleX,\n    scaleY,\n    angle,\n    opacity: 1,\n    selectable: true,\n    evented: true,\n    clipPath: undefined,\n    cropX: 0,\n    cropY: 0,\n    borderColor: '#3b82f6',\n    cornerColor: '#ffffff',\n    cornerStrokeColor: '#3b82f6',\n  });\n  if (imgName) (newImg as FabricImage & { name?: string }).name = imgName;\n\n  if (wasPixel) {\n    const layer = asPixelLayer(newImg);\n    refreshPixelLayerDisplay(layer);\n    refreshPixelLayerContentBounds(layer);\n    syncPixelLayerInteraction(layer);\n  }\n\n  const index = canvas.getObjects().indexOf(img);\n  canvas.remove(img);\n  if (index >= 0) canvas.insertAt(index, newImg);\n  else canvas.add(newImg);\n\n  return newImg;\n}\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { Check, X } from 'lucide-react';\nimport { type FabricImage } from 'fabric';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { useTranslation } from '../../i18n';\nimport {\n  applyCropModeObjectSettings,\n  bakeImageCrop,\n  clampCropRectToImage,\n  createImageCropRect,\n  canUseImageCropTool,\n  type CropOverlayRect,\n} from '../../utils/imageCrop';\nimport { getVisualZoom } from '../../utils/canvasZoomRender';\nimport { TextBody } from '../ui';\n\ntype ImageBorderSnapshot = {\n  borderColor?: string;\n  cornerColor?: string;\n  cornerStrokeColor?: string;\n  opacity?: number;\n  selectable?: boolean;\n  evented?: boolean;\n};\n\nexport const CropOverlay: React.FC = () => {\n  const t = useTranslation();\n  const {\n    activeTool,\n    setActiveTool,\n    canvasInstance,\n    saveHistoryState,\n    setActiveObject,\n    syncLayers,\n    pauseHistory,\n    resumeHistory,\n  } = useEditorStore();\n\n  const [cropRect, setCropRect] = useState<CropOverlayRect | null>(null);\n  const targetImgRef = useRef<FabricImage | null>(null);\n  const borderSnapshotRef = useRef<ImageBorderSnapshot | null>(null);\n  const historyPausedRef = useRef(false);\n  const [errorMsg, setErrorMsg] = useState<string | null>(null);\n  const [isApplying, setIsApplying] = useState(false);\n\n  const pauseCropHistory = () => {\n    if (historyPausedRef.current) return;\n    pauseHistory();\n    historyPausedRef.current = true;\n  };\n\n  const resumeCropHistory = () => {\n    if (!historyPausedRef.current) return;\n    resumeHistory();\n    historyPausedRef.current = false;\n  };\n\n  const teardownCrop = (restoreImage = true) => {\n    const canvas = canvasInstance;\n    const img = targetImgRef.current;\n    if (restoreImage && img && canvas?.getObjects().includes(img)) {\n      const snap = borderSnapshotRef.current;\n      if (snap) {\n        img.set({\n          borderColor: snap.borderColor,\n          cornerColor: snap.cornerColor,\n          cornerStrokeColor: snap.cornerStrokeColor,\n          opacity: snap.opacity ?? 1,\n          selectable: snap.selectable ?? true,\n          evented: snap.evented ?? true,\n        });\n      } else {\n        img.set({ opacity: 1, selectable: true, evented: true });\n      }\n    }\n    if (cropRect && canvas) {\n      canvas.remove(cropRect);\n    }\n    setCropRect(null);\n    targetImgRef.current = null;\n    borderSnapshotRef.current = null;\n    canvas?.requestRenderAll();\n  };\n\n  useEffect(() => {\n    if (activeTool !== 'crop' || !canvasInstance) {\n      if (cropRect || targetImgRef.current) teardownCrop(true);\n      resumeCropHistory();\n      return;\n    }\n\n    if (cropRect) return;\n\n    try {\n      const currentActive = canvasInstance.getActiveObject();\n      if (!canUseImageCropTool(currentActive, canvasInstance)) {\n        setActiveTool('select');\n        return;\n      }\n\n      const img = currentActive;\n      targetImgRef.current = img;\n\n      borderSnapshotRef.current = {\n        borderColor: img.borderColor as string | undefined,\n        cornerColor: img.cornerColor as string | undefined,\n        cornerStrokeColor: img.cornerStrokeColor as string | undefined,\n        opacity: img.opacity,\n        selectable: img.selectable,\n        evented: img.evented,\n      };\n\n      // Pause before adding chrome so undo only sees before \u2192 after apply.\n      pauseCropHistory();\n\n      img.set({\n        opacity: 0.5,\n        borderColor: '#ffffff',\n        cornerColor: '#ffffff',\n        cornerStrokeColor: '#ffffff',\n        selectable: false,\n        evented: false,\n      });\n\n      const rect = createImageCropRect(img, getVisualZoom(canvasInstance));\n      let imgId = (img as FabricImage & { id?: string }).id;\n      if (!imgId) {\n        imgId = `obj-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n        img.set('id', imgId);\n      }\n      rect.weCropImageId = imgId;\n      rect.setCoords();\n      canvasInstance.add(rect);\n      canvasInstance.bringObjectToFront(rect);\n      applyCropModeObjectSettings(canvasInstance, rect, img);\n      canvasInstance.setActiveObject(rect);\n      canvasInstance.requestRenderAll();\n      setCropRect(rect);\n      setErrorMsg(null);\n    } catch (err: unknown) {\n      console.error('CROP ERROR', err);\n      setErrorMsg(err instanceof Error ? err.message : String(err));\n      teardownCrop(true);\n      resumeCropHistory();\n      setActiveTool('select');\n    }\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- cropRect lifecycle is intentional\n  }, [activeTool, canvasInstance, cropRect, setActiveTool]);\n\n  useEffect(() => {\n    if (!canvasInstance || !cropRect || activeTool !== 'crop') return;\n\n    const keepCropRectActive = () => {\n      if (canvasInstance.getActiveObject() !== cropRect) {\n        canvasInstance.setActiveObject(cropRect);\n        applyCropModeObjectSettings(canvasInstance, cropRect, targetImgRef.current);\n      }\n    };\n\n    canvasInstance.on('selection:created', keepCropRectActive);\n    canvasInstance.on('selection:updated', keepCropRectActive);\n    canvasInstance.on('selection:cleared', keepCropRectActive);\n\n    return () => {\n      canvasInstance.off('selection:created', keepCropRectActive);\n      canvasInstance.off('selection:updated', keepCropRectActive);\n      canvasInstance.off('selection:cleared', keepCropRectActive);\n    };\n  }, [canvasInstance, cropRect, activeTool]);\n\n  useEffect(() => {\n    if (!canvasInstance || !cropRect || !targetImgRef.current) return;\n\n    const img = targetImgRef.current;\n    const onLiveTransform = () => {\n      clampCropRectToImage(cropRect, img, { normalizeScale: false });\n      canvasInstance.requestRenderAll();\n    };\n    const onModified = () => {\n      clampCropRectToImage(cropRect, img, { normalizeScale: true });\n      canvasInstance.requestRenderAll();\n    };\n\n    cropRect.on('moving', onLiveTransform);\n    cropRect.on('scaling', onLiveTransform);\n    cropRect.on('modified', onModified);\n\n    return () => {\n      cropRect.off('moving', onLiveTransform);\n      cropRect.off('scaling', onLiveTransform);\n      cropRect.off('modified', onModified);\n    };\n  }, [canvasInstance, cropRect]);\n\n  // Always resume if the component unmounts mid-crop.\n  useEffect(() => () => resumeCropHistory(), []);\n\n  const applyCrop = async () => {\n    if (!canvasInstance || !targetImgRef.current || !cropRect || isApplying) return;\n    setIsApplying(true);\n    try {\n      const img = targetImgRef.current;\n      clampCropRectToImage(cropRect, img, { normalizeScale: true });\n      const newImg = await bakeImageCrop(canvasInstance, img, cropRect);\n\n      canvasInstance.remove(cropRect);\n      setCropRect(null);\n      targetImgRef.current = null;\n      borderSnapshotRef.current = null;\n\n      canvasInstance.setActiveObject(newImg);\n      setActiveObject(newImg);\n      syncLayers();\n      setActiveTool('select');\n      canvasInstance.requestRenderAll();\n\n      // One undo step: pre-crop \u2192 post-crop.\n      resumeCropHistory();\n      saveHistoryState();\n    } catch (err: unknown) {\n      console.error('Apply crop failed', err);\n      setErrorMsg(err instanceof Error ? err.message : String(err));\n      resumeCropHistory();\n    } finally {\n      setIsApplying(false);\n    }\n  };\n\n  const cancelCrop = () => {\n    const img = targetImgRef.current;\n    const canvas = canvasInstance;\n    teardownCrop(true);\n    resumeCropHistory();\n    setActiveTool('select');\n    if (img && canvas?.getObjects().includes(img)) {\n      canvas.setActiveObject(img);\n      setActiveObject(img);\n    }\n  };\n\n  if (errorMsg) {\n    return (\n      <div className=\"absolute bottom-20 left-1/2 z-50 -translate-x-1/2 rounded-xl bg-red-500 p-4 text-white shadow-xl\">\n        <TextBody as=\"span\" size=\"sm\" className=\"text-white\">\n          {t.crop.errorPrefix}: {errorMsg}\n        </TextBody>\n        <button\n          type=\"button\"\n          className=\"ml-4 rounded bg-white/20 px-2 py-1\"\n          onClick={() => {\n            setErrorMsg(null);\n            resumeCropHistory();\n            setActiveTool('select');\n          }}\n        >\n          <TextBody as=\"span\" size=\"sm\" className=\"text-white\">{t.crop.closeError}</TextBody>\n        </button>\n      </div>\n    );\n  }\n\n  if (activeTool !== 'crop' || !cropRect) return null;\n\n  return (\n    <div className=\"absolute bottom-2 left-1/2 -translate-x-1/2 z-50 flex items-center gap-2 bg-[#13131A]/95 backdrop-blur-md border border-panel-border px-3 py-2 rounded-xl shadow-2xl pointer-events-auto animate-fade-in\">\n      <TextBody as=\"span\" size=\"sm\" className=\"text-[#F0F0F5] pr-2 border-r border-panel-border whitespace-nowrap\">\n        {t.crop.activeTitle}\n      </TextBody>\n      <button\n        type=\"button\"\n        onClick={cancelCrop}\n        disabled={isApplying}\n        className=\"flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-red-300 transition-colors hover:bg-red-500/15 disabled:opacity-50\"\n        title={t.crop.cancelTooltip}\n      >\n        <X size={14} />\n        <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-red-300\">{t.crop.cancelLabel}</TextBody>\n      </button>\n      <button\n        type=\"button\"\n        onClick={() => void applyCrop()}\n        disabled={isApplying}\n        className=\"flex items-center gap-1.5 rounded-lg bg-[var(--we-accent)] px-3 py-1.5 text-white transition-colors hover:bg-[var(--we-accent-hover)] disabled:opacity-50\"\n        title={t.crop.applyTooltip}\n      >\n        <Check size={14} />\n        <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-white\">{t.crop.applyLabel}</TextBody>\n      </button>\n    </div>\n  );\n};\n", "import React, { useEffect, useRef } from 'react';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { Circle, Line, Path } from 'fabric';\nimport { useTranslation } from '../../i18n';\nimport { TextBody } from '../ui';\n\nexport const PenToolOverlay: React.FC = () => {\n  const t = useTranslation();\n  const { activeTool, canvasInstance, setActiveTool, saveHistoryState, syncLayers } = useEditorStore();\n  \n  const nodesRef = useRef<{ x: number, y: number }[]>([]);\n  const circlesRef = useRef<Circle[]>([]);\n  const linesRef = useRef<Line[]>([]);\n  const tempLineRef = useRef<Line | null>(null);\n\n  useEffect(() => {\n    if (!canvasInstance) return;\n\n    const clearPreview = () => {\n      circlesRef.current.forEach(c => canvasInstance.remove(c));\n      linesRef.current.forEach(l => canvasInstance.remove(l));\n      if (tempLineRef.current) canvasInstance.remove(tempLineRef.current);\n      circlesRef.current = [];\n      linesRef.current = [];\n      tempLineRef.current = null;\n      nodesRef.current = [];\n      canvasInstance.requestRenderAll();\n    };\n\n    const finishPath = () => {\n      const nodes = nodesRef.current;\n      if (nodes.length > 1) {\n        // Build path string\n        let pathStr = `M ${nodes[0].x} ${nodes[0].y}`;\n        let isClosed = false;\n        \n        for (let i = 1; i < nodes.length; i++) {\n          if (i === nodes.length - 1 && nodes[i].x === nodes[0].x && nodes[i].y === nodes[0].y) {\n            pathStr += ' Z';\n            isClosed = true;\n          } else {\n            pathStr += ` L ${nodes[i].x} ${nodes[i].y}`;\n          }\n        }\n        \n        const { fill: masterFill, stroke: masterStroke } = useEditorStore.getState().masterColors;\n        const pathObj = new Path(pathStr, {\n          fill: isClosed ? masterFill : 'transparent',\n          stroke: masterStroke,\n          strokeWidth: 2,\n          name: 'Vector Path'\n        } as any);\n\n        canvasInstance.add(pathObj);\n        canvasInstance.setActiveObject(pathObj);\n        saveHistoryState();\n        syncLayers();\n      }\n      clearPreview();\n      setActiveTool('select');\n    };\n\n    if (activeTool !== 'pen') {\n      if (nodesRef.current.length > 0) {\n        finishPath();\n      }\n      return;\n    }\n\n    const onMouseDown = (e: any) => {\n      if (e.e.shiftKey) {\n        finishPath();\n        return;\n      }\n      \n      const pointer = canvasInstance.getScenePoint(e.e);\n      \n      // Auto-close path if clicking near the first node\n      if (nodesRef.current.length > 2) {\n        const firstNode = nodesRef.current[0];\n        const dist = Math.hypot(pointer.x - firstNode.x, pointer.y - firstNode.y);\n        if (dist < 15) { // 15px snap radius\n          // Close the path\n          nodesRef.current.push({ x: firstNode.x, y: firstNode.y });\n          finishPath();\n          return;\n        }\n      }\n\n      nodesRef.current.push({ x: pointer.x, y: pointer.y });\n      \n      const circle = new Circle({\n        left: pointer.x,\n        top: pointer.y,\n        radius: 4,\n        fill: '#3b82f6',\n        stroke: '#ffffff',\n        strokeWidth: 2,\n        originX: 'center',\n        originY: 'center',\n        selectable: false,\n        evented: false,\n      });\n      canvasInstance.add(circle);\n      circlesRef.current.push(circle);\n\n      if (nodesRef.current.length > 1) {\n        const prev = nodesRef.current[nodesRef.current.length - 2];\n        const line = new Line([prev.x, prev.y, pointer.x, pointer.y], {\n          stroke: '#3b82f6',\n          strokeWidth: 2,\n          selectable: false,\n          evented: false,\n        });\n        canvasInstance.add(line);\n        linesRef.current.push(line);\n      }\n\n      // Prepare temp line\n      if (!tempLineRef.current) {\n        tempLineRef.current = new Line([pointer.x, pointer.y, pointer.x, pointer.y], {\n          stroke: '#3b82f6',\n          strokeWidth: 2,\n          strokeDashArray: [5, 5],\n          selectable: false,\n          evented: false,\n        });\n        canvasInstance.add(tempLineRef.current);\n      } else {\n        tempLineRef.current.set({ x1: pointer.x, y1: pointer.y, x2: pointer.x, y2: pointer.y });\n      }\n\n      canvasInstance.requestRenderAll();\n    };\n\n    const onMouseMove = (e: any) => {\n      if (nodesRef.current.length === 0 || !tempLineRef.current) return;\n      const pointer = canvasInstance.getScenePoint(e.e);\n      tempLineRef.current.set({ x2: pointer.x, y2: pointer.y });\n      canvasInstance.requestRenderAll();\n    };\n\n    const onKeyDown = (e: KeyboardEvent) => {\n      if (activeTool === 'pen' && (e.key === 'Enter' || e.key === 'Escape')) {\n        finishPath();\n      }\n    };\n\n    canvasInstance.on('mouse:down', onMouseDown);\n    canvasInstance.on('mouse:move', onMouseMove);\n    window.addEventListener('keydown', onKeyDown);\n\n    return () => {\n      canvasInstance.off('mouse:down', onMouseDown);\n      canvasInstance.off('mouse:move', onMouseMove);\n      window.removeEventListener('keydown', onKeyDown);\n    };\n  }, [activeTool, canvasInstance]);\n\n  return (\n    <>\n      {activeTool === 'pen' && (\n        <div className=\"pointer-events-none absolute top-24 left-1/2 z-40 flex -translate-x-1/2 select-none items-center gap-2 rounded-full bg-[var(--we-accent)] px-4 py-2.5 shadow-xl\">\n          <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-white\">\n            {t.canvas.pen.pathHint}\n          </TextBody>\n        </div>\n      )}\n    </>\n  );\n};\n", "import React from 'react';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { FabricObject, ActiveSelection, Path, Point } from 'fabric';\nimport * as martinez from 'martinez-polygon-clipping';\nimport { useTranslation } from '../../i18n';\nimport { TextBody } from '../ui';\n\n// Convierte un objeto Fabric a un pol\u00EDgono compatible con martinez\nconst fabricObjectToPolygon = (obj: FabricObject): number[][][] => {\n  // Simplificaci\u00F3n r\u00E1pida: Extraemos las coordenadas del bounding box o puntos si es un pol\u00EDgono\n  // Para producci\u00F3n, se requerir\u00EDa un muestreo de puntos a lo largo de las curvas de un Path.\n  const points: number[][] = [];\n  \n  if (obj.type === 'polygon' || obj.type === 'polyline') {\n    const pts = (obj as any).points;\n    const matrix = obj.calcTransformMatrix();\n    for (const pt of pts) {\n      const p = new Point(pt.x, pt.y).transform(matrix);\n      points.push([p.x, p.y]);\n    }\n  } else {\n    // Para rect\u00E1ngulos, c\u00EDrculos, im\u00E1genes, etc.\n    const coords = obj.getCoords();\n    points.push([coords[0].x, coords[0].y]);\n    points.push([coords[1].x, coords[1].y]);\n    points.push([coords[2].x, coords[2].y]);\n    points.push([coords[3].x, coords[3].y]);\n  }\n  \n  // Cerrar el pol\u00EDgono\n  if (points.length > 0) {\n    points.push([...points[0]]);\n  }\n  \n  return [points]; // [ring]\n};\n\nconst polygonToFabricPath = (geom: number[][][][]): Path => {\n  let pathStr = '';\n  for (const polygon of geom) {\n    for (const ring of polygon) {\n      for (let i = 0; i < ring.length; i++) {\n        if (i === 0) pathStr += `M ${ring[i][0]} ${ring[i][1]} `;\n        else pathStr += `L ${ring[i][0]} ${ring[i][1]} `;\n      }\n      pathStr += 'Z ';\n    }\n  }\n  return new Path(pathStr, { fill: '#3b82f6', stroke: '#2563eb', strokeWidth: 1 } as any);\n};\n\nexport const BooleanOperationsMenu: React.FC = () => {\n  const t = useTranslation();\n  const { activeObject, canvasInstance, setActiveObject, saveHistoryState } = useEditorStore();\n\n  if (!activeObject || activeObject.type !== 'activeselection') return null;\n\n  const selection = activeObject as ActiveSelection;\n  const objects = selection.getObjects();\n  if (objects.length !== 2) return null; // Solo 2 objetos para boolean\n\n  const executeOperation = (type: 'union' | 'intersection' | 'difference') => {\n    if (!canvasInstance) return;\n\n    try {\n      const poly1 = fabricObjectToPolygon(objects[0]);\n      const poly2 = fabricObjectToPolygon(objects[1]);\n\n      let resultGeom: any = [];\n      if (type === 'union') {\n        resultGeom = martinez.union(poly1 as any, poly2 as any);\n      } else if (type === 'intersection') {\n        resultGeom = martinez.intersection(poly1 as any, poly2 as any);\n      } else if (type === 'difference') {\n        resultGeom = martinez.diff(poly1 as any, poly2 as any);\n      }\n\n      const resultPath = polygonToFabricPath(resultGeom || []);\n      \n      canvasInstance.remove(objects[0], objects[1]);\n      canvasInstance.discardActiveObject();\n      canvasInstance.add(resultPath);\n      canvasInstance.setActiveObject(resultPath);\n      \n      setActiveObject(resultPath);\n      saveHistoryState();\n    } catch (err) {\n      console.error('Error in boolean operation:', err);\n    }\n  };\n\n  return (\n    <div className=\"absolute top-20 left-1/2 z-40 flex -translate-x-1/2 animate-fade-in items-center gap-1 rounded-lg border border-dark-800 bg-dark-900 p-1.5 shadow-xl\">\n      <button\n        type=\"button\"\n        onClick={() => executeOperation('union')}\n        className=\"rounded px-3 py-1.5 transition-colors hover:bg-dark-800\"\n      >\n        <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-white\">\n          {t.canvas.booleanOps.union}\n        </TextBody>\n      </button>\n      <div className=\"h-4 w-px bg-dark-700\" />\n      <button\n        type=\"button\"\n        onClick={() => executeOperation('difference')}\n        className=\"rounded px-3 py-1.5 transition-colors hover:bg-dark-800\"\n      >\n        <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-white\">\n          {t.canvas.booleanOps.subtract}\n        </TextBody>\n      </button>\n      <div className=\"h-4 w-px bg-dark-700\" />\n      <button\n        type=\"button\"\n        onClick={() => executeOperation('intersection')}\n        className=\"rounded px-3 py-1.5 transition-colors hover:bg-dark-800\"\n      >\n        <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-white\">\n          {t.canvas.booleanOps.intersect}\n        </TextBody>\n      </button>\n    </div>\n  );\n};\n", "import React, { useEffect, useRef } from 'react';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { Group, util } from 'fabric';\nimport { useTranslation } from '../../i18n';\nimport { TextBody, TextTitle } from '../ui';\n\nexport const MaskEditorPanel: React.FC = () => {\n  const t = useTranslation();\n\n  const { \n    maskMode, activeMaskTarget, setMaskMode, setActiveMaskTarget, \n    canvasInstance, setActiveTool, saveHistoryState, syncLayers \n  } = useEditorStore();\n\n  const originalObjectsCount = useRef<number>(0);\n  \n  useEffect(() => {\n    if (!maskMode || !canvasInstance || !activeMaskTarget) return;\n\n    setActiveTool('brush');\n    originalObjectsCount.current = canvasInstance.getObjects().length;\n    \n    // Opcionalmente atenuar los dem\u00E1s objetos\n    canvasInstance.getObjects().forEach(obj => {\n      if (obj !== activeMaskTarget) {\n        obj.set('opacity', (obj.opacity || 1) * 0.3);\n      }\n    });\n    canvasInstance.requestRenderAll();\n\n  }, [maskMode, activeMaskTarget, canvasInstance]);\n\n  if (!maskMode || !activeMaskTarget || !canvasInstance) return null;\n\n  const handleApply = () => {\n    const allObjs = canvasInstance.getObjects();\n    const newObjs = allObjs.slice(originalObjectsCount.current);\n\n    if (newObjs.length > 0) {\n      // Remover de la escena los nuevos trazos\n      newObjs.forEach(o => canvasInstance.remove(o));\n      \n      const maskGroup = new Group(newObjs, {\n        originX: 'center',\n        originY: 'center',\n      } as any);\n\n      // Usar inversamente la matriz de transformaci\u00F3n del objeto objetivo para alinear la m\u00E1scara\n      const inv = util.invertTransform(activeMaskTarget.calcTransformMatrix());\n      const groupCenter = maskGroup.getCenterPoint();\n      const localCenter = util.transformPoint(groupCenter, inv);\n\n      maskGroup.set({ \n        left: localCenter.x, \n        top: localCenter.y,\n        angle: (maskGroup.angle || 0) - (activeMaskTarget.angle || 0),\n        scaleX: (maskGroup.scaleX || 1) / (activeMaskTarget.scaleX || 1),\n        scaleY: (maskGroup.scaleY || 1) / (activeMaskTarget.scaleY || 1),\n      }); \n\n      activeMaskTarget.set({ clipPath: maskGroup });\n      (activeMaskTarget as any).isMasked = true;\n    }\n\n    restoreOpacities();\n    setMaskMode(false);\n    setActiveMaskTarget(null);\n    setActiveTool('select');\n    saveHistoryState();\n    syncLayers();\n    canvasInstance.requestRenderAll();\n  };\n\n  const handleCancel = () => {\n    const allObjs = canvasInstance.getObjects();\n    const newObjs = allObjs.slice(originalObjectsCount.current);\n    newObjs.forEach(o => canvasInstance.remove(o));\n\n    restoreOpacities();\n    setMaskMode(false);\n    setActiveMaskTarget(null);\n    setActiveTool('select');\n    canvasInstance.requestRenderAll();\n  };\n\n  const restoreOpacities = () => {\n    canvasInstance.getObjects().forEach(obj => {\n      if (obj !== activeMaskTarget) {\n        // Asumiendo que la opacidad original era 1 por simplicidad o restaurando si hubi\u00E9ramos guardado\n        obj.set('opacity', 1);\n      }\n    });\n  };\n\n  return (\n    <div className=\"absolute top-20 left-1/2 -translate-x-1/2 z-40 bg-dark-900 border border-[var(--we-accent)] shadow-2xl shadow-[color-mix(in_srgb,var(--we-accent)_20%,transparent)] rounded-xl p-3 flex items-center gap-3 animate-fade-in backdrop-blur-md\">\n      <div className=\"flex flex-col\">\n        <TextTitle as=\"span\" size=\"sm\">\n          {t.mask.title}\n        </TextTitle>\n        <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400\">\n          {t.mask.hint}\n        </TextBody>\n      </div>\n      <div className=\"w-px h-8 bg-dark-800 mx-1\" />\n      <button\n        onClick={handleCancel}\n        className=\"px-4 py-2 hover:bg-dark-800 text-dark-300 hover:text-white rounded-lg transition-colors cursor-pointer\"\n      >\n        <TextBody as=\"span\" size=\"md\" className=\"font-semibold\">\n          {t.common.cancel}\n        </TextBody>\n      </button>\n      <button\n        onClick={handleApply}\n        className=\"px-4 py-2 bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] text-white rounded-lg shadow-lg transition-colors cursor-pointer\"\n      >\n        <TextBody as=\"span\" size=\"md\" className=\"font-bold\">\n          {t.common.apply}\n        </TextBody>\n      </button>\n    </div>\n  );\n};\n", "/**\n * Map Fabric scene (page) pixels \u2192 overlay host pixels.\n * Prefer measuring the canvas element so CSS zoom / borders stay in sync\n * (store.zoom alone can lag or miss offsets).\n */\n\nexport type OverlayCoordMap = {\n  ox: number;\n  oy: number;\n  scale: number;\n};\n\nexport function buildOverlayCoordMap(\n  canvas: {\n    getWidth: () => number;\n    getHeight: () => number;\n    upperCanvasEl?: HTMLCanvasElement | null;\n    getElement?: () => HTMLCanvasElement;\n  } | null | undefined,\n  host: HTMLElement | null | undefined,\n): OverlayCoordMap | null {\n  if (!canvas || !host) return null;\n  const el = canvas.upperCanvasEl || canvas.getElement?.();\n  if (!el) return null;\n  const canvasRect = el.getBoundingClientRect();\n  const hostRect = host.getBoundingClientRect();\n  const cw = Math.max(1, canvas.getWidth());\n  const ch = Math.max(1, canvas.getHeight());\n  const scale = Math.max(\n    0.01,\n    (canvasRect.width / cw + canvasRect.height / ch) / 2,\n  );\n  return {\n    ox: canvasRect.left - hostRect.left,\n    oy: canvasRect.top - hostRect.top,\n    scale,\n  };\n}\n\nexport function sceneToOverlay(\n  map: OverlayCoordMap,\n  sceneX: number,\n  sceneY: number,\n): { x: number; y: number } {\n  return {\n    x: map.ox + sceneX * map.scale,\n    y: map.oy + sceneY * map.scale,\n  };\n}\n\n/** Pointer client coords \u2192 overlay host local px (matches the cursor on screen). */\nexport function clientToOverlay(\n  host: HTMLElement,\n  clientX: number,\n  clientY: number,\n): { x: number; y: number } {\n  const r = host.getBoundingClientRect();\n  return { x: clientX - r.left, y: clientY - r.top };\n}\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { ActiveSelection, Point, type Canvas, type FabricObject } from 'fabric';\nimport { isMarqueeTool, useEditorStore } from '../../store/useEditorStore';\nimport { clientToOverlay } from '../../utils/overlayCoords';\n\ntype Draft =\n  | { kind: 'rect'; x0: number; y0: number; x1: number; y1: number }\n  | { kind: 'ellipse'; x0: number; y0: number; x1: number; y1: number }\n  | { kind: 'lasso'; points: { x: number; y: number }[] };\n\ntype ScreenDraft =\n  | { kind: 'rect' | 'ellipse'; x0: number; y0: number; x1: number; y1: number }\n  | { kind: 'lasso'; points: { x: number; y: number }[] };\n\nfunction normRect(a: { x0: number; y0: number; x1: number; y1: number }) {\n  const left = Math.min(a.x0, a.x1);\n  const top = Math.min(a.y0, a.y1);\n  return { left, top, width: Math.abs(a.x1 - a.x0), height: Math.abs(a.y1 - a.y0) };\n}\n\nfunction boxOf(obj: FabricObject) {\n  const r = obj.getBoundingRect();\n  return {\n    left: r.left,\n    top: r.top,\n    right: r.left + r.width,\n    bottom: r.top + r.height,\n    cx: r.left + r.width / 2,\n    cy: r.top + r.height / 2,\n  };\n}\n\nfunction rectHits(\n  box: ReturnType<typeof boxOf>,\n  sel: { left: number; top: number; width: number; height: number },\n) {\n  return (\n    box.left < sel.left + sel.width &&\n    box.right > sel.left &&\n    box.top < sel.top + sel.height &&\n    box.bottom > sel.top\n  );\n}\n\nfunction ellipseHits(\n  box: ReturnType<typeof boxOf>,\n  sel: { left: number; top: number; width: number; height: number },\n) {\n  const rx = sel.width / 2;\n  const ry = sel.height / 2;\n  if (rx <= 0 || ry <= 0) return false;\n  const cx = sel.left + rx;\n  const cy = sel.top + ry;\n  const inside = (x: number, y: number) => {\n    const nx = (x - cx) / rx;\n    const ny = (y - cy) / ry;\n    return nx * nx + ny * ny <= 1;\n  };\n  if (inside(box.cx, box.cy)) return true;\n  if (\n    inside(box.left, box.top) ||\n    inside(box.right, box.top) ||\n    inside(box.left, box.bottom) ||\n    inside(box.right, box.bottom)\n  ) {\n    return true;\n  }\n  return box.left <= cx && box.right >= cx && box.top <= cy && box.bottom >= cy;\n}\n\nfunction pointInPoly(x: number, y: number, pts: { x: number; y: number }[]) {\n  let inside = false;\n  for (let i = 0, j = pts.length - 1; i < pts.length; j = i++) {\n    const a = pts[i];\n    const b = pts[j];\n    if (!a || !b) continue;\n    const intersect =\n      a.y > y !== b.y > y && x < ((b.x - a.x) * (y - a.y)) / (b.y - a.y || 1e-6) + a.x;\n    if (intersect) inside = !inside;\n  }\n  return inside;\n}\n\nfunction applyMarquee(canvas: Canvas, draft: Draft) {\n  // Leaving pixel-mask context \u2014 object marquee is canvas-level selection.\n  useEditorStore.getState().clearMagicWandSelection();\n\n  const candidates = canvas.getObjects().filter((obj) => {\n    const o = obj as FabricObject & { id?: string; isImageCropOverlay?: boolean; name?: string };\n    if (!obj.visible || o.isImageCropOverlay || o.id === 'background' || o.name === 'clone-stamp-layer') {\n      return false;\n    }\n    if ((obj as FabricObject & { locked?: boolean }).locked) return false;\n    const box = boxOf(obj);\n    if (draft.kind === 'rect') return rectHits(box, normRect(draft));\n    if (draft.kind === 'ellipse') return ellipseHits(box, normRect(draft));\n    if (draft.points.length < 3) return false;\n    return pointInPoly(box.cx, box.cy, draft.points);\n  });\n\n  canvas.discardActiveObject();\n  if (candidates.length === 1) {\n    canvas.setActiveObject(candidates[0]!);\n  } else if (candidates.length > 1) {\n    const sel = new ActiveSelection(candidates, { canvas });\n    sel.set({\n      lockMovementX: false,\n      lockMovementY: false,\n      hasControls: false,\n      hasBorders: false,\n      evented: true,\n      selectable: true,\n    });\n    sel.setCoords();\n    canvas.setActiveObject(sel);\n  }\n  canvas.requestRenderAll();\n  useEditorStore.getState().setActiveObject(canvas.getActiveObject() ?? null);\n  // Hand off to Move/Select so the user can immediately drag the selection.\n  useEditorStore.getState().setActiveTool('select');\n}\n\n/**\n * Freehand object marquee (select-lasso) + Alt-drag rect marquee on Select (V)\n * so multi-select works even over large images that fill the canvas.\n * Rectangular / elliptical tools are pixel shape lassos (ShapeLassoOverlay).\n */\nexport const MarqueeSelectOverlay: React.FC = () => {\n  const { activeTool, canvasInstance } = useEditorStore();\n  const hostRef = useRef<HTMLDivElement | null>(null);\n  const [screenDraft, setScreenDraft] = useState<ScreenDraft | null>(null);\n  const drawingRef = useRef(false);\n  const draftRef = useRef<Draft | null>(null);\n  const savedSkipRef = useRef<boolean | null>(null);\n\n  useEffect(() => {\n    const canvas = canvasInstance;\n    const isDedicatedMarquee = isMarqueeTool(activeTool);\n    const isSelectTool = activeTool === 'select' || activeTool === 'move-only';\n    if (!canvas || (!isDedicatedMarquee && !isSelectTool)) {\n      setScreenDraft(null);\n      draftRef.current = null;\n      return;\n    }\n\n    const scenePoint = (e: MouseEvent) => canvas.getScenePoint(e);\n    const screenPoint = (e: MouseEvent) => {\n      const host = hostRef.current;\n      if (!host) return null;\n      return clientToOverlay(host, e.clientX, e.clientY);\n    };\n\n    const beginMarquee = (e: MouseEvent, kind: Draft['kind']) => {\n      const screen = screenPoint(e);\n      if (!screen) return;\n      drawingRef.current = true;\n      // Ignore object hits while drawing so drag doesn't move a single image.\n      savedSkipRef.current = canvas.skipTargetFind;\n      canvas.skipTargetFind = true;\n      canvas.selection = false;\n\n      const p = scenePoint(e);\n      const next: Draft =\n        kind === 'lasso'\n          ? { kind: 'lasso', points: [{ x: p.x, y: p.y }] }\n          : { kind, x0: p.x, y0: p.y, x1: p.x, y1: p.y };\n      draftRef.current = next;\n      const screenNext: ScreenDraft =\n        kind === 'lasso'\n          ? { kind: 'lasso', points: [screen] }\n          : { kind, x0: screen.x, y0: screen.y, x1: screen.x, y1: screen.y };\n      setScreenDraft(screenNext);\n    };\n\n    const onDown = (opt: { e: Event; target?: FabricObject | null }) => {\n      const e = opt.e as MouseEvent;\n      if (e.button !== 0) return;\n\n      if (isDedicatedMarquee) {\n        e.preventDefault();\n        e.stopPropagation();\n        beginMarquee(e, 'lasso');\n        return;\n      }\n\n      // Select (V): Alt+drag, empty hit, or outside the selected image \u2192 free marquee.\n      // Corner/edge/rotate controls sit outside the image fill \u2014 do not steal those\n      // for marquee (Fabric already started scale/rotate via _currentTransform).\n      const p = scenePoint(e);\n      const active = canvas.getActiveObject() as FabricObject | null;\n      const activeIsImage = !!active && (active.type || '').toLowerCase() === 'image';\n      const outsideActiveImage =\n        activeIsImage &&\n        typeof active.containsPoint === 'function' &&\n        !active.containsPoint(new Point(p.x, p.y));\n      const emptyHit = !opt.target;\n      const live = (\n        canvas as Canvas & {\n          _currentTransform?: { corner?: string; target?: FabricObject | null } | null;\n        }\n      )._currentTransform;\n      const onActiveControl =\n        !!active && !!live?.corner && live.target === active;\n\n      if (!onActiveControl && (e.altKey || emptyHit || outsideActiveImage)) {\n        e.preventDefault();\n        e.stopPropagation();\n        const c = canvas as Canvas & {\n          _currentTransform?: unknown;\n          _groupSelector?: unknown;\n        };\n        c._currentTransform = null;\n        c._groupSelector = null;\n        beginMarquee(e, 'rect');\n      }\n    };\n\n    const onMove = (opt: { e: Event }) => {\n      if (!drawingRef.current || !draftRef.current) return;\n      const e = opt.e as MouseEvent;\n      e.preventDefault();\n      const p = scenePoint(e);\n      const screen = screenPoint(e);\n      if (!screen) return;\n      const prev = draftRef.current;\n      const next: Draft =\n        prev.kind === 'lasso'\n          ? { ...prev, points: [...prev.points, { x: p.x, y: p.y }] }\n          : { ...prev, x1: p.x, y1: p.y };\n      draftRef.current = next;\n      setScreenDraft((prevScreen) => {\n        if (!prevScreen) return prevScreen;\n        if (prevScreen.kind === 'lasso') {\n          return { kind: 'lasso', points: [...prevScreen.points, screen] };\n        }\n        return { ...prevScreen, x1: screen.x, y1: screen.y };\n      });\n    };\n\n    const onUp = () => {\n      if (!drawingRef.current) return;\n      drawingRef.current = false;\n      if (savedSkipRef.current != null) {\n        canvas.skipTargetFind = savedSkipRef.current;\n        savedSkipRef.current = null;\n      }\n      const d = draftRef.current;\n      draftRef.current = null;\n      setScreenDraft(null);\n      if (!d) return;\n\n      const sizeOk =\n        d.kind === 'lasso'\n          ? d.points.length >= 3\n          : Math.abs(d.x1 - d.x0) > 3 || Math.abs(d.y1 - d.y0) > 3;\n      if (!sizeOk) return;\n      applyMarquee(canvas, d);\n    };\n\n    canvas.on('mouse:down', onDown);\n    canvas.on('mouse:move', onMove);\n    canvas.on('mouse:up', onUp);\n    return () => {\n      canvas.off('mouse:down', onDown);\n      canvas.off('mouse:move', onMove);\n      canvas.off('mouse:up', onUp);\n      drawingRef.current = false;\n      if (savedSkipRef.current != null) {\n        canvas.skipTargetFind = savedSkipRef.current;\n        savedSkipRef.current = null;\n      }\n    };\n  }, [canvasInstance, activeTool]);\n\n  let shape: React.ReactNode = null;\n  if (screenDraft) {\n    if (screenDraft.kind === 'lasso' && screenDraft.points.length > 1) {\n      const d = screenDraft.points\n        .map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x} ${p.y}`)\n        .join(' ');\n      shape = <path d={`${d} Z`} />;\n    } else if (screenDraft.kind === 'ellipse' || screenDraft.kind === 'rect') {\n      const left = Math.min(screenDraft.x0, screenDraft.x1);\n      const top = Math.min(screenDraft.y0, screenDraft.y1);\n      const width = Math.abs(screenDraft.x1 - screenDraft.x0);\n      const height = Math.abs(screenDraft.y1 - screenDraft.y0);\n      shape =\n        screenDraft.kind === 'ellipse' ? (\n          <ellipse\n            cx={left + width / 2}\n            cy={top + height / 2}\n            rx={width / 2}\n            ry={height / 2}\n          />\n        ) : (\n          <rect x={left} y={top} width={width} height={height} />\n        );\n    }\n  }\n\n  const isDedicatedMarquee = isMarqueeTool(activeTool);\n  const isSelectTool = activeTool === 'select' || activeTool === 'move-only';\n  if (!isDedicatedMarquee && !isSelectTool) return null;\n\n  return (\n    <div ref={hostRef} className=\"pointer-events-none absolute inset-0 z-10 overflow-visible\">\n      {shape ? (\n        <svg\n          className=\"absolute inset-0 overflow-visible\"\n          width=\"100%\"\n          height=\"100%\"\n          aria-hidden\n        >\n          <g\n            fill=\"color-mix(in srgb, var(--we-accent) 12%, transparent)\"\n            stroke=\"var(--we-accent)\"\n            strokeWidth={1.25}\n            strokeDasharray=\"5 4\"\n            vectorEffect=\"non-scaling-stroke\"\n          >\n            {shape}\n          </g>\n        </svg>\n      ) : null}\n    </div>\n  );\n};\n", "import { useEffect, useRef } from 'react';\nimport { type Canvas } from 'fabric';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { getActiveMessages } from '../../i18n';\nimport {\n  ensurePixelLayerCanvas,\n  ensurePixelLayerCoversPage,\n  isPixelLayer,\n  refreshPixelLayerContentBounds,\n  refreshPixelLayerDisplay,\n  sceneToLayerPixel,\n  syncPixelLayerInteraction,\n  unionOpaqueBounds,\n  type PixelLayerImage,\n} from '../../utils/pixelLayer';\n\nfunction snapshotPage(canvas: Canvas): HTMLCanvasElement {\n  // Fabric bitmap is page-sized (visual zoom is CSS); export at 1:1 page pixels.\n  return canvas.toCanvasElement(1);\n}\n\n/**\n * Stamp a circular sample from page-space source into layer-space dest.\n * Source (srcX, srcY) and dest (destX, destY) may live in different buffers;\n * drawImage is offset so the source sample lands under the brush.\n */\nfunction stampCircle(\n  dest: CanvasRenderingContext2D,\n  source: HTMLCanvasElement,\n  destX: number,\n  destY: number,\n  srcX: number,\n  srcY: number,\n  radius: number,\n) {\n  dest.save();\n  dest.beginPath();\n  dest.arc(destX, destY, Math.max(0.5, radius), 0, Math.PI * 2);\n  dest.closePath();\n  dest.clip();\n  dest.drawImage(source, destX - srcX, destY - srcY);\n  dest.restore();\n}\n\nexport function CloneStampOverlay() {\n  const { activeTool, canvasInstance } = useEditorStore();\n  const sourceRef = useRef<{ x: number; y: number } | null>(null);\n  const offsetRef = useRef<{ x: number; y: number } | null>(null);\n  const paintingRef = useRef(false);\n  const lastRef = useRef<{ x: number; y: number } | null>(null);\n  const snapshotRef = useRef<HTMLCanvasElement | null>(null);\n  const sourceMarkerRef = useRef<HTMLDivElement | null>(null);\n\n  useEffect(() => {\n    const canvas = canvasInstance;\n    if (!canvas || activeTool !== 'clone-stamp') return;\n\n    const scenePoint = (e: MouseEvent) => canvas.getScenePoint(e);\n\n    const placeMarker = (sceneX: number, sceneY: number) => {\n      const marker = sourceMarkerRef.current;\n      if (!marker) return;\n      const zoom = useEditorStore.getState().zoom || 1;\n      // Overlay sits in pageStage (CSS size = page \u00D7 zoom), sibling of the\n      // CSS-scaled Fabric wrapper \u2014 map scene px \u2192 host px with visual zoom.\n      marker.style.left = `${sceneX * zoom}px`;\n      marker.style.top = `${sceneY * zoom}px`;\n      marker.style.display = 'block';\n    };\n\n    const paintAt = (sceneX: number, sceneY: number) => {\n      const store = useEditorStore.getState();\n      if (!snapshotRef.current || !offsetRef.current) return;\n      const layer = store.resolvePaintTargetLayer();\n      if (!layer || !isPixelLayer(layer)) return;\n\n      const page = store.pages.find((p) => p.id === store.activePageId) || store.pages[0];\n      if (!page) return;\n\n      // Rebake to page-sized 1:1 buffer so brushes can hit anywhere on the artboard\n      // and scene coords map cleanly into the layer (same as paint bucket).\n      ensurePixelLayerCoversPage(layer, page.width, page.height);\n\n      const radius = Math.max(1, store.brushSettings.width) / 2;\n      const srcSceneX = sceneX - offsetRef.current.x;\n      const srcSceneY = sceneY - offsetRef.current.y;\n      const dest = sceneToLayerPixel(layer, sceneX, sceneY);\n\n      const el = ensurePixelLayerCanvas(layer as PixelLayerImage);\n      const ctx = el.getContext('2d');\n      if (!ctx) return;\n\n      // Sample from the page snapshot in scene/page pixels; paint into layer-local.\n      stampCircle(\n        ctx,\n        snapshotRef.current,\n        dest.x,\n        dest.y,\n        srcSceneX,\n        srcSceneY,\n        radius,\n      );\n\n      layer.weContentCanvas = el;\n      const dab = {\n        x: Math.round(dest.x - radius),\n        y: Math.round(dest.y - radius),\n        w: Math.max(1, Math.round(radius * 2)),\n        h: Math.max(1, Math.round(radius * 2)),\n      };\n      const prevBounds = layer.weOpaqueBounds;\n      refreshPixelLayerDisplay(layer);\n      layer.weOpaqueBounds = unionOpaqueBounds(prevBounds, dab);\n      if (!layer.weOpaqueBounds) refreshPixelLayerContentBounds(layer);\n      syncPixelLayerInteraction(layer);\n      canvas.requestRenderAll();\n\n      placeMarker(srcSceneX, srcSceneY);\n    };\n\n    const onDown = (opt: { e: Event }) => {\n      const e = opt.e as MouseEvent;\n      if (e.button !== 0) return;\n      const pt = scenePoint(e);\n      if (e.altKey) {\n        sourceRef.current = { x: pt.x, y: pt.y };\n        offsetRef.current = null;\n        snapshotRef.current = snapshotPage(canvas);\n        paintingRef.current = false;\n        lastRef.current = null;\n        placeMarker(pt.x, pt.y);\n        return;\n      }\n      if (!sourceRef.current) return;\n      if (!useEditorStore.getState().resolvePaintTargetLayer()) {\n        useEditorStore.getState().addToast(getActiveMessages().layers.mustSelectLayer, 'warning');\n        return;\n      }\n      if (!offsetRef.current) {\n        offsetRef.current = {\n          x: pt.x - sourceRef.current.x,\n          y: pt.y - sourceRef.current.y,\n        };\n      }\n      if (!snapshotRef.current) snapshotRef.current = snapshotPage(canvas);\n      paintingRef.current = true;\n      lastRef.current = { x: pt.x, y: pt.y };\n      paintAt(pt.x, pt.y);\n    };\n\n    const onMove = (opt: { e: Event }) => {\n      if (!paintingRef.current) return;\n      const pt = scenePoint(opt.e as MouseEvent);\n      const last = lastRef.current;\n      if (last) {\n        const dx = pt.x - last.x;\n        const dy = pt.y - last.y;\n        const dist = Math.hypot(dx, dy);\n        const step = Math.max(1, useEditorStore.getState().brushSettings.width / 4);\n        if (dist >= step) {\n          const n = Math.floor(dist / step);\n          for (let i = 1; i <= n; i++) {\n            paintAt(last.x + (dx * i) / n, last.y + (dy * i) / n);\n          }\n          lastRef.current = { x: pt.x, y: pt.y };\n        }\n      } else {\n        paintAt(pt.x, pt.y);\n        lastRef.current = { x: pt.x, y: pt.y };\n      }\n    };\n\n    const onUp = () => {\n      if (paintingRef.current) {\n        paintingRef.current = false;\n        lastRef.current = null;\n        useEditorStore.getState().syncLayers();\n        useEditorStore.getState().saveHistoryState();\n      }\n    };\n\n    canvas.on('mouse:down', onDown);\n    canvas.on('mouse:move', onMove);\n    canvas.on('mouse:up', onUp);\n    return () => {\n      canvas.off('mouse:down', onDown);\n      canvas.off('mouse:move', onMove);\n      canvas.off('mouse:up', onUp);\n    };\n  }, [activeTool, canvasInstance]);\n\n  if (activeTool !== 'clone-stamp') return null;\n\n  return (\n    <div\n      ref={sourceMarkerRef}\n      className=\"pointer-events-none absolute z-50 size-3 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white shadow-[0_0_0_1px_rgba(0,0,0,0.6)]\"\n      style={{ display: 'none', left: 0, top: 0 }}\n      aria-hidden\n    />\n  );\n}\n", "import React, { useEffect, useRef } from 'react';\nimport { FabricImage, Point, type FabricObject, type TPointerEventInfo } from 'fabric';\nimport { isPixelSelectionTool, useEditorStore } from '../../store/useEditorStore';\nimport {\n  combineMasks,\n  computeMagicWandMask,\n  fabricImageObjectToImageData,\n  imageDataHasOpaquePixels,\n  maskToPreviewDataUrl,\n  scenePointToImagePixels,\n  type SelectionCombineMode,\n} from '../../utils/magicWandSelection';\n\nfunction isFabricImage(obj: FabricObject | null | undefined): obj is FabricImage {\n  return !!obj && (obj.type || '').toLowerCase() === 'image';\n}\n\n/** Prefer hit image; else the currently selected image (even if click is outside its bounds). */\nfunction resolveSelectionImage(\n  canvas: { getObjects: () => FabricObject[]; getActiveObject: () => FabricObject | undefined | null },\n  point: Point,\n  fabricTarget?: FabricObject | null,\n): FabricImage | null {\n  if (isFabricImage(fabricTarget)) return fabricTarget;\n\n  const storeActive = useEditorStore.getState().activeObject as FabricObject | null;\n  if (isFabricImage(storeActive)) return storeActive;\n\n  const canvasActive = canvas.getActiveObject();\n  if (isFabricImage(canvasActive)) return canvasActive;\n\n  for (let i = canvas.getObjects().length - 1; i >= 0; i--) {\n    const obj = canvas.getObjects()[i];\n    if (!obj || !obj.visible) continue;\n    if ((obj as FabricObject & { name?: string }).name === 'clone-stamp-layer') continue;\n    if (!isFabricImage(obj)) continue;\n    if (typeof obj.containsPoint === 'function' && obj.containsPoint(point)) {\n      return obj;\n    }\n  }\n  return null;\n}\n\nfunction resolveCombineMode(\n  e: MouseEvent,\n  base: SelectionCombineMode,\n): SelectionCombineMode {\n  if (e.shiftKey) return 'add';\n  if (e.ctrlKey || e.metaKey) return 'subtract';\n  return base;\n}\n\n/**\n * Magic wand: click an image \u2192 select similar pixels (tolerance / contiguous).\n * Overlay shows the current mask; apply actions live in MagicWandToolPanel.\n */\nexport const MagicWandOverlay: React.FC = () => {\n  const {\n    activeTool,\n    canvasInstance,\n    magicWandSettings,\n    setMagicWandSelection,\n    clearMagicWandSelection,\n    addToast,\n  } = useEditorStore();\n\n  const samplingRef = useRef(false);\n\n  useEffect(() => {\n    // Keep pixel selection when switching to Move/Select (V) so it can float;\n    // clear only when leaving selection tools entirely.\n    if (isPixelSelectionTool(activeTool) || activeTool === 'select' || activeTool === 'move-only') {\n      return;\n    }\n    clearMagicWandSelection();\n  }, [activeTool, clearMagicWandSelection]);\n\n  useEffect(() => {\n    if (activeTool !== 'magic-wand' || !canvasInstance) return;\n    const canvasAo = canvasInstance.getActiveObject();\n    const storeAo = useEditorStore.getState().activeObject;\n    const img = isFabricImage(storeAo)\n      ? storeAo\n      : isFabricImage(canvasAo)\n        ? canvasAo\n        : null;\n    if (!img) return;\n    if (canvasInstance.getActiveObject() !== img) {\n      canvasInstance.setActiveObject(img);\n      canvasInstance.requestRenderAll();\n    }\n    if (storeAo !== img) {\n      useEditorStore.getState().setActiveObject(img);\n    }\n  }, [activeTool, canvasInstance]);\n\n  useEffect(() => {\n    const canvas = canvasInstance;\n    if (!canvas || activeTool !== 'magic-wand') return;\n\n    const resolveImage = (e: MouseEvent, fabricTarget?: FabricObject | null): FabricImage | null => {\n      const scene = canvas.getScenePoint(e);\n      const point = new Point(scene.x, scene.y);\n      return resolveSelectionImage(canvas, point, fabricTarget);\n    };\n\n    const sampleImage = (img: FabricImage, e: MouseEvent) => {\n      const objectId =\n        (img as FabricObject & { id?: string }).id || `img-${Date.now()}`;\n      if (!(img as FabricObject & { id?: string }).id) {\n        (img as FabricObject & { id?: string }).id = objectId;\n      }\n\n      canvas.setActiveObject(img);\n      useEditorStore.getState().setActiveObject(img);\n      canvas.requestRenderAll();\n\n      const scene = canvas.getScenePoint(e);\n      // Clamp outside clicks onto the selected image so wand works from outside.\n      const mapped = scenePointToImagePixels(img, scene.x, scene.y, { allowOutside: true });\n      if (!mapped) return;\n\n      const { width, height } = mapped;\n      const px = Math.min(width - 1, Math.max(0, mapped.px));\n      const py = Math.min(height - 1, Math.max(0, mapped.py));\n      const imageData = fabricImageObjectToImageData(img);\n\n      if (!imageDataHasOpaquePixels(imageData)) {\n        addToast(\n          'No se pueden leer los p\u00EDxeles de esta imagen (CORS o imagen vac\u00EDa).',\n          'error',\n        );\n        return;\n      }\n\n      const sampleX = (px / width) * imageData.width;\n      const sampleY = (py / height) * imageData.height;\n\n      const nextMask = computeMagicWandMask(imageData, sampleX, sampleY, {\n        tolerance: magicWandSettings.tolerance,\n        contiguous: magicWandSettings.contiguous,\n      });\n\n      if (!nextMask) return;\n\n      const mode = resolveCombineMode(e, magicWandSettings.selectionMode);\n      const prev = useEditorStore.getState().magicWandSelection;\n      const baseMask =\n        prev && prev.objectId === objectId\n          ? {\n              width: prev.width,\n              height: prev.height,\n              data: prev.maskData,\n              bounds: {\n                minX: 0,\n                minY: 0,\n                maxX: prev.width - 1,\n                maxY: prev.height - 1,\n              },\n              pixelCount: prev.pixelCount,\n            }\n          : null;\n\n      const merged = combineMasks(baseMask, nextMask, mode);\n      if (!merged) {\n        clearMagicWandSelection();\n        return;\n      }\n\n      setMagicWandSelection({\n        objectId,\n        previewUrl: maskToPreviewDataUrl(merged),\n        width: merged.width,\n        height: merged.height,\n        pixelCount: merged.pixelCount,\n        maskData: merged.data,\n      });\n    };\n\n    const onDown = (opt: TPointerEventInfo) => {\n      const e = opt.e as MouseEvent;\n      if (e.button !== 0) return;\n      e.preventDefault();\n      if (samplingRef.current) return;\n      samplingRef.current = true;\n\n      try {\n        const img = resolveImage(e, opt.target ?? null);\n        if (!img) {\n          const mode = resolveCombineMode(e, magicWandSettings.selectionMode);\n          if (mode === 'new') clearMagicWandSelection();\n          return;\n        }\n        sampleImage(img, e);\n      } catch (err) {\n        console.error('Magic wand sample failed', err);\n        addToast('Error al muestrear la imagen con la varita m\u00E1gica.', 'error');\n      } finally {\n        samplingRef.current = false;\n      }\n    };\n\n    canvas.on('mouse:down', onDown);\n    return () => {\n      canvas.off('mouse:down', onDown);\n    };\n  }, [\n    canvasInstance,\n    activeTool,\n    magicWandSettings.tolerance,\n    magicWandSettings.contiguous,\n    magicWandSettings.selectionMode,\n    setMagicWandSelection,\n    clearMagicWandSelection,\n    addToast,\n  ]);\n\n  return null;\n};\n", "import React, { useEffect, useRef } from 'react';\nimport { FabricImage, Point, type FabricObject, type TPointerEventInfo } from 'fabric';\nimport { getActiveMessages } from '../../i18n';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport {\n  applyPaintBucketFill,\n  computeMagicWandMask,\n  fabricImageToImageData,\n  imageDataToCanvas,\n} from '../../utils/magicWandSelection';\nimport { parseCssColor } from '../../utils/colorRgba';\nimport {\n  asPixelLayer,\n  ensurePixelLayerCanvas,\n  ensurePixelLayerCoversPage,\n  isFabricImage,\n  isPixelLayer,\n  refreshPixelLayerContentBounds,\n  refreshPixelLayerDisplay,\n  sceneToLayerPixel,\n  syncPixelLayerInteraction,\n  type PixelLayerImage,\n} from '../../utils/pixelLayer';\n\nfunction resolveFillImage(\n  canvas: { getObjects: () => FabricObject[]; getActiveObject: () => FabricObject | undefined | null },\n  point: Point,\n  fabricTarget?: FabricObject | null,\n): FabricImage | null {\n  // Prefer the active image so clicks on empty page still paint into the layer.\n  const storeActive = useEditorStore.getState().activeObject as FabricObject | null;\n  if (isFabricImage(storeActive)) return storeActive;\n\n  const canvasActive = canvas.getActiveObject();\n  if (isFabricImage(canvasActive)) return canvasActive;\n\n  if (isFabricImage(fabricTarget)) return fabricTarget;\n\n  for (let i = canvas.getObjects().length - 1; i >= 0; i--) {\n    const obj = canvas.getObjects()[i];\n    if (!obj || !obj.visible) continue;\n    if ((obj as FabricObject & { name?: string }).name === 'clone-stamp-layer') continue;\n    if (!isFabricImage(obj)) continue;\n    if (typeof obj.containsPoint === 'function' && obj.containsPoint(point)) {\n      return obj;\n    }\n  }\n  return null;\n}\n\n/**\n * Paint bucket: expands the selected pixel layer to page size, then flood-fills.\n * Click empty artboard \u2192 fills transparent page area (layer grows to canvas).\n * Click opaque content \u2192 fills similar pixels inside the content.\n */\nexport const PaintBucketOverlay: React.FC = () => {\n  const {\n    activeTool,\n    canvasInstance,\n    paintBucketSettings,\n    masterColors,\n    syncLayers,\n    saveHistoryState,\n    addToast,\n  } = useEditorStore();\n\n  const fillingRef = useRef(false);\n\n  useEffect(() => {\n    if (activeTool !== 'paint-bucket' || !canvasInstance) return;\n    const store = useEditorStore.getState();\n    const canvasAo = canvasInstance.getActiveObject();\n    const storeAo = store.activeObject;\n    const fromPaint = store.paintTargetLayerId\n      ? (canvasInstance.getObjects().find(\n          (o) => (o as FabricObject & { id?: string }).id === store.paintTargetLayerId,\n        ) as FabricObject | undefined) ?? null\n      : null;\n    const img = isFabricImage(storeAo)\n      ? storeAo\n      : isFabricImage(canvasAo)\n        ? canvasAo\n        : isFabricImage(fromPaint)\n          ? fromPaint\n          : null;\n    if (!img) return;\n    if (canvasInstance.getActiveObject() !== img) {\n      canvasInstance.setActiveObject(img);\n      canvasInstance.requestRenderAll();\n    }\n    if (storeAo !== img) {\n      useEditorStore.getState().setActiveObject(img);\n    }\n  }, [activeTool, canvasInstance]);\n\n  useEffect(() => {\n    const canvas = canvasInstance;\n    if (!canvas || activeTool !== 'paint-bucket') return;\n\n    const onDown = (opt: TPointerEventInfo) => {\n      const e = opt.e as MouseEvent;\n      if (e.button !== 0) return;\n      e.preventDefault();\n      if (fillingRef.current) return;\n      fillingRef.current = true;\n\n      try {\n        const scene = canvas.getScenePoint(e);\n        const point = new Point(scene.x, scene.y);\n        const img = resolveFillImage(canvas, point, opt.target ?? null);\n        if (!img) {\n          addToast(getActiveMessages().canvas.paintBucket.noImage, 'info');\n          return;\n        }\n\n        if (!(img as FabricObject & { id?: string }).id) {\n          (img as FabricObject & { id?: string }).id = `img-${Date.now()}`;\n        }\n\n        const store = useEditorStore.getState();\n        const page = store.pages.find((p) => p.id === store.activePageId) || store.pages[0];\n        if (!page) return;\n\n        // Grow/rebake selected image into a page-sized pixel layer first.\n        const layer: PixelLayerImage = isPixelLayer(img) ? img : asPixelLayer(img);\n        ensurePixelLayerCoversPage(layer, page.width, page.height);\n\n        canvas.setActiveObject(layer);\n        useEditorStore.getState().setActiveObject(layer);\n        canvas.requestRenderAll();\n\n        const el = ensurePixelLayerCanvas(layer);\n        const local = sceneToLayerPixel(layer, scene.x, scene.y);\n        const px = Math.min(el.width - 1, Math.max(0, Math.floor(local.x)));\n        const py = Math.min(el.height - 1, Math.max(0, Math.floor(local.y)));\n\n        const imageData = fabricImageToImageData(el, el.width, el.height);\n        if (imageData.width < 1 || imageData.height < 1) {\n          addToast(getActiveMessages().canvas.paintBucket.readError, 'error');\n          return;\n        }\n\n        const mask = computeMagicWandMask(imageData, px + 0.5, py + 0.5, {\n          tolerance: paintBucketSettings.tolerance,\n          contiguous: paintBucketSettings.contiguous,\n          allowTransparentSeed: true,\n        });\n        if (!mask || mask.pixelCount === 0) return;\n\n        const rgba = parseCssColor(masterColors.fill || '#FFFFFF');\n        applyPaintBucketFill(\n          imageData,\n          mask,\n          { r: rgba.r, g: rgba.g, b: rgba.b },\n          {\n            opacity: rgba.a,\n            antiAlias: paintBucketSettings.antiAlias,\n          },\n        );\n\n        const edited = imageDataToCanvas(imageData);\n        layer.weContentCanvas = edited;\n        refreshPixelLayerDisplay(layer);\n        refreshPixelLayerContentBounds(layer);\n        syncPixelLayerInteraction(layer);\n        canvas.requestRenderAll();\n        syncLayers();\n        saveHistoryState();\n      } catch (err) {\n        console.error('Paint bucket fill failed', err);\n        addToast(getActiveMessages().canvas.paintBucket.fillError, 'error');\n      } finally {\n        fillingRef.current = false;\n      }\n    };\n\n    canvas.on('mouse:down', onDown);\n    return () => {\n      canvas.off('mouse:down', onDown);\n    };\n  }, [\n    canvasInstance,\n    activeTool,\n    paintBucketSettings.tolerance,\n    paintBucketSettings.contiguous,\n    paintBucketSettings.antiAlias,\n    masterColors.fill,\n    syncLayers,\n    saveHistoryState,\n    addToast,\n  ]);\n\n  return null;\n};\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { FabricImage, Point, type FabricObject, type TPointerEventInfo } from 'fabric';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport {\n  combineMasks,\n  fabricImageObjectToImageData,\n  imageDataHasOpaquePixels,\n  maskFromPolygon,\n  maskToPreviewDataUrl,\n  scenePointToImagePixels,\n  type SelectionCombineMode,\n} from '../../utils/magicWandSelection';\nimport { clientToOverlay } from '../../utils/overlayCoords';\n\nfunction isFabricImage(obj: FabricObject | null | undefined): obj is FabricImage {\n  return !!obj && (obj.type || '').toLowerCase() === 'image';\n}\n\nfunction resolveSelectionImage(\n  canvas: { getObjects: () => FabricObject[]; getActiveObject: () => FabricObject | undefined | null },\n  point: Point,\n  fabricTarget?: FabricObject | null,\n): FabricImage | null {\n  if (isFabricImage(fabricTarget)) return fabricTarget;\n  const storeActive = useEditorStore.getState().activeObject as FabricObject | null;\n  if (isFabricImage(storeActive)) return storeActive;\n  const canvasActive = canvas.getActiveObject();\n  if (isFabricImage(canvasActive)) return canvasActive;\n  for (let i = canvas.getObjects().length - 1; i >= 0; i--) {\n    const o = canvas.getObjects()[i];\n    if (!isFabricImage(o) || !o.visible) continue;\n    if ((o as FabricObject & { name?: string }).name === 'clone-stamp-layer') continue;\n    if (o.containsPoint?.(point)) return o;\n  }\n  return null;\n}\n\nfunction resolveCombineMode(\n  e: MouseEvent,\n  base: SelectionCombineMode,\n): SelectionCombineMode {\n  if (e.shiftKey) return 'add';\n  if (e.ctrlKey || e.metaKey) return 'subtract';\n  return base;\n}\n\n/**\n * Freehand lasso over an image \u2192 pixel selection (shared with magic wand mask).\n * Preview path uses host-local client coords so it stays under the cursor\n * regardless of CSS zoom; mask math stays in scene/image space.\n */\nexport const PixelLassoOverlay: React.FC = () => {\n  const {\n    activeTool,\n    canvasInstance,\n    magicWandSettings,\n    setMagicWandSelection,\n    clearMagicWandSelection,\n    addToast,\n  } = useEditorStore();\n\n  const hostRef = useRef<HTMLDivElement | null>(null);\n  const [draft, setDraft] = useState<{ x: number; y: number }[] | null>(null);\n  const drawingRef = useRef(false);\n  const targetImgRef = useRef<FabricImage | null>(null);\n  const pointsRef = useRef<{ x: number; y: number }[]>([]);\n  const rasterSizeRef = useRef<{ w: number; h: number } | null>(null);\n\n  useEffect(() => {\n    const canvas = canvasInstance;\n    if (!canvas || activeTool !== 'pixel-lasso') {\n      setDraft(null);\n      drawingRef.current = false;\n      targetImgRef.current = null;\n      pointsRef.current = [];\n      rasterSizeRef.current = null;\n      return;\n    }\n\n    const screenPoint = (e: MouseEvent) => {\n      const host = hostRef.current;\n      if (!host) return null;\n      return clientToOverlay(host, e.clientX, e.clientY);\n    };\n\n    const onDown = (opt: TPointerEventInfo) => {\n      const e = opt.e as MouseEvent;\n      if (e.button !== 0) return;\n      e.preventDefault();\n\n      const scene = canvas.getScenePoint(e);\n      const point = new Point(scene.x, scene.y);\n      const img = resolveSelectionImage(canvas, point, opt.target ?? null);\n      if (!img) return;\n\n      canvas.setActiveObject(img);\n      useEditorStore.getState().setActiveObject(img);\n\n      const mapped = scenePointToImagePixels(img, scene.x, scene.y, { allowOutside: true });\n      if (!mapped) return;\n\n      const imageData = fabricImageObjectToImageData(img);\n      if (!imageDataHasOpaquePixels(imageData)) {\n        addToast(\n          'No se pueden leer los p\u00EDxeles de esta imagen (CORS o imagen vac\u00EDa).',\n          'error',\n        );\n        return;\n      }\n\n      const px = (mapped.px / mapped.width) * imageData.width;\n      const py = (mapped.py / mapped.height) * imageData.height;\n      const screen = screenPoint(e);\n      if (!screen) return;\n\n      targetImgRef.current = img;\n      rasterSizeRef.current = { w: imageData.width, h: imageData.height };\n      drawingRef.current = true;\n      pointsRef.current = [{ x: px, y: py }];\n      setDraft([screen]);\n    };\n\n    const onMove = (opt: TPointerEventInfo) => {\n      if (!drawingRef.current || !targetImgRef.current || !rasterSizeRef.current) return;\n      const e = opt.e as MouseEvent;\n      const scene = canvas.getScenePoint(e);\n      const mapped = scenePointToImagePixels(targetImgRef.current, scene.x, scene.y, {\n        allowOutside: true,\n      });\n      if (!mapped) return;\n      const { w, h } = rasterSizeRef.current;\n      const px = (mapped.px / mapped.width) * w;\n      const py = (mapped.py / mapped.height) * h;\n      pointsRef.current.push({ x: px, y: py });\n      const screen = screenPoint(e);\n      if (!screen) return;\n      setDraft((prev) => (prev ? [...prev, screen] : [screen]));\n    };\n\n    const onUp = (opt: TPointerEventInfo) => {\n      if (!drawingRef.current || !targetImgRef.current || !rasterSizeRef.current) return;\n      drawingRef.current = false;\n      const img = targetImgRef.current;\n      const { w, h } = rasterSizeRef.current;\n      const e = opt.e as MouseEvent;\n      const pts = pointsRef.current;\n      targetImgRef.current = null;\n      rasterSizeRef.current = null;\n      pointsRef.current = [];\n      setDraft(null);\n\n      if (pts.length < 3) return;\n\n      const nextMask = maskFromPolygon(w, h, pts);\n      if (!nextMask) return;\n\n      const objectId =\n        (img as FabricObject & { id?: string }).id || `img-${Date.now()}`;\n      if (!(img as FabricObject & { id?: string }).id) {\n        (img as FabricObject & { id?: string }).id = objectId;\n      }\n\n      const mode = resolveCombineMode(e, magicWandSettings.selectionMode);\n      const prev = useEditorStore.getState().magicWandSelection;\n      const baseMask =\n        prev && prev.objectId === objectId\n          ? {\n              width: prev.width,\n              height: prev.height,\n              data: prev.maskData,\n              bounds: {\n                minX: 0,\n                minY: 0,\n                maxX: prev.width - 1,\n                maxY: prev.height - 1,\n              },\n              pixelCount: prev.pixelCount,\n            }\n          : null;\n\n      const merged = combineMasks(baseMask, nextMask, mode);\n      if (!merged) {\n        clearMagicWandSelection();\n        return;\n      }\n\n      setMagicWandSelection({\n        objectId,\n        previewUrl: maskToPreviewDataUrl(merged),\n        width: merged.width,\n        height: merged.height,\n        pixelCount: merged.pixelCount,\n        maskData: merged.data,\n      });\n    };\n\n    canvas.on('mouse:down', onDown);\n    canvas.on('mouse:move', onMove);\n    canvas.on('mouse:up', onUp);\n    return () => {\n      canvas.off('mouse:down', onDown);\n      canvas.off('mouse:move', onMove);\n      canvas.off('mouse:up', onUp);\n    };\n  }, [\n    canvasInstance,\n    activeTool,\n    magicWandSettings.selectionMode,\n    setMagicWandSelection,\n    clearMagicWandSelection,\n    addToast,\n  ]);\n\n  if (activeTool !== 'pixel-lasso') return null;\n\n  const d =\n    draft && draft.length >= 2\n      ? draft.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x} ${p.y}`).join(' ')\n      : '';\n\n  return (\n    <div ref={hostRef} className=\"pointer-events-none absolute inset-0 z-10 overflow-visible\">\n      {d ? (\n        <svg\n          className=\"absolute inset-0 overflow-visible\"\n          width=\"100%\"\n          height=\"100%\"\n          aria-hidden\n        >\n          <path\n            d={`${d} Z`}\n            fill=\"color-mix(in srgb, var(--we-accent) 18%, transparent)\"\n            stroke=\"var(--we-accent)\"\n            strokeWidth={1.25}\n            strokeDasharray=\"5 4\"\n            vectorEffect=\"non-scaling-stroke\"\n          />\n        </svg>\n      ) : null}\n    </div>\n  );\n};\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { FabricImage, Point, type FabricObject, type TPointerEventInfo } from 'fabric';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport {\n  combineMasks,\n  fabricImageObjectToImageData,\n  imageDataHasOpaquePixels,\n  maskFromEllipse,\n  maskFromRect,\n  maskToPreviewDataUrl,\n  scenePointToImagePixels,\n  type SelectionCombineMode,\n} from '../../utils/magicWandSelection';\nimport { clientToOverlay } from '../../utils/overlayCoords';\n\nfunction isFabricImage(obj: FabricObject | null | undefined): obj is FabricImage {\n  return !!obj && (obj.type || '').toLowerCase() === 'image';\n}\n\nfunction resolveSelectionImage(\n  canvas: { getObjects: () => FabricObject[]; getActiveObject: () => FabricObject | undefined | null },\n  point: Point,\n  fabricTarget?: FabricObject | null,\n): FabricImage | null {\n  if (isFabricImage(fabricTarget)) return fabricTarget;\n  const storeActive = useEditorStore.getState().activeObject as FabricObject | null;\n  if (isFabricImage(storeActive)) return storeActive;\n  const canvasActive = canvas.getActiveObject();\n  if (isFabricImage(canvasActive)) return canvasActive;\n  for (let i = canvas.getObjects().length - 1; i >= 0; i--) {\n    const o = canvas.getObjects()[i];\n    if (!isFabricImage(o) || !o.visible) continue;\n    if ((o as FabricObject & { name?: string }).name === 'clone-stamp-layer') continue;\n    if (o.containsPoint?.(point)) return o;\n  }\n  return null;\n}\n\nfunction resolveCombineMode(\n  e: MouseEvent,\n  base: SelectionCombineMode,\n): SelectionCombineMode {\n  if (e.shiftKey) return 'add';\n  if (e.ctrlKey || e.metaKey) return 'subtract';\n  return base;\n}\n\ntype ShapeKind = 'rect' | 'ellipse';\n\ntype Draft = {\n  kind: ShapeKind;\n  x0: number;\n  y0: number;\n  x1: number;\n  y1: number;\n};\n\n/**\n * Rectangular / elliptical lasso \u2192 pixel selection (same mask system as freehand lasso).\n */\nexport const ShapeLassoOverlay: React.FC = () => {\n  const {\n    activeTool,\n    canvasInstance,\n    magicWandSettings,\n    setMagicWandSelection,\n    clearMagicWandSelection,\n    addToast,\n  } = useEditorStore();\n\n  const shapeKind: ShapeKind | null =\n    activeTool === 'select-rect'\n      ? 'rect'\n      : activeTool === 'select-ellipse'\n        ? 'ellipse'\n        : null;\n\n  const hostRef = useRef<HTMLDivElement | null>(null);\n  const [draft, setDraft] = useState<Draft | null>(null);\n  const drawingRef = useRef(false);\n  const targetImgRef = useRef<FabricImage | null>(null);\n  const rasterSizeRef = useRef<{ w: number; h: number } | null>(null);\n  const pixelCornersRef = useRef<{ x0: number; y0: number; x1: number; y1: number } | null>(\n    null,\n  );\n  const savedSkipRef = useRef<boolean | null>(null);\n\n  useEffect(() => {\n    const canvas = canvasInstance;\n    if (!canvas || !shapeKind) {\n      setDraft(null);\n      drawingRef.current = false;\n      targetImgRef.current = null;\n      rasterSizeRef.current = null;\n      pixelCornersRef.current = null;\n      return;\n    }\n\n    const screenPoint = (e: MouseEvent) => {\n      const host = hostRef.current;\n      if (!host) return null;\n      return clientToOverlay(host, e.clientX, e.clientY);\n    };\n\n    const onDown = (opt: TPointerEventInfo) => {\n      const e = opt.e as MouseEvent;\n      if (e.button !== 0) return;\n      e.preventDefault();\n      e.stopPropagation();\n\n      const scene = canvas.getScenePoint(e);\n      const point = new Point(scene.x, scene.y);\n      const img = resolveSelectionImage(canvas, point, opt.target ?? null);\n      if (!img) {\n        addToast('Selecciona o haz clic sobre una capa de imagen primero.', 'warning');\n        return;\n      }\n\n      canvas.setActiveObject(img);\n      useEditorStore.getState().setActiveObject(img);\n\n      const mapped = scenePointToImagePixels(img, scene.x, scene.y, { allowOutside: true });\n      if (!mapped) return;\n\n      const imageData = fabricImageObjectToImageData(img);\n      if (!imageDataHasOpaquePixels(imageData)) {\n        addToast(\n          'No se pueden leer los p\u00EDxeles de esta imagen (CORS o imagen vac\u00EDa).',\n          'error',\n        );\n        return;\n      }\n\n      const px = (mapped.px / mapped.width) * imageData.width;\n      const py = (mapped.py / mapped.height) * imageData.height;\n      const screen = screenPoint(e);\n      if (!screen) return;\n\n      savedSkipRef.current = canvas.skipTargetFind;\n      canvas.skipTargetFind = true;\n      canvas.selection = false;\n\n      targetImgRef.current = img;\n      rasterSizeRef.current = { w: imageData.width, h: imageData.height };\n      pixelCornersRef.current = { x0: px, y0: py, x1: px, y1: py };\n      drawingRef.current = true;\n      setDraft({ kind: shapeKind, x0: screen.x, y0: screen.y, x1: screen.x, y1: screen.y });\n    };\n\n    const onMove = (opt: TPointerEventInfo) => {\n      if (!drawingRef.current || !targetImgRef.current || !rasterSizeRef.current) return;\n      const e = opt.e as MouseEvent;\n      e.preventDefault();\n      const scene = canvas.getScenePoint(e);\n      const mapped = scenePointToImagePixels(targetImgRef.current, scene.x, scene.y, {\n        allowOutside: true,\n      });\n      if (!mapped || !pixelCornersRef.current) return;\n      const { w, h } = rasterSizeRef.current;\n      const px = (mapped.px / mapped.width) * w;\n      const py = (mapped.py / mapped.height) * h;\n      pixelCornersRef.current = {\n        ...pixelCornersRef.current,\n        x1: px,\n        y1: py,\n      };\n      const screen = screenPoint(e);\n      if (!screen) return;\n      setDraft((prev) =>\n        prev ? { ...prev, x1: screen.x, y1: screen.y } : null,\n      );\n    };\n\n    const onUp = (opt: TPointerEventInfo) => {\n      if (!drawingRef.current || !targetImgRef.current || !rasterSizeRef.current) return;\n      drawingRef.current = false;\n      if (savedSkipRef.current != null) {\n        canvas.skipTargetFind = savedSkipRef.current;\n        savedSkipRef.current = null;\n      }\n\n      const img = targetImgRef.current;\n      const { w, h } = rasterSizeRef.current;\n      const corners = pixelCornersRef.current;\n      const e = opt.e as MouseEvent;\n      targetImgRef.current = null;\n      rasterSizeRef.current = null;\n      pixelCornersRef.current = null;\n      setDraft(null);\n\n      if (!corners) return;\n      if (\n        Math.abs(corners.x1 - corners.x0) < 2 &&\n        Math.abs(corners.y1 - corners.y0) < 2\n      ) {\n        return;\n      }\n\n      const nextMask =\n        shapeKind === 'ellipse'\n          ? maskFromEllipse(w, h, corners.x0, corners.y0, corners.x1, corners.y1)\n          : maskFromRect(w, h, corners.x0, corners.y0, corners.x1, corners.y1);\n      if (!nextMask) return;\n\n      const objectId =\n        (img as FabricObject & { id?: string }).id || `img-${Date.now()}`;\n      if (!(img as FabricObject & { id?: string }).id) {\n        (img as FabricObject & { id?: string }).id = objectId;\n      }\n\n      const mode = resolveCombineMode(e, magicWandSettings.selectionMode);\n      const prev = useEditorStore.getState().magicWandSelection;\n      const baseMask =\n        prev && prev.objectId === objectId\n          ? {\n              width: prev.width,\n              height: prev.height,\n              data: prev.maskData,\n              bounds: {\n                minX: 0,\n                minY: 0,\n                maxX: prev.width - 1,\n                maxY: prev.height - 1,\n              },\n              pixelCount: prev.pixelCount,\n            }\n          : null;\n\n      const merged = combineMasks(baseMask, nextMask, mode);\n      if (!merged) {\n        clearMagicWandSelection();\n        return;\n      }\n\n      setMagicWandSelection({\n        objectId,\n        previewUrl: maskToPreviewDataUrl(merged),\n        width: merged.width,\n        height: merged.height,\n        pixelCount: merged.pixelCount,\n        maskData: merged.data,\n      });\n    };\n\n    canvas.on('mouse:down', onDown);\n    canvas.on('mouse:move', onMove);\n    canvas.on('mouse:up', onUp);\n    return () => {\n      canvas.off('mouse:down', onDown);\n      canvas.off('mouse:move', onMove);\n      canvas.off('mouse:up', onUp);\n      drawingRef.current = false;\n      if (savedSkipRef.current != null) {\n        canvas.skipTargetFind = savedSkipRef.current;\n        savedSkipRef.current = null;\n      }\n    };\n  }, [\n    canvasInstance,\n    shapeKind,\n    magicWandSettings.selectionMode,\n    setMagicWandSelection,\n    clearMagicWandSelection,\n    addToast,\n  ]);\n\n  if (!shapeKind) return null;\n\n  let shape: React.ReactNode = null;\n  if (draft) {\n    const left = Math.min(draft.x0, draft.x1);\n    const top = Math.min(draft.y0, draft.y1);\n    const width = Math.abs(draft.x1 - draft.x0);\n    const height = Math.abs(draft.y1 - draft.y0);\n    shape =\n      draft.kind === 'ellipse' ? (\n        <ellipse\n          cx={left + width / 2}\n          cy={top + height / 2}\n          rx={width / 2}\n          ry={height / 2}\n        />\n      ) : (\n        <rect x={left} y={top} width={width} height={height} />\n      );\n  }\n\n  return (\n    <div ref={hostRef} className=\"pointer-events-none absolute inset-0 z-10 overflow-visible\">\n      {shape ? (\n        <svg\n          className=\"absolute inset-0 overflow-visible\"\n          width=\"100%\"\n          height=\"100%\"\n          aria-hidden\n        >\n          <g\n            fill=\"color-mix(in srgb, var(--we-accent) 18%, transparent)\"\n            stroke=\"var(--we-accent)\"\n            strokeWidth={1.25}\n            strokeDasharray=\"5 4\"\n            vectorEffect=\"non-scaling-stroke\"\n          >\n            {shape}\n          </g>\n        </svg>\n      ) : null}\n    </div>\n  );\n};\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { FabricImage, Point, type FabricObject, type TPointerEventInfo } from 'fabric';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport {\n  combineMasks,\n  fabricImageObjectToImageData,\n  imageDataHasOpaquePixels,\n  maskFromPolygon,\n  maskToPreviewDataUrl,\n  scenePointToImagePixels,\n  type SelectionCombineMode,\n} from '../../utils/magicWandSelection';\nimport { clientToOverlay } from '../../utils/overlayCoords';\n\nfunction isFabricImage(obj: FabricObject | null | undefined): obj is FabricImage {\n  return !!obj && (obj.type || '').toLowerCase() === 'image';\n}\n\nfunction resolveCombineMode(\n  e: { shiftKey?: boolean; ctrlKey?: boolean; metaKey?: boolean },\n  base: SelectionCombineMode,\n): SelectionCombineMode {\n  if (e.shiftKey) return 'add';\n  if (e.ctrlKey || e.metaKey) return 'subtract';\n  return base;\n}\n\nconst CLOSE_HIT_PX = 10;\n\n/**\n * Polygonal lasso: click to place vertices, close by clicking the first point\n * (or double-click / Enter). Escape cancels the draft.\n * Preview vertices use host-local client coords so they stay under the cursor.\n */\nexport const PolygonLassoOverlay: React.FC = () => {\n  const { activeTool, canvasInstance } = useEditorStore();\n\n  const hostRef = useRef<HTMLDivElement | null>(null);\n  const [screenPts, setScreenPts] = useState<{ x: number; y: number }[]>([]);\n  const [cursor, setCursor] = useState<{ x: number; y: number } | null>(null);\n  const imgRef = useRef<FabricImage | null>(null);\n  const pixelPtsRef = useRef<{ x: number; y: number }[]>([]);\n  const rasterSizeRef = useRef<{ w: number; h: number } | null>(null);\n  const screenPtsRef = useRef<{ x: number; y: number }[]>([]);\n\n  useEffect(() => {\n    screenPtsRef.current = screenPts;\n  }, [screenPts]);\n\n  useEffect(() => {\n    const canvas = canvasInstance;\n    if (!canvas || activeTool !== 'polygon-lasso') {\n      setScreenPts([]);\n      setCursor(null);\n      imgRef.current = null;\n      pixelPtsRef.current = [];\n      rasterSizeRef.current = null;\n      return;\n    }\n\n    const screenPoint = (e: MouseEvent) => {\n      const host = hostRef.current;\n      if (!host) return null;\n      return clientToOverlay(host, e.clientX, e.clientY);\n    };\n\n    const resetDraft = () => {\n      setScreenPts([]);\n      setCursor(null);\n      imgRef.current = null;\n      pixelPtsRef.current = [];\n      rasterSizeRef.current = null;\n    };\n\n    const commitPolygon = (mods: {\n      shiftKey?: boolean;\n      ctrlKey?: boolean;\n      metaKey?: boolean;\n    }) => {\n      const img = imgRef.current;\n      const size = rasterSizeRef.current;\n      const pts = pixelPtsRef.current;\n      const store = useEditorStore.getState();\n      if (!img || !size || pts.length < 3) {\n        resetDraft();\n        return;\n      }\n\n      const nextMask = maskFromPolygon(size.w, size.h, pts);\n      resetDraft();\n      if (!nextMask) return;\n\n      const objectId =\n        (img as FabricObject & { id?: string }).id || `img-${Date.now()}`;\n      if (!(img as FabricObject & { id?: string }).id) {\n        (img as FabricObject & { id?: string }).id = objectId;\n      }\n\n      const mode = resolveCombineMode(mods, store.magicWandSettings.selectionMode);\n      const prev = store.magicWandSelection;\n      const baseMask =\n        prev && prev.objectId === objectId\n          ? {\n              width: prev.width,\n              height: prev.height,\n              data: prev.maskData,\n              bounds: {\n                minX: 0,\n                minY: 0,\n                maxX: prev.width - 1,\n                maxY: prev.height - 1,\n              },\n              pixelCount: prev.pixelCount,\n            }\n          : null;\n\n      const merged = combineMasks(baseMask, nextMask, mode);\n      if (!merged) {\n        store.clearMagicWandSelection();\n        return;\n      }\n\n      store.setMagicWandSelection({\n        objectId,\n        previewUrl: maskToPreviewDataUrl(merged),\n        width: merged.width,\n        height: merged.height,\n        pixelCount: merged.pixelCount,\n        maskData: merged.data,\n      });\n    };\n\n    const resolveImage = (e: MouseEvent, target?: FabricObject | null): FabricImage | null => {\n      const scene = canvas.getScenePoint(e);\n      const point = new Point(scene.x, scene.y);\n      if (isFabricImage(target)) return target;\n      const storeActive = useEditorStore.getState().activeObject as FabricObject | null;\n      if (isFabricImage(storeActive)) return storeActive;\n      const active = canvas.getActiveObject();\n      if (isFabricImage(active)) return active;\n      for (let i = canvas.getObjects().length - 1; i >= 0; i--) {\n        const o = canvas.getObjects()[i];\n        if (!isFabricImage(o) || !o.visible) continue;\n        if ((o as FabricObject & { name?: string }).name === 'clone-stamp-layer') continue;\n        if (o.containsPoint?.(point)) return o;\n      }\n      return null;\n    };\n\n    const onDown = (opt: TPointerEventInfo) => {\n      const e = opt.e as MouseEvent;\n      if (e.button !== 0) return;\n      e.preventDefault();\n\n      const screen = screenPoint(e);\n      if (!screen) return;\n\n      if (screenPtsRef.current.length >= 3) {\n        const first = screenPtsRef.current[0]!;\n        const distScreen = Math.hypot(screen.x - first.x, screen.y - first.y);\n        if (distScreen <= CLOSE_HIT_PX) {\n          commitPolygon(e);\n          return;\n        }\n      }\n\n      let img = imgRef.current;\n      if (!img) {\n        img = resolveImage(e, opt.target ?? null);\n        if (!img) return;\n        const imageData = fabricImageObjectToImageData(img);\n        if (!imageDataHasOpaquePixels(imageData)) {\n          useEditorStore\n            .getState()\n            .addToast(\n              'No se pueden leer los p\u00EDxeles de esta imagen (CORS o imagen vac\u00EDa).',\n              'error',\n            );\n          return;\n        }\n        canvas.setActiveObject(img);\n        useEditorStore.getState().setActiveObject(img);\n        imgRef.current = img;\n        rasterSizeRef.current = { w: imageData.width, h: imageData.height };\n      }\n\n      const scene = canvas.getScenePoint(e);\n      const mapped = scenePointToImagePixels(img, scene.x, scene.y, { allowOutside: true });\n      const size = rasterSizeRef.current;\n      if (!mapped || !size) return;\n      const px = (mapped.px / mapped.width) * size.w;\n      const py = (mapped.py / mapped.height) * size.h;\n\n      pixelPtsRef.current = [...pixelPtsRef.current, { x: px, y: py }];\n      setScreenPts((prev) => [...prev, screen]);\n      setCursor(screen);\n    };\n\n    const onDblClick = (opt: TPointerEventInfo) => {\n      const e = opt.e as MouseEvent;\n      e.preventDefault();\n      if (pixelPtsRef.current.length >= 3) commitPolygon(e);\n    };\n\n    const onMove = (opt: TPointerEventInfo) => {\n      if (!imgRef.current || screenPtsRef.current.length === 0) return;\n      const screen = screenPoint(opt.e as MouseEvent);\n      if (!screen) return;\n      setCursor(screen);\n    };\n\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') {\n        e.preventDefault();\n        resetDraft();\n        return;\n      }\n      if (e.key === 'Enter' && pixelPtsRef.current.length >= 3) {\n        e.preventDefault();\n        commitPolygon(e);\n      }\n    };\n\n    canvas.on('mouse:down', onDown);\n    canvas.on('mouse:dblclick', onDblClick);\n    canvas.on('mouse:move', onMove);\n    window.addEventListener('keydown', onKey);\n    return () => {\n      canvas.off('mouse:down', onDown);\n      canvas.off('mouse:dblclick', onDblClick);\n      canvas.off('mouse:move', onMove);\n      window.removeEventListener('keydown', onKey);\n    };\n  }, [canvasInstance, activeTool]);\n\n  if (activeTool !== 'polygon-lasso') return null;\n\n  const pts = cursor ? [...screenPts, cursor] : screenPts;\n  const d = pts.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x} ${p.y}`).join(' ');\n  const first = pts[0];\n  const canClose = screenPts.length >= 3;\n\n  return (\n    <div ref={hostRef} className=\"pointer-events-none absolute inset-0 z-10 overflow-visible\">\n      {pts.length > 0 ? (\n        <svg\n          className=\"absolute inset-0 overflow-visible\"\n          width=\"100%\"\n          height=\"100%\"\n          aria-hidden\n        >\n          <path\n            d={d}\n            fill=\"none\"\n            stroke=\"var(--we-accent)\"\n            strokeWidth={1.5}\n            strokeDasharray=\"6 4\"\n            vectorEffect=\"non-scaling-stroke\"\n          />\n          {pts.slice(0, screenPts.length).map((p, i) => (\n            <circle\n              key={i}\n              cx={p.x}\n              cy={p.y}\n              r={i === 0 && canClose ? 5 : 3}\n              fill={i === 0 && canClose ? 'var(--we-accent)' : '#fff'}\n              stroke=\"#000\"\n              strokeWidth={1}\n            />\n          ))}\n          {canClose && first ? (\n            <circle\n              cx={first.x}\n              cy={first.y}\n              r={CLOSE_HIT_PX}\n              fill=\"color-mix(in srgb, var(--we-accent) 20%, transparent)\"\n              stroke=\"var(--we-accent)\"\n              strokeWidth={1}\n              strokeDasharray=\"3 3\"\n            />\n          ) : null}\n        </svg>\n      ) : null}\n    </div>\n  );\n};\n", "import React, { useEffect, useRef } from 'react';\nimport { FabricImage, Point, type FabricObject, type TPointerEventInfo } from 'fabric';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport {\n  fabricImageObjectToImageData,\n  imageDataHasOpaquePixels,\n  imageDataToCanvas,\n  scenePointToImagePixels,\n} from '../../utils/magicWandSelection';\n\nfunction isFabricImage(obj: FabricObject | null | undefined): obj is FabricImage {\n  return !!obj && (obj.type || '').toLowerCase() === 'image';\n}\n\nfunction eraseCircle(\n  imageData: ImageData,\n  cx: number,\n  cy: number,\n  radius: number,\n) {\n  const { width, height, data } = imageData;\n  const r = Math.max(0.5, radius);\n  const r2 = r * r;\n  const x0 = Math.max(0, Math.floor(cx - r));\n  const y0 = Math.max(0, Math.floor(cy - r));\n  const x1 = Math.min(width - 1, Math.ceil(cx + r));\n  const y1 = Math.min(height - 1, Math.ceil(cy + r));\n  for (let y = y0; y <= y1; y++) {\n    for (let x = x0; x <= x1; x++) {\n      const dx = x + 0.5 - cx;\n      const dy = y + 0.5 - cy;\n      if (dx * dx + dy * dy > r2) continue;\n      data[((y * width + x) * 4) + 3] = 0;\n    }\n  }\n}\n\n/**\n * Soft pixel eraser on the active / clicked Fabric image.\n */\nexport const PixelEraserOverlay: React.FC = () => {\n  const { activeTool, canvasInstance, brushSettings, addToast } = useEditorStore();\n  const paintingRef = useRef(false);\n  const imgRef = useRef<FabricImage | null>(null);\n  const imageDataRef = useRef<ImageData | null>(null);\n  const lastRef = useRef<{ x: number; y: number } | null>(null);\n\n  useEffect(() => {\n    const canvas = canvasInstance;\n    if (!canvas || activeTool !== 'eraser') return;\n\n    const commitRaster = () => {\n      const img = imgRef.current;\n      const imageData = imageDataRef.current;\n      if (!img || !imageData) return;\n      const el = imageDataToCanvas(imageData);\n      img.setElement(el);\n      img.set({ dirty: true });\n      img.setCoords();\n      canvas.requestRenderAll();\n    };\n\n    const paintAt = (sceneX: number, sceneY: number) => {\n      const img = imgRef.current;\n      const imageData = imageDataRef.current;\n      if (!img || !imageData) return;\n      const mapped = scenePointToImagePixels(img, sceneX, sceneY);\n      if (!mapped) return;\n      const px = (mapped.px / mapped.width) * imageData.width;\n      const py = (mapped.py / mapped.height) * imageData.height;\n      const radiusImg =\n        (Math.max(1, brushSettings.width) / 2) /\n        Math.max(0.001, Math.abs(img.scaleX || 1)) *\n        (imageData.width / Math.max(1, img.width || 1));\n      eraseCircle(imageData, px, py, radiusImg);\n      commitRaster();\n    };\n\n    const resolveImage = (e: MouseEvent, target?: FabricObject | null): FabricImage | null => {\n      if (isFabricImage(target)) return target;\n      const scene = canvas.getScenePoint(e);\n      const point = new Point(scene.x, scene.y);\n      const active = canvas.getActiveObject();\n      if (isFabricImage(active) && active.containsPoint?.(point)) return active;\n      for (let i = canvas.getObjects().length - 1; i >= 0; i--) {\n        const o = canvas.getObjects()[i];\n        if (!isFabricImage(o) || !o.visible) continue;\n        if ((o as FabricObject & { name?: string }).name === 'clone-stamp-layer') continue;\n        if (o.containsPoint?.(point)) return o;\n      }\n      return null;\n    };\n\n    const onDown = (opt: TPointerEventInfo) => {\n      const e = opt.e as MouseEvent;\n      if (e.button !== 0) return;\n      e.preventDefault();\n      const img = resolveImage(e, opt.target ?? null);\n      if (!img) return;\n\n      const imageData = fabricImageObjectToImageData(img);\n      if (!imageDataHasOpaquePixels(imageData)) {\n        addToast(\n          'No se pueden leer los p\u00EDxeles de esta imagen (CORS o imagen vac\u00EDa).',\n          'error',\n        );\n        return;\n      }\n\n      canvas.setActiveObject(img);\n      useEditorStore.getState().setActiveObject(img);\n      imgRef.current = img;\n      imageDataRef.current = imageData;\n      paintingRef.current = true;\n      const scene = canvas.getScenePoint(e);\n      lastRef.current = { x: scene.x, y: scene.y };\n      paintAt(scene.x, scene.y);\n    };\n\n    const onMove = (opt: TPointerEventInfo) => {\n      if (!paintingRef.current || !lastRef.current) return;\n      const scene = canvas.getScenePoint(opt.e as MouseEvent);\n      const spacing = Math.max(1, brushSettings.width / 3);\n      const dx = scene.x - lastRef.current.x;\n      const dy = scene.y - lastRef.current.y;\n      const dist = Math.hypot(dx, dy);\n      if (dist < spacing) return;\n      const steps = Math.max(1, Math.floor(dist / spacing));\n      for (let i = 1; i <= steps; i++) {\n        paintAt(\n          lastRef.current.x + (dx * i) / steps,\n          lastRef.current.y + (dy * i) / steps,\n        );\n      }\n      lastRef.current = { x: scene.x, y: scene.y };\n    };\n\n    const onUp = () => {\n      if (!paintingRef.current) return;\n      paintingRef.current = false;\n      lastRef.current = null;\n      imgRef.current = null;\n      imageDataRef.current = null;\n      useEditorStore.getState().saveHistoryState();\n      useEditorStore.getState().syncLayers();\n    };\n\n    canvas.on('mouse:down', onDown);\n    canvas.on('mouse:move', onMove);\n    canvas.on('mouse:up', onUp);\n    return () => {\n      canvas.off('mouse:down', onDown);\n      canvas.off('mouse:move', onMove);\n      canvas.off('mouse:up', onUp);\n      paintingRef.current = false;\n    };\n  }, [canvasInstance, activeTool, brushSettings.width, addToast]);\n\n  return null;\n};\n", "import React, { useEffect, useRef } from 'react';\nimport type { TPointerEventInfo } from 'fabric';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { getActiveMessages } from '../../i18n';\nimport {\n  cssColorToMaskGray,\n  expandPixelLayerToIncludeRect,\n  hasLayerMask,\n  isPixelLayer,\n  refreshPixelLayerDisplay,\n  sceneToLayerPixel,\n  syncPixelLayerInteraction,\n  type PixelLayerImage,\n} from '../../utils/pixelLayer';\n\n/**\n * Live mask painting: stamps grayscale dabs while dragging so the composite\n * updates immediately (no wait until path:created).\n */\nexport const MaskPaintOverlay: React.FC = () => {\n  const activeTool = useEditorStore((s) => s.activeTool);\n  const layerPaintTarget = useEditorStore((s) => s.layerPaintTarget);\n  const canvasInstance = useEditorStore((s) => s.canvasInstance);\n  const brushSettings = useEditorStore((s) => s.brushSettings);\n  const masterColors = useEditorStore((s) => s.masterColors);\n\n  const paintingRef = useRef(false);\n  const layerRef = useRef<PixelLayerImage | null>(null);\n  const lastRef = useRef<{ x: number; y: number } | null>(null);\n  const dirtyRef = useRef<{ x: number; y: number; w: number; h: number } | null>(null);\n  const rafRef = useRef<number | null>(null);\n  const savedSkipRef = useRef(false);\n  const savedSelectionRef = useRef(true);\n\n  useEffect(() => {\n    const canvas = canvasInstance;\n    // Layer-mask paint uses the brush tool. Magic Eraser is a separate AI tool\n    // (content marks), not a brush style \u2014 do not mix the two here.\n    if (!canvas || activeTool !== 'brush' || layerPaintTarget !== 'mask') return;\n\n    // Avoid Fabric dragging the layer while painting the mask.\n    savedSkipRef.current = canvas.skipTargetFind;\n    savedSelectionRef.current = canvas.selection;\n    canvas.skipTargetFind = true;\n    canvas.selection = false;\n\n    const flushDirty = (layer: PixelLayerImage) => {\n      const dirty = dirtyRef.current;\n      dirtyRef.current = null;\n      if (dirty) refreshPixelLayerDisplay(layer, dirty);\n      else refreshPixelLayerDisplay(layer);\n      canvas.requestRenderAll();\n    };\n\n    const scheduleRefresh = (layer: PixelLayerImage) => {\n      if (rafRef.current != null) return;\n      rafRef.current = requestAnimationFrame(() => {\n        rafRef.current = null;\n        flushDirty(layer);\n      });\n    };\n\n    const unionDirty = (x: number, y: number, r: number) => {\n      const pad = r + 1;\n      const nx = x - pad;\n      const ny = y - pad;\n      const nw = pad * 2;\n      const nh = pad * 2;\n      const cur = dirtyRef.current;\n      if (!cur) {\n        dirtyRef.current = { x: nx, y: ny, w: nw, h: nh };\n        return;\n      }\n      const x0 = Math.min(cur.x, nx);\n      const y0 = Math.min(cur.y, ny);\n      const x1 = Math.max(cur.x + cur.w, nx + nw);\n      const y1 = Math.max(cur.y + cur.h, ny + nh);\n      dirtyRef.current = { x: x0, y: y0, w: x1 - x0, h: y1 - y0 };\n    };\n\n    const stampDab = (layer: PixelLayerImage, sceneX: number, sceneY: number) => {\n      if (!layer.weMaskCanvas) return;\n      const local = sceneToLayerPixel(layer, sceneX, sceneY);\n      const sx = Math.max(0.001, Math.abs(layer.scaleX || 1));\n      const radius = Math.max(0.5, brushSettings.width / 2 / sx);\n      const prevW = layer.weMaskCanvas.width;\n      const prevH = layer.weMaskCanvas.height;\n      expandPixelLayerToIncludeRect(layer, {\n        x: local.x - radius,\n        y: local.y - radius,\n        w: radius * 2,\n        h: radius * 2,\n      });\n      const mask = layer.weMaskCanvas;\n      if (!mask) return;\n      // Canvas grew \u2014 discard dirty rect; expand already recomposited fully.\n      if (mask.width !== prevW || mask.height !== prevH) {\n        dirtyRef.current = null;\n      }\n      const mapped = sceneToLayerPixel(layer, sceneX, sceneY);\n      const ctx = mask.getContext('2d');\n      if (!ctx) return;\n\n      const gray = cssColorToMaskGray(\n        masterColors.fill || brushSettings.color || '#ffffff',\n      );\n      const opacity = Math.min(1, Math.max(0, brushSettings.opacity ?? 1));\n\n      ctx.save();\n      ctx.globalAlpha = opacity;\n      ctx.fillStyle = gray;\n      ctx.beginPath();\n      ctx.arc(mapped.x, mapped.y, radius, 0, Math.PI * 2);\n      ctx.fill();\n      ctx.restore();\n\n      unionDirty(mapped.x, mapped.y, radius);\n      scheduleRefresh(layer);\n    };\n\n    const paintAlong = (sceneX: number, sceneY: number) => {\n      const layer = layerRef.current;\n      if (!layer) return;\n      const last = lastRef.current;\n      if (!last) {\n        stampDab(layer, sceneX, sceneY);\n        lastRef.current = { x: sceneX, y: sceneY };\n        return;\n      }\n      const dx = sceneX - last.x;\n      const dy = sceneY - last.y;\n      const dist = Math.hypot(dx, dy);\n      const spacing = Math.max(1, brushSettings.width / 3);\n      if (dist < spacing) return;\n      const steps = Math.max(1, Math.floor(dist / spacing));\n      for (let i = 1; i <= steps; i++) {\n        const t = i / steps;\n        stampDab(layer, last.x + dx * t, last.y + dy * t);\n      }\n      lastRef.current = { x: sceneX, y: sceneY };\n    };\n\n    const onDown = (opt: TPointerEventInfo) => {\n      const e = opt.e as MouseEvent;\n      if (e.button !== 0) return;\n      e.preventDefault();\n\n      const store = useEditorStore.getState();\n      const layer = store.resolvePaintTargetLayer();\n      if (!layer || !isPixelLayer(layer) || !hasLayerMask(layer)) {\n        store.addToast(getActiveMessages().layers.mustSelectLayer, 'warning');\n        return;\n      }\n\n      paintingRef.current = true;\n      layerRef.current = layer;\n      lastRef.current = null;\n      dirtyRef.current = null;\n      // Full composite once so dirty-rect updates have a valid base.\n      refreshPixelLayerDisplay(layer);\n      const scene = canvas.getScenePoint(e);\n      paintAlong(scene.x, scene.y);\n    };\n\n    const onMove = (opt: TPointerEventInfo) => {\n      if (!paintingRef.current) return;\n      const e = opt.e as MouseEvent;\n      const scene = canvas.getScenePoint(e);\n      paintAlong(scene.x, scene.y);\n    };\n\n    const onUp = () => {\n      if (!paintingRef.current) return;\n      paintingRef.current = false;\n      const layer = layerRef.current;\n      if (layer) {\n        if (rafRef.current != null) {\n          cancelAnimationFrame(rafRef.current);\n          rafRef.current = null;\n        }\n        flushDirty(layer);\n        syncPixelLayerInteraction(layer);\n        useEditorStore.getState().syncLayers();\n        useEditorStore.getState().saveHistoryState();\n      }\n      layerRef.current = null;\n      lastRef.current = null;\n      dirtyRef.current = null;\n    };\n\n    canvas.on('mouse:down', onDown);\n    canvas.on('mouse:move', onMove);\n    canvas.on('mouse:up', onUp);\n    canvas.on('mouse:out', onUp);\n\n    return () => {\n      canvas.off('mouse:down', onDown);\n      canvas.off('mouse:move', onMove);\n      canvas.off('mouse:up', onUp);\n      canvas.off('mouse:out', onUp);\n      canvas.skipTargetFind = savedSkipRef.current;\n      canvas.selection = savedSelectionRef.current;\n      if (rafRef.current != null) cancelAnimationFrame(rafRef.current);\n      paintingRef.current = false;\n      layerRef.current = null;\n    };\n  }, [\n    canvasInstance,\n    activeTool,\n    layerPaintTarget,\n    brushSettings.width,\n    brushSettings.opacity,\n    brushSettings.color,\n    masterColors.fill,\n  ]);\n\n  return null;\n};\n", "import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FabricImage, type FabricObject } from 'fabric';\nimport { isPixelSelectionTool, useEditorStore } from '../../store/useEditorStore';\nimport {\n  extractMaskEdges,\n  paintMarchingAnts,\n} from '../../utils/magicWandSelection';\nimport { buildOverlayCoordMap } from '../../utils/overlayCoords';\n\n/**\n * Photoshop-style marching ants over the current pixel selection mask.\n */\nexport const PixelSelectionMarchingAnts: React.FC = () => {\n  const { activeTool, canvasInstance, zoom, magicWandSelection } = useEditorStore();\n  const [hostEl, setHostEl] = useState<HTMLDivElement | null>(null);\n  const hostRef = useCallback((node: HTMLDivElement | null) => {\n    setHostEl(node);\n  }, []);\n  const canvasRef = useRef<HTMLCanvasElement | null>(null);\n  const edgesRef = useRef<Uint8Array | null>(null);\n  const offsetRef = useRef(0);\n  const rafRef = useRef<number | null>(null);\n\n  const show =\n    isPixelSelectionTool(activeTool) ||\n    activeTool === 'select' ||\n    activeTool === 'move-only';\n\n  const overlayStyle = useMemo(() => {\n    if (!magicWandSelection || !canvasInstance || !show) return null;\n    const img = canvasInstance.getObjects().find(\n      (o) => (o as FabricObject & { id?: string }).id === magicWandSelection.objectId,\n    ) as FabricImage | undefined;\n    if (!img) return null;\n    const br = img.getBoundingRect();\n    const map = buildOverlayCoordMap(canvasInstance, hostEl);\n    const scale = map?.scale ?? zoom ?? 1;\n    const ox = map?.ox ?? 0;\n    const oy = map?.oy ?? 0;\n    return {\n      left: ox + br.left * scale,\n      top: oy + br.top * scale,\n      width: br.width * scale,\n      height: br.height * scale,\n    };\n  }, [magicWandSelection, canvasInstance, zoom, activeTool, show, hostEl]);\n\n  useEffect(() => {\n    if (!magicWandSelection) {\n      edgesRef.current = null;\n      return;\n    }\n    edgesRef.current = extractMaskEdges(\n      magicWandSelection.maskData,\n      magicWandSelection.width,\n      magicWandSelection.height,\n    );\n  }, [magicWandSelection]);\n\n  useEffect(() => {\n    const el = canvasRef.current;\n    if (!el || !magicWandSelection || !overlayStyle || !show) {\n      if (rafRef.current != null) {\n        cancelAnimationFrame(rafRef.current);\n        rafRef.current = null;\n      }\n      return;\n    }\n\n    const w = magicWandSelection.width;\n    const h = magicWandSelection.height;\n    el.width = w;\n    el.height = h;\n    const ctx = el.getContext('2d', { willReadFrequently: true });\n    if (!ctx) return;\n\n    let last = 0;\n    const tick = (t: number) => {\n      if (t - last >= 40) {\n        last = t;\n        offsetRef.current = (offsetRef.current + 1) % 8;\n        const edges = edgesRef.current;\n        if (edges) {\n          ctx.clearRect(0, 0, w, h);\n          paintMarchingAnts(ctx, edges, w, h, offsetRef.current, 8);\n        }\n      }\n      rafRef.current = requestAnimationFrame(tick);\n    };\n    rafRef.current = requestAnimationFrame(tick);\n\n    return () => {\n      if (rafRef.current != null) {\n        cancelAnimationFrame(rafRef.current);\n        rafRef.current = null;\n      }\n    };\n  }, [magicWandSelection, overlayStyle, activeTool, show]);\n\n  if (!show) return null;\n\n  return (\n    <div ref={hostRef} className=\"pointer-events-none absolute inset-0 z-10 overflow-visible\">\n      {magicWandSelection && overlayStyle ? (\n        <canvas\n          ref={canvasRef}\n          className=\"pointer-events-none absolute\"\n          style={{\n            left: overlayStyle.left,\n            top: overlayStyle.top,\n            width: overlayStyle.width,\n            height: overlayStyle.height,\n            imageRendering: 'pixelated',\n          }}\n          aria-hidden\n        />\n      ) : null}\n    </div>\n  );\n};\n", "import React from 'react';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { useTranslation } from '../../i18n';\nimport { TextBody, TextTitle } from '../ui';\n\ntype BrushRadiusPopupProps = {\n  x: number;\n  y: number;\n  onClose: () => void;\n};\n\nexport const BrushRadiusPopup: React.FC<BrushRadiusPopupProps> = ({ x, y, onClose }) => {\n  const t = useTranslation();\n  const { brushSettings, updateBrushSettings } = useEditorStore();\n  const radius = Math.max(1, Math.round(brushSettings.width));\n\n  return (\n    <>\n      <div className=\"fixed inset-0 z-50 cursor-default\" onClick={onClose} onContextMenu={(e) => { e.preventDefault(); onClose(); }} />\n      <div\n        className=\"fixed z-50 w-52 rounded-xl border border-panel-border bg-panel backdrop-blur-md shadow-2xl p-3 flex flex-col gap-2.5\"\n        style={{\n          left: Math.min(x, window.innerWidth - 220),\n          top: Math.min(y, window.innerHeight - 120),\n        }}\n        onMouseDown={(e) => e.stopPropagation()}\n      >\n        <TextTitle as=\"h3\" size=\"xs\" className=\"text-center uppercase tracking-wider text-[var(--we-accent)]\">\n          {t.canvas.brush.radiusPopupTitle}\n        </TextTitle>\n        <input\n          type=\"range\"\n          min={1}\n          max={200}\n          value={radius}\n          onChange={(e) => updateBrushSettings({ width: parseInt(e.target.value, 10) || 1 })}\n          className=\"w-full h-1 bg-black-capsule rounded-full appearance-none cursor-pointer accent-[var(--we-accent)]\"\n          aria-label={t.canvas.brush.radiusSlider}\n        />\n        <div className=\"flex items-center gap-2\">\n          <TextBody as=\"span\" size=\"sm\" className=\"shrink-0 font-semibold text-white/80\">\n            {t.canvas.brush.radiusInput}\n          </TextBody>\n          <input\n            type=\"number\"\n            min={1}\n            max={500}\n            value={radius}\n            onChange={(e) => {\n              const next = Math.max(1, Math.min(500, parseInt(e.target.value, 10) || 1));\n              updateBrushSettings({ width: next });\n            }}\n            className=\"flex-1 min-w-0 h-7 bg-black-capsule border border-panel-border rounded-md px-2 font-sans text-xs font-medium text-white font-mono font-bold text-center focus:outline-none focus:border-[var(--we-accent)]\"\n          />\n          <TextBody as=\"span\" size=\"sm\" className=\"font-mono text-white/70\">\n            px\n          </TextBody>\n        </div>\n      </div>\n    </>\n  );\n};\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { isBrushRadiusTool, useEditorStore } from '../../store/useEditorStore';\nimport { TextBody } from '../ui';\n\nconst PREVIEW_MS = 750;\n\n/**\n * Center-screen brush diameter preview when width changes\n * (brush / clone-stamp / eraser panels or right-click radius popup).\n */\nexport const BrushSizeCenterPreview: React.FC = () => {\n  const { activeTool, brushSettings, zoom } = useEditorStore();\n  const [visible, setVisible] = useState(false);\n  const prevWidthRef = useRef(brushSettings.width);\n  const hideTimerRef = useRef<number | null>(null);\n\n  useEffect(() => {\n    if (!isBrushRadiusTool(activeTool)) {\n      setVisible(false);\n      prevWidthRef.current = brushSettings.width;\n      return;\n    }\n\n    if (prevWidthRef.current === brushSettings.width) return;\n    prevWidthRef.current = brushSettings.width;\n\n    setVisible(true);\n    if (hideTimerRef.current != null) window.clearTimeout(hideTimerRef.current);\n    hideTimerRef.current = window.setTimeout(() => {\n      setVisible(false);\n      hideTimerRef.current = null;\n    }, PREVIEW_MS);\n\n    return () => {\n      if (hideTimerRef.current != null) {\n        window.clearTimeout(hideTimerRef.current);\n        hideTimerRef.current = null;\n      }\n    };\n  }, [brushSettings.width, activeTool]);\n\n  if (!visible || !isBrushRadiusTool(activeTool)) return null;\n\n  const diameter = Math.max(4, Math.round(brushSettings.width * (zoom || 1)));\n  const label = `${Math.round(brushSettings.width)} px`;\n\n  return (\n    <div\n      className=\"pointer-events-none fixed inset-0 z-[70] flex items-center justify-center\"\n      aria-hidden\n    >\n      <div className=\"relative flex flex-col items-center gap-2\">\n        <div\n          className=\"rounded-full border-2 border-white shadow-[0_0_0_1px_rgba(0,0,0,0.55),0_8px_28px_rgba(0,0,0,0.45)] bg-[color-mix(in_srgb,var(--we-accent)_22%,transparent)]\"\n          style={{ width: diameter, height: diameter }}\n        />\n        <TextBody\n          as=\"span\"\n          size=\"sm\"\n          className=\"rounded-md border border-panel-border bg-panel/95 px-2 py-0.5 font-mono font-bold text-white shadow-lg backdrop-blur-sm\"\n        >\n          {label}\n        </TextBody>\n      </div>\n    </div>\n  );\n};\n", "import { Group, Rect, Circle, Polygon, Path, Textbox, Shadow } from 'fabric';\n\n// Helper to get star polygon points\nconst getStarPoints = (centerX: number, centerY: number, points: number, outerRadius: number, innerRadius: number) => {\n  const result = [];\n  const angle = Math.PI / points;\n  for (let i = 0; i < 2 * points; i++) {\n    const r = (i & 1) === 0 ? outerRadius : innerRadius;\n    const currX = centerX + Math.cos(i * angle - Math.PI / 2) * r;\n    const currY = centerY + Math.sin(i * angle - Math.PI / 2) * r;\n    result.push({ x: currX, y: currY });\n  }\n  return result;\n};\n\n// Helper for hexagon points\nconst getHexagonPoints = (radius: number) => {\n  const points = [];\n  for (let i = 0; i < 6; i++) {\n    const angle_deg = 60 * i - 30;\n    const angle_rad = Math.PI / 180 * angle_deg;\n    points.push({\n      x: radius * Math.cos(angle_rad),\n      y: radius * Math.sin(angle_rad)\n    });\n  }\n  return points;\n};\n\nexport const createFrame = (tool: string, centerX: number, centerY: number): Group | null => {\n  if (!tool.startsWith('frame-')) return null;\n\n  let elements: any[] = [];\n  let groupLeft = centerX;\n  let groupTop = centerY;\n\n  // Reusable styling\n  const bezelColor = '#18181b'; // dark-900\n  const bezelStroke = '#3f3f46'; // dark-700\n  const placeColor = '#d4d4d8'; // zinc-300\n\n  switch (tool) {\n    // --- DEVICES ---\n    case 'frame-mobile': {\n      const bezel = new Rect({ width: 140, height: 280, fill: bezelColor, rx: 20, ry: 20, stroke: bezelStroke, strokeWidth: 4 });\n      const notch = new Rect({ width: 40, height: 10, left: 50, top: 12, fill: bezelStroke, rx: 5, ry: 5 });\n      const placeholder = new Rect({ width: 124, height: 254, left: 8, top: 13, fill: placeColor, rx: 12, ry: 12, name: 'frame-placeholder' });\n      elements = [bezel, notch, placeholder];\n      groupLeft = centerX - 70; groupTop = centerY - 140;\n      break;\n    }\n    case 'frame-ipad': {\n      const bezel = new Rect({ width: 280, height: 380, fill: bezelColor, rx: 16, ry: 16, stroke: bezelStroke, strokeWidth: 3 });\n      const camera = new Circle({ radius: 3, fill: bezelStroke, left: 137, top: 8 });\n      const placeholder = new Rect({ width: 256, height: 356, left: 12, top: 12, fill: placeColor, rx: 6, ry: 6, name: 'frame-placeholder' });\n      elements = [bezel, camera, placeholder];\n      groupLeft = centerX - 140; groupTop = centerY - 190;\n      break;\n    }\n    case 'frame-laptop': {\n      const bezel = new Rect({ width: 400, height: 250, fill: bezelColor, rx: 12, ry: 12, stroke: bezelStroke, strokeWidth: 2 });\n      const camera = new Circle({ radius: 2, fill: bezelStroke, left: 198, top: 6 });\n      const keyboard = new Path('M -20 250 L 10 265 H 390 L 420 250 Z', { fill: '#27272a', stroke: bezelStroke, strokeWidth: 1 });\n      const placeholder = new Rect({ width: 384, height: 230, left: 8, top: 10, fill: placeColor, rx: 4, ry: 4, name: 'frame-placeholder' });\n      elements = [bezel, camera, keyboard, placeholder];\n      groupLeft = centerX - 200; groupTop = centerY - 130;\n      break;\n    }\n    case 'frame-desktop': {\n      const bezel = new Rect({ width: 480, height: 300, fill: bezelColor, rx: 8, ry: 8, stroke: bezelStroke, strokeWidth: 2 });\n      const chin = new Rect({ width: 480, height: 40, top: 300, fill: '#27272a', rx: 0, ry: 0 });\n      const stand = new Rect({ width: 80, height: 60, left: 200, top: 340, fill: '#3f3f46' });\n      const standBase = new Rect({ width: 140, height: 10, left: 170, top: 400, fill: '#52525b', rx: 5, ry: 5 });\n      const placeholder = new Rect({ width: 460, height: 280, left: 10, top: 10, fill: placeColor, name: 'frame-placeholder' });\n      elements = [bezel, chin, stand, standBase, placeholder];\n      groupLeft = centerX - 240; groupTop = centerY - 200;\n      break;\n    }\n    case 'frame-watch': {\n      const strapTop = new Rect({ width: 70, height: 40, left: 15, top: -30, fill: '#27272a', rx: 5, ry: 5 });\n      const strapBot = new Rect({ width: 70, height: 40, left: 15, top: 110, fill: '#27272a', rx: 5, ry: 5 });\n      const bezel = new Rect({ width: 100, height: 120, fill: bezelColor, rx: 24, ry: 24, stroke: '#52525b', strokeWidth: 4 });\n      const crown = new Rect({ width: 8, height: 20, left: 102, top: 30, fill: '#52525b', rx: 4, ry: 4 });\n      const placeholder = new Rect({ width: 84, height: 104, left: 8, top: 8, fill: placeColor, rx: 16, ry: 16, name: 'frame-placeholder' });\n      elements = [strapTop, strapBot, bezel, crown, placeholder];\n      groupLeft = centerX - 50; groupTop = centerY - 60;\n      break;\n    }\n\n    // --- PHYSICAL MEDIA ---\n    case 'frame-polaroid': {\n      const card = new Rect({ width: 220, height: 265, fill: '#ffffff', rx: 4, ry: 4, shadow: new Shadow({ color: 'rgba(0,0,0,0.1)', blur: 15, offsetX: 5, offsetY: 5 }) });\n      const placeholder = new Rect({ width: 196, height: 196, left: 12, top: 12, fill: placeColor, name: 'frame-placeholder' });\n      elements = [card, placeholder];\n      groupLeft = centerX - 110; groupTop = centerY - 132;\n      break;\n    }\n    case 'frame-polaroid-scatter': {\n      const card1 = new Rect({ width: 180, height: 215, fill: '#ffffff', rx: 4, ry: 4, angle: -8, shadow: new Shadow({ color: 'rgba(0,0,0,0.1)', blur: 10, offsetX: -2, offsetY: 5 }) });\n      const place1 = new Rect({ width: 160, height: 160, left: 10, top: 10, fill: '#e4e4e7', angle: -8, name: 'frame-placeholder-bg' }); // Bg just for visual\n      \n      const card2 = new Rect({ width: 180, height: 215, left: 40, top: 20, fill: '#ffffff', rx: 4, ry: 4, angle: 6, shadow: new Shadow({ color: 'rgba(0,0,0,0.15)', blur: 12, offsetX: 4, offsetY: 6 }) });\n      // We only use ONE official placeholder for the drag-to-fit to target (the front one)\n      const placeholder = new Rect({ width: 160, height: 160, left: 48, top: 32, fill: placeColor, angle: 6, name: 'frame-placeholder' });\n      \n      elements = [card1, place1, card2, placeholder];\n      groupLeft = centerX - 110; groupTop = centerY - 120;\n      break;\n    }\n    case 'frame-billboard': {\n      const pole1 = new Rect({ width: 16, height: 100, left: 40, top: 200, fill: '#3f3f46' });\n      const pole2 = new Rect({ width: 16, height: 100, left: 344, top: 200, fill: '#3f3f46' });\n      const board = new Rect({ width: 400, height: 200, fill: '#18181b', rx: 4, ry: 4 });\n      const placeholder = new Rect({ width: 380, height: 180, left: 10, top: 10, fill: placeColor, name: 'frame-placeholder' });\n      elements = [pole1, pole2, board, placeholder];\n      groupLeft = centerX - 200; groupTop = centerY - 150;\n      break;\n    }\n    case 'frame-poster': {\n      const tapeTop = new Rect({ width: 40, height: 14, left: 80, top: -7, fill: '#fef08a', opacity: 0.7, angle: -3 });\n      const tapeBot = new Rect({ width: 40, height: 14, left: 90, top: 295, fill: '#fef08a', opacity: 0.7, angle: 4 });\n      const placeholder = new Rect({ width: 200, height: 300, fill: placeColor, shadow: new Shadow({ color: 'rgba(0,0,0,0.1)', blur: 8, offsetX: 0, offsetY: 8 }), ...{ name: 'frame-placeholder' } as any });\n      elements = [placeholder, tapeTop, tapeBot];\n      groupLeft = centerX - 100; groupTop = centerY - 150;\n      break;\n    }\n    case 'frame-business-card': {\n      const card = new Rect({ width: 300, height: 168, fill: '#ffffff', rx: 8, ry: 8, shadow: new Shadow({ color: 'rgba(0,0,0,0.1)', blur: 12, offsetX: 5, offsetY: 5 }) });\n      const placeholder = new Rect({ width: 300, height: 168, fill: placeColor, rx: 8, ry: 8, name: 'frame-placeholder' }); // The whole card is the placeholder\n      elements = [card, placeholder];\n      groupLeft = centerX - 150; groupTop = centerY - 84;\n      break;\n    }\n\n    // --- WEB & UI ---\n    case 'frame-browser': {\n      const windowObj = new Rect({ width: 500, height: 320, fill: '#ffffff', rx: 8, ry: 8, stroke: '#e4e4e7', strokeWidth: 1, shadow: new Shadow({ color: 'rgba(0,0,0,0.15)', blur: 20, offsetX: 0, offsetY: 10 }) });\n      const topBar = new Rect({ width: 500, height: 36, fill: '#f4f4f5', rx: 8, ry: 8 });\n      // Cover bottom radius of top bar\n      const topBarCover = new Rect({ width: 500, height: 18, top: 18, fill: '#f4f4f5' });\n      const dot1 = new Circle({ radius: 5, left: 16, top: 13, fill: '#ef4444' });\n      const dot2 = new Circle({ radius: 5, left: 34, top: 13, fill: '#f59e0b' });\n      const dot3 = new Circle({ radius: 5, left: 52, top: 13, fill: '#22c55e' });\n      const searchBar = new Rect({ width: 300, height: 20, left: 100, top: 8, fill: '#ffffff', rx: 4, ry: 4, stroke: '#e4e4e7', strokeWidth: 1 });\n      const placeholder = new Rect({ width: 500, height: 284, top: 36, fill: placeColor, name: 'frame-placeholder' });\n      elements = [windowObj, topBar, topBarCover, dot1, dot2, dot3, searchBar, placeholder];\n      groupLeft = centerX - 250; groupTop = centerY - 160;\n      break;\n    }\n    case 'frame-video-player': {\n      const player = new Rect({ width: 480, height: 270, fill: '#000000', rx: 8, ry: 8 });\n      const placeholder = new Rect({ width: 480, height: 270, fill: placeColor, rx: 8, ry: 8, name: 'frame-placeholder' });\n      const controlsBg = new Rect({ width: 480, height: 40, top: 230, fill: 'rgba(0,0,0,0.6)' });\n      const playBtn = new Polygon([{x:0, y:0}, {x:12, y:8}, {x:0, y:16}], { left: 16, top: 242, fill: '#ffffff' });\n      const progressTrack = new Rect({ width: 380, height: 4, left: 45, top: 248, fill: '#52525b', rx: 2, ry: 2 });\n      const progressBar = new Rect({ width: 120, height: 4, left: 45, top: 248, fill: '#ef4444', rx: 2, ry: 2 });\n      elements = [player, placeholder, controlsBg, playBtn, progressTrack, progressBar];\n      groupLeft = centerX - 240; groupTop = centerY - 135;\n      break;\n    }\n    case 'frame-chat': {\n      // iMessage-like bubble (removed unused variable)\n      const placeholder = new Path('M 20 0 H 200 C 211 0 220 9 220 20 V 100 C 220 111 211 120 200 120 H 40 C 29 120 20 111 20 100 V 20 C 20 9 11 0 0 0 Z', { fill: placeColor, ...{ name: 'frame-placeholder' } as any });\n      // Text hint\n      const text = new Textbox('Arrastra imagen aqu\u00ED', { left: 40, top: 50, fontSize: 16, fill: '#ffffff', fontFamily: 'Inter', width: 160, textAlign: 'center' });\n      elements = [placeholder, text]; // placeholder acts as the bubble itself\n      groupLeft = centerX - 110; groupTop = centerY - 60;\n      break;\n    }\n\n    // --- ABSTRACT SHAPES ---\n    case 'frame-circle': {\n      const placeholder = new Circle({ radius: 100, fill: placeColor, name: 'frame-placeholder' });\n      elements = [placeholder];\n      groupLeft = centerX - 100; groupTop = centerY - 100;\n      break;\n    }\n    case 'frame-arch': {\n      // Custom Arch SVG\n      const placeholder = new Path('M 0 100 C 0 44.7 44.7 0 100 0 C 155.3 0 200 44.7 200 100 V 250 H 0 V 100 Z', { fill: placeColor, name: 'frame-placeholder' });\n      elements = [placeholder];\n      groupLeft = centerX - 100; groupTop = centerY - 125;\n      break;\n    }\n    case 'frame-hexagon': {\n      const pts = getHexagonPoints(100);\n      const placeholder = new Polygon(pts, { fill: placeColor, ...{ name: 'frame-placeholder' } as any });\n      elements = [placeholder];\n      groupLeft = centerX - 100; groupTop = centerY - 86.6;\n      break;\n    }\n    case 'frame-heart': {\n      // Scaled heart path\n      const path = 'M 0 60 C 0 26.8 26.8 0 60 0 C 80 0 98 10 108 26 C 118 10 136 0 156 0 C 189.2 0 216 26.8 216 60 C 216 110 108 190 108 190 C 108 190 0 110 0 60 Z';\n      const placeholder = new Path(path, { fill: placeColor, name: 'frame-placeholder' });\n      elements = [placeholder];\n      groupLeft = centerX - 108; groupTop = centerY - 95;\n      break;\n    }\n    case 'frame-blob': {\n      const placeholder = new Path('M 40 20 C 75 5, 130 15, 150 60 C 170 105, 140 145, 110 160 C 75 175, 25 160, 15 115 C 5 70, 5 35, 40 20 Z', { fill: placeColor, name: 'frame-placeholder' });\n      elements = [placeholder];\n      groupLeft = centerX - 85; groupTop = centerY - 90;\n      break;\n    }\n    case 'frame-pill': {\n      const placeholder = new Rect({ width: 240, height: 100, rx: 50, ry: 50, fill: placeColor, name: 'frame-placeholder' });\n      elements = [placeholder];\n      groupLeft = centerX - 120; groupTop = centerY - 50;\n      break;\n    }\n    case 'frame-diamond': {\n      const placeholder = new Polygon([{x:100, y:0}, {x:200, y:100}, {x:100, y:200}, {x:0, y:100}], { fill: placeColor, ...{ name: 'frame-placeholder' } as any });\n      elements = [placeholder];\n      groupLeft = centerX - 100; groupTop = centerY - 100;\n      break;\n    }\n    case 'frame-star-pro': {\n      const pts = getStarPoints(0, 0, 8, 100, 60);\n      const placeholder = new Polygon(pts, { fill: placeColor, ...{ name: 'frame-placeholder' } as any });\n      elements = [placeholder];\n      groupLeft = centerX - 100; groupTop = centerY - 100;\n      break;\n    }\n    case 'frame-circle-double': {\n      const outer = new Circle({ radius: 100, fill: 'transparent', stroke: '#ffffff', strokeWidth: 3 });\n      const inner = new Circle({ radius: 92, fill: 'transparent', stroke: '#ffffff', strokeWidth: 2, strokeDashArray: [4, 4], left: 8, top: 8 });\n      const placeholder = new Circle({ radius: 84, fill: placeColor, left: 16, top: 16, name: 'frame-placeholder' });\n      elements = [outer, inner, placeholder];\n      groupLeft = centerX - 100; groupTop = centerY - 100;\n      break;\n    }\n    default:\n      return null;\n  }\n\n  // Create the wrapping group to identify it as a canva-frame\n  const group = new Group(elements, {\n    left: groupLeft,\n    top: groupTop,\n    ...{ name: 'canva-frame' } as any,\n  });\n\n  return group;\n};\n", "import { Path } from 'fabric';\n\nexport const customShapeCategories = {\n  banners: [\n    { id: 'banner-ribbon', name: 'Ribbon', path: 'M 0 20 L 20 0 H 180 L 200 20 L 180 40 H 20 Z' },\n    { id: 'banner-flag', name: 'Flag', path: 'M 0 0 H 200 V 50 L 100 40 L 0 50 Z' },\n    { id: 'banner-tag', name: 'Tag', path: 'M 20 0 H 200 V 60 H 20 L 0 30 Z' },\n    { id: 'banner-classic', name: 'Classic Banner', path: 'M 10 10 L 30 10 L 30 0 L 170 0 L 170 10 L 190 10 L 180 30 L 190 50 L 170 50 L 170 60 L 30 60 L 30 50 L 10 50 L 20 30 Z' },\n    { id: 'banner-pennant', name: 'Pennant', path: 'M 0 0 H 200 L 170 25 L 200 50 H 0 Z' },\n    { id: 'banner-bookmark', name: 'Bookmark', path: 'M 0 0 H 50 V 100 L 25 80 L 0 100 Z' },\n    { id: 'banner-label', name: 'Label', path: 'M 10 0 H 190 A 10 10 0 0 1 200 10 V 40 A 10 10 0 0 1 190 50 H 10 A 10 10 0 0 1 0 40 V 10 A 10 10 0 0 1 10 0 Z' },\n  ],\n  badges: [\n    { id: 'badge-shield', name: 'Shield', path: 'M 0 0 H 100 V 40 C 100 80 50 100 50 100 C 50 100 0 80 0 40 Z' },\n    { id: 'badge-star-burst', name: 'Starburst', path: 'M 50 0 L 61 35 L 98 35 L 68 57 L 79 91 L 50 70 L 21 91 L 32 57 L 2 35 L 39 35 Z' },\n    { id: 'badge-rosette', name: 'Rosette', path: 'M 50 0 A 50 50 0 1 1 49.9 0 Z M 30 90 L 30 140 L 50 120 L 70 140 L 70 90 Z' }, // Circular with ribbons\n    { id: 'badge-seal', name: 'Seal', path: 'M 50 0 L 60 10 L 75 5 L 80 20 L 95 25 L 90 40 L 100 50 L 90 60 L 95 75 L 80 80 L 75 95 L 60 90 L 50 100 L 40 90 L 25 95 L 20 80 L 5 75 L 10 60 L 0 50 L 10 40 L 5 25 L 20 20 L 25 5 L 40 10 Z' },\n    { id: 'badge-hexagon', name: 'Hexagon', path: 'M 50 0 L 93.3 25 L 93.3 75 L 50 100 L 6.7 75 L 6.7 25 Z' },\n    { id: 'badge-octagon', name: 'Octagon', path: 'M 30 0 H 70 L 100 30 V 70 L 70 100 H 30 L 0 70 V 30 Z' },\n    { id: 'badge-award', name: 'Award', path: 'M 50 20 A 30 30 0 1 0 50 80 A 30 30 0 1 0 50 20 M 35 75 L 25 120 L 50 105 L 75 120 L 65 75' },\n  ],\n  callouts: [\n    { id: 'callout-speech', name: 'Speech Bubble', path: 'M 0 20 A 20 20 0 0 1 20 0 H 180 A 20 20 0 0 1 200 20 V 80 A 20 20 0 0 1 180 100 H 60 L 20 130 V 100 H 20 A 20 20 0 0 1 0 80 Z' },\n    { id: 'callout-thought', name: 'Thought Bubble', path: 'M 50 30 C 50 10 80 10 80 30 C 100 20 120 40 110 60 C 130 80 100 100 80 90 C 70 110 40 100 40 80 C 10 90 10 60 30 50 C 10 30 30 10 50 30 Z M 20 110 A 10 10 0 1 1 20 110 M 10 130 A 5 5 0 1 1 10 130' },\n    { id: 'callout-megaphone', name: 'Megaphone', path: 'M 20 40 L 70 20 V 80 L 20 60 Z M 70 15 H 100 V 85 H 70 Z M 20 40 H 0 V 60 H 20 Z' },\n    { id: 'callout-whisper', name: 'Whisper Bubble', path: 'M 20 0 H 180 V 80 H 60 L 20 110 V 80 H 20 Z' }, // A dashed line representation in code usually handled by strokeDashArray\n    { id: 'callout-round', name: 'Round Bubble', path: 'M 100 0 C 155.23 0 200 35.82 200 80 C 200 124.18 155.23 160 100 160 C 78.53 160 58.63 154.54 41.69 145.06 L 0 180 L 15.35 137.96 C 5.56 121.36 0 101.44 0 80 C 0 35.82 44.77 0 100 0 Z' },\n    { id: 'callout-shout', name: 'Shout Bubble', path: 'M 100 0 L 120 30 L 170 20 L 150 60 L 190 90 L 150 110 L 180 160 L 130 140 L 100 180 L 70 140 L 20 160 L 50 110 L 10 90 L 50 60 L 30 20 L 80 30 Z' },\n  ],\n  arrows: [\n    { id: 'arrow-curved', name: 'Curved Arrow', path: 'M 0 100 C 0 50 50 0 100 0 V 20 L 150 -10 L 100 -40 V -20 C 30 -20 -20 40 -20 100 Z' },\n    { id: 'arrow-double', name: 'Double Arrow', path: 'M 30 20 L 0 50 L 30 80 V 60 H 170 V 80 L 200 50 L 170 20 V 40 H 30 Z' },\n    { id: 'arrow-split', name: 'Split Arrow', path: 'M 0 40 H 80 V 0 L 130 50 L 80 100 V 60 H 0 Z' },\n    { id: 'arrow-circle', name: 'Circle Arrow', path: 'M 50 0 A 50 50 0 1 1 0 50 L 20 50 A 30 30 0 1 0 50 20 V 40 L 80 10 L 50 -20 Z' },\n    { id: 'arrow-u-turn', name: 'U-Turn', path: 'M 100 100 V 50 C 100 20 50 20 50 50 V 100 H 30 V 50 C 30 0 120 0 120 50 V 100 H 140 L 110 130 L 80 100 Z' },\n    { id: 'arrow-chevron', name: 'Chevron', path: 'M 0 0 L 50 50 L 0 100 L 20 100 L 70 50 L 20 0 Z' },\n  ],\n  comic: [\n    { id: 'comic-explosion', name: 'Explosion', path: 'M 50 0 L 60 30 L 100 20 L 70 50 L 90 90 L 50 70 L 10 90 L 30 50 L 0 20 L 40 30 Z' },\n    { id: 'comic-splash', name: 'Splash', path: 'M 50 10 C 60 30 80 20 90 40 C 110 50 90 70 100 90 C 80 100 70 80 50 90 C 30 80 20 100 0 90 C 10 70 -10 50 10 40 C 20 20 40 30 50 10 Z' },\n    { id: 'comic-pow', name: 'Pow!', path: 'M 50 0 L 65 25 L 100 15 L 80 40 L 110 60 L 75 75 L 90 100 L 50 85 L 10 100 L 25 75 L -10 60 L 20 40 L 0 15 L 35 25 Z' },\n    { id: 'comic-zap', name: 'Zap', path: 'M 40 0 L 0 60 H 40 L 20 100 L 60 40 H 20 Z' },\n    { id: 'comic-cloud', name: 'Cloud', path: 'M 25 60 C 25 40 40 25 60 25 C 65 10 85 0 105 10 C 120 0 140 10 140 30 C 160 35 160 65 140 70 C 145 90 125 100 105 95 C 90 110 65 105 60 85 C 40 90 25 75 25 60 Z' },\n  ],\n  social: [\n    { id: 'social-heart', name: 'Heart', path: 'M 50 25 C 50 0 0 0 0 25 C 0 50 50 80 50 100 C 50 80 100 50 100 25 C 100 0 50 0 50 25 Z' },\n    { id: 'social-like', name: 'Thumbs Up', path: 'M 30 100 H 0 V 40 H 30 Z M 40 40 V 10 C 40 0 60 0 60 20 V 40 H 90 C 100 40 100 50 90 60 L 80 90 C 75 100 65 100 50 100 H 40 Z' },\n    { id: 'social-share', name: 'Share', path: 'M 80 20 A 20 20 0 1 0 80 30 L 35 55 A 20 20 0 1 0 35 65 L 80 90 A 20 20 0 1 0 85 80 L 40 55 A 20 20 0 1 0 40 45 L 85 20 A 20 20 0 0 0 80 20 Z' },\n    { id: 'social-retweet', name: 'Retweet', path: 'M 10 40 H 70 V 20 L 100 50 L 70 80 V 60 H 30 V 90 H 10 Z M 90 60 H 30 V 80 L 0 50 L 30 20 V 40 H 70 V 10 H 90 Z' }, // Simplified\n    { id: 'social-star', name: 'Star', path: 'M 50 0 L 61 35 H 98 L 68 57 L 79 91 L 50 70 L 21 91 L 32 57 L 2 35 H 39 Z' },\n    { id: 'social-send', name: 'Send/Paper Plane', path: 'M 0 50 L 100 0 L 50 100 L 40 60 Z' },\n  ],\n  icons: [\n    { id: 'icon-check', name: 'Checkmark', path: 'M 10 50 L 40 80 L 90 10 L 80 0 L 40 60 L 20 40 Z' },\n    { id: 'icon-cross', name: 'Cross', path: 'M 10 0 L 50 40 L 90 0 L 100 10 L 60 50 L 100 90 L 90 100 L 50 60 L 10 100 L 0 90 L 40 50 L 0 10 Z' },\n    { id: 'icon-location', name: 'Location Pin', path: 'M 50 0 C 20 0 0 20 0 50 C 0 80 50 130 50 130 C 50 130 100 80 100 50 C 100 20 80 0 50 0 Z M 50 70 C 35 70 25 60 25 45 C 25 30 35 20 50 20 C 65 20 75 30 75 45 C 75 60 65 70 50 70 Z' },\n    { id: 'icon-clock', name: 'Clock', path: 'M 50 0 C 20 0 0 20 0 50 C 0 80 20 100 50 100 C 80 100 100 80 100 50 C 100 20 80 0 50 0 Z M 55 50 H 80 V 60 H 45 V 20 H 55 Z' },\n    { id: 'icon-calendar', name: 'Calendar', path: 'M 10 20 H 90 V 100 H 10 Z M 10 40 H 90 M 30 10 V 30 M 70 10 V 30 M 30 60 H 40 V 70 H 30 Z' },\n    { id: 'icon-music', name: 'Music Note', path: 'M 40 80 A 20 20 0 1 1 20 60 V 0 L 90 20 V 60 A 20 20 0 1 1 70 40 V 30 L 40 10 Z' },\n    { id: 'icon-play', name: 'Play', path: 'M 20 10 L 90 50 L 20 90 Z' },\n  ]\n};\n\n// Helper function to create the custom shape object\nexport const createCustomShape = (shapeId: string, centerX: number, centerY: number, fill: string): any => {\n  let foundShape = null;\n  \n  for (const category of Object.values(customShapeCategories)) {\n    const match = category.find(s => s.id === shapeId);\n    if (match) {\n      foundShape = match;\n      break;\n    }\n  }\n\n  if (!foundShape) return null;\n\n  // Render path\n  const pathObj = new Path(foundShape.path, {\n    fill: fill || '#ef4444', // Default to brand color if not provided\n    name: 'custom-shape',\n  });\n  \n  // Center the path properly based on its inherent bounding box\n  pathObj.set({\n    left: centerX - (pathObj.width * pathObj.scaleX) / 2,\n    top: centerY - (pathObj.height * pathObj.scaleY) / 2,\n  });\n\n  return pathObj;\n};\n", "import { parse as parseOpentypeFont } from 'opentype.js';\nimport { Path } from 'fabric';\n\n\n/**\n * Helper function to convert a Data URL base64 string to an ArrayBuffer\n */\nfunction dataUrlToArrayBuffer(dataUrl: string): ArrayBuffer {\n  const base64 = dataUrl.split(',')[1];\n  const binary_string = window.atob(base64);\n  const len = binary_string.length;\n  const bytes = new Uint8Array(len);\n  for (let i = 0; i < len; i++) {\n    bytes[i] = binary_string.charCodeAt(i);\n  }\n  return bytes.buffer;\n}\n\n/**\n * Converts a text object to vector paths using opentype.js\n * Works best with custom fonts that have been uploaded as data URLs\n */\nexport const convertTextToPath = async (\n  textObj: any,\n  fontDataUrl: string\n): Promise<any> => {\n  try {\n    const arrayBuffer = dataUrlToArrayBuffer(fontDataUrl);\n    const font = parseOpentypeFont(arrayBuffer);\n\n    const text = textObj.text || '';\n    const fontSize = textObj.fontSize || 40;\n    const x = textObj.left;\n    const y = textObj.top + fontSize; // Baseline approximation\n\n    // Get the path from opentype\n    const path = font.getPath(text, x, y, fontSize);\n    const svgData = path.toSVG(2);\n\n    // The svgData is a single <path d=\"...\" /> string\n    // We extract the 'd' attribute\n    const match = svgData.match(/d=\"([^\"]+)\"/);\n    if (match && match[1]) {\n      const pathData = match[1];\n      const fabricPath = new Path(pathData, {\n        fill: textObj.fill,\n        stroke: textObj.stroke,\n        strokeWidth: textObj.strokeWidth,\n        left: textObj.left,\n        top: textObj.top,\n        scaleX: textObj.scaleX,\n        scaleY: textObj.scaleY,\n        angle: textObj.angle,\n        name: 'converted-text-path'\n      });\n      return fabricPath;\n    }\n    return null;\n  } catch (error) {\n    console.error(\"Error converting text to path:\", error);\n    return null;\n  }\n};\n", "import React from 'react';\nimport { DraggableToolPanel } from '../../DraggableToolPanel';\nimport { ColorInput, PanelField, PanelSection, Switch, TextBody } from '../../ui';\nimport { useEditorStore } from '../../../store/useEditorStore';\nimport { useTranslation } from '../../../i18n';\nimport { parseCssColor, rgbaToCss } from '../../../utils/colorRgba';\n\nexport interface CanvasGridPanelProps {\n  anchorRef: React.RefObject<HTMLElement | null>;\n  onClose: () => void;\n}\n\nconst GRID_COLOR_PRESETS = [\n  { key: 'pink' as const, val: 'rgba(236, 72, 153, 0.08)' },\n  { key: 'blue' as const, val: 'rgba(59, 130, 246, 0.08)' },\n  { key: 'red' as const, val: 'rgba(239, 68, 68, 0.08)' },\n  { key: 'gray' as const, val: 'rgba(255, 255, 255, 0.05)' },\n];\n\nexport const CanvasGridPanel: React.FC<CanvasGridPanelProps> = ({\n  anchorRef,\n  onClose,\n}) => {\n  const t = useTranslation();\n  const layoutGridEnabled = useEditorStore((s) => s.layoutGridEnabled);\n  const setLayoutGridEnabled = useEditorStore((s) => s.setLayoutGridEnabled);\n  const layoutGridType = useEditorStore((s) => s.layoutGridType);\n  const setLayoutGridType = useEditorStore((s) => s.setLayoutGridType);\n  const layoutGridColumns = useEditorStore((s) => s.layoutGridColumns);\n  const setLayoutGridColumns = useEditorStore((s) => s.setLayoutGridColumns);\n  const layoutGridGutter = useEditorStore((s) => s.layoutGridGutter);\n  const setLayoutGridGutter = useEditorStore((s) => s.setLayoutGridGutter);\n  const layoutGridMargin = useEditorStore((s) => s.layoutGridMargin);\n  const setLayoutGridMargin = useEditorStore((s) => s.setLayoutGridMargin);\n  const layoutGridSize = useEditorStore((s) => s.layoutGridSize);\n  const setLayoutGridSize = useEditorStore((s) => s.setLayoutGridSize);\n  const layoutGridColor = useEditorStore((s) => s.layoutGridColor);\n  const setLayoutGridColor = useEditorStore((s) => s.setLayoutGridColor);\n\n  const parsed = parseCssColor(layoutGridColor || 'rgba(236, 72, 153, 0.08)');\n  const colorInputValue = rgbaToCss({ ...parsed, a: Math.max(parsed.a, 0.08) });\n\n  const presetLabel = (key: (typeof GRID_COLOR_PRESETS)[number]['key']) => {\n    switch (key) {\n      case 'pink':\n        return t.canvas.gridPanel.colorPink;\n      case 'blue':\n        return t.canvas.gridPanel.colorBlue;\n      case 'red':\n        return t.canvas.gridPanel.colorRed;\n      case 'gray':\n        return t.canvas.gridPanel.colorGray;\n    }\n  };\n\n  return (\n    <DraggableToolPanel\n      panelId=\"canvas-grid\"\n      title={t.canvas.gridPanel.title}\n      anchorRef={anchorRef}\n      onClose={onClose}\n      contentClassName=\"flex flex-col min-w-[320px]\"\n    >\n      <div className=\"flex flex-col gap-3 p-3\">\n        <PanelField\n          label={t.canvas.gridPanel.activate}\n          trailing={\n            <Switch\n              checked={layoutGridEnabled}\n              onChange={setLayoutGridEnabled}\n              ariaLabel={t.canvas.gridPanel.activate}\n            />\n          }\n        />\n\n        <PanelSection title={t.canvas.gridPanel.type}>\n          <div className=\"flex gap-1 rounded-xl bg-black-capsule p-1\">\n            {(\n              [\n                { value: 'columns' as const, label: t.canvas.gridPanel.columns },\n                { value: 'grid' as const, label: t.canvas.gridPanel.modular },\n              ] as const\n            ).map(({ value, label }) => {\n              const active = layoutGridType === value;\n              return (\n                <button\n                  key={value}\n                  type=\"button\"\n                  onClick={() => setLayoutGridType(value)}\n                  className={`flex-1 select-none whitespace-nowrap rounded-lg px-2 py-1.5 transition-colors ${\n                    active\n                      ? 'bg-[var(--we-accent-capsule)] text-white'\n                      : 'text-white/70 hover:bg-black-capsule-hover hover:text-white'\n                  }`}\n                  aria-pressed={active}\n                >\n                  <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-inherit\">\n                    {label}\n                  </TextBody>\n                </button>\n              );\n            })}\n          </div>\n        </PanelSection>\n\n        {layoutGridType === 'columns' ? (\n          <>\n            <PanelField\n              variant=\"slide\"\n              label={t.canvas.gridPanel.columnCount}\n              min={2}\n              max={24}\n              step={1}\n              numericValue={layoutGridColumns}\n              onChange={setLayoutGridColumns}\n            />\n            <PanelField\n              variant=\"slide\"\n              label={t.canvas.gridPanel.gutter}\n              min={0}\n              max={100}\n              step={1}\n              numericValue={layoutGridGutter}\n              onChange={setLayoutGridGutter}\n            />\n            <PanelField\n              variant=\"slide\"\n              label={t.canvas.gridPanel.margin}\n              min={0}\n              max={200}\n              step={1}\n              numericValue={layoutGridMargin}\n              onChange={setLayoutGridMargin}\n            />\n          </>\n        ) : (\n          <PanelField\n            variant=\"slide\"\n            label={t.canvas.gridPanel.gridSize}\n            min={5}\n            max={100}\n            step={5}\n            numericValue={layoutGridSize}\n            formatValue={(n) => `${n}px`}\n            onChange={setLayoutGridSize}\n          />\n        )}\n\n        <PanelSection title={t.canvas.gridPanel.gridColor}>\n          <ColorInput\n            label={t.canvas.gridPanel.gridColor}\n            opacityLabel={t.canvas.brush.opacity}\n            value={colorInputValue}\n            onChange={(css) => {\n              const next = parseCssColor(css, parsed);\n              // Keep grid lines subtle.\n              const a = Math.min(0.25, Math.max(0.03, next.a));\n              setLayoutGridColor(rgbaToCss({ ...next, a }));\n            }}\n          />\n          <div className=\"flex gap-1 flex-wrap\">\n            {GRID_COLOR_PRESETS.map((c) => {\n              const active = layoutGridColor === c.val;\n              return (\n                <button\n                  key={c.key}\n                  type=\"button\"\n                  onClick={() => setLayoutGridColor(c.val)}\n                  className={`min-w-[3.5rem] flex-1 select-none rounded-lg border px-2 py-1.5 transition-colors ${\n                    active\n                      ? 'border-[var(--we-accent)] bg-[var(--we-accent-capsule)] text-white'\n                      : 'border-panel-border bg-black-capsule text-white/80 hover:bg-black-capsule-hover hover:text-white'\n                  }`}\n                >\n                  <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-inherit\">\n                    {presetLabel(c.key)}\n                  </TextBody>\n                </button>\n              );\n            })}\n          </div>\n        </PanelSection>\n      </div>\n    </DraggableToolPanel>\n  );\n};\n\nexport default CanvasGridPanel;\n", "import React from 'react';\nimport { DraggableToolPanel } from '../../DraggableToolPanel';\nimport { ToolPanelTabs } from '../../ui';\nimport { useEditorStore } from '../../../store/useEditorStore';\nimport { useTranslation } from '../../../i18n';\n\nexport type ColorBlindnessMode =\n  | 'normal'\n  | 'protanopia'\n  | 'deuteranopia'\n  | 'tritanopia';\n\nexport interface CanvasColorblindPanelProps {\n  anchorRef: React.RefObject<HTMLElement | null>;\n  onClose: () => void;\n}\n\nexport const CanvasColorblindPanel: React.FC<CanvasColorblindPanelProps> = ({\n  anchorRef,\n  onClose,\n}) => {\n  const t = useTranslation();\n  const colorBlindnessMode = useEditorStore((s) => s.colorBlindnessMode);\n  const setColorBlindnessMode = useEditorStore((s) => s.setColorBlindnessMode);\n\n  const tabs = [\n    { id: 'normal' as const, label: t.canvas.colorblind.modes.normal },\n    { id: 'protanopia' as const, label: t.canvas.colorblind.modes.protanopia },\n    {\n      id: 'deuteranopia' as const,\n      label: t.canvas.colorblind.modes.deuteranopia,\n    },\n    { id: 'tritanopia' as const, label: t.canvas.colorblind.modes.tritanopia },\n  ];\n\n  return (\n    <DraggableToolPanel\n      panelId=\"canvas-colorblind\"\n      title={t.canvas.colorblind.title}\n      anchorRef={anchorRef}\n      onClose={onClose}\n      contentClassName=\"flex flex-col min-w-[360px]\"\n    >\n      <ToolPanelTabs\n        tabs={tabs}\n        value={colorBlindnessMode as ColorBlindnessMode}\n        onChange={(id) => setColorBlindnessMode(id)}\n      />\n    </DraggableToolPanel>\n  );\n};\n\nexport default CanvasColorblindPanel;\n", "import React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Plus, Trash2, UploadCloud, X } from 'lucide-react';\nimport { Button, PanelSection, ToolPanelTabs, TextBody, TextTitle } from '../../ui';\nimport { useBrandSelection } from '../../../context/BrandSelectionContext';\nimport { useDialog } from '../../DialogModal';\nimport { useTranslation } from '../../../i18n';\nimport {\n  listImageJobsWithS3,\n  looksLikeS3Url,\n  isRemoteImageUrl,\n  type FileImageItem,\n} from '../../../services/imageJobsService';\nimport { searchStock, downloadStockPhoto, type StockPhoto } from '../../../services/stockService';\nimport { STOCK_LAYERS } from '../../Sidebar';\nimport { useEditorStore } from '../../../store/useEditorStore';\nimport { modeAccentVars, useModeAccent } from '../../../theme/modeAccent';\n\n\nexport type UploadTab = 'device' | 'files' | 'stock';\n\nexport interface CanvasUploadPanelProps {\n  open: boolean;\n  onClose: () => void;\n  processUploadedFile: (file: File) => void | Promise<void>;\n  handleAddImageLayer: (url: string, name: string) => void | Promise<void>;\n  panelFileInputRef: React.RefObject<HTMLInputElement | null>;\n}\n\nexport const CanvasUploadPanel: React.FC<CanvasUploadPanelProps> = ({\n  open,\n  onClose,\n  processUploadedFile,\n  handleAddImageLayer,\n  panelFileInputRef,\n}) => {\n  const t = useTranslation();\n  const mode = useModeAccent();\n  const dialog = useDialog();\n  const { brand } = useBrandSelection();\n  const uploadedAssets = useEditorStore((s) => s.uploadedAssets);\n  const clearUploadedAssets = useEditorStore((s) => s.clearUploadedAssets);\n  const deleteUploadedAsset = useEditorStore((s) => s.deleteUploadedAsset);\n\n  const [tab, setTab] = useState<UploadTab>('device');\n  const [isDragging, setIsDragging] = useState(false);\n  const [jobItems, setJobItems] = useState<FileImageItem[]>([]);\n  const [filesLoading, setFilesLoading] = useState(false);\n  const [stockQuery, setStockQuery] = useState('');\n  const [stockPhotos, setStockPhotos] = useState<StockPhoto[]>([]);\n  const [stockLoading, setStockLoading] = useState(false);\n  const [isAdding, setIsAdding] = useState(false);\n  const stockAbortRef = useRef<AbortController | null>(null);\n  /** Blocks double/triple clicks on logos, history thumbs, stock, etc. */\n  const addingRef = useRef(false);\n\n  const beginAdd = (): boolean => {\n    if (addingRef.current || isAdding) return false;\n    addingRef.current = true;\n    setIsAdding(true);\n    return true;\n  };\n\n  const endAdd = () => {\n    addingRef.current = false;\n    setIsAdding(false);\n  };\n\n  /** Same path as typing a URL + Insert: dismiss first so a 2nd click cannot re-fire. */\n  const addImageAndClose = async (url: string, name: string) => {\n    if (!url?.trim() || !beginAdd()) return;\n    onClose();\n    try {\n      await handleAddImageLayer(url.trim(), name);\n    } catch (err) {\n      console.error('Failed to add image from upload panel', err);\n    } finally {\n      endAdd();\n    }\n  };\n\n  const addStockAndClose = async (photo: StockPhoto) => {\n    if (!beginAdd()) return;\n    const name = photo.alt || photo.photographer || photo.id;\n    onClose();\n    try {\n      const downloaded = await downloadStockPhoto(photo);\n      await handleAddImageLayer(downloaded.objectUrl, name);\n    } catch (err) {\n      console.error('Stock add error:', err);\n    } finally {\n      endAdd();\n    }\n  };\n\n  const processFileAndClose = async (file: File) => {\n    if (!beginAdd()) return;\n    onClose();\n    try {\n      await processUploadedFile(file);\n    } finally {\n      endAdd();\n    }\n  };\n\n  const onFileInputChange = async (e: React.ChangeEvent<HTMLInputElement>) => {\n    const files = Array.from(e.target.files ?? []).filter((f) =>\n      f.type.startsWith('image/'),\n    );\n    // Clear before awaiting so the same file can be re-selected later.\n    e.target.value = '';\n    if (files.length === 0 || !beginAdd()) return;\n    onClose();\n    try {\n      const first = files[0];\n      if (first) await processUploadedFile(first);\n    } finally {\n      endAdd();\n    }\n  };\n\n  // Reset the add-lock only when the panel opens again \u2014 never on close,\n  // or a double-click can sneak a 2nd add after onClose() clears the flag.\n  useEffect(() => {\n    if (!open) return;\n    addingRef.current = false;\n    setIsAdding(false);\n  }, [open]);\n\n  useEffect(() => {\n    if (!open) return;\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'Escape' && !addingRef.current) onClose();\n    };\n    window.addEventListener('keydown', onKey);\n    document.body.style.overflow = 'hidden';\n    return () => {\n      window.removeEventListener('keydown', onKey);\n      document.body.style.overflow = '';\n    };\n  }, [open, onClose]);\n\n  useEffect(() => {\n    if (!open || tab !== 'files') return;\n    const ac = new AbortController();\n    setFilesLoading(true);\n    listImageJobsWithS3({ signal: ac.signal })\n      .then((items) => {\n        if (!ac.signal.aborted) setJobItems(items);\n      })\n      .finally(() => {\n        if (!ac.signal.aborted) setFilesLoading(false);\n      });\n    return () => ac.abort();\n  }, [open, tab]);\n\n  useEffect(() => {\n    if (!open || tab !== 'stock') return;\n    stockAbortRef.current?.abort();\n    const ac = new AbortController();\n    stockAbortRef.current = ac;\n    const q = stockQuery.trim();\n    const timer = window.setTimeout(() => {\n      setStockLoading(true);\n      searchStock({ q: q || 'abstract', page: 1, perPage: 24, signal: ac.signal })\n        .then((res) => {\n          if (!ac.signal.aborted) setStockPhotos(res.photos ?? []);\n        })\n        .catch(() => {\n          if (!ac.signal.aborted) setStockPhotos([]);\n        })\n        .finally(() => {\n          if (!ac.signal.aborted) setStockLoading(false);\n        });\n    }, 280);\n    return () => {\n      window.clearTimeout(timer);\n      ac.abort();\n    };\n  }, [open, tab, stockQuery]);\n\n  const brandLogos = useMemo(() => {\n    const logos = brand?.brandLogos?.filter((l) => l?.logoUrl) ?? [];\n    if (logos.length > 0) return logos;\n    if (brand?.logoUrl) {\n      return [{ logoUrl: brand.logoUrl, description: brand.name }];\n    }\n    return [];\n  }, [brand]);\n\n  const brandImages: FileImageItem[] = useMemo(() => {\n    const imgs = brand?.images ?? [];\n    return imgs\n      .filter((img) => img?.url && isRemoteImageUrl(img.url))\n      .map((img) => ({\n        id: img.id,\n        url: img.url,\n        name: img.alt || img.id,\n        source: 'brand' as const,\n      }));\n  }, [brand?.images]);\n\n  const remoteUploads: FileImageItem[] = useMemo(\n    () =>\n      uploadedAssets\n        .filter((a) => looksLikeS3Url(a.url))\n        .map((a) => ({\n          id: a.id,\n          url: a.url,\n          name: a.name,\n          source: 'upload' as const,\n        })),\n    [uploadedAssets],\n  );\n\n  const filesGrid = useMemo(() => {\n    const seen = new Set<string>();\n    const out: FileImageItem[] = [];\n    for (const item of [...jobItems, ...remoteUploads]) {\n      if (seen.has(item.url)) continue;\n      seen.add(item.url);\n      out.push(item);\n    }\n    return out;\n  }, [jobItems, remoteUploads]);\n\n  const thumbClass =\n    'group relative aspect-square rounded-lg overflow-hidden border border-panel-border bg-black-capsule cursor-pointer hover:border-[var(--we-accent)] transition-all disabled:pointer-events-none disabled:opacity-50';\n\n  if (!open) return null;\n\n  return createPortal(\n    <div\n      className=\"fixed inset-0 z-[100] flex items-center justify-center bg-black/60 backdrop-blur-sm p-3 sm:p-5 animate-fade-in\"\n      style={modeAccentVars(mode)}\n      data-we-mode={mode}\n    >\n      <div\n        className=\"absolute inset-0 cursor-default\"\n        onClick={() => {\n          if (!addingRef.current) onClose();\n        }}\n      />\n      <div\n        role=\"dialog\"\n        aria-modal\n        aria-busy={isAdding}\n        aria-label={t.canvas.uploadPanel.title}\n        className=\"relative z-[101] flex h-[min(92vh,960px)] w-[min(96vw,1280px)] flex-col overflow-hidden rounded-2xl border border-panel-border bg-panel shadow-2xl\"\n      >\n        <div className=\"flex shrink-0 items-center justify-between border-b border-panel-border px-5 py-3.5\">\n          <TextTitle as=\"h2\" size=\"md\" className=\"text-white\">\n            {t.canvas.uploadPanel.title}\n          </TextTitle>\n          <button\n            type=\"button\"\n            onClick={onClose}\n            disabled={isAdding}\n            className=\"rounded-lg p-1.5 text-white/70 hover:bg-black-capsule hover:text-white transition-colors disabled:opacity-40\"\n            aria-label={t.common.close}\n          >\n            <X size={18} />\n          </button>\n        </div>\n\n        <ToolPanelTabs\n          tabs={[\n            { id: 'device' as const, label: t.canvas.uploadPanel.tabDevice },\n            { id: 'files' as const, label: t.canvas.uploadPanel.tabFiles },\n            { id: 'stock' as const, label: t.canvas.uploadPanel.tabStock },\n          ]}\n          value={tab}\n          onChange={setTab}\n        />\n\n        <div className=\"flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto p-5\">\n          {tab === 'device' && (\n            <>\n              <label\n                onDragOver={(e) => {\n                  e.preventDefault();\n                  setIsDragging(true);\n                }}\n                onDragLeave={() => setIsDragging(false)}\n                onDrop={(e) => {\n                  e.preventDefault();\n                  setIsDragging(false);\n                  const files = e.dataTransfer.files;\n                  if (files) Array.from(files).forEach(processFileAndClose);\n                }}\n                className={`flex flex-col items-center justify-center gap-3 border-2 border-dashed rounded-xl px-6 py-12 cursor-pointer transition-colors ${\n                  isDragging\n                    ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)]'\n                    : 'border-panel-border hover:border-[var(--we-accent)]/70 hover:bg-black-capsule'\n                }`}\n              >\n                <UploadCloud\n                  size={36}\n                  className={\n                    isDragging ? 'text-[var(--we-accent)]' : 'text-white/70'\n                  }\n                />\n                <TextBody as=\"span\" size=\"md\" className=\"text-center text-white/80\">\n                  {isDragging\n                    ? t.canvas.uploadPanel.dragDropActive\n                    : t.canvas.uploadPanel.dragDrop}\n                </TextBody>\n                <input\n                  ref={panelFileInputRef}\n                  type=\"file\"\n                  accept=\"image/*\"\n                  onChange={onFileInputChange}\n                  className=\"hidden\"\n                  aria-hidden\n                />\n              </label>\n\n              {brandLogos.length > 0 && (\n                <PanelSection title={t.canvas.uploadPanel.brandLogosHeader}>\n                  <div className=\"grid grid-cols-4 sm:grid-cols-6 md:grid-cols-8 gap-2.5\">\n                    {brandLogos.map((logo, i) => {\n                      const name = logo.description || brand?.name || `Logo ${i + 1}`;\n                      return (\n                        <button\n                          key={`${logo.logoUrl}-${i}`}\n                          type=\"button\"\n                          disabled={isAdding}\n                          onClick={() => {\n                            void addImageAndClose(logo.logoUrl, name);\n                          }}\n                          className={`${thumbClass} bg-white/5`}\n                          title={name}\n                        >\n                          <img\n                            src={logo.logoUrl}\n                            alt={name}\n                            className=\"w-full h-full object-contain p-1.5\"\n                          />\n                        </button>\n                      );\n                    })}\n                  </div>\n                </PanelSection>\n              )}\n\n              <div className=\"flex items-center gap-2\">\n                <TextBody as=\"span\" size=\"sm\" className=\"uppercase text-white/80 tracking-wider w-10 shrink-0\">\n                  {t.canvas.uploadPanel.urlLabel}\n                </TextBody>\n                <input\n                  type=\"text\"\n                  placeholder={t.canvas.uploadPanel.urlPlaceholder}\n                  id=\"upload-panel-url-input\"\n                  onKeyDown={(e) => {\n                    if (e.key === 'Enter') {\n                      const input = e.currentTarget;\n                      if (input.value.trim()) {\n                        addImageAndClose(\n                          input.value.trim(),\n                          t.canvas.uploadPanel.urlImageName,\n                        );\n                        input.value = '';\n                      }\n                    }\n                  }}\n                  className=\"flex-1 min-w-0 bg-black-capsule border border-panel-border rounded-lg px-2 py-1.5 text-[10px] text-ink-primary focus:outline-none focus:border-[var(--we-accent)] font-medium\"\n                />\n                <Button\n                  type=\"button\"\n                  variant=\"accent\"\n                  size=\"sm\"\n                  disabled={isAdding}\n                  onClick={() => {\n                    const input = document.getElementById(\n                      'upload-panel-url-input',\n                    ) as HTMLInputElement | null;\n                    if (input && input.value.trim()) {\n                      void addImageAndClose(\n                        input.value.trim(),\n                        t.canvas.uploadPanel.urlImageName,\n                      );\n                      input.value = '';\n                    }\n                  }}\n                >\n                  <TextBody as=\"span\" size=\"sm\">{t.canvas.uploadPanel.insert}</TextBody>\n                </Button>\n              </div>\n\n              {uploadedAssets.length > 0 && (\n                <PanelSection\n                  title={t.canvas.uploadPanel.historyHeader(uploadedAssets.length)}\n                  trailing={\n                    <button\n                      type=\"button\"\n                      onClick={async () => {\n                        const ok = await dialog.confirm(\n                          t.canvas.uploadPanel.clearHistoryBody,\n                          {\n                            title: t.canvas.uploadPanel.clearHistoryTitle,\n                            variant: 'danger',\n                            confirmText: t.canvas.uploadPanel.clearHistoryConfirm,\n                            cancelText: t.common.cancel,\n                          },\n                        );\n                        if (ok) clearUploadedAssets();\n                      }}\n                      className=\"cursor-pointer select-none text-red-400 transition-colors hover:text-red-300\"\n                    >\n                      <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-inherit\">\n                        {t.canvas.uploadPanel.clearAll}\n                      </TextBody>\n                    </button>\n                  }\n                >\n                  <div className=\"grid grid-cols-4 sm:grid-cols-6 md:grid-cols-8 gap-2.5\">\n                    {uploadedAssets.map((asset) => (\n                      <button\n                        key={asset.id}\n                        type=\"button\"\n                        disabled={isAdding}\n                        onClick={() => {\n                          void addImageAndClose(asset.url, asset.name);\n                        }}\n                        className={thumbClass}\n                        title={asset.name}\n                      >\n                        <img\n                          src={asset.url}\n                          alt={asset.name}\n                          className=\"w-full h-full object-cover\"\n                        />\n                        <span\n                          role=\"button\"\n                          tabIndex={-1}\n                          onClick={(e) => {\n                            e.stopPropagation();\n                            if (!isAdding) deleteUploadedAsset(asset.id);\n                          }}\n                          className=\"absolute top-0.5 right-0.5 p-0.5 rounded bg-black/75 text-white/70 hover:text-red-400 opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer\"\n                          title={t.canvas.uploadPanel.tooltipDeleteAsset}\n                        >\n                          <Trash2 size={8} />\n                        </span>\n                      </button>\n                    ))}\n                  </div>\n                </PanelSection>\n              )}\n            </>\n          )}\n\n          {tab === 'files' && (\n            <div className=\"flex min-h-0 flex-1 flex-col gap-4\">\n              {brandImages.length > 0 && (\n                <PanelSection title={t.canvas.uploadPanel.brandImagesHeader}>\n                  <div className=\"grid grid-cols-4 sm:grid-cols-6 md:grid-cols-8 gap-2.5\">\n                    {brandImages.map((item) => (\n                      <button\n                        key={item.id}\n                        type=\"button\"\n                        disabled={isAdding}\n                        onClick={() => {\n                          void addImageAndClose(item.url, item.name);\n                        }}\n                        className={thumbClass}\n                        title={item.name}\n                      >\n                        <img\n                          src={item.url}\n                          alt={item.name}\n                          className=\"w-full h-full object-cover\"\n                        />\n                      </button>\n                    ))}\n                  </div>\n                </PanelSection>\n              )}\n\n              {filesLoading ? (\n                <PanelSection title={t.canvas.uploadPanel.jobsHeader}>\n                  <div\n                    className=\"grid grid-cols-4 sm:grid-cols-6 md:grid-cols-8 gap-2.5\"\n                    aria-busy\n                    aria-label={t.canvas.uploadPanel.stockLoading}\n                  >\n                    {Array.from({ length: 16 }).map((_, i) => (\n                      <div\n                        key={i}\n                        className=\"aspect-square rounded-lg border border-panel-border bg-black-capsule animate-pulse\"\n                        style={{ animationDelay: `${i * 40}ms` }}\n                      />\n                    ))}\n                  </div>\n                </PanelSection>\n              ) : filesGrid.length > 0 ? (\n                <PanelSection title={t.canvas.uploadPanel.jobsHeader}>\n                  <div className=\"grid grid-cols-4 sm:grid-cols-6 md:grid-cols-8 gap-2.5\">\n                    {filesGrid.map((item) => (\n                      <button\n                        key={`${item.source}-${item.id}`}\n                        type=\"button\"\n                        disabled={isAdding}\n                        onClick={() => {\n                          void addImageAndClose(item.url, item.name);\n                        }}\n                        className={thumbClass}\n                        title={item.name}\n                      >\n                        <img\n                          src={item.url}\n                          alt={item.name}\n                          className=\"w-full h-full object-cover\"\n                        />\n                      </button>\n                    ))}\n                  </div>\n                </PanelSection>\n              ) : brandImages.length === 0 ? (\n                <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n                  {t.canvas.uploadPanel.filesEmpty}\n                </TextBody>\n              ) : null}\n            </div>\n          )}\n\n          {tab === 'stock' && (\n            <div className=\"flex min-h-0 flex-1 flex-col gap-4\">\n              <input\n                type=\"search\"\n                value={stockQuery}\n                onChange={(e) => setStockQuery(e.target.value)}\n                placeholder={t.canvas.uploadPanel.stockSearchPlaceholder}\n                className=\"w-full shrink-0 bg-black-capsule border border-panel-border rounded-lg px-3 py-2 text-sm font-medium text-ink-primary focus:outline-none focus:border-[var(--we-accent)]\"\n              />\n\n              {stockLoading ? (\n                <div\n                  className=\"grid grid-cols-4 sm:grid-cols-6 md:grid-cols-8 gap-2.5\"\n                  aria-busy\n                  aria-label={t.canvas.uploadPanel.stockLoading}\n                >\n                  {Array.from({ length: 16 }).map((_, i) => (\n                    <div\n                      key={i}\n                      className=\"aspect-square rounded-lg border border-panel-border bg-black-capsule animate-pulse\"\n                      style={{ animationDelay: `${i * 40}ms` }}\n                    />\n                  ))}\n                </div>\n              ) : stockPhotos.length === 0 ? (\n                <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n                  {t.canvas.uploadPanel.stockEmpty}\n                </TextBody>\n              ) : (\n                <div className=\"grid grid-cols-4 sm:grid-cols-6 md:grid-cols-8 gap-2.5\">\n                  {stockPhotos.map((photo) => {\n                    const name = photo.alt || photo.photographer || photo.id;\n                    const url = photo.regularUrl || photo.fullUrl;\n                    return (\n                      <button\n                        key={photo.id}\n                        type=\"button\"\n                        disabled={isAdding}\n                        onClick={() => {\n                          void addStockAndClose(photo);\n                        }}\n                        className={thumbClass}\n                        title={name}\n                      >\n                        <img\n                          src={photo.thumbnailUrl || url}\n                          alt={name}\n                          className=\"w-full h-full object-cover\"\n                        />\n                      </button>\n                    );\n                  })}\n                </div>\n              )}\n\n              <PanelSection\n                title={t.canvas.uploadPanel.stockHeader}\n                trailing={\n                  <Button\n                    type=\"button\"\n                    variant=\"accent\"\n                    size=\"sm\"\n                    icon={<Plus size={9} />}\n                    title={t.canvas.uploadPanel.stockMoreTitle}\n                    onClick={() => {\n                      window.dispatchEvent(\n                        new CustomEvent('wizard:set-sidebar-tab', {\n                          detail: 'upload',\n                        }),\n                      );\n                    }}\n                  >\n                    {t.canvas.uploadPanel.stockMoreButton}\n                  </Button>\n                }\n              >\n                <div className=\"grid grid-cols-4 sm:grid-cols-6 md:grid-cols-8 gap-2.5\">\n                  {STOCK_LAYERS.map((item, idx) => {\n                    const layerName = t.presets.stockLayer[item.nameKey];\n                    return (\n                      <button\n                        key={idx}\n                        type=\"button\"\n                        disabled={isAdding}\n                        onClick={() => {\n                          void addImageAndClose(item.url, layerName);\n                        }}\n                        className={thumbClass}\n                      >\n                        <img\n                          src={item.thumb}\n                          alt={layerName}\n                          className=\"w-full h-full object-cover\"\n                        />\n                      </button>\n                    );\n                  })}\n                </div>\n              </PanelSection>\n            </div>\n          )}\n        </div>\n      </div>\n    </div>,\n    document.body,\n  );\n};\n\nexport default CanvasUploadPanel;\n", "import React from 'react';\nimport { DraggableToolPanel } from '../../DraggableToolPanel';\nimport {\n  PanelField,\n  PanelSection,\n  SelectDropdown,\n  Switch,\n} from '../../ui';\nimport { useTranslation } from '../../../i18n';\nimport type { BrushSettings } from '../../../store/useEditorStore';\nimport { useEditorStore } from '../../../store/useEditorStore';\nimport { BRUSH_PRESETS } from '../../Sidebar';\nimport { parseCssColor, rgbaToHex6 } from '../../../utils/colorRgba';\n\nexport interface BrushToolPanelProps {\n  anchorRef: React.RefObject<HTMLElement | null>;\n  onClose: () => void;\n  brushSettings: BrushSettings;\n  updateBrushSettings: (settings: Partial<BrushSettings>) => void;\n}\n\nexport const BrushToolPanel: React.FC<BrushToolPanelProps> = ({\n  anchorRef,\n  onClose,\n  brushSettings,\n  updateBrushSettings,\n}) => {\n  const t = useTranslation();\n  const updateMasterColors = useEditorStore((s) => s.updateMasterColors);\n\n  const styleOptions = [\n    { value: 'pencil', label: t.canvas.brush.styleOptions.pencil },\n    { value: 'calligraphy', label: t.canvas.brush.styleOptions.calligraphy },\n    { value: 'highlighter', label: t.canvas.brush.styleOptions.highlighter },\n    { value: 'chalk', label: t.canvas.brush.styleOptions.chalk },\n    { value: 'spray', label: t.canvas.brush.styleOptions.spray },\n    { value: 'circle', label: t.canvas.brush.styleOptions.circle },\n  ];\n\n  const presetOptions = [\n    { value: 'none', label: t.canvas.brush.presetDefault },\n    ...BRUSH_PRESETS.map((p) => ({\n      value: p.name,\n      label: t.presets.brush[p.nameKey],\n    })),\n  ];\n\n  const glowCss = brushSettings.shadowColor || '#000000';\n\n  return (\n    <DraggableToolPanel\n      panelId=\"canvas-brush\"\n      title={t.canvas.brush.configTitle}\n      anchorRef={anchorRef}\n      onClose={onClose}\n      defaultPlacement=\"center-left\"\n      contentClassName=\"flex flex-col min-w-[300px] max-w-[360px] max-h-[70vh] overflow-y-auto\"\n    >\n      <div className=\"flex flex-col gap-2 p-3\">\n        <PanelField\n          label={t.canvas.brush.style}\n          trailing={\n            <SelectDropdown\n              value={brushSettings.type || 'pencil'}\n              options={styleOptions}\n              ariaLabel={t.canvas.brush.style}\n              onChange={(v) => {\n                updateBrushSettings({\n                  type: v as BrushSettings['type'],\n                });\n              }}\n            />\n          }\n        />\n\n        <PanelField\n          label={t.canvas.brush.presets}\n          trailing={\n            <SelectDropdown\n              value=\"none\"\n              options={presetOptions}\n              ariaLabel={t.canvas.brush.presets}\n              onChange={(v) => {\n                if (v === 'none') return;\n                const preset = BRUSH_PRESETS.find((p) => p.name === v);\n                if (!preset) return;\n                updateBrushSettings({\n                  type: preset.type,\n                  color: preset.color,\n                  width: preset.width,\n                  opacity: preset.opacity,\n                  shadowEnabled: preset.shadowEnabled,\n                  shadowBlur: preset.shadowBlur,\n                  shadowColor: preset.shadowColor,\n                  stabilization:\n                    preset.stabilization !== undefined\n                      ? preset.stabilization\n                      : 0.3,\n                  pressureSensitivity: !!preset.pressureSensitivity,\n                });\n                // Preset color becomes the master fill (Photoshop foreground).\n                if (preset.color) {\n                  updateMasterColors({ fill: preset.color });\n                }\n              }}\n            />\n          }\n        />\n\n        <PanelField\n          variant=\"slide\"\n          label={t.canvas.brush.opacity}\n          min={1}\n          max={100}\n          step={1}\n          numericValue={Math.round((brushSettings.opacity ?? 1) * 100)}\n          formatValue={(n) => `${Math.round(n)}%`}\n          onChange={(n) => updateBrushSettings({ opacity: n / 100 })}\n        />\n\n        <PanelField\n          variant=\"slide\"\n          label={t.canvas.brush.widthLabel}\n          min={1}\n          max={100}\n          step={1}\n          numericValue={brushSettings.width}\n          formatValue={(n) => `${n}px`}\n          onChange={(n) => updateBrushSettings({ width: n })}\n        />\n\n        <PanelField\n          variant=\"slide\"\n          label={t.canvas.brush.smoothingLabel}\n          min={0}\n          max={90}\n          step={5}\n          numericValue={Math.round(\n            (brushSettings.stabilization !== undefined\n              ? brushSettings.stabilization\n              : 0.3) * 100,\n          )}\n          formatValue={(n) => `${n}%`}\n          onChange={(n) => updateBrushSettings({ stabilization: n / 100 })}\n        />\n\n        <PanelSection>\n          <PanelField\n            label={t.canvas.brush.glowTitle}\n            trailing={\n              <Switch\n                checked={!!brushSettings.shadowEnabled}\n                onChange={(next) =>\n                  updateBrushSettings({ shadowEnabled: next })\n                }\n                ariaLabel={t.canvas.brush.glowTitle}\n              />\n            }\n          />\n          {brushSettings.shadowEnabled ? (\n            <>\n              <PanelField\n                variant=\"slide\"\n                label={t.canvas.brush.glowRadius}\n                min={1}\n                max={50}\n                step={1}\n                numericValue={brushSettings.shadowBlur || 0}\n                formatValue={(n) => `${n}px`}\n                onChange={(n) => updateBrushSettings({ shadowBlur: n })}\n              />\n              <PanelField\n                label={t.canvas.brush.glowColor}\n                trailing={\n                  <input\n                    type=\"color\"\n                    aria-label={t.canvas.brush.glowColor}\n                    value={rgbaToHex6(parseCssColor(glowCss))}\n                    onChange={(e) =>\n                      updateBrushSettings({ shadowColor: e.target.value })\n                    }\n                    className=\"size-6 cursor-pointer rounded border border-panel-border bg-transparent\"\n                  />\n                }\n              />\n            </>\n          ) : null}\n        </PanelSection>\n      </div>\n    </DraggableToolPanel>\n  );\n};\n\nexport default BrushToolPanel;\n", "import React from 'react';\nimport { DraggableToolPanel } from '../../DraggableToolPanel';\nimport { PanelField, PanelSection, TextBody } from '../../ui';\nimport { useTranslation } from '../../../i18n';\nimport { useEditorStore } from '../../../store/useEditorStore';\n\nexport interface MagicEraserToolPanelProps {\n  anchorRef: React.RefObject<HTMLElement | null>;\n  onClose: () => void;\n}\n\n/** Size/opacity only \u2014 Magic Eraser is a separate tool from freehand brush. */\nexport const MagicEraserToolPanel: React.FC<MagicEraserToolPanelProps> = ({\n  anchorRef,\n  onClose,\n}) => {\n  const t = useTranslation();\n  const { brushSettings, updateBrushSettings } = useEditorStore();\n\n  return (\n    <DraggableToolPanel\n      panelId=\"canvas-magic-eraser\"\n      title={t.canvas.magicEraserPanel.title}\n      anchorRef={anchorRef}\n      onClose={onClose}\n      defaultPlacement=\"center-left\"\n      contentClassName=\"flex flex-col min-w-[280px] max-w-[320px]\"\n    >\n      <div className=\"flex flex-col gap-2 p-3\">\n        <TextBody as=\"p\" size=\"sm\" className=\"leading-relaxed text-white/80\">\n          {t.canvas.magicEraserPanel.hint}\n        </TextBody>\n        <PanelSection>\n          <PanelField\n            variant=\"slide\"\n            label={t.canvas.brush.opacity}\n            min={1}\n            max={100}\n            step={1}\n            numericValue={Math.round((brushSettings.opacity ?? 0.5) * 100)}\n            formatValue={(n) => `${Math.round(n)}%`}\n            onChange={(n) => updateBrushSettings({ opacity: n / 100 })}\n          />\n          <PanelField\n            variant=\"slide\"\n            label={t.canvas.brush.widthLabel}\n            min={1}\n            max={100}\n            step={1}\n            numericValue={brushSettings.width}\n            formatValue={(n) => `${n}px`}\n            onChange={(n) => updateBrushSettings({ width: n })}\n          />\n        </PanelSection>\n      </div>\n    </DraggableToolPanel>\n  );\n};\n\nexport default MagicEraserToolPanel;\n", "import React from 'react';\nimport { Eraser, Layers2, Minus, PaintBucket, Plus, X } from 'lucide-react';\nimport { DraggableToolPanel } from '../../DraggableToolPanel';\nimport { Button, PanelField, PanelSection, Switch, TextBody } from '../../ui';\nimport { useTranslation } from '../../../i18n';\nimport { useEditorStore, type SelectionCombineMode } from '../../../store/useEditorStore';\n\n\nexport interface MagicWandToolPanelProps {\n  anchorRef: React.RefObject<HTMLElement | null>;\n  onClose: () => void;\n  /** When true, hide wand-only controls (tolerance / contiguous). */\n  lassoMode?: boolean;\n  /** Polygonal lasso copy/hints. */\n  polygonMode?: boolean;\n  /** Rectangular / elliptical pixel lasso. */\n  shapeMode?: 'rect' | 'ellipse';\n}\n\nexport const MagicWandToolPanel: React.FC<MagicWandToolPanelProps> = ({\n  anchorRef,\n  onClose,\n  lassoMode = false,\n  polygonMode = false,\n  shapeMode,\n}) => {\n  const t = useTranslation();\n  const {\n    magicWandSettings,\n    magicWandSelection,\n    updateMagicWandSettings,\n    clearMagicWandSelection,\n    applyMagicWandDelete,\n    applyMagicWandFill,\n    applyMagicWandCutToLayer,\n  } = useEditorStore();\n\n  const hasSelection = !!magicWandSelection && magicWandSelection.pixelCount > 0;\n  const mode = magicWandSettings.selectionMode;\n  const shapeCopy =\n    shapeMode === 'ellipse'\n      ? t.canvas.ellipseLasso\n      : shapeMode === 'rect'\n        ? t.canvas.rectLasso\n        : null;\n  const panelTitle = polygonMode\n    ? t.canvas.polygonLasso.title\n    : shapeCopy\n      ? shapeCopy.title\n      : lassoMode\n        ? t.canvas.pixelLasso.title\n        : t.canvas.magicWand.title;\n  const panelHint = polygonMode\n    ? t.canvas.polygonLasso.hint\n    : shapeCopy\n      ? shapeCopy.hint\n      : lassoMode\n        ? t.canvas.pixelLasso.hint\n        : t.canvas.magicWand.hint;\n  const noSel = polygonMode\n    ? t.canvas.polygonLasso.noSelection\n    : shapeCopy\n      ? shapeCopy.noSelection\n      : lassoMode\n        ? t.canvas.pixelLasso.noSelection\n        : t.canvas.magicWand.noSelection;\n\n  const setMode = (next: SelectionCombineMode) => {\n    updateMagicWandSettings({\n      selectionMode: mode === next && next !== 'new' ? 'new' : next,\n    });\n  };\n\n  return (\n    <DraggableToolPanel\n      panelId={\n        polygonMode\n          ? 'canvas-polygon-lasso'\n          : shapeMode === 'ellipse'\n            ? 'canvas-ellipse-lasso'\n            : shapeMode === 'rect'\n              ? 'canvas-rect-lasso'\n              : lassoMode\n                ? 'canvas-pixel-lasso'\n                : 'canvas-magic-wand'\n      }\n      title={panelTitle}\n      anchorRef={anchorRef}\n      onClose={onClose}\n      defaultPlacement=\"center-left\"\n      contentClassName=\"flex flex-col min-w-[280px] max-w-[320px]\"\n    >\n      <div className=\"flex flex-col gap-2 p-3\">\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80 leading-relaxed\">\n          {panelHint}\n        </TextBody>\n\n        <PanelSection title={t.canvas.magicWand.selectionMode}>\n          <div className=\"flex items-center gap-1.5\">\n            <Button\n              type=\"button\"\n              variant={mode === 'add' ? 'accent' : 'secondary'}\n              size=\"sm\"\n              className=\"flex-1 justify-center gap-1\"\n              onClick={() => setMode('add')}\n              title={t.canvas.magicWand.addModeHint}\n            >\n              <Plus size={14} />\n              {t.canvas.magicWand.addMode}\n            </Button>\n            <Button\n              type=\"button\"\n              variant={mode === 'subtract' ? 'accent' : 'secondary'}\n              size=\"sm\"\n              className=\"flex-1 justify-center gap-1\"\n              onClick={() => setMode('subtract')}\n              title={t.canvas.magicWand.subtractModeHint}\n            >\n              <Minus size={14} />\n              {t.canvas.magicWand.subtractMode}\n            </Button>\n          </div>\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80 mt-1\">\n            {t.canvas.magicWand.modifierHint}\n          </TextBody>\n        </PanelSection>\n\n        {!lassoMode && (\n          <PanelSection title={t.canvas.magicWand.properties}>\n            <PanelField\n              label={t.canvas.magicWand.tolerance}\n              variant=\"slide\"\n              min={0}\n              max={150}\n              step={1}\n              numericValue={magicWandSettings.tolerance}\n              defaultValue={32}\n              resetLabel={t.canvas.magicWand.resetTolerance}\n              onChange={(v) => updateMagicWandSettings({ tolerance: Math.round(v) })}\n              formatValue={(n) => String(Math.round(n))}\n            />\n            <PanelField\n              label={t.canvas.magicWand.contiguous}\n              trailing={\n                <Switch\n                  checked={magicWandSettings.contiguous}\n                  onChange={(checked) =>\n                    updateMagicWandSettings({ contiguous: checked })\n                  }\n                  ariaLabel={t.canvas.magicWand.contiguous}\n                />\n              }\n            />\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {t.canvas.magicWand.fillUsesMaster}\n            </TextBody>\n          </PanelSection>\n        )}\n\n        {lassoMode && (\n          <PanelSection title={t.canvas.magicWand.properties}>\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {t.canvas.magicWand.fillUsesMaster}\n            </TextBody>\n          </PanelSection>\n        )}\n\n        {hasSelection ? (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-[var(--we-accent)]\">\n            {t.canvas.magicWand.selectedPixels(magicWandSelection!.pixelCount)}\n          </TextBody>\n        ) : (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n            {noSel}\n          </TextBody>\n        )}\n\n        <PanelSection title={t.canvas.magicWand.actions}>\n          <div className=\"flex flex-col gap-1.5\">\n            <Button\n              variant=\"accent\"\n              size=\"sm\"\n              className=\"w-full justify-center gap-1.5\"\n              disabled={!hasSelection}\n              onClick={() => void applyMagicWandDelete()}\n            >\n              <Eraser size={13} />\n              {t.canvas.magicWand.delete}\n            </Button>\n            <Button\n              variant=\"secondary\"\n              size=\"sm\"\n              className=\"w-full justify-center gap-1.5\"\n              disabled={!hasSelection}\n              onClick={() => void applyMagicWandFill()}\n            >\n              <PaintBucket size={13} />\n              {t.canvas.magicWand.fill}\n            </Button>\n            <Button\n              variant=\"secondary\"\n              size=\"sm\"\n              className=\"w-full justify-center gap-1.5\"\n              disabled={!hasSelection}\n              onClick={() => void applyMagicWandCutToLayer()}\n            >\n              <Layers2 size={13} />\n              {t.canvas.magicWand.cutToLayer}\n            </Button>\n            <Button\n              variant=\"ghost\"\n              size=\"sm\"\n              className=\"w-full justify-center gap-1.5\"\n              disabled={!hasSelection}\n              onClick={() => clearMagicWandSelection()}\n            >\n              <X size={13} />\n              {t.canvas.magicWand.deselect}\n            </Button>\n          </div>\n        </PanelSection>\n      </div>\n    </DraggableToolPanel>\n  );\n};\n", "import React from 'react';\nimport { DraggableToolPanel } from '../../DraggableToolPanel';\nimport { PanelField, PanelSection, Switch, TextBody } from '../../ui';\nimport { useTranslation } from '../../../i18n';\nimport { useEditorStore } from '../../../store/useEditorStore';\n\nexport interface PaintBucketToolPanelProps {\n  anchorRef: React.RefObject<HTMLElement | null>;\n  onClose: () => void;\n}\n\nexport const PaintBucketToolPanel: React.FC<PaintBucketToolPanelProps> = ({\n  anchorRef,\n  onClose,\n}) => {\n  const t = useTranslation();\n  const paintBucketSettings = useEditorStore((s) => s.paintBucketSettings);\n  const updatePaintBucketSettings = useEditorStore((s) => s.updatePaintBucketSettings);\n\n  return (\n    <DraggableToolPanel\n      panelId=\"canvas-paint-bucket\"\n      title={t.canvas.paintBucket.title}\n      anchorRef={anchorRef}\n      onClose={onClose}\n      defaultPlacement=\"center-left\"\n      contentClassName=\"flex flex-col min-w-[280px] max-w-[320px]\"\n    >\n      <div className=\"flex flex-col gap-2 p-3\">\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80 leading-relaxed\">\n          {t.canvas.paintBucket.hint}\n        </TextBody>\n\n        <PanelSection title={t.canvas.paintBucket.properties}>\n          <PanelField\n            label={t.canvas.paintBucket.tolerance}\n            variant=\"slide\"\n            min={0}\n            max={255}\n            step={1}\n            numericValue={paintBucketSettings.tolerance}\n            defaultValue={32}\n            resetLabel={t.canvas.paintBucket.resetTolerance}\n            onChange={(v) => updatePaintBucketSettings({ tolerance: Math.round(v) })}\n            formatValue={(n) => String(Math.round(n))}\n          />\n          <PanelField\n            label={t.canvas.paintBucket.contiguous}\n            trailing={\n              <Switch\n                checked={paintBucketSettings.contiguous}\n                onChange={(checked) =>\n                  updatePaintBucketSettings({ contiguous: checked })\n                }\n                ariaLabel={t.canvas.paintBucket.contiguous}\n              />\n            }\n          />\n          <PanelField\n            label={t.canvas.paintBucket.antiAlias}\n            trailing={\n              <Switch\n                checked={paintBucketSettings.antiAlias}\n                onChange={(checked) =>\n                  updatePaintBucketSettings({ antiAlias: checked })\n                }\n                ariaLabel={t.canvas.paintBucket.antiAlias}\n              />\n            }\n          />\n        </PanelSection>\n      </div>\n    </DraggableToolPanel>\n  );\n};\n\nexport default PaintBucketToolPanel;\n", "import React from 'react';\nimport { DraggableToolPanel } from '../../DraggableToolPanel';\nimport { PanelField, PanelSection, TextBody } from '../../ui';\nimport { useTranslation } from '../../../i18n';\nimport { useEditorStore } from '../../../store/useEditorStore';\n\nexport interface CloneStampToolPanelProps {\n  anchorRef: React.RefObject<HTMLElement | null>;\n  onClose: () => void;\n}\n\nexport const CloneStampToolPanel: React.FC<CloneStampToolPanelProps> = ({\n  anchorRef,\n  onClose,\n}) => {\n  const t = useTranslation();\n  const { brushSettings, updateBrushSettings } = useEditorStore();\n\n  return (\n    <DraggableToolPanel\n      panelId=\"canvas-clone-stamp\"\n      title={t.canvas.cloneStamp.title}\n      anchorRef={anchorRef}\n      onClose={onClose}\n      defaultPlacement=\"center-left\"\n      contentClassName=\"flex flex-col min-w-[280px] max-w-[320px]\"\n    >\n      <div className=\"flex flex-col gap-2 p-3\">\n        <TextBody as=\"p\" size=\"sm\" className=\"leading-relaxed text-white/80\">\n          {t.canvas.cloneStamp.hint}\n        </TextBody>\n        <PanelSection title={t.canvas.cloneStamp.brush}>\n          <PanelField\n            label={t.canvas.brush.widthLabel}\n            variant=\"slide\"\n            min={1}\n            max={200}\n            step={1}\n            numericValue={brushSettings.width}\n            defaultValue={40}\n            resetLabel={t.canvas.brush.widthLabel}\n            onChange={(v) => updateBrushSettings({ width: Math.round(v) })}\n            formatValue={(n) => `${Math.round(n)} px`}\n          />\n        </PanelSection>\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n          {t.canvas.cloneStamp.rightClickHint}\n        </TextBody>\n      </div>\n    </DraggableToolPanel>\n  );\n};\n", "import React from 'react';\nimport { DraggableToolPanel } from '../../DraggableToolPanel';\nimport { PanelField, PanelSection, TextBody } from '../../ui';\nimport { useTranslation } from '../../../i18n';\nimport { useEditorStore } from '../../../store/useEditorStore';\n\nexport interface EraserToolPanelProps {\n  anchorRef: React.RefObject<HTMLElement | null>;\n  onClose: () => void;\n}\n\nexport const EraserToolPanel: React.FC<EraserToolPanelProps> = ({\n  anchorRef,\n  onClose,\n}) => {\n  const t = useTranslation();\n  const { brushSettings, updateBrushSettings } = useEditorStore();\n\n  return (\n    <DraggableToolPanel\n      panelId=\"canvas-eraser\"\n      title={t.canvas.eraser.title}\n      anchorRef={anchorRef}\n      onClose={onClose}\n      defaultPlacement=\"center-left\"\n      contentClassName=\"flex flex-col min-w-[280px] max-w-[320px]\"\n    >\n      <div className=\"flex flex-col gap-2 p-3\">\n        <TextBody as=\"p\" size=\"sm\" className=\"leading-relaxed text-white/80\">\n          {t.canvas.eraser.hint}\n        </TextBody>\n        <PanelSection title={t.canvas.eraser.brush}>\n          <PanelField\n            label={t.canvas.brush.widthLabel}\n            variant=\"slide\"\n            min={1}\n            max={200}\n            step={1}\n            numericValue={brushSettings.width}\n            defaultValue={40}\n            resetLabel={t.canvas.brush.widthLabel}\n            onChange={(v) => updateBrushSettings({ width: Math.round(v) })}\n            formatValue={(n) => `${Math.round(n)} px`}\n          />\n        </PanelSection>\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n          {t.canvas.eraser.rightClickHint}\n        </TextBody>\n      </div>\n    </DraggableToolPanel>\n  );\n};\n", "import React, { useRef, useState } from 'react';\nimport { Magnet, Square, Image, Type, Frame } from 'lucide-react';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { useTranslation } from '../../i18n';\nimport { ViewportPortalMenu } from '../../utils/ViewportPortalMenu';\nimport { TextBody, TextTitle } from '../ui';\n\nconst SnapSwitchRow: React.FC<{\n  label: string;\n  icon: React.ReactNode;\n  checked: boolean;\n  disabled?: boolean;\n  onChange: (next: boolean) => void;\n}> = ({ label, icon, checked, disabled = false, onChange }) => (\n  <button\n    type=\"button\"\n    role=\"switch\"\n    aria-checked={checked}\n    disabled={disabled}\n    onClick={() => onChange(!checked)}\n    className={`flex items-center justify-between gap-3 rounded-lg p-2 text-left transition-colors ${\n      disabled\n        ? 'cursor-not-allowed text-white/80 opacity-40'\n        : 'cursor-pointer text-white hover:bg-black-capsule'\n    }`}\n  >\n    <span className=\"flex min-w-0 items-center gap-2.5\">\n      {icon}\n      <TextBody as=\"span\" size=\"sm\" className=\"truncate font-semibold\">\n        {label}\n      </TextBody>\n    </span>\n    <span\n      className={`relative inline-flex h-5 w-9 shrink-0 rounded-full transition-colors ${\n        checked ? 'bg-[var(--we-accent)]' : 'bg-black-capsule'\n      }`}\n    >\n      <span\n        className={`absolute top-0.5 left-0.5 h-4 w-4 rounded-full bg-white shadow transition-transform ${\n          checked ? 'translate-x-4' : 'translate-x-0'\n        }`}\n      />\n    </span>\n  </button>\n);\n\nconst toolBtn =\n  'h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors';\n\n/** Magnetic snap control for the image bottom toolstrip. */\nexport const SnapMagnetButton: React.FC = () => {\n  const t = useTranslation();\n  const [open, setOpen] = useState(false);\n  const triggerRef = useRef<HTMLButtonElement | null>(null);\n  const { snapSettings, setSnapSettings } = useEditorStore();\n\n  return (\n    <div className=\"relative\">\n      <button\n        ref={triggerRef}\n        type=\"button\"\n        onClick={() => setOpen((o) => !o)}\n        title={t.toolbar.image.snapping}\n        aria-label={t.toolbar.image.snapping}\n        aria-expanded={open}\n        className={`${toolBtn} ${\n          snapSettings.enabled || open\n            ? 'bg-[var(--we-accent)] text-white font-bold'\n            : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n        }`}\n      >\n        <Magnet size={16} />\n        {!open && (\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 mb-2 -translate-x-1/2\">\n            {t.toolbar.image.snapping}\n          </TextBody>\n        )}\n      </button>\n\n      <ViewportPortalMenu\n        open={open}\n        onClose={() => setOpen(false)}\n        anchorRef={triggerRef}\n        prefer=\"above\"\n        zIndex={40}\n        className=\"flex w-56 flex-col gap-0.5 rounded-xl border border-panel-border bg-panel p-1.5 shadow-2xl backdrop-blur-md\"\n      >\n        <TextTitle as=\"p\" size=\"xs\" className=\"px-2.5 py-1 uppercase tracking-wider text-[var(--we-accent)]\">\n          {t.toolbar.image.snapping}\n        </TextTitle>\n        <SnapSwitchRow\n          label={t.toolbar.image.snapMaster}\n          icon={<Magnet size={13} className=\"text-white/80\" />}\n          checked={snapSettings.enabled}\n          onChange={(enabled) => setSnapSettings({ enabled })}\n        />\n        <div className=\"my-1 h-px bg-panel-border\" />\n        <SnapSwitchRow\n          label={t.toolbar.image.snapShapes}\n          icon={<Square size={13} className=\"text-white/80\" />}\n          checked={snapSettings.shapes}\n          disabled={!snapSettings.enabled}\n          onChange={(shapes) => setSnapSettings({ shapes })}\n        />\n        <SnapSwitchRow\n          label={t.toolbar.image.snapImages}\n          icon={<Image size={13} className=\"text-white/80\" />}\n          checked={snapSettings.images}\n          disabled={!snapSettings.enabled}\n          onChange={(images) => setSnapSettings({ images })}\n        />\n        <SnapSwitchRow\n          label={t.toolbar.image.snapText}\n          icon={<Type size={13} className=\"text-white/80\" />}\n          checked={snapSettings.text}\n          disabled={!snapSettings.enabled}\n          onChange={(text) => setSnapSettings({ text })}\n        />\n        <SnapSwitchRow\n          label={t.toolbar.image.snapCanvasEdges}\n          icon={<Frame size={13} className=\"text-white/80\" />}\n          checked={snapSettings.canvasEdges}\n          disabled={!snapSettings.enabled}\n          onChange={(canvasEdges) => setSnapSettings({ canvasEdges })}\n        />\n      </ViewportPortalMenu>\n    </div>\n  );\n};\n", "import React, { useEffect, useMemo, useRef, useState } from 'react';\nimport {\n  Palette,\n  Plus,\n  Trash2,\n  ChevronLeft,\n  ChevronRight,\n  Edit2,\n  X,\n} from 'lucide-react';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { useBrandSelection } from '../../context/BrandSelectionContext';\nimport { useTranslation } from '../../i18n';\nimport { generateHarmony, type HarmonyType } from '../../utils/colorUtils';\nimport { DraggableToolPanel } from '../DraggableToolPanel';\nimport { TextBody } from '../ui';\n\nconst toolBtn =\n  'h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors';\n\nfunction normalizeBrandHex(hex: string): string | null {\n  const raw = (hex || '').trim();\n  if (!raw) return null;\n  const withHash = raw.startsWith('#') ? raw : `#${raw}`;\n  if (!/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(withHash)) return null;\n  return withHash.length === 4\n    ? `#${withHash[1]}${withHash[1]}${withHash[2]}${withHash[2]}${withHash[3]}${withHash[3]}`\n    : withHash.slice(0, 7);\n}\n\n/** Brand kit (palettes / harmony) for the image bottom toolstrip \u2014 floating + draggable. */\nexport const BrandKitButton: React.FC = () => {\n  const t = useTranslation();\n  const { brand } = useBrandSelection();\n  const [open, setOpen] = useState(false);\n  const triggerRef = useRef<HTMLButtonElement | null>(null);\n  const [baseHarmonyColor, setBaseHarmonyColor] = useState('#3b82f6');\n  const [harmonyType, setHarmonyType] = useState<HarmonyType>('complementary');\n  const [generatedHarmony, setGeneratedHarmony] = useState<string[]>([]);\n\n  const {\n    canvasInstance,\n    activeObject,\n    saveHistoryState,\n    savedPalettes,\n    addPalette,\n    upsertPalette,\n    updatePaletteName,\n    addColorToPalette,\n    updateColorInPalette,\n    removeColorFromPalette,\n    reorderColorInPalette,\n    deletePalette,\n  } = useEditorStore();\n\n  const brandColors = useMemo(() => {\n    const seen = new Set<string>();\n    const out: string[] = [];\n    for (const c of brand?.primaryColors ?? []) {\n      const hex = normalizeBrandHex(c?.hex || '');\n      if (!hex) continue;\n      const key = hex.toLowerCase();\n      if (seen.has(key)) continue;\n      seen.add(key);\n      out.push(hex);\n    }\n    return out;\n  }, [brand?.primaryColors]);\n\n  // Seed a usable brand palette + harmony base from the loaded brand.\n  useEffect(() => {\n    if (!brand?.id || brandColors.length === 0) return;\n    setBaseHarmonyColor(brandColors[0]!);\n    upsertPalette({\n      id: `brand-kit-${brand.id}`,\n      name: t.sidebar.brand.brandPaletteName(brand.name),\n      colors: brandColors,\n    });\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- sync on brand identity / colors only\n  }, [brand?.id, brand?.name, brandColors.join('|'), upsertPalette]);\n\n  useEffect(() => {\n    setGeneratedHarmony(generateHarmony(baseHarmonyColor, harmonyType));\n  }, [baseHarmonyColor, harmonyType]);\n\n  return (\n    <div className=\"relative\">\n      <button\n        ref={triggerRef}\n        type=\"button\"\n        onClick={() => setOpen((o) => !o)}\n        title={t.toolbar.image.brandKit}\n        aria-label={t.toolbar.image.brandKit}\n        aria-expanded={open}\n        className={`${toolBtn} ${\n          open\n            ? 'bg-[var(--we-accent)] text-white font-bold'\n            : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n        }`}\n      >\n        <Palette size={16} />\n        {!open && (\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 mb-2 -translate-x-1/2\">\n            {t.toolbar.image.brandKit}\n          </TextBody>\n        )}\n      </button>\n\n      {open && (\n        <DraggableToolPanel\n          panelId=\"brand-kit-colors\"\n          title={t.toolbar.image.brandKit}\n          anchorRef={triggerRef}\n          onClose={() => setOpen(false)}\n          contentClassName=\"flex max-h-[70vh] w-80 flex-col gap-4 overflow-y-auto p-4\"\n        >\n          <div className=\"flex flex-col gap-3 rounded-xl border border-panel-border bg-black-capsule p-3\">\n            <TextBody as=\"span\" size=\"sm\" className=\"font-bold uppercase tracking-wider text-white/80\">\n              {t.sidebar.brand.harmonyGenerator}\n            </TextBody>\n\n            <div className=\"flex items-center gap-3\">\n              <div className=\"flex flex-1 flex-col gap-1\">\n                <TextBody as=\"label\" size=\"sm\" className=\"font-semibold uppercase text-white/80\">\n                  {t.sidebar.brand.baseColorLabel}\n                </TextBody>\n                <div className=\"flex overflow-hidden rounded-lg border border-panel-border bg-panel focus-within:border-[var(--we-accent)] transition-colors\">\n                  <label\n                    className=\"relative block h-8 w-8 shrink-0 cursor-pointer\"\n                    title={t.sidebar.brand.baseColorTooltip}\n                  >\n                    <div className=\"absolute inset-0\" style={{ backgroundColor: baseHarmonyColor }} />\n                    <input\n                      type=\"color\"\n                      value={baseHarmonyColor}\n                      onChange={(e) => setBaseHarmonyColor(e.target.value)}\n                      className=\"absolute inset-0 h-full w-full cursor-pointer opacity-0\"\n                    />\n                  </label>\n                  <input\n                    type=\"text\"\n                    value={baseHarmonyColor.toUpperCase()}\n                    onChange={(e) => setBaseHarmonyColor(e.target.value)}\n                    className=\"w-full bg-transparent px-2 font-sans text-xs font-medium font-mono uppercase text-white focus:outline-none\"\n                  />\n                </div>\n              </div>\n              <div className=\"flex flex-1 flex-col gap-1\">\n                <TextBody as=\"label\" size=\"sm\" className=\"font-semibold uppercase text-white/80\">\n                  {t.sidebar.brand.harmonyRuleLabel}\n                </TextBody>\n                <select\n                  value={harmonyType}\n                  onChange={(e) => setHarmonyType(e.target.value as HarmonyType)}\n                  className=\"h-8 w-full cursor-pointer appearance-none rounded-lg border border-panel-border bg-panel px-2 font-sans text-xs font-medium text-white focus:border-[var(--we-accent)] focus:outline-none\"\n                >\n                  <option value=\"complementary\">{t.sidebar.brand.harmony.complementary}</option>\n                  <option value=\"analogous\">{t.sidebar.brand.harmony.analogous}</option>\n                  <option value=\"triadic\">{t.sidebar.brand.harmony.triadic}</option>\n                  <option value=\"split-complementary\">\n                    {t.sidebar.brand.harmony.splitComplementary}\n                  </option>\n                  <option value=\"tetradic\">{t.sidebar.brand.harmony.tetradic}</option>\n                  <option value=\"monochromatic\">{t.sidebar.brand.harmony.monochromatic}</option>\n                </select>\n              </div>\n            </div>\n\n            <div className=\"flex h-10 overflow-hidden rounded-lg border border-panel-border shadow-sm\">\n              {generatedHarmony.map((hex, i) => (\n                <div\n                  key={i}\n                  className=\"group relative flex-1 cursor-pointer transition-transform hover:z-10 hover:scale-110\"\n                >\n                  <div className=\"h-full w-full\" style={{ backgroundColor: hex }} />\n                  <input\n                    type=\"color\"\n                    value={hex}\n                    onChange={(e) => {\n                      const next = [...generatedHarmony];\n                      next[i] = e.target.value;\n                      setGeneratedHarmony(next);\n                    }}\n                    className=\"absolute inset-0 h-full w-full cursor-pointer opacity-0\"\n                  />\n                </div>\n              ))}\n            </div>\n\n            <button\n              type=\"button\"\n              onClick={() => {\n                if (generatedHarmony.length === 5) {\n                  const names: Record<string, string> = {\n                    complementary: t.sidebar.brand.harmonyName.complementary,\n                    analogous: t.sidebar.brand.harmonyName.analogous,\n                    triadic: t.sidebar.brand.harmonyName.triadic,\n                    'split-complementary': t.sidebar.brand.harmonyName.splitComplementary,\n                    tetradic: t.sidebar.brand.harmonyName.tetradic,\n                    monochromatic: t.sidebar.brand.harmonyName.monochromatic,\n                  };\n                  addPalette({\n                    id: `palette-${Date.now()}`,\n                    name: names[harmonyType] || t.sidebar.brand.harmonyName.fallback,\n                    colors: generatedHarmony,\n                  });\n                }\n              }}\n              className=\"w-full cursor-pointer rounded-lg border border-panel-border bg-panel py-1.5 transition-colors hover:bg-black-capsule-hover\"\n            >\n              <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-white\">\n                {t.sidebar.brand.savePalette}\n              </TextBody>\n            </button>\n          </div>\n\n          <div className=\"flex flex-col gap-2\">\n            <div className=\"flex items-center justify-between\">\n              <TextBody as=\"span\" size=\"sm\" className=\"font-bold uppercase tracking-wider text-white/80\">\n                {t.sidebar.brand.savedPalettes}\n              </TextBody>\n              <button\n                type=\"button\"\n                onClick={() =>\n                  addPalette({\n                    id: `palette-${Date.now()}`,\n                    name: t.sidebar.brand.newPalette,\n                    colors: ['#000000', '#ffffff'],\n                  })\n                }\n                className=\"flex cursor-pointer items-center gap-1 transition-colors hover:text-[var(--we-accent-hover)]\"\n              >\n                <Plus size={10} />\n                <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-[var(--we-accent)]\">\n                  {t.sidebar.brand.addShort}\n                </TextBody>\n              </button>\n            </div>\n\n            {!savedPalettes || savedPalettes.length === 0 ? (\n              <TextBody\n                as=\"p\"\n                size=\"sm\"\n                className=\"rounded-xl border border-dashed border-panel-border p-4 text-center text-white/80\"\n              >\n                {t.sidebar.brand.noPalettes}\n              </TextBody>\n            ) : (\n              <div className=\"flex max-h-52 flex-col gap-2 overflow-y-auto pr-0.5\">\n                {(savedPalettes || []).map((palette) => (\n                  <div\n                    key={palette.id}\n                    className=\"flex flex-col gap-2 rounded-xl border border-panel-border bg-black-capsule p-2.5\"\n                  >\n                    <div className=\"flex items-center justify-between\">\n                      <input\n                        type=\"text\"\n                        value={palette.name || t.sidebar.brand.paletteNamePlaceholder}\n                        onChange={(e) => updatePaletteName(palette.id, e.target.value)}\n                        className=\"w-3/4 truncate rounded border-none bg-transparent px-1 py-0.5 font-sans text-xs font-medium text-white focus:outline-none focus:ring-1 focus:ring-[var(--we-accent)]/50\"\n                      />\n                      <div className=\"flex items-center gap-1\">\n                        <label\n                          className=\"relative flex cursor-pointer items-center justify-center p-1 text-white/80 transition-colors hover:text-[var(--we-accent)]\"\n                          title={t.sidebar.brand.tooltipAddColor}\n                        >\n                          <Plus size={11} />\n                          <input\n                            type=\"color\"\n                            className=\"absolute inset-0 h-full w-full cursor-pointer opacity-0\"\n                            onChange={(e) => addColorToPalette(palette.id, e.target.value)}\n                          />\n                        </label>\n                        <button\n                          type=\"button\"\n                          onClick={() => deletePalette(palette.id)}\n                          className=\"cursor-pointer p-1 text-white/80 transition-colors hover:text-red-400\"\n                        >\n                          <Trash2 size={11} />\n                        </button>\n                      </div>\n                    </div>\n                    <div className=\"flex flex-wrap gap-1.5\">\n                      {(palette.colors || []).map((hex, i) => (\n                        <div key={`${i}-${hex}`} className=\"group/swatch relative shrink-0\">\n                          <button\n                            type=\"button\"\n                            onClick={() => {\n                              void navigator.clipboard.writeText(hex.toUpperCase());\n                              if (\n                                activeObject &&\n                                [\n                                  'rect',\n                                  'circle',\n                                  'triangle',\n                                  'polygon',\n                                  'ellipse',\n                                  'path',\n                                  'textbox',\n                                  'text',\n                                ].includes(activeObject.type?.toLowerCase() || '')\n                              ) {\n                                activeObject.set({ fill: hex });\n                                canvasInstance?.requestRenderAll();\n                                saveHistoryState();\n                              }\n                            }}\n                            className=\"h-6 w-6 cursor-copy rounded-md border border-panel-border shadow-sm transition-transform hover:scale-110\"\n                            style={{ backgroundColor: hex }}\n                            title={hex.toUpperCase()}\n                          />\n                          <div className=\"pointer-events-none absolute bottom-full left-1/2 z-50 -translate-x-1/2 pb-1 opacity-0 transition-opacity group-hover/swatch:pointer-events-auto group-hover/swatch:opacity-100\">\n                            <div className=\"flex items-center rounded-md border border-panel-border bg-panel shadow-xl\">\n                              <button\n                                type=\"button\"\n                                onClick={(e) => {\n                                  e.stopPropagation();\n                                  if (i > 0) reorderColorInPalette(palette.id, i, i - 1);\n                                }}\n                                disabled={i === 0}\n                                className=\"p-1 text-white/80 hover:text-white disabled:opacity-30\"\n                              >\n                                <ChevronLeft size={10} />\n                              </button>\n                              <label\n                                className=\"relative cursor-pointer p-1 text-white/80 hover:text-[var(--we-accent)]\"\n                                title={t.sidebar.brand.tooltipEditColor}\n                              >\n                                <Edit2 size={10} />\n                                <input\n                                  type=\"color\"\n                                  value={hex}\n                                  onChange={(e) =>\n                                    updateColorInPalette(palette.id, i, e.target.value)\n                                  }\n                                  className=\"absolute inset-0 h-0 w-0 cursor-pointer opacity-0\"\n                                />\n                              </label>\n                              <button\n                                type=\"button\"\n                                onClick={(e) => {\n                                  e.stopPropagation();\n                                  removeColorFromPalette(palette.id, i);\n                                }}\n                                className=\"p-1 text-white/80 hover:text-red-400\"\n                              >\n                                <X size={10} />\n                              </button>\n                              <button\n                                type=\"button\"\n                                onClick={(e) => {\n                                  e.stopPropagation();\n                                  if (i < palette.colors.length - 1) {\n                                    reorderColorInPalette(palette.id, i, i + 1);\n                                  }\n                                }}\n                                disabled={i === palette.colors.length - 1}\n                                className=\"p-1 text-white/80 hover:text-white disabled:opacity-30\"\n                              >\n                                <ChevronRight size={10} />\n                              </button>\n                            </div>\n                          </div>\n                        </div>\n                      ))}\n                    </div>\n                  </div>\n                ))}\n              </div>\n            )}\n          </div>\n        </DraggableToolPanel>\n      )}\n    </div>\n  );\n};\n", "import React, { useRef, useState } from 'react';\nimport { ZoomIn, ZoomOut, Maximize, ChevronDown, Undo2, Redo2 } from 'lucide-react';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { useTranslation } from '../../i18n';\nimport { applyCanvasZoomRender } from '../../utils/canvasZoomRender';\nimport { ViewportPortalMenu } from '../../utils/ViewportPortalMenu';\nimport { TextBody } from '../ui';\n\nconst btnCls =\n  'h-8 w-8 rounded-lg flex items-center justify-center cursor-pointer text-white/80 hover:text-white hover:bg-[var(--we-accent-muted)] transition-all relative active:scale-95';\n\ntype CanvasZoomDockProps = {\n  /**\n   * `docked` \u2014 sits in the image bottom tool bar (default).\n   * `floating` \u2014 legacy absolute overlay (avoid for image shell).\n   */\n  variant?: 'docked' | 'floating';\n};\n\n/**\n * Undo / redo + zoom controls for the image canvas column.\n */\nexport const CanvasZoomDock: React.FC<CanvasZoomDockProps> = ({\n  variant = 'docked',\n}) => {\n  const t = useTranslation();\n  const [isZoomMenuOpen, setIsZoomMenuOpen] = useState(false);\n  const zoomTriggerRef = useRef<HTMLButtonElement | null>(null);\n  const {\n    zoom,\n    setZoom,\n    undo,\n    redo,\n    canUndo,\n    canRedo,\n    pages,\n    activePageId,\n    canvasInstance,\n  } = useEditorStore();\n\n  const activePage = pages.find((p) => p.id === activePageId) || pages[0];\n\n  const handleZoomIn = () => setZoom(Math.min(zoom + 0.1, 5));\n  const handleZoomOut = () => setZoom(Math.max(zoom - 0.1, 0.1));\n  const handleFitPage = () => {\n    if (!canvasInstance || !activePage) return;\n    const el = canvasInstance.getElement()?.parentElement;\n    if (!el) return;\n    const scaleX = el.clientWidth / activePage.width;\n    const scaleY = el.clientHeight / activePage.height;\n    const next = Math.min(scaleX, scaleY) * 0.9;\n    setZoom(next);\n    applyCanvasZoomRender(canvasInstance, activePage.width, activePage.height, next);\n  };\n\n  const shell =\n    variant === 'floating'\n      ? 'pointer-events-auto absolute top-8 right-3 z-50 flex items-center gap-0.5 rounded-panel border border-panel-border bg-panel p-1 shadow-2xl shadow-black/60 backdrop-blur-md select-none'\n      : 'flex shrink-0 items-center gap-0.5 select-none';\n\n  return (\n    <div className={shell}>\n      <button\n        type=\"button\"\n        onClick={() => undo()}\n        disabled={!canUndo()}\n        title={t.toolbar.image.undo}\n        className={`${btnCls} ${!canUndo() ? 'opacity-30 pointer-events-none' : ''}`}\n      >\n        <Undo2 size={14} />\n      </button>\n      <button\n        type=\"button\"\n        onClick={() => redo()}\n        disabled={!canRedo()}\n        title={t.toolbar.image.redo}\n        className={`${btnCls} ${!canRedo() ? 'opacity-30 pointer-events-none' : ''}`}\n      >\n        <Redo2 size={14} />\n      </button>\n\n      <div className=\"mx-0.5 h-5 w-px bg-panel-border\" aria-hidden />\n\n      <button type=\"button\" onClick={handleZoomOut} title={t.toolbar.image.zoomOut} className={btnCls}>\n        <ZoomOut size={14} />\n      </button>\n\n      <div className=\"relative\">\n        <button\n          ref={zoomTriggerRef}\n          type=\"button\"\n          onClick={() => setIsZoomMenuOpen((o) => !o)}\n          className=\"flex h-8 min-w-[58px] cursor-pointer select-none items-center justify-center gap-1 rounded-lg px-2.5 text-white/80 transition-all hover:bg-[var(--we-accent-muted)] hover:text-white\"\n        >\n          <Maximize size={10} className=\"text-white/80\" />\n          <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-inherit\">\n            {Math.round(zoom * 100)}%\n          </TextBody>\n          <ChevronDown\n            size={10}\n            className={`text-white/80 transition-transform duration-200 ${isZoomMenuOpen ? 'rotate-180' : ''}`}\n          />\n        </button>\n\n        <ViewportPortalMenu\n          open={isZoomMenuOpen}\n          onClose={() => setIsZoomMenuOpen(false)}\n          anchorRef={zoomTriggerRef}\n          prefer=\"above\"\n          align=\"left\"\n          zIndex={40}\n          className=\"flex w-36 flex-col gap-0.5 rounded-xl border border-panel-border bg-panel p-1.5 shadow-xl backdrop-blur-md\"\n        >\n          {[\n            { label: '50%', value: 0.5 },\n            { label: '75%', value: 0.75 },\n            { label: '100%', value: 1 },\n            { label: '150%', value: 1.5 },\n            { label: '200%', value: 2 },\n          ].map(({ label, value }) => (\n            <button\n              key={label}\n              type=\"button\"\n              onClick={() => {\n                setZoom(value);\n                setIsZoomMenuOpen(false);\n              }}\n              className={`cursor-pointer rounded-lg px-3 py-1.5 text-left transition-colors ${\n                Math.round(zoom * 100) === Math.round(value * 100)\n                  ? 'bg-[var(--we-accent)] text-white'\n                  : 'text-white hover:bg-black-capsule'\n              }`}\n            >\n              <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-inherit\">\n                {label}\n              </TextBody>\n            </button>\n          ))}\n          <div className=\"my-1 h-px bg-panel-border\" />\n          <button\n            type=\"button\"\n            onClick={() => {\n              handleFitPage();\n              setIsZoomMenuOpen(false);\n            }}\n            className=\"cursor-pointer rounded-lg px-3 py-1.5 text-left text-white transition-colors hover:bg-black-capsule\"\n          >\n            <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-white\">\n              {t.toolbar.image.fitCanvas}\n            </TextBody>\n          </button>\n        </ViewportPortalMenu>\n      </div>\n\n      <button type=\"button\" onClick={handleZoomIn} title={t.toolbar.image.zoomIn} className={btnCls}>\n        <ZoomIn size={14} />\n      </button>\n    </div>\n  );\n};\n", "import React, { memo } from 'react';\n\ntype FabricCanvasHostProps = {\n  canvasRef: React.RefObject<HTMLCanvasElement | null>;\n};\n\n/**\n * Stable mount point for Fabric. Parent zoom/pan re-renders must NOT\n * reconcile this node \u2014 Fabric owns the wrapper DOM around the canvas,\n * and React resetting it causes visible flicker while zooming.\n */\nfunction FabricCanvasHostImpl({ canvasRef }: FabricCanvasHostProps) {\n  return <canvas ref={canvasRef} />;\n}\n\nexport const FabricCanvasHost = memo(FabricCanvasHostImpl, () => true);\n", "import React, { useState, useEffect } from 'react';\nimport { X, Plus, Trash2, Check, Settings2, BarChart2, Lightbulb } from 'lucide-react';\nimport type { ChartDataPoint, ChartType, ChartOptions } from '../utils/chartUtils';\nimport { useTranslation } from '../i18n';\nimport { modeAccentVars, useModeAccent } from '../theme/modeAccent';\nimport { TextBody, TextTitle } from './ui';\n\ninterface ChartDataModalProps {\n  isOpen: boolean;\n  onClose: () => void;\n  initialData: ChartDataPoint[];\n  initialType: ChartType;\n  initialOptions?: Partial<ChartOptions>;\n  onSave: (data: ChartDataPoint[], type: ChartType, options: Partial<ChartOptions>) => void;\n}\n\nexport const ChartDataModal: React.FC<ChartDataModalProps> = ({\n  isOpen,\n  onClose,\n  initialData,\n  initialType,\n  initialOptions,\n  onSave,\n}) => {\n  const t = useTranslation();\n  const mode = useModeAccent();\n  const [activeTab, setActiveTab] = useState<'datos' | 'diseno'>('datos');\n\n  const [data, setData] = useState<ChartDataPoint[]>([]);\n  const [chartType, setChartType] = useState<ChartType>('bar');\n  const [options, setOptions] = useState<Partial<ChartOptions>>({\n    showLabels: true,\n    theme: 'dark',\n    textColor: '#ffffff',\n    backgroundColor: 'transparent',\n  });\n\n  useEffect(() => {\n    if (isOpen) {\n      setData(JSON.parse(JSON.stringify(initialData)));\n      setChartType(initialType);\n      setActiveTab('datos');\n      if (initialOptions) {\n        setOptions((prev) => ({ ...prev, ...initialOptions }));\n      } else {\n        setOptions({\n          showLabels: true,\n          theme: 'dark',\n          textColor: '#ffffff',\n          backgroundColor: 'transparent',\n        });\n      }\n    }\n  }, [isOpen, initialData, initialType, initialOptions]);\n\n  if (!isOpen) return null;\n\n  const handleUpdateRow = (index: number, field: keyof ChartDataPoint, value: string | number) => {\n    const newData = [...data];\n    const row = newData[index];\n    if (!row) return;\n    if (field === 'value') {\n      row.value = Number(value) || 0;\n    } else if (field === 'label') {\n      row.label = String(value);\n    } else if (field === 'color') {\n      row.color = String(value);\n    }\n    setData(newData);\n  };\n\n  const handleAddRow = () => {\n    setData([\n      ...data,\n      { label: t.modal.chartData.itemLabel(data.length + 1), value: 10, color: '#DB2777' },\n    ]);\n  };\n\n  const handleDeleteRow = (index: number) => {\n    setData(data.filter((_, i) => i !== index));\n  };\n\n  const handleSave = () => {\n    onSave(data, chartType, options);\n    onClose();\n  };\n\n  const tabActive =\n    'border-[var(--we-accent)] text-[var(--we-accent)]';\n  const tabIdle = 'border-transparent text-white/80 hover:text-white';\n  const typeActive =\n    'bg-[var(--we-accent)] border-[var(--we-accent)] text-white';\n  const typeIdle =\n    'bg-black-capsule border-panel-border text-white/80 hover:bg-black-capsule-hover hover:text-white';\n\n  return (\n    <div\n      className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4 animate-fade-in\"\n      style={modeAccentVars(mode)}\n      data-we-mode={mode}\n    >\n      <div className=\"bg-panel border border-panel-border rounded-2xl w-full max-w-xl overflow-hidden shadow-2xl flex flex-col max-h-[90vh]\">\n        <div className=\"border-b border-panel-border bg-black-capsule/40\">\n          <div className=\"flex items-center justify-between p-4 pb-2\">\n            <TextTitle as=\"h2\" size=\"sm\" className=\"uppercase tracking-wider\">\n              {t.modal.chartData.title}\n            </TextTitle>\n            <button\n              type=\"button\"\n              onClick={onClose}\n              className=\"p-1.5 text-white/80 hover:text-white rounded-lg hover:bg-black-capsule transition-colors\"\n            >\n              <X size={16} />\n            </button>\n          </div>\n\n          <div className=\"flex px-4 gap-4\">\n            <button\n              type=\"button\"\n              onClick={() => setActiveTab('datos')}\n              className={`pb-3 px-1 border-b-2 transition-all flex items-center gap-1.5 ${\n                activeTab === 'datos' ? tabActive : tabIdle\n              }`}\n            >\n              <BarChart2 size={14} />\n              <TextBody as=\"span\" size=\"sm\" className=\"font-bold uppercase tracking-wide\">\n                {t.modal.chartData.tabData}\n              </TextBody>\n            </button>\n            <button\n              type=\"button\"\n              onClick={() => setActiveTab('diseno')}\n              className={`pb-3 px-1 border-b-2 transition-all flex items-center gap-1.5 ${\n                activeTab === 'diseno' ? tabActive : tabIdle\n              }`}\n            >\n              <Settings2 size={14} />\n              <TextBody as=\"span\" size=\"sm\" className=\"font-bold uppercase tracking-wide\">\n                {t.modal.chartData.tabDesign}\n              </TextBody>\n            </button>\n          </div>\n        </div>\n\n        <div className=\"p-4 flex-1 overflow-y-auto custom-scrollbar flex flex-col gap-4\">\n          <div className=\"flex flex-col gap-2\">\n            <TextBody as=\"label\" size=\"sm\" className=\"font-bold text-white/80 uppercase tracking-wider\">\n              {t.modal.chartData.chartType}\n            </TextBody>\n            <div className=\"grid grid-cols-4 gap-2\">\n              {(\n                [\n                  { id: 'bar', label: t.modal.chartData.bar },\n                  { id: 'line', label: t.modal.chartData.line },\n                  { id: 'pie', label: t.modal.chartData.pie },\n                  { id: 'donut', label: t.modal.chartData.donut },\n                ] as const\n              ).map((item) => (\n                <button\n                  key={item.id}\n                  type=\"button\"\n                  onClick={() => setChartType(item.id)}\n                  className={`py-2 px-3 rounded-xl border transition-all ${\n                    chartType === item.id ? typeActive : typeIdle\n                  }`}\n                >\n                  <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                    {item.label}\n                  </TextBody>\n                </button>\n              ))}\n            </div>\n          </div>\n\n          <div className=\"h-px bg-panel-border w-full my-1\" />\n\n          {activeTab === 'datos' && (\n            <div className=\"flex flex-col gap-2 animate-fade-in\">\n              <div className=\"flex items-center justify-between\">\n                <TextBody as=\"label\" size=\"sm\" className=\"font-bold text-white/80 uppercase tracking-wider\">\n                  {t.modal.chartData.valuesTable}\n                </TextBody>\n                <button\n                  type=\"button\"\n                  onClick={handleAddRow}\n                  className=\"flex items-center gap-1 bg-black-capsule hover:bg-black-capsule-hover text-white/80 hover:text-white px-2 py-1 rounded transition-colors\"\n                >\n                  <Plus size={12} />\n                  <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                    {t.modal.chartData.addRow}\n                  </TextBody>\n                </button>\n              </div>\n\n              <div className=\"bg-black-capsule border border-panel-border rounded-xl overflow-hidden shadow-inner\">\n                <table className=\"w-full text-left text-white/80\">\n                  <thead className=\"bg-panel border-b border-panel-border\">\n                    <tr>\n                      <th className=\"px-3 py-2 w-[40%]\">\n                        <TextBody as=\"span\" size=\"sm\" className=\"uppercase text-white/80\">\n                          {t.modal.chartData.labelCol}\n                        </TextBody>\n                      </th>\n                      <th className=\"px-3 py-2 w-[30%]\">\n                        <TextBody as=\"span\" size=\"sm\" className=\"uppercase text-white/80\">\n                          {t.modal.chartData.valueCol}\n                        </TextBody>\n                      </th>\n                      <th className=\"px-3 py-2 w-[20%]\">\n                        <TextBody as=\"span\" size=\"sm\" className=\"uppercase text-white/80\">\n                          {t.modal.chartData.colorCol}\n                        </TextBody>\n                      </th>\n                      <th className=\"px-3 py-2 w-[10%] text-right\" />\n                    </tr>\n                  </thead>\n                  <tbody>\n                    {data.map((row, index) => (\n                      <tr\n                        key={index}\n                        className=\"border-b border-panel-border/50 last:border-0 hover:bg-white/5 transition-colors\"\n                      >\n                        <td className=\"px-3 py-1.5\">\n                          <input\n                            type=\"text\"\n                            value={row.label}\n                            onChange={(e) => handleUpdateRow(index, 'label', e.target.value)}\n                            className=\"w-full bg-transparent border-none font-sans text-xs font-medium text-white focus:ring-0 px-0 py-1 outline-none\"\n                            placeholder={t.modal.chartData.rowNamePlaceholder}\n                          />\n                        </td>\n                        <td className=\"px-3 py-1.5\">\n                          <input\n                            type=\"number\"\n                            value={row.value}\n                            onChange={(e) => handleUpdateRow(index, 'value', e.target.value)}\n                            className=\"w-full bg-transparent border-none font-sans text-xs font-medium text-white focus:ring-0 px-0 py-1 outline-none\"\n                            placeholder=\"0\"\n                          />\n                        </td>\n                        <td className=\"px-3 py-1.5\">\n                          <div className=\"flex items-center gap-2\">\n                            <label className=\"w-5 h-5 rounded cursor-pointer overflow-hidden border border-white/10 flex-shrink-0 relative\">\n                              <input\n                                type=\"color\"\n                                value={row.color}\n                                onChange={(e) => handleUpdateRow(index, 'color', e.target.value)}\n                                className=\"absolute inset-0 opacity-0 cursor-pointer w-full h-full\"\n                              />\n                              <div className=\"w-full h-full\" style={{ backgroundColor: row.color }} />\n                            </label>\n                            <TextBody as=\"span\" size=\"sm\" className=\"font-mono uppercase text-white/80\">\n                              {row.color}\n                            </TextBody>\n                          </div>\n                        </td>\n                        <td className=\"px-3 py-1.5 text-right\">\n                          <button\n                            type=\"button\"\n                            onClick={() => handleDeleteRow(index)}\n                            className=\"text-white/50 hover:text-red-400 transition-colors p-1\"\n                            title={t.modal.versionHistory.delete}\n                          >\n                            <Trash2 size={13} />\n                          </button>\n                        </td>\n                      </tr>\n                    ))}\n                    {data.length === 0 && (\n                      <tr>\n                        <td colSpan={4} className=\"px-4 py-8 text-center\">\n                          <TextBody as=\"span\" size=\"sm\" className=\"italic text-white/80\">\n                            {t.modal.chartData.noData}\n                          </TextBody>\n                        </td>\n                      </tr>\n                    )}\n                  </tbody>\n                </table>\n              </div>\n            </div>\n          )}\n\n          {activeTab === 'diseno' && (\n            <div className=\"flex flex-col gap-4 animate-fade-in\">\n              <div className=\"grid grid-cols-2 gap-4\">\n                <div className=\"flex flex-col gap-2\">\n                  <TextBody as=\"label\" size=\"sm\" className=\"font-bold text-white/80 uppercase tracking-wider\">\n                    {t.modal.chartData.themeLabel}\n                  </TextBody>\n                  <div className=\"flex bg-black-capsule p-1 rounded-lg border border-panel-border\">\n                    <button\n                      type=\"button\"\n                      onClick={() => setOptions({ ...options, theme: 'dark' })}\n                      className={`flex-1 py-1.5 rounded-md transition-all ${\n                        options.theme === 'dark'\n                          ? 'bg-[var(--we-accent)] text-white shadow-sm'\n                          : 'text-white/80 hover:text-white'\n                      }`}\n                    >\n                      <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                        {t.modal.chartData.dark}\n                      </TextBody>\n                    </button>\n                    <button\n                      type=\"button\"\n                      onClick={() => setOptions({ ...options, theme: 'light' })}\n                      className={`flex-1 py-1.5 rounded-md transition-all ${\n                        options.theme === 'light'\n                          ? 'bg-[var(--we-accent)] text-white shadow-sm'\n                          : 'text-white/80 hover:text-white'\n                      }`}\n                    >\n                      <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                        {t.modal.chartData.light}\n                      </TextBody>\n                    </button>\n                  </div>\n                </div>\n\n                <div className=\"flex flex-col gap-2\">\n                  <TextBody as=\"label\" size=\"sm\" className=\"font-bold text-white/80 uppercase tracking-wider\">\n                    {t.modal.chartData.numericValuesLabel}\n                  </TextBody>\n                  <label className=\"flex items-center justify-between bg-panel border border-panel-border rounded-lg p-2 px-3 cursor-pointer hover:bg-black-capsule transition-colors\">\n                    <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-white/80\">\n                      {t.modal.chartData.showDataLabels}\n                    </TextBody>\n                    <div className=\"relative inline-block w-8 h-4 rounded-full bg-black-capsule transition-colors\">\n                      <input\n                        type=\"checkbox\"\n                        checked={!!options.showLabels}\n                        onChange={(e) => setOptions({ ...options, showLabels: e.target.checked })}\n                        className=\"sr-only\"\n                      />\n                      <div\n                        className={`absolute w-3 h-3 rounded-full top-0.5 transition-all ${\n                          options.showLabels\n                            ? 'left-[18px] bg-[var(--we-accent)] shadow-[0_0_8px_color-mix(in_srgb,var(--we-accent)_50%,transparent)]'\n                            : 'left-0.5 bg-white opacity-50'\n                        }`}\n                      />\n                    </div>\n                  </label>\n                </div>\n\n                <div className=\"flex flex-col gap-2\">\n                  <TextBody as=\"label\" size=\"sm\" className=\"font-bold text-white/80 uppercase tracking-wider\">\n                    {t.modal.chartData.textColorLabel}\n                  </TextBody>\n                  <div className=\"flex items-center gap-2 bg-panel border border-panel-border rounded-lg p-1.5 pr-3\">\n                    <label className=\"w-7 h-7 rounded cursor-pointer overflow-hidden border border-white/10 flex-shrink-0 relative\">\n                      <input\n                        type=\"color\"\n                        value={options.textColor}\n                        onChange={(e) => setOptions({ ...options, textColor: e.target.value })}\n                        className=\"absolute inset-0 opacity-0 cursor-pointer w-full h-full\"\n                      />\n                      <div className=\"w-full h-full\" style={{ backgroundColor: options.textColor }} />\n                    </label>\n                    <input\n                      type=\"text\"\n                      value={options.textColor?.toUpperCase()}\n                      onChange={(e) => setOptions({ ...options, textColor: e.target.value })}\n                      className=\"bg-transparent border-none font-sans text-xs font-medium text-white font-mono uppercase focus:outline-none flex-1\"\n                    />\n                  </div>\n                </div>\n\n                <div className=\"flex flex-col gap-2\">\n                  <TextBody as=\"label\" size=\"sm\" className=\"font-bold text-white/80 uppercase tracking-wider\">\n                    {t.modal.chartData.bgColorLabel}\n                  </TextBody>\n                  <div className=\"flex items-center gap-2 bg-panel border border-panel-border rounded-lg p-1.5 pr-3\">\n                    <label className=\"w-7 h-7 rounded cursor-pointer overflow-hidden border border-white/10 flex-shrink-0 relative\">\n                      <input\n                        type=\"color\"\n                        value={\n                          options.backgroundColor === 'transparent'\n                            ? '#000000'\n                            : options.backgroundColor\n                        }\n                        onChange={(e) =>\n                          setOptions({ ...options, backgroundColor: e.target.value })\n                        }\n                        className=\"absolute inset-0 opacity-0 cursor-pointer w-full h-full\"\n                      />\n                      <div\n                        className=\"w-full h-full\"\n                        style={{\n                          backgroundColor:\n                            options.backgroundColor === 'transparent'\n                              ? 'transparent'\n                              : options.backgroundColor,\n                          backgroundImage:\n                            options.backgroundColor === 'transparent'\n                              ? 'url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABZJREFUeNpi2rV7928Gxv///zMABBgA7ZAHy6q2LhcAAAAASUVORK5CYII=\")'\n                              : 'none',\n                        }}\n                      />\n                    </label>\n                    <div className=\"flex flex-col flex-1 gap-1\">\n                      <input\n                        type=\"text\"\n                        value={\n                          options.backgroundColor === 'transparent'\n                            ? t.panel.transparent\n                            : options.backgroundColor?.toUpperCase()\n                        }\n                        onChange={(e) => {\n                          const val = e.target.value.trim();\n                          if (/^(none|transparent|transparente)$/i.test(val)) {\n                            setOptions({ ...options, backgroundColor: 'transparent' });\n                            return;\n                          }\n                          setOptions({ ...options, backgroundColor: e.target.value });\n                        }}\n                        className=\"bg-transparent border-none font-sans text-xs font-medium text-white font-mono focus:outline-none w-full placeholder:normal-case\"\n                      />\n                      <label className=\"flex items-center gap-1.5 cursor-pointer\">\n                        <input\n                          type=\"checkbox\"\n                          checked={options.backgroundColor === 'transparent'}\n                          onChange={(e) =>\n                            setOptions({\n                              ...options,\n                              backgroundColor: e.target.checked ? 'transparent' : '#111827',\n                            })\n                          }\n                          className=\"accent-[var(--we-accent)] rounded-sm w-3 h-3\"\n                        />\n                        <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                          {t.modal.chartData.transparentBg}\n                        </TextBody>\n                      </label>\n                    </div>\n                  </div>\n                </div>\n              </div>\n\n              <div className=\"mt-2 p-3 bg-[var(--we-accent-muted)] border border-[var(--we-accent)]/20 rounded-xl flex items-start gap-2\">\n                <Lightbulb size={20} className=\"text-[var(--we-accent)] flex-shrink-0 mt-0.5\" />\n                <TextBody as=\"p\" size=\"sm\" className=\"leading-relaxed text-white/80\">\n                  {t.modal.chartData.proTip}\n                </TextBody>\n              </div>\n            </div>\n          )}\n        </div>\n\n        <div className=\"p-4 border-t border-panel-border bg-black-capsule/40 flex justify-end gap-3\">\n          <button\n            type=\"button\"\n            onClick={onClose}\n            className=\"px-4 py-2 text-white/80 hover:text-white transition-colors\"\n          >\n            <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n              {t.modal.dialog.cancel}\n            </TextBody>\n          </button>\n          <button\n            type=\"button\"\n            onClick={handleSave}\n            className=\"flex items-center gap-2 px-6 py-2 bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] text-white rounded-xl transition-all shadow-lg shadow-[color-mix(in_srgb,var(--we-accent)_25%,transparent)] active:scale-95\"\n          >\n            <Check size={14} />\n            <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-white\">\n              {t.modal.chartData.apply}\n            </TextBody>\n          </button>\n        </div>\n      </div>\n    </div>\n  );\n};\n", "/**\n * Align Fabric pointer \u2192 scene mapping with CSS-scale zoom.\n *\n * Visual zoom uses `transform: scale(...)` on the Fabric wrapper\n * (`applyCanvasZoomRender`). Fabric's default pointer path mixes\n * `clientX + scroll`, element offset (+ scroll again), retina, and\n * backing-store size \u2014 which drifts from the cursor for brush/eraser.\n *\n * Map with getBoundingClientRect + logical canvas size only.\n */\n\nimport { Point, util, type Canvas, type TPointerEvent } from 'fabric';\n\nfunction clientXY(e: TPointerEvent): { x: number; y: number } {\n  const ne = e as MouseEvent & {\n    touches?: TouchList;\n    changedTouches?: TouchList;\n  };\n  const t = ne.touches?.[0] || ne.changedTouches?.[0];\n  return {\n    x: t ? t.clientX : ne.clientX,\n    y: t ? t.clientY : ne.clientY,\n  };\n}\n\nfunction isIdentityVpt(vpt: number[] | undefined): boolean {\n  if (!vpt || vpt.length < 6) return true;\n  return (\n    Math.abs(vpt[0]! - 1) < 1e-6 &&\n    Math.abs(vpt[3]! - 1) < 1e-6 &&\n    Math.abs(vpt[1]!) < 1e-6 &&\n    Math.abs(vpt[2]!) < 1e-6 &&\n    Math.abs(vpt[4]!) < 1e-6 &&\n    Math.abs(vpt[5]!) < 1e-6\n  );\n}\n\n/** Viewport (screen-mapped) point in logical canvas pixels. */\nfunction pointerFromEvent(canvas: Canvas, e: TPointerEvent): Point {\n  const el = canvas.upperCanvasEl;\n  if (!el) return new Point(0, 0);\n  const bounds = el.getBoundingClientRect();\n  const { x: cx, y: cy } = clientXY(e);\n  const bw = bounds.width || 1;\n  const bh = bounds.height || 1;\n  const lw = Math.max(1, canvas.getWidth());\n  const lh = Math.max(1, canvas.getHeight());\n  return new Point(((cx - bounds.left) / bw) * lw, ((cy - bounds.top) / bh) * lh);\n}\n\nexport function patchFabricPointerForCssZoom(canvas: Canvas): void {\n  canvas.getViewportPoint = ((e: TPointerEvent) =>\n    pointerFromEvent(canvas, e)) as Canvas['getViewportPoint'];\n\n  canvas.getScenePoint = ((e: TPointerEvent) => {\n    const viewport = pointerFromEvent(canvas, e);\n    const vpt = canvas.viewportTransform;\n    if (isIdentityVpt(vpt)) return viewport;\n    // Viewport \u2192 scene (undo Fabric viewportTransform).\n    return util.sendPointToPlane(viewport, vpt as [number, number, number, number, number, number], undefined);\n  }) as Canvas['getScenePoint'];\n}\n", "import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { Point, type FabricImage, type FabricObject } from 'fabric';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport {\n  getPixelLayerContentOriginFractions,\n  getPixelLayerContentSceneCorners,\n  isPixelLayer,\n  pixelLayerHasContent,\n  syncPixelLayerInteraction,\n} from '../../utils/pixelLayer';\nimport { clampCropRectToImage, type CropOverlayRect } from '../../utils/imageCrop';\n\ntype HandleId = 'tl' | 'mt' | 'tr' | 'ml' | 'mr' | 'bl' | 'mb' | 'br' | 'rotate';\n\ntype OverlayBox = {\n  left: number;\n  top: number;\n  width: number;\n  height: number;\n  locked: boolean;\n  /** Crop tool: only mid-edge handles, no rotate. */\n  cropMode?: boolean;\n};\n\ntype OriginFrac = number | 'left' | 'center' | 'right' | 'top' | 'bottom';\n\ntype DragState = {\n  handle: HandleId;\n  startX: number;\n  startY: number;\n  originScaleX: number;\n  originScaleY: number;\n  originAngle: number;\n  /** Unscaled pixel size used for scale math (content bounds for pixel layers). */\n  originWidth: number;\n  originHeight: number;\n  /** Shift: scale from center (both sides move). */\n  centerSceneX: number;\n  centerSceneY: number;\n  centerClientX: number;\n  centerClientY: number;\n  centerFracX: OriginFrac;\n  centerFracY: OriginFrac;\n  /** Default: opposite edge/corner stays fixed. */\n  edgeAnchorX: number;\n  edgeAnchorY: number;\n  edgeFracX: OriginFrac;\n  edgeFracY: OriginFrac;\n};\n\n/** Opposite edge/corner to the dragged handle (Fabric / content origin). */\nfunction oppositeOriginForHandle(handle: HandleId): { ox: OriginFrac; oy: OriginFrac } {\n  switch (handle) {\n    case 'mr':\n      return { ox: 'left', oy: 'center' };\n    case 'ml':\n      return { ox: 'right', oy: 'center' };\n    case 'mb':\n      return { ox: 'center', oy: 'top' };\n    case 'mt':\n      return { ox: 'center', oy: 'bottom' };\n    case 'br':\n      return { ox: 'left', oy: 'top' };\n    case 'bl':\n      return { ox: 'right', oy: 'top' };\n    case 'tr':\n      return { ox: 'left', oy: 'bottom' };\n    case 'tl':\n      return { ox: 'right', oy: 'bottom' };\n    default:\n      return { ox: 'center', oy: 'center' };\n  }\n}\n\nfunction anchorPointForHandle(\n  handle: HandleId,\n  left: number,\n  top: number,\n  right: number,\n  bottom: number,\n): { x: number; y: number } {\n  const cx = (left + right) / 2;\n  const cy = (top + bottom) / 2;\n  switch (handle) {\n    case 'mr':\n      return { x: left, y: cy };\n    case 'ml':\n      return { x: right, y: cy };\n    case 'mb':\n      return { x: cx, y: top };\n    case 'mt':\n      return { x: cx, y: bottom };\n    case 'br':\n      return { x: left, y: top };\n    case 'bl':\n      return { x: right, y: top };\n    case 'tr':\n      return { x: left, y: bottom };\n    case 'tl':\n      return { x: right, y: bottom };\n    default:\n      return { x: cx, y: cy };\n  }\n}\n\ntype HostMapCache = {\n  ox: number;\n  oy: number;\n  /** Uniform page\u2192host scale (visual zoom). Always sx === sy. */\n  scale: number;\n};\n\nconst BOX_EPSILON_PX = 0.5;\n\nfunction isLockedObject(obj: FabricObject): boolean {\n  return !!(obj as FabricObject & { locked?: boolean }).locked || obj.lockMovementX === true;\n}\n\nfunction isCropOverlay(obj: FabricObject | null | undefined): boolean {\n  return !!(obj as FabricObject & { isImageCropOverlay?: boolean })?.isImageCropOverlay;\n}\n\n/**\n * Map Fabric scene (page) px \u2192 host (pageFrame) px.\n * Scale is measured from the canvas element (CSS zoom included), averaged so\n * X/Y stay uniform \u2014 never use store.zoom alone (it can lag the DOM scale).\n */\nfunction buildHostMap(\n  canvas: {\n    getWidth: () => number;\n    getHeight: () => number;\n    upperCanvasEl?: HTMLCanvasElement | null;\n    getElement?: () => HTMLCanvasElement;\n  },\n  host: HTMLElement,\n): HostMapCache | null {\n  const el = canvas.upperCanvasEl || canvas.getElement?.();\n  if (!el) return null;\n  const canvasRect = el.getBoundingClientRect();\n  const hostRect = host.getBoundingClientRect();\n  const cw = Math.max(1, canvas.getWidth());\n  const ch = Math.max(1, canvas.getHeight());\n  const sx = canvasRect.width / cw;\n  const sy = canvasRect.height / ch;\n  // Uniform scale avoids anamorphic chrome; measured from DOM so it matches CSS zoom.\n  const scale = Math.max(0.01, (sx + sy) / 2);\n  return {\n    ox: canvasRect.left - hostRect.left,\n    oy: canvasRect.top - hostRect.top,\n    scale,\n  };\n}\n\nfunction sceneToHostCached(map: HostMapCache, sceneX: number, sceneY: number): { x: number; y: number } {\n  return {\n    x: map.ox + sceneX * map.scale,\n    y: map.oy + sceneY * map.scale,\n  };\n}\n\nfunction snapBox(raw: OverlayBox): OverlayBox {\n  const left = Math.round(raw.left);\n  const top = Math.round(raw.top);\n  const right = Math.round(raw.left + raw.width);\n  const bottom = Math.round(raw.top + raw.height);\n  return {\n    left,\n    top,\n    width: Math.max(1, right - left),\n    height: Math.max(1, bottom - top),\n    locked: raw.locked,\n    cropMode: raw.cropMode,\n  };\n}\n\nfunction boxesEqual(a: OverlayBox | null, b: OverlayBox | null): boolean {\n  if (a === b) return true;\n  if (!a || !b) return false;\n  return (\n    a.locked === b.locked &&\n    !!a.cropMode === !!b.cropMode &&\n    Math.abs(a.left - b.left) < BOX_EPSILON_PX &&\n    Math.abs(a.top - b.top) < BOX_EPSILON_PX &&\n    Math.abs(a.width - b.width) < BOX_EPSILON_PX &&\n    Math.abs(a.height - b.height) < BOX_EPSILON_PX\n  );\n}\n\nfunction resolveCropTargetImage(\n  canvas: { getObjects: () => FabricObject[] },\n  cropRect: CropOverlayRect,\n): FabricImage | null {\n  const id = cropRect.weCropImageId;\n  if (id) {\n    const byId = canvas.getObjects().find(\n      (o) => (o as FabricObject & { id?: string }).id === id,\n    );\n    if (byId && (byId.type || '').toLowerCase() === 'image') return byId as FabricImage;\n  }\n  const images = canvas.getObjects().filter(\n    (o) =>\n      (o.type || '').toLowerCase() === 'image' &&\n      !isCropOverlay(o),\n  );\n  return (images[0] as FabricImage | undefined) ?? null;\n}\n\nfunction readOverlayBox(\n  canvas: {\n    getActiveObject: () => FabricObject | undefined;\n    getObjects?: () => FabricObject[];\n    getWidth: () => number;\n    getHeight: () => number;\n    upperCanvasEl?: HTMLCanvasElement | null;\n    getElement?: () => HTMLCanvasElement;\n  },\n  host: HTMLElement,\n  opts?: { skipSetCoords?: boolean; map?: HostMapCache | null },\n): OverlayBox | null {\n  const obj = canvas.getActiveObject();\n  if (!obj) return null;\n  const tool = useEditorStore.getState().activeTool;\n  if (tool === 'pen') return null;\n\n  const cropMode = tool === 'crop' && isCropOverlay(obj);\n  if (tool === 'crop' && !cropMode) return null;\n  if (!cropMode && isCropOverlay(obj)) return null;\n\n  if (!cropMode && isPixelLayer(obj) && !pixelLayerHasContent(obj)) return null;\n\n  if (!opts?.skipSetCoords) obj.setCoords();\n\n  let sceneCorners: { x: number; y: number }[] | null = null;\n  if (!cropMode && isPixelLayer(obj)) {\n    sceneCorners = getPixelLayerContentSceneCorners(obj);\n    // Never fall back to getCoords() for pixel layers \u2014 that is the page buffer size.\n    if (!sceneCorners) return null;\n  } else {\n    const coords = obj.getCoords();\n    if (!coords || coords.length < 4) return null;\n    sceneCorners = coords.map((p) => ({ x: p.x, y: p.y }));\n  }\n\n  const map = opts?.map ?? buildHostMap(canvas, host);\n  if (!map) return null;\n\n  const pts = sceneCorners.map((p) => sceneToHostCached(map, p.x, p.y));\n  const xs = pts.map((p) => p.x);\n  const ys = pts.map((p) => p.y);\n  const left = Math.min(...xs);\n  const right = Math.max(...xs);\n  const top = Math.min(...ys);\n  const bottom = Math.max(...ys);\n\n  return snapBox({\n    left,\n    top,\n    width: Math.max(1, right - left),\n    height: Math.max(1, bottom - top),\n    locked: cropMode ? false : isLockedObject(obj),\n    cropMode,\n  });\n}\n\nconst HANDLES: { id: HandleId; cursor: string; posClass: string }[] = [\n  { id: 'tl', cursor: 'nwse-resize', posClass: 'left-0 top-0' },\n  { id: 'mt', cursor: 'ns-resize', posClass: 'left-1/2 top-0' },\n  { id: 'tr', cursor: 'nesw-resize', posClass: 'left-full top-0' },\n  { id: 'ml', cursor: 'ew-resize', posClass: 'left-0 top-1/2' },\n  { id: 'mr', cursor: 'ew-resize', posClass: 'left-full top-1/2' },\n  { id: 'bl', cursor: 'nesw-resize', posClass: 'left-0 top-full' },\n  { id: 'mb', cursor: 'ns-resize', posClass: 'left-1/2 top-full' },\n  { id: 'br', cursor: 'nwse-resize', posClass: 'left-full top-full' },\n];\n\n/**\n * DOM selection chrome. During object transforms the box is painted\n * imperatively (no React re-render) so it stays glued to the layer.\n */\nexport const SelectionControlsOverlay: React.FC<{\n  hostRef: React.RefObject<HTMLElement | null>;\n}> = ({ hostRef }) => {\n  const canvasInstance = useEditorStore((s) => s.canvasInstance);\n  const zoom = useEditorStore((s) => s.zoom);\n  const activeObject = useEditorStore((s) => s.activeObject);\n  const activeTool = useEditorStore((s) => s.activeTool);\n  const saveHistoryState = useEditorStore((s) => s.saveHistoryState);\n\n  // React only tracks visibility / lock / crop \u2014 geometry is applied via DOM.\n  const [chrome, setChrome] = useState<{ visible: boolean; locked: boolean; cropMode: boolean }>({\n    visible: false,\n    locked: false,\n    cropMode: false,\n  });\n\n  const dragRef = useRef<DragState | null>(null);\n  const boxRef = useRef<OverlayBox | null>(null);\n  const boxElRef = useRef<HTMLDivElement | null>(null);\n  const rafRef = useRef<number | null>(null);\n  const mapCacheRef = useRef<HostMapCache | null>(null);\n  const paintBoxRef = useRef<(next: OverlayBox | null) => void>(() => {});\n\n  const paintBox = (next: OverlayBox | null) => {\n    const el = boxElRef.current;\n    if (!next || next.width < 2 || next.height < 2) {\n      if (el) el.style.visibility = 'hidden';\n      if (boxRef.current !== null) boxRef.current = null;\n      setChrome((prev) =>\n        prev.visible ? { visible: false, locked: false, cropMode: false } : prev,\n      );\n      return;\n    }\n\n    if (!boxesEqual(boxRef.current, next)) {\n      boxRef.current = next;\n      if (el) {\n        el.style.visibility = 'visible';\n        // transform is cheaper than left/top for continuous dragging.\n        el.style.transform = `translate(${next.left}px, ${next.top}px)`;\n        el.style.width = `${next.width}px`;\n        el.style.height = `${next.height}px`;\n      }\n    }\n\n    setChrome((prev) =>\n      prev.visible &&\n      prev.locked === next.locked &&\n      prev.cropMode === !!next.cropMode\n        ? prev\n        : { visible: true, locked: next.locked, cropMode: !!next.cropMode },\n    );\n  };\n  paintBoxRef.current = paintBox;\n\n  useLayoutEffect(() => {\n    // Sync DOM node after React mounts chrome.\n    const next = boxRef.current;\n    const el = boxElRef.current;\n    if (!el || !next) return;\n    el.style.visibility = 'visible';\n    el.style.transform = `translate(${next.left}px, ${next.top}px)`;\n    el.style.width = `${next.width}px`;\n    el.style.height = `${next.height}px`;\n  }, [chrome.visible]);\n\n  useEffect(() => {\n    const canvas = canvasInstance;\n    const host = hostRef.current;\n    if (!canvas || !host) {\n      boxRef.current = null;\n      setChrome({ visible: false, locked: false, cropMode: false });\n      return;\n    }\n\n    const hideNativeChrome = () => {\n      const obj = canvas.getActiveObject();\n      if (!obj) return;\n      // Crop overlay + normal selection: DOM chrome owns handles (visible off-artboard).\n      if (isCropOverlay(obj) || useEditorStore.getState().activeTool === 'crop') {\n        if (isCropOverlay(obj)) {\n          obj.set({\n            hasControls: false,\n            hasBorders: false,\n            borderColor: 'transparent',\n            cornerColor: 'transparent',\n            cornerStrokeColor: 'transparent',\n            borderOpacityWhenMoving: 0,\n            padding: 0,\n          });\n        }\n        return;\n      }\n      if (isPixelLayer(obj)) {\n        // Re-apply content-only hit testing (page-sized buffers must not steal clicks).\n        syncPixelLayerInteraction(obj);\n        return;\n      }\n      obj.set({\n        hasControls: false,\n        hasBorders: false,\n        borderColor: 'transparent',\n        cornerColor: 'transparent',\n        cornerStrokeColor: 'transparent',\n        borderOpacityWhenMoving: 0,\n        padding: 0,\n      });\n      if (typeof obj.setControlsVisibility === 'function') {\n        obj.setControlsVisibility({\n          tl: false,\n          tr: false,\n          bl: false,\n          br: false,\n          ml: false,\n          mt: false,\n          mr: false,\n          mb: false,\n          mtr: false,\n        });\n      }\n    };\n\n    const refresh = (opts?: { skipSetCoords?: boolean; rebuildMap?: boolean }) => {\n      if (opts?.rebuildMap !== false) {\n        mapCacheRef.current = buildHostMap(canvas, host);\n      }\n      paintBoxRef.current(\n        readOverlayBox(canvas, host, {\n          skipSetCoords: opts?.skipSetCoords,\n          map: mapCacheRef.current,\n        }),\n      );\n    };\n\n    // One paint per animation frame during continuous transforms.\n    const scheduleLive = () => {\n      if (rafRef.current != null) return;\n      rafRef.current = requestAnimationFrame(() => {\n        rafRef.current = null;\n        // setCoords already ran inside Fabric's transform path.\n        refresh({ skipSetCoords: true, rebuildMap: false });\n      });\n    };\n\n    const onSel = () => {\n      hideNativeChrome();\n      mapCacheRef.current = buildHostMap(canvas, host);\n      refresh({ rebuildMap: false });\n    };\n\n    const onModified = () => {\n      mapCacheRef.current = buildHostMap(canvas, host);\n      refresh({ rebuildMap: false });\n    };\n\n    canvas.on('selection:created', onSel);\n    canvas.on('selection:updated', onSel);\n    canvas.on('selection:cleared', onModified);\n    canvas.on('object:moving', scheduleLive);\n    canvas.on('object:scaling', scheduleLive);\n    canvas.on('object:rotating', scheduleLive);\n    canvas.on('object:modified', onModified);\n\n    hideNativeChrome();\n    mapCacheRef.current = buildHostMap(canvas, host);\n    refresh({ rebuildMap: false });\n\n    return () => {\n      if (rafRef.current != null) {\n        cancelAnimationFrame(rafRef.current);\n        rafRef.current = null;\n      }\n      canvas.off('selection:created', onSel);\n      canvas.off('selection:updated', onSel);\n      canvas.off('selection:cleared', onModified);\n      canvas.off('object:moving', scheduleLive);\n      canvas.off('object:scaling', scheduleLive);\n      canvas.off('object:rotating', scheduleLive);\n      canvas.off('object:modified', onModified);\n    };\n  }, [canvasInstance, hostRef, zoom, activeObject, activeTool]);\n\n  useEffect(() => {\n    const onMove = (e: PointerEvent) => {\n      const drag = dragRef.current;\n      const canvas = canvasInstance;\n      const obj = canvas?.getActiveObject();\n      const host = hostRef.current;\n      if (!drag || !canvas || !obj || !host) return;\n\n      const z = Math.max(0.01, useEditorStore.getState().zoom);\n\n      if (drag.handle === 'rotate') {\n        const ang0 = Math.atan2(drag.startY - drag.centerClientY, drag.startX - drag.centerClientX);\n        const ang1 = Math.atan2(e.clientY - drag.centerClientY, e.clientX - drag.centerClientX);\n        obj.set({ angle: drag.originAngle + ((ang1 - ang0) * 180) / Math.PI });\n        obj.setPositionByOrigin(\n          new Point(drag.centerSceneX, drag.centerSceneY),\n          drag.centerFracX,\n          drag.centerFracY,\n        );\n        obj.setCoords();\n        canvas.requestRenderAll();\n        if (!mapCacheRef.current) mapCacheRef.current = buildHostMap(canvas, host);\n        paintBoxRef.current(\n          readOverlayBox(canvas, host, { skipSetCoords: true, map: mapCacheRef.current }),\n        );\n        return;\n      }\n\n      // Screen px \u2192 scene px via measured map scale (matches chrome).\n      const mapScale = mapCacheRef.current?.scale || z;\n      const sceneDx = (e.clientX - drag.startX) / mapScale;\n      const sceneDy = (e.clientY - drag.startY) / mapScale;\n\n      // Project pointer delta into object-local axes (handles rotation).\n      const rad = ((obj.angle || 0) * Math.PI) / 180;\n      const localDx = sceneDx * Math.cos(rad) + sceneDy * Math.sin(rad);\n      const localDy = -sceneDx * Math.sin(rad) + sceneDy * Math.cos(rad);\n\n      const w0 = Math.max(1, drag.originWidth * drag.originScaleX);\n      const h0 = Math.max(1, drag.originHeight * drag.originScaleY);\n\n      const fromLeft = drag.handle === 'tl' || drag.handle === 'ml' || drag.handle === 'bl';\n      const fromRight = drag.handle === 'tr' || drag.handle === 'mr' || drag.handle === 'br';\n      const fromTop = drag.handle === 'tl' || drag.handle === 'mt' || drag.handle === 'tr';\n      const fromBottom = drag.handle === 'bl' || drag.handle === 'mb' || drag.handle === 'br';\n\n      // Shift = scale from center (both sides move). Default = opposite edge fixed.\n      const fromCenter = e.shiftKey;\n      const sizeMul = fromCenter ? 2 : 1;\n\n      let newW = w0;\n      let newH = h0;\n      if (fromRight) newW = Math.max(8, w0 + localDx * sizeMul);\n      if (fromLeft) newW = Math.max(8, w0 - localDx * sizeMul);\n      if (fromBottom) newH = Math.max(8, h0 + localDy * sizeMul);\n      if (fromTop) newH = Math.max(8, h0 - localDy * sizeMul);\n\n      const isCorner =\n        drag.handle === 'tl' || drag.handle === 'tr' || drag.handle === 'bl' || drag.handle === 'br';\n      // Corners keep aspect unless Ctrl (free). Shift only toggles center origin.\n      if (isCorner && !e.ctrlKey && !e.metaKey) {\n        const ratio = w0 / Math.max(1, h0);\n        if (Math.abs(localDx) > Math.abs(localDy)) newH = Math.max(8, newW / ratio);\n        else newW = Math.max(8, newH * ratio);\n      }\n\n      const scaleX = newW / Math.max(1, drag.originWidth);\n      const scaleY = newH / Math.max(1, drag.originHeight);\n      obj.set({ scaleX, scaleY });\n\n      if (fromCenter) {\n        obj.setPositionByOrigin(\n          new Point(drag.centerSceneX, drag.centerSceneY),\n          drag.centerFracX,\n          drag.centerFracY,\n        );\n      } else {\n        obj.setPositionByOrigin(\n          new Point(drag.edgeAnchorX, drag.edgeAnchorY),\n          drag.edgeFracX,\n          drag.edgeFracY,\n        );\n      }\n      obj.setCoords();\n\n      if (isCropOverlay(obj)) {\n        // Do not clamp mid-drag \u2014 that recenters and fights opposite-edge resize.\n      } else {\n        const ox = fromCenter ? 'center' : String(drag.edgeFracX);\n        const oy = fromCenter ? 'center' : String(drag.edgeFracY);\n        canvas.fire('object:scaling', {\n          target: obj,\n          transform: {\n            corner: drag.handle,\n            action: 'scale',\n            originX: ox,\n            originY: oy,\n          },\n          e,\n        });\n      }\n      canvas.requestRenderAll();\n      if (!mapCacheRef.current) mapCacheRef.current = buildHostMap(canvas, host);\n      paintBoxRef.current(\n        readOverlayBox(canvas, host, { skipSetCoords: true, map: mapCacheRef.current }),\n      );\n    };\n\n    const onUp = () => {\n      if (!dragRef.current) return;\n      const canvas = canvasInstance;\n      const obj = canvas?.getActiveObject();\n      dragRef.current = null;\n      mapCacheRef.current = null;\n      if (obj && isCropOverlay(obj) && canvas) {\n        const img = resolveCropTargetImage(canvas, obj as CropOverlayRect);\n        if (img) {\n          clampCropRectToImage(obj as CropOverlayRect, img, { normalizeScale: true });\n          canvas.requestRenderAll();\n        }\n        // Crop session pauses history \u2014 do not push undo steps for handle drags.\n        return;\n      }\n      saveHistoryState();\n    };\n\n    window.addEventListener('pointermove', onMove);\n    window.addEventListener('pointerup', onUp);\n    return () => {\n      window.removeEventListener('pointermove', onMove);\n      window.removeEventListener('pointerup', onUp);\n    };\n  }, [canvasInstance, hostRef, saveHistoryState]);\n\n  if (!chrome.visible) return null;\n\n  const startDrag = (handle: HandleId, e: React.PointerEvent) => {\n    e.preventDefault();\n    e.stopPropagation();\n    const canvas = canvasInstance;\n    const obj = canvas?.getActiveObject();\n    const host = hostRef.current;\n    const box = boxRef.current;\n    if (!canvas || !obj || !host || !box || box.locked) return;\n\n    const content = isPixelLayer(obj) ? getPixelLayerContentOriginFractions(obj) : null;\n    const corners = isPixelLayer(obj) ? getPixelLayerContentSceneCorners(obj) : null;\n\n    let left: number;\n    let top: number;\n    let right: number;\n    let bottom: number;\n    let centerSceneX: number;\n    let centerSceneY: number;\n    let originWidth: number;\n    let originHeight: number;\n    let centerFracX: OriginFrac = 'center';\n    let centerFracY: OriginFrac = 'center';\n    let edgeFracX: OriginFrac;\n    let edgeFracY: OriginFrac;\n\n    const opp = oppositeOriginForHandle(handle);\n\n    if (content && corners && corners.length >= 4) {\n      const xs = corners.map((p) => p.x);\n      const ys = corners.map((p) => p.y);\n      left = Math.min(...xs);\n      right = Math.max(...xs);\n      top = Math.min(...ys);\n      bottom = Math.max(...ys);\n      centerSceneX = (left + right) / 2;\n      centerSceneY = (top + bottom) / 2;\n      originWidth = content.contentW;\n      originHeight = content.contentH;\n      centerFracX = content.ox;\n      centerFracY = content.oy;\n      // Content-edge fractions within the page buffer (0\u20131).\n      const elW = Math.max(1, (obj.width || 1));\n      const elH = Math.max(1, (obj.height || 1));\n      // Approximate from content AABB vs buffer using known content size/center.\n      const contentLeftFrac = content.ox - content.contentW / (2 * elW);\n      const contentRightFrac = content.ox + content.contentW / (2 * elW);\n      const contentTopFrac = content.oy - content.contentH / (2 * elH);\n      const contentBottomFrac = content.oy + content.contentH / (2 * elH);\n      edgeFracX =\n        opp.ox === 'left'\n          ? contentLeftFrac\n          : opp.ox === 'right'\n            ? contentRightFrac\n            : content.ox;\n      edgeFracY =\n        opp.oy === 'top'\n          ? contentTopFrac\n          : opp.oy === 'bottom'\n            ? contentBottomFrac\n            : content.oy;\n    } else {\n      const coords = obj.getCoords();\n      if (coords && coords.length >= 4) {\n        const xs = coords.map((p) => p.x);\n        const ys = coords.map((p) => p.y);\n        left = Math.min(...xs);\n        right = Math.max(...xs);\n        top = Math.min(...ys);\n        bottom = Math.max(...ys);\n      } else {\n        const c = obj.getCenterPoint();\n        const w = (obj.width || 1) * Math.abs(obj.scaleX || 1);\n        const h = (obj.height || 1) * Math.abs(obj.scaleY || 1);\n        left = c.x - w / 2;\n        right = c.x + w / 2;\n        top = c.y - h / 2;\n        bottom = c.y + h / 2;\n      }\n      centerSceneX = (left + right) / 2;\n      centerSceneY = (top + bottom) / 2;\n      originWidth = obj.width || 1;\n      originHeight = obj.height || 1;\n      edgeFracX = opp.ox;\n      edgeFracY = opp.oy;\n    }\n\n    const edgeAnchor = anchorPointForHandle(handle, left, top, right, bottom);\n\n    mapCacheRef.current = buildHostMap(canvas, host);\n    const map = mapCacheRef.current;\n    const cHost = map\n      ? sceneToHostCached(map, centerSceneX, centerSceneY)\n      : { x: centerSceneX, y: centerSceneY };\n    const hostRect = host.getBoundingClientRect();\n\n    dragRef.current = {\n      handle,\n      startX: e.clientX,\n      startY: e.clientY,\n      originScaleX: obj.scaleX || 1,\n      originScaleY: obj.scaleY || 1,\n      originAngle: obj.angle || 0,\n      originWidth,\n      originHeight,\n      centerSceneX,\n      centerSceneY,\n      centerClientX: hostRect.left + cHost.x,\n      centerClientY: hostRect.top + cHost.y,\n      centerFracX,\n      centerFracY,\n      edgeAnchorX: edgeAnchor.x,\n      edgeAnchorY: edgeAnchor.y,\n      edgeFracX,\n      edgeFracY,\n    };\n  };\n\n  const visibleHandles = chrome.cropMode\n    ? HANDLES.filter((h) => h.id === 'mt' || h.id === 'mb' || h.id === 'ml' || h.id === 'mr')\n    : HANDLES;\n\n  return (\n    <div className=\"pointer-events-none absolute inset-0 z-30 overflow-visible\" data-we-no-deselect>\n      <div\n        ref={boxElRef}\n        className={`absolute left-0 top-0 will-change-transform ${\n          chrome.cropMode\n            ? 'shadow-[0_0_0_1.5px_#3b82f6,0_0_0_3px_rgba(59,130,246,0.35)]'\n            : 'shadow-[0_0_0_1px_#3b82f6,0_0_0_2px_rgba(0,0,0,0.25)]'\n        }`}\n        style={{ visibility: 'hidden' }}\n      >\n        {!chrome.locked &&\n          visibleHandles.map((h) => (\n            <button\n              key={h.id}\n              type=\"button\"\n              aria-label={h.id}\n              onPointerDown={(e) => startDrag(h.id, e)}\n              className={`pointer-events-auto absolute flex size-5 shrink-0 -translate-x-1/2 -translate-y-1/2 items-center justify-center border-0 bg-transparent p-0 ${h.posClass}`}\n              style={{ cursor: h.cursor }}\n            >\n              <span className=\"pointer-events-none block size-3 shrink-0 rounded-xs border-2 border-[#3b82f6] bg-white shadow-sm\" />\n            </button>\n          ))}\n        {!chrome.locked && !chrome.cropMode && (\n          <button\n            type=\"button\"\n            aria-label=\"rotate\"\n            onPointerDown={(e) => startDrag('rotate', e)}\n            className=\"pointer-events-auto absolute left-full top-1/2 flex size-6 shrink-0 translate-x-2 -translate-y-1/2 cursor-grab items-center justify-center border-0 bg-transparent p-0\"\n            title=\"Rotar\"\n          >\n            <span className=\"pointer-events-none block size-4 shrink-0 rounded-full border-2 border-[#3b82f6] bg-white shadow-sm\" />\n          </button>\n        )}\n      </div>\n    </div>\n  );\n};\n", "/**\n * Skeleton loader over every Fabric object marked `weAiLoading`.\n * Host is the page frame (same mapping as SelectionControlsOverlay).\n * Box follows object center + size + rotation so edits keep their transform.\n */\n\nimport React, { useEffect, useState } from 'react';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { isAiLoadingObject, listAiLoadingObjects } from '../../utils/aiLoadingLayer';\nimport { TextTitle } from '../ui';\nimport { useTranslation } from '../../i18n';\n\ntype Box = {\n  id: string;\n  /** Center X in host coords */\n  left: number;\n  /** Center Y in host coords */\n  top: number;\n  width: number;\n  height: number;\n  angle: number;\n};\n\nfunction measureBoxes(\n  canvas: {\n    getObjects: () => unknown[];\n    getWidth: () => number;\n    getHeight: () => number;\n    upperCanvasEl?: HTMLCanvasElement | null;\n    getElement?: () => HTMLCanvasElement;\n  },\n  host: HTMLElement,\n): Box[] {\n  const el = canvas.upperCanvasEl || canvas.getElement?.();\n  if (!el) return [];\n  const canvasRect = el.getBoundingClientRect();\n  const hostRect = host.getBoundingClientRect();\n  const cw = Math.max(1, canvas.getWidth());\n  const ch = Math.max(1, canvas.getHeight());\n  const scale = Math.max(0.01, (canvasRect.width / cw + canvasRect.height / ch) / 2);\n  const ox = canvasRect.left - hostRect.left;\n  const oy = canvasRect.top - hostRect.top;\n\n  const out: Box[] = [];\n  for (const obj of listAiLoadingObjects(canvas as never)) {\n    obj.setCoords();\n    const center = obj.getCenterPoint();\n    const w = Math.max(24, obj.getScaledWidth() * scale);\n    const h = Math.max(24, obj.getScaledHeight() * scale);\n    const id = obj.id || `ai-${out.length}`;\n    out.push({\n      id,\n      left: ox + center.x * scale,\n      top: oy + center.y * scale,\n      width: w,\n      height: h,\n      angle: obj.angle ?? 0,\n    });\n  }\n  return out;\n}\n\nexport function AiLoadingOverlay({\n  hostRef,\n}: {\n  hostRef: React.RefObject<HTMLElement | null>;\n}) {\n  const t = useTranslation();\n  const canvasInstance = useEditorStore((s) => s.canvasInstance);\n  const canvasSyncTrigger = useEditorStore((s) => s.canvasSyncTrigger);\n  const isAiGenerating = useEditorStore((s) => s.isAiGenerating);\n  const activeTool = useEditorStore((s) => s.activeTool);\n  const zoom = useEditorStore((s) => s.zoom);\n  const [boxes, setBoxes] = useState<Box[]>([]);\n  const loadingLabel =\n    activeTool === 'magic-eraser'\n      ? t.canvas.magicEraserPanel.loading\n      : t.editor.aiGenerating;\n\n  useEffect(() => {\n    const host = hostRef.current;\n    if (!canvasInstance || !host) {\n      setBoxes([]);\n      return;\n    }\n\n    let raf = 0;\n    const tick = () => {\n      const next = measureBoxes(canvasInstance, host);\n      setBoxes((prev) => {\n        if (\n          prev.length === next.length &&\n          prev.every(\n            (b, i) =>\n              b.id === next[i]?.id &&\n              Math.abs(b.left - (next[i]?.left ?? 0)) < 0.5 &&\n              Math.abs(b.top - (next[i]?.top ?? 0)) < 0.5 &&\n              Math.abs(b.width - (next[i]?.width ?? 0)) < 0.5 &&\n              Math.abs(b.height - (next[i]?.height ?? 0)) < 0.5 &&\n              Math.abs(b.angle - (next[i]?.angle ?? 0)) < 0.05,\n          )\n        ) {\n          return prev;\n        }\n        return next;\n      });\n      if (listAiLoadingObjects(canvasInstance).length > 0 || isAiGenerating) {\n        raf = requestAnimationFrame(tick);\n      }\n    };\n\n    raf = requestAnimationFrame(tick);\n\n    const onAfter = () => {\n      cancelAnimationFrame(raf);\n      raf = requestAnimationFrame(tick);\n    };\n    canvasInstance.on('after:render', onAfter);\n\n    return () => {\n      cancelAnimationFrame(raf);\n      canvasInstance.off('after:render', onAfter);\n    };\n  }, [canvasInstance, hostRef, canvasSyncTrigger, isAiGenerating, zoom]);\n\n  useEffect(() => {\n    if (!canvasInstance || !hostRef.current) return;\n    if (!isAiGenerating && listAiLoadingObjects(canvasInstance).every(isAiLoadingObject)) {\n      setBoxes(measureBoxes(canvasInstance, hostRef.current));\n    }\n  }, [canvasInstance, hostRef, isAiGenerating, canvasSyncTrigger]);\n\n  if (boxes.length === 0) return null;\n\n  return (\n    <div className=\"pointer-events-none absolute inset-0 z-30 overflow-hidden\">\n      {boxes.map((box) => (\n        <div\n          key={box.id}\n          className=\"absolute flex items-center justify-center overflow-hidden rounded-2xl border border-white/10 bg-[#2e2e34] shadow-[0_12px_32px_rgba(0,0,0,0.45)]\"\n          style={{\n            left: box.left,\n            top: box.top,\n            width: box.width,\n            height: box.height,\n            transform: `translate(-50%, -50%) rotate(${box.angle}deg)`,\n          }}\n        >\n          <div className=\"animate-ai-shimmer pointer-events-none absolute inset-0 overflow-hidden\">\n            <div className=\"we-ai-shimmer-bar absolute inset-y-0 left-0 w-1/2 bg-gradient-to-r from-transparent via-white/[0.05] to-transparent\" />\n          </div>\n          <TextTitle as=\"span\" size=\"sm\" className=\"we-generating-label relative z-[1] tracking-wide\">\n            {loadingLabel}\n          </TextTitle>\n        </div>\n      ))}\n    </div>\n  );\n}\n", "import React, { useEffect, useLayoutEffect, useRef, useState, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Canvas, Rect, Circle as FabricCircle, Triangle as FabricTriangle, Textbox, Line, FabricObject, FabricImage, Ellipse, Polygon, Path, PencilBrush, SprayBrush, CircleBrush, Shadow, Point, Group, ActiveSelection } from 'fabric';\nimport { useEditorStore, applyCanvasBackground, updateTextPath, reconstructClippingMasks, isMarqueeTool, isLassoGroupTool, isEraserGroupTool, isBrushRadiusTool, fitTextboxToContent, sizeTextboxToNaturalWidth, getEffectiveFontSize, isTextObject, bakeTextScale, remeasureTextObject, type EraserGroupTool, type LassoGroupTool } from '../store/useEditorStore';\nimport { PencilSparkles } from './icons/PencilSparkles';\nimport { installIndependentCornerRender } from '../utils/roundedRectCorners';\nimport { reapplyAllPixelLayerLocks, isSoleCanvasLayer, isPixelLayer, pixelLayerHasContent, syncPixelLayerInteraction, getPixelLayerContentSceneAabb, WE_FABRIC_CUSTOM_PROPERTIES, type PixelLayerImage } from '../utils/pixelLayer';\nimport {\n  beginCtrlDragSession,\n  cancelCtrlDragGhost,\n  captureTransformCornerOrigin,\n  commitCtrlDragGhost,\n  ensureCtrlDragGhost,\n  rebaselineLiveTransform,\n  syncTransformCenteredOrigin,\n  type CtrlDragDuplicateSession,\n} from '../utils/fabricTransformModifiers';\n\n// \u2500\u2500 Feature flags: ocultan features cuyo endpoint .NET no existe todav\u00EDa \u2500\u2500\n// Togglear a `true` cuando el .NET exponga el endpoint.\n// Ver AGENTS.md \u00A75.3 del paquete + wizard-ai-frontend/docs para tracking.\nconst FEATURE_FLAGS = {\n  /**\n   * \"AI Design Copilot\" \u2014 llama a `/api/ai/design-preset`.\n   * El .NET no expone ese endpoint (AGENTS.md \u00A75.3).\n   * Togglear a `true` cuando el .NET implemente `/api/ai/design-preset`.\n   */\n  SHOW_DESIGN_COPILOT: false,\n} as const;\n\n// Keep in sync with useEditorStore \u2014 must include wePixelLayer or reload drops raster tools.\nFabricObject.customProperties = [...WE_FABRIC_CUSTOM_PROPERTIES];\n\nimport type { ToolType } from '../store/useEditorStore';\nimport { ChevronDown, Copy, Clipboard, Trash2, Lock, Unlock, Paintbrush, ChevronUp, ChevronsUp, ChevronsDown, Grid, RefreshCw, MousePointer, Hand, Scissors, Brush, FolderPlus, FolderMinus, Sparkles, PenTool, Link2, Unlink, Type, PaintBucket, Shapes as ShapesIcon, ImageUp, LayoutGrid, Ruler, Eye, UploadCloud, BarChart, LineChart, PieChart, QrCode, ScanBarcode, Bold, Italic, Underline, AlignLeft, AlignCenter, AlignRight, SquareBottomDashedScissors, Stamp, SquareDashed, CircleDashed, Lasso, X, Plus, Wand2, Eraser, Waypoints, Check } from 'lucide-react';\nimport { CropOverlay } from './editor/CropOverlay';\nimport { PenToolOverlay } from './editor/PenToolOverlay';\nimport { BooleanOperationsMenu } from './editor/BooleanOperationsMenu';\nimport { MaskEditorPanel } from './editor/MaskEditorPanel';\nimport { MarqueeSelectOverlay } from './editor/MarqueeSelectOverlay';\nimport { CloneStampOverlay } from './editor/CloneStampOverlay';\nimport { MagicWandOverlay } from './editor/MagicWandOverlay';\nimport { PaintBucketOverlay } from './editor/PaintBucketOverlay';\nimport { PixelLassoOverlay } from './editor/PixelLassoOverlay';\nimport { ShapeLassoOverlay } from './editor/ShapeLassoOverlay';\nimport { PolygonLassoOverlay } from './editor/PolygonLassoOverlay';\nimport { PixelEraserOverlay } from './editor/PixelEraserOverlay';\nimport { MaskPaintOverlay } from './editor/MaskPaintOverlay';\nimport { PixelSelectionMarchingAnts } from './editor/PixelSelectionMarchingAnts';\nimport { BrushRadiusPopup } from './editor/BrushRadiusPopup';\nimport { BrushSizeCenterPreview } from './editor/BrushSizeCenterPreview';\n\nimport { createFrame } from '../utils/frameFactory';\nimport { createCustomShape, customShapeCategories } from '../utils/customShapeFactory';\nimport { convertTextToPath } from '../utils/textToPathUtils';\nimport { sampleCanvasHexAtClient } from '../utils/useEyedropper';\nimport { extractColorsFromImage, GOOGLE_FONTS_CATALOG } from './Sidebar';\nimport { ToolPanelTabs, toolTileClass, toolTileCardClass, IconButton, CanvasSizeChip, SelectDropdown } from './ui';\nimport { CanvasGridPanel } from './editor/tool-panels/CanvasGridPanel';\nimport { CanvasColorblindPanel } from './editor/tool-panels/CanvasColorblindPanel';\nimport { CanvasUploadPanel } from './editor/tool-panels/CanvasUploadPanel';\nimport { BrushToolPanel } from './editor/tool-panels/BrushToolPanel';\nimport { MagicEraserToolPanel } from './editor/tool-panels/MagicEraserToolPanel';\nimport { MagicWandToolPanel } from './editor/tool-panels/MagicWandToolPanel';\nimport { PaintBucketToolPanel } from './editor/tool-panels/PaintBucketToolPanel';\nimport { CloneStampToolPanel } from './editor/tool-panels/CloneStampToolPanel';\nimport { EraserToolPanel } from './editor/tool-panels/EraserToolPanel';\nimport { SnapMagnetButton } from './editor/SnapMagnetButton';\nimport { BrandKitButton } from './editor/BrandKitButton';\nimport { CanvasZoomDock } from './editor/CanvasZoomDock';\nimport { FabricCanvasHost } from './editor/FabricCanvasHost';\nimport { generateLoremIpsum } from '../utils/loremUtils';\nimport QRCode from 'qrcode';\nimport JsBarcode from 'jsbarcode';\nimport { generateChartImage, type ChartType, type ChartDataPoint, type ChartOptions } from '../utils/chartUtils';\nimport { ChartDataModal } from './ChartDataModal';\nimport { VersionHistoryModal } from './VersionHistoryModal';\nimport { DraggableToolPanel } from './DraggableToolPanel';\nimport '../utils/fabricText3D'; // Import to register the class\nimport { useDialog } from '../components/DialogModal';\nimport { useTranslation } from '../i18n';\nimport { isApplePlatform, modShortcut } from '../utils/modKey';\nimport { useBrandSelection } from '../context/BrandSelectionContext';\nimport { modeAccentVars, useModeAccent } from '../theme/modeAccent';\nimport { canUseImageCropTool } from '../utils/imageCrop';\nimport { resolveImageSrcForCanvas } from '../services/imageJobsService';\nimport { applyCanvasZoomRender, getVisualZoom } from '../utils/canvasZoomRender';\nimport { patchFabricPointerForCssZoom } from '../utils/fabricPointerCssZoom';\nimport { SelectionControlsOverlay } from './editor/SelectionControlsOverlay';\nimport { AiLoadingOverlay } from './editor/AiLoadingOverlay';\nimport { ViewportPortalMenu } from '../utils/ViewportPortalMenu';\nimport { TextBody, TextTitle } from './ui';\n\n\nconst getType = (obj?: any) => {\n  const type = obj?.type?.toLowerCase() || '';\n  if (type === 'textbox3d') return 'textbox';\n  return type;\n};\n\ntype SnapKind = 'shape' | 'image' | 'text' | 'ignore';\n\nfunction classifySnapTarget(obj: { type?: string; visible?: boolean; id?: string; isImageCropOverlay?: boolean }): SnapKind {\n  if (!obj.visible || obj.isImageCropOverlay || obj.id === 'background') return 'ignore';\n  const type = getType(obj);\n  if (type === 'activeselection') return 'ignore';\n  if (type === 'image' || type === 'fabricimage') return 'image';\n  if (type === 'textbox' || type === 'text' || type === 'i-text' || type === 'textbox3d') return 'text';\n  return 'shape';\n}\n\nfunction sceneBox(obj: {\n  setCoords: () => void;\n  getBoundingRect: () => { left: number; top: number; width: number; height: number };\n}) {\n  // Pixel layers: magnet to opaque CONTENT, not the full page-sized buffer.\n  if (isPixelLayer(obj as FabricObject)) {\n    const aabb = getPixelLayerContentSceneAabb(obj as PixelLayerImage);\n    if (aabb) return aabb;\n  }\n  obj.setCoords();\n  const r = obj.getBoundingRect();\n  return {\n    left: r.left,\n    right: r.left + r.width,\n    centerX: r.left + r.width / 2,\n    top: r.top,\n    bottom: r.top + r.height,\n    centerY: r.top + r.height / 2,\n    width: r.width,\n    height: r.height,\n  };\n}\n\n/** Which AABB edges move for a given Fabric control corner. */\nfunction movingEdgesForCorner(\n  corner: string,\n  centered: boolean,\n): { left: boolean; right: boolean; top: boolean; bottom: boolean } {\n  if (centered) {\n    return { left: true, right: true, top: true, bottom: true };\n  }\n  return {\n    left: ['ml', 'tl', 'bl'].includes(corner),\n    right: ['mr', 'tr', 'br'].includes(corner),\n    top: ['mt', 'tl', 'tr'].includes(corner),\n    bottom: ['mb', 'bl', 'br'].includes(corner),\n  };\n}\n\nfunction getActivePageSize(): { width: number; height: number } {\n  const store = useEditorStore.getState();\n  const page = store.pages.find((p) => p.id === store.activePageId) || store.pages[0];\n  return { width: page?.width ?? 1080, height: page?.height ?? 1080 };\n}\n\nfunction placeOnPageCenter(obj: FabricObject) {\n  const { width, height } = getActivePageSize();\n  obj.setXY(new Point(width / 2, height / 2), 'center', 'center');\n}\n\nconst getRulerStep = (zoom: number) => {\n  if (zoom < 0.15) return { tick: 200, label: 1000 };\n  if (zoom < 0.3) return { tick: 100, label: 500 };\n  if (zoom < 0.7) return { tick: 50, label: 200 };\n  if (zoom < 1.5) return { tick: 10, label: 100 };\n  if (zoom < 4) return { tick: 5, label: 50 };\n  return { tick: 1, label: 10 };\n};\n\n// \u2500\u2500 Toolstrip floating panel keys (T-20260707-12) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Only one of these panels can be open at a time. Replaces 8 individual\n// `useState<boolean>` flags that had inconsistent mutual-exclusion logic.\ntype FloatingToolPanel =\n  | 'shapes'\n  | 'frames'\n  | 'ai'\n  | 'upload'\n  | 'grid'\n  | 'colorblind';\n\n// Customize Fabric.js selection handles globally (Figma style)\nFabricObject.prototype.borderColor = '#3b82f6';\nFabricObject.prototype.cornerColor = '#ffffff';\nFabricObject.prototype.cornerStrokeColor = '#3b82f6';\nFabricObject.prototype.cornerSize = 8;\nFabricObject.prototype.cornerStyle = 'circle';\nFabricObject.prototype.transparentCorners = false;\nFabricObject.prototype.padding = 0;\nFabricObject.prototype.borderScaleFactor = 1;\n\nlet clipboard: any = null;\n\nclass StablePencilBrush extends PencilBrush {\n  public stabilization = 0.3;\n  public pressureSensitivity = false;\n  protected _lastPoint: { x: number; y: number } | null = null;\n  protected _lastTime = 0;\n  protected _nominalWidth = 5;\n\n  onMouseDown(pointer: any, options: any) {\n    this._lastPoint = { x: pointer.x, y: pointer.y };\n    this._lastTime = Date.now();\n    this._nominalWidth = this.width;\n    super.onMouseDown(pointer, options);\n  }\n\n  onMouseMove(pointer: any, options: any) {\n    const now = Date.now();\n    let smoothedPointer = pointer;\n\n    if (this._lastPoint) {\n      if (this.stabilization > 0) {\n        const smoothedX = this._lastPoint.x * this.stabilization + pointer.x * (1 - this.stabilization);\n        const smoothedY = this._lastPoint.y * this.stabilization + pointer.y * (1 - this.stabilization);\n        smoothedPointer = new Point(smoothedX, smoothedY);\n      }\n\n      if (this.pressureSensitivity) {\n        const dx = smoothedPointer.x - this._lastPoint.x;\n        const dy = smoothedPointer.y - this._lastPoint.y;\n        const dist = Math.sqrt(dx * dx + dy * dy);\n        const dt = Math.max(1, now - this._lastTime);\n        const velocity = dist / dt;\n\n        const maxVelocity = 3.0;\n        const speedRatio = Math.min(1, velocity / maxVelocity);\n        \n        const minScale = 0.3;\n        const targetWidth = this._nominalWidth * (1.0 - (1.0 - minScale) * speedRatio);\n        \n        this.width = this.width * 0.8 + targetWidth * 0.2;\n      }\n    }\n\n    this._lastPoint = { x: smoothedPointer.x, y: smoothedPointer.y };\n    this._lastTime = now;\n    super.onMouseMove(smoothedPointer, options);\n  }\n\n  onMouseUp(options: any) {\n    this.width = this._nominalWidth;\n    return super.onMouseUp(options);\n  }\n}\n\nclass CalligraphyBrush extends StablePencilBrush {\n  constructor(canvas: Canvas) {\n    super(canvas);\n    this.strokeLineCap = 'square';\n    this.strokeLineJoin = 'miter';\n  }\n}\n\nclass HighlighterBrush extends StablePencilBrush {\n  constructor(canvas: Canvas) {\n    super(canvas);\n    this.strokeLineCap = 'square';\n    this.strokeLineJoin = 'miter';\n  }\n}\n\nclass ChalkBrush extends StablePencilBrush {\n  constructor(canvas: Canvas) {\n    super(canvas);\n    this.strokeLineCap = 'round';\n    this.strokeLineJoin = 'round';\n    this.strokeDashArray = [2, 4];\n  }\n}\n\nimport { ensureFontReady, ensureGoogleFontLoaded, isSystemFontFamily } from '../utils/googleFonts';\n\nconst loadGoogleFont = (fontName: string): Promise<void> => ensureGoogleFontLoaded(fontName);\n\n\nexport function CanvasArea() {\n  const t = useTranslation();\n  const mode = useModeAccent();\n  const { brand: activeBrand } = useBrandSelection();\n  const cm = t.canvas.contextMenu;\n  const eye = t.canvas.eyedropper;\n  const containerRef = useRef<HTMLDivElement>(null);\n  const canvasRef = useRef<HTMLCanvasElement>(null);\n  const fabricCanvasRef = useRef<Canvas | null>(null);\n  const pageStageRef = useRef<HTMLDivElement>(null);\n  const pageFrameRef = useRef<HTMLDivElement>(null);\n  const panLayerRef = useRef<HTMLDivElement>(null);\n  const hrulerRef = useRef<HTMLCanvasElement | null>(null);\n  const vrulerRef = useRef<HTMLCanvasElement | null>(null);\n  const [workspacePan, setWorkspacePan] = useState({ x: 0, y: 0 });\n  const workspacePanRef = useRef({ x: 0, y: 0 });\n  const [, setIsZoomMenuOpen] = useState(false);\n  // T-20260707-13: `isHelpOpen` y `setIsHelpOpen` eliminados. La tecla `?` ahora\n  // controla el modal unificado de atajos, gestionado desde App.tsx.\n  const [, ] = useState(false); // isFileMenuOpen removed (unused)\n  const [isVersionHistoryModalOpen, setIsVersionHistoryModalOpen] = useState(false);\n\n    const [shapesTab, setShapesTab] = useState<'figures' | 'shapes' | 'graficos' | 'qr-barcode'>('figures');\n  // --- Gr\u00E1ficos / QR / Barcode state (movido desde Sidebar T-20260706-XX) ---\n  const [qrText, setQrText] = useState<string>('');\n  const [barcodeText, setBarcodeText] = useState<string>('');\n  const [isChartModalOpen, setIsChartModalOpen] = useState(false);\n  const [chartModalData, setChartModalData] = useState<ChartDataPoint[]>([]);\n  const [chartModalType, setChartModalType] = useState<ChartType>('bar');\n  const [chartModalOptions, setChartModalOptions] = useState<Partial<ChartOptions>>({});\n  const [editingChartObj, setEditingChartObj] = useState<any>(null);\n  // --- Panel Texto ---\n  const [isTextPanelOpen, setIsTextPanelOpen] = useState(false);\n  const [isEraserMenuOpen, setIsEraserMenuOpen] = useState(false);\n  const eraserMenuAnchorRef = useRef<HTMLDivElement | null>(null);\n  const [eraserGroupTool, setEraserGroupTool] = useState<EraserGroupTool>('eraser');\n  const eraserMenuHoldTimer = useRef<number | null>(null);\n  const [isLassoMenuOpen, setIsLassoMenuOpen] = useState(false);\n  const lassoMenuAnchorRef = useRef<HTMLDivElement | null>(null);\n  const [lassoGroupTool, setLassoGroupTool] = useState<LassoGroupTool>('select-rect');\n  const lassoMenuHoldTimer = useRef<number | null>(null);\n  const [radiusPopup, setRadiusPopup] = useState<{ x: number; y: number } | null>(null);\n  // \u2500\u2500 T-20260707-12: unified state for the 8 toolstrip floating panels.\n  // Only one can be open at a time; opening another closes the previous.\n  const [activeToolPanel, setActiveToolPanel] = useState<FloatingToolPanel | null>(null);\n  const toggleActiveToolPanel = (key: FloatingToolPanel) => {\n    setActiveToolPanel((prev) => {\n      const next = prev === key ? null : key;\n      return next;\n    });\n  };\n\n  const dismissToolPanels = useCallback(() => {\n    setActiveToolPanel(null);\n  }, []);\n\n  useEffect(() => {\n    const onRadiusPopup = (ev: Event) => {\n      const detail = (ev as CustomEvent<{ x: number; y: number }>).detail;\n      if (!detail) return;\n      setContextMenu((prev) => ({ ...prev, visible: false }));\n      setRadiusPopup({ x: detail.x, y: detail.y });\n    };\n    window.addEventListener('we-brush-radius-popup', onRadiusPopup);\n    return () => window.removeEventListener('we-brush-radius-popup', onRadiusPopup);\n  }, []);\n\n  useEffect(() => {\n    if (activeToolPanel !== 'ai') return;\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') dismissToolPanels();\n    };\n    document.addEventListener('keydown', onKey);\n    const prev = document.body.style.overflow;\n    document.body.style.overflow = 'hidden';\n    return () => {\n      document.removeEventListener('keydown', onKey);\n      document.body.style.overflow = prev;\n    };\n  }, [activeToolPanel, dismissToolPanels]);\n\n  const [textPanelTab, setTextPanelTab] = useState<'insertar' | 'lorem' | 'propiedades' | 'fuentes'>('insertar');\n  const [isFontDropdownOpen, setIsFontDropdownOpen] = useState(false);\n  const fontTriggerRef = useRef<HTMLButtonElement | null>(null);\n  const [loremLength, setLoremLength] = useState<'words' | 'sentences' | 'paragraphs'>('paragraphs');\n  const [loremAmount, setLoremAmount] = useState<number>(3);\n  // --- Panel AI Studio ---\n  const [aiPanelTab, setAiPanelTab] = useState<'generador' | 'copilot' | 'copywriter'>('generador');\n  const [textToImagePrompt, setTextToImagePrompt] = useState('');\n  const [textToImageAspect, setTextToImageAspect] = useState<\n    '1:1' | '4:5' | '9:16' | '16:9' | '3:2'\n  >('1:1');\n  const [textToImageResolution, setTextToImageResolution] = useState<'1K' | '2K'>(\n    '2K',\n  );\n  const [textToImageRefs, setTextToImageRefs] = useState<\n    { id: string; file: File; previewUrl: string }[]\n  >([]);\n  const textToImageRefInputRef = useRef<HTMLInputElement | null>(null);\n  const [copywritePrompt, setCopywritePrompt] = useState('');\n  const [designCopilotPrompt, setDesignCopilotPrompt] = useState('');\n  const [, ] = useState(''); // sketchToImagePrompt removed (unused)\n  const [generateInAreaPrompt, setGenerateInAreaPrompt] = useState('');\n  // \u2500\u2500 Refs para paneles arrastrables \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  const shapesAnchorRef     = useRef<HTMLButtonElement | null>(null);\n  const aiAnchorRef         = useRef<HTMLButtonElement | null>(null);\n  const uploadAnchorRef     = useRef<HTMLButtonElement | null>(null);\n  const brushAnchorRef      = useRef<HTMLButtonElement | null>(null);\n  const paintBucketAnchorRef = useRef<HTMLButtonElement | null>(null);\n  const wandAnchorRef       = useRef<HTMLButtonElement | null>(null);\n  const lassoAnchorRef      = useRef<HTMLButtonElement | null>(null);\n  const eraserAnchorRef     = useRef<HTMLButtonElement | null>(null);\n  const cloneStampAnchorRef = useRef<HTMLButtonElement | null>(null);\n  const gridAnchorRef       = useRef<HTMLButtonElement | null>(null);\n  const colorBlindAnchorRef = useRef<HTMLButtonElement | null>(null);\n  const panelFileInputRef = useRef<HTMLInputElement>(null);\n  const [hudPos, setHudPos] = useState<{ x: number; y: number } | null>(null);\n  const [croppingObj, setCroppingObj] = useState<{ image: any; shape: any } | null>(null);\n  const [contextMenu, setContextMenu] = useState<{\n    x: number;\n    y: number;\n    visible: boolean;\n    targetObject: any | null;\n  }>({ x: 0, y: 0, visible: false, targetObject: null });\n  const contextMenuRef = useRef<HTMLDivElement>(null);\n  const [eyedropperColor, setEyedropperColor] = useState<string>('#000000');\n\n  // Clamp context menu inside the viewport BEFORE the browser paints,\n  // so the position adjustment never shows as a visible jump.\n  useLayoutEffect(() => {\n    if (!contextMenu.visible) return;\n    const el = contextMenuRef.current;\n    if (!el) return;\n    const margin = 8;\n    const menuW = el.offsetWidth;\n    const menuH = el.offsetHeight;\n    const x = Math.max(margin, Math.min(contextMenu.x, window.innerWidth - menuW - margin));\n    const y = Math.max(margin, Math.min(contextMenu.y, window.innerHeight - menuH - margin));\n    el.style.left = `${x}px`;\n    el.style.top = `${y}px`;\n  }, [contextMenu.visible, contextMenu.x, contextMenu.y, contextMenu.targetObject]);\n\n  const activeGuidesRef = useRef<{\n    x: number[];\n    y: number[];\n    spacingGuides: any[];\n  } | null>(null);\n\n  // --- Handlers de Gr\u00E1ficos / QR / Barcode (movidos desde Sidebar T-20260706-XX) ---\n  useEffect(() => {\n    const handleEditChart = (e: any) => {\n      const target = e.detail.target;\n      if (target && target.chartData && target.chartType) {\n        setChartModalData(target.chartData);\n        setChartModalType(target.chartType);\n        setChartModalOptions(target.chartOptions || {});\n        setEditingChartObj(target);\n        setIsChartModalOpen(true);\n      }\n    };\n    window.addEventListener('edit-chart', handleEditChart);\n    return () => window.removeEventListener('edit-chart', handleEditChart);\n  }, []);\n\n  const renderChartToCanvas = async (data: ChartDataPoint[], type: ChartType, options?: Partial<ChartOptions>, existingObj?: any) => {\n    try {\n      const defaultOptions: ChartOptions = { width: 600, height: 400, showLabels: true, theme: 'dark', textColor: '#ffffff', backgroundColor: 'transparent' };\n      const mergedOptions = { ...defaultOptions, ...options };\n      const dataUrl = await generateChartImage(type, data, mergedOptions);\n      const chartImg = await FabricImage.fromURL(dataUrl);\n      chartImg.set({\n        left: existingObj ? existingObj.left : 0,\n        top: existingObj ? existingObj.top : 0,\n        scaleX: existingObj ? existingObj.scaleX : 0.6,\n        scaleY: existingObj ? existingObj.scaleY : 0.6,\n        name: 'chart',\n        chartData: JSON.parse(JSON.stringify(data)),\n        chartType: type,\n        chartOptions: JSON.parse(JSON.stringify(mergedOptions))\n      });\n      if (existingObj) {\n        canvasInstance?.remove(existingObj);\n      } else {\n        placeOnPageCenter(chartImg);\n      }\n      canvasInstance?.add(chartImg);\n      canvasInstance?.setActiveObject(chartImg);\n      canvasInstance?.requestRenderAll();\n      useEditorStore.getState().saveHistoryState();\n    } catch (e) {\n      console.error('Error rendering chart:', e);\n    }\n  };\n\n  const handleInsertChart = (type: ChartType) => {\n    const defaultData: ChartDataPoint[] = [\n      { label: 'Item 1', value: 40, color: '#3b82f6' },\n      { label: 'Item 2', value: 30, color: '#10b981' },\n      { label: 'Item 3', value: 20, color: '#f59e0b' }\n    ];\n    renderChartToCanvas(defaultData, type, {});;\n  };\n\n  const handleSaveChartData = (data: ChartDataPoint[], type: ChartType, options: Partial<ChartOptions>) => {\n    if (editingChartObj) {\n      renderChartToCanvas(data, type, options, editingChartObj);\n    }\n  };\n\n  const handleInsertQR = async () => {\n    if (!qrText.trim()) return;\n    try {\n      const qrDataUrl = await QRCode.toDataURL(qrText, { width: 300, margin: 2, color: { dark: '#000000', light: '#ffffff' } });\n      const qrImg = await FabricImage.fromURL(qrDataUrl);\n      qrImg.set({ scaleX: 0.5, scaleY: 0.5 });\n      placeOnPageCenter(qrImg);\n      qrImg.setControlsVisibility({ mb: false, mt: false, ml: false, mr: false });\n      canvasInstance?.add(qrImg);\n      canvasInstance?.setActiveObject(qrImg);\n      canvasInstance?.requestRenderAll();\n      useEditorStore.getState().saveHistoryState();\n      setQrText('');;\n    } catch (e) {\n      console.error(e);\n    }\n  };\n\n  const handleInsertBarcode = async () => {\n    if (!barcodeText.trim()) return;\n    try {\n      const canvas = document.createElement('canvas');\n      JsBarcode(canvas, barcodeText, { format: 'CODE128', displayValue: true, margin: 10 });\n      const dataUrl = canvas.toDataURL('image/png');\n      const bcImg = await FabricImage.fromURL(dataUrl);\n      bcImg.set({ scaleX: 0.5, scaleY: 0.5 });\n      placeOnPageCenter(bcImg);\n      canvasInstance?.add(bcImg);\n      canvasInstance?.setActiveObject(bcImg);\n      canvasInstance?.requestRenderAll();\n      useEditorStore.getState().saveHistoryState();\n      setBarcodeText('');;\n    } catch (e) {\n      console.error(e);\n      dialog.alert('Texto inv\u00E1lido para C\u00F3digo de Barras (CODE128)', { title: 'Error de c\u00F3digo de barras', variant: 'error' });\n    }\n  };\n  // -------------------------\n\n  const handlePointerMove = (e: React.PointerEvent<HTMLDivElement>) => {\n    if (\n      activeTool !== 'brush' &&\n      activeTool !== 'magic-eraser' &&\n      activeTool !== 'eyedropper' &&\n      activeTool !== 'clone-stamp' &&\n      activeTool !== 'eraser'\n    ) {\n      if (hudPos !== null) setHudPos(null);\n      return;\n    }\n    const rect = e.currentTarget.getBoundingClientRect();\n    const x = e.clientX - rect.left;\n    const y = e.clientY - rect.top;\n    setHudPos({ x, y });\n\n    if (activeTool === 'eyedropper' && fabricCanvasRef.current) {\n      const canvasEl = (fabricCanvasRef.current as { lowerCanvasEl?: HTMLCanvasElement }).lowerCanvasEl;\n      if (canvasEl) {\n        const hex = sampleCanvasHexAtClient(canvasEl, e.clientX, e.clientY);\n        if (hex) setEyedropperColor(hex);\n      }\n    }\n  };\n\n  const handlePointerLeave = () => {\n    if (hudPos !== null) setHudPos(null);\n  };\n  \n  const dialog = useDialog();\n  const {\n    pages,\n    activePageId,\n    activeTool,\n    activeCustomShape,\n    zoom,\n    brushSettings,\n    layerPaintTarget,\n    undo,\n    redo,\n    setCanvasInstance,\n    setActiveObject,\n    setLayers,\n    layers,\n    setActiveTool,\n    setZoom,\n    saveHistoryState,\n    canvasInstance,\n    textSettings,\n    activeObject,\n    setActiveCustomShape,\n    updateBrushSettings,\n    rulersEnabled,\n    setRulersEnabled,\n    layoutGridEnabled,\n    setExtractedColors,\n    addUploadedAsset,\n    applyInstantMask,\n    releaseClippingMask,\n    groupSelectedObjects,\n    ungroupObjects,\n    isAiGenerating,\n    runRemoveBg,\n    runSketchToImage,\n    runGenerateInArea,\n    runSelectSubject,\n    runAiMagicEraser,\n    syncLayers,\n    colorBlindnessMode,\n    canvasSyncTrigger,\n    customFonts,\n    updateTextSettings,\n    addCustomFont,\n    deleteCustomFont,\n    runTextToImage,\n    runAiDesignCopilot,\n    runAiCopywrite,\n    applyAiCopywritingSuggestion,\n    aiCopywritingSuggestions,\n    aiStudioError,\n    setAiStudioError,\n    geminiApiKey,\n    setGeminiApiKey,\n    // guidesEnabled and setGuidesEnabled removed (unused in this component)\n  } = useEditorStore();\n\n  const generateTextToImageAndClose = useCallback(async () => {\n    if (isAiGenerating || !textToImagePrompt.trim()) return;\n    // Close AI Studio immediately so the canvas skeleton is visible.\n    dismissToolPanels();\n    await runTextToImage({\n      prompt: textToImagePrompt,\n      aspectRatio: textToImageAspect,\n      resolution: textToImageResolution,\n      references: textToImageRefs.map((r) => r.file),\n    });\n  }, [\n    isAiGenerating,\n    textToImagePrompt,\n    textToImageAspect,\n    textToImageResolution,\n    textToImageRefs,\n    runTextToImage,\n    dismissToolPanels,\n  ]);\n\n  // Keep track of the object we want to color with the eyedropper, so clicking the canvas doesn't lose it\n  const eyedropperTargetRef = useRef<any>(null);\n\n  useEffect(() => {\n    if (activeTool !== 'eyedropper') {\n      eyedropperTargetRef.current = activeObject;\n    }\n  }, [activeTool, activeObject]);\n\n  const previousToolRef = useRef<ToolType | null>(null);\n\n  // Helper to dynamically update fabric object interaction constraints based on activeTool\n  const updateFabricObjectsSettings = useCallback((tool: ToolType) => {\n    const canvas = canvasInstance || fabricCanvasRef.current;\n    if (!canvas) return;\n\n    // Snapshot multi-selection before mutating members (Fabric drops ActiveSelection otherwise).\n    const prevActive = canvas.getActiveObject();\n    const multiSelected =\n      prevActive &&\n      (prevActive.type || '').toLowerCase() === 'activeselection' &&\n      typeof (prevActive as { getObjects?: () => FabricObject[] }).getObjects === 'function'\n        ? (prevActive as { getObjects: () => FabricObject[] }).getObjects().slice()\n        : null;\n    const keepLockedSelection =\n      tool === 'magic-wand' ||\n      tool === 'select-rect' ||\n      tool === 'select-ellipse' ||\n      tool === 'pixel-lasso' ||\n      tool === 'polygon-lasso' ||\n      tool === 'eraser' ||\n      tool === 'paint-bucket';\n    const singleToRestore =\n      keepLockedSelection && prevActive && !multiSelected\n        ? (prevActive as FabricObject)\n        : null;\n\n    canvas.getObjects().forEach((obj: any) => {\n      const isLocked = !!obj.locked;\n\n      if (tool === 'pan' || tool === 'eyedropper') {\n        obj.set({\n          selectable: false,\n          evented: false,\n        });\n      } else if (keepLockedSelection) {\n        // Keep images hittable/selected; lock transforms so clicks sample / erase instead of dragging.\n        const isImage = (obj.type || '').toLowerCase() === 'image';\n        obj.set({\n          selectable: isImage && !isLocked,\n          evented: isImage && !isLocked,\n          hasControls: false,\n          lockMovementX: true,\n          lockMovementY: true,\n          lockScalingX: true,\n          lockScalingY: true,\n          lockRotation: true,\n        });\n      } else if (tool === 'move-only') {\n        obj.set({\n          selectable: !isLocked,\n          evented: true,\n          hasControls: false,\n          hasBorders: false,\n          lockMovementX: isLocked,\n          lockMovementY: isLocked,\n          lockScalingX: true,\n          lockScalingY: true,\n          lockRotation: true,\n        });\n      } else if (tool === 'rotate-only') {\n        obj.set({\n          selectable: !isLocked,\n          evented: true,\n          hasControls: false,\n          hasBorders: false,\n          lockMovementX: true,\n          lockMovementY: true,\n          lockScalingX: true,\n          lockScalingY: true,\n          lockRotation: isLocked,\n        });\n      } else if (tool === 'crop') {\n        // Crop overlay: Fabric draw only \u2014 edge handles live in SelectionControlsOverlay\n        // so they remain visible/editable outside the artboard clip.\n        if ((obj as { isImageCropOverlay?: boolean }).isImageCropOverlay) {\n          obj.set({\n            selectable: true,\n            evented: true,\n            hasControls: false,\n            hasBorders: false,\n          });\n          return;\n        }\n        obj.set({\n          selectable: false,\n          evented: false,\n          hasControls: false,\n          hasBorders: false,\n        });\n      } else {\n        // default 'select', marquee tools, or shape drawing.\n        // Fabric native chrome stays off \u2014 SelectionControlsOverlay draws it.\n        obj.set({\n          selectable: !isLocked,\n          evented: true,\n          hasControls: false,\n          hasBorders: false,\n          lockMovementX: isLocked,\n          lockMovementY: isLocked,\n          lockScalingX: isLocked,\n          lockScalingY: isLocked,\n          lockRotation: isLocked,\n          borderColor: 'transparent',\n          cornerColor: 'transparent',\n          cornerStrokeColor: 'transparent',\n        });\n        if (typeof obj.setControlsVisibility === 'function') {\n          obj.setControlsVisibility({\n            tl: false, tr: false, br: false, bl: false,\n            ml: false, mt: false, mr: false, mb: false,\n            mtr: false\n          });\n        }\n      }\n\n      // Empty pixel layers stay page-sized but never show move/scale chrome.\n      if (\n        isPixelLayer(obj) &&\n        !pixelLayerHasContent(obj) &&\n        tool !== 'pan' &&\n        tool !== 'eyedropper' &&\n        tool !== 'crop'\n      ) {\n        syncPixelLayerInteraction(obj);\n        if (isLocked) {\n          obj.set({\n            selectable: false,\n            evented: false,\n            hasControls: false,\n            hasBorders: false,\n          });\n        }\n      }\n    });\n\n    if (multiSelected && multiSelected.length > 1 && (tool === 'select' || tool === 'move-only' || isMarqueeTool(tool))) {\n      const stillOnCanvas = multiSelected.filter((o) => canvas.getObjects().includes(o));\n      if (stillOnCanvas.length > 1) {\n        const sel = new ActiveSelection(stillOnCanvas, { canvas });\n        sel.set({\n          lockMovementX: false,\n          lockMovementY: false,\n          hasControls: false,\n          hasBorders: false,\n          evented: true,\n          selectable: true,\n        });\n        sel.setCoords();\n        canvas.setActiveObject(sel);\n        useEditorStore.getState().setActiveObject(sel);\n      } else if (stillOnCanvas.length === 1) {\n        canvas.setActiveObject(stillOnCanvas[0]!);\n        useEditorStore.getState().setActiveObject(stillOnCanvas[0]!);\n      }\n    } else if (singleToRestore && canvas.getObjects().includes(singleToRestore)) {\n      // Mutating lock/selectable flags clears Fabric selection \u2014 re-apply for paint tools.\n      canvas.setActiveObject(singleToRestore);\n      useEditorStore.getState().setActiveObject(singleToRestore);\n    }\n\n    canvas.requestRenderAll();\n  }, [canvasInstance]);\n\n  // Reactively sync active tool restrictions and canvas selection behavior\n  useEffect(() => {\n    updateFabricObjectsSettings(activeTool);\n\n    const canvas = canvasInstance || fabricCanvasRef.current;\n    if (!canvas) return;\n\n    if (activeTool === 'select' || activeTool === 'move-only' || activeTool === 'rotate-only') {\n      canvas.selection = true;\n      canvas.skipTargetFind = false;\n      canvas.defaultCursor = 'default';\n    } else if (\n      activeTool === 'magic-wand' ||\n      activeTool === 'select-rect' ||\n      activeTool === 'select-ellipse' ||\n      activeTool === 'pixel-lasso' ||\n      activeTool === 'polygon-lasso' ||\n      activeTool === 'eraser' ||\n      activeTool === 'paint-bucket'\n    ) {\n      // Skip Fabric target-find so clicks outside the image keep the selection\n      // and overlays can map points onto the selected image.\n      canvas.selection = false;\n      canvas.skipTargetFind = true;\n      canvas.defaultCursor = 'crosshair';\n      canvas.hoverCursor = 'crosshair';\n      const store = useEditorStore.getState();\n      const storeAo = store.activeObject as FabricObject | null;\n      const canvasAo = canvas.getActiveObject();\n      const fromPaintTarget = store.paintTargetLayerId\n        ? (canvas.getObjects().find(\n            (o) => (o as FabricObject & { id?: string }).id === store.paintTargetLayerId,\n          ) as FabricObject | undefined) ?? null\n        : null;\n      const ao =\n        (storeAo && canvas.getObjects().includes(storeAo) ? storeAo : null) ||\n        (canvasAo && canvas.getObjects().includes(canvasAo) ? canvasAo : null) ||\n        fromPaintTarget;\n      if (ao) {\n        canvas.setActiveObject(ao);\n        store.setActiveObject(ao);\n        canvas.requestRenderAll();\n      }\n    } else if (isMarqueeTool(activeTool) || activeTool === 'clone-stamp') {\n      canvas.selection = false;\n      canvas.skipTargetFind = true;\n      canvas.defaultCursor = 'crosshair';\n      canvas.hoverCursor = 'crosshair';\n    } else if (activeTool === 'crop') {\n      canvas.selection = false;\n      canvas.skipTargetFind = false;\n      canvas.defaultCursor = 'default';\n      canvas.hoverCursor = 'default';\n    } else {\n      canvas.selection = false;\n\n      if (activeTool === 'eyedropper') {\n        canvas.skipTargetFind = true;\n        canvas.defaultCursor = 'crosshair';\n        canvas.hoverCursor = 'crosshair';\n      } else if (activeTool === 'pan') {\n        // T-20260707-13: mano \u2192 cursor 'grab' (idle) y 'grabbing' (al arrastrar)\n        canvas.skipTargetFind = true;\n        canvas.defaultCursor = 'grab';\n        canvas.hoverCursor = 'grab';\n      } else {\n        canvas.skipTargetFind = false;\n        canvas.defaultCursor = 'default';\n        canvas.hoverCursor = 'default';\n      }\n\n      // Discard active selection only when switching to pan. For brush, keep selection to allow contextual drawing/erasing.\n      if (activeTool === 'pan') {\n        canvas.discardActiveObject();\n        canvas.requestRenderAll();\n        setActiveObject(null);\n      }\n    }\n  }, [activeTool, canvasInstance, updateFabricObjectsSettings, setActiveObject]);\n\n  const clearFabricMarquee = () => {\n    const canvas = fabricCanvasRef.current as (Canvas & { _groupSelector?: unknown }) | null;\n    if (!canvas) return;\n    canvas._groupSelector = null;\n    canvas.requestRenderAll();\n  };\n\n  // Free-canvas panning via transform offset (pan tool left-click or middle mouse on any tool).\n  useEffect(() => {\n    const container = containerRef.current;\n    if (!container) return;\n\n    let isPanningActive = false;\n    let isMiddleButtonPanSession = false;\n    let startX = 0;\n    let startY = 0;\n    let originX = 0;\n    let originY = 0;\n\n    const handlePointerDown = (e: PointerEvent) => {\n      const store = useEditorStore.getState();\n      const isMiddleButtonPan = e.button === 1;\n      const isPanToolLeftClick = e.button === 0 && store.activeTool === 'pan';\n\n      if (!isMiddleButtonPan && !isPanToolLeftClick) return;\n\n      e.preventDefault();\n      e.stopPropagation();\n\n      // Middle-click pans in place \u2014 do not switch the active tool (that remounts\n      // this effect and drops the first press).\n      isMiddleButtonPanSession = isMiddleButtonPan;\n      if (isMiddleButtonPan) {\n        clearFabricMarquee();\n      }\n\n      isPanningActive = true;\n      startX = e.clientX;\n      startY = e.clientY;\n      originX = workspacePanRef.current.x;\n      originY = workspacePanRef.current.y;\n      container.style.cursor = 'grabbing';\n      container.setPointerCapture(e.pointerId);\n    };\n\n    const handlePointerMove = (e: PointerEvent) => {\n      if (!isPanningActive) return;\n      if (isMiddleButtonPanSession) {\n        e.preventDefault();\n        e.stopPropagation();\n      }\n      const nextPan = {\n        x: originX + (e.clientX - startX),\n        y: originY + (e.clientY - startY),\n      };\n      workspacePanRef.current = nextPan;\n      setWorkspacePan(nextPan);\n    };\n\n    const finishPan = (e: PointerEvent) => {\n      if (!isPanningActive) return;\n      isPanningActive = false;\n      isMiddleButtonPanSession = false;\n      clearFabricMarquee();\n\n      const currentTool = useEditorStore.getState().activeTool;\n      container.style.cursor = currentTool === 'pan' ? 'grab' : '';\n      try {\n        container.releasePointerCapture(e.pointerId);\n      } catch (err) {}\n    };\n\n    const blockMiddleMouseForFabric = (e: MouseEvent) => {\n      if (e.button === 1 || (e.type === 'mousemove' && (e.buttons & 4))) {\n        e.preventDefault();\n        e.stopPropagation();\n        clearFabricMarquee();\n      }\n    };\n\n    const handleAuxClick = (e: MouseEvent) => {\n      if (e.button === 1) {\n        e.preventDefault();\n      }\n    };\n\n    container.addEventListener('pointerdown', handlePointerDown, { capture: true });\n    container.addEventListener('pointermove', handlePointerMove, { capture: true });\n    container.addEventListener('pointerup', finishPan, { capture: true });\n    container.addEventListener('pointercancel', finishPan, { capture: true });\n    container.addEventListener('mousedown', blockMiddleMouseForFabric, { capture: true });\n    container.addEventListener('mousemove', blockMiddleMouseForFabric, { capture: true });\n    container.addEventListener('mouseup', blockMiddleMouseForFabric, { capture: true });\n    container.addEventListener('auxclick', handleAuxClick, { capture: true });\n\n    if (activeTool === 'pan') {\n      container.style.cursor = 'grab';\n    } else {\n      container.style.cursor = 'default';\n    }\n\n    return () => {\n      container.removeEventListener('pointerdown', handlePointerDown, { capture: true });\n      container.removeEventListener('pointermove', handlePointerMove, { capture: true });\n      container.removeEventListener('pointerup', finishPan, { capture: true });\n      container.removeEventListener('pointercancel', finishPan, { capture: true });\n      container.removeEventListener('mousedown', blockMiddleMouseForFabric, { capture: true });\n      container.removeEventListener('mousemove', blockMiddleMouseForFabric, { capture: true });\n      container.removeEventListener('mouseup', blockMiddleMouseForFabric, { capture: true });\n      container.removeEventListener('auxclick', handleAuxClick, { capture: true });\n    };\n  }, [activeTool]);\n\n  // Ctrl/Cmd + wheel: pan + CSS zoom only (Fabric bitmap stays page-sized).\n  useEffect(() => {\n    const container = containerRef.current;\n    if (!container) return;\n\n    let rafId = 0;\n    let pending: {\n      nextZoom: number;\n      nextPan: { x: number; y: number };\n    } | null = null;\n\n    const flushZoom = () => {\n      rafId = 0;\n      const job = pending;\n      pending = null;\n      if (!job) return;\n\n      const { nextZoom, nextPan } = job;\n      workspacePanRef.current = nextPan;\n\n      if (panLayerRef.current) {\n        panLayerRef.current.style.transform =\n          `translate(calc(-50% + ${nextPan.x}px), calc(-50% + ${nextPan.y}px))`;\n      }\n\n      const store = useEditorStore.getState();\n      const page = store.pages.find((p) => p.id === store.activePageId) || store.pages[0];\n      if (page && pageFrameRef.current) {\n        pageFrameRef.current.style.width = `${page.width * nextZoom}px`;\n        pageFrameRef.current.style.height = `${page.height * nextZoom}px`;\n\n        const canvas = fabricCanvasRef.current || store.canvasInstance;\n        if (canvas) {\n          // CSS scale only \u2014 do not requestRenderAll (that was flickering).\n          applyCanvasZoomRender(canvas, page.width, page.height, nextZoom);\n        }\n      }\n\n      setWorkspacePan(nextPan);\n      setZoom(nextZoom);\n    };\n\n    const handleWheelZoom = (e: WheelEvent) => {\n      if (!e.ctrlKey && !e.metaKey) return;\n      e.preventDefault();\n      e.stopPropagation();\n\n      const rect = container.getBoundingClientRect();\n      const cursorX = e.clientX - rect.left;\n      const cursorY = e.clientY - rect.top;\n      const centerX = rect.width / 2;\n      const centerY = rect.height / 2;\n\n      const store = useEditorStore.getState();\n      const currentZoom = pending?.nextZoom ?? store.zoom;\n      const currentPan = pending?.nextPan ?? workspacePanRef.current;\n      const zoomFactor = Math.exp(-e.deltaY * 0.002);\n      const rawNextZoom = currentZoom * zoomFactor;\n      const nextZoom = Math.max(0.1, Math.min(10, Math.round(rawNextZoom * 1000) / 1000));\n      if (Math.abs(nextZoom - currentZoom) < 0.0001) return;\n\n      const worldX = (cursorX - centerX - currentPan.x) / currentZoom;\n      const worldY = (cursorY - centerY - currentPan.y) / currentZoom;\n      const nextPan = {\n        x: cursorX - centerX - worldX * nextZoom,\n        y: cursorY - centerY - worldY * nextZoom,\n      };\n\n      pending = { nextZoom, nextPan };\n      if (!rafId) rafId = requestAnimationFrame(flushZoom);\n    };\n\n    container.addEventListener('wheel', handleWheelZoom, { passive: false });\n    return () => {\n      container.removeEventListener('wheel', handleWheelZoom);\n      if (rafId) cancelAnimationFrame(rafId);\n    };\n  }, [setZoom]);\n\n  // Load custom fonts from DB on mount\n  useEffect(() => {\n    useEditorStore.getState().loadCustomFonts();\n  }, []);\n\n  const activePage = pages.find((p) => p.id === activePageId) || pages[0];\n\n  // 1. Initialize Fabric Canvas\n  useEffect(() => {\n    if (!canvasRef.current) return;\n\n    // Create Fabric canvas (bitmap capped \u2014 see applyCanvasZoomRender)\n    const canvas = new Canvas(canvasRef.current, {\n      width: activePage.width,\n      height: activePage.height,\n      preserveObjectStacking: true,\n      stopContextMenu: false,\n      fireRightClick: true,\n      controlsAboveOverlay: true,\n    } as any);\n    applyCanvasBackground(canvas, activePage.backgroundColor, activePage.width, activePage.height);\n    applyCanvasZoomRender(canvas, activePage.width, activePage.height, zoom);\n    // CSS-scale zoom breaks Fabric's default pointer math \u2014 keep brush/eraser on cursor.\n    patchFabricPointerForCssZoom(canvas);\n\n    fabricCanvasRef.current = canvas;\n    setCanvasInstance(canvas);\n\n    canvas.requestRenderAll();\n\n    // Fabric appends a hidden textarea to document.body on text edit. Focusing\n    // it (especially with large padding-top from fontSize) scrolls the page\n    // and \"breaks\" the shell layout. Keep textareas in a zero-size host and\n    // re-focus with preventScroll.\n    const textAreaHost = document.createElement('div');\n    textAreaHost.setAttribute('data-we-fabric-textarea-host', '1');\n    textAreaHost.style.cssText =\n      'position:fixed;left:0;top:0;width:0;height:0;overflow:hidden;opacity:0;pointer-events:none;z-index:-1;';\n    document.body.appendChild(textAreaHost);\n\n    const bindTextAreaHost = (obj: unknown) => {\n      if (!isTextObject(obj)) return;\n      (obj as { hiddenTextareaContainer?: HTMLElement | null }).hiddenTextareaContainer =\n        textAreaHost;\n    };\n    canvas.getObjects().forEach(bindTextAreaHost);\n    canvas.on('object:added', (e: { target?: unknown }) => {\n      bindTextAreaHost(e.target);\n    });\n    canvas.on('text:editing:entered', (e: { target?: { hiddenTextarea?: HTMLTextAreaElement | null } }) => {\n      const ta = e.target?.hiddenTextarea;\n      if (!ta) return;\n      ta.style.position = 'fixed';\n      ta.style.left = '0';\n      ta.style.top = '0';\n      ta.style.width = '1px';\n      ta.style.height = '1px';\n      ta.style.padding = '0';\n      ta.style.margin = '0';\n      ta.style.opacity = '0';\n      ta.style.pointerEvents = 'none';\n      try {\n        ta.focus({ preventScroll: true });\n      } catch {\n        ta.focus();\n      }\n    });\n\n    // Event listeners flags to prevent duplicate history during load\n    let isInternalAction = false;\n    let ctrlDragSession: CtrlDragDuplicateSession | null = null;\n\n    const syncLayersAndHistory = (e?: any) => {\n      if (isInternalAction) return;\n      // Preview duplicate ghost must not dirty layers/history mid-drag.\n      if (e?.target && (e.target as { _weDupGhost?: boolean })._weDupGhost) return;\n      // Crop chrome is ephemeral \u2014 never push undo steps or list it as a layer.\n      if (e?.target && (e.target as { isImageCropOverlay?: boolean }).isImageCropOverlay) {\n        useEditorStore.getState().syncLayers();\n        return;\n      }\n      const store = useEditorStore.getState();\n      \n      // Ensure every new object gets a unique master ID\n      if (e && e.target && !(e.target as any).id && !store.isHistoryAction) {\n        (e.target as any).set('id', `obj-${Date.now()}-${Math.random().toString(36).substring(2,9)}`);\n      }\n\n      store.syncLayers();\n      store.saveHistoryState();\n      updateFabricObjectsSettings(store.activeTool);\n    };\n\n    // Textbox: hide mt/mb (height-only scale). Those stretch glyphs without\n    // Side handles change wrap width; hide mt/mb so Y-only scale cannot desync glyphs.\n    const configureTextboxControls = (obj: any) => {\n      if (!obj || !(obj.type || '').toLowerCase().includes('text')) return;\n      if (typeof obj.setControlsVisibility === 'function') {\n        obj.setControlsVisibility({ mt: false, mb: false });\n      } else {\n        if (obj.controls?.mt) obj.controls.mt.visible = false;\n        if (obj.controls?.mb) obj.controls.mb.visible = false;\n      }\n      obj.objectCaching = false;\n      if (obj.weTextAutoWidth === undefined) obj.weTextAutoWidth = true;\n    };\n\n    canvas.on('object:added', (e: any) => {\n      configureTextboxControls(e?.target);\n      if (e?.target) installIndependentCornerRender(e.target);\n      syncLayersAndHistory(e);\n    });\n    canvas.on('object:removed', (e: any) => {\n      const removedObj = e.target;\n      if (removedObj && (removedObj as { _weDupGhost?: boolean })._weDupGhost) {\n        return;\n      }\n      if (removedObj && (removedObj as any).id) {\n        canvas.getObjects().forEach((o: any) => {\n          if ((o as any).clippedToLayerId === (removedObj as any).id) {\n            o.clipPath = null;\n            (o as any).clippedToLayerId = undefined;\n            if ((o as any)._originalRender) {\n              o.render = (o as any)._originalRender;\n              (o as any)._originalRender = undefined;\n            }\n          }\n        });\n      }\n      syncLayersAndHistory();\n    });\n\n    canvas.on('before:transform', (opt: any) => {\n      const transform = opt?.transform;\n      const ev = opt?.e as MouseEvent | undefined;\n      if (!transform?.target) return;\n\n      captureTransformCornerOrigin(canvas);\n      // Shift (or Alt) = scale from center; default = opposite edge/corner fixed.\n      syncTransformCenteredOrigin(canvas, !!(ev && (ev.shiftKey || ev.altKey)));\n\n      if (transform.action === 'drag') {\n        ctrlDragSession = beginCtrlDragSession(\n          transform.target,\n          !!(ev && (ev.ctrlKey || ev.metaKey)),\n        );\n      } else {\n        cancelCtrlDragGhost(canvas, ctrlDragSession);\n        ctrlDragSession = null;\n      }\n    });\n\n    canvas.on('object:modified', (e: any) => {\n      const obj = e.target;\n      const action = String(e.action || e.transform?.action || '');\n\n      // Ctrl/Cmd+drag with a live ghost \u2192 keep ghost at start, original at drop.\n      if (action === 'drag' && ctrlDragSession && obj === ctrlDragSession.target) {\n        const session = ctrlDragSession;\n        ctrlDragSession = null;\n        if (session.ghost) {\n          isInternalAction = true;\n          commitCtrlDragGhost(canvas, session);\n          isInternalAction = false;\n          useEditorStore.getState().setActiveObject(session.target);\n          useEditorStore.getState().setLayers(canvas.getObjects().slice().reverse());\n          useEditorStore.getState().saveHistoryState();\n          return;\n        }\n        cancelCtrlDragGhost(canvas, session);\n      } else {\n        cancelCtrlDragGhost(canvas, ctrlDragSession);\n        ctrlDragSession = null;\n      }\n\n      if (obj && isTextObject(obj)) {\n        // Only reflow on scale/resize. Drag/rotate/unknown must NOT bake or\n        // remasure \u2014 that looked like a font/size jump when moving text.\n        if (action === 'resizing' || action === 'resize') {\n          obj.weTextAutoWidth = false;\n          fitTextboxToContent(obj);\n          canvas.requestRenderAll();\n        } else if (action.startsWith('scale')) {\n          void remeasureTextObject(obj).then(() => canvas.requestRenderAll());\n        }\n        if (action.startsWith('scale') || action === 'resizing' || action === 'resize') {\n          const store = useEditorStore.getState();\n          const nextSize = getEffectiveFontSize(obj);\n          const nextFamily =\n            (obj as { fontFamily?: string }).fontFamily || store.textSettings.fontFamily;\n          if (\n            store.textSettings.fontSize !== nextSize ||\n            store.textSettings.fontFamily !== nextFamily\n          ) {\n            useEditorStore.setState({\n              textSettings: {\n                ...store.textSettings,\n                fontSize: nextSize,\n                fontFamily: nextFamily,\n              },\n            });\n          }\n        }\n      }\n      syncLayersAndHistory(e);\n    });\n\n    canvas.on('object:scaling', (e: any) => {\n      const ev = e.e as MouseEvent | undefined;\n      // Re-assert center every frame while Alt is held (Fabric may invert origin).\n      syncTransformCenteredOrigin(canvas, !!(ev && (ev.shiftKey || ev.altKey)));\n\n      const obj = e.target;\n      if (obj) {\n        // Text: canvas-edge only (object snap fights Textbox reflow).\n        // Image/shape: canvas + other shapes/images/text.\n        runObjectSnap(\n          obj,\n          'resize',\n          isTextObject(obj) ? { canvasEdgesOnly: true } : undefined,\n          e,\n        );\n      }\n\n      // Do NOT write textSettings here. Per-frame Zustand updates during\n      // scale re-entered React's update depth limit (Maximum update depth\n      // at this handler). Font size syncs on object:modified instead.\n    });\n\n    canvas.on('object:resizing', (e: any) => {\n      const ev = e.e as MouseEvent | undefined;\n      syncTransformCenteredOrigin(canvas, !!(ev && (ev.shiftKey || ev.altKey)));\n\n      const obj = e.target;\n      if (!obj) return;\n      if (isTextObject(obj)) {\n        obj.weTextAutoWidth = false;\n        runObjectSnap(obj, 'resize', { canvasEdgesOnly: true }, e);\n        return;\n      }\n      runObjectSnap(obj, 'resize', undefined, e);\n    });\n\n    const cloneProps = () => [...(FabricObject.customProperties || []), 'linkId'];\n\n    // Shift/Alt mid-resize (center origin) + Ctrl mid-drag (ghost / cancel).\n    const onModifierKey = (e: KeyboardEvent) => {\n      const isCenterMod =\n        e.key === 'Shift' ||\n        e.code === 'ShiftLeft' ||\n        e.code === 'ShiftRight' ||\n        e.key === 'Alt' ||\n        e.code === 'AltLeft' ||\n        e.code === 'AltRight';\n      const isCtrl =\n        e.key === 'Control' ||\n        e.code === 'ControlLeft' ||\n        e.code === 'ControlRight' ||\n        e.key === 'Meta' ||\n        e.code === 'MetaLeft' ||\n        e.code === 'MetaRight';\n\n      if (isCenterMod) {\n        const wantCentered = e.type === 'keydown';\n        if (syncTransformCenteredOrigin(canvas, wantCentered)) {\n          e.preventDefault();\n          canvas.requestRenderAll();\n        } else if (wantCentered) {\n          // Still force-center on keydown even if already \"centered\" (re-assert).\n          syncTransformCenteredOrigin(canvas, true);\n          canvas.requestRenderAll();\n        }\n      }\n\n      if (isCtrl && ctrlDragSession) {\n        const held = e.type === 'keydown';\n        ctrlDragSession.ctrlHeld = held;\n        if (held) {\n          void ensureCtrlDragGhost(canvas, ctrlDragSession, cloneProps());\n        } else {\n          cancelCtrlDragGhost(canvas, ctrlDragSession);\n        }\n      }\n    };\n    window.addEventListener('keydown', onModifierKey);\n    window.addEventListener('keyup', onModifierKey);\n\n\n    canvas.on('contextmenu', (opt: any) => {\n      const e = opt.e as MouseEvent;\n      e.preventDefault();\n      e.stopPropagation();\n      if (isBrushRadiusTool(useEditorStore.getState().activeTool)) {\n        // Fabric owns the canvas pointer events \u2014 open radius popup here\n        // (React onContextMenu on the wrapper never sees right-clicks on the upper canvas).\n        window.dispatchEvent(\n          new CustomEvent('we-brush-radius-popup', {\n            detail: { x: e.clientX, y: e.clientY },\n          }),\n        );\n        return;\n      }\n      \n      const target = opt.target || canvas.findTarget(e);\n      const current = canvas.getActiveObject();\n      const inMulti =\n        !!target &&\n        !!current &&\n        getType(current) === 'activeselection' &&\n        typeof (current as { getObjects?: () => FabricObject[] }).getObjects === 'function' &&\n        (current as { getObjects: () => FabricObject[] }).getObjects().includes(target);\n\n      if (target && !inMulti) {\n        canvas.setActiveObject(target);\n        canvas.requestRenderAll();\n        setActiveObject(target);\n      } else if (!target) {\n        canvas.discardActiveObject();\n        canvas.requestRenderAll();\n        setActiveObject(null);\n      }\n\n      const menuTarget = inMulti ? current : target || null;\n      setContextMenu({\n        x: e.clientX,\n        y: e.clientY,\n        visible: true,\n        targetObject: menuTarget,\n      });\n    });\n\n    // Snapping and smart guides (move + scale/resize).\n    const runObjectSnap = (\n      targetObj: any,\n      mode: 'move' | 'resize',\n      opts?: { canvasEdgesOnly?: boolean },\n      fabricEvent?: { transform?: { corner?: string; action?: string; originX?: string | number; originY?: string | number } },\n    ) => {\n      const store = useEditorStore.getState();\n      const snap = store.snapSettings;\n      if (!snap.enabled) return;\n      if (!targetObj || (targetObj as { isImageCropOverlay?: boolean }).isImageCropOverlay) return;\n\n      const currentPage = store.pages.find((p) => p.id === store.activePageId) || store.pages[0];\n      if (!currentPage) return;\n\n      const zoom = getVisualZoom(canvas);\n      // Slightly looser on resize so edges catch other objects more reliably.\n      const threshold = (mode === 'resize' ? 12 : 8) / zoom;\n      const activeRect = sceneBox(targetObj);\n\n      const xs: number[] = [];\n      const ys: number[] = [];\n      if (snap.canvasEdges) {\n        xs.push(0, currentPage.width / 2, currentPage.width);\n        ys.push(0, currentPage.height / 2, currentPage.height);\n      }\n\n      // Image/shape resize + all moves: magnet to other shapes / images / text.\n      if (!opts?.canvasEdgesOnly) {\n        const moving = new Set<unknown>([targetObj]);\n        if (getType(targetObj) === 'activeselection' && typeof targetObj.getObjects === 'function') {\n          targetObj.getObjects().forEach((o: unknown) => moving.add(o));\n        }\n\n        canvas.getObjects().forEach((otherObj) => {\n          if (moving.has(otherObj)) return;\n          const kind = classifySnapTarget(otherObj as { type?: string; visible?: boolean; id?: string; isImageCropOverlay?: boolean });\n          if (kind === 'ignore') return;\n          if (kind === 'shape' && !snap.shapes) return;\n          if (kind === 'image' && !snap.images) return;\n          if (kind === 'text' && !snap.text) return;\n          const otherRect = sceneBox(otherObj);\n          xs.push(otherRect.left, otherRect.centerX, otherRect.right);\n          ys.push(otherRect.top, otherRect.centerY, otherRect.bottom);\n        });\n      }\n\n      if (xs.length === 0 && ys.length === 0) return;\n\n      if (mode === 'move') {\n        let snapX: number | null = null;\n        let snapY: number | null = null;\n        let guideX: number | null = null;\n        let guideY: number | null = null;\n        let minDiffX = threshold;\n        let minDiffY = threshold;\n\n        const considerX = (x: number, edge: 'left' | 'right' | 'centerX') => {\n          const diff = Math.abs(activeRect[edge] - x);\n          if (diff < minDiffX) {\n            minDiffX = diff;\n            snapX = targetObj.left + (x - activeRect[edge]);\n            guideX = x;\n          }\n        };\n        const considerY = (y: number, edge: 'top' | 'bottom' | 'centerY') => {\n          const diff = Math.abs(activeRect[edge] - y);\n          if (diff < minDiffY) {\n            minDiffY = diff;\n            snapY = targetObj.top + (y - activeRect[edge]);\n            guideY = y;\n          }\n        };\n\n        xs.forEach((x) => {\n          considerX(x, 'left');\n          considerX(x, 'right');\n          considerX(x, 'centerX');\n        });\n        ys.forEach((y) => {\n          considerY(y, 'top');\n          considerY(y, 'bottom');\n          considerY(y, 'centerY');\n        });\n\n        if (snapX !== null) targetObj.set({ left: snapX });\n        if (snapY !== null) targetObj.set({ top: snapY });\n\n        activeGuidesRef.current = {\n          x: guideX !== null ? [guideX] : [],\n          y: guideY !== null ? [guideY] : [],\n          spacingGuides: [],\n        };\n        canvas.requestRenderAll();\n        return;\n      }\n\n      // Resize / scale: snap moving edges; keep opposite edge(s) fixed via AABB nudge.\n      const live = (canvas as unknown as { _currentTransform?: {\n        corner?: string;\n        action?: string;\n        originX?: string | number;\n        originY?: string | number;\n      } })._currentTransform;\n      const fromEvent = fabricEvent?.transform;\n      const activeCtrl = typeof targetObj.getActiveControl === 'function'\n        ? targetObj.getActiveControl()\n        : null;\n      const corner = String(\n        live?.corner || fromEvent?.corner || activeCtrl?.key || '',\n      );\n      if (!corner) {\n        activeGuidesRef.current = { x: [], y: [], spacingGuides: [] };\n        return;\n      }\n      const action = String(live?.action || fromEvent?.action || '');\n      const originX = live?.originX ?? fromEvent?.originX;\n      const originY = live?.originY ?? fromEvent?.originY;\n      const centered =\n        originX === 'center' || originX === 0.5\n          ? originY === 'center' || originY === 0.5\n          : false;\n      const edges = movingEdgesForCorner(corner, centered);\n\n      if (!Number.isFinite(activeRect.width) || !Number.isFinite(activeRect.height)\n        || activeRect.width < 2 || activeRect.height < 2) {\n        activeGuidesRef.current = { x: [], y: [], spacingGuides: [] };\n        return;\n      }\n\n      let guideX: number | null = null;\n      let guideY: number | null = null;\n      let wantLeft: number | null = null;\n      let wantRight: number | null = null;\n      let wantTop: number | null = null;\n      let wantBottom: number | null = null;\n      let minDiffX = threshold;\n      let minDiffY = threshold;\n\n      // Only accept guides that keep a non-inverted box (otherwise a far/invalid\n      // candidate can win by distance and then the whole snap is aborted).\n      const minSize = 2;\n      const leftBound = centered ? activeRect.centerX - minSize : activeRect.left;\n      const rightBound = centered ? activeRect.centerX + minSize : activeRect.right;\n      const topBound = centered ? activeRect.centerY - minSize : activeRect.top;\n      const bottomBound = centered ? activeRect.centerY + minSize : activeRect.bottom;\n\n      xs.forEach((x) => {\n        if (edges.left && x <= rightBound - minSize) {\n          const diff = Math.abs(activeRect.left - x);\n          if (diff <= minDiffX) {\n            minDiffX = diff;\n            guideX = x;\n            wantLeft = x;\n            wantRight = null;\n          }\n        }\n        if (edges.right && x >= leftBound + minSize) {\n          const diff = Math.abs(activeRect.right - x);\n          if (diff <= minDiffX) {\n            minDiffX = diff;\n            guideX = x;\n            wantRight = x;\n            wantLeft = null;\n          }\n        }\n      });\n      ys.forEach((y) => {\n        if (edges.top && y <= bottomBound - minSize) {\n          const diff = Math.abs(activeRect.top - y);\n          if (diff <= minDiffY) {\n            minDiffY = diff;\n            guideY = y;\n            wantTop = y;\n            wantBottom = null;\n          }\n        }\n        if (edges.bottom && y >= topBound + minSize) {\n          const diff = Math.abs(activeRect.bottom - y);\n          if (diff <= minDiffY) {\n            minDiffY = diff;\n            guideY = y;\n            wantBottom = y;\n            wantTop = null;\n          }\n        }\n      });\n\n      if (wantLeft == null && wantRight == null && wantTop == null && wantBottom == null) {\n        activeGuidesRef.current = { x: [], y: [], spacingGuides: [] };\n        return;\n      }\n\n      let newLeft = activeRect.left;\n      let newRight = activeRect.right;\n      let newTop = activeRect.top;\n      let newBottom = activeRect.bottom;\n\n      if (centered) {\n        const cx = activeRect.centerX;\n        const cy = activeRect.centerY;\n        if (wantLeft != null) {\n          const half = Math.max(1, cx - wantLeft);\n          newLeft = cx - half;\n          newRight = cx + half;\n        } else if (wantRight != null) {\n          const half = Math.max(1, wantRight - cx);\n          newLeft = cx - half;\n          newRight = cx + half;\n        }\n        if (wantTop != null) {\n          const half = Math.max(1, cy - wantTop);\n          newTop = cy - half;\n          newBottom = cy + half;\n        } else if (wantBottom != null) {\n          const half = Math.max(1, wantBottom - cy);\n          newTop = cy - half;\n          newBottom = cy + half;\n        }\n      } else {\n        if (wantLeft != null) newLeft = wantLeft;\n        if (wantRight != null) newRight = wantRight;\n        if (wantTop != null) newTop = wantTop;\n        if (wantBottom != null) newBottom = wantBottom;\n      }\n\n      if (newRight - newLeft < minSize || newBottom - newTop < minSize) {\n        activeGuidesRef.current = { x: [], y: [], spacingGuides: [] };\n        return;\n      }\n\n      const oldW = activeRect.width;\n      const oldH = activeRect.height;\n      let factorX = (newRight - newLeft) / oldW;\n      let factorY = (newBottom - newTop) / oldH;\n\n      const snappedX = wantLeft != null || wantRight != null;\n      const snappedY = wantTop != null || wantBottom != null;\n      const uniform =\n        action === 'scale' ||\n        !!(targetObj as { lockUniScaling?: boolean }).lockUniScaling;\n\n      if (uniform) {\n        let factor = 1;\n        if (snappedX && snappedY) factor = minDiffX <= minDiffY ? factorX : factorY;\n        else if (snappedX) factor = factorX;\n        else factor = factorY;\n        factorX = factor;\n        factorY = factor;\n      } else {\n        if (!snappedX) factorX = 1;\n        if (!snappedY) factorY = 1;\n      }\n\n      const sane = (f: number) => Number.isFinite(f) && f >= 0.05 && f <= 20;\n      if (!sane(factorX) || !sane(factorY)) {\n        activeGuidesRef.current = { x: [], y: [], spacingGuides: [] };\n        return;\n      }\n      if (Math.abs(factorX - 1) < 1e-4 && Math.abs(factorY - 1) < 1e-4) {\n        activeGuidesRef.current = {\n          x: guideX !== null ? [guideX] : [],\n          y: guideY !== null ? [guideY] : [],\n          spacingGuides: [],\n        };\n        canvas.requestRenderAll();\n        return;\n      }\n\n      const beforeLeft = targetObj.left ?? 0;\n      const beforeTop = targetObj.top ?? 0;\n\n      if (action === 'resizing') {\n        const nextW = Math.max(\n          (targetObj as { minWidth?: number }).minWidth || 20,\n          (targetObj.width || 0) * factorX,\n        );\n        if (!Number.isFinite(nextW) || nextW < 2) return;\n        targetObj.set({ width: nextW, dirty: true });\n        if (Math.abs(factorY - 1) > 1e-4 && targetObj.height != null) {\n          const nextH = Math.max(1, (targetObj.height || 0) * factorY);\n          if (Number.isFinite(nextH)) targetObj.set({ height: nextH });\n        }\n      } else {\n        const nextSX = (targetObj.scaleX || 1) * factorX;\n        const nextSY = (targetObj.scaleY || 1) * factorY;\n        if (!Number.isFinite(nextSX) || !Number.isFinite(nextSY)) return;\n        targetObj.set({ scaleX: nextSX, scaleY: nextSY });\n      }\n\n      targetObj.setCoords();\n      const after = sceneBox(targetObj);\n\n      let dx = 0;\n      let dy = 0;\n      if (centered) {\n        dx = activeRect.centerX - after.centerX;\n        dy = activeRect.centerY - after.centerY;\n      } else {\n        if (!edges.left) dx = activeRect.left - after.left;\n        else if (!edges.right) dx = activeRect.right - after.right;\n        if (!edges.top) dy = activeRect.top - after.top;\n        else if (!edges.bottom) dy = activeRect.bottom - after.bottom;\n      }\n\n      const nextLeft = beforeLeft + dx;\n      const nextTop = beforeTop + dy;\n      if (!Number.isFinite(nextLeft) || !Number.isFinite(nextTop)) {\n        if (action === 'resizing') {\n          targetObj.set({ width: (targetObj.width || 0) / factorX });\n        } else {\n          targetObj.set({\n            scaleX: (targetObj.scaleX || 1) / factorX,\n            scaleY: (targetObj.scaleY || 1) / factorY,\n          });\n        }\n        targetObj.setCoords();\n        return;\n      }\n\n      targetObj.set({ left: nextLeft, top: nextTop });\n      targetObj.setCoords();\n      rebaselineLiveTransform(canvas);\n\n      activeGuidesRef.current = {\n        x: guideX !== null ? [guideX] : [],\n        y: guideY !== null ? [guideY] : [],\n        spacingGuides: [],\n      };\n      canvas.requestRenderAll();\n    };\n\n    canvas.on('object:moving', (e: any) => {\n      if (ctrlDragSession && e.target === ctrlDragSession.target) {\n        ctrlDragSession.moved = true;\n        const ev = e.e as MouseEvent | undefined;\n        const held = !!(ev && (ev.ctrlKey || ev.metaKey));\n        ctrlDragSession.ctrlHeld = held;\n        if (held) {\n          void ensureCtrlDragGhost(canvas, ctrlDragSession, cloneProps());\n        } else if (ctrlDragSession.ghost) {\n          cancelCtrlDragGhost(canvas, ctrlDragSession);\n        }\n      }\n\n      if (e.target) runObjectSnap(e.target, 'move');\n    });\n\n    const clearActiveGuides = (e?: any) => {\n      if (activeGuidesRef.current) {\n        activeGuidesRef.current = null;\n        canvas.requestRenderAll();\n      }\n      \n      // Smart Linking Propagation\n      if (e?.target) {\n        const store = useEditorStore.getState();\n        const obj = e.target;\n        if ((obj as any).linkId) {\n          store.propagateLinkedObject(obj);\n        } else if (obj.type === 'activeselection') {\n          // If a group of items is modified, check if any of them have linkId\n          const objects = (obj as any).getObjects();\n          objects.forEach((subObj: any) => {\n            if (subObj.linkId) {\n              store.propagateLinkedObject(subObj); // This is approximate for group selections\n            }\n          });\n        }\n      }\n    };\n\n    canvas.on('object:modified', clearActiveGuides);\n    canvas.on('selection:cleared', clearActiveGuides);\n    canvas.on('selection:updated', clearActiveGuides);\n    canvas.on('mouse:up', clearActiveGuides);\n    \n    canvas.on('mouse:down', (e) => {\n      const store = useEditorStore.getState();\n      if (store.activeTool === 'eyedropper') {\n        const canvasEl = (canvas as { lowerCanvasEl?: HTMLCanvasElement }).lowerCanvasEl;\n        if (canvasEl && e.e) {\n          const evt = e.e as MouseEvent;\n          const hex = sampleCanvasHexAtClient(canvasEl, evt.clientX, evt.clientY);\n          if (hex) {\n            const channel: 'fill' | 'stroke' =\n              evt.shiftKey ? 'stroke' : store.eyedropperApplyChannel || 'fill';\n\n            // Photoshop: eyedropper always updates the tool color (FG/BG).\n            if (channel === 'stroke') {\n              store.updateMasterColors({ stroke: hex, activeChannel: 'stroke' });\n            } else {\n              store.updateMasterColors({ fill: hex, activeChannel: 'fill' });\n            }\n\n            const applyToObj = (obj: FabricObject) => {\n              const type = (obj.type || '').toLowerCase();\n              if (type === 'image' || type === 'group' || type === 'activeselection') return false;\n              if (channel === 'stroke') {\n                obj.set({\n                  stroke: hex,\n                  strokeWidth: Math.max(1, (obj as FabricObject & { strokeWidth?: number }).strokeWidth || 1),\n                });\n              } else {\n                obj.set({ fill: hex });\n              }\n              return true;\n            };\n\n            const activeObj = eyedropperTargetRef.current as FabricObject | null;\n            let applied = false;\n            if (activeObj) {\n              const type = (activeObj.type || '').toLowerCase();\n              if (type === 'activeselection' && typeof (activeObj as { getObjects?: () => FabricObject[] }).getObjects === 'function') {\n                for (const child of (activeObj as { getObjects: () => FabricObject[] }).getObjects()) {\n                  if (applyToObj(child)) applied = true;\n                }\n              } else if (applyToObj(activeObj)) {\n                applied = true;\n              }\n\n              if (applied && isTextObject(activeObj)) {\n                if (channel === 'stroke') {\n                  store.updateTextSettings({\n                    stroke: hex,\n                    strokeWidth: Math.max(1, store.textSettings.strokeWidth || 1),\n                  });\n                } else {\n                  store.updateTextSettings({ fill: hex });\n                }\n              } else if (applied) {\n                store.setActiveObject(activeObj);\n              }\n            }\n\n            if (!applied && !activeObj) {\n              // No target object \u2014 color already stored in masterColors (tool FG/BG).\n            } else if (applied) {\n              canvas.requestRenderAll();\n              store.saveHistoryState();\n            }\n\n            store.setEyedropperApplyChannel('fill');\n            store.setActiveTool('select');\n          }\n        }\n      }\n    });\n\n    canvas.on('text:changed', (e: any) => {\n      const obj = e.target;\n      if (!obj || !isTextObject(obj)) return;\n      if ((obj as any).curvature) {\n        updateTextPath(obj, (obj as any).curvature);\n      }\n      // Grow auto-width after Fabric's updateFromTextArea (which already\n      // re-anchored the top edge). Our fit must preserve that same top edge.\n      fitTextboxToContent(obj);\n      canvas.requestRenderAll();\n    });\n\n    canvas.on('mouse:dblclick', (e) => {\n      const target = e.target;\n      if (!target) return;\n\n      if ((target as any).name === 'chart') {\n        window.dispatchEvent(new CustomEvent('edit-chart', { detail: { target } }));\n        return;\n      }\n\n      if (getType(target) === 'image' && (target as any).clipPath) {\n        const img = target as any;\n        const shape = img.clipPath;\n        \n        // Remove clipPath from image\n        img.set({ clipPath: null });\n        \n        // Add shape back to canvas\n        shape.set({\n          opacity: 0.5,\n          selectable: true,\n          evented: true,\n        });\n        canvas.add(shape);\n        canvas.setActiveObject(shape);\n        canvas.requestRenderAll();\n        \n        setCroppingObj({ image: img, shape });\n      } else if (getType(target) === 'group' && (target as any).name === 'canva-frame-clipped') {\n        const frameGroup = target as any;\n        const imgObj = frameGroup.getObjects().find((o: any) => getType(o) === 'image');\n        const placeholder = frameGroup.clippedPlaceholder;\n\n        if (!imgObj || !placeholder) return;\n\n        // Extract image and placeholder from group temporarily\n        canvas.discardActiveObject();\n        canvas.remove(frameGroup);\n\n        const groupLeft = frameGroup.left;\n        const groupTop = frameGroup.top;\n        const groupScaleX = frameGroup.scaleX;\n        const groupScaleY = frameGroup.scaleY;\n        const groupAngle = frameGroup.angle;\n\n        // Convert child positions back to absolute workspace coordinates\n        imgObj.set({\n          left: groupLeft + (imgObj.left * groupScaleX),\n          top: groupTop + (imgObj.top * groupScaleY),\n          scaleX: imgObj.scaleX * groupScaleX,\n          scaleY: imgObj.scaleY * groupScaleY,\n          angle: imgObj.angle + groupAngle,\n          clipPath: null,\n        });\n        canvas.add(imgObj);\n\n        placeholder.set({\n          left: groupLeft + (placeholder.left * groupScaleX),\n          top: groupTop + (placeholder.top * groupScaleY),\n          scaleX: placeholder.scaleX * groupScaleX,\n          scaleY: placeholder.scaleY * groupScaleY,\n          angle: placeholder.angle + groupAngle,\n          opacity: 0.5,\n          selectable: true,\n          evented: true,\n        });\n        canvas.add(placeholder);\n        canvas.setActiveObject(placeholder);\n        canvas.requestRenderAll();\n\n        const bezelObjects = frameGroup.getObjects().filter((o: any) => o !== imgObj);\n        bezelObjects.forEach((o: any) => {\n          o.set({\n            left: groupLeft + (o.left * groupScaleX),\n            top: groupTop + (o.top * groupScaleY),\n            scaleX: o.scaleX * groupScaleX,\n            scaleY: o.scaleY * groupScaleY,\n            angle: o.angle + groupAngle,\n          });\n        });\n\n        setCroppingObj({\n          image: imgObj,\n          shape: placeholder,\n          bezelObjects,\n        } as any);\n      }\n    });\n    \n  canvas.on('path:created', (e: any) => {\n      const store = useEditorStore.getState();\n      const path = e?.path;\n      if (!path) return;\n      // Brush / magic-eraser free-draw stamps into a pixel layer or eraser-marks.\n      if (store.activeTool === 'brush' || store.activeTool === 'magic-eraser') {\n        store.commitBrushPathToPixelLayer(path);\n      }\n    });\n    \n    canvas.on('selection:created', () => {\n      const active = canvas.getActiveObject();\n      useEditorStore.getState().setActiveObject(active || null);\n    });\n\n    canvas.on('selection:updated', () => {\n      const active = canvas.getActiveObject();\n      useEditorStore.getState().setActiveObject(active || null);\n    });\n\n    canvas.on('selection:cleared', () => {\n      const store = useEditorStore.getState();\n      const tool = store.activeTool;\n      // Paint tools mutate selectable/lock flags and Fabric clears selection as a side effect.\n      // Keep the store layer (and re-apply on canvas) so Layers / fill target stay selected.\n      if (\n        tool === 'paint-bucket' ||\n        tool === 'eraser' ||\n        tool === 'magic-wand' ||\n        tool === 'select-rect' ||\n        tool === 'select-ellipse' ||\n        tool === 'pixel-lasso' ||\n        tool === 'polygon-lasso'\n      ) {\n        const prev = store.activeObject as FabricObject | null;\n        const fromPaint = store.paintTargetLayerId\n          ? (canvas.getObjects().find(\n              (o) => (o as FabricObject & { id?: string }).id === store.paintTargetLayerId,\n            ) as FabricObject | undefined) ?? null\n          : null;\n        const keep =\n          (prev && canvas.getObjects().includes(prev) ? prev : null) || fromPaint;\n        if (keep) {\n          requestAnimationFrame(() => {\n            const live = useEditorStore.getState();\n            if (\n              live.activeTool !== tool ||\n              !canvas.getObjects().includes(keep)\n            ) {\n              return;\n            }\n            canvas.setActiveObject(keep);\n            live.setActiveObject(keep);\n            canvas.requestRenderAll();\n          });\n          return;\n        }\n      }\n      store.setActiveObject(null);\n    });\n\n    const handleResize = () => {\n      canvas.calcOffset();\n    };\n    window.addEventListener('resize', handleResize);\n\n    // Cleanup on unmount\n    return () => {\n      window.removeEventListener('keydown', onModifierKey);\n      window.removeEventListener('keyup', onModifierKey);\n      setCanvasInstance(null);\n      canvas.dispose();\n      fabricCanvasRef.current = null;\n      window.removeEventListener('resize', handleResize);\n      textAreaHost.remove();\n    };\n  }, []); // Only run once on mount\n\n  // Keep document from scrolling when Fabric focuses its hidden textarea.\n  useEffect(() => {\n    const html = document.documentElement;\n    const body = document.body;\n    const prevHtmlOverflow = html.style.overflow;\n    const prevBodyOverflow = body.style.overflow;\n    const prevHtmlOverscroll = html.style.overscrollBehavior;\n    html.style.overflow = 'hidden';\n    body.style.overflow = 'hidden';\n    html.style.overscrollBehavior = 'none';\n    return () => {\n      html.style.overflow = prevHtmlOverflow;\n      body.style.overflow = prevBodyOverflow;\n      html.style.overscrollBehavior = prevHtmlOverscroll;\n    };\n  }, []);\n\n  // Grid/guides overlay. Also drops leftover hover-outline listeners that Fast Refresh\n  // leaves attached because the canvas init effect does not remount.\n  useEffect(() => {\n    const canvas = canvasInstance;\n    if (!canvas) return;\n\n    canvas.off('mouse:over');\n    canvas.off('mouse:out');\n    canvas.off('after:render');\n    canvas.getObjects().forEach((obj) => {\n      delete (obj as { _isHovered?: boolean })._isHovered;\n    });\n\n    const onAfterRender = (opt: { ctx?: CanvasRenderingContext2D | null }) => {\n      const ctx = opt?.ctx;\n      if (!ctx) return;\n      const store = useEditorStore.getState();\n      const currentPage = store.pages.find((p) => p.id === store.activePageId) || store.pages[0];\n      if (!currentPage) return;\n\n      ctx.save();\n      const vpt = canvas.viewportTransform;\n      if (vpt) ctx.transform(vpt[0], vpt[1], vpt[2], vpt[3], vpt[4], vpt[5]);\n\n      if (store.layoutGridEnabled) {\n        ctx.save();\n        if (store.layoutGridType === 'columns') {\n          const cols = store.layoutGridColumns || 12;\n          const gutter = store.layoutGridGutter || 20;\n          const margin = store.layoutGridMargin || 20;\n          const gridColor = store.layoutGridColor || 'rgba(236, 72, 153, 0.08)';\n          const canvasWidth = currentPage.width;\n          const canvasHeight = currentPage.height;\n          const availableWidth = canvasWidth - (margin * 2) - (gutter * (cols - 1));\n          const colWidth = availableWidth / cols;\n          ctx.fillStyle = gridColor;\n          for (let i = 0; i < cols; i++) {\n            const x = margin + i * (colWidth + gutter);\n            ctx.fillRect(x, 0, colWidth, canvasHeight);\n          }\n        } else if (store.layoutGridType === 'grid') {\n          const size = store.layoutGridSize || 20;\n          const gridColor = store.layoutGridColor || 'rgba(236, 72, 153, 0.08)';\n          const canvasWidth = currentPage.width;\n          const canvasHeight = currentPage.height;\n          ctx.strokeStyle = gridColor;\n          ctx.lineWidth = 1 / getVisualZoom(canvas);\n          ctx.beginPath();\n          for (let x = size; x < canvasWidth; x += size) {\n            ctx.moveTo(x, 0);\n            ctx.lineTo(x, canvasHeight);\n          }\n          for (let y = size; y < canvasHeight; y += size) {\n            ctx.moveTo(0, y);\n            ctx.lineTo(canvasWidth, y);\n          }\n          ctx.stroke();\n        }\n        ctx.restore();\n      }\n\n      if (store.snapSettings.enabled && activeGuidesRef.current) {\n        ctx.save();\n        const vz = getVisualZoom(canvas);\n        ctx.strokeStyle = '#ec4899';\n        ctx.lineWidth = 1 / vz;\n        ctx.setLineDash([6 / vz, 4 / vz]);\n        activeGuidesRef.current.x.forEach((gx) => {\n          ctx.beginPath();\n          ctx.moveTo(gx, -1000);\n          ctx.lineTo(gx, currentPage.height + 1000);\n          ctx.stroke();\n        });\n        activeGuidesRef.current.y.forEach((gy) => {\n          ctx.beginPath();\n          ctx.moveTo(-1000, gy);\n          ctx.lineTo(currentPage.width + 1000, gy);\n          ctx.stroke();\n        });\n        ctx.restore();\n      }\n      ctx.restore();\n    };\n\n    canvas.on('after:render', onAfterRender);\n    canvas.requestRenderAll();\n\n    return () => {\n      canvas.off('after:render', onAfterRender);\n    };\n  }, [canvasInstance]);\n\n  // 2. Sync CSS zoom / page size (no Fabric redraw on zoom-only)\n  useEffect(() => {\n    const canvas = canvasInstance || fabricCanvasRef.current;\n    if (!canvas) return;\n    applyCanvasZoomRender(canvas, activePage.width, activePage.height, zoom);\n  }, [canvasInstance, zoom, activePage.width, activePage.height]);\n\n  // 2b. Background only when page or fill changes (not on every zoom tick)\n  useEffect(() => {\n    const canvas = canvasInstance || fabricCanvasRef.current;\n    if (!canvas) return;\n    applyCanvasBackground(\n      canvas,\n      activePage.backgroundColor,\n      activePage.width,\n      activePage.height,\n    );\n    canvas.requestRenderAll();\n  }, [canvasInstance, activePage.width, activePage.height, activePage.backgroundColor]);\n\n  // 3. Sync page change (load new JSON and page dimensions)\n  useEffect(() => {\n    const canvas = canvasInstance || fabricCanvasRef.current;\n    if (!canvas) return;\n\n    // Avoid pushing history while loading\n    applyCanvasZoomRender(canvas, activePage.width, activePage.height, zoom);\n    applyCanvasBackground(canvas, activePage.backgroundColor, activePage.width, activePage.height);\n\n    // Load serialized JSON\n    useEditorStore.setState({ isHistoryAction: true });\n    canvas.loadFromJSON(activePage.json).then(() => {\n      // Manually restore custom properties if Fabric missed them\n      const jsonObjects = activePage.json?.objects || [];\n      const canvasObjects = canvas.getObjects();\n      \n      if (jsonObjects.length === canvasObjects.length) {\n        canvasObjects.forEach((obj, i) => {\n          const match = jsonObjects[i];\n          if (match.id) (obj as any).set('id', match.id);\n          if (match.linkId) (obj as any).set('linkId', match.linkId);\n          if (match.name) (obj as any).set('name', match.name);\n          if (match.clippedToLayerId) (obj as any).set('clippedToLayerId', match.clippedToLayerId);\n          if (match.isClipPathMask !== undefined) (obj as any).set('isClipPathMask', match.isClipPathMask);\n          if (match.eraserPaths) (obj as any).set('eraserPaths', match.eraserPaths);\n          if (match.chartData) (obj as any).set('chartData', match.chartData);\n          if (match.chartType) (obj as any).set('chartType', match.chartType);\n          if (match.chartOptions) (obj as any).set('chartOptions', match.chartOptions);\n          if (match.weCornerRadii) (obj as any).set('weCornerRadii', match.weCornerRadii);\n          if (match.weCornersLinked !== undefined) (obj as any).set('weCornersLinked', match.weCornersLinked);\n          if (match.wePixelLayer !== undefined) (obj as any).set('wePixelLayer', match.wePixelLayer);\n          if (match.weBaseLayer !== undefined) (obj as any).set('weBaseLayer', match.weBaseLayer);\n          if (match.weTextAutoWidth !== undefined) (obj as any).set('weTextAutoWidth', match.weTextAutoWidth);\n          installIndependentCornerRender(obj);\n        });\n      } else {\n        console.warn('Canvas object count mismatch during hydration. Custom properties might be lost.');\n        canvasObjects.forEach((obj) => installIndependentCornerRender(obj));\n      }\n\n      canvas.getObjects().forEach((obj) => {\n        if (isTextObject(obj)) {\n          (obj as { hiddenTextareaContainer?: HTMLElement | null }).hiddenTextareaContainer =\n            document.querySelector('[data-we-fabric-textarea-host=\"1\"]') as HTMLElement | null;\n        }\n      });\n\n      reconstructClippingMasks(canvas);\n      applyCanvasBackground(canvas, activePage.backgroundColor, activePage.width, activePage.height);\n      \n      // Restore locked properties and preload Google Fonts\n      const fontLoadPromises: Promise<void>[] = [];\n\n      canvas.getObjects().forEach((obj) => {\n        const isLocked = (obj as any).locked === true;\n        if (isLocked && !(obj as any).wePixelLayer) {\n          obj.set({\n            lockMovementX: true,\n            lockMovementY: true,\n            lockScalingX: true,\n            lockScalingY: true,\n            lockRotation: true,\n            hasControls: false,\n            hasBorders: false,\n            selectable: false,\n            borderColor: 'transparent',\n            cornerColor: 'transparent',\n            cornerStrokeColor: 'transparent',\n          });\n        }\n\n        // Textboxes: no height-only handles; fit wrap column to measured glyphs\n        const type = (obj.type || '').toLowerCase();\n        if (type.includes('text')) {\n          if (typeof (obj as any).setControlsVisibility === 'function') {\n            (obj as any).setControlsVisibility({ mt: false, mb: false });\n          } else {\n            if ((obj as any).controls?.mt) (obj as any).controls.mt.visible = false;\n            if ((obj as any).controls?.mb) (obj as any).controls.mb.visible = false;\n          }\n          (obj as any).objectCaching = false;\n          if ((obj as any).weTextAutoWidth === undefined) (obj as any).weTextAutoWidth = true;\n          // Do NOT bake/fit here \u2014 fallback face metrics shrink the box and the\n          // real glyphs overflow until remasure runs after fonts.load.\n        }\n\n        if (getType(obj) === 'textbox' || getType(obj) === 'text') {\n          const font = (obj as any).fontFamily;\n          if (font && !isSystemFontFamily(font)) {\n            fontLoadPromises.push(loadGoogleFont(font));\n          }\n        }\n      });\n\n      const remasureAllText = () => {\n        const jobs = canvas.getObjects().filter(isTextObject).map((obj) => remeasureTextObject(obj));\n        return Promise.all(jobs).then(() => {\n          canvas.requestRenderAll();\n          useEditorStore.getState().syncLayers();\n        });\n      };\n\n      if (fontLoadPromises.length > 0) {\n        Promise.all(fontLoadPromises).then(() => remasureAllText());\n      } else {\n        void remasureAllText();\n      }\n\n      // Restore drawing mode if activeTool is a freehand paint tool\n      const restoredTool = useEditorStore.getState().activeTool;\n      if (restoredTool === 'brush' || restoredTool === 'magic-eraser') {\n        canvas.isDrawingMode = true;\n      }\n\n      reapplyAllPixelLayerLocks(canvas, activePage.width, activePage.height);\n      \n      canvas.calcOffset();\n      canvas.requestRenderAll();\n      setLayers(canvas.getObjects().slice().reverse());\n      useEditorStore.setState({ isHistoryAction: false });\n    });\n  }, [canvasInstance, activePageId, canvasSyncTrigger]);\n\n  // Helper to convert hex + opacity to RGBA\n  const hexToRgba = (hex: string, opacity: number) => {\n    const cleanHex = hex.replace('#', '');\n    let r = 0, g = 0, b = 0;\n    if (cleanHex.length === 3) {\n      r = parseInt(cleanHex[0] + cleanHex[0], 16);\n      g = parseInt(cleanHex[1] + cleanHex[1], 16);\n      b = parseInt(cleanHex[2] + cleanHex[2], 16);\n    } else if (cleanHex.length === 6) {\n      r = parseInt(cleanHex.substring(0, 2), 16);\n      g = parseInt(cleanHex.substring(2, 4), 16);\n      b = parseInt(cleanHex.substring(4, 6), 16);\n    }\n    return `rgba(${r}, ${g}, ${b}, ${opacity})`;\n  };\n\n  // 4. Handle Tool Selection Triggers (Shapes and Text)\n  useEffect(() => {\n    const canvas = fabricCanvasRef.current;\n    if (!canvas) return;\n\n    if (\n      activeTool === 'select' ||\n      isMarqueeTool(activeTool) ||\n      activeTool === 'magic-wand' ||\n      activeTool === 'select-rect' ||\n      activeTool === 'select-ellipse' ||\n      activeTool === 'pixel-lasso' ||\n      activeTool === 'polygon-lasso' ||\n      activeTool === 'eraser' ||\n      activeTool === 'brush' ||\n      activeTool === 'magic-eraser' ||\n      activeTool === 'clone-stamp' ||\n      activeTool === 'pan' ||\n      activeTool === 'move-only' ||\n      activeTool === 'rotate-only' ||\n      activeTool === 'crop' ||\n      activeTool === 'eyedropper' ||\n      activeTool === 'pen' ||\n      activeTool === 'paint-bucket'\n    ) {\n      return;\n    }\n\n    // Add shapes or text in the center of the page and return to select mode\n    const { width: pageW, height: pageH } = getActivePageSize();\n    const centerX = pageW / 2;\n    const centerY = pageH / 2;\n    const { fill: masterFill, stroke: masterStroke } = useEditorStore.getState().masterColors;\n\n    let newObj: FabricObject | null = null;\n\n    const getStarPoints = (cx: number, cy: number, spikes: number, outerRadius: number, innerRadius: number) => {\n      let rot = (Math.PI / 2) * 3;\n      let x = cx;\n      let y = cy;\n      const step = Math.PI / spikes;\n      const points = [];\n      for (let i = 0; i < spikes; i++) {\n        x = cx + Math.cos(rot) * outerRadius;\n        y = cy + Math.sin(rot) * outerRadius;\n        points.push({ x, y });\n        rot += step;\n        x = cx + Math.cos(rot) * innerRadius;\n        y = cy + Math.sin(rot) * innerRadius;\n        points.push({ x, y });\n        rot += step;\n      }\n      return points;\n    };\n\n    const getPolygonPoints = (sides: number, radius: number) => {\n      const points = [];\n      for (let i = 0; i < sides; i++) {\n        const angle = (i * 2 * Math.PI) / sides - Math.PI / 2;\n        points.push({\n          x: Math.cos(angle) * radius,\n          y: Math.sin(angle) * radius,\n        });\n      }\n      return points;\n    };\n\n    switch (activeTool) {\n      case 'rect':\n        newObj = new Rect({\n          left: centerX - 50,\n          top: centerY - 50,\n          width: 100,\n          height: 100,\n          fill: masterFill,\n          stroke: masterStroke,\n          strokeWidth: 0,\n        });\n        break;\n      case 'rounded-rect':\n        newObj = new Rect({\n          left: centerX - 50,\n          top: centerY - 50,\n          width: 100,\n          height: 100,\n          fill: masterFill,\n          stroke: masterStroke,\n          rx: 15,\n          ry: 15,\n          strokeWidth: 0,\n        });\n        break;\n      case 'circle':\n        newObj = new FabricCircle({\n          left: centerX - 50,\n          top: centerY - 50,\n          radius: 50,\n          fill: masterFill,\n          stroke: masterStroke,\n          strokeWidth: 0,\n        });\n        break;\n      case 'ellipse':\n        newObj = new Ellipse({\n          left: centerX - 60,\n          top: centerY - 40,\n          rx: 60,\n          ry: 40,\n          fill: masterFill,\n          stroke: masterStroke,\n          strokeWidth: 0,\n        });\n        break;\n      case 'custom-shape':\n        if (activeCustomShape) {\n          newObj = createCustomShape(activeCustomShape, centerX, centerY, masterFill);\n          if (newObj) {\n            newObj.set({\n              stroke: masterStroke,\n              strokeWidth: 0,\n            });\n          }\n        }\n        break;\n      case 'triangle':\n        newObj = new FabricTriangle({\n          left: centerX - 50,\n          top: centerY - 50,\n          width: 100,\n          height: 100,\n          fill: masterFill,\n          stroke: masterStroke,\n          strokeWidth: 0,\n        });\n        break;\n      case 'star': {\n        const pts = getStarPoints(0, 0, 5, 50, 20);\n        newObj = new Polygon(pts, {\n          left: centerX - 50,\n          top: centerY - 50,\n          fill: masterFill,\n          stroke: masterStroke,\n          strokeWidth: 0,\n        });\n        break;\n      }\n      case 'polygon': {\n        const pts = getPolygonPoints(6, 50);\n        newObj = new Polygon(pts, {\n          left: centerX - 50,\n          top: centerY - 50,\n          fill: masterFill,\n          stroke: masterStroke,\n          strokeWidth: 0,\n        });\n        break;\n      }\n      case 'arrow':\n        newObj = new Path('M 0 20 L 60 20 L 60 0 L 100 30 L 60 60 L 60 40 L 0 40 Z', {\n          left: centerX - 50,\n          top: centerY - 30,\n          width: 100,\n          height: 60,\n          fill: masterFill,\n          stroke: masterStroke,\n          strokeWidth: 0,\n        });\n        break;\n      case 'speech-bubble':\n        newObj = new Path('M 10 10 H 90 A 10 10 0 0 1 100 20 V 60 A 10 10 0 0 1 90 70 H 40 L 20 90 V 70 H 10 A 10 10 0 0 1 0 60 V 20 A 10 10 0 0 1 10 10 Z', {\n          left: centerX - 50,\n          top: centerY - 45,\n          width: 100,\n          height: 90,\n          fill: masterFill,\n          stroke: masterStroke,\n          strokeWidth: 0,\n        });\n        break;\n      case 'heart':\n        newObj = new Path('M 50 15 C 35 -5, 0 -5, 0 30 C 0 55, 35 80, 50 90 C 65 80, 100 55, 100 30 C 100 -5, 65 -5, 50 15 Z', {\n          left: centerX - 50,\n          top: centerY - 45,\n          width: 100,\n          height: 90,\n          fill: masterFill,\n          stroke: masterStroke,\n          strokeWidth: 0,\n        });\n        break;\n      case 'cross':\n        newObj = new Path('M 35 0 H 65 V 35 H 100 V 65 H 65 V 100 H 35 V 65 H 0 V 35 H 35 Z', {\n          left: centerX - 50,\n          top: centerY - 50,\n          width: 100,\n          height: 100,\n          fill: masterFill,\n          stroke: masterStroke,\n          strokeWidth: 0,\n        });\n        break;\n      case 'line':\n        newObj = new Line([centerX - 75, centerY, centerX + 75, centerY], {\n          stroke: masterFill,\n          strokeWidth: 4,\n        });\n        break;\n      case 'text': {\n        const placeholder = 'Haz doble clic para editar';\n        newObj = new Textbox(placeholder, {\n          left: centerX - 150,\n          top: centerY - 25,\n          width: 500,\n          fontSize: textSettings.fontSize,\n          fontFamily: textSettings.fontFamily,\n          fill: masterFill,\n          textAlign: textSettings.textAlign as any,\n          fontWeight: textSettings.fontWeight,\n          fontStyle: textSettings.fontStyle as any,\n          underline: textSettings.underline,\n          charSpacing: textSettings.charSpacing,\n          lineHeight: textSettings.lineHeight,\n          linethrough: textSettings.linethrough,\n          overline: textSettings.overline,\n          stroke: textSettings.strokeWidth > 0 ? masterStroke : textSettings.stroke,\n          strokeWidth: textSettings.strokeWidth,\n          // Avoid stale cache mismatches vs selection controls when zooming\n          objectCaching: false,\n          weTextAutoWidth: true,\n        } as any);\n        const finishTextSize = () => {\n          sizeTextboxToNaturalWidth(newObj);\n          canvas?.requestRenderAll();\n        };\n        const family = textSettings.fontFamily || 'Inter';\n        const size = textSettings.fontSize || 40;\n        const ensureFont = () => {\n          if (typeof document === 'undefined' || !document.fonts?.load) {\n            requestAnimationFrame(finishTextSize);\n            return;\n          }\n          void document.fonts\n            .load(`${size}px \"${family}\"`)\n            .catch(() => undefined)\n            .then(() => {\n              // Also pull remote face if not a system font\n              if (!isSystemFontFamily(family)) {\n                return loadGoogleFont(family);\n              }\n            })\n            .then(finishTextSize);\n        };\n        ensureFont();\n        break;\n      }\n    }\n\n    if (activeTool.startsWith('frame-')) {\n      newObj = createFrame(activeTool, centerX, centerY) as any;\n    }\n\n    if (newObj) {\n      placeOnPageCenter(newObj);\n      canvas.add(newObj);\n      canvas.setActiveObject(newObj);\n      canvas.requestRenderAll();\n      setActiveObject(newObj);\n      setLayers(canvas.getObjects().slice().reverse());\n      saveHistoryState();\n    }\n\n    // Switch back to select mode\n    setActiveTool('select');\n  }, [activeTool]);\n\n  // Keep last eraser / lasso group tool for their flyouts.\n  useEffect(() => {\n    if (isEraserGroupTool(activeTool)) {\n      setEraserGroupTool(activeTool);\n    }\n    if (isLassoGroupTool(activeTool)) {\n      setLassoGroupTool(activeTool);\n    }\n  }, [activeTool]);\n\n  // Dedicated useEffect to manage and reactively sync freehand paint tools.\n  useEffect(() => {\n    const canvas = canvasInstance || fabricCanvasRef.current;\n    if (!canvas) return;\n\n    const isMagicEraser = activeTool === 'magic-eraser';\n    const isBrush = activeTool === 'brush';\n    if (!isBrush && !isMagicEraser) {\n      canvas.isDrawingMode = false;\n      return;\n    }\n\n    // Mask painting uses MaskPaintOverlay (live dabs) \u2014 not Fabric free-draw.\n    // Magic Eraser never uses layer-mask paint; it paints content marks.\n    if (isBrush && layerPaintTarget === 'mask') {\n      canvas.isDrawingMode = false;\n      return;\n    }\n\n    const resolveMagicEraserTarget = () => {\n      const store = useEditorStore.getState();\n      const layer = store.resolvePaintTargetLayer();\n      if (layer) return layer;\n      const pinnedId = store.magicEraserTargetId || store.lastSelectedObjectId;\n      if (pinnedId && store.canvasInstance) {\n        const pinned = store.canvasInstance\n          .getObjects()\n          .find((o) => (o as { id?: string }).id === pinnedId);\n        if (pinned && (pinned.type || '').toLowerCase() === 'image') {\n          return pinned;\n        }\n      }\n      const ao = store.activeObject;\n      if (ao && (ao.type || '').toLowerCase() === 'image') return ao;\n      return null;\n    };\n\n    // Magic eraser: no drawing until a layer/image is selected.\n    if (isMagicEraser && !resolveMagicEraserTarget()) {\n      canvas.isDrawingMode = false;\n      return;\n    }\n\n    // Block free-draw start when no paint target / image layer is selected.\n    const guardPaintTarget = (opt: { e: Event }) => {\n      const store = useEditorStore.getState();\n      const e = opt.e as MouseEvent;\n      if (e.button !== 0) return;\n\n      if (isMagicEraser) {\n        const target = resolveMagicEraserTarget();\n        if (target) {\n          const id =\n            (target as { id?: string }).id ||\n            `img-${Date.now()}`;\n          if (!(target as { id?: string }).id) {\n            target.set({ id } as never);\n          }\n          store.setMagicEraserTargetId(id);\n          return;\n        }\n      } else if (store.resolvePaintTargetLayer()) {\n        return;\n      }\n\n      // Cancel this stroke: leave drawing mode briefly so Fabric drops the gesture.\n      canvas.isDrawingMode = false;\n      store.addToast(t.layers.mustSelectLayer, 'warning');\n      requestAnimationFrame(() => {\n        const live = useEditorStore.getState();\n        if (live.activeTool === 'brush' && live.layerPaintTarget !== 'mask') {\n          canvas.isDrawingMode = true;\n        } else if (\n          live.activeTool === 'magic-eraser' &&\n          resolveMagicEraserTarget()\n        ) {\n          canvas.isDrawingMode = true;\n        }\n      });\n    };\n    canvas.on('mouse:down', guardPaintTarget);\n\n    canvas.isDrawingMode = true;\n    canvas.calcOffset(); // Recalculate canvas coordinates to prevent pointer mismatch\n\n    const currentType = isMagicEraser ? 'pencil' : brushSettings.type || 'pencil';\n    let brush = canvas.freeDrawingBrush;\n\n    // Determine if we need to create/re-instantiate the brush class\n    const needsNewBrush =\n      !brush ||\n      (currentType === 'pencil' &&\n        !(\n          brush instanceof StablePencilBrush &&\n          !(brush instanceof CalligraphyBrush) &&\n          !(brush instanceof HighlighterBrush) &&\n          !(brush instanceof ChalkBrush)\n        )) ||\n      (currentType === 'calligraphy' && !(brush instanceof CalligraphyBrush)) ||\n      (currentType === 'highlighter' && !(brush instanceof HighlighterBrush)) ||\n      (currentType === 'chalk' && !(brush instanceof ChalkBrush)) ||\n      (currentType === 'spray' && !(brush instanceof SprayBrush)) ||\n      (currentType === 'circle' && !(brush instanceof CircleBrush));\n\n    if (needsNewBrush) {\n      if (currentType === 'pencil') {\n        brush = new StablePencilBrush(canvas);\n      } else if (currentType === 'calligraphy') {\n        brush = new CalligraphyBrush(canvas);\n      } else if (currentType === 'highlighter') {\n        brush = new HighlighterBrush(canvas);\n      } else if (currentType === 'chalk') {\n        brush = new ChalkBrush(canvas);\n      } else if (currentType === 'spray') {\n        const sprayBrush = new SprayBrush(canvas);\n        sprayBrush.density = 25; // Good aesthetic density preset\n        sprayBrush.dotWidth = 2.5; // Good aesthetic dot size\n        brush = sprayBrush;\n      } else if (currentType === 'circle') {\n        brush = new CircleBrush(canvas);\n      }\n      canvas.freeDrawingBrush = brush;\n    }\n\n    if (canvas.freeDrawingBrush) {\n      if (isMagicEraser) {\n        // Fixed red marks for AI mask \u2014 do not mutate the user's brush style settings.\n        const op = brushSettings.opacity !== undefined ? brushSettings.opacity : 0.5;\n        canvas.freeDrawingBrush.color = hexToRgba('#ef4444', op);\n        canvas.freeDrawingBrush.width = brushSettings.width;\n        canvas.freeDrawingBrush.shadow = null;\n        if (canvas.freeDrawingBrush instanceof StablePencilBrush) {\n          canvas.freeDrawingBrush.stabilization = 0.3;\n          canvas.freeDrawingBrush.pressureSensitivity = false;\n        }\n      } else {\n        // 1. Color with Opacity\n        const op = brushSettings.opacity !== undefined ? brushSettings.opacity : 1.0;\n        canvas.freeDrawingBrush.color = hexToRgba(brushSettings.color, op);\n\n        // 2. Stroke Width\n        canvas.freeDrawingBrush.width = brushSettings.width;\n\n        // 3. Shadow config\n        if (brushSettings.shadowEnabled && brushSettings.shadowBlur > 0) {\n          canvas.freeDrawingBrush.shadow = new Shadow({\n            blur: brushSettings.shadowBlur,\n            offsetX: 0,\n            offsetY: 0,\n            affectStroke: true,\n            color: brushSettings.shadowColor || '#000000',\n          });\n        } else {\n          canvas.freeDrawingBrush.shadow = null;\n        }\n\n        // 4. Custom settings for StablePencilBrush subclasses\n        if (canvas.freeDrawingBrush instanceof StablePencilBrush) {\n          canvas.freeDrawingBrush.stabilization =\n            brushSettings.stabilization !== undefined ? brushSettings.stabilization : 0.3;\n          canvas.freeDrawingBrush.pressureSensitivity = !!brushSettings.pressureSensitivity;\n        }\n      }\n    }\n\n    return () => {\n      canvas.off('mouse:down', guardPaintTarget);\n    };\n  }, [\n    canvasInstance,\n    activeTool,\n    activeObject,\n    layerPaintTarget,\n    brushSettings.type,\n    brushSettings.color,\n    brushSettings.width,\n    brushSettings.opacity,\n    brushSettings.shadowColor,\n    brushSettings.shadowBlur,\n    brushSettings.shadowEnabled,\n    brushSettings.stabilization,\n    brushSettings.pressureSensitivity,\n    t.layers.mustSelectLayer,\n  ]);\n\n  // Reactively load Google Fonts when fontFamily changes (incl. live preview).\n  useEffect(() => {\n    const canvas = fabricCanvasRef.current;\n    if (!canvas || !activeObject) return;\n\n    if (getType(activeObject) === 'textbox' || getType(activeObject) === 'text') {\n      const font = textSettings.fontFamily;\n      if (!font) return;\n      const target = activeObject;\n      const size = Math.max(1, (target as { fontSize?: number }).fontSize || textSettings.fontSize || 40);\n      const weight = (target as { fontWeight?: string | number }).fontWeight || textSettings.fontWeight || 'normal';\n      const style = (target as { fontStyle?: string }).fontStyle || textSettings.fontStyle || 'normal';\n      void ensureFontReady(font, { size, weight, style })\n        .then(() => {\n          // Drop stale previews: user may have arrowed past this face already.\n          if (useEditorStore.getState().textSettings.fontFamily !== font) return;\n          if (useEditorStore.getState().activeObject !== target) return;\n          // Assign without Fabric set() \u2014 avoid sync initDimensions on fallback metrics.\n          target.fontFamily = font;\n          target.dirty = true;\n          return remeasureTextObject(target);\n        })\n        .then(() => {\n          if (useEditorStore.getState().textSettings.fontFamily !== font) return;\n          if (useEditorStore.getState().activeObject !== target) return;\n          target.setCoords();\n          canvas.requestRenderAll();\n        });\n    }\n  }, [textSettings.fontFamily, activeObject]);\n\n  // When any face finishes downloading, remasure active text so late arrivals\n  // (display=swap / Poppins-like faces) do not leave controls undersized.\n  useEffect(() => {\n    if (typeof document === 'undefined' || !document.fonts?.addEventListener) return;\n    const onFontsDone = () => {\n      const canvas = fabricCanvasRef.current;\n      const obj = useEditorStore.getState().activeObject;\n      if (!canvas || !obj || !isTextObject(obj)) return;\n      void remeasureTextObject(obj).then(() => {\n        obj.setCoords();\n        canvas.requestRenderAll();\n      });\n    };\n    document.fonts.addEventListener('loadingdone', onFontsDone);\n    return () => document.fonts.removeEventListener('loadingdone', onFontsDone);\n  }, []);\n\n  // 5. Global Keyboard Shortcuts\n  useEffect(() => {\n    const handleKeyDown = (e: KeyboardEvent) => {\n      const canvas = fabricCanvasRef.current;\n      if (!canvas) return;\n\n      const activeObj = canvas.getActiveObject();\n      \n      const isInputFocused = document.activeElement?.tagName === 'INPUT' || \n                             document.activeElement?.tagName === 'TEXTAREA' ||\n                             document.activeElement?.tagName === 'SELECT' ||\n                             document.activeElement?.hasAttribute('contenteditable') ||\n                             (activeObj && (activeObj as any).isEditing);\n      \n      if (isInputFocused) return;\n\n      const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;\n      const cmdOrCtrl = isMac ? e.metaKey : e.ctrlKey;\n\n      // A. Undo / Redo\n      if (cmdOrCtrl && (e.key === 'z' || e.key === 'Z')) {\n        e.preventDefault();\n        if (e.shiftKey) {\n          redo();\n        } else {\n          undo();\n        }\n      }\n      else if (cmdOrCtrl && (e.key === 'y' || e.key === 'Y')) {\n        e.preventDefault();\n        redo();\n      }\n\n      // B. Group / Ungroup (Cmd+G / Cmd+Shift+G)\n      else if (cmdOrCtrl && (e.key === 'g' || e.key === 'G')) {\n        e.preventDefault();\n        if (e.shiftKey) {\n          ungroupObjects();\n        } else {\n          groupSelectedObjects();\n        }\n      }\n\n      // B. Duplicate (Cmd+D / Ctrl+D)\n      else if (cmdOrCtrl && (e.key === 'd' || e.key === 'D')) {\n        e.preventDefault();\n        if (activeObj) {\n          activeObj.clone().then((clonedObj) => {\n            canvas.discardActiveObject();\n            clonedObj.set({\n              left: clonedObj.left + 15,\n              top: clonedObj.top + 15,\n              evented: true,\n            });\n\n            if ((activeObj as any).name) {\n              (clonedObj as any).name = (activeObj as any).name;\n            }\n\n            if (getType(clonedObj) === 'activeselection') {\n              clonedObj.canvas = canvas;\n              (clonedObj as any).forEachObject((obj: any) => {\n                canvas.add(obj);\n              });\n              clonedObj.setCoords();\n            } else {\n              canvas.add(clonedObj);\n            }\n            canvas.setActiveObject(clonedObj);\n            canvas.requestRenderAll();\n            setActiveObject(clonedObj);\n            setLayers(canvas.getObjects().slice().reverse());\n            saveHistoryState();\n          });\n        }\n      }\n\n      // C. Delete Selected (Delete / Backspace)\n      else if (e.key === 'Delete' || e.key === 'Backspace') {\n        e.preventDefault();\n        const store = useEditorStore.getState();\n        // Pixel selection (wand / lasso) takes priority over deleting the Fabric object.\n        if (store.magicWandSelection && store.magicWandSelection.pixelCount > 0) {\n          void store.applyMagicWandDelete();\n          return;\n        }\n        if (activeObj) {\n          if (getType(activeObj) === 'activeselection') {\n            const selectedCount = (activeObj as { size?: () => number }).size?.() ?? 0;\n            const total = canvas.getObjects().length;\n            if (selectedCount >= total && total > 0) {\n              // Keep one empty layer: clear the first, remove the rest.\n              const objs = canvas.getObjects().slice();\n              const keep = objs[0];\n              for (let i = 1; i < objs.length; i++) {\n                const o = objs[i];\n                if (o) canvas.remove(o);\n              }\n              canvas.discardActiveObject();\n              if (keep) {\n                const result = store.deleteLayerOrClear(keep);\n                if (result === 'blocked') {\n                  store.addToast(t.layers.cannotDeleteLastLayer, 'warning');\n                }\n              }\n              return;\n            }\n            (activeObj as any).forEachObject((obj: any) => {\n              canvas.remove(obj);\n            });\n            canvas.discardActiveObject();\n          } else {\n            const result = store.deleteLayerOrClear(activeObj);\n            if (result === 'blocked') {\n              store.addToast(t.layers.cannotDeleteLastLayer, 'warning');\n            }\n            // store already syncs layers + history for removed|cleared\n            return;\n          }\n          canvas.requestRenderAll();\n          setActiveObject(null);\n          setLayers(canvas.getObjects().slice().reverse());\n          saveHistoryState();\n        }\n      }\n      else if (cmdOrCtrl && (e.key === 'c' || e.key === 'C')) {\n        if (activeObj) {\n          e.preventDefault();\n          activeObj.clone(['linkId']).then((cloned: any) => {\n            clipboard = cloned;\n          });\n        }\n      }\n      else if (cmdOrCtrl && (e.key === 'v' || e.key === 'V')) {\n        e.preventDefault();\n        if (clipboard) {\n          clipboard.clone(['linkId']).then((clonedObj: any) => {\n            canvas.discardActiveObject();\n            clonedObj.set({\n              left: clonedObj.left + 15,\n              top: clonedObj.top + 15,\n              evented: true,\n            });\n            if (getType(clonedObj) === 'activeselection') {\n              clonedObj.canvas = canvas;\n              clonedObj.forEachObject((obj: any) => {\n                obj.set('id', `obj-${Date.now()}-${Math.random().toString(36).substring(2,9)}`);\n                canvas.add(obj);\n              });\n              clonedObj.setCoords();\n            } else {\n              clonedObj.set('id', `obj-${Date.now()}-${Math.random().toString(36).substring(2,9)}`);\n              canvas.add(clonedObj);\n            }\n            canvas.setActiveObject(clonedObj);\n            canvas.requestRenderAll();\n            setActiveObject(clonedObj);\n            setLayers(canvas.getObjects().slice().reverse());\n            saveHistoryState();\n          });\n        }\n      }\n\n      // D. Precise Arrow Nudging\n      else if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {\n        if (activeObj) {\n          if (activeObj.lockMovementX || activeObj.lockMovementY) return;\n          e.preventDefault();\n          const amount = e.shiftKey ? 10 : 1;\n          \n          switch (e.key) {\n            case 'ArrowUp':\n              activeObj.set({ top: activeObj.top - amount });\n              break;\n            case 'ArrowDown':\n              activeObj.set({ top: activeObj.top + amount });\n              break;\n            case 'ArrowLeft':\n              activeObj.set({ left: activeObj.left - amount });\n              break;\n            case 'ArrowRight':\n              activeObj.set({ left: activeObj.left + amount });\n              break;\n          }\n          activeObj.setCoords();\n          canvas.requestRenderAll();\n          saveHistoryState();\n        }\n      }\n      \n      // E. Space: exit eyedropper; otherwise hold to pan\n      else if (e.key === ' ' && !isInputFocused && !e.repeat) {\n        const currentTool = useEditorStore.getState().activeTool;\n        if (currentTool === 'eyedropper') {\n          previousToolRef.current = null;\n          setActiveTool('select');\n          e.preventDefault();\n          return;\n        }\n        previousToolRef.current = currentTool;\n        setActiveTool('pan');\n        e.preventDefault();\n      }\n\n      // Keyboard Help Modal Toggle: removido en T-20260707-13. La tecla `?` ahora se\n      // gestiona desde App.tsx (que controla el \u00FAnico modal de atajos).\n\n      // F. Swap master fill/stroke (Photoshop X)\n      else if (!cmdOrCtrl && !e.altKey && !e.shiftKey && e.key.toLowerCase() === 'x' && !isInputFocused) {\n        e.preventDefault();\n        useEditorStore.getState().swapMasterColors();\n      }\n\n      // G. Tool Quick Selection Shortcuts (T-20260707-13)\n      // Map de tecla \u2192 herramienta destino. Todas las herramientas se\n      // TOGGLEN: si ya est\u00E1 activa, vuelve a 'select'.\n      else if (!cmdOrCtrl && !e.altKey && !e.shiftKey) {\n        const key = e.key.toLowerCase();\n        const shortcutMap: Record<string, ToolType> = {\n          v:  'select',\n          h:  'pan',\n          b:  'brush',\n          g:  'paint-bucket',\n          s:  'clone-stamp',\n          w:  'magic-wand',\n          l:  'pixel-lasso',\n          o:  'polygon-lasso',\n          e:  'eraser',\n          c:  'crop',\n          i:  'eyedropper',\n          p:  'pen',\n          t:  'text',\n          r:  'rect',\n        };\n        const target = shortcutMap[key];\n        if (target) {\n          if (target === 'crop' && !canUseImageCropTool(activeObj, fabricCanvasRef.current || canvasInstance)) return;\n          e.preventDefault();\n          if (target === 'eyedropper') {\n            useEditorStore.getState().setEyedropperApplyChannel('fill');\n          }\n          // T-20260707-13: toggle \u2014 si es la misma herramienta, vuelve a 'select'.\n          // Al cambiar a una herramienta (incluido 'brush') cerrar cualquier panel abierto.\n          setActiveTool((prev) => {\n            const nextTool = prev === target ? 'select' : target;\n            if (nextTool !== 'select') dismissToolPanels();\n            return nextTool;\n          });\n        }\n      }\n    };\n\n    const handleKeyUp = (e: KeyboardEvent) => {\n      if (e.key === ' ' && previousToolRef.current) {\n        setActiveTool(previousToolRef.current);\n        previousToolRef.current = null;\n        e.preventDefault();\n      }\n    };\n\n    window.addEventListener('keydown', handleKeyDown);\n    window.addEventListener('keyup', handleKeyUp);\n    return () => {\n      window.removeEventListener('keydown', handleKeyDown);\n      window.removeEventListener('keyup', handleKeyUp);\n    };\n  }, [undo, redo, activePageId, setActiveTool]);\n\n  // Paste image handler from clipboard\n  useEffect(() => {\n    const canvas = fabricCanvasRef.current;\n    if (!canvas) return;\n\n    const handlePaste = (e: ClipboardEvent) => {\n      const items = e.clipboardData?.items;\n      if (!items) return;\n\n      for (let i = 0; i < items.length; i++) {\n        if (items[i].type.indexOf('image') !== -1) {\n          const file = items[i].getAsFile();\n          if (!file) continue;\n\n          e.preventDefault();\n          const reader = new FileReader();\n          reader.onload = async (event) => {\n            const dataUrl = event.target?.result as string;\n            \n            const imgEl = new Image();\n            imgEl.src = dataUrl;\n            imgEl.onload = () => {\n              const width = imgEl.naturalWidth || 800;\n              const height = imgEl.naturalHeight || 600;\n              const formattedSize = file.size > 1024 * 1024\n                ? (file.size / (1024 * 1024)).toFixed(1) + ' MB'\n                : (file.size / 1024).toFixed(0) + ' KB';\n\n              useEditorStore.getState().addUploadedAsset(file.name, dataUrl, formattedSize, file.type, width, height);\n              void useEditorStore.getState().stampImageOntoActivePixelLayer(dataUrl, {\n                name: file.name,\n              });\n            };\n          };\n          reader.readAsDataURL(file);\n          break;\n        }\n      }\n    };\n\n    window.addEventListener('paste', handlePaste);\n    return () => {\n      window.removeEventListener('paste', handlePaste);\n    };\n  }, [canvasInstance, activePageId]);\n\n  const handleDrop = async (e: React.DragEvent<HTMLDivElement>) => {\n    e.preventDefault();\n    const canvas = fabricCanvasRef.current;\n    if (!canvas) return;\n\n    // Helper function to process drop logic (from sidebar or OS)\n    const processDroppedImage = async (dataUrl: string, name: string, dropEvent: React.DragEvent<HTMLDivElement>, fileIndex = 0) => {\n      const img = await FabricImage.fromURL(dataUrl);\n      const scenePoint = canvas.getScenePoint(dropEvent.nativeEvent);\n      const pointer = scenePoint;\n      \n      let targetFrame: any = null;\n      \n      // Check if dropped inside a canva-frame\n      const objects = canvas.getObjects();\n      for (let i = objects.length - 1; i >= 0; i--) {\n        const obj = objects[i];\n        if ((obj as any).name === 'canva-frame') {\n          if (obj.containsPoint(pointer)) {\n            targetFrame = obj;\n            break;\n          }\n        }\n      }\n\n      if (targetFrame && targetFrame.getObjects) {\n        const frameObjects = targetFrame.getObjects();\n        const placeholder = frameObjects.find((o: any) => o.name === 'frame-placeholder');\n        \n        if (placeholder) {\n          const imgEl = img.getElement() as HTMLImageElement;\n          const pW = placeholder.getScaledWidth();\n          const pH = placeholder.getScaledHeight();\n          const scale = Math.max(pW / img.width, pH / img.height);\n          \n          import('fabric').then(({ Pattern }) => {\n            const pattern = new Pattern({\n              source: imgEl,\n              repeat: 'no-repeat',\n            });\n            // Object-fit: cover logic via transform matrix\n            pattern.patternTransform = [\n              scale, 0, 0, scale, \n              (pW - img.width * scale) / 2, \n              (pH - img.height * scale) / 2\n            ];\n            \n            placeholder.set('fill', pattern);\n            canvas.requestRenderAll();\n            saveHistoryState();\n          });\n          return;\n        }\n      }\n\n      // Default drop: stamp into the active fixed pixel layer (Photoshop-style)\n      const offsetX = fileIndex * 20;\n      const offsetY = fileIndex * 20;\n      void useEditorStore.getState().stampImageOntoActivePixelLayer(dataUrl, {\n        name,\n        centerX: scenePoint.x + offsetX,\n        centerY: scenePoint.y + offsetY,\n      });\n    };\n\n    // 1. Check for Sidebar Drag (URL payload)\n    const draggedUrl = e.dataTransfer.getData('text/plain');\n    const draggedName = e.dataTransfer.getData('image/name') || 'Imagen Insertada';\n    \n    if (draggedUrl) {\n      await processDroppedImage(draggedUrl, draggedName, e);\n      return;\n    }\n\n    // 2. Check for OS File Drop\n    const files = e.dataTransfer.files;\n    if (files && files.length > 0) {\n      Array.from(files).forEach((file, index) => {\n        if (file.type.startsWith('image/')) {\n          const reader = new FileReader();\n          reader.onload = async (event) => {\n            const dataUrl = event.target?.result as string;\n            const imgEl = new Image();\n            imgEl.src = dataUrl;\n            imgEl.onload = async () => {\n              const formattedSize = file.size > 1024 * 1024\n                ? (file.size / (1024 * 1024)).toFixed(1) + ' MB'\n                : (file.size / 1024).toFixed(0) + ' KB';\n\n              useEditorStore.getState().addUploadedAsset(file.name, dataUrl, formattedSize, file.type, imgEl.naturalWidth || 800, imgEl.naturalHeight || 600);\n              await processDroppedImage(dataUrl, file.name, e, index);\n            };\n          };\n          reader.readAsDataURL(file);\n        }\n      });\n    }\n  };\n\n\n  \n  const handleFitPage = () => {\n    if (!containerRef.current) return;\n    const wRatio = (containerRef.current.clientWidth - 80) / activePage.width;\n    const hRatio = (containerRef.current.clientHeight - 80) / activePage.height;\n    const fitRatio = Math.min(wRatio, hRatio, 1);\n    setZoom(Math.round(fitRatio * 10) / 10);\n    setWorkspacePan({ x: 0, y: 0 });\n    workspacePanRef.current = { x: 0, y: 0 };\n    setIsZoomMenuOpen(false);\n  };\n\n  // handlePanelFileUpload eliminado: ahora el bot\u00F3n \"Subir imagen\" abre el panel flotante (T-20260706-10)\n\n  // Panel: handle canvas background color change\n  // (removido: ahora el panel flotante usa updatePageBgColor directamente)\n\n  // Extraer colores de la imagen activa cuando cambia el objeto o el canvas\n  useEffect(() => {\n    if (activeObject && activeObject.type === 'image') {\n      const imgObj = activeObject as any;\n      const src = imgObj._element?.src || imgObj.src;\n      if (src && (src.startsWith('http') || src.startsWith('data:'))) {\n        extractColorsFromImage(src).then((colors: string[]) => {\n          if (colors && colors.length > 0) setExtractedColors(colors);\n        });\n      }\n    } else if (canvasInstance) {\n      const firstImg = canvasInstance.getObjects().find((o: any) => o.type === 'image') as any;\n      const src = firstImg?._element?.src || firstImg?.src;\n      if (src && (src.startsWith('http') || src.startsWith('data:'))) {\n        extractColorsFromImage(src).then((colors: string[]) => {\n          if (colors && colors.length > 0) setExtractedColors(colors);\n        });\n      }\n    }\n  }, [activeObject, canvasInstance, setExtractedColors]);\n\n  // Upload: stamp into selected pixel layer, or create a content-sized pixel layer\n  // (paint bucket expands to page size when painting outside the image).\n  const handleAddImageLayer = async (url: string, name: string) => {\n    if (!url?.trim()) return;\n    try {\n      const src = await resolveImageSrcForCanvas(url.trim());\n      await useEditorStore.getState().stampImageOntoActivePixelLayer(src, { name });\n    } catch (err) {\n      console.error('Failed to add image layer', err);\n    }\n  };\n\n  // Upload: procesar archivo subido (resuelve cuando la imagen ya est\u00E1 en el lienzo)\n  const processUploadedFile = (file: File): Promise<void> => {\n    if (!canvasInstance) return Promise.resolve();\n    return new Promise((resolve, reject) => {\n      const reader = new FileReader();\n      reader.onerror = () => reject(reader.error ?? new Error('Failed to read file'));\n      reader.onload = (event) => {\n        const dataUrl = event.target?.result as string;\n        const imgEl = new Image();\n        imgEl.onerror = () => reject(new Error('Failed to decode image'));\n        imgEl.onload = () => {\n          void (async () => {\n            try {\n              const width = imgEl.naturalWidth || 800;\n              const height = imgEl.naturalHeight || 600;\n              const formattedSize = file.size > 1024 * 1024\n                ? (file.size / (1024 * 1024)).toFixed(1) + ' MB'\n                : (file.size / 1024).toFixed(0) + ' KB';\n              await addUploadedAsset(file.name, dataUrl, formattedSize, file.type, width, height);\n              await handleAddImageLayer(dataUrl, file.name);\n              resolve();\n            } catch (err) {\n              reject(err);\n            }\n          })();\n        };\n        imgEl.src = dataUrl;\n      };\n      reader.readAsDataURL(file);\n    });\n  };\n\n  // Auto-fit page on dimensions change or on page change\n  useEffect(() => {\n    const timer = setTimeout(() => {\n      handleFitPage();\n    }, 60);\n    return () => clearTimeout(timer);\n  }, [activePageId, activePage.width, activePage.height]);\n\n  useEffect(() => {\n    workspacePanRef.current = workspacePan;\n  }, [workspacePan]);\n\n  const getCanvasOffsetInWorkspace = () => {\n    const el = containerRef.current;\n    if (!el) return { left: 0, top: 0 };\n\n    const cw = activePage.width * zoom;\n    const ch = activePage.height * zoom;\n    const viewportW = el.clientWidth;\n    const viewportH = el.clientHeight;\n\n    return {\n      left: (viewportW - cw) / 2 + workspacePan.x,\n      top: (viewportH - ch) / 2 + workspacePan.y,\n    };\n  };\n\n  // Animation loop\n  useEffect(() => {\n    let animationFrameId: number;\n    let startTime = Date.now();\n    \n    const renderLoop = () => {\n      const canvas = fabricCanvasRef.current;\n      if (canvas) {\n        let needsRender = false;\n        const now = Date.now();\n        const t = (now - startTime) / 1000; // time in seconds\n        \n        canvas.getObjects().forEach((obj: any) => {\n          if (obj.isAnimated && obj.animationType && obj.animationType !== 'none') {\n            needsRender = true;\n            if (!obj._origAnimValues) {\n              obj._origAnimValues = { scaleX: obj.scaleX, scaleY: obj.scaleY, top: obj.top, angle: obj.angle };\n            }\n            \n            switch (obj.animationType) {\n              case 'pulse': {\n                const s = 1 + 0.1 * Math.sin(t * Math.PI * 2);\n                obj.set({\n                  scaleX: obj._origAnimValues.scaleX * s,\n                  scaleY: obj._origAnimValues.scaleY * s\n                });\n                break;\n              }\n              case 'bounce': {\n                const y = -20 * Math.abs(Math.sin(t * Math.PI * 2));\n                obj.set({\n                  top: obj._origAnimValues.top + y\n                });\n                break;\n              }\n              case 'spin': {\n                // To spin around center, we ensure originX and originY are center\n                // But changing origin messes up position if not handled, so we just rotate\n                obj.set({\n                  angle: obj._origAnimValues.angle + (now - startTime) * 0.05\n                });\n                break;\n              }\n            }\n          } else if (obj._origAnimValues) {\n            // Restore if animation was removed\n            obj.set({\n              scaleX: obj._origAnimValues.scaleX,\n              scaleY: obj._origAnimValues.scaleY,\n              top: obj._origAnimValues.top,\n              angle: obj._origAnimValues.angle\n            });\n            delete obj._origAnimValues;\n            needsRender = true;\n          }\n        });\n        \n        if (needsRender) {\n          canvas.requestRenderAll();\n        }\n      }\n      animationFrameId = requestAnimationFrame(renderLoop);\n    };\n    \n    renderLoop();\n    return () => cancelAnimationFrame(animationFrameId);\n  }, []);\n\n  // Redraw rulers\n  useEffect(() => {\n    if (!rulersEnabled) return;\n    const hr = hrulerRef.current;\n    const vr = vrulerRef.current;\n    if (!hr || !vr || !containerRef.current) return;\n    \n    const viewportW = containerRef.current.clientWidth;\n    const viewportH = containerRef.current.clientHeight;\n    \n    const dpr = window.devicePixelRatio || 1;\n    hr.width = viewportW * dpr;\n    hr.height = 20 * dpr;\n    hr.style.width = `${viewportW}px`;\n    hr.style.height = `20px`;\n    \n    vr.width = 20 * dpr;\n    vr.height = viewportH * dpr;\n    vr.style.width = `20px`;\n    vr.style.height = `${viewportH}px`;\n    \n    const hctx = hr.getContext('2d');\n    const vctx = vr.getContext('2d');\n    if (!hctx || !vctx) return;\n    \n    hctx.scale(dpr, dpr);\n    vctx.scale(dpr, dpr);\n    \n    // Fill backgrounds\n    hctx.fillStyle = '#18181b'; // bg-dark-900\n    hctx.fillRect(0, 0, viewportW, 20);\n    vctx.fillStyle = '#18181b';\n    vctx.fillRect(0, 0, 20, viewportH);\n    \n    const offset = getCanvasOffsetInWorkspace();\n    const { tick, label } = getRulerStep(zoom);\n    \n    hctx.strokeStyle = '#3f3f46'; // dark-700\n    hctx.fillStyle = '#a1a1aa'; // zinc-400\n    hctx.font = '9px monospace';\n    \n    // Draw horizontal ticks\n    const startX = Math.floor((-offset.left) / zoom / tick) * tick;\n    const endX = Math.ceil((viewportW - offset.left) / zoom / tick) * tick;\n    \n    for (let x = startX; x <= endX; x += tick) {\n      const px = x * zoom + offset.left;\n      if (px < 20) continue;\n      \n      hctx.beginPath();\n      hctx.moveTo(px, 20);\n      if (x % label === 0) {\n        hctx.lineTo(px, 8);\n        hctx.fillText(x.toString(), px + 3, 15);\n      } else {\n        hctx.lineTo(px, 14);\n      }\n      hctx.stroke();\n    }\n    \n    // Draw vertical ticks\n    vctx.strokeStyle = '#3f3f46';\n    vctx.fillStyle = '#a1a1aa';\n    vctx.font = '9px monospace';\n    \n    const startY = Math.floor((-offset.top) / zoom / tick) * tick;\n    const endY = Math.ceil((viewportH - offset.top) / zoom / tick) * tick;\n    \n    for (let y = startY; y <= endY; y += tick) {\n      const py = y * zoom + offset.top;\n      if (py < 20) continue;\n      \n      vctx.beginPath();\n      vctx.moveTo(20, py);\n      if (y % label === 0) {\n        vctx.lineTo(8, py);\n        vctx.save();\n        vctx.translate(15, py + 3);\n        vctx.rotate(-Math.PI / 2);\n        vctx.fillText(y.toString(), 0, 0);\n        vctx.restore();\n      } else {\n        vctx.lineTo(14, py);\n      }\n      vctx.stroke();\n    }\n  }, [zoom, workspacePan, activePage.width, activePage.height, rulersEnabled]);\n\n  const finishCropping = () => {\n    if (!croppingObj || !canvasInstance) return;\n    const { image, shape, bezelObjects } = croppingObj as any;\n    \n    if (bezelObjects && bezelObjects.length > 0) {\n      canvasInstance.discardActiveObject();\n      canvasInstance.remove(image);\n      canvasInstance.remove(shape);\n\n      shape.set({\n        opacity: 1,\n        selectable: false,\n        evented: false,\n      });\n      shape.absolutePositioned = true;\n\n      image.set({\n        clipPath: shape,\n      });\n\n      // Recalculate bezel objects coordinates relative to the new group\n      // Grouping in Fabric automatically sets the sub-objects coordinates relative to center,\n      // so we just add the objects back to a new Group.\n      bezelObjects.forEach((o: any) => {\n        o.set({\n          selectable: false,\n          evented: false,\n        });\n      });\n\n      const newFrameGroup = new Group([...bezelObjects, image], {\n        name: 'canva-frame-clipped',\n        clippedPlaceholder: shape,\n      } as any);\n\n      canvasInstance.add(newFrameGroup);\n      canvasInstance.setActiveObject(newFrameGroup);\n      canvasInstance.requestRenderAll();\n    } else {\n      shape.set({\n        opacity: 1,\n        selectable: false,\n        evented: false,\n      });\n      shape.absolutePositioned = true;\n      \n      image.set({\n        clipPath: shape,\n      });\n      \n      canvasInstance.remove(shape);\n      canvasInstance.setActiveObject(image);\n      canvasInstance.requestRenderAll();\n    }\n    \n    setCroppingObj(null);\n    saveHistoryState();\n  };\n\n  const handleContextMenu = (e: React.MouseEvent) => {\n    e.preventDefault();\n    if (isBrushRadiusTool(activeTool)) {\n      setContextMenu((prev) => ({ ...prev, visible: false }));\n      setRadiusPopup({ x: e.clientX, y: e.clientY });\n      return;\n    }\n    const canvas = canvasInstance || fabricCanvasRef.current;\n    if (!canvas) return;\n\n    const target = canvas.findTarget(e.nativeEvent);\n\n    if (target) {\n      canvas.setActiveObject(target as any);\n      canvas.requestRenderAll();\n      setActiveObject(target as any);\n    }\n\n    setContextMenu({\n      x: e.clientX,\n      y: e.clientY,\n      visible: true,\n      targetObject: (target as any) || null,\n    });\n  };\n\n  const handleDuplicate = (obj: any) => {\n    if (!canvasInstance || !obj) return;\n    obj.clone().then((clonedObj: any) => {\n      canvasInstance.discardActiveObject();\n      clonedObj.set({\n        left: clonedObj.left + 15,\n        top: clonedObj.top + 15,\n        evented: true,\n      });\n\n      if (obj.name) {\n        clonedObj.name = obj.name;\n      }\n\n      if (getType(clonedObj) === 'activeselection') {\n        clonedObj.canvas = canvasInstance;\n        clonedObj.forEachObject((o: any) => {\n          canvasInstance.add(o);\n        });\n        clonedObj.setCoords();\n      } else {\n        canvasInstance.add(clonedObj);\n      }\n      canvasInstance.setActiveObject(clonedObj);\n      canvasInstance.requestRenderAll();\n      setActiveObject(clonedObj);\n      setLayers(canvasInstance.getObjects().slice().reverse());\n      saveHistoryState();\n    });\n  };\n\n  const handleToggleLock = (obj: any) => {\n    if (!canvasInstance || !obj) return;\n    const isLocked = !obj.lockMovementX;\n    obj.set({\n      lockMovementX: isLocked,\n      lockMovementY: isLocked,\n      lockScalingX: isLocked,\n      lockScalingY: isLocked,\n      lockRotation: isLocked,\n      hasControls: false,\n      hasBorders: false,\n      selectable: !isLocked,\n      borderColor: 'transparent',\n      cornerColor: 'transparent',\n      cornerStrokeColor: 'transparent',\n    });\n    obj.locked = isLocked;\n    canvasInstance.setActiveObject(obj);\n    canvasInstance.requestRenderAll();\n    setActiveObject(obj);\n    saveHistoryState();\n  };\n\n  const handleCopy = (obj: any) => {\n    if (!obj) return;\n    obj.clone(['linkId']).then((cloned: any) => {\n      clipboard = cloned;\n    });\n  };\n\n  const handlePaste = () => {\n    if (!canvasInstance || !clipboard) return;\n    clipboard.clone(['linkId']).then((clonedObj: any) => {\n      canvasInstance.discardActiveObject();\n      clonedObj.set({\n        left: clonedObj.left + 15,\n        top: clonedObj.top + 15,\n        evented: true,\n      });\n      if (getType(clonedObj) === 'activeselection') {\n        clonedObj.canvas = canvasInstance;\n        clonedObj.forEachObject((obj: any) => {\n          obj.set('id', `obj-${Date.now()}-${Math.random().toString(36).substring(2,9)}`);\n          canvasInstance.add(obj);\n        });\n        clonedObj.setCoords();\n      } else {\n        clonedObj.set('id', `obj-${Date.now()}-${Math.random().toString(36).substring(2,9)}`);\n        canvasInstance.add(clonedObj);\n      }\n      canvasInstance.setActiveObject(clonedObj);\n      canvasInstance.requestRenderAll();\n      setActiveObject(clonedObj);\n      setLayers(canvasInstance.getObjects().slice().reverse());\n      saveHistoryState();\n    });\n  };\n\n  const handleCopyStyle = (obj: any) => {\n    if (!obj) return;\n    const style: any = {\n      type: getType(obj),\n      opacity: obj.opacity,\n    };\n    if (['rect', 'circle', 'triangle', 'ellipse', 'polygon', 'path'].includes(getType(obj))) {\n      style.fill = obj.fill;\n      style.stroke = obj.stroke;\n      style.strokeWidth = obj.strokeWidth;\n      style.strokeDashArray = obj.strokeDashArray;\n      style.shadow = obj.shadow ? new Shadow({\n        color: obj.shadow.color,\n        blur: obj.shadow.blur,\n        offsetX: obj.shadow.offsetX,\n        offsetY: obj.shadow.offsetY,\n      }) : null;\n    }\n    if (getType(obj) === 'textbox' || getType(obj) === 'text') {\n      style.fill = obj.fill;\n      style.stroke = obj.stroke;\n      style.strokeWidth = obj.strokeWidth;\n      style.fontFamily = obj.fontFamily;\n      style.fontSize = obj.fontSize;\n      style.fontWeight = obj.fontWeight;\n      style.fontStyle = obj.fontStyle;\n      style.underline = obj.underline;\n      style.charSpacing = obj.charSpacing;\n      style.lineHeight = obj.lineHeight;\n      style.shadow = obj.shadow ? new Shadow({\n        color: obj.shadow.color,\n        blur: obj.shadow.blur,\n        offsetX: obj.shadow.offsetX,\n        offsetY: obj.shadow.offsetY,\n      }) : null;\n      style.curvature = obj.curvature;\n    }\n    useEditorStore.getState().setCopiedStyle(style);\n  };\n\n  const handlePasteStyle = (obj: any) => {\n    const copiedStyle = useEditorStore.getState().copiedStyle;\n    if (!obj || !copiedStyle) return;\n    const settings: any = {};\n    if (copiedStyle.opacity !== undefined) settings.opacity = copiedStyle.opacity;\n\n    if (['rect', 'circle', 'triangle', 'ellipse', 'polygon', 'path'].includes(getType(obj))) {\n      if (copiedStyle.fill !== undefined) settings.fill = copiedStyle.fill;\n      if (copiedStyle.stroke !== undefined) settings.stroke = copiedStyle.stroke;\n      if (copiedStyle.strokeWidth !== undefined) settings.strokeWidth = copiedStyle.strokeWidth;\n      if (copiedStyle.strokeDashArray !== undefined) settings.strokeDashArray = copiedStyle.strokeDashArray;\n      if (copiedStyle.shadow !== undefined) settings.shadow = copiedStyle.shadow;\n    }\n\n    if (getType(obj) === 'textbox' || getType(obj) === 'text') {\n      if (copiedStyle.fill !== undefined) settings.fill = copiedStyle.fill;\n      if (copiedStyle.stroke !== undefined) settings.stroke = copiedStyle.stroke;\n      if (copiedStyle.strokeWidth !== undefined) settings.strokeWidth = copiedStyle.strokeWidth;\n      if (copiedStyle.fontFamily !== undefined) settings.fontFamily = copiedStyle.fontFamily;\n      if (copiedStyle.fontSize !== undefined) settings.fontSize = copiedStyle.fontSize;\n      if (copiedStyle.fontWeight !== undefined) settings.fontWeight = copiedStyle.fontWeight;\n      if (copiedStyle.fontStyle !== undefined) settings.fontStyle = copiedStyle.fontStyle;\n      if (copiedStyle.underline !== undefined) settings.underline = copiedStyle.underline;\n      if (copiedStyle.charSpacing !== undefined) settings.charSpacing = copiedStyle.charSpacing;\n      if (copiedStyle.lineHeight !== undefined) settings.lineHeight = copiedStyle.lineHeight;\n      if (copiedStyle.shadow !== undefined) settings.shadow = copiedStyle.shadow;\n      if (copiedStyle.curvature !== undefined) {\n        settings.curvature = copiedStyle.curvature;\n        updateTextPath(obj, copiedStyle.curvature);\n      }\n    }\n\n    obj.set(settings);\n    canvasInstance?.requestRenderAll();\n    saveHistoryState();\n  };\n\n  const handleBringToFront = (obj: any) => {\n    if (!canvasInstance || !obj) return;\n    canvasInstance.bringObjectToFront(obj);\n    canvasInstance.requestRenderAll();\n    setLayers(canvasInstance.getObjects().slice().reverse());\n    saveHistoryState();\n  };\n\n  const handleSendToBack = (obj: any) => {\n    if (!canvasInstance || !obj) return;\n    canvasInstance.sendObjectToBack(obj);\n    canvasInstance.requestRenderAll();\n    setLayers(canvasInstance.getObjects().slice().reverse());\n    saveHistoryState();\n  };\n\n  const handleBringForward = (obj: any) => {\n    if (!canvasInstance || !obj) return;\n    canvasInstance.bringObjectForward(obj);\n    canvasInstance.requestRenderAll();\n    setLayers(canvasInstance.getObjects().slice().reverse());\n    saveHistoryState();\n  };\n\n  const handleSendBackward = (obj: any) => {\n    if (!canvasInstance || !obj) return;\n    canvasInstance.sendObjectBackwards(obj);\n    canvasInstance.requestRenderAll();\n    setLayers(canvasInstance.getObjects().slice().reverse());\n    saveHistoryState();\n  };\n\n  const handleDelete = async (obj: any) => {\n    if (!canvasInstance || !obj) return;\n    const store = useEditorStore.getState();\n    const isMulti = getType(obj) === 'activeselection';\n    const count = isMulti ? (obj as { size?: () => number }).size?.() ?? 2 : 1;\n    const deletingAll =\n      (isMulti && count >= canvasInstance.getObjects().length) ||\n      (!isMulti && isSoleCanvasLayer(canvasInstance));\n\n    // Sole layer already empty \u2014 nothing to clear.\n    if (!isMulti && isSoleCanvasLayer(canvasInstance) && isPixelLayer(obj) && !pixelLayerHasContent(obj as PixelLayerImage)) {\n      store.addToast(t.layers.cannotDeleteLastLayer, 'warning');\n      return;\n    }\n\n    const label =\n      (obj as { name?: string }).name ||\n      getType(obj) ||\n      t.layers.tooltip.delete;\n    const ok = await dialog.confirm(\n      isMulti\n        ? t.slides.slideCanvas.deleteSelectionBody(count)\n        : t.layers.deleteLayerBody(label),\n      {\n        title: t.layers.deleteLayerTitle,\n        variant: 'danger',\n        confirmText: t.layers.deleteLayerConfirm,\n        cancelText: t.common.cancel,\n      },\n    );\n    if (!ok) return;\n    if (isMulti) {\n      if (deletingAll) {\n        const objs = canvasInstance.getObjects().slice();\n        const keep = objs[0];\n        for (let i = 1; i < objs.length; i++) {\n          const o = objs[i];\n          if (o) canvasInstance.remove(o);\n        }\n        canvasInstance.discardActiveObject();\n        if (keep) {\n          const result = store.deleteLayerOrClear(keep);\n          if (result === 'blocked') {\n            store.addToast(t.layers.cannotDeleteLastLayer, 'warning');\n          }\n        }\n        return;\n      }\n      (obj as any).forEachObject((o: any) => {\n        canvasInstance.remove(o);\n      });\n      canvasInstance.discardActiveObject();\n    } else {\n      const result = store.deleteLayerOrClear(obj);\n      if (result === 'blocked') {\n        store.addToast(t.layers.cannotDeleteLastLayer, 'warning');\n      }\n      return;\n    }\n    canvasInstance.requestRenderAll();\n    setActiveObject(null);\n    setLayers(canvasInstance.getObjects().slice().reverse());\n    saveHistoryState();\n  };\n\n  const handleExportSelection = (obj: any) => {\n    if (!canvasInstance || !obj) return;\n    try {\n      const dataUrl = obj.toDataURL({\n        format: 'png',\n        quality: 0.95,\n        multiplier: 2,\n      });\n\n      const link = document.createElement('a');\n      link.href = dataUrl;\n      link.download = `${obj.type || 'layer'}-${Date.now()}.png`;\n      link.click();\n    } catch (err) {\n      console.error(\"Export selection failed:\", err);\n    }\n  };\n  const handleTextOnPath = (selection: any) => {\n    if (!selection || selection.type !== 'activeselection') return;\n    \n    const objects = selection.getObjects();\n    const textObj = objects.find((o: any) => o.type === 'textbox' || o.type === 'itext' || o.type === 'text');\n    const pathObj = objects.find((o: any) => o.type === 'path');\n\n    if (textObj && pathObj) {\n      textObj.set({\n        path: pathObj,\n        pathAlign: 'center',\n        pathSide: 'left'\n      });\n      \n      pathObj.set({\n        visible: false,\n        evented: false,\n        selectable: false\n      });\n      \n      const canvas = fabricCanvasRef.current;\n      if (canvas) {\n        canvas.discardActiveObject();\n        canvas.setActiveObject(textObj);\n        canvas.requestRenderAll();\n        saveHistoryState();\n      }\n    }\n  };\n\n  const handleTextMask = (selection: any) => {\n    if (!selection || selection.type !== 'activeselection') return;\n    \n    const objects = selection.getObjects();\n    const textObj = objects.find((o: any) => o.type === 'textbox' || o.type === 'itext' || o.type === 'text');\n    const imageObj = objects.find((o: any) => o.type === 'image');\n\n    if (textObj && imageObj) {\n      textObj.set({\n        globalCompositeOperation: 'destination-in'\n      });\n      \n      const canvas = fabricCanvasRef.current;\n      if (canvas) {\n        // We group them so the mask applies locally\n        selection.toGroup();\n        canvas.requestRenderAll();\n        saveHistoryState();\n      }\n    }\n  };\n\n  const canCropImage = canUseImageCropTool(activeObject, canvasInstance);\n\n  return (\n    <div className=\"flex flex-1 flex-col min-w-0 min-h-0 h-full overflow-hidden bg-dark-950\">\n      \n      {/* Docked bottom tool bar \u2014 same shell pattern as slides/audio */}\n      <aside className=\"order-2 z-30 flex w-full shrink-0 items-center justify-between gap-2 border-t border-panel-border bg-panel px-2 py-1.5 select-none\">\n        <div className=\"flex min-w-0 flex-1 items-center gap-1 overflow-x-auto\">\n        {/* 1. Cursor / puntero \u2014 solo selecci\u00F3n de objetos (sin subherramientas de lazo) */}\n        <button\n          type=\"button\"\n          onClick={() => {\n            setActiveTool('select');\n            setIsLassoMenuOpen(false);\n            setIsEraserMenuOpen(false);\n            dismissToolPanels();\n          }}\n          className={`h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors ${\n            activeTool === 'select' || activeTool === 'move-only' || activeTool === 'rotate-only'\n              ? 'bg-[var(--we-accent)] text-white font-bold'\n              : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n          }`}\n          aria-label={t.canvas.toolstrip.select}\n          aria-pressed={activeTool === 'select' || activeTool === 'move-only' || activeTool === 'rotate-only'}\n        >\n          <MousePointer size={16} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">\n            {t.canvas.toolstrip.select}\n          </TextBody>\n        </button>\n\n        {/* 2. Mano (pan) */}\n        <button\n          onClick={() => setActiveTool('pan')}\n          className={`h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors ${\n            activeTool === 'pan'\n              ? 'bg-[var(--we-accent)] text-white font-bold'\n              : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n          }`}\n          aria-label=\"Mano / Desplazar\"\n          aria-pressed={activeTool === 'pan'}\n        >\n          <Hand size={16} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">{t.canvas.toolstrip.hand}</TextBody>\n        </button>\n\n        {/* Separador */}\n        <div className=\"w-px h-6 bg-panel-border mx-1\" aria-hidden />\n\n        {/* 3. Texto */}\n        <button\n          onClick={() => setActiveTool('text')}\n          className={`h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors ${\n            activeTool === 'text'\n              ? 'bg-[var(--we-accent)] text-white font-bold'\n              : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n          }`}\n          aria-label=\"Texto\"\n          aria-pressed={activeTool === 'text'}\n        >\n          <Type size={16} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">{t.canvas.toolstrip.text}</TextBody>\n        </button>\n\n        {/* 4. Bote de pintura (relleno tipo Photoshop) */}\n        <button\n          ref={paintBucketAnchorRef}\n          onClick={() => {\n            const nextTool = activeTool === 'paint-bucket' ? 'select' : 'paint-bucket';\n            setActiveTool(nextTool);\n            if (nextTool === 'paint-bucket') dismissToolPanels();\n          }}\n          className={`h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors ${\n            activeTool === 'paint-bucket'\n              ? 'bg-[var(--we-accent)] text-white font-bold'\n              : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n          }`}\n          aria-label={t.canvas.toolstrip.paintBucketAria}\n          aria-pressed={activeTool === 'paint-bucket'}\n        >\n          <PaintBucket size={16} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">{t.canvas.toolstrip.paintBucket}</TextBody>\n        </button>\n\n        {/* 5. Pincel */}\n        <button\n          type=\"button\"\n          ref={brushAnchorRef}\n          onClick={() => {\n            const nextTool = activeTool === 'brush' ? 'select' : 'brush';\n            setActiveTool(nextTool);\n            setIsEraserMenuOpen(false);\n            setIsLassoMenuOpen(false);\n            if (nextTool === 'brush') dismissToolPanels();\n          }}\n          className={`h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors ${\n            activeTool === 'brush'\n              ? 'bg-[var(--we-accent)] text-white font-bold'\n              : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n          }`}\n          aria-label={t.canvas.toolstrip.brush}\n          aria-pressed={activeTool === 'brush'}\n        >\n          <Brush size={16} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">\n            {t.canvas.toolstrip.brush}\n          </TextBody>\n        </button>\n\n        {/* 5b. Tap\u00F3n de clonar */}\n        <button\n          type=\"button\"\n          ref={cloneStampAnchorRef}\n          onClick={() => {\n            const nextTool = activeTool === 'clone-stamp' ? 'select' : 'clone-stamp';\n            setActiveTool(nextTool);\n            if (nextTool === 'clone-stamp') dismissToolPanels();\n          }}\n          className={`h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors ${\n            activeTool === 'clone-stamp'\n              ? 'bg-[var(--we-accent)] text-white font-bold'\n              : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n          }`}\n          aria-label={t.canvas.toolstrip.cloneStamp}\n          aria-pressed={activeTool === 'clone-stamp'}\n        >\n          <Stamp size={16} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">{t.canvas.toolstrip.cloneStamp}</TextBody>\n        </button>\n\n        {/* 5c. Varita m\u00E1gica */}\n        <button\n          type=\"button\"\n          ref={wandAnchorRef}\n          onClick={() => {\n            const nextTool = activeTool === 'magic-wand' ? 'select' : 'magic-wand';\n            setActiveTool(nextTool);\n            if (nextTool === 'magic-wand') dismissToolPanels();\n          }}\n          className={`h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors ${\n            activeTool === 'magic-wand'\n              ? 'bg-[var(--we-accent)] text-white font-bold'\n              : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n          }`}\n          aria-label={t.canvas.toolstrip.magicWand}\n          aria-pressed={activeTool === 'magic-wand'}\n        >\n          <Wand2 size={16} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">{t.canvas.toolstrip.magicWand}</TextBody>\n        </button>\n\n        {/* 5d. Lazo \u2014 rectangular / circular / libre + lazos de p\u00EDxeles */}\n        <div className=\"relative\" ref={lassoMenuAnchorRef}>\n          <button\n            type=\"button\"\n            ref={lassoAnchorRef}\n            onClick={() => {\n              const nextTool = isLassoGroupTool(activeTool) ? 'select' : lassoGroupTool;\n              setActiveTool(nextTool);\n              setIsLassoMenuOpen(false);\n              setIsEraserMenuOpen(false);\n              if (isLassoGroupTool(nextTool)) dismissToolPanels();\n            }}\n            className={`h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors ${\n              isLassoGroupTool(activeTool)\n                ? 'bg-[var(--we-accent)] text-white font-bold'\n                : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n            }`}\n            aria-label={t.canvas.toolstrip.lassoGroup}\n            aria-pressed={isLassoGroupTool(activeTool)}\n          >\n            {lassoGroupTool === 'select-ellipse' ? (\n              <CircleDashed size={16} />\n            ) : lassoGroupTool === 'select-rect' ? (\n              <SquareDashed size={16} />\n            ) : lassoGroupTool === 'polygon-lasso' ? (\n              <Waypoints size={16} />\n            ) : (\n              <Lasso size={16} />\n            )}\n            {!isLassoMenuOpen && (\n              <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">\n                {t.canvas.toolstrip.lassoGroup}\n              </TextBody>\n            )}\n          </button>\n          <button\n            type=\"button\"\n            className=\"absolute bottom-0 right-0 z-10 flex h-3.5 w-3.5 items-center justify-center rounded-sm text-current opacity-80 hover:opacity-100 hover:bg-black/30\"\n            aria-label={t.canvas.toolstrip.lassoMenu}\n            aria-expanded={isLassoMenuOpen}\n            onClick={(e) => {\n              e.stopPropagation();\n              setIsLassoMenuOpen((open) => !open);\n              setIsEraserMenuOpen(false);\n              dismissToolPanels();\n            }}\n            onPointerDown={(e) => {\n              e.stopPropagation();\n              if (lassoMenuHoldTimer.current != null) {\n                window.clearTimeout(lassoMenuHoldTimer.current);\n              }\n              lassoMenuHoldTimer.current = window.setTimeout(() => {\n                setIsLassoMenuOpen(true);\n                setIsEraserMenuOpen(false);\n                dismissToolPanels();\n                lassoMenuHoldTimer.current = null;\n              }, 320);\n            }}\n            onPointerUp={() => {\n              if (lassoMenuHoldTimer.current != null) {\n                window.clearTimeout(lassoMenuHoldTimer.current);\n                lassoMenuHoldTimer.current = null;\n              }\n            }}\n            onPointerLeave={() => {\n              if (lassoMenuHoldTimer.current != null) {\n                window.clearTimeout(lassoMenuHoldTimer.current);\n                lassoMenuHoldTimer.current = null;\n              }\n            }}\n          >\n            <ChevronDown size={8} />\n          </button>\n          <ViewportPortalMenu\n            open={isLassoMenuOpen}\n            onClose={() => setIsLassoMenuOpen(false)}\n            anchorRef={lassoMenuAnchorRef}\n            prefer=\"above\"\n            zIndex={40}\n            className=\"flex w-56 flex-col gap-0.5 rounded-xl border border-panel-border bg-panel p-1.5 shadow-2xl\"\n          >\n            {(\n              [\n                {\n                  id: 'select-rect' as const,\n                  label: t.canvas.toolstrip.selectRect,\n                  icon: SquareDashed,\n                },\n                {\n                  id: 'select-ellipse' as const,\n                  label: t.canvas.toolstrip.selectEllipse,\n                  icon: CircleDashed,\n                },\n                {\n                  id: 'select-lasso' as const,\n                  label: t.canvas.toolstrip.selectLasso,\n                  icon: Lasso,\n                },\n                {\n                  id: 'pixel-lasso' as const,\n                  label: t.canvas.toolstrip.pixelLasso,\n                  icon: Lasso,\n                },\n                {\n                  id: 'polygon-lasso' as const,\n                  label: t.canvas.toolstrip.polygonLasso,\n                  icon: Waypoints,\n                },\n              ] as const\n            ).map(({ id, label, icon: Icon }) => (\n              <button\n                key={id}\n                type=\"button\"\n                onClick={() => {\n                  setLassoGroupTool(id);\n                  setActiveTool(id);\n                  setIsLassoMenuOpen(false);\n                  dismissToolPanels();\n                }}\n                className={`flex items-center gap-2.5 px-2 py-1.5 rounded-lg text-left text-xs font-semibold cursor-pointer transition-colors ${\n                  activeTool === id\n                    ? 'bg-[var(--we-accent)] text-white'\n                    : 'text-white/80 hover:bg-[var(--we-accent-muted)]'\n                }`}\n              >\n                <Icon size={14} />\n                <span>{label}</span>\n              </button>\n            ))}\n          </ViewportPortalMenu>\n        </div>\n\n        {/* 5e. Borrador \u2014 p\u00EDxeles + borrador m\u00E1gico */}\n        <div className=\"relative\" ref={eraserMenuAnchorRef}>\n          <button\n            type=\"button\"\n            ref={eraserAnchorRef}\n            onClick={() => {\n              const nextTool = isEraserGroupTool(activeTool) ? 'select' : eraserGroupTool;\n              setActiveTool(nextTool);\n              setIsEraserMenuOpen(false);\n              setIsLassoMenuOpen(false);\n              if (isEraserGroupTool(nextTool)) dismissToolPanels();\n            }}\n            className={`h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors ${\n              isEraserGroupTool(activeTool)\n                ? 'bg-[var(--we-accent)] text-white font-bold'\n                : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n            }`}\n            aria-label={\n              eraserGroupTool === 'magic-eraser'\n                ? t.canvas.toolstrip.magicEraser\n                : t.canvas.toolstrip.eraser\n            }\n            aria-pressed={isEraserGroupTool(activeTool)}\n          >\n            {eraserGroupTool === 'magic-eraser' ? (\n              <PencilSparkles size={16} />\n            ) : (\n              <Eraser size={16} />\n            )}\n            {!isEraserMenuOpen && (\n              <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">\n                {eraserGroupTool === 'magic-eraser'\n                  ? t.canvas.toolstrip.magicEraser\n                  : t.canvas.toolstrip.eraser}\n              </TextBody>\n            )}\n          </button>\n          <button\n            type=\"button\"\n            className=\"absolute bottom-0 right-0 z-10 flex h-3.5 w-3.5 items-center justify-center rounded-sm text-current opacity-80 hover:opacity-100 hover:bg-black/30\"\n            aria-label={t.canvas.toolstrip.eraserMenu}\n            aria-expanded={isEraserMenuOpen}\n            onClick={(e) => {\n              e.stopPropagation();\n              setIsEraserMenuOpen((open) => !open);\n              setIsLassoMenuOpen(false);\n              dismissToolPanels();\n            }}\n            onPointerDown={(e) => {\n              e.stopPropagation();\n              if (eraserMenuHoldTimer.current != null) {\n                window.clearTimeout(eraserMenuHoldTimer.current);\n              }\n              eraserMenuHoldTimer.current = window.setTimeout(() => {\n                setIsEraserMenuOpen(true);\n                setIsLassoMenuOpen(false);\n                dismissToolPanels();\n                eraserMenuHoldTimer.current = null;\n              }, 320);\n            }}\n            onPointerUp={() => {\n              if (eraserMenuHoldTimer.current != null) {\n                window.clearTimeout(eraserMenuHoldTimer.current);\n                eraserMenuHoldTimer.current = null;\n              }\n            }}\n            onPointerLeave={() => {\n              if (eraserMenuHoldTimer.current != null) {\n                window.clearTimeout(eraserMenuHoldTimer.current);\n                eraserMenuHoldTimer.current = null;\n              }\n            }}\n          >\n            <ChevronDown size={8} />\n          </button>\n          <ViewportPortalMenu\n            open={isEraserMenuOpen}\n            onClose={() => setIsEraserMenuOpen(false)}\n            anchorRef={eraserMenuAnchorRef}\n            prefer=\"above\"\n            zIndex={40}\n            className=\"flex w-52 flex-col gap-0.5 rounded-xl border border-panel-border bg-panel p-1.5 shadow-2xl\"\n          >\n            {(\n              [\n                { id: 'eraser' as const, label: t.canvas.toolstrip.eraser, icon: Eraser },\n                {\n                  id: 'magic-eraser' as const,\n                  label: t.canvas.toolstrip.magicEraser,\n                  icon: PencilSparkles,\n                },\n              ] as const\n            ).map(({ id, label, icon: Icon }) => (\n              <button\n                key={id}\n                type=\"button\"\n                onClick={() => {\n                  setEraserGroupTool(id);\n                  setActiveTool(id);\n                  setIsEraserMenuOpen(false);\n                  dismissToolPanels();\n                }}\n                className={`flex items-center gap-2.5 px-2 py-1.5 rounded-lg text-left text-xs font-semibold cursor-pointer transition-colors ${\n                  activeTool === id\n                    ? 'bg-[var(--we-accent)] text-white'\n                    : 'text-white/80 hover:bg-[var(--we-accent-muted)]'\n                }`}\n              >\n                <Icon size={14} />\n                <span>{label}</span>\n              </button>\n            ))}\n          </ViewportPortalMenu>\n        </div>\n\n        {/* 6. Figuras (abre panel flotante con tabs Figuras/Formas) */}\n        <div className=\"relative\">\n          <button\n            onClick={() => {\n              toggleActiveToolPanel('shapes');;;;;\n            }}\n            className={`h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors ${\n              (activeToolPanel === 'shapes') || ['rect','rounded-rect','circle','ellipse','triangle','line','star','polygon','arrow','speech-bubble','heart','cross','custom-shape'].includes(activeTool)\n                ? 'bg-[var(--we-accent)] text-white font-bold'\n                : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n            }`}\n            aria-label={t.canvas.toolstrip.shapes}\n            aria-expanded={(activeToolPanel === 'shapes')}\n            ref={shapesAnchorRef}\n          >\n            <ShapesIcon size={16} />\n            <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">{t.canvas.toolstrip.shapes}</TextBody>\n          </button>\n        </div>\n\n        {/* Frames & mockups \u2014 hidden until the panel is redesigned */}\n\n        {/* Separador */}\n        <div className=\"w-px h-6 bg-panel-border mx-1\" aria-hidden />\n\n        {/* 6d. AI Studio */}\n        <div className=\"relative\">\n          <button\n            onClick={() => {\n              toggleActiveToolPanel('ai');\n              setIsTextPanelOpen(false);\n              // Drop stale errors from other tools (magic eraser, etc.).\n              setAiStudioError(null);\n            }}\n            className={`h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors ${\n              (activeToolPanel === 'ai')\n                ? 'bg-[var(--we-accent)] text-white font-bold'\n                : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n            }`}\n            aria-label={t.canvas.toolstrip.aiStudio}\n            aria-expanded={(activeToolPanel === 'ai')}\n            ref={aiAnchorRef}\n          >\n            <Sparkles size={16} />\n            <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">{t.canvas.toolstrip.aiStudio}</TextBody>\n          </button>\n        </div>\n\n        {/* Separador */}\n        <div className=\"w-px h-6 bg-panel-border mx-1\" aria-hidden />\n\n        {/* 7. Subir imagen (abre panel flotante de subida) */}\n        <div className=\"relative\">\n          <button\n            onClick={() => {\n              toggleActiveToolPanel('upload');;;;;;\n            }}\n            className={`h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors ${\n              (activeToolPanel === 'upload')\n                ? 'bg-[var(--we-accent)] text-white font-bold'\n                : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n            }`}\n            aria-label={t.canvas.toolstrip.upload}\n            aria-expanded={(activeToolPanel === 'upload')}\n            ref={uploadAnchorRef}\n          >\n            <ImageUp size={16} />\n            <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">{t.canvas.toolstrip.upload}</TextBody>\n          </button>\n        </div>\n\n        {/* Recortar imagen \u2014 requiere una imagen seleccionada */}\n        <button\n          type=\"button\"\n          disabled={!canCropImage && activeTool !== 'crop'}\n          onClick={() => {\n            if (!canCropImage && activeTool !== 'crop') return;\n            dismissToolPanels();\n            setActiveTool((prev) => (prev === 'crop' ? 'select' : 'crop'));\n          }}\n          className={`h-9 w-9 rounded-md flex items-center justify-center relative transition-colors ${\n            !canCropImage && activeTool !== 'crop'\n              ? 'opacity-35 cursor-not-allowed text-white/40'\n              : activeTool === 'crop'\n                ? 'bg-[var(--we-accent)] text-white font-bold cursor-pointer'\n                : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold cursor-pointer'\n          }`}\n          aria-label={t.canvas.toolstrip.crop}\n          aria-pressed={activeTool === 'crop'}\n        >\n          <SquareBottomDashedScissors size={16} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">{canCropImage || activeTool === 'crop'\n              ? t.canvas.toolstrip.crop\n              : t.canvas.toolstrip.cropDisabled}</TextBody>\n        </button>\n\n        {/* Separador */}\n        <div className=\"w-px h-6 bg-panel-border mx-1\" aria-hidden />\n\n        {/* 9. Columnas (abre panel flotante de grid) */}\n        <button\n          onClick={() => {\n            toggleActiveToolPanel('grid');;\n          }}\n          className={`h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors ${\n            (activeToolPanel === 'grid') || layoutGridEnabled\n              ? 'bg-[var(--we-accent)] text-white font-bold'\n              : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n          }`}\n          aria-label={t.canvas.toolstrip.gridAria}\n          aria-expanded={(activeToolPanel === 'grid')}\n          aria-pressed={(activeToolPanel === 'grid') || layoutGridEnabled}\n          ref={gridAnchorRef}\n        >\n          <LayoutGrid size={16} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">{t.canvas.toolstrip.grid}</TextBody>\n        </button>\n\n        {/* 10. Reglas (mostrar/ocultar) */}\n        <button\n          onClick={() => setRulersEnabled(!rulersEnabled)}\n          className={`h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors ${\n            rulersEnabled\n              ? 'bg-[var(--we-accent)] text-white font-bold'\n              : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n          }`}\n          aria-label={rulersEnabled ? t.canvas.toolstrip.rulersAriaHide : t.canvas.toolstrip.rulersAriaShow}\n          aria-pressed={rulersEnabled}\n        >\n          <Ruler size={16} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">{rulersEnabled ? t.canvas.toolstrip.hideRulers : t.canvas.toolstrip.showRulers}</TextBody>\n        </button>\n\n        {/* 11. Simulador de daltonismo (dropdown vertical hacia arriba) */}\n        <div className=\"relative\">\n          <button\n            onClick={() => {\n              toggleActiveToolPanel('colorblind');\n\n\n            }}\n            className={`h-9 w-9 rounded-md flex items-center justify-center cursor-pointer relative transition-colors ${\n              (activeToolPanel === 'colorblind') || colorBlindnessMode !== 'normal'\n                ? 'bg-[var(--we-accent)] text-white font-bold'\n                : 'text-white/70 hover:text-white hover:bg-[var(--we-accent-muted)] font-semibold'\n            }`}\n            aria-label={t.canvas.toolstrip.colorblindAria}\n            aria-expanded={(activeToolPanel === 'colorblind')}\n            aria-pressed={colorBlindnessMode !== 'normal'}\n            ref={colorBlindAnchorRef}\n          >\n            <Eye size={16} />\n            <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full left-1/2 -translate-x-1/2 mb-2\">{t.canvas.toolstrip.colorblind}</TextBody>\n          </button>\n        </div>\n\n        <div className=\"w-px h-6 bg-panel-border mx-1\" aria-hidden />\n\n        <SnapMagnetButton />\n        <BrandKitButton />\n        </div>\n        <CanvasZoomDock variant=\"docked\" />\n      </aside>\n\n      <div className=\"relative order-1 flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden\">\n\n      {(activeToolPanel === 'grid') && (\n        <CanvasGridPanel\n          anchorRef={gridAnchorRef}\n          onClose={() => dismissToolPanels()}\n        />\n      )}\n\n      {/* Panel flotante de Figuras/Formas \u2014 tabs Figuras / Formas */}\n      {(activeToolPanel === 'shapes') && (\n        <DraggableToolPanel\n          panelId=\"canvas-shapes\"\n          title={t.canvas.shapesPanel.title}\n          anchorRef={shapesAnchorRef}\n          onClose={() => dismissToolPanels()}\n          contentClassName=\"flex flex-col max-h-[70vh] overflow-y-auto min-w-[400px]\"\n        >\n            <ToolPanelTabs\n              tabs={[\n                { id: 'figures', label: t.canvas.shapesPanel.tabFigures },\n                { id: 'shapes', label: t.canvas.shapesPanel.tabShapes },\n                { id: 'graficos', label: t.canvas.shapesPanel.tabCharts },\n                { id: 'qr-barcode', label: t.canvas.shapesPanel.tabQrCode },\n              ]}\n              value={shapesTab}\n              onChange={setShapesTab}\n            />\n            {/* Contenido scrolleable */}\n            <div className=\"flex flex-col gap-3 p-3 overflow-y-auto\">\n              {shapesTab === 'figures' && (\n                <>\n                  {/* B\u00E1sicas */}\n                  <div>\n                    <TextTitle as=\"span\" size=\"sm\" className=\"uppercase text-white tracking-wider block mb-1.5\">{t.canvas.shapesPanel.basicFigures}</TextTitle>\n                    <div className=\"flex flex-wrap gap-1.5\">\n                      {[\n                        { tool: 'rect' as ToolType, label: t.canvas.shapesPanel.rect, color: 'text-[var(--we-accent)]' },\n                        { tool: 'rounded-rect' as ToolType, label: t.canvas.shapesPanel.rounded, color: 'text-indigo-400' },\n                        { tool: 'circle' as ToolType, label: t.canvas.shapesPanel.circle, color: 'text-emerald-400' },\n                        { tool: 'ellipse' as ToolType, label: t.canvas.shapesPanel.ellipse, color: 'text-[var(--we-accent)]' },\n                        { tool: 'line' as ToolType, label: t.canvas.shapesPanel.line, color: 'text-pink-400' },\n                      ].map(({ tool, label, color }) => (\n                        <button\n                          key={tool}\n                          onClick={() => { setActiveTool(tool); /* setActiveToolPanel handles exclusion */; }}\n                          className={`h-6 w-6 ${toolTileClass(activeTool === tool)}`}\n                          title={label}\n                          aria-label={label}\n                        >\n                          <svg className={`w-4 h-4 ${activeTool === tool ? '' : color}`} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.2\">\n                            {tool === 'rect' && <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"0\" />}\n                            {tool === 'rounded-rect' && <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"4.5\" />}\n                            {tool === 'circle' && <circle cx=\"12\" cy=\"12\" r=\"9\" />}\n                            {tool === 'ellipse' && <ellipse cx=\"12\" cy=\"12\" rx=\"9\" ry=\"5.5\" />}\n                            {tool === 'line' && <line x1=\"3\" y1=\"21\" x2=\"21\" y2=\"3\" strokeLinecap=\"round\" />}\n                          </svg>\n                        </button>\n                      ))}\n                    </div>\n                  </div>\n\n                  {/* Pol\u00EDgonos y Estrellas */}\n                  <div>\n                    <TextTitle as=\"span\" size=\"sm\" className=\"uppercase text-white tracking-wider block mb-1.5\">{t.canvas.shapesPanel.polygonsAndStars}</TextTitle>\n                    <div className=\"flex flex-wrap gap-1.5\">\n                      {[\n                        { tool: 'triangle' as ToolType, label: t.canvas.shapesPanel.triangle, color: 'text-amber-400', path: <polygon points=\"12,3 2,21 22,21\" strokeLinejoin=\"round\" /> },\n                        { tool: 'polygon' as ToolType, label: t.canvas.shapesPanel.hexagon, color: 'text-orange-400', path: <polygon points=\"12,2 20.66,7 20.66,17 12,22 3.34,17 3.34,7\" strokeLinejoin=\"round\" /> },\n                        { tool: 'star' as ToolType, label: t.canvas.shapesPanel.star, color: 'text-yellow-400', path: <polygon points=\"12,2 15.2,8.6 22,9.6 17.1,14.5 18.2,21.3 12,18 5.8,21.3 6.9,14.5 2,9.6 8.8,8.6\" strokeLinejoin=\"round\" /> },\n                      ].map(({ tool, label, color, path }) => (\n                        <button\n                          key={tool}\n                          onClick={() => { setActiveTool(tool); /* setActiveToolPanel handles exclusion */; }}\n                          className={`h-6 w-6 ${toolTileClass(activeTool === tool)}`}\n                          title={label}\n                          aria-label={label}\n                        >\n                          <svg className={`w-4 h-4 ${activeTool === tool ? '' : color}`} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.2\">\n                            {path}\n                          </svg>\n                        </button>\n                      ))}\n                    </div>\n                  </div>\n\n                  {/* Especiales */}\n                  <div>\n                    <TextTitle as=\"span\" size=\"sm\" className=\"uppercase text-white tracking-wider block mb-1.5\">{t.canvas.shapesPanel.specialFigures}</TextTitle>\n                    <div className=\"flex flex-wrap gap-1.5\">\n                      {[\n                        { tool: 'arrow' as ToolType, label: t.canvas.shapesPanel.arrow, color: 'text-rose-400' },\n                        { tool: 'heart' as ToolType, label: t.canvas.shapesPanel.heart, color: 'text-red-400' },\n                        { tool: 'speech-bubble' as ToolType, label: t.canvas.shapesPanel.speechBubble, color: 'text-cyan-400' },\n                        { tool: 'cross' as ToolType, label: t.canvas.shapesPanel.cross, color: 'text-teal-400' },\n                      ].map(({ tool, label, color }) => (\n                        <button\n                          key={tool}\n                          onClick={() => { setActiveTool(tool); /* setActiveToolPanel handles exclusion */; }}\n                          className={`h-6 w-6 ${toolTileClass(activeTool === tool)}`}\n                          title={label}\n                          aria-label={label}\n                        >\n                          <svg className={`w-4 h-4 ${activeTool === tool ? '' : color}`} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.2\">\n                            {tool === 'arrow' && <path d=\"M5 12h14M12 5l7 7-7 7\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />}\n                            {tool === 'heart' && <path d=\"M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />}\n                            {tool === 'speech-bubble' && <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />}\n                            {tool === 'cross' && <path d=\"M12 5v14M5 12h14\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />}\n                          </svg>\n                        </button>\n                      ))}\n                    </div>\n                  </div>\n                </>\n              )}\n\n              {shapesTab === 'shapes' && (\n                <>\n                  {Object.entries(customShapeCategories).map(([category, shapes]) => (\n                    <div key={category}>\n                      <TextTitle as=\"span\" size=\"sm\" className=\"uppercase text-white tracking-wider block mb-1.5\">{category}</TextTitle>\n                      <div className=\"flex flex-wrap gap-1.5\">\n                        {shapes.map((shape) => (\n                          <button\n                            key={shape.id}\n                            onClick={() => {\n                              setActiveCustomShape(shape.id);\n                              setActiveTool('custom-shape');;\n                            }}\n                            className={`h-6 w-6 ${toolTileClass(\n                              activeTool === 'custom-shape' && activeCustomShape === shape.id,\n                            )}`}\n                            title={shape.name}\n                            aria-label={shape.name}\n                          >\n                            <svg className=\"w-4 h-4\" viewBox=\"-20 -20 240 240\" fill=\"currentColor\">\n                              <path d={shape.path} />\n                            </svg>\n                          </button>\n                        ))}\n                      </div>\n                    </div>\n                  ))}\n                </>\n              )}\n\n              {/* TAB: GR\u00C1FICOS */}\n              {shapesTab === 'graficos' && (\n                <>\n                  <div className=\"flex items-center gap-2 mb-1\">\n                    <BarChart size={14} className=\"text-[var(--we-accent)]\" />\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-white uppercase tracking-wider\">{t.canvas.shapesPanel.editableCharts}</TextBody>\n                  </div>\n                  <TextBody as=\"p\" size=\"sm\" className=\"text-white/80 mb-3\">{t.canvas.shapesPanel.editChartHint}</TextBody>\n                  <div className=\"grid grid-cols-2 gap-2\">\n                    <button\n                      onClick={() => handleInsertChart('bar')}\n                      className=\"py-3 bg-black-capsule hover:bg-black-capsule-hover text-white/80 hover:text-white rounded-xl text-xs font-semibold border border-panel-border hover:border-[var(--we-accent)]/40 transition-all flex flex-col items-center gap-2 group\"\n                      aria-label={t.canvas.shapesPanel.insertBarChart}\n                    >\n                      <BarChart size={20} className=\"text-[var(--we-accent)] group-hover:text-white/80 transition-colors\" />\n                      <span>{t.canvas.shapesPanel.chartBar}</span>\n                    </button>\n                    <button\n                      onClick={() => handleInsertChart('line')}\n                      className=\"py-3 bg-black-capsule hover:bg-black-capsule-hover text-white/80 hover:text-white rounded-xl text-xs font-semibold border border-panel-border hover:border-[var(--we-accent)]/40 transition-all flex flex-col items-center gap-2 group\"\n                      aria-label={t.canvas.shapesPanel.insertLineChart}\n                    >\n                      <LineChart size={20} className=\"text-white0 group-hover:text-[var(--we-accent)] transition-colors\" />\n                      <span>{t.canvas.shapesPanel.chartLine}</span>\n                    </button>\n                    <button\n                      onClick={() => handleInsertChart('pie')}\n                      className=\"py-3 bg-black-capsule hover:bg-black-capsule-hover text-white/80 hover:text-white rounded-xl text-xs font-semibold border border-panel-border hover:border-[var(--we-accent)]/40 transition-all flex flex-col items-center gap-2 group\"\n                      aria-label={t.canvas.shapesPanel.insertPieChart}\n                    >\n                      <PieChart size={20} className=\"text-warning group-hover:text-white transition-colors\" />\n                      <span>{t.canvas.shapesPanel.chartPie}</span>\n                    </button>\n                    <button\n                      onClick={() => handleInsertChart('donut')}\n                      className=\"py-3 bg-black-capsule hover:bg-black-capsule-hover text-white/80 hover:text-white rounded-xl text-xs font-semibold border border-panel-border hover:border-[var(--we-accent)]/40 transition-all flex flex-col items-center gap-2 group\"\n                      aria-label={t.canvas.shapesPanel.insertDonutChart}\n                    >\n                      <div className=\"relative\">\n                        <PieChart size={20} className=\"text-white/80 group-hover:text-white/80 transition-colors\" />\n                        <div className=\"absolute inset-1/4 bg-panel rounded-full w-2.5 h-2.5\" />\n                      </div>\n                      <span>{t.canvas.shapesPanel.chartDonut}</span>\n                    </button>\n                  </div>\n                </>\n              )}\n\n              {/* TAB: QR & C\u00D3DIGO DE BARRAS */}\n              {shapesTab === 'qr-barcode' && (\n                <>\n                  <div className=\"flex flex-col gap-2\">\n                    <div className=\"flex items-center gap-2 mb-1\">\n                      <QrCode size={14} className=\"text-[var(--we-accent)]\" />\n                      <TextBody as=\"span\" size=\"sm\" className=\"text-white uppercase tracking-wider\">{t.canvas.shapesPanel.qrGenerator}</TextBody>\n                    </div>\n                    <input\n                      type=\"text\"\n                      id=\"floating-panel-qr-input\"\n                      value={qrText}\n                      onChange={e => setQrText(e.target.value)}\n                      onKeyDown={e => { if (e.key === 'Enter') handleInsertQR(); }}\n                      placeholder={t.canvas.shapesPanel.qrPlaceholder}\n                      className=\"w-full text-xs px-3 py-2 bg-black-capsule border border-panel-border hover:border-[var(--we-accent)]/40 focus:border-[var(--we-accent)] focus:ring-1 focus:ring-[var(--we-accent)]/30 rounded-lg text-white placeholder:text-white/40 outline-none transition-all\"\n                    />\n                    <button\n                      onClick={handleInsertQR}\n                      disabled={!qrText.trim()}\n                      className=\"w-full py-2 bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] active:opacity-90 disabled:opacity-40 disabled:cursor-not-allowed text-white rounded-md text-[11px] font-bold transition-all\"\n                    >\n                      {t.canvas.shapesPanel.insertQr}\n                    </button>\n                  </div>\n                  <div className=\"w-full h-px bg-panel-border my-1\" aria-hidden />\n                  <div className=\"flex flex-col gap-2\">\n                    <div className=\"flex items-center gap-2 mb-1\">\n                      <ScanBarcode size={14} className=\"text-[var(--we-accent)]\" />\n                      <TextBody as=\"span\" size=\"sm\" className=\"text-white uppercase tracking-wider\">{t.canvas.shapesPanel.barcodeGenerator}</TextBody>\n                    </div>\n                    <input\n                      type=\"text\"\n                      id=\"floating-panel-barcode-input\"\n                      value={barcodeText}\n                      onChange={e => setBarcodeText(e.target.value)}\n                      onKeyDown={e => { if (e.key === 'Enter') handleInsertBarcode(); }}\n                      placeholder={t.canvas.shapesPanel.barcodePlaceholder}\n                      className=\"w-full text-xs px-3 py-2 bg-black-capsule border border-panel-border hover:border-[var(--we-accent)]/40 focus:border-[var(--we-accent)] focus:ring-1 focus:ring-[var(--we-accent)]/30 rounded-lg text-white placeholder:text-white/40 outline-none transition-all\"\n                    />\n                    <button\n                      onClick={handleInsertBarcode}\n                      disabled={!barcodeText.trim()}\n                      className=\"w-full py-2 bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] active:opacity-90 disabled:opacity-40 disabled:cursor-not-allowed text-white rounded-md text-[11px] font-bold transition-all\"\n                    >\n                      {t.canvas.shapesPanel.insertBarcode}\n                    </button>\n                  </div>\n                </>\n              )}\n\n            </div>\n        </DraggableToolPanel>\n      )}\n\n      {/* Panel flotante de Editor de Texto (movido desde Sidebar T-20260706-13) */}\n      {isTextPanelOpen && (\n        <>\n          <div className=\"fixed inset-0 z-30 cursor-default\" onClick={() => setIsTextPanelOpen(false)} />\n          <div\n            className=\"fixed bottom-20 left-1/2 -translate-x-1/2 bg-panel border-el border-panel-border rounded-panel shadow-2xl z-40 animate-fade-in flex flex-col max-h-[80vh] min-w-[500px]\"\n            role=\"dialog\"\n            aria-label={t.properties.text.editorTitle}\n          >\n            {/* T\u00EDtulo */}\n            <div className=\"px-3 py-1.5 text-[10px] font-bold text-white/80 uppercase tracking-wider border-b border-panel-border flex items-center gap-1.5\">\n              <Type size={12} className=\"text-[var(--we-accent)]\" /> {t.properties.text.editorTitle}\n            </div>\n            {/* Tabs */}\n            <div className=\"flex gap-1 p-1.5 border-b border-panel-border\">\n              {([ { id: 'insertar', label: t.properties.text.tabInsert }, { id: 'lorem', label: 'Lorem Ipsum' }, { id: 'propiedades', label: t.properties.text.tabProperties }, { id: 'fuentes', label: t.properties.text.tabFonts } ] as const).map((tab) => (\n                <button\n                  key={tab.id}\n                  onClick={() => setTextPanelTab(tab.id)}\n                  className={`flex-1 px-2 py-1 text-[10px] font-bold rounded transition-colors ${\n                    textPanelTab === tab.id ? 'bg-brand-600 text-white' : 'text-white/80 hover:bg-brand-800/40 hover:text-white'\n                  }`}\n                  aria-pressed={textPanelTab === tab.id}\n                >{tab.label}</button>\n              ))}\n            </div>\n\n            {/* Contenido */}\n            <div className=\"flex flex-col gap-3 p-3 overflow-y-auto\">\n\n              {/* TAB: INSERTAR */}\n              {textPanelTab === 'insertar' && (\n                <>\n                  <TextTitle as=\"span\" size=\"sm\" className=\"uppercase text-white tracking-wider\">{t.properties.text.addTextToCanvas}</TextTitle>\n                  <div className=\"flex flex-col gap-2\">\n                    <button\n                      onClick={() => { updateTextSettings({ fontSize: 48, fontWeight: 'bold' }); setActiveTool('text'); setIsTextPanelOpen(false); }}\n                      className=\"w-full py-3 bg-black-capsule hover:bg-brand-800 border-el border-panel-border hover:border-brand-600/50 text-white rounded-md flex items-center justify-between px-4 transition-all\"\n                    >\n                      <TextTitle as=\"span\" size=\"lg\" className=\"font-black text-white\">{t.properties.text.addTitle}</TextTitle>\n                      <TextBody as=\"span\" size=\"sm\" className=\"text-[var(--we-accent)] font-mono\">48px</TextBody>\n                    </button>\n                    <button\n                      onClick={() => { updateTextSettings({ fontSize: 28, fontWeight: 'bold' }); setActiveTool('text'); setIsTextPanelOpen(false); }}\n                      className=\"w-full py-2.5 bg-black-capsule hover:bg-brand-800 border-el border-panel-border hover:border-brand-600/50 text-white rounded-md flex items-center justify-between px-4 transition-all\"\n                    >\n                      <TextBody as=\"span\" size=\"md\" className=\"font-bold text-white\">{t.properties.text.addSubtitle}</TextBody>\n                      <TextBody as=\"span\" size=\"sm\" className=\"text-[var(--we-accent)] font-mono\">28px</TextBody>\n                    </button>\n                    <button\n                      onClick={() => { updateTextSettings({ fontSize: 16, fontWeight: 'normal' }); setActiveTool('text'); setIsTextPanelOpen(false); }}\n                      className=\"w-full py-2 bg-black-capsule hover:bg-brand-800 border-el border-panel-border hover:border-brand-600/50 text-white rounded-md flex items-center justify-between px-4 transition-all\"\n                    >\n                      <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{t.properties.text.addBodyText}</TextBody>\n                      <TextBody as=\"span\" size=\"sm\" className=\"text-[var(--we-accent)] font-mono\">16px</TextBody>\n                    </button>\n                  </div>\n                </>\n              )}\n\n              {/* TAB: LOREM IPSUM */}\n              {textPanelTab === 'lorem' && (\n                <>\n                  <div className=\"flex items-center gap-2 mb-1\">\n                    <Type size={14} className=\"text-[var(--we-accent)]\" />\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-white uppercase tracking-wider\">{t.properties.text.loremGenerator}</TextBody>\n                  </div>\n                  <TextBody as=\"p\" size=\"sm\" className=\"text-[var(--we-accent)]\">{t.properties.text.loremHint}</TextBody>\n                  <div className=\"flex gap-2\">\n                    <select\n                      value={loremLength}\n                      onChange={e => setLoremLength(e.target.value as any)}\n                      className=\"flex-1 text-xs px-3 py-2 bg-black-capsule border border-panel-border hover:border-[var(--we-accent)]/40 focus:border-[var(--we-accent)] rounded-lg text-white outline-none transition-all\"\n                    >\n                      <option value=\"words\">{t.properties.text.loremWords}</option>\n                      <option value=\"sentences\">{t.properties.text.loremSentences}</option>\n                      <option value=\"paragraphs\">{t.properties.text.loremParagraphs}</option>\n                    </select>\n                    <input\n                      type=\"number\" min=\"1\" max=\"100\"\n                      value={loremAmount}\n                      onChange={e => setLoremAmount(parseInt(e.target.value) || 1)}\n                      className=\"w-20 text-xs px-3 py-2 bg-black-capsule border border-panel-border hover:border-[var(--we-accent)]/40 focus:border-[var(--we-accent)] rounded-lg text-white text-center font-mono outline-none transition-all\"\n                    />\n                  </div>\n                  <button\n                    onClick={() => {\n                      const text = generateLoremIpsum(loremLength, loremAmount);\n                      const canvas = canvasInstance;\n                      if (!canvas) return;\n                      const active = canvas.getActiveObject() as any;\n                      if (active && (active.type === 'textbox' || active.type === 'text' || active.type === 'Textbox')) {\n                        active.set({ text });\n                        canvas.requestRenderAll();\n                        useEditorStore.getState().saveHistoryState();\n                      } else {\n                        updateTextSettings({ fontSize: 24, fontWeight: 'normal' });\n                        setActiveTool('text');\n                        setTimeout(() => {\n                          const a = canvas.getActiveObject() as any;\n                          if (a && a.set) { a.set({ text }); canvas.requestRenderAll(); useEditorStore.getState().saveHistoryState(); }\n                        }, 200);\n                      }\n                      setIsTextPanelOpen(false);\n                    }}\n                    className=\"w-full py-2 bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] text-white rounded-md text-[11px] font-bold transition-all\"\n                  >{t.properties.text.loremApply}</button>\n                </>\n              )}\n\n              {/* TAB: PROPIEDADES */}\n              {textPanelTab === 'propiedades' && (\n                <>\n                  {activeObject && (activeObject.type === 'Textbox' || activeObject.type === 'textbox' || activeObject.type === 'text') ? (\n                    <div className=\"flex flex-col gap-3\">\n                      {/* Tipograf\u00EDa */}\n                      <div className=\"flex flex-col gap-1.5 relative\">\n                        <TextBody as=\"label\" size=\"sm\" className=\"text-white/80 uppercase tracking-wider\">{t.properties.text.typography}</TextBody>\n                        <button\n                          ref={fontTriggerRef}\n                          type=\"button\"\n                          onClick={() => setIsFontDropdownOpen(!isFontDropdownOpen)}\n                          className=\"w-full bg-brand-input border-el border-panel-border hover:border-brand-600 rounded-md px-3 py-2 text-xs text-white text-left font-bold flex items-center justify-between focus:outline-none focus:border-brand-500 cursor-pointer transition-colors\"\n                          style={{ fontFamily: textSettings.fontFamily }}\n                        >\n                          <span>{textSettings.fontFamily}</span>\n                          <ChevronDown size={14} className={`text-[var(--we-accent)] transition-transform ${isFontDropdownOpen ? 'rotate-180' : ''}`} />\n                        </button>\n                        <ViewportPortalMenu\n                          open={isFontDropdownOpen}\n                          onClose={() => setIsFontDropdownOpen(false)}\n                          anchorRef={fontTriggerRef}\n                          zIndex={50}\n                          className=\"flex max-h-60 w-[min(18rem,calc(100vw-1.5rem))] flex-col gap-1 overflow-y-auto rounded-md border border-panel-border bg-panel p-2 shadow-2xl\"\n                        >\n                              {customFonts.length > 0 && (\n                                <div className=\"flex flex-col gap-0.5 border-b border-panel-border pb-1.5 mb-1.5\">\n                                  <TextTitle as=\"span\" size=\"xs\" className=\"uppercase tracking-widest px-2 py-0.5 text-[var(--we-accent)]\">{t.properties.text.myFonts}</TextTitle>\n                                  {customFonts.map((f) => (\n                                    <div key={f.name} className=\"group/item flex items-center justify-between hover:bg-black-capsule rounded-md p-1.5 cursor-pointer\">\n                                      <button type=\"button\" onClick={() => { updateTextSettings({ fontFamily: f.name }); setIsFontDropdownOpen(false); }} className=\"text-[11px] text-white text-left font-bold flex-1\" style={{ fontFamily: f.name }}>{f.name}</button>\n                                      <button type=\"button\" onClick={(e) => { e.stopPropagation(); deleteCustomFont(f.name); }} className=\"p-1 text-[var(--we-accent)] hover:text-red-400 rounded hover:bg-brand-800 hidden group-hover/item:block cursor-pointer\" title={t.properties.text.deleteFontTitle}><Trash2 size={11} /></button>\n                                    </div>\n                                  ))}\n                                </div>\n                              )}\n                              {['Sans-Serif', 'Serif', 'Display / T\u00EDtulos', 'Escritura', 'Monospace'].map((cat) => {\n                                const catFonts = GOOGLE_FONTS_CATALOG.filter(f => f.category === cat);\n                                return (\n                                  <div key={cat} className=\"flex flex-col gap-0.5 mt-1\">\n                                    <TextTitle as=\"span\" size=\"xs\" className=\"uppercase tracking-widest px-2 py-0.5 text-white/80\">{cat}</TextTitle>\n                                    {catFonts.map((f) => (\n                                      <button key={f.name} type=\"button\" onClick={() => { updateTextSettings({ fontFamily: f.name }); setIsFontDropdownOpen(false); }}\n                                        className={`text-sm hover:bg-black-capsule rounded-md p-1.5 text-left cursor-pointer transition-colors ${textSettings.fontFamily === f.name ? 'text-[var(--we-accent)] bg-brand-600/10 font-black' : 'text-white'}`}\n                                        style={{ fontFamily: f.name }}\n                                      >{f.name}</button>\n                                    ))}\n                                  </div>\n                                );\n                              })}\n                        </ViewportPortalMenu>\n                      </div>\n                      {/* Tama\u00F1o */}\n                      <div className=\"flex flex-col gap-1.5\">\n                        <TextBody as=\"label\" size=\"sm\" className=\"text-white/80 uppercase tracking-wider\">{t.properties.text.fontSize}</TextBody>\n                        <div className=\"flex items-center gap-1\">\n                          <button onClick={() => updateTextSettings({ fontSize: Math.max(1, textSettings.fontSize - 1) })} className=\"bg-brand-600 border-el border-panel-border hover:bg-brand-800 text-white w-9 h-9 rounded-md flex items-center justify-center font-bold text-lg cursor-pointer\">-</button>\n                          <input type=\"number\" value={textSettings.fontSize} onChange={(e) => updateTextSettings({ fontSize: Math.max(1, parseInt(e.target.value) || 12) })} className=\"flex-1 bg-brand-input border-el border-panel-border rounded-md p-2 text-xs font-bold text-center text-white focus:outline-none focus:border-brand-500 h-9\" />\n                          <button onClick={() => updateTextSettings({ fontSize: textSettings.fontSize + 1 })} className=\"bg-brand-600 border-el border-panel-border hover:bg-brand-800 text-white w-9 h-9 rounded-md flex items-center justify-center font-bold text-lg cursor-pointer\">+</button>\n                        </div>\n                      </div>\n                      {/* Estilo */}\n                      <div className=\"flex flex-col gap-1.5\">\n                        <TextBody as=\"label\" size=\"sm\" className=\"text-white/80 uppercase tracking-wider\">{t.properties.text.style}</TextBody>\n                        <div className=\"flex items-center gap-1 bg-brand-950 border-el border-panel-border p-1 rounded-md\">\n                          <button onClick={() => updateTextSettings({ fontWeight: textSettings.fontWeight === 'bold' ? 'normal' : 'bold' })} className={`flex-1 py-1.5 rounded-md flex justify-center cursor-pointer transition-colors ${textSettings.fontWeight === 'bold' ? 'bg-brand-700 text-[var(--we-accent)]' : 'text-[var(--we-accent)] hover:text-white'}`} title={t.properties.text.bold}><Bold size={15} /></button>\n                          <button onClick={() => updateTextSettings({ fontStyle: textSettings.fontStyle === 'italic' ? 'normal' : 'italic' })} className={`flex-1 py-1.5 rounded-md flex justify-center cursor-pointer transition-colors ${textSettings.fontStyle === 'italic' ? 'bg-brand-700 text-[var(--we-accent)]' : 'text-[var(--we-accent)] hover:text-white'}`} title={t.properties.text.italic}><Italic size={15} /></button>\n                          <button onClick={() => updateTextSettings({ underline: !textSettings.underline })} className={`flex-1 py-1.5 rounded-md flex justify-center cursor-pointer transition-colors ${textSettings.underline ? 'bg-brand-700 text-[var(--we-accent)]' : 'text-[var(--we-accent)] hover:text-white'}`} title={t.properties.text.underline}><Underline size={15} /></button>\n                          <button onClick={() => updateTextSettings({ linethrough: !textSettings.linethrough })} className={`flex-1 py-1.5 rounded-md flex justify-center cursor-pointer font-bold transition-colors ${textSettings.linethrough ? 'bg-brand-700 text-[var(--we-accent)]' : 'text-[var(--we-accent)] hover:text-white'}`} title={t.properties.text.strikethrough} style={{ textDecoration: 'line-through' }}><span className=\"text-xs\">S</span></button>\n                        </div>\n                      </div>\n                      {/* Alineaci\u00F3n */}\n                      <div className=\"flex flex-col gap-1.5\">\n                        <TextBody as=\"label\" size=\"sm\" className=\"text-white/80 uppercase tracking-wider\">{t.properties.text.alignment}</TextBody>\n                        <div className=\"flex items-center gap-1 bg-brand-950 border-el border-panel-border p-1 rounded-md\">\n                          {[{ id: 'left', icon: <AlignLeft size={15} /> }, { id: 'center', icon: <AlignCenter size={15} /> }, { id: 'right', icon: <AlignRight size={15} /> }].map((item) => (\n                            <button key={item.id} onClick={() => updateTextSettings({ textAlign: item.id })} className={`flex-1 py-1.5 rounded-md flex justify-center cursor-pointer transition-colors ${textSettings.textAlign === item.id ? 'bg-brand-700 text-[var(--we-accent)]' : 'text-[var(--we-accent)] hover:text-white'}`}>{item.icon}</button>\n                          ))}\n                        </div>\n                      </div>\n                      {/* Interlineado */}\n                      <div className=\"flex flex-col gap-1.5\">\n                        <div className=\"flex justify-between\">\n                          <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{t.properties.text.lineHeight}</TextBody>\n                          <TextBody as=\"span\" size=\"sm\" className=\"rounded bg-black-capsule px-1 font-mono text-white\">{textSettings.lineHeight}</TextBody>\n                        </div>\n                        <input type=\"range\" min=\"0.8\" max=\"3.0\" step=\"0.05\" value={textSettings.lineHeight} onChange={(e) => updateTextSettings({ lineHeight: parseFloat(e.target.value) })} className=\"accent-brand-500 bg-black-capsule h-1.5 rounded-lg appearance-none cursor-pointer w-full\" />\n                      </div>\n                      {/* Espaciado letras */}\n                      <div className=\"flex flex-col gap-1.5\">\n                        <div className=\"flex justify-between\">\n                          <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{t.properties.text.letterSpacing}</TextBody>\n                          <TextBody as=\"span\" size=\"sm\" className=\"rounded bg-black-capsule px-1 font-mono text-white\">{textSettings.charSpacing}</TextBody>\n                        </div>\n                        <input type=\"range\" min=\"-50\" max=\"300\" step=\"10\" value={textSettings.charSpacing} onChange={(e) => updateTextSettings({ charSpacing: parseInt(e.target.value) })} className=\"accent-brand-500 bg-black-capsule h-1.5 rounded-lg appearance-none cursor-pointer w-full\" />\n                      </div>\n                      {/* Curvatura */}\n                      <div className=\"flex flex-col gap-1.5\">\n                        <div className=\"flex justify-between\">\n                          <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{t.properties.text.textCurvature}</TextBody>\n                          <TextBody as=\"span\" size=\"sm\" className=\"rounded bg-black-capsule px-1 font-mono text-white\">{textSettings.curvature || 0}%</TextBody>\n                        </div>\n                        <input type=\"range\" min=\"-100\" max=\"100\" step=\"5\" value={textSettings.curvature || 0} onChange={(e) => updateTextSettings({ curvature: parseInt(e.target.value) })} className=\"accent-brand-500 bg-black-capsule h-1.5 rounded-lg appearance-none cursor-pointer w-full\" />\n                      </div>\n                    </div>\n                  ) : (\n                    <div className=\"flex flex-col items-center justify-center py-8 text-center\">\n                      <Type size={28} className=\"text-brand-600 mb-3\" />\n                      <TextBody as=\"p\" size=\"sm\" className=\"text-[var(--we-accent)]\">{t.properties.text.noTextSelected}</TextBody>\n                      <button onClick={() => { setActiveTool('text'); setIsTextPanelOpen(false); }} className=\"mt-3 px-4 py-2 bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] text-white rounded-md text-xs font-bold transition-all\">{t.properties.text.activateTextTool}</button>\n                    </div>\n                  )}\n                </>\n              )}\n\n              {/* TAB: FUENTES */}\n              {textPanelTab === 'fuentes' && (\n                <>\n                  <div className=\"flex items-center gap-2\">\n                    <UploadCloud size={14} className=\"text-[var(--we-accent)]\" />\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-white uppercase tracking-wider\">{t.properties.text.uploadFonts}</TextBody>\n                  </div>\n                  <TextBody as=\"p\" size=\"sm\" className=\"text-[var(--we-accent)]\">{t.properties.text.supportedFormats}</TextBody>\n                  <div className=\"relative flex flex-col items-center justify-center p-4 border border-dashed border-panel-border hover:border-brand-500/50 hover:bg-black-capsule/20 rounded-md transition-all duration-200 cursor-pointer\">\n                    <input\n                      type=\"file\" accept=\".ttf,.otf,.woff,.woff2\"\n                      onChange={(e) => {\n                        const file = e.target.files?.[0]; if (!file) return;\n                        const name = file.name.substring(0, file.name.lastIndexOf('.'));\n                        const reader = new FileReader();\n                        reader.onload = (event) => { const dataUrl = event.target?.result as string; addCustomFont(name, dataUrl); };\n                        reader.readAsDataURL(file);\n                      }}\n                      className=\"absolute inset-0 opacity-0 cursor-pointer w-full h-full\"\n                    />\n                    <UploadCloud size={20} className=\"text-[var(--we-accent)] mb-1\" />\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-white leading-none\">{t.properties.text.uploadFontFile}</TextBody>\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-[var(--we-accent)] mt-1\">{t.properties.text.uploadHint}</TextBody>\n                  </div>\n                  {customFonts.length > 0 && (\n                    <div className=\"flex flex-col gap-1 mt-1\">\n                      <TextTitle as=\"span\" size=\"sm\" className=\"uppercase text-white tracking-wider mb-1\">{t.properties.text.loadedFonts}</TextTitle>\n                      {customFonts.map((f) => (\n                        <div key={f.name} className=\"group flex items-center justify-between py-1.5 px-2 bg-black-capsule rounded-md\">\n                          <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-white\" style={{ fontFamily: f.name }}>{f.name}</TextBody>\n                          <button onClick={() => deleteCustomFont(f.name)} className=\"p-1 text-[var(--we-accent)] hover:text-red-400 rounded hover:bg-brand-800 opacity-0 group-hover:opacity-100 cursor-pointer transition-all\" title={t.properties.text.deleteFontTitle}><Trash2 size={11} /></button>\n                        </div>\n                      ))}\n                    </div>\n                  )}\n                </>\n              )}\n\n            </div>\n        </div>\n        </>\n      )}\n\n      {/* AI Studio \u2014 centered modal */}\n      {activeToolPanel === 'ai' &&\n        typeof document !== 'undefined' &&\n        createPortal(\n          <div\n            className=\"fixed inset-0 z-[100] flex items-center justify-center bg-black/75 p-4 backdrop-blur-sm animate-fade-in-opacity\"\n            style={modeAccentVars(mode)}\n            data-we-mode={mode}\n          >\n            <div className=\"absolute inset-0 cursor-default\" onClick={() => dismissToolPanels()} aria-hidden />\n            <div\n              role=\"dialog\"\n              aria-modal\n              aria-label={t.canvas.aiStudio.title}\n              className=\"relative z-[101] flex max-h-[90vh] w-full max-w-xl flex-col overflow-hidden rounded-2xl border border-panel-border bg-panel shadow-2xl shadow-black/60 animate-slide-in\"\n            >\n              <div className=\"flex shrink-0 items-center justify-between gap-3 border-b border-panel-border px-4 py-3\">\n                <TextTitle as=\"h2\" size=\"sm\" className=\"uppercase tracking-wider text-white\">\n                  {t.canvas.aiStudio.title}\n                </TextTitle>\n                <IconButton label={t.common.close} size=\"sm\" variant=\"ghost\" onClick={() => dismissToolPanels()}>\n                  <X size={16} />\n                </IconButton>\n              </div>\n\n              {isAiGenerating && (\n                <div className=\"px-3 py-1.5 border-b border-panel-border flex items-center gap-1.5\">\n                  <div className=\"relative w-16 h-1 bg-black-capsule rounded-full overflow-hidden\">\n                    <div className=\"absolute top-0 bottom-0 left-0 w-1/2 bg-[var(--we-accent)] rounded-full animate-pulse\" />\n                  </div>\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                    {t.canvas.aiStudio.processing}\n                  </TextBody>\n                </div>\n              )}\n\n              <ToolPanelTabs\n                dense\n                tabs={[\n                  { id: 'generador', label: t.canvas.aiStudio.tab.generador },\n                  ...(FEATURE_FLAGS.SHOW_DESIGN_COPILOT\n                    ? [{ id: 'copilot' as const, label: t.canvas.aiStudio.tab.copilot }]\n                    : []),\n                  { id: 'copywriter', label: t.canvas.aiStudio.tab.copywriter },\n                ]}\n                value={aiPanelTab}\n                onChange={setAiPanelTab}\n              />\n\n              {aiStudioError && (\n                <div className=\"mx-3 mt-2 p-2.5 bg-red-950/40 border border-red-500/20 rounded-md text-red-200 text-[10px] leading-relaxed flex items-start gap-2\">\n                  <div className=\"w-1.5 h-1.5 bg-red-500 rounded-full mt-1 flex-shrink-0 animate-ping\" />\n                  <div>{aiStudioError}</div>\n                </div>\n              )}\n\n              <div className=\"flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto p-4\">\n\n              {/* TAB: GENERADOR de imagen */}\n              {aiPanelTab === 'generador' && (\n                <div className=\"flex flex-col gap-3\">\n                  <div className=\"flex flex-wrap items-center gap-2\">\n                    <input\n                      ref={textToImageRefInputRef}\n                      type=\"file\"\n                      accept=\"image/*\"\n                      multiple\n                      className=\"hidden\"\n                      onChange={(e) => {\n                        const files = Array.from(e.target.files ?? []).filter(\n                          (f) => f.type.startsWith('image/'),\n                        );\n                        if (files.length === 0) return;\n                        setTextToImageRefs((prev) => {\n                          const next = [...prev];\n                          for (const file of files) {\n                            if (next.length >= 6) break;\n                            next.push({\n                              id: `${file.name}-${file.size}-${Date.now()}-${Math.random()}`,\n                              file,\n                              previewUrl: URL.createObjectURL(file),\n                            });\n                          }\n                          return next;\n                        });\n                        e.target.value = '';\n                      }}\n                    />\n\n                    {textToImageRefs.map((ref) => (\n                      <div\n                        key={ref.id}\n                        className=\"relative size-10 shrink-0 overflow-hidden rounded-lg border border-panel-border bg-black-capsule\"\n                      >\n                        <img\n                          src={ref.previewUrl}\n                          alt=\"\"\n                          className=\"h-full w-full object-cover\"\n                        />\n                        <button\n                          type=\"button\"\n                          onClick={() => {\n                            URL.revokeObjectURL(ref.previewUrl);\n                            setTextToImageRefs((prev) =>\n                              prev.filter((r) => r.id !== ref.id),\n                            );\n                          }}\n                          className=\"absolute -right-0.5 -top-0.5 flex size-4 items-center justify-center rounded-full bg-black/80 text-white/90 hover:text-red-400 cursor-pointer\"\n                          aria-label={t.common.close}\n                        >\n                          <X size={9} />\n                        </button>\n                      </div>\n                    ))}\n\n                    {textToImageRefs.length < 6 && (\n                      <button\n                        type=\"button\"\n                        onClick={() => textToImageRefInputRef.current?.click()}\n                        className=\"flex shrink-0 items-center gap-2 text-white/70 hover:text-[var(--we-accent)] cursor-pointer group\"\n                      >\n                        <span className=\"flex size-10 items-center justify-center rounded-lg border border-dashed border-panel-border bg-black-capsule group-hover:border-[var(--we-accent)] transition-colors\">\n                          <Plus size={16} strokeWidth={2.5} />\n                        </span>\n                        {textToImageRefs.length === 0 && (\n                          <TextBody as=\"span\" size=\"sm\" className=\"\">\n                            {t.canvas.aiStudio.generador.referencesAdd}\n                          </TextBody>\n                        )}\n                      </button>\n                    )}\n                  </div>\n\n                  <textarea\n                    value={textToImagePrompt}\n                    onChange={(e) => setTextToImagePrompt(e.target.value)}\n                    onKeyDown={(e) => {\n                      if (e.key !== 'Enter' || e.shiftKey) return;\n                      e.preventDefault();\n                      void generateTextToImageAndClose();\n                    }}\n                    placeholder={t.canvas.aiStudio.generador.promptPlaceholder}\n                    className=\"w-full h-20 text-xs p-3 bg-black-capsule border border-panel-border hover:border-[var(--we-accent)]/40 focus:border-[var(--we-accent)] rounded-lg text-white outline-none resize-none placeholder:text-white/40 transition-all\"\n                  />\n\n                  <div className=\"flex flex-col gap-1\">\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                      {t.canvas.aiStudio.generador.aspectLabel}\n                    </TextBody>\n                    <SelectDropdown\n                      ariaLabel={t.canvas.aiStudio.generador.aspectLabel}\n                      value={textToImageAspect}\n                      size=\"md\"\n                      align=\"left\"\n                      className=\"w-full rounded-xl border border-panel-border bg-black-capsule px-3 py-1.5\"\n                      onChange={(v) =>\n                        setTextToImageAspect(v as typeof textToImageAspect)\n                      }\n                      options={[\n                        { value: '1:1', label: '1:1' },\n                        { value: '4:5', label: '4:5' },\n                        { value: '9:16', label: '9:16' },\n                        { value: '16:9', label: '16:9' },\n                        { value: '3:2', label: '3:2' },\n                      ]}\n                    />\n                  </div>\n\n                  <div className=\"flex flex-col gap-1\">\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                      {t.canvas.aiStudio.generador.resolutionLabel}\n                    </TextBody>\n                    <SelectDropdown\n                      ariaLabel={t.canvas.aiStudio.generador.resolutionLabel}\n                      value={textToImageResolution}\n                      size=\"md\"\n                      align=\"left\"\n                      className=\"w-full rounded-xl border border-panel-border bg-black-capsule px-3 py-1.5\"\n                      onChange={(v) =>\n                        setTextToImageResolution(v as '1K' | '2K')\n                      }\n                      options={[\n                        { value: '1K', label: '1K' },\n                        { value: '2K', label: '2K' },\n                      ]}\n                    />\n                  </div>\n\n                  <button\n                    type=\"button\"\n                    onClick={() => void generateTextToImageAndClose()}\n                    disabled={isAiGenerating || !textToImagePrompt.trim()}\n                    className=\"w-full py-2.5 px-4 text-xs font-bold text-white bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] disabled:opacity-50 rounded-md active:scale-[0.98] transition-all cursor-pointer\"\n                  >\n                    {isAiGenerating\n                      ? t.canvas.aiStudio.generador.generating\n                      : t.canvas.aiStudio.generador.generate}\n                  </button>\n\n                  {/* Generar en \u00E1rea si hay rect seleccionado */}\n                  {activeObject && activeObject.type?.toLowerCase() === 'rect' && (\n                    <div className=\"border-t border-panel-border pt-3 flex flex-col gap-2\">\n                      <TextTitle as=\"span\" size=\"sm\" className=\"uppercase text-white tracking-wider\">\n                        {t.canvas.aiStudio.generador.inAreaHeader}\n                      </TextTitle>\n                      <input\n                        type=\"text\"\n                        value={generateInAreaPrompt}\n                        onChange={(e) => setGenerateInAreaPrompt(e.target.value)}\n                        onKeyDown={(e) => {\n                          if (e.key !== 'Enter') return;\n                          e.preventDefault();\n                          if (isAiGenerating || !generateInAreaPrompt.trim()) return;\n                          dismissToolPanels();\n                          void runGenerateInArea(generateInAreaPrompt);\n                        }}\n                        placeholder={t.canvas.aiStudio.generador.inAreaPlaceholder}\n                        className=\"w-full text-xs px-2.5 py-1.5 bg-black-capsule border border-panel-border hover:border-[var(--we-accent)]/40 focus:border-[var(--we-accent)] rounded-lg text-white outline-none transition-all\"\n                      />\n                      <button\n                        type=\"button\"\n                        onClick={() => {\n                          dismissToolPanels();\n                          void runGenerateInArea(generateInAreaPrompt);\n                        }}\n                        disabled={isAiGenerating || !generateInAreaPrompt.trim()}\n                        className=\"w-full py-2 bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] disabled:opacity-50 text-white rounded-md text-xs font-bold cursor-pointer transition-all\"\n                      >\n                        {isAiGenerating\n                          ? t.canvas.aiStudio.generador.generatingInArea\n                          : t.canvas.aiStudio.generador.generateInArea}\n                      </button>\n                    </div>\n                  )}\n                </div>\n              )}\n\n              {/* TAB: COPILOT */}\n              {FEATURE_FLAGS.SHOW_DESIGN_COPILOT && aiPanelTab === 'copilot' && (\n                <div className=\"flex flex-col gap-3\">\n                  <div className=\"flex items-center gap-1.5\">\n                    <Sparkles size={14} className=\"text-[var(--we-accent)] animate-pulse\" />\n                    <TextTitle as=\"span\" size=\"xs\" className=\"uppercase tracking-wider text-white\">{t.canvas.aiStudio.copilot.title}</TextTitle>\n                  </div>\n                  <TextBody as=\"p\" size=\"sm\" className=\"text-[var(--we-accent)] leading-normal\">\n                    {t.canvas.aiStudio.copilot.intro}\n                    {activeObject ? (\n                      <TextBody as=\"span\" size=\"sm\" className=\"mt-1 block font-semibold text-[var(--we-accent)]\">{t.canvas.aiStudio.copilot.activeObject(activeObject.type || '')}</TextBody>\n                    ) : (\n                      <TextBody as=\"span\" size=\"sm\" className=\"mt-1 block italic text-white/80\">{t.canvas.aiStudio.copilot.noSelection}</TextBody>\n                    )}\n                  </TextBody>\n                  <textarea\n                    value={designCopilotPrompt}\n                    onChange={(e) => setDesignCopilotPrompt(e.target.value)}\n                    onKeyDown={(e) => {\n                      if (e.key !== 'Enter' || e.shiftKey) return;\n                      e.preventDefault();\n                      if (isAiGenerating || !designCopilotPrompt.trim()) return;\n                      void runAiDesignCopilot(designCopilotPrompt);\n                    }}\n                    disabled={isAiGenerating}\n                    placeholder={t.canvas.aiStudio.copilot.placeholder}\n                    className=\"w-full h-16 text-xs p-2.5 bg-black-capsule border border-panel-border hover:border-[var(--we-accent)]/40 focus:border-[var(--we-accent)] rounded-lg text-white outline-none resize-none placeholder:text-white/40 transition-all\"\n                  />\n                  <button\n                    onClick={async () => {\n                      if (!designCopilotPrompt.trim()) return;\n                      await runAiDesignCopilot(designCopilotPrompt);\n                    }}\n                    disabled={isAiGenerating || !designCopilotPrompt.trim()}\n                    className=\"w-full py-2 bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] disabled:opacity-50 text-white rounded-md text-xs font-bold cursor-pointer transition-all active:scale-[0.98]\"\n                  >{isAiGenerating ? t.canvas.aiStudio.copilot.applying : t.canvas.aiStudio.copilot.apply}</button>\n\n                  {/* API Key Gemini */}\n                  <div className=\"border-t border-panel-border pt-3 flex flex-col gap-2\">\n                    <div className=\"flex items-center justify-between\">\n                      <TextBody as=\"label\" size=\"sm\" className=\"text-white/80 uppercase tracking-wider\">{t.canvas.aiStudio.copilot.geminiKeyLabel}</TextBody>\n                      {geminiApiKey ? (\n                        <TextBody as=\"span\" size=\"sm\" className=\"text-[var(--we-accent)] bg-purple-950/40 border border-purple-500/20 px-2 py-0.5 rounded-full\">\u25CF {t.canvas.aiStudio.copilot.apiActive}</TextBody>\n                      ) : (\n                        <TextBody as=\"span\" size=\"sm\" className=\"text-amber-500 bg-amber-950/40 border border-amber-500/20 px-2 py-0.5 rounded-full\">\u25CB {t.canvas.aiStudio.copilot.localFallback}</TextBody>\n                      )}\n                    </div>\n                    <input\n                      type=\"password\"\n                      value={geminiApiKey}\n                      onChange={(e) => setGeminiApiKey(e.target.value)}\n                      placeholder={t.canvas.aiStudio.copilot.geminiKeyPlaceholder}\n                      className=\"w-full text-xs px-3 py-2 bg-black-capsule border border-panel-border hover:border-[var(--we-accent)]/40 focus:border-[var(--we-accent)] rounded-lg text-white outline-none transition-all font-mono\"\n                    />\n                    <TextBody as=\"p\" size=\"sm\" className=\"text-[var(--we-accent)]\">{t.canvas.aiStudio.copilot.geminiKeyHint}</TextBody>\n                  </div>\n                </div>\n              )}\n\n              {/* TAB: COPYWRITER */}\n              {aiPanelTab === 'copywriter' && (\n                <div className=\"flex flex-col gap-3\">\n                  <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{t.canvas.aiStudio.copywriter.intro}</TextBody>\n                  <TextBody\n                    as=\"p\"\n                    size=\"sm\"\n                    className={\n                      activeBrand?.name ? 'text-[var(--we-accent)]' : 'text-white/80'\n                    }\n                  >\n                    {activeBrand?.name\n                      ? t.canvas.aiStudio.copywriter.brandHint(activeBrand.name)\n                      : t.canvas.aiStudio.copywriter.brandMissing}\n                  </TextBody>\n                  <div className=\"flex gap-1.5\">\n                    <input type=\"text\" value={copywritePrompt} onChange={(e) => setCopywritePrompt(e.target.value)} onKeyDown={(e) => { if (e.key !== 'Enter') return; e.preventDefault(); if (isAiGenerating || !copywritePrompt.trim()) return; void runAiCopywrite(copywritePrompt); }} placeholder={t.canvas.aiStudio.copywriter.promptPlaceholder} className=\"flex-1 min-w-0 text-xs px-2.5 py-1.5 bg-black-capsule border border-panel-border hover:border-[var(--we-accent)]/40 focus:border-[var(--we-accent)] rounded-lg text-white outline-none transition-all\" />\n                    <button onClick={() => runAiCopywrite(copywritePrompt)} disabled={isAiGenerating || !copywritePrompt.trim()} className=\"flex-shrink-0 p-1.5 px-3.5 bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] disabled:opacity-40 text-white rounded-md text-xs font-bold cursor-pointer transition-all active:scale-95\">{t.canvas.aiStudio.copywriter.write}</button>\n                  </div>\n                  {aiCopywritingSuggestions && (\n                    <div className=\"flex flex-col gap-2 border-t border-panel-border pt-3\">\n                      <TextBody as=\"span\" size=\"sm\" className=\"text-white/80 uppercase tracking-wider mb-1\">{t.canvas.aiStudio.copywriter.selectHint}</TextBody>\n                      {([\n                        { key: 'comercial', label: t.canvas.aiStudio.copywriter.styles.comercial },\n                        { key: 'creativa', label: t.canvas.aiStudio.copywriter.styles.creativa },\n                        { key: 'directa', label: t.canvas.aiStudio.copywriter.styles.directa },\n                      ] as const).map(({ key, label }) => (\n                        <button\n                          key={key}\n                          type=\"button\"\n                          onClick={() => applyAiCopywritingSuggestion(aiCopywritingSuggestions[key])}\n                          className=\"group rounded-xl border border-panel-border bg-black-capsule p-3 text-left transition-colors hover:border-[var(--we-accent)]/50 hover:bg-black-capsule-hover cursor-pointer\"\n                        >\n                          <div className=\"mb-1.5 flex items-center justify-between gap-2\">\n                            <TextBody as=\"span\" size=\"sm\" className=\"uppercase tracking-wider text-[var(--we-accent)]\">{label}</TextBody>\n                            <TextBody as=\"span\" size=\"sm\" className=\"text-white/80 transition-colors group-hover:text-white\">{t.canvas.aiStudio.copywriter.apply}</TextBody>\n                          </div>\n                          <TextBody as=\"p\" size=\"sm\" className=\"leading-snug text-white\">{aiCopywritingSuggestions[key]}</TextBody>\n                        </button>\n                      ))}\n                    </div>\n                  )}\n                </div>\n              )}\n\n              </div>\n            </div>\n          </div>,\n          document.body,\n        )}\n\n      {/* Chart Data Modal (movido desde Sidebar) */}\n      <ChartDataModal\n        isOpen={isChartModalOpen}\n        onClose={() => setIsChartModalOpen(false)}\n        initialData={chartModalData}\n        initialType={chartModalType}\n        initialOptions={chartModalOptions}\n        onSave={handleSaveChartData}\n      />\n\n      {activeTool === 'brush' && (\n        <BrushToolPanel\n          anchorRef={brushAnchorRef}\n          onClose={() => setActiveTool('select')}\n          brushSettings={brushSettings}\n          updateBrushSettings={updateBrushSettings}\n        />\n      )}\n\n      {activeTool === 'magic-eraser' && (\n        <MagicEraserToolPanel\n          anchorRef={eraserAnchorRef}\n          onClose={() => setActiveTool('select')}\n        />\n      )}\n\n      {activeTool === 'paint-bucket' && (\n        <PaintBucketToolPanel\n          anchorRef={paintBucketAnchorRef}\n          onClose={() => setActiveTool('select')}\n        />\n      )}\n\n      {activeTool === 'clone-stamp' && (\n        <CloneStampToolPanel\n          anchorRef={cloneStampAnchorRef}\n          onClose={() => setActiveTool('select')}\n        />\n      )}\n\n      {activeTool === 'magic-wand' && (\n        <MagicWandToolPanel\n          anchorRef={wandAnchorRef}\n          onClose={() => setActiveTool('select')}\n        />\n      )}\n\n      {(activeTool === 'select-rect' || activeTool === 'select-ellipse') && (\n        <MagicWandToolPanel\n          anchorRef={lassoAnchorRef}\n          onClose={() => setActiveTool('select')}\n          lassoMode\n          shapeMode={activeTool === 'select-ellipse' ? 'ellipse' : 'rect'}\n        />\n      )}\n\n      {activeTool === 'pixel-lasso' && (\n        <MagicWandToolPanel\n          anchorRef={lassoAnchorRef}\n          onClose={() => setActiveTool('select')}\n          lassoMode\n        />\n      )}\n\n      {activeTool === 'polygon-lasso' && (\n        <MagicWandToolPanel\n          anchorRef={lassoAnchorRef}\n          onClose={() => setActiveTool('select')}\n          lassoMode\n          polygonMode\n        />\n      )}\n\n      {activeTool === 'eraser' && (\n        <EraserToolPanel\n          anchorRef={eraserAnchorRef}\n          onClose={() => setActiveTool('select')}\n        />\n      )}\n\n      {/* Panel flotante del Simulador de Daltonismo */}\n      {(activeToolPanel === 'colorblind') && (\n        <CanvasColorblindPanel\n          anchorRef={colorBlindAnchorRef}\n          onClose={() => dismissToolPanels()}\n        />\n      )}\n\n      <CanvasUploadPanel\n        open={activeToolPanel === 'upload'}\n        onClose={() => dismissToolPanels()}\n        processUploadedFile={processUploadedFile}\n        handleAddImageLayer={handleAddImageLayer}\n        panelFileInputRef={panelFileInputRef}\n      />\n\n      {/* Rulers overlay */}\n      {rulersEnabled && (\n        <>\n          <canvas ref={hrulerRef} className=\"absolute top-0 left-[20px] right-0 h-[20px] z-20 pointer-events-none\" />\n          <canvas ref={vrulerRef} className=\"absolute top-[20px] left-0 bottom-0 w-[20px] z-20 pointer-events-none\" />\n          <div className=\"absolute top-0 left-0 w-[20px] h-[20px] bg-dark-900 border-r border-b border-dark-850 z-30 flex items-center justify-center text-[8px] text-zinc-500 font-bold font-mono select-none\">\n            px\n          </div>\n        </>\n      )}\n\n      <CropOverlay />\n      <PenToolOverlay />\n      <BooleanOperationsMenu />\n      <MaskEditorPanel />\n      {radiusPopup && (\n        <BrushRadiusPopup x={radiusPopup.x} y={radiusPopup.y} onClose={() => setRadiusPopup(null)} />\n      )}\n      <BrushSizeCenterPreview />\n\n      {/* Floating Crop Mask Control */}\n      {croppingObj && (\n        <div \n          className=\"absolute top-24 left-1/2 -translate-x-1/2 z-40 bg-brand-500 hover:bg-brand-600 active:scale-95 text-white font-bold text-xs px-4 py-2.5 rounded-full shadow-xl flex items-center gap-2 cursor-pointer transition-all border border-brand-400 select-none animate-bounce\" \n          onClick={finishCropping}\n        >\n          <span>{t.canvas.finishCropMask}</span>\n        </div>\n      )}\n\n      {/* SVG Filters for Color Blindness Simulation */}\n      <svg className=\"absolute w-0 h-0 pointer-events-none\" aria-hidden=\"true\">\n        <defs>\n          <filter id=\"cb-protanopia\" colorInterpolationFilters=\"sRGB\">\n            <feColorMatrix type=\"matrix\" values=\"0.567 0.433 0 0 0  0.558 0.442 0 0 0  0 0.242 0.758 0 0  0 0 0 1 0\" />\n          </filter>\n          <filter id=\"cb-deuteranopia\" colorInterpolationFilters=\"sRGB\">\n            <feColorMatrix type=\"matrix\" values=\"0.625 0.375 0 0 0  0.7 0.3 0 0 0  0 0.3 0.7 0 0  0 0 0 1 0\" />\n          </filter>\n          <filter id=\"cb-tritanopia\" colorInterpolationFilters=\"sRGB\">\n            <feColorMatrix type=\"matrix\" values=\"0.95 0.05 0 0 0  0 0.433 0.567 0 0  0 0.475 0.525 0 0  0 0 0 1 0\" />\n          </filter>\n        </defs>\n      </svg>\n\n      {/* Outer Workspace Container (Checkerboard Background styled as Dot Grid) */}\n      <div\n        ref={containerRef}\n        onDragOver={(e) => e.preventDefault()}\n        onDrop={handleDrop}\n        onPointerDown={(e) => {\n          // Deselect Fabric object + pixel mask when clicking outside the page stage.\n          if (e.button !== 0) return;\n          const target = e.target as HTMLElement | null;\n          if (!target) return;\n          if (\n            target.closest(\n              'aside, button, a, input, textarea, select, label, [role=\"dialog\"], [role=\"menu\"], [role=\"listbox\"], [data-we-no-deselect]',\n            )\n          ) {\n            return;\n          }\n          if (pageStageRef.current?.contains(target)) return;\n\n          const canvas = fabricCanvasRef.current ?? canvasInstance;\n          if (canvas) {\n            canvas.discardActiveObject();\n            canvas.requestRenderAll();\n          }\n          setActiveObject(null);\n          useEditorStore.getState().clearMagicWandSelection();\n        }}\n        onPointerMove={handlePointerMove}\n        onPointerLeave={handlePointerLeave}\n        onContextMenu={handleContextMenu}\n        className=\"flex-1 min-h-0 overflow-hidden canvas-checkerboard relative select-none\"\n        style={{\n          marginTop: rulersEnabled ? '20px' : '0px',\n          marginLeft: rulersEnabled ? '20px' : '0px',\n        }}\n      >\n        <style>\n          {`\n            /* Force SVG filter on the fabric container and its children canvases */\n            .color-blindness-target,\n            .color-blindness-target canvas {\n               filter: ${colorBlindnessMode !== 'normal' ? `url(#cb-${colorBlindnessMode})` : 'none'} !important;\n               -webkit-filter: ${colorBlindnessMode !== 'normal' ? `url(#cb-${colorBlindnessMode})` : 'none'} !important;\n            }\n          `}\n        </style>\n\n        {/* Pannable workspace \u2014 transform offset instead of scroll (unbounded free canvas) */}\n        <div\n          ref={panLayerRef}\n          className=\"absolute left-1/2 top-1/2 will-change-transform\"\n          style={{\n            transform: `translate(calc(-50% + ${workspacePan.x}px), calc(-50% + ${workspacePan.y}px))`,\n          }}\n        >\n          {/* Page frame + size chip. Object pixels stay clipped to the page;\n              selection chrome is drawn by SelectionControlsOverlay above. */}\n          <div\n            ref={pageFrameRef}\n            className=\"relative overflow-visible\"\n            style={{\n              width: activePage.width * zoom,\n              height: activePage.height * zoom,\n            }}\n          >\n            <div className=\"absolute left-1/2 top-0 z-20 -translate-x-1/2 -translate-y-full\">\n              <CanvasSizeChip zoom={zoom} />\n            </div>\n            <div\n              ref={pageStageRef}\n              className=\"color-blindness-target relative h-full w-full overflow-hidden border border-white/[0.04] bg-white shadow-[0_25px_60px_rgba(0,0,0,0.55)]\"\n            >\n              <FabricCanvasHost canvasRef={canvasRef} />\n              <MarqueeSelectOverlay />\n              <CloneStampOverlay />\n              <MagicWandOverlay />\n              <PaintBucketOverlay />\n              <ShapeLassoOverlay />\n              <PixelLassoOverlay />\n              <PolygonLassoOverlay />\n              <PixelEraserOverlay />\n              <MaskPaintOverlay />\n              <PixelSelectionMarchingAnts />\n            </div>\n            {/* Outside pageStage clip so handles stay visible off-artboard;\n                inside panLayer so chrome pans/zooms with the page (no lag). */}\n            <SelectionControlsOverlay hostRef={pageFrameRef} />\n            <AiLoadingOverlay hostRef={pageFrameRef} />\n          </div>\n        </div>\n\n        {/* Dynamic Brush HUD Cursor */}\n        {(activeTool === 'brush' ||\n          activeTool === 'magic-eraser' ||\n          activeTool === 'clone-stamp' ||\n          activeTool === 'eraser') &&\n          hudPos && (\n          <div\n            className=\"absolute pointer-events-none rounded-full border border-white shadow-[0_0_0_1px_rgba(0,0,0,0.5)] z-50 -translate-x-1/2 -translate-y-1/2\"\n            style={{\n              left: hudPos.x,\n              top: hudPos.y,\n              width: Math.max(4, brushSettings.width * zoom),\n              height: Math.max(4, brushSettings.width * zoom),\n              backgroundColor: hexToRgba(brushSettings.color, 0.15),\n            }}\n          />\n        )}\n\n        {/* Dynamic Eyedropper HUD \u2014 sample point at cursor; preview + label offset top-right */}\n        {activeTool === 'eyedropper' && hudPos && (() => {\n          const activeObj = eyedropperTargetRef.current;\n          let targetLabel = eye.pageBackground;\n          let isInvalid = false;\n          if (activeObj) {\n            const typeStr = activeObj.type?.toLowerCase() || '';\n            if (['image', 'group'].includes(typeStr)) {\n              targetLabel = eye.invalidImage;\n              isInvalid = true;\n            } else if (['textbox', 'text', 'i-text'].includes(typeStr)) {\n              targetLabel = eye.selectedText;\n            } else {\n              targetLabel = eye.selectedShape;\n            }\n          }\n\n          return (\n            <div\n              className=\"pointer-events-none absolute z-50\"\n              style={{ left: hudPos.x, top: hudPos.y }}\n            >\n              {/* Exact sample point under the cursor */}\n              <div\n                className=\"absolute left-0 top-0 size-1.5 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white ring-1 ring-black/70\"\n                aria-hidden\n              />\n              {/* Preview + label offset so they don't cover the pixel being sampled */}\n              <div className=\"absolute left-0 top-0 flex translate-x-3 -translate-y-[calc(100%+8px)] flex-col items-start gap-1.5\">\n                <div\n                  className=\"size-11 rounded-full border-[3px] border-white shadow-[0_8px_16px_rgba(0,0,0,0.45)]\"\n                  style={{ backgroundColor: eyedropperColor }}\n                />\n                <div\n                  className={`rounded-lg border px-2.5 py-1.5 text-[11px] font-bold shadow-xl backdrop-blur-md ${\n                    isInvalid\n                      ? 'border-red-400 bg-red-500/90 text-white'\n                      : 'border-dark-700 bg-dark-900/90 text-zinc-400'\n                  }`}\n                >\n                  <div className=\"whitespace-nowrap\">\n                    {eye.paint} <TextBody as=\"span\" size=\"sm\" className=\"ml-1 text-white\">{targetLabel}</TextBody>\n                  </div>\n                  <div className=\"mt-0.5 select-none text-[10px] font-medium text-white/80\">\n                    {eye.cancelSpaceHint}\n                  </div>\n                </div>\n              </div>\n            </div>\n          );\n        })()}\n      </div>\n\n      {/* Dynamic Context Menu */}\n      {contextMenu.visible && (\n        <>\n          <div \n            className=\"fixed inset-0 z-40 cursor-default\" \n            onClick={() => setContextMenu(prev => ({ ...prev, visible: false }))} \n            onContextMenu={(e) => { \n              e.preventDefault(); \n              setContextMenu(prev => ({ ...prev, visible: false })); \n            }} \n          />\n          <div\n            ref={contextMenuRef}\n            className=\"fixed z-50 min-w-[210px] rounded-xl border border-dark-800/80 bg-dark-950/90 backdrop-blur-md shadow-[0_20px_50px_rgba(0,0,0,0.6)] p-1.5 flex flex-col gap-0.5 animate-fade-in select-none text-left\"\n            style={{ left: contextMenu.x, top: contextMenu.y }}\n          >\n            {contextMenu.targetObject ? (\n              <>\n                {/* Object Specific Options */}\n                <div className=\"px-2.5 py-1 text-[9px] uppercase font-bold text-dark-500 tracking-wider\">\n                  {cm.objectActions}\n                </div>\n                \n                <button\n                  onClick={() => {\n                    handleDuplicate(contextMenu.targetObject);\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  className=\"w-full flex items-center justify-between px-2.5 py-1.5 text-xs text-zinc-300 hover:text-white hover:bg-white/5 rounded-lg transition-colors cursor-pointer\"\n                >\n                  <div className=\"flex items-center gap-2\">\n                    <Copy size={13} className=\"text-dark-400\" />\n                    <span>{cm.duplicate}</span>\n                  </div>\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-dark-500 font-mono\">{modShortcut('D')}</TextBody>\n                </button>\n\n                <button\n                  onClick={() => {\n                    handleToggleLock(contextMenu.targetObject);\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-zinc-300 hover:text-white hover:bg-white/5 rounded-lg transition-colors cursor-pointer\"\n                >\n                  {contextMenu.targetObject.lockMovementX ? (\n                    <>\n                      <Unlock size={13} className=\"text-amber-500\" />\n                      <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-amber-400\">{cm.unlock}</TextBody>\n                    </>\n                  ) : (\n                    <>\n                      <Lock size={13} className=\"text-dark-400\" />\n                      <TextBody as=\"span\" size=\"sm\">{cm.lock}</TextBody>\n                    </>\n                  )}\n                </button>\n\n                {(\n                  (activeObject && getType(activeObject) === 'activeselection') ||\n                  (contextMenu.targetObject && getType(contextMenu.targetObject) === 'activeselection') ||\n                  (fabricCanvasRef.current && fabricCanvasRef.current.getActiveObjects().length > 1)\n                ) && (\n                  <button\n                    onClick={() => {\n                      groupSelectedObjects();\n                      setContextMenu(prev => ({ ...prev, visible: false }));\n                    }}\n                    className=\"w-full flex items-center justify-between px-2.5 py-1.5 text-xs text-[var(--we-accent)] hover:text-white hover:bg-[var(--we-accent-muted)] rounded-lg transition-colors cursor-pointer font-bold\"\n                  >\n                    <div className=\"flex items-center gap-2\">\n                      <FolderPlus size={13} />\n                      <span>{cm.groupLayers}</span>\n                    </div>\n                    <TextBody as=\"span\" size=\"sm\" className=\"font-mono opacity-70\">{modShortcut('G')}</TextBody>\n                  </button>\n                )}\n\n                {activeObject && getType(activeObject) === 'group' && !['canva-frame', 'canva-frame-clipped'].includes((activeObject as any).name) && (\n                  <button\n                    onClick={() => {\n                      ungroupObjects();\n                      setContextMenu(prev => ({ ...prev, visible: false }));\n                    }}\n                    className=\"w-full flex items-center justify-between px-2.5 py-1.5 text-xs text-amber-400 hover:text-amber-300 hover:bg-amber-500/10 rounded-lg transition-colors cursor-pointer font-bold\"\n                  >\n                    <div className=\"flex items-center gap-2\">\n                      <FolderMinus size={13} />\n                      <span>{cm.ungroup}</span>\n                    </div>\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-amber-500 font-mono\">{isApplePlatform() ? '\u2318\u21E7G' : 'Ctrl+Shift+G'}</TextBody>\n                  </button>\n                )}\n\n                <div className=\"h-px bg-dark-850 my-1 mx-1.5\" />\n\n                <div className=\"px-2.5 py-0.5 text-[9px] uppercase font-bold text-dark-500 tracking-wider\">\n                  {cm.organizeLayers}\n                </div>\n\n                <button\n                  onClick={() => {\n                    handleBringToFront(contextMenu.targetObject);\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-zinc-300 hover:text-white hover:bg-white/5 rounded-lg transition-colors cursor-pointer font-semibold\"\n                >\n                  <ChevronsUp size={13} className=\"text-dark-400\" />\n                  <span>{cm.bringToFront}</span>\n                </button>\n\n                <button\n                  onClick={() => {\n                    handleBringForward(contextMenu.targetObject);\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-zinc-300 hover:text-white hover:bg-white/5 rounded-lg transition-colors cursor-pointer\"\n                >\n                  <ChevronUp size={13} className=\"text-dark-400\" />\n                  <span>{cm.bringForward}</span>\n                </button>\n\n                <button\n                  onClick={() => {\n                    handleSendBackward(contextMenu.targetObject);\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-zinc-300 hover:text-white hover:bg-white/5 rounded-lg transition-colors cursor-pointer\"\n                >\n                  <ChevronDown size={13} className=\"text-dark-400\" />\n                  <span>{cm.sendBackward}</span>\n                </button>\n\n                <button\n                  onClick={() => {\n                    handleSendToBack(contextMenu.targetObject);\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-zinc-300 hover:text-white hover:bg-white/5 rounded-lg transition-colors cursor-pointer font-semibold\"\n                >\n                  <ChevronsDown size={13} className=\"text-dark-400\" />\n                  <span>{cm.sendToBack}</span>\n                </button>\n\n                <div className=\"h-px bg-dark-850 my-1 mx-1.5\" />\n\n                <div className=\"px-2.5 py-0.5 text-[9px] uppercase font-bold text-dark-500 tracking-wider\">\n                  {cm.stylesAndMasks}\n                </div>\n\n                <button\n                  onClick={() => {\n                    handleCopyStyle(contextMenu.targetObject);\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-zinc-300 hover:text-white hover:bg-white/5 rounded-lg transition-colors cursor-pointer\"\n                >\n                  <Paintbrush size={13} className=\"text-dark-400\" />\n                  <span>{cm.copyStyle}</span>\n                </button>\n\n                <button\n                  onClick={() => {\n                    handlePasteStyle(contextMenu.targetObject);\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  disabled={!useEditorStore.getState().copiedStyle}\n                  className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-zinc-300 hover:text-white hover:bg-white/5 rounded-lg transition-colors disabled:opacity-35 disabled:cursor-not-allowed cursor-pointer\"\n                >\n                  <Clipboard size={13} className=\"text-dark-400\" />\n                  <span>{cm.pasteStyle}</span>\n                </button>\n\n                {getType(contextMenu.targetObject) === 'image' && (\n                  <>\n                    <div className=\"h-px bg-dark-850 my-1 mx-1.5\" />\n                    <div className=\"px-2.5 py-0.5 text-[9px] uppercase font-bold text-dark-500 tracking-wider\">\n                      {cm.quickMask}\n                    </div>\n                    <div className=\"grid grid-cols-5 gap-1 px-2 py-1\">\n                      <button\n                        onClick={() => {\n                          applyInstantMask(contextMenu.targetObject, 'circle');\n                          setContextMenu(prev => ({ ...prev, visible: false }));\n                        }}\n                        className=\"py-1 px-0.5 bg-white/5 hover:bg-brand-500/20 border border-dark-800 hover:border-brand-500/50 rounded text-[9px] text-zinc-300 hover:text-white transition-all cursor-pointer font-bold text-center\"\n                        title={cm.maskCircleTitle}\n                      >\n                        {cm.maskCircle}\n                      </button>\n                      <button\n                        onClick={() => {\n                          applyInstantMask(contextMenu.targetObject, 'rounded-rect');\n                          setContextMenu(prev => ({ ...prev, visible: false }));\n                        }}\n                        className=\"py-1 px-0.5 bg-white/5 hover:bg-brand-500/20 border border-dark-800 hover:border-brand-500/50 rounded text-[9px] text-zinc-300 hover:text-white transition-all cursor-pointer font-bold text-center\"\n                        title={cm.maskRoundedTitle}\n                      >\n                        {cm.maskRounded}\n                      </button>\n                      <button\n                        onClick={() => {\n                          applyInstantMask(contextMenu.targetObject, 'heart');\n                          setContextMenu(prev => ({ ...prev, visible: false }));\n                        }}\n                        className=\"py-1 px-0.5 bg-white/5 hover:bg-brand-500/20 border border-dark-800 hover:border-brand-500/50 rounded text-[9px] text-zinc-300 hover:text-white transition-all cursor-pointer font-bold text-center\"\n                        title={cm.maskHeartTitle}\n                      >\n                        {cm.maskHeart}\n                      </button>\n                      <button\n                        onClick={() => {\n                          applyInstantMask(contextMenu.targetObject, 'star');\n                          setContextMenu(prev => ({ ...prev, visible: false }));\n                        }}\n                        className=\"py-1 px-0.5 bg-white/5 hover:bg-brand-500/20 border border-dark-800 hover:border-brand-500/50 rounded text-[9px] text-zinc-300 hover:text-white transition-all cursor-pointer font-bold text-center\"\n                        title={cm.maskStarTitle}\n                      >\n                        {cm.maskStar}\n                      </button>\n                      <button\n                        onClick={() => {\n                          applyInstantMask(contextMenu.targetObject, 'triangle');\n                          setContextMenu(prev => ({ ...prev, visible: false }));\n                        }}\n                        className=\"py-1 px-0.5 bg-white/5 hover:bg-brand-500/20 border border-dark-800 hover:border-brand-500/50 rounded text-[9px] text-zinc-300 hover:text-white transition-all cursor-pointer font-bold text-center\"\n                        title={cm.maskTriangleTitle}\n                      >\n                        {cm.maskTriangle}\n                      </button>\n                    </div>\n                  </>\n                )}\n\n                <div className=\"h-px bg-dark-850 my-1 mx-1.5\" />\n\n                <div className=\"px-2.5 py-0.5 text-[9px] uppercase font-bold text-dark-500 tracking-wider\">\n                  {cm.smartLinking}\n                </div>\n\n                <button\n                  onClick={() => {\n                    useEditorStore.getState().linkSelectedObjects();\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-zinc-300 hover:text-white hover:bg-white/5 rounded-lg transition-colors cursor-pointer\"\n                >\n                  <Link2 size={13} className=\"text-brand-500\" />\n                  <span>{cm.link}</span>\n                </button>\n\n                {contextMenu.targetObject?.linkId && (\n                  <button\n                    onClick={() => {\n                      useEditorStore.getState().unlinkSelectedObjects();\n                      setContextMenu(prev => ({ ...prev, visible: false }));\n                    }}\n                    className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-zinc-300 hover:text-white hover:bg-white/5 rounded-lg transition-colors cursor-pointer\"\n                  >\n                    <Unlink size={13} className=\"text-dark-400\" />\n                    <span>{cm.unlink}</span>\n                  </button>\n                )}\n\n                <div className=\"h-px bg-dark-850 my-1 mx-1.5\" />\n\n                {(contextMenu.targetObject.clipPath || (getType(contextMenu.targetObject) === 'group' && contextMenu.targetObject.name === 'canva-frame-clipped')) && (\n                  <button\n                    onClick={() => {\n                      releaseClippingMask();\n                      setContextMenu(prev => ({ ...prev, visible: false }));\n                    }}\n                    className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-amber-400 hover:text-amber-300 hover:bg-amber-500/10 rounded-lg transition-colors cursor-pointer font-bold\"\n                  >\n                    <span>{cm.releaseMask}</span>\n                  </button>\n                )}\n\n                {/* AI Magic Actions Contextual Options */}\n                {((getType(contextMenu.targetObject) === 'image') || \n                  (getType(contextMenu.targetObject) === 'path') || \n                  (getType(contextMenu.targetObject) === 'rect') || \n                  (activeObject && (getType(activeObject) === 'activeselection' || getType(activeObject) === 'group'))) && (\n                  <>\n                    <div className=\"h-px bg-dark-850 my-1 mx-1.5\" />\n                    <div className=\"px-2.5 py-0.5 text-[9px] uppercase font-bold text-brand-400 tracking-wider flex items-center gap-1\">\n                      <Sparkles size={9} className=\"text-brand-400 animate-pulse\" />\n                      <span>{cm.aiMagic}</span>\n                    </div>\n\n                    {/* Magic eraser / mask edit \u2014 paint marks then Apply */}\n                    {getType(contextMenu.targetObject) === 'image' && (\n                      <button\n                        onClick={() => {\n                          const target = contextMenu.targetObject;\n                          if (target && fabricCanvasRef.current) {\n                            const id =\n                              (target as { id?: string }).id ||\n                              `img-${Date.now()}`;\n                            if (!(target as { id?: string }).id) {\n                              target.set({ id } as never);\n                            }\n                            fabricCanvasRef.current.setActiveObject(target);\n                            useEditorStore.getState().setActiveObject(target);\n                            useEditorStore.getState().setMagicEraserTargetId(id);\n                          }\n                          useEditorStore.getState().setLayerPaintTarget('content');\n                          // Separate tool \u2014 do not overwrite the user's brush style settings.\n                          updateBrushSettings({ opacity: 0.5 });\n                          setEraserGroupTool('magic-eraser');\n                          setActiveTool('magic-eraser');\n                          setContextMenu((prev) => ({ ...prev, visible: false }));\n                        }}\n                        disabled={isAiGenerating}\n                        className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-purple-300 hover:text-purple-200 hover:bg-purple-500/10 rounded-lg transition-colors cursor-pointer font-bold disabled:opacity-40\"\n                      >\n                        <PencilSparkles size={13} className=\"text-purple-400\" />\n                        <span>{cm.maskEditing}</span>\n                      </button>\n                    )}\n\n                    {/* Quitar Fondo option */}\n                    {getType(contextMenu.targetObject) === 'image' && (\n                      <button\n                        onClick={() => {\n                          runRemoveBg();\n                          setContextMenu(prev => ({ ...prev, visible: false }));\n                        }}\n                        disabled={isAiGenerating}\n                        className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-purple-300 hover:text-purple-200 hover:bg-purple-500/10 rounded-lg transition-colors cursor-pointer font-bold disabled:opacity-40\"\n                      >\n                        <Sparkles size={13} className=\"text-purple-400\" />\n                        <span>{cm.removeBg}</span>\n                      </button>\n                    )}\n\n                    {/* Separar Sujeto option */}\n                    {getType(contextMenu.targetObject) === 'image' && (\n                      <button\n                        onClick={() => {\n                          runSelectSubject();\n                          setContextMenu(prev => ({ ...prev, visible: false }));\n                        }}\n                        disabled={isAiGenerating}\n                        className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-purple-300 hover:text-purple-200 hover:bg-purple-500/10 rounded-lg transition-colors cursor-pointer font-bold disabled:opacity-40\"\n                      >\n                        <Sparkles size={13} className=\"text-purple-400\" />\n                        <span>{cm.separateSubject}</span>\n                      </button>\n                    )}\n\n                    {/* Generar en \u00C1rea option */}\n                    {getType(contextMenu.targetObject) === 'rect' && (\n                      <button\n                        onClick={() => {\n                          void (async () => {\n                            setContextMenu((prev) => ({ ...prev, visible: false }));\n                            const userPrompt = await dialog.prompt(cm.generateInAreaPrompt, {\n                              title: cm.generateInArea,\n                              placeholder: t.canvas.aiStudio.generador.inAreaPlaceholder,\n                              confirmText: t.canvas.aiStudio.generador.generateInArea,\n                            });\n                            if (userPrompt?.trim()) {\n                              void runGenerateInArea(userPrompt.trim());\n                            }\n                          })();\n                        }}\n                        disabled={isAiGenerating}\n                        className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-[var(--we-accent)] hover:text-[var(--we-accent-hover)] hover:bg-[var(--we-accent-muted)] rounded-lg transition-colors cursor-pointer font-bold disabled:opacity-40\"\n                      >\n                        <Sparkles size={13} className=\"text-[var(--we-accent)]\" />\n                        <span>{cm.generateInArea}</span>\n                      </button>\n                    )}\n\n                    {/* Boceto a Imagen option */}\n                    {(getType(contextMenu.targetObject) === 'path' || (activeObject && getType(activeObject) === 'activeselection')) && (\n                      <button\n                        onClick={() => {\n                          void (async () => {\n                            setContextMenu((prev) => ({ ...prev, visible: false }));\n                            const userPrompt = await dialog.prompt(cm.sketchToImagePrompt, {\n                              title: cm.sketchToImage,\n                              confirmText: cm.sketchToImage,\n                            });\n                            if (userPrompt?.trim()) {\n                              void runSketchToImage(userPrompt.trim());\n                            }\n                          })();\n                        }}\n                        disabled={isAiGenerating}\n                        className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-pink-300 hover:text-pink-200 hover:bg-pink-500/10 rounded-lg transition-colors cursor-pointer font-bold disabled:opacity-40\"\n                      >\n                        <Sparkles size={13} className=\"text-pink-400\" />\n                        <span>{cm.sketchToImage}</span>\n                      </button>\n                    )}\n\n                    {/* Convert to Path (Only for Custom Fonts) */}\n                    {(getType(contextMenu.targetObject) === 'textbox' || getType(contextMenu.targetObject) === 'itext' || getType(contextMenu.targetObject) === 'text') && (\n                      <button\n                        onClick={async () => {\n                          const obj = contextMenu.targetObject;\n                          const fontName = obj.fontFamily;\n                          const customFont = customFonts.find(f => f.name === fontName);\n                          \n                          if (customFont) {\n                            const pathObj = await convertTextToPath(obj, customFont.dataUrl);\n                            if (pathObj && fabricCanvasRef.current) {\n                              fabricCanvasRef.current.remove(obj);\n                              fabricCanvasRef.current.add(pathObj);\n                              fabricCanvasRef.current.setActiveObject(pathObj);\n                              fabricCanvasRef.current.requestRenderAll();\n                              saveHistoryState();\n                            } else {\n                              dialog.alert(cm.convertError, { title: cm.convertErrorTitle, variant: \"error\" });\n                            }\n                          } else {\n                            dialog.alert(cm.convertCustomOnly, { title: cm.convertCustomOnlyTitle, variant: \"warning\" });\n                          }\n                          setContextMenu(prev => ({ ...prev, visible: false }));\n                        }}\n                        className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-orange-300 hover:text-orange-200 hover:bg-orange-500/10 rounded-lg transition-colors cursor-pointer font-bold\"\n                      >\n                        <PenTool size={13} className=\"text-orange-400\" />\n                        <span>{cm.convertToCurves}</span>\n                      </button>\n                    )}\n                  </>\n                )}\n\n                {/* Text on Path / Mask operations for ActiveSelection */}\n                {contextMenu.targetObject && contextMenu.targetObject.type === 'activeselection' && (\n                  <>\n                    <div className=\"h-px bg-dark-850 my-1 mx-1.5\" />\n                    \n                    {(() => {\n                      const objects = contextMenu.targetObject.getObjects();\n                      const hasText = objects.some((o: any) => o.type === 'textbox' || o.type === 'itext' || o.type === 'text');\n                      const hasPath = objects.some((o: any) => o.type === 'path');\n                      const hasImage = objects.some((o: any) => o.type === 'image');\n                      \n                      return (\n                        <>\n                          {hasText && hasPath && objects.length === 2 && (\n                            <button\n                              onClick={() => {\n                                handleTextOnPath(contextMenu.targetObject);\n                                setContextMenu(prev => ({ ...prev, visible: false }));\n                              }}\n                              className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-brand-300 hover:text-white hover:bg-brand-500/20 rounded-lg transition-colors cursor-pointer font-bold\"\n                            >\n                              <Type size={13} className=\"text-brand-400\" />\n                              <span>{cm.textOnPath}</span>\n                            </button>\n                          )}\n                          \n                          {hasText && hasImage && objects.length === 2 && (\n                            <button\n                              onClick={() => {\n                                handleTextMask(contextMenu.targetObject);\n                                setContextMenu(prev => ({ ...prev, visible: false }));\n                              }}\n                              className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-brand-300 hover:text-white hover:bg-brand-500/20 rounded-lg transition-colors cursor-pointer font-bold\"\n                            >\n                              <Scissors size={13} className=\"text-brand-400\" />\n                              <span>{cm.textMask}</span>\n                            </button>\n                          )}\n                        </>\n                      );\n                    })()}\n                  </>\n                )}\n\n                <div className=\"h-px bg-dark-850 my-1 mx-1.5\" />\n\n                <button\n                  onClick={() => {\n                    handleCopy(contextMenu.targetObject);\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  className=\"w-full flex items-center justify-between px-2.5 py-1.5 text-xs text-zinc-300 hover:text-white hover:bg-white/5 rounded-lg transition-colors cursor-pointer\"\n                >\n                  <div className=\"flex items-center gap-2\">\n                    <Copy size={13} className=\"text-dark-400\" />\n                    <span>{cm.copyObject}</span>\n                  </div>\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-dark-500 font-mono\">{modShortcut('C')}</TextBody>\n                </button>\n\n                <button\n                  onClick={() => {\n                    handleExportSelection(contextMenu.targetObject);\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-zinc-300 hover:text-white hover:bg-white/5 rounded-lg transition-colors cursor-pointer\"\n                >\n                  <Clipboard size={13} className=\"text-dark-400\" />\n                  <span>{cm.exportLayer}</span>\n                </button>\n\n                <button\n                  onClick={async () => {\n                    await handleDelete(contextMenu.targetObject);\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  className=\"w-full flex items-center justify-between px-2.5 py-1.5 text-xs text-rose-400 hover:text-rose-300 hover:bg-rose-500/10 rounded-lg transition-colors cursor-pointer font-semibold\"\n                >\n                  <div className=\"flex items-center gap-2\">\n                    <Trash2 size={13} />\n                    <span>{cm.delete}</span>\n                  </div>\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-rose-500/60 font-mono\">Del</TextBody>\n                </button>\n              </>\n            ) : (\n              <>\n                {/* General/Canvas Options */}\n                <div className=\"px-2.5 py-1 text-[9px] uppercase font-bold text-dark-500 tracking-wider\">\n                  {cm.generalActions}\n                </div>\n\n                <button\n                  onClick={() => {\n                    handlePaste();\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  disabled={!clipboard}\n                  className=\"w-full flex items-center justify-between px-2.5 py-1.5 text-xs text-zinc-300 hover:text-white hover:bg-white/5 rounded-lg transition-colors disabled:opacity-35 disabled:cursor-not-allowed cursor-pointer\"\n                >\n                  <div className=\"flex items-center gap-2\">\n                    <Clipboard size={13} className=\"text-dark-400\" />\n                    <span>{cm.paste}</span>\n                  </div>\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-dark-500 font-mono\">{modShortcut('V')}</TextBody>\n                </button>\n\n                <button\n                  onClick={() => {\n                    const canvas = canvasInstance || fabricCanvasRef.current;\n                    if (canvas && canvas.getActiveObject()) {\n                      handlePasteStyle(canvas.getActiveObject());\n                    }\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  disabled={!useEditorStore.getState().copiedStyle || !(canvasInstance || fabricCanvasRef.current)?.getActiveObject()}\n                  className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-zinc-300 hover:text-white hover:bg-white/5 rounded-lg transition-colors disabled:opacity-35 disabled:cursor-not-allowed cursor-pointer\"\n                >\n                  <Paintbrush size={13} className=\"text-dark-400\" />\n                  <span>{cm.pasteStyle}</span>\n                </button>\n\n                <div className=\"h-px bg-dark-850 my-1 mx-1.5\" />\n\n                <button\n                  onClick={() => {\n                    useEditorStore.getState().setLayoutGridEnabled(!useEditorStore.getState().layoutGridEnabled);\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  className=\"w-full flex items-center justify-between px-2.5 py-1.5 text-xs text-zinc-300 hover:text-white hover:bg-white/5 rounded-lg transition-colors cursor-pointer\"\n                >\n                  <div className=\"flex items-center gap-2\">\n                    <Grid size={13} className=\"text-dark-400\" />\n                    <span>{cm.showGrid}</span>\n                  </div>\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400\">{useEditorStore.getState().layoutGridEnabled ? 'ON' : 'OFF'}</TextBody>\n                </button>\n\n                <button\n                  onClick={async () => {\n                    const ok = await dialog.confirm(t.layers.pages.clearCanvasBody, {\n                      title: t.layers.pages.clearCanvasTitle,\n                      variant: 'danger',\n                      confirmText: t.layers.pages.clearCanvasConfirm,\n                      cancelText: t.common.cancel,\n                    });\n                    if (!ok) return;\n                    if (canvasInstance) {\n                      canvasInstance.clear();\n                      setActiveObject(null);\n                      setLayers([]);\n                      applyCanvasBackground(canvasInstance, activePage.backgroundColor, activePage.width, activePage.height);\n                      saveHistoryState();\n                    }\n                    setContextMenu(prev => ({ ...prev, visible: false }));\n                  }}\n                  className=\"w-full flex items-center gap-2 px-2.5 py-1.5 text-xs text-rose-400 hover:text-rose-300 hover:bg-rose-500/10 rounded-lg transition-colors cursor-pointer font-semibold\"\n                >\n                  <RefreshCw size={13} />\n                  <span>{cm.clearCanvas}</span>\n                </button>\n              </>\n            )}\n          </div>\n        </>\n      )}\n\n      {/* Floating Magic Eraser actions \u2014 check applies clean, X cancels mask marks */}\n      {layers.length >= 0 && canvasInstance?.getObjects().some((obj: any) => obj.type?.toLowerCase() === 'path' && obj.name === 'eraser-mark') && (\n        <div className=\"absolute bottom-6 left-1/2 z-40 flex -translate-x-1/2 items-center gap-1 rounded-xl border border-panel-border bg-panel p-1.5 shadow-2xl animate-fade-in\">\n          <button\n            type=\"button\"\n            onClick={async () => {\n              const store = useEditorStore.getState();\n              const pinnedId = store.magicEraserTargetId || store.lastSelectedObjectId;\n              const pinned = pinnedId\n                ? canvasInstance\n                    ?.getObjects()\n                    .find((o: any) => o.id === pinnedId && o.type?.toLowerCase() === 'image')\n                : null;\n              const imageObj =\n                pinned ||\n                (canvasInstance?.getActiveObject()?.type?.toLowerCase() === 'image'\n                  ? canvasInstance.getActiveObject()\n                  : null);\n\n              if (imageObj) {\n                canvasInstance?.setActiveObject(imageObj);\n                setActiveObject(imageObj);\n                const id =\n                  (imageObj as { id?: string }).id || `img-${Date.now()}`;\n                if (!(imageObj as { id?: string }).id) {\n                  imageObj.set({ id } as never);\n                }\n                store.setMagicEraserTargetId(id);\n                canvasInstance?.requestRenderAll();\n              }\n              await runAiMagicEraser();\n            }}\n            disabled={isAiGenerating}\n            title={isAiGenerating ? t.canvas.magicEraserCleaning : t.canvas.magicEraserApply}\n            aria-label={isAiGenerating ? t.canvas.magicEraserCleaning : t.canvas.magicEraserApply}\n            className=\"flex size-9 items-center justify-center rounded-lg bg-[var(--we-accent)] text-white transition-all hover:bg-[var(--we-accent-hover)] active:scale-95 disabled:pointer-events-none disabled:opacity-40\"\n          >\n            <Check size={16} strokeWidth={2.5} aria-hidden />\n          </button>\n          <button\n            type=\"button\"\n            onClick={() => {\n              const eraserMarks = canvasInstance?.getObjects().filter((obj: any) => obj.name === 'eraser-mark') || [];\n              eraserMarks.forEach(mark => canvasInstance?.remove(mark));\n              canvasInstance?.requestRenderAll();\n              syncLayers();\n              saveHistoryState();\n            }}\n            disabled={isAiGenerating}\n            title={t.canvas.magicEraserClearMarks}\n            aria-label={t.canvas.magicEraserClearMarks}\n            className=\"flex size-9 items-center justify-center rounded-lg border border-panel-border bg-dark-850 text-white/80 transition-all hover:border-[var(--we-accent)]/40 hover:text-white active:scale-95 disabled:pointer-events-none disabled:opacity-40\"\n          >\n            <X size={16} strokeWidth={2.5} aria-hidden />\n          </button>\n        </div>\n      )}\n\n      {/* Version History Modal (desde men\u00FA de archivo en barra superior) */}\n      {isVersionHistoryModalOpen && <VersionHistoryModal onClose={() => setIsVersionHistoryModalOpen(false)} />}\n\n      </div>\n    </div>\n  );\n}\n\nexport default CanvasArea;\n", "import React, { useRef, useState } from 'react';\nimport { Minus, Plus } from 'lucide-react';\nimport { useAudioStore } from '../../store/useAudioStore';\nimport { useTranslation } from '../../i18n';\nimport { IconButton, TextBody, TextTitle } from '../ui';\n\n\nconst BPM_MIN = 20;\nconst BPM_MAX = 300;\nconst TAP_RESET_MS = 2200;\n\n/**\n * BPM capsule \u2014 tap tempo, half/double, nudge, and beat-snap enable.\n * Aligns timeline grid snapping to the project tempo.\n */\nexport const AudioBpmControl: React.FC = () => {\n  const t = useTranslation();\n  const te = t.audio.editor;\n  const bpm = useAudioStore((s) => s.bpm);\n  const snapEnabled = useAudioStore((s) => s.snapEnabled);\n  const setBpm = useAudioStore((s) => s.setBpm);\n  const setSnap = useAudioStore((s) => s.setSnap);\n  const addToast = useAudioStore((s) => s.addToast);\n\n  const tapsRef = useRef<number[]>([]);\n  const [tapFlash, setTapFlash] = useState(false);\n\n  const commitBpm = (next: number, enableBeatSnap = true) => {\n    const clamped = Math.round(Math.max(BPM_MIN, Math.min(BPM_MAX, next)));\n    setBpm(clamped);\n    if (enableBeatSnap && clamped > 0) {\n      setSnap(true, 'beat');\n    }\n  };\n\n  const onTap = () => {\n    const now = performance.now();\n    const taps = tapsRef.current.filter((ts) => now - ts < TAP_RESET_MS);\n    taps.push(now);\n    tapsRef.current = taps;\n    setTapFlash(true);\n    window.setTimeout(() => setTapFlash(false), 120);\n\n    if (taps.length < 2) {\n      addToast(te.bpmTapHint, 'info');\n      return;\n    }\n    const intervals: number[] = [];\n    for (let i = 1; i < taps.length; i++) {\n      intervals.push(taps[i]! - taps[i - 1]!);\n    }\n    // Use last up to 6 intervals for a stable average.\n    const sample = intervals.slice(-6);\n    const avgMs = sample.reduce((a, b) => a + b, 0) / sample.length;\n    if (avgMs <= 0) return;\n    const detected = Math.round(60000 / avgMs);\n    commitBpm(detected);\n    addToast(te.bpmTapSet(detected), 'success');\n  };\n\n  return (\n    <div className=\"ml-2 flex items-center gap-0.5 rounded-full border border-panel-border bg-black-capsule px-1 py-0.5\">\n      <TextTitle as=\"span\" size=\"xs\" className=\"px-1.5 uppercase tracking-wider text-white/80\">\n        {te.bpmLabel}\n      </TextTitle>\n      <IconButton\n        variant=\"ghost\"\n        size=\"sm\"\n        label={te.bpmDown}\n        className=\"!h-6 !w-6\"\n        onClick={() => commitBpm((bpm || 120) - 1)}\n      >\n        <Minus size={12} />\n      </IconButton>\n      <input\n        type=\"number\"\n        min={BPM_MIN}\n        max={BPM_MAX}\n        value={bpm || ''}\n        onChange={(e) => {\n          const raw = Number(e.target.value);\n          if (!Number.isFinite(raw)) {\n            setBpm(0);\n            return;\n          }\n          commitBpm(raw);\n        }}\n        title={te.bpmTitle}\n        aria-label={te.bpmTitle}\n        className=\"h-6 w-12 rounded-md border-0 bg-transparent px-0.5 text-center font-sans font-semibold text-white outline-none focus:bg-black-capsule-hover\"\n      />\n      <IconButton\n        variant=\"ghost\"\n        size=\"sm\"\n        label={te.bpmUp}\n        className=\"!h-6 !w-6\"\n        onClick={() => commitBpm((bpm || 120) + 1)}\n      >\n        <Plus size={12} />\n      </IconButton>\n      <button\n        type=\"button\"\n        title={te.bpmHalf}\n        onClick={() => {\n          if (bpm > 0) commitBpm(bpm / 2);\n        }}\n        className=\"h-6 rounded-md px-1.5 text-white/80 hover:bg-black-capsule-hover hover:text-white\"\n      >\n        <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n          /2\n        </TextBody>\n      </button>\n      <button\n        type=\"button\"\n        title={te.bpmDouble}\n        onClick={() => {\n          if (bpm > 0) commitBpm(bpm * 2);\n        }}\n        className=\"h-6 rounded-md px-1.5 text-white/80 hover:bg-black-capsule-hover hover:text-white\"\n      >\n        <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n          \u00D72\n        </TextBody>\n      </button>\n      <button\n        type=\"button\"\n        title={te.bpmTap}\n        onClick={onTap}\n        className={`h-6 rounded-md px-1.5 transition-colors ${\n          tapFlash\n            ? 'bg-[var(--we-accent)] text-white'\n            : 'text-white/80 hover:bg-black-capsule-hover hover:text-white'\n        }`}\n      >\n        <TextBody as=\"span\" size=\"sm\" className=\"font-bold\">\n          {te.bpmTapShort}\n        </TextBody>\n      </button>\n      <button\n        type=\"button\"\n        title={te.bpmBeatSnap}\n        aria-pressed={snapEnabled}\n        onClick={() => setSnap(!snapEnabled, 'beat')}\n        className={`mr-0.5 h-6 rounded-md px-1.5 transition-colors ${\n          snapEnabled\n            ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)]'\n            : 'text-white/80 hover:bg-black-capsule-hover hover:text-white'\n        }`}\n      >\n        <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n          {te.bpmGridShort}\n        </TextBody>\n      </button>\n    </div>\n  );\n};\n", "import React from 'react';\nimport {\n  Magnet,\n  Pause,\n  Play,\n  Redo2,\n  Repeat,\n  SkipBack,\n  SkipForward,\n  Square,\n  Undo2,\n  ZoomIn,\n  ZoomOut,\n} from 'lucide-react';\nimport { useAudioStore, AUDIO_ZOOM_MIN, AUDIO_ZOOM_MAX } from '../../store/useAudioStore';\nimport { getAudioEngine } from '../../lib/audio/AudioEngine';\nimport { useTranslation } from '../../i18n';\nimport { IconButton } from '../ui';\nimport { AudioBpmControl } from './AudioBpmControl';\n\nfunction formatTimecode(seconds: number): string {\n  const s = Math.max(0, seconds);\n  const m = Math.floor(s / 60);\n  const sec = Math.floor(s % 60);\n  const ms = Math.floor((s % 1) * 1000);\n  return `${String(m).padStart(2, '0')}:${String(sec).padStart(2, '0')}.${String(ms).padStart(3, '0')}`;\n}\n\n/**\n * Bottom chrome for Audio DAW: transport + undo/redo + timeline zoom capsule.\n */\nexport const AudioBottomToolbar: React.FC = () => {\n  const t = useTranslation();\n  const {\n    isPlaying,\n    playheadTime,\n    projectDuration,\n    loopEnabled,\n    loopStart,\n    loopEnd,\n    snapEnabled,\n    tracks,\n    assets,\n    masterVolumeDb,\n    zoom,\n    history,\n    historyIndex,\n    setIsPlaying,\n    setPlayhead,\n    setLoop,\n    setSnap,\n    setZoom,\n    undo,\n    redo,\n  } = useAudioStore();\n\n  const canUndo = historyIndex > 0;\n  const canRedo = historyIndex < history.length - 1;\n\n  const togglePlay = async () => {\n    const engine = getAudioEngine();\n    if (isPlaying) {\n      engine.pause();\n      setIsPlaying(false);\n      return;\n    }\n    engine.setProjectDuration(projectDuration);\n    engine.setLoop(loopEnabled, loopStart, loopEnd);\n    engine.setPlayheadCallback((time) => {\n      useAudioStore.getState().setPlayhead(time);\n    });\n    await engine.syncGraphs(tracks);\n    await engine.play({ tracks, assets, playheadTime, masterVolumeDb });\n    setIsPlaying(true);\n  };\n\n  React.useEffect(() => {\n    void getAudioEngine().syncGraphs(tracks);\n  }, [tracks]);\n\n  React.useEffect(() => {\n    getAudioEngine().setLoop(loopEnabled, loopStart, loopEnd);\n  }, [loopEnabled, loopStart, loopEnd]);\n\n  const stop = () => {\n    getAudioEngine().stop();\n    setIsPlaying(false);\n    setPlayhead(0);\n  };\n\n  const setZoomAnchored = (nextRaw: number) => {\n    const viewX = 200;\n    const timeSec = (useAudioStore.getState().scrollLeft + viewX) / zoom;\n    const next = Math.max(AUDIO_ZOOM_MIN, Math.min(AUDIO_ZOOM_MAX, nextRaw));\n    setZoom(next, { timeSec, viewX });\n  };\n\n  const zoomBy = (factor: number) => setZoomAnchored(zoom * factor);\n\n  return (\n    <div\n      data-testid=\"audio-bottom-toolbar\"\n      className=\"we-audio-transport flex h-11 shrink-0 items-center gap-1 border-t border-panel-border bg-panel px-2 select-none\"\n    >\n      <IconButton\n        variant=\"ghost\"\n        size=\"sm\"\n        label={t.audio.editor.shortcuts.undo}\n        disabled={!canUndo}\n        onClick={() => undo()}\n      >\n        <Undo2 size={15} />\n      </IconButton>\n      <IconButton\n        variant=\"ghost\"\n        size=\"sm\"\n        label={t.audio.editor.shortcuts.redo}\n        disabled={!canRedo}\n        onClick={() => redo()}\n      >\n        <Redo2 size={15} />\n      </IconButton>\n\n      <div className=\"mx-1 h-5 w-px bg-panel-border\" />\n\n      <IconButton variant=\"ghost\" size=\"sm\" label=\"Inicio\" onClick={() => setPlayhead(0)}>\n        <SkipBack size={14} />\n      </IconButton>\n      <button\n        type=\"button\"\n        onClick={() => void togglePlay()}\n        title={isPlaying ? 'Pausa' : 'Reproducir'}\n        className=\"flex h-8 w-8 items-center justify-center rounded-full bg-[var(--we-accent)] text-white shadow-sm hover:bg-[var(--we-accent-hover)]\"\n      >\n        {isPlaying ? <Pause size={15} /> : <Play size={15} className=\"ml-0.5\" />}\n      </button>\n      <IconButton variant=\"ghost\" size=\"sm\" label=\"Detener\" onClick={stop}>\n        <Square size={13} />\n      </IconButton>\n      <IconButton\n        variant=\"ghost\"\n        size=\"sm\"\n        label=\"+1s\"\n        onClick={() => setPlayhead(Math.min(projectDuration, playheadTime + 1))}\n      >\n        <SkipForward size={14} />\n      </IconButton>\n\n      <span className=\"mx-2 min-w-[96px] select-none font-mono tabular-nums text-white\">\n        {formatTimecode(playheadTime)}\n      </span>\n\n      <IconButton\n        variant=\"ghost\"\n        size=\"sm\"\n        label=\"Loop\"\n        active={loopEnabled}\n        aria-pressed={loopEnabled}\n        onClick={() => {\n          if (loopEnabled) {\n            setLoop(false);\n            return;\n          }\n          // Prefer current range if already valid; else window from playhead.\n          if (loopEnd > loopStart + 0.05) {\n            setLoop(true, loopStart, loopEnd);\n            return;\n          }\n          const start = playheadTime;\n          const end = Math.min(projectDuration, Math.max(start + 4, start + 8));\n          setLoop(true, start, end);\n        }}\n      >\n        <Repeat size={14} />\n      </IconButton>\n      <IconButton\n        variant=\"ghost\"\n        size=\"sm\"\n        label={t.audio.editor.snap}\n        active={snapEnabled}\n        aria-pressed={snapEnabled}\n        onClick={() => setSnap(!snapEnabled)}\n      >\n        <Magnet size={14} />\n      </IconButton>\n\n      <AudioBpmControl />\n\n      {/* Zoom capsule: \u2212 slider + */}\n      <div className=\"ml-auto flex items-center gap-0.5 rounded-full border border-panel-border bg-black-capsule px-1 py-0.5\">\n        <IconButton\n          variant=\"ghost\"\n          size=\"sm\"\n          label={t.audio.editor.zoomOut}\n          onClick={() => zoomBy(1 / 1.08)}\n          className=\"!h-6 !w-6\"\n        >\n          <ZoomOut size={13} />\n        </IconButton>\n        <input\n          type=\"range\"\n          min={AUDIO_ZOOM_MIN}\n          max={AUDIO_ZOOM_MAX}\n          step={1}\n          value={Math.min(AUDIO_ZOOM_MAX, Math.max(AUDIO_ZOOM_MIN, zoom))}\n          onChange={(e) => setZoomAnchored(Number(e.target.value))}\n          aria-label={t.audio.editor.zoomIn}\n          className=\"h-1 w-24 cursor-pointer appearance-none rounded-full bg-panel accent-[var(--we-accent)] focus:outline-none\"\n        />\n        <IconButton\n          variant=\"ghost\"\n          size=\"sm\"\n          label={t.audio.editor.zoomIn}\n          onClick={() => zoomBy(1.08)}\n          className=\"!h-6 !w-6\"\n        >\n          <ZoomIn size={13} />\n        </IconButton>\n      </div>\n    </div>\n  );\n};\n", "import { create } from 'zustand';\n\nexport type AudioRightPanelId = 'inspector' | 'fx' | 'chat' | 'record' | 'lyrics';\n\nexport type AudioLibraryTabId = 'assets' | 'myFiles';\n\nexport type AudioAiToolTab =\n  | 'music'\n  | 'extend'\n  | 'sfx'\n  | 'tts'\n  | 'voice'\n  | 'isolate'\n  | 'stems'\n  | 'automix'\n  | 'cleanup'\n  | 'lyrics';\n\ntype AudioUiState = {\n  /** Top library section inside the right dock (was left rail). */\n  libraryTab: AudioLibraryTabId;\n  setLibraryTab: (id: AudioLibraryTabId) => void;\n\n  /** Preferred AI sub-tool when opening the AI library tab. */\n  aiToolTab: AudioAiToolTab;\n  setAiToolTab: (id: AudioAiToolTab) => void;\n  /** When true, AI panel shows tool params instead of the catalog list. */\n  aiToolDetailOpen: boolean;\n  setAiToolDetailOpen: (open: boolean) => void;\n\n  rightPanel: AudioRightPanelId | null;\n  setRightPanel: (id: AudioRightPanelId | null) => void;\n  toggleRightPanel: (id: AudioRightPanelId) => void;\n\n  /** Mixer opens as a modal (not a right-dock panel). */\n  mixerOpen: boolean;\n  setMixerOpen: (open: boolean) => void;\n  toggleMixer: () => void;\n\n  /** Open inspector + AI tool detail. */\n  openAiTool: (tool: AudioAiToolTab) => void;\n\n  /** Clip ids currently being processed by an AI tool (timeline loader). */\n  aiProcessingClipIds: string[];\n  setAiProcessingClipIds: (ids: string[]) => void;\n};\n\nexport const useAudioUiStore = create<AudioUiState>((set) => ({\n  libraryTab: 'assets',\n  setLibraryTab: (id) => set({ libraryTab: id }),\n\n  aiToolTab: 'music',\n  setAiToolTab: (id) => set({ aiToolTab: id }),\n  aiToolDetailOpen: false,\n  setAiToolDetailOpen: (open) => set({ aiToolDetailOpen: open }),\n\n  rightPanel: null,\n  setRightPanel: (id) => set({ rightPanel: id }),\n  toggleRightPanel: (id) =>\n    set((s) => ({ rightPanel: s.rightPanel === id ? null : id })),\n\n  mixerOpen: false,\n  setMixerOpen: (open) => set({ mixerOpen: open }),\n  toggleMixer: () => set((s) => ({ mixerOpen: !s.mixerOpen })),\n\n  openAiTool: (tool) =>\n    set({\n      rightPanel: 'inspector',\n      aiToolTab: tool,\n      aiToolDetailOpen: true,\n      mixerOpen: false,\n    }),\n\n  aiProcessingClipIds: [],\n  setAiProcessingClipIds: (ids) => set({ aiProcessingClipIds: ids }),\n}));\n", "import React, { useState } from 'react';\nimport { useAudioStore, type AutomationLane as Lane } from '../../store/useAudioStore';\nimport { useTranslation } from '../../i18n';\nimport { Button, PanelField, PanelSection, SelectDropdown, TextBody } from '../ui';\n\n\n/**\n * Automation editor for the selected track (volume / pan).\n * Curves are also drawn on the timeline.\n */\nexport const AutomationLaneEditor: React.FC = () => {\n  const t = useTranslation();\n  const { tracks, selectedTrackIds, setAutomationLane, playheadTime } = useAudioStore();\n  const [property, setProperty] = useState<'volume' | 'pan'>('volume');\n  const track = tracks.find((t2) => t2.id === selectedTrackIds[0]) ?? tracks[0];\n  if (!track) {\n    return (\n      <TextBody as=\"p\" size=\"sm\" className=\"px-3 py-2 text-white/80\">\n        {t.audio.automation.noTrackHint}\n      </TextBody>\n    );\n  }\n\n  const lane: Lane =\n    track.automation.find((a) => a.property === property) || {\n      id: `auto_${track.id}_${property}`,\n      property,\n      points: [],\n    };\n\n  const defaultValue = property === 'volume' ? track.volumeDb : track.pan;\n  const min = property === 'volume' ? -48 : -1;\n  const max = property === 'volume' ? 12 : 1;\n  const step = property === 'volume' ? 0.5 : 0.01;\n\n  return (\n    <PanelSection title={t.audio.automation.header} divided>\n      <PanelField\n        label={t.audio.automation.property}\n        trailing={\n          <SelectDropdown\n            value={property}\n            options={[\n              { value: 'volume', label: t.audio.automation.propertyVolume },\n              { value: 'pan', label: t.audio.automation.propertyPan },\n            ]}\n            onChange={(v) => setProperty(v as 'volume' | 'pan')}\n            ariaLabel={t.audio.automation.property}\n          />\n        }\n      />\n      <Button\n        variant=\"accent\"\n        size=\"sm\"\n        className=\"w-full\"\n        onClick={() => {\n          const points = [\n            ...lane.points,\n            {\n              id: `pt_${Date.now()}`,\n              time: playheadTime,\n              value: defaultValue,\n            },\n          ].sort((a, b) => a.time - b.time);\n          setAutomationLane(track.id, { ...lane, property, points });\n        }}\n      >\n        {t.audio.automation.addPoint}\n      </Button>\n      {lane.points.length === 0 && (\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n          {t.audio.automation.noPointsHint}\n        </TextBody>\n      )}\n      {lane.points.map((p) => (\n        <div key={p.id} className=\"flex flex-col gap-1\">\n          <div className=\"flex items-center justify-between gap-2 px-0.5\">\n            <TextBody as=\"span\" size=\"sm\" className=\"tabular-nums text-white/80\">\n              {p.time.toFixed(2)}s\n            </TextBody>\n            <button\n              type=\"button\"\n              className=\"font-sans font-semibold text-red-300 hover:text-red-200\"\n              onClick={() => {\n                const points = lane.points.filter((x) => x.id !== p.id);\n                setAutomationLane(track.id, { ...lane, property, points });\n              }}\n            >\n              \u00D7\n            </button>\n          </div>\n          <PanelField\n            variant=\"slide\"\n            label={\n              property === 'volume'\n                ? t.audio.automation.propertyVolume\n                : t.audio.automation.propertyPan\n            }\n            min={min}\n            max={max}\n            step={step}\n            numericValue={p.value}\n            onChange={(next) => {\n              const points = lane.points.map((x) =>\n                x.id === p.id ? { ...x, value: next } : x,\n              );\n              setAutomationLane(track.id, { ...lane, property, points });\n            }}\n            formatValue={(v) =>\n              property === 'volume' ? `${v.toFixed(1)} dB` : v.toFixed(2)\n            }\n          />\n        </div>\n      ))}\n    </PanelSection>\n  );\n};\n", "/**\n * Generic job polling for async /api/audio/* operations.\n */\n\nimport { getWizardApiClient, NetworkError } from '../wizardApiClient';\n\nexport type AudioJobStatus = 'queued' | 'running' | 'succeeded' | 'failed';\n\nexport interface AudioJob<T = unknown> {\n  id: string;\n  kind: string;\n  status: AudioJobStatus;\n  result?: T;\n  error?: string;\n  createdAt: number;\n  updatedAt: number;\n}\n\nexport interface PollJobOptions {\n  jobId: string;\n  /** Polling interval in ms. Default 1500. */\n  intervalMs?: number;\n  /** Max wait in ms. Default 180000 (3 min). */\n  timeoutMs?: number;\n  signal?: AbortSignal;\n  onStatus?: (job: AudioJob) => void;\n}\n\n/**\n * Polls GET /api/audio/jobs/:id until succeeded, failed, aborted, or timeout.\n */\nexport async function pollAudioJob<T = unknown>(\n  opts: PollJobOptions\n): Promise<AudioJob<T>> {\n  const intervalMs = opts.intervalMs ?? 1500;\n  const timeoutMs = opts.timeoutMs ?? 180_000;\n  const started = Date.now();\n  const client = getWizardApiClient();\n\n  while (true) {\n    if (opts.signal?.aborted) {\n      throw new NetworkError('Job polling was aborted', opts.signal.reason);\n    }\n    if (Date.now() - started > timeoutMs) {\n      throw new NetworkError(`Job ${opts.jobId} timed out after ${timeoutMs}ms`);\n    }\n\n    const job = await client.getForJson<AudioJob<T>>(\n      `/api/audio/jobs/${opts.jobId}`,\n      undefined,\n      { signal: opts.signal }\n    );\n    opts.onStatus?.(job);\n\n    if (job.status === 'succeeded') return job;\n    if (job.status === 'failed') {\n      throw new NetworkError(job.error || `Job ${opts.jobId} failed`);\n    }\n\n    await sleep(intervalMs, opts.signal);\n  }\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n  return new Promise((resolve, reject) => {\n    if (signal?.aborted) {\n      reject(new NetworkError('Job polling was aborted', signal.reason));\n      return;\n    }\n    const timer = setTimeout(resolve, ms);\n    const onAbort = () => {\n      clearTimeout(timer);\n      reject(new NetworkError('Job polling was aborted', signal?.reason));\n    };\n    signal?.addEventListener('abort', onAbort, { once: true });\n  });\n}\n\n/** Decode a job result that carries base64 audio into a Blob. */\nexport function audioResultToBlob(result: {\n  mimeType: string;\n  audioBase64: string;\n}): Blob {\n  const binary = atob(result.audioBase64);\n  const bytes = new Uint8Array(binary.length);\n  for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n  return new Blob([bytes], { type: result.mimeType || 'audio/mpeg' });\n}\n", "/**\n * Encode an AudioBuffer (or OfflineAudioContext result) to a WAV Blob.\n */\n\nexport type WavBitDepth = 16 | 24 | 32;\n\nexport interface EncodeWavOptions {\n  /** TPDF dither when quantizing to 16/24-bit. */\n  dither?: boolean;\n}\n\n/** Triangular PDF dither in \u00B11 LSB units. */\nfunction tpdf(): number {\n  return Math.random() + Math.random() - 1;\n}\n\nexport function encodeWav(\n  buffer: AudioBuffer,\n  bitDepth: WavBitDepth = 16,\n  opts: EncodeWavOptions = {}\n): Blob {\n  const dither = opts.dither !== false && bitDepth !== 32;\n  const numChannels = buffer.numberOfChannels;\n  const sampleRate = buffer.sampleRate;\n  const numFrames = buffer.length;\n  const bytesPerSample = bitDepth / 8;\n  const blockAlign = numChannels * bytesPerSample;\n  const dataSize = numFrames * blockAlign;\n  const headerSize = 44;\n  const arrayBuffer = new ArrayBuffer(headerSize + dataSize);\n  const view = new DataView(arrayBuffer);\n\n  writeString(view, 0, 'RIFF');\n  view.setUint32(4, 36 + dataSize, true);\n  writeString(view, 8, 'WAVE');\n  writeString(view, 12, 'fmt ');\n  view.setUint32(16, 16, true);\n  view.setUint16(20, bitDepth === 32 ? 3 : 1, true); // IEEE float for 32-bit\n  view.setUint16(22, numChannels, true);\n  view.setUint32(24, sampleRate, true);\n  view.setUint32(28, sampleRate * blockAlign, true);\n  view.setUint16(32, blockAlign, true);\n  view.setUint16(34, bitDepth, true);\n  writeString(view, 36, 'data');\n  view.setUint32(40, dataSize, true);\n\n  const channels: Float32Array[] = [];\n  for (let c = 0; c < numChannels; c++) {\n    channels.push(buffer.getChannelData(c));\n  }\n\n  let offset = 44;\n  for (let i = 0; i < numFrames; i++) {\n    for (let c = 0; c < numChannels; c++) {\n      let sample = channels[c]?.[i] ?? 0;\n      if (bitDepth === 16) {\n        if (dither) sample += tpdf() / 32768;\n        const s = Math.max(-1, Math.min(1, sample));\n        view.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n        offset += 2;\n      } else if (bitDepth === 24) {\n        if (dither) sample += tpdf() / 8388608;\n        const s = Math.max(-1, Math.min(1, sample));\n        const intVal = Math.floor(s < 0 ? s * 0x800000 : s * 0x7fffff);\n        view.setUint8(offset, intVal & 0xff);\n        view.setUint8(offset + 1, (intVal >> 8) & 0xff);\n        view.setUint8(offset + 2, (intVal >> 16) & 0xff);\n        offset += 3;\n      } else {\n        view.setFloat32(offset, sample, true);\n        offset += 4;\n      }\n    }\n  }\n\n  return new Blob([arrayBuffer], { type: 'audio/wav' });\n}\n\nfunction writeString(view: DataView, offset: number, str: string) {\n  for (let i = 0; i < str.length; i++) {\n    view.setUint8(offset + i, str.charCodeAt(i));\n  }\n}\n", "/**\n * Approximate stem separation via isolation API + offline band splits.\n * Not a neural demucs \u2014 usable placeholder until .NET exposes real stems.\n */\n\nimport { encodeWav } from './wavEncoder';\n\nexport type StemName = 'vocals' | 'drums' | 'bass' | 'other';\n\n/** Offline filter a buffer through a Biquad and return a new AudioBuffer. */\nasync function filterBuffer(\n  buffer: AudioBuffer,\n  configure: (f: BiquadFilterNode) => void\n): Promise<AudioBuffer> {\n  const ctx = new OfflineAudioContext(\n    buffer.numberOfChannels,\n    buffer.length,\n    buffer.sampleRate\n  );\n  const src = ctx.createBufferSource();\n  src.buffer = buffer;\n  const f = ctx.createBiquadFilter();\n  configure(f);\n  src.connect(f);\n  f.connect(ctx.destination);\n  src.start();\n  return ctx.startRendering();\n}\n\n/** Invert-mix: a - b (same length), clipped. */\nfunction subtractBuffers(a: AudioBuffer, b: AudioBuffer): AudioBuffer {\n  const len = Math.min(a.length, b.length);\n  const ch = Math.min(a.numberOfChannels, b.numberOfChannels);\n  const out = new AudioBuffer({ length: len, numberOfChannels: ch, sampleRate: a.sampleRate });\n  for (let c = 0; c < ch; c++) {\n    const A = a.getChannelData(c);\n    const B = b.getChannelData(c);\n    const O = out.getChannelData(c);\n    for (let i = 0; i < len; i++) {\n      O[i] = Math.max(-1, Math.min(1, (A[i] ?? 0) - (B[i] ?? 0) * 0.85));\n    }\n  }\n  return out;\n}\n\nasync function decodeBlob(blob: Blob): Promise<AudioBuffer> {\n  const ctx = new AudioContext();\n  try {\n    const ab = await blob.arrayBuffer();\n    return await ctx.decodeAudioData(ab.slice(0));\n  } finally {\n    void ctx.close();\n  }\n}\n\nfunction toBlob(buffer: AudioBuffer): Blob {\n  return encodeWav(buffer, 16, { dither: false });\n}\n\n/**\n * Build stem blobs from an original mix + optional isolated vocals blob.\n */\nexport async function buildStemBlobs(opts: {\n  original: Blob;\n  vocals?: Blob | null;\n}): Promise<Record<StemName, Blob>> {\n  const originalBuf = await decodeBlob(opts.original);\n  let vocalsBuf: AudioBuffer;\n  if (opts.vocals) {\n    try {\n      vocalsBuf = await decodeBlob(opts.vocals);\n      // Match length by padding/truncating\n      if (vocalsBuf.length !== originalBuf.length) {\n        const ctx = new OfflineAudioContext(\n          originalBuf.numberOfChannels,\n          originalBuf.length,\n          originalBuf.sampleRate\n        );\n        const aligned = ctx.createBuffer(\n          originalBuf.numberOfChannels,\n          originalBuf.length,\n          originalBuf.sampleRate\n        );\n        for (let c = 0; c < aligned.numberOfChannels; c++) {\n          const src = vocalsBuf.getChannelData(Math.min(c, vocalsBuf.numberOfChannels - 1));\n          aligned.getChannelData(c).set(src.subarray(0, Math.min(src.length, aligned.length)));\n        }\n        vocalsBuf = aligned;\n      }\n    } catch {\n      vocalsBuf = await filterBuffer(originalBuf, (f) => {\n        f.type = 'bandpass';\n        f.frequency.value = 1200;\n        f.Q.value = 0.7;\n      });\n    }\n  } else {\n    vocalsBuf = await filterBuffer(originalBuf, (f) => {\n      f.type = 'bandpass';\n      f.frequency.value = 1200;\n      f.Q.value = 0.65;\n    });\n  }\n\n  const bassBuf = await filterBuffer(originalBuf, (f) => {\n    f.type = 'lowpass';\n    f.frequency.value = 180;\n    f.Q.value = 0.7;\n  });\n\n  const drumsBuf = await filterBuffer(originalBuf, (f) => {\n    f.type = 'bandpass';\n    f.frequency.value = 200;\n    f.Q.value = 0.5;\n  });\n\n  const otherBuf = subtractBuffers(originalBuf, vocalsBuf);\n\n  return {\n    vocals: toBlob(vocalsBuf),\n    bass: toBlob(bassBuf),\n    drums: toBlob(drumsBuf),\n    other: toBlob(otherBuf),\n  };\n}\n", "/**\n * Music generation via Audio DAW `POST /api/audio/generate-music` (async job).\n * Body: { prompt, durationSeconds, bpm, account_id, brand_id } \u2014 ids only, no brand JSON.\n * brand_id is always required (.NET: \"No active brand selected for this creative builder\").\n */\n\nimport { getEditorIdentity } from '../identity';\nimport { getWizardApiClient } from '../wizardApiClient';\nimport { audioResultToBlob, pollAudioJob } from './jobPolling';\n\nexport interface GenerateMusicOptions {\n  prompt: string;\n  durationSeconds?: number;\n  bpm?: number;\n  signal?: AbortSignal;\n  onStatus?: (status: string) => void;\n}\n\nexport interface GenerateMusicResult {\n  blob: Blob;\n  durationSeconds: number;\n  jobId: string;\n}\n\n/** Exact Swagger Audio DAW JSON for generate/extend music. */\nfunction musicRequestBody(opts: {\n  prompt: string;\n  durationSeconds: number;\n  bpm?: number;\n}) {\n  const { accountId, brandId } = getEditorIdentity();\n  return {\n    prompt: opts.prompt.trim(),\n    durationSeconds: opts.durationSeconds,\n    bpm: opts.bpm ?? 0,\n    account_id: String(accountId),\n    brand_id: String(brandId),\n  };\n}\n\nasync function startMusicJob(\n  path: '/api/audio/generate-music' | '/api/audio/extend-music',\n  body: ReturnType<typeof musicRequestBody>,\n  opts: { signal?: AbortSignal; onStatus?: (status: string) => void }\n) {\n  // Debug: exact browser \u2192 BFF payload (brandDataJson is NEVER sent here).\n  console.group(`[audio-daw] POST ${path}`);\n  console.log(\n    'NOTE: This body is what the editor sends. No brandDataJson / Brand Memory.',\n  );\n  console.log('body', body);\n  console.log('promptLength', body.prompt.length, '(should be your short brief)');\n  console.log('promptPreview', body.prompt.slice(0, 200));\n  console.log('identity', getEditorIdentity());\n  console.groupEnd();\n\n  const client = getWizardApiClient();\n  try {\n    const started = await client.postJsonForJson<{ job_id: string; status: string }>(\n      path,\n      body,\n      { signal: opts.signal }\n    );\n    console.log(`[audio-daw] ${path} \u2192 accepted`, started);\n    console.log(\n      '[audio-daw] If the job later fails with KAIMAN STRATEGIC CONTEXT / text_too_long, ' +\n        'the .NET job runner expanded Brand Memory into the ElevenLabs prompt AFTER accept \u2014 not this request.',\n    );\n    opts.onStatus?.(started.status);\n    const job = await pollAudioJob<{\n      mimeType: string;\n      audioBase64: string;\n      durationSeconds: number;\n    }>({\n      jobId: started.job_id,\n      signal: opts.signal,\n      onStatus: (j) => opts.onStatus?.(j.status),\n    });\n    console.log(`[audio-daw] job ${started.job_id} \u2192`, {\n      status: job.status,\n      hasResult: Boolean(job.result),\n      resultMime: job.result?.mimeType,\n      resultDuration: job.result?.durationSeconds,\n      audioBase64Chars: job.result?.audioBase64?.length,\n    });\n    if (!job.result) throw new Error('Music job succeeded without result');\n    return job;\n  } catch (err) {\n    const msg = err instanceof Error ? err.message : String(err);\n    if (/KAIMAN STUDIO STRATEGIC CONTEXT|text_too_long|invalid_text_length/i.test(msg)) {\n      console.error(\n        '[audio-daw] Backend enriched the prompt with Brand Memory before calling ElevenLabs. ' +\n          'Editor only sent prompt + brand_id (see log above). Escalate to PM: generate-music must pass the user prompt as-is to ElevenLabs, not Brand Memory.',\n        err,\n      );\n    } else {\n      console.error(`[audio-daw] ${path} failed`, err);\n    }\n    throw err;\n  }\n}\n\nexport async function generateMusic(\n  opts: GenerateMusicOptions\n): Promise<GenerateMusicResult> {\n  const durationSeconds = opts.durationSeconds ?? 30;\n  const job = await startMusicJob(\n    '/api/audio/generate-music',\n    musicRequestBody({\n      prompt: opts.prompt,\n      durationSeconds,\n      bpm: opts.bpm,\n    }),\n    opts\n  );\n  return {\n    blob: audioResultToBlob(job.result!),\n    durationSeconds: job.result!.durationSeconds ?? durationSeconds,\n    jobId: job.id,\n  };\n}\n\nexport interface ExtendMusicOptions {\n  prompt: string;\n  durationSeconds?: number;\n  bpm?: number;\n  signal?: AbortSignal;\n  onStatus?: (status: string) => void;\n}\n\nexport async function extendMusic(opts: ExtendMusicOptions): Promise<GenerateMusicResult> {\n  const durationSeconds = opts.durationSeconds ?? 15;\n  const job = await startMusicJob(\n    '/api/audio/extend-music',\n    musicRequestBody({\n      prompt: opts.prompt,\n      durationSeconds,\n      bpm: opts.bpm,\n    }),\n    opts\n  );\n  return {\n    blob: audioResultToBlob(job.result!),\n    durationSeconds: job.result!.durationSeconds ?? durationSeconds,\n    jobId: job.id,\n  };\n}\n\nexport interface SeparateStemsResult {\n  stems: Record<string, Blob>;\n}\n\nexport async function separateStems(opts: {\n  file: Blob;\n  signal?: AbortSignal;\n}): Promise<SeparateStemsResult> {\n  const { accountId, brandId } = getEditorIdentity();\n  const { buildStemBlobs } = await import('../../lib/audio/stemSplit');\n\n  let vocals: Blob | null = null;\n  try {\n    const res = await getWizardApiClient().postMultipartForJson<{\n      stems: Record<string, { mimeType: string; audioBase64: string }>;\n    }>(\n      '/api/audio/separate-stems',\n      {\n        file: opts.file,\n        account_id: String(accountId),\n        brand_id: String(brandId),\n      },\n      { signal: opts.signal }\n    );\n    if (res.stems?.vocals) {\n      vocals = audioResultToBlob(res.stems.vocals);\n    }\n  } catch {\n    // Fall through to local band-split without isolated vocals\n  }\n\n  const stems = await buildStemBlobs({ original: opts.file, vocals });\n  return { stems };\n}\n", "/**\n * Sound-effects via Audio DAW `POST /api/audio/generate-sfx`.\n * Same id fields as generate-music \u2014 brand_id only, never brand JSON in prompt.\n */\n\nimport { getEditorIdentity } from '../identity';\nimport { getWizardApiClient } from '../wizardApiClient';\n\nexport interface GenerateSfxOptions {\n  prompt: string;\n  durationSeconds?: number;\n  bpm?: number;\n  signal?: AbortSignal;\n}\n\nexport async function generateSfx(opts: GenerateSfxOptions): Promise<Blob> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postJson(\n    '/api/audio/generate-sfx',\n    {\n      prompt: opts.prompt.trim(),\n      durationSeconds: opts.durationSeconds ?? 5,\n      bpm: opts.bpm ?? 0,\n      account_id: String(accountId),\n      brand_id: String(brandId),\n    },\n    { signal: opts.signal }\n  );\n}\n", "/**\n * TTS and voice-change via /api/audio/* (local backend \u2192 ElevenLabs).\n */\n\nimport { getEditorIdentity } from '../identity';\nimport { getWizardApiClient } from '../wizardApiClient';\nimport { TTS_VOICES, type TtsVoiceId } from '../voiceoverService';\n\nexport { TTS_VOICES };\nexport type { TtsVoiceId };\n\nexport interface GenerateTtsOptions {\n  text: string;\n  voiceId?: string;\n  speed?: number;\n  signal?: AbortSignal;\n}\n\nexport async function generateTts(opts: GenerateTtsOptions): Promise<Blob> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postJson(\n    '/api/audio/tts',\n    {\n      text: opts.text,\n      voiceId: opts.voiceId ?? TTS_VOICES[0]?.id,\n      speed: opts.speed ?? 1,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n}\n\nexport interface VoiceChangeOptions {\n  file: Blob;\n  voiceId: string;\n  signal?: AbortSignal;\n}\n\nexport async function changeVoice(opts: VoiceChangeOptions): Promise<Blob> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postMultipart(\n    '/api/audio/voice-change',\n    {\n      file: opts.file,\n      voiceId: opts.voiceId,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n}\n", "/**\n * Audio isolation (vocals / denoise) via /api/audio/isolate.\n */\n\nimport { getEditorIdentity } from '../identity';\nimport { getWizardApiClient } from '../wizardApiClient';\n\nexport interface IsolateAudioOptions {\n  file: Blob;\n  signal?: AbortSignal;\n}\n\nexport async function isolateAudio(opts: IsolateAudioOptions): Promise<Blob> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postMultipart(\n    '/api/audio/isolate',\n    {\n      file: opts.file,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n}\n", "/**\n * Detect and remove silent regions from an AudioBuffer.\n */\n\nexport interface TrimSilenceOptions {\n  /** Absolute amplitude threshold (0\u20131). */\n  threshold?: number;\n  /** Minimum silence length to cut (seconds). */\n  minSilenceSeconds?: number;\n  /** Padding kept around speech (seconds). */\n  paddingSeconds?: number;\n}\n\n/** Concatenate non-silent segments into a new AudioBuffer. */\nexport async function trimSilenceFromBuffer(\n  buffer: AudioBuffer,\n  opts: TrimSilenceOptions = {}\n): Promise<AudioBuffer> {\n  const threshold = opts.threshold ?? 0.012;\n  const minSilence = Math.floor((opts.minSilenceSeconds ?? 0.45) * buffer.sampleRate);\n  const padding = Math.floor((opts.paddingSeconds ?? 0.08) * buffer.sampleRate);\n\n  const ch0 = buffer.getChannelData(0);\n  const len = ch0.length;\n  const window = Math.max(1, Math.floor(buffer.sampleRate * 0.02));\n\n  type Seg = { start: number; end: number };\n  const speech: Seg[] = [];\n  let i = 0;\n  while (i < len) {\n    let peak = 0;\n    const end = Math.min(len, i + window);\n    for (let j = i; j < end; j++) {\n      const v = Math.abs(ch0[j] ?? 0);\n      if (v > peak) peak = v;\n    }\n    const loud = peak >= threshold;\n    if (loud) {\n      const start = Math.max(0, i - padding);\n      let k = end;\n      while (k < len) {\n        let p = 0;\n        const e2 = Math.min(len, k + window);\n        for (let j = k; j < e2; j++) {\n          const v = Math.abs(ch0[j] ?? 0);\n          if (v > p) p = v;\n        }\n        if (p < threshold) {\n          // look ahead for sustained silence\n          let silentRun = e2 - k;\n          let t = e2;\n          while (t < len && silentRun < minSilence) {\n            let p2 = 0;\n            const e3 = Math.min(len, t + window);\n            for (let j = t; j < e3; j++) {\n              const v = Math.abs(ch0[j] ?? 0);\n              if (v > p2) p2 = v;\n            }\n            if (p2 >= threshold) break;\n            silentRun += e3 - t;\n            t = e3;\n          }\n          if (silentRun >= minSilence) {\n            speech.push({ start, end: Math.min(len, k + padding) });\n            i = t;\n            break;\n          }\n        }\n        k = e2;\n        if (k >= len) {\n          speech.push({ start, end: len });\n          i = len;\n          break;\n        }\n      }\n      if (i < end) i = end;\n    } else {\n      i = end;\n    }\n  }\n\n  if (!speech.length) return buffer;\n\n  // Merge overlapping\n  speech.sort((a, b) => a.start - b.start);\n  const merged: Seg[] = [];\n  for (const s of speech) {\n    const last = merged[merged.length - 1];\n    if (last && s.start <= last.end) last.end = Math.max(last.end, s.end);\n    else merged.push({ ...s });\n  }\n\n  const total = merged.reduce((n, s) => n + (s.end - s.start), 0);\n  if (total < buffer.sampleRate * 0.05) return buffer;\n\n  const out = new AudioBuffer({\n    length: total,\n    numberOfChannels: buffer.numberOfChannels,\n    sampleRate: buffer.sampleRate,\n  });\n  let write = 0;\n  for (const s of merged) {\n    const n = s.end - s.start;\n    for (let c = 0; c < buffer.numberOfChannels; c++) {\n      out.getChannelData(c).set(buffer.getChannelData(c).subarray(s.start, s.end), write);\n    }\n    write += n;\n  }\n  return out;\n}\n\nexport async function bufferToWavBlob(buffer: AudioBuffer): Promise<Blob> {\n  const { encodeWav } = await import('./wavEncoder');\n  return encodeWav(buffer, 16, { dither: false });\n}\n", "import React, { useEffect, useRef, useState } from 'react';\nimport {\n  AudioLines,\n  Captions,\n  ChevronDown,\n  ChevronLeft,\n  ChevronUp,\n  Copy,\n  Loader2,\n  Mic2,\n  Music2,\n  Pause,\n  Play,\n  Scissors,\n  SlidersHorizontal,\n  Sparkles,\n  Split,\n  Volume2,\n  Wand2,\n} from 'lucide-react';\nimport { useAudioStore, createAudioClip } from '../../store/useAudioStore';\nimport { extendMusic, generateMusic, separateStems } from '../../services/audio/musicService';\nimport { generateSfx } from '../../services/audio/sfxService';\nimport { generateTts, changeVoice, TTS_VOICES } from '../../services/audio/voiceService';\nimport { isolateAudio } from '../../services/audio/isolationService';\nimport { transcribeAudio } from '../../services/transcriptionService';\nimport { decodeAudioBlob, extractPeaks } from '../../lib/audio/peaks';\nimport { defaultEffectParams } from '../../lib/audio/effects/createEffectChain';\nimport { analyzeBuffer } from '../../lib/audio/loudness';\nimport { bufferToWavBlob, trimSilenceFromBuffer } from '../../lib/audio/silenceTrim';\nimport { getAudioEngine } from '../../lib/audio/AudioEngine';\nimport { segmentsToWords } from '../../lib/audio/transcriptEdit';\nimport { useTranslation } from '../../i18n';\nimport { useAudioUiStore } from '../../store/useAudioUiStore';\nimport {\n  Button,\n  IconButton,\n  PanelField,\n  PanelSection,\n  SelectDropdown,\n  TextBody,\n  TextTitle,\n} from '../ui';\n\ntype AiTab =\n  | 'music'\n  | 'extend'\n  | 'sfx'\n  | 'tts'\n  | 'voice'\n  | 'isolate'\n  | 'stems'\n  | 'automix'\n  | 'cleanup'\n  | 'lyrics';\n\ntype ToolDef = {\n  id: AiTab;\n  icon: React.ReactNode;\n};\n\n/** Compact inspector list \u2014 most used first. */\nconst PRIMARY_TOOLS: ToolDef[] = [\n  { id: 'music', icon: <Music2 size={16} /> },\n  { id: 'tts', icon: <Mic2 size={16} /> },\n  { id: 'isolate', icon: <Scissors size={16} /> },\n  { id: 'stems', icon: <Split size={16} /> },\n];\n\nconst MORE_TOOLS: ToolDef[] = [\n  { id: 'extend', icon: <AudioLines size={16} /> },\n  { id: 'sfx', icon: <Volume2 size={16} /> },\n  { id: 'voice', icon: <Wand2 size={16} /> },\n  { id: 'lyrics', icon: <Captions size={16} /> },\n  { id: 'automix', icon: <SlidersHorizontal size={16} /> },\n  { id: 'cleanup', icon: <Sparkles size={16} /> },\n];\n\nconst ALL_TOOLS = [...PRIMARY_TOOLS, ...MORE_TOOLS];\n\nconst voiceDemoUrlCache = new Map<string, string>();\n\nfunction ToolRow({\n  tool,\n  name,\n  description,\n  onClick,\n}: {\n  tool: ToolDef;\n  name: string;\n  description: string;\n  onClick: () => void;\n}) {\n  return (\n    <button\n      type=\"button\"\n      onClick={onClick}\n      className=\"relative flex w-full cursor-pointer items-start gap-2.5 overflow-hidden rounded-xl border border-transparent bg-black-capsule px-2.5 py-2.5 text-left transition-colors hover:border-[color-mix(in_srgb,var(--we-accent)_35%,transparent)] hover:bg-[var(--we-accent-muted)] active:scale-[0.99]\"\n    >\n      <span className=\"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-[var(--we-accent)] text-white\">\n        {tool.icon}\n      </span>\n      <span className=\"min-w-0 flex-1\">\n        <TextTitle as=\"span\" size=\"sm\" className=\"block text-white\">\n          {name}\n        </TextTitle>\n        <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 text-pretty block leading-snug text-white/80\">\n          {description}\n        </TextBody>\n      </span>\n    </button>\n  );\n}\n\nfunction VoicePicker({\n  voiceId,\n  onChange,\n  ariaLabel,\n  playLabel,\n  pauseLabel,\n}: {\n  voiceId: string;\n  onChange: (id: string) => void;\n  ariaLabel: string;\n  playLabel: string;\n  pauseLabel: string;\n}) {\n  const [playing, setPlaying] = useState(false);\n  const [loading, setLoading] = useState(false);\n  const audioRef = useRef<HTMLAudioElement | null>(null);\n\n  useEffect(() => {\n    audioRef.current?.pause();\n    audioRef.current = null;\n    setPlaying(false);\n    setLoading(false);\n  }, [voiceId]);\n\n  useEffect(() => {\n    return () => {\n      audioRef.current?.pause();\n      audioRef.current = null;\n    };\n  }, []);\n\n  const togglePreview = async () => {\n    if (playing && audioRef.current) {\n      audioRef.current.pause();\n      setPlaying(false);\n      return;\n    }\n    const catalog = TTS_VOICES.find((v) => v.id === voiceId);\n    const preview = catalog?.previewUrl;\n    if (!preview) return;\n    setLoading(true);\n    try {\n      let url = voiceDemoUrlCache.get(voiceId);\n      if (!url) {\n        const res = await fetch(preview);\n        if (!res.ok) throw new Error(`Preview HTTP ${res.status}`);\n        url = preview;\n        voiceDemoUrlCache.set(voiceId, url);\n      }\n      audioRef.current?.pause();\n      const audio = new Audio(url);\n      audioRef.current = audio;\n      audio.onended = () => setPlaying(false);\n      audio.onpause = () => setPlaying(false);\n      await audio.play();\n      setPlaying(true);\n    } catch {\n      setPlaying(false);\n    } finally {\n      setLoading(false);\n    }\n  };\n\n  const voiceOptions = TTS_VOICES.map((v) => ({ value: v.id, label: v.label }));\n  const hasPreview = Boolean(TTS_VOICES.find((v) => v.id === voiceId)?.previewUrl);\n\n  return (\n    <div className=\"flex items-center gap-1.5\">\n      <SelectDropdown\n        value={voiceId}\n        options={voiceOptions}\n        onChange={onChange}\n        ariaLabel={ariaLabel}\n      />\n      <IconButton\n        variant=\"ghost\"\n        size=\"sm\"\n        label={playing ? pauseLabel : playLabel}\n        disabled={!hasPreview || loading}\n        onClick={() => void togglePreview()}\n      >\n        {loading ? (\n          <Loader2 size={14} className=\"animate-spin\" />\n        ) : playing ? (\n          <Pause size={14} />\n        ) : (\n          <Play size={14} />\n        )}\n      </IconButton>\n    </div>\n  );\n}\n\n/** AI tools catalog + params \u2014 lives at the top of the audio inspector. */\nexport const AiAudioPanel: React.FC = () => {\n  const tr = useTranslation();\n  const {\n    tracks,\n    assets,\n    playheadTime,\n    selectedClipIds,\n    bpm,\n    addAsset,\n    addClip,\n    addTrack,\n    addToast,\n    updateTrack,\n    addEffect,\n    selectTrack,\n    applySongStructureMarkers,\n    clearSongStructureMarkers,\n    setTranscript,\n  } = useAudioStore();\n\n  const markers = useAudioStore((s) => s.markers);\n  const hasSongStructure = markers.some((m) => m.source === 'song-structure');\n\n  const aiToolTab = useAudioUiStore((s) => s.aiToolTab);\n  const setAiToolTab = useAudioUiStore((s) => s.setAiToolTab);\n  const toolOpen = useAudioUiStore((s) => s.aiToolDetailOpen);\n  const setToolOpen = useAudioUiStore((s) => s.setAiToolDetailOpen);\n  const setAiProcessingClipIds = useAudioUiStore((s) => s.setAiProcessingClipIds);\n\n  const [tab, setTab] = useState<AiTab>(aiToolTab || 'music');\n  const [showMore, setShowMore] = useState(false);\n  const [prompt, setPrompt] = useState('');\n  const [text, setText] = useState('');\n  const [duration, setDuration] = useState(30);\n  const [voiceId, setVoiceId] = useState(TTS_VOICES[0]?.id || '');\n  const [busy, setBusy] = useState(false);\n  const [status, setStatus] = useState('');\n  const [lyrics, setLyrics] = useState<Array<{ start: number; end: number; text: string }>>([]);\n\n  useEffect(() => {\n    if (aiToolTab && aiToolTab !== tab) setTab(aiToolTab);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [aiToolTab]);\n\n  const selectAiTab = (id: AiTab) => {\n    setTab(id);\n    setAiToolTab(id);\n    setToolOpen(true);\n  };\n\n  const backToCatalog = () => setToolOpen(false);\n\n  const insertBlob = async (\n    blob: Blob,\n    name: string,\n    durationHint?: number,\n    trackIdOverride?: string,\n  ) => {\n    const buffer = await decodeAudioBlob(blob);\n    const peaks = await extractPeaks(buffer);\n    const id = `ai_${Date.now()}_${Math.random().toString(36).slice(2, 5)}`;\n    const file = new File([blob], name, { type: blob.type || 'audio/mpeg' });\n    const url = URL.createObjectURL(blob);\n    addAsset({\n      id,\n      name,\n      url,\n      duration: durationHint ?? buffer.duration,\n      sampleRate: buffer.sampleRate,\n      channels: buffer.numberOfChannels,\n      file,\n      peaks: peaks.peaks,\n      peaksSampleRate: peaks.peaksSampleRate,\n    });\n    let trackId = trackIdOverride;\n    if (!trackId) {\n      trackId = addTrack(tr.audio.ai.trackNames.aiTrack, 'audio');\n      selectTrack(trackId);\n    }\n    addClip(\n      createAudioClip({\n        trackId,\n        assetId: id,\n        startTime: playheadTime,\n        duration: durationHint ?? buffer.duration,\n        name,\n      }),\n    );\n  };\n\n  const selectedAsset = (() => {\n    for (const t of tracks) {\n      const c = t.clips.find((x) => x.id === selectedClipIds[0]);\n      if (c) return assets.find((a) => a.id === c.assetId);\n    }\n    return undefined;\n  })();\n\n  const runAutoMix = async () => {\n    const engine = getAudioEngine();\n    const audioTracks = tracks.filter((t) => t.type === 'audio');\n    const targetLufs = -18;\n    let i = 0;\n    for (const t of audioTracks) {\n      const isVoice = /voz|vocal|host|guest|voice|tts/i.test(t.name);\n      let measured = -24;\n      const clip = t.clips[0];\n      const asset = clip ? assets.find((a) => a.id === clip.assetId) : undefined;\n      if (asset) {\n        const buf = await engine.loadAsset(asset);\n        if (buf) measured = analyzeBuffer(buf).lufs;\n      }\n      const delta = targetLufs - measured;\n      const volumeDb = Math.max(-24, Math.min(6, (isVoice ? -2 : -6) + delta * 0.35));\n      updateTrack(t.id, {\n        volumeDb,\n        pan: isVoice ? 0 : i % 2 === 0 ? -0.25 : 0.25,\n      });\n      if (isVoice && !t.effects.some((e) => e.type === 'highpass')) {\n        addEffect(t.id, {\n          id: `fx_hp_${Date.now()}_${i}`,\n          type: 'highpass',\n          enabled: true,\n          order: 0,\n          params: defaultEffectParams('highpass'),\n        });\n      }\n      if (!t.effects.some((e) => e.type === 'compressor')) {\n        addEffect(t.id, {\n          id: `fx_comp_${Date.now()}_${i}`,\n          type: 'compressor',\n          enabled: true,\n          order: 1,\n          params: defaultEffectParams('compressor'),\n        });\n      }\n      i++;\n    }\n    addToast(tr.audio.ai.toasts.autoMix, 'success');\n  };\n\n  const runPodcastCleanup = async () => {\n    if (!selectedAsset?.file) throw new Error(tr.audio.ai.toasts.noVoiceClip);\n    setStatus(tr.audio.ai.status.isolating);\n    const cleaned = await isolateAudio({ file: selectedAsset.file });\n    setStatus(tr.audio.ai.status.removingSilence);\n    const decoded = await decodeAudioBlob(cleaned);\n    const trimmed = await trimSilenceFromBuffer(decoded);\n    const wav = await bufferToWavBlob(trimmed);\n    const trackId = addTrack(tr.audio.ai.trackNames.podcastTrack, 'audio');\n    selectTrack(trackId);\n    await insertBlob(wav, `Cleanup ${Date.now()}.wav`, trimmed.duration, trackId);\n    addEffect(trackId, {\n      id: `fx_hp_clean_${Date.now()}`,\n      type: 'highpass',\n      enabled: true,\n      order: 0,\n      params: { ...defaultEffectParams('highpass'), frequency: 90 },\n    });\n    addEffect(trackId, {\n      id: `fx_comp_clean_${Date.now()}`,\n      type: 'compressor',\n      enabled: true,\n      order: 1,\n      params: defaultEffectParams('compressor'),\n    });\n    const stats = analyzeBuffer(trimmed);\n    updateTrack(trackId, { volumeDb: Math.max(-12, Math.min(0, -14 - stats.lufs)) });\n    addToast(tr.audio.ai.toasts.podcastCleanup, 'success');\n  };\n\n  const run = async () => {\n    setBusy(true);\n    setStatus('');\n    const processingIds =\n      selectedClipIds.length > 0\n        ? [...selectedClipIds]\n        : tab === 'automix'\n          ? tracks.flatMap((trTrack) => trTrack.clips.map((c) => c.id))\n          : [];\n    if (processingIds.length) setAiProcessingClipIds(processingIds);\n    try {\n      if (tab === 'music') {\n        const result = await generateMusic({\n          prompt,\n          durationSeconds: duration,\n          bpm: bpm || undefined,\n          onStatus: setStatus,\n        });\n        await insertBlob(result.blob, `Music ${Date.now()}.mp3`, result.durationSeconds);\n        addToast(tr.audio.ai.toasts.musicGenerated, 'success');\n      } else if (tab === 'extend') {\n        const result = await extendMusic({\n          prompt: prompt || 'continue seamlessly',\n          durationSeconds: Math.min(duration, 30),\n          bpm: bpm || undefined,\n          onStatus: setStatus,\n        });\n        await insertBlob(result.blob, `Extend ${Date.now()}.mp3`, result.durationSeconds);\n        addToast(tr.audio.ai.toasts.extendGenerated, 'success');\n      } else if (tab === 'sfx') {\n        const blob = await generateSfx({ prompt, durationSeconds: Math.min(duration, 22) });\n        await insertBlob(blob, `SFX ${Date.now()}.mp3`, Math.min(duration, 22));\n        addToast(tr.audio.ai.toasts.sfxGenerated, 'success');\n      } else if (tab === 'tts') {\n        const blob = await generateTts({ text, voiceId });\n        await insertBlob(blob, `TTS ${Date.now()}.mp3`);\n        addToast(tr.audio.ai.toasts.voiceoverGenerated, 'success');\n      } else if (tab === 'voice') {\n        if (!selectedAsset?.file) throw new Error(tr.audio.ai.toasts.noAudioClip);\n        const blob = await changeVoice({ file: selectedAsset.file, voiceId });\n        await insertBlob(blob, `Voice ${Date.now()}.mp3`);\n        addToast(tr.audio.ai.toasts.voiceChanged, 'success');\n      } else if (tab === 'isolate') {\n        if (!selectedAsset?.file) throw new Error(tr.audio.ai.toasts.noAudioClip);\n        const blob = await isolateAudio({ file: selectedAsset.file });\n        await insertBlob(blob, `Isolated ${Date.now()}.mp3`);\n        addToast(tr.audio.ai.toasts.audioIsolated, 'success');\n      } else if (tab === 'stems') {\n        if (!selectedAsset?.file) throw new Error(tr.audio.ai.toasts.noAudioClip);\n        setStatus(tr.audio.ai.status.separatingStems);\n        const { stems } = await separateStems({ file: selectedAsset.file });\n        for (const [stemName, blob] of Object.entries(stems)) {\n          const trackId = addTrack(stemName, 'audio');\n          selectTrack(trackId);\n          await insertBlob(blob, `${stemName}.wav`, undefined, trackId);\n        }\n        addToast(tr.audio.ai.toasts.stemsSeparated, 'success');\n      } else if (tab === 'automix') {\n        await runAutoMix();\n      } else if (tab === 'cleanup') {\n        await runPodcastCleanup();\n      } else if (tab === 'lyrics') {\n        if (!selectedAsset?.file) throw new Error(tr.audio.ai.toasts.noAudioClip);\n        const segments = await transcribeAudio({ file: selectedAsset.file });\n        setLyrics(segments.map((s) => ({ start: s.start, end: s.end, text: s.text })));\n        let clipId = selectedClipIds[0];\n        let clipStart = playheadTime;\n        for (const t2 of tracks) {\n          const c = t2.clips.find((x) => x.id === selectedClipIds[0]);\n          if (c) {\n            clipId = c.id;\n            clipStart = c.startTime;\n            break;\n          }\n        }\n        if (clipId) {\n          setTranscript(segmentsToWords(segments, clipId, clipStart));\n        }\n        if (!tracks.find((t2) => t2.type === 'lyrics')) {\n          addTrack(tr.audio.ai.trackNames.lyricsTrack, 'lyrics');\n        }\n        addToast(tr.audio.ai.toasts.transcriptReady, 'success');\n      }\n    } catch (err) {\n      const raw =\n        err instanceof Error\n          ? err.message\n          : typeof err === 'string'\n            ? err\n            : '';\n      const detail =\n        err && typeof err === 'object' && 'detail' in err\n          ? String((err as { detail?: unknown }).detail ?? '')\n          : raw;\n      const combined = `${raw}\\n${detail}`;\n      const isMusicPromptTooLong =\n        /string_too_long/i.test(combined) ||\n        /text_too_long|invalid_text_length/i.test(combined) ||\n        (/at most (4100|450)/i.test(combined) && /prompt|text/i.test(combined)) ||\n        (/MusicComposeService/i.test(combined) && /422/i.test(combined)) ||\n        /KAIMAN STUDIO STRATEGIC CONTEXT/i.test(combined);\n      addToast(\n        isMusicPromptTooLong\n          ? tr.audio.ai.toasts.musicPromptTooLong\n          : raw || tr.audio.ai.toasts.agentError,\n        'error',\n      );\n    } finally {\n      setAiProcessingClipIds([]);\n      setBusy(false);\n      setStatus('');\n    }\n  };\n\n  const needsPrompt = tab === 'music' || tab === 'extend' || tab === 'sfx';\n  const needsSelection =\n    tab === 'voice' || tab === 'isolate' || tab === 'stems' || tab === 'cleanup' || tab === 'lyrics';\n  const hasClipFile = Boolean(selectedAsset?.file && selectedAsset.file.size > 0);\n  const canRun =\n    !busy &&\n    (needsPrompt ? prompt.trim().length > 0 : true) &&\n    (tab === 'tts' ? text.trim().length > 0 && Boolean(voiceId) : true) &&\n    (tab === 'voice' ? hasClipFile && Boolean(voiceId) : true) &&\n    (needsSelection && tab !== 'voice' ? hasClipFile : true) &&\n    (tab === 'automix' ? tracks.some((t) => t.type === 'audio' && t.clips.length > 0) : true);\n\n  const actionLabel =\n    tab === 'automix'\n      ? tr.audio.ai.actionLabel.applyAutomix\n      : tab === 'cleanup'\n        ? tr.audio.ai.actionLabel.cleanupPodcast\n        : tab === 'stems'\n          ? tr.audio.ai.actionLabel.separateStems\n          : tab === 'extend'\n            ? tr.audio.ai.actionLabel.extend\n            : tr.audio.ai.actionLabel.generate;\n\n  const activeTool = ALL_TOOLS.find((t) => t.id === tab);\n\n  const submitOnEnter = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n    if (e.key !== 'Enter' || e.shiftKey) return;\n    e.preventDefault();\n    if (canRun) void run();\n  };\n\n  const renderTools = (tools: ToolDef[]) => (\n    <div className=\"flex flex-col gap-1.5\">\n      {tools.map((tool) => (\n        <ToolRow\n          key={tool.id}\n          tool={tool}\n          name={tr.audio.ai.tab[tool.id]}\n          description={tr.audio.ai.endpointHint[tool.id]}\n          onClick={() => selectAiTab(tool.id)}\n        />\n      ))}\n    </div>\n  );\n\n  if (toolOpen) {\n    return (\n      <div className=\"we-audio-ai-panel\">\n        <PanelSection title={tr.audio.ai.tab[tab]} description={tr.audio.ai.endpointHint[tab]}>\n          <button\n            type=\"button\"\n            onClick={backToCatalog}\n            className=\"flex w-full cursor-pointer items-center gap-2 rounded-xl border border-transparent bg-black-capsule px-2.5 py-2 text-left transition-colors hover:bg-[var(--we-accent-muted)]\"\n          >\n            <span className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-[var(--we-accent)] text-white\">\n              <ChevronLeft size={16} />\n            </span>\n            <span className=\"min-w-0 flex-1\">\n              <TextTitle as=\"span\" size=\"sm\" className=\"block text-white\">\n                {tr.audio.ai.chooseAnotherTool}\n              </TextTitle>\n              <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 block text-white/80\">\n                {activeTool ? tr.audio.ai.tab[activeTool.id] : ''}\n              </TextBody>\n            </span>\n          </button>\n\n          {needsPrompt && (\n            <div className=\"flex flex-col gap-2\">\n              <textarea\n                value={prompt}\n                onChange={(e) => setPrompt(e.target.value)}\n                onKeyDown={submitOnEnter}\n                placeholder={\n                  tab === 'music'\n                    ? tr.audio.ai.placeholders.music\n                    : tab === 'extend'\n                      ? tr.audio.ai.placeholders.extend\n                      : tr.audio.ai.placeholders.sfx\n                }\n                className=\"h-24 w-full resize-none rounded-xl border border-panel-border bg-black-capsule p-2.5 font-sans font-medium text-white placeholder:text-white/50 focus:border-[var(--we-accent)] focus:outline-none\"\n              />\n              <PanelField\n                variant=\"slide\"\n                label={tr.audio.ai.durationLabel}\n                min={1}\n                max={tab === 'sfx' ? 22 : 120}\n                step={1}\n                numericValue={duration}\n                onChange={setDuration}\n                formatValue={(v) => `${v}s`}\n              />\n              {tab === 'music' && (\n                <Button\n                  variant=\"outline\"\n                  size=\"sm\"\n                  onClick={() => {\n                    if (hasSongStructure) {\n                      clearSongStructureMarkers();\n                      addToast(tr.audio.ai.songStructureClearedToast, 'success');\n                    } else {\n                      applySongStructureMarkers();\n                      addToast(tr.audio.ai.songStructureToast, 'success');\n                    }\n                  }}\n                >\n                  {hasSongStructure\n                    ? tr.audio.ai.songStructureClear\n                    : tr.audio.ai.songStructure}\n                </Button>\n              )}\n            </div>\n          )}\n\n          {tab === 'tts' && (\n            <div className=\"flex flex-col gap-2\">\n              <textarea\n                value={text}\n                onChange={(e) => setText(e.target.value)}\n                onKeyDown={submitOnEnter}\n                placeholder={tr.audio.ai.placeholders.tts}\n                className=\"h-24 w-full resize-none rounded-xl border border-panel-border bg-black-capsule p-2.5 font-sans font-medium text-white placeholder:text-white/50 focus:border-[var(--we-accent)] focus:outline-none\"\n              />\n              <PanelField\n                label={tr.audio.ai.tab.tts}\n                trailing={\n                  <VoicePicker\n                    voiceId={voiceId}\n                    onChange={setVoiceId}\n                    ariaLabel={tr.audio.ai.tab.tts}\n                    playLabel={tr.audio.ai.playVoicePreview}\n                    pauseLabel={tr.audio.ai.pauseVoicePreview}\n                  />\n                }\n              />\n            </div>\n          )}\n\n          {needsSelection && (\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {tr.audio.ai.selectedClip(selectedAsset?.name || '')}\n            </TextBody>\n          )}\n\n          {tab === 'voice' && (\n            <PanelField\n              label={tr.audio.ai.tab.voice}\n              trailing={\n                <VoicePicker\n                  voiceId={voiceId}\n                  onChange={setVoiceId}\n                  ariaLabel={tr.audio.ai.tab.voice}\n                  playLabel={tr.audio.ai.playVoicePreview}\n                  pauseLabel={tr.audio.ai.pauseVoicePreview}\n                />\n              }\n            />\n          )}\n\n          {tab === 'automix' && (\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {tr.audio.ai.hints.automix}\n            </TextBody>\n          )}\n          {tab === 'cleanup' && (\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {tr.audio.ai.hints.cleanup}\n            </TextBody>\n          )}\n          {tab === 'stems' && (\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {tr.audio.ai.hints.stems}\n            </TextBody>\n          )}\n\n          {lyrics.length > 0 && (\n            <div className=\"max-h-40 space-y-1 overflow-y-auto rounded-xl border border-panel-border bg-black-capsule p-2\">\n              {lyrics.map((l, i) => (\n                <div key={i} className=\"font-sans font-medium text-white\">\n                  <span className=\"mr-2 select-none tabular-nums text-white/80\">\n                    {l.start.toFixed(1)}\u2013{l.end.toFixed(1)}\n                  </span>\n                  {l.text}\n                </div>\n              ))}\n            </div>\n          )}\n\n          {tab === 'lyrics' && lyrics.length > 0 && (\n            <Button\n              variant=\"secondary\"\n              size=\"md\"\n              className=\"w-full\"\n              icon={<Copy size={14} />}\n              onClick={() => {\n                const text = lyrics\n                  .map((l) => l.text)\n                  .join(' ')\n                  .replace(/\\s+/g, ' ')\n                  .trim();\n                if (!text) {\n                  addToast(tr.audio.lyrics.toasts.nothingToCopy, 'warning');\n                  return;\n                }\n                void navigator.clipboard.writeText(text).then(\n                  () => addToast(tr.audio.lyrics.toasts.transcriptCopied, 'success'),\n                  (err) =>\n                    addToast(\n                      err instanceof Error ? err.message : tr.audio.lyrics.toasts.copyError,\n                      'error',\n                    ),\n                );\n              }}\n            >\n              {tr.audio.lyrics.copyLyrics}\n            </Button>\n          )}\n\n          <Button\n            variant=\"accent\"\n            size=\"md\"\n            disabled={!canRun}\n            loading={busy}\n            className=\"w-full\"\n            onClick={() => void run()}\n          >\n            {busy ? status || tr.audio.ai.generating : actionLabel}\n          </Button>\n        </PanelSection>\n      </div>\n    );\n  }\n\n  return (\n    <div className=\"we-audio-ai-panel\">\n      <PanelSection title={tr.audio.sidebar.titleAi} description={tr.audio.ai.catalogHint} divided>\n        {renderTools(PRIMARY_TOOLS)}\n        {showMore && renderTools(MORE_TOOLS)}\n        <button\n          type=\"button\"\n          onClick={() => setShowMore((v) => !v)}\n          className=\"flex w-full cursor-pointer items-center justify-center gap-1.5 rounded-xl px-2 py-2 font-sans font-semibold text-white/80 transition-colors hover:bg-[var(--we-accent-muted)] hover:text-white\"\n        >\n          {showMore ? <ChevronUp size={14} /> : <ChevronDown size={14} />}\n          {showMore ? tr.audio.ai.showLessTools : tr.audio.ai.showMoreTools}\n        </button>\n      </PanelSection>\n    </div>\n  );\n};\n", "import React from 'react';\nimport { useAudioStore } from '../../store/useAudioStore';\nimport { useAudioUiStore } from '../../store/useAudioUiStore';\nimport { AutomationLaneEditor } from './AutomationLane';\nimport { AiAudioPanel } from './AiAudioPanel';\nimport { useTranslation } from '../../i18n';\nimport {\n  Button,\n  PanelBody,\n  PanelField,\n  PanelSection,\n  SelectDropdown,\n  Switch,\n} from '../ui';\nimport { useDialog } from '../DialogModal';\nimport { TextBody } from '../ui';\n\n\nconst CURVE_OPTS = (t: ReturnType<typeof useTranslation>) => [\n  { value: 'linear', label: t.audio.inspector.curveLinear },\n  { value: 'logarithmic', label: t.audio.inspector.curveLog },\n  { value: 's-curve', label: t.audio.inspector.curveSCurve },\n  { value: 'exponential', label: t.audio.inspector.curveExp },\n];\n\nfunction formatTc(seconds: number): string {\n  const s = Math.max(0, seconds);\n  const m = Math.floor(s / 60);\n  const sec = Math.floor(s % 60);\n  const ms = Math.floor((s % 1) * 100);\n  return `${String(m).padStart(2, '0')}:${String(sec).padStart(2, '0')}.${String(ms).padStart(2, '0')}`;\n}\n\nexport const AudioInspector: React.FC = () => {\n  const t = useTranslation();\n  const dialog = useDialog();\n  const openAiTool = useAudioUiStore((s) => s.openAiTool);\n  const aiToolDetailOpen = useAudioUiStore((s) => s.aiToolDetailOpen);\n  const { tracks, selectedClipIds, updateClip, duplicateClip, removeClip } =\n    useAudioStore();\n\n  let clip = null as ReturnType<typeof useAudioStore.getState>['tracks'][0]['clips'][0] | null;\n  for (const t2 of tracks) {\n    const found = t2.clips.find((c) => c.id === selectedClipIds[0]);\n    if (found) {\n      clip = found;\n      break;\n    }\n  }\n\n  if (!clip) {\n    return (\n      <PanelBody>\n        <AiAudioPanel />\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n          {t.audio.inspector.emptyHint}\n        </TextBody>\n        {!aiToolDetailOpen && <AutomationLaneEditor />}\n      </PanelBody>\n    );\n  }\n\n  const fadeMax = Math.max(0.1, clip.duration / 2);\n  const xfMax = Math.max(0.05, clip.duration / 2);\n  const curveOpts = CURVE_OPTS(t);\n  const xfOpts = [\n    { value: 'equal-power', label: t.audio.inspector.crossfadeEqualPower },\n    { value: 'linear', label: t.audio.inspector.crossfadeLinear },\n    { value: 'exponential', label: t.audio.inspector.crossfadeExponential },\n  ];\n  const speedOpts = [\n    { value: '0.5', label: t.audio.inspector.speedHalf },\n    { value: '1', label: t.audio.inspector.speedStandard },\n    { value: '1.5', label: t.audio.inspector.speedOneHalf },\n    { value: '2', label: t.audio.inspector.speedDouble },\n  ];\n  const speedKey = String(clip.speed);\n  const speedSelectValue = speedOpts.some((o) => o.value === speedKey) ? speedKey : '1';\n\n  return (\n    <PanelBody>\n      <AiAudioPanel />\n\n      {!aiToolDetailOpen && (\n        <>\n          <PanelSection title={t.audio.inspector.selection} divided>\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {t.audio.inspector.selectionHint}\n            </TextBody>\n            <div className=\"grid grid-cols-2 gap-2\">\n              <label className=\"flex flex-col gap-1\">\n                <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                  {t.audio.inspector.selStart}\n                </TextBody>\n                <input\n                  value={formatTc(clip.startTime)}\n                  readOnly\n                  className=\"h-9 rounded-xl border border-panel-border bg-black-capsule px-3 font-sans text-xs font-medium tabular-nums text-white outline-none\"\n                />\n              </label>\n              <label className=\"flex flex-col gap-1\">\n                <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                  {t.audio.inspector.selEnd}\n                </TextBody>\n                <input\n                  value={formatTc(clip.startTime + clip.duration)}\n                  readOnly\n                  className=\"h-9 rounded-xl border border-panel-border bg-black-capsule px-3 font-sans text-xs font-medium tabular-nums text-white outline-none\"\n                />\n              </label>\n            </div>\n            <PanelField\n              label={t.audio.inspector.playbackSpeed}\n              trailing={\n                <SelectDropdown\n                  value={speedSelectValue}\n                  options={speedOpts}\n                  onChange={(v) => updateClip(clip!.id, { speed: Number(v) })}\n                  ariaLabel={t.audio.inspector.playbackSpeed}\n                />\n              }\n            />\n          </PanelSection>\n\n          <PanelSection title={t.audio.inspector.name} divided>\n            <input\n              value={clip.name || ''}\n              onChange={(e) => updateClip(clip!.id, { name: e.target.value })}\n              className=\"h-9 w-full rounded-xl border border-panel-border bg-black-capsule px-3 font-sans text-xs font-medium text-white outline-none focus:border-[var(--we-accent)]\"\n            />\n          </PanelSection>\n\n          <PanelSection title={t.audio.inspector.soundLevels} divided>\n            <PanelField\n              variant=\"slide\"\n              label={t.audio.inspector.gain}\n              min={0}\n              max={2}\n              step={0.01}\n              numericValue={clip.gain}\n              formatValue={() =>\n                `${(20 * Math.log10(Math.max(0.0001, clip.gain))).toFixed(1)} dB`\n              }\n              onChange={(v) => updateClip(clip!.id, { gain: v })}\n            />\n            <PanelField\n              variant=\"slide\"\n              label={clip.pitchSeparate ? t.audio.inspector.speedStretch : t.audio.inspector.speed}\n              min={0.25}\n              max={4}\n              step={0.01}\n              numericValue={clip.speed}\n              onChange={(v) => updateClip(clip!.id, { speed: v })}\n            />\n            <PanelField\n              label={t.audio.inspector.pitchTimeIndependent}\n              trailing={\n                <Switch\n                  checked={!!clip.pitchSeparate}\n                  onChange={(checked) => updateClip(clip!.id, { pitchSeparate: checked })}\n                />\n              }\n            />\n            <PanelField\n              variant=\"slide\"\n              label={t.audio.inspector.pitch}\n              min={-12}\n              max={12}\n              step={1}\n              numericValue={clip.pitch}\n              onChange={(v) => updateClip(clip!.id, { pitch: v })}\n            />\n          </PanelSection>\n\n          <PanelSection title={t.audio.inspector.backgroundNoise} divided>\n            <PanelField\n              label={t.audio.inspector.removeNoise}\n              trailing={\n                <Switch\n                  checked={false}\n                  onChange={(checked) => {\n                    if (checked) openAiTool('cleanup');\n                  }}\n                />\n              }\n            />\n          </PanelSection>\n\n          <PanelSection title={t.audio.sidebar.titleInspector} divided>\n            <PanelField\n              variant=\"slide\"\n              label={t.audio.inspector.fadeIn}\n              min={0}\n              max={fadeMax}\n              step={0.01}\n              numericValue={clip.fadeIn}\n              onChange={(v) => updateClip(clip!.id, { fadeIn: v })}\n            />\n            <PanelField\n              variant=\"slide\"\n              label={t.audio.inspector.fadeOut}\n              min={0}\n              max={fadeMax}\n              step={0.01}\n              numericValue={clip.fadeOut}\n              onChange={(v) => updateClip(clip!.id, { fadeOut: v })}\n            />\n            <PanelField\n              variant=\"slide\"\n              label={t.audio.inspector.crossfadeIn}\n              min={0}\n              max={xfMax}\n              step={0.01}\n              numericValue={clip.crossfadeIn ?? 0}\n              onChange={(v) =>\n                updateClip(clip!.id, { crossfadeIn: v, fadeIn: Math.max(clip.fadeIn, v) })\n              }\n            />\n            <PanelField\n              variant=\"slide\"\n              label={t.audio.inspector.crossfadeOut}\n              min={0}\n              max={xfMax}\n              step={0.01}\n              numericValue={clip.crossfadeOut ?? 0}\n              onChange={(v) =>\n                updateClip(clip!.id, { crossfadeOut: v, fadeOut: Math.max(clip.fadeOut, v) })\n              }\n            />\n            <PanelField\n              label={t.audio.inspector.crossfadeEqualPower}\n              trailing={\n                <SelectDropdown\n                  value={clip.crossfadeCurve || 'equal-power'}\n                  options={xfOpts}\n                  onChange={(v) =>\n                    updateClip(clip!.id, {\n                      crossfadeCurve: v as typeof clip.crossfadeCurve,\n                    })\n                  }\n                  ariaLabel={t.audio.inspector.crossfadeEqualPower}\n                />\n              }\n            />\n            <Button\n              variant=\"accent\"\n              size=\"sm\"\n              className=\"w-full\"\n              onClick={() =>\n                useAudioStore\n                  .getState()\n                  .applyCrossfadeBetweenSelected(0.25, clip.crossfadeCurve || 'equal-power')\n              }\n            >\n              {t.audio.inspector.applyCrossfade}\n            </Button>\n            <PanelField\n              label={t.audio.inspector.fadeInCurve}\n              trailing={\n                <SelectDropdown\n                  value={clip.fadeInCurve}\n                  options={curveOpts}\n                  onChange={(v) =>\n                    updateClip(clip!.id, { fadeInCurve: v as typeof clip.fadeInCurve })\n                  }\n                  ariaLabel={t.audio.inspector.fadeInCurve}\n                />\n              }\n            />\n            <PanelField\n              label={t.audio.inspector.fadeOutCurve}\n              trailing={\n                <SelectDropdown\n                  value={clip.fadeOutCurve}\n                  options={curveOpts}\n                  onChange={(v) =>\n                    updateClip(clip!.id, { fadeOutCurve: v as typeof clip.fadeOutCurve })\n                  }\n                  ariaLabel={t.audio.inspector.fadeOutCurve}\n                />\n              }\n            />\n            <PanelField\n              label={t.audio.inspector.mute}\n              trailing={\n                <Switch\n                  checked={clip.muted}\n                  onChange={(checked) => updateClip(clip!.id, { muted: checked })}\n                />\n              }\n            />\n            <PanelField\n              label={t.audio.inspector.invertPhase}\n              trailing={\n                <Switch\n                  checked={clip.inverted}\n                  onChange={(checked) => updateClip(clip!.id, { inverted: checked })}\n                />\n              }\n            />\n            <div className=\"flex gap-2 pt-1\">\n              <Button\n                variant=\"secondary\"\n                size=\"sm\"\n                className=\"flex-1\"\n                onClick={() => duplicateClip(clip!.id)}\n              >\n                {t.audio.inspector.duplicate}\n              </Button>\n              <Button\n                variant=\"danger\"\n                size=\"sm\"\n                className=\"flex-1\"\n                onClick={() => {\n                  void (async () => {\n                    const ok = await dialog.confirm(t.audio.editor.deleteClipConfirm, {\n                      title: t.audio.editor.deleteConfirmTitle,\n                      variant: 'danger',\n                      confirmText: t.audio.editor.deleteConfirmBtn,\n                      cancelText: t.common.cancel,\n                    });\n                    if (ok) removeClip(clip!.id);\n                  })();\n                }}\n              >\n                {t.audio.inspector.delete}\n              </Button>\n            </div>\n          </PanelSection>\n\n          <AutomationLaneEditor />\n        </>\n      )}\n    </PanelBody>\n  );\n};\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { Save, Trash2 } from 'lucide-react';\nimport { useAudioStore, type AudioEffectType, type AppliedAudioEffect } from '../../store/useAudioStore';\nimport { defaultEffectParams } from '../../lib/audio/effects/createEffectChain';\nimport { getAudioEngine } from '../../lib/audio/AudioEngine';\nimport { useTranslation } from '../../i18n';\nimport { IconButton, PanelBody, PanelField, PanelSection, SelectDropdown, Slider, Switch, TextBody } from '../ui';\n\n\nconst EFFECT_TYPES: AudioEffectType[] = [\n  'eq',\n  'compressor',\n  'gate',\n  'reverb',\n  'delay',\n  'chorus',\n  'distortion',\n  'highpass',\n  'lowpass',\n  'limiter',\n];\n\nconst PRESET_KEY = 'we-audio-fx-presets';\nconst ADD_SENTINEL = '__add__';\nconst PRESET_SENTINEL = '__preset__';\n\ntype PresetMap = Record<string, Array<{ name: string; params: Record<string, number | boolean | string> }>>;\n\nfunction loadPresets(): PresetMap {\n  try {\n    return JSON.parse(localStorage.getItem(PRESET_KEY) || '{}') as PresetMap;\n  } catch {\n    return {};\n  }\n}\n\nfunction savePresets(map: PresetMap) {\n  localStorage.setItem(PRESET_KEY, JSON.stringify(map));\n}\n\nfunction paramRange(key: string): { min: number; max: number; step: number } {\n  if (key.includes('Freq') || key === 'frequency') return { min: 20, max: 20000, step: 1 };\n  if (key.includes('mix') || key === 'feedback') return { min: 0, max: 1, step: 0.01 };\n  return { min: -48, max: 24, step: 1 };\n}\n\nfunction EqCurve({ params }: { params: Record<string, number | boolean | string> }) {\n  const canvasRef = useRef<HTMLCanvasElement>(null);\n  useEffect(() => {\n    const canvas = canvasRef.current;\n    if (!canvas) return;\n    const ctx = canvas.getContext('2d');\n    if (!ctx) return;\n    const w = canvas.width;\n    const h = canvas.height;\n    ctx.clearRect(0, 0, w, h);\n    ctx.fillStyle = '#121218';\n    ctx.fillRect(0, 0, w, h);\n    ctx.strokeStyle = 'rgba(255,255,255,0.12)';\n    ctx.beginPath();\n    ctx.moveTo(0, h / 2);\n    ctx.lineTo(w, h / 2);\n    ctx.stroke();\n\n    const low = Number(params.lowGain ?? 0);\n    const mid = Number(params.midGain ?? 0);\n    const high = Number(params.highGain ?? 0);\n    const accent =\n      getComputedStyle(document.documentElement).getPropertyValue('--we-accent').trim() ||\n      '#9F1239';\n    ctx.strokeStyle = accent;\n    ctx.lineWidth = 2;\n    ctx.beginPath();\n    for (let x = 0; x < w; x++) {\n      const t = x / (w - 1);\n      const yDb =\n        low * (1 - t) * (1 - t) +\n        mid * Math.exp(-Math.pow((t - 0.45) / 0.15, 2)) +\n        high * t * t;\n      const y = h / 2 - (yDb / 24) * (h / 2 - 4);\n      if (x === 0) ctx.moveTo(x, y);\n      else ctx.lineTo(x, y);\n    }\n    ctx.stroke();\n  }, [params]);\n\n  return (\n    <canvas\n      ref={canvasRef}\n      width={220}\n      height={64}\n      className=\"w-full rounded-xl border border-panel-border\"\n    />\n  );\n}\n\nexport const EffectsRack: React.FC = () => {\n  const tr = useTranslation();\n  const { tracks, selectedTrackIds, addEffect, updateEffect, removeEffect } = useAudioStore();\n  const track = tracks.find((t) => t.id === selectedTrackIds[0]) ?? tracks[0];\n  const [presets, setPresets] = useState<PresetMap>(() => loadPresets());\n  const [addTick, setAddTick] = useState(0);\n\n  if (!track) {\n    return (\n      <PanelBody>\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n          {tr.audio.fx.noTrackHint}\n        </TextBody>\n      </PanelBody>\n    );\n  }\n\n  const savePreset = (fx: AppliedAudioEffect) => {\n    const name = window.prompt(tr.audio.fx.savePresetPrompt, tr.audio.fx.defaultPresetName(fx.type));\n    if (!name) return;\n    const next: PresetMap = {\n      ...presets,\n      [fx.type]: [...(presets[fx.type] || []), { name, params: { ...fx.params } }],\n    };\n    setPresets(next);\n    savePresets(next);\n  };\n\n  const typeOptions = [\n    { value: ADD_SENTINEL, label: tr.audio.fx.addEffect },\n    ...EFFECT_TYPES.map((tt) => ({\n      value: tt,\n      label: tr.audio.fx.types[tt as keyof typeof tr.audio.fx.types],\n    })),\n  ];\n\n  return (\n    <PanelBody>\n      <PanelSection\n        title={tr.audio.fx.fxHeader(track.name)}\n        trailing={\n          <SelectDropdown\n            key={addTick}\n            value={ADD_SENTINEL}\n            options={typeOptions}\n            onChange={(v) => {\n              if (!v || v === ADD_SENTINEL) return;\n              const type = v as AudioEffectType;\n              addEffect(track.id, {\n                id: `fx_${Math.random().toString(36).slice(2, 8)}`,\n                type,\n                enabled: true,\n                order: track.effects.length,\n                params: defaultEffectParams(type),\n              });\n              setAddTick((n) => n + 1);\n            }}\n            ariaLabel={tr.audio.fx.addEffect}\n          />\n        }\n      >\n        {track.effects.length === 0 && (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n            {tr.audio.fx.noEffectsHint}\n          </TextBody>\n        )}\n\n        {track.effects.map((fx) => {\n          const presetOpts = [\n            { value: PRESET_SENTINEL, label: tr.audio.fx.loadPreset },\n            ...(presets[fx.type] || []).map((p) => ({ value: p.name, label: p.name })),\n          ];\n          return (\n            <div\n              key={fx.id}\n              className=\"flex flex-col gap-2 rounded-xl border border-panel-border bg-black-capsule/50 p-2\"\n            >\n              <div className=\"flex items-center gap-2\">\n                <Switch\n                  checked={fx.enabled}\n                  onChange={(checked) => updateEffect(track.id, fx.id, { enabled: checked })}\n                  ariaLabel={fx.type}\n                />\n                <TextBody as=\"span\" size=\"sm\" className=\"min-w-0 flex-1 uppercase text-white\">\n                  {fx.type}\n                </TextBody>\n                <IconButton\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  label={tr.audio.fx.savePresetTooltip}\n                  onClick={() => savePreset(fx)}\n                >\n                  <Save size={12} />\n                </IconButton>\n                <IconButton\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  label={tr.audio.inspector.delete}\n                  onClick={() => removeEffect(track.id, fx.id)}\n                >\n                  <Trash2 size={12} />\n                </IconButton>\n              </div>\n\n              {fx.type === 'eq' && <EqCurve params={fx.params} />}\n\n              {(presets[fx.type]?.length ?? 0) > 0 && (\n                <PanelField\n                  label={tr.audio.fx.loadPreset}\n                  trailing={\n                    <SelectDropdown\n                      value={PRESET_SENTINEL}\n                      options={presetOpts}\n                      onChange={(v) => {\n                        if (!v || v === PRESET_SENTINEL) return;\n                        const preset = presets[fx.type]?.find((p) => p.name === v);\n                        if (preset) updateEffect(track.id, fx.id, { params: { ...preset.params } });\n                      }}\n                      ariaLabel={tr.audio.fx.loadPreset}\n                    />\n                  }\n                />\n              )}\n\n              {fx.type === 'compressor' && <CompressorGrReadout trackId={track.id} />}\n\n              <div className=\"flex flex-col gap-2\">\n                {Object.entries(fx.params).map(([key, val]) =>\n                  typeof val === 'number' ? (\n                    <Slider\n                      key={key}\n                      label={key}\n                      value={val}\n                      {...paramRange(key)}\n                      onChange={(next) =>\n                        updateEffect(track.id, fx.id, {\n                          params: { ...fx.params, [key]: next },\n                        })\n                      }\n                      formatValue={(n) =>\n                        paramRange(key).step < 1 ? n.toFixed(2) : String(Math.round(n))\n                      }\n                    />\n                  ) : null,\n                )}\n              </div>\n            </div>\n          );\n        })}\n      </PanelSection>\n    </PanelBody>\n  );\n};\n\nfunction CompressorGrReadout({ trackId }: { trackId: string }) {\n  const ref = useRef<HTMLSpanElement>(null);\n  useEffect(() => {\n    let raf = 0;\n    const tick = () => {\n      if (ref.current) {\n        const gr = getAudioEngine().getCompressorReductionDb(trackId);\n        ref.current.textContent = `GR: ${gr.toFixed(1)} dB`;\n      }\n      raf = requestAnimationFrame(tick);\n    };\n    raf = requestAnimationFrame(tick);\n    return () => cancelAnimationFrame(raf);\n  }, [trackId]);\n  return (\n    <div className=\"select-none font-sans font-medium text-teal-400\">\n      <span ref={ref}>GR: 0.0 dB</span>\n    </div>\n  );\n}\n", "import React, { useEffect, useRef } from 'react';\nimport { getAudioEngine } from '../../lib/audio/AudioEngine';\n\ninterface Props {\n  height?: number;\n  width?: number;\n  /** Track id, or 'master' / undefined for master bus. */\n  trackId?: string;\n  showLufs?: boolean;\n}\n\nexport const LevelMeter: React.FC<Props> = ({\n  height = 80,\n  width = 12,\n  trackId = 'master',\n  showLufs = false,\n}) => {\n  const canvasRef = useRef<HTMLCanvasElement>(null);\n  const lufsRef = useRef<HTMLSpanElement>(null);\n\n  useEffect(() => {\n    let raf = 0;\n    const draw = () => {\n      const canvas = canvasRef.current;\n      if (!canvas) return;\n      const ctx = canvas.getContext('2d');\n      if (!ctx) return;\n      const { peakL, rmsL, lufsApprox } = getAudioEngine().getMeterLevels(trackId);\n      ctx.clearRect(0, 0, width, height);\n      ctx.fillStyle = '#1C1C26';\n      ctx.fillRect(0, 0, width, height);\n      const peakH = peakL * height;\n      const rmsH = rmsL * height;\n      ctx.fillStyle = peakL > 0.9 ? '#FF4081' : '#00BFA5';\n      ctx.fillRect(1, height - peakH, width - 2, peakH);\n      ctx.fillStyle = '#6C63FF';\n      ctx.fillRect(1, height - rmsH, width - 2, rmsH);\n      if (showLufs && lufsRef.current && lufsApprox != null) {\n        lufsRef.current.textContent = `${lufsApprox.toFixed(1)} LUFS`;\n      }\n      raf = requestAnimationFrame(draw);\n    };\n    raf = requestAnimationFrame(draw);\n    return () => cancelAnimationFrame(raf);\n  }, [height, width, trackId, showLufs]);\n\n  return (\n    <div className=\"we-audio-meter flex flex-col items-center gap-0.5\">\n      <canvas ref={canvasRef} width={width} height={height} className=\"rounded-sm\" />\n      {showLufs && (\n        <span ref={lufsRef} className=\" text-[#666680] tabular-nums whitespace-nowrap\">\n          \u2014 LUFS\n        </span>\n      )}\n    </div>\n  );\n};\n", "import React from 'react';\nimport { Trash2 } from 'lucide-react';\nimport { useAudioStore } from '../../store/useAudioStore';\nimport { LevelMeter } from './LevelMeter';\nimport { useTranslation } from '../../i18n';\nimport { useDialog } from '../DialogModal';\nimport { IconButton, Slider, TextBody, TextTitle } from '../ui';\n\n\nexport const Mixer: React.FC = () => {\n  const t = useTranslation();\n  const dialog = useDialog();\n  const {\n    tracks,\n    masterVolumeDb,\n    updateTrack,\n    setMasterVolumeDb,\n    toggleTrackMute,\n    toggleTrackSolo,\n    addTrack,\n    removeTrack,\n    setTrackSend,\n    lufsHistory,\n    truePeakDb,\n    integratedLufs,\n  } = useAudioStore();\n\n  const audioTracks = tracks.filter((tr) => tr.type === 'audio' || tr.type === 'bus');\n  const buses = tracks.filter((tr) => tr.type === 'bus');\n\n  return (\n    <div className=\"we-audio-mixer flex h-full min-h-[min(70vh,560px)] gap-3 overflow-x-auto rounded-xl bg-black-capsule/40 p-3\">\n      {audioTracks.map((track) => {\n        const sendAmount =\n          track.type === 'audio' && buses[0]\n            ? track.sends?.find((s) => s.busId === buses[0]!.id)?.amount ?? 0\n            : 0;\n        return (\n          <div\n            key={track.id}\n            className=\"flex w-36 flex-shrink-0 flex-col items-stretch gap-2 rounded-xl border border-panel-border bg-panel p-3\"\n          >\n            <div className=\"flex items-center gap-1\">\n              <span\n                className=\"h-2 w-2 shrink-0 rounded-full bg-[var(--we-accent)]\"\n                style={track.color ? { background: track.color } : undefined}\n              />\n              <TextBody as=\"span\" size=\"sm\" className=\"min-w-0 flex-1 truncate text-center text-white\">\n                {track.name}\n              </TextBody>\n              {track.type === 'bus' && (\n                <IconButton\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  label={t.audio.mixer.deleteBus}\n                  onClick={() => {\n                    void (async () => {\n                      const ok = await dialog.confirm(\n                        t.audio.editor.deleteTrackConfirm(track.name),\n                        {\n                          title: t.audio.editor.deleteConfirmTitle,\n                          variant: 'danger',\n                          confirmText: t.audio.editor.deleteConfirmBtn,\n                          cancelText: t.common.cancel,\n                        },\n                      );\n                      if (ok) removeTrack(track.id);\n                    })();\n                  }}\n                >\n                  <Trash2 size={11} className=\"text-red-300\" />\n                </IconButton>\n              )}\n            </div>\n            <TextBody as=\"span\" size=\"sm\" className=\"text-center text-white/80\">\n              {track.type === 'bus' ? 'BUS' : 'IN \u2192 OUT'}\n            </TextBody>\n            <div className=\"flex min-h-0 flex-1 justify-center py-1\">\n              <LevelMeter height={220} width={12} trackId={track.id} />\n            </div>\n            <Slider\n              label={t.audio.inspector.gain}\n              value={track.volumeDb}\n              min={-48}\n              max={12}\n              step={0.5}\n              onChange={(v) => updateTrack(track.id, { volumeDb: v })}\n              formatValue={(v) => `${v.toFixed(1)} dB`}\n            />\n            <Slider\n              label=\"Pan\"\n              value={track.pan}\n              min={-1}\n              max={1}\n              step={0.01}\n              onChange={(v) => updateTrack(track.id, { pan: v })}\n              formatValue={(v) => v.toFixed(2)}\n            />\n            {buses[0] && track.type === 'audio' && (\n              <Slider\n                label={`Send ${buses[0].name}`}\n                value={sendAmount}\n                min={0}\n                max={1}\n                step={0.01}\n                onChange={(v) => setTrackSend(track.id, buses[0]!.id, v)}\n                formatValue={(v) => v.toFixed(2)}\n              />\n            )}\n            <div className=\"flex justify-center gap-1\">\n              <button\n                type=\"button\"\n                onClick={() => toggleTrackMute(track.id)}\n                className={`rounded px-1.5 py-0.5 font-sans font-bold ${\n                  track.muted\n                    ? 'bg-red-500/30 text-red-300'\n                    : 'bg-black-capsule text-white/80'\n                }`}\n              >\n                M\n              </button>\n              <button\n                type=\"button\"\n                onClick={() => toggleTrackSolo(track.id)}\n                className={`rounded px-1.5 py-0.5 font-sans font-bold ${\n                  track.solo\n                    ? 'bg-yellow-500/30 text-yellow-300'\n                    : 'bg-black-capsule text-white/80'\n                }`}\n              >\n                S\n              </button>\n            </div>\n            <TextBody as=\"span\" size=\"sm\" className=\"text-center text-white/80\">\n              {track.effects.filter((e) => e.enabled).length} FX\n            </TextBody>\n          </div>\n        );\n      })}\n\n      <button\n        type=\"button\"\n        onClick={() => addTrack(`Bus ${buses.length + 1}`, 'bus')}\n        className=\"w-20 flex-shrink-0 self-stretch rounded-xl border border-dashed border-panel-border font-sans font-semibold text-white/80 hover:border-[var(--we-accent)] hover:text-[var(--we-accent)]\"\n      >\n        + Bus\n      </button>\n\n      <div className=\"flex w-40 flex-shrink-0 flex-col items-stretch gap-2 rounded-xl border border-[color-mix(in_srgb,var(--we-accent)_40%,transparent)] bg-panel p-3\">\n        <TextTitle as=\"span\" size=\"xs\" className=\"text-center text-[var(--we-accent)]\">\n          Master\n        </TextTitle>\n        <div className=\"flex min-h-0 flex-1 justify-center py-1\">\n          <LevelMeter height={220} width={12} trackId=\"master\" showLufs />\n        </div>\n        <svg width={96} height={36} className=\"mx-auto\">\n          <polyline\n            fill=\"none\"\n            stroke=\"var(--we-accent)\"\n            strokeWidth=\"1.2\"\n            points={lufsHistory\n              .map((v, i) => {\n                const x = (i / Math.max(1, lufsHistory.length - 1)) * 94 + 1;\n                const y = 34 - Math.max(0, Math.min(34, ((v + 40) / 40) * 34));\n                return `${x},${y}`;\n              })\n              .join(' ')}\n          />\n        </svg>\n        <TextBody as=\"span\" size=\"sm\" className=\"text-center tabular-nums text-white/80\">\n          {lufsHistory.length\n            ? `S ${lufsHistory[lufsHistory.length - 1]!.toFixed(1)}`\n            : 'S \u2014'}\n        </TextBody>\n        <TextBody as=\"span\" size=\"sm\" className=\"text-center tabular-nums text-[var(--we-accent)]\">\n          I {integratedLufs > -69 ? integratedLufs.toFixed(1) : '\u2014'} LUFS\n        </TextBody>\n        <TextBody as=\"span\" size=\"sm\" className=\"text-center tabular-nums text-pink-400\">\n          TP {truePeakDb.toFixed(1)} dBTP\n        </TextBody>\n        <Slider\n          label={t.audio.inspector.gain}\n          value={masterVolumeDb}\n          min={-48}\n          max={12}\n          step={0.5}\n          onChange={setMasterVolumeDb}\n          formatValue={(v) => `${v.toFixed(1)} dB`}\n        />\n        <TextBody as=\"span\" size=\"sm\" className=\"text-center text-[var(--we-accent)]\">\n          Limiter ON\n        </TextBody>\n      </div>\n    </div>\n  );\n};\n", "/**\n * Conversational audio agent \u2014 POST /api/audio/agent.\n * Returns assistant text + tool_calls for the client-side executor.\n */\n\nimport { getEditorIdentity } from '../identity';\nimport { getWizardApiClient } from '../wizardApiClient';\n\nexport interface AgentMessage {\n  role: 'system' | 'user' | 'assistant' | 'tool';\n  content?: string | null;\n  name?: string;\n  tool_call_id?: string;\n  tool_calls?: AgentToolCall[];\n}\n\nexport interface AgentToolCall {\n  id: string;\n  type: 'function';\n  function: {\n    name: string;\n    arguments: string;\n  };\n}\n\nexport interface AgentToolDef {\n  type: 'function';\n  function: {\n    name: string;\n    description: string;\n    parameters: Record<string, unknown>;\n  };\n}\n\nexport interface AudioAgentTurnOptions {\n  messages: AgentMessage[];\n  projectSnapshot: unknown;\n  tools: AgentToolDef[];\n  signal?: AbortSignal;\n}\n\nexport interface AudioAgentReply {\n  role: 'assistant';\n  content: string | null;\n  tool_calls: AgentToolCall[];\n}\n\nexport async function runAudioAgentTurn(\n  opts: AudioAgentTurnOptions\n): Promise<AudioAgentReply> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postJsonForJson<AudioAgentReply>(\n    '/api/audio/agent',\n    {\n      messages: opts.messages,\n      projectSnapshot: opts.projectSnapshot,\n      tools: opts.tools,\n      account_id: accountId,\n      brand_id: brandId,\n    },\n    { signal: opts.signal }\n  );\n}\n", "/**\n * OpenAI-style tool definitions for the conversational audio agent.\n */\n\nimport type { AgentToolDef } from '../../../services/audio/audioAgentService';\n\nexport const AUDIO_AGENT_TOOLS: AgentToolDef[] = [\n  {\n    type: 'function',\n    function: {\n      name: 'add_track',\n      description: 'Add a new audio track to the project',\n      parameters: {\n        type: 'object',\n        properties: {\n          name: { type: 'string' },\n          type: { type: 'string', enum: ['audio', 'bus', 'lyrics'] },\n        },\n        required: ['name'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'set_track_volume',\n      description: 'Set or adjust track volume in dB',\n      parameters: {\n        type: 'object',\n        properties: {\n          trackId: { type: 'string' },\n          trackIndex: { type: 'number' },\n          volumeDb: { type: 'number' },\n          relative: { type: 'boolean', description: 'If true, add volumeDb to current' },\n        },\n        required: ['volumeDb'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'set_track_pan',\n      description: 'Set track pan (-1 left to +1 right)',\n      parameters: {\n        type: 'object',\n        properties: {\n          trackId: { type: 'string' },\n          trackIndex: { type: 'number' },\n          pan: { type: 'number' },\n        },\n        required: ['pan'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'add_effect',\n      description: 'Add an effect to a track',\n      parameters: {\n        type: 'object',\n        properties: {\n          trackId: { type: 'string' },\n          trackIndex: { type: 'number' },\n          effectType: {\n            type: 'string',\n            enum: [\n              'eq',\n              'compressor',\n              'gate',\n              'reverb',\n              'delay',\n              'chorus',\n              'distortion',\n              'highpass',\n              'lowpass',\n              'limiter',\n            ],\n          },\n          params: { type: 'object' },\n        },\n        required: ['effectType'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'split_clip_at',\n      description: 'Split the selected clip (or clipId) at a time in seconds',\n      parameters: {\n        type: 'object',\n        properties: {\n          clipId: { type: 'string' },\n          time: { type: 'number' },\n        },\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'apply_fade',\n      description: 'Apply fade in/out to selected clip',\n      parameters: {\n        type: 'object',\n        properties: {\n          clipId: { type: 'string' },\n          fadeInSeconds: { type: 'number' },\n          fadeOutSeconds: { type: 'number' },\n        },\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'normalize_track',\n      description: 'Raise clip gains on a track toward unity peak',\n      parameters: {\n        type: 'object',\n        properties: {\n          trackId: { type: 'string' },\n          trackIndex: { type: 'number' },\n        },\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'remove_silence',\n      description: 'Remove long silences by shortening gaps between clips (simple ripple)',\n      parameters: {\n        type: 'object',\n        properties: {\n          trackId: { type: 'string' },\n          trackIndex: { type: 'number' },\n          minSilenceSeconds: { type: 'number' },\n        },\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'generate_music',\n      description: 'Generate instrumental music with AI and insert at playhead',\n      parameters: {\n        type: 'object',\n        properties: {\n          prompt: { type: 'string' },\n          durationSeconds: { type: 'number' },\n          bpm: { type: 'number' },\n        },\n        required: ['prompt'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'generate_sfx',\n      description: 'Generate a sound effect with AI and insert at playhead',\n      parameters: {\n        type: 'object',\n        properties: {\n          prompt: { type: 'string' },\n          durationSeconds: { type: 'number' },\n        },\n        required: ['prompt'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'generate_voiceover',\n      description: 'Generate TTS voiceover and insert at playhead',\n      parameters: {\n        type: 'object',\n        properties: {\n          text: { type: 'string' },\n          voiceId: { type: 'string' },\n        },\n        required: ['text'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'isolate_vocals',\n      description: 'Isolate voice / remove background from selected clip',\n      parameters: {\n        type: 'object',\n        properties: {\n          clipId: { type: 'string' },\n        },\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'set_bpm',\n      description: 'Set project BPM',\n      parameters: {\n        type: 'object',\n        properties: { bpm: { type: 'number' } },\n        required: ['bpm'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'export_project',\n      description: 'Request an export (opens export UI / flags intent)',\n      parameters: {\n        type: 'object',\n        properties: {\n          format: { type: 'string', enum: ['wav', 'mp3', 'ogg', 'flac'] },\n          targetLufs: { type: 'number' },\n        },\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'bounce_in_place',\n      description: 'Open bounce-in-place / export UI for the selection',\n      parameters: { type: 'object', properties: {} },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'crossfade_clips',\n      description: 'Apply fade in/out to selected clips to create a crossfade feel',\n      parameters: {\n        type: 'object',\n        properties: { fadeSeconds: { type: 'number' } },\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'auto_mix',\n      description: 'Apply a simple auto-mix (levels, pan, highpass on vocals)',\n      parameters: { type: 'object', properties: {} },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'extend_music',\n      description: 'Extend / continue the selected music clip with AI',\n      parameters: {\n        type: 'object',\n        properties: {\n          prompt: { type: 'string' },\n          durationSeconds: { type: 'number' },\n        },\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'separate_stems',\n      description: 'Separate selected clip into stems (vocals/drums/bass/other)',\n      parameters: {\n        type: 'object',\n        properties: { clipId: { type: 'string' } },\n      },\n    },\n  },\n];\n\nexport const COSTLY_TOOLS = new Set([\n  'generate_music',\n  'generate_sfx',\n  'generate_voiceover',\n  'isolate_vocals',\n  'export_project',\n  'bounce_in_place',\n  'extend_music',\n  'separate_stems',\n]);\n", "/**\n * Executes agent tool calls against useAudioStore.\n * Batches a full turn into a single undo entry.\n */\n\nimport {\n  createAudioClip,\n  useAudioStore,\n  type AudioEffectType,\n} from '../../../store/useAudioStore';\nimport type { AgentToolCall } from '../../../services/audio/audioAgentService';\nimport { extendMusic, generateMusic, separateStems } from '../../../services/audio/musicService';\nimport { generateSfx } from '../../../services/audio/sfxService';\nimport { generateTts } from '../../../services/audio/voiceService';\nimport { isolateAudio } from '../../../services/audio/isolationService';\nimport { defaultEffectParams } from '../effects/createEffectChain';\nimport { COSTLY_TOOLS } from './tools';\nimport { decodeAudioBlob, extractPeaks } from '../peaks';\n\nexport interface ToolExecutionResult {\n  toolCallId: string;\n  name: string;\n  ok: boolean;\n  summary: string;\n  requiresConfirmation?: boolean;\n  pendingArgs?: Record<string, unknown>;\n}\n\nfunction resolveTrackId(args: Record<string, unknown>): string | null {\n  const state = useAudioStore.getState();\n  if (typeof args.trackId === 'string') return args.trackId;\n  if (typeof args.trackIndex === 'number') {\n    return state.tracks[args.trackIndex]?.id ?? null;\n  }\n  if (state.selectedTrackIds[0]) return state.selectedTrackIds[0];\n  return state.tracks[0]?.id ?? null;\n}\n\nfunction resolveClipId(args: Record<string, unknown>): string | null {\n  const state = useAudioStore.getState();\n  if (typeof args.clipId === 'string') return args.clipId;\n  return state.selectedClipIds[0] ?? null;\n}\n\nasync function insertBlobAsClip(\n  blob: Blob,\n  name: string,\n  durationHint?: number,\n  trackIdOverride?: string,\n): Promise<string> {\n  const state = useAudioStore.getState();\n  // Always land AI output on its own track so it does not stack on the source.\n  let trackId = trackIdOverride;\n  if (!trackId) {\n    trackId = state.addTrack('AI', 'audio');\n    state.selectTrack(trackId);\n  }\n\n  let duration = durationHint ?? 0;\n  try {\n    const buffer = await decodeAudioBlob(blob);\n    duration = buffer.duration;\n    const peaks = await extractPeaks(buffer);\n    const id = `asset_${Math.random().toString(36).slice(2, 10)}`;\n    const file = new File([blob], name, { type: blob.type || 'audio/mpeg' });\n    const url = URL.createObjectURL(blob);\n    state.addAsset({\n      id,\n      name,\n      url,\n      duration,\n      sampleRate: buffer.sampleRate,\n      channels: buffer.numberOfChannels,\n      file,\n      peaks: peaks.peaks,\n      peaksSampleRate: peaks.peaksSampleRate,\n    });\n    const clip = createAudioClip({\n      trackId,\n      assetId: id,\n      startTime: state.playheadTime,\n      duration,\n      name,\n    });\n    state.addClip(clip);\n    return clip.id;\n  } catch {\n    const id = `asset_${Math.random().toString(36).slice(2, 10)}`;\n    const file = new File([blob], name, { type: blob.type || 'audio/mpeg' });\n    const url = URL.createObjectURL(blob);\n    duration = duration || 5;\n    state.addAsset({ id, name, url, duration, file });\n    const clip = createAudioClip({\n      trackId,\n      assetId: id,\n      startTime: state.playheadTime,\n      duration,\n      name,\n    });\n    state.addClip(clip);\n    return clip.id;\n  }\n}\n\nasync function executeOne(\n  name: string,\n  args: Record<string, unknown>,\n  opts: { confirmCostly: boolean }\n): Promise<ToolExecutionResult> {\n  const store = useAudioStore.getState();\n\n  if (COSTLY_TOOLS.has(name) && opts.confirmCostly) {\n    return {\n      toolCallId: '',\n      name,\n      ok: false,\n      summary: `Confirmaci\u00F3n requerida para ${name}`,\n      requiresConfirmation: true,\n      pendingArgs: args,\n    };\n  }\n\n  switch (name) {\n    case 'add_track': {\n      const id = store.addTrack(\n        String(args.name || 'Pista'),\n        (args.type as 'audio' | 'bus' | 'lyrics') || 'audio'\n      );\n      return { toolCallId: '', name, ok: true, summary: `Pista creada (${id})` };\n    }\n    case 'set_track_volume': {\n      const trackId = resolveTrackId(args);\n      if (!trackId) return { toolCallId: '', name, ok: false, summary: 'Pista no encontrada' };\n      const track = store.tracks.find((t) => t.id === trackId)!;\n      const delta = Number(args.volumeDb);\n      const next = args.relative ? track.volumeDb + delta : delta;\n      store.updateTrack(trackId, { volumeDb: next });\n      return { toolCallId: '', name, ok: true, summary: `Volumen \u2192 ${next.toFixed(1)} dB` };\n    }\n    case 'set_track_pan': {\n      const trackId = resolveTrackId(args);\n      if (!trackId) return { toolCallId: '', name, ok: false, summary: 'Pista no encontrada' };\n      store.updateTrack(trackId, { pan: Math.max(-1, Math.min(1, Number(args.pan))) });\n      return { toolCallId: '', name, ok: true, summary: `Pan \u2192 ${args.pan}` };\n    }\n    case 'add_effect': {\n      const trackId = resolveTrackId(args);\n      if (!trackId) return { toolCallId: '', name, ok: false, summary: 'Pista no encontrada' };\n      const type = args.effectType as AudioEffectType;\n      const track = store.tracks.find((t) => t.id === trackId)!;\n      store.addEffect(trackId, {\n        id: `fx_${Math.random().toString(36).slice(2, 8)}`,\n        type,\n        enabled: true,\n        order: track.effects.length,\n        params: {\n          ...defaultEffectParams(type),\n          ...(typeof args.params === 'object' && args.params ? (args.params as object) : {}),\n        },\n      });\n      return { toolCallId: '', name, ok: true, summary: `Efecto ${type} a\u00F1adido` };\n    }\n    case 'split_clip_at': {\n      const clipId = resolveClipId(args);\n      if (!clipId) return { toolCallId: '', name, ok: false, summary: 'Clip no seleccionado' };\n      const time = typeof args.time === 'number' ? args.time : store.playheadTime;\n      store.splitClip(clipId, time);\n      return { toolCallId: '', name, ok: true, summary: `Clip dividido en ${time.toFixed(2)}s` };\n    }\n    case 'apply_fade': {\n      const clipId = resolveClipId(args);\n      if (!clipId) return { toolCallId: '', name, ok: false, summary: 'Clip no seleccionado' };\n      store.updateClip(clipId, {\n        fadeIn: Number(args.fadeInSeconds ?? 0),\n        fadeOut: Number(args.fadeOutSeconds ?? 0),\n      });\n      return { toolCallId: '', name, ok: true, summary: 'Fades aplicados' };\n    }\n    case 'normalize_track': {\n      const trackId = resolveTrackId(args);\n      if (!trackId) return { toolCallId: '', name, ok: false, summary: 'Pista no encontrada' };\n      const track = store.tracks.find((t) => t.id === trackId)!;\n      for (const clip of track.clips) {\n        store.updateClip(clip.id, { gain: Math.min(2, Math.max(clip.gain, 1)) });\n      }\n      return { toolCallId: '', name, ok: true, summary: 'Pista normalizada (gain \u2192 1)' };\n    }\n    case 'remove_silence': {\n      const trackId = resolveTrackId(args);\n      if (!trackId) return { toolCallId: '', name, ok: false, summary: 'Pista no encontrada' };\n      const minGap = Number(args.minSilenceSeconds ?? 1);\n      const track = store.tracks.find((t) => t.id === trackId)!;\n      const sorted = [...track.clips].sort((a, b) => a.startTime - b.startTime);\n      let cursor = 0;\n      for (const clip of sorted) {\n        const gap = clip.startTime - cursor;\n        if (gap > minGap) {\n          store.moveClip(clip.id, cursor);\n          cursor += clip.duration;\n        } else {\n          cursor = clip.startTime + clip.duration;\n        }\n      }\n      return { toolCallId: '', name, ok: true, summary: `Silencios > ${minGap}s compactados` };\n    }\n    case 'set_bpm': {\n      store.setBpm(Number(args.bpm));\n      return { toolCallId: '', name, ok: true, summary: `BPM \u2192 ${args.bpm}` };\n    }\n    case 'generate_music': {\n      const result = await generateMusic({\n        prompt: String(args.prompt),\n        durationSeconds: Number(args.durationSeconds ?? 30),\n        bpm: typeof args.bpm === 'number' ? args.bpm : undefined,\n      });\n      const clipId = await insertBlobAsClip(\n        result.blob,\n        `AI Music ${Date.now()}.mp3`,\n        result.durationSeconds\n      );\n      return { toolCallId: '', name, ok: true, summary: `M\u00FAsica generada (clip ${clipId})` };\n    }\n    case 'generate_sfx': {\n      const blob = await generateSfx({\n        prompt: String(args.prompt),\n        durationSeconds: Number(args.durationSeconds ?? 5),\n      });\n      const clipId = await insertBlobAsClip(blob, `SFX ${Date.now()}.mp3`, Number(args.durationSeconds ?? 5));\n      return { toolCallId: '', name, ok: true, summary: `SFX generado (clip ${clipId})` };\n    }\n    case 'generate_voiceover': {\n      const blob = await generateTts({\n        text: String(args.text),\n        voiceId: typeof args.voiceId === 'string' ? args.voiceId : undefined,\n      });\n      const clipId = await insertBlobAsClip(blob, `VO ${Date.now()}.mp3`);\n      return { toolCallId: '', name, ok: true, summary: `Voiceover generado (clip ${clipId})` };\n    }\n    case 'isolate_vocals': {\n      const clipId = resolveClipId(args);\n      if (!clipId) return { toolCallId: '', name, ok: false, summary: 'Clip no seleccionado' };\n      let assetId: string | null = null;\n      for (const t of store.tracks) {\n        const c = t.clips.find((x) => x.id === clipId);\n        if (c) {\n          assetId = c.assetId;\n          break;\n        }\n      }\n      const asset = store.assets.find((a) => a.id === assetId);\n      if (!asset?.file) return { toolCallId: '', name, ok: false, summary: 'Asset no disponible' };\n      const blob = await isolateAudio({ file: asset.file });\n      const newClipId = await insertBlobAsClip(blob, `Isolated ${asset.name}`);\n      return { toolCallId: '', name, ok: true, summary: `Voz aislada (clip ${newClipId})` };\n    }\n    case 'export_project': {\n      store.setExportModalOpen(true);\n      return {\n        toolCallId: '',\n        name,\n        ok: true,\n        summary: `Modal de export abierto (${String(args.format || 'wav')})`,\n      };\n    }\n    case 'bounce_in_place': {\n      store.setExportModalOpen(true);\n      return {\n        toolCallId: '',\n        name,\n        ok: true,\n        summary: 'Abre export y usa Bounce in place',\n      };\n    }\n    case 'auto_mix': {\n      const { analyzeBuffer } = await import('../loudness');\n      const { getAudioEngine } = await import('../AudioEngine');\n      const engine = getAudioEngine();\n      const tracks = store.tracks.filter((t) => t.type === 'audio');\n      let i = 0;\n      for (const t of tracks) {\n        const isVoice = /voz|vocal|host|guest|voice/i.test(t.name);\n        let measured = -24;\n        const clip = t.clips[0];\n        const asset = clip ? store.assets.find((a) => a.id === clip.assetId) : undefined;\n        if (asset) {\n          const buf = await engine.loadAsset(asset);\n          if (buf) measured = analyzeBuffer(buf).lufs;\n        }\n        const delta = -18 - measured;\n        store.updateTrack(t.id, {\n          volumeDb: Math.max(-24, Math.min(6, (isVoice ? -2 : -6) + delta * 0.35)),\n          pan: isVoice ? 0 : i % 2 === 0 ? -0.25 : 0.25,\n        });\n        if (!t.effects.some((e) => e.type === 'highpass') && isVoice) {\n          store.addEffect(t.id, {\n            id: `fx_hp_${i}`,\n            type: 'highpass',\n            enabled: true,\n            order: 0,\n            params: { frequency: 80, Q: 0.7 },\n          });\n        }\n        i++;\n      }\n      return { toolCallId: '', name, ok: true, summary: 'Auto-mezcla por loudness aplicada' };\n    }\n    case 'crossfade_clips': {\n      const ids = store.selectedClipIds;\n      if (ids.length < 1) {\n        return { toolCallId: '', name, ok: false, summary: 'Selecciona clips para crossfade' };\n      }\n      const fade = Number(args.fadeSeconds ?? 0.25);\n      store.applyCrossfadeBetweenSelected(fade, 'equal-power');\n      return {\n        toolCallId: '',\n        name,\n        ok: true,\n        summary: `Crossfade equal-power ~${fade}s (overlap real)`,\n      };\n    }\n    case 'extend_music': {\n      const result = await extendMusic({\n        prompt: String(args.prompt || 'continue the instrumental'),\n        durationSeconds: Number(args.durationSeconds ?? 15),\n      });\n      const clipId = await insertBlobAsClip(\n        result.blob,\n        `Extend ${Date.now()}.mp3`,\n        result.durationSeconds\n      );\n      return { toolCallId: '', name, ok: true, summary: `Extensi\u00F3n a\u00F1adida (clip ${clipId})` };\n    }\n    case 'separate_stems': {\n      const clipId = resolveClipId(args);\n      if (!clipId) return { toolCallId: '', name, ok: false, summary: 'Clip no seleccionado' };\n      let assetId: string | null = null;\n      for (const t of store.tracks) {\n        const c = t.clips.find((x) => x.id === clipId);\n        if (c) {\n          assetId = c.assetId;\n          break;\n        }\n      }\n      const asset = store.assets.find((a) => a.id === assetId);\n      if (!asset?.file) return { toolCallId: '', name, ok: false, summary: 'Asset no disponible' };\n      const { stems } = await separateStems({ file: asset.file });\n      const ids: string[] = [];\n      for (const [stemName, blob] of Object.entries(stems)) {\n        const trackId = store.addTrack(stemName, 'audio');\n        const id = await insertBlobAsClip(blob, `${stemName}.wav`, undefined, trackId);\n        ids.push(id);\n      }\n      return {\n        toolCallId: '',\n        name,\n        ok: true,\n        summary: `Stems creados: ${Object.keys(stems).join(', ')} (${ids.length} clips)`,\n      };\n    }\n    default:\n      return { toolCallId: '', name, ok: false, summary: `Tool desconocida: ${name}` };\n  }\n}\n\n/**\n * Execute all tool calls from one agent turn.\n * @param confirmCostly when true, costly tools return requiresConfirmation instead of running.\n */\nexport async function executeToolCalls(\n  toolCalls: AgentToolCall[],\n  opts: { confirmCostly?: boolean } = {}\n): Promise<ToolExecutionResult[]> {\n  const confirmCostly = opts.confirmCostly ?? true;\n  const store = useAudioStore.getState();\n  store.beginHistoryBatch('AI agent turn');\n\n  const results: ToolExecutionResult[] = [];\n  try {\n    for (const call of toolCalls) {\n      let args: Record<string, unknown> = {};\n      try {\n        args = JSON.parse(call.function.arguments || '{}') as Record<string, unknown>;\n      } catch {\n        results.push({\n          toolCallId: call.id,\n          name: call.function.name,\n          ok: false,\n          summary: 'Argumentos JSON inv\u00E1lidos',\n        });\n        continue;\n      }\n      const result = await executeOne(call.function.name, args, { confirmCostly });\n      result.toolCallId = call.id;\n      results.push(result);\n    }\n  } finally {\n    store.endHistoryBatch();\n  }\n  return results;\n}\n\n/** Run a previously confirmation-gated tool. */\nexport async function executeConfirmedTool(\n  name: string,\n  args: Record<string, unknown>\n): Promise<ToolExecutionResult> {\n  const store = useAudioStore.getState();\n  store.beginHistoryBatch(`AI ${name}`);\n  try {\n    return await executeOne(name, args, { confirmCostly: false });\n  } finally {\n    store.endHistoryBatch();\n  }\n}\n", "import React, { useRef, useState } from 'react';\nimport { Loader2, Send, Undo2 } from 'lucide-react';\nimport { useAudioStore } from '../../store/useAudioStore';\nimport {\n  runAudioAgentTurn,\n  type AgentMessage,\n} from '../../services/audio/audioAgentService';\nimport { AUDIO_AGENT_TOOLS } from '../../lib/audio/agent/tools';\nimport {\n  executeConfirmedTool,\n  executeToolCalls,\n  type ToolExecutionResult,\n} from '../../lib/audio/agent/executor';\nimport { useTranslation } from '../../i18n';\nimport { TextBody } from '../ui';\n\ninterface ChatBubble {\n  id: string;\n  role: 'user' | 'assistant' | 'system';\n  content: string;\n  toolResults?: ToolExecutionResult[];\n  pending?: Array<{ name: string; args: Record<string, unknown> }>;\n}\n\nconst MAX_AGENT_ROUNDS = 4;\n\nexport const AudioChatPanel: React.FC = () => {\n  const tr = useTranslation();\n  const { getProjectSnapshot, undo, addToast } = useAudioStore();\n  const [input, setInput] = useState('');\n  const [busy, setBusy] = useState(false);\n  const [messages, setMessages] = useState<ChatBubble[]>([\n    {\n      id: 'welcome',\n      role: 'assistant',\n      content: tr.audio.chat.welcome,\n    },\n  ]);\n  const historyRef = useRef<AgentMessage[]>([]);\n\n  const send = async () => {\n    const text = input.trim();\n    if (!text || busy) return;\n    setInput('');\n    const userBubble: ChatBubble = { id: `u_${Date.now()}`, role: 'user', content: text };\n    setMessages((m) => [...m, userBubble]);\n    historyRef.current.push({ role: 'user', content: text });\n    setBusy(true);\n\n    try {\n      const allToolResults: ToolExecutionResult[] = [];\n      const pending: ChatBubble['pending'] = [];\n      let lastContent = '';\n\n      for (let round = 0; round < MAX_AGENT_ROUNDS; round++) {\n        const reply = await runAudioAgentTurn({\n          messages: historyRef.current,\n          projectSnapshot: getProjectSnapshot(),\n          tools: AUDIO_AGENT_TOOLS,\n        });\n\n        historyRef.current.push({\n          role: 'assistant',\n          content: reply.content,\n          tool_calls: reply.tool_calls,\n        });\n        lastContent = reply.content || lastContent;\n\n        if (!reply.tool_calls?.length) break;\n\n        const toolResults = await executeToolCalls(reply.tool_calls, { confirmCostly: true });\n        allToolResults.push(...toolResults);\n\n        let hasPending = false;\n        for (const r of toolResults) {\n          if (r.requiresConfirmation && r.pendingArgs) {\n            pending.push({ name: r.name, args: r.pendingArgs });\n            hasPending = true;\n          }\n          historyRef.current.push({\n            role: 'tool',\n            tool_call_id: r.toolCallId,\n            content: JSON.stringify({ ok: r.ok, summary: r.summary }),\n          });\n        }\n\n        // Stop multi-turn if user must confirm costly ops\n        if (hasPending) break;\n\n        // Continue loop so the model can react to tool results\n        if (toolResults.every((r) => !r.ok)) break;\n      }\n\n      setMessages((m) => [\n        ...m,\n        {\n          id: `a_${Date.now()}`,\n          role: 'assistant',\n          content: lastContent || (allToolResults.length ? tr.audio.chat.toasts.done : '\u2026'),\n          toolResults: allToolResults,\n          pending: pending.length ? pending : undefined,\n        },\n      ]);\n    } catch (err) {\n      const msg = err instanceof Error ? err.message : tr.audio.chat.toasts.agentError;\n      addToast(msg, 'error');\n      setMessages((m) => [\n        ...m,\n        { id: `e_${Date.now()}`, role: 'assistant', content: msg },\n      ]);\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const confirm = async (name: string, args: Record<string, unknown>, bubbleId: string) => {\n    setBusy(true);\n    try {\n      const result = await executeConfirmedTool(name, args);\n      historyRef.current.push({\n        role: 'tool',\n        tool_call_id: `confirm_${Date.now()}`,\n        content: JSON.stringify({ ok: result.ok, summary: result.summary }),\n      });\n\n      // Follow-up turn so the agent can continue after confirmation\n      let followContent = '';\n      try {\n        const reply = await runAudioAgentTurn({\n          messages: historyRef.current,\n          projectSnapshot: getProjectSnapshot(),\n          tools: AUDIO_AGENT_TOOLS,\n        });\n        historyRef.current.push({\n          role: 'assistant',\n          content: reply.content,\n          tool_calls: reply.tool_calls,\n        });\n        followContent = reply.content || '';\n        if (reply.tool_calls?.length) {\n          const more = await executeToolCalls(reply.tool_calls, { confirmCostly: true });\n          for (const r of more) {\n            historyRef.current.push({\n              role: 'tool',\n              tool_call_id: r.toolCallId,\n              content: JSON.stringify({ ok: r.ok, summary: r.summary }),\n            });\n          }\n          setMessages((m) =>\n            m.map((b) =>\n              b.id === bubbleId\n                ? {\n                    ...b,\n                    content: followContent || b.content,\n                    pending: b.pending?.filter((p) => p.name !== name),\n                    toolResults: [...(b.toolResults || []), result, ...more],\n                  }\n                : b\n            )\n          );\n          addToast(result.summary, result.ok ? 'success' : 'error');\n          return;\n        }\n      } catch {\n        /* follow-up optional */\n      }\n\n      setMessages((m) =>\n        m.map((b) =>\n          b.id === bubbleId\n            ? {\n                ...b,\n                content: followContent || b.content,\n                pending: b.pending?.filter((p) => p.name !== name),\n                toolResults: [...(b.toolResults || []), result],\n              }\n            : b\n        )\n      );\n      addToast(result.summary, result.ok ? 'success' : 'error');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : tr.audio.chat.toasts.error, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  return (\n    <div className=\"we-audio-chat flex flex-col h-full\">\n      <div className=\"flex-1 overflow-y-auto p-3 space-y-2\">\n        {messages.map((b) => (\n          <div\n            key={b.id}\n            className={`rounded-xl px-3 py-2 ${\n              b.role === 'user'\n                ? 'ml-6 bg-[var(--we-accent-muted)] text-white'\n                : 'mr-4 border border-panel-border bg-black-capsule text-white'\n            }`}\n          >\n            <TextBody as=\"p\" size=\"sm\" className=\"whitespace-pre-wrap\">\n              {b.content}\n            </TextBody>\n            {b.toolResults?.map((r, i) => (\n              <TextBody\n                key={i}\n                as=\"div\"\n                size=\"sm\"\n                className={`mt-1.5 rounded px-2 py-1 ${\n                  r.ok ? 'bg-[#00BFA5]/15 text-[#00BFA5]' : 'bg-red-500/15 text-red-300'\n                }`}\n              >\n                {r.name}: {r.summary}\n              </TextBody>\n            ))}\n            {b.pending?.map((p, i) => (\n              <button\n                key={i}\n                type=\"button\"\n                disabled={busy}\n                onClick={() => void confirm(p.name, p.args, b.id)}\n                className=\"mt-1.5 mr-1 rounded bg-[#FFD54F]/20 px-2 py-1 text-[#FFD54F]\"\n              >\n                <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-[#FFD54F]\">\n                  {tr.audio.chat.confirmAction(p.name)}\n                </TextBody>\n              </button>\n            ))}\n            {b.toolResults && b.toolResults.some((r) => r.ok) && (\n              <button\n                type=\"button\"\n                onClick={() => undo()}\n                className=\"mt-1.5 inline-flex items-center gap-1 text-[#8888A0] hover:text-[#F0F0F5]\"\n              >\n                <Undo2 size={10} />\n                <TextBody as=\"span\" size=\"sm\" className=\"text-inherit\">\n                  {tr.audio.chat.undoAction}\n                </TextBody>\n              </button>\n            )}\n          </div>\n        ))}\n      </div>\n\n      <div className=\"flex gap-2 border-t border-panel-border p-2\">\n        <input\n          value={input}\n          onChange={(e) => setInput(e.target.value)}\n          onKeyDown={(e) => {\n            if (e.key === 'Enter' && !e.shiftKey) {\n              e.preventDefault();\n              void send();\n            }\n          }}\n          placeholder={tr.audio.chat.inputPlaceholder}\n          className=\"h-9 flex-1 rounded-xl border border-panel-border bg-black-capsule px-3 font-sans font-medium text-white outline-none focus:border-[var(--we-accent)]\"\n          disabled={busy}\n        />\n        <button\n          type=\"button\"\n          disabled={busy || !input.trim()}\n          onClick={() => void send()}\n          className=\"flex h-9 w-9 items-center justify-center rounded-xl bg-[var(--we-accent)] text-white hover:bg-[var(--we-accent-hover)] disabled:opacity-50\"\n        >\n          {busy ? <Loader2 size={14} className=\"animate-spin\" /> : <Send size={14} />}\n        </button>\n      </div>\n    </div>\n  );\n};\n", "/**\n * Microphone recording with optional monitoring via Web Audio.\n */\n\nexport interface RecordingHandle {\n  stop: () => Promise<{ blob: Blob; duration: number }>;\n  cancel: () => void;\n}\n\nexport interface StartRecordingOptions {\n  /** Monitor input through speakers (careful with feedback). */\n  monitor?: boolean;\n  mimeType?: string;\n  onLevel?: (peak: number) => void;\n}\n\nexport async function startRecording(\n  opts: StartRecordingOptions = {}\n): Promise<RecordingHandle> {\n  const stream = await navigator.mediaDevices.getUserMedia({\n    audio: {\n      echoCancellation: true,\n      noiseSuppression: true,\n      autoGainControl: false,\n    },\n  });\n\n  const mimeType =\n    opts.mimeType ||\n    (MediaRecorder.isTypeSupported('audio/webm;codecs=opus')\n      ? 'audio/webm;codecs=opus'\n      : 'audio/webm');\n\n  const recorder = new MediaRecorder(stream, { mimeType });\n  const chunks: BlobPart[] = [];\n  const startedAt = performance.now();\n\n  let monitorCtx: AudioContext | null = null;\n  let analyser: AnalyserNode | null = null;\n  let raf = 0;\n\n  if (opts.monitor || opts.onLevel) {\n    monitorCtx = new AudioContext();\n    const source = monitorCtx.createMediaStreamSource(stream);\n    analyser = monitorCtx.createAnalyser();\n    analyser.fftSize = 1024;\n    source.connect(analyser);\n    if (opts.monitor) {\n      // Very quiet monitor to reduce feedback risk\n      const gain = monitorCtx.createGain();\n      gain.gain.value = 0.15;\n      analyser.connect(gain);\n      gain.connect(monitorCtx.destination);\n    }\n    const data = new Float32Array(analyser.fftSize);\n    const tick = () => {\n      if (!analyser) return;\n      analyser.getFloatTimeDomainData(data);\n      let peak = 0;\n      for (let i = 0; i < data.length; i++) {\n        peak = Math.max(peak, Math.abs(data[i] ?? 0));\n      }\n      opts.onLevel?.(peak);\n      raf = requestAnimationFrame(tick);\n    };\n    raf = requestAnimationFrame(tick);\n  }\n\n  recorder.ondataavailable = (e) => {\n    if (e.data.size > 0) chunks.push(e.data);\n  };\n  recorder.start(200);\n\n  const cleanup = () => {\n    if (raf) cancelAnimationFrame(raf);\n    stream.getTracks().forEach((t) => t.stop());\n    void monitorCtx?.close();\n    monitorCtx = null;\n    analyser = null;\n  };\n\n  return {\n    stop: () =>\n      new Promise((resolve, reject) => {\n        recorder.onstop = () => {\n          const duration = (performance.now() - startedAt) / 1000;\n          const blob = new Blob(chunks, { type: mimeType });\n          cleanup();\n          resolve({ blob, duration });\n        };\n        recorder.onerror = () => {\n          cleanup();\n          reject(new Error('Recording failed'));\n        };\n        if (recorder.state === 'recording') recorder.stop();\n        else {\n          cleanup();\n          resolve({ blob: new Blob(chunks, { type: mimeType }), duration: 0 });\n        }\n      }),\n    cancel: () => {\n      try {\n        if (recorder.state === 'recording') recorder.stop();\n      } catch {\n        /* ignore */\n      }\n      cleanup();\n    },\n  };\n}\n", "import React, { useRef, useState } from 'react';\nimport { Circle, Square } from 'lucide-react';\nimport { useAudioStore, createAudioClip } from '../../store/useAudioStore';\nimport { startRecording, type RecordingHandle } from '../../lib/audio/recording';\nimport { decodeAudioBlob, extractPeaks } from '../../lib/audio/peaks';\nimport { useTranslation } from '../../i18n';\nimport { TextBody, TextTitle } from '../ui';\n\n\nexport const RecordingPanel: React.FC = () => {\n  const t = useTranslation();\n  const {\n    tracks,\n    playheadTime,\n    loopEnabled,\n    loopStart,\n    loopEnd,\n    addAsset,\n    addClip,\n    addToast,\n    setActiveTake,\n    compTakeInRegion,\n  } = useAudioStore();\n  const [recording, setRecording] = useState(false);\n  const [level, setLevel] = useState(0);\n  const [countdown, setCountdown] = useState(0);\n  const [monitor, setMonitor] = useState(false);\n  const [punch, setPunch] = useState(false);\n  const handleRef = useRef<RecordingHandle | null>(null);\n\n  const armed = tracks.find((t) => t.armed) ?? tracks[0];\n\n  // Group takes by takeGroupId (one entry per lane)\n  const takeGroups = (() => {\n    const map = new Map<string, Array<{ id: string; lane: number; name: string; active: boolean }>>();\n    for (const track of tracks) {\n      for (const c of track.clips) {\n        if (!c.takeGroupId) continue;\n        const list = map.get(c.takeGroupId) || [];\n        if (list.some((x) => x.lane === c.takeLane)) {\n          // Prefer showing active if any clip in lane is active\n          const existing = list.find((x) => x.lane === c.takeLane)!;\n          if (c.compActive !== false && !c.muted) existing.active = true;\n          continue;\n        }\n        list.push({\n          id: c.id,\n          lane: c.takeLane,\n          name: c.name || t.audio.recording.takeNameFallback(c.takeLane + 1),\n          active: c.compActive !== false && !c.muted,\n        });\n        map.set(c.takeGroupId, list);\n      }\n    }\n    return [...map.entries()];\n  })();\n\n  const begin = async () => {\n    if (!armed) {\n      addToast(t.audio.recording.toasts.noArmedTrack, 'warning');\n      return;\n    }\n    setCountdown(3);\n    for (let i = 3; i > 0; i--) {\n      setCountdown(i);\n      await new Promise((r) => setTimeout(r, 1000));\n    }\n    setCountdown(0);\n    try {\n      handleRef.current = await startRecording({\n        monitor,\n        onLevel: setLevel,\n      });\n      setRecording(true);\n      if (punch && loopEnabled) {\n        useAudioStore.getState().setPlayhead(loopStart);\n      }\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : t.audio.recording.toasts.micError, 'error');\n    }\n  };\n\n  const stop = async () => {\n    const handle = handleRef.current;\n    if (!handle) return;\n    setRecording(false);\n    try {\n      const { blob, duration } = await handle.stop();\n      const buffer = await decodeAudioBlob(blob);\n      const peaks = await extractPeaks(buffer);\n      const id = `rec_${Date.now()}`;\n      const trackId = armed?.id || tracks[0]!.id;\n      const start = punch && loopEnabled ? loopStart : playheadTime;\n      let clipDur = duration || buffer.duration;\n      if (punch && loopEnabled) {\n        clipDur = Math.min(clipDur, Math.max(0.1, loopEnd - loopStart));\n      }\n\n      // Same punch region \u2192 same take group; next lane\n      const takeGroupId =\n        punch && loopEnabled\n          ? `tg_${trackId}_${loopStart.toFixed(2)}_${loopEnd.toFixed(2)}`\n          : `tg_${id}`;\n      const existingLanes = useAudioStore\n        .getState()\n        .tracks.find((t) => t.id === trackId)\n        ?.clips.filter((c) => c.takeGroupId === takeGroupId)\n        .map((c) => c.takeLane) ?? [];\n      const takeLane = existingLanes.length ? Math.max(...existingLanes) + 1 : 0;\n\n      const file = new File([blob], t.audio.recording.takeFileName(takeLane + 1), { type: blob.type });\n      const url = URL.createObjectURL(blob);\n      addAsset({\n        id,\n        name: file.name,\n        url,\n        duration: clipDur,\n        sampleRate: buffer.sampleRate,\n        channels: buffer.numberOfChannels,\n        file,\n        peaks: peaks.peaks,\n        peaksSampleRate: peaks.peaksSampleRate,\n      });\n\n      const clip = createAudioClip({\n        trackId,\n        assetId: id,\n        startTime: start,\n        duration: clipDur,\n        name: file.name,\n        trimOut: clipDur,\n        takeLane,\n        takeGroupId,\n        compActive: true,\n      });\n      addClip(clip);\n      // Activate this take (mutes others in group)\n      setActiveTake(takeGroupId, takeLane);\n      addToast(t.audio.recording.toasts.takeRecorded(takeLane + 1), 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : t.audio.recording.toasts.saveError, 'error');\n    } finally {\n      handleRef.current = null;\n      setLevel(0);\n    }\n  };\n\n  return (\n    <div className=\"we-audio-recording flex flex-col gap-3 p-3\">\n      <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n        {t.audio.recording.armedTrack(armed?.name || '')}\n      </TextBody>\n      <TextBody as=\"label\" size=\"sm\" className=\"flex items-center gap-2 text-white/80\">\n        <input\n          type=\"checkbox\"\n          checked={monitor}\n          onChange={(e) => setMonitor(e.target.checked)}\n          className=\"accent-[var(--we-accent)]\"\n        />\n        {t.audio.recording.monitorLabel}\n      </TextBody>\n      <TextBody as=\"label\" size=\"sm\" className=\"flex items-center gap-2 text-white/80\">\n        <input\n          type=\"checkbox\"\n          checked={punch}\n          onChange={(e) => setPunch(e.target.checked)}\n          className=\"accent-[var(--we-accent)]\"\n        />\n        {t.audio.recording.punchLabel}\n      </TextBody>\n      {punch && loopEnabled && (\n        <TextBody as=\"p\" size=\"sm\" className=\"text-amber-300\">\n          {t.audio.recording.punchStatus(loopStart.toFixed(1), loopEnd.toFixed(1))}\n        </TextBody>\n      )}\n      {countdown > 0 && (\n        <div className=\"text-center font-display text-3xl font-bold text-[var(--we-accent)]\">\n          {countdown}\n        </div>\n      )}\n      <div className=\"h-2 overflow-hidden rounded-full bg-black-capsule\">\n        <div\n          className=\"h-full bg-[var(--we-accent)] transition-all\"\n          style={{ width: `${Math.min(100, level * 100)}%` }}\n        />\n      </div>\n      {!recording ? (\n        <button\n          type=\"button\"\n          onClick={() => void begin()}\n          className=\"flex h-9 items-center justify-center gap-2 rounded-xl border border-red-500/40 bg-red-500/20 font-sans font-bold text-red-300\"\n        >\n          <Circle size={12} fill=\"currentColor\" />\n          {t.audio.recording.recordButton}\n        </button>\n      ) : (\n        <button\n          type=\"button\"\n          onClick={() => void stop()}\n          className=\"flex h-9 items-center justify-center gap-2 rounded-xl border border-panel-border bg-black-capsule font-sans font-bold text-white\"\n        >\n          <Square size={12} />\n          {t.audio.recording.stopButton}\n        </button>\n      )}\n\n      {takeGroups.length > 0 && (\n        <div className=\"space-y-2\">\n          <TextTitle as=\"span\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n            {t.audio.recording.takeLanesHeader}\n          </TextTitle>\n          {loopEnabled && (\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {t.audio.recording.loopHint(loopStart.toFixed(1), loopEnd.toFixed(1))}\n            </TextBody>\n          )}\n          {takeGroups.map(([groupId, takes]) => (\n            <div key={groupId} className=\"space-y-1 rounded-xl border border-panel-border p-2\">\n              <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                {t.audio.recording.groupLabel(groupId)}\n              </TextBody>\n              {takes\n                .sort((a, b) => a.lane - b.lane)\n                .map((take) => (\n                  <button\n                    key={take.id}\n                    type=\"button\"\n                    onClick={(e) => {\n                      if (loopEnabled && !e.shiftKey) {\n                        compTakeInRegion(groupId, take.lane, loopStart, loopEnd);\n                        addToast(t.audio.recording.toasts.takeActiveInLoop(take.lane + 1), 'success');\n                      } else {\n                        setActiveTake(groupId, take.lane);\n                      }\n                    }}\n                    className={`block w-full rounded-lg border px-2 py-1 text-left font-sans font-medium ${\n                      take.active\n                        ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)] text-white'\n                        : 'border-panel-border bg-black-capsule text-white/80'\n                    }`}\n                  >\n                    {t.audio.recording.takeLabel(take.lane + 1, take.name, take.active)}\n                  </button>\n                ))}\n            </div>\n          ))}\n        </div>\n      )}\n    </div>\n  );\n};\n", "import React, { useState } from 'react';\nimport { Loader2, Scissors, Type, Volume2 } from 'lucide-react';\nimport { useAudioStore, createAudioClip } from '../../store/useAudioStore';\nimport { segmentsToWords, wordsToRanges, shiftWordsAfter } from '../../lib/audio/transcriptEdit';\nimport { transcribeAudioVerbose } from '../../services/transcriptionService';\nimport { generateTts, TTS_VOICES } from '../../services/audio/voiceService';\nimport { decodeAudioBlob, extractPeaks } from '../../lib/audio/peaks';\nimport { useTranslation } from '../../i18n';\nimport { TextBody, TextTitle } from '../ui';\n\n\n/**\n * Transcript-linked editing: select words, cut/ripple, remove fillers, replace with TTS.\n */\nexport const LyricsPanel: React.FC = () => {\n  const tr = useTranslation();\n  const {\n    markers,\n    playheadTime,\n    setPlayhead,\n    addMarker,\n    removeMarker,\n    transcript,\n    selectedTranscriptIds,\n    selectTranscriptWords,\n    deleteSelectedTranscriptWords,\n    removeFillerWords,\n    setTranscript,\n    tracks,\n    assets,\n    selectedClipIds,\n    addAsset,\n    addClip,\n    addToast,\n    moveClip,\n  } = useAudioStore();\n\n  const [busy, setBusy] = useState(false);\n  const [replaceText, setReplaceText] = useState('');\n  const [voiceId, setVoiceId] = useState(TTS_VOICES[0]?.id || '');\n\n  const selectedAsset = (() => {\n    for (const t of tracks) {\n      const c = t.clips.find((x) => x.id === selectedClipIds[0]);\n      if (c) return { clip: c, asset: assets.find((a) => a.id === c.assetId) };\n    }\n    return null;\n  })();\n\n  const runTranscribe = async () => {\n    if (!selectedAsset?.asset?.file || !selectedAsset.clip) {\n      addToast(tr.audio.lyrics.toasts.selectVoiceClip, 'warning');\n      return;\n    }\n    setBusy(true);\n    try {\n      const result = await transcribeAudioVerbose({ file: selectedAsset.asset.file });\n      const words = segmentsToWords(\n        result.segments,\n        selectedAsset.clip.id,\n        selectedAsset.clip.startTime,\n        result.words\n      );\n      setTranscript(words);\n      // Replace previous transcript markers only (mk_tw_*)\n      const keep = markers.filter((m) => !m.id.startsWith('mk_tw_'));\n      useAudioStore.setState({ markers: keep });\n      words\n        .filter((_, i) => i % 8 === 0)\n        .forEach((w) =>\n          addMarker({\n            id: `mk_tw_${w.id}`,\n            time: w.start,\n            name: w.text,\n            color: '#00BFA5',\n          })\n        );\n      addToast(tr.audio.lyrics.toasts.wordsTranscribed(words.length), 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : tr.audio.lyrics.toasts.transcribeError, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const replaceWithTts = async () => {\n    const text = replaceText.trim();\n    if (!text || !selectedTranscriptIds.length) {\n      addToast(tr.audio.lyrics.toasts.selectWordsWriteReplace, 'warning');\n      return;\n    }\n    setBusy(true);\n    try {\n      const ranges = wordsToRanges(transcript, new Set(selectedTranscriptIds));\n      const range = ranges[0];\n      if (!range) return;\n      const insertAt = range.start;\n      const cutDur = range.end - range.start;\n\n      const blob = await generateTts({ text, voiceId });\n      const buffer = await decodeAudioBlob(blob);\n      const peaks = await extractPeaks(buffer);\n      const ttsDur = buffer.duration;\n      const id = `tts_rep_${Date.now()}`;\n      const file = new File([blob], `Replace ${Date.now()}.mp3`, { type: blob.type });\n      const url = URL.createObjectURL(blob);\n      addAsset({\n        id,\n        name: file.name,\n        url,\n        duration: ttsDur,\n        sampleRate: buffer.sampleRate,\n        channels: buffer.numberOfChannels,\n        file,\n        peaks: peaks.peaks,\n        peaksSampleRate: peaks.peaksSampleRate,\n      });\n\n      const trackId =\n        selectedAsset?.clip.trackId ||\n        tracks.find((t) => t.type === 'audio')?.id ||\n        useAudioStore.getState().addTrack('VO', 'audio');\n\n      // 1) Punch-cut WITHOUT ripple (splits + remove middle; right stays at range.end)\n      deleteSelectedTranscriptWords({ ripple: false });\n\n      // 2) Make room for TTS: shift clips that start at/after insertAt by +(ttsDur - remaining gap)\n      // After non-ripple punch, right piece still starts at range.end \u2192 gap of cutDur exists.\n      // We want TTS of ttsDur in that gap: shift by (ttsDur - cutDur).\n      const delta = ttsDur - cutDur;\n      if (Math.abs(delta) > 0.001) {\n        const st = useAudioStore.getState();\n        for (const t of st.tracks) {\n          for (const c of t.clips) {\n            if (c.startTime >= range.end - 0.001) {\n              moveClip(c.id, Math.max(0, c.startTime + delta));\n            }\n          }\n        }\n        let words = useAudioStore.getState().transcript;\n        words = shiftWordsAfter(words, range.end, delta);\n        useAudioStore.getState().setTranscript(words);\n      }\n\n      // 3) Insert TTS at original cut start\n      const clip = createAudioClip({\n        trackId,\n        assetId: id,\n        startTime: insertAt,\n        duration: ttsDur,\n        name: text.slice(0, 24),\n        crossfadeIn: 0.08,\n        crossfadeOut: 0.08,\n        fadeIn: 0.08,\n        fadeOut: 0.08,\n        crossfadeCurve: 'equal-power',\n      });\n      addClip(clip);\n      addToast(tr.audio.lyrics.toasts.replacedTts, 'success');\n      setReplaceText('');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : tr.audio.lyrics.toasts.ttsError, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  return (\n    <div className=\"we-audio-lyrics flex h-full flex-col gap-2 overflow-hidden p-3\">\n      <div className=\"flex items-center justify-between gap-1\">\n        <TextTitle as=\"span\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n          {tr.audio.lyrics.title}\n        </TextTitle>\n        <button\n          type=\"button\"\n          disabled={busy}\n          onClick={() => void runTranscribe()}\n          className=\"flex items-center gap-1 font-sans font-bold text-[var(--we-accent)]\"\n        >\n          {busy ? <Loader2 size={10} className=\"animate-spin\" /> : <Type size={10} />}\n          {tr.audio.lyrics.transcribeClip}\n        </button>\n      </div>\n\n      <div className=\"flex flex-wrap gap-1\">\n        <button\n          type=\"button\"\n          onClick={() => deleteSelectedTranscriptWords()}\n          disabled={!selectedTranscriptIds.length}\n          className=\"flex h-7 items-center gap-1 rounded-lg border border-panel-border bg-black-capsule px-2 font-sans font-medium text-white disabled:opacity-40\"\n        >\n          <Scissors size={10} /> {tr.audio.lyrics.cut}\n        </button>\n        <button\n          type=\"button\"\n          onClick={() => removeFillerWords()}\n          className=\"h-7 rounded-lg border border-panel-border bg-black-capsule px-2 font-sans font-medium text-amber-300\"\n        >\n          {tr.audio.lyrics.removeFillers}\n        </button>\n      </div>\n\n      <div className=\"min-h-0 flex-1 overflow-y-auto rounded-xl border border-panel-border bg-panel p-2\">\n        {transcript.length === 0 ? (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n            {tr.audio.lyrics.emptyHint}\n          </TextBody>\n        ) : (\n          <TextBody as=\"p\" size=\"sm\" className=\"flex flex-wrap gap-1 leading-relaxed text-white\">\n            {transcript.map((w) => {\n              const selected = selectedTranscriptIds.includes(w.id);\n              const active = playheadTime >= w.start && playheadTime < w.end;\n              return (\n                <button\n                  key={w.id}\n                  type=\"button\"\n                  onClick={(e) => {\n                    selectTranscriptWords([w.id], e.shiftKey);\n                    setPlayhead(w.start);\n                  }}\n                  className={`rounded px-1 ${\n                    selected\n                      ? 'bg-[var(--we-accent)] text-white'\n                      : active\n                        ? 'bg-[var(--we-accent-muted)] text-white'\n                        : w.isFiller\n                          ? 'text-amber-300/80'\n                          : 'text-white/80 hover:bg-black-capsule'\n                  }`}\n                >\n                  {w.text}\n                </button>\n              );\n            })}\n          </TextBody>\n        )}\n      </div>\n\n      <div className=\"space-y-1.5 border-t border-panel-border pt-2\">\n        <TextTitle as=\"span\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n          {tr.audio.lyrics.replaceSection}\n        </TextTitle>\n        <textarea\n          value={replaceText}\n          onChange={(e) => setReplaceText(e.target.value)}\n          placeholder={tr.audio.lyrics.replacePlaceholder}\n          className=\"h-14 w-full resize-none rounded-xl border border-panel-border bg-black-capsule p-2 font-sans font-medium text-white outline-none focus:border-[var(--we-accent)]\"\n        />\n        <select\n          value={voiceId}\n          onChange={(e) => setVoiceId(e.target.value)}\n          className=\"h-7 w-full rounded-lg border border-panel-border bg-black-capsule px-1 font-sans font-medium text-white\"\n        >\n          {TTS_VOICES.map((v) => (\n            <option key={v.id} value={v.id}>\n              {v.label}\n            </option>\n          ))}\n        </select>\n        <button\n          type=\"button\"\n          disabled={busy || !replaceText.trim()}\n          onClick={() => void replaceWithTts()}\n          className=\"flex h-8 w-full items-center justify-center gap-1 rounded-xl bg-[var(--we-accent)] font-sans font-bold text-white hover:bg-[var(--we-accent-hover)] disabled:opacity-50\"\n        >\n          <Volume2 size={12} /> {tr.audio.lyrics.replaceWithVoice}\n        </button>\n      </div>\n\n      <div className=\"max-h-28 overflow-y-auto border-t border-panel-border pt-2\">\n        <div className=\"mb-1 flex items-center justify-between\">\n          <TextTitle as=\"span\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n            {tr.audio.lyrics.markersSection}\n          </TextTitle>\n          <button\n            type=\"button\"\n            onClick={() =>\n              addMarker({\n                id: `mk_${Date.now()}`,\n                time: playheadTime,\n                name: tr.audio.lyrics.markerName(markers.length + 1),\n                color: '#FFD54F',\n              })\n            }\n            className=\"font-sans font-bold text-[var(--we-accent)]\"\n          >\n            {tr.audio.lyrics.markerAddHere}\n          </button>\n        </div>\n        {markers\n          .slice()\n          .sort((a, b) => a.time - b.time)\n          .map((m) => (\n            <button\n              key={m.id}\n              type=\"button\"\n              onClick={() => setPlayhead(m.time)}\n              className=\"flex w-full items-center gap-2 rounded px-1 py-0.5 text-left font-sans font-medium text-white/80 hover:bg-black-capsule\"\n            >\n              <span className=\"w-10 tabular-nums\">{m.time.toFixed(1)}</span>\n              <span className=\"flex-1 truncate text-white\">{m.name}</span>\n              <span\n                role=\"button\"\n                tabIndex={0}\n                onClick={(e) => {\n                  e.stopPropagation();\n                  removeMarker(m.id);\n                }}\n                className=\"hover:text-red-400\"\n              >\n                x\n              </span>\n            </button>\n          ))}\n      </div>\n\n    </div>\n  );\n};\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { Loader2, Music, Pause, Play, RefreshCw } from 'lucide-react';\nimport {\n  fetchRemoteMediaAsFile,\n  listMediaJobsWithS3,\n  type FileMediaItem,\n} from '../../services/imageJobsService';\nimport { useAudioStore, createAudioClip } from '../../store/useAudioStore';\nimport { decodeAudioBlob, extractPeaks } from '../../lib/audio/peaks';\nimport { useTranslation } from '../../i18n';\nimport { Button, IconButton, PanelBody, PanelSection, TextBody } from '../ui';\n\n\nfunction previewProxyUrl(url: string, name: string): string {\n  return `/api/download?mode=download&filename=${encodeURIComponent(name)}&url=${encodeURIComponent(url)}`;\n}\n\n/**\n * Cloud AI audio jobs \u2014 download and drop onto the audio timeline.\n */\nexport const AudioJobsPanel: React.FC = () => {\n  const t = useTranslation();\n  const tp = t.audio.jobsPanel;\n  const { addAsset, addClip, addTrack, addToast, playheadTime, tracks, assets } =\n    useAudioStore();\n  const [items, setItems] = useState<FileMediaItem[]>([]);\n  const [loading, setLoading] = useState(true);\n  const [addingId, setAddingId] = useState<string | null>(null);\n  const [error, setError] = useState<string | null>(null);\n  const [playingId, setPlayingId] = useState<string | null>(null);\n  const previewRef = useRef<HTMLAudioElement | null>(null);\n\n  const stopPreview = () => {\n    const a = previewRef.current;\n    if (a) {\n      a.pause();\n      a.removeAttribute('src');\n      a.load();\n    }\n    setPlayingId(null);\n  };\n\n  useEffect(() => () => stopPreview(), []);\n\n  const load = async (signal?: AbortSignal) => {\n    setLoading(true);\n    setError(null);\n    try {\n      const rows = await listMediaJobsWithS3({ signal });\n      if (!signal?.aborted) setItems(rows.filter((r) => r.kind === 'audio'));\n    } catch {\n      if (!signal?.aborted) {\n        setItems([]);\n        setError(tp.loadError);\n      }\n    } finally {\n      if (!signal?.aborted) setLoading(false);\n    }\n  };\n\n  useEffect(() => {\n    const ac = new AbortController();\n    void load(ac.signal);\n    return () => ac.abort();\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  const togglePreview = (item: FileMediaItem, e: React.MouseEvent) => {\n    e.stopPropagation();\n    e.preventDefault();\n    if (playingId === item.id) {\n      stopPreview();\n      return;\n    }\n    stopPreview();\n    const audio = previewRef.current ?? new Audio();\n    previewRef.current = audio;\n    const safeName = `${item.name.replace(/[^\\w.\\-]+/g, '_').slice(0, 40)}.mp3`;\n    audio.src = previewProxyUrl(item.url, safeName);\n    audio.onended = () => setPlayingId(null);\n    audio.onerror = () => {\n      setPlayingId(null);\n      addToast(tp.previewError, 'error');\n    };\n    void audio.play().then(\n      () => setPlayingId(item.id),\n      () => {\n        setPlayingId(null);\n        addToast(tp.previewError, 'error');\n      },\n    );\n  };\n\n  const addToTimeline = async (item: FileMediaItem) => {\n    setAddingId(item.id);\n    stopPreview();\n    try {\n      const displayName = (item.category?.trim() || item.name).trim();\n      const safeName = `${displayName.replace(/[^\\w.\\-]+/g, '_').slice(0, 40)}.mp3`;\n      const downloaded = await fetchRemoteMediaAsFile(item.url, safeName, 'audio/mpeg');\n      if (!downloaded) throw new Error(tp.fetchError);\n\n      const existing = assets.find(\n        (a) => a.url === item.url || (a as { remoteUrl?: string }).remoteUrl === item.url,\n      );\n      let assetId = existing?.id;\n      let duration = existing?.duration;\n\n      if (!assetId) {\n        const buffer = await decodeAudioBlob(downloaded.file);\n        const peaks = await extractPeaks(buffer);\n        assetId = `job_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;\n        duration = buffer.duration;\n        addAsset({\n          id: assetId,\n          name: displayName,\n          url: downloaded.objectUrl,\n          duration,\n          sampleRate: buffer.sampleRate,\n          channels: buffer.numberOfChannels,\n          file: downloaded.file,\n          peaks: peaks.peaks,\n          peaksSampleRate: peaks.peaksSampleRate,\n        });\n      } else {\n        URL.revokeObjectURL(downloaded.objectUrl);\n      }\n\n      let trackId = tracks.find((tr) => tr.type === 'audio')?.id;\n      if (!trackId) trackId = addTrack(tp.defaultTrackName, 'audio');\n\n      addClip(\n        createAudioClip({\n          trackId,\n          assetId,\n          startTime: playheadTime,\n          duration: duration ?? 5,\n          name: displayName,\n        }),\n      );\n      addToast(tp.addedToast(item.name), 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : tp.fetchError, 'error');\n    } finally {\n      setAddingId(null);\n    }\n  };\n\n  return (\n    <PanelBody>\n      <PanelSection\n        title={tp.header}\n        trailing={\n          <IconButton\n            variant=\"ghost\"\n            size=\"sm\"\n            label={tp.refresh}\n            onClick={() => void load()}\n            disabled={loading}\n          >\n            <RefreshCw size={14} className={loading ? 'animate-spin' : undefined} />\n          </IconButton>\n        }\n      >\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{tp.hint}</TextBody>\n\n        {loading && (\n          <div className=\"grid grid-cols-1 gap-2\" aria-busy aria-label={tp.loading}>\n            {Array.from({ length: 4 }).map((_, i) => (\n              <div\n                key={i}\n                className=\"h-12 animate-pulse rounded-xl border border-panel-border bg-black-capsule\"\n              />\n            ))}\n          </div>\n        )}\n\n        {!loading && error && (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-red-300\">{error}</TextBody>\n        )}\n\n        {!loading && !error && items.length === 0 && (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{tp.empty}</TextBody>\n        )}\n\n        {!loading && items.length > 0 && (\n          <ul className=\"flex flex-col gap-1.5\">\n            {items.map((item) => {\n              const title = (item.category?.trim() || item.name).trim();\n              return (\n              <li key={item.id}>\n                <div className=\"flex items-center gap-1 rounded-xl border border-panel-border bg-panel px-1.5 py-1.5 transition-colors hover:border-[var(--we-accent-stroke)] hover:bg-[var(--we-accent-panel)]\">\n                  <button\n                    type=\"button\"\n                    disabled={addingId === item.id}\n                    onClick={() => void addToTimeline(item)}\n                    className=\"flex min-w-0 flex-1 items-center gap-2 px-1 py-0.5 text-left disabled:opacity-50\"\n                    title={tp.addHint}\n                  >\n                    <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-[var(--we-accent-capsule)] text-[var(--we-accent)]\">\n                      {addingId === item.id ? (\n                        <Loader2 size={14} className=\"animate-spin\" />\n                      ) : (\n                        <Music size={14} />\n                      )}\n                    </span>\n                    <TextBody as=\"span\" size=\"sm\" className=\"min-w-0 flex-1 truncate text-white\">\n                      {title}\n                    </TextBody>\n                  </button>\n                  <IconButton\n                    variant=\"ghost\"\n                    size=\"sm\"\n                    label={playingId === item.id ? tp.previewStop : tp.preview}\n                    onClick={(e) => togglePreview(item, e)}\n                    active={playingId === item.id}\n                  >\n                    {playingId === item.id ? <Pause size={14} /> : <Play size={14} />}\n                  </IconButton>\n                </div>\n              </li>\n              );\n            })}\n          </ul>\n        )}\n\n        {!loading && error && (\n          <Button variant=\"secondary\" size=\"sm\" onClick={() => void load()}>\n            {tp.refresh}\n          </Button>\n        )}\n      </PanelSection>\n    </PanelBody>\n  );\n};\n", "import React, { useCallback, useState } from 'react';\nimport {\n  Folder,\n  HardDrive,\n  MessageSquare,\n  Mic2,\n  Music2,\n  RotateCcw,\n  Scissors,\n  SlidersHorizontal,\n  Upload,\n} from 'lucide-react';\nimport { IconButton, Modal } from '../ui';\nimport { useTranslation } from '../../i18n';\nimport {\n  useAudioUiStore,\n  type AudioLibraryTabId,\n  type AudioRightPanelId,\n} from '../../store/useAudioUiStore';\nimport { AudioInspector } from './AudioInspector';\nimport { EffectsRack } from './EffectsRack';\nimport { Mixer } from './Mixer';\nimport { AudioChatPanel } from './AudioChatPanel';\nimport { RecordingPanel } from './RecordingPanel';\nimport { LyricsPanel } from './LyricsPanel';\nimport { AudioJobsPanel } from './AudioJobsPanel';\nimport { TextBody, TextTitle } from '../ui';\n\n\nconst DEFAULT_WIDTH = 340;\nconst MIN_WIDTH = 280;\nconst MAX_WIDTH = 520;\n\nconst RAIL: {\n  id: AudioRightPanelId;\n  icon: React.ReactNode;\n  labelKey: 'tabClip' | 'tabFx' | 'tabChat' | 'tabRecord' | 'tabLyrics';\n  titleKey: 'titleInspector' | 'titleFx' | 'titleChat' | 'titleRecord' | 'titleLyrics';\n}[] = [\n  { id: 'inspector', icon: <Scissors size={17} />, labelKey: 'tabClip', titleKey: 'titleInspector' },\n  { id: 'fx', icon: <Music2 size={17} />, labelKey: 'tabFx', titleKey: 'titleFx' },\n  { id: 'chat', icon: <MessageSquare size={17} />, labelKey: 'tabChat', titleKey: 'titleChat' },\n  { id: 'record', icon: <Mic2 size={17} />, labelKey: 'tabRecord', titleKey: 'titleRecord' },\n  { id: 'lyrics', icon: <Music2 size={17} />, labelKey: 'tabLyrics', titleKey: 'titleLyrics' },\n];\n\nfunction PanelContent({ id }: { id: AudioRightPanelId }) {\n  switch (id) {\n    case 'inspector':\n      return <AudioInspector />;\n    case 'fx':\n      return <EffectsRack />;\n    case 'chat':\n      return <AudioChatPanel />;\n    case 'record':\n      return <RecordingPanel />;\n    case 'lyrics':\n      return <LyricsPanel />;\n  }\n}\n\nexport interface AudioRightSidebarProps {\n  onImportFiles: () => void;\n}\n\n/**\n * Right dock: library by default; inspector/FX/etc replace library when a rail\n * button is active (same pattern as video RightSidebar).\n */\nexport const AudioRightSidebar: React.FC<AudioRightSidebarProps> = ({ onImportFiles }) => {\n  const t = useTranslation();\n  const libraryTab = useAudioUiStore((s) => s.libraryTab);\n  const setLibraryTab = useAudioUiStore((s) => s.setLibraryTab);\n  const activePanel = useAudioUiStore((s) => s.rightPanel);\n  const setRightPanel = useAudioUiStore((s) => s.setRightPanel);\n  const toggleRightPanel = useAudioUiStore((s) => s.toggleRightPanel);\n  const mixerOpen = useAudioUiStore((s) => s.mixerOpen);\n  const setMixerOpen = useAudioUiStore((s) => s.setMixerOpen);\n  const toggleMixer = useAudioUiStore((s) => s.toggleMixer);\n  const [panelWidth, setPanelWidth] = useState(DEFAULT_WIDTH);\n\n  const onResizeStart = useCallback(\n    (e: React.MouseEvent) => {\n      e.preventDefault();\n      const startX = e.clientX;\n      const startW = panelWidth;\n      const onMove = (ev: MouseEvent) => {\n        setPanelWidth(Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, startW + (startX - ev.clientX))));\n      };\n      const onUp = () => {\n        window.removeEventListener('mousemove', onMove);\n        window.removeEventListener('mouseup', onUp);\n      };\n      window.addEventListener('mousemove', onMove);\n      window.addEventListener('mouseup', onUp);\n    },\n    [panelWidth],\n  );\n\n  const titleKey = RAIL.find((p) => p.id === activePanel)?.titleKey;\n  const headerTitle = activePanel && titleKey\n    ? t.audio.sidebar[titleKey]\n    : libraryTab === 'myFiles'\n      ? t.leftPanel.myFiles\n      : t.audio.sidebar.titleLibrary;\n\n  const libraryTabs: { id: AudioLibraryTabId; icon: React.ReactNode; label: string }[] = [\n    { id: 'assets', icon: <Folder size={13} />, label: t.leftPanel.assets },\n    { id: 'myFiles', icon: <HardDrive size={13} />, label: t.leftPanel.myFiles },\n  ];\n\n  return (\n    <>\n      <aside className=\"flex h-full min-h-0 shrink-0 select-none border-l border-panel-border bg-panel\">\n        <div className=\"relative flex h-full min-h-0 flex-col\" style={{ width: `${panelWidth}px` }}>\n          <div\n            role=\"separator\"\n            aria-orientation=\"vertical\"\n            aria-label={t.panel.resizeWidth}\n            onMouseDown={onResizeStart}\n            className=\"absolute inset-y-0 left-0 z-10 w-1.5 cursor-ew-resize group/hresize\"\n          >\n            <div className=\"absolute inset-y-0 left-0 w-0.5 rounded-r-full bg-transparent transition-colors group-hover/hresize:bg-[var(--we-accent-capsule)]\" />\n          </div>\n\n          <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-panel-border px-3 py-2 pl-4\">\n            <TextTitle as=\"h2\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n              {headerTitle}\n            </TextTitle>\n            <div className=\"flex items-center gap-0.5\">\n              {activePanel && (\n                <IconButton\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  label={t.panel.closePanel}\n                  onClick={() => setRightPanel(null)}\n                >\n                  <span className=\"text-xs\">\u00D7</span>\n                </IconButton>\n              )}\n              {panelWidth !== DEFAULT_WIDTH && (\n                <IconButton\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  label={t.panel.resetWidth}\n                  onClick={() => setPanelWidth(DEFAULT_WIDTH)}\n                >\n                  <RotateCcw size={14} />\n                </IconButton>\n              )}\n            </div>\n          </div>\n\n          <div className=\"min-h-0 flex-1 overflow-y-auto\">\n            {activePanel ? (\n              <PanelContent id={activePanel} />\n            ) : (\n              <>\n                <div className=\"flex shrink-0 gap-1 px-2 pt-2\">\n                  {libraryTabs.map((tab) => {\n                    const active = libraryTab === tab.id;\n                    return (\n                      <button\n                        key={tab.id}\n                        type=\"button\"\n                        title={tab.label}\n                        onClick={() => setLibraryTab(tab.id)}\n                        className={`\n                          inline-flex flex-1 items-center justify-center gap-1 rounded-lg px-2 py-1.5\n                          font-sans font-semibold transition-colors\n                          ${\n                            active\n                              ? 'bg-[var(--we-accent-muted)] text-white'\n                              : 'text-white/80 hover:bg-black-capsule hover:text-white'\n                          }\n                        `}\n                      >\n                        {tab.icon}\n                        <span className=\"truncate\">{tab.label}</span>\n                      </button>\n                    );\n                  })}\n                </div>\n                <div\n                  className={\n                    libraryTab === 'myFiles' ? '' : 'p-3'\n                  }\n                >\n                  {libraryTab === 'assets' ? (\n                    <div className=\"flex flex-col gap-3\">\n                      <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n                        {t.audio.editor.dragFormatHint}\n                      </TextBody>\n                      <button\n                        type=\"button\"\n                        onClick={onImportFiles}\n                        className=\"inline-flex items-center justify-center gap-2 rounded-xl bg-[var(--we-accent)] px-3 py-2 font-sans text-xs font-semibold text-white hover:bg-[var(--we-accent-hover)]\"\n                      >\n                        <Upload size={14} />\n                        {t.audio.editor.chooseFiles}\n                      </button>\n                    </div>\n                  ) : (\n                    <AudioJobsPanel />\n                  )}\n                </div>\n              </>\n            )}\n          </div>\n        </div>\n\n        <div className=\"flex w-11 shrink-0 flex-col items-center gap-1.5 border-l border-panel-border bg-panel py-2\">\n          <button\n            type=\"button\"\n            title={t.audio.sidebar.tabLibrary}\n            onClick={() => setRightPanel(null)}\n            className={`\n              relative flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg\n              transition-all duration-150 active:scale-90\n              ${\n                !activePanel && !mixerOpen\n                  ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--we-accent)_35%,transparent)]'\n                  : 'text-white/80 hover:bg-black-capsule hover:text-white'\n              }\n            `}\n          >\n            {!activePanel && !mixerOpen && (\n              <span className=\"absolute right-0 top-1/2 h-4 w-0.5 -translate-y-1/2 rounded-l-full bg-[var(--we-accent)]\" />\n            )}\n            <Folder size={17} />\n          </button>\n\n          <div className=\"my-0.5 h-px w-5 bg-panel-border\" aria-hidden />\n\n          {RAIL.map((item) => {\n            const isActive = activePanel === item.id;\n            return (\n              <button\n                key={item.id}\n                type=\"button\"\n                title={t.audio.sidebar[item.labelKey]}\n                onClick={() => toggleRightPanel(item.id)}\n                className={`\n                  relative flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg\n                  transition-all duration-150 active:scale-90\n                  ${\n                    isActive\n                      ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--we-accent)_35%,transparent)]'\n                      : 'text-white/80 hover:bg-black-capsule hover:text-white'\n                  }\n                `}\n              >\n                {isActive && (\n                  <span className=\"absolute right-0 top-1/2 h-4 w-0.5 -translate-y-1/2 rounded-l-full bg-[var(--we-accent)]\" />\n                )}\n                {item.icon}\n              </button>\n            );\n          })}\n\n          <div className=\"mt-auto flex flex-col items-center gap-1.5 border-t border-panel-border pt-2\">\n            <button\n              type=\"button\"\n              title={t.audio.sidebar.tabMixer}\n              onClick={() => toggleMixer()}\n              className={`\n                relative flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg\n                transition-all duration-150 active:scale-90\n                ${\n                  mixerOpen\n                    ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--we-accent)_35%,transparent)]'\n                    : 'text-white/80 hover:bg-black-capsule hover:text-white'\n                }\n              `}\n            >\n              {mixerOpen && (\n                <span className=\"absolute right-0 top-1/2 h-4 w-0.5 -translate-y-1/2 rounded-l-full bg-[var(--we-accent)]\" />\n              )}\n              <SlidersHorizontal size={17} />\n            </button>\n          </div>\n        </div>\n      </aside>\n\n      <Modal\n        isOpen={mixerOpen}\n        onClose={() => setMixerOpen(false)}\n        title={t.audio.sidebar.titleMixer}\n        size=\"full\"\n        bodyClassName=\"flex flex-col !py-4\"\n      >\n        <div className=\"-mx-2 flex min-h-0 flex-1 flex-col\">\n          <Mixer />\n        </div>\n      </Modal>\n    </>\n  );\n};\n", "import React from 'react';\nimport { Lock, Mic, Plus, Trash2, VolumeX, Headphones } from 'lucide-react';\nimport { useAudioStore } from '../../store/useAudioStore';\nimport { useTranslation, getActiveMessages } from '../../i18n';\nimport { useDialog } from '../DialogModal';\nimport { IconButton, TextBody, TextTitle } from '../ui';\n\n\nconst TRACK_HEIGHT = 100;\n\ninterface Props {\n  width: number;\n}\n\nexport const AudioTrackControls: React.FC<Props> = ({ width }) => {\n  const t = useTranslation();\n  const dialog = useDialog();\n  const {\n    tracks,\n    scrollTop,\n    selectedTrackIds,\n    addTrack,\n    removeTrack,\n    toggleTrackMute,\n    toggleTrackSolo,\n    toggleTrackLock,\n    toggleTrackArm,\n    selectTrack,\n    updateTrack,\n    addToast,\n  } = useAudioStore();\n\n  const deleteTrack = async (trackId: string, name: string) => {\n    const audioCount = tracks.filter((tr) => tr.type === 'audio' || tr.type === 'bus').length;\n    if (audioCount <= 1) {\n      addToast(getActiveMessages().store.toasts.audio.keepOneTrack, 'warning');\n      return;\n    }\n    const ok = await dialog.confirm(t.audio.editor.deleteTrackConfirm(name), {\n      title: t.audio.editor.deleteConfirmTitle,\n      variant: 'danger',\n      confirmText: t.audio.editor.deleteConfirmBtn,\n      cancelText: t.common.cancel,\n    });\n    if (!ok) return;\n    removeTrack(trackId);\n    addToast(getActiveMessages().store.toasts.audio.trackDeleted(name), 'info');\n  };\n\n  return (\n    <div\n      className=\"we-audio-track-controls relative z-0 flex shrink-0 flex-col overflow-hidden border-r border-panel-border bg-panel\"\n      style={{ width: `${width}px` }}\n    >\n      <div className=\"flex h-8 shrink-0 items-center justify-between gap-1 border-b border-panel-border px-2\">\n        <TextTitle as=\"span\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n          {t.audio.tracks.header}\n        </TextTitle>\n        <IconButton\n          variant=\"ghost\"\n          size=\"sm\"\n          label={t.audio.tracks.addTrack}\n          onClick={() => addTrack(`${t.audio.tracks.header} ${tracks.length + 1}`)}\n        >\n          <Plus size={12} />\n        </IconButton>\n      </div>\n      <div className=\"relative min-h-0 flex-1 overflow-hidden\">\n        {/* Runtime Y sync with timeline scrollTop \u2014 Tailwind cannot express translateY(dynamic). */}\n        <div style={{ transform: `translateY(-${scrollTop}px)` }}>\n          {tracks.map((track) => {\n            const selected = selectedTrackIds.includes(track.id);\n            return (\n              <div\n                key={track.id}\n                className={`flex cursor-pointer flex-col justify-center border-b border-panel-border px-2 ${\n                  selected\n                    ? 'bg-[var(--we-accent-muted)]'\n                    : 'bg-panel hover:bg-black-capsule'\n                }`}\n                style={{ height: TRACK_HEIGHT }}\n                onClick={() => selectTrack(track.id)}\n              >\n                <div className=\"mb-1 flex items-center gap-1.5\">\n                  <span\n                    className=\"h-2 w-2 shrink-0 rounded-full bg-[var(--we-accent)]\"\n                    style={track.color ? { background: track.color } : undefined}\n                  />\n                  <input\n                    value={track.name}\n                    onChange={(e) => updateTrack(track.id, { name: e.target.value })}\n                    onClick={(e) => e.stopPropagation()}\n                    className=\"min-w-0 flex-1 bg-transparent font-sans font-semibold text-white outline-none\"\n                  />\n                  <IconButton\n                    variant=\"ghost\"\n                    size=\"sm\"\n                    label={t.audio.tracks.deleteTrack}\n                    onClick={(e) => {\n                      e.stopPropagation();\n                      void deleteTrack(track.id, track.name);\n                    }}\n                  >\n                    <Trash2 size={11} className=\"text-red-300\" />\n                  </IconButton>\n                </div>\n                <div className=\"flex items-center gap-0.5\">\n                  <IconButton\n                    variant=\"ghost\"\n                    size=\"sm\"\n                    label={t.audio.tracks.mute}\n                    active={track.muted}\n                    className={track.muted ? 'text-red-400' : undefined}\n                    onClick={(e) => {\n                      e.stopPropagation();\n                      toggleTrackMute(track.id);\n                    }}\n                  >\n                    <VolumeX size={11} />\n                  </IconButton>\n                  <IconButton\n                    variant=\"ghost\"\n                    size=\"sm\"\n                    label={t.audio.tracks.solo}\n                    active={track.solo}\n                    className={track.solo ? 'text-yellow-400' : undefined}\n                    onClick={(e) => {\n                      e.stopPropagation();\n                      toggleTrackSolo(track.id);\n                    }}\n                  >\n                    <Headphones size={11} />\n                  </IconButton>\n                  <IconButton\n                    variant=\"ghost\"\n                    size=\"sm\"\n                    label={t.audio.tracks.arm}\n                    active={track.armed}\n                    className={track.armed ? 'bg-red-500 text-white hover:bg-red-500' : undefined}\n                    onClick={(e) => {\n                      e.stopPropagation();\n                      toggleTrackArm(track.id);\n                    }}\n                  >\n                    <Mic size={11} />\n                  </IconButton>\n                  <IconButton\n                    variant=\"ghost\"\n                    size=\"sm\"\n                    label={t.audio.tracks.lock}\n                    active={track.locked}\n                    onClick={(e) => {\n                      e.stopPropagation();\n                      toggleTrackLock(track.id);\n                    }}\n                  >\n                    <Lock size={11} />\n                  </IconButton>\n                  <TextBody as=\"span\" size=\"sm\" className=\"ml-auto tabular-nums text-white/80\">\n                    {track.volumeDb.toFixed(0)} dB\n                  </TextBody>\n                </div>\n              </div>\n            );\n          })}\n        </div>\n      </div>\n    </div>\n  );\n};\n\nexport const AUDIO_TRACK_HEIGHT = TRACK_HEIGHT;\n", "/**\n * Zoom-aware timeline snap + beat grid subdivisions.\n * Whole-beat snap feels jumpy for cuts; denser steps when zoomed in.\n */\n\nexport type SnapMode = 'time' | 'beat';\n\nexport type BeatGridLine = {\n  t: number;\n  kind: 'bar' | 'beat' | 'sub';\n};\n\n/** Snap increment in seconds for the current zoom / tempo. */\nexport function snapStepSeconds(opts: {\n  snapEnabled: boolean;\n  snapMode: SnapMode;\n  bpm: number;\n  zoom: number;\n}): number | null {\n  if (!opts.snapEnabled) return null;\n  const zoom = Math.max(1, opts.zoom);\n\n  if (opts.snapMode === 'beat' && opts.bpm > 0) {\n    const beat = 60 / opts.bpm;\n    const pxPerBeat = beat * zoom;\n    // Target ~8\u201320px between snap points for precise cuts without jitter.\n    let div = 1;\n    if (pxPerBeat >= 192) div = 16;\n    else if (pxPerBeat >= 96) div = 8;\n    else if (pxPerBeat >= 48) div = 4;\n    else if (pxPerBeat >= 24) div = 2;\n    return beat / div;\n  }\n\n  // Time mode: ~8px steps, snapped to nice durations.\n  const target = 8 / zoom;\n  const candidates = [0.001, 0.005, 0.01, 0.02, 0.05, 0.1, 0.25, 0.5, 1, 2, 5];\n  for (const c of candidates) {\n    if (c >= target) return c;\n  }\n  return 5;\n}\n\nexport function snapTime(tSec: number, step: number | null): number {\n  if (step == null || step <= 0) return Math.max(0, tSec);\n  return Math.max(0, Math.round(tSec / step) * step);\n}\n\n/** Beat / bar / subdivision lines visible in the viewport. */\nexport function buildBeatGridLines(opts: {\n  bpm: number;\n  zoom: number;\n  scrollLeft: number;\n  width: number;\n  beatsPerBar?: number;\n  projectDuration?: number;\n}): BeatGridLine[] {\n  const { bpm, zoom, scrollLeft, width } = opts;\n  if (!(bpm > 0) || zoom <= 0) return [];\n\n  const beat = 60 / bpm;\n  const beatsPerBar = Math.max(1, opts.beatsPerBar ?? 4);\n  const pxPerBeat = beat * zoom;\n\n  let div = 1;\n  if (pxPerBeat >= 192) div = 16;\n  else if (pxPerBeat >= 96) div = 8;\n  else if (pxPerBeat >= 48) div = 4;\n  else if (pxPerBeat >= 24) div = 2;\n\n  const step = beat / div;\n  const viewStart = scrollLeft / zoom;\n  const viewEnd = (scrollLeft + width) / zoom;\n  const startI = Math.max(0, Math.floor(viewStart / step) - 1);\n  const endI = Math.ceil(viewEnd / step) + 1;\n  const maxT = opts.projectDuration != null ? opts.projectDuration + beat : Infinity;\n\n  const lines: BeatGridLine[] = [];\n  const maxLines = 800;\n  for (let i = startI; i <= endI && lines.length < maxLines; i++) {\n    const t = i * step;\n    if (t > maxT) break;\n    const beatIndex = Math.round(t / beat);\n    const onBeat = Math.abs(t / beat - beatIndex) < 1e-6;\n    const onBar = onBeat && beatIndex % beatsPerBar === 0;\n    lines.push({\n      t,\n      kind: onBar ? 'bar' : onBeat ? 'beat' : 'sub',\n    });\n  }\n  return lines;\n}\n", "import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Stage, Layer, Rect, Line, Text, Group, Shape } from 'react-konva';\nimport {\n  ClipboardPaste,\n  Copy,\n  EyeOff,\n  Folder,\n  Link2,\n  Lock,\n  Plus,\n  Scissors,\n  Sparkles,\n  Trash2,\n  Upload,\n  Waves,\n} from 'lucide-react';\nimport { useAudioStore, AUDIO_ZOOM_MIN, AUDIO_ZOOM_MAX } from '../../store/useAudioStore';\nimport { useAudioUiStore } from '../../store/useAudioUiStore';\nimport {\n  buildBeatGridLines,\n  snapStepSeconds,\n  snapTime,\n} from '../../lib/audio/timelineSnap';\nimport { AUDIO_TRACK_HEIGHT } from './AudioTrackControls';\nimport { useTranslation } from '../../i18n';\nimport { FEATURE_HEX, modeAccentVars, useModeAccent } from '../../theme/modeAccent';\nimport { modShortcut } from '../../utils/modKey';\nimport { useDialog } from '../DialogModal';\nimport { TextBody, TextTitle } from '../ui';\n\n\nconst RULER_HEIGHT = 28;\nconst LOOP_MIN_DURATION = 0.1;\nconst LOOP_HANDLE_W = 8;\nconst PLAYHEAD_HIT_HALF = 7;\nconst SNAP_THRESHOLD_PX = 8;\nconst SPLIT_EDGE_MARGIN_PX = 8;\nconst SPLIT_HOVER_DELAY_MS = 1000;\nconst SPLIT_PLAYHEAD_HIT_PX = 40;\nconst SPLIT_PLAYHEAD_KEEP_PX = 72;\nconst SPLIT_LEAVE_MS = 280;\nconst CLIP_INSET_Y = 6;\n/** Softer wheel steps so zoom doesn't jump into laggy densities. */\nconst ZOOM_WHEEL_FACTOR = 1.04;\n/** Cap bars per clip \u2014 fewer Shape draws = smoother scroll/zoom. */\nconst MAX_WAVEFORM_BARS = 96;\n/** Skip drawing waveform for clips fully outside the viewport (plus pad). */\nconst WAVEFORM_VIEW_PAD_PX = 64;\n\nfunction setStageCursor(stage: { container: () => HTMLDivElement } | null, cursor: string) {\n  if (!stage) return;\n  stage.container().style.cursor = cursor;\n}\n\ninterface Props {\n  width: number;\n  height: number;\n  onImportLocal?: () => void;\n  onOpenMyFiles?: () => void;\n}\n\ntype ClipMenuState = { x: number; y: number; clipId: string };\ntype EmptyMenuState = { x: number; y: number };\n\nexport const AudioTimeline: React.FC<Props> = ({\n  width,\n  height,\n  onImportLocal,\n  onOpenMyFiles,\n}) => {\n  const t = useTranslation();\n  const mode = useModeAccent();\n  const dialog = useDialog();\n  const openAiTool = useAudioUiStore((s) => s.openAiTool);\n  const setRightPanel = useAudioUiStore((s) => s.setRightPanel);\n  const aiProcessingClipIds = useAudioUiStore((s) => s.aiProcessingClipIds);\n  const {\n    tracks,\n    assets,\n    playheadTime,\n    zoom,\n    scrollLeft,\n    scrollTop,\n    projectDuration,\n    selectedClipIds,\n    clipboardClips,\n    regions,\n    markers,\n    transcript,\n    selectedTranscriptIds,\n    selectTranscriptWords,\n    bpm,\n    timeSignature,\n    snapEnabled,\n    snapMode,\n    editMode,\n    loopEnabled,\n    loopStart,\n    loopEnd,\n    setLoop,\n    setPlayhead,\n    setScrollLeft,\n    setScrollTop,\n    moveClipToTrackIndex,\n    moveSelectedClips,\n    trimClip,\n    trimSelectedClips,\n    selectClip,\n    selectClips,\n    clearSelection,\n    splitClip,\n    joinAdjacentClip,\n    copySelectedClips,\n    cutSelectedClips,\n    pasteClips,\n    removeSelectedClips,\n    duplicateClip,\n    updateClip,\n    addTrack,\n    toggleTrackLock,\n    removeMarker,\n  } = useAudioStore();\n\n  const containerRef = useRef<HTMLDivElement>(null);\n  const menuRef = useRef<HTMLDivElement>(null);\n  const emptyMenuRef = useRef<HTMLDivElement>(null);\n  const dragOriginRef = useRef<{ clipId: string; startX: number } | null>(null);\n  const pendingSnapLineRef = useRef<number | null>(null);\n  const splitHoverTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const splitHoverLeaveRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const splitHoverClipRef = useRef<string | null>(null);\n  const splitHoverReadyRef = useRef(false);\n  const panRef = useRef<{ x: number; y: number; scrollLeft: number; scrollTop: number } | null>(\n    null,\n  );\n  const [contextMenu, setContextMenu] = useState<ClipMenuState | null>(null);\n  const [emptyMenu, setEmptyMenu] = useState<EmptyMenuState | null>(null);\n  const [snapLineX, setSnapLineX] = useState<number | null>(null);\n  const [aiPulse, setAiPulse] = useState(0.45);\n  const [splitHover, setSplitHover] = useState<{ clipId: string; ready: boolean } | null>(null);\n  const [isPanning, setIsPanning] = useState(false);\n  const [marquee, setMarquee] = useState<{\n    x0: number;\n    y0: number;\n    x1: number;\n    y1: number;\n    additive: boolean;\n  } | null>(null);\n  const marqueeActiveRef = useRef(false);\n  const marqueeRef = useRef<{\n    x0: number;\n    y0: number;\n    x1: number;\n    y1: number;\n    additive: boolean;\n  } | null>(null);\n\n  const totalWidth = Math.max(width, projectDuration * zoom + 200);\n  const totalHeight = Math.max(height, tracks.length * AUDIO_TRACK_HEIGHT + RULER_HEIGHT);\n\n  const assetMap = useMemo(() => new Map(assets.map((a) => [a.id, a])), [assets]);\n  const aiProcessingSet = useMemo(() => new Set(aiProcessingClipIds), [aiProcessingClipIds]);\n\n  useEffect(() => {\n    const el = containerRef.current;\n    if (!el) return;\n    const onWheel = (e: WheelEvent) => {\n      const zoomMod = e.ctrlKey || e.metaKey || e.altKey;\n      if (zoomMod) {\n        e.preventDefault();\n        const rect = el.getBoundingClientRect();\n        const viewX = e.clientX - rect.left;\n        const timeSec = (scrollLeft + viewX) / zoom;\n        const next = Math.max(\n          AUDIO_ZOOM_MIN,\n          Math.min(AUDIO_ZOOM_MAX, zoom * (e.deltaY > 0 ? 1 / ZOOM_WHEEL_FACTOR : ZOOM_WHEEL_FACTOR)),\n        );\n        useAudioStore.getState().setZoom(next, { timeSec, viewX });\n      } else if (e.shiftKey) {\n        e.preventDefault();\n        setScrollLeft(Math.max(0, scrollLeft + e.deltaY));\n      } else if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) {\n        setScrollLeft(Math.max(0, scrollLeft + e.deltaX));\n      } else {\n        setScrollTop(Math.max(0, scrollTop + e.deltaY));\n      }\n    };\n    el.addEventListener('wheel', onWheel, { passive: false });\n    return () => el.removeEventListener('wheel', onWheel);\n  }, [zoom, scrollLeft, scrollTop, setScrollLeft, setScrollTop]);\n\n  // Middle-mouse drag to pan the timeline in all directions.\n  useEffect(() => {\n    const el = containerRef.current;\n    if (!el) return;\n\n    const onDown = (e: MouseEvent) => {\n      if (e.button !== 1) return;\n      e.preventDefault();\n      e.stopPropagation();\n      panRef.current = {\n        x: e.clientX,\n        y: e.clientY,\n        scrollLeft: useAudioStore.getState().scrollLeft,\n        scrollTop: useAudioStore.getState().scrollTop,\n      };\n      setIsPanning(true);\n    };\n    const onMove = (e: MouseEvent) => {\n      const pan = panRef.current;\n      if (!pan) return;\n      e.preventDefault();\n      const dx = e.clientX - pan.x;\n      const dy = e.clientY - pan.y;\n      const state = useAudioStore.getState();\n      const maxX = Math.max(0, state.projectDuration * state.zoom + 200 - width);\n      const contentH = RULER_HEIGHT + state.tracks.length * AUDIO_TRACK_HEIGHT;\n      const maxY = Math.max(0, contentH - height);\n      setScrollLeft(Math.max(0, Math.min(maxX, pan.scrollLeft - dx)));\n      setScrollTop(Math.max(0, Math.min(maxY, pan.scrollTop - dy)));\n    };\n    const onUp = () => {\n      if (!panRef.current) return;\n      panRef.current = null;\n      setIsPanning(false);\n    };\n    const preventAutoScroll = (e: MouseEvent) => {\n      if (e.button === 1) e.preventDefault();\n    };\n\n    el.addEventListener('mousedown', onDown, true);\n    window.addEventListener('mousemove', onMove);\n    window.addEventListener('mouseup', onUp);\n    el.addEventListener('auxclick', preventAutoScroll);\n    return () => {\n      el.removeEventListener('mousedown', onDown, true);\n      window.removeEventListener('mousemove', onMove);\n      window.removeEventListener('mouseup', onUp);\n      el.removeEventListener('auxclick', preventAutoScroll);\n    };\n  }, [setScrollLeft, setScrollTop, width, height]);\n\n  useEffect(() => {\n    if (!contextMenu && !emptyMenu) return;\n    const close = () => {\n      setContextMenu(null);\n      setEmptyMenu(null);\n    };\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') close();\n    };\n    window.addEventListener('mousedown', close);\n    window.addEventListener('keydown', onKey);\n    return () => {\n      window.removeEventListener('mousedown', close);\n      window.removeEventListener('keydown', onKey);\n    };\n  }, [contextMenu, emptyMenu]);\n\n  useEffect(() => {\n    if (!contextMenu || !menuRef.current) return;\n    const el = menuRef.current;\n    const rect = el.getBoundingClientRect();\n    const margin = 8;\n    let x = contextMenu.x;\n    let y = contextMenu.y;\n    if (x + rect.width > window.innerWidth - margin) x = window.innerWidth - rect.width - margin;\n    if (y + rect.height > window.innerHeight - margin) y = window.innerHeight - rect.height - margin;\n    el.style.left = `${Math.max(margin, x)}px`;\n    el.style.top = `${Math.max(margin, y)}px`;\n  }, [contextMenu]);\n\n  useEffect(() => {\n    if (!emptyMenu || !emptyMenuRef.current) return;\n    const el = emptyMenuRef.current;\n    const rect = el.getBoundingClientRect();\n    const margin = 8;\n    let x = emptyMenu.x;\n    let y = emptyMenu.y;\n    if (x + rect.width > window.innerWidth - margin) x = window.innerWidth - rect.width - margin;\n    if (y + rect.height > window.innerHeight - margin) y = window.innerHeight - rect.height - margin;\n    el.style.left = `${Math.max(margin, x)}px`;\n    el.style.top = `${Math.max(margin, y)}px`;\n  }, [emptyMenu]);\n\n  useEffect(() => {\n    if (!aiProcessingClipIds.length) return;\n    let raf = 0;\n    const start = performance.now();\n    const tick = (now: number) => {\n      const phase = ((now - start) % 900) / 900;\n      setAiPulse(0.3 + 0.4 * (0.5 + 0.5 * Math.sin(phase * Math.PI * 2)));\n      raf = requestAnimationFrame(tick);\n    };\n    raf = requestAnimationFrame(tick);\n    return () => cancelAnimationFrame(raf);\n  }, [aiProcessingClipIds.length]);\n\n  const syncSnapLineFromDrag = useCallback(() => {\n    const next = pendingSnapLineRef.current;\n    setSnapLineX((prev) => (prev === next ? prev : next));\n  }, []);\n\n  const snapStep = useMemo(\n    () => snapStepSeconds({ snapEnabled, snapMode, bpm, zoom }),\n    [snapEnabled, snapMode, bpm, zoom],\n  );\n\n  /** Zoom-aware grid snap for scrubbing, trim, and playhead (finer when zoomed in). */\n  const snap = useCallback(\n    (tSec: number) => snapTime(tSec, snapStep),\n    [snapStep],\n  );\n\n  /** Edge + playhead snap during clip drag (same idea as video timeline). */\n  const computeSnapPosition = (\n    x: number,\n    clipWidthPx: number,\n    draggingClipId: string,\n  ): { x: number; snapLineX: number | null } => {\n    if (!snapEnabled) {\n      return { x, snapLineX: null };\n    }\n\n    let snappedX = x;\n    let foundSnap = false;\n    let snapTargetX = 0;\n\n    const snapCandidates: number[] = [playheadTime * zoom];\n    for (const track of tracks) {\n      for (const c of track.clips) {\n        if (c.id === draggingClipId) continue;\n        if (selectedClipIds.includes(draggingClipId) && selectedClipIds.includes(c.id)) continue;\n        snapCandidates.push(c.startTime * zoom);\n        snapCandidates.push((c.startTime + c.duration) * zoom);\n      }\n    }\n    for (const m of markers) {\n      snapCandidates.push(m.time * zoom);\n    }\n\n    for (const snapPoint of snapCandidates) {\n      if (Math.abs(x - snapPoint) < SNAP_THRESHOLD_PX) {\n        snappedX = snapPoint;\n        foundSnap = true;\n        snapTargetX = snapPoint;\n        break;\n      }\n    }\n\n    if (!foundSnap) {\n      for (const snapPoint of snapCandidates) {\n        if (Math.abs(x + clipWidthPx - snapPoint) < SNAP_THRESHOLD_PX) {\n          snappedX = snapPoint - clipWidthPx;\n          foundSnap = true;\n          snapTargetX = snapPoint;\n          break;\n        }\n      }\n    }\n\n    if (!foundSnap && snapStep != null) {\n      const tSec = Math.max(0, x / zoom);\n      const snappedT = snapTime(tSec, snapStep);\n      snappedX = snappedT * zoom;\n      foundSnap = true;\n      snapTargetX = snappedX;\n    }\n\n    return { x: Math.max(0, snappedX), snapLineX: foundSnap ? snapTargetX : null };\n  };\n\n  const openEmptyMenu = (clientX: number, clientY: number) => {\n    setContextMenu(null);\n    setEmptyMenu({ x: clientX, y: clientY });\n  };\n\n  const confirmDeleteSelection = async () => {\n    const n = selectedClipIds.length;\n    if (!n) return;\n    const ok = await dialog.confirm(\n      n === 1 ? t.audio.editor.deleteClipConfirm : t.audio.editor.deleteClipsConfirm(n),\n      {\n        title: t.audio.editor.deleteConfirmTitle,\n        variant: 'danger',\n        confirmText: t.audio.editor.deleteConfirmBtn,\n        cancelText: t.common.cancel,\n      },\n    );\n    if (ok) removeSelectedClips();\n  };\n\n  const clipAbsY = (trackIndex: number) =>\n    RULER_HEIGHT + trackIndex * AUDIO_TRACK_HEIGHT - scrollTop + CLIP_INSET_Y;\n\n  const snapTrackIndexFromAbsY = (absY: number, allowNewTrack: boolean) => {\n    const raw = Math.round((absY + scrollTop - RULER_HEIGHT - CLIP_INSET_Y) / AUDIO_TRACK_HEIGHT);\n    if (allowNewTrack) return Math.max(0, Math.min(tracks.length, raw));\n    return Math.max(0, Math.min(Math.max(0, tracks.length - 1), raw));\n  };\n\n  const clipsIntersectingMarquee = useCallback(\n    (box: { x0: number; y0: number; x1: number; y1: number }) => {\n      const left = Math.min(box.x0, box.x1);\n      const right = Math.max(box.x0, box.x1);\n      const top = Math.min(box.y0, box.y1);\n      const bottom = Math.max(box.y0, box.y1);\n      const ids: string[] = [];\n      const clipH = AUDIO_TRACK_HEIGHT - CLIP_INSET_Y * 2;\n      tracks.forEach((track, ti) => {\n        if (track.locked) return;\n        const trackTop = RULER_HEIGHT + ti * AUDIO_TRACK_HEIGHT;\n        for (const clip of track.clips) {\n          const clipLeft = clip.startTime * zoom;\n          const clipRight = clipLeft + clip.duration * zoom;\n          const clipTop = trackTop + CLIP_INSET_Y;\n          const clipBottom = clipTop + clipH;\n          if (clipRight < left || clipLeft > right) continue;\n          if (clipBottom < top || clipTop > bottom) continue;\n          ids.push(clip.id);\n        }\n      });\n      return ids;\n    },\n    [tracks, zoom],\n  );\n\n  const finishMarquee = useCallback(\n    (box: { x0: number; y0: number; x1: number; y1: number; additive: boolean } | null) => {\n      marqueeActiveRef.current = false;\n      marqueeRef.current = null;\n      setMarquee(null);\n      if (!box) return;\n      const w = Math.abs(box.x1 - box.x0);\n      const h = Math.abs(box.y1 - box.y0);\n      if (w < 3 && h < 3) {\n        if (!box.additive) clearSelection();\n        return;\n      }\n      const ids = clipsIntersectingMarquee(box);\n      if (ids.length === 0) {\n        if (!box.additive) clearSelection();\n        return;\n      }\n      selectClips(ids, box.additive);\n    },\n    [clearSelection, clipsIntersectingMarquee, selectClips],\n  );\n\n  useEffect(() => {\n    if (!marquee) return;\n    const onMove = (ev: MouseEvent) => {\n      if (!marqueeActiveRef.current || !containerRef.current) return;\n      const rect = containerRef.current.getBoundingClientRect();\n      const x = ev.clientX - rect.left + scrollLeft;\n      const y = ev.clientY - rect.top + scrollTop;\n      setMarquee((prev) => {\n        if (!prev) return null;\n        const next = { ...prev, x1: x, y1: y };\n        marqueeRef.current = next;\n        return next;\n      });\n    };\n    const onUp = () => {\n      finishMarquee(marqueeRef.current);\n    };\n    window.addEventListener('mousemove', onMove);\n    window.addEventListener('mouseup', onUp);\n    return () => {\n      window.removeEventListener('mousemove', onMove);\n      window.removeEventListener('mouseup', onUp);\n    };\n  }, [marquee, scrollLeft, scrollTop, finishMarquee]);\n\n  const clearSplitHover = useCallback(() => {\n    if (splitHoverTimerRef.current) {\n      clearTimeout(splitHoverTimerRef.current);\n      splitHoverTimerRef.current = null;\n    }\n    if (splitHoverLeaveRef.current) {\n      clearTimeout(splitHoverLeaveRef.current);\n      splitHoverLeaveRef.current = null;\n    }\n    splitHoverClipRef.current = null;\n    splitHoverReadyRef.current = false;\n    setSplitHover(null);\n  }, []);\n\n  useEffect(() => () => clearSplitHover(), [clearSplitHover]);\n\n  const scheduleSplitHoverClear = useCallback(() => {\n    if (splitHoverLeaveRef.current) clearTimeout(splitHoverLeaveRef.current);\n    splitHoverLeaveRef.current = setTimeout(() => {\n      splitHoverLeaveRef.current = null;\n      clearSplitHover();\n    }, SPLIT_LEAVE_MS);\n  }, [clearSplitHover]);\n\n  const cancelSplitHoverClear = useCallback(() => {\n    if (splitHoverLeaveRef.current) {\n      clearTimeout(splitHoverLeaveRef.current);\n      splitHoverLeaveRef.current = null;\n    }\n  }, []);\n\n  const armSplitHoverOnClip = useCallback(\n    (\n      clip: { id: string; startTime: number; duration: number },\n      locked: boolean,\n      pointerX?: number,\n    ) => {\n      if (locked) {\n        clearSplitHover();\n        return;\n      }\n      const margin = Math.max(0.05, SPLIT_EDGE_MARGIN_PX / zoom);\n      const playheadOnClip =\n        playheadTime > clip.startTime + margin &&\n        playheadTime < clip.startTime + clip.duration - margin;\n      if (!playheadOnClip) {\n        clearSplitHover();\n        return;\n      }\n      const sameClip = splitHoverClipRef.current === clip.id;\n      if (sameClip && splitHoverReadyRef.current) {\n        cancelSplitHoverClear();\n        return;\n      }\n      if (pointerX != null) {\n        const playheadX = playheadTime * zoom;\n        const hitPx = sameClip ? SPLIT_PLAYHEAD_KEEP_PX : SPLIT_PLAYHEAD_HIT_PX;\n        if (Math.abs(pointerX - playheadX) > hitPx) {\n          clearSplitHover();\n          return;\n        }\n      }\n      cancelSplitHoverClear();\n      if (!sameClip) {\n        if (splitHoverTimerRef.current) {\n          clearTimeout(splitHoverTimerRef.current);\n          splitHoverTimerRef.current = null;\n        }\n        splitHoverClipRef.current = clip.id;\n        splitHoverReadyRef.current = false;\n        setSplitHover({ clipId: clip.id, ready: false });\n        splitHoverTimerRef.current = setTimeout(() => {\n          splitHoverTimerRef.current = null;\n          splitHoverReadyRef.current = true;\n          if (splitHoverLeaveRef.current) {\n            clearTimeout(splitHoverLeaveRef.current);\n            splitHoverLeaveRef.current = null;\n          }\n          setSplitHover((prev) =>\n            prev && prev.clipId === clip.id ? { ...prev, ready: true } : prev,\n          );\n        }, SPLIT_HOVER_DELAY_MS);\n      }\n    },\n    [cancelSplitHoverClear, clearSplitHover, playheadTime, zoom],\n  );\n\n  useEffect(() => {\n    if (!splitHover) return;\n    const margin = Math.max(0.05, SPLIT_EDGE_MARGIN_PX / zoom);\n    let stillValid = false;\n    for (const tr of tracks) {\n      const c = tr.clips.find((x) => x.id === splitHover.clipId);\n      if (!c) continue;\n      stillValid =\n        playheadTime > c.startTime + margin &&\n        playheadTime < c.startTime + c.duration - margin;\n      break;\n    }\n    if (!stillValid) clearSplitHover();\n  }, [clearSplitHover, playheadTime, splitHover, tracks, zoom]);\n\n  const rulerTicks: number[] = [];\n  const tickEvery = zoom > 100 ? 1 : zoom > 50 ? 5 : 10;\n\n  const beatGridLines = useMemo(\n    () =>\n      buildBeatGridLines({\n        bpm,\n        zoom,\n        scrollLeft,\n        width,\n        beatsPerBar: timeSignature[0] || 4,\n        projectDuration,\n      }),\n    [bpm, zoom, scrollLeft, width, timeSignature, projectDuration],\n  );\n  for (let tSec = 0; tSec <= projectDuration; tSec += tickEvery) rulerTicks.push(tSec);\n\n  const menuClip = contextMenu\n    ? tracks.flatMap((tr) => tr.clips.map((c) => ({ clip: c, track: tr }))).find((x) => x.clip.id === contextMenu.clipId)\n    : null;\n\n  const canJoinMenuClip = useMemo(() => {\n    if (!menuClip) return false;\n    const EPS = 0.05;\n    const clip = menuClip.clip;\n    return menuClip.track.clips.some((other) => {\n      if (other.id === clip.id) return false;\n      if (other.assetId !== clip.assetId) return false;\n      if (Math.abs(other.speed - clip.speed) > 1e-6) return false;\n      const abutsForward =\n        Math.abs(clip.startTime + clip.duration - other.startTime) < EPS &&\n        Math.abs(clip.trimOut - other.trimIn) < EPS;\n      const abutsBack =\n        Math.abs(other.startTime + other.duration - clip.startTime) < EPS &&\n        Math.abs(other.trimOut - clip.trimIn) < EPS;\n      return abutsForward || abutsBack;\n    });\n  }, [menuClip]);\n\n  const menuBtn =\n    'flex w-full cursor-pointer items-center gap-2 px-3 py-2 text-left font-sans text-xs font-medium text-white transition-colors hover:bg-[var(--we-accent-muted)]';\n  const menuKbd = 'ml-auto select-none font-sans text-xs font-medium text-white/50';\n\n  const runMenu = (fn: () => void) => {\n    fn();\n    setContextMenu(null);\n  };\n\n  return (\n    <div\n      ref={containerRef}\n      className={`we-audio-timeline relative min-w-0 flex-1 bg-[#0A0A0F] ${isPanning ? 'cursor-grabbing' : ''}`}\n    >      {editMode === 'ripple' && (\n        <div className=\"absolute top-1 right-2 z-10 rounded bg-[#FFD54F]/15 px-1.5 py-0.5 text-xs font-bold text-[#FFD54F]\">\n          {t.audio.timeline.ripple}\n        </div>\n      )}\n      <Stage\n        width={width}\n        height={height}\n        x={-scrollLeft}\n        y={0}\n        onContextMenu={(e) => {\n          // Empty stage / track background \u2014 not clips (clips cancelBubble).\n          if (e.target === e.target.getStage()) {\n            e.evt.preventDefault();\n            openEmptyMenu(e.evt.clientX, e.evt.clientY);\n          }\n        }}\n        onMouseDown={(e) => {\n          const stage = e.target.getStage();\n          if (!stage) return;\n          const pos = stage.getPointerPosition();\n          if (!pos || pos.y >= RULER_HEIGHT) return;\n          const seek = () => {\n            const p = stage.getPointerPosition();\n            if (!p) return;\n            setPlayhead(snap((p.x + scrollLeft) / zoom));\n          };\n          seek();\n          const onMove = () => seek();\n          const onUp = () => {\n            window.removeEventListener('mousemove', onMove);\n            window.removeEventListener('mouseup', onUp);\n          };\n          window.addEventListener('mousemove', onMove);\n          window.addEventListener('mouseup', onUp);\n        }}\n      >\n        {/* Tracks / clips \u2014 below overlay so scroll + drag never cover the ruler/playhead */}\n        <Layer>\n          {beatGridLines.map(({ t, kind }) => (\n            <Line\n              key={`beat-${kind}-${t.toFixed(5)}`}\n              points={[t * zoom, RULER_HEIGHT, t * zoom, totalHeight]}\n              stroke={\n                kind === 'bar'\n                  ? 'rgba(159,18,57,0.45)'\n                  : kind === 'beat'\n                    ? 'rgba(255,255,255,0.1)'\n                    : 'rgba(255,255,255,0.04)'\n              }\n              strokeWidth={kind === 'bar' ? 1.25 : 1}\n              listening={false}\n            />\n          ))}\n          {regions.map((r) => (\n            <Rect\n              key={r.id}\n              x={r.startTime * zoom}\n              y={RULER_HEIGHT}\n              width={Math.max(2, (r.endTime - r.startTime) * zoom)}\n              height={totalHeight - RULER_HEIGHT}\n              fill=\"#6C63FF18\"\n              listening={false}\n            />\n          ))}\n\n          {markers.map((m) => (\n            <Line\n              key={m.id}\n              points={[m.time * zoom, RULER_HEIGHT, m.time * zoom, totalHeight]}\n              stroke={m.color || '#FFD54F'}\n              strokeWidth={m.source === 'song-structure' ? 2 : 1}\n              dash={[4, 4]}\n              hitStrokeWidth={12}\n              onClick={(e) => {\n                e.cancelBubble = true;\n                removeMarker(m.id);\n              }}\n              onTap={(e) => {\n                e.cancelBubble = true;\n                removeMarker(m.id);\n              }}\n            />\n          ))}\n\n          {tracks.map((track, ti) => {\n            const y = RULER_HEIGHT + ti * AUDIO_TRACK_HEIGHT - scrollTop;\n            const volLane = track.automation.find((a) => a.property === 'volume');\n\n            return (\n              <Group key={track.id} y={y}>\n                <Rect\n                  x={0}\n                  y={0}\n                  width={totalWidth}\n                  height={AUDIO_TRACK_HEIGHT}\n                  fill={ti % 2 === 0 ? '#0C0C12' : '#0A0A0F'}\n                  onMouseDown={(e) => {\n                    if (e.evt.button !== 0) return;\n                    e.cancelBubble = true;\n                    const stage = e.target.getStage();\n                    const pointer = stage?.getPointerPosition();\n                    if (!pointer) return;\n                    const x = pointer.x + scrollLeft;\n                    const yAbs = pointer.y + scrollTop;\n                    marqueeActiveRef.current = true;\n                    const box = {\n                      x0: x,\n                      y0: yAbs,\n                      x1: x,\n                      y1: yAbs,\n                      additive: e.evt.shiftKey || e.evt.ctrlKey || e.evt.metaKey,\n                    };\n                    marqueeRef.current = box;\n                    setMarquee(box);\n                  }}\n                  onContextMenu={(e) => {\n                    e.evt.preventDefault();\n                    e.cancelBubble = true;\n                    openEmptyMenu(e.evt.clientX, e.evt.clientY);\n                  }}\n                />\n                <Line\n                  points={[0, AUDIO_TRACK_HEIGHT, totalWidth, AUDIO_TRACK_HEIGHT]}\n                  stroke=\"#2A2A38\"\n                  strokeWidth={1}\n                  listening={false}\n                />\n\n                {volLane && volLane.points.length > 0 && (\n                  <Line\n                    points={volLane.points\n                      .slice()\n                      .sort((a, b) => a.time - b.time)\n                      .flatMap((p) => {\n                        const norm = Math.max(0, Math.min(1, (p.value + 48) / 60));\n                        return [\n                          p.time * zoom,\n                          AUDIO_TRACK_HEIGHT - 4 - norm * (AUDIO_TRACK_HEIGHT - 16),\n                        ];\n                      })}\n                    stroke=\"#FFD54F88\"\n                    strokeWidth={1.5}\n                    listening={false}\n                  />\n                )}\n              </Group>\n            );\n          })}\n\n          {/* Clips in a flat layer so drag never orphans nodes between track groups */}\n          {tracks.flatMap((track, ti) => {\n            const clipH = AUDIO_TRACK_HEIGHT - CLIP_INSET_Y * 2;\n            return track.clips.map((clip) => {\n              const asset = assetMap.get(clip.assetId);\n              const x = clip.startTime * zoom;\n              const w = Math.max(4, clip.duration * zoom);\n              const selected = selectedClipIds.includes(clip.id);\n              const accent = selected ? '#FF2D95' : '#C8C8D0';\n              const fillBg = selected ? '#140810' : '#16161C';\n              const peaks = asset?.peaks;\n              const peaksSr = asset?.peaksSampleRate || 200;\n              const xfIn = clip.crossfadeIn || clip.fadeIn || 0;\n              const xfOut = clip.crossfadeOut || clip.fadeOut || 0;\n              const fadeInW = Math.min(w / 2, xfIn * zoom);\n              const fadeOutW = Math.min(w / 2, xfOut * zoom);\n              // Bars span full clip width; cap at MAX_WAVEFORM_BARS (single Shape draw).\n              const minBarSlotPx = zoom > 100 ? 5 : zoom > 60 ? 6 : 7;\n              const sampleCount = Math.max(\n                6,\n                Math.min(MAX_WAVEFORM_BARS, Math.floor(w / minBarSlotPx) || 1),\n              );\n              const barSlot = w / sampleCount;\n              const barW = Math.max(1, barSlot * 0.72);\n              const barPad = (barSlot - barW) / 2;\n              const inactive = Boolean(\n                clip.muted || (clip.takeGroupId && clip.compActive === false),\n              );\n              const label = clip.name || asset?.name || t.audio.timeline.clipFallback;\n              const pillText = label;\n              const pillW = Math.min(w - 16, Math.max(48, pillText.length * 6.4 + 18));\n              const isAiBusy = aiProcessingSet.has(clip.id);\n              const absY = clipAbsY(ti);\n              const waveInView =\n                x + w > scrollLeft - WAVEFORM_VIEW_PAD_PX &&\n                x < scrollLeft + width + WAVEFORM_VIEW_PAD_PX &&\n                absY + clipH > -WAVEFORM_VIEW_PAD_PX &&\n                absY < height + WAVEFORM_VIEW_PAD_PX;\n\n              return (\n                <Group\n                  key={clip.id}\n                  x={x}\n                  y={absY}\n                  draggable={!track.locked && !isAiBusy}\n                  opacity={inactive ? 0.35 : 1}\n                  dragBoundFunc={(pos) => {\n                    const { x: snappedX, snapLineX: nextSnapLine } = computeSnapPosition(\n                      pos.x,\n                      w,\n                      clip.id,\n                    );\n                    pendingSnapLineRef.current = nextSnapLine;\n                    // Alone on last track: don't preview a ghost row below (create+prune).\n                    const aloneOnLast = ti === tracks.length - 1 && track.clips.length === 1;\n                    const trackIdx = snapTrackIndexFromAbsY(pos.y, !aloneOnLast);\n                    return { x: snappedX, y: clipAbsY(trackIdx) };\n                  }}\n                  onDragStart={(e) => {\n                    clearSplitHover();\n                    dragOriginRef.current = { clipId: clip.id, startX: e.target.x() };\n                    e.target.moveToTop();\n                  }}\n                  onDragMove={() => {\n                    syncSnapLineFromDrag();\n                  }}\n                  onDragEnd={(e) => {\n                    const origin = dragOriginRef.current;\n                    dragOriginRef.current = null;\n                    pendingSnapLineRef.current = null;\n                    setSnapLineX(null);\n\n                    const newStart = Math.max(0, e.target.x() / zoom);\n                    const delta = newStart - clip.startTime;\n                    const aloneOnLast = ti === tracks.length - 1 && track.clips.length === 1;\n                    const trackIndex = snapTrackIndexFromAbsY(e.target.y(), !aloneOnLast);\n                    const sameTrack =\n                      trackIndex < tracks.length && tracks[trackIndex]?.id === clip.trackId;\n\n                    if (\n                      selected &&\n                      selectedClipIds.length > 1 &&\n                      selectedClipIds.includes(clip.id) &&\n                      origin &&\n                      sameTrack\n                    ) {\n                      moveSelectedClips(delta);\n                      e.target.position({ x: (clip.startTime + delta) * zoom, y: absY });\n                      return;\n                    }\n\n                    moveClipToTrackIndex(clip.id, newStart, trackIndex);\n                    // Snap Y to the post-move lane (store may have pruned empty tracks).\n                    const afterTracks = useAudioStore.getState().tracks;\n                    const finalTi = afterTracks.findIndex((tr) =>\n                      tr.clips.some((c) => c.id === clip.id),\n                    );\n                    const laneY = clipAbsY(finalTi >= 0 ? finalTi : Math.min(trackIndex, afterTracks.length - 1));\n                    e.target.position({ x: newStart * zoom, y: laneY });\n                  }}\n                  onMouseEnter={(e) => {\n                    const stage = e.target.getStage();\n                    const pointer = stage?.getPointerPosition();\n                    armSplitHoverOnClip(clip, track.locked, pointer?.x);\n                  }}\n                  onMouseMove={(e) => {\n                    const stage = e.target.getStage();\n                    const pointer = stage?.getPointerPosition();\n                    armSplitHoverOnClip(clip, track.locked, pointer?.x);\n                  }}\n                  onMouseLeave={() => {\n                    if (!splitHoverReadyRef.current) clearSplitHover();\n                    else scheduleSplitHoverClear();\n                  }}\n                  onClick={(e) => {\n                    e.cancelBubble = true;\n                    selectClip(clip.id, e.evt.shiftKey || e.evt.metaKey || e.evt.ctrlKey);\n                    setRightPanel('inspector');\n                  }}\n                  onContextMenu={(e) => {\n                    e.evt.preventDefault();\n                    e.cancelBubble = true;\n                    setEmptyMenu(null);\n                    clearSplitHover();\n                    selectClip(clip.id, e.evt.shiftKey || e.evt.metaKey || e.evt.ctrlKey);\n                    setRightPanel('inspector');\n                    setContextMenu({\n                      x: e.evt.clientX,\n                      y: e.evt.clientY,\n                      clipId: clip.id,\n                    });\n                  }}\n                >\n                  <Rect\n                    width={w}\n                    height={clipH}\n                    fill={fillBg}\n                    cornerRadius={10}\n                    stroke={accent}\n                    strokeWidth={selected ? 2 : 1.25}\n                    shadowColor={selected ? accent : undefined}\n                    shadowBlur={selected ? 14 : 0}\n                    shadowOpacity={selected ? 0.45 : 0}\n                  />\n                  {peaks &&\n                    peaks.length >= 2 &&\n                    !inactive &&\n                    waveInView &&\n                    w >= 8 && (\n                      <Shape\n                        listening={false}\n                        perfectDrawEnabled={false}\n                        hitStrokeWidth={0}\n                        sceneFunc={(ctx, shape) => {\n                          const pairCount = Math.floor(peaks.length / 2);\n                          if (pairCount < 1) return;\n                          const mid = clipH / 2;\n                          const speed = clip.speed || 1;\n                          ctx.fillStyle = accent;\n                          ctx.globalAlpha = selected ? 0.95 : 0.7;\n                          for (let i = 0; i < sampleCount; i++) {\n                            const tFrac = (i + 0.5) / sampleCount;\n                            const t0 = clip.trimIn + tFrac * clip.duration * speed;\n                            const idx = Math.min(\n                              pairCount - 1,\n                              Math.max(0, Math.floor(t0 * peaksSr)),\n                            );\n                            const min = peaks[idx * 2] ?? 0;\n                            const max = peaks[idx * 2 + 1] ?? 0;\n                            const amp = Math.max(2, Math.abs(max - min) * mid * 0.82);\n                            const barH = Math.min(mid * 1.7, Math.max(3, amp));\n                            const px = i * barSlot + barPad;\n                            ctx.fillRect(px, mid - barH / 2, barW, barH);\n                          }\n                          ctx.globalAlpha = 1;\n                          ctx.fillStrokeShape(shape);\n                        }}\n                      />\n                    )}\n                  {fadeInW > 2 && (\n                    <Line\n                      points={[0, clipH, fadeInW, 0, fadeInW, clipH]}\n                      closed\n                      fill={selected ? '#FF2D9533' : '#FFFFFF18'}\n                      listening={false}\n                    />\n                  )}\n                  {fadeOutW > 2 && (\n                    <Line\n                      points={[w - fadeOutW, 0, w, clipH, w - fadeOutW, clipH]}\n                      closed\n                      fill={selected ? '#FF2D9533' : '#FFFFFF18'}\n                      listening={false}\n                    />\n                  )}\n                  {w > 48 && (\n                    <Group x={8} y={6} listening={false}>\n                      <Rect\n                        width={pillW}\n                        height={18}\n                        fill={selected ? accent : 'rgba(200,200,208,0.22)'}\n                        cornerRadius={9}\n                        stroke={selected ? undefined : accent}\n                        strokeWidth={selected ? 0 : 1}\n                      />\n                      <Text\n                        text={pillText}\n                        x={9}\n                        y={3}\n                        fontSize={10}\n                        fill={selected ? '#FFFFFF' : '#E8E8EC'}\n                        width={pillW - 16}\n                        ellipsis\n                      />\n                    </Group>\n                  )}\n                  {isAiBusy && (\n                    <Group listening={false}>\n                      <Rect\n                        width={w}\n                        height={clipH}\n                        fill=\"#FF2D95\"\n                        opacity={aiPulse * 0.35}\n                        cornerRadius={10}\n                      />\n                      <Rect\n                        x={Math.max(4, w / 2 - 18)}\n                        y={Math.max(4, clipH / 2 - 10)}\n                        width={36}\n                        height={20}\n                        fill=\"rgba(10,10,15,0.75)\"\n                        cornerRadius={10}\n                        stroke=\"#FF2D95\"\n                        strokeWidth={1}\n                        opacity={0.55 + aiPulse * 0.45}\n                      />\n                      <Text\n                        text=\"AI\"\n                        x={Math.max(4, w / 2 - 18)}\n                        y={Math.max(7, clipH / 2 - 6)}\n                        width={36}\n                        align=\"center\"\n                        fontSize={10}\n                        fontStyle=\"bold\"\n                        fill=\"#FFFFFF\"\n                        opacity={0.7 + aiPulse * 0.3}\n                      />\n                    </Group>\n                  )}\n                  <Rect\n                    x={Math.max(0, fadeInW - 3)}\n                    y={0}\n                    width={6}\n                    height={clipH}\n                    fill={selected ? '#FF2D9588' : '#C8C8D088'}\n                    draggable={!isAiBusy}\n                    onDragMove={(e) => {\n                      e.target.y(0);\n                      e.target.x(Math.max(0, Math.min(w / 2, e.target.x())));\n                    }}\n                    onDragEnd={(e) => {\n                      const sec = Math.max(0, e.target.x() / zoom);\n                      useAudioStore.getState().updateClip(clip.id, {\n                        crossfadeIn: sec,\n                        fadeIn: sec,\n                        crossfadeCurve: clip.crossfadeCurve || 'equal-power',\n                      });\n                      e.target.position({ x: Math.max(0, fadeInW - 3), y: 0 });\n                    }}\n                  />\n                  <Rect\n                    x={Math.max(0, w - fadeOutW - 3)}\n                    y={0}\n                    width={6}\n                    height={clipH}\n                    fill={selected ? '#FF2D9588' : '#C8C8D088'}\n                    draggable={!isAiBusy}\n                    onDragMove={(e) => {\n                      e.target.y(0);\n                      e.target.x(Math.max(w / 2, Math.min(w - 6, e.target.x())));\n                    }}\n                    onDragEnd={(e) => {\n                      const sec = Math.max(0, (w - e.target.x()) / zoom);\n                      useAudioStore.getState().updateClip(clip.id, {\n                        crossfadeOut: sec,\n                        fadeOut: sec,\n                        crossfadeCurve: clip.crossfadeCurve || 'equal-power',\n                      });\n                      e.target.position({ x: Math.max(0, w - fadeOutW - 3), y: 0 });\n                    }}\n                  />\n                  <Rect\n                    x={0}\n                    y={0}\n                    width={6}\n                    height={clipH}\n                    fill=\"#00000055\"\n                    draggable={!isAiBusy}\n                    onDragMove={(e) => {\n                      e.target.y(0);\n                      const dx = e.target.x();\n                      e.target.x(Math.max(0, Math.min(w - 12, dx)));\n                    }}\n                    onDragEnd={(e) => {\n                      const dx = e.target.x();\n                      const deltaT = dx / zoom;\n                      const newDur = clip.duration - deltaT;\n                      if (newDur > 0.05) {\n                        if (selected && selectedClipIds.length > 1) {\n                          trimSelectedClips(deltaT * clip.speed, -deltaT);\n                        } else {\n                          trimClip(\n                            clip.id,\n                            clip.trimIn + deltaT * clip.speed,\n                            clip.trimOut,\n                            newDur,\n                          );\n                          moveClipToTrackIndex(clip.id, clip.startTime + deltaT, ti);\n                        }\n                      }\n                      e.target.position({ x: 0, y: 0 });\n                    }}\n                  />\n                  <Rect\n                    x={w - 6}\n                    y={0}\n                    width={6}\n                    height={clipH}\n                    fill=\"#00000055\"\n                    draggable={!isAiBusy}\n                    onDragMove={(e) => {\n                      e.target.y(0);\n                    }}\n                    onDragEnd={(e) => {\n                      const newW = e.target.x() + 6;\n                      const newDur = Math.max(0.05, newW / zoom);\n                      const deltaDur = newDur - clip.duration;\n                      if (selected && selectedClipIds.length > 1) {\n                        trimSelectedClips(0, deltaDur);\n                      } else {\n                        trimClip(\n                          clip.id,\n                          clip.trimIn,\n                          clip.trimIn + newDur * clip.speed,\n                          newDur,\n                        );\n                      }\n                      e.target.position({ x: w - 6, y: 0 });\n                    }}\n                  />\n                </Group>\n              );\n            });\n          })}\n\n          {marquee && (\n            <Rect\n              x={Math.min(marquee.x0, marquee.x1)}\n              y={Math.min(marquee.y0, marquee.y1) - scrollTop}\n              width={Math.abs(marquee.x1 - marquee.x0)}\n              height={Math.abs(marquee.y1 - marquee.y0)}\n              fill=\"rgba(159, 18, 57, 0.18)\"\n              stroke=\"#FF2D95\"\n              strokeWidth={1}\n              dash={[4, 3]}\n              listening={false}\n            />\n          )}\n\n          {/* Loop range \u2014 ruler drag to move; edge handles to resize */}\n          {loopEnabled &&\n            (() => {\n              const accent = FEATURE_HEX.audio;\n              const x = loopStart * zoom;\n              const w = Math.max(2, (loopEnd - loopStart) * zoom);\n              const bindWindowDrag = (\n                stage: { container: () => HTMLDivElement } | null,\n                onMove: () => void,\n              ) => {\n                const up = () => {\n                  window.removeEventListener('mousemove', onMove);\n                  window.removeEventListener('mouseup', up);\n                  setStageCursor(stage, 'default');\n                };\n                window.addEventListener('mousemove', onMove);\n                window.addEventListener('mouseup', up);\n              };\n              return (\n                <Group>\n                  <Rect\n                    x={x}\n                    y={RULER_HEIGHT}\n                    width={w}\n                    height={Math.max(0, totalHeight - RULER_HEIGHT)}\n                    fill={`${accent}18`}\n                    listening={false}\n                  />\n                  <Rect\n                    x={x}\n                    y={0}\n                    width={w}\n                    height={RULER_HEIGHT}\n                    fill={`${accent}40`}\n                    onMouseEnter={(e) => setStageCursor(e.target.getStage(), 'grab')}\n                    onMouseLeave={(e) => setStageCursor(e.target.getStage(), 'default')}\n                    onMouseDown={(e) => {\n                      e.cancelBubble = true;\n                      const stage = e.target.getStage();\n                      const startPtr = stage?.getPointerPosition();\n                      if (!startPtr) return;\n                      const originStart = loopStart;\n                      const originEnd = loopEnd;\n                      const originTime = (startPtr.x + scrollLeft) / zoom;\n                      setStageCursor(stage, 'grabbing');\n                      const onMove = () => {\n                        const p = stage?.getPointerPosition();\n                        if (!p) return;\n                        const delta = (p.x + scrollLeft) / zoom - originTime;\n                        const dur = originEnd - originStart;\n                        let ns = Math.max(0, snap(originStart + delta));\n                        let ne = ns + dur;\n                        if (ne > projectDuration) {\n                          ne = projectDuration;\n                          ns = Math.max(0, ne - dur);\n                        }\n                        setLoop(true, ns, Math.max(ns + LOOP_MIN_DURATION, ne));\n                      };\n                      bindWindowDrag(stage, onMove);\n                    }}\n                  />\n                  <Line\n                    points={[x, 0, x, totalHeight]}\n                    stroke={accent}\n                    strokeWidth={1.5}\n                    listening={false}\n                  />\n                  <Line\n                    points={[x + w, 0, x + w, totalHeight]}\n                    stroke={accent}\n                    strokeWidth={1.5}\n                    listening={false}\n                  />\n                  <Rect\n                    x={x - LOOP_HANDLE_W / 2}\n                    y={0}\n                    width={LOOP_HANDLE_W}\n                    height={totalHeight}\n                    fill={accent}\n                    opacity={0.95}\n                    onMouseEnter={(e) => setStageCursor(e.target.getStage(), 'ew-resize')}\n                    onMouseLeave={(e) => setStageCursor(e.target.getStage(), 'default')}\n                    onMouseDown={(e) => {\n                      e.cancelBubble = true;\n                      const stage = e.target.getStage();\n                      const endAtDrag = loopEnd;\n                      setStageCursor(stage, 'ew-resize');\n                      const onMove = () => {\n                        const p = stage?.getPointerPosition();\n                        if (!p) return;\n                        let ns = snap((p.x + scrollLeft) / zoom);\n                        ns = Math.max(0, Math.min(ns, endAtDrag - LOOP_MIN_DURATION));\n                        setLoop(true, ns, endAtDrag);\n                      };\n                      bindWindowDrag(stage, onMove);\n                    }}\n                  />\n                  <Rect\n                    x={x + w - LOOP_HANDLE_W / 2}\n                    y={0}\n                    width={LOOP_HANDLE_W}\n                    height={totalHeight}\n                    fill={accent}\n                    opacity={0.95}\n                    onMouseEnter={(e) => setStageCursor(e.target.getStage(), 'ew-resize')}\n                    onMouseLeave={(e) => setStageCursor(e.target.getStage(), 'default')}\n                    onMouseDown={(e) => {\n                      e.cancelBubble = true;\n                      const stage = e.target.getStage();\n                      const startAtDrag = loopStart;\n                      setStageCursor(stage, 'ew-resize');\n                      const onMove = () => {\n                        const p = stage?.getPointerPosition();\n                        if (!p) return;\n                        let ne = snap((p.x + scrollLeft) / zoom);\n                        ne = Math.min(\n                          projectDuration,\n                          Math.max(ne, startAtDrag + LOOP_MIN_DURATION),\n                        );\n                        setLoop(true, startAtDrag, ne);\n                      };\n                      bindWindowDrag(stage, onMove);\n                    }}\n                  />\n                </Group>\n              );\n            })()}\n\n        </Layer>\n\n        {/* Ruler + playhead above tracks (clips call moveToTop on drag within the content layer) */}\n        <Layer>\n          <Rect x={0} y={0} width={totalWidth} height={RULER_HEIGHT} fill=\"#0F0F16\" />\n          {rulerTicks.map((tick) => (\n            <Group key={tick} x={tick * zoom}>\n              <Line points={[0, RULER_HEIGHT - 8, 0, RULER_HEIGHT]} stroke=\"#2A2A38\" strokeWidth={1} />\n              <Text\n                text={`${Math.floor(tick / 60)}:${String(Math.floor(tick % 60)).padStart(2, '0')}`}\n                x={4}\n                y={6}\n                fontSize={10}\n                fill=\"#8888A0\"\n                listening={false}\n              />\n            </Group>\n          ))}\n\n          {transcript.length > 0 &&\n            transcript.map((w) => {\n              const x = w.start * zoom;\n              const wPx = Math.max(2, (w.end - w.start) * zoom);\n              const selected = selectedTranscriptIds.includes(w.id);\n              return (\n                <Group\n                  key={w.id}\n                  x={x}\n                  y={RULER_HEIGHT - 14}\n                  onClick={(e) => {\n                    e.cancelBubble = true;\n                    selectTranscriptWords([w.id], e.evt.shiftKey || e.evt.metaKey);\n                    setPlayhead(w.start);\n                  }}\n                >\n                  <Rect\n                    width={wPx}\n                    height={12}\n                    fill={selected ? '#6C63FF' : w.isFiller ? '#FFD54F55' : '#00BFA533'}\n                    cornerRadius={2}\n                  />\n                  {wPx > 18 && (\n                    <Text\n                      text={w.text}\n                      x={2}\n                      y={1}\n                      fontSize={8}\n                      fill={selected ? '#fff' : '#C8C8D8'}\n                      width={wPx - 4}\n                      ellipsis\n                      listening={false}\n                    />\n                  )}\n                </Group>\n              );\n            })}\n\n          {/* Playhead \u2014 full-height hit zone; drag with ew-resize */}\n          <Group\n            x={playheadTime * zoom}\n            y={0}\n            draggable\n            dragBoundFunc={(pos) => {\n              const t = snap(Math.max(0, pos.x / zoom));\n              return { x: t * zoom, y: 0 };\n            }}\n            onMouseEnter={(e) => setStageCursor(e.target.getStage(), 'ew-resize')}\n            onMouseLeave={(e) => setStageCursor(e.target.getStage(), 'default')}\n            onDragStart={(e) => {\n              clearSplitHover();\n              setStageCursor(e.target.getStage(), 'ew-resize');\n              e.cancelBubble = true;\n            }}\n            onDragMove={(e) => {\n              setPlayhead(snap(Math.max(0, e.target.x() / zoom)));\n            }}\n            onDragEnd={(e) => {\n              setPlayhead(snap(Math.max(0, e.target.x() / zoom)));\n              setStageCursor(e.target.getStage(), 'ew-resize');\n            }}\n            onMouseMove={() => {\n              // Hovering the playhead over a clip arms the split chip.\n              const tSec = playheadTime;\n              for (const tr of tracks) {\n                if (tr.locked) continue;\n                const hit = tr.clips.find(\n                  (c) => tSec > c.startTime + 0.05 && tSec < c.startTime + c.duration - 0.05,\n                );\n                if (hit) {\n                  armSplitHoverOnClip(hit, tr.locked);\n                  return;\n                }\n              }\n            }}\n          >\n            <Rect\n              x={-PLAYHEAD_HIT_HALF}\n              y={0}\n              width={PLAYHEAD_HIT_HALF * 2}\n              height={totalHeight}\n              fill=\"transparent\"\n            />\n            <Line\n              points={[0, 0, 0, totalHeight]}\n              stroke=\"#FF4081\"\n              strokeWidth={1.5}\n              listening={false}\n            />\n          </Group>\n\n          {snapLineX !== null && (\n            <Line\n              points={[snapLineX, 0, snapLineX, totalHeight]}\n              stroke=\"#FFD54F\"\n              strokeWidth={1}\n              dash={[4, 4]}\n              listening={false}\n            />\n          )}\n        </Layer>\n      </Stage>\n\n      {contextMenu && menuClip && (\n        <div\n          ref={menuRef}\n          className=\"fixed z-50 min-w-[220px] rounded-xl border border-panel-border bg-panel py-1 shadow-2xl\"\n          style={{\n            top: contextMenu.y,\n            left: contextMenu.x,\n            ...modeAccentVars(mode),\n          }}\n          onMouseDown={(e) => e.stopPropagation()}\n        >\n          <TextTitle as=\"span\" size=\"xs\" className=\"px-3 py-1.5 uppercase tracking-wider text-[var(--we-accent)]\">{t.audio.clipMenu.title}</TextTitle>\n          <button\n            type=\"button\"\n            className={menuBtn}\n            onClick={() => runMenu(() => copySelectedClips())}\n          >\n            <Copy size={12} className=\"text-[var(--we-accent)]\" />\n            <TextBody as=\"span\" size=\"sm\">{t.audio.clipMenu.copy}</TextBody>\n            <span className={menuKbd}>{modShortcut('C')}</span>\n          </button>\n          <button\n            type=\"button\"\n            className={menuBtn}\n            onClick={() => runMenu(() => cutSelectedClips())}\n          >\n            <Scissors size={12} className=\"text-[var(--we-accent)]\" />\n            <TextBody as=\"span\" size=\"sm\">{t.audio.clipMenu.cut}</TextBody>\n            <span className={menuKbd}>{modShortcut('X')}</span>\n          </button>\n          <button\n            type=\"button\"\n            className={menuBtn}\n            disabled={!clipboardClips.length}\n            onClick={() => runMenu(() => pasteClips())}\n          >\n            <ClipboardPaste size={12} className=\"text-[var(--we-accent)]\" />\n            <TextBody as=\"span\" size=\"sm\">{t.audio.clipMenu.paste}</TextBody>\n            <span className={menuKbd}>{modShortcut('V')}</span>\n          </button>\n\n          <div className=\"my-1 border-t border-panel-border\" />\n\n          <button\n            type=\"button\"\n            className={menuBtn}\n            onClick={() =>\n              runMenu(() => {\n                duplicateClip(menuClip.clip.id);\n              })\n            }\n          >\n            <Plus size={12} className=\"text-[var(--we-accent)]\" />\n            <TextBody as=\"span\" size=\"sm\">{t.audio.clipMenu.createBar}</TextBody>\n            <span className={menuKbd}>{modShortcut('D')}</span>\n          </button>\n          <button\n            type=\"button\"\n            className={menuBtn}\n            disabled={!canJoinMenuClip}\n            onClick={() => runMenu(() => joinAdjacentClip(menuClip.clip.id))}\n          >\n            <Link2 size={12} className=\"text-[var(--we-accent)]\" />\n            <TextBody as=\"span\" size=\"sm\">{t.audio.clipMenu.joinAdjacent}</TextBody>\n          </button>\n          <button\n            type=\"button\"\n            className={menuBtn}\n            onClick={() =>\n              runMenu(() =>\n                updateClip(menuClip.clip.id, { inverted: !menuClip.clip.inverted }),\n              )\n            }\n          >\n            <Waves size={12} className=\"text-[var(--we-accent)]\" />\n            <TextBody as=\"span\" size=\"sm\">{t.audio.clipMenu.invert}</TextBody>\n            <span className={menuKbd}>{modShortcut('I')}</span>\n          </button>\n\n          <div className=\"my-1 border-t border-panel-border\" />\n\n          <button\n            type=\"button\"\n            className={menuBtn}\n            onClick={() =>\n              runMenu(() => updateClip(menuClip.clip.id, { muted: !menuClip.clip.muted }))\n            }\n          >\n            <EyeOff size={12} className=\"text-[var(--we-accent)]\" />\n            <TextBody as=\"span\" size=\"sm\">{menuClip.clip.muted ? t.audio.clipMenu.show : t.audio.clipMenu.hide}</TextBody>\n            <span className={menuKbd}>{modShortcut('H')}</span>\n          </button>\n          <button\n            type=\"button\"\n            className={menuBtn}\n            onClick={() => runMenu(() => toggleTrackLock(menuClip.track.id))}\n          >\n            <Lock size={12} className=\"text-[var(--we-accent)]\" />\n            <span>\n              {menuClip.track.locked ? t.audio.clipMenu.unlock : t.audio.clipMenu.lock}\n            </span>\n            <span className={menuKbd}>{modShortcut('L')}</span>\n          </button>\n\n          <div className=\"my-1 border-t border-panel-border\" />\n\n          <button\n            type=\"button\"\n            className={menuBtn}\n            onClick={() =>\n              runMenu(() => {\n                openAiTool('isolate');\n              })\n            }\n          >\n            <Sparkles size={12} className=\"text-[var(--we-accent)]\" />\n            <TextBody as=\"span\" size=\"sm\">{t.audio.clipMenu.isolate}</TextBody>\n          </button>\n          <button\n            type=\"button\"\n            className={menuBtn}\n            onClick={() =>\n              runMenu(() => {\n                openAiTool('cleanup');\n              })\n            }\n          >\n            <Sparkles size={12} className=\"text-[var(--we-accent)]\" />\n            <TextBody as=\"span\" size=\"sm\">{t.audio.clipMenu.removeNoise}</TextBody>\n          </button>\n          <button\n            type=\"button\"\n            className={menuBtn}\n            onClick={() =>\n              runMenu(() => {\n                splitClip(menuClip.clip.id, playheadTime);\n              })\n            }\n          >\n            <Scissors size={12} className=\"text-[var(--we-accent)]\" />\n            <TextBody as=\"span\" size=\"sm\">{t.audio.tools.split}</TextBody>\n          </button>\n          <button\n            type=\"button\"\n            className={menuBtn}\n            onClick={() => runMenu(() => addTrack(t.audio.tracks.addTrack))}\n          >\n            <Plus size={12} className=\"text-[var(--we-accent)]\" />\n            <TextBody as=\"span\" size=\"sm\">{t.audio.tracks.addTrack}</TextBody>\n          </button>\n\n          <div className=\"my-1 border-t border-panel-border\" />\n\n          <button\n            type=\"button\"\n            className={`${menuBtn} text-red-300`}\n            onClick={() => {\n              setContextMenu(null);\n              void confirmDeleteSelection();\n            }}\n          >\n            <Trash2 size={12} />\n            <TextBody as=\"span\" size=\"sm\">{t.audio.clipMenu.delete}</TextBody>\n          </button>\n        </div>\n      )}\n\n      {emptyMenu && (\n        <div\n          ref={emptyMenuRef}\n          className=\"fixed z-50 min-w-[220px] rounded-xl border border-panel-border bg-panel py-1 shadow-2xl\"\n          style={{\n            top: emptyMenu.y,\n            left: emptyMenu.x,\n            ...modeAccentVars(mode),\n          }}\n          onMouseDown={(e) => e.stopPropagation()}\n        >\n          <TextTitle as=\"span\" size=\"xs\" className=\"px-3 py-1.5 uppercase tracking-wider text-[var(--we-accent)]\">{t.audio.clipMenu.emptyTitle}</TextTitle>\n          <button\n            type=\"button\"\n            className={menuBtn}\n            onClick={() => {\n              setEmptyMenu(null);\n              onImportLocal?.();\n            }}\n          >\n            <Upload size={12} className=\"text-[var(--we-accent)]\" />\n            <TextBody as=\"span\" size=\"sm\">{t.audio.clipMenu.importLocal}</TextBody>\n          </button>\n          <button\n            type=\"button\"\n            className={menuBtn}\n            onClick={() => {\n              setEmptyMenu(null);\n              onOpenMyFiles?.();\n            }}\n          >\n            <Folder size={12} className=\"text-[var(--we-accent)]\" />\n            <TextBody as=\"span\" size=\"sm\">{t.audio.clipMenu.importMyFiles}</TextBody>\n          </button>\n          <button\n            type=\"button\"\n            className={menuBtn}\n            disabled={!clipboardClips.length}\n            onClick={() => {\n              setEmptyMenu(null);\n              pasteClips();\n            }}\n          >\n            <ClipboardPaste size={12} className=\"text-[var(--we-accent)]\" />\n            <TextBody as=\"span\" size=\"sm\">{t.audio.clipMenu.paste}</TextBody>\n            <span className={menuKbd}>{modShortcut('V')}</span>\n          </button>\n        </div>\n      )}\n\n      {splitHover?.ready &&\n        (() => {\n          const trackIndex = tracks.findIndex((tr) =>\n            tr.clips.some((c) => c.id === splitHover.clipId),\n          );\n          const track = trackIndex >= 0 ? tracks[trackIndex] : undefined;\n          const clip = track?.clips.find((c) => c.id === splitHover.clipId);\n          const host = containerRef.current;\n          if (!clip || !host || trackIndex < 0) return null;\n\n          const hostRect = host.getBoundingClientRect();\n          const playheadX = playheadTime * zoom - scrollLeft;\n          const centerY =\n            RULER_HEIGHT + trackIndex * AUDIO_TRACK_HEIGHT - scrollTop + AUDIO_TRACK_HEIGHT / 2;\n\n          return (\n            <button\n              type=\"button\"\n              data-we-split-chip\n              className=\"fixed z-[60] flex -translate-x-1/2 -translate-y-1/2 cursor-pointer items-center gap-1.5 rounded-lg border border-panel-border bg-panel px-2.5 py-1.5 font-sans text-xs font-semibold text-white shadow-2xl transition-opacity hover:opacity-80\"\n              style={{\n                left: hostRect.left + playheadX,\n                top: hostRect.top + centerY,\n                ...modeAccentVars(mode),\n              }}\n              onMouseEnter={cancelSplitHoverClear}\n              onMouseLeave={scheduleSplitHoverClear}\n              onClick={(e) => {\n                e.preventDefault();\n                e.stopPropagation();\n                splitClip(splitHover.clipId, playheadTime);\n                clearSplitHover();\n              }}\n            >\n              <Scissors size={12} className=\"text-[var(--we-accent)]\" />\n              <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                {t.audio.tools.split}\n              </TextBody>\n            </button>\n          );\n        })()}\n    </div>\n  );\n};\n", "import React from 'react';\nimport {\n  ClipboardPaste,\n  Copy,\n  Scissors,\n  ScissorsLineDashed,\n} from 'lucide-react';\nimport { useAudioStore } from '../../store/useAudioStore';\nimport { useTranslation } from '../../i18n';\nimport { IconButton } from '../ui';\n\n/**\n * Edit tools above the audio timeline (split / trim / copy / paste).\n */\nexport const AudioTimelineToolbar: React.FC = () => {\n  const t = useTranslation();\n  const {\n    playheadTime,\n    selectedClipIds,\n    clipboardClips,\n    splitClip,\n    copySelectedClips,\n    pasteClips,\n    trimSelectedToPlayhead,\n  } = useAudioStore();\n\n  const hasSelection = selectedClipIds.length > 0;\n  const canPaste = clipboardClips.length > 0;\n\n  return (\n    <div className=\"flex h-9 shrink-0 items-center gap-0.5 border-b border-panel-border bg-panel px-2 select-none\">\n      <IconButton\n        variant=\"ghost\"\n        size=\"sm\"\n        label={t.audio.tools.split}\n        disabled={!hasSelection}\n        onClick={() => {\n          const id = selectedClipIds[0];\n          if (id) splitClip(id, playheadTime);\n        }}\n      >\n        <Scissors size={14} />\n      </IconButton>\n      <IconButton\n        variant=\"ghost\"\n        size=\"sm\"\n        label={t.audio.tools.trimStart}\n        disabled={!hasSelection}\n        onClick={() => trimSelectedToPlayhead('start')}\n      >\n        <ScissorsLineDashed size={14} className=\"-scale-x-100\" />\n      </IconButton>\n      <IconButton\n        variant=\"ghost\"\n        size=\"sm\"\n        label={t.audio.tools.trimEnd}\n        disabled={!hasSelection}\n        onClick={() => trimSelectedToPlayhead('end')}\n      >\n        <ScissorsLineDashed size={14} />\n      </IconButton>\n\n      <div className=\"mx-1 h-4 w-px bg-panel-border\" />\n\n      <IconButton\n        variant=\"ghost\"\n        size=\"sm\"\n        label={t.audio.tools.copy}\n        disabled={!hasSelection}\n        onClick={() => copySelectedClips()}\n      >\n        <Copy size={14} />\n      </IconButton>\n      <IconButton\n        variant=\"ghost\"\n        size=\"sm\"\n        label={t.audio.tools.paste}\n        disabled={!canPaste}\n        onClick={() => pasteClips()}\n      >\n        <ClipboardPaste size={14} />\n      </IconButton>\n    </div>\n  );\n};\n", "/**\n * Encode an AudioBuffer to MP3 in-process (no FFmpeg.wasm).\n * FFmpeg load/exec often hangs in the browser on libmp3lame; lamejs is reliable.\n */\n\nimport { Mp3Encoder } from '@breezystack/lamejs';\n\nfunction floatToInt16(sample: number): number {\n  const s = Math.max(-1, Math.min(1, sample));\n  return s < 0 ? Math.round(s * 0x8000) : Math.round(s * 0x7fff);\n}\n\nexport type EncodeMp3Options = {\n  /** Constant bitrate kbps (default 192). */\n  kbps?: number;\n  onProgress?: (p: number) => void;\n};\n\n/**\n * Encode stereo/mono AudioBuffer \u2192 audio/mpeg Blob.\n * Yields to the event loop so the export UI can paint progress.\n */\nexport async function encodeMp3FromAudioBuffer(\n  buffer: AudioBuffer,\n  opts: EncodeMp3Options = {},\n): Promise<Blob> {\n  const kbps = opts.kbps ?? 192;\n  const channels = Math.min(2, Math.max(1, buffer.numberOfChannels)) as 1 | 2;\n  const sampleRate = buffer.sampleRate;\n  const encoder = new Mp3Encoder(channels, sampleRate, kbps);\n\n  const left = buffer.getChannelData(0);\n  const right = channels > 1 ? buffer.getChannelData(1) : left;\n  const total = left.length;\n  const blockSize = 1152;\n  const parts: BlobPart[] = [];\n\n  for (let i = 0; i < total; i += blockSize) {\n    const len = Math.min(blockSize, total - i);\n    const leftChunk = new Int16Array(len);\n    const rightChunk = channels > 1 ? new Int16Array(len) : leftChunk;\n    for (let j = 0; j < len; j++) {\n      leftChunk[j] = floatToInt16(left[i + j] ?? 0);\n      if (channels > 1) {\n        rightChunk[j] = floatToInt16(right[i + j] ?? 0);\n      }\n    }\n\n    const encoded =\n      channels === 1\n        ? encoder.encodeBuffer(leftChunk)\n        : encoder.encodeBuffer(leftChunk, rightChunk);\n    if (encoded.length > 0) parts.push(encoded);\n\n    if (i === 0 || i % (blockSize * 40) === 0) {\n      opts.onProgress?.(Math.min(0.99, i / Math.max(1, total)));\n      await new Promise<void>((r) => setTimeout(r, 0));\n    }\n  }\n\n  const flush = encoder.flush();\n  if (flush.length > 0) parts.push(flush);\n  opts.onProgress?.(1);\n  return new Blob(parts, { type: 'audio/mpeg' });\n}\n", "/**\n * Offline mixdown of the audio project using OfflineAudioContext.\n * Parity with live scheduler: pitchSeparate stretch, equal-power crossfades, take mute.\n */\n\nimport type { AudioAsset, AudioClip, AudioTrack } from '../../store/useAudioStore';\nimport { dbToLinear, evaluateFade } from './dsp/gain';\nimport { createEffectChain } from './effects/createEffectChain';\nimport { encodeWav, type WavBitDepth } from './wavEncoder';\nimport { encodeMp3FromAudioBuffer } from './mp3Encoder';\nimport { applyGainInPlace, gainForTargetLufs } from './loudness';\nimport { getFFmpeg } from '../../services/ffmpegService';\nimport { schedulePanAutomation, scheduleVolumeAutomation } from './automation';\nimport { timeStretchBuffer } from './timeStretch';\nimport { scheduleShapedFade, type CrossfadeCurve } from './crossfade';\n\nconst FFMPEG_EXEC_TIMEOUT_MS = 120_000;\n\nasync function encodeWithFfmpeg(\n  wav: Blob,\n  format: 'ogg' | 'flac',\n  onProgress?: (p: number, step: string) => void,\n): Promise<Blob> {\n  onProgress?.(0.88, 'Cargando encoder\u2026');\n  const ffmpeg = await getFFmpeg();\n  const inputName = 'input.wav';\n  const outputName = `output.${format}`;\n  const wavBytes = new Uint8Array(await wav.arrayBuffer());\n  await ffmpeg.writeFile(inputName, wavBytes);\n\n  onProgress?.(0.92, `Codificando ${format.toUpperCase()}\u2026`);\n  const args =\n    format === 'ogg'\n      ? ['-y', '-i', inputName, '-codec:a', 'libvorbis', '-q:a', '6', outputName]\n      : ['-y', '-i', inputName, '-codec:a', 'flac', outputName];\n\n  const code = await ffmpeg.exec(args, FFMPEG_EXEC_TIMEOUT_MS);\n  if (code !== 0) {\n    throw new Error(\n      `No se pudo codificar a ${format.toUpperCase()} (c\u00F3digo ${code}). Prueba WAV o MP3.`,\n    );\n  }\n\n  const data = await ffmpeg.readFile(outputName);\n  await ffmpeg.deleteFile(inputName).catch(() => {});\n  await ffmpeg.deleteFile(outputName).catch(() => {});\n\n  const bytes = data instanceof Uint8Array ? data : new TextEncoder().encode(String(data));\n  if (!bytes.byteLength) {\n    throw new Error(`El encoder devolvi\u00F3 un archivo ${format.toUpperCase()} vac\u00EDo.`);\n  }\n  const mime = format === 'ogg' ? 'audio/ogg' : 'audio/flac';\n  return new Blob([Uint8Array.from(bytes)], { type: mime });\n}\n\nexport interface OfflineRenderOptions {\n  tracks: AudioTrack[];\n  assets: AudioAsset[];\n  duration: number;\n  sampleRate?: number;\n  /** If set, only render this track (stem export). */\n  stemTrackId?: string;\n  startTime?: number;\n  endTime?: number;\n  targetLufs?: number | null;\n  format?: 'wav' | 'mp3' | 'ogg' | 'flac';\n  bitDepth?: WavBitDepth;\n  dither?: boolean;\n  onProgress?: (p: number, step: string) => void;\n  signal?: AbortSignal;\n}\n\nasync function decodeAll(\n  assets: AudioAsset[],\n  sampleRate: number\n): Promise<Map<string, AudioBuffer>> {\n  const map = new Map<string, AudioBuffer>();\n  const ctx = new OfflineAudioContext(2, 1, sampleRate);\n  for (const asset of assets) {\n    if (!asset.file && !asset.url) continue;\n    try {\n      const ab = await (asset.file?.arrayBuffer() ?? fetch(asset.url).then((r) => r.arrayBuffer()));\n      const buf = await ctx.decodeAudioData(ab.slice(0));\n      map.set(asset.id, buf);\n    } catch (err) {\n      console.error('offline decode failed', asset.name, err);\n    }\n  }\n  return map;\n}\n\nfunction prepareStretchBuffers(\n  tracks: AudioTrack[],\n  buffers: Map<string, AudioBuffer>\n): Map<string, AudioBuffer> {\n  const out = new Map(buffers);\n  for (const track of tracks) {\n    for (const clip of track.clips) {\n      if (!clip.pitchSeparate || Math.abs(clip.speed - 1) < 0.01) continue;\n      const key = `${clip.assetId}|stretch|${clip.speed.toFixed(3)}`;\n      if (out.has(key)) continue;\n      const src = out.get(clip.assetId);\n      if (!src) continue;\n      out.set(key, timeStretchBuffer(src, 1 / clip.speed));\n    }\n  }\n  return out;\n}\n\nfunction applyOfflineOverlapCrossfade(\n  param: AudioParam,\n  clips: AudioClip[],\n  clip: AudioClip,\n  when: number,\n  regionStart: number,\n  remaining: number\n) {\n  const others = clips.filter(\n    (c) => c.id !== clip.id && !c.muted && !(c.takeGroupId && c.compActive === false)\n  );\n  for (const other of others) {\n    const overlapStart = Math.max(clip.startTime, other.startTime);\n    const overlapEnd = Math.min(\n      clip.startTime + clip.duration,\n      other.startTime + other.duration\n    );\n    if (overlapEnd - overlapStart < 0.02) continue;\n\n    const curve: CrossfadeCurve = clip.crossfadeCurve || 'equal-power';\n    if (clip.startTime <= other.startTime) {\n      const fadeDur = Math.min(\n        overlapEnd - overlapStart,\n        Math.max(clip.crossfadeOut || clip.fadeOut, 0.05)\n      );\n      const fadeAt = overlapEnd - fadeDur;\n      const startWhen = Math.max(0, fadeAt - regionStart);\n      if (startWhen + fadeDur <= when) continue;\n      scheduleShapedFade(param, Math.max(when, startWhen), fadeDur, clip.gain, curve, 'out');\n    } else {\n      const fadeDur = Math.min(\n        overlapEnd - overlapStart,\n        Math.max(clip.crossfadeIn || clip.fadeIn, 0.05)\n      );\n      const startWhen = Math.max(0, overlapStart - regionStart);\n      if (startWhen + fadeDur <= when) continue;\n      scheduleShapedFade(param, Math.max(when, startWhen), fadeDur, clip.gain, curve, 'in');\n    }\n  }\n  void remaining;\n}\n\nfunction scheduleClipOnOffline(\n  ctx: OfflineAudioContext,\n  buffer: AudioBuffer,\n  clip: AudioClip,\n  siblings: AudioClip[],\n  dest: AudioNode,\n  regionStart: number,\n  useStretch: boolean\n) {\n  const relativeStart = clip.startTime - regionStart;\n  if (relativeStart + clip.duration <= 0) return;\n  if (relativeStart >= ctx.length / ctx.sampleRate) return;\n\n  const source = ctx.createBufferSource();\n  source.buffer = buffer;\n  source.playbackRate.value = clip.pitchSeparate\n    ? Math.pow(2, clip.pitch / 12)\n    : clip.speed * Math.pow(2, clip.pitch / 12);\n\n  const gainNode = ctx.createGain();\n  const base = clip.muted ? 0 : clip.gain * (clip.inverted ? -1 : 1);\n  const when = Math.max(0, relativeStart);\n  gainNode.gain.setValueAtTime(0, when);\n\n  if (clip.fadeIn > 0) {\n    const steps = 6;\n    for (let i = 0; i <= steps; i++) {\n      const t = i / steps;\n      gainNode.gain.linearRampToValueAtTime(\n        evaluateFade(t, clip.fadeInCurve, 'in') * base,\n        when + clip.fadeIn * t\n      );\n    }\n  } else {\n    gainNode.gain.setValueAtTime(base, when);\n  }\n\n  if (clip.fadeOut > 0) {\n    const fadeStart = when + Math.max(0, clip.duration - clip.fadeOut);\n    gainNode.gain.setValueAtTime(base, fadeStart);\n    const steps = 6;\n    for (let i = 0; i <= steps; i++) {\n      const t = i / steps;\n      gainNode.gain.linearRampToValueAtTime(\n        evaluateFade(t, clip.fadeOutCurve, 'out') * base,\n        fadeStart + clip.fadeOut * t\n      );\n    }\n  }\n\n  applyOfflineOverlapCrossfade(gainNode.gain, siblings, clip, when, regionStart, clip.duration);\n\n  source.connect(gainNode);\n  gainNode.connect(dest);\n\n  const speedForOffset = clip.pitchSeparate ? 1 : clip.speed;\n  const bufferOffset = useStretch\n    ? clip.trimIn / Math.max(0.01, clip.speed)\n    : clip.trimIn;\n  const duration = clip.duration / Math.max(0.01, speedForOffset);\n  try {\n    source.start(when, bufferOffset, duration);\n  } catch {\n    /* clip outside offline window */\n  }\n}\n\nexport async function renderAudioProject(opts: OfflineRenderOptions): Promise<Blob> {\n  const sampleRate = opts.sampleRate ?? 48000;\n  const start = opts.startTime ?? 0;\n  const end = opts.endTime ?? opts.duration;\n  const lengthSec = Math.max(0.1, end - start);\n  const length = Math.ceil(lengthSec * sampleRate);\n\n  opts.onProgress?.(0.05, 'Decodificando assets...');\n  if (opts.signal?.aborted) throw new Error('Export aborted');\n\n  let buffers = await decodeAll(opts.assets, sampleRate);\n  opts.onProgress?.(0.2, 'Time-stretch...');\n  buffers = prepareStretchBuffers(opts.tracks, buffers);\n  opts.onProgress?.(0.25, 'Mezclando...');\n\n  const ctx = new OfflineAudioContext(2, length, sampleRate);\n  const master = ctx.createGain();\n  const limiter = ctx.createDynamicsCompressor();\n  limiter.threshold.value = -1;\n  limiter.knee.value = 0;\n  limiter.ratio.value = 20;\n  limiter.attack.value = 0.001;\n  limiter.release.value = 0.05;\n  master.connect(limiter);\n  limiter.connect(ctx.destination);\n\n  const tracks = opts.stemTrackId\n    ? opts.tracks.filter((t) => t.id === opts.stemTrackId)\n    : opts.tracks;\n\n  const anySolo = tracks.some((t) => t.solo);\n  const busInputs = new Map<string, GainNode>();\n\n  for (const track of tracks) {\n    if (track.type !== 'bus') continue;\n    if (track.muted) continue;\n    if (anySolo && !track.solo) continue;\n\n    const input = ctx.createGain();\n    const trackGain = ctx.createGain();\n    trackGain.gain.value = dbToLinear(track.volumeDb);\n    const panner = ctx.createStereoPanner();\n    panner.pan.value = track.pan;\n    scheduleVolumeAutomation(trackGain.gain, track.automation, track.volumeDb, start, 0, lengthSec, ctx);\n    schedulePanAutomation(panner.pan, track.automation, track.pan, start, 0, lengthSec);\n    const chain = createEffectChain(ctx, track.effects);\n    input.connect(trackGain);\n    trackGain.connect(chain.input);\n    chain.output.connect(panner);\n    panner.connect(master);\n    busInputs.set(track.id, input);\n  }\n\n  for (const track of tracks) {\n    if (track.type !== 'audio') continue;\n    if (track.muted) continue;\n    if (anySolo && !track.solo) continue;\n\n    const trackGain = ctx.createGain();\n    trackGain.gain.value = dbToLinear(track.volumeDb);\n    const panner = ctx.createStereoPanner();\n    panner.pan.value = track.pan;\n\n    scheduleVolumeAutomation(\n      trackGain.gain,\n      track.automation,\n      track.volumeDb,\n      start,\n      0,\n      lengthSec,\n      ctx\n    );\n    schedulePanAutomation(panner.pan, track.automation, track.pan, start, 0, lengthSec);\n\n    const chain = createEffectChain(ctx, track.effects);\n    trackGain.connect(chain.input);\n    chain.output.connect(panner);\n    panner.connect(master);\n\n    for (const send of track.sends || []) {\n      const busIn = busInputs.get(send.busId);\n      if (!busIn || send.amount <= 0.001) continue;\n      const g = ctx.createGain();\n      g.gain.value = send.amount;\n      chain.output.connect(g);\n      g.connect(busIn);\n    }\n\n    for (const clip of track.clips) {\n      if (clip.muted || (clip.takeGroupId && clip.compActive === false)) continue;\n      const useStretch = Boolean(clip.pitchSeparate && Math.abs(clip.speed - 1) > 0.01);\n      const bufKey = useStretch\n        ? `${clip.assetId}|stretch|${clip.speed.toFixed(3)}`\n        : clip.assetId;\n      const buffer = buffers.get(bufKey) ?? buffers.get(clip.assetId);\n      if (!buffer) continue;\n      scheduleClipOnOffline(ctx, buffer, clip, track.clips, trackGain, start, useStretch);\n    }\n  }\n\n  opts.onProgress?.(0.55, 'Renderizando...');\n  const rendered = await ctx.startRendering();\n\n  if (opts.targetLufs != null) {\n    opts.onProgress?.(0.7, 'Normalizando LUFS...');\n    const g = gainForTargetLufs(rendered, opts.targetLufs);\n    applyGainInPlace(rendered, g);\n  }\n\n  const format = opts.format ?? 'wav';\n  opts.onProgress?.(0.85, `Codificando ${format.toUpperCase()}\u2026`);\n\n  if (format === 'wav') {\n    const blob = encodeWav(rendered, opts.bitDepth ?? 16, { dither: opts.dither !== false });\n    opts.onProgress?.(1, 'Listo');\n    return blob;\n  }\n\n  // MP3: pure JS (FFmpeg.wasm + libmp3lame often hangs forever in Chromium).\n  if (format === 'mp3') {\n    const blob = await encodeMp3FromAudioBuffer(rendered, {\n      kbps: 192,\n      onProgress: (p) => opts.onProgress?.(0.85 + p * 0.14, 'Codificando MP3\u2026'),\n    });\n    opts.onProgress?.(1, 'Listo');\n    return blob;\n  }\n\n  const wav = encodeWav(rendered, 16, { dither: opts.dither !== false });\n  const blob = await encodeWithFfmpeg(wav, format, opts.onProgress);\n  opts.onProgress?.(1, 'Listo');\n  return blob;\n}\n\n/** Bounce selection (or whole project) to a WAV blob for bounce-in-place. */\nexport async function bounceSelection(opts: {\n  tracks: AudioTrack[];\n  assets: AudioAsset[];\n  startTime: number;\n  endTime: number;\n  stemTrackId?: string;\n}): Promise<Blob> {\n  return renderAudioProject({\n    tracks: opts.tracks,\n    assets: opts.assets,\n    duration: opts.endTime,\n    startTime: opts.startTime,\n    endTime: opts.endTime,\n    stemTrackId: opts.stemTrackId,\n    format: 'wav',\n    bitDepth: 24,\n  });\n}\n", "import React, { useState } from 'react';\nimport { useAudioStore } from '../../store/useAudioStore';\nimport { renderAudioProject } from '../../lib/audio/offlineRender';\nimport { useTranslation } from '../../i18n';\nimport { modeExportFilename } from '../../utils/exportDownloadName';\nimport { Button, Modal, PanelField, SelectDropdown, Switch, TextBody } from '../ui';\n\n\ninterface Props {\n  open: boolean;\n  onClose: () => void;\n}\n\nexport const AudioExportModal: React.FC<Props> = ({ open, onClose }) => {\n  const tr = useTranslation();\n  const {\n    tracks,\n    assets,\n    projectDuration,\n    regions,\n    selectedClipIds,\n    addToast,\n    truePeakDb,\n    lufsHistory,\n    integratedLufs,\n  } = useAudioStore();\n  const [format, setFormat] = useState<'wav' | 'mp3' | 'ogg' | 'flac'>('wav');\n  const [bitDepth, setBitDepth] = useState<16 | 24 | 32>(24);\n  const [targetLufs, setTargetLufs] = useState<-14 | -16 | null>(-14);\n  const [stemTrackId, setStemTrackId] = useState<string>('');\n  const [regionMode, setRegionMode] = useState<'full' | 'selection' | 'region'>('full');\n  const [regionId, setRegionId] = useState<string>('');\n  const [dither, setDither] = useState(true);\n  const [progress, setProgress] = useState(0);\n  const [step, setStep] = useState('');\n  const [busy, setBusy] = useState(false);\n\n  const resolveRange = (): { start: number; end: number } => {\n    if (regionMode === 'region' && regionId) {\n      const r = regions.find((x) => x.id === regionId);\n      if (r) return { start: r.startTime, end: r.endTime };\n    }\n    if (regionMode === 'selection' && selectedClipIds.length) {\n      let min = Infinity;\n      let max = -Infinity;\n      for (const t of tracks) {\n        for (const c of t.clips) {\n          if (!selectedClipIds.includes(c.id)) continue;\n          min = Math.min(min, c.startTime);\n          max = Math.max(max, c.startTime + c.duration);\n        }\n      }\n      if (Number.isFinite(min) && max > min) return { start: min, end: max };\n    }\n    return { start: 0, end: projectDuration };\n  };\n\n  const exportNow = async () => {\n    setBusy(true);\n    try {\n      const { start, end } = resolveRange();\n      const blob = await renderAudioProject({\n        tracks,\n        assets,\n        duration: projectDuration,\n        startTime: start,\n        endTime: end,\n        format,\n        bitDepth,\n        dither: format === 'wav' ? dither : false,\n        targetLufs,\n        stemTrackId: stemTrackId || undefined,\n        onProgress: (p, s) => {\n          setProgress(p);\n          setStep(s);\n        },\n      });\n      const a = document.createElement('a');\n      a.href = URL.createObjectURL(blob);\n      a.download = modeExportFilename('audio', format);\n      a.click();\n      URL.revokeObjectURL(a.href);\n      addToast(tr.audio.export.toasts.ready, 'success');\n      onClose();\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : tr.audio.export.toasts.errorExport, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  return (\n    <Modal isOpen={open} onClose={onClose} title={tr.audio.export.title} size=\"md\">\n      <div className=\"mb-4 flex flex-wrap gap-3\">\n        <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n          {tr.audio.export.meters.shortTerm}{' '}\n          <TextBody as=\"span\" size=\"sm\" className=\"tabular-nums text-teal-400\">\n            {lufsHistory.length ? lufsHistory[lufsHistory.length - 1]!.toFixed(1) : '\u2014'}\n          </TextBody>\n        </TextBody>\n        <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n          {tr.audio.export.meters.integrated}{' '}\n          <TextBody as=\"span\" size=\"sm\" className=\"tabular-nums text-[var(--we-accent)]\">\n            {integratedLufs > -69 ? integratedLufs.toFixed(1) : '\u2014'} LUFS\n          </TextBody>\n        </TextBody>\n        <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n          {tr.audio.export.meters.truePeak}{' '}\n          <TextBody as=\"span\" size=\"sm\" className=\"tabular-nums text-pink-400\">\n            {truePeakDb.toFixed(1)} dBTP\n          </TextBody>\n        </TextBody>\n      </div>\n\n      <div className=\"flex flex-col gap-2\">\n        <PanelField\n          label={tr.audio.export.rangeLabel}\n          trailing={\n            <SelectDropdown\n              value={regionMode}\n              options={[\n                { value: 'full', label: tr.audio.export.rangeFull },\n                { value: 'selection', label: tr.audio.export.rangeSelection },\n                { value: 'region', label: tr.audio.export.rangeRegion },\n              ]}\n              onChange={(v) => setRegionMode(v as typeof regionMode)}\n              ariaLabel={tr.audio.export.rangeLabel}\n            />\n          }\n        />\n        {regionMode === 'region' && (\n          <PanelField\n            label={tr.audio.export.chooseRegion}\n            trailing={\n              <SelectDropdown\n                value={regionId}\n                options={[\n                  { value: '', label: tr.audio.export.chooseRegion },\n                  ...regions.map((r) => ({\n                    value: r.id,\n                    label: `${r.name} (${r.startTime.toFixed(1)}\u2013${r.endTime.toFixed(1)}s)`,\n                  })),\n                ]}\n                onChange={setRegionId}\n                ariaLabel={tr.audio.export.chooseRegion}\n              />\n            }\n          />\n        )}\n        <PanelField\n          label={tr.audio.export.formatLabel}\n          trailing={\n            <SelectDropdown\n              value={format}\n              options={[\n                { value: 'wav', label: 'WAV' },\n                { value: 'mp3', label: 'MP3' },\n                { value: 'ogg', label: 'OGG' },\n                { value: 'flac', label: 'FLAC' },\n              ]}\n              onChange={(v) => setFormat(v as typeof format)}\n              ariaLabel={tr.audio.export.formatLabel}\n            />\n          }\n        />\n        {format === 'wav' && (\n          <>\n            <PanelField\n              label={tr.audio.export.bitDepthLabel}\n              trailing={\n                <SelectDropdown\n                  value={String(bitDepth)}\n                  options={[\n                    { value: '16', label: tr.audio.export.bitDepth16 },\n                    { value: '24', label: tr.audio.export.bitDepth24 },\n                    { value: '32', label: tr.audio.export.bitDepth32 },\n                  ]}\n                  onChange={(v) => setBitDepth(Number(v) as 16 | 24 | 32)}\n                  ariaLabel={tr.audio.export.bitDepthLabel}\n                />\n              }\n            />\n            <PanelField\n              label={tr.audio.export.ditherLabel}\n              trailing={<Switch checked={dither} onChange={setDither} />}\n            />\n          </>\n        )}\n        <PanelField\n          label={tr.audio.export.lufsLabel}\n          trailing={\n            <SelectDropdown\n              value={targetLufs === null ? 'none' : String(targetLufs)}\n              options={[\n                { value: '-14', label: tr.audio.export.lufsStreaming },\n                { value: '-16', label: tr.audio.export.lufsPodcast },\n                { value: 'none', label: tr.audio.export.lufsNone },\n              ]}\n              onChange={(v) =>\n                setTargetLufs(v === 'none' ? null : (Number(v) as -14 | -16))\n              }\n              ariaLabel={tr.audio.export.lufsLabel}\n            />\n          }\n        />\n        <PanelField\n          label={tr.audio.export.stemLabel}\n          trailing={\n            <SelectDropdown\n              value={stemTrackId}\n              options={[\n                { value: '', label: tr.audio.export.fullMix },\n                ...tracks.map((t) => ({ value: t.id, label: t.name })),\n              ]}\n              onChange={setStemTrackId}\n              ariaLabel={tr.audio.export.stemLabel}\n            />\n          }\n        />\n      </div>\n\n      {busy && (\n        <div className=\"mt-4\">\n          <div className=\"h-1.5 overflow-hidden rounded-full bg-black-capsule\">\n            <div\n              className=\"h-full bg-[var(--we-accent)] transition-all\"\n              style={{ width: `${Math.round(progress * 100)}%` }}\n            />\n          </div>\n          <TextBody as=\"p\" size=\"sm\" className=\"mt-1 text-white/80\">{step}</TextBody>\n        </div>\n      )}\n\n      <div className=\"mt-5 flex gap-2\">\n        <Button\n          variant=\"accent\"\n          size=\"md\"\n          className=\"flex-1\"\n          disabled={busy}\n          loading={busy}\n          onClick={() => void exportNow()}\n        >\n          {busy ? tr.audio.export.exporting : tr.audio.export.exportButton}\n        </Button>\n      </div>\n    </Modal>\n  );\n};\n", "import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { Upload } from 'lucide-react';\nimport { useAudioStore } from '../../store/useAudioStore';\nimport { AudioBottomToolbar } from './AudioBottomToolbar';\nimport { AudioRightSidebar } from './AudioRightSidebar';\nimport { AudioTrackControls } from './AudioTrackControls';\nimport { AudioTimeline } from './AudioTimeline';\nimport { AudioTimelineToolbar } from './AudioTimelineToolbar';\nimport { AudioExportModal } from './AudioExportModal';\nimport { EditorShellHeader } from '../editor/EditorShellHeader';\nimport { ShellFileMenu } from '../editor/ShellFileMenu';\nimport { modeAccentVars } from '../../theme/modeAccent';\nimport { ModeProjectTabs } from '../editor/ModeProjectTabs';\nimport { Modal } from '../ui/Modal';\nimport { Button } from '../ui/Button';\nimport { decodeAudioBlob, extractPeaks } from '../../lib/audio/peaks';\nimport { createAudioClip } from '../../store/useAudioStore';\nimport { exportProjectToWzrda, importProjectFromWzrda } from '../../utils/audioProjectFile';\nimport { projectAccept } from '../../utils/projectExtensions';\nimport { getAudioEngine } from '../../lib/audio/AudioEngine';\nimport { uploadCurrentProjectToCloudWithToast } from '../../utils/cloudSaveToast';\nimport { I18nProvider, type Locale, type Messages, useTranslation } from '../../i18n';\nimport { EditorEmptyState } from '../editor/EditorEmptyState';\nimport type { Editable } from '../../services/editableService';\nimport { isApplePlatform, modShortcut } from '../../utils/modKey';\nimport { useDialog } from '../DialogModal';\nimport { useAudioUiStore } from '../../store/useAudioUiStore';\nimport { TextBody } from '../ui';\n\n\ninterface AudioEditorProps {\n  onSwitchMode?: (mode: 'video' | 'image' | 'audio' | 'text' | 'slides') => void;\n  onNewProject?: () => void;\n  backHref?: string;\n  backLinkText?: string;\n  /** UI locale. Defaults to 'es'. See ../../i18n for the available locales. */\n  locale?: Locale;\n  /** Persistent \"Back\" button handler. Falls back to window.history.back(). */\n  onBack?: () => void;\n  /** Called when the user clicks a recent cloud canvas in the empty state. */\n  onOpenCloudProject?: (editable: Editable) => void;\n}\n\nfunction audioShortcutKeys(): Array<{\n  keys: string;\n  descKey: keyof Messages['audio']['editor']['shortcuts'];\n}> {\n  const mod = isApplePlatform() ? '\u2318' : 'Ctrl';\n  const join = isApplePlatform() ? '' : '+';\n  return [\n    { keys: 'Space', descKey: 'playPause' },\n    { keys: 'S', descKey: 'splitClip' },\n    { keys: 'Delete', descKey: 'delete' },\n    { keys: modShortcut('Z'), descKey: 'undo' },\n    {\n      keys: isApplePlatform() ? '\u2318\u21E7Z' : 'Ctrl+Shift+Z',\n      descKey: 'redo',\n    },\n    {\n      keys: `${mod}${join}C / ${mod}${join}V`,\n      descKey: 'copyPaste',\n    },\n    { keys: '\u2190 / \u2192', descKey: 'nudge' },\n    { keys: 'L', descKey: 'loop' },\n    { keys: 'R', descKey: 'toggleRipple' },\n    { keys: 'M', descKey: 'createRegion' },\n    { keys: 'Z', descKey: 'zoomSelection' },\n    { keys: '?', descKey: 'showShortcuts' },\n    { keys: 'Ctrl/\u2318+rueda \u00B7 clic medio', descKey: 'zoomTimeline' },\n  ];\n}\n\nexport const AudioEditor: React.FC<AudioEditorProps> = ({\n  onSwitchMode,\n  onNewProject,\n  backHref,\n  backLinkText,\n  locale,\n  onBack,\n  onOpenCloudProject,\n}) => {\n  const t = useTranslation();\n  const dialog = useDialog();\n  const {\n    audioProjects,\n    tracks,\n    playheadTime,\n    projectDuration,\n    selectedClipIds,\n    editMode,\n    exportModalOpen,\n    undo,\n    redo,\n    addAsset,\n    addClip,\n    addToast,\n    importAudioProject,\n    splitClip,\n    removeSelectedClips,\n    copySelectedClips,\n    cutSelectedClips,\n    pasteClips,\n    nudgeSelectedClips,\n    setLoopToSelection,\n    setEditMode,\n    setExportModalOpen,\n    addRegion,\n    zoom,\n    zoomToSelection,\n    ensureAssetPeaks,\n  } = useAudioStore();\n\n  const [trackControlsWidth] = useState(180);\n  const [timelineWidth, setTimelineWidth] = useState(800);\n  const [dragOver, setDragOver] = useState(false);\n  const [showHelp, setShowHelp] = useState(false);\n  const [isSavingCloud, setIsSavingCloud] = useState(false);\n  const timelineWrapRef = useRef<HTMLDivElement>(null);\n  const fileInputRef = useRef<HTMLInputElement>(null);\n  const projectInputRef = useRef<HTMLInputElement>(null);\n\n  const hasProject = audioProjects.length > 0;\n  const hasClips = tracks.some((t) => t.clips.length > 0);\n\n  useEffect(() => {\n    if (hasProject) ensureAssetPeaks();\n  }, [hasProject, ensureAssetPeaks]);\n\n  useEffect(() => {\n    const el = timelineWrapRef.current;\n    if (!el) return;\n    const ro = new ResizeObserver(() => setTimelineWidth(el.clientWidth));\n    ro.observe(el);\n    setTimelineWidth(el.clientWidth);\n    return () => ro.disconnect();\n  }, [hasProject]);\n\n  useEffect(() => {\n    return () => {\n      getAudioEngine().dispose();\n    };\n  }, []);\n\n  useEffect(() => {\n    const onKey = (e: KeyboardEvent) => {\n      const tag = (e.target as HTMLElement)?.tagName;\n      if (tag === 'INPUT' || tag === 'TEXTAREA' || (e.target as HTMLElement)?.isContentEditable) {\n        return;\n      }\n      if (e.key === '?' || (e.shiftKey && e.key === '/')) {\n        e.preventDefault();\n        setShowHelp((v) => !v);\n        return;\n      }\n      if (e.code === 'Space') {\n        e.preventDefault();\n        document\n          .querySelector<HTMLButtonElement>(\n            '.we-audio-transport button[title=\"Reproducir\"], .we-audio-transport button[title=\"Pausa\"]'\n          )\n          ?.click();\n      }\n      if ((e.metaKey || e.ctrlKey) && e.key === 'z' && !e.shiftKey) {\n        e.preventDefault();\n        undo();\n      }\n      if ((e.metaKey || e.ctrlKey) && (e.key === 'y' || (e.key === 'z' && e.shiftKey))) {\n        e.preventDefault();\n        redo();\n      }\n      if ((e.metaKey || e.ctrlKey) && e.key === 'c') {\n        e.preventDefault();\n        copySelectedClips();\n      }\n      if ((e.metaKey || e.ctrlKey) && e.key === 'x') {\n        e.preventDefault();\n        cutSelectedClips();\n      }\n      if ((e.metaKey || e.ctrlKey) && e.key === 'v') {\n        e.preventDefault();\n        pasteClips();\n      }\n      if (e.key === 's' || e.key === 'S') {\n        const id = selectedClipIds[0];\n        if (id) splitClip(id, playheadTime);\n      }\n      if (e.key === 'Delete' || e.key === 'Backspace') {\n        e.preventDefault();\n        const ids = useAudioStore.getState().selectedClipIds;\n        if (!ids.length) return;\n        void (async () => {\n          const ok = await dialog.confirm(\n            ids.length === 1\n              ? t.audio.editor.deleteClipConfirm\n              : t.audio.editor.deleteClipsConfirm(ids.length),\n            {\n              title: t.audio.editor.deleteConfirmTitle,\n              variant: 'danger',\n              confirmText: t.audio.editor.deleteConfirmBtn,\n              cancelText: t.common.cancel,\n            },\n          );\n          if (ok) removeSelectedClips();\n        })();\n      }\n      if (e.key === 'ArrowLeft') {\n        e.preventDefault();\n        nudgeSelectedClips(e.shiftKey ? -1 : -0.1);\n      }\n      if (e.key === 'ArrowRight') {\n        e.preventDefault();\n        nudgeSelectedClips(e.shiftKey ? 1 : 0.1);\n      }\n      if (e.key === 'l' || e.key === 'L') {\n        setLoopToSelection();\n      }\n      if (e.key === 'r' || e.key === 'R') {\n        setEditMode(editMode === 'ripple' ? 'normal' : 'ripple');\n        addToast(editMode === 'ripple' ? t.audio.editor.toasts.modeNormal : t.audio.editor.toasts.modeRipple, 'info');\n      }\n      if (e.key === 'm' || e.key === 'M') {\n        const state = useAudioStore.getState();\n        const ids = state.selectedClipIds;\n        if (!ids.length) return;\n        let start = Infinity;\n        let end = -Infinity;\n        for (const t2 of state.tracks) {\n          for (const c of t2.clips) {\n            if (!ids.includes(c.id)) continue;\n            start = Math.min(start, c.startTime);\n            end = Math.max(end, c.startTime + c.duration);\n          }\n        }\n        if (Number.isFinite(start) && end > start) {\n          addRegion({\n            id: `reg_${Date.now()}`,\n            startTime: start,\n            endTime: end,\n            name: t.audio.editor.toasts.regionName(state.regions.length + 1),\n          });\n          addToast(t.audio.editor.toasts.regionCreated, 'success');\n        }\n      }\n      if (e.key === 'z' || e.key === 'Z') {\n        if (e.metaKey || e.ctrlKey) return; // undo/redo\n        e.preventDefault();\n        zoomToSelection(timelineWidth || 800);\n      }\n    };\n    window.addEventListener('keydown', onKey);\n    return () => window.removeEventListener('keydown', onKey);\n  }, [\n    undo,\n    redo,\n    selectedClipIds,\n    playheadTime,\n    splitClip,\n    removeSelectedClips,\n    copySelectedClips,\n    cutSelectedClips,\n    pasteClips,\n    nudgeSelectedClips,\n    setLoopToSelection,\n    setEditMode,\n    editMode,\n    addRegion,\n    addToast,\n    zoomToSelection,\n    timelineWidth,\n    dialog,\n    t,\n  ]);\n\n  const importAudioFiles = useCallback(\n    async (files: FileList | File[] | null) => {\n      if (!files?.length) return;\n      const list = Array.from(files);\n      for (const file of list) {\n        if (!file.type.startsWith('audio/') && !/\\.(mp3|wav|ogg|flac|m4a|aac|webm)$/i.test(file.name)) {\n          continue;\n        }\n        try {\n          const buffer = await decodeAudioBlob(file);\n          const peaks = await extractPeaks(buffer);\n          const id = `asset_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;\n          const url = URL.createObjectURL(file);\n          addAsset({\n            id,\n            name: file.name,\n            url,\n            duration: buffer.duration,\n            sampleRate: buffer.sampleRate,\n            channels: buffer.numberOfChannels,\n            file,\n            peaks: peaks.peaks,\n            peaksSampleRate: peaks.peaksSampleRate,\n          });\n          const trackId = useAudioStore.getState().tracks[0]?.id;\n          if (trackId) {\n            addClip(\n              createAudioClip({\n                trackId,\n                assetId: id,\n                startTime: useAudioStore.getState().playheadTime,\n                duration: buffer.duration,\n                name: file.name,\n              })\n            );\n          }\n        } catch {\n          addToast(t.audio.editor.toasts.importFailed(file.name), 'error');\n        }\n      }\n    },\n    [addAsset, addClip, addToast, t]\n  );\n\n  const saveLocal = async () => {\n    const state = useAudioStore.getState();\n    const name =\n      state.audioProjects.find((p) => p.id === state.activeAudioProjectId)?.name || 'audio';\n    const blob = await exportProjectToWzrda({\n      name,\n      sampleRate: state.sampleRate,\n      bpm: state.bpm,\n      timeSignature: state.timeSignature,\n      tracks: state.tracks,\n      markers: state.markers,\n      regions: state.regions,\n      assets: state.assets,\n      projectDuration: state.projectDuration,\n    });\n    const a = document.createElement('a');\n    a.href = URL.createObjectURL(blob);\n    a.download = `${name}.kaia`;\n    a.click();\n    URL.revokeObjectURL(a.href);\n  };\n\n  const openProject = async (file: File) => {\n    try {\n      const data = await importProjectFromWzrda(file);\n      importAudioProject(data, file.name);\n      addToast(t.audio.editor.toasts.projectOpened, 'success');\n    } catch {\n      try {\n        const text = await file.text();\n        const data = JSON.parse(text);\n        importAudioProject(data, file.name);\n        addToast(t.audio.editor.toasts.projectOpened, 'success');\n      } catch {\n        addToast(t.audio.editor.toasts.projectInvalid, 'error');\n      }\n    }\n  };\n\n  const saveToCloud = async () => {\n    if (isSavingCloud) return;\n    setIsSavingCloud(true);\n    try {\n      await uploadCurrentProjectToCloudWithToast('audio');\n    } catch {\n      // Error toast is already shown and stays until the user closes it.\n    } finally {\n      setIsSavingCloud(false);\n    }\n  };\n\n  const shellHeader = (\n    <EditorShellHeader\n      mode=\"audio\"\n      onBack={onBack}\n      backHref={backHref}\n      backLabel={backLinkText}\n      onSwitchMode={(m) => onSwitchMode?.(m)}\n      onNewProject={onNewProject}\n      newProjectTitle={t.editor.newProject.audio}\n      onExport={hasProject ? () => setExportModalOpen(true) : undefined}\n      exportDisabled={!hasProject}\n      fileMenu={\n        <ShellFileMenu\n          onNew={onNewProject}\n          onOpen={() => projectInputRef.current?.click()}\n          onSave={hasProject ? () => void saveLocal() : undefined}\n          onSaveToCloud={hasProject ? () => void saveToCloud() : undefined}\n          isSavingCloud={isSavingCloud}\n        />\n      }\n      tabs={<ModeProjectTabs mode=\"audio\" />}\n    />\n  );\n\n  if (!hasProject) {\n    return (\n      <I18nProvider locale={locale}>\n      <div\n        data-we-mode=\"audio\"\n        style={modeAccentVars('audio')}\n        className=\"relative flex flex-col h-full w-full bg-[#0A0A0F]\"\n      >\n        {shellHeader}\n        <div className=\"flex-1 min-h-0 relative\">\n          <EditorEmptyState\n            mode=\"Audio\"\n            onCreate={onNewProject ?? (() => {})}\n            onOpenCloud={onOpenCloudProject ?? (() => {})}\n          />\n        </div>\n      </div>\n      </I18nProvider>\n    );\n  }\n\n  return (\n    <I18nProvider locale={locale}>\n    <div\n      data-we-mode=\"audio\"\n      style={modeAccentVars('audio')}\n      className=\"we-audio-editor relative flex h-full w-full flex-col bg-[#0A0A0F] text-[#F0F0F5]\"\n    >\n      {shellHeader}\n\n      <div className=\"relative flex min-h-0 flex-1 flex-col\">\n        <div className=\"flex min-h-0 w-full flex-1\">\n          <div className=\"relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden\">\n            <AudioTimelineToolbar />\n            <div\n              className={`relative flex min-h-0 flex-1 border-b border-panel-border ${dragOver ? 'ring-2 ring-inset ring-[var(--we-accent)]' : ''}`}\n              onDragOver={(e) => {\n                e.preventDefault();\n                setDragOver(true);\n              }}\n              onDragLeave={() => setDragOver(false)}\n              onDrop={(e) => {\n                e.preventDefault();\n                setDragOver(false);\n                void importAudioFiles(e.dataTransfer.files);\n              }}\n            >\n              <AudioTrackControls width={trackControlsWidth} />\n              <div\n                ref={timelineWrapRef}\n                className=\"relative z-10 min-w-0 flex-1 overflow-x-auto overflow-y-hidden\"\n              >\n                <AudioTimeline\n                  width={Math.max(timelineWidth, projectDuration * zoom + 400)}\n                  height={2000}\n                  onImportLocal={() => fileInputRef.current?.click()}\n                  onOpenMyFiles={() => {\n                    useAudioUiStore.getState().setLibraryTab('myFiles');\n                    useAudioUiStore.getState().setRightPanel(null);\n                  }}\n                />\n                {!hasClips && (\n                  <div className=\"pointer-events-none absolute inset-0 z-10 flex flex-col items-center justify-center bg-[#0A0A0F]/70\">\n                    <Upload size={28} className=\"mb-2 text-[var(--we-accent)]\" />\n                    <TextBody as=\"p\" size=\"sm\" className=\" text-white\">\n                      {t.audio.editor.dragHere}\n                    </TextBody>\n                    <TextBody as=\"p\" size=\"sm\" className=\"mt-1 text-white/80\">\n                      {t.audio.editor.dragFormatHint}\n                    </TextBody>\n                    <button\n                      type=\"button\"\n                      className=\"pointer-events-auto mt-3 h-8 rounded-lg bg-[var(--we-accent)] px-3 font-sans font-bold text-white hover:bg-[var(--we-accent-hover)]\"\n                      onClick={() => fileInputRef.current?.click()}\n                    >\n                      {t.audio.editor.chooseFiles}\n                    </button>\n                  </div>\n                )}\n                {dragOver && (\n                  <div className=\"pointer-events-none absolute inset-0 z-20 flex items-center justify-center border-2 border-dashed border-[var(--we-accent)] bg-[var(--we-accent-muted)]\">\n                    <TextBody as=\"span\" size=\"sm\" className=\" text-white\">\n                      {t.audio.editor.dropToImport}\n                    </TextBody>\n                  </div>\n                )}\n              </div>\n            </div>\n          </div>\n\n          <AudioRightSidebar onImportFiles={() => fileInputRef.current?.click()} />\n        </div>\n\n        <AudioBottomToolbar />\n      </div>\n\n      <input\n        ref={fileInputRef}\n        type=\"file\"\n        accept=\"audio/*,.mp3,.wav,.ogg,.flac,.m4a,.aac\"\n        multiple\n        className=\"hidden\"\n        onChange={(e) => void importAudioFiles(e.target.files)}\n      />\n      <input\n        ref={projectInputRef}\n        type=\"file\"\n        accept={projectAccept('audio', ['application/json'])}\n        className=\"hidden\"\n        onChange={(e) => {\n          const f = e.target.files?.[0];\n          if (f) void openProject(f);\n        }}\n      />\n\n      <AudioExportModal\n        open={exportModalOpen}\n        onClose={() => setExportModalOpen(false)}\n      />\n\n      <Modal\n        isOpen={showHelp}\n        onClose={() => setShowHelp(false)}\n        title={t.audio.editor.shortcutsTitle}\n        size=\"md\"\n      >\n        <ul className=\"space-y-1.5\">\n          {audioShortcutKeys().map((s) => (\n            <li key={s.keys} className=\"flex justify-between gap-3 font-sans font-medium\">\n              <kbd className=\"shrink-0 font-mono text-[var(--we-accent)]\">{s.keys}</kbd>\n              <span className=\"select-none text-right text-white/80\">\n                {t.audio.editor.shortcuts[s.descKey]}\n              </span>\n            </li>\n          ))}\n        </ul>\n        <div className=\"mt-4 flex justify-end\">\n          <Button variant=\"ghost\" onClick={() => setShowHelp(false)}>\n            {t.audio.editor.shortcutsClose}\n          </Button>\n        </div>\n      </Modal>\n\n      <AudioToasts />\n    </div>\n    </I18nProvider>\n  );\n};\n\nfunction AudioToasts() {\n  const { toasts, removeToast } = useAudioStore();\n  return (\n    <div className=\"fixed bottom-4 right-20 z-[90] flex flex-col gap-2\">\n      {toasts.map((t) => (\n        <div\n          key={t.id}\n          onClick={() => removeToast(t.id)}\n          className={`px-3 py-2 rounded-lg shadow-lg cursor-pointer ${\n            t.type === 'error'\n              ? 'bg-red-500/90 text-white'\n              : t.type === 'success'\n                ? 'bg-[#00BFA5]/90 text-white'\n                : t.type === 'warning'\n                  ? 'bg-[#FFD54F]/90 text-black'\n                  : 'bg-[#1C1C26] text-[#F0F0F5] border border-[#2A2A38]'\n          }`}\n        >\n          {t.message}\n        </div>\n      ))}\n    </div>\n  );\n}\n\nexport default AudioEditor;\n", "/**\n * TipTap mark for AI suggestions (accept / reject inline diffs).\n */\n\nimport { Mark, mergeAttributes } from '@tiptap/core';\n\nexport interface AiSuggestionAttrs {\n  id: string;\n  kind: string;\n  original: string;\n  replacement: string;\n  rationale: string;\n}\n\ndeclare module '@tiptap/core' {\n  interface Commands<ReturnType> {\n    aiSuggestion: {\n      setAiSuggestion: (attrs: Partial<AiSuggestionAttrs>) => ReturnType;\n      unsetAiSuggestion: () => ReturnType;\n    };\n  }\n}\n\nexport const AiSuggestion = Mark.create({\n  name: 'aiSuggestion',\n\n  addAttributes() {\n    return {\n      id: { default: null },\n      kind: { default: 'rewrite' },\n      original: { default: '' },\n      replacement: { default: '' },\n      rationale: { default: '' },\n    };\n  },\n\n  parseHTML() {\n    return [{ tag: 'span[data-ai-suggestion]' }];\n  },\n\n  renderHTML({ HTMLAttributes }) {\n    return [\n      'span',\n      mergeAttributes(HTMLAttributes, {\n        'data-ai-suggestion': HTMLAttributes.id || '',\n        class: 'we-ai-suggestion',\n        style:\n          'background: rgba(108,99,255,0.25); border-bottom: 2px solid #6C63FF; border-radius: 2px;',\n      }),\n      0,\n    ];\n  },\n\n  addCommands() {\n    return {\n      setAiSuggestion:\n        (attrs) =>\n        ({ commands }) =>\n          commands.setMark(this.name, attrs),\n      unsetAiSuggestion:\n        () =>\n        ({ commands }) =>\n          commands.unsetMark(this.name),\n    };\n  },\n});\n", "/**\n * TipTip mark for claim / source comments (needs citation).\n */\n\nimport { Mark, mergeAttributes } from '@tiptap/core';\n\ndeclare module '@tiptap/core' {\n  interface Commands<ReturnType> {\n    commentMark: {\n      setCommentMark: (attrs: { id?: string; note?: string }) => ReturnType;\n      unsetCommentMark: () => ReturnType;\n    };\n  }\n}\n\nexport const CommentMark = Mark.create({\n  name: 'commentMark',\n\n  addAttributes() {\n    return {\n      id: { default: null },\n      note: { default: '' },\n    };\n  },\n\n  parseHTML() {\n    return [{ tag: 'span[data-comment-mark]' }];\n  },\n\n  renderHTML({ HTMLAttributes }) {\n    return [\n      'span',\n      mergeAttributes(HTMLAttributes, {\n        'data-comment-mark': HTMLAttributes.id || '',\n        class: 'we-comment-mark',\n        style:\n          'background: rgba(255,213,79,0.2); border-bottom: 2px dashed #FFD54F; cursor: help;',\n        title: HTMLAttributes.note || 'Requiere fuente o dato',\n      }),\n      0,\n    ];\n  },\n\n  addCommands() {\n    return {\n      setCommentMark:\n        (attrs) =>\n        ({ commands }) =>\n          commands.setMark(this.name, attrs),\n      unsetCommentMark:\n        () =>\n        ({ commands }) =>\n          commands.unsetMark(this.name),\n    };\n  },\n});\n", "import { Node, mergeAttributes } from '@tiptap/core';\n\ndeclare module '@tiptap/core' {\n  interface Commands<ReturnType> {\n    callout: {\n      setCallout: () => ReturnType;\n    };\n  }\n}\n\nexport const Callout = Node.create({\n  name: 'callout',\n  group: 'block',\n  content: 'block+',\n  defining: true,\n\n  addOptions() {\n    return {\n      defaultText: 'Nota destacada',\n    };\n  },\n\n  parseHTML() {\n    return [{ tag: 'aside[data-callout]' }];\n  },\n\n  renderHTML({ HTMLAttributes }) {\n    return [\n      'aside',\n      mergeAttributes(HTMLAttributes, {\n        'data-callout': 'true',\n        class: 'we-callout',\n        style:\n          'border-left: 3px solid #6C63FF; background: rgba(108,99,255,0.08); padding: 0.75rem 1rem; margin: 0.75rem 0; border-radius: 0 6px 6px 0;',\n      }),\n      0,\n    ];\n  },\n\n  addCommands() {\n    return {\n      setCallout:\n        () =>\n        ({ commands }) =>\n          commands.insertContent({\n            type: this.name,\n            content: [\n              {\n                type: 'paragraph',\n                content: [{ type: 'text', text: this.options.defaultText }],\n              },\n            ],\n          }),\n    };\n  },\n});\n", "import { Mark, mergeAttributes } from '@tiptap/core';\n\ndeclare module '@tiptap/core' {\n  interface Commands<ReturnType> {\n    footnote: {\n      setFootnote: (attrs?: { note?: string }) => ReturnType;\n      unsetFootnote: () => ReturnType;\n    };\n  }\n}\n\nexport const Footnote = Mark.create({\n  name: 'footnote',\n\n  addAttributes() {\n    return {\n      note: { default: '' },\n    };\n  },\n\n  parseHTML() {\n    return [{ tag: 'sup[data-footnote]' }];\n  },\n\n  renderHTML({ HTMLAttributes }) {\n    return [\n      'sup',\n      mergeAttributes(HTMLAttributes, {\n        'data-footnote': 'true',\n        class: 'we-footnote',\n        style: 'color: #6C63FF; cursor: help; font-size: 0.75em;',\n        title: HTMLAttributes.note || 'Nota al pie',\n      }),\n      0,\n    ];\n  },\n\n  addCommands() {\n    return {\n      setFootnote:\n        (attrs) =>\n        ({ commands }) =>\n          commands.setMark(this.name, attrs || {}),\n      unsetFootnote:\n        () =>\n        ({ commands }) =>\n          commands.unsetMark(this.name),\n    };\n  },\n});\n", "/**\n * Decorate forbidden (red) and preferred (green) brand terms in the document.\n */\n\nimport { Extension } from '@tiptap/core';\nimport { Plugin, PluginKey } from '@tiptap/pm/state';\nimport { Decoration, DecorationSet } from '@tiptap/pm/view';\nimport { useTextStore } from '../../../store/useTextStore';\n\nconst key = new PluginKey('brandHighlight');\n\nfunction buildDecorations(doc: import('@tiptap/pm/model').Node) {\n  const brand = useTextStore.getState().brandVoice;\n  const forbidden = brand.forbiddenTerms.filter(Boolean);\n  const preferred = brand.preferredTerms.filter(Boolean);\n  if (!forbidden.length && !preferred.length) return DecorationSet.empty;\n\n  const decorations: import('@tiptap/pm/view').Decoration[] = [];\n\n  doc.descendants((node, pos) => {\n    if (!node.isText || !node.text) return true;\n    const text = node.text;\n    const lower = text.toLowerCase();\n\n    const scan = (terms: string[], className: string, style: string) => {\n      for (const term of terms) {\n        const t = term.toLowerCase();\n        if (!t) continue;\n        let from = 0;\n        while (from < lower.length) {\n          const idx = lower.indexOf(t, from);\n          if (idx < 0) break;\n          decorations.push(\n            Decoration.inline(pos + idx, pos + idx + t.length, {\n              class: className,\n              style,\n            })\n          );\n          from = idx + t.length;\n        }\n      }\n    };\n\n    scan(\n      forbidden,\n      'we-brand-forbidden',\n      'background: rgba(255,64,129,0.22); border-bottom: 1px solid #FF4081;'\n    );\n    scan(\n      preferred,\n      'we-brand-preferred',\n      'background: rgba(0,191,165,0.15); border-bottom: 1px solid #00BFA5;'\n    );\n    return true;\n  });\n\n  return DecorationSet.create(doc, decorations);\n}\n\nexport const BrandHighlight = Extension.create({\n  name: 'brandHighlight',\n\n  addProseMirrorPlugins() {\n    return [\n      new Plugin({\n        key,\n        state: {\n          init: (_, state) => buildDecorations(state.doc),\n          apply: (tr, old, _oldState, newState) => {\n            // Rebuild when doc changes or brand meta is forced\n            if (tr.docChanged || tr.getMeta('brandHighlight')) {\n              return buildDecorations(newState.doc);\n            }\n            return old;\n          },\n        },\n        props: {\n          decorations(state) {\n            return key.getState(state);\n          },\n        },\n      }),\n    ];\n  },\n});\n\n/** Call after brandVoice preferred/forbidden edits to refresh decorations. */\nexport function refreshBrandHighlights(editor: import('@tiptap/core').Editor | null) {\n  if (!editor) return;\n  const { tr } = editor.state;\n  tr.setMeta('brandHighlight', true);\n  editor.view.dispatch(tr);\n}\n", "/**\n * TipTap slash-command suggestion extension (/h2, /table, /rewrite\u2026).\n */\n\nimport { Extension } from '@tiptap/core';\nimport { PluginKey } from '@tiptap/pm/state';\nimport Suggestion, { type SuggestionOptions } from '@tiptap/suggestion';\nimport { computePosition, flip, shift, offset } from '@floating-ui/dom';\n\nexport type SlashItem = {\n  title: string;\n  description: string;\n  command: (props: { editor: import('@tiptap/core').Editor; range: { from: number; to: number } }) => void;\n};\n\nexport function buildSlashItems(\n  onAiOp?: (op: 'rewrite' | 'tighten' | 'expand' | 'claim' | 'comment') => void,\n  labels?: { calloutTitle?: string; calloutDescription?: string }\n): SlashItem[] {\n  return [\n    {\n      title: 'Titulo H1',\n      description: 'Encabezado principal',\n      command: ({ editor, range }) => {\n        editor.chain().focus().deleteRange(range).setNode('heading', { level: 1 }).run();\n      },\n    },\n    {\n      title: 'Titulo H2',\n      description: 'Seccion',\n      command: ({ editor, range }) => {\n        editor.chain().focus().deleteRange(range).setNode('heading', { level: 2 }).run();\n      },\n    },\n    {\n      title: 'Titulo H3',\n      description: 'Subseccion',\n      command: ({ editor, range }) => {\n        editor.chain().focus().deleteRange(range).setNode('heading', { level: 3 }).run();\n      },\n    },\n    {\n      title: 'Titulo H4',\n      description: 'Sub-subseccion',\n      command: ({ editor, range }) => {\n        editor.chain().focus().deleteRange(range).setNode('heading', { level: 4 }).run();\n      },\n    },\n    {\n      title: 'Tabla',\n      description: 'Insertar tabla 3x3',\n      command: ({ editor, range }) => {\n        editor\n          .chain()\n          .focus()\n          .deleteRange(range)\n          .insertTable({ rows: 3, cols: 3, withHeaderRow: true })\n          .run();\n      },\n    },\n    {\n      title: labels?.calloutTitle ?? 'Destacado',\n      description: labels?.calloutDescription ?? 'Bloque destacado',\n      command: ({ editor, range }) => {\n        editor.chain().focus().deleteRange(range).setCallout().run();\n      },\n    },\n    {\n      title: 'Nota al pie',\n      description: 'Marca footnote en la seleccion',\n      command: ({ editor, range }) => {\n        editor.chain().focus().deleteRange(range).run();\n        const note = window.prompt('Texto de la nota al pie:') || 'Nota';\n        const { from, to } = editor.state.selection;\n        if (from === to) {\n          editor\n            .chain()\n            .focus()\n            .insertContent({\n              type: 'text',\n              text: '[nota]',\n              marks: [{ type: 'footnote', attrs: { note } }],\n            })\n            .run();\n        } else {\n          editor.chain().focus().setFootnote({ note }).run();\n        }\n      },\n    },\n    {\n      title: 'CTA',\n      description: 'Parrafo de llamada a la accion',\n      command: ({ editor, range }) => {\n        editor\n          .chain()\n          .focus()\n          .deleteRange(range)\n          .insertContent({\n            type: 'paragraph',\n            content: [\n              {\n                type: 'text',\n                marks: [{ type: 'bold' }],\n                text: 'CTA: ',\n              },\n              { type: 'text', text: 'Describe la accion que quieres que haga el lector.' },\n            ],\n          })\n          .run();\n      },\n    },\n    {\n      title: 'Reescribir',\n      description: 'IA: rewrite seleccion',\n      command: ({ editor, range }) => {\n        editor.chain().focus().deleteRange(range).run();\n        onAiOp?.('rewrite');\n      },\n    },\n    {\n      title: 'Compactar',\n      description: 'IA: tighten',\n      command: ({ editor, range }) => {\n        editor.chain().focus().deleteRange(range).run();\n        onAiOp?.('tighten');\n      },\n    },\n    {\n      title: 'Expandir',\n      description: 'IA: expand',\n      command: ({ editor, range }) => {\n        editor.chain().focus().deleteRange(range).run();\n        onAiOp?.('expand');\n      },\n    },\n    {\n      title: 'Claim',\n      description: 'Marcar afirmacion',\n      command: ({ editor, range }) => {\n        editor.chain().focus().deleteRange(range).run();\n        onAiOp?.('claim');\n      },\n    },\n    {\n      title: 'Comentario',\n      description: 'Anadir comentario local',\n      command: ({ editor, range }) => {\n        editor.chain().focus().deleteRange(range).run();\n        onAiOp?.('comment');\n      },\n    },\n  ];\n}\n\nfunction renderSlashMenu(): SuggestionOptions<SlashItem>['render'] {\n  return () => {\n    let popup: HTMLDivElement | null = null;\n    let selected = 0;\n    let items: SlashItem[] = [];\n    let command: ((item: SlashItem) => void) | null = null;\n\n    const redraw = () => {\n      if (!popup) return;\n      popup.innerHTML = '';\n      items.forEach((item, i) => {\n        const row = document.createElement('button');\n        row.type = 'button';\n        row.className = 'we-slash-item';\n        row.style.cssText = `display:block;width:100%;text-align:left;padding:6px 10px;border:0;background:${\n          i === selected ? '#6C63FF' : 'transparent'\n        };color:${i === selected ? '#fff' : '#C8C8D8'};cursor:pointer;font-size:11px;`;\n        row.innerHTML = `<div style=\"font-weight:700\">${item.title}</div><div style=\"opacity:.7;font-size:10px\">${item.description}</div>`;\n        row.onmousedown = (e) => {\n          e.preventDefault();\n          command?.(item);\n        };\n        popup!.appendChild(row);\n      });\n    };\n\n    return {\n      onStart: (props) => {\n        items = props.items;\n        command = props.command;\n        selected = 0;\n        popup = document.createElement('div');\n        popup.className = 'we-slash-menu';\n        popup.style.cssText =\n          'z-index:80;min-width:220px;max-height:280px;overflow:auto;border:1px solid #2A2A38;border-radius:8px;background:#14141E;box-shadow:0 8px 24px rgba(0,0,0,.45);position:fixed;left:0;top:0;';\n        document.body.appendChild(popup);\n        redraw();\n        const rect = props.clientRect?.();\n        if (rect && popup) {\n          void computePosition(\n            {\n              getBoundingClientRect: () => rect,\n            } as Element,\n            popup,\n            {\n              placement: 'bottom-start',\n              strategy: 'fixed',\n              middleware: [offset(6), flip(), shift({ padding: 8 })],\n            }\n          ).then(({ x, y }) => {\n            if (!popup) return;\n            Object.assign(popup.style, {\n              left: `${x}px`,\n              top: `${y}px`,\n            });\n          });\n        }\n      },\n      onUpdate: (props) => {\n        items = props.items;\n        command = props.command;\n        selected = 0;\n        redraw();\n        const rect = props.clientRect?.();\n        if (rect && popup) {\n          void computePosition(\n            { getBoundingClientRect: () => rect } as Element,\n            popup,\n            {\n              placement: 'bottom-start',\n              strategy: 'fixed',\n              middleware: [offset(6), flip(), shift({ padding: 8 })],\n            }\n          ).then(({ x, y }) => {\n            if (!popup) return;\n            Object.assign(popup.style, { left: `${x}px`, top: `${y}px` });\n          });\n        }\n      },\n      onKeyDown: (props) => {\n        if (props.event.key === 'ArrowDown') {\n          selected = (selected + 1) % Math.max(1, items.length);\n          redraw();\n          return true;\n        }\n        if (props.event.key === 'ArrowUp') {\n          selected = (selected - 1 + items.length) % Math.max(1, items.length);\n          redraw();\n          return true;\n        }\n        if (props.event.key === 'Enter') {\n          const item = items[selected];\n          if (item) command?.(item);\n          return true;\n        }\n        if (props.event.key === 'Escape') {\n          popup?.remove();\n          popup = null;\n          return true;\n        }\n        return false;\n      },\n      onExit: () => {\n        popup?.remove();\n        popup = null;\n      },\n    };\n  };\n}\n\nexport function createSlashCommandExtension(\n  onAiOp?: (op: 'rewrite' | 'tighten' | 'expand' | 'claim' | 'comment') => void,\n  labels?: { calloutTitle?: string; calloutDescription?: string }\n) {\n  const items = buildSlashItems(onAiOp, labels);\n  return Extension.create({\n    name: 'slashCommand',\n    addProseMirrorPlugins() {\n      return [\n        Suggestion({\n          editor: this.editor,\n          char: '/',\n          pluginKey: new PluginKey('slashCommand'),\n          items: ({ query }) => {\n            const q = query.toLowerCase();\n            return items.filter(\n              (i) =>\n                i.title.toLowerCase().includes(q) ||\n                i.description.toLowerCase().includes(q)\n            );\n          },\n          command: ({ editor, range, props }) => {\n            props.command({ editor, range });\n          },\n          render: renderSlashMenu(),\n        }),\n      ];\n    },\n  });\n}\n", "import React, { useCallback, useRef } from 'react';\nimport Image from '@tiptap/extension-image';\nimport { NodeViewWrapper, ReactNodeViewRenderer, type NodeViewProps } from '@tiptap/react';\nimport { mergeAttributes } from '@tiptap/core';\n\ndeclare module '@tiptap/core' {\n  interface Commands<ReturnType> {\n    resizableImage: {\n      setImage: (options: {\n        src: string;\n        alt?: string;\n        title?: string;\n        width?: number | string | null;\n        height?: number | string | null;\n      }) => ReturnType;\n    };\n  }\n}\n\nfunction ResizableImageView({ node, updateAttributes, selected }: NodeViewProps) {\n  const imgRef = useRef<HTMLImageElement>(null);\n  const startRef = useRef<{ x: number; w: number } | null>(null);\n\n  const width = node.attrs.width as number | string | null;\n  const height = node.attrs.height as number | string | null;\n\n  const onPointerDown = useCallback(\n    (e: React.PointerEvent) => {\n      e.preventDefault();\n      e.stopPropagation();\n      const el = imgRef.current;\n      if (!el) return;\n      const startW = el.getBoundingClientRect().width;\n      startRef.current = { x: e.clientX, w: startW };\n      (e.target as HTMLElement).setPointerCapture(e.pointerId);\n\n      const onMove = (ev: PointerEvent) => {\n        const start = startRef.current;\n        if (!start) return;\n        const next = Math.max(80, Math.min(900, Math.round(start.w + (ev.clientX - start.x))));\n        updateAttributes({ width: next, height: null });\n      };\n      const onUp = (ev: PointerEvent) => {\n        startRef.current = null;\n        window.removeEventListener('pointermove', onMove);\n        window.removeEventListener('pointerup', onUp);\n        try {\n          (ev.target as HTMLElement).releasePointerCapture(ev.pointerId);\n        } catch {\n          /* ignore */\n        }\n      };\n      window.addEventListener('pointermove', onMove);\n      window.addEventListener('pointerup', onUp);\n    },\n    [updateAttributes],\n  );\n\n  return (\n    <NodeViewWrapper\n      as=\"figure\"\n      className={`we-resizable-image relative my-3 inline-block max-w-full ${\n        selected ? 'ring-2 ring-[var(--we-accent)] ring-offset-2 ring-offset-white' : ''\n      }`}\n      data-drag-handle\n    >\n      <img\n        ref={imgRef}\n        src={node.attrs.src as string}\n        alt={(node.attrs.alt as string) || ''}\n        title={(node.attrs.title as string) || undefined}\n        className=\"block h-auto max-w-full rounded-md\"\n        style={{\n          width: width ? (typeof width === 'number' ? `${width}px` : String(width)) : undefined,\n          height: height ? (typeof height === 'number' ? `${height}px` : String(height)) : 'auto',\n        }}\n        draggable={false}\n      />\n      {selected && (\n        <button\n          type=\"button\"\n          aria-label=\"Resize image\"\n          onPointerDown={onPointerDown}\n          className=\"absolute bottom-1 right-1 z-10 h-3.5 w-3.5 cursor-nwse-resize rounded-sm border-2 border-white bg-[var(--we-accent)] shadow\"\n        />\n      )}\n    </NodeViewWrapper>\n  );\n}\n\n/** TipTap Image with width/height attrs + corner drag handle when selected. */\nexport const ResizableImage = Image.extend({\n  name: 'image',\n\n  addAttributes() {\n    return {\n      ...this.parent?.(),\n      width: {\n        default: null,\n        parseHTML: (el) => {\n          const w = (el as HTMLElement).getAttribute('width') || (el as HTMLElement).style.width;\n          if (!w) return null;\n          const n = parseInt(w, 10);\n          return Number.isFinite(n) ? n : w;\n        },\n        renderHTML: (attrs) => {\n          if (!attrs.width) return {};\n          const w = typeof attrs.width === 'number' ? `${attrs.width}` : String(attrs.width);\n          return { width: w, style: `width: ${typeof attrs.width === 'number' ? `${attrs.width}px` : attrs.width}` };\n        },\n      },\n      height: {\n        default: null,\n        parseHTML: (el) => {\n          const h = (el as HTMLElement).getAttribute('height') || (el as HTMLElement).style.height;\n          if (!h) return null;\n          const n = parseInt(h, 10);\n          return Number.isFinite(n) ? n : h;\n        },\n        renderHTML: (attrs) => {\n          if (!attrs.height) return {};\n          return {\n            height: String(attrs.height),\n          };\n        },\n      },\n    };\n  },\n\n  renderHTML({ HTMLAttributes }) {\n    return ['img', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)];\n  },\n\n  addNodeView() {\n    return ReactNodeViewRenderer(ResizableImageView);\n  },\n}).configure({\n  allowBase64: true,\n  inline: false,\n});\n", "/**\n * Paragraph / heading indent via margin-left (list sink/lift when in a list).\n */\n\nimport { Extension } from '@tiptap/core';\n\ndeclare module '@tiptap/core' {\n  interface Commands<ReturnType> {\n    indent: {\n      indent: () => ReturnType;\n      outdent: () => ReturnType;\n    };\n  }\n}\n\nconst INDENT_TYPES = ['paragraph', 'heading'] as const;\nconst MAX_INDENT = 8;\nconst INDENT_PX = 24;\n\nexport const Indent = Extension.create({\n  name: 'indent',\n\n  addGlobalAttributes() {\n    return [\n      {\n        types: [...INDENT_TYPES],\n        attributes: {\n          indent: {\n            default: 0,\n            parseHTML: (el) => {\n              const raw = el.getAttribute('data-indent');\n              const n = raw ? parseInt(raw, 10) : 0;\n              return Number.isFinite(n) ? Math.max(0, Math.min(MAX_INDENT, n)) : 0;\n            },\n            renderHTML: (attrs) => {\n              const level = Number(attrs.indent) || 0;\n              if (level <= 0) return {};\n              return {\n                'data-indent': String(level),\n                style: `margin-left: ${level * INDENT_PX}px`,\n              };\n            },\n          },\n        },\n      },\n    ];\n  },\n\n  addCommands() {\n    return {\n      indent:\n        () =>\n        ({ editor, chain, state, commands }) => {\n          if (editor.can().sinkListItem('listItem')) {\n            return chain().focus().sinkListItem('listItem').run();\n          }\n          const { $from } = state.selection;\n          const type = $from.parent.type.name;\n          if (!INDENT_TYPES.includes(type as (typeof INDENT_TYPES)[number])) return false;\n          const cur = Number($from.parent.attrs.indent) || 0;\n          return commands.updateAttributes(type, { indent: Math.min(MAX_INDENT, cur + 1) });\n        },\n      outdent:\n        () =>\n        ({ editor, chain, state, commands }) => {\n          if (editor.can().liftListItem('listItem')) {\n            return chain().focus().liftListItem('listItem').run();\n          }\n          const { $from } = state.selection;\n          const type = $from.parent.type.name;\n          if (!INDENT_TYPES.includes(type as (typeof INDENT_TYPES)[number])) return false;\n          const cur = Number($from.parent.attrs.indent) || 0;\n          return commands.updateAttributes(type, { indent: Math.max(0, cur - 1) });\n        },\n    };\n  },\n});\n", "/**\n * Italic mark that only uses _text_ (WhatsApp-style).\n * StarterKit italic also maps *text* \u2192 italic; WhatsApp uses * for bold, so we\n * disable StarterKit italic and register this instead.\n */\n\nimport { Mark, markInputRule, markPasteRule, mergeAttributes } from '@tiptap/core';\n\nconst underscoreInputRegex = /(?:^|\\s)(_(?!\\s+_)((?:[^_]+))_(?!\\s+_))$/;\nconst underscorePasteRegex = /(?:^|\\s)(_(?!\\s+_)((?:[^_]+))_(?!\\s+_))/g;\n\nexport const UnderscoreItalic = Mark.create({\n  name: 'italic',\n\n  addOptions() {\n    return { HTMLAttributes: {} };\n  },\n\n  parseHTML() {\n    return [\n      { tag: 'em' },\n      {\n        tag: 'i',\n        getAttrs: (node) =>\n          (node as HTMLElement).style.fontStyle !== 'normal' && null,\n      },\n      {\n        style: 'font-style=normal',\n        clearMark: (mark) => mark.type.name === this.name,\n      },\n      { style: 'font-style=italic' },\n    ];\n  },\n\n  renderHTML({ HTMLAttributes }) {\n    return ['em', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];\n  },\n\n  addCommands() {\n    return {\n      setItalic:\n        () =>\n        ({ commands }) =>\n          commands.setMark(this.name),\n      toggleItalic:\n        () =>\n        ({ commands }) =>\n          commands.toggleMark(this.name),\n      unsetItalic:\n        () =>\n        ({ commands }) =>\n          commands.unsetMark(this.name),\n    };\n  },\n\n  addKeyboardShortcuts() {\n    return {\n      'Mod-i': () => this.editor.commands.toggleItalic(),\n      'Mod-I': () => this.editor.commands.toggleItalic(),\n    };\n  },\n\n  addInputRules() {\n    return [\n      markInputRule({ find: underscoreInputRegex, type: this.type }),\n    ];\n  },\n\n  addPasteRules() {\n    return [\n      markPasteRule({ find: underscorePasteRegex, type: this.type }),\n    ];\n  },\n});\n", "/**\n * WhatsApp-style inline formatting input/paste rules:\n *   *bold*   \u2192 bold   (also keeps StarterKit **bold**)\n *   ~strike~ \u2192 strike (also keeps StarterKit ~~strike~~)\n *   _italic_ \u2192 handled by UnderscoreItalic\n *   `code`   \u2192 handled by StarterKit Code\n * Lists (- / 1.) and quotes (>) \u2192 StarterKit wrapping rules\n */\n\nimport { Extension, markInputRule, markPasteRule } from '@tiptap/core';\n\n/** Single *\u2026* that is not part of **\u2026** */\nconst waBoldInput = /(?:^|\\s)(\\*(?!\\*)(?!\\s+\\*)((?:[^*]+))\\*(?!\\*))$/;\nconst waBoldPaste = /(?:^|\\s)(\\*(?!\\*)(?!\\s+\\*)((?:[^*]+))\\*(?!\\*))/g;\n\n/** Single ~\u2026~ that is not part of ~~\u2026~~ */\nconst waStrikeInput = /(?:^|\\s)(~(?!~)(?!\\s+~)((?:[^~]+))~(?!~))$/;\nconst waStrikePaste = /(?:^|\\s)(~(?!~)(?!\\s+~)((?:[^~]+))~(?!~))/g;\n\nexport const WhatsAppFormatting = Extension.create({\n  name: 'whatsappFormatting',\n\n  addInputRules() {\n    const bold = this.editor.schema.marks.bold;\n    const strike = this.editor.schema.marks.strike;\n    if (!bold || !strike) return [];\n    return [\n      markInputRule({ find: waBoldInput, type: bold }),\n      markInputRule({ find: waStrikeInput, type: strike }),\n    ];\n  },\n\n  addPasteRules() {\n    const bold = this.editor.schema.marks.bold;\n    const strike = this.editor.schema.marks.strike;\n    if (!bold || !strike) return [];\n    return [\n      markPasteRule({ find: waBoldPaste, type: bold }),\n      markPasteRule({ find: waStrikePaste, type: strike }),\n    ];\n  },\n});\n", "import StarterKit from '@tiptap/starter-kit';\nimport { Table, TableRow, TableCell, TableHeader } from '@tiptap/extension-table';\nimport { Placeholder, CharacterCount } from '@tiptap/extensions';\nimport Link from '@tiptap/extension-link';\nimport Text from '@tiptap/extension-text';\nimport { TextStyle, FontSize } from '@tiptap/extension-text-style';\nimport { Color } from '@tiptap/extension-color';\nimport { FontFamily } from '@tiptap/extension-font-family';\nimport { TextAlign } from '@tiptap/extension-text-align';\nimport { Highlight } from '@tiptap/extension-highlight';\nimport { Superscript } from '@tiptap/extension-superscript';\nimport { AiSuggestion } from './aiSuggestion';\nimport { CommentMark } from './commentMark';\nimport { Callout } from './callout';\nimport { Footnote } from './footnote';\nimport { BrandHighlight } from './brandHighlight';\nimport { createSlashCommandExtension } from './slashCommand';\nimport { ResizableImage } from './resizableImage';\nimport { Indent } from './indent';\nimport { UnderscoreItalic } from './underscoreItalic';\nimport { WhatsAppFormatting } from './whatsappFormatting';\n\nexport function createTextExtensions(opts?: {\n  onSlashAiOp?: (op: 'rewrite' | 'tighten' | 'expand' | 'claim' | 'comment') => void;\n  placeholder?: string;\n  calloutDefaultText?: string;\n  slashCalloutTitle?: string;\n  slashCalloutDescription?: string;\n  /** Native `title` on <a> \u2014 Ctrl/\u2318+click hint. */\n  linkOpenHint?: string;\n}) {\n  return [\n    StarterKit.configure({\n      heading: { levels: [1, 2, 3, 4, 5] },\n      textStyle: false,\n      // Default italic maps *text* \u2192 italic; WhatsApp uses * for bold.\n      italic: false,\n    }),\n    UnderscoreItalic,\n    WhatsAppFormatting,\n    TextStyle,\n    FontSize,\n    Color,\n    FontFamily,\n    Indent,\n    TextAlign.configure({\n      types: ['heading', 'paragraph'],\n    }),\n    Highlight.configure({ multicolor: true }),\n    Superscript,\n    ResizableImage,\n    Table.configure({ resizable: true }),\n    TableRow,\n    TableHeader,\n    TableCell,\n    Link.configure({\n      openOnClick: false,\n      autolink: true,\n      HTMLAttributes: {\n        // Presentation via CSS (`.we-text-prose a`); title = open hint.\n        class: 'we-text-link',\n        ...(opts?.linkOpenHint ? { title: opts.linkOpenHint } : {}),\n        rel: 'noopener noreferrer nofollow',\n      },\n    }),\n    Text,\n    Callout.configure({\n      defaultText: opts?.calloutDefaultText ?? 'Nota destacada',\n    }),\n    Footnote,\n    BrandHighlight,\n    Placeholder.configure({\n      placeholder: opts?.placeholder ?? 'Escribe o pulsa / para comandos\u2026',\n    }),\n    CharacterCount,\n    AiSuggestion,\n    CommentMark,\n    createSlashCommandExtension(opts?.onSlashAiOp, {\n      calloutTitle: opts?.slashCalloutTitle,\n      calloutDescription: opts?.slashCalloutDescription,\n    }),\n  ];\n}\n\nexport {\n  AiSuggestion,\n  CommentMark,\n  Callout,\n  Footnote,\n  BrandHighlight,\n  ResizableImage,\n  Indent,\n  UnderscoreItalic,\n  WhatsAppFormatting,\n};\n", "/**\n * TipTap page-break decorations \u2014 insert spacers so text stays inside the\n * page content box (below top margin, above bottom margin).\n */\n\nimport { Plugin, PluginKey } from '@tiptap/pm/state';\nimport { Decoration, DecorationSet } from '@tiptap/pm/view';\nimport type { EditorView } from '@tiptap/pm/view';\nimport type React from 'react';\n\nexport const PAGE_GAP_PX = 24;\n\n/** ~1 line of leading-relaxed @ 15px \u2014 keeps glyphs above the bottom guide. */\nconst FIT_SLACK_PX = 24;\n\nconst KEY = new PluginKey<DecorationSet>('pageBreaks');\n\nexport interface PageConfig {\n  pageHeightPx: number;\n  marginTopPx: number;\n  marginBottomPx: number;\n}\n\ntype BlockMetrics = {\n  offset: number;\n  /** Border-box height (integer). */\n  h: number;\n  mt: number;\n  mb: number;\n};\n\nfunction makeSpacerEl(height: number): HTMLElement {\n  const renderedHeight = Math.max(1, Math.ceil(height));\n  const div = document.createElement('div');\n  div.setAttribute('data-page-gap', '1');\n  div.style.cssText =\n    `display:block;height:${renderedHeight}px;background:transparent;` +\n    `pointer-events:none;user-select:none;-webkit-user-select:none;flex-shrink:0;line-height:0;`;\n  return div;\n}\n\nfunction readBlock(el: HTMLElement, offset: number): BlockMetrics | null {\n  // offsetHeight is a stable integer border-box; getBoundingClientRect can\n  // under-report fractional line boxes across many blocks.\n  const h = el.offsetHeight;\n  if (h <= 0) return null;\n  const style = window.getComputedStyle(el);\n  return {\n    offset,\n    h,\n    mt: Math.max(0, Math.ceil(parseFloat(style.marginTop) || 0)),\n    mb: Math.max(0, Math.ceil(parseFloat(style.marginBottom) || 0)),\n  };\n}\n\nfunction collectBlocks(view: EditorView): BlockMetrics[] {\n  const items: BlockMetrics[] = [];\n  view.state.doc.forEach((node, offset) => {\n    if (!node.isBlock) return;\n    const el = view.nodeDOM(offset) as HTMLElement | null;\n    if (!el || el.getAttribute('data-page-gap') === '1') return;\n    const metrics = readBlock(el, offset);\n    if (metrics) items.push(metrics);\n  });\n  return items;\n}\n\n/**\n * Flow blocks into pages. `y` is the running end of the margin-box on the\n * current page (includes the previous block's margin-bottom). Fit checks use\n * the text bottom (border-box end) so trailing margin may sit in the slack\n * zone, but glyphs must stay above the bottom margin guide.\n */\nfunction buildDecos(view: EditorView, cfg: PageConfig): DecorationSet {\n  const { pageHeightPx, marginTopPx, marginBottomPx } = cfg;\n  const contentAreaH = Math.max(\n    1,\n    pageHeightPx - marginTopPx - marginBottomPx - FIT_SLACK_PX\n  );\n  const pagePeriod = pageHeightPx + PAGE_GAP_PX;\n  // unused content + bottom margin + gap + next top margin (+ slack recovery).\n  const pageBridgeH = pagePeriod - contentAreaH;\n\n  const blocks = collectBlocks(view);\n  const decos: Decoration[] = [];\n\n  let y = 0;\n  let lastMb = 0;\n  let gapIdx = 0;\n\n  for (const block of blocks) {\n    const { offset, h, mt, mb } = block;\n\n    let textBottom: number;\n    if (y <= 0) {\n      textBottom = mt + h;\n    } else {\n      const yWithoutLastMb = y - lastMb;\n      const collapsed = Math.max(lastMb, mt);\n      textBottom = yWithoutLastMb + collapsed + h;\n    }\n    const newY = textBottom + mb;\n\n    if (y > 0 && textBottom > contentAreaH) {\n      const unusedContentH = Math.max(0, contentAreaH - y);\n      const breakHeight = unusedContentH + pageBridgeH;\n      decos.push(\n        Decoration.widget(offset, () => makeSpacerEl(breakHeight), {\n          side: -1,\n          key: `pgap-${gapIdx}-${Math.round(breakHeight)}`,\n        })\n      );\n      gapIdx++;\n      // Fresh page \u2014 block starts after the next page's top margin (in spacer).\n      y = mt + h + mb;\n      lastMb = mb;\n      continue;\n    }\n\n    y = newY;\n    lastMb = mb;\n  }\n\n  return DecorationSet.create(view.state.doc, decos);\n}\n\nexport function createPageBreakPlugin(\n  configRef: React.MutableRefObject<PageConfig>\n): Plugin {\n  return new Plugin<DecorationSet>({\n    key: KEY,\n\n    state: {\n      init: () => DecorationSet.empty,\n      apply(tr, decos, _, newState) {\n        const fresh: DecorationSet | undefined = tr.getMeta(KEY);\n        if (fresh !== undefined) return fresh;\n        return decos.map(tr.mapping, newState.doc);\n      },\n    },\n\n    view(view: EditorView) {\n      let rafId: number | null = null;\n      let lastHash = '';\n      let dispatching = false;\n      let ro: ResizeObserver | null = null;\n\n      const compute = () => {\n        if (dispatching) return;\n\n        const newDecos = buildDecos(view, configRef.current);\n        const hash = newDecos\n          .find()\n          .map((decoration) => `${decoration.from}:${String(decoration.spec?.key ?? '')}`)\n          .join('|');\n\n        if (hash === lastHash) return;\n        lastHash = hash;\n        dispatching = true;\n\n        try {\n          view.dispatch(\n            view.state.tr\n              .setMeta(KEY, newDecos)\n              .setMeta('addToHistory', false)\n          );\n        } finally {\n          dispatching = false;\n        }\n      };\n\n      const schedule = () => {\n        if (rafId !== null) cancelAnimationFrame(rafId);\n        // Double rAF: wait for layout after font/style changes.\n        rafId = requestAnimationFrame(() => {\n          rafId = requestAnimationFrame(compute);\n        });\n      };\n\n      ro = new ResizeObserver(() => schedule());\n      ro.observe(view.dom);\n\n      if (typeof document !== 'undefined' && document.fonts?.ready) {\n        void document.fonts.ready.then(() => schedule());\n      }\n\n      return {\n        update: schedule,\n        destroy() {\n          if (rafId !== null) cancelAnimationFrame(rafId);\n          ro?.disconnect();\n        },\n      };\n    },\n\n    props: {\n      decorations: (state) => KEY.getState(state) ?? DecorationSet.empty,\n    },\n  });\n}\n", "/**\n * Clean pasted HTML from Google Docs / Word / rich editors.\n */\n\nexport function cleanPastedHtml(html: string): string {\n  if (!html) return html;\n  let out = html;\n  // Strip Word/Google Docs conditional comments and mso styles\n  out = out.replace(/<!--\\[if[\\s\\S]*?<!\\[endif\\]-->/gi, '');\n  out = out.replace(/<\\/?o:p[^>]*>/gi, '');\n  out = out.replace(/\\s*class=\"[^\"]*Mso[^\"]*\"/gi, '');\n  out = out.replace(/\\s*style=\"[^\"]*mso-[^\"]*\"/gi, '');\n  // Unwrap google docs spans that only carry font metadata\n  out = out.replace(\n    /<span[^>]*style=\"[^\"]*font-weight:\\s*normal[^\"]*\"[^>]*>([\\s\\S]*?)<\\/span>/gi,\n    '$1'\n  );\n  out = out.replace(/<span[^>]*>\\s*<\\/span>/gi, '');\n  // Drop empty font tags\n  out = out.replace(/<\\/?font[^>]*>/gi, '');\n  // Normalize non-breaking spaces\n  out = out.replace(/&nbsp;/gi, ' ');\n  out = out.replace(/\\u00a0/g, ' ');\n  return out;\n}\n", "import { create } from 'zustand';\n\nexport type TextLeftTabId = 'outline' | 'myFiles';\n\ntype TextUiState = {\n  leftTab: TextLeftTabId;\n  leftContentOpen: boolean;\n  setLeftTab: (id: TextLeftTabId) => void;\n  setLeftContentOpen: (open: boolean) => void;\n  toggleLeftTab: (id: TextLeftTabId) => void;\n\n  /** Right dock open/closed; active tab lives on useTextStore.rightTab for Cmd+K. */\n  rightDockOpen: boolean;\n  setRightDockOpen: (open: boolean) => void;\n  toggleRightDock: () => void;\n\n  /** Page setup modal (size / orientation / margins). */\n  pageSetupOpen: boolean;\n  setPageSetupOpen: (open: boolean) => void;\n\n  /** Full-screen suggestions / diffs review (not the right dock tab). */\n  suggestionsModalOpen: boolean;\n  setSuggestionsModalOpen: (open: boolean) => void;\n\n  /** Margin guides overlay on the document canvas. */\n  showMarginGuides: boolean;\n  setShowMarginGuides: (on: boolean) => void;\n  toggleMarginGuides: () => void;\n};\n\nexport const useTextUiStore = create<TextUiState>((set) => ({\n  leftTab: 'outline',\n  leftContentOpen: true,\n  setLeftTab: (id) => set({ leftTab: id, leftContentOpen: true }),\n  setLeftContentOpen: (open) => set({ leftContentOpen: open }),\n  toggleLeftTab: (id) =>\n    set((s) => {\n      if (s.leftContentOpen && s.leftTab === id) {\n        return { leftContentOpen: false };\n      }\n      return { leftTab: id, leftContentOpen: true };\n    }),\n\n  rightDockOpen: true,\n  setRightDockOpen: (open) => set({ rightDockOpen: open }),\n  toggleRightDock: () => set((s) => ({ rightDockOpen: !s.rightDockOpen })),\n\n  pageSetupOpen: false,\n  setPageSetupOpen: (open) => set({ pageSetupOpen: open }),\n\n  suggestionsModalOpen: false,\n  setSuggestionsModalOpen: (open) => set({ suggestionsModalOpen: open }),\n\n  showMarginGuides: true,\n  setShowMarginGuides: (on) => set({ showMarginGuides: on }),\n  toggleMarginGuides: () => set((s) => ({ showMarginGuides: !s.showMarginGuides })),\n}));\n", "/**\n * Conversational text agent \u2014 POST /api/text/agent.\n */\n\nimport { getEditorIdentity } from '../identity';\nimport { getWizardApiClient } from '../wizardApiClient';\n\nexport interface AgentMessage {\n  role: 'system' | 'user' | 'assistant' | 'tool';\n  content?: string | null;\n  name?: string;\n  tool_call_id?: string;\n  tool_calls?: AgentToolCall[];\n}\n\nexport interface AgentToolCall {\n  id: string;\n  type: 'function';\n  function: {\n    name: string;\n    arguments: string;\n  };\n}\n\nexport interface AgentToolDef {\n  type: 'function';\n  function: {\n    name: string;\n    description: string;\n    parameters: Record<string, unknown>;\n  };\n}\n\nexport interface TextAgentTurnOptions {\n  messages: AgentMessage[];\n  projectSnapshot: unknown;\n  tools: AgentToolDef[];\n  /** When true, model should propose a plan before costly tool calls. */\n  planMode?: boolean;\n  signal?: AbortSignal;\n}\n\nexport interface TextAgentReply {\n  role: 'assistant';\n  content: string | null;\n  tool_calls: AgentToolCall[];\n}\n\nexport async function runTextAgentTurn(\n  opts: TextAgentTurnOptions\n): Promise<TextAgentReply> {\n  const { accountId, brandId } = getEditorIdentity();\n  return getWizardApiClient().postJsonForJson<TextAgentReply>(\n    '/api/text/agent',\n    {\n      messages: opts.messages,\n      projectSnapshot: opts.projectSnapshot,\n      tools: opts.tools,\n      planMode: opts.planMode ?? false,\n      account_id: String(accountId),\n      brand_id: String(brandId),\n    },\n    { signal: opts.signal }\n  );\n}\n", "import { getWizardApiClient } from '../wizardApiClient';\n\nexport type TextHealthStatus = {\n  ok: boolean;\n  status?: string;\n  raw?: unknown;\n};\n\nexport async function checkTextHealth(\n  signal?: AbortSignal,\n): Promise<TextHealthStatus> {\n  try {\n    const res = await getWizardApiClient().getForJson<Record<string, unknown>>(\n      '/api/text/health',\n      undefined,\n      { signal },\n    );\n    const status =\n      typeof res?.status === 'string'\n        ? res.status\n        : typeof res?.Status === 'string'\n          ? (res.Status as string)\n          : 'ok';\n    const ok =\n      status.toLowerCase() === 'ok' ||\n      status.toLowerCase() === 'healthy' ||\n      res?.ok === true;\n    return { ok, status, raw: res };\n  } catch (err) {\n    return {\n      ok: false,\n      status: err instanceof Error ? err.message : 'unreachable',\n    };\n  }\n}\n", "export {\n  generateText,\n  rewriteText,\n  generateVariants,\n  generateOutline,\n  scoreBrandVoice,\n  runSectionOp,\n  scoreAbVariants,\n  runCompliancePass,\n  voiceMatchRewrite,\n  analyzeClaims,\n} from './generateService';\nexport type { SectionOp } from './generateService';\n\nexport { runTextAgentTurn } from './textAgentService';\nexport type {\n  AgentMessage,\n  AgentToolCall,\n  AgentToolDef,\n  TextAgentTurnOptions,\n  TextAgentReply,\n} from './textAgentService';\n\nexport { checkTextHealth } from './healthService';\nexport type { TextHealthStatus } from './healthService';\n", "import React, { useEffect, useRef } from 'react';\nimport {\n  ClipboardPaste,\n  Copy,\n  Scissors,\n  MessageSquarePlus,\n} from 'lucide-react';\nimport type { Editor } from '@tiptap/core';\nimport { useTranslation } from '../../i18n';\nimport { modeAccentVars, useModeAccent } from '../../theme/modeAccent';\nimport { modShortcut } from '../../utils/modKey';\nimport { TextBody, TextTitle } from '../ui';\n\nexport type TextContextMenuState = {\n  x: number;\n  y: number;\n};\n\ntype Props = {\n  editor: Editor;\n  menu: TextContextMenuState;\n  onClose: () => void;\n  onComment: () => void;\n};\n\n/**\n * Word-like right-click menu for the TipTap document surface.\n * Formatting that lives in the sticky toolbar is omitted here.\n */\nexport const TextContextMenu: React.FC<Props> = ({\n  editor,\n  menu,\n  onClose,\n  onComment,\n}) => {\n  const tr = useTranslation();\n  const mode = useModeAccent();\n  const ref = useRef<HTMLDivElement>(null);\n  const t = tr.text.contextMenu;\n\n  useEffect(() => {\n    const onDown = (e: MouseEvent) => {\n      if (ref.current && !ref.current.contains(e.target as Node)) onClose();\n    };\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') onClose();\n    };\n    window.addEventListener('mousedown', onDown);\n    window.addEventListener('keydown', onKey);\n    return () => {\n      window.removeEventListener('mousedown', onDown);\n      window.removeEventListener('keydown', onKey);\n    };\n  }, [onClose]);\n\n  const run = (fn: () => void) => {\n    fn();\n    onClose();\n  };\n\n  const item =\n    'flex w-full cursor-pointer items-center gap-2 px-3 py-2 text-left text-white transition-colors hover:bg-[var(--we-accent-muted)] disabled:opacity-40';\n\n  return (\n    <div\n      ref={ref}\n      role=\"menu\"\n      data-testid=\"text-context-menu\"\n      className=\"fixed z-[80] min-w-[220px] rounded-xl border border-panel-border bg-panel py-1 shadow-2xl\"\n      style={{\n        top: menu.y,\n        left: menu.x,\n        ...modeAccentVars(mode),\n      }}\n      onMouseDown={(e) => e.stopPropagation()}\n    >\n      <TextTitle as=\"p\" size=\"xs\" className=\"px-3 py-1.5 uppercase tracking-wider text-[var(--we-accent)]\">\n        {t.title}\n      </TextTitle>\n\n      <button type=\"button\" className={item} onClick={() => run(() => editor.chain().focus().undo().run())}>\n        <TextBody as=\"span\" size=\"sm\">{t.undo}</TextBody>\n        <TextBody as=\"span\" size=\"sm\" className=\"ml-auto text-white/50\">{modShortcut('Z')}</TextBody>\n      </button>\n      <button type=\"button\" className={item} onClick={() => run(() => editor.chain().focus().redo().run())}>\n        <TextBody as=\"span\" size=\"sm\">{t.redo}</TextBody>\n        <TextBody as=\"span\" size=\"sm\" className=\"ml-auto text-white/50\">{modShortcut('Shift+Z')}</TextBody>\n      </button>\n\n      <div className=\"my-1 border-t border-panel-border\" />\n\n      <button\n        type=\"button\"\n        className={item}\n        onClick={() =>\n          run(() => {\n            const { from, to } = editor.state.selection;\n            if (from === to) return;\n            document.execCommand('cut');\n          })\n        }\n      >\n        <Scissors size={12} className=\"text-[var(--we-accent)]\" />\n        <TextBody as=\"span\" size=\"sm\">{t.cut}</TextBody>\n        <TextBody as=\"span\" size=\"sm\" className=\"ml-auto text-white/50\">{modShortcut('X')}</TextBody>\n      </button>\n      <button\n        type=\"button\"\n        className={item}\n        onClick={() =>\n          run(() => {\n            document.execCommand('copy');\n          })\n        }\n      >\n        <Copy size={12} className=\"text-[var(--we-accent)]\" />\n        <TextBody as=\"span\" size=\"sm\">{t.copy}</TextBody>\n        <TextBody as=\"span\" size=\"sm\" className=\"ml-auto text-white/50\">{modShortcut('C')}</TextBody>\n      </button>\n      <button\n        type=\"button\"\n        className={item}\n        onClick={() =>\n          run(() => {\n            void navigator.clipboard.readText().then((text) => {\n              if (text) editor.chain().focus().insertContent(text).run();\n            });\n          })\n        }\n      >\n        <ClipboardPaste size={12} className=\"text-[var(--we-accent)]\" />\n        <TextBody as=\"span\" size=\"sm\">{t.paste}</TextBody>\n        <TextBody as=\"span\" size=\"sm\" className=\"ml-auto text-white/50\">{modShortcut('V')}</TextBody>\n      </button>\n\n      <div className=\"my-1 border-t border-panel-border\" />\n\n      <button type=\"button\" className={item} onClick={() => run(onComment)}>\n        <MessageSquarePlus size={12} className=\"text-[var(--we-accent)]\" />\n        <TextBody as=\"span\" size=\"sm\">{t.comment}</TextBody>\n      </button>\n    </div>\n  );\n};\n", "import React, { useEffect, useState } from 'react';\nimport { useTranslation } from '../../i18n';\nimport { Modal, Button, TextBody, TextTitle } from '../ui';\n\nexport type CommentComposerState = {\n  from: number;\n  to: number;\n  quote: string;\n  /** Kept for callers that still pass caret coords (ignored; UI is a modal). */\n  x?: number;\n  y?: number;\n};\n\ntype Props = {\n  draft: CommentComposerState;\n  onClose: () => void;\n  onSave: (note: string) => void;\n};\n\n/**\n * Modal composer to pin a comment on the current text selection.\n */\nexport const TextCommentComposer: React.FC<Props> = ({ draft, onClose, onSave }) => {\n  const tr = useTranslation();\n  const tc = tr.text.comments;\n  const [note, setNote] = useState('');\n\n  useEffect(() => {\n    setNote('');\n  }, [draft.from, draft.to, draft.quote]);\n\n  useEffect(() => {\n    const onKey = (e: KeyboardEvent) => {\n      if ((e.metaKey || e.ctrlKey) && e.key === 'Enter' && note.trim()) {\n        e.preventDefault();\n        onSave(note.trim());\n      }\n    };\n    window.addEventListener('keydown', onKey);\n    return () => window.removeEventListener('keydown', onKey);\n  }, [note, onSave]);\n\n  return (\n    <Modal\n      isOpen\n      onClose={onClose}\n      title={tc.popoverTitle}\n      size=\"sm\"\n    >\n      <div className=\"flex flex-col gap-3\" data-testid=\"text-comment-composer\">\n        {draft.quote ? (\n          <TextBody as=\"p\" size=\"sm\" className=\"line-clamp-3 rounded-xl border border-panel-border bg-black-capsule px-2.5 py-2 italic text-white/80\">\n            \u201C{draft.quote}\u201D\n          </TextBody>\n        ) : null}\n        <textarea\n          value={note}\n          onChange={(e) => setNote(e.target.value)}\n          placeholder={tc.placeholder}\n          rows={4}\n          className=\"w-full resize-none rounded-xl border border-panel-border bg-black-capsule p-2.5 font-sans text-[12px] font-medium text-white outline-none placeholder:text-white/50 focus:border-[var(--we-accent)]\"\n          autoFocus\n        />\n        <div className=\"flex gap-2\">\n          <Button variant=\"secondary\" size=\"md\" className=\"flex-1\" onClick={onClose}>\n            {tc.popoverCancel}\n          </Button>\n          <Button\n            variant=\"accent\"\n            size=\"md\"\n            className=\"flex-1\"\n            disabled={!note.trim()}\n            onClick={() => onSave(note.trim())}\n          >\n            {tc.popoverSave}\n          </Button>\n        </div>\n      </div>\n    </Modal>\n  );\n};\n", "import React, { useEffect, useState } from 'react';\nimport { Modal, Button } from '../ui';\nimport { useTranslation } from '../../i18n';\n\ntype Props = {\n  open: boolean;\n  onClose: () => void;\n  onSave: (note: string) => void;\n  initialNote?: string;\n};\n\n/**\n * Footnote note entry \u2014 modal (never window.prompt).\n */\nexport const TextFootnoteModal: React.FC<Props> = ({\n  open,\n  onClose,\n  onSave,\n  initialNote = '',\n}) => {\n  const tr = useTranslation();\n  const c = tr.text.canvas;\n  const [note, setNote] = useState(initialNote);\n\n  useEffect(() => {\n    if (open) setNote(initialNote || c.footnoteDefault);\n  }, [open, initialNote, c.footnoteDefault]);\n\n  return (\n    <Modal isOpen={open} onClose={onClose} title={c.footnote} size=\"sm\">\n      <div className=\"flex flex-col gap-3\">\n        <textarea\n          value={note}\n          onChange={(e) => setNote(e.target.value)}\n          placeholder={c.footnotePrompt}\n          rows={4}\n          className=\"w-full resize-none rounded-xl border border-panel-border bg-black-capsule p-2.5 font-sans text-[12px] font-medium text-white outline-none placeholder:text-white/50 focus:border-[var(--we-accent)]\"\n          autoFocus\n        />\n        <div className=\"flex gap-2\">\n          <Button variant=\"secondary\" size=\"md\" className=\"flex-1\" onClick={onClose}>\n            {tr.text.comments.popoverCancel}\n          </Button>\n          <Button\n            variant=\"accent\"\n            size=\"md\"\n            className=\"flex-1\"\n            disabled={!note.trim()}\n            onClick={() => {\n              onSave(note.trim());\n              onClose();\n            }}\n          >\n            {tr.text.comments.popoverSave}\n          </Button>\n        </div>\n      </div>\n    </Modal>\n  );\n};\n", "export type LinkScheme = 'http' | 'https';\n\nexport type ParsedLinkInput = {\n  scheme: LinkScheme;\n  /** Host + path/query/hash with leading schemes stripped. */\n  host: string;\n  hadScheme: boolean;\n};\n\nconst SCHEME_RE = /^(https?):\\/\\//i;\n\n/**\n * Strip one or more leading http(s):// schemes and collapse leftover slashes.\n * Prefer http only when every explicit scheme was http (never https).\n */\nexport function parseLinkInput(raw: string): ParsedLinkInput {\n  let s = String(raw ?? '').trim();\n  const schemes: LinkScheme[] = [];\n\n  while (SCHEME_RE.test(s)) {\n    const m = s.match(SCHEME_RE);\n    if (!m?.[1]) break;\n    schemes.push(m[1].toLowerCase() as LinkScheme);\n    s = s.slice(m[0].length);\n  }\n\n  // Collapse accidental \"https:////host\" or leftover leading slashes after strip\n  s = s.replace(/^\\/+/, '');\n\n  const hadScheme = schemes.length > 0;\n  const scheme: LinkScheme =\n    hadScheme && schemes.every((sc) => sc === 'http') ? 'http' : 'https';\n\n  return { scheme, host: s, hadScheme };\n}\n\n/** Display value for the input (no scheme). */\nexport function stripLinkScheme(raw: string): string {\n  return parseLinkInput(raw).host;\n}\n\n/**\n * Build a single absolute http(s) URL from free-form user input.\n * Empty / scheme-only input \u2192 ''.\n */\nexport function normalizeLinkUrl(raw: string): string {\n  const { scheme, host } = parseLinkInput(raw);\n  if (!host) return '';\n  return `${scheme}://${host}`;\n}\n\n/**\n * Whether the input can be applied as a hyperlink.\n * Rejects empty, scheme-only, and strings the URL parser cannot load as http(s).\n */\nexport function isApplyableLinkUrl(raw: string): boolean {\n  const url = normalizeLinkUrl(raw);\n  if (!url) return false;\n  try {\n    const u = new URL(url);\n    if (u.protocol !== 'http:' && u.protocol !== 'https:') return false;\n    const host = u.hostname.trim();\n    if (!host) return false;\n    // Reject lone dots / empty labels that URL sometimes accepts\n    if (host === '.' || host.startsWith('.') || host.endsWith('.')) return false;\n    return true;\n  } catch {\n    return false;\n  }\n}\n", "import React, { useEffect, useState } from 'react';\nimport { Modal, Button, TextBody } from '../ui';\nimport { useTranslation } from '../../i18n';\nimport {\n  isApplyableLinkUrl,\n  normalizeLinkUrl,\n  parseLinkInput,\n  type LinkScheme,\n} from '../../lib/text/normalizeLinkUrl';\n\ntype Props = {\n  open: boolean;\n  onClose: () => void;\n  /** Apply URL (empty string removes the link). */\n  onSave: (url: string) => void;\n  /** Remove link without saving a new URL. */\n  onRemove?: () => void;\n  initialUrl?: string;\n  hasExistingLink?: boolean;\n};\n\n/**\n * Insert / edit hyperlink \u2014 modal (never window.prompt).\n * Scheme is shown as a fixed prefix; the input only holds host/path.\n */\nexport const TextLinkModal: React.FC<Props> = ({\n  open,\n  onClose,\n  onSave,\n  onRemove,\n  initialUrl = '',\n  hasExistingLink = false,\n}) => {\n  const tr = useTranslation();\n  const c = tr.text.canvas;\n  const [scheme, setScheme] = useState<LinkScheme>('https');\n  const [host, setHost] = useState('');\n\n  useEffect(() => {\n    if (!open) return;\n    const parsed = parseLinkInput(initialUrl || '');\n    setScheme(parsed.scheme);\n    setHost(parsed.host);\n  }, [open, initialUrl]);\n\n  const composed = host.trim() ? `${scheme}://${host.trim()}` : '';\n  const canApply = isApplyableLinkUrl(composed);\n\n  const apply = () => {\n    const url = normalizeLinkUrl(composed);\n    if (!url || !isApplyableLinkUrl(url)) return;\n    onSave(url);\n    onClose();\n  };\n\n  return (\n    <Modal isOpen={open} onClose={onClose} title={c.link} size=\"sm\">\n      <div className=\"flex flex-col gap-3\">\n        <label className=\"flex flex-col gap-1.5\">\n          <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n            {c.linkPrompt}\n          </TextBody>\n          <div className=\"flex min-w-0 overflow-hidden rounded-xl border border-panel-border bg-black-capsule focus-within:border-[var(--we-accent)]\">\n            <span\n              className=\"shrink-0 border-r border-panel-border px-2.5 py-2.5\"\n              aria-hidden\n            >\n              <TextBody as=\"span\" size=\"sm\" className=\"text-white/50\">\n                {scheme}://\n              </TextBody>\n            </span>\n            <input\n              type=\"text\"\n              inputMode=\"url\"\n              autoComplete=\"url\"\n              value={host}\n              onChange={(e) => {\n                const parsed = parseLinkInput(e.target.value);\n                if (parsed.hadScheme) setScheme(parsed.scheme);\n                setHost(parsed.host);\n              }}\n              onPaste={(e) => {\n                const text = e.clipboardData.getData('text');\n                if (!text) return;\n                e.preventDefault();\n                const parsed = parseLinkInput(text);\n                if (parsed.hadScheme) setScheme(parsed.scheme);\n                setHost(parsed.host);\n              }}\n              onKeyDown={(e) => {\n                if (e.key === 'Enter' && canApply) {\n                  e.preventDefault();\n                  apply();\n                }\n              }}\n              placeholder={c.linkPlaceholder}\n              className=\"min-w-0 flex-1 bg-transparent px-3 py-2.5 font-sans text-[12px] font-medium text-white outline-none placeholder:text-white/40\"\n              autoFocus\n            />\n          </div>\n        </label>\n        <div className=\"flex flex-wrap gap-2\">\n          <Button variant=\"secondary\" size=\"md\" className=\"flex-1\" onClick={onClose}>\n            {tr.text.comments.popoverCancel}\n          </Button>\n          {hasExistingLink && onRemove ? (\n            <Button\n              variant=\"danger\"\n              size=\"md\"\n              className=\"flex-1\"\n              onClick={() => {\n                onRemove();\n                onClose();\n              }}\n            >\n              {c.linkRemove}\n            </Button>\n          ) : null}\n          <Button variant=\"accent\" size=\"md\" className=\"flex-1\" disabled={!canApply} onClick={apply}>\n            {c.linkApply}\n          </Button>\n        </div>\n      </div>\n    </Modal>\n  );\n};\n", "import React, { useEffect, useState } from 'react';\nimport { Minus, Plus, Trash2 } from 'lucide-react';\nimport { useTranslation } from '../../i18n';\nimport { Modal, Button, TextBody, TextTitle } from '../ui';\n\ntype Props = {\n  open: boolean;\n  onClose: () => void;\n  /** Cursor is inside an existing table. */\n  editing: boolean;\n  onInsert: (rows: number, cols: number) => void;\n  onAddRow: () => void;\n  onDelRow: () => void;\n  onAddCol: () => void;\n  onDelCol: () => void;\n  onDeleteTable: () => void;\n};\n\n/**\n * Insert / edit TipTap table \u2014 modal so docks never clip the controls.\n */\nexport const TextTableModal: React.FC<Props> = ({\n  open,\n  onClose,\n  editing,\n  onInsert,\n  onAddRow,\n  onDelRow,\n  onAddCol,\n  onDelCol,\n  onDeleteTable,\n}) => {\n  const tr = useTranslation();\n  const c = tr.text.canvas;\n  const [rows, setRows] = useState(3);\n  const [cols, setCols] = useState(3);\n\n  useEffect(() => {\n    if (open && !editing) {\n      setRows(3);\n      setCols(3);\n    }\n  }, [open, editing]);\n\n  return (\n    <Modal\n      isOpen={open}\n      onClose={onClose}\n      title={editing ? c.tableEdit : c.tableInsert}\n      size=\"sm\"\n    >\n      {editing ? (\n        <div className=\"flex flex-col gap-3\">\n          <div className=\"grid grid-cols-2 gap-2\">\n            <Button variant=\"secondary\" size=\"md\" icon={<Plus size={14} />} onClick={onAddRow}>\n              {c.tableAddRow}\n            </Button>\n            <Button variant=\"secondary\" size=\"md\" icon={<Minus size={14} />} onClick={onDelRow}>\n              {c.tableDelRow}\n            </Button>\n            <Button variant=\"secondary\" size=\"md\" icon={<Plus size={14} />} onClick={onAddCol}>\n              {c.tableAddCol}\n            </Button>\n            <Button variant=\"secondary\" size=\"md\" icon={<Minus size={14} />} onClick={onDelCol}>\n              {c.tableDelCol}\n            </Button>\n          </div>\n          <Button\n            variant=\"outline\"\n            size=\"md\"\n            className=\"w-full !text-rose-300\"\n            icon={<Trash2 size={14} />}\n            onClick={() => {\n              onDeleteTable();\n              onClose();\n            }}\n          >\n            {c.tableDelete}\n          </Button>\n          <Button variant=\"secondary\" size=\"md\" className=\"w-full\" onClick={onClose}>\n            {tr.text.comments.popoverCancel}\n          </Button>\n        </div>\n      ) : (\n        <div className=\"flex flex-col gap-3\">\n          <div className=\"flex items-center justify-between gap-2\">\n            <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n              {c.tableRows}\n            </TextBody>\n            <div className=\"inline-flex items-center gap-1\">\n              <button\n                type=\"button\"\n                className=\"flex h-8 w-8 items-center justify-center rounded-lg bg-black-capsule text-white hover:bg-black-capsule-hover\"\n                onClick={() => setRows((n) => Math.max(1, n - 1))}\n              >\n                <Minus size={14} />\n              </button>\n              <TextBody as=\"span\" size=\"sm\" className=\"w-8 text-center text-white\">\n                {rows}\n              </TextBody>\n              <button\n                type=\"button\"\n                className=\"flex h-8 w-8 items-center justify-center rounded-lg bg-black-capsule text-white hover:bg-black-capsule-hover\"\n                onClick={() => setRows((n) => Math.min(12, n + 1))}\n              >\n                <Plus size={14} />\n              </button>\n            </div>\n          </div>\n          <div className=\"flex items-center justify-between gap-2\">\n            <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n              {c.tableCols}\n            </TextBody>\n            <div className=\"inline-flex items-center gap-1\">\n              <button\n                type=\"button\"\n                className=\"flex h-8 w-8 items-center justify-center rounded-lg bg-black-capsule text-white hover:bg-black-capsule-hover\"\n                onClick={() => setCols((n) => Math.max(1, n - 1))}\n              >\n                <Minus size={14} />\n              </button>\n              <TextBody as=\"span\" size=\"sm\" className=\"w-8 text-center text-white\">\n                {cols}\n              </TextBody>\n              <button\n                type=\"button\"\n                className=\"flex h-8 w-8 items-center justify-center rounded-lg bg-black-capsule text-white hover:bg-black-capsule-hover\"\n                onClick={() => setCols((n) => Math.min(12, n + 1))}\n              >\n                <Plus size={14} />\n              </button>\n            </div>\n          </div>\n          <div className=\"flex gap-2 pt-1\">\n            <Button variant=\"secondary\" size=\"md\" className=\"flex-1\" onClick={onClose}>\n              {tr.text.comments.popoverCancel}\n            </Button>\n            <Button\n              variant=\"accent\"\n              size=\"md\"\n              className=\"flex-1\"\n              onClick={() => {\n                onInsert(rows, cols);\n                onClose();\n              }}\n            >\n              {c.tableInsertAction}\n            </Button>\n          </div>\n        </div>\n      )}\n    </Modal>\n  );\n};\n", "import React, { useEffect, useCallback, useState, useRef, useMemo } from 'react';\nimport { useEditor, EditorContent } from '@tiptap/react';\nimport { BubbleMenu } from '@tiptap/react/menus';\nimport { Extension } from '@tiptap/core';\nimport type { Editor, JSONContent } from '@tiptap/core';\nimport {\n  Bold,\n  Italic,\n  List,\n  ListOrdered,\n  Quote,\n  Strikethrough,\n  MessageSquarePlus,\n  Volume2,\n  Superscript,\n  Link as LinkIcon,\n  Highlighter,\n  AlignLeft,\n  AlignCenter,\n  AlignRight,\n  AlignJustify,\n  Indent,\n  Outdent,\n  ChevronDown,\n  Table as TableIcon,\n} from 'lucide-react';\nimport { createTextExtensions } from '../../lib/text/extensions';\nimport { createPageBreakPlugin, PAGE_GAP_PX } from '../../lib/text/extensions/pageBreak';\nimport { cleanPastedHtml } from '../../lib/text/pasteClean';\nimport { useTextStore, TEXT_PAGE_SIZES } from '../../store/useTextStore';\nimport { useTextUiStore } from '../../store/useTextUiStore';\nimport { runSectionOp } from '../../services/text';\nimport { getDocPlainText } from '../../store/useTextStore';\nimport { useTranslation } from '../../i18n';\nimport { GOOGLE_FONTS_CATALOG } from '../Sidebar';\nimport { TextContextMenu, type TextContextMenuState } from './TextContextMenu';\nimport {\n  TextCommentComposer,\n  type CommentComposerState,\n} from './TextCommentComposer';\nimport { TextFootnoteModal } from './TextFootnoteModal';\nimport { TextLinkModal } from './TextLinkModal';\nimport { TextTableModal } from './TextTableModal';\nimport { FontPickerFlyout, IconButton, SelectDropdown, TextBody, TextTitle } from '../ui';\n\nconst FONT_SIZES = [8, 9, 10, 11, 12, 14, 15, 16, 18, 20, 24, 28, 32, 36, 48, 72, 96];\nconst DEFAULT_FONT = 'Inter';\n\nfunction resolveFontFamily(raw: unknown): string {\n  const name = String(raw ?? '')\n    .replace(/['\"]/g, '')\n    .split(',')[0]\n    ?.trim();\n  return name || DEFAULT_FONT;\n}\n\nfunction ensureGoogleFont(name: string) {\n  if (typeof document === 'undefined' || !name.trim()) return;\n  const id = `we-gfont-${name.replace(/\\s+/g, '-')}`;\n  if (document.getElementById(id)) return;\n  const link = document.createElement('link');\n  link.id = id;\n  link.rel = 'stylesheet';\n  link.href = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(name)}:wght@400;500;600;700&display=swap`;\n  document.head.appendChild(link);\n  void document.fonts?.load(`16px \"${name}\"`).catch(() => undefined);\n}\n\ninterface Props {\n  doc: JSONContent;\n  editable?: boolean;\n}\n\ntype SlashAiOp = 'rewrite' | 'tighten' | 'expand' | 'claim' | 'comment';\n\nlet _slashAiHandler: ((op: SlashAiOp) => void) | null = null;\n\nexport const DocumentCanvas: React.FC<Props> = ({ doc, editable = true }) => {\n  const tr = useTranslation();\n  const c = tr.text.canvas;\n  const tc = tr.text.comments;\n  const tClaims = tr.text.claims;\n  const setDocFromEditor = useTextStore((s) => s.setDocFromEditor);\n  const activeId = useTextStore((s) => s.activeTextProjectId);\n  const addToast = useTextStore((s) => s.addToast);\n  const activeProject = useTextStore((s) =>\n    s.textProjects.find((p) => p.id === s.activeTextProjectId) ?? null\n  );\n  const showMargins = useTextUiStore((s) => s.showMarginGuides);\n  const [ctxMenu, setCtxMenu] = useState<TextContextMenuState | null>(null);\n  const [commentDraft, setCommentDraft] = useState<CommentComposerState | null>(null);\n  const [footnoteOpen, setFootnoteOpen] = useState(false);\n  const footnoteSelectionRef = useRef<{ from: number; to: number } | null>(null);\n  const commentDraftRef = useRef<CommentComposerState | null>(null);\n  commentDraftRef.current = commentDraft;\n  const savedSelectionRef = useRef<{ from: number; to: number } | null>(null);\n  const fontTriggerRef = useRef<HTMLButtonElement | null>(null);\n  const fontCommitRef = useRef('Inter');\n  const [fontOpen, setFontOpen] = useState(false);\n  const [tableOpen, setTableOpen] = useState(false);\n  const [linkOpen, setLinkOpen] = useState(false);\n  const [linkInitialUrl, setLinkInitialUrl] = useState('');\n  const [isReadingAloud, setIsReadingAloud] = useState(false);\n  const pageContentWrapRef = useRef<HTMLDivElement | null>(null);\n  /** Outer page stack height rounded up to full page sheets (A4, Letter, \u2026). */\n  const [pageStackMinH, setPageStackMinH] = useState(0);\n\n  // Default to A4 if no project or project has no pageSize\n  const pageSize = TEXT_PAGE_SIZES.find((p) => p.id === (activeProject?.pageSize ?? 'a4'))\n    ?? TEXT_PAGE_SIZES.find((p) => p.id === 'a4')\n    ?? TEXT_PAGE_SIZES[0];\n  const orientation = activeProject?.orientation ?? 'portrait';\n  const isLandscape  = orientation === 'landscape';\n  const orientationClass = isLandscape ? 'landscape' : 'portrait';\n\n  const pageWidthMm  = isLandscape ? pageSize.heightMm : pageSize.widthMm;\n  const pageHeightMm = isLandscape ? pageSize.widthMm  : pageSize.heightMm;\n  const customMargins = (activeProject as { customMarginsMm?: { top: number; right: number; bottom: number; left: number } } | null)?.customMarginsMm;\n  const marginMm = customMargins ?? pageSize.marginMm;\n  const MM_TO_PX = 3.7795275591;\n  const pageWidthPx  = Math.round(pageWidthMm  * MM_TO_PX);\n  const pageHeightPx = Math.round(pageHeightMm * MM_TO_PX);\n  const marginPx = {\n    top:    Math.round(marginMm.top    * MM_TO_PX),\n    right:  Math.round(marginMm.right  * MM_TO_PX),\n    bottom: Math.round(marginMm.bottom * MM_TO_PX),\n    left:   Math.round(marginMm.left   * MM_TO_PX),\n  };\n\n  // Mutable ref read by the page-break plugin \u2014 keeps plugin stable across re-renders\n  const pageBreakConfigRef = useRef({\n    pageHeightPx,\n    marginTopPx:    marginPx.top,\n    marginBottomPx: marginPx.bottom,\n  });\n  useEffect(() => {\n    pageBreakConfigRef.current = {\n      pageHeightPx,\n      marginTopPx:    marginPx.top,\n      marginBottomPx: marginPx.bottom,\n    };\n  }, [pageHeightPx, marginPx.top, marginPx.bottom]);\n\n  // Create page-break plugin once; it reads from the ref at runtime\n  const pageBreakExtension = useMemo(\n    () =>\n      Extension.create({\n        name: 'pageBreakExt',\n        addProseMirrorPlugins: () => [createPageBreakPlugin(pageBreakConfigRef)],\n      }),\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n    [] // stable \u2014 plugin reads from ref\n  );\n\n  const onSlashAiOp = useCallback(async (op: SlashAiOp) => {\n    const editor = _editorRef;\n    if (!editor) return;\n    const store = useTextStore.getState();\n    const { from, to } = editor.state.selection;\n    const selected =\n      from !== to\n        ? editor.state.doc.textBetween(from, to, ' ')\n        : getDocPlainText(editor.getJSON()).slice(0, 2000);\n\n    if (op === 'comment') {\n      if (from === to) {\n        store.addToast(tc.toasts.selectText, 'warning');\n        return;\n      }\n      const view = editor.view;\n      const coords = view.coordsAtPos(to);\n      setCommentDraft({\n        from,\n        to,\n        quote: selected.slice(0, 160),\n        x: coords.left,\n        y: coords.bottom,\n      });\n      return;\n    }\n    if (op === 'claim') {\n      if (!selected.trim()) {\n        store.addToast(c.selectTextFirst, 'warning');\n        return;\n      }\n      const id = store.addClaim(selected, 'needs_citation');\n      if (from !== to) {\n        editor\n          .chain()\n          .focus()\n          .setCommentMark({ id, note: tClaims.claimNeedsCitation })\n          .run();\n      }\n      store.setRightTab('claims');\n      return;\n    }\n\n    try {\n      const mapped =\n        op === 'rewrite' ? 'elevate' : op === 'tighten' ? 'tighten' : 'expand';\n      const res = await runSectionOp({\n        text: selected,\n        op: mapped,\n      });\n      const id = store.addSuggestion({\n        kind: op === 'rewrite' ? 'rewrite' : op,\n        original: selected.slice(0, 500),\n        replacement: res.text,\n        rationale: res.rationale || op,\n      });\n      if (from !== to) {\n        editor\n          .chain()\n          .focus()\n          .setAiSuggestion({\n            id,\n            kind: op,\n            original: selected.slice(0, 500),\n            replacement: res.text,\n            rationale: res.rationale || '',\n          })\n          .run();\n      }\n      useTextUiStore.getState().setSuggestionsModalOpen(true);\n      store.addToast(c.suggestionReady, 'success');\n    } catch (err) {\n      store.addToast(err instanceof Error ? err.message : tr.text.ai.toasts.generic, 'error');\n    }\n  }, [c.selectTextFirst, c.suggestionReady, tc.toasts.selectText, tClaims.claimNeedsCitation, tr.text.ai.toasts.generic]);\n\n  useEffect(() => {\n    _slashAiHandler = (op) => {\n      void onSlashAiOp(op);\n    };\n    return () => {\n      _slashAiHandler = null;\n    };\n  }, [onSlashAiOp]);\n\n  const editor = useEditor({\n    immediatelyRender: false,\n    extensions: [\n      ...createTextExtensions({\n        onSlashAiOp: (op) => _slashAiHandler?.(op),\n        calloutDefaultText: c.calloutDefault,\n        slashCalloutTitle: c.callout,\n        slashCalloutDescription: c.calloutSlashHint,\n        linkOpenHint: c.linkOpenHint,\n      }),\n      pageBreakExtension,\n    ],\n    content: doc,\n    editable,\n    editorProps: {\n      attributes: {\n        class:\n          'we-text-prose prose max-w-none focus:outline-none text-[15px] leading-relaxed text-black',\n      },\n      transformPastedHTML: (html) => cleanPastedHtml(html),\n      handleClick: (view, _pos, event) => {\n        if (event.button !== 0) return false;\n        if (!(event.ctrlKey || event.metaKey)) return false;\n        const target = event.target as HTMLElement | null;\n        const anchor = target?.closest?.('a');\n        if (!anchor || !view.dom.contains(anchor)) return false;\n        const href = anchor.getAttribute('href');\n        if (!href) return false;\n        event.preventDefault();\n        window.open(href, '_blank', 'noopener,noreferrer');\n        return true;\n      },\n    },\n    onUpdate: ({ editor: ed }) => {\n      setDocFromEditor(ed.getJSON());\n    },\n    onSelectionUpdate: () => {\n      // Sticky toolbar + BubbleMenu handle selection chrome (no floating comment chip).\n    },\n  });\n\n  // Keep native title in sync with locale (extension HTMLAttributes are fixed at init).\n  useEffect(() => {\n    if (!editor || editor.isDestroyed) return;\n    const hint = c.linkOpenHint;\n    const syncTitles = () => {\n      if (!editor || editor.isDestroyed) return;\n      // view.dom throws until EditorContent has mounted the ProseMirror view\n      try {\n        if (!editor.view) return;\n        editor.view.dom.querySelectorAll('a[href]').forEach((el) => {\n          el.setAttribute('title', hint);\n        });\n      } catch {\n        /* not mounted yet */\n      }\n    };\n    const raf = requestAnimationFrame(syncTitles);\n    editor.on('create', syncTitles);\n    editor.on('update', syncTitles);\n    return () => {\n      cancelAnimationFrame(raf);\n      if (!editor.isDestroyed) {\n        editor.off('create', syncTitles);\n        editor.off('update', syncTitles);\n      }\n    };\n  }, [editor, c.linkOpenHint]);\n\n  // Sync TipTap when project switches OR store doc changes externally (restore/import/AI).\n  useEffect(() => {\n    if (!editor || editor.isDestroyed) return;\n    try {\n      if (!editor.view) return;\n      const current = JSON.stringify(editor.getJSON());\n      const next = JSON.stringify(doc);\n      if (current !== next) {\n        editor.commands.setContent(doc, { emitUpdate: false });\n      }\n    } catch {\n      /* view/commands not ready (e.g. mode switch / unmount race) */\n    }\n  }, [activeId, doc, editor]);\n\n  useEffect(() => {\n    if (!editor || editor.isDestroyed) return;\n    try {\n      editor.setEditable(editable);\n    } catch {\n      /* destroyed mid-switch */\n    }\n  }, [editor, editable]);\n\n  // Keep the page sheet tall enough to show a full last page (not a growing stub).\n  useEffect(() => {\n    const wrap = pageContentWrapRef.current;\n    if (!wrap || !editor || editor.isDestroyed) return;\n\n    const period = pageHeightPx + PAGE_GAP_PX;\n    const syncMinHeight = () => {\n      if (editor.isDestroyed) return;\n      const contentH = wrap.scrollHeight;\n      const pages = Math.max(1, Math.ceil(contentH / period));\n      const fullH = pages * pageHeightPx + (pages - 1) * PAGE_GAP_PX;\n      setPageStackMinH((prev) => (prev === fullH ? prev : fullH));\n    };\n\n    syncMinHeight();\n    const ro = new ResizeObserver(syncMinHeight);\n    ro.observe(wrap);\n    // Also remeasure after ProseMirror page-gap decorations settle.\n    const onUpdate = () => requestAnimationFrame(syncMinHeight);\n    editor.on('update', onUpdate);\n    editor.on('selectionUpdate', onUpdate);\n    return () => {\n      ro.disconnect();\n      if (!editor.isDestroyed) {\n        editor.off('update', onUpdate);\n        editor.off('selectionUpdate', onUpdate);\n      }\n    };\n  }, [pageHeightPx, editor]);\n\n  // Refresh brand term decorations when preferred/forbidden lists change\n  const preferredKey = useTextStore((s) => s.brandVoice.preferredTerms.join('\\0'));\n  const forbiddenKey = useTextStore((s) => s.brandVoice.forbiddenTerms.join('\\0'));\n  useEffect(() => {\n    if (!editor || editor.isDestroyed) return;\n    try {\n      if (!editor.view) return;\n      const { tr } = editor.state;\n      tr.setMeta('brandHighlight', true);\n      editor.view.dispatch(tr);\n    } catch {\n      /* view not ready */\n    }\n  }, [editor, preferredKey, forbiddenKey]);\n\n  const saveCommentDraft = useCallback(\n    (note: string) => {\n      if (!editor || !commentDraft) return;\n      const store = useTextStore.getState();\n      const id = store.addComment(note, commentDraft.quote, true);\n      editor\n        .chain()\n        .focus()\n        .setTextSelection({ from: commentDraft.from, to: commentDraft.to })\n        .setCommentMark({ id, note })\n        .run();\n      store.setRightTab('comments');\n      store.addToast(tc.toasts.anchored, 'success');\n      setCommentDraft(null);\n    },\n    [commentDraft, editor, tc.toasts.anchored],\n  );\n\n  const readAloud = () => {\n    if (!editor || typeof window === 'undefined' || !('speechSynthesis' in window)) {\n      addToast(c.readAloudUnavailable, 'warning');\n      return;\n    }\n    const synth = window.speechSynthesis;\n    if (isReadingAloud || synth.speaking || synth.pending) {\n      synth.cancel();\n      setIsReadingAloud(false);\n      return;\n    }\n    const { from, to } = editor.state.selection;\n    const text =\n      from !== to\n        ? editor.state.doc.textBetween(from, to, ' ')\n        : editor.state.doc.textContent;\n    if (!text.trim()) {\n      addToast(c.selectTextFirst, 'warning');\n      return;\n    }\n    // Chrome often returns [] until voiceschanged; warm the list first.\n    void synth.getVoices();\n    const u = new SpeechSynthesisUtterance(text.slice(0, 4000));\n    u.lang = useTextStore.getState().language === 'en' ? 'en-US' : 'es-ES';\n    u.onend = () => setIsReadingAloud(false);\n    u.onerror = () => setIsReadingAloud(false);\n    setIsReadingAloud(true);\n    synth.cancel();\n    window.setTimeout(() => {\n      synth.speak(u);\n      // Some Chromium builds start paused until resume().\n      if (synth.paused) synth.resume();\n    }, 50);\n  };\n\n  const openLinkModal = () => {\n    if (!editor) return;\n    const previousUrl = String(editor.getAttributes('link').href || '');\n    setLinkInitialUrl(previousUrl);\n    setLinkOpen(true);\n  };\n\n  const clearLinkMarks = () => {\n    if (!editor) return;\n    // Legacy applies baked #0ea5e9 + underline into marks; strip those with the link.\n    const color = String(editor.getAttributes('textStyle').color || '')\n      .trim()\n      .toLowerCase();\n    let chain = editor.chain().focus().extendMarkRange('link').unsetLink().unsetUnderline();\n    if (color === '#0ea5e9') chain = chain.unsetColor();\n    chain.run();\n  };\n\n  const applyLinkUrl = (url: string) => {\n    if (!editor) return;\n    if (!url) {\n      clearLinkMarks();\n      return;\n    }\n    // Appearance comes from `.we-text-prose a` CSS so unsetLink alone clears the look.\n    editor.chain().focus().extendMarkRange('link').setLink({ href: url }).run();\n  };\n\n  const removeLink = () => {\n    clearLinkMarks();\n  };\n\n  if (!editor) {\n    return (\n      <TextBody as=\"div\" size=\"sm\" className=\"flex-1 flex items-center justify-center text-white/80\">{c.loading}</TextBody>\n    );\n  }\n\n  const currentFont = resolveFontFamily(editor.getAttributes('textStyle').fontFamily);\n  const currentSize = parseInt(editor.getAttributes('textStyle').fontSize || '15', 10);\n  const currentColor =\n    String(editor.getAttributes('textStyle').color || '').trim() || '#111827';\n  const currentHighlight = String(editor.getAttributes('highlight').color || '').trim() || '#FFD54F';\n  const blockType = editor.isActive('heading', { level: 1 })\n    ? 'h1'\n    : editor.isActive('heading', { level: 2 })\n      ? 'h2'\n      : editor.isActive('heading', { level: 3 })\n        ? 'h3'\n        : editor.isActive('heading', { level: 4 })\n          ? 'h4'\n          : editor.isActive('heading', { level: 5 })\n            ? 'h5'\n            : 'p';\n\n  const withSelection = (fn: () => void) => {\n    const saved = savedSelectionRef.current;\n    if (saved) {\n      editor.commands.setTextSelection({ from: saved.from, to: saved.to });\n    }\n    fn();\n    savedSelectionRef.current = null;\n  };\n\n  const applyTextColor = (hex: string) => {\n    withSelection(() => {\n      editor.chain().focus().setColor(hex).run();\n    });\n  };\n\n  const applyHighlightColor = (hex: string) => {\n    withSelection(() => {\n      editor.chain().focus().setHighlight({ color: hex }).run();\n    });\n  };\n\n  return (\n      <div className=\"we-text-canvas flex-1 min-h-0 overflow-y-auto\">\n        <div\n          className=\"sticky top-0 z-10 flex flex-wrap items-center gap-1 border-b border-panel-border bg-[#0A0A0F] px-3 py-1.5\"\n          onMouseDown={() => {\n            const { from, to } = editor.state.selection;\n            savedSelectionRef.current = { from, to };\n          }}\n        >\n          <button\n            ref={fontTriggerRef}\n            type=\"button\"\n            title={c.fontLabel}\n            onMouseDown={(e) => {\n              e.preventDefault();\n              const { from, to } = editor.state.selection;\n              savedSelectionRef.current = { from, to };\n              fontCommitRef.current = currentFont;\n              setFontOpen((v) => !v);\n            }}\n            className=\"inline-flex h-8 w-[12rem] shrink-0 items-center gap-1.5 rounded-xl bg-black-capsule px-2.5 text-white hover:bg-black-capsule-hover\"\n          >\n            <TextBody as=\"span\" size=\"sm\" className=\"min-w-0 flex-1 truncate\">\n              {currentFont}\n            </TextBody>\n            <ChevronDown\n              size={12}\n              strokeWidth={2.25}\n              className={`shrink-0 text-white/80 transition-transform ${fontOpen ? 'rotate-180' : ''}`}\n            />\n          </button>\n          <FontPickerFlyout\n            open={fontOpen}\n            onClose={() => setFontOpen(false)}\n            anchorRef={fontTriggerRef}\n            value={fontCommitRef.current}\n            fonts={GOOGLE_FONTS_CATALOG}\n            searchPlaceholder={c.fontLabel}\n            onPreview={(name) => {\n              const family = name ?? fontCommitRef.current;\n              ensureGoogleFont(family);\n              const saved = savedSelectionRef.current;\n              const chain = editor.chain().focus();\n              if (saved) {\n                chain.setTextSelection({ from: saved.from, to: saved.to });\n              }\n              chain.setFontFamily(family).run();\n            }}\n            onSelect={(name) => {\n              fontCommitRef.current = name;\n              ensureGoogleFont(name);\n              const saved = savedSelectionRef.current;\n              const chain = editor.chain().focus();\n              if (saved) {\n                chain.setTextSelection({ from: saved.from, to: saved.to });\n              }\n              chain.setFontFamily(name).run();\n              savedSelectionRef.current = null;\n              setFontOpen(false);\n            }}\n          />\n\n          <div className=\"inline-flex h-8 w-[5rem] shrink-0 items-center rounded-xl bg-black-capsule\">\n            <SelectDropdown\n              className=\"w-full\"\n              value={String(currentSize)}\n              options={(() => {\n                const sizes = FONT_SIZES.includes(currentSize)\n                  ? FONT_SIZES\n                  : [...FONT_SIZES, currentSize].sort((a, b) => a - b);\n                return sizes.map((n) => ({ value: String(n), label: `${n}` }));\n              })()}\n              onChange={(v) => {\n                const px = Math.max(8, Math.min(144, parseInt(v, 10) || 15));\n                withSelection(() => {\n                  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n                  (editor.chain().focus() as any).setFontSize(`${px}px`).run();\n                });\n              }}\n              ariaLabel={c.fontSize}\n            />\n          </div>\n\n          <ColorPickerBtn\n            value={currentColor}\n            onChange={applyTextColor}\n            title={c.textColor}\n          />\n          <HighlightColorBtn\n            value={currentHighlight}\n            onChange={applyHighlightColor}\n            title={c.highlightColor}\n          />\n\n          <div className=\"mx-0.5 h-4 w-px bg-panel-border\" aria-hidden />\n\n          <div className=\"inline-flex h-8 w-[9rem] shrink-0 items-center rounded-xl bg-black-capsule\">\n            <SelectDropdown\n              className=\"w-full\"\n              value={blockType}\n              options={[\n                { value: 'p', label: c.paragraph },\n                { value: 'h1', label: c.h1 },\n                { value: 'h2', label: c.h2 },\n                { value: 'h3', label: c.h3 },\n                { value: 'h4', label: c.h4 },\n                { value: 'h5', label: c.h5 },\n              ]}\n              onChange={(v) => {\n                withSelection(() => {\n                  const chain = editor.chain().focus();\n                  if (v === 'p') chain.setParagraph().run();\n                  else chain.toggleHeading({ level: Number(v.slice(1)) as 1 | 2 | 3 | 4 | 5 }).run();\n                });\n              }}\n              ariaLabel={c.paragraph}\n            />\n          </div>\n\n          <div className=\"mx-0.5 h-4 w-px bg-panel-border\" aria-hidden />\n\n          <IconButton\n            variant=\"ghost\"\n            size=\"sm\"\n            label={c.bold}\n            active={editor.isActive('bold')}\n            onMouseDown={(e) => e.preventDefault()}\n            onClick={() => editor.chain().focus().toggleBold().run()}\n          >\n            <Bold size={14} />\n          </IconButton>\n          <IconButton\n            variant=\"ghost\"\n            size=\"sm\"\n            label={c.italic}\n            active={editor.isActive('italic')}\n            onMouseDown={(e) => e.preventDefault()}\n            onClick={() => editor.chain().focus().toggleItalic().run()}\n          >\n            <Italic size={14} />\n          </IconButton>\n          <IconButton\n            variant=\"ghost\"\n            size=\"sm\"\n            label={c.strike}\n            active={editor.isActive('strike')}\n            onMouseDown={(e) => e.preventDefault()}\n            onClick={() => editor.chain().focus().toggleStrike().run()}\n          >\n            <Strikethrough size={14} />\n          </IconButton>\n\n          <div className=\"mx-0.5 h-4 w-px bg-panel-border\" aria-hidden />\n\n          <IconButton\n            variant=\"ghost\"\n            size=\"sm\"\n            label={c.bulletList}\n            active={editor.isActive('bulletList')}\n            onMouseDown={(e) => e.preventDefault()}\n            onClick={() => {\n              withSelection(() => {\n                editor.chain().focus().toggleBulletList().run();\n              });\n            }}\n          >\n            <List size={14} />\n          </IconButton>\n          <IconButton\n            variant=\"ghost\"\n            size=\"sm\"\n            label={c.orderedList}\n            active={editor.isActive('orderedList')}\n            onMouseDown={(e) => e.preventDefault()}\n            onClick={() => {\n              withSelection(() => {\n                editor.chain().focus().toggleOrderedList().run();\n              });\n            }}\n          >\n            <ListOrdered size={14} />\n          </IconButton>\n\n          <div className=\"mx-0.5 h-4 w-px bg-panel-border\" aria-hidden />\n\n          <IconButton\n            variant=\"ghost\"\n            size=\"sm\"\n            label={c.alignLeft}\n            active={editor.isActive({ textAlign: 'left' })}\n            onMouseDown={(e) => e.preventDefault()}\n            onClick={() => editor.chain().focus().setTextAlign('left').run()}\n          >\n            <AlignLeft size={14} />\n          </IconButton>\n          <IconButton\n            variant=\"ghost\"\n            size=\"sm\"\n            label={c.alignCenter}\n            active={editor.isActive({ textAlign: 'center' })}\n            onMouseDown={(e) => e.preventDefault()}\n            onClick={() => editor.chain().focus().setTextAlign('center').run()}\n          >\n            <AlignCenter size={14} />\n          </IconButton>\n          <IconButton\n            variant=\"ghost\"\n            size=\"sm\"\n            label={c.alignRight}\n            active={editor.isActive({ textAlign: 'right' })}\n            onMouseDown={(e) => e.preventDefault()}\n            onClick={() => editor.chain().focus().setTextAlign('right').run()}\n          >\n            <AlignRight size={14} />\n          </IconButton>\n          <IconButton\n            variant=\"ghost\"\n            size=\"sm\"\n            label={c.alignJustify}\n            active={editor.isActive({ textAlign: 'justify' })}\n            onMouseDown={(e) => e.preventDefault()}\n            onClick={() => editor.chain().focus().setTextAlign('justify').run()}\n          >\n            <AlignJustify size={14} />\n          </IconButton>\n\n          <div className=\"mx-0.5 h-4 w-px bg-panel-border\" aria-hidden />\n\n          <IconButton\n            variant=\"ghost\"\n            size=\"sm\"\n            label={c.link}\n            active={editor.isActive('link') || linkOpen}\n            onMouseDown={(e) => e.preventDefault()}\n            onClick={openLinkModal}\n          >\n            <LinkIcon size={14} />\n          </IconButton>\n\n          <IconButton\n            variant=\"ghost\"\n            size=\"sm\"\n            label={c.table}\n            active={editor.isActive('table') || tableOpen}\n            onMouseDown={(e) => e.preventDefault()}\n            onClick={() => setTableOpen(true)}\n          >\n            <TableIcon size={14} />\n          </IconButton>\n\n          <IconButton\n            variant=\"ghost\"\n            size=\"sm\"\n            label={isReadingAloud ? c.readAloudStop : c.readAloudTitle}\n            active={isReadingAloud}\n            onMouseDown={(e) => e.preventDefault()}\n            onClick={readAloud}\n          >\n            <Volume2 size={14} />\n          </IconButton>\n        </div>\n      <BubbleMenu editor={editor}>\n        <div\n          className=\"flex max-w-[320px] flex-wrap items-center gap-0.5 rounded-lg border border-panel-border bg-panel p-1 shadow-xl\"\n          onMouseDown={(e) => e.preventDefault()}\n        >\n          <MenuBtn\n            onClick={() => editor.chain().focus().indent().run()}\n            title={c.indent}\n          >\n            <Indent size={12} />\n          </MenuBtn>\n          <MenuBtn\n            onClick={() => editor.chain().focus().outdent().run()}\n            title={c.outdent}\n          >\n            <Outdent size={12} />\n          </MenuBtn>\n          <BtnSep />\n          <MenuBtn\n            active={editor.isActive('blockquote')}\n            onClick={() => editor.chain().focus().toggleBlockquote().run()}\n            title={c.blockquote}\n          >\n            <Quote size={12} />\n          </MenuBtn>\n          <MenuBtn\n            onClick={() => editor.chain().focus().setCallout().run()}\n            title={c.callout}\n          >\n            <Quote size={12} className=\"opacity-70\" />\n          </MenuBtn>\n          <MenuBtn\n            active={editor.isActive('superscript')}\n            onClick={() => editor.chain().focus().toggleSuperscript().run()}\n            title={c.superscript}\n          >\n            <Superscript size={12} />\n          </MenuBtn>\n          <BtnSep />\n          <MenuBtn\n            onClick={() => void onSlashAiOp('comment')}\n            title={c.comment}\n          >\n            <MessageSquarePlus size={12} />\n          </MenuBtn>\n          <MenuBtn\n            onClick={() => {\n              const { from, to } = editor.state.selection;\n              footnoteSelectionRef.current = { from, to };\n              setFootnoteOpen(true);\n            }}\n            title={c.footnote}\n          >\n            <Superscript size={12} />\n          </MenuBtn>\n        </div>\n      </BubbleMenu>\n\n      {/*\n        \u2500\u2500 Multi-page canvas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n        Visual structure\n        \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        \u2022 Outer div: dark background (#16161f). Acts as the \"paper table\".\n        \u2022 Inner div: the actual page container \u2014 white background.\n          CSS repeating-linear-gradient paints:\n            - white  (0 \u2192 pageHeightPx)        : one page\n            - #16161f (pageHeightPx \u2192 pageHeightPx+GAP) : inter-page gap\n          Period = pageHeightPx + PAGE_GAP_PX.\n        \u2022 ProseMirror plugin inserts transparent spacers at page breaks\n          so text never flows into the margin/gap area.\n        \u2022 Margin guide lines are drawn via pointer-events:none overlays that\n          use a repeating gradient \u2014 they NEVER cover text (z-index < z-0).\n        \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n      <div\n        className=\"we-text-page-stack flex-1 min-h-0 overflow-y-auto\"\n        style={{ background: '#16161f' }}\n      >\n        <div className=\"flex flex-col items-center py-10 pb-32\">\n          <div\n            data-orientation={orientationClass}\n            className=\"relative\"\n            style={{\n              width:  pageWidthPx,\n              minHeight: Math.max(pageHeightPx, pageStackMinH || pageHeightPx),\n              /*\n               * White page background with dark inter-page gap.\n               * Period = pageHeightPx + PAGE_GAP_PX.\n               * Everything within [0, pageHeightPx] is pure white.\n               * [pageHeightPx, pageHeightPx+GAP] is the dark gap visible\n               * through the transparent spacer decorations.\n               */\n              backgroundImage: [\n                `linear-gradient(to bottom,`,\n                `  #ffffff 0px,`,\n                `  #ffffff ${pageHeightPx}px,`,\n                `  #16161f ${pageHeightPx}px,`,\n                `  #16161f ${pageHeightPx + PAGE_GAP_PX}px`,\n                `)`,\n              ].join(''),\n              backgroundSize:   `100% ${pageHeightPx + PAGE_GAP_PX}px`,\n              backgroundRepeat: 'repeat-y',\n              // Subtle shadow per page: bottom of each white section gets a drop shadow\n              boxShadow: '0 4px 24px rgba(0,0,0,0.55), 0 1px 0 rgba(0,0,0,0.15)',\n            }}\n            onContextMenu={(e) => {\n              e.preventDefault();\n              setCtxMenu({ x: e.clientX, y: e.clientY });\n            }}\n          >\n            {/* Margin guide lines \u2014 CSS background, pointer-events:none, never covers text */}\n            {showMargins && (\n              <div\n                className=\"pointer-events-none absolute inset-0\"\n                style={{\n                  zIndex: 0,\n                  backgroundImage: [\n                    // 1. Left margin rule\n                    `linear-gradient(to right,`,\n                    `  transparent ${marginPx.left - 1}px,`,\n                    `  rgba(148,163,184,0.4) ${marginPx.left - 1}px,`,\n                    `  rgba(148,163,184,0.4) ${marginPx.left}px,`,\n                    `  transparent ${marginPx.left}px),`,\n                    // 2. Right margin rule\n                    `linear-gradient(to left,`,\n                    `  transparent ${marginPx.right - 1}px,`,\n                    `  rgba(148,163,184,0.4) ${marginPx.right - 1}px,`,\n                    `  rgba(148,163,184,0.4) ${marginPx.right}px,`,\n                    `  transparent ${marginPx.right}px),`,\n                    // 3. Top margin rule (repeating, one per page)\n                    `linear-gradient(to bottom,`,\n                    `  rgba(148,163,184,0.4) 0px,`,\n                    `  rgba(148,163,184,0.4) 1px,`,\n                    `  transparent 1px),`,\n                    // 4. Bottom margin rule (repeating, one per page)\n                    `linear-gradient(to bottom,`,\n                    `  rgba(148,163,184,0.4) 0px,`,\n                    `  rgba(148,163,184,0.4) 1px,`,\n                    `  transparent 1px)`,\n                  ].join(''),\n                  // Each layer's background-size\n                  backgroundSize: [\n                    `100% 100%`,       // left rule  (full height)\n                    `, 100% 100%`,     // right rule (full height)\n                    `, 100% ${pageHeightPx + PAGE_GAP_PX}px`, // top rule  repeats per page\n                    `, 100% ${pageHeightPx + PAGE_GAP_PX}px`, // bottom rule repeats per page\n                  ].join(''),\n                  // Each layer's background-position\n                  backgroundPosition: [\n                    `0 0`,             // left rule  starts at top-left\n                    `, 0 0`,           // right rule starts at top-right\n                    `, 0 ${marginPx.top}px`, // top guide at marginTop from page top\n                    `, 0 ${pageHeightPx - marginPx.bottom}px`, // bottom guide at (pageH - marginBottom)\n                  ].join(''),\n                  backgroundRepeat: 'no-repeat, no-repeat, repeat-y, repeat-y',\n                }}\n              />\n            )}\n\n            {/* Editor content \u2014 z-index 1, always above guide overlays */}\n            <div\n              ref={pageContentWrapRef}\n              className=\"relative\"\n              style={{\n                zIndex:      1,\n                paddingTop:  marginPx.top,\n                paddingRight: marginPx.right,\n                paddingLeft:  marginPx.left,\n                '--we-text-page-margin-left': `${marginPx.left}px`,\n                '--we-text-page-margin-right': `${marginPx.right}px`,\n              } as React.CSSProperties}\n            >\n              <EditorContent editor={editor} />\n              {/* Final spacer: ensure last page is fully visible when scrolled */}\n              <div style={{ height: marginPx.bottom }} />\n            </div>\n          </div>\n        </div>\n      </div>\n\n      {ctxMenu && editor && (\n        <TextContextMenu\n          editor={editor}\n          menu={ctxMenu}\n          onClose={() => setCtxMenu(null)}\n          onComment={() => {\n            // Capture selection before the menu unmounts / blurs the editor.\n            void onSlashAiOp('comment');\n          }}\n        />\n      )}\n\n      {commentDraft && (\n        <TextCommentComposer\n          draft={commentDraft}\n          onClose={() => setCommentDraft(null)}\n          onSave={saveCommentDraft}\n        />\n      )}\n\n      <TextLinkModal\n        open={linkOpen}\n        onClose={() => setLinkOpen(false)}\n        initialUrl={linkInitialUrl}\n        hasExistingLink={Boolean(linkInitialUrl)}\n        onSave={applyLinkUrl}\n        onRemove={removeLink}\n      />\n\n      <TextFootnoteModal\n        open={footnoteOpen}\n        onClose={() => {\n          setFootnoteOpen(false);\n          footnoteSelectionRef.current = null;\n        }}\n        onSave={(note) => {\n          const sel = footnoteSelectionRef.current;\n          if (!sel) return;\n          const { from, to } = sel;\n          if (from === to) {\n            editor\n              .chain()\n              .focus()\n              .insertContent({\n                type: 'text',\n                text: '[n]',\n                marks: [{ type: 'footnote', attrs: { note } }],\n              })\n              .run();\n          } else {\n            editor\n              .chain()\n              .focus()\n              .setTextSelection({ from, to })\n              .setFootnote({ note })\n              .run();\n          }\n          footnoteSelectionRef.current = null;\n        }}\n      />\n\n      <TextTableModal\n        open={tableOpen}\n        onClose={() => setTableOpen(false)}\n        editing={editor.isActive('table')}\n        onInsert={(rows, cols) => {\n          const saved = savedSelectionRef.current;\n          const chain = editor.chain().focus();\n          if (saved) {\n            chain.setTextSelection({ from: saved.from, to: saved.to });\n          }\n          const ok = chain\n            .insertTable({ rows, cols, withHeaderRow: true })\n            .run();\n          savedSelectionRef.current = null;\n          if (!ok) {\n            addToast(c.tableInsertFailed, 'warning');\n          }\n        }}\n        onAddRow={() => editor.chain().focus().addRowAfter().run()}\n        onDelRow={() => editor.chain().focus().deleteRow().run()}\n        onAddCol={() => editor.chain().focus().addColumnAfter().run()}\n        onDelCol={() => editor.chain().focus().deleteColumn().run()}\n        onDeleteTable={() => editor.chain().focus().deleteTable().run()}\n      />\n\n      <EditorBridge editor={editor} />\n    </div>\n  );\n};\n\nfunction MenuBtn({\n  children,\n  active,\n  onClick,\n  title,\n}: {\n  children: React.ReactNode;\n  active?: boolean;\n  onClick: () => void;\n  title: string;\n}) {\n  return (\n    <button\n      type=\"button\"\n      title={title}\n      onClick={onClick}\n      className={`w-7 h-7 rounded flex items-center justify-center ${\n        active ? 'bg-[var(--we-accent)] text-white' : 'text-white/80 hover:bg-black-capsule'\n      }`}\n    ><TextBody as=\"span\" size=\"sm\">{children}</TextBody></button>\n  );\n}\n\nfunction BtnSep() {\n  return <div className=\"w-px h-5 bg-panel-border mx-0.5\" aria-hidden />;\n}\n\nfunction ColorPickerBtn({\n  value,\n  onChange,\n  title,\n}: {\n  value: string;\n  onChange: (color: string) => void;\n  title: string;\n}) {\n  const swatch = value || '#000000';\n  return (\n    <label\n      className=\"relative flex h-7 w-7 cursor-pointer items-center justify-center rounded-lg border border-panel-border bg-black-capsule hover:border-[var(--we-accent)]\"\n      title={title}\n    >\n      <span\n        className=\"h-3.5 w-3.5 rounded-sm\"\n        style={{ background: swatch }}\n        aria-hidden\n      />\n      <input\n        type=\"color\"\n        value={/^#[0-9a-fA-F]{6}$/.test(value) ? value : '#000000'}\n        onChange={(e) => onChange(e.target.value)}\n        className=\"absolute inset-0 h-full w-full cursor-pointer opacity-0\"\n      />\n    </label>\n  );\n}\n\nfunction HighlightColorBtn({\n  value,\n  onChange,\n  title,\n}: {\n  value: string;\n  onChange: (color: string) => void;\n  title: string;\n}) {\n  return (\n    <label\n      className=\"relative flex h-7 w-7 cursor-pointer items-center justify-center rounded-lg border border-dashed border-panel-border bg-black-capsule text-white/80 hover:border-[var(--we-accent)] hover:text-white\"\n      title={title}\n    >\n      <Highlighter size={12} />\n      <input\n        type=\"color\"\n        value={/^#[0-9a-fA-F]{6}$/.test(value) ? value : '#FFD54F'}\n        onChange={(e) => onChange(e.target.value)}\n        className=\"absolute inset-0 h-full w-full cursor-pointer opacity-0\"\n      />\n    </label>\n  );\n}\n\nlet _editorRef: Editor | null = null;\n\nexport function getActiveTextEditor(): Editor | null {\n  const ed = _editorRef;\n  if (!ed || ed.isDestroyed) return null;\n  return ed;\n}\n\n/** Register the live TipTap instance for panels/agent (sync + layout). */\nconst EditorBridge: React.FC<{ editor: Editor }> = ({ editor }) => {\n  // Keep ref current during render so clicks in side panels never race useEffect.\n  if (!editor.isDestroyed && _editorRef !== editor) {\n    _editorRef = editor;\n  }\n  React.useLayoutEffect(() => {\n    if (!editor.isDestroyed) _editorRef = editor;\n    return () => {\n      if (_editorRef === editor) _editorRef = null;\n    };\n  }, [editor]);\n  return null;\n};\n", "import React from 'react';\nimport { useTextStore } from '../../store/useTextStore';\nimport { getActiveTextEditor } from './DocumentCanvas';\nimport { useTranslation } from '../../i18n';\nimport { PanelBody, PanelSection, TextBody } from '../ui';\n\nexport const OutlinePanel: React.FC = () => {\n  const tr = useTranslation();\n  const outline = useTextStore((s) => s.outline);\n\n  const jumpTo = (index: number) => {\n    const editor = getActiveTextEditor();\n    if (!editor) return;\n    let headingIdx = -1;\n    editor.state.doc.descendants((node, pos) => {\n      if (node.type.name === 'heading') {\n        headingIdx += 1;\n        if (headingIdx === index) {\n          editor.chain().focus().setTextSelection(pos + 1).run();\n          return false;\n        }\n      }\n      return true;\n    });\n  };\n\n  return (\n    <PanelBody className=\"we-text-outline h-full overflow-y-auto\">\n      <PanelSection>\n        {outline.length === 0 ? (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n            {tr.text.outline.empty}\n          </TextBody>\n        ) : (\n          <ul className=\"space-y-0.5\">\n            {outline.map((item) => (\n              <li key={item.id}>\n                <button\n                  type=\"button\"\n                  onClick={() => jumpTo(item.index)}\n                  className=\"w-full truncate rounded-lg px-1 py-1 text-left text-white/80 hover:bg-black-capsule hover:text-white\"\n                  style={{ paddingLeft: 4 + (item.level - 1) * 10 }}\n                >\n                  <TextBody as=\"span\" size=\"sm\" className=\"mr-1 text-white/50\">\n                    H{item.level}\n                  </TextBody>\n                  <TextBody as=\"span\" size=\"sm\">\n                    {item.text || '\u2026'}\n                  </TextBody>\n                </button>\n              </li>\n            ))}\n          </ul>\n        )}\n      </PanelSection>\n    </PanelBody>\n  );\n};\n", "import React, { useEffect, useState } from 'react';\nimport { FileText, Loader2, RefreshCw } from 'lucide-react';\nimport {\n  listTextStudioJobs,\n  type TextJobContentKind,\n  type TextJobItem,\n} from '../../services/imageJobsService';\nimport { useTextStore } from '../../store/useTextStore';\nimport { getActiveTextEditor } from './DocumentCanvas';\nimport { useTranslation } from '../../i18n';\nimport { Button, IconButton, PanelBody, PanelSection, TextBody, TextTitle } from '../ui';\n\n/**\n * Brand files for Text studio: images into the doc + analysis/script copy import.\n */\nexport const TextJobsPanel: React.FC = () => {\n  const t = useTranslation();\n  const tp = t.text.jobsPanel;\n  const addToast = useTextStore((s) => s.addToast);\n  const [items, setItems] = useState<TextJobItem[]>([]);\n  const [filter, setFilter] = useState<'all' | TextJobContentKind>('all');\n  const [loading, setLoading] = useState(true);\n  const [busyId, setBusyId] = useState<string | null>(null);\n  const [error, setError] = useState<string | null>(null);\n\n  const load = async (signal?: AbortSignal) => {\n    setLoading(true);\n    setError(null);\n    try {\n      const rows = await listTextStudioJobs({ signal });\n      if (!signal?.aborted) setItems(rows);\n    } catch {\n      if (!signal?.aborted) {\n        setItems([]);\n        setError(tp.loadError);\n      }\n    } finally {\n      if (!signal?.aborted) setLoading(false);\n    }\n  };\n\n  useEffect(() => {\n    const ac = new AbortController();\n    void load(ac.signal);\n    return () => ac.abort();\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  const filtered = filter === 'all' ? items : items.filter((i) => i.kind === filter);\n\n  const kindLabel = (kind: TextJobContentKind) => {\n    if (kind === 'image') return tp.kindImage;\n    if (kind === 'analysis') return tp.kindAnalysis;\n    if (kind === 'script') return tp.kindScript;\n    return tp.kindText;\n  };\n\n  const insertItem = async (item: TextJobItem) => {\n    const editor = getActiveTextEditor();\n    if (!editor) {\n      addToast(tp.noEditor, 'warning');\n      return;\n    }\n    setBusyId(item.id);\n    try {\n      if (item.kind === 'image' && item.url) {\n        editor.chain().focus().setImage({ src: item.url, alt: item.name }).run();\n        addToast(tp.imageAdded, 'success');\n        return;\n      }\n      if (item.text) {\n        const heading =\n          item.kind === 'analysis'\n            ? tp.importAnalysisHeading\n            : item.kind === 'script'\n              ? tp.importScriptHeading\n              : tp.importTextHeading;\n        const paragraphs = item.text\n          .split(/\\n\\n+/)\n          .map((p) => p.replace(/\\n/g, ' ').trim())\n          .filter(Boolean)\n          .map((p) => ({\n            type: 'paragraph' as const,\n            content: [{ type: 'text' as const, text: p }],\n          }));\n        editor\n          .chain()\n          .focus()\n          .insertContent([\n            {\n              type: 'heading',\n              attrs: { level: 2 },\n              content: [{ type: 'text', text: heading }],\n            },\n            ...(paragraphs.length\n              ? paragraphs\n              : [\n                  {\n                    type: 'paragraph' as const,\n                    content: [{ type: 'text' as const, text: item.name }],\n                  },\n                ]),\n          ])\n          .run();\n        addToast(tp.textImported, 'success');\n        return;\n      }\n      addToast(tp.insertError, 'warning');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : tp.insertError, 'error');\n    } finally {\n      setBusyId(null);\n    }\n  };\n\n  return (\n    <PanelBody>\n      <PanelSection\n        description={tp.hint}\n        trailing={\n          <IconButton\n            variant=\"ghost\"\n            size=\"sm\"\n            label={tp.refresh}\n            onClick={() => void load()}\n            disabled={loading}\n          >\n            <RefreshCw size={14} className={loading ? 'animate-spin' : undefined} />\n          </IconButton>\n        }\n      >\n        <div className=\"flex flex-wrap gap-1\" role=\"group\" aria-label={tp.filterAria}>\n          {(\n            [\n              ['all', tp.filterAll],\n              ['image', tp.filterImage],\n              ['analysis', tp.filterAnalysis],\n              ['script', tp.filterScript],\n              ['text', tp.filterText],\n            ] as const\n          ).map(([id, label]) => (\n            <button\n              key={id}\n              type=\"button\"\n              onClick={() => setFilter(id)}\n              className={`rounded-lg px-2 py-1 transition-colors ${\n                filter === id\n                  ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)]'\n                  : 'bg-black-capsule text-white/80 hover:text-white'\n              }`}\n            >\n              <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                {label}\n              </TextBody>\n            </button>\n          ))}\n        </div>\n\n        {loading && (\n          <div className=\"grid grid-cols-2 gap-2\" aria-busy aria-label={tp.loading}>\n            {Array.from({ length: 6 }).map((_, i) => (\n              <div\n                key={i}\n                className=\"aspect-square animate-pulse rounded-xl border border-panel-border bg-black-capsule\"\n              />\n            ))}\n          </div>\n        )}\n\n        {!loading && error && (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-red-300\">{error}</TextBody>\n        )}\n\n        {!loading && !error && filtered.length === 0 && (\n          <TextBody as=\"p\" size=\"sm\" className=\"py-6 text-center text-white/80\">\n            {items.length ? tp.emptyFilter : tp.empty}\n          </TextBody>\n        )}\n\n        {!loading && filtered.length > 0 && (\n          <div className=\"grid grid-cols-2 gap-2\">\n            {filtered.map((item) => {\n              const busy = busyId === item.id;\n              const isImage = item.kind === 'image' && Boolean(item.url);\n              return (\n                <button\n                  key={item.id}\n                  type=\"button\"\n                  disabled={busy}\n                  onClick={() => void insertItem(item)}\n                  title={isImage ? tp.addImageHint : tp.addTextHint}\n                  className=\"group relative aspect-square cursor-pointer overflow-hidden rounded-xl border border-panel-border bg-black-capsule transition-colors hover:border-[var(--we-accent)] disabled:opacity-60\"\n                >\n                  {isImage ? (\n                    <img\n                      src={item.url}\n                      alt={item.name}\n                      className=\"h-full w-full object-cover transition-transform group-hover:scale-105\"\n                    />\n                  ) : (\n                    <div className=\"flex h-full w-full flex-col items-center justify-center gap-2 bg-panel p-2\">\n                      <span className=\"flex h-10 w-10 items-center justify-center rounded-xl bg-[var(--we-accent-capsule)] text-[var(--we-accent)]\">\n                        <FileText size={18} />\n                      </span>\n                      <TextBody as=\"span\" size=\"sm\" className=\"line-clamp-3 px-1 text-center text-white\">\n                        {item.text?.slice(0, 120) || item.name}\n                      </TextBody>\n                    </div>\n                  )}\n                  <div className=\"absolute inset-x-0 bottom-0 flex items-center justify-between gap-1 bg-black/70 px-1.5 py-1.5 backdrop-blur-sm\">\n                    <TextBody as=\"span\" size=\"sm\" className=\"min-w-0 truncate text-white\">\n                      {item.name}\n                    </TextBody>\n                    <TextBody as=\"span\" size=\"sm\" className=\"shrink-0 uppercase text-white/70\">\n                      {kindLabel(item.kind)}\n                    </TextBody>\n                  </div>\n                  {busy && (\n                    <div className=\"absolute inset-0 flex items-center justify-center bg-black/50\">\n                      <Loader2 size={16} className=\"animate-spin text-white\" />\n                    </div>\n                  )}\n                </button>\n              );\n            })}\n          </div>\n        )}\n\n        {!loading && error && (\n          <Button variant=\"secondary\" size=\"sm\" onClick={() => void load()}>\n            {tp.refresh}\n          </Button>\n        )}\n      </PanelSection>\n    </PanelBody>\n  );\n};\n", "import React, { useCallback, useRef, useState } from 'react';\nimport {\n  HardDrive,\n  ImagePlus,\n  ListTree,\n  Redo2,\n  RotateCcw,\n  Settings2,\n  Undo2,\n} from 'lucide-react';\nimport { useTranslation } from '../../i18n';\nimport { useTextUiStore, type TextLeftTabId } from '../../store/useTextUiStore';\nimport { modShortcut } from '../../utils/modKey';\nimport { getActiveTextEditor } from './DocumentCanvas';\nimport { OutlinePanel } from './OutlinePanel';\nimport { TextJobsPanel } from './TextJobsPanel';\nimport { IconButton, TextBody, TextTitle } from '../ui';\n\nconst DEFAULT_WIDTH = 260;\nconst MIN_WIDTH = 200;\nconst MAX_WIDTH = 400;\n\nfunction RailIconButton({\n  title,\n  onClick,\n  active,\n  showBar,\n  children,\n}: {\n  title: string;\n  onClick: () => void;\n  active?: boolean;\n  showBar?: boolean;\n  children: React.ReactNode;\n}) {\n  return (\n    <button\n      type=\"button\"\n      title={title}\n      onClick={onClick}\n      className={`\n        relative flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg\n        transition-all duration-150 active:scale-90\n        ${\n          active\n            ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--we-accent)_35%,transparent)]'\n            : 'text-white/80 hover:bg-black-capsule hover:text-white'\n        }\n      `}\n    >\n      {showBar && active && (\n        <span className=\"absolute left-0 top-1/2 h-4 w-0.5 -translate-y-1/2 rounded-r-full bg-[var(--we-accent)]\" />\n      )}\n      {children}\n    </button>\n  );\n}\n\nexport const TextLeftPanel: React.FC = () => {\n  const t = useTranslation();\n  const leftTab = useTextUiStore((s) => s.leftTab);\n  const contentOpen = useTextUiStore((s) => s.leftContentOpen);\n  const toggleLeftTab = useTextUiStore((s) => s.toggleLeftTab);\n  const setLeftContentOpen = useTextUiStore((s) => s.setLeftContentOpen);\n  const setPageSetupOpen = useTextUiStore((s) => s.setPageSetupOpen);\n  const showMarginGuides = useTextUiStore((s) => s.showMarginGuides);\n  const toggleMarginGuides = useTextUiStore((s) => s.toggleMarginGuides);\n  const [panelWidth, setPanelWidth] = useState(DEFAULT_WIDTH);\n  const imgInputRef = useRef<HTMLInputElement>(null);\n\n  const rail: { id: TextLeftTabId; icon: React.ReactNode; label: string }[] = [\n    { id: 'outline', icon: <ListTree size={17} />, label: t.text.sidebar.tabOutline },\n    { id: 'myFiles', icon: <HardDrive size={17} />, label: t.leftPanel.myFiles },\n  ];\n\n  const onResizeStart = useCallback(\n    (e: React.MouseEvent) => {\n      e.preventDefault();\n      const startX = e.clientX;\n      const startW = panelWidth;\n      const onMove = (ev: MouseEvent) => {\n        setPanelWidth(Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, startW + (ev.clientX - startX))));\n      };\n      const onUp = () => {\n        window.removeEventListener('mousemove', onMove);\n        window.removeEventListener('mouseup', onUp);\n      };\n      window.addEventListener('mousemove', onMove);\n      window.addEventListener('mouseup', onUp);\n    },\n    [panelWidth],\n  );\n\n  const runUndo = () => {\n    const editor = getActiveTextEditor();\n    if (editor?.can().undo()) editor.chain().focus().undo().run();\n  };\n\n  const runRedo = () => {\n    const editor = getActiveTextEditor();\n    if (editor?.can().redo()) editor.chain().focus().redo().run();\n  };\n\n  const handleImage = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const f = e.target.files?.[0];\n    if (!f) return;\n    const reader = new FileReader();\n    reader.onload = (ev) => {\n      const src = String(ev.target?.result ?? '');\n      if (!src) return;\n      const editor = getActiveTextEditor();\n      if (editor) {\n        editor.chain().focus().setImage({ src, alt: f.name }).run();\n      }\n    };\n    reader.readAsDataURL(f);\n    e.target.value = '';\n  };\n\n  const title =\n    leftTab === 'myFiles' ? t.leftPanel.myFiles : t.text.sidebar.titleOutline;\n\n  return (\n    <aside className=\"flex h-full min-h-0 shrink-0 select-none border-r border-panel-border bg-panel\">\n      <div className=\"flex w-11 shrink-0 flex-col items-center gap-1.5 border-r border-panel-border bg-panel py-2\">\n        {rail.map((item) => {\n          const isActive = contentOpen && leftTab === item.id;\n          return (\n            <RailIconButton\n              key={item.id}\n              title={item.label}\n              onClick={() => toggleLeftTab(item.id)}\n              active={isActive}\n              showBar\n            >\n              {item.icon}\n            </RailIconButton>\n          );\n        })}\n\n        <div className=\"my-0.5 h-px w-5 bg-panel-border\" aria-hidden />\n\n        <RailIconButton title={`${t.keyboardHelp.undo} (${modShortcut('Z')})`} onClick={runUndo}>\n          <Undo2 size={17} />\n        </RailIconButton>\n        <RailIconButton\n          title={`${t.keyboardHelp.redo} (${modShortcut('Shift+Z')})`}\n          onClick={runRedo}\n        >\n          <Redo2 size={17} />\n        </RailIconButton>\n\n        <div className=\"my-0.5 h-px w-5 bg-panel-border\" aria-hidden />\n\n        <RailIconButton\n          title={t.text.bottomBar.insertImage}\n          onClick={() => imgInputRef.current?.click()}\n        >\n          <ImagePlus size={17} />\n        </RailIconButton>\n        <RailIconButton\n          title={t.text.pageToolbar.marginsButtonTitle}\n          onClick={() => setPageSetupOpen(true)}\n        >\n          <Settings2 size={17} />\n        </RailIconButton>\n        <RailIconButton\n          title={t.text.pageToolbar.guidesTitle}\n          onClick={() => toggleMarginGuides()}\n          active={showMarginGuides}\n        >\n          <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" aria-hidden>\n            <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\" />\n            <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"0.5\" strokeDasharray=\"2 1.5\" />\n          </svg>\n        </RailIconButton>\n\n        <input\n          ref={imgInputRef}\n          type=\"file\"\n          accept=\"image/*\"\n          className=\"hidden\"\n          onChange={handleImage}\n        />\n      </div>\n\n      {contentOpen && (\n        <div className=\"relative flex h-full min-h-0 flex-col\" style={{ width: panelWidth }}>\n          <div\n            role=\"separator\"\n            aria-orientation=\"vertical\"\n            aria-label={t.panel.resizeWidth}\n            onMouseDown={onResizeStart}\n            className=\"absolute inset-y-0 right-0 z-10 w-1.5 cursor-ew-resize group/hresize\"\n          >\n            <div className=\"absolute inset-y-0 right-0 w-0.5 rounded-l-full bg-transparent transition-colors group-hover/hresize:bg-[var(--we-accent-capsule)]\" />\n          </div>\n\n          <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-panel-border px-3 py-2 pr-4\">\n            <TextTitle as=\"h2\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n              {title}\n            </TextTitle>\n            <div className=\"flex items-center gap-0.5\">\n              {panelWidth !== DEFAULT_WIDTH && (\n                <IconButton\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  label={t.panel.resetWidth}\n                  onClick={() => setPanelWidth(DEFAULT_WIDTH)}\n                >\n                  <RotateCcw size={14} />\n                </IconButton>\n              )}\n              <IconButton\n                variant=\"ghost\"\n                size=\"sm\"\n                label={t.panel.closePanel}\n                onClick={() => setLeftContentOpen(false)}\n              >\n                <TextBody as=\"span\" size=\"sm\">\u00D7</TextBody>\n              </IconButton>\n            </div>\n          </div>\n\n          <div className=\"min-h-0 flex-1 overflow-y-auto\">\n            {leftTab === 'myFiles' ? <TextJobsPanel /> : <OutlinePanel />}\n          </div>\n        </div>\n      )}\n    </aside>\n  );\n};\n", "/**\n * Markdown / HTML conversion helpers for Text mode export/import.\n */\n\nimport type { JSONContent } from '@tiptap/core';\nimport TurndownService from 'turndown';\nimport { marked } from 'marked';\n\nconst turndown = new TurndownService({\n  headingStyle: 'atx',\n  codeBlockStyle: 'fenced',\n  bulletListMarker: '-',\n});\n\nexport function htmlToMarkdown(html: string): string {\n  return turndown.turndown(html || '');\n}\n\nexport function markdownToHtml(md: string): string {\n  return String(marked.parse(md || '', { async: false }));\n}\n\n/**\n * Map WhatsApp-style markers to CommonMark so `marked` renders them correctly.\n * Order matters: protect fences/code, then ** / ~~, then single * / ~.\n */\nexport function whatsappMarkersToMarkdown(md: string): string {\n  let raw = md || '';\n  const slots: string[] = [];\n  const park = (chunk: string) => {\n    const i = slots.length;\n    slots.push(chunk);\n    return `\\u0000${i}\\u0000`;\n  };\n\n  // Fenced code blocks\n  raw = raw.replace(/```[\\s\\S]*?```/g, (m) => park(m));\n  // Inline code\n  raw = raw.replace(/`[^`\\n]+`/g, (m) => park(m));\n  // Existing markdown bold / strike\n  raw = raw.replace(/\\*\\*[^*]+\\*\\*/g, (m) => park(m));\n  raw = raw.replace(/~~[^~]+~~/g, (m) => park(m));\n  // WhatsApp bold *text* \u2192 **text**\n  raw = raw.replace(\n    /(^|[\\s([{])\\*([^*\\n]+)\\*(?=[\\s)\\]}.,!?:;]|$)/g,\n    (_m, pre: string, inner: string) => `${pre}**${inner}**`\n  );\n  // WhatsApp strike ~text~ \u2192 ~~text~~\n  raw = raw.replace(\n    /(^|[\\s([{])~([^~\\n]+)~(?=[\\s)\\]}.,!?:;]|$)/g,\n    (_m, pre: string, inner: string) => `${pre}~~${inner}~~`\n  );\n\n  raw = raw.replace(/\\u0000(\\d+)\\u0000/g, (_m, i: string) => slots[Number(i)] ?? '');\n  return raw;\n}\n\n/**\n * Convert AI / chat copy (markdown + WhatsApp markers) into HTML TipTap can insert.\n * Strips a single wrapping ``` fence when the model returns fenced markdown.\n */\nexport function aiMarkdownToHtml(md: string): string {\n  let raw = (md || '').trim();\n  if (!raw) return '<p></p>';\n  const fence = /^```(?:markdown|md|text)?\\s*\\n([\\s\\S]*?)\\n```$/i.exec(raw);\n  if (fence?.[1]) raw = fence[1].trim();\n  return markdownToHtml(whatsappMarkersToMarkdown(raw));\n}\n\nfunction inlineToHtml(nodes: JSONContent[] | undefined): string {\n  if (!nodes?.length) return '';\n  return nodes\n    .map((n) => {\n      let t = escapeHtml(n.text || '');\n      const marks = n.marks || [];\n      if (marks.some((m) => m.type === 'bold')) t = `<strong>${t}</strong>`;\n      if (marks.some((m) => m.type === 'italic')) t = `<em>${t}</em>`;\n      if (marks.some((m) => m.type === 'strike')) t = `<s>${t}</s>`;\n      return t;\n    })\n    .join('');\n}\n\nfunction escapeHtml(s: string): string {\n  return s\n    .replace(/&/g, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;');\n}\n\nexport function jsonToHtml(doc: JSONContent): string {\n  const blocks = (doc.content || []).map((node) => {\n    switch (node.type) {\n      case 'heading': {\n        const level = node.attrs?.level || 1;\n        return `<h${level}>${inlineToHtml(node.content)}</h${level}>`;\n      }\n      case 'paragraph':\n        return `<p>${inlineToHtml(node.content)}</p>`;\n      case 'blockquote':\n        return `<blockquote>${jsonToHtml({ type: 'doc', content: node.content })}</blockquote>`;\n      case 'bulletList':\n        return `<ul>${(node.content || [])\n          .map(\n            (li) =>\n              `<li>${inlineToHtml(li.content?.[0]?.content)}</li>`\n          )\n          .join('')}</ul>`;\n      case 'orderedList':\n        return `<ol>${(node.content || [])\n          .map(\n            (li) =>\n              `<li>${inlineToHtml(li.content?.[0]?.content)}</li>`\n          )\n          .join('')}</ol>`;\n      case 'callout':\n        return `<aside data-callout=\"true\">${jsonToHtml({ type: 'doc', content: node.content })}</aside>`;\n      case 'table':\n        return `<table>${(node.content || [])\n          .map(\n            (row) =>\n              `<tr>${(row.content || [])\n                .map((cell) => {\n                  const tag = cell.type === 'tableHeader' ? 'th' : 'td';\n                  return `<${tag}>${inlineToHtml(cell.content?.[0]?.content)}</${tag}>`;\n                })\n                .join('')}</tr>`\n          )\n          .join('')}</table>`;\n      default:\n        return node.content\n          ? jsonToHtml({ type: 'doc', content: node.content })\n          : '';\n    }\n  });\n  return blocks.filter(Boolean).join('\\n');\n}\n\nexport function jsonToMarkdown(doc: JSONContent): string {\n  return htmlToMarkdown(jsonToHtml(doc));\n}\n", "/**\n * Apply an AI suggestion into the active TipTap editor reliably.\n */\n\nimport type { Editor, JSONContent } from '@tiptap/core';\nimport { aiMarkdownToHtml } from './markdown';\nimport { useTextStore } from '../../store/useTextStore';\nimport { getActiveTextEditor } from '../../components/text/DocumentCanvas';\n\nfunction findTextRange(\n  editor: Editor,\n  needle: string\n): { from: number; to: number } | null {\n  if (!needle) return null;\n  const full = editor.state.doc.textContent;\n  const idx = full.indexOf(needle);\n  if (idx < 0) {\n    // Fallback: prefix match (up to 120 chars) only if unique\n    const prefix = needle.slice(0, Math.min(120, needle.length));\n    if (prefix.length < 8) return null;\n    const first = full.indexOf(prefix);\n    const second = full.indexOf(prefix, first + 1);\n    if (first < 0 || second >= 0) return null;\n    return mapStringIndexToPos(editor, first, first + needle.length);\n  }\n  // Prefer unique full match\n  const second = full.indexOf(needle, idx + 1);\n  if (second >= 0) {\n    // Ambiguous \u2014 still take first but only if marked path failed\n    return mapStringIndexToPos(editor, idx, idx + needle.length);\n  }\n  return mapStringIndexToPos(editor, idx, idx + needle.length);\n}\n\nfunction mapStringIndexToPos(\n  editor: Editor,\n  startIdx: number,\n  endIdx: number\n): { from: number; to: number } | null {\n  let acc = 0;\n  let fromPos = -1;\n  let toPos = -1;\n  editor.state.doc.descendants((node, pos) => {\n    if (!node.isText || !node.text) return true;\n    const next = acc + node.text.length;\n    if (fromPos < 0 && startIdx >= acc && startIdx < next) {\n      fromPos = pos + (startIdx - acc);\n    }\n    if (fromPos >= 0 && toPos < 0 && endIdx <= next) {\n      toPos = pos + (endIdx - acc);\n      return false;\n    }\n    if (fromPos >= 0 && toPos < 0 && endIdx > next && startIdx < next) {\n      // spans multiple nodes \u2014 keep scanning\n    }\n    acc = next;\n    return true;\n  });\n  // Multi-node span: recompute end\n  if (fromPos >= 0 && toPos < 0) {\n    acc = 0;\n    editor.state.doc.descendants((node, pos) => {\n      if (!node.isText || !node.text) return true;\n      const next = acc + node.text.length;\n      if (endIdx <= next) {\n        toPos = pos + (endIdx - acc);\n        return false;\n      }\n      acc = next;\n      return true;\n    });\n  }\n  if (fromPos >= 0 && toPos > fromPos) return { from: fromPos, to: toPos };\n  return null;\n}\n\nfunction insertMarkdown(editor: Editor, markdown: string, atEnd: boolean) {\n  const html = aiMarkdownToHtml(markdown);\n  if (atEnd) {\n    const end = editor.state.doc.content.size;\n    editor.chain().focus().insertContentAt(end, html).run();\n    return;\n  }\n  editor.chain().focus().insertContent(html).run();\n}\n\nfunction markdownToPlainBlocks(markdown: string): JSONContent[] {\n  const text = (markdown || '').trim();\n  if (!text) return [{ type: 'paragraph' }];\n  return text\n    .split(/\\n\\n+/)\n    .map((p) => p.replace(/\\n/g, ' ').trim())\n    .filter(Boolean)\n    .map((p) => ({\n      type: 'paragraph' as const,\n      content: [{ type: 'text' as const, text: p }],\n    }));\n}\n\nfunction isEffectivelyEmptyDoc(doc: JSONContent | null | undefined): boolean {\n  const content = doc?.content;\n  if (!content?.length) return true;\n  if (content.length > 1) return false;\n  const only = content[0];\n  if (!only || only.type !== 'paragraph') return false;\n  const inner = only.content;\n  if (!inner?.length) return true;\n  return inner.every((n) => !String(n.text || '').trim());\n}\n\n/**\n * Append markdown/HTML-capable copy into the open document.\n * Prefers the live TipTap instance; falls back to store.doc (canvas syncs).\n */\nexport function insertMarkdownIntoDocument(markdown: string): boolean {\n  const trimmed = (markdown || '').trim();\n  if (!trimmed) return false;\n\n  const editor = getActiveTextEditor();\n  if (editor) {\n    try {\n      insertMarkdown(editor, trimmed, true);\n      useTextStore.getState().setDocFromEditor(editor.getJSON());\n      return true;\n    } catch {\n      // Fall through to store merge (view not ready, destroyed mid-call, etc.).\n    }\n  }\n\n  const store = useTextStore.getState();\n  const blocks = markdownToPlainBlocks(trimmed);\n  if (!blocks.length) return false;\n  const prev = store.doc;\n  const nextContent = isEffectivelyEmptyDoc(prev)\n    ? blocks\n    : [...(prev.content || []), ...blocks];\n  store.setDocFromEditor({ type: 'doc', content: nextContent });\n  return true;\n}\n\n/** Full document range covered by an `aiSuggestion` mark with this id. */\nexport function findAiSuggestionRange(\n  editor: Editor,\n  id: string\n): { from: number; to: number } | null {\n  let from = -1;\n  let to = -1;\n  editor.state.doc.descendants((node, pos) => {\n    if (!node.isText) return true;\n    const marked = node.marks.some(\n      (m) => m.type.name === 'aiSuggestion' && m.attrs.id === id\n    );\n    if (marked) {\n      if (from < 0) from = pos;\n      to = pos + node.nodeSize;\n    }\n    return true;\n  });\n  if (from >= 0 && to > from) return { from, to };\n  return null;\n}\n\n/** Strip the pending-review highlight for a suggestion id (all text nodes). */\nexport function clearAiSuggestionMark(\n  editor: Editor | null,\n  id: string\n): boolean {\n  if (!editor) return false;\n  const range = findAiSuggestionRange(editor, id);\n  if (!range) return false;\n  const markType = editor.schema.marks.aiSuggestion;\n  if (!markType) return false;\n  editor.view.dispatch(editor.state.tr.removeMark(range.from, range.to, markType));\n  return true;\n}\n\n/**\n * @returns true if content was applied to the editor\n */\nexport function applyAcceptToEditor(\n  editor: Editor | null,\n  id: string,\n  original: string,\n  replacement: string\n): boolean {\n  if (!editor || !replacement) return false;\n  const html = aiMarkdownToHtml(replacement);\n\n  const markRange = findAiSuggestionRange(editor, id);\n  if (markRange) {\n    editor.chain().focus().insertContentAt(markRange, html).run();\n    // Belt-and-suspenders: drop any leftover pending mark for this id.\n    clearAiSuggestionMark(editor, id);\n    return true;\n  }\n\n  const trimmedOrig = original.trim();\n  if (trimmedOrig) {\n    // Whole-doc replace when original \u2248 document\n    const full = editor.state.doc.textContent.trim();\n    if (\n      full &&\n      (full === trimmedOrig ||\n        full.startsWith(trimmedOrig.slice(0, Math.min(200, trimmedOrig.length))))\n    ) {\n      editor.chain().focus().setContent(html).run();\n      clearAiSuggestionMark(editor, id);\n      return true;\n    }\n\n    const range = findTextRange(editor, trimmedOrig);\n    if (range) {\n      editor.chain().focus().insertContentAt(range, html).run();\n      clearAiSuggestionMark(editor, id);\n      return true;\n    }\n  }\n\n  // Empty original or not found \u2014 append at end (never spam cursor)\n  insertMarkdown(editor, replacement, true);\n  clearAiSuggestionMark(editor, id);\n  return true;\n}\n", "/**\n * TipTap JSON <-> DOCX (structured) and mammoth import helpers.\n */\n\nimport type { JSONContent } from '@tiptap/core';\nimport {\n  Document as DocxDocument,\n  Packer,\n  Paragraph,\n  TextRun,\n  HeadingLevel,\n  Table,\n  TableRow,\n  TableCell,\n  WidthType,\n  BorderStyle,\n} from 'docx';\nimport { convertToHtml as mammothConvertToHtml } from 'mammoth';\n\nfunction textOf(node: JSONContent): string {\n  if (node.type === 'text') return node.text || '';\n  return (node.content || []).map(textOf).join('');\n}\n\nfunction runsFromInline(nodes: JSONContent[] | undefined): TextRun[] {\n  if (!nodes?.length) return [new TextRun('')];\n  return nodes.map((n) => {\n    const marks = n.marks || [];\n    return new TextRun({\n      text: n.text || '',\n      bold: marks.some((m) => m.type === 'bold'),\n      italics: marks.some((m) => m.type === 'italic'),\n      strike: marks.some((m) => m.type === 'strike'),\n    });\n  });\n}\n\nfunction headingLevel(level: number) {\n  if (level === 1) return HeadingLevel.HEADING_1;\n  if (level === 2) return HeadingLevel.HEADING_2;\n  if (level === 3) return HeadingLevel.HEADING_3;\n  return HeadingLevel.HEADING_4;\n}\n\nfunction nodeToBlocks(node: JSONContent): Array<Paragraph | Table> {\n  switch (node.type) {\n    case 'heading':\n      return [\n        new Paragraph({\n          heading: headingLevel(node.attrs?.level || 1),\n          children: runsFromInline(node.content),\n        }),\n      ];\n    case 'paragraph':\n      return [\n        new Paragraph({\n          children: runsFromInline(node.content),\n          spacing: { after: 160 },\n        }),\n      ];\n    case 'blockquote':\n      return [\n        new Paragraph({\n          children: [\n            new TextRun({ text: textOf(node), italics: true }),\n          ],\n          indent: { left: 420 },\n          spacing: { after: 120 },\n        }),\n      ];\n    case 'bulletList':\n    case 'orderedList':\n      return (node.content || []).flatMap((li, idx) => {\n        const para = li.content?.[0];\n        const prefix = node.type === 'orderedList' ? `${idx + 1}. ` : '\u2022 ';\n        return [\n          new Paragraph({\n            children: [\n              new TextRun(prefix),\n              ...runsFromInline(para?.content),\n            ],\n            spacing: { after: 80 },\n          }),\n        ];\n      });\n    case 'table': {\n      const rows = (node.content || []).map(\n        (row) =>\n          new TableRow({\n            children: (row.content || []).map(\n              (cell) =>\n                new TableCell({\n                  width: { size: 3000, type: WidthType.DXA },\n                  borders: {\n                    top: { style: BorderStyle.SINGLE, size: 1, color: '2A2A38' },\n                    bottom: { style: BorderStyle.SINGLE, size: 1, color: '2A2A38' },\n                    left: { style: BorderStyle.SINGLE, size: 1, color: '2A2A38' },\n                    right: { style: BorderStyle.SINGLE, size: 1, color: '2A2A38' },\n                  },\n                  children: (cell.content || []).flatMap((c) =>\n                    c.type === 'paragraph'\n                      ? [\n                          new Paragraph({\n                            children: runsFromInline(c.content),\n                          }),\n                        ]\n                      : [new Paragraph({ children: [new TextRun(textOf(c))] })]\n                  ),\n                })\n            ),\n          })\n      );\n      return [new Table({ rows, width: { size: 9000, type: WidthType.DXA } })];\n    }\n    case 'callout':\n      return [\n        new Paragraph({\n          children: [\n            new TextRun({ text: '[Callout] ', bold: true }),\n            new TextRun(textOf(node)),\n          ],\n          spacing: { after: 160 },\n        }),\n      ];\n    default:\n      if (node.content) return node.content.flatMap(nodeToBlocks);\n      return [];\n  }\n}\n\nexport async function tipTapJsonToDocxBlob(\n  doc: JSONContent,\n  title: string\n): Promise<Blob> {\n  const children: Array<Paragraph | Table> = [\n    new Paragraph({\n      text: title || 'Documento',\n      heading: HeadingLevel.HEADING_1,\n    }),\n    ...(doc.content || []).flatMap(nodeToBlocks),\n  ];\n  const docx = new DocxDocument({\n    sections: [{ children }],\n  });\n  return Packer.toBlob(docx);\n}\n\nexport async function docxFileToHtml(file: Blob): Promise<string> {\n  const buf = await file.arrayBuffer();\n  const result = await mammothConvertToHtml({ arrayBuffer: buf });\n  return result.value;\n}\n\n/** Minimal HTML \u2192 TipTap JSON (headings, p, lists, tables). */\nexport function htmlToTipTapDoc(html: string): JSONContent {\n  const parser = new DOMParser();\n  const dom = parser.parseFromString(`<div id=\"root\">${html}</div>`, 'text/html');\n  const root = dom.getElementById('root');\n  if (!root) return { type: 'doc', content: [{ type: 'paragraph' }] };\n\n  const walkInline = (el: Node): JSONContent[] => {\n    const out: JSONContent[] = [];\n    el.childNodes.forEach((child) => {\n      if (child.nodeType === Node.TEXT_NODE) {\n        const t = child.textContent || '';\n        if (t) out.push({ type: 'text', text: t });\n      } else if (child.nodeType === Node.ELEMENT_NODE) {\n        const e = child as HTMLElement;\n        const tag = e.tagName.toLowerCase();\n        const inner = walkInline(e);\n        if (tag === 'strong' || tag === 'b') {\n          inner.forEach((n) => {\n            if (n.type === 'text') {\n              n.marks = [...(n.marks || []), { type: 'bold' }];\n            }\n          });\n        }\n        if (tag === 'em' || tag === 'i') {\n          inner.forEach((n) => {\n            if (n.type === 'text') {\n              n.marks = [...(n.marks || []), { type: 'italic' }];\n            }\n          });\n        }\n        out.push(...inner);\n      }\n    });\n    return out;\n  };\n\n  const blockFromEl = (el: Element): JSONContent | null => {\n    const tag = el.tagName.toLowerCase();\n    if (/^h[1-4]$/.test(tag)) {\n      return {\n        type: 'heading',\n        attrs: { level: Number(tag[1]) },\n        content: walkInline(el),\n      };\n    }\n    if (tag === 'p') {\n      const content = walkInline(el);\n      return { type: 'paragraph', content: content.length ? content : undefined };\n    }\n    if (tag === 'ul' || tag === 'ol') {\n      return {\n        type: tag === 'ul' ? 'bulletList' : 'orderedList',\n        content: Array.from(el.children)\n          .filter((c) => c.tagName.toLowerCase() === 'li')\n          .map((li) => ({\n            type: 'listItem',\n            content: [\n              {\n                type: 'paragraph',\n                content: walkInline(li),\n              },\n            ],\n          })),\n      };\n    }\n    if (tag === 'table') {\n      return {\n        type: 'table',\n        content: Array.from(el.querySelectorAll('tr')).map((tr) => ({\n          type: 'tableRow',\n          content: Array.from(tr.children).map((cell) => ({\n            type: cell.tagName.toLowerCase() === 'th' ? 'tableHeader' : 'tableCell',\n            content: [\n              {\n                type: 'paragraph',\n                content: walkInline(cell),\n              },\n            ],\n          })),\n        })),\n      };\n    }\n    if (tag === 'blockquote') {\n      return {\n        type: 'blockquote',\n        content: Array.from(el.children)\n          .map((c) => blockFromEl(c))\n          .filter(Boolean) as JSONContent[],\n      };\n    }\n    return null;\n  };\n\n  const content: JSONContent[] = [];\n  Array.from(root.children).forEach((el) => {\n    const block = blockFromEl(el);\n    if (block) content.push(block);\n  });\n  if (!content.length) {\n    const text = root.textContent?.trim();\n    if (text) {\n      content.push({\n        type: 'paragraph',\n        content: [{ type: 'text', text }],\n      });\n    } else {\n      content.push({ type: 'paragraph' });\n    }\n  }\n  return { type: 'doc', content };\n}\n", "import React, { useMemo } from 'react';\nimport { Modal, Button } from '../ui';\nimport { useTranslation } from '../../i18n';\nimport { aiMarkdownToHtml } from '../../lib/text/markdown';\n\ntype Props = {\n  open: boolean;\n  title: string;\n  text: string;\n  onClose: () => void;\n  onInsert: () => void;\n  onSaveSuggestion: () => void;\n};\n\n/**\n * Shows AI-generated copy before it hits the document or suggestions queue.\n * Renders markdown (bold, lists) so asterisks/dashes are not shown literally.\n * Prose HTML uses Quicksand via font-sans (content preview, not chrome labels).\n */\nexport const TextAiResultModal: React.FC<Props> = ({\n  open,\n  title,\n  text,\n  onClose,\n  onInsert,\n  onSaveSuggestion,\n}) => {\n  const tr = useTranslation();\n  const ai = tr.text.ai;\n  const html = useMemo(() => aiMarkdownToHtml(text), [text]);\n\n  return (\n    <Modal isOpen={open} onClose={onClose} title={title} size=\"lg\">\n      <div className=\"flex flex-col gap-3\">\n        <div\n          className=\"we-text-prose max-h-[50vh] overflow-y-auto rounded-xl border border-panel-border bg-black-capsule p-3 font-sans text-[13px] font-medium leading-relaxed text-white [&_li]:my-0.5 [&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-5 [&_p]:mb-2 [&_p:last-child]:mb-0 [&_strong]:font-bold [&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-5\"\n          dangerouslySetInnerHTML={{ __html: html }}\n        />\n        <div className=\"flex flex-wrap gap-2\">\n          <Button variant=\"secondary\" size=\"md\" className=\"flex-1\" onClick={onClose}>\n            {ai.resultDiscard}\n          </Button>\n          <Button variant=\"outline\" size=\"md\" className=\"flex-1\" onClick={onSaveSuggestion}>\n            {ai.resultToSuggestions}\n          </Button>\n          <Button variant=\"accent\" size=\"md\" className=\"flex-1\" onClick={onInsert}>\n            {ai.resultInsert}\n          </Button>\n        </div>\n      </div>\n    </Modal>\n  );\n};\n", "/**\n * Present compliance API flags in a user-friendly way.\n * Backend messages are often mixed ES/EN or lightly typo'd \u2014 normalize for display.\n */\n\nexport type ComplianceSeverity = 'info' | 'warn' | 'block';\n\nexport type ComplianceFlag = {\n  severity: ComplianceSeverity;\n  message: string;\n};\n\nexport type ComplianceOutcome = 'ok' | 'warn' | 'block';\n\nexport function complianceOutcome(flags: ComplianceFlag[]): ComplianceOutcome {\n  if (flags.some((f) => f.severity === 'block')) return 'block';\n  if (flags.some((f) => f.severity === 'warn')) return 'warn';\n  return 'ok';\n}\n\n/** Light cleanup of model/backend wording for Spanish UI. */\nexport function normalizeComplianceMessage(\n  message: string,\n  locale: 'es' | 'en'\n): string {\n  let m = message.replace(/\\s+/g, ' ').trim();\n  if (!m) return m;\n\n  // Severity is shown as a badge \u2014 strip if the model echoed it in the text.\n  m = m.replace(/^(info|warn|warning|block|error)\\s*[,:\\-\u2013]?\\s*/i, '');\n\n  if (locale === 'es') {\n    m = m\n      .replace(/\\bflasgs?\\b/gi, 'avisos')\n      .replace(/\\bflags?\\b/gi, 'avisos')\n      .replace(/\\bcriticos\\b/gi, 'cr\u00EDticos')\n      .replace(/\\btipicos\\b/gi, 't\u00EDpicos')\n      .replace(/\\bonload\\s+brand\\b/gi, 'alineado con la marca')\n      .replace(/\\bon[- ]?brand\\b/gi, 'alineado con la marca')\n      .replace(/\\bdisclaimers?\\b/gi, 'avisos legales')\n      .replace(/\\bwarnings?\\b/gi, 'avisos')\n      .replace(/\\bwarns?\\b/gi, 'avisos')\n      .replace(/\\bblocks?\\b/gi, 'bloqueos')\n      .replace(\n        /\\bsin avisos cr\u00EDticos[;,]?\\s*alineado con la marca/gi,\n        'Sin avisos cr\u00EDticos; alineado con la marca'\n      );\n  } else {\n    m = m\n      .replace(/\\bflasgs?\\b/gi, 'flags')\n      .replace(/\\bcriticos\\b/gi, 'critical')\n      .replace(/\\btipicos\\b/gi, 'typical')\n      .replace(/\\bonload\\s+brand\\b/gi, 'on-brand');\n  }\n\n  return m.charAt(0).toUpperCase() + m.slice(1);\n}\n\nexport function presentComplianceFlags(\n  flags: ComplianceFlag[],\n  locale: 'es' | 'en'\n): ComplianceFlag[] {\n  // Drop generic \"info\" tips (e.g. industry boilerplate) \u2014 only warn/block matter.\n  return flags\n    .filter((f) => f.severity === 'warn' || f.severity === 'block')\n    .map((f) => ({\n      severity: f.severity,\n      message: normalizeComplianceMessage(f.message, locale),\n    }));\n}\n", "import React, { useState } from 'react';\nimport {\n  ChevronLeft,\n  ClipboardList,\n  FileAudio,\n  FileText,\n  GitCompare,\n  ListTree,\n  Mic,\n  PenLine,\n  Plus,\n  Scale,\n  Scissors,\n  Shield,\n  Sparkles,\n  Trash2,\n  Wand2,\n} from 'lucide-react';\nimport {\n  useTextStore,\n  getDocPlainText,\n  type TextTone,\n} from '../../store/useTextStore';\nimport {\n  generateOutline,\n  generateText,\n  rewriteText,\n  runCompliancePass,\n  runSectionOp,\n  scoreAbVariants,\n  scoreBrandVoice,\n  voiceMatchRewrite,\n  type SectionOp,\n} from '../../services/text';\nimport { transcribeAudio } from '../../services/transcriptionService';\nimport { getActiveTextEditor } from './DocumentCanvas';\nimport { applyAcceptToEditor } from '../../lib/text/applySuggestion';\nimport { aiMarkdownToHtml } from '../../lib/text/markdown';\nimport { htmlToTipTapDoc } from '../../lib/text/docxBridge';\nimport { useTranslation, useLocale } from '../../i18n';\nimport { TextAiResultModal } from './TextAiResultModal';\nimport { useTextUiStore } from '../../store/useTextUiStore';\nimport { Button, IconButton, PanelBody, PanelField, PanelSection, SelectDropdown, SubtitleAiLoader, ToolPanelTabs, TextBody, TextTitle } from '../ui';\nimport {\n  complianceOutcome,\n  presentComplianceFlags,\n  type ComplianceFlag,\n} from '../../lib/text/complianceFeedback';\n\ntype Tab =\n  | 'generate'\n  | 'rewrite'\n  | 'ops'\n  | 'outline'\n  | 'brand'\n  | 'ab'\n  | 'compliance'\n  | 'voice'\n  | 'transcript'\n  | 'clip';\n\ntype TextScope = 'doc' | 'selection';\n\ntype ResultDraft = {\n  title: string;\n  text: string;\n  original: string;\n  kind: 'rewrite' | 'expand' | 'tighten' | 'elevate' | 'localize' | 'brand' | 'other';\n  rationale?: string;\n  scope: TextScope;\n  selectionFrom?: number;\n  selectionTo?: number;\n};\n\ntype ToolDef = {\n  id: Tab;\n  icon: React.ReactNode;\n};\n\nconst ALL_TOOLS: ToolDef[] = [\n  { id: 'generate', icon: <Sparkles size={16} /> },\n  { id: 'rewrite', icon: <PenLine size={16} /> },\n  { id: 'ops', icon: <Scissors size={16} /> },\n  { id: 'outline', icon: <ListTree size={16} /> },\n  { id: 'brand', icon: <Shield size={16} /> },\n  { id: 'voice', icon: <Wand2 size={16} /> },\n  { id: 'ab', icon: <GitCompare size={16} /> },\n  { id: 'compliance', icon: <Scale size={16} /> },\n  { id: 'clip', icon: <ClipboardList size={16} /> },\n  { id: 'transcript', icon: <FileAudio size={16} /> },\n];\n\nconst TONE_TOKENS: TextTone[] = [\n  'neutral',\n  'formal',\n  'casual',\n  'persuasive',\n  'technical',\n  'friendly',\n];\n\nconst SECTION_OPS: SectionOp[] = ['tighten', 'elevate', 'localize', 'expand'];\n\nconst INDUSTRY_TOKENS = ['general', 'fintech', 'salud'] as const;\nconst INDUSTRY_OTHER = '__other__';\n\nconst TEXTAREA_CLASS =\n  'w-full resize-none rounded-xl border border-panel-border bg-black-capsule p-2.5 font-sans text-[12px] font-medium text-white placeholder:text-white/50 focus:border-[var(--we-accent)] focus:outline-none';\n\nconst INPUT_CLASS =\n  'w-full rounded-xl border border-panel-border bg-black-capsule px-2.5 py-2 font-sans text-[12px] font-medium text-white placeholder:text-white/50 focus:border-[var(--we-accent)] focus:outline-none';\n\nfunction ToolRow({\n  tool,\n  name,\n  description,\n  onClick,\n}: {\n  tool: ToolDef;\n  name: string;\n  description: string;\n  onClick: () => void;\n}) {\n  return (\n    <button\n      type=\"button\"\n      onClick={onClick}\n      className=\"relative flex w-full cursor-pointer items-start gap-2.5 overflow-hidden rounded-xl border border-transparent bg-black-capsule px-2.5 py-2.5 text-left transition-colors hover:border-[color-mix(in_srgb,var(--we-accent)_35%,transparent)] hover:bg-[var(--we-accent-muted)] active:scale-[0.99]\"\n    >\n      <span className=\"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-[var(--we-accent)] text-white\">\n        {tool.icon}\n      </span>\n      <span className=\"min-w-0 flex-1\">\n        <TextTitle as=\"span\" size=\"sm\" className=\"block text-white\">\n          {name}\n        </TextTitle>\n        <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 text-pretty block leading-snug text-white/80\">\n          {description}\n        </TextBody>\n      </span>\n    </button>\n  );\n}\n\nexport const AiTextPanel: React.FC = () => {\n  const t = useTranslation();\n  const locale = useLocale();\n  const ai = t.text.ai;\n  const [tab, setTab] = useState<Tab>('generate');\n  const [toolOpen, setToolOpen] = useState(false);\n  const [busy, setBusy] = useState(false);\n  const [prompt, setPrompt] = useState('');\n  const [instruction, setInstruction] = useState(ai.rewriteDefault);\n  const [sectionOp, setSectionOp] = useState<SectionOp>('tighten');\n  const [abHooks, setAbHooks] = useState<string[]>(['', '']);\n  const [abScores, setAbScores] = useState<\n    Array<{\n      letter: string;\n      clarity: number;\n      ctaStrength: number;\n      brandFit: number;\n      notes?: string;\n    }>\n  >([]);\n  const [industry, setIndustry] = useState('general');\n  const [customIndustry, setCustomIndustry] = useState('');\n  const [complianceFlags, setComplianceFlags] = useState<ComplianceFlag[]>([]);\n  const [complianceRan, setComplianceRan] = useState(false);\n  const [voiceSamples, setVoiceSamples] = useState('');\n  const [textScope, setTextScope] = useState<TextScope>('doc');\n  const [preferredTermsDraft, setPreferredTermsDraft] = useState('');\n  const [forbiddenTermsDraft, setForbiddenTermsDraft] = useState('');\n  const [resultDraft, setResultDraft] = useState<ResultDraft | null>(null);\n  const doc = useTextStore((s) => s.doc);\n  const textBankSamples = useTextStore((s) => s.brandVoice.textBankSamples);\n  const tone = useTextStore((s) => s.tone);\n  const language = useTextStore((s) => s.language);\n  const docType = useTextStore((s) => s.docType);\n  const brandVoice = useTextStore((s) => s.brandVoice);\n  const addSuggestion = useTextStore((s) => s.addSuggestion);\n  const setDoc = useTextStore((s) => s.setDoc);\n  const setDocFromEditor = useTextStore((s) => s.setDocFromEditor);\n  const setBrandVoice = useTextStore((s) => s.setBrandVoice);\n  const setTone = useTextStore((s) => s.setTone);\n  const setVariants = useTextStore((s) => s.setVariants);\n  const variants = useTextStore((s) => s.variants);\n  const setRightTab = useTextStore((s) => s.setRightTab);\n  const addToast = useTextStore((s) => s.addToast);\n\n  const toneOptions = TONE_TOKENS.map((tn) => ({\n    value: tn,\n    label: ai.tones[tn],\n  }));\n  const opOptions = SECTION_OPS.map((op) => ({\n    value: op,\n    label: ai.ops[op],\n  }));\n  const industryOptions = [\n    ...INDUSTRY_TOKENS.map((id) => ({\n      value: id,\n      label:\n        id === 'salud'\n          ? ai.industries.health\n          : id === 'fintech'\n            ? ai.industries.fintech\n            : ai.industries.general,\n    })),\n    { value: INDUSTRY_OTHER, label: ai.industries.other },\n  ];\n\n  const resolveIndustry = () =>\n    industry === INDUSTRY_OTHER\n      ? customIndustry.trim()\n      : industry;\n\n  const selectionOnly = () => {\n    const editor = getActiveTextEditor();\n    if (!editor) return '';\n    const { from, to } = editor.state.selection;\n    if (from === to) return '';\n    return editor.state.doc.textBetween(from, to, ' ');\n  };\n\n  const scopedText = () =>\n    textScope === 'doc' ? getDocPlainText(doc) : selectionOnly();\n\n  const captureScope = (): Pick<\n    ResultDraft,\n    'original' | 'scope' | 'selectionFrom' | 'selectionTo'\n  > & { text: string } => {\n    const text = scopedText();\n    const editor = getActiveTextEditor();\n    let selectionFrom: number | undefined;\n    let selectionTo: number | undefined;\n    if (textScope === 'selection' && editor) {\n      const { from, to } = editor.state.selection;\n      if (from !== to) {\n        selectionFrom = from;\n        selectionTo = to;\n      }\n    }\n    return {\n      text,\n      original: text,\n      scope: textScope,\n      selectionFrom,\n      selectionTo,\n    };\n  };\n\n  const pushSug = (\n    original: string,\n    replacement: string,\n    kind: 'rewrite' | 'expand' | 'tighten' | 'elevate' | 'localize' | 'brand' | 'other',\n    rationale?: string\n  ) => {\n    let orig = original;\n    if (!orig.trim()) {\n      orig = getDocPlainText(doc).slice(0, 2000);\n    }\n    const id = addSuggestion({ kind, original: orig, replacement, rationale });\n    const editor = getActiveTextEditor();\n    if (editor) {\n      const { from, to } = editor.state.selection;\n      if (from !== to) {\n        editor\n          .chain()\n          .focus()\n          .setAiSuggestion({\n            id,\n            kind,\n            original: orig,\n            replacement,\n            rationale: rationale || '',\n          })\n          .run();\n      }\n    }\n    useTextUiStore.getState().setSuggestionsModalOpen(true);\n  };\n\n  const showResult = (draft: ResultDraft) => {\n    setResultDraft(draft);\n  };\n\n  /** Replace scoped original text; generate (empty original) inserts at cursor / fills empty doc. */\n  const insertResultText = (draft: ResultDraft) => {\n    const html = aiMarkdownToHtml(draft.text);\n    const jsonDoc = htmlToTipTapDoc(html);\n    const blocks = jsonDoc.content?.length\n      ? jsonDoc.content\n      : [{ type: 'paragraph' as const, content: [{ type: 'text' as const, text: draft.text }] }];\n\n    const editor = getActiveTextEditor();\n    if (!editor) {\n      // No live editor \u2014 still persist into the store so Apply is not a no-op.\n      if (!draft.original.trim() || draft.scope === 'doc') {\n        setDoc(jsonDoc);\n      }\n      return;\n    }\n\n    const syncStore = () => {\n      setDocFromEditor(editor.getJSON());\n    };\n\n    if (draft.scope === 'doc' && draft.original.trim()) {\n      editor.chain().focus().setContent(jsonDoc).run();\n      syncStore();\n      return;\n    }\n\n    if (\n      draft.scope === 'selection' &&\n      draft.selectionFrom != null &&\n      draft.selectionTo != null &&\n      draft.selectionFrom < draft.selectionTo\n    ) {\n      editor\n        .chain()\n        .focus()\n        .insertContentAt(\n          { from: draft.selectionFrom, to: draft.selectionTo },\n          blocks\n        )\n        .run();\n      syncStore();\n      return;\n    }\n\n    if (draft.original.trim()) {\n      applyAcceptToEditor(editor, '', draft.original, draft.text);\n      syncStore();\n      return;\n    }\n\n    // Generate / append: fill empty doc, otherwise insert at saved caret (or end).\n    const isEmpty = !editor.state.doc.textContent.trim();\n    if (isEmpty) {\n      editor.chain().focus().setContent(jsonDoc).run();\n    } else {\n      const pos =\n        draft.selectionFrom != null\n          ? draft.selectionFrom\n          : editor.state.doc.content.size;\n      const ok = editor.chain().focus().insertContentAt(pos, blocks).run();\n      if (!ok) {\n        editor.chain().focus('end').insertContent(blocks).run();\n      }\n    }\n    syncStore();\n  };\n\n  const onEnterRun = (e: React.KeyboardEvent, enabled: boolean, run: () => void) => {\n    if (e.key === 'Enter' && !e.shiftKey) {\n      e.preventDefault();\n      if (enabled && !busy) run();\n    }\n  };\n\n  const runGenerate = async () => {\n    if (!prompt.trim()) return;\n    setBusy(true);\n    try {\n      const res = await generateText({ prompt, tone, language });\n      const ed = getActiveTextEditor();\n      const caret = ed?.state.selection.from;\n      showResult({\n        title: ai.tab.generate,\n        text: res.text,\n        original: '',\n        kind: 'expand',\n        rationale: ai.rationales.generation,\n        // Insert path (empty original) \u2014 keep caret so Apply drops text there.\n        scope: 'doc',\n        selectionFrom: caret,\n        selectionTo: caret,\n      });\n      addToast(t.text.ai.toasts.generated, 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : t.text.ai.toasts.generic, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const runRewrite = async () => {\n    const scope = captureScope();\n    if (!scope.text.trim()) {\n      addToast(t.text.ai.toasts.selectText, 'warning');\n      return;\n    }\n    setBusy(true);\n    try {\n      const res = await rewriteText({ text: scope.text, instruction, tone });\n      showResult({\n        title: ai.tab.rewrite,\n        text: res.text,\n        original: scope.original,\n        kind: 'rewrite',\n        rationale: instruction,\n        scope: scope.scope,\n        selectionFrom: scope.selectionFrom,\n        selectionTo: scope.selectionTo,\n      });\n      addToast(t.text.ai.toasts.rewriteReady, 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : t.text.ai.toasts.generic, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const runOps = async () => {\n    const scope = captureScope();\n    if (!scope.text.trim()) {\n      addToast(t.text.ai.toasts.selectText, 'warning');\n      return;\n    }\n    setBusy(true);\n    try {\n      const res = await runSectionOp({ text: scope.text, op: sectionOp, locale: language });\n      showResult({\n        title: ai.tab.ops,\n        text: res.text,\n        original: scope.original,\n        kind: sectionOp === 'expand' ? 'expand' : sectionOp,\n        rationale: res.rationale || sectionOp,\n        scope: scope.scope,\n        selectionFrom: scope.selectionFrom,\n        selectionTo: scope.selectionTo,\n      });\n      addToast(t.text.ai.toasts.opReady(ai.ops[sectionOp]), 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : t.text.ai.toasts.generic, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const runOutline = async () => {\n    if (!prompt.trim()) return;\n    setBusy(true);\n    try {\n      const res = await generateOutline({ topic: prompt, docType });\n      const outlineBlocks = [\n        {\n          type: 'heading' as const,\n          attrs: { level: 1 },\n          content: [{ type: 'text' as const, text: prompt }],\n        },\n        ...res.sections.flatMap((sec) => [\n          {\n            type: 'heading' as const,\n            attrs: { level: 2 },\n            content: [{ type: 'text' as const, text: sec.heading }],\n          },\n          {\n            type: 'paragraph' as const,\n            content: sec.intent\n              ? [{ type: 'text' as const, text: ai.outlineIntent(sec.intent) }]\n              : [],\n          },\n        ]),\n      ];\n\n      // Append after existing content \u2014 never wipe what the user already wrote.\n      const editor = getActiveTextEditor();\n      if (editor) {\n        const end = editor.state.doc.content.size;\n        editor.chain().focus().insertContentAt(end, outlineBlocks).run();\n        setDocFromEditor(editor.getJSON());\n      } else {\n        const existing = (doc.content ?? []).filter((node) => {\n          if (node.type !== 'paragraph') return true;\n          const text = (node.content ?? [])\n            .map((n) => (n.type === 'text' ? n.text ?? '' : ''))\n            .join('');\n          return text.trim().length > 0;\n        });\n        setDoc({ type: 'doc', content: [...existing, ...outlineBlocks] });\n      }\n      addToast(t.text.ai.toasts.outlineApplied, 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : t.text.ai.toasts.generic, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const runBrand = async () => {\n    const scope = captureScope();\n    if (!scope.text.trim()) {\n      addToast(\n        textScope === 'selection'\n          ? t.text.ai.toasts.selectText\n          : t.text.ai.toasts.selectOrWrite,\n        'warning'\n      );\n      return;\n    }\n    const preferredTerms = preferredTermsDraft\n      .split('\\n')\n      .map((s) => s.trim())\n      .filter(Boolean);\n    const forbiddenTerms = forbiddenTermsDraft\n      .split('\\n')\n      .map((s) => s.trim())\n      .filter(Boolean);\n    setBusy(true);\n    try {\n      setBrandVoice({ preferredTerms, forbiddenTerms, tone });\n      const score = await scoreBrandVoice({\n        text: scope.text,\n        preferredTerms,\n        forbiddenTerms,\n        tone,\n      });\n      setBrandVoice({ score: score.score, notes: score.notes });\n      if (score.score < 85) {\n        const res = await rewriteText({\n          text: scope.text.slice(0, 4000),\n          instruction: ai.brandAlignInstruction(score.notes.join('; ')),\n          tone,\n        });\n        showResult({\n          title: ai.tab.brand,\n          text: res.text,\n          original: scope.original,\n          kind: 'brand',\n          rationale: ai.brandScoreRationale(score.score),\n          scope: scope.scope,\n          selectionFrom: scope.selectionFrom,\n          selectionTo: scope.selectionTo,\n        });\n      }\n      addToast(t.text.ai.toasts.brandScore(score.score), 'info');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : t.text.ai.toasts.generic, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const runAb = async () => {\n    const entries = abHooks\n      .map((s, i) => ({ text: s.trim(), letter: hookLetter(i) }))\n      .filter((e) => e.text);\n    if (entries.length < 2) {\n      addToast(t.text.ai.toasts.separateHooks, 'warning');\n      return;\n    }\n    setBusy(true);\n    try {\n      const res = await scoreAbVariants({ variants: entries.map((e) => e.text) });\n      setAbScores(\n        res.scores.map((s, i) => ({\n          letter: entries[i]?.letter ?? hookLetter(i),\n          clarity: s.clarity,\n          ctaStrength: s.ctaStrength,\n          brandFit: s.brandFit,\n          notes: s.notes,\n        }))\n      );\n      addToast(t.text.ai.toasts.abScored, 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : t.text.ai.toasts.generic, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const runCompliance = async () => {\n    const scope = captureScope();\n    if (!scope.text.trim()) {\n      addToast(t.text.ai.toasts.selectOrWrite, 'warning');\n      return;\n    }\n    const industryValue = resolveIndustry();\n    if (!industryValue) {\n      addToast(ai.industryOtherRequired, 'warning');\n      return;\n    }\n    setBusy(true);\n    try {\n      const res = await runCompliancePass({\n        text: scope.text,\n        industry: industryValue,\n        forbidden: brandVoice.forbiddenTerms,\n        disclaimers: brandVoice.legalDisclaimers,\n      });\n      const flags = presentComplianceFlags(res.flags ?? [], locale);\n      setComplianceFlags(flags);\n      setComplianceRan(true);\n      const outcome = complianceOutcome(flags);\n      if (outcome === 'block') {\n        addToast(ai.toasts.complianceBlock, 'warning');\n      } else if (outcome === 'warn') {\n        addToast(ai.toasts.complianceWarn, 'warning');\n      } else {\n        addToast(ai.toasts.complianceOk, 'success');\n      }\n    } catch (err) {\n      setComplianceRan(false);\n      setComplianceFlags([]);\n      addToast(err instanceof Error ? err.message : t.text.ai.toasts.generic, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const runVoice = async () => {\n    const scope = captureScope();\n    const fromInput = voiceSamples\n      .split(/\\n---\\n|\\n\\n/)\n      .map((s) => s.trim())\n      .filter(Boolean);\n    const samples = fromInput.length ? fromInput : textBankSamples.filter(Boolean);\n    if (!scope.text.trim()) {\n      addToast(t.text.ai.toasts.selectOrWrite, 'warning');\n      return;\n    }\n    if (!samples.length) {\n      addToast(t.text.ai.toasts.pasteSamples, 'warning');\n      return;\n    }\n    setBusy(true);\n    try {\n      const res = await voiceMatchRewrite({ text: scope.text, samples });\n      showResult({\n        title: ai.tab.voice,\n        text: res.text,\n        original: scope.original,\n        kind: 'brand',\n        rationale: res.rationale || ai.rationales.voiceMatch,\n        scope: scope.scope,\n        selectionFrom: scope.selectionFrom,\n        selectionTo: scope.selectionTo,\n      });\n      addToast(t.text.ai.toasts.voiceMatchReady, 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : t.text.ai.toasts.generic, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const runClip = async () => {\n    const scope = captureScope();\n    if (!scope.text.trim()) {\n      addToast(t.text.ai.toasts.selectOrWrite, 'warning');\n      return;\n    }\n    setBusy(true);\n    try {\n      const res = await generateText({\n        prompt: ai.clipPrompt(scope.text.slice(0, 4000)),\n        language,\n        maxWords: 120,\n      });\n      setVariants([\n        ...variants.filter((v) => v.channel !== 'instagram'),\n        {\n          id: `var_clip_${Date.now()}`,\n          channel: 'instagram',\n          title: ai.clipVariantTitle,\n          content: res.text,\n          stale: false,\n          updatedAt: Date.now(),\n        },\n      ]);\n      setRightTab('variants');\n      addToast(t.text.ai.toasts.clipInVariants, 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : t.text.ai.toasts.generic, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const runTranscript = async (file: File) => {\n    setBusy(true);\n    try {\n      const segments = await transcribeAudio({ file });\n      const paragraphs = segments.map((seg) => ({\n        type: 'paragraph' as const,\n        content: [\n          {\n            type: 'text' as const,\n            text: `[${seg.start.toFixed(1)}s] ${seg.text.trim()}`,\n          },\n        ],\n      }));\n      const next = {\n        type: 'doc' as const,\n        content: [\n          {\n            type: 'heading' as const,\n            attrs: { level: 1 },\n            content: [{ type: 'text' as const, text: t.text.ai.sectionFallback }],\n          },\n          ...paragraphs,\n        ],\n      };\n      setDoc(next);\n      getActiveTextEditor()?.commands.setContent(next);\n      addToast(t.text.ai.toasts.segmentsImported(segments.length), 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : t.text.ai.toasts.transcribeError, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const selectTool = (id: Tab) => {\n    setTab(id);\n    setToolOpen(true);\n    setTextScope('doc');\n    if (id === 'brand') {\n      setPreferredTermsDraft(brandVoice.preferredTerms.join('\\n'));\n      setForbiddenTermsDraft(brandVoice.forbiddenTerms.join('\\n'));\n    }\n  };\n\n  const activeTool = ALL_TOOLS.find((x) => x.id === tab);\n\n  const voiceSamplesList = voiceSamples\n    .split(/\\n---\\n|\\n\\n/)\n    .map((s) => s.trim())\n    .filter(Boolean);\n  const abVariantCount = abHooks.map((s) => s.trim()).filter(Boolean).length;\n\n  const hookLetter = (index: number) => String.fromCharCode(65 + index);\n\n  const updateAbHook = (index: number, value: string) => {\n    setAbHooks((prev) => prev.map((h, i) => (i === index ? value : h)));\n  };\n\n  const addAbHook = () => {\n    setAbHooks((prev) => [...prev, '']);\n  };\n\n  const removeAbHook = (index: number) => {\n    setAbHooks((prev) => (prev.length <= 2 ? prev : prev.filter((_, i) => i !== index)));\n  };\n\n  const canRun =\n    tab === 'generate' || tab === 'outline'\n      ? prompt.trim().length > 0\n      : tab === 'rewrite'\n        ? scopedText().trim().length > 0 && instruction.trim().length > 0\n        : tab === 'ops'\n          ? scopedText().trim().length > 0\n          : tab === 'brand'\n            ? scopedText().trim().length > 0\n            : tab === 'ab'\n              ? abVariantCount >= 2\n              : tab === 'compliance'\n                ? scopedText().trim().length > 0\n                : tab === 'voice'\n                  ? scopedText().trim().length > 0 &&\n                    (voiceSamplesList.length > 0 || textBankSamples.some(Boolean))\n                  : tab === 'clip'\n                    ? scopedText().trim().length > 0\n                    : true;\n\n  const runActive = () => {\n    if (tab === 'generate') void runGenerate();\n    else if (tab === 'rewrite') void runRewrite();\n    else if (tab === 'ops') void runOps();\n    else if (tab === 'outline') void runOutline();\n    else if (tab === 'brand') void runBrand();\n    else if (tab === 'ab') void runAb();\n    else if (tab === 'compliance') void runCompliance();\n    else if (tab === 'voice') void runVoice();\n    else if (tab === 'clip') void runClip();\n  };\n\n  const renderTools = (tools: ToolDef[]) => (\n    <div className=\"flex flex-col gap-1.5\">\n      {tools.map((tool) => (\n        <ToolRow\n          key={tool.id}\n          tool={tool}\n          name={ai.tab[tool.id]}\n          description={ai.endpointHint[tool.id]}\n          onClick={() => selectTool(tool.id)}\n        />\n      ))}\n    </div>\n  );\n\n  if (!toolOpen) {\n    return (\n      <PanelBody className=\"h-full min-h-0 overflow-y-auto\">\n        <PanelSection>\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n            {ai.catalogHint}\n          </TextBody>\n          {renderTools(ALL_TOOLS)}\n        </PanelSection>\n      </PanelBody>\n    );\n  }\n\n  return (\n    <PanelBody className=\"h-full min-h-0 overflow-y-auto\">\n      <PanelSection title={ai.tab[tab]} description={ai.endpointHint[tab]}>\n        <button\n          type=\"button\"\n          onClick={() => setToolOpen(false)}\n          className=\"flex w-full cursor-pointer items-center gap-2 rounded-xl border border-transparent bg-black-capsule px-2.5 py-2 text-left transition-colors hover:bg-[var(--we-accent-muted)]\"\n        >\n          <span className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-[var(--we-accent)] text-white\">\n            <ChevronLeft size={16} />\n          </span>\n          <span className=\"min-w-0 flex-1\">\n            <TextTitle as=\"span\" size=\"sm\" className=\"block text-white\">\n              {ai.chooseAnotherTool}\n            </TextTitle>\n            <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 block text-white/80\">\n              {activeTool ? ai.tab[activeTool.id] : ''}\n            </TextBody>\n          </span>\n        </button>\n\n        <PanelField\n          label={ai.toneLabel}\n          trailing={\n            <SelectDropdown\n              value={tone}\n              options={toneOptions}\n              onChange={(v) => setTone(v as TextTone)}\n              ariaLabel={ai.toneLabel}\n            />\n          }\n        />\n\n        {(tab === 'generate' || tab === 'outline') && (\n          <textarea\n            value={prompt}\n            onChange={(e) => setPrompt(e.target.value)}\n            onKeyDown={(e) => onEnterRun(e, canRun, runActive)}\n            placeholder={\n              tab === 'outline' ? ai.placeholders.outline : ai.placeholders.prompt\n            }\n            className={`h-24 ${TEXTAREA_CLASS}`}\n          />\n        )}\n\n        {tab === 'rewrite' && (\n          <textarea\n            value={instruction}\n            onChange={(e) => setInstruction(e.target.value)}\n            onKeyDown={(e) => onEnterRun(e, canRun, runActive)}\n            placeholder={ai.placeholders.rewriteInstruction}\n            className={`h-20 ${TEXTAREA_CLASS}`}\n          />\n        )}\n\n        {(tab === 'rewrite' ||\n          tab === 'ops' ||\n          tab === 'brand' ||\n          tab === 'voice' ||\n          tab === 'compliance' ||\n          tab === 'clip') && (\n          <>\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {ai.textScopeLabel}\n            </TextBody>\n            <ToolPanelTabs\n              dense\n              className=\"rounded-xl border border-panel-border bg-black-capsule !border-b-0\"\n              tabs={[\n                { id: 'doc' as const, label: ai.brandUseDoc },\n                { id: 'selection' as const, label: ai.brandUseSelection },\n              ]}\n              value={textScope}\n              onChange={setTextScope}\n            />\n            {textScope === 'selection' && !selectionOnly().trim() ? (\n              <TextBody as=\"p\" size=\"sm\" className=\"rounded-xl border border-amber-500/30 bg-amber-500/10 px-2.5 py-2 text-amber-200\">\n                {ai.brandSelectHint}\n              </TextBody>\n            ) : (\n              <TextBody as=\"p\" size=\"sm\" className=\"max-h-20 overflow-y-auto whitespace-pre-wrap rounded-xl border border-panel-border bg-black-capsule p-2.5 text-white/80\">\n                {scopedText().slice(0, 600) || '\u2014'}\n                {scopedText().length > 600 ? '\u2026' : ''}\n              </TextBody>\n            )}\n          </>\n        )}\n\n        {tab === 'ops' && (\n          <PanelField\n            label={ai.opLabel}\n            trailing={\n              <SelectDropdown\n                value={sectionOp}\n                options={opOptions}\n                onChange={(v) => setSectionOp(v as SectionOp)}\n                ariaLabel={ai.opLabel}\n              />\n            }\n          />\n        )}\n\n        {tab === 'brand' && (\n          <>\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {ai.brandPreferredLabel}\n            </TextBody>\n            <textarea\n              value={preferredTermsDraft}\n              onChange={(e) => setPreferredTermsDraft(e.target.value)}\n              onKeyDown={(e) => onEnterRun(e, canRun, runActive)}\n              placeholder={ai.placeholders.preferredTerms}\n              className={`h-20 ${TEXTAREA_CLASS}`}\n            />\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {ai.brandForbiddenLabel}\n            </TextBody>\n            <textarea\n              value={forbiddenTermsDraft}\n              onChange={(e) => setForbiddenTermsDraft(e.target.value)}\n              onKeyDown={(e) => onEnterRun(e, canRun, runActive)}\n              placeholder={ai.placeholders.forbiddenTerms}\n              className={`h-20 ${TEXTAREA_CLASS}`}\n            />\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {ai.brandScoreLabel}{' '}\n              <span className=\"font-bold text-[var(--we-accent)]\">\n                {brandVoice.score != null ? brandVoice.score : '\u2014'}\n              </span>\n              {brandVoice.notes.length > 0 && (\n                <span className=\"mt-1 block\">{brandVoice.notes.join(' \u00B7 ')}</span>\n              )}\n            </TextBody>\n          </>\n        )}\n\n        {tab === 'ab' && (\n          <>\n            <div className=\"flex flex-col gap-2\">\n              {abHooks.map((hook, index) => {\n                const letter = hookLetter(index);\n                return (\n                  <div key={index} className=\"flex flex-col gap-1\">\n                    <div className=\"flex items-center justify-between gap-2\">\n                      <TextBody as=\"label\" size=\"sm\" className=\"uppercase tracking-wider text-white\">\n                        {ai.hookLabel(letter)}\n                      </TextBody>\n                      {abHooks.length > 2 && (\n                        <IconButton\n                          variant=\"ghost\"\n                          size=\"sm\"\n                          label={ai.removeHook}\n                          onClick={() => removeAbHook(index)}\n                        >\n                          <Trash2 size={12} />\n                        </IconButton>\n                      )}\n                    </div>\n                    <textarea\n                      value={hook}\n                      onChange={(e) => updateAbHook(index, e.target.value)}\n                      onKeyDown={(e) => onEnterRun(e, canRun, runActive)}\n                      placeholder={ai.hookPlaceholder(letter)}\n                      rows={2}\n                      className={`min-h-[3.5rem] ${TEXTAREA_CLASS}`}\n                    />\n                  </div>\n                );\n              })}\n              <Button\n                type=\"button\"\n                variant=\"outline\"\n                size=\"sm\"\n                className=\"w-full\"\n                icon={<Plus size={14} />}\n                onClick={addAbHook}\n              >\n                {ai.addHook}\n              </Button>\n            </div>\n            {abScores.length > 0 && (\n              <ul className=\"max-h-32 space-y-1.5 overflow-y-auto rounded-xl border border-panel-border bg-black-capsule p-2.5 text-white/80\">\n                {abScores.map((s, i) => (\n                  <TextBody as=\"li\" size=\"sm\" key={i} className=\"border-b border-panel-border/60 pb-1.5 last:border-0 last:pb-0\">\n                    <span className=\"font-semibold text-emerald-300\">\n                      {ai.hookLabel(s.letter)}\n                    </span>\n                    {' \u00B7 '}\n                    {ai.abScoreClarity} {s.clarity} \u00B7 {ai.abScoreCta} {s.ctaStrength} \u00B7{' '}\n                    {ai.abScoreBrand} {s.brandFit}\n                    {s.notes ? ` \u2014 ${s.notes}` : ''}\n                  </TextBody>\n                ))}\n              </ul>\n            )}\n          </>\n        )}\n\n        {tab === 'compliance' && (\n          <>\n            <PanelField\n              label={ai.industryLabel}\n              trailing={\n                <SelectDropdown\n                  value={industry}\n                  options={industryOptions}\n                  onChange={(v) => {\n                    setIndustry(v);\n                    setComplianceRan(false);\n                    setComplianceFlags([]);\n                  }}\n                  ariaLabel={ai.industryLabel}\n                />\n              }\n            />\n            {industry === INDUSTRY_OTHER && (\n              <input\n                type=\"text\"\n                value={customIndustry}\n                onChange={(e) => {\n                  setCustomIndustry(e.target.value);\n                  setComplianceRan(false);\n                  setComplianceFlags([]);\n                }}\n                placeholder={ai.industryOtherPlaceholder}\n                aria-label={ai.industries.other}\n                className={INPUT_CLASS}\n              />\n            )}\n            {complianceRan && (\n              <div className=\"space-y-2 rounded-xl border border-panel-border bg-black-capsule p-3\">\n                <TextTitle as=\"p\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n                  {ai.complianceResultsTitle}\n                </TextTitle>\n                <TextBody\n                  as=\"p\"\n                  size=\"sm\"\n                  className={`leading-snug ${\n                    complianceOutcome(complianceFlags) === 'block'\n                      ? 'text-rose-300'\n                      : complianceOutcome(complianceFlags) === 'warn'\n                        ? 'text-amber-300'\n                        : 'text-emerald-300'\n                  }`}\n                >\n                  {complianceOutcome(complianceFlags) === 'block'\n                    ? ai.complianceSummaryBlock\n                    : complianceOutcome(complianceFlags) === 'warn'\n                      ? ai.complianceSummaryWarn\n                      : ai.complianceSummaryOk}\n                </TextBody>\n                {complianceFlags.length > 0 && (\n                  <ul className=\"max-h-40 space-y-2 overflow-y-auto\">\n                    {complianceFlags.map((f, i) => (\n                      <li\n                        key={`${f.severity}-${i}`}\n                        className=\"rounded-lg border border-panel-border/70 bg-black-capsule-hover/40 px-2.5 py-2\"\n                      >\n                        <TextBody\n                          as=\"span\"\n                          size=\"sm\"\n                          className={`mb-1 inline-block rounded-md px-1.5 py-0.5 font-bold uppercase tracking-wide ${\n                            f.severity === 'block'\n                              ? 'bg-rose-500/20 text-rose-300'\n                              : 'bg-amber-500/20 text-amber-300'\n                          }`}\n                        >\n                          {ai.complianceSeverity[f.severity]}\n                        </TextBody>\n                        <TextBody as=\"p\" size=\"sm\" className=\"leading-snug text-white\">\n                          {f.message}\n                        </TextBody>\n                      </li>\n                    ))}\n                  </ul>\n                )}\n              </div>\n            )}\n          </>\n        )}\n\n        {tab === 'voice' && (\n          <>\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {textBankSamples.length\n                ? ai.voiceWithBank(textBankSamples.length)\n                : ai.voiceNoBank}\n            </TextBody>\n            <textarea\n              value={voiceSamples}\n              onChange={(e) => setVoiceSamples(e.target.value)}\n              onKeyDown={(e) => onEnterRun(e, canRun, runActive)}\n              placeholder={ai.placeholders.voiceSamples}\n              className={`h-28 ${TEXTAREA_CLASS}`}\n            />\n          </>\n        )}\n\n        {tab === 'clip' && (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n            {ai.clipHint}\n          </TextBody>\n        )}\n\n        {tab === 'transcript' && (\n          <>\n            {busy ? (\n              <SubtitleAiLoader\n                variant=\"card\"\n                label={ai.audioTranscribing}\n                hint={ai.audioTranscribingHint}\n              />\n            ) : (\n              <label className=\"flex h-28 cursor-pointer flex-col items-center justify-center gap-2 rounded-xl border border-dashed border-panel-border bg-black-capsule hover:border-[var(--we-accent)]\">\n                <span className=\"flex h-8 w-8 items-center justify-center rounded-lg bg-[var(--we-accent)] text-white\">\n                  <Mic size={16} />\n                </span>\n                <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                  {ai.audioUploadLabel}\n                </TextBody>\n                <input\n                  type=\"file\"\n                  accept=\"audio/*,video/*,.mp3,.wav,.mp4,.webm\"\n                  className=\"hidden\"\n                  onChange={(e) => {\n                    const f = e.target.files?.[0];\n                    e.target.value = '';\n                    if (f) void runTranscript(f);\n                  }}\n                />\n              </label>\n            )}\n          </>\n        )}\n\n        {tab !== 'transcript' && (\n          <Button\n            variant=\"accent\"\n            size=\"md\"\n            className=\"w-full\"\n            loading={busy}\n            disabled={!canRun || busy}\n            icon={tab === 'outline' ? <FileText size={14} /> : <Sparkles size={14} />}\n            onClick={runActive}\n          >\n            {ai.runButton}\n          </Button>\n        )}\n      </PanelSection>\n\n      <TextAiResultModal\n        open={Boolean(resultDraft)}\n        title={resultDraft?.title ?? ai.tab.generate}\n        text={resultDraft?.text ?? ''}\n        onClose={() => setResultDraft(null)}\n        onInsert={() => {\n          if (!resultDraft) return;\n          insertResultText(resultDraft);\n          setResultDraft(null);\n          addToast(ai.toasts.inserted, 'success');\n        }}\n        onSaveSuggestion={() => {\n          if (!resultDraft) return;\n          pushSug(\n            resultDraft.original,\n            resultDraft.text,\n            resultDraft.kind,\n            resultDraft.rationale\n          );\n          setResultDraft(null);\n          addToast(ai.toasts.sentToSuggestions, 'success');\n        }}\n      />\n    </PanelBody>\n  );\n};\n", "/**\n * OpenAI-style tool definitions for the text conversational agent.\n */\n\nimport type { AgentToolDef } from '../../../services/text/textAgentService';\n\nexport const TEXT_AGENT_TOOLS: AgentToolDef[] = [\n  {\n    type: 'function',\n    function: {\n      name: 'generate_content',\n      description:\n        'Write NEW copy from a brief/prompt and insert it into the document. Use when the user asks to add, draft, or write text (e.g. about their brand) and there may be little or no existing document text. Prefer this over rewrite when creating content from scratch.',\n      parameters: {\n        type: 'object',\n        properties: {\n          prompt: {\n            type: 'string',\n            description: 'What to write (topic, brand angle, length, tone hints)',\n          },\n          maxWords: { type: 'number' },\n        },\n        required: ['prompt'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'rewrite_selection',\n      description:\n        'Rewrite existing document/selection text (creates an accept/reject suggestion). Requires non-empty document or selection. Do NOT use for colors/fonts \u2014 those are not supported.',\n      parameters: {\n        type: 'object',\n        properties: {\n          instruction: { type: 'string' },\n          text: { type: 'string', description: 'Text to rewrite if no selection' },\n        },\n        required: ['instruction'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'change_tone',\n      description: 'Change tone of the document or selection',\n      parameters: {\n        type: 'object',\n        properties: {\n          tone: {\n            type: 'string',\n            enum: ['neutral', 'formal', 'casual', 'persuasive', 'technical', 'friendly'],\n          },\n          text: { type: 'string' },\n        },\n        required: ['tone'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'expand_section',\n      description: 'Expand a section heading into a draft paragraph (suggestion)',\n      parameters: {\n        type: 'object',\n        properties: {\n          heading: { type: 'string' },\n          intent: { type: 'string' },\n        },\n        required: ['heading'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'tighten',\n      description: 'Make text more concise',\n      parameters: {\n        type: 'object',\n        properties: { text: { type: 'string' } },\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'insert_section',\n      description: 'Insert a new H2 section with placeholder body',\n      parameters: {\n        type: 'object',\n        properties: {\n          heading: { type: 'string' },\n          body: { type: 'string' },\n        },\n        required: ['heading'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'generate_variants',\n      description: 'Generate multichannel variants from the document',\n      parameters: {\n        type: 'object',\n        properties: {\n          channels: {\n            type: 'array',\n            items: { type: 'string' },\n          },\n        },\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'translate_document',\n      description: 'Translate document text to a target language (suggestion)',\n      parameters: {\n        type: 'object',\n        properties: {\n          targetLanguage: { type: 'string' },\n          text: { type: 'string' },\n        },\n        required: ['targetLanguage'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'apply_brand_voice',\n      description: 'Score and rewrite toward brand voice',\n      parameters: { type: 'object', properties: {} },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'create_outline',\n      description: 'Create an outline for a topic and replace document structure',\n      parameters: {\n        type: 'object',\n        properties: {\n          topic: { type: 'string' },\n          docType: { type: 'string' },\n        },\n        required: ['topic'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'summarize',\n      description: 'Summarize the document into a short blurb (suggestion)',\n      parameters: {\n        type: 'object',\n        properties: { maxWords: { type: 'number' } },\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'export_document',\n      description: 'Open the export modal',\n      parameters: {\n        type: 'object',\n        properties: {\n          format: { type: 'string', enum: ['md', 'html', 'pdf', 'docx', 'txt'] },\n        },\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'handoff_to_video',\n      description: 'Flag intent to hand off document as video text/subtitle clips',\n      parameters: { type: 'object', properties: {} },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'handoff_to_audio',\n      description: 'Flag intent to hand off document as TTS voiceover project',\n      parameters: { type: 'object', properties: {} },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'section_op',\n      description: 'Typed section operation: tighten, elevate, localize, or expand',\n      parameters: {\n        type: 'object',\n        properties: {\n          op: {\n            type: 'string',\n            enum: ['tighten', 'elevate', 'localize', 'expand'],\n          },\n          text: { type: 'string' },\n          locale: { type: 'string' },\n        },\n        required: ['op'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'analyze_claims',\n      description: 'Detect claims that need citations',\n      parameters: { type: 'object', properties: {} },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'compliance_pass',\n      description: 'Run a compliance / legal language pass',\n      parameters: {\n        type: 'object',\n        properties: { industry: { type: 'string' } },\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'make_clip_script',\n      description: 'Create a short-form clip/Reel script variant from the document',\n      parameters: {\n        type: 'object',\n        properties: {\n          platform: { type: 'string', enum: ['instagram', 'youtube', 'x'] },\n        },\n      },\n    },\n  },\n];\n\nexport const COSTLY_TOOLS = new Set([\n  'generate_content',\n  'rewrite_selection',\n  'change_tone',\n  'expand_section',\n  'tighten',\n  'generate_variants',\n  'translate_document',\n  'apply_brand_voice',\n  'create_outline',\n  'summarize',\n  'handoff_to_video',\n  'handoff_to_audio',\n  'section_op',\n  'analyze_claims',\n  'compliance_pass',\n  'make_clip_script',\n]);\n", "/**\n * User-facing labels and error copy for the text chat agent.\n */\n\nimport { toUserFacingError } from '../../../utils/userFacingError';\nimport { getActiveMessages } from '../../../i18n';\n\nexport function textToolLabel(name: string): string {\n  const tools = getActiveMessages().text.chat.tools as Record<string, string>;\n  return tools[name] ?? name.replace(/_/g, ' ');\n}\n\n/** Map API / runtime failures to short localized chat copy (never technical dumps). */\nexport function friendlyToolError(err: unknown): string {\n  return toUserFacingError(err, { context: 'text-agent' });\n}\n\nexport function isStyleOnlyInstruction(instruction: string): boolean {\n  return /\\b(color|rojo|azul|verde|negro|blanco|negrita|cursiva|bold|italic|underline|fuente|tipograf[i\u00ED]a|font[- ]?size|tama[n\u00F1]o de letra)\\b/i.test(\n    instruction,\n  );\n}\n", "/**\n * Executes text agent tool calls \u2014 produces suggestions rather than silent rewrites.\n */\n\nimport {\n  useTextStore,\n  getDocPlainText,\n  type TextChannel,\n  type TextTone,\n} from '../../../store/useTextStore';\nimport type { AgentToolCall } from '../../../services/text/textAgentService';\nimport {\n  analyzeClaims,\n  generateOutline,\n  generateText,\n  generateVariants,\n  rewriteText,\n  runCompliancePass,\n  runSectionOp,\n  scoreBrandVoice,\n  type SectionOp,\n} from '../../../services/text';\nimport { getActiveTextEditor } from '../../../components/text/DocumentCanvas';\nimport { aiMarkdownToHtml } from '../markdown';\nimport { insertMarkdownIntoDocument } from '../applySuggestion';\nimport { COSTLY_TOOLS } from './tools';\nimport {\n  friendlyToolError,\n  isStyleOnlyInstruction,\n  textToolLabel,\n} from './friendly';\nimport { getActiveMessages } from '../../../i18n';\n\nexport interface ToolExecutionResult {\n  toolCallId: string;\n  name: string;\n  ok: boolean;\n  summary: string;\n  requiresConfirmation?: boolean;\n  pendingArgs?: Record<string, unknown>;\n}\n\nfunction parseArgs(raw: string): Record<string, unknown> {\n  try {\n    return JSON.parse(raw || '{}') as Record<string, unknown>;\n  } catch {\n    return {};\n  }\n}\n\nfunction selectionOrDocText(args: Record<string, unknown>): string {\n  if (typeof args.text === 'string' && args.text.trim()) return args.text;\n  const editor = getActiveTextEditor();\n  if (editor) {\n    const { from, to } = editor.state.selection;\n    if (from !== to) return editor.state.doc.textBetween(from, to, ' ');\n  }\n  return getDocPlainText(useTextStore.getState().doc);\n}\n\nfunction needText(args: Record<string, unknown>): string | null {\n  const text = selectionOrDocText(args).trim();\n  return text || null;\n}\n\nfunction chatCopy() {\n  return getActiveMessages().text.chat;\n}\n\nfunction pushSuggestion(opts: {\n  kind: 'rewrite' | 'tone' | 'tighten' | 'expand' | 'elevate' | 'localize' | 'brand' | 'claim' | 'other';\n  original: string;\n  replacement: string;\n  rationale?: string;\n}) {\n  const id = useTextStore.getState().addSuggestion({\n    kind: opts.kind,\n    original: opts.original,\n    replacement: opts.replacement,\n    rationale: opts.rationale,\n  });\n  const editor = getActiveTextEditor();\n  if (editor && opts.original) {\n    const { from, to } = editor.state.selection;\n    if (from !== to) {\n      editor\n        .chain()\n        .focus()\n        .setAiSuggestion({\n          id,\n          kind: opts.kind,\n          original: opts.original,\n          replacement: opts.replacement,\n          rationale: opts.rationale || '',\n        })\n        .run();\n    }\n  }\n  return id;\n}\n\nasync function executeOne(\n  name: string,\n  args: Record<string, unknown>\n): Promise<{ ok: boolean; summary: string }> {\n  const store = useTextStore.getState();\n  const t = chatCopy();\n\n  switch (name) {\n    case 'generate_content': {\n      const prompt = String(args.prompt || '').trim();\n      if (!prompt) {\n        return { ok: false, summary: t.errors.promptRequired };\n      }\n      const maxWords = typeof args.maxWords === 'number' ? args.maxWords : 280;\n      const brandBits = [\n        store.projectName && `Marca/proyecto: ${store.projectName}`,\n        store.brandVoice.preferredTerms.length\n          ? `T\u00E9rminos preferidos: ${store.brandVoice.preferredTerms.join(', ')}`\n          : '',\n        store.tone && `Tono: ${store.tone}`,\n      ]\n        .filter(Boolean)\n        .join('. ');\n      const res = await generateText({\n        prompt: brandBits ? `${prompt}\\n\\nContexto: ${brandBits}` : prompt,\n        tone: store.tone,\n        language: store.language,\n        maxWords,\n      });\n      if (insertMarkdownIntoDocument(res.text)) {\n        return { ok: true, summary: t.summaries.contentInserted };\n      }\n      pushSuggestion({\n        kind: 'other',\n        original: '',\n        replacement: res.text,\n        rationale: prompt,\n      });\n      return { ok: true, summary: t.summaries.contentSuggested };\n    }\n    case 'rewrite_selection': {\n      const instruction =\n        typeof args.instruction === 'string' ? args.instruction : 'Mejora claridad';\n      if (isStyleOnlyInstruction(instruction)) {\n        return { ok: false, summary: t.errors.styleUnsupported };\n      }\n      const text = needText(args);\n      if (!text) return { ok: false, summary: t.errors.textRequired };\n      const res = await rewriteText({ text, instruction, tone: store.tone });\n      pushSuggestion({\n        kind: 'rewrite',\n        original: text.slice(0, 500),\n        replacement: res.text,\n        rationale: res.rationale || instruction,\n      });\n      return { ok: true, summary: t.summaries.rewrite };\n    }\n    case 'change_tone': {\n      const tone = (typeof args.tone === 'string' ? args.tone : 'neutral') as TextTone;\n      const text = needText(args);\n      if (!text) return { ok: false, summary: t.errors.textRequired };\n      const res = await rewriteText({\n        text,\n        instruction: `Cambia el tono a ${tone}`,\n        tone,\n      });\n      store.setTone(tone);\n      pushSuggestion({\n        kind: 'tone',\n        original: text.slice(0, 500),\n        replacement: res.text,\n        rationale: `Tono: ${tone}`,\n      });\n      return { ok: true, summary: t.summaries.tone(tone) };\n    }\n    case 'expand_section': {\n      const heading = String(args.heading || 'Secci\u00F3n').trim() || 'Secci\u00F3n';\n      const intent = typeof args.intent === 'string' ? args.intent : '';\n      const res = await generateText({\n        prompt: `Escribe un p\u00E1rrafo para la secci\u00F3n \"${heading}\". ${intent}`.trim(),\n        tone: store.tone,\n        language: store.language,\n        maxWords: 180,\n      });\n      pushSuggestion({\n        kind: 'expand',\n        original: '',\n        replacement: res.text,\n        rationale: `Expandir: ${heading}`,\n      });\n      return { ok: true, summary: t.summaries.expand(heading) };\n    }\n    case 'tighten': {\n      const text = needText(args);\n      if (!text) return { ok: false, summary: t.errors.textRequired };\n      const res = await rewriteText({\n        text,\n        instruction: 'Haz el texto m\u00E1s conciso sin perder el mensaje',\n        tone: store.tone,\n      });\n      pushSuggestion({\n        kind: 'tighten',\n        original: text.slice(0, 500),\n        replacement: res.text,\n      });\n      return { ok: true, summary: t.summaries.tighten };\n    }\n    case 'insert_section': {\n      const heading = String(args.heading || 'Nueva secci\u00F3n');\n      const body = typeof args.body === 'string' ? args.body : '';\n      const editor = getActiveTextEditor();\n      if (editor) {\n        editor\n          .chain()\n          .focus()\n          .insertContent([\n            { type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: heading }] },\n          ])\n          .insertContent(body ? aiMarkdownToHtml(body) : { type: 'paragraph' })\n          .run();\n        store.setDocFromEditor(editor.getJSON());\n      }\n      return { ok: true, summary: t.summaries.sectionInserted(heading) };\n    }\n    case 'generate_variants': {\n      const plain = needText(args) || getDocPlainText(store.doc).trim();\n      if (!plain) return { ok: false, summary: t.errors.textRequired };\n      const channels = Array.isArray(args.channels)\n        ? (args.channels as string[])\n        : ['instagram', 'linkedin', 'x', 'email'];\n      const res = await generateVariants({ text: plain, channels });\n      store.setVariants(\n        res.variants.map((v, i) => ({\n          id: `var_${Date.now()}_${i}`,\n          channel: v.channel as TextChannel,\n          title: v.title || v.channel,\n          content: v.content,\n          stale: false,\n          updatedAt: Date.now(),\n        }))\n      );\n      store.setRightTab('variants');\n      return { ok: true, summary: t.summaries.variants(res.variants.length) };\n    }\n    case 'translate_document': {\n      const text = needText(args);\n      if (!text) return { ok: false, summary: t.errors.textRequired };\n      const lang = String(args.targetLanguage || 'en');\n      const res = await rewriteText({\n        text,\n        instruction: `Traduce al idioma: ${lang}. Conserva el significado.`,\n      });\n      pushSuggestion({\n        kind: 'other',\n        original: text.slice(0, 500),\n        replacement: res.text,\n        rationale: `Traducci\u00F3n \u2192 ${lang}`,\n      });\n      return { ok: true, summary: t.summaries.translate(lang) };\n    }\n    case 'apply_brand_voice': {\n      const text = getDocPlainText(store.doc).trim();\n      if (!text) return { ok: false, summary: t.errors.textRequired };\n      const score = await scoreBrandVoice({\n        text,\n        preferredTerms: store.brandVoice.preferredTerms,\n        forbiddenTerms: store.brandVoice.forbiddenTerms,\n        tone: store.tone,\n      });\n      store.setBrandVoice({ score: score.score, notes: score.notes });\n      if (score.score < 80) {\n        const res = await rewriteText({\n          text: text.slice(0, 4000),\n          instruction: `Alinea con brand voice (${store.tone}). Notas: ${score.notes.join('; ')}`,\n          tone: store.tone,\n        });\n        pushSuggestion({\n          kind: 'brand',\n          original: text.slice(0, 400),\n          replacement: res.text,\n          rationale: `Brand score ${score.score}`,\n        });\n      }\n      return { ok: true, summary: t.summaries.brandScore(score.score) };\n    }\n    case 'create_outline': {\n      const topic = String(args.topic || store.projectName || '').trim();\n      if (!topic) return { ok: false, summary: t.errors.promptRequired };\n      const res = await generateOutline({\n        topic,\n        docType: typeof args.docType === 'string' ? args.docType : store.docType,\n      });\n      const content = [\n        {\n          type: 'heading',\n          attrs: { level: 1 },\n          content: [{ type: 'text', text: topic }],\n        },\n        ...res.sections.flatMap((sec) => [\n          {\n            type: 'heading',\n            attrs: { level: 2 },\n            content: [{ type: 'text', text: sec.heading }],\n          },\n          {\n            type: 'paragraph',\n            content: sec.intent\n              ? [{ type: 'text', text: `[Intenci\u00F3n: ${sec.intent}]` }]\n              : [],\n          },\n        ]),\n      ];\n      store.setDoc({ type: 'doc', content });\n      const editor = getActiveTextEditor();\n      editor?.commands.setContent({ type: 'doc', content });\n      return { ok: true, summary: t.summaries.outline(res.sections.length) };\n    }\n    case 'summarize': {\n      const text = getDocPlainText(store.doc).trim();\n      if (!text) return { ok: false, summary: t.errors.textRequired };\n      const maxWords = typeof args.maxWords === 'number' ? args.maxWords : 80;\n      const res = await generateText({\n        prompt: `Resume en m\u00E1ximo ${maxWords} palabras:\\n\\n${text.slice(0, 6000)}`,\n        language: store.language,\n        maxWords,\n      });\n      pushSuggestion({\n        kind: 'other',\n        original: '',\n        replacement: res.text,\n        rationale: 'Resumen',\n      });\n      return { ok: true, summary: t.summaries.summarize };\n    }\n    case 'export_document': {\n      store.setExportModalOpen(true);\n      return { ok: true, summary: t.summaries.exportOpen };\n    }\n    case 'handoff_to_video': {\n      store.addToast(t.summaries.handoffVideoToast, 'info');\n      store.setExportModalOpen(true);\n      return { ok: true, summary: t.summaries.handoffVideo };\n    }\n    case 'handoff_to_audio': {\n      store.addToast(t.summaries.handoffAudioToast, 'info');\n      store.setExportModalOpen(true);\n      return { ok: true, summary: t.summaries.handoffAudio };\n    }\n    case 'section_op': {\n      const text = needText(args);\n      if (!text) return { ok: false, summary: t.errors.textRequired };\n      const op = (typeof args.op === 'string' ? args.op : 'tighten') as SectionOp;\n      const res = await runSectionOp({\n        text,\n        op,\n        locale: typeof args.locale === 'string' ? args.locale : store.language,\n      });\n      pushSuggestion({\n        kind:\n          op === 'tighten' || op === 'expand' || op === 'elevate' || op === 'localize'\n            ? op\n            : 'other',\n        original: text.slice(0, 500),\n        replacement: res.text,\n        rationale: res.rationale || op,\n      });\n      return { ok: true, summary: t.summaries.sectionOp(op) };\n    }\n    case 'analyze_claims': {\n      const text = getDocPlainText(store.doc).trim();\n      if (!text) return { ok: false, summary: t.errors.textRequired };\n      const res = await analyzeClaims({ text });\n      store.setClaims(\n        res.claims.map((c, i) => ({\n          id: `claim_${Date.now()}_${i}`,\n          text: c.text,\n          status: (c.status as 'needs_citation') || 'needs_citation',\n          note: c.note,\n          createdAt: Date.now(),\n        }))\n      );\n      store.setRightTab('claims');\n      return { ok: true, summary: t.summaries.claims(res.claims.length) };\n    }\n    case 'compliance_pass': {\n      const text = getDocPlainText(store.doc).trim();\n      if (!text) return { ok: false, summary: t.errors.textRequired };\n      const res = await runCompliancePass({\n        text,\n        industry: typeof args.industry === 'string' ? args.industry : undefined,\n        forbidden: store.brandVoice.forbiddenTerms,\n        disclaimers: store.brandVoice.legalDisclaimers,\n      });\n      const { presentComplianceFlags, complianceOutcome } = await import('../complianceFeedback');\n      const { getActiveLocale } = await import('../../../i18n');\n      const flags = presentComplianceFlags(res.flags ?? [], getActiveLocale());\n      const outcome = complianceOutcome(flags);\n      const ai = getActiveMessages().text.ai;\n      store.addToast(\n        outcome === 'block'\n          ? ai.toasts.complianceBlock\n          : outcome === 'warn'\n            ? ai.toasts.complianceWarn\n            : ai.toasts.complianceOk,\n        outcome === 'ok' ? 'success' : 'warning'\n      );\n      return {\n        ok: true,\n        summary:\n          outcome === 'block'\n            ? ai.complianceSummaryBlock\n            : outcome === 'warn'\n              ? ai.complianceSummaryWarn\n              : ai.complianceSummaryOk,\n      };\n    }\n    case 'make_clip_script': {\n      const plain = getDocPlainText(store.doc).trim();\n      if (!plain) return { ok: false, summary: t.errors.textRequired };\n      const platform = typeof args.platform === 'string' ? args.platform : 'instagram';\n      const res = await generateText({\n        prompt: `Convierte esto en un guion corto tipo Reel/Shorts para ${platform} (hook + 3 beats + CTA), m\u00E1ximo 120 palabras:\\n\\n${plain.slice(0, 4000)}`,\n        language: store.language,\n        maxWords: 120,\n      });\n      const channel = (\n        platform === 'youtube' ? 'youtube' : platform === 'x' ? 'x' : 'instagram'\n      ) as TextChannel;\n      store.setVariants([\n        ...store.variants.filter((v) => v.channel !== channel),\n        {\n          id: `var_clip_${Date.now()}`,\n          channel,\n          title: `Guion corto (${platform})`,\n          content: res.text,\n          stale: false,\n          updatedAt: Date.now(),\n        },\n      ]);\n      store.setRightTab('variants');\n      return { ok: true, summary: t.summaries.clip(platform) };\n    }\n    default:\n      return { ok: false, summary: t.errors.unknownTool(name) };\n  }\n}\n\nexport async function executeToolCalls(\n  toolCalls: AgentToolCall[],\n  opts?: { confirmCostly?: boolean }\n): Promise<ToolExecutionResult[]> {\n  const t = chatCopy();\n  const results: ToolExecutionResult[] = [];\n  for (const call of toolCalls) {\n    const name = call.function.name;\n    const args = parseArgs(call.function.arguments);\n    if (opts?.confirmCostly && COSTLY_TOOLS.has(name)) {\n      const label = textToolLabel(name);\n      results.push({\n        toolCallId: call.id,\n        name,\n        ok: false,\n        summary: t.confirmAction(label),\n        requiresConfirmation: true,\n        pendingArgs: args,\n      });\n      continue;\n    }\n    try {\n      const r = await executeOne(name, args);\n      results.push({ toolCallId: call.id, name, ok: r.ok, summary: r.summary });\n    } catch (err) {\n      results.push({\n        toolCallId: call.id,\n        name,\n        ok: false,\n        summary: friendlyToolError(err),\n      });\n    }\n  }\n  return results;\n}\n\nexport async function executeConfirmedTool(\n  name: string,\n  args: Record<string, unknown>,\n  toolCallId: string\n): Promise<ToolExecutionResult> {\n  try {\n    const r = await executeOne(name, args);\n    return { toolCallId, name, ok: r.ok, summary: r.summary };\n  } catch (err) {\n    return {\n      toolCallId,\n      name,\n      ok: false,\n      summary: friendlyToolError(err),\n    };\n  }\n}\n", "import React, { useRef, useState } from 'react';\nimport { Loader2, Send } from 'lucide-react';\nimport { useTextStore } from '../../store/useTextStore';\nimport {\n  runTextAgentTurn,\n  type AgentMessage,\n} from '../../services/text/textAgentService';\nimport { TEXT_AGENT_TOOLS } from '../../lib/text/agent/tools';\nimport {\n  executeConfirmedTool,\n  executeToolCalls,\n} from '../../lib/text/agent/executor';\nimport { friendlyToolError, textToolLabel } from '../../lib/text/agent/friendly';\nimport { useTranslation } from '../../i18n';\nimport { Button, IconButton, PanelField, Switch, TextBody } from '../ui';\n\nconst MAX_AGENT_ROUNDS = 4;\n\ntype ChatBubble = {\n  id: string;\n  role: 'user' | 'assistant' | 'tool';\n  content: string;\n  /** false = failed tool / error copy (amber). */\n  ok?: boolean;\n  pending?: { name: string; args: Record<string, unknown>; toolCallId: string };\n};\n\n/**\n * Conversational text agent \u2014 same multi-round loop as AudioChatPanel.\n */\nexport const TextChatPanel: React.FC = () => {\n  const tr = useTranslation();\n  const [input, setInput] = useState('');\n  const [busy, setBusy] = useState(false);\n  const [bubbles, setBubbles] = useState<ChatBubble[]>([]);\n  const historyRef = useRef<AgentMessage[]>([]);\n  /** After a plan was shown, next turns use tools until toggle is re-enabled. */\n  const planPresentedRef = useRef(false);\n  const addToast = useTextStore((s) => s.addToast);\n  const getProjectSnapshot = useTextStore((s) => s.getProjectSnapshot);\n  const agentPlanMode = useTextStore((s) => s.agentPlanMode);\n  const setAgentPlanMode = useTextStore((s) => s.setAgentPlanMode);\n\n  const runTurn = async (userText?: string) => {\n    if (busy) return;\n    const text = (userText ?? input).trim();\n    if (!text && !historyRef.current.length) return;\n\n    setBusy(true);\n    if (text) {\n      historyRef.current.push({ role: 'user', content: text });\n      setBubbles((b) => [\n        ...b,\n        { id: `u_${Date.now()}`, role: 'user', content: text },\n      ]);\n      setInput('');\n    }\n\n    const executePlan =\n      /ejecuta(r)?\\s+el\\s+plan/i.test(text) || /execute\\s+plan/i.test(text);\n    // Plan mode only strips tools on the *first* planning turn; afterwards tools work.\n    const usePlanMode =\n      agentPlanMode && !executePlan && !planPresentedRef.current;\n\n    if (executePlan) {\n      planPresentedRef.current = true;\n    }\n\n    try {\n      for (let round = 0; round < MAX_AGENT_ROUNDS; round++) {\n        const reply = await runTextAgentTurn({\n          messages: historyRef.current,\n          projectSnapshot: getProjectSnapshot(),\n          tools: TEXT_AGENT_TOOLS,\n          planMode: usePlanMode && round === 0,\n        });\n\n        historyRef.current.push({\n          role: 'assistant',\n          content: reply.content,\n          tool_calls: reply.tool_calls,\n        });\n\n        if (reply.content) {\n          setBubbles((b) => [\n            ...b,\n            {\n              id: `a_${Date.now()}_${round}`,\n              role: 'assistant',\n              content: reply.content || '',\n            },\n          ]);\n        }\n\n        if (usePlanMode && round === 0 && !reply.tool_calls?.length) {\n          planPresentedRef.current = true;\n          setBubbles((b) => [\n            ...b,\n            {\n              id: `hint_${Date.now()}`,\n              role: 'assistant',\n              content: tr.text.chat.planReadyHint,\n            },\n          ]);\n          break;\n        }\n\n        if (!reply.tool_calls?.length) break;\n\n        const toolResults = await executeToolCalls(reply.tool_calls, {\n          confirmCostly: true,\n        });\n\n        let needsConfirm = false;\n        for (const r of toolResults) {\n          if (r.requiresConfirmation && r.pendingArgs) {\n            needsConfirm = true;\n            const label = textToolLabel(r.name);\n            setBubbles((b) => [\n              ...b,\n              {\n                id: `p_${r.toolCallId}`,\n                role: 'tool',\n                content: tr.text.chat.confirmAction(label),\n                pending: {\n                  name: r.name,\n                  args: r.pendingArgs!,\n                  toolCallId: r.toolCallId,\n                },\n              },\n            ]);\n          } else {\n            historyRef.current.push({\n              role: 'tool',\n              tool_call_id: r.toolCallId,\n              content: JSON.stringify({ ok: r.ok, summary: r.summary }),\n            });\n            setBubbles((b) => [\n              ...b,\n              {\n                id: `t_${r.toolCallId}`,\n                role: 'tool',\n                content: r.summary,\n                ok: r.ok,\n              },\n            ]);\n          }\n        }\n        if (needsConfirm) break;\n      }\n    } catch (err) {\n      const friendly = friendlyToolError(err);\n      addToast(friendly, 'error');\n      setBubbles((b) => [\n        ...b,\n        {\n          id: `err_${Date.now()}`,\n          role: 'assistant',\n          content: friendly,\n          ok: false,\n        },\n      ]);\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const confirm = async (pending: NonNullable<ChatBubble['pending']>) => {\n    setBusy(true);\n    try {\n      const r = await executeConfirmedTool(\n        pending.name,\n        pending.args,\n        pending.toolCallId\n      );\n      historyRef.current.push({\n        role: 'tool',\n        tool_call_id: r.toolCallId,\n        content: JSON.stringify({ ok: r.ok, summary: r.summary }),\n      });\n      setBubbles((b) =>\n        b\n          .filter((x) => x.id !== `p_${pending.toolCallId}`)\n          .concat({\n            id: `t_${r.toolCallId}`,\n            role: 'tool',\n            content: r.summary,\n            ok: r.ok,\n          })\n      );\n      await runTurn('');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  return (\n    <div className=\"flex h-full min-h-0 flex-col\">\n      <div className=\"shrink-0 border-b border-panel-border px-3 py-2\">\n        <PanelField\n          label={tr.text.chat.planModeLabel}\n          trailing={\n            <Switch\n              checked={agentPlanMode}\n              onChange={(next) => {\n                setAgentPlanMode(next);\n                planPresentedRef.current = false;\n              }}\n              ariaLabel={tr.text.chat.planModeLabel}\n            />\n          }\n        />\n        <TextBody as=\"p\" size=\"sm\" className=\"mt-1.5 text-white/80\">\n          {tr.text.chat.planModeHint}\n        </TextBody>\n      </div>\n\n      <div className=\"min-h-0 flex-1 space-y-2 overflow-y-auto p-3\">\n        {bubbles.length === 0 && (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n            {tr.text.chat.emptyHint}\n          </TextBody>\n        )}\n        {bubbles.map((b) => {\n          const toolTone =\n            b.role !== 'tool'\n              ? ''\n              : b.pending || b.ok === false\n                ? 'text-amber-200'\n                : 'text-emerald-300';\n          return (\n            <div\n              key={b.id}\n              className={`rounded-xl px-3 py-2 ${\n                b.role === 'user'\n                  ? 'ml-4 bg-[var(--we-accent-muted)] text-white'\n                  : b.role === 'tool'\n                    ? `border border-panel-border bg-black-capsule ${toolTone}`\n                    : 'mr-4 border border-panel-border bg-black-capsule text-white'\n              }`}\n            >\n              <TextBody as=\"p\" size=\"sm\" selectable className=\"whitespace-pre-wrap\">\n                {b.content}\n              </TextBody>\n              {b.pending && (\n                <Button\n                  variant=\"accent\"\n                  size=\"xs\"\n                  className=\"mt-1.5 w-full\"\n                  disabled={busy}\n                  onClick={() => void confirm(b.pending!)}\n                >\n                  {tr.text.chat.confirmAction(textToolLabel(b.pending.name))}\n                </Button>\n              )}\n            </div>\n          );\n        })}\n      </div>\n\n      <div className=\"flex shrink-0 items-start gap-2 border-t border-panel-border p-2\">\n        <textarea\n          value={input}\n          onChange={(e) => setInput(e.target.value)}\n          onKeyDown={(e) => {\n            if (e.key === 'Enter' && !e.shiftKey) {\n              e.preventDefault();\n              void runTurn();\n            }\n          }}\n          placeholder={tr.text.chat.inputPlaceholder}\n          disabled={busy}\n          rows={4}\n          className=\"min-h-[6.5rem] flex-1 resize-y rounded-xl border border-panel-border bg-black-capsule px-3 py-2.5 font-sans text-[12px] font-medium text-white outline-none placeholder:text-white/50 focus:border-[var(--we-accent)] disabled:opacity-50\"\n        />\n        <IconButton\n          label={tr.text.chat.inputPlaceholder}\n          disabled={busy || !input.trim()}\n          onClick={() => void runTurn()}\n          className=\"!bg-[var(--we-accent)] !text-white hover:!bg-[var(--we-accent-hover)] disabled:!opacity-40\"\n        >\n          {busy ? <Loader2 size={14} className=\"animate-spin\" /> : <Send size={14} />}\n        </IconButton>\n      </div>\n    </div>\n  );\n};\n", "import React, { useState } from 'react';\nimport { FilePlus2, RefreshCw } from 'lucide-react';\nimport { useTextStore, type TextChannel, getDocPlainText } from '../../store/useTextStore';\nimport { generateVariants } from '../../services/text';\nimport { getActiveTextEditor } from './DocumentCanvas';\nimport { insertMarkdownIntoDocument } from '../../lib/text/applySuggestion';\nimport { useTranslation } from '../../i18n';\nimport { Button, PanelBody, PanelSection, ToolPanelTabs, TextBody, TextTitle } from '../ui';\n\nconst CHANNEL_IDS: TextChannel[] = [\n  'instagram',\n  'linkedin',\n  'x',\n  'email',\n  'ad',\n  'youtube',\n];\n\ntype TextScope = 'doc' | 'selection';\n\n/** Strip noisy backend suffixes like \"(brand loaded)\" from titles/content. */\nfunction cleanVariantText(value: string): string {\n  return value\n    .replace(/\\s*\\(\\s*brand\\s+loaded\\s*\\)\\s*/gi, ' ')\n    .replace(/\\s{2,}/g, ' ')\n    .trim();\n}\n\nexport const VariantsBoard: React.FC = () => {\n  const tr = useTranslation();\n  const tv = tr.text.variants;\n  const ai = tr.text.ai;\n  const variants = useTextStore((s) => s.variants);\n  const setVariants = useTextStore((s) => s.setVariants);\n  const updateVariant = useTextStore((s) => s.updateVariant);\n  const doc = useTextStore((s) => s.doc);\n  const channelTones = useTextStore((s) => s.brandVoice.channelTones);\n  const addToast = useTextStore((s) => s.addToast);\n  const [busy, setBusy] = useState(false);\n  const [textScope, setTextScope] = useState<TextScope>('doc');\n\n  // Scrub legacy \"(brand loaded)\" suffixes already stored in the project.\n  React.useEffect(() => {\n    const prev = useTextStore.getState().variants;\n    let changed = false;\n    const next = prev.map((v) => {\n      const title = cleanVariantText(v.title);\n      const content = cleanVariantText(v.content);\n      if (title !== v.title || content !== v.content) {\n        changed = true;\n        return { ...v, title, content };\n      }\n      return v;\n    });\n    if (changed) setVariants(next);\n  }, [setVariants]);\n\n  const channelLabel = (id: string) =>\n    tv.channels[id as keyof typeof tv.channels] ?? id;\n\n  const selectionOnly = () => {\n    const editor = getActiveTextEditor();\n    if (!editor) return '';\n    const { from, to } = editor.state.selection;\n    if (from === to) return '';\n    return editor.state.doc.textBetween(from, to, ' ');\n  };\n\n  const scopedText = () =>\n    textScope === 'doc' ? getDocPlainText(doc) : selectionOnly();\n\n  const run = async (onlyStale = false) => {\n    setBusy(true);\n    try {\n      const plain = scopedText();\n      if (!plain.trim()) {\n        addToast(\n          textScope === 'selection' ? ai.toasts.selectText : tv.toasts.writeFirst,\n          'warning'\n        );\n        return;\n      }\n      const channels = onlyStale\n        ? variants.filter((v) => v.stale).map((v) => v.channel)\n        : CHANNEL_IDS;\n      const unique = [...new Set(channels.length ? channels : CHANNEL_IDS)];\n      const tones: Record<string, string> = {};\n      for (const ch of unique) {\n        const t = channelTones[ch];\n        if (t) tones[ch] = t;\n      }\n      const result = await generateVariants({\n        text: plain,\n        channels: unique,\n        channelTones: Object.keys(tones).length ? tones : undefined,\n      });\n      if (onlyStale && variants.length) {\n        const next = variants.map((v) => {\n          const fresh = result.variants.find((r) => r.channel === v.channel);\n          if (!fresh || !v.stale) return v;\n          return {\n            ...v,\n            title: cleanVariantText(fresh.title || v.title),\n            content: cleanVariantText(fresh.content),\n            stale: false,\n            updatedAt: Date.now(),\n          };\n        });\n        for (const fresh of result.variants) {\n          if (!next.some((v) => v.channel === fresh.channel)) {\n            next.push({\n              id: `var_${Date.now()}_${fresh.channel}`,\n              channel: fresh.channel as TextChannel,\n              title: cleanVariantText(fresh.title || channelLabel(fresh.channel)),\n              content: cleanVariantText(fresh.content),\n              stale: false,\n              updatedAt: Date.now(),\n            });\n          }\n        }\n        setVariants(next);\n      } else {\n        setVariants(\n          result.variants.map((v, i) => ({\n            id: `var_${Date.now()}_${i}`,\n            channel: v.channel as TextChannel,\n            title: cleanVariantText(v.title || channelLabel(v.channel)),\n            content: cleanVariantText(v.content),\n            stale: false,\n            updatedAt: Date.now(),\n          }))\n        );\n      }\n      addToast(onlyStale ? tv.toasts.staleRegenerated : tv.toasts.generated, 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : tv.toasts.error, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const addToDocument = (content: string) => {\n    if (!content.trim()) return;\n    const ok = insertMarkdownIntoDocument(content);\n    if (!ok) {\n      addToast(tv.toasts.noEditor, 'warning');\n      return;\n    }\n    addToast(tv.toasts.addedToDocument, 'success');\n  };\n\n  const staleCount = variants.filter((v) => v.stale).length;\n  const preview = scopedText();\n\n  return (\n    <PanelBody className=\"flex h-full min-h-0 flex-col overflow-hidden\">\n      <PanelSection className=\"shrink-0\">\n        <div className=\"flex items-center justify-end gap-2\">\n          <Button\n            variant=\"accent\"\n            size=\"xs\"\n            loading={busy}\n            disabled={busy || !preview.trim()}\n            icon={<RefreshCw size={10} />}\n            onClick={() => void run(false)}\n          >\n            {tv.generate}\n          </Button>\n        </div>\n        {staleCount > 0 && (\n          <button\n            type=\"button\"\n            disabled={busy}\n            onClick={() => void run(true)}\n            className=\"w-full rounded-xl border border-amber-400/30 bg-amber-400/10 px-2.5 py-2 text-left text-amber-200 hover:bg-amber-400/15 disabled:opacity-40\"\n          >\n            <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-amber-200\">\n              {tv.regenerateStale(staleCount)}\n            </TextBody>\n          </button>\n        )}\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n          {ai.textScopeLabel}\n        </TextBody>\n        <ToolPanelTabs\n          dense\n          className=\"rounded-xl border border-panel-border bg-black-capsule !border-b-0\"\n          tabs={[\n            { id: 'doc' as const, label: ai.brandUseDoc },\n            { id: 'selection' as const, label: ai.brandUseSelection },\n          ]}\n          value={textScope}\n          onChange={setTextScope}\n        />\n        {textScope === 'selection' && !selectionOnly().trim() ? (\n          <TextBody\n            as=\"p\"\n            size=\"sm\"\n            className=\"rounded-xl border border-amber-500/30 bg-amber-500/10 px-2.5 py-2 text-amber-200\"\n          >\n            {ai.brandSelectHint}\n          </TextBody>\n        ) : (\n          <TextBody\n            as=\"p\"\n            size=\"sm\"\n            className=\"max-h-16 overflow-y-auto whitespace-pre-wrap rounded-xl border border-panel-border bg-black-capsule p-2 text-white/80\"\n          >\n            {preview.slice(0, 400) || '\u2014'}\n            {preview.length > 400 ? '\u2026' : ''}\n          </TextBody>\n        )}\n      </PanelSection>\n\n      <div className=\"min-h-0 flex-1 space-y-2 overflow-y-auto\">\n        {variants.length === 0 ? (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n            {tv.empty}\n          </TextBody>\n        ) : (\n          variants.map((v) => (\n            <div\n              key={v.id}\n              className={`flex flex-col gap-2 rounded-xl border p-2.5 ${\n                v.stale\n                  ? 'border-amber-400/40 bg-amber-400/5'\n                  : 'border-panel-border bg-black-capsule'\n              }`}\n            >\n              <div className=\"flex min-w-0 items-start justify-between gap-2\">\n                <TextTitle\n                  as=\"span\"\n                  size=\"xs\"\n                  className=\"min-w-0 flex-1 break-words text-[var(--we-accent)]\"\n                >\n                  {cleanVariantText(v.title)}\n                </TextTitle>\n                {v.stale && (\n                  <button\n                    type=\"button\"\n                    className=\"shrink-0 text-amber-300 hover:underline\"\n                    onClick={() => void run(true)}\n                  >\n                    <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-amber-300\">\n                      {tv.staleRegen}\n                    </TextBody>\n                  </button>\n                )}\n              </div>\n              <textarea\n                value={v.content}\n                onChange={(e) =>\n                  updateVariant(v.id, {\n                    content: e.target.value,\n                    stale: false,\n                    updatedAt: Date.now(),\n                  })\n                }\n                rows={6}\n                className=\"max-h-48 min-h-[6rem] w-full resize-y overflow-y-auto whitespace-pre-wrap rounded-lg border border-transparent bg-black-capsule-hover/40 p-2 font-sans text-[12px] font-medium leading-relaxed text-white outline-none focus:border-[var(--we-accent)]\"\n              />\n              <div className=\"flex min-w-0 items-center justify-between gap-2\">\n                <TextBody as=\"span\" size=\"sm\" className=\"shrink-0 tabular-nums text-white/80\">\n                  {tv.chars(v.content.length)}\n                </TextBody>\n                <Button\n                  type=\"button\"\n                  variant=\"outline\"\n                  size=\"xs\"\n                  className=\"min-w-0\"\n                  icon={<FilePlus2 size={11} />}\n                  disabled={!v.content.trim()}\n                  onClick={() => addToDocument(v.content)}\n                >\n                  <span className=\"truncate\">{tv.addToDocument}</span>\n                </Button>\n              </div>\n            </div>\n          ))\n        )}\n      </div>\n    </PanelBody>\n  );\n};\n", "import React, { useState } from 'react';\nimport { useTextStore } from '../../store/useTextStore';\nimport { getActiveTextEditor } from './DocumentCanvas';\nimport { useTranslation } from '../../i18n';\nimport { Check, MapPin, RotateCcw, Trash2 } from 'lucide-react';\nimport { Button, IconButton, PanelBody, PanelSection, TextBody, TextTitle } from '../ui';\n\nconst FLASH_CLASS = 'we-comment-flash';\n\nexport const CommentsPanel: React.FC = () => {\n  const tr = useTranslation();\n  const tc = tr.text.comments;\n  const comments = useTextStore((s) => s.comments);\n  const addComment = useTextStore((s) => s.addComment);\n  const resolveComment = useTextStore((s) => s.resolveComment);\n  const removeComment = useTextStore((s) => s.removeComment);\n  const addToast = useTextStore((s) => s.addToast);\n  const [note, setNote] = useState('');\n\n  const addNote = () => {\n    if (!note.trim()) {\n      addToast(tc.toasts.writeNote, 'warning');\n      return;\n    }\n    const editor = getActiveTextEditor();\n    if (editor) {\n      const { from, to } = editor.state.selection;\n      if (from !== to) {\n        const quote = editor.state.doc.textBetween(from, to, ' ');\n        const id = addComment(note.trim(), quote, true);\n        editor.chain().focus().setCommentMark({ id, note: note.trim() }).run();\n        setNote('');\n        addToast(tc.toasts.anchored, 'success');\n        return;\n      }\n    }\n    // No selection \u2192 unanchored note (no Ir).\n    addComment(note.trim(), undefined, false);\n    setNote('');\n    addToast(tc.toasts.noteSaved ?? tc.toasts.anchored, 'success');\n  };\n\n  /** Collect full mark span \u2014 TipTap often splits one mark across text nodes. */\n  const findMarkRange = (id: string): { from: number; to: number } | null => {\n    const editor = getActiveTextEditor();\n    if (!editor) return null;\n    const want = String(id);\n    let from: number | null = null;\n    let to: number | null = null;\n    editor.state.doc.descendants((node, pos) => {\n      if (!node.isText) return true;\n      const mark = node.marks.find(\n        (m) => m.type.name === 'commentMark' && String(m.attrs.id) === want,\n      );\n      if (!mark) return true;\n      if (from == null) from = pos;\n      to = pos + node.nodeSize;\n      return true;\n    });\n    if (from == null || to == null) return null;\n    return { from, to };\n  };\n\n  const flashMark = (range: { from: number; to: number }) => {\n    const editor = getActiveTextEditor();\n    if (!editor) return;\n    try {\n      const start = editor.view.domAtPos(range.from);\n      let el: HTMLElement | null =\n        start.node.nodeType === Node.TEXT_NODE\n          ? start.node.parentElement\n          : (start.node as HTMLElement);\n      while (el && !el.classList?.contains('we-comment-mark')) {\n        el = el.parentElement;\n      }\n      if (!el) {\n        editor.commands.scrollIntoView();\n        return;\n      }\n      el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n      el.classList.remove(FLASH_CLASS);\n      // Force reflow so the animation retriggers.\n      void el.offsetWidth;\n      el.classList.add(FLASH_CLASS);\n      window.setTimeout(() => el?.classList.remove(FLASH_CLASS), 1400);\n    } catch {\n      editor.commands.scrollIntoView();\n    }\n  };\n\n  const jumpTo = (id: string) => {\n    const editor = getActiveTextEditor();\n    if (!editor) return;\n    const range = findMarkRange(id);\n    if (!range) {\n      addToast(tc.toasts.markMissing, 'warning');\n      return;\n    }\n    editor.chain().focus().setTextSelection(range).run();\n    flashMark(range);\n  };\n\n  const unsetMark = (id: string) => {\n    const editor = getActiveTextEditor();\n    if (!editor) return;\n    const range = findMarkRange(id);\n    if (!range) return;\n    editor.chain().focus().setTextSelection(range).unsetCommentMark().run();\n  };\n\n  const open = comments.filter((c) => !c.resolved);\n  const done = comments.filter((c) => c.resolved);\n\n  return (\n    <PanelBody className=\"h-full min-h-0 overflow-hidden\">\n      <PanelSection description={tc.openCount(open.length)}>\n        <textarea\n          value={note}\n          onChange={(e) => setNote(e.target.value)}\n          placeholder={tc.placeholder}\n          rows={2}\n          className=\"w-full resize-none rounded-xl border border-panel-border bg-black-capsule p-2 font-sans text-[11px] font-medium text-white outline-none placeholder:text-white/50 focus:border-[var(--we-accent)]\"\n        />\n        <Button variant=\"accent\" size=\"sm\" className=\"w-full\" onClick={addNote}>\n          {tc.addSelection}\n        </Button>\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n          {tc.anchorHint}\n        </TextBody>\n      </PanelSection>\n\n      <div className=\"min-h-0 flex-1 space-y-3 overflow-y-auto\">\n        {comments.length === 0 ? (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{tc.empty}</TextBody>\n        ) : (\n          <>\n            {open.length > 0 && (\n              <PanelSection title={tc.openSection}>\n                <div className=\"space-y-2\">\n                  {open.map((c) => (\n                    <CommentCard\n                      key={c.id}\n                      note={c.note}\n                      quote={c.quote}\n                      anchored={Boolean(c.anchored ?? c.quote)}\n                      labels={tc}\n                      onJump={() => jumpTo(c.id)}\n                      onResolve={() => resolveComment(c.id, true)}\n                      onRemove={() => {\n                        unsetMark(c.id);\n                        removeComment(c.id);\n                      }}\n                    />\n                  ))}\n                </div>\n              </PanelSection>\n            )}\n            {done.length > 0 && (\n              <PanelSection title={tc.resolvedSection}>\n                <div className=\"space-y-2\">\n                  {done.map((c) => (\n                    <CommentCard\n                      key={c.id}\n                      note={c.note}\n                      quote={c.quote}\n                      resolved\n                      anchored={Boolean(c.anchored ?? c.quote)}\n                      labels={tc}\n                      onJump={() => jumpTo(c.id)}\n                      onResolve={() => resolveComment(c.id, false)}\n                      onRemove={() => {\n                        unsetMark(c.id);\n                        removeComment(c.id);\n                      }}\n                    />\n                  ))}\n                </div>\n              </PanelSection>\n            )}\n          </>\n        )}\n      </div>\n    </PanelBody>\n  );\n};\n\nfunction CommentCard({\n  note,\n  quote,\n  resolved,\n  anchored,\n  labels,\n  onJump,\n  onResolve,\n  onRemove,\n}: {\n  note: string;\n  quote?: string;\n  resolved?: boolean;\n  anchored: boolean;\n  labels: {\n    jump: string;\n    resolve: string;\n    reopen: string;\n    remove: string;\n  };\n  onJump: () => void;\n  onResolve: () => void;\n  onRemove: () => void;\n}) {\n  return (\n    <div\n      className={`rounded-xl border bg-black-capsule p-2.5 ${\n        resolved\n          ? 'border-panel-border opacity-70'\n          : 'border-[color-mix(in_srgb,var(--we-accent)_35%,transparent)]'\n      }`}\n    >\n      {quote && (\n        <TextBody as=\"p\" size=\"sm\" className=\"mb-1 truncate italic text-white/80\">\n          \u201C{quote}\u201D\n        </TextBody>\n      )}\n      <TextBody as=\"p\" size=\"sm\" className=\"mb-2 text-white\">{note}</TextBody>\n      <div className=\"flex items-center gap-1\">\n        {anchored && (\n          <IconButton variant=\"ghost\" size=\"sm\" label={labels.jump} onClick={onJump}>\n            <MapPin size={12} />\n          </IconButton>\n        )}\n        <IconButton\n          variant=\"ghost\"\n          size=\"sm\"\n          label={resolved ? labels.reopen : labels.resolve}\n          onClick={onResolve}\n        >\n          {resolved ? <RotateCcw size={12} /> : <Check size={12} />}\n        </IconButton>\n        <IconButton variant=\"ghost\" size=\"sm\" label={labels.remove} onClick={onRemove}>\n          <Trash2 size={12} />\n        </IconButton>\n      </div>\n    </div>\n  );\n}\n", "import React, { useState } from 'react';\nimport {\n  useTextStore,\n  getDocPlainText,\n  type TextClaimStatus,\n} from '../../store/useTextStore';\nimport { analyzeClaims } from '../../services/text';\nimport { getActiveTextEditor } from './DocumentCanvas';\nimport { useTranslation } from '../../i18n';\nimport { Button, PanelBody, PanelSection, SelectDropdown, ToolPanelTabs, TextBody, TextTitle } from '../ui';\n\nconst STATUSES: TextClaimStatus[] = [\n  'unverified',\n  'needs_citation',\n  'ok',\n  'flagged',\n];\n\ntype TextScope = 'doc' | 'selection';\n\nexport const ClaimsPanel: React.FC = () => {\n  const tr = useTranslation();\n  const tc = tr.text.claims;\n  const ai = tr.text.ai;\n  const claims = useTextStore((s) => s.claims);\n  const addClaim = useTextStore((s) => s.addClaim);\n  const updateClaim = useTextStore((s) => s.updateClaim);\n  const removeClaim = useTextStore((s) => s.removeClaim);\n  const setClaims = useTextStore((s) => s.setClaims);\n  const doc = useTextStore((s) => s.doc);\n  const addToast = useTextStore((s) => s.addToast);\n  const [busy, setBusy] = useState(false);\n  const [textScope, setTextScope] = useState<TextScope>('doc');\n\n  const statusOptions = STATUSES.map((s) => ({\n    value: s,\n    label: tc.statuses[s],\n  }));\n\n  const selectionOnly = () => {\n    const editor = getActiveTextEditor();\n    if (!editor) return '';\n    const { from, to } = editor.state.selection;\n    if (from === to) return '';\n    return editor.state.doc.textBetween(from, to, ' ');\n  };\n\n  const scopedText = () =>\n    textScope === 'doc' ? getDocPlainText(doc) : selectionOnly();\n\n  const markSelection = () => {\n    const editor = getActiveTextEditor();\n    if (!editor) return;\n    const { from, to } = editor.state.selection;\n    if (from === to) {\n      addToast(tc.toasts.selectClaim, 'warning');\n      return;\n    }\n    const text = editor.state.doc.textBetween(from, to, ' ');\n    const id = addClaim(text, 'needs_citation');\n    editor\n      .chain()\n      .focus()\n      .setCommentMark({ id, note: tc.claimNeedsCitation })\n      .run();\n    addToast(tc.toasts.marked, 'success');\n  };\n\n  const runAnalyze = async () => {\n    const text = scopedText();\n    if (!text.trim()) {\n      addToast(\n        textScope === 'selection' ? tc.toasts.selectClaim : ai.toasts.selectOrWrite,\n        'warning'\n      );\n      return;\n    }\n    setBusy(true);\n    try {\n      const res = await analyzeClaims({ text });\n      setClaims(\n        res.claims.map((c, i) => ({\n          id: `claim_${Date.now()}_${i}`,\n          text: c.text,\n          status: (c.status as TextClaimStatus) || 'unverified',\n          note: c.note,\n          createdAt: Date.now(),\n        }))\n      );\n      addToast(tc.toasts.detected(res.claims.length), 'info');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : tc.toasts.error, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  return (\n    <PanelBody className=\"h-full min-h-0 overflow-hidden\">\n      <PanelSection\n        description={tc.count(claims.length)}\n        trailing={\n          <Button\n            variant=\"accent\"\n            size=\"xs\"\n            loading={busy}\n            disabled={busy || !scopedText().trim()}\n            onClick={() => void runAnalyze()}\n          >\n            {tc.analyze}\n          </Button>\n        }\n      >\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n          {ai.textScopeLabel}\n        </TextBody>\n        <ToolPanelTabs\n          dense\n          className=\"rounded-xl border border-panel-border bg-black-capsule !border-b-0\"\n          tabs={[\n            { id: 'doc' as const, label: ai.brandUseDoc },\n            { id: 'selection' as const, label: ai.brandUseSelection },\n          ]}\n          value={textScope}\n          onChange={setTextScope}\n        />\n        {textScope === 'selection' && !selectionOnly().trim() ? (\n          <TextBody as=\"p\" size=\"sm\" className=\"rounded-xl border border-amber-500/30 bg-amber-500/10 px-2.5 py-2 text-amber-200\">\n            {ai.brandSelectHint}\n          </TextBody>\n        ) : (\n          <TextBody as=\"p\" size=\"sm\" className=\"max-h-16 overflow-y-auto whitespace-pre-wrap rounded-xl border border-panel-border bg-black-capsule p-2 text-white/80\">\n            {scopedText().slice(0, 400) || '\u2014'}\n            {scopedText().length > 400 ? '\u2026' : ''}\n          </TextBody>\n        )}\n        <Button variant=\"outline\" size=\"sm\" className=\"w-full\" onClick={markSelection}>\n          {tc.markSelection}\n        </Button>\n      </PanelSection>\n\n      <div className=\"min-h-0 flex-1 space-y-2 overflow-y-auto\">\n        {claims.length === 0 ? (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n            {tc.empty}\n          </TextBody>\n        ) : (\n          claims.map((c) => (\n            <div\n              key={c.id}\n              className=\"space-y-1 rounded-xl border border-panel-border bg-black-capsule p-2\"\n            >\n              <TextBody as=\"p\" size=\"sm\" className=\"text-white\">{c.text}</TextBody>\n              {c.note && (\n                <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n                  {c.note}\n                </TextBody>\n              )}\n              <div className=\"flex items-center gap-1\">\n                <div className=\"min-w-0 flex-1 rounded-xl bg-black-capsule-hover/40 px-1\">\n                  <SelectDropdown\n                    value={c.status}\n                    options={statusOptions}\n                    onChange={(v) =>\n                      updateClaim(c.id, { status: v as TextClaimStatus })\n                    }\n                    ariaLabel={c.status}\n                    size=\"md\"\n                  />\n                </div>\n                <button\n                  type=\"button\"\n                  onClick={() => removeClaim(c.id)}\n                  className=\"shrink-0 px-1 text-rose-400 hover:underline\"\n                >\n                  <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                    {tc.remove}\n                  </TextBody>\n                </button>\n              </div>\n            </div>\n          ))\n        )}\n      </div>\n    </PanelBody>\n  );\n};\n", "import React, { useMemo, useState } from 'react';\nimport {\n  useTextStore,\n  type TextSuggestionKind,\n} from '../../store/useTextStore';\nimport { getActiveTextEditor } from './DocumentCanvas';\nimport { applyAcceptToEditor, clearAiSuggestionMark } from '../../lib/text/applySuggestion';\nimport { aiMarkdownToHtml } from '../../lib/text/markdown';\nimport { useTranslation } from '../../i18n';\nimport { useTextUiStore } from '../../store/useTextUiStore';\nimport { Modal, PanelField, SelectDropdown, TextBody, TextTitle } from '../ui';\n\nconst KINDS: Array<TextSuggestionKind | 'all'> = [\n  'all',\n  'rewrite',\n  'tighten',\n  'expand',\n  'elevate',\n  'localize',\n  'tone',\n  'brand',\n  'claim',\n  'other',\n];\n\n/**\n * Full-screen review of AI before/after suggestions (opened from the right rail).\n */\nexport const SuggestionsModal: React.FC = () => {\n  const tr = useTranslation();\n  const ts = tr.text.suggestions;\n  const open = useTextUiStore((s) => s.suggestionsModalOpen);\n  const setOpen = useTextUiStore((s) => s.setSuggestionsModalOpen);\n\n  const suggestions = useTextStore((s) => s.suggestions);\n  const acceptSuggestion = useTextStore((s) => s.acceptSuggestion);\n  const rejectSuggestion = useTextStore((s) => s.rejectSuggestion);\n  const acceptAllSuggestions = useTextStore((s) => s.acceptAllSuggestions);\n  const rejectAllSuggestions = useTextStore((s) => s.rejectAllSuggestions);\n  const addToast = useTextStore((s) => s.addToast);\n  const [filter, setFilter] = useState<TextSuggestionKind | 'all'>('all');\n\n  const pending = useMemo(\n    () =>\n      suggestions.filter(\n        (s) => s.status === 'pending' && (filter === 'all' || s.kind === filter)\n      ),\n    [suggestions, filter]\n  );\n\n  const groupedRationales = useMemo(() => {\n    const map = new Map<string, number>();\n    for (const s of pending) {\n      const key = s.rationale || s.kind;\n      map.set(key, (map.get(key) || 0) + 1);\n    }\n    return [...map.entries()];\n  }, [pending]);\n\n  const filterOptions = KINDS.map((k) => ({\n    value: k,\n    label: k === 'all' ? ts.filterAll : ts.kinds[k],\n  }));\n\n  const kindLabel = (kind: TextSuggestionKind) => ts.kinds[kind] ?? kind;\n\n  const applyAccept = (id: string) => {\n    const s = suggestions.find((x) => x.id === id);\n    if (s) {\n      applyAcceptToEditor(getActiveTextEditor(), id, s.original, s.replacement);\n    } else {\n      clearAiSuggestionMark(getActiveTextEditor(), id);\n    }\n    acceptSuggestion(id);\n    addToast(ts.toasts.accepted, 'success');\n  };\n\n  const applyReject = (id: string, quiet = false) => {\n    clearAiSuggestionMark(getActiveTextEditor(), id);\n    rejectSuggestion(id);\n    if (!quiet) addToast(ts.toasts.rejected, 'info');\n  };\n\n  const acceptAll = () => {\n    const editor = getActiveTextEditor();\n    for (const s of pending) {\n      applyAcceptToEditor(editor, s.id, s.original, s.replacement);\n    }\n    acceptAllSuggestions();\n    addToast(ts.toasts.allAccepted, 'success');\n  };\n\n  const rejectAll = () => {\n    pending.forEach((s) => applyReject(s.id, true));\n    rejectAllSuggestions();\n    addToast(ts.toasts.rejected, 'info');\n  };\n\n  return (\n    <Modal\n      isOpen={open}\n      onClose={() => setOpen(false)}\n      title={tr.text.sidebar.titleSuggestions}\n      size=\"full\"\n      bodyClassName=\"flex min-h-0 flex-col gap-4 overflow-hidden !py-4\"\n    >\n      <div className=\"flex shrink-0 flex-wrap items-center justify-between gap-3 border-b border-panel-border pb-3\">\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n          {ts.pendingCount(pending.length)}\n        </TextBody>\n        <div className=\"flex flex-wrap items-center gap-3\">\n          <div className=\"min-w-[10rem]\">\n            <PanelField\n              label={ts.filterLabel}\n              trailing={\n                <SelectDropdown\n                  value={filter}\n                  options={filterOptions}\n                  onChange={(v) => setFilter(v as TextSuggestionKind | 'all')}\n                  ariaLabel={ts.filterLabel}\n                />\n              }\n            />\n          </div>\n          {pending.length > 0 && (\n            <div className=\"flex gap-3\">\n              <button\n                type=\"button\"\n                onClick={acceptAll}\n                className=\"text-emerald-400 hover:underline\"\n              ><TextBody as=\"span\" size=\"sm\">{ts.acceptAll}</TextBody></button>\n              <button\n                type=\"button\"\n                onClick={rejectAll}\n                className=\"text-emerald-400 hover:underline\"\n              ><TextBody as=\"span\" size=\"sm\">{ts.rejectAll}</TextBody></button>\n            </div>\n          )}\n        </div>\n      </div>\n\n      {groupedRationales.length > 0 && (\n        <div className=\"shrink-0 space-y-1 rounded-xl border border-panel-border bg-black-capsule p-3 text-white/80\">\n          <TextTitle as=\"p\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n            {ts.rationales}\n          </TextTitle>\n          <div className=\"flex flex-wrap gap-x-4 gap-y-1\">\n            {groupedRationales.map(([r, n]) => (\n              <p key={r} className=\"select-none\">\n                {n}\u00D7 {r}\n              </p>\n            ))}\n          </div>\n        </div>\n      )}\n\n      <div className=\"min-h-0 flex-1 space-y-4 overflow-y-auto pr-1\">\n        {pending.length === 0 ? (\n          <TextBody as=\"p\" size=\"md\" className=\"text-white/80\">\n            {ts.empty}\n          </TextBody>\n        ) : (\n          pending.map((s) => (\n            <div\n              key={s.id}\n              className=\"space-y-3 rounded-2xl border border-panel-border bg-black-capsule p-4\"\n            >\n              <div className=\"flex flex-wrap items-baseline gap-2\">\n                <TextBody as=\"span\" size=\"sm\" className=\"uppercase tracking-wide text-[var(--we-accent)]\">\n                  {kindLabel(s.kind)}\n                </TextBody>\n                {s.rationale && (\n                  <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n                    {s.rationale}\n                  </TextBody>\n                )}\n              </div>\n              <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n                {ts.chooseHint}\n              </TextBody>\n              <div className=\"grid grid-cols-1 gap-3 md:grid-cols-2 md:gap-4\">\n                <button\n                  type=\"button\"\n                  title={ts.before}\n                  onClick={() => applyReject(s.id)}\n                  className=\"flex min-h-[12rem] flex-col items-stretch justify-start rounded-xl border border-transparent bg-black-capsule-hover/60 p-4 text-left transition-colors hover:border-emerald-400/50 hover:bg-emerald-500/10 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--we-accent)]\"\n                >\n                  <TextTitle as=\"p\" size=\"xs\" className=\"mb-2 uppercase tracking-wider text-emerald-300/90\">\n                    {ts.before}\n                  </TextTitle>\n                  <TextBody as=\"p\" size=\"sm\" className=\"whitespace-pre-wrap leading-relaxed text-white/80\">\n                    {s.original || ts.emptyOriginal}\n                  </TextBody>\n                </button>\n                <button\n                  type=\"button\"\n                  title={ts.after}\n                  onClick={() => applyAccept(s.id)}\n                  className=\"flex min-h-[12rem] flex-col items-stretch justify-start rounded-xl border border-transparent bg-black-capsule-hover/60 p-4 text-left transition-colors hover:border-emerald-400/50 hover:bg-emerald-500/10 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--we-accent)]\"\n                >\n                  <TextTitle as=\"p\" size=\"xs\" className=\"mb-2 uppercase tracking-wider text-emerald-300/90\">\n                    {ts.after}\n                  </TextTitle>\n                  <div\n                    className=\"we-text-prose whitespace-normal font-sans text-[14px] font-medium leading-relaxed text-white [&_li]:my-1 [&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-5 [&_p]:mb-2 [&_p:last-child]:mb-0 [&_strong]:font-bold [&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-5\"\n                    dangerouslySetInnerHTML={{ __html: aiMarkdownToHtml(s.replacement) }}\n                  />\n                </button>\n              </div>\n            </div>\n          ))\n        )}\n      </div>\n    </Modal>\n  );\n};\n", "import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n  CheckSquare,\n  Flag,\n  Layers,\n  MessageCircle,\n  MessageSquare,\n  RotateCcw,\n  Sparkles,\n} from 'lucide-react';\nimport { useTranslation } from '../../i18n';\nimport { useTextStore, type TextRightTab } from '../../store/useTextStore';\nimport { useTextUiStore } from '../../store/useTextUiStore';\nimport { AiTextPanel } from './AiTextPanel';\nimport { TextChatPanel } from './TextChatPanel';\nimport { VariantsBoard } from './VariantsBoard';\nimport { CommentsPanel } from './CommentsPanel';\nimport { ClaimsPanel } from './ClaimsPanel';\nimport { SuggestionsModal } from './SuggestionsModal';\nimport { IconButton, TextBody, TextTitle } from '../ui';\n\nconst DEFAULT_WIDTH = 320;\nconst MIN_WIDTH = 260;\nconst MAX_WIDTH = 480;\n\n/** Tabs that open inside the right dock (suggestions opens a modal instead). */\nconst RAIL: {\n  id: Exclude<TextRightTab, 'suggestions'>;\n  icon: React.ReactNode;\n  labelKey: 'tabAi' | 'tabChat' | 'tabVariants' | 'tabComments' | 'tabClaims';\n  titleKey: 'titleAi' | 'titleChat' | 'titleVariants' | 'titleComments' | 'titleClaims';\n}[] = [\n  { id: 'ai', icon: <Sparkles size={17} />, labelKey: 'tabAi', titleKey: 'titleAi' },\n  { id: 'chat', icon: <MessageSquare size={17} />, labelKey: 'tabChat', titleKey: 'titleChat' },\n  { id: 'variants', icon: <Layers size={17} />, labelKey: 'tabVariants', titleKey: 'titleVariants' },\n  { id: 'comments', icon: <MessageCircle size={17} />, labelKey: 'tabComments', titleKey: 'titleComments' },\n  { id: 'claims', icon: <Flag size={17} />, labelKey: 'tabClaims', titleKey: 'titleClaims' },\n];\n\nfunction PanelContent({ id }: { id: Exclude<TextRightTab, 'suggestions'> }) {\n  switch (id) {\n    case 'ai':\n      return <AiTextPanel />;\n    case 'chat':\n      return <TextChatPanel />;\n    case 'variants':\n      return <VariantsBoard />;\n    case 'comments':\n      return <CommentsPanel />;\n    case 'claims':\n      return <ClaimsPanel />;\n  }\n}\n\nfunction dockTab(tab: TextRightTab): Exclude<TextRightTab, 'suggestions'> {\n  return tab === 'suggestions' ? 'ai' : tab;\n}\n\nexport const TextRightSidebar: React.FC = () => {\n  const t = useTranslation();\n  const activeTab = useTextStore((s) => s.rightTab);\n  const setRightTab = useTextStore((s) => s.setRightTab);\n  const pendingSuggestions = useTextStore(\n    (s) => s.suggestions.filter((x) => x.status === 'pending').length\n  );\n  const rightDockOpen = useTextUiStore((s) => s.rightDockOpen);\n  const setRightDockOpen = useTextUiStore((s) => s.setRightDockOpen);\n  const suggestionsModalOpen = useTextUiStore((s) => s.suggestionsModalOpen);\n  const setSuggestionsModalOpen = useTextUiStore((s) => s.setSuggestionsModalOpen);\n  const [panelWidth, setPanelWidth] = useState(DEFAULT_WIDTH);\n\n  const dockActive = dockTab(activeTab);\n\n  // Migrate removed tabs (brand / seo / versions / suggestions-as-dock) to AI.\n  useEffect(() => {\n    const legacy = activeTab as string;\n    if (\n      legacy === 'brand' ||\n      legacy === 'seo' ||\n      legacy === 'versions' ||\n      legacy === 'suggestions'\n    ) {\n      if (legacy === 'suggestions') {\n        setSuggestionsModalOpen(true);\n      }\n      setRightTab('ai');\n    }\n  }, [activeTab, setRightTab, setSuggestionsModalOpen]);\n\n  // Cmd+K / store tab changes should open the dock (except suggestions \u2192 modal).\n  const prevStoreTab = useRef(activeTab);\n  useEffect(() => {\n    if (activeTab !== prevStoreTab.current) {\n      const prev = prevStoreTab.current;\n      prevStoreTab.current = activeTab;\n      if (activeTab === 'suggestions') {\n        setSuggestionsModalOpen(true);\n        return;\n      }\n      if (prev === 'suggestions') return;\n      setRightDockOpen(true);\n    }\n  }, [activeTab, setRightDockOpen, setSuggestionsModalOpen]);\n\n  const onResizeStart = useCallback(\n    (e: React.MouseEvent) => {\n      e.preventDefault();\n      const startX = e.clientX;\n      const startW = panelWidth;\n      const onMove = (ev: MouseEvent) => {\n        setPanelWidth(Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, startW + (startX - ev.clientX))));\n      };\n      const onUp = () => {\n        window.removeEventListener('mousemove', onMove);\n        window.removeEventListener('mouseup', onUp);\n      };\n      window.addEventListener('mousemove', onMove);\n      window.addEventListener('mouseup', onUp);\n    },\n    [panelWidth]\n  );\n\n  const toggle = (id: Exclude<TextRightTab, 'suggestions'>) => {\n    if (rightDockOpen && dockActive === id) {\n      setRightDockOpen(false);\n      return;\n    }\n    setRightTab(id);\n    setRightDockOpen(true);\n  };\n\n  const titleKey = RAIL.find((p) => p.id === dockActive)?.titleKey ?? 'titleAi';\n\n  return (\n    <>\n      <aside className=\"flex h-full min-h-0 shrink-0 select-none border-l border-panel-border bg-panel\">\n        {rightDockOpen && (\n          <div className=\"relative flex h-full min-h-0 flex-col\" style={{ width: panelWidth }}>\n            <div\n              role=\"separator\"\n              aria-orientation=\"vertical\"\n              aria-label={t.panel.resizeWidth}\n              onMouseDown={onResizeStart}\n              className=\"absolute inset-y-0 left-0 z-10 w-1.5 cursor-ew-resize group/hresize\"\n            >\n              <div className=\"absolute inset-y-0 left-0 w-0.5 rounded-r-full bg-transparent transition-colors group-hover/hresize:bg-[var(--we-accent-capsule)]\" />\n            </div>\n\n            <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-panel-border px-3 py-2 pl-4\">\n              <TextTitle as=\"h2\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n                {t.text.sidebar[titleKey]}\n              </TextTitle>\n              {panelWidth !== DEFAULT_WIDTH && (\n                <IconButton\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  label={t.panel.resetWidth}\n                  onClick={() => setPanelWidth(DEFAULT_WIDTH)}\n                >\n                  <RotateCcw size={14} />\n                </IconButton>\n              )}\n            </div>\n\n            <div className=\"min-h-0 flex-1 overflow-y-auto\">\n              <PanelContent id={dockActive} />\n            </div>\n          </div>\n        )}\n\n        <div className=\"flex w-11 shrink-0 flex-col items-center border-l border-panel-border bg-panel py-2\">\n          <div className=\"flex flex-1 flex-col items-center gap-1.5\">\n            {RAIL.map((item) => {\n              const isActive = rightDockOpen && dockActive === item.id;\n              return (\n                <button\n                  key={item.id}\n                  type=\"button\"\n                  title={t.text.sidebar[item.labelKey]}\n                  onClick={() => toggle(item.id)}\n                  className={`\n                    relative flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg\n                    transition-all duration-150 active:scale-90\n                    ${\n                      isActive\n                        ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--we-accent)_35%,transparent)]'\n                        : 'text-white/80 hover:bg-black-capsule hover:text-white'\n                    }\n                  `}\n                >\n                  {isActive && (\n                    <span className=\"absolute right-0 top-1/2 h-4 w-0.5 -translate-y-1/2 rounded-l-full bg-[var(--we-accent)]\" />\n                  )}\n                  {item.icon}\n                </button>\n              );\n            })}\n          </div>\n\n          <div className=\"mt-auto flex w-full flex-col items-center gap-1.5 pt-2\">\n            <div className=\"mx-auto h-px w-6 bg-panel-border\" aria-hidden />\n            <button\n              type=\"button\"\n              title={t.text.sidebar.tabSuggestions}\n              onClick={() => setSuggestionsModalOpen(true)}\n              className={`\n                relative flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg\n                transition-all duration-150 active:scale-90\n                ${\n                  suggestionsModalOpen\n                    ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--we-accent)_35%,transparent)]'\n                    : 'text-white/80 hover:bg-black-capsule hover:text-white'\n                }\n              `}\n            >\n              <CheckSquare size={17} />\n              {pendingSuggestions > 0 && (\n                <TextBody as=\"span\" size=\"sm\" className=\"absolute -right-0.5 -top-0.5 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-[var(--we-accent)] px-0.5 leading-none text-white\">\n                  {pendingSuggestions > 9 ? '9+' : pendingSuggestions}\n                </TextBody>\n              )}\n            </button>\n          </div>\n        </div>\n      </aside>\n\n      <SuggestionsModal />\n    </>\n  );\n};\n", "import React from 'react';\nimport { useTextStore } from '../../store/useTextStore';\nimport { CHANNEL_LIMITS } from '../../lib/text/readability';\nimport type { InclusiveTipId } from '../../lib/text/clarity';\nimport { useTranslation } from '../../i18n';\nimport { TextBody } from '../ui';\n\nexport const MetricsBar: React.FC = () => {\n  const tr = useTranslation();\n  const m = tr.text.metrics;\n  const metrics = useTextStore((s) => s.metrics);\n  const clarity = useTextStore((s) => s.clarity);\n  const channel = useTextStore((s) => s.targetChannel);\n  const brandScore = useTextStore((s) => s.brandVoice.score);\n  const limit = CHANNEL_LIMITS[channel] ?? 0;\n  const over =\n    limit > 0 && metrics.characters > limit\n      ? ` / max ${limit}`\n      : limit > 0\n        ? ` / ${limit}`\n        : '';\n\n  const inclusiveTitle = clarity.inclusiveFlags\n    .map((id) => m.inclusiveTips[id as InclusiveTipId] ?? String(id))\n    .join(' \u00B7 ');\n\n  return (\n    <div className=\"we-text-metrics flex flex-wrap items-center gap-3 border-t border-panel-border bg-[#0F0F16] px-3 py-1.5 text-white/80\">\n      <TextBody as=\"span\" size=\"sm\" className=\"tabular-nums\">\n        {metrics.words} {m.words}\n      </TextBody>\n      <TextBody as=\"span\" size=\"sm\" className=\"tabular-nums\">\n        {metrics.characters} {m.chars}\n        {over}\n      </TextBody>\n      <TextBody as=\"span\" size=\"sm\" className=\"tabular-nums\">\n        {m.flesch} {metrics.flesch}\n      </TextBody>\n      <TextBody as=\"span\" size=\"sm\" className=\"tabular-nums\">\n        {m.clarity} {clarity.clarityScore}\n      </TextBody>\n      <TextBody as=\"span\" size=\"sm\" className=\"tabular-nums\">\n        ~{metrics.readingTimeMinutes} min\n      </TextBody>\n      {clarity.jargonHits.length > 0 && (\n        <TextBody as=\"span\" size=\"sm\" className=\"text-amber-300\" title={clarity.jargonHits.join(', ')}>\n          {m.jargon} {clarity.jargonHits.length}\n        </TextBody>\n      )}\n      {clarity.forbiddenHits.length > 0 && (\n        <TextBody as=\"span\" size=\"sm\" className=\"text-rose-400\" title={clarity.forbiddenHits.join(', ')}>\n          {m.forbidden} {clarity.forbiddenHits.length}\n        </TextBody>\n      )}\n      {clarity.inclusiveFlags.length > 0 && (\n        <TextBody as=\"span\" size=\"sm\" className=\"text-amber-300\" title={inclusiveTitle}>\n          {m.inclusive} {clarity.inclusiveFlags.length}\n        </TextBody>\n      )}\n      {brandScore != null && (\n        <TextBody as=\"span\" size=\"sm\" className=\"ml-auto tabular-nums text-[var(--we-accent)]\">\n          {m.brand} {brandScore}\n        </TextBody>\n      )}\n    </div>\n  );\n};\n", "/**\n * Clean HTML / MDX export for CMS paste (no OAuth publish).\n */\n\nimport type { JSONContent } from '@tiptap/core';\nimport { jsonToHtml, jsonToMarkdown } from './markdown';\n\nexport function exportCleanHtml(doc: JSONContent, title: string): string {\n  const body = jsonToHtml(doc);\n  return `<!DOCTYPE html>\n<html lang=\"es\">\n<head>\n<meta charset=\"utf-8\"/>\n<title>${escapeHtml(title)}</title>\n</head>\n<body>\n<article>\n${body}\n</article>\n</body>\n</html>\n`;\n}\n\nexport function exportMdx(doc: JSONContent, meta: {\n  title: string;\n  description?: string;\n  slug?: string;\n  keywords?: string[];\n}): string {\n  const md = jsonToMarkdown(doc);\n  const kw = (meta.keywords || []).join(', ');\n  return `---\ntitle: ${yamlQuote(meta.title)}\ndescription: ${yamlQuote(meta.description || '')}\nslug: ${yamlQuote(meta.slug || '')}\nkeywords: ${yamlQuote(kw)}\n---\n\n${md}\n`;\n}\n\nfunction escapeHtml(s: string): string {\n  return s\n    .replace(/&/g, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;')\n    .replace(/\"/g, '&quot;');\n}\n\nfunction yamlQuote(s: string): string {\n  return JSON.stringify(s || '');\n}\n", "/**\n * Extract heading \u2192 body sections from TipTap JSON for handoffs.\n */\n\nimport type { JSONContent } from '@tiptap/core';\n\nexport type DocSection = { heading: string; body: string };\n\nfunction inlineText(node: JSONContent): string {\n  if (node.type === 'text') return node.text || '';\n  return (node.content || []).map(inlineText).join('');\n}\n\nfunction blockText(node: JSONContent): string {\n  if (node.type === 'heading' || node.type === 'paragraph') {\n    return inlineText(node);\n  }\n  if (node.type === 'bulletList' || node.type === 'orderedList') {\n    return (node.content || [])\n      .map((li) => blockText(li.content?.[0] || li))\n      .filter(Boolean)\n      .join('. ');\n  }\n  return inlineText(node);\n}\n\nexport function extractSectionsFromDoc(doc: JSONContent): DocSection[] {\n  const content = doc.content || [];\n  const sections: DocSection[] = [];\n  let current: DocSection | null = null;\n\n  for (const node of content) {\n    if (node.type === 'heading') {\n      if (current && (current.heading || current.body)) sections.push(current);\n      current = { heading: blockText(node).trim(), body: '' };\n      continue;\n    }\n    const text = blockText(node).trim();\n    if (!text) continue;\n    if (!current) {\n      current = { heading: '', body: text };\n    } else {\n      current.body = current.body ? `${current.body}\\n\\n${text}` : text;\n    }\n  }\n  if (current && (current.heading || current.body)) sections.push(current);\n\n  return sections.filter((s) => (s.body || s.heading).trim());\n}\n\n/** TTS-ready chunk: prefer body under heading, fall back to heading. */\nexport function sectionToTtsText(section: DocSection): string {\n  if (section.body.trim()) {\n    return section.heading\n      ? `${section.heading}. ${section.body}`.trim()\n      : section.body.trim();\n  }\n  return section.heading.trim();\n}\n", "import React, { useState } from 'react';\nimport { X, Film, Music2 } from 'lucide-react';\nimport { jsPDF } from 'jspdf';\nimport { useTextStore, getDocPlainText } from '../../store/useTextStore';\nimport { htmlToMarkdown, jsonToHtml } from '../../lib/text/markdown';\nimport { exportCleanHtml, exportMdx } from '../../lib/text/exportFormats';\nimport { tipTapJsonToDocxBlob } from '../../lib/text/docxBridge';\nimport {\n  extractSectionsFromDoc,\n  sectionToTtsText,\n} from '../../lib/text/sectionBodies';\nimport { getActiveTextEditor } from './DocumentCanvas';\nimport { useVideoStore } from '../../store/useVideoStore';\nimport { useAudioStore, createAudioClip } from '../../store/useAudioStore';\nimport { generateTts } from '../../services/audio/voiceService';\nimport { decodeAudioBlob, extractPeaks } from '../../lib/audio/peaks';\nimport { useTranslation } from '../../i18n';\nimport { modeExportFilename } from '../../utils/exportDownloadName';\nimport { modeAccentVars, useModeAccent } from '../../theme/modeAccent';\nimport { TextBody, TextTitle } from '../ui';\ninterface Props {\n  open: boolean;\n  onClose: () => void;\n  onSwitchMode?: (mode: 'video' | 'audio') => void;\n}\n\nexport const TextExportModal: React.FC<Props> = ({ open, onClose, onSwitchMode }) => {\n  const t = useTranslation();\n  const mode = useModeAccent();\n  const store = useTextStore();\n  const {\n    projectName,\n    doc,\n    docType,\n    language,\n    tone,\n    targetChannel,\n    outline,\n    variants,\n    suggestions,\n    snapshots,\n    brandVoice,\n    metrics,\n    seoMeta,\n    workflowStatus,\n    comments,\n    claims,\n    enforceComplianceOnExport,\n    setEnforce,\n    addToast,\n    canExport,\n  } = store;\n  const [busy, setBusy] = useState(false);\n\n  if (!open) return null;\n\n  const guard = () => {\n    const { ok, blockers } = canExport();\n    if (!ok) {\n      addToast(blockers[0] || 'Export bloqueado por compliance', 'warning');\n      return false;\n    }\n    const soft = blockers.find((b) => b.startsWith('Aviso:'));\n    if (soft) addToast(soft, 'info');\n    return true;\n  };\n\n  const download = (blob: Blob, filename: string) => {\n    const a = document.createElement('a');\n    a.href = URL.createObjectURL(blob);\n    a.download = filename;\n    a.click();\n    URL.revokeObjectURL(a.href);\n  };\n\n  const plain = () => getDocPlainText(doc);\n  const html = () => getActiveTextEditor()?.getHTML() || jsonToHtml(doc);\n\n  const exportMd = () => {\n    if (!guard()) return;\n    const md = htmlToMarkdown(html());\n    download(new Blob([md], { type: 'text/markdown' }), modeExportFilename('text', 'md'));\n  };\n\n  const exportHtml = () => {\n    if (!guard()) return;\n    download(\n      new Blob([exportCleanHtml(doc, projectName || t.text.export.fallbackName)], {\n        type: 'text/html',\n      }),\n      modeExportFilename('text', 'html')\n    );\n  };\n\n  const exportMdxFile = () => {\n    if (!guard()) return;\n    const mdx = exportMdx(doc, {\n      title: seoMeta.title || projectName || t.text.export.fallbackName,\n      description: seoMeta.description,\n      slug: seoMeta.slug,\n      keywords: seoMeta.keywords,\n    });\n    download(new Blob([mdx], { type: 'text/markdown' }), modeExportFilename('text', 'mdx'));\n  };\n\n  const exportTxt = () => {\n    if (!guard()) return;\n    download(new Blob([plain()], { type: 'text/plain' }), modeExportFilename('text', 'txt'));\n  };\n\n  const exportJson = () => {\n    if (!guard()) return;\n    download(\n      new Blob(\n        [\n          JSON.stringify(\n            {\n              schemaVersion: 2,\n              name: projectName,\n              docType,\n              language,\n              tone,\n              targetChannel,\n              workflowStatus,\n              seoMeta,\n              doc,\n              outline,\n              variants,\n              suggestions,\n              snapshots,\n              brandVoice,\n              metrics,\n              comments,\n              claims,\n            },\n            null,\n            2\n          ),\n        ],\n        { type: 'application/json' }\n      ),\n      modeExportFilename('text', 'json')\n    );\n  };\n\n  const exportPdf = () => {\n    if (!guard()) return;\n    const pdf = new jsPDF({ unit: 'pt', format: 'a4' });\n    const text = plain();\n    const lines = pdf.splitTextToSize(text, 500);\n    pdf.setFontSize(11);\n    let y = 48;\n    for (const line of lines) {\n      if (y > 780) {\n        pdf.addPage();\n        y = 48;\n      }\n      pdf.text(line, 48, y);\n      y += 14;\n    }\n    pdf.save(modeExportFilename('text', 'pdf'));\n  };\n\n  const exportDocx = async () => {\n    if (!guard()) return;\n    setBusy(true);\n    try {\n      const blob = await tipTapJsonToDocxBlob(doc, projectName || t.text.export.fallbackName);\n      download(blob, modeExportFilename('text', 'docx'));\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  /** Script handoff: prefer outline sections with timed text clips. */\n  const handoffVideo = () => {\n    if (!guard()) return;\n    const vs = useVideoStore.getState();\n    if (!vs.videoProjects.length) {\n      vs.createVideoProject(projectName || 'Desde texto', '16:9', '#000000');\n    }\n    const trackId =\n      vs.tracks.find((t) => t.type === 'text' || t.id.includes('text'))?.id ||\n      vs.tracks[0]?.id;\n    if (!trackId) {\n      addToast(t.text.export.toasts.noTextTrack, 'warning');\n      return;\n    }\n\n    const fromDoc = extractSectionsFromDoc(doc);\n    const sections = fromDoc.length\n      ? fromDoc.map((s) => ({\n          label: s.heading || s.body.slice(0, 24),\n          body: (s.body || s.heading).slice(0, 500),\n        }))\n      : plain()\n          .split(/(?<=[.!?])\\s+/)\n          .map((s) => s.trim())\n          .filter(Boolean)\n          .slice(0, 40)\n          .map((s) => ({ label: s.slice(0, 24), body: s }));\n\n    let t = 0;\n    for (const sec of sections) {\n      const dur = Math.min(10, Math.max(2.5, sec.body.split(/\\s+/).length * 0.35));\n      vs.addTextClip({\n        trackId,\n        assetId: '',\n        startTime: t,\n        duration: dur,\n        trimIn: 0,\n        trimOut: 0,\n        speed: 1,\n        volume: 1,\n        opacity: 1,\n        muted: false,\n        text: sec.body,\n        name: sec.label.slice(0, 28),\n      });\n      t += dur;\n    }\n    addToast(\n      sections.length\n        ? t.text.export.toasts.handoffVideoDone(sections.length)\n        : t.text.export.toasts.docEmpty,\n      'info'\n    );\n    onSwitchMode?.('video');\n    onClose();\n  };\n\n  const handoffAudio = async () => {\n    if (!guard()) return;\n    setBusy(true);\n    try {\n      const sections = extractSectionsFromDoc(doc).slice(0, 8);\n      if (!sections.length) {\n        addToast(t.text.export.toasts.noTtsContent, 'warning');\n        return;\n      }\n      const as = useAudioStore.getState();\n      if (!as.audioProjects.length) {\n        as.createAudioProject(projectName || 'Desde texto', { template: 'voiceover' });\n      }\n      let start = 0;\n      for (let i = 0; i < sections.length; i++) {\n        const sec = sections[i]!;\n        const text = sectionToTtsText(sec).slice(0, 1200);\n        if (!text.trim()) continue;\n        const blob = await generateTts({ text });\n        const buffer = await decodeAudioBlob(blob);\n        const peaks = await extractPeaks(buffer);\n        const id = `tts_ho_${Date.now()}_${i}`;\n        const file = new File([blob], `Section ${i + 1}.mp3`, { type: blob.type });\n        const url = URL.createObjectURL(blob);\n        as.addAsset({\n          id,\n          name: file.name,\n          url,\n          duration: buffer.duration,\n          sampleRate: buffer.sampleRate,\n          channels: buffer.numberOfChannels,\n          file,\n          peaks: peaks.peaks,\n          peaksSampleRate: peaks.peaksSampleRate,\n        });\n        const trackId = as.tracks[0]?.id || as.addTrack('VO', 'audio');\n        as.addClip(\n          createAudioClip({\n            trackId,\n            assetId: id,\n            startTime: start,\n            duration: buffer.duration,\n            name: (sec.heading || text).slice(0, 24),\n          })\n        );\n        start += buffer.duration + 0.15;\n      }\n      addToast(t.text.export.toasts.handoffAudioDone, 'success');\n      onSwitchMode?.('audio');\n      onClose();\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : t.text.export.toasts.ttsError, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  return (\n    <div\n      className=\"fixed inset-0 z-[100] flex items-center justify-center bg-black/75 p-4 backdrop-blur-sm\"\n      data-we-mode={mode}\n      style={modeAccentVars(mode)}\n    >\n      <div className=\"absolute inset-0 cursor-default\" onClick={onClose} />\n      <div className=\"relative z-[101] w-full max-w-md rounded-2xl border border-panel-border bg-panel p-4 shadow-2xl\">\n        <div className=\"mb-3 flex items-center justify-between\">\n          <TextTitle as=\"h3\" size=\"sm\" className=\"text-white\">\n            {t.text.export.title}\n          </TextTitle>\n          <button\n            type=\"button\"\n            onClick={onClose}\n            className=\"rounded-lg p-1 text-white/80 hover:bg-black-capsule hover:text-white\"\n          >\n            <X size={14} />\n          </button>\n        </div>\n        <div className=\"mb-3 grid grid-cols-2 gap-2\">\n          {[\n            [t.text.export.formats.md, exportMd],\n            [t.text.export.formats.html, exportHtml],\n            [t.text.export.formats.mdx, exportMdxFile],\n            [t.text.export.formats.txt, exportTxt],\n            [t.text.export.formats.json, exportJson],\n            [t.text.export.formats.pdf, exportPdf],\n            [t.text.export.formats.docx, () => void exportDocx()],\n          ].map(([label, fn]) => (\n            <button\n              key={label as string}\n              type=\"button\"\n              disabled={busy}\n              onClick={fn as () => void}\n              className=\"h-9 rounded-xl border border-panel-border bg-black-capsule text-white hover:border-[var(--we-accent)] disabled:opacity-50\"\n            >\n              {label as string}\n            </button>\n          ))}\n        </div>\n        <TextBody as=\"p\" size=\"sm\" className=\"mb-2 text-white/80\">\n          {t.text.export.mdxHint}\n        </TextBody>\n        <label className=\"mb-3 flex cursor-pointer items-center gap-2 rounded-xl border border-panel-border bg-black-capsule px-2 py-1.5 hover:border-[var(--we-accent)]\">\n          <input\n            type=\"checkbox\"\n            checked={enforceComplianceOnExport}\n            onChange={(e) => setEnforce(e.target.checked)}\n            className=\"accent-[var(--we-accent)]\"\n          />\n          <TextBody as=\"span\" size=\"sm\" className=\"text-white\">\n            {t.text.export.complianceLabel}\n          </TextBody>\n        </label>\n        <div className=\"space-y-2 border-t border-panel-border pt-3\">\n          <TextTitle as=\"span\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n            {t.text.export.bridgesHeader}\n          </TextTitle>\n          <button\n            type=\"button\"\n            disabled={busy}\n            onClick={handoffVideo}\n            className=\"flex h-9 w-full items-center justify-center gap-2 rounded-xl bg-[var(--we-accent-muted)] text-[var(--we-accent)] disabled:opacity-50\"\n          >\n            <Film size={12} /> <TextBody as=\"span\" size=\"sm\">{t.text.export.handoffVideo}</TextBody>\n          </button>\n          <button\n            type=\"button\"\n            disabled={busy}\n            onClick={() => void handoffAudio()}\n            className=\"flex h-9 w-full items-center justify-center gap-2 rounded-xl bg-[var(--we-accent-muted)] text-[var(--we-accent)] disabled:opacity-50\"\n          >\n            <Music2 size={12} /> {t.text.export.handoffAudio}\n          </button>\n        </div>\n      </div>\n    </div>\n  );\n};\n", "import React, { useEffect, useMemo, useState } from 'react';\nimport { useTextStore } from '../../store/useTextStore';\nimport { useTextUiStore } from '../../store/useTextUiStore';\nimport { getActiveTextEditor } from './DocumentCanvas';\nimport { useTranslation } from '../../i18n';\nimport { modeAccentVars, useModeAccent } from '../../theme/modeAccent';\nimport { TextBody, TextTitle } from '../ui';\n\ntype Cmd = {\n  id: string;\n  label: string;\n  group: string;\n  run: () => void;\n};\n\nexport const TextCommandPalette: React.FC = () => {\n  const tr = useTranslation();\n  const mode = useModeAccent();\n  const [open, setOpen] = useState(false);\n  const [q, setQ] = useState('');\n  const [idx, setIdx] = useState(0);\n  const setRightTab = useTextStore((s) => s.setRightTab);\n  const setExportModalOpen = useTextStore((s) => s.setExportModalOpen);\n  const createNamedSnapshot = useTextStore((s) => s.createNamedSnapshot);\n  const setSuggestionsModalOpen = useTextUiStore((s) => s.setSuggestionsModalOpen);\n\n  const commands = useMemo<Cmd[]>(\n    () => [\n      {\n        id: 'tab-ai',\n        label: tr.text.commandPalette.commands.tabAi,\n        group: tr.text.commandPalette.groupNavigation,\n        run: () => setRightTab('ai'),\n      },\n      {\n        id: 'tab-chat',\n        label: tr.text.commandPalette.commands.tabChat,\n        group: tr.text.commandPalette.groupNavigation,\n        run: () => setRightTab('chat'),\n      },\n      {\n        id: 'tab-sug',\n        label: tr.text.commandPalette.commands.tabSuggestions,\n        group: tr.text.commandPalette.groupNavigation,\n        run: () => setSuggestionsModalOpen(true),\n      },\n      {\n        id: 'tab-comments',\n        label: tr.text.commandPalette.commands.tabComments,\n        group: tr.text.commandPalette.groupNavigation,\n        run: () => setRightTab('comments'),\n      },\n      {\n        id: 'tab-claims',\n        label: tr.text.commandPalette.commands.tabClaims,\n        group: tr.text.commandPalette.groupNavigation,\n        run: () => setRightTab('claims'),\n      },\n      {\n        id: 'fmt-h2',\n        label: tr.text.commandPalette.commands.fmtH2,\n        group: tr.text.commandPalette.groupFormat,\n        run: () =>\n          getActiveTextEditor()\n            ?.chain()\n            .focus()\n            .toggleHeading({ level: 2 })\n            .run(),\n      },\n      {\n        id: 'fmt-callout',\n        label: tr.text.commandPalette.commands.fmtCallout,\n        group: tr.text.commandPalette.groupFormat,\n        run: () => getActiveTextEditor()?.chain().focus().setCallout().run(),\n      },\n      {\n        id: 'export',\n        label: tr.text.commandPalette.commands.export,\n        group: tr.text.commandPalette.groupFile,\n        run: () => setExportModalOpen(true),\n      },\n      {\n        id: 'snap',\n        label: tr.text.commandPalette.commands.snap,\n        group: tr.text.commandPalette.groupFile,\n        run: () => createNamedSnapshot(),\n      },\n    ],\n    [tr, setRightTab, setExportModalOpen, createNamedSnapshot, setSuggestionsModalOpen]\n  );\n\n  const filtered = useMemo(() => {\n    const qq = q.trim().toLowerCase();\n    if (!qq) return commands;\n    return commands.filter((c) => c.label.toLowerCase().includes(qq));\n  }, [commands, q]);\n\n  useEffect(() => {\n    const onKey = (e: KeyboardEvent) => {\n      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {\n        e.preventDefault();\n        setOpen((v) => !v);\n        setQ('');\n        setIdx(0);\n      }\n    };\n    window.addEventListener('keydown', onKey);\n    return () => window.removeEventListener('keydown', onKey);\n  }, []);\n\n  useEffect(() => {\n    if (!open) return;\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') setOpen(false);\n      if (e.key === 'ArrowDown') {\n        e.preventDefault();\n        setIdx((i) => Math.min(filtered.length - 1, i + 1));\n      }\n      if (e.key === 'ArrowUp') {\n        e.preventDefault();\n        setIdx((i) => Math.max(0, i - 1));\n      }\n      if (e.key === 'Enter') {\n        e.preventDefault();\n        const cmd = filtered[idx];\n        if (cmd) {\n          cmd.run();\n          setOpen(false);\n        }\n      }\n    };\n    window.addEventListener('keydown', onKey);\n    return () => window.removeEventListener('keydown', onKey);\n  }, [open, filtered, idx]);\n\n  if (!open) return null;\n\n  return (\n    <div\n      className=\"fixed inset-0 z-[100] flex items-start justify-center bg-black/60 pt-[15vh] backdrop-blur-sm\"\n      data-we-mode={mode}\n      style={modeAccentVars(mode)}\n      onClick={() => setOpen(false)}\n    >\n      <div\n        className=\"w-full max-w-md overflow-hidden rounded-2xl border border-panel-border bg-panel shadow-2xl\"\n        onClick={(e) => e.stopPropagation()}\n      >\n        <input\n          autoFocus\n          value={q}\n          onChange={(e) => {\n            setQ(e.target.value);\n            setIdx(0);\n          }}\n          placeholder={tr.text.commandPalette.placeholder}\n          className=\"h-11 w-full border-b border-panel-border bg-transparent px-3 text-white outline-none focus:border-[var(--we-accent)]\"\n        />\n        <div className=\"max-h-72 overflow-y-auto py-1\">\n          {filtered.length === 0 ? (\n            <TextBody as=\"p\" size=\"sm\" className=\"px-3 py-2 text-white/80\">\n              {tr.text.commandPalette.emptyResult}\n            </TextBody>\n          ) : (\n            filtered.map((c, i) => (\n              <button\n                key={c.id}\n                type=\"button\"\n                onClick={() => {\n                  c.run();\n                  setOpen(false);\n                }}\n                className={`flex w-full items-center px-3 py-2 text-left ${\n                  i === idx\n                    ? 'bg-[var(--we-accent)] text-white'\n                    : 'text-white/80 hover:bg-black-capsule'\n                }`}\n              >\n                <TextBody as=\"span\" size=\"sm\" className=\"opacity-60 mr-2\">{c.group}</TextBody>\n                <TextBody as=\"span\" size=\"sm\">{c.label}</TextBody>\n              </button>\n            ))\n          )}\n        </div>\n      </div>\n    </div>\n  );\n};\n", "import React, { useEffect, useState } from 'react';\nimport { useTranslation } from '../../i18n';\nimport { useTextStore, TEXT_PAGE_SIZES, type TextPageSizeId } from '../../store/useTextStore';\nimport { useTextUiStore } from '../../store/useTextUiStore';\nimport { Modal, Button, PanelField, SelectDropdown, TextBody, TextTitle } from '../ui';\n\n/**\n * Page size / orientation / margins \u2014 modal only (no floating page toolbar).\n */\nexport const TextPageSetupModal: React.FC = () => {\n  const tr = useTranslation();\n  const open = useTextUiStore((s) => s.pageSetupOpen);\n  const setPageSetupOpen = useTextUiStore((s) => s.setPageSetupOpen);\n  const activeProject = useTextStore((s) =>\n    s.textProjects.find((p) => p.id === s.activeTextProjectId) ?? null,\n  );\n  const setProjectPageSize = useTextStore((s) => s.setProjectPageSize);\n  const setProjectOrientation = useTextStore((s) => s.setProjectOrientation);\n  const setProjectMargins = useTextStore((s) => s.setProjectMargins);\n\n  const pageSize =\n    TEXT_PAGE_SIZES.find((p) => p.id === activeProject?.pageSize) ?? TEXT_PAGE_SIZES[0];\n  const orientation = activeProject?.orientation ?? 'portrait';\n  const defaultMargins = pageSize.marginMm;\n  const custom = (\n    activeProject as\n      | { customMarginsMm?: { top: number; right: number; bottom: number; left: number } }\n      | null\n  )?.customMarginsMm;\n\n  const [top, setTop] = useState(custom?.top ?? defaultMargins.top);\n  const [right, setRight] = useState(custom?.right ?? defaultMargins.right);\n  const [bottom, setBottom] = useState(custom?.bottom ?? defaultMargins.bottom);\n  const [left, setLeft] = useState(custom?.left ?? defaultMargins.left);\n\n  useEffect(() => {\n    if (!open) return;\n    setTop(custom?.top ?? defaultMargins.top);\n    setRight(custom?.right ?? defaultMargins.right);\n    setBottom(custom?.bottom ?? defaultMargins.bottom);\n    setLeft(custom?.left ?? defaultMargins.left);\n  }, [open, custom, defaultMargins.top, defaultMargins.right, defaultMargins.bottom, defaultMargins.left]);\n\n  const apply = () => setProjectMargins({ top, right, bottom, left });\n\n  const resetToDefault = () => {\n    setTop(defaultMargins.top);\n    setRight(defaultMargins.right);\n    setBottom(defaultMargins.bottom);\n    setLeft(defaultMargins.left);\n    setProjectMargins(defaultMargins);\n  };\n\n  return (\n    <Modal\n      isOpen={open}\n      onClose={() => setPageSetupOpen(false)}\n      title={tr.text.pageToolbar.pageSetupTitle}\n      size=\"sm\"\n    >\n      <div className=\"flex flex-col gap-3\">\n        <PanelField\n          label={tr.text.pageToolbar.pageSizeLabel}\n          trailing={\n            <SelectDropdown\n              value={activeProject?.pageSize ?? 'a4'}\n              options={TEXT_PAGE_SIZES.map((p) => ({ value: p.id, label: p.name }))}\n              onChange={(v) => setProjectPageSize(v as TextPageSizeId)}\n              ariaLabel={tr.text.pageToolbar.pageSizeLabel}\n            />\n          }\n        />\n\n        <div className=\"flex gap-1 rounded-xl bg-black-capsule p-1\">\n          {(['portrait', 'landscape'] as const).map((o) => (\n            <button\n              key={o}\n              type=\"button\"\n              onClick={() => setProjectOrientation(o)}\n              className={`flex-1 rounded-lg py-2 transition-colors ${\n                orientation === o\n                  ? 'bg-[var(--we-accent-capsule)] text-[var(--we-accent)]'\n                  : 'text-white/80 hover:text-white'\n              }`}\n            >\n              <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                {o === 'portrait'\n                  ? tr.text.pageToolbar.orientationPortrait\n                  : tr.text.pageToolbar.orientationLandscape}\n              </TextBody>\n            </button>\n          ))}\n        </div>\n\n        {/* Preview uses runtime % from margin mm \u2014 Tailwind cannot express dynamic % */}\n        <div\n          className=\"relative mx-auto rounded border border-panel-border bg-white\"\n          style={{ width: 80, height: 104 }}\n        >\n          <div\n            className=\"absolute inset-x-0 top-0 border-b border-[var(--we-accent)] bg-[var(--we-accent-muted)]\"\n            style={{ height: `${Math.round((top / 50) * 40)}%` }}\n          />\n          <div\n            className=\"absolute inset-x-0 bottom-0 border-t border-[var(--we-accent)] bg-[var(--we-accent-muted)]\"\n            style={{ height: `${Math.round((bottom / 50) * 40)}%` }}\n          />\n          <div\n            className=\"absolute inset-y-0 left-0 border-r border-[var(--we-accent)] bg-[var(--we-accent-muted)]\"\n            style={{ width: `${Math.round((left / 40) * 35)}%` }}\n          />\n          <div\n            className=\"absolute inset-y-0 right-0 border-l border-[var(--we-accent)] bg-[var(--we-accent-muted)]\"\n            style={{ width: `${Math.round((right / 40) * 35)}%` }}\n          />\n          <TextBody as=\"span\" size=\"sm\" className=\"absolute inset-0 flex items-center justify-center text-black/40\">\n            {pageSize.name}\n          </TextBody>\n        </div>\n\n        <PanelField\n          variant=\"slide\"\n          label={tr.text.pageToolbar.marginUnit(tr.text.pageToolbar.marginTop)}\n          min={0}\n          max={60}\n          step={1}\n          numericValue={top}\n          formatValue={(n) => `${n}`}\n          onChange={setTop}\n        />\n        <PanelField\n          variant=\"slide\"\n          label={tr.text.pageToolbar.marginUnit(tr.text.pageToolbar.marginBottom)}\n          min={0}\n          max={60}\n          step={1}\n          numericValue={bottom}\n          formatValue={(n) => `${n}`}\n          onChange={setBottom}\n        />\n        <PanelField\n          variant=\"slide\"\n          label={tr.text.pageToolbar.marginUnit(tr.text.pageToolbar.marginLeft)}\n          min={0}\n          max={60}\n          step={1}\n          numericValue={left}\n          formatValue={(n) => `${n}`}\n          onChange={setLeft}\n        />\n        <PanelField\n          variant=\"slide\"\n          label={tr.text.pageToolbar.marginUnit(tr.text.pageToolbar.marginRight)}\n          min={0}\n          max={60}\n          step={1}\n          numericValue={right}\n          formatValue={(n) => `${n}`}\n          onChange={setRight}\n        />\n\n        <div className=\"flex gap-2 pt-1\">\n          <Button variant=\"secondary\" size=\"md\" className=\"flex-1\" onClick={resetToDefault}>\n            {tr.text.pageToolbar.reset}\n          </Button>\n          <Button\n            variant=\"accent\"\n            size=\"md\"\n            className=\"flex-1\"\n            onClick={() => {\n              apply();\n              setPageSetupOpen(false);\n            }}\n          >\n            {tr.text.pageToolbar.apply}\n          </Button>\n        </div>\n      </div>\n    </Modal>\n  );\n};\n", "import React, { useRef, useState } from 'react';\nimport { useTextStore } from '../../store/useTextStore';\nimport { EditorShellHeader } from '../editor/EditorShellHeader';\nimport { ShellFileMenu } from '../editor/ShellFileMenu';\nimport { ModeProjectTabs } from '../editor/ModeProjectTabs';\nimport { modeAccentVars } from '../../theme/modeAccent';\nimport { DocumentCanvas } from './DocumentCanvas';\nimport { TextLeftPanel } from './TextLeftPanel';\nimport { TextRightSidebar } from './TextRightSidebar';\nimport { MetricsBar } from './MetricsBar';\nimport { TextExportModal } from './TextExportModal';\nimport { TextCommandPalette } from './TextCommandPalette';\nimport { TextPageSetupModal } from './TextPageSetupModal';\nimport { I18nProvider, type Locale, useTranslation } from '../../i18n';\nimport {\n  exportProjectToWzrdt,\n  importProjectFromWzrdt,\n  textProjectFromStore,\n} from '../../utils/textProjectFile';\nimport { projectAccept } from '../../utils/projectExtensions';\nimport { markdownToHtml } from '../../lib/text/markdown';\nimport { docxFileToHtml, htmlToTipTapDoc } from '../../lib/text/docxBridge';\nimport { uploadCurrentProjectToCloudWithToast } from '../../utils/cloudSaveToast';\nimport { EditorEmptyState } from '../editor/EditorEmptyState';\nimport type { Editable } from '../../services/editableService';\nimport { TextBody, TextTitle } from '../ui';\ninterface TextEditorProps {\n  onSwitchMode?: (mode: 'video' | 'image' | 'audio' | 'text' | 'slides') => void;\n  onNewProject?: () => void;\n  backHref?: string;\n  backLinkText?: string;\n  locale?: Locale;\n  onBack?: () => void;\n  onOpenCloudProject?: (editable: Editable) => void;\n}\n\nexport const TextEditor: React.FC<TextEditorProps> = ({\n  onSwitchMode,\n  onNewProject,\n  backHref,\n  backLinkText,\n  locale,\n  onBack,\n  onOpenCloudProject,\n}) => {\n  const t = useTranslation();\n  const {\n    textProjects,\n    doc,\n    exportModalOpen,\n    setExportModalOpen,\n    importTextProject,\n    addToast,\n  } = useTextStore();\n\n  const projectInputRef = useRef<HTMLInputElement>(null);\n  const [isSavingCloud, setIsSavingCloud] = useState(false);\n  const hasProject = textProjects.length > 0;\n\n  const saveLocal = async () => {\n    const state = useTextStore.getState();\n    const project = state.textProjects.find((p) => p.id === state.activeTextProjectId);\n    if (!project) return;\n    const blob = await exportProjectToWzrdt(\n      textProjectFromStore({\n        ...project,\n        name: state.projectName || project.name,\n        doc: state.doc,\n        outline: state.outline,\n        variants: state.variants,\n        suggestions: state.suggestions,\n        snapshots: state.snapshots,\n        brandVoice: state.brandVoice,\n        metrics: state.metrics,\n        clarity: state.clarity,\n        docType: state.docType,\n        language: state.language,\n        tone: state.tone,\n        targetChannel: state.targetChannel,\n        workflowStatus: state.workflowStatus,\n        seoMeta: state.seoMeta,\n        comments: state.comments,\n        claims: state.claims,\n        enforceComplianceOnExport: state.enforceComplianceOnExport,\n      })\n    );\n    const a = document.createElement('a');\n    a.href = URL.createObjectURL(blob);\n    a.download = `${state.projectName || project.name}.kait`;\n    a.click();\n    URL.revokeObjectURL(a.href);\n  };\n\n  const openProject = async (file: File) => {\n    try {\n      const lower = file.name.toLowerCase();\n      if (lower.endsWith('.docx')) {\n        const html = await docxFileToHtml(file);\n        importTextProject(\n          {\n            name: file.name.replace(/\\.docx$/i, ''),\n            doc: htmlToTipTapDoc(html),\n          },\n          file.name\n        );\n        addToast(t.text.editor.toasts.docxImported, 'success');\n        return;\n      }\n      if (lower.endsWith('.md')) {\n        const md = await file.text();\n        const html = markdownToHtml(md);\n        importTextProject(\n          {\n            name: file.name.replace(/\\.md$/i, ''),\n            doc: htmlToTipTapDoc(html),\n          },\n          file.name\n        );\n        addToast(t.text.editor.toasts.markdownImported, 'success');\n        return;\n      }\n      const data = await importProjectFromWzrdt(file);\n      importTextProject(data, file.name);\n      addToast(t.text.editor.toasts.projectOpened, 'success');\n    } catch {\n      addToast(t.text.editor.toasts.projectInvalid, 'error');\n    }\n  };\n\n  const saveToCloud = async () => {\n    if (isSavingCloud) return;\n    setIsSavingCloud(true);\n    try {\n      await uploadCurrentProjectToCloudWithToast('text');\n    } catch {\n      // Error toast is already shown and stays until the user closes it.\n    } finally {\n      setIsSavingCloud(false);\n    }\n  };\n\n  const shellHeader = (\n    <EditorShellHeader\n      mode=\"text\"\n      onBack={onBack}\n      backHref={backHref}\n      backLabel={backLinkText}\n      onSwitchMode={(m) => onSwitchMode?.(m)}\n      onNewProject={onNewProject}\n      newProjectTitle={t.editor.newProject.text}\n      onExport={hasProject ? () => setExportModalOpen(true) : undefined}\n      exportDisabled={!hasProject}\n      fileMenu={\n        <ShellFileMenu\n          onNew={onNewProject}\n          onOpen={() => projectInputRef.current?.click()}\n          onSave={hasProject ? () => void saveLocal() : undefined}\n          onSaveToCloud={hasProject ? () => void saveToCloud() : undefined}\n          isSavingCloud={isSavingCloud}\n        />\n      }\n      tabs={<ModeProjectTabs mode=\"text\" />}\n    />\n  );\n\n  if (!hasProject) {\n    return (\n      <div\n        data-we-mode=\"text\"\n        style={modeAccentVars('text')}\n        className=\"relative flex h-full w-full flex-col bg-[#0A0A0F]\"\n      >\n        {shellHeader}\n        <div className=\"relative min-h-0 flex-1\">\n          <EditorEmptyState\n            mode=\"Text\"\n            onCreate={onNewProject ?? (() => {})}\n            onOpenCloud={onOpenCloudProject ?? (() => {})}\n          />\n        </div>\n      </div>\n    );\n  }\n\n  return (\n    <I18nProvider locale={locale}>\n      <div\n        data-we-mode=\"text\"\n        style={modeAccentVars('text')}\n        className=\"we-text-editor relative flex h-full w-full flex-col bg-[#0A0A0F] text-[#F0F0F5]\"\n      >\n        {shellHeader}\n\n        <div className=\"relative flex min-h-0 flex-1 flex-col\">\n          <div className=\"flex min-h-0 w-full flex-1\">\n            <TextLeftPanel />\n\n            <div className=\"flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden\">\n              <DocumentCanvas doc={doc} />\n              <MetricsBar />\n            </div>\n\n            <TextRightSidebar />\n          </div>\n        </div>\n\n        <input\n          ref={projectInputRef}\n          type=\"file\"\n          accept={projectAccept('text', [\n            '.md',\n            '.json',\n            '.docx',\n            'application/json',\n            'text/markdown',\n            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n          ])}\n          className=\"hidden\"\n          onChange={(e) => {\n            const f = e.target.files?.[0];\n            if (f) void openProject(f);\n          }}\n        />\n\n        <TextExportModal\n          open={exportModalOpen}\n          onClose={() => setExportModalOpen(false)}\n          onSwitchMode={(m) => onSwitchMode?.(m)}\n        />\n\n        <TextPageSetupModal />\n        <TextCommandPalette />\n        <TextToasts />\n      </div>\n    </I18nProvider>\n  );\n};\n\nfunction TextToasts() {\n  const { toasts, removeToast } = useTextStore();\n  return (\n    <div className=\"fixed bottom-4 right-20 z-[90] flex flex-col gap-2\">\n      {toasts.map((toast) => (\n        <div\n          key={toast.id}\n          onClick={() => removeToast(toast.id)}\n          className={`cursor-pointer rounded-lg px-3 py-2 shadow-lg ${\n            toast.type === 'error'\n              ? 'bg-red-500/90 text-white'\n              : toast.type === 'success'\n                ? 'bg-[#00BFA5]/90 text-white'\n                : toast.type === 'warning'\n                  ? 'bg-[#FFD54F]/90 text-black'\n                  : 'border border-panel-border bg-black-capsule text-white'\n          }`}\n        >\n          <TextBody as=\"p\" size=\"sm\">\n            {toast.message}\n          </TextBody>\n        </div>\n      ))}\n    </div>\n  );\n}\n\nexport default TextEditor;\n", "import { create } from 'zustand';\n\nexport type CoachTip = {\n  slideIndex: number;\n  tip: string;\n  pacingSeconds?: number;\n};\n\nexport type CritiqueIssue = {\n  severity: string;\n  slideIndex?: number;\n  slideId?: string;\n  message: string;\n  fix?: string;\n};\n\nexport type CritiqueQuestion = {\n  slideIndex: number;\n  question: string;\n  tip?: string;\n};\n\ntype SlidesUiState = {\n  leftDockOpen: boolean;\n  setLeftDockOpen: (open: boolean) => void;\n  toggleLeftDock: () => void;\n\n  rightDockOpen: boolean;\n  setRightDockOpen: (open: boolean) => void;\n\n  /** Selection context menu (canvas right-click). */\n  contextMenu: { x: number; y: number } | null;\n  setContextMenu: (pos: { x: number; y: number } | null) => void;\n\n  /** Alt-text editor for the selected image/object. */\n  altTextModal: { objectId: string; value: string } | null;\n  setAltTextModal: (state: { objectId: string; value: string } | null) => void;\n\n  /** Speaker coach results \u2014 kept when switching right-rail panels. */\n  coachSummary: string;\n  coachTips: CoachTip[];\n  setCoachResult: (summary: string, tips: CoachTip[]) => void;\n  clearCoachResult: () => void;\n\n  /** Design critic + Q&A \u2014 kept when switching panels. */\n  critiqueIssues: CritiqueIssue[];\n  critiqueScore: number | null;\n  critiqueMinutes: number | null;\n  critiqueQuestions: CritiqueQuestion[];\n  setCritiqueResult: (opts: {\n    score: number | null;\n    minutes: number | null;\n    issues: CritiqueIssue[];\n  }) => void;\n  setCritiqueQuestions: (questions: CritiqueQuestion[]) => void;\n};\n\nexport const useSlidesUiStore = create<SlidesUiState>((set) => ({\n  leftDockOpen: true,\n  setLeftDockOpen: (open) => set({ leftDockOpen: open }),\n  toggleLeftDock: () => set((s) => ({ leftDockOpen: !s.leftDockOpen })),\n\n  rightDockOpen: true,\n  setRightDockOpen: (open) => set({ rightDockOpen: open }),\n\n  contextMenu: null,\n  setContextMenu: (pos) => set({ contextMenu: pos }),\n\n  altTextModal: null,\n  setAltTextModal: (state) => set({ altTextModal: state }),\n\n  coachSummary: '',\n  coachTips: [],\n  setCoachResult: (summary, tips) => set({ coachSummary: summary, coachTips: tips }),\n  clearCoachResult: () => set({ coachSummary: '', coachTips: [] }),\n\n  critiqueIssues: [],\n  critiqueScore: null,\n  critiqueMinutes: null,\n  critiqueQuestions: [],\n  setCritiqueResult: ({ score, minutes, issues }) =>\n    set({ critiqueScore: score, critiqueMinutes: minutes, critiqueIssues: issues }),\n  setCritiqueQuestions: (questions) => set({ critiqueQuestions: questions }),\n}));\n\nexport type { SlidesRightTab } from '../types/slides.types';\n", "import React, { useState } from 'react';\nimport {\n  BarChart3,\n  ChevronLeft,\n  LayoutTemplate,\n  Languages,\n  PenLine,\n  Sparkles,\n  StickyNote,\n} from 'lucide-react';\nimport { useSlidesStore, flushSlidesPersistence } from '../../store/useSlidesStore';\nimport {\n  generateDeck,\n  rewriteSlide,\n  generateSpeakerNotes,\n  translateDeck,\n  dataToChart,\n  dataNarrative,\n} from '../../services/slides/deckService';\nimport type { ChartType } from '../../utils/chartUtils';\nimport { useTranslation } from '../../i18n';\nimport { Button, PanelBody, PanelField, PanelSection, SelectDropdown, TextBody, TextTitle } from '../ui';\n\ntype ToolId =\n  | 'generate'\n  | 'rewrite'\n  | 'layout'\n  | 'notes'\n  | 'translate'\n  | 'data';\n\ntype ToolDef = {\n  id: ToolId;\n  icon: React.ReactNode;\n};\n\nconst ALL_TOOLS: ToolDef[] = [\n  { id: 'generate', icon: <Sparkles size={16} /> },\n  { id: 'rewrite', icon: <PenLine size={16} /> },\n  { id: 'layout', icon: <LayoutTemplate size={16} /> },\n  { id: 'notes', icon: <StickyNote size={16} /> },\n  { id: 'translate', icon: <Languages size={16} /> },\n  { id: 'data', icon: <BarChart3 size={16} /> },\n];\n\nconst TEXTAREA =\n  'w-full rounded-xl border border-panel-border bg-black-capsule px-3 py-2 font-sans text-[12px] font-medium text-white outline-none placeholder:text-white/40 focus:border-[var(--we-accent)]';\n\nfunction ToolRow({\n  tool,\n  name,\n  description,\n  onClick,\n}: {\n  tool: ToolDef;\n  name: string;\n  description: string;\n  onClick: () => void;\n}) {\n  return (\n    <button\n      type=\"button\"\n      onClick={onClick}\n      className=\"relative flex w-full cursor-pointer items-start gap-2.5 overflow-hidden rounded-xl border border-transparent bg-black-capsule px-2.5 py-2.5 text-left transition-colors hover:border-[color-mix(in_srgb,var(--we-accent)_35%,transparent)] hover:bg-[var(--we-accent-muted)] active:scale-[0.99]\"\n    >\n      <span className=\"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-[var(--we-accent)] text-white\">\n        {tool.icon}\n      </span>\n      <span className=\"min-w-0 flex-1\">\n        <TextTitle as=\"span\" size=\"sm\" className=\"block text-white\">\n          {name}\n        </TextTitle>\n        <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 text-pretty block leading-snug text-white/80\">\n          {description}\n        </TextBody>\n      </span>\n    </button>\n  );\n}\n\nexport const SlidesAiPanel: React.FC = () => {\n  const t = useTranslation();\n  const ai = t.slides.ai;\n  const {\n    addToast,\n    applyOutline,\n    applyGeneratedDeck,\n    slides,\n    activeSlideId,\n    applyLayoutContent,\n    setSlideNotes,\n    addSlide,\n    insertChart,\n    applyMagicLayout,\n    applySemanticRestyle,\n    applyDeckTranslation,\n  } = useSlidesStore();\n  const [tab, setTab] = useState<ToolId | null>(null);\n  const [brief, setBrief] = useState('');\n  const [audience, setAudience] = useState('');\n  const [count, setCount] = useState(8);\n  const [busyAction, setBusyAction] = useState<string | null>(null);\n  const [csv, setCsv] = useState('Mes,Ventas\\nEne,10\\nFeb,14\\nMar,18');\n  const [lang, setLang] = useState('es');\n  const busy = busyAction !== null;\n\n  const langOptions = [\n    { value: 'es', label: ai.langEs },\n    { value: 'en', label: ai.langEn },\n    { value: 'pt', label: ai.langPt },\n  ];\n\n  const activeTool = ALL_TOOLS.find((x) => x.id === tab);\n\n  const runGenerate = async () => {\n    if (!brief.trim() || busy) return;\n    setBusyAction('generate');\n    try {\n      const theme = useSlidesStore.getState().theme;\n      const res = await generateDeck({\n        brief,\n        audience: audience || undefined,\n        slideCount: count,\n        tone: 'professional',\n        language: lang || 'es',\n        theme,\n      });\n      console.log('[slides] generate-deck response', {\n        deckTitle: res.deckTitle,\n        hasThemeHint: Boolean(res.themeHint),\n        slides: res.slides.map((s) => ({\n          layoutId: s.layoutId,\n          title: s.title,\n          hasImagePrompt: Boolean(s.imagePrompt),\n          hasStockQuery: Boolean(s.stockQuery),\n          hasImageUrl: Boolean(s.image?.url),\n          shapes: s.shapes?.length || 0,\n          hasChart: Boolean(s.chartHint),\n        })),\n      });\n      const applied = await applyGeneratedDeck(res);\n      await flushSlidesPersistence();\n      addToast(\n        ai.toasts.deckGeneratedRich(\n          applied.slideCount,\n          applied.imagesPlaced,\n          applied.chartsPlaced\n        ),\n        'success'\n      );\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : ai.toasts.deckError, 'error');\n    } finally {\n      setBusyAction(null);\n    }\n  };\n\n  const runRewrite = async (op: 'condense' | 'less-text' | 'audience') => {\n    if (busy) return;\n    const slide = slides.find((s) => s.id === activeSlideId);\n    if (!slide) return;\n    const outline = useSlidesStore.getState().getOutline().find((o) => o.slideId === slide.id);\n    const title = (outline?.title || slide.name || 'Slide').trim();\n    let body = (outline?.bullets || []).join('\\n').trim();\n    // Fallback: pull any textbox content if outline has no bullets yet.\n    if (!body) {\n      const json = slide.json as { objects?: Array<Record<string, unknown>> } | undefined;\n      body = (json?.objects || [])\n        .map((o) => (typeof o.text === 'string' ? o.text.trim() : ''))\n        .filter(Boolean)\n        .join('\\n');\n    }\n    if (!body) {\n      addToast(ai.toasts.rewriteEmpty, 'info');\n      return;\n    }\n    setBusyAction(op);\n    try {\n      const res = await rewriteSlide({\n        title,\n        body,\n        op,\n        audience: audience.trim() || 'general',\n      });\n      applyLayoutContent(slide.id, {\n        title: res.title,\n        body: res.body,\n        bullets: res.body,\n      });\n      if (res.notes) setSlideNotes(slide.id, res.notes);\n      await flushSlidesPersistence();\n      addToast(ai.toasts.slideRewritten, 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : ai.toasts.generic, 'error');\n    } finally {\n      setBusyAction(null);\n    }\n  };\n\n  const runNotes = async () => {\n    if (busy) return;\n    setBusyAction('notes');\n    try {\n      const outline = useSlidesStore.getState().getOutline();\n      const res = await generateSpeakerNotes({\n        slides: outline.map((o) => ({ title: o.title, body: o.bullets.join('\\n') })),\n      });\n      res.notes.forEach((n, i) => {\n        const id = outline[i]?.slideId;\n        if (id) setSlideNotes(id, n);\n      });\n      await flushSlidesPersistence();\n      addToast(ai.toasts.notesGenerated, 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : ai.toasts.generic, 'error');\n    } finally {\n      setBusyAction(null);\n    }\n  };\n\n  const runTranslate = async () => {\n    if (busy) return;\n    setBusyAction('translate');\n    try {\n      const outline = useSlidesStore.getState().getOutline();\n      const requestPayload = {\n        targetLanguage: lang,\n        slides: outline.map((o) => ({\n          title: o.title,\n          body: o.bullets.join('\\n'),\n          notes: slides.find((s) => s.id === o.slideId)?.notes ?? '',\n        })),\n      };\n      console.log('[slides] translate-deck request', requestPayload);\n\n      const res = await translateDeck(requestPayload);\n      console.log('[slides] translate-deck response', res);\n\n      if (!res.slides?.length) {\n        addToast(ai.toasts.translateEmpty, 'warning');\n        return;\n      }\n\n      const changed = res.slides.some(\n        (s, i) =>\n          s.title !== requestPayload.slides[i]?.title ||\n          s.body !== requestPayload.slides[i]?.body ||\n          (s.notes || '') !== (requestPayload.slides[i]?.notes || '')\n      );\n      if (!changed) {\n        console.warn('[slides] translation still unchanged after fallback');\n        addToast(ai.toasts.translateNoChange, 'warning');\n        return;\n      }\n\n      // Patch texts in place \u2014 never rebuild layout JSON (that wiped images).\n      useSlidesStore.getState().applyDeckTranslation(\n        res.slides\n          .map((s, i) => ({\n            slideId: outline[i]?.slideId || '',\n            title: s.title,\n            body: s.body || '',\n            notes: s.notes,\n            previousTitle: requestPayload.slides[i]?.title,\n            previousBody: requestPayload.slides[i]?.body,\n          }))\n          .filter((s) => s.slideId)\n      );\n      try {\n        await flushSlidesPersistence();\n      } catch (persistErr) {\n        // Local deck already updated; cloud 404 must not look like a translate failure.\n        console.warn('[slides] translate persist failed (deck already updated)', persistErr);\n      }\n      addToast(\n        res.usedFallback ? ai.toasts.deckTranslatedFallback : ai.toasts.deckTranslated,\n        'success'\n      );\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : ai.toasts.generic, 'error');\n    } finally {\n      setBusyAction(null);\n    }\n  };\n\n  const runChart = async () => {\n    if (busy) return;\n    setBusyAction('chart');\n    try {\n      const res = await dataToChart({ csv });\n      const chartType = (\n        ['bar', 'line', 'pie', 'donut'].includes(res.chartType) ? res.chartType : 'bar'\n      ) as ChartType;\n      const id = addSlide('chart');\n      applyLayoutContent(id, {\n        title: ai.toasts.chartFallbackTitle(chartType),\n        body: '',\n      });\n      useSlidesStore.getState().setActiveSlideId(id);\n      await insertChart({\n        chartType,\n        labels: res.labels,\n        series: res.series.map((s) => ({ name: s.name, data: s.data })),\n      });\n      await flushSlidesPersistence();\n      addToast(ai.toasts.chartInserted, 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : ai.toasts.generic, 'error');\n    } finally {\n      setBusyAction(null);\n    }\n  };\n\n  const runNarrative = async () => {\n    if (busy) return;\n    setBusyAction('narrative');\n    try {\n      const requestPayload = { csv, audience: audience || 'general' };\n      console.log('[slides] data-narrative request', requestPayload);\n      const res = await dataNarrative(requestPayload);\n      console.log('[slides] data-narrative response', res);\n      const id = addSlide('bullets');\n      applyLayoutContent(id, {\n        title: res.title,\n        bullets: res.bullets.map((b) => `\u2022 ${b}`).join('\\n'),\n        body: res.insight,\n      });\n      await flushSlidesPersistence();\n      addToast(ai.toasts.narrativeCreated, 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : ai.toasts.generic, 'error');\n    } finally {\n      setBusyAction(null);\n    }\n  };\n\n  if (!tab) {\n    return (\n      <PanelBody className=\"h-full overflow-y-auto\">\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{ai.hint}</TextBody>\n        <PanelSection title={ai.toolsHeader}>\n          <div className=\"flex flex-col gap-1.5\">\n            {ALL_TOOLS.map((tool) => (\n              <ToolRow\n                key={tool.id}\n                tool={tool}\n                name={ai.tools[tool.id]}\n                description={ai.tools[`${tool.id}Desc`]}\n                onClick={() => setTab(tool.id)}\n              />\n            ))}\n          </div>\n        </PanelSection>\n      </PanelBody>\n    );\n  }\n\n  return (\n    <PanelBody className=\"h-full overflow-y-auto\">\n      <button\n        type=\"button\"\n        onClick={() => setTab(null)}\n        className=\"mb-1 inline-flex items-center gap-1 text-white/80 hover:text-white\"\n      ><ChevronLeft size={14} /> <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">{ai.backToList}</TextBody></button>\n      <TextTitle as=\"h3\" size=\"sm\" className=\"text-white\">\n        {activeTool ? ai.tools[activeTool.id] : ''}\n      </TextTitle>\n\n      {tab === 'generate' && (\n        <PanelSection>\n          <textarea\n            value={brief}\n            onChange={(e) => setBrief(e.target.value)}\n            placeholder={ai.briefPlaceholder}\n            className={`h-24 ${TEXTAREA}`}\n          />\n          <PanelField\n            label={ai.audienceLabel}\n            trailing={\n              <input\n                value={audience}\n                onChange={(e) => setAudience(e.target.value)}\n                placeholder={ai.audiencePlaceholder}\n                className=\"w-32 bg-transparent text-right font-sans text-[12px] font-medium text-white outline-none placeholder:text-white/40\"\n              />\n            }\n          />\n          <PanelField\n            label={ai.countLabel}\n            variant=\"slide\"\n            min={3}\n            max={30}\n            step={1}\n            numericValue={count}\n            onChange={setCount}\n          />\n          <PanelField\n            label={ai.languageLabel}\n            trailing={\n              <SelectDropdown\n                value={lang}\n                options={langOptions}\n                onChange={setLang}\n                ariaLabel={ai.languageLabel}\n              />\n            }\n          />\n          <Button\n            variant=\"accent\"\n            size=\"md\"\n            className=\"w-full\"\n            loading={busyAction === 'generate'}\n            disabled={busy}\n            onClick={() => void runGenerate()}\n          >\n            {busyAction === 'generate' ? ai.generating : ai.generateButton}\n          </Button>\n        </PanelSection>\n      )}\n\n      {tab === 'rewrite' && (\n        <PanelSection>\n          <PanelField\n            label={ai.audienceLabel}\n            trailing={\n              <input\n                value={audience}\n                onChange={(e) => setAudience(e.target.value)}\n                placeholder={ai.audiencePlaceholder}\n                className=\"w-32 bg-transparent text-right font-sans text-[12px] font-medium text-white outline-none placeholder:text-white/40\"\n              />\n            }\n          />\n          <div className=\"grid grid-cols-1 gap-1.5\">\n            <Button\n              variant=\"secondary\"\n              size=\"sm\"\n              loading={busyAction === 'condense'}\n              disabled={busy}\n              onClick={() => void runRewrite('condense')}\n            >\n              {busyAction === 'condense' ? ai.generating : ai.condense}\n            </Button>\n            <Button\n              variant=\"secondary\"\n              size=\"sm\"\n              loading={busyAction === 'less-text'}\n              disabled={busy}\n              onClick={() => void runRewrite('less-text')}\n            >\n              {busyAction === 'less-text' ? ai.generating : ai.lessText}\n            </Button>\n            <Button\n              variant=\"secondary\"\n              size=\"sm\"\n              loading={busyAction === 'audience'}\n              disabled={busy}\n              onClick={() => void runRewrite('audience')}\n            >\n              {busyAction === 'audience' ? ai.generating : ai.audience}\n            </Button>\n          </div>\n        </PanelSection>\n      )}\n\n      {tab === 'layout' && (\n        <PanelSection>\n          <Button\n            variant=\"secondary\"\n            size=\"sm\"\n            className=\"w-full\"\n            onClick={() => {\n              void (async () => {\n                await applyMagicLayout();\n                await flushSlidesPersistence();\n              })();\n            }}\n          >\n            {ai.magicLayout}\n          </Button>\n          <Button\n            variant=\"secondary\"\n            size=\"sm\"\n            className=\"w-full\"\n            onClick={() => {\n              applySemanticRestyle('board');\n              void flushSlidesPersistence();\n            }}\n          >\n            {ai.restyleBoard}\n          </Button>\n        </PanelSection>\n      )}\n\n      {tab === 'notes' && (\n        <PanelSection>\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{ai.tools.notesDesc}</TextBody>\n          <Button\n            variant=\"accent\"\n            size=\"md\"\n            className=\"w-full\"\n            loading={busyAction === 'notes'}\n            disabled={busy}\n            onClick={() => void runNotes()}\n          >\n            {busyAction === 'notes' ? ai.generating : ai.speakerNotes}\n          </Button>\n        </PanelSection>\n      )}\n\n      {tab === 'translate' && (\n        <PanelSection>\n          <PanelField\n            label={ai.languageLabel}\n            trailing={\n              <SelectDropdown\n                value={lang}\n                options={langOptions}\n                onChange={setLang}\n                ariaLabel={ai.languageLabel}\n              />\n            }\n          />\n          <Button\n            variant=\"accent\"\n            size=\"md\"\n            className=\"w-full\"\n            loading={busyAction === 'translate'}\n            disabled={busy}\n            onClick={() => void runTranslate()}\n          >\n            {busyAction === 'translate' ? ai.generating : ai.translateButton}\n          </Button>\n        </PanelSection>\n      )}\n\n      {tab === 'data' && (\n        <PanelSection>\n          <textarea\n            value={csv}\n            onChange={(e) => setCsv(e.target.value)}\n            className={`h-28 font-mono text-[11px] ${TEXTAREA}`}\n          />\n          <Button\n            variant=\"secondary\"\n            size=\"sm\"\n            className=\"w-full\"\n            loading={busyAction === 'chart'}\n            disabled={busy}\n            onClick={() => void runChart()}\n          >\n            {busyAction === 'chart' ? ai.generating : ai.insertChart}\n          </Button>\n          <Button\n            variant=\"secondary\"\n            size=\"sm\"\n            className=\"w-full\"\n            loading={busyAction === 'narrative'}\n            disabled={busy}\n            onClick={() => void runNarrative()}\n          >\n            {busyAction === 'narrative' ? ai.generating : ai.dataToNarrative}\n          </Button>\n        </PanelSection>\n      )}\n    </PanelBody>\n  );\n};\n", "export const SLIDES_AGENT_TOOLS = [\n  {\n    type: 'function',\n    function: {\n      name: 'add_slide',\n      description: 'Add a new slide with a layout and content',\n      parameters: {\n        type: 'object',\n        properties: {\n          layoutId: { type: 'string' },\n          title: { type: 'string' },\n          bullets: { type: 'array', items: { type: 'string' } },\n          notes: { type: 'string' },\n        },\n        required: ['title'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'apply_layout',\n      description: 'Change layout of the active or given slide',\n      parameters: {\n        type: 'object',\n        properties: {\n          slideId: { type: 'string' },\n          layoutId: { type: 'string' },\n        },\n        required: ['layoutId'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'restyle_deck',\n      description: 'Apply a named theme preset to the whole deck',\n      parameters: {\n        type: 'object',\n        properties: {\n          themeId: { type: 'string' },\n        },\n        required: ['themeId'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'semantic_restyle',\n      description: 'Apply semantic restyle mode: board | sales | internal',\n      parameters: {\n        type: 'object',\n        properties: {\n          mode: { type: 'string', enum: ['board', 'sales', 'internal'] },\n        },\n        required: ['mode'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'rewrite_slide',\n      description: 'Rewrite slide title/body',\n      parameters: {\n        type: 'object',\n        properties: {\n          slideId: { type: 'string' },\n          title: { type: 'string' },\n          body: { type: 'string' },\n        },\n        required: ['body'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'reorder_slides',\n      description: 'Reorder slides by id list',\n      parameters: {\n        type: 'object',\n        properties: {\n          slideIds: { type: 'array', items: { type: 'string' } },\n        },\n        required: ['slideIds'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'add_notes',\n      description: 'Set speaker notes on a slide',\n      parameters: {\n        type: 'object',\n        properties: {\n          slideId: { type: 'string' },\n          notes: { type: 'string' },\n        },\n        required: ['notes'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'condense_deck',\n      description: 'Reduce deck to N slides keeping core message',\n      parameters: {\n        type: 'object',\n        properties: {\n          maxSlides: { type: 'number' },\n        },\n        required: ['maxSlides'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'translate_deck',\n      description: 'Translate all slide text',\n      parameters: {\n        type: 'object',\n        properties: {\n          targetLanguage: { type: 'string' },\n        },\n        required: ['targetLanguage'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'magic_layout',\n      description: 'Reflow objects on the active or given slide',\n      parameters: {\n        type: 'object',\n        properties: {\n          slideId: { type: 'string' },\n        },\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'apply_design_fix',\n      description: 'Apply a design fix: condense-text | fix-contrast | autofit | ensure-alt',\n      parameters: {\n        type: 'object',\n        properties: {\n          kind: { type: 'string' },\n          slideId: { type: 'string' },\n        },\n        required: ['kind'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'insert_chart',\n      description: 'Insert a chart on the active slide from labels and values',\n      parameters: {\n        type: 'object',\n        properties: {\n          chartType: { type: 'string' },\n          labels: { type: 'array', items: { type: 'string' } },\n          values: { type: 'array', items: { type: 'number' } },\n          seriesName: { type: 'string' },\n        },\n        required: ['labels', 'values'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'generate_image',\n      description: 'Generate an AI image and place it on the active slide (costly)',\n      parameters: {\n        type: 'object',\n        properties: {\n          prompt: { type: 'string' },\n        },\n        required: ['prompt'],\n      },\n    },\n  },\n  {\n    type: 'function',\n    function: {\n      name: 'insert_stock',\n      description: 'Search stock and insert the first photo on the active slide (costly)',\n      parameters: {\n        type: 'object',\n        properties: {\n          query: { type: 'string' },\n        },\n        required: ['query'],\n      },\n    },\n  },\n] as const;\n\nexport const COSTLY_TOOLS = new Set([\n  'generate_image',\n  'insert_stock',\n  'translate_deck',\n  'condense_deck',\n]);\n", "import { useSlidesStore } from '../../../store/useSlidesStore';\nimport type { SemanticRestyleMode, SlideLayoutId } from '../../../types/slides.types';\nimport { THEME_PRESETS } from '../../slides/themes';\nimport { translateDeck, rewriteSlide, proxySlideImage } from '../../../services/slides/deckService';\nimport { generateImage } from '../../../services/imageService';\nimport { searchStock } from '../../../services/stockService';\nimport type { ChartType } from '../../../utils/chartUtils';\nimport type { DesignFixKind } from '../designFixes';\n\nfunction uid(prefix: string): string {\n  return `${prefix}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nasync function placeImageOnActiveSlide(blob: Blob, name: string, alt: string): Promise<string> {\n  const store = useSlidesStore.getState();\n  const slideId = store.activeSlideId;\n  if (!slideId) return 'No active slide';\n  const slide = store.slides.find((s) => s.id === slideId);\n  if (!slide) return 'Slide missing';\n  const file = new File([blob], name, { type: blob.type || 'image/png' });\n  const url = URL.createObjectURL(file);\n  const assetId = uid('asset');\n  store.addAsset({\n    id: assetId,\n    name,\n    mimeType: file.type,\n    file,\n    url,\n  });\n  const json = structuredClone(slide.json) as { objects?: Array<Record<string, unknown>> };\n  json.objects = [\n    ...(json.objects || []),\n    {\n      type: 'Image',\n      version: '6.0.0',\n      left: 960,\n      top: 240,\n      width: 800,\n      height: 500,\n      scaleX: 1,\n      scaleY: 1,\n      src: url,\n      id: uid('obj'),\n      assetId,\n      alt,\n      name,\n    },\n  ];\n  store.updateSlideJson(slideId, json, true);\n  return `Placed image on ${slideId}`;\n}\n\nexport async function executeSlidesToolCall(\n  name: string,\n  argsJson: string\n): Promise<string> {\n  let args: Record<string, unknown> = {};\n  try {\n    args = JSON.parse(argsJson || '{}') as Record<string, unknown>;\n  } catch {\n    return 'Invalid JSON arguments';\n  }\n\n  const store = useSlidesStore.getState();\n\n  switch (name) {\n    case 'add_slide': {\n      const layoutId = (args.layoutId as SlideLayoutId) || 'bullets';\n      const id = store.addSlide(layoutId, store.activeSlideId || undefined);\n      const title = String(args.title || 'Nueva');\n      const bullets = Array.isArray(args.bullets) ? (args.bullets as string[]) : [];\n      store.applyLayoutContent(id, {\n        title,\n        bullets: bullets.map((b) => `\u2022 ${b}`).join('\\n'),\n        body: bullets.map((b) => `\u2022 ${b}`).join('\\n'),\n      });\n      if (args.notes) store.setSlideNotes(id, String(args.notes));\n      return `Added slide ${id}`;\n    }\n    case 'apply_layout': {\n      const slideId = String(args.slideId || store.activeSlideId || '');\n      store.setSlideLayout(slideId, (args.layoutId as SlideLayoutId) || 'title-body');\n      return `Applied layout to ${slideId}`;\n    }\n    case 'restyle_deck': {\n      const theme = THEME_PRESETS.find((t) => t.id === args.themeId) || THEME_PRESETS[0]!;\n      store.setTheme({ ...theme });\n      return `Applied theme ${theme.name}`;\n    }\n    case 'semantic_restyle': {\n      const mode = String(args.mode || 'board') as SemanticRestyleMode;\n      store.applySemanticRestyle(mode);\n      return `Semantic restyle ${mode}`;\n    }\n    case 'rewrite_slide': {\n      const slideId = String(args.slideId || store.activeSlideId || '');\n      const outline = store.getOutline().find((o) => o.slideId === slideId);\n      const title = String(args.title || outline?.title || 'Slide');\n      const bodyFromOutline = outline?.bullets.map((b) => `\u2022 ${b}`).join('\\n') || '';\n      const body = String(args.body || bodyFromOutline);\n      const op = (String(args.op || 'condense') as 'condense' | 'less-text' | 'audience');\n      if (args.title && args.body && !args.op) {\n        store.applyLayoutContent(slideId, {\n          title: String(args.title),\n          body: String(args.body),\n          bullets: String(args.body),\n        });\n        return `Rewrote ${slideId}`;\n      }\n      try {\n        const res = await rewriteSlide({\n          title,\n          body,\n          op,\n          audience: args.audience ? String(args.audience) : 'general',\n        });\n        store.applyLayoutContent(slideId, {\n          title: res.title,\n          body: res.body,\n          bullets: res.body,\n        });\n        if (res.notes) store.setSlideNotes(slideId, res.notes);\n        return `Rewrote ${slideId} (${op})`;\n      } catch (err) {\n        return `Rewrite failed: ${err instanceof Error ? err.message : 'error'}`;\n      }\n    }\n    case 'reorder_slides': {\n      const ids = args.slideIds as string[];\n      if (!Array.isArray(ids)) return 'Missing slideIds';\n      ids.forEach((id, i) => store.moveSlide(id, i));\n      return 'Reordered';\n    }\n    case 'add_notes': {\n      const slideId = String(args.slideId || store.activeSlideId || '');\n      store.setSlideNotes(slideId, String(args.notes || ''));\n      return `Notes set on ${slideId}`;\n    }\n    case 'condense_deck': {\n      const max = Number(args.maxSlides) || 5;\n      const keep = store.slides.slice(0, max);\n      store.slides.forEach((s, i) => {\n        if (i >= max) store.setSlideHidden(s.id, true);\n      });\n      return `Condensed to ${keep.length} visible slides`;\n    }\n    case 'translate_deck': {\n      const outline = store.getOutline();\n      const res = await translateDeck({\n        slides: outline.map((o) => ({\n          title: o.title,\n          body: o.bullets.join('\\n'),\n          notes: store.slides.find((s) => s.id === o.slideId)?.notes,\n        })),\n        targetLanguage: String(args.targetLanguage || 'en'),\n      });\n      store.applyDeckTranslation(\n        res.slides\n          .map((s, i) => ({\n            slideId: outline[i]?.slideId || '',\n            title: s.title,\n            body: s.body || '',\n            notes: s.notes,\n            previousTitle: outline[i]?.title,\n            previousBody: outline[i]?.bullets.join('\\n'),\n          }))\n          .filter((s) => s.slideId)\n      );\n      const { flushSlidesPersistence } = await import('../../../store/useSlidesStore');\n      try {\n        await flushSlidesPersistence();\n      } catch (persistErr) {\n        console.warn('[slides] agent translate persist failed', persistErr);\n      }\n      return res.usedFallback ? 'Deck translated (via subtitle fallback)' : 'Deck translated';\n    }\n    case 'magic_layout': {\n      await store.applyMagicLayout(args.slideId ? String(args.slideId) : undefined);\n      return 'Magic layout applied';\n    }\n    case 'apply_design_fix': {\n      const kind = String(args.kind || 'autofit') as DesignFixKind;\n      store.applyDesignFix(kind, args.slideId ? String(args.slideId) : undefined);\n      return `Applied fix ${kind}`;\n    }\n    case 'insert_chart': {\n      const labels = Array.isArray(args.labels) ? (args.labels as string[]) : [];\n      const values = Array.isArray(args.values) ? (args.values as number[]) : [];\n      const chartType = (String(args.chartType || 'bar') as ChartType) || 'bar';\n      await store.insertChart({\n        chartType,\n        labels,\n        series: [{ name: String(args.seriesName || 'Serie'), data: values }],\n      });\n      return 'Chart inserted';\n    }\n    case 'generate_image': {\n      const prompt = String(args.prompt || '').trim();\n      if (!prompt) return 'Missing prompt';\n      const blob = await generateImage({ prompt });\n      return placeImageOnActiveSlide(blob, 'ai-image.png', prompt);\n    }\n    case 'insert_stock': {\n      const query = String(args.query || '').trim();\n      if (!query) return 'Missing query';\n      const result = await searchStock({ q: query, page: 1, perPage: 1 });\n      const photo = result.photos[0];\n      if (!photo) return 'No stock results';\n      const remote = photo.regularUrl || photo.fullUrl;\n      let blob: Blob | null = null;\n      try {\n        const direct = await fetch(remote, { mode: 'cors' });\n        if (direct.ok) blob = await direct.blob();\n      } catch {\n        /* fall through to same-origin proxy */\n      }\n      if (!blob) {\n        blob = await proxySlideImage({ url: remote });\n      }\n      return placeImageOnActiveSlide(blob, `stock-${photo.id}.jpg`, photo.alt || query);\n    }\n    default:\n      return `Unknown tool: ${name}`;\n  }\n}\n", "import React, { useRef, useState } from 'react';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { runSlidesAgentTurn } from '../../services/slides/deckService';\nimport { SLIDES_AGENT_TOOLS, COSTLY_TOOLS } from '../../lib/slides/agent/tools';\nimport { executeSlidesToolCall } from '../../lib/slides/agent/executor';\nimport { useTranslation } from '../../i18n';\nimport { Button, PanelField, Switch, TextBody, TextTitle } from '../ui';\n\ntype Msg = { role: 'user' | 'assistant' | 'system'; content: string };\n\nexport const SlidesChatPanel: React.FC = () => {\n  const t = useTranslation();\n  const { agentPlanMode, setAgentPlanMode, addToast, slides, name, theme } = useSlidesStore();\n  const [messages, setMessages] = useState<Msg[]>([]);\n  const [input, setInput] = useState('');\n  const [busy, setBusy] = useState(false);\n  const planPresentedRef = useRef(false);\n\n  const send = async () => {\n    if (!input.trim() || busy) return;\n    const userMsg: Msg = { role: 'user', content: input.trim() };\n    const nextMessages = [...messages, userMsg];\n    setMessages(nextMessages);\n    setInput('');\n    setBusy(true);\n\n    try {\n      const executeHint = /ejecuta|execute|hazlo|aplica el plan/i.test(userMsg.content);\n      const usePlan = agentPlanMode && !planPresentedRef.current && !executeHint;\n\n      const reply = await runSlidesAgentTurn({\n        messages: nextMessages,\n        projectSnapshot: {\n          name,\n          theme: theme.name,\n          slideCount: slides.length,\n          outline: useSlidesStore.getState().getOutline(),\n        },\n        tools: usePlan ? [] : [...SLIDES_AGENT_TOOLS],\n        planMode: usePlan,\n      });\n\n      if (usePlan) planPresentedRef.current = true;\n      if (executeHint || !agentPlanMode) planPresentedRef.current = false;\n\n      let content = reply.content || '';\n      if (reply.tool_calls?.length) {\n        const results: string[] = [];\n        for (const call of reply.tool_calls) {\n          const toolName = call.function.name;\n          if (COSTLY_TOOLS.has(toolName) && agentPlanMode && !executeHint) {\n            results.push(t.slides.chat.planModeOmit(toolName));\n            continue;\n          }\n          const result = await executeSlidesToolCall(toolName, call.function.arguments);\n          results.push(`${toolName}: ${result}`);\n        }\n        content = `${content}\\n\\n${results.join('\\n')}`.trim();\n      }\n\n      setMessages((m) => [...m, { role: 'assistant', content: content || t.slides.chat.done }]);\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : t.slides.chat.error, 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  return (\n    <div className=\"flex h-full flex-col\">\n      <div className=\"border-b border-panel-border px-3 py-2\">\n        <PanelField\n          label={t.slides.chat.planModeLabel}\n          trailing={\n            <Switch\n              checked={agentPlanMode}\n              onChange={(on) => {\n                setAgentPlanMode(on);\n                planPresentedRef.current = false;\n              }}\n            />\n          }\n        />\n      </div>\n      <div className=\"min-h-0 flex-1 space-y-2 overflow-y-auto p-3\">\n        {messages.map((m, i) => (\n          <div\n            key={i}\n            className={`whitespace-pre-wrap rounded-xl px-2.5 py-2 ${\n              m.role === 'user'\n                ? 'ml-6 bg-[var(--we-accent-muted)] text-white'\n                : 'mr-4 bg-black-capsule text-white/80'\n            }`}\n          >\n            <TextBody as=\"p\" size=\"sm\" selectable>\n              {m.content}\n            </TextBody>\n          </div>\n        ))}\n        {!messages.length && (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n            {t.slides.chat.emptyHint(agentPlanMode)}\n          </TextBody>\n        )}\n      </div>\n      <div className=\"flex gap-2 border-t border-panel-border p-2\">\n        <input\n          value={input}\n          onChange={(e) => setInput(e.target.value)}\n          onKeyDown={(e) => {\n            if (e.key === 'Enter') void send();\n          }}\n          placeholder={t.slides.chat.inputPlaceholder}\n          className=\"min-w-0 flex-1 rounded-xl border border-panel-border bg-black-capsule px-3 py-2 font-sans text-[12px] font-medium text-white outline-none placeholder:text-white/40 focus:border-[var(--we-accent)]\"\n        />\n        <Button variant=\"accent\" size=\"md\" disabled={busy} onClick={() => void send()}>\n          {t.slides.chat.sendButton}\n        </Button>\n      </div>\n    </div>\n  );\n};\n", "import React from 'react';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { useTextStore } from '../../store/useTextStore';\nimport { useTranslation } from '../../i18n';\nimport type { SemanticRestyleMode } from '../../types/slides.types';\nimport { Button, PanelBody, PanelField, PanelSection, SelectDropdown, Switch, TextBody, TextTitle } from '../ui';\n\nconst CANVAS_PRESETS = [\n  { w: 1920, h: 1080, id: '16:9' },\n  { w: 1080, h: 1920, id: '9:16' },\n  { w: 1440, h: 1080, id: '4:3' },\n  { w: 1754, h: 1240, id: 'A4' },\n] as const;\n\n/** Theme + canvas settings \u2014 light default only (no dark/pitch presets). */\nexport const ThemePanel: React.FC = () => {\n  const t = useTranslation();\n  const tp = t.slides.themePanel;\n  const {\n    theme,\n    setDeckBackground,\n    showBaseline,\n    setShowBaseline,\n    resizeDeck,\n    size,\n    setBrandTerms,\n    applySemanticRestyle,\n  } = useSlidesStore();\n  const brandVoice = useTextStore((s) => s.brandVoice) || {\n    forbiddenTerms: [] as string[],\n    preferredTerms: [] as string[],\n  };\n\n  const restyleOptions = [\n    { value: 'board', label: tp.restyleBoard },\n    { value: 'sales', label: tp.restyleSales },\n    { value: 'internal', label: tp.restyleInternal },\n  ];\n\n  const canvasOptions = CANVAS_PRESETS.map((p) => ({\n    value: p.id,\n    label: p.id,\n  }));\n  const canvasValue =\n    CANVAS_PRESETS.find((p) => p.w === size.width && p.h === size.height)?.id ?? '16:9';\n\n  return (\n    <PanelBody>\n      <PanelSection title={tp.canvas}>\n        <PanelField\n          label={tp.canvasRatio}\n          trailing={\n            <SelectDropdown\n              value={canvasValue}\n              options={canvasOptions}\n              onChange={(id) => {\n                const p = CANVAS_PRESETS.find((x) => x.id === id);\n                if (p) resizeDeck(p.w, p.h);\n              }}\n              ariaLabel={tp.canvasRatio}\n            />\n          }\n        />\n        <PanelField\n          label={tp.baseline}\n          trailing={<Switch checked={showBaseline} onChange={setShowBaseline} />}\n        />\n      </PanelSection>\n\n      <PanelSection title={tp.semanticRestyle}>\n        <PanelField\n          label={tp.restyleMode}\n          trailing={\n            <SelectDropdown\n              value=\"board\"\n              options={restyleOptions}\n              onChange={(v) => applySemanticRestyle(v as SemanticRestyleMode)}\n              ariaLabel={tp.restyleMode}\n            />\n          }\n        />\n      </PanelSection>\n\n      <PanelSection title={tp.brandTerms}>\n        <Button\n          variant=\"secondary\"\n          size=\"sm\"\n          className=\"w-full\"\n          onClick={() =>\n            setBrandTerms(brandVoice.forbiddenTerms || [], brandVoice.preferredTerms || [])\n          }\n        >\n          {tp.importBrandTerms}\n        </Button>\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n          {tp.forbiddenLabel((brandVoice.forbiddenTerms || []).length)} \u00B7{' '}\n          {tp.preferredLabel((brandVoice.preferredTerms || []).length)}\n        </TextBody>\n      </PanelSection>\n\n      <PanelSection title={tp.colors} description={tp.colorsBackgroundOnly}>\n        <label\n          className=\"group relative flex h-16 w-full cursor-pointer overflow-hidden rounded-xl border border-panel-border\"\n          title={tp.colorBackground}\n        >\n          <span\n            className=\"absolute inset-0\"\n            style={{ backgroundColor: theme.colors.background }}\n            aria-hidden\n          />\n          <input\n            type=\"color\"\n            value={theme.colors.background}\n            onChange={(e) => setDeckBackground(e.target.value)}\n            className=\"absolute inset-0 h-full w-full cursor-pointer opacity-0\"\n            aria-label={tp.colorBackground}\n          />\n          <TextBody as=\"span\" size=\"sm\" className=\"relative mt-auto w-full truncate bg-black/55 px-2 py-1.5 text-center text-white\">\n            {tp.colorBackground}\n          </TextBody>\n        </label>\n      </PanelSection>\n    </PanelBody>\n  );\n};\n", "import React, { useMemo, useState } from 'react';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { useTranslation } from '../../i18n';\nimport { Button, PanelBody, PanelSection, TextBody, TextTitle } from '../ui';\n\nconst TEXTAREA =\n  'min-h-64 w-full resize-y rounded-xl border border-panel-border bg-black-capsule p-2.5 font-mono text-[12px] font-medium text-white outline-none placeholder:text-white/40 focus:border-[var(--we-accent)]';\n\nexport const DeckOutlinePanel: React.FC = () => {\n  const t = useTranslation();\n  const op = t.slides.deckOutlinePanel;\n  const { getOutline, applyOutline, setActiveSlideId, slides, activeSlideId } = useSlidesStore();\n  const outline = useMemo(() => getOutline(), [getOutline, slides]);\n  const [text, setText] = useState('');\n\n  const loadFromDeck = () => {\n    const lines: string[] = [];\n    for (const item of outline) {\n      lines.push(`# ${item.title}`);\n      for (const b of item.bullets) lines.push(`- ${b}`);\n      lines.push('');\n    }\n    setText(lines.join('\\n'));\n  };\n\n  const apply = () => {\n    const items: Array<{ title: string; bullets: string[] }> = [];\n    let current: { title: string; bullets: string[] } | null = null;\n    for (const raw of text.split('\\n')) {\n      const line = raw.trim();\n      if (!line) continue;\n      if (line.startsWith('#')) {\n        if (current) items.push(current);\n        current = { title: line.replace(/^#+\\s*/, ''), bullets: [] };\n      } else if (line.startsWith('-') || line.startsWith('\u2022')) {\n        if (!current) current = { title: op.defaultSection, bullets: [] };\n        current.bullets.push(line.replace(/^[-\u2022]\\s*/, ''));\n      } else if (current) {\n        current.bullets.push(line);\n      }\n    }\n    if (current) items.push(current);\n    if (items.length) applyOutline(items);\n  };\n\n  return (\n    <PanelBody className=\"h-full min-h-0 overflow-hidden\">\n      <PanelSection title={op.editorTitle} description={op.editorHint}>\n        <div className=\"flex gap-2\">\n          <Button variant=\"secondary\" size=\"sm\" className=\"flex-1\" onClick={loadFromDeck}>\n            {op.extract}\n          </Button>\n          <Button variant=\"accent\" size=\"sm\" className=\"flex-1\" onClick={apply}>\n            {op.apply}\n          </Button>\n        </div>\n        <textarea\n          value={text}\n          onChange={(e) => setText(e.target.value)}\n          placeholder={op.placeholder}\n          className={TEXTAREA}\n        />\n      </PanelSection>\n\n      <PanelSection title={op.slidesTitle} divided className=\"min-h-0 flex-1 overflow-hidden\">\n        <div className=\"flex max-h-56 flex-col gap-1 overflow-y-auto\">\n          {outline.map((item, index) => {\n            const active = item.slideId === activeSlideId;\n            return (\n              <button\n                key={item.slideId}\n                type=\"button\"\n                onClick={() => setActiveSlideId(item.slideId)}\n                className={`w-full rounded-xl px-2.5 py-2 text-left transition-colors ${\n                  active\n                    ? 'bg-[var(--we-accent-muted)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--we-accent)_35%,transparent)]'\n                    : 'bg-black-capsule hover:bg-black-capsule-hover'\n                }`}\n              >\n                <TextTitle as=\"span\" size=\"sm\" className=\"block text-white\">\n                  {index + 1}. {item.title}\n                </TextTitle>\n                <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                  {op.bulletsCount(item.bullets.length)}\n                </TextBody>\n              </button>\n            );\n          })}\n          {!outline.length && (\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{op.empty}</TextBody>\n          )}\n        </div>\n      </PanelSection>\n    </PanelBody>\n  );\n};\n", "import React from 'react';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport type { ElementBuild } from '../../types/slides.types';\nimport type { TextAnimationPreset } from '../../store/useVideoStore';\nimport { useTranslation } from '../../i18n';\nimport { Button, PanelBody, PanelField, PanelSection, SelectDropdown, TextBody, TextTitle } from '../ui';\n\nconst PRESETS: TextAnimationPreset[] = [\n  'fade',\n  'fade-up',\n  'slide-left',\n  'scale-in',\n  'bounce-in',\n  'blur-in',\n];\n\nconst TRANSITIONS = [\n  'cut',\n  'cross-dissolve',\n  'fade-black',\n  'slide-left',\n  'slide-right',\n  'push-left',\n  'zoom-in',\n  'blur-dissolve',\n  'morph-cut',\n] as const;\n\nexport const BuildsPanel: React.FC = () => {\n  const t = useTranslation();\n  const bp = t.slides.buildsPanel;\n  const { slides, activeSlideId, selectedObjectIds, setSlideBuilds, setSlideTransition } =\n    useSlidesStore();\n  const slide = slides.find((s) => s.id === activeSlideId);\n  if (!slide) {\n    return (\n      <TextBody as=\"p\" size=\"sm\" className=\"p-3 text-white/80\">\n        {t.slides.notesPanel.noActiveSlide}\n      </TextBody>\n    );\n  }\n\n  const addBuild = () => {\n    const objectId = selectedObjectIds[0];\n    if (!objectId) return;\n    const build: ElementBuild = {\n      objectId,\n      order: slide.builds.length,\n      trigger: 'click',\n      animation: 'fade-up',\n      durationMs: 400,\n      delayMs: 0,\n    };\n    setSlideBuilds(slide.id, [...slide.builds, build]);\n  };\n\n  const transitionOptions = TRANSITIONS.map((tr) => ({\n    value: tr,\n    label: bp.transitionLabels?.[tr] ?? tr,\n  }));\n\n  const presetOptions = PRESETS.map((p) => ({\n    value: p,\n    label: bp.presetLabels?.[p] ?? p,\n  }));\n\n  return (\n    <PanelBody className=\"h-full overflow-y-auto\">\n      <PanelSection title={bp.transitionLabel}>\n        <PanelField\n          label={bp.transitionLabel}\n          trailing={\n            <SelectDropdown\n              value={slide.transition.type}\n              options={transitionOptions}\n              onChange={(v) =>\n                setSlideTransition(slide.id, {\n                  ...slide.transition,\n                  type: v as typeof slide.transition.type,\n                })\n              }\n              ariaLabel={bp.transitionLabel}\n            />\n          }\n        />\n        <PanelField\n          label={bp.durationLabel}\n          variant=\"slide\"\n          min={0}\n          max={5}\n          step={0.1}\n          numericValue={slide.transition.duration}\n          onChange={(n) =>\n            setSlideTransition(slide.id, {\n              ...slide.transition,\n              duration: n,\n            })\n          }\n        />\n      </PanelSection>\n\n      <PanelSection\n        title={bp.buildsHeader(slide.builds.length)}\n        divided\n        trailing={\n          <Button\n            variant=\"accent\"\n            size=\"xs\"\n            disabled={!selectedObjectIds.length}\n            onClick={addBuild}\n          >\n            {bp.addToSelected}\n          </Button>\n        }\n      >\n        {!slide.builds.length ? (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n            {bp.empty}\n          </TextBody>\n        ) : (\n          <div className=\"flex flex-col gap-2\">\n            {slide.builds.map((b, i) => (\n              <div\n                key={`${b.objectId}-${i}`}\n                className=\"flex flex-col gap-1.5 rounded-xl border border-panel-border bg-black-capsule p-2.5\"\n              >\n                <TextBody as=\"p\" size=\"sm\" className=\"truncate text-white/80\">\n                  {bp.objectLabel(b.objectId)}\n                </TextBody>\n                <SelectDropdown\n                  value={b.animation}\n                  options={presetOptions}\n                  onChange={(v) => {\n                    const next = [...slide.builds];\n                    next[i] = { ...b, animation: v as TextAnimationPreset };\n                    setSlideBuilds(slide.id, next);\n                  }}\n                  ariaLabel={bp.animationLabel}\n                  className=\"w-full\"\n                />\n                <SelectDropdown\n                  value={b.trigger}\n                  options={[\n                    { value: 'click', label: bp.triggerClick },\n                    { value: 'with-previous', label: bp.triggerWithPrevious },\n                    { value: 'after-previous', label: bp.triggerAfterPrevious },\n                  ]}\n                  onChange={(v) => {\n                    const next = [...slide.builds];\n                    next[i] = { ...b, trigger: v as ElementBuild['trigger'] };\n                    setSlideBuilds(slide.id, next);\n                  }}\n                  ariaLabel={bp.triggerLabel}\n                  className=\"w-full\"\n                />\n                <Button\n                  variant=\"ghost\"\n                  size=\"xs\"\n                  className=\"self-start text-red-400\"\n                  onClick={() =>\n                    setSlideBuilds(\n                      slide.id,\n                      slide.builds.filter((_, j) => j !== i),\n                    )\n                  }\n                >\n                  {bp.remove}\n                </Button>\n              </div>\n            ))}\n          </div>\n        )}\n      </PanelSection>\n    </PanelBody>\n  );\n};\n", "import React, { useState } from 'react';\nimport { Check, Trash2 } from 'lucide-react';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { useLocale, useTranslation } from '../../i18n';\nimport { Button, PanelBody, PanelSection, TextBody, TextTitle } from '../ui';\n\nfunction formatCommentTime(ts: number, locale: string): string {\n  try {\n    return new Intl.DateTimeFormat(locale, {\n      day: '2-digit',\n      month: 'short',\n      hour: '2-digit',\n      minute: '2-digit',\n    }).format(ts);\n  } catch {\n    return '';\n  }\n}\n\nexport const CommentsPanel: React.FC = () => {\n  const t = useTranslation();\n  const locale = useLocale();\n  const cp = t.slides.commentsPanel;\n  const { slides, activeSlideId, addComment, resolveComment, removeComment } = useSlidesStore();\n  const slide = slides.find((s) => s.id === activeSlideId);\n  const [note, setNote] = useState('');\n\n  if (!slide) {\n    return (\n      <PanelBody className=\"h-full overflow-y-auto\">\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n          {cp.noActiveSlide}\n        </TextBody>\n      </PanelBody>\n    );\n  }\n\n  const submit = () => {\n    const value = note.trim();\n    if (!value) return;\n    addComment(slide.id, value);\n    setNote('');\n  };\n\n  return (\n    <PanelBody className=\"h-full overflow-y-auto\">\n      <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{cp.hint}</TextBody>\n\n      <PanelSection>\n        <textarea\n          value={note}\n          onChange={(e) => setNote(e.target.value)}\n          onKeyDown={(e) => {\n            if (e.key === 'Enter' && !e.shiftKey) {\n              e.preventDefault();\n              submit();\n            }\n          }}\n          placeholder={cp.inputPlaceholder}\n          rows={3}\n          className=\"w-full resize-none rounded-xl border border-panel-border bg-black-capsule px-3 py-2 font-sans text-[12px] font-medium text-white outline-none placeholder:text-white/40 focus:border-[var(--we-accent)]\"\n        />\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{cp.enterHint}</TextBody>\n        <Button\n          variant=\"accent\"\n          size=\"md\"\n          className=\"h-9 w-full shrink-0\"\n          disabled={!note.trim()}\n          onClick={submit}\n        >\n          {cp.add}\n        </Button>\n      </PanelSection>\n\n      <PanelSection title={cp.listTitle(slide.comments.length)}>\n        {!slide.comments.length ? (\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{cp.empty}</TextBody>\n        ) : (\n          <div className=\"flex flex-col gap-2\">\n            {slide.comments.map((c) => (\n              <article\n                key={c.id}\n                className={`rounded-xl border p-3 ${\n                  c.resolved\n                    ? 'border-panel-border bg-black-capsule/50 opacity-70'\n                    : 'border-panel-border bg-black-capsule'\n                }`}\n              >\n                <div className=\"flex flex-wrap items-center gap-1.5\">\n                  {c.resolved ? (\n                    <TextBody as=\"span\" size=\"sm\" className=\"inline-flex items-center gap-1 rounded-md bg-emerald-500/15 px-1.5 py-0.5 text-emerald-300\">\n                      <Check size={11} aria-hidden />\n                      {cp.resolved}\n                    </TextBody>\n                  ) : (\n                    <TextBody as=\"span\" size=\"sm\" className=\"inline-flex rounded-md bg-[var(--we-accent-muted)] px-1.5 py-0.5 text-[var(--we-accent)]\">\n                      {cp.open}\n                    </TextBody>\n                  )}\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                    {formatCommentTime(c.createdAt, locale)}\n                  </TextBody>\n                </div>\n\n                <TextBody as=\"p\" size=\"sm\" className=\"mt-2 leading-snug text-white\">\n                  {c.note}\n                </TextBody>\n\n                {c.quote && (\n                  <TextBody as=\"p\" size=\"sm\" className=\"mt-1.5 border-l-2 border-[var(--we-accent)] pl-2 italic text-white/80\">\n                    {c.quote}\n                  </TextBody>\n                )}\n\n                <div className=\"mt-2.5 flex flex-wrap gap-1.5\">\n                  {!c.resolved && (\n                    <Button\n                      variant=\"secondary\"\n                      size=\"xs\"\n                      className=\"h-7 gap-1 px-2\"\n                      icon={<Check size={12} />}\n                      onClick={() => resolveComment(slide.id, c.id)}\n                    >\n                      {cp.resolve}\n                    </Button>\n                  )}\n                  <Button\n                    variant=\"ghost\"\n                    size=\"xs\"\n                    className=\"h-7 gap-1 px-2 text-red-300 hover:text-red-200\"\n                    icon={<Trash2 size={12} />}\n                    onClick={() => removeComment(slide.id, c.id)}\n                  >\n                    {cp.remove}\n                  </Button>\n                </div>\n              </article>\n            ))}\n          </div>\n        )}\n      </PanelSection>\n    </PanelBody>\n  );\n};\n", "import React, { useState } from 'react';\nimport {\n  AlertTriangle,\n  ChevronLeft,\n  CircleAlert,\n  Info,\n  LayoutTemplate,\n  ListChecks,\n  MessageCircleQuestion,\n  ScanSearch,\n  SplitSquareVertical,\n  Type,\n  Contrast,\n  Accessibility,\n  Wrench,\n} from 'lucide-react';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { useSlidesUiStore } from '../../store/useSlidesUiStore';\nimport { designCritique, qaPrep } from '../../services/slides/deckService';\nimport { useTextStore } from '../../store/useTextStore';\nimport { auditSlideContrast } from '../../lib/slides/a11y';\nimport { useTranslation } from '../../i18n';\nimport { Button, PanelBody, PanelSection, TextBody, TextTitle } from '../ui';\n\ntype ToolId =\n  | 'audit'\n  | 'qa'\n  | 'condense'\n  | 'contrast'\n  | 'autofit'\n  | 'magicLayout'\n  | 'split'\n  | 'alt';\n\ntype ToolDef = {\n  id: ToolId;\n  icon: React.ReactNode;\n};\n\nconst ALL_TOOLS: ToolDef[] = [\n  { id: 'audit', icon: <ScanSearch size={16} /> },\n  { id: 'qa', icon: <MessageCircleQuestion size={16} /> },\n  { id: 'condense', icon: <Type size={16} /> },\n  { id: 'contrast', icon: <Contrast size={16} /> },\n  { id: 'autofit', icon: <ListChecks size={16} /> },\n  { id: 'magicLayout', icon: <LayoutTemplate size={16} /> },\n  { id: 'split', icon: <SplitSquareVertical size={16} /> },\n  { id: 'alt', icon: <Accessibility size={16} /> },\n];\n\ntype CriticIssue = {\n  severity: string;\n  slideIndex?: number;\n  slideId?: string;\n  message: string;\n  fix?: string;\n};\n\nfunction ToolRow({\n  tool,\n  name,\n  description,\n  onClick,\n}: {\n  tool: ToolDef;\n  name: string;\n  description: string;\n  onClick: () => void;\n}) {\n  return (\n    <button\n      type=\"button\"\n      onClick={onClick}\n      className=\"relative flex w-full cursor-pointer items-start gap-2.5 overflow-hidden rounded-xl border border-transparent bg-black-capsule px-2.5 py-2.5 text-left transition-colors hover:border-[color-mix(in_srgb,var(--we-accent)_35%,transparent)] hover:bg-[var(--we-accent-muted)] active:scale-[0.99]\"\n    >\n      <span className=\"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-[var(--we-accent)] text-white\">\n        {tool.icon}\n      </span>\n      <span className=\"min-w-0 flex-1\">\n        <TextTitle as=\"span\" size=\"sm\" className=\"block text-white\">\n          {name}\n        </TextTitle>\n        <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 block text-pretty leading-snug text-white/80\">\n          {description}\n        </TextBody>\n      </span>\n    </button>\n  );\n}\n\nfunction severityMeta(\n  severity: string,\n  labels: { error: string; warn: string; info: string }\n): { label: string; Icon: typeof Info; card: string; badge: string } {\n  if (severity === 'error') {\n    return {\n      label: labels.error,\n      Icon: CircleAlert,\n      card: 'border-red-500/35 bg-red-500/10',\n      badge: 'bg-red-500/20 text-red-200',\n    };\n  }\n  if (severity === 'warn') {\n    return {\n      label: labels.warn,\n      Icon: AlertTriangle,\n      card: 'border-amber-500/35 bg-amber-500/10',\n      badge: 'bg-amber-500/20 text-amber-100',\n    };\n  }\n  return {\n    label: labels.info,\n    Icon: Info,\n    card: 'border-panel-border bg-black-capsule',\n    badge: 'bg-white/10 text-white/80',\n  };\n}\n\nexport const DesignCriticPanel: React.FC = () => {\n  const t = useTranslation();\n  const dc = t.slides.designCriticPanel;\n  const {\n    addToast,\n    getOutline,\n    slides,\n    theme,\n    applyDesignFix,\n    applyMagicLayout,\n    splitDenseSlide,\n    forbiddenTerms,\n  } = useSlidesStore();\n  const textForbidden = useTextStore((s) => s.brandVoice?.forbiddenTerms || []);\n  const forbidden = forbiddenTerms.length ? forbiddenTerms : textForbidden;\n\n  const issues = useSlidesUiStore((s) => s.critiqueIssues);\n  const score = useSlidesUiStore((s) => s.critiqueScore);\n  const minutes = useSlidesUiStore((s) => s.critiqueMinutes);\n  const questions = useSlidesUiStore((s) => s.critiqueQuestions);\n  const setCritiqueResult = useSlidesUiStore((s) => s.setCritiqueResult);\n  const setCritiqueQuestions = useSlidesUiStore((s) => s.setCritiqueQuestions);\n\n  const [tab, setTab] = useState<ToolId | null>(null);\n  const [busy, setBusy] = useState(false);\n\n  const activeTool = ALL_TOOLS.find((x) => x.id === tab);\n\n  const toolName = (id: ToolId) => dc.tools[id];\n  const toolDesc = (id: ToolId) => dc.tools[`${id}Desc` as keyof typeof dc.tools];\n\n  const runAudit = async () => {\n    if (busy) return;\n    setBusy(true);\n    try {\n      const outline = getOutline();\n      const localIssues: CriticIssue[] = [];\n      outline.forEach((o, i) => {\n        const slide = slides.find((s) => s.id === o.slideId);\n        const words = [o.title, ...o.bullets].join(' ').split(/\\s+/).filter(Boolean).length;\n        if (words > 80) {\n          localIssues.push({\n            severity: 'warn',\n            slideIndex: i,\n            slideId: o.slideId,\n            message: `Demasiado texto (${words} palabras). Regla 6x6.`,\n            fix: 'split',\n          });\n        }\n        for (const term of forbidden) {\n          const hay = `${o.title} ${o.bullets.join(' ')}`.toLowerCase();\n          if (term && hay.includes(term.toLowerCase())) {\n            localIssues.push({\n              severity: 'error',\n              slideIndex: i,\n              slideId: o.slideId,\n              message: `Termino prohibido de marca: \"${term}\"`,\n            });\n          }\n        }\n        if (slide) {\n          localIssues.push(\n            ...auditSlideContrast(i, slide.json, theme.colors.background).map((x) => ({\n              ...x,\n              slideId: o.slideId,\n              fix: 'contrast',\n            }))\n          );\n        }\n      });\n\n      const res = await designCritique({\n        slides: outline.map((o) => ({\n          title: o.title,\n          body: o.bullets.join('\\n'),\n          wordCount: [o.title, ...o.bullets].join(' ').split(/\\s+/).filter(Boolean).length,\n        })),\n      });\n      setCritiqueResult({\n        score: res.score,\n        minutes: res.estimatedMinutes,\n        issues: [\n          ...localIssues,\n          ...res.issues.map((iss) => ({\n            ...iss,\n            slideId: iss.slideIndex != null ? outline[iss.slideIndex]?.slideId : undefined,\n          })),\n        ],\n      });\n      addToast(dc.auditDone, 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : 'Error', 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const runQa = async () => {\n    if (busy) return;\n    setBusy(true);\n    try {\n      const outline = getOutline();\n      const res = await qaPrep({\n        slides: outline.map((o) => ({ title: o.title, body: o.bullets.join('\\n') })),\n      });\n      setCritiqueQuestions(res.questions);\n      addToast(dc.qaReady, 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : 'Error', 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const applyFix = (fix?: string, slideId?: string) => {\n    if (fix === 'contrast') applyDesignFix('fix-contrast', slideId);\n    else if (fix === 'split') splitDenseSlide(slideId);\n    else if (fix === 'autofit') applyDesignFix('autofit', slideId);\n    else if (fix === 'condense') applyDesignFix('condense-text', slideId);\n    else if (fix === 'layout') void applyMagicLayout(slideId);\n    else if (fix === 'alt') applyDesignFix('ensure-alt', slideId);\n  };\n\n  const runQuickFix = (id: ToolId) => {\n    if (id === 'condense') applyDesignFix('condense-text');\n    else if (id === 'contrast') applyDesignFix('fix-contrast');\n    else if (id === 'autofit') applyDesignFix('autofit');\n    else if (id === 'magicLayout') void applyMagicLayout();\n    else if (id === 'split') splitDenseSlide();\n    else if (id === 'alt') applyDesignFix('ensure-alt');\n    addToast(dc.fixApplied, 'success');\n  };\n\n  const severityLabels = {\n    error: dc.severityError,\n    warn: dc.severityWarn,\n    info: dc.severityInfo,\n  };\n\n  if (!tab) {\n    return (\n      <PanelBody className=\"h-full overflow-y-auto\">\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{dc.hint}</TextBody>\n        <PanelSection title={dc.toolsHeader}>\n          <div className=\"flex flex-col gap-1.5\">\n            {ALL_TOOLS.map((tool) => (\n              <ToolRow\n                key={tool.id}\n                tool={tool}\n                name={toolName(tool.id)}\n                description={String(toolDesc(tool.id))}\n                onClick={() => setTab(tool.id)}\n              />\n            ))}\n          </div>\n        </PanelSection>\n      </PanelBody>\n    );\n  }\n\n  const isQuickFix =\n    tab === 'condense' ||\n    tab === 'contrast' ||\n    tab === 'autofit' ||\n    tab === 'magicLayout' ||\n    tab === 'split' ||\n    tab === 'alt';\n\n  return (\n    <PanelBody className=\"h-full overflow-y-auto\">\n      <button\n        type=\"button\"\n        onClick={() => setTab(null)}\n        className=\"mb-1 inline-flex items-center gap-1 text-white/80 hover:text-white\"\n      ><ChevronLeft size={14} /> <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">{dc.backToList}</TextBody></button>\n      <TextTitle as=\"h3\" size=\"sm\" className=\"text-white\">\n        {activeTool ? toolName(activeTool.id) : ''}\n      </TextTitle>\n      <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n        {activeTool ? String(toolDesc(activeTool.id)) : ''}\n      </TextBody>\n\n      {tab === 'audit' && (\n        <PanelSection>\n          <Button\n            variant=\"accent\"\n            size=\"md\"\n            className=\"h-9 w-full shrink-0\"\n            loading={busy}\n            onClick={() => void runAudit()}\n          >\n            {busy ? dc.generating : dc.runAudit}\n          </Button>\n          {(score !== null || minutes !== null) && (\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {dc.scoreLine(score, minutes, slides.length)}\n            </TextBody>\n          )}\n          <div className=\"flex flex-col gap-2\">\n            {issues.map((iss, i) => {\n              const meta = severityMeta(iss.severity, severityLabels);\n              const Icon = meta.Icon;\n              return (\n                <article key={i} className={`rounded-xl border p-3 ${meta.card}`}>\n                  <div className=\"flex flex-wrap items-center gap-1.5\">\n                    <span\n                      className={`inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 ${meta.badge}`}\n                    >\n                      <Icon size={11} aria-hidden />\n                      {meta.label}\n                    </span>\n                    {iss.slideIndex !== undefined && (\n                      <TextBody as=\"span\" size=\"sm\" className=\"rounded-md bg-black/30 px-1.5 py-0.5 text-white/80\">\n                        {dc.slidePrefix(iss.slideIndex)}\n                      </TextBody>\n                    )}\n                  </div>\n                  <TextBody as=\"p\" size=\"sm\" className=\"mt-2 leading-snug text-white\">\n                    {iss.message}\n                  </TextBody>\n                  {iss.fix && (\n                    <Button\n                      variant=\"ghost\"\n                      size=\"xs\"\n                      className=\"mt-2 h-7 gap-1 px-2 text-[var(--we-accent)]\"\n                      icon={<Wrench size={12} />}\n                      onClick={() => applyFix(iss.fix, iss.slideId)}\n                    >\n                      {dc.applyFix}\n                    </Button>\n                  )}\n                </article>\n              );\n            })}\n          </div>\n        </PanelSection>\n      )}\n\n      {tab === 'qa' && (\n        <PanelSection>\n          <Button\n            variant=\"accent\"\n            size=\"md\"\n            className=\"h-9 w-full shrink-0\"\n            loading={busy}\n            onClick={() => void runQa()}\n          >\n            {busy ? dc.generating : dc.runQa}\n          </Button>\n          <div className=\"flex flex-col gap-2\">\n            {questions.map((q, i) => (\n              <article\n                key={i}\n                className=\"rounded-xl border border-panel-border bg-black-capsule p-3\"\n              >\n                <TextTitle as=\"p\" size=\"sm\" className=\"text-white\">\n                  {dc.slidePrefix(q.slideIndex)}\n                </TextTitle>\n                <TextBody as=\"p\" size=\"sm\" className=\"mt-1 leading-snug text-white\">\n                  {q.question}\n                </TextBody>\n                {q.tip && (\n                  <TextBody as=\"p\" size=\"sm\" className=\"mt-1.5 text-white/80\">\n                    {q.tip}\n                  </TextBody>\n                )}\n              </article>\n            ))}\n          </div>\n        </PanelSection>\n      )}\n\n      {isQuickFix && (\n        <PanelSection>\n          <Button\n            variant=\"accent\"\n            size=\"md\"\n            className=\"h-9 w-full shrink-0\"\n            onClick={() => runQuickFix(tab)}\n          >\n            {dc.applyFix}\n          </Button>\n        </PanelSection>\n      )}\n    </PanelBody>\n  );\n};\n", "import React, { useMemo, useState } from 'react';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { useSlidesUiStore } from '../../store/useSlidesUiStore';\nimport { speakerCoach } from '../../services/slides/deckService';\nimport { useTranslation } from '../../i18n';\nimport { Button, PanelBody, TextBody, TextTitle } from '../ui';\n\nexport const CoachPanel: React.FC = () => {\n  const t = useTranslation();\n  const coach = t.slides.coachPanel;\n  const { getOutline, slides, rehearsalTimes, clearRehearsalTimes, setSlideNotes, addToast } =\n    useSlidesStore();\n  const summary = useSlidesUiStore((s) => s.coachSummary);\n  const tips = useSlidesUiStore((s) => s.coachTips);\n  const setCoachResult = useSlidesUiStore((s) => s.setCoachResult);\n  const [busy, setBusy] = useState(false);\n\n  const rehearsalSummary = useMemo(() => {\n    const entries = Object.entries(rehearsalTimes);\n    if (!entries.length) return null;\n    const total = entries.reduce((a, [, s]) => a + s, 0);\n    const avg = total / entries.length;\n    return { total, avg, count: entries.length };\n  }, [rehearsalTimes]);\n\n  const run = async () => {\n    if (busy) return;\n    setBusy(true);\n    try {\n      const outline = getOutline();\n      const res = await speakerCoach({\n        slides: outline.map((o) => ({\n          title: o.title,\n          body: o.bullets.join('\\n'),\n          notes: slides.find((s) => s.id === o.slideId)?.notes ?? '',\n          rehearsalSeconds: rehearsalTimes[o.slideId || ''] ?? 0,\n        })),\n      });\n      setCoachResult(res.summary, res.tips);\n      addToast(coach.done, 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : 'Error', 'error');\n    } finally {\n      setBusy(false);\n    }\n  };\n\n  const applyTipsToNotes = () => {\n    if (!tips.length) return;\n    const outline = getOutline();\n    let applied = 0;\n    tips.forEach((tip) => {\n      const slideId = outline[tip.slideIndex]?.slideId;\n      if (!slideId || !tip.tip.trim()) return;\n      const current = useSlidesStore.getState().slides.find((s) => s.id === slideId);\n      const existing = (current?.notes || '').trim();\n      const pacing =\n        tip.pacingSeconds != null ? coach.pacingSeconds(tip.pacingSeconds).replace(/^ \u00B7 /, '') : '';\n      const block = pacing ? `${tip.tip.trim()} (${pacing})` : tip.tip.trim();\n      if (existing.includes(tip.tip.trim())) {\n        applied += 1;\n        return;\n      }\n      setSlideNotes(slideId, existing ? `${existing}\\n\\n${block}` : block);\n      applied += 1;\n    });\n    if (applied > 0) addToast(coach.appliedToNotes(applied), 'success');\n  };\n\n  return (\n    <PanelBody className=\"h-full overflow-y-auto\">\n      <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{coach.intro}</TextBody>\n      {rehearsalSummary && (\n        <TextBody as=\"div\" size=\"sm\" className=\"rounded-xl border border-panel-border bg-black-capsule p-2.5 text-white/80\">\n          {coach.rehearsalSummary(rehearsalSummary.count, rehearsalSummary.total, rehearsalSummary.avg)}\n          <button\n            type=\"button\"\n            onClick={() => clearRehearsalTimes()}\n            className=\"mt-1 block text-[var(--we-accent)] hover:underline\"\n          >\n            <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n              {coach.clearTimings}\n            </TextBody>\n          </button>\n        </TextBody>\n      )}\n      <Button\n        variant=\"accent\"\n        size=\"md\"\n        className=\"h-9 w-full shrink-0\"\n        loading={busy}\n        onClick={() => void run()}\n      >\n        {busy ? t.slides.ai.generating : coach.run}\n      </Button>\n      {tips.length > 0 && (\n        <Button\n          variant=\"secondary\"\n          size=\"md\"\n          className=\"h-9 w-full shrink-0\"\n          disabled={busy}\n          onClick={applyTipsToNotes}\n        >\n          {coach.applyToNotes}\n        </Button>\n      )}\n      {summary && (\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white\">{summary}</TextBody>\n      )}\n      <div className=\"flex flex-col gap-2\">\n        {tips.map((tip, i) => (\n          <TextBody as=\"div\" size=\"sm\" className=\"rounded-xl border border-panel-border bg-black-capsule p-2.5 text-white/80\" key={i}>\n            <TextTitle as=\"p\" size=\"sm\" className=\"text-white\">\n              {coach.slideLabel(tip.slideIndex)}\n              {tip.pacingSeconds != null ? coach.pacingSeconds(tip.pacingSeconds) : ''}\n            </TextTitle>\n            <TextBody as=\"p\" size=\"sm\" className=\"mt-1 text-white/80\">\n              {tip.tip}\n            </TextBody>\n          </TextBody>\n        ))}\n      </div>\n    </PanelBody>\n  );\n};\n", "/** Align / distribute helpers for Fabric-like objects with left/top/width/height. */\n\nexport interface Box {\n  left: number;\n  top: number;\n  width: number;\n  height: number;\n  [key: string]: unknown;\n}\n\nexport type AlignEdge =\n  | 'left'\n  | 'center'\n  | 'right'\n  | 'top'\n  | 'middle'\n  | 'bottom';\n\nexport function alignObjects(objects: Box[], edge: AlignEdge): Box[] {\n  if (objects.length < 2) return objects;\n  const minL = Math.min(...objects.map((o) => o.left));\n  const maxR = Math.max(...objects.map((o) => o.left + o.width));\n  const minT = Math.min(...objects.map((o) => o.top));\n  const maxB = Math.max(...objects.map((o) => o.top + o.height));\n  const cx = (minL + maxR) / 2;\n  const cy = (minT + maxB) / 2;\n\n  return objects.map((o) => {\n    const next = { ...o };\n    switch (edge) {\n      case 'left':\n        next.left = minL;\n        break;\n      case 'right':\n        next.left = maxR - o.width;\n        break;\n      case 'center':\n        next.left = cx - o.width / 2;\n        break;\n      case 'top':\n        next.top = minT;\n        break;\n      case 'bottom':\n        next.top = maxB - o.height;\n        break;\n      case 'middle':\n        next.top = cy - o.height / 2;\n        break;\n    }\n    return next;\n  });\n}\n\nexport function distributeObjects(objects: Box[], axis: 'horizontal' | 'vertical'): Box[] {\n  if (objects.length < 3) return objects;\n  const sorted = [...objects].sort((a, b) =>\n    axis === 'horizontal' ? a.left - b.left : a.top - b.top\n  );\n  const first = sorted[0]!;\n  const last = sorted[sorted.length - 1]!;\n  if (axis === 'horizontal') {\n    const totalW = sorted.reduce((s, o) => s + o.width, 0);\n    const span = last.left + last.width - first.left;\n    const gap = (span - totalW) / (sorted.length - 1);\n    let x = first.left;\n    return sorted.map((o) => {\n      const next = { ...o, left: x };\n      x += o.width + gap;\n      return next;\n    });\n  }\n  const totalH = sorted.reduce((s, o) => s + o.height, 0);\n  const span = last.top + last.height - first.top;\n  const gap = (span - totalH) / (sorted.length - 1);\n  let y = first.top;\n  return sorted.map((o) => {\n    const next = { ...o, top: y };\n    y += o.height + gap;\n    return next;\n  });\n}\n\nexport function equalizeSize(objects: Box[], mode: 'width' | 'height' | 'both'): Box[] {\n  if (!objects.length) return objects;\n  const avgW = objects.reduce((s, o) => s + o.width, 0) / objects.length;\n  const avgH = objects.reduce((s, o) => s + o.height, 0) / objects.length;\n  return objects.map((o) => ({\n    ...o,\n    width: mode === 'height' ? o.width : avgW,\n    height: mode === 'width' ? o.height : avgH,\n  }));\n}\n", "import React, { useEffect, useRef, useCallback, useState } from 'react';\nimport { Canvas, Textbox, Rect, Circle, FabricImage, ActiveSelection, type FabricObject } from 'fabric';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { useSlidesUiStore } from '../../store/useSlidesUiStore';\nimport { autofitTextbox, markOverflow } from '../../lib/slides/autofit';\nimport { alignObjects, distributeObjects, type Box } from '../../lib/slides/align';\nimport { useTranslation } from '../../i18n';\nimport { useDialog } from '../DialogModal';\nimport { rebindCanvasImageAssets, stampImageAssetId } from '../../lib/slides/mediaAssets';\n\nconst CUSTOM_PROPS = [\n  'id',\n  'placeholderRole',\n  'themeRole',\n  'morphSourceId',\n  'assetId',\n  'overflow',\n  'name',\n  'alt',\n  'chartData',\n];\n\nfunction uid(prefix = 'obj'): string {\n  return `${prefix}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/** Blob/data URLs must not set crossOrigin or Fabric fails to decode. */\nasync function loadFabricImage(url: string): Promise<FabricImage> {\n  const isLocal = url.startsWith('blob:') || url.startsWith('data:');\n  if (isLocal) return FabricImage.fromURL(url);\n  return FabricImage.fromURL(url, { crossOrigin: 'anonymous' });\n}\n\nexport const SlideCanvas: React.FC = () => {\n  const t = useTranslation();\n  const dialog = useDialog();\n  const containerRef = useRef<HTMLDivElement>(null);\n  const canvasElRef = useRef<HTMLCanvasElement | null>(null);\n  const fabricRef = useRef<Canvas | null>(null);\n  const skipSaveRef = useRef(false);\n\n  const {\n    size,\n    theme,\n    activeSlideId,\n    slides,\n    canvasReloadEpoch,\n    showGrid,\n    showBaseline,\n    snapSettings,\n    forbiddenTerms,\n    preferredTerms,\n    updateSlideJson,\n    setSelectedObjectIds,\n    insertChart,\n    addToast,\n  } = useSlidesStore();\n\n  const sizeRef = useRef(size);\n  const snapSettingsRef = useRef(snapSettings);\n  const activeGuidesRef = useRef<{ x: number[]; y: number[] }>({ x: [], y: [] });\n  const activeSlideIdRef = useRef(activeSlideId);\n  const skipReloadRef = useRef(false);\n  /** historyIndex from our canvas persist \u2014 skip reload only for that exact index. */\n  const persistedHistoryIndexRef = useRef<number | null>(null);\n  /** Last canvasReloadEpoch we loaded \u2014 always reload when store bumps it (AI tools). */\n  const loadedReloadEpochRef = useRef(0);\n  sizeRef.current = size;\n  snapSettingsRef.current = snapSettings;\n  activeSlideIdRef.current = activeSlideId;\n\n  const scrollHostRef = useRef<HTMLDivElement>(null);\n  const [fitScale, setFitScale] = useState(1);\n  const fitScaleRef = useRef(1);\n  fitScaleRef.current = fitScale;\n\n  const activeSlide = slides.find((s) => s.id === activeSlideId);\n\n  const persist = useCallback(() => {\n    const canvas = fabricRef.current;\n    const id = activeSlideIdRef.current;\n    if (!canvas || !id || skipSaveRef.current) return;\n    const json = (canvas as unknown as { toObject: (props?: string[]) => unknown }).toObject(CUSTOM_PROPS);\n    let thumbnail: string | undefined;\n    try {\n      const mult = Math.min(1, 320 / Math.max(1, sizeRef.current.width));\n      thumbnail = canvas.toDataURL({\n        format: 'jpeg',\n        quality: 0.45,\n        multiplier: mult,\n      });\n    } catch {\n      thumbnail = undefined;\n    }\n    // Avoid reload flicker only when THIS historyIndex came from our persist.\n    // AI tools also bump historyIndex \u2014 those must reload or the canvas keeps\n    // stale objects and later persist() overwrites the AI result.\n    skipReloadRef.current = true;\n    updateSlideJson(id, json, true, thumbnail);\n    const after = useSlidesStore.getState().slides.find((s) => s.id === id);\n    persistedHistoryIndexRef.current =\n      typeof after?.historyIndex === 'number' ? after.historyIndex : null;\n  }, [updateSlideJson]);\n\n  const persistRef = useRef(persist);\n  persistRef.current = persist;\n\n  // Init canvas \u2014 mount Fabric imperatively to avoid React reconciliation\n  // conflicts with Fabric's DOM mutations (it wraps our canvas in its own\n  // container div on init, which breaks React's expected sibling tree).\n  useEffect(() => {\n    if (!containerRef.current) return;\n    const lower = document.createElement('canvas');\n    containerRef.current.appendChild(lower);\n    canvasElRef.current = lower;\n    const canvas = new Canvas(lower, {\n      width: size.width,\n      height: size.height,\n      preserveObjectStacking: true,\n      // Always start with the theme background; the theme-sync effect below\n      // will keep it in sync whenever the theme changes.\n      backgroundColor: theme.colors.background,\n    });\n    canvas.setZoom(1);\n    fabricRef.current = canvas;\n\n    const openContextMenu = (e: Event, target?: FabricObject | null) => {\n      const me = e as MouseEvent;\n      me.preventDefault();\n      me.stopPropagation();\n      if (target) {\n        if (canvas.getActiveObject() !== target) {\n          canvas.setActiveObject(target);\n          canvas.requestRenderAll();\n        }\n        const ids = canvas\n          .getActiveObjects()\n          .map((o) => String((o as FabricObject & { id?: string }).id || ''))\n          .filter(Boolean);\n        setSelectedObjectIds(ids);\n        window.dispatchEvent(\n          new CustomEvent('slides-selection', { detail: { count: ids.length, ids } }),\n        );\n      }\n      useSlidesUiStore.getState().setContextMenu({ x: me.clientX, y: me.clientY });\n    };\n\n    canvas.on('contextmenu', (opt) => {\n      openContextMenu(opt.e, opt.target ?? null);\n    });\n    // Fallback: some environments only surface button=2 on mouse:down.\n    canvas.on('mouse:down', (opt) => {\n      const e = opt.e as MouseEvent;\n      if (e.button !== 2) return;\n      openContextMenu(e, opt.target ?? null);\n    });\n\n    const onModified = () => {\n      activeGuidesRef.current = { x: [], y: [] };\n      persistRef.current();\n      window.dispatchEvent(new CustomEvent('slides-selection-moved'));\n    };\n    const onSelection = () => {\n      const active = canvas.getActiveObjects();\n      const ids = active.map((o) => String((o as FabricObject & { id?: string }).id || '')).filter(Boolean);\n      setSelectedObjectIds(ids);\n      window.dispatchEvent(new CustomEvent('slides-selection', { detail: { count: active.length, ids } }));\n    };\n    const onClear = () => {\n      setSelectedObjectIds([]);\n      window.dispatchEvent(new CustomEvent('slides-selection', { detail: { count: 0, ids: [] } }));\n    };\n    canvas.on('object:modified', onModified);\n    canvas.on('selection:created', onSelection);\n    canvas.on('selection:updated', onSelection);\n    canvas.on('selection:cleared', onClear);\n\n    // Smart guides + per-target snap (shapes / images / text / canvas edges)\n    const classify = (o: FabricObject): 'shape' | 'image' | 'text' | 'ignore' => {\n      const t = String(o.type || '').toLowerCase();\n      const n = String((o as FabricObject & { name?: string }).name || '').toLowerCase();\n      if (t === 'textbox' || t === 'i-text' || t === 'text') return 'text';\n      if (t === 'image' || t === 'fabricimage' || n === 'chart') return 'image';\n      if (t === 'activeselection') return 'ignore';\n      return 'shape';\n    };\n\n    canvas.on('object:moving', (e) => {\n      const snap = snapSettingsRef.current;\n      if (!snap.enabled || !e.target) {\n        activeGuidesRef.current = { x: [], y: [] };\n        return;\n      }\n      const obj = e.target;\n      const threshold = 8 / Math.max(0.15, fitScaleRef.current);\n      const w = sizeRef.current.width;\n      const h = sizeRef.current.height;\n      const ow = (obj.width || 0) * (obj.scaleX || 1);\n      const oh = (obj.height || 0) * (obj.scaleY || 1);\n      let left = obj.left ?? 0;\n      let top = obj.top ?? 0;\n      const edges = {\n        left,\n        right: left + ow,\n        centerX: left + ow / 2,\n        top,\n        bottom: top + oh,\n        centerY: top + oh / 2,\n      };\n\n      const xs: number[] = [];\n      const ys: number[] = [];\n      if (snap.canvasEdges) {\n        xs.push(0, w / 2, w);\n        ys.push(0, h / 2, h);\n      }\n      const moving = new Set<FabricObject>([obj]);\n      if (obj.type === 'activeselection' && typeof (obj as { getObjects?: () => FabricObject[] }).getObjects === 'function') {\n        (obj as { getObjects: () => FabricObject[] }).getObjects().forEach((o) => moving.add(o));\n      }\n      for (const other of canvas.getObjects()) {\n        if (moving.has(other)) continue;\n        const kind = classify(other);\n        if (kind === 'ignore') continue;\n        if (kind === 'shape' && !snap.shapes) continue;\n        if (kind === 'image' && !snap.images) continue;\n        if (kind === 'text' && !snap.text) continue;\n        const ow2 = (other.width || 0) * (other.scaleX || 1);\n        const oh2 = (other.height || 0) * (other.scaleY || 1);\n        const ol = other.left ?? 0;\n        const ot = other.top ?? 0;\n        xs.push(ol, ol + ow2 / 2, ol + ow2);\n        ys.push(ot, ot + oh2 / 2, ot + oh2);\n      }\n\n      let guideX: number | null = null;\n      let guideY: number | null = null;\n      let minDx = threshold;\n      let minDy = threshold;\n\n      const considerX = (x: number, edge: 'left' | 'right' | 'centerX') => {\n        const diff = Math.abs(edges[edge] - x);\n        if (diff < minDx) {\n          minDx = diff;\n          left = left + (x - edges[edge]);\n          guideX = x;\n        }\n      };\n      const considerY = (y: number, edge: 'top' | 'bottom' | 'centerY') => {\n        const diff = Math.abs(edges[edge] - y);\n        if (diff < minDy) {\n          minDy = diff;\n          top = top + (y - edges[edge]);\n          guideY = y;\n        }\n      };\n\n      for (const x of xs) {\n        considerX(x, 'left');\n        considerX(x, 'right');\n        considerX(x, 'centerX');\n      }\n      for (const y of ys) {\n        considerY(y, 'top');\n        considerY(y, 'bottom');\n        considerY(y, 'centerY');\n      }\n\n      obj.set({ left, top });\n      activeGuidesRef.current = {\n        x: guideX !== null ? [guideX] : [],\n        y: guideY !== null ? [guideY] : [],\n      };\n      window.dispatchEvent(new CustomEvent('slides-selection-moved'));\n    });\n\n    const onAfterRender = () => {\n      const guides = activeGuidesRef.current;\n      if (!snapSettingsRef.current.enabled || (!guides.x.length && !guides.y.length)) return;\n      const ctx = canvas.getContext();\n      if (!ctx) return;\n      const vz = fitScaleRef.current || 1;\n      const w = sizeRef.current.width;\n      const h = sizeRef.current.height;\n      ctx.save();\n      ctx.strokeStyle = '#ec4899';\n      ctx.lineWidth = 1 / vz;\n      ctx.setLineDash([6 / vz, 4 / vz]);\n      for (const gx of guides.x) {\n        ctx.beginPath();\n        ctx.moveTo(gx, -40);\n        ctx.lineTo(gx, h + 40);\n        ctx.stroke();\n      }\n      for (const gy of guides.y) {\n        ctx.beginPath();\n        ctx.moveTo(-40, gy);\n        ctx.lineTo(w + 40, gy);\n        ctx.stroke();\n      }\n      ctx.restore();\n    };\n    canvas.on('after:render', onAfterRender);\n\n    canvas.on('object:scaling', () => window.dispatchEvent(new CustomEvent('slides-selection-moved')));\n    canvas.on('object:rotating', () => window.dispatchEvent(new CustomEvent('slides-selection-moved')));\n\n    return () => {\n      canvas.dispose();\n      const parent = lower.parentNode;\n      if (parent && lower.parentNode === parent) {\n        parent.removeChild(lower);\n      }\n      canvasElRef.current = null;\n      fabricRef.current = null;\n    };\n  }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n  // Logical canvas size (no store zoom \u2014 display scale is CSS-only).\n  useEffect(() => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    canvas.setDimensions({ width: size.width, height: size.height });\n    canvas.setZoom(1);\n    canvas.calcOffset();\n    canvas.requestRenderAll();\n  }, [size.width, size.height]);\n\n  // Fit preview to host without horizontal scroll (local scale, equality-guarded).\n  // Host must fill its parent (absolute inset-0) so shrinking content cannot trap a small clientHeight.\n  useEffect(() => {\n    const host = scrollHostRef.current;\n    if (!host) return;\n    const applyFit = () => {\n      const pad = 48;\n      const availW = Math.max(120, host.clientWidth - pad);\n      const availH = Math.max(120, host.clientHeight - pad);\n      const sx = availW / Math.max(1, sizeRef.current.width);\n      const sy = availH / Math.max(1, sizeRef.current.height);\n      const next = Math.min(sx, sy);\n      setFitScale((prev) => (Math.abs(prev - next) < 0.002 ? prev : next));\n    };\n    applyFit();\n    const ro = new ResizeObserver(() => {\n      requestAnimationFrame(applyFit);\n    });\n    ro.observe(host);\n    return () => ro.disconnect();\n  }, [size.width, size.height]);\n\n  // Apply CSS display size when fit scale changes (fabric buffer stays logical).\n  useEffect(() => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const w = size.width * fitScale;\n    const h = size.height * fitScale;\n    const el = canvas.getElement()?.parentElement as HTMLElement | null;\n    if (el) {\n      el.style.width = `${w}px`;\n      el.style.height = `${h}px`;\n    }\n    const lower = canvas.lowerCanvasEl as HTMLCanvasElement | undefined;\n    const upper = canvas.upperCanvasEl as HTMLCanvasElement | undefined;\n    for (const node of [lower, upper]) {\n      if (!node) continue;\n      node.style.width = `${w}px`;\n      node.style.height = `${h}px`;\n    }\n    canvas.calcOffset();\n  }, [fitScale, size.width, size.height]);\n\n  // Load slide JSON when switching slides / undo-redo / theme \u2014 not after every persist.\n  const prevSlideIdRef = useRef<string | null>(null);\n  useEffect(() => {\n    const canvas = fabricRef.current;\n    if (!canvas || !activeSlide) return;\n\n    const prevId = prevSlideIdRef.current;\n    const slideChanged = Boolean(prevId && prevId !== activeSlideId);\n\n    // Flush unsaved canvas into the previous slide before swapping content \u2014\n    // skip when the previous id is gone (e.g. generate-deck replaced the deck).\n    if (slideChanged && !skipSaveRef.current) {\n      const stillExists = useSlidesStore\n        .getState()\n        .slides.some((s) => s.id === prevId);\n      if (stillExists) {\n        const json = (canvas as unknown as { toObject: (props?: string[]) => unknown }).toObject(CUSTOM_PROPS);\n        updateSlideJson(prevId!, json, false);\n      }\n    }\n    prevSlideIdRef.current = activeSlideId;\n\n    const epochBumped = canvasReloadEpoch !== loadedReloadEpochRef.current;\n\n    // Own persist bumped historyIndex \u2014 canvas already matches store (same slide only).\n    // Never skip when canvasReloadEpoch advanced (translate / generate / AI tools),\n    // including when historyIndex is capped at 49 and does not change.\n    if (\n      !epochBumped &&\n      skipReloadRef.current &&\n      !slideChanged &&\n      persistedHistoryIndexRef.current != null &&\n      activeSlide.historyIndex === persistedHistoryIndexRef.current\n    ) {\n      skipReloadRef.current = false;\n      return;\n    }\n    skipReloadRef.current = false;\n    persistedHistoryIndexRef.current = null;\n    loadedReloadEpochRef.current = canvasReloadEpoch;\n\n    let cancelled = false;\n    skipSaveRef.current = true;\n    void canvas.loadFromJSON(activeSlide.json || { objects: [] }).then(async () => {\n      if (cancelled || fabricRef.current !== canvas) return;\n      const ctx = typeof canvas.getContext === 'function' ? canvas.getContext() : null;\n      if (!ctx) return;\n      canvas.backgroundColor = theme.colors.background;\n      // Re-point images at fresh blob URLs from the asset registry (JSON often\n      // still has dead blob: srcs from the previous session).\n      await rebindCanvasImageAssets(canvas, useSlidesStore.getState().assets);\n      canvas.requestRenderAll();\n      skipSaveRef.current = false;\n    }).catch(() => {\n      skipSaveRef.current = false;\n    });\n\n    return () => {\n      cancelled = true;\n    };\n  }, [activeSlideId, activeSlide?.historyIndex, canvasReloadEpoch, theme.id, size.width, size.height, updateSlideJson, theme.colors.background]); // eslint-disable-line react-hooks/exhaustive-deps\n\n  // Sync background color whenever the theme changes without a full slide reload\n  // (e.g. user picks a different theme, or HMR reloads the module).\n  useEffect(() => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    canvas.backgroundColor = theme.colors.background;\n    canvas.requestRenderAll();\n  }, [theme.colors.background]);\n\n  const addText = () => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const tb = new Textbox('Nuevo texto', {\n      left: size.width / 2 - 200,\n      top: size.height / 2 - 40,\n      width: 400,\n      fontSize: theme.typeScale.body,\n      fontFamily: theme.fonts.body,\n      fill: theme.colors.body,\n    });\n    (tb as FabricObject & { id?: string; themeRole?: string }).id = uid();\n    (tb as FabricObject & { themeRole?: string }).themeRole = 'body';\n    canvas.add(tb);\n    canvas.setActiveObject(tb);\n    canvas.requestRenderAll();\n    persist();\n  };\n\n  const addRect = () => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const r = new Rect({\n      left: size.width / 2 - 100,\n      top: size.height / 2 - 60,\n      width: 200,\n      height: 120,\n      fill: theme.colors.accent,\n      rx: theme.radii.md,\n      ry: theme.radii.md,\n    });\n    (r as FabricObject & { id?: string }).id = uid();\n    canvas.add(r);\n    canvas.setActiveObject(r);\n    persist();\n  };\n\n  const addCircle = () => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const c = new Circle({\n      left: size.width / 2 - 60,\n      top: size.height / 2 - 60,\n      radius: 60,\n      fill: theme.colors.accent,\n    });\n    (c as FabricObject & { id?: string }).id = uid();\n    canvas.add(c);\n    canvas.setActiveObject(c);\n    persist();\n  };\n\n  const addImageFile = async (file: File) => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    try {\n      const url = URL.createObjectURL(file);\n      await placeMediaOnCanvas(url, file.name, file.type || 'image/png', file);\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : t.slides.slideCanvas.imageAddError, 'error');\n    }\n  };\n\n  const addMediaFromUrl = async (url: string, name: string, mimeType?: string) => {\n    try {\n      await placeMediaOnCanvas(url, name, mimeType || guessMime(name, url));\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : t.slides.slideCanvas.imageAddError, 'error');\n    }\n  };\n\n  const placeMediaOnCanvas = async (\n    url: string,\n    name: string,\n    mimeType: string,\n    file?: File,\n  ) => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const isVideo = mimeType.startsWith('video/') || /\\.(mp4|webm|mov|m4v)(\\?|#|$)/i.test(url);\n\n    let img: FabricImage;\n    if (isVideo) {\n      const video = document.createElement('video');\n      video.muted = true;\n      video.loop = true;\n      video.playsInline = true;\n      video.preload = 'auto';\n      if (!url.startsWith('blob:') && !url.startsWith('data:')) {\n        video.crossOrigin = 'anonymous';\n      }\n      video.src = url;\n      await new Promise<void>((resolve, reject) => {\n        video.onloadeddata = () => resolve();\n        video.onerror = () => reject(new Error(t.slides.slideCanvas.imageAddError));\n      });\n      try {\n        void video.play();\n      } catch {\n        /* autoplay may be blocked; still show first frame */\n      }\n      img = new FabricImage(video, {\n        left: size.width / 2 - 200,\n        top: size.height / 2 - 150,\n      });\n    } else {\n      img = await loadFabricImage(url);\n      img.set({ left: size.width / 2 - 200, top: size.height / 2 - 150 });\n    }\n\n    img.scaleToWidth(Math.min(600, size.width * 0.4));\n    const objectId = uid('obj');\n    const assetId = uid('asset');\n    (img as FabricObject & { id?: string }).id = objectId;\n    stampImageAssetId(img as FabricImage & { assetId?: string }, assetId);\n    canvas.add(img);\n    canvas.setActiveObject(img);\n    canvas.requestRenderAll();\n    useSlidesStore.getState().addAsset({\n      id: assetId,\n      name,\n      mimeType: mimeType || (isVideo ? 'video/mp4' : 'image/png'),\n      file,\n      url,\n    });\n    persist();\n  };\n\n  const guessMime = (name: string, url: string) => {\n    if (/\\.(mp4|webm|mov|m4v)(\\?|#|$)/i.test(name) || /\\.(mp4|webm|mov|m4v)(\\?|#|$)/i.test(url)) {\n      return 'video/mp4';\n    }\n    if (/\\.(png|jpe?g|gif|webp|avif|svg)(\\?|#|$)/i.test(name) || /\\.(png|jpe?g|gif|webp|avif|svg)(\\?|#|$)/i.test(url)) {\n      return 'image/png';\n    }\n    return 'application/octet-stream';\n  };\n\n  const replaceSelectedImage = async (fileOrUrl: File | { url: string; name: string; mimeType?: string }) => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const active = canvas.getActiveObject() as FabricImage | null;\n    if (!active || String(active.type || '').toLowerCase() !== 'image') {\n      addToast(t.slides.slideCanvas.selectImageOrObject, 'info');\n      return;\n    }\n    const left = active.left ?? 0;\n    const top = active.top ?? 0;\n    const targetW = (active.width || 1) * (active.scaleX || 1);\n    const id = (active as FabricObject & { id?: string }).id || uid();\n\n    let url: string;\n    let name: string;\n    let mimeType: string;\n    let file: File | undefined;\n    if (fileOrUrl instanceof File) {\n      file = fileOrUrl;\n      url = URL.createObjectURL(fileOrUrl);\n      name = fileOrUrl.name;\n      mimeType = fileOrUrl.type || 'image/png';\n    } else {\n      url = fileOrUrl.url;\n      name = fileOrUrl.name;\n      mimeType = fileOrUrl.mimeType || guessMime(fileOrUrl.name, fileOrUrl.url);\n    }\n\n    const next = await loadFabricImage(url);\n    next.set({ left, top });\n    next.scaleToWidth(targetW);\n    (next as FabricObject & { id?: string }).id = id;\n    const prevAssetId = (active as FabricObject & { assetId?: string }).assetId;\n    const assetId = prevAssetId || uid('asset');\n    stampImageAssetId(next as FabricImage & { assetId?: string }, assetId);\n    canvas.remove(active);\n    canvas.add(next);\n    canvas.setActiveObject(next);\n    useSlidesStore.getState().addAsset({\n      id: assetId,\n      name,\n      mimeType,\n      file,\n      url,\n    });\n    persist();\n  };\n\n  const setSelectedFontFamily = (fontFamily: string, opts?: { preview?: boolean }) => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const objs = canvas.getActiveObjects();\n    if (!objs.length) return;\n    for (const o of objs) {\n      const t = String(o.type || '').toLowerCase();\n      if (t === 'textbox' || t === 'i-text' || t === 'text') {\n        o.set('fontFamily', fontFamily);\n      }\n    }\n    canvas.requestRenderAll();\n    if (!opts?.preview) persist();\n  };\n\n  const getSelectedFontFamily = (): string | null => {\n    const canvas = fabricRef.current;\n    if (!canvas) return null;\n    const active = canvas.getActiveObject() as FabricObject & { fontFamily?: string } | null;\n    if (!active) return null;\n    const t = String(active.type || '').toLowerCase();\n    if (t === 'textbox' || t === 'i-text' || t === 'text') {\n      return String(active.fontFamily || theme.fonts.body);\n    }\n    return null;\n  };\n\n  const setSelectedFontSize = (fontSize: number) => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const size = Math.max(8, Math.min(240, Math.round(fontSize)));\n    const objs = canvas.getActiveObjects();\n    if (!objs.length) return;\n    for (const o of objs) {\n      const t = String(o.type || '').toLowerCase();\n      if (t === 'textbox' || t === 'i-text' || t === 'text') {\n        o.set('fontSize', size);\n        (o as FabricObject & { themeRole?: string }).themeRole = undefined;\n      }\n    }\n    canvas.requestRenderAll();\n    persist();\n  };\n\n  const getSelectedFontSize = (): number | null => {\n    const canvas = fabricRef.current;\n    if (!canvas) return null;\n    const active = canvas.getActiveObject() as FabricObject & { fontSize?: number } | null;\n    if (!active) return null;\n    const t = String(active.type || '').toLowerCase();\n    if (t === 'textbox' || t === 'i-text' || t === 'text') {\n      const n = Number(active.fontSize);\n      return Number.isFinite(n) ? n : null;\n    }\n    return null;\n  };\n\n  const setSelectedFill = (fill: string) => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const objs = canvas.getActiveObjects();\n    if (!objs.length) return;\n    for (const o of objs) {\n      const t = String(o.type || '').toLowerCase();\n      if (t === 'image' || t === 'fabricimage') continue;\n      o.set('fill', fill);\n      // Detach from theme token so global restyle won't overwrite this pick.\n      (o as FabricObject & { themeRole?: string }).themeRole = undefined;\n    }\n    canvas.requestRenderAll();\n    persist();\n  };\n\n  const getSelectedFill = (): string | null => {\n    const canvas = fabricRef.current;\n    if (!canvas) return null;\n    const active = canvas.getActiveObject() as FabricObject & { fill?: unknown } | null;\n    if (!active) return null;\n    const t = String(active.type || '').toLowerCase();\n    if (t === 'image' || t === 'fabricimage') return null;\n    return typeof active.fill === 'string' ? active.fill : null;\n  };\n\n  const nudgeSelected = (dx: number, dy: number) => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const objs = canvas.getActiveObjects();\n    if (!objs.length) return;\n    for (const o of objs) {\n      o.set({\n        left: (o.left || 0) + dx,\n        top: (o.top || 0) + dy,\n      });\n      o.setCoords();\n    }\n    canvas.requestRenderAll();\n    persist();\n  };\n\n  const runAlign = (edge: 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom') => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const objs = canvas.getActiveObjects() as Array<FabricObject & Box>;\n    if (objs.length < 2) {\n      addToast(t.slides.slideCanvas.selectAtLeast2, 'info');\n      return;\n    }\n    const boxes = objs.map((o) => ({\n      left: o.left || 0,\n      top: o.top || 0,\n      width: (o.width || 0) * (o.scaleX || 1),\n      height: (o.height || 0) * (o.scaleY || 1),\n    }));\n    const next = alignObjects(boxes, edge);\n    objs.forEach((o, i) => o.set({ left: next[i]!.left, top: next[i]!.top }));\n    canvas.requestRenderAll();\n    persist();\n  };\n\n  const runDistribute = (axis: 'horizontal' | 'vertical') => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const objs = canvas.getActiveObjects() as Array<FabricObject & Box>;\n    if (objs.length < 3) {\n      addToast(t.slides.slideCanvas.selectAtLeast3, 'info');\n      return;\n    }\n    const boxes = objs.map((o) => ({\n      left: o.left || 0,\n      top: o.top || 0,\n      width: (o.width || 0) * (o.scaleX || 1),\n      height: (o.height || 0) * (o.scaleY || 1),\n    }));\n    const next = distributeObjects(boxes, axis);\n    // Match by sorting same way\n    const sorted = [...objs].sort((a, b) =>\n      axis === 'horizontal' ? (a.left || 0) - (b.left || 0) : (a.top || 0) - (b.top || 0)\n    );\n    sorted.forEach((o, i) => o.set({ left: next[i]!.left, top: next[i]!.top }));\n    canvas.requestRenderAll();\n    persist();\n  };\n\n  const runAutofit = () => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const obj = canvas.getActiveObject() as (FabricObject & { text?: string; fontSize?: number; fontFamily?: string; width?: number; height?: number; scaleY?: number }) | null;\n    if (!obj || typeof obj.text !== 'string') {\n      addToast(t.slides.slideCanvas.selectTextBox, 'info');\n      return;\n    }\n    const result = autofitTextbox({\n      text: obj.text,\n      width: (obj.width || 200) * (obj.scaleX || 1),\n      maxHeight: (obj.height || 100) * (obj.scaleY || 1),\n      fontFamily: obj.fontFamily || theme.fonts.body,\n      maxFontSize: obj.fontSize || 48,\n    });\n    obj.set({ fontSize: result.fontSize });\n    markOverflow(obj as unknown as Record<string, unknown>, result.overflow);\n    canvas.requestRenderAll();\n    persist();\n    if (result.overflow) addToast(t.slides.slideCanvas.overflowWarning, 'warning');\n  };\n\n  const addChart = (kind?: 'bar' | 'line' | 'pie' | 'donut') => {\n    const presets: Record<NonNullable<typeof kind>, { labels: string[]; series: Array<{ name: string; data: number[] }> }> = {\n      bar:   { labels: ['A', 'B', 'C', 'D'], series: [{ name: 'Serie 1', data: [12, 19, 8, 15] }] },\n      line:  { labels: ['Ene', 'Feb', 'Mar', 'Abr'], series: [{ name: 'Tendencia', data: [5, 9, 14, 21] }] },\n      pie:   { labels: ['A', 'B', 'C'], series: [{ name: 'Distribucion', data: [40, 35, 25] }] },\n      donut: { labels: ['A', 'B', 'C', 'D'], series: [{ name: 'Categorias', data: [30, 25, 25, 20] }] },\n    };\n    void insertChart({\n      chartType: kind ?? 'bar',\n      ...(presets[kind ?? 'bar']),\n    });\n  };\n\n  const setAltOnSelection = () => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const obj = canvas.getActiveObject() as FabricObject & { id?: string; alt?: string } | null;\n    if (!obj?.id) {\n      addToast(t.slides.slideCanvas.selectImageOrObject, 'info');\n      return;\n    }\n    useSlidesUiStore.getState().setAltTextModal({\n      objectId: obj.id,\n      value: obj.alt || '',\n    });\n  };\n\n  const bringSelectedForward = () => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const obj = canvas.getActiveObject();\n    if (!obj) return;\n    canvas.bringObjectForward(obj);\n    canvas.requestRenderAll();\n    persist();\n  };\n\n  const sendSelectedBackward = () => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const obj = canvas.getActiveObject();\n    if (!obj) return;\n    canvas.sendObjectBackwards(obj);\n    canvas.requestRenderAll();\n    persist();\n  };\n\n  const bringSelectedToFront = () => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const obj = canvas.getActiveObject();\n    if (!obj) return;\n    canvas.bringObjectToFront(obj);\n    canvas.requestRenderAll();\n    persist();\n  };\n\n  const sendSelectedToBack = () => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const obj = canvas.getActiveObject();\n    if (!obj) return;\n    canvas.sendObjectToBack(obj);\n    canvas.requestRenderAll();\n    persist();\n  };\n\n  const removeSelected = async () => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const active = canvas.getActiveObjects();\n    if (active.length === 0) {\n      addToast(t.slides.slideCanvas.selectToDelete, 'info');\n      return;\n    }\n    const ok = await dialog.confirm(t.slides.slideCanvas.deleteSelectionBody(active.length), {\n      title: t.layers.deleteLayerTitle,\n      variant: 'danger',\n      confirmText: t.layers.deleteLayerConfirm,\n      cancelText: t.common.cancel,\n    });\n    if (!ok) return;\n    active.forEach((o) => canvas.remove(o));\n    canvas.discardActiveObject();\n    canvas.requestRenderAll();\n    persist();\n  };\n\n  const selectAll = () => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const objs = canvas.getObjects().filter((o) => o.selectable !== false);\n    if (objs.length === 0) return;\n    if (objs.length === 1) {\n      canvas.setActiveObject(objs[0]!);\n    } else {\n      const sel = new ActiveSelection(objs, canvas);\n      canvas.setActiveObject(sel);\n    }\n    canvas.requestRenderAll();\n  };\n\n  const duplicateSelected = () => {\n    const canvas = fabricRef.current;\n    if (!canvas) return;\n    const active = canvas.getActiveObject();\n    if (!active) {\n      addToast(t.slides.slideCanvas.selectToDuplicate, 'info');\n      return;\n    }\n    active.clone(['id', 'themeRole', 'placeholderRole', 'morphSourceId', 'assetId', 'overflow', 'name', 'alt', 'chartData'] as unknown as string[]).then((clone: FabricObject) => {\n      (clone as FabricObject & { id?: string }).id = uid();\n      clone.set({\n        left: (active.left || 0) + 20,\n        top:  (active.top  || 0) + 20,\n      });\n      canvas.add(clone);\n      canvas.setActiveObject(clone);\n      canvas.requestRenderAll();\n      persist();\n    });\n  };\n\n  // Expose actions via data attribute bridge for toolbar\n  useEffect(() => {\n    (window as unknown as { __slidesCanvas?: Record<string, unknown> }).__slidesCanvas = {\n      addText,\n      addRect,\n      addCircle,\n      addImageFile,\n      addMediaFromUrl,\n      replaceSelectedImage,\n      setSelectedFontFamily,\n      getSelectedFontFamily,\n      setSelectedFontSize,\n      getSelectedFontSize,\n      setSelectedFill,\n      getSelectedFill,\n      nudgeSelected,\n      addChart,\n      setAltOnSelection,\n      bringSelectedForward,\n      sendSelectedBackward,\n      bringSelectedToFront,\n      sendSelectedToBack,\n      runAlign,\n      runDistribute,\n      runAutofit,\n      removeSelected,\n      duplicateSelected,\n      selectAll,\n      persist,\n      getCanvas: () => fabricRef.current,\n    };\n    return () => {\n      delete (window as unknown as { __slidesCanvas?: unknown }).__slidesCanvas;\n    };\n  });\n\n  const brandHits = (() => {\n    const hits: Array<{ top: number; left: number; width: number; kind: 'forbidden' | 'preferred' }> =\n      [];\n    const json = activeSlide?.json as { objects?: Array<Record<string, unknown>> } | undefined;\n    for (const o of json?.objects || []) {\n      if (typeof o.text !== 'string') continue;\n      const text = o.text.toLowerCase();\n      const left = Number(o.left || 0) * fitScale;\n      const top = Number(o.top || 0) * fitScale;\n      const width = Number(o.width || 200) * Number(o.scaleX || 1) * fitScale;\n      for (const term of forbiddenTerms) {\n        if (term && text.includes(term.toLowerCase())) {\n          hits.push({ left, top, width, kind: 'forbidden' });\n          break;\n        }\n      }\n      for (const term of preferredTerms) {\n        if (term && text.includes(term.toLowerCase())) {\n          hits.push({ left, top, width, kind: 'preferred' });\n          break;\n        }\n      }\n    }\n    return hits;\n  })();\n\n  return (\n    <div\n      ref={scrollHostRef}\n      className=\"absolute inset-0 flex items-center justify-center overflow-hidden bg-[#0A0A0F] p-6\"\n      onContextMenu={(e) => {\n        e.preventDefault();\n        // Padding / empty host area (Fabric handles the canvas surface itself).\n        useSlidesUiStore.getState().setContextMenu({ x: e.clientX, y: e.clientY });\n      }}\n    >\n      <div\n        className=\"relative shadow-2xl shadow-black/60 ring-1 ring-panel-border\"\n        style={{ width: size.width * fitScale, height: size.height * fitScale }}\n      >\n        {showGrid && (\n          <div\n            className=\"pointer-events-none absolute inset-0 z-10 opacity-20\"\n            style={{\n              backgroundImage:\n                'linear-gradient(#8888A0 1px, transparent 1px), linear-gradient(90deg, #8888A0 1px, transparent 1px)',\n              backgroundSize: `${40 * fitScale}px ${40 * fitScale}px`,\n            }}\n          />\n        )}\n        {showBaseline && (\n          <div\n            className=\"pointer-events-none absolute inset-0 z-10 opacity-25\"\n            style={{\n              // Runtime spacing from theme \u2014 Tailwind cannot express this.\n              backgroundImage: `repeating-linear-gradient(\n                to bottom,\n                transparent,\n                transparent ${Math.max(8, theme.typeScale.body * 1.35) * fitScale - 1}px,\n                color-mix(in srgb, var(--we-accent) 55%, transparent) ${Math.max(8, theme.typeScale.body * 1.35) * fitScale - 1}px,\n                color-mix(in srgb, var(--we-accent) 55%, transparent) ${Math.max(8, theme.typeScale.body * 1.35) * fitScale}px\n              )`,\n            }}\n          />\n        )}\n        {brandHits.map((h, i) => (\n          <div\n            key={i}\n            className=\"pointer-events-none absolute z-20 rounded-sm\"\n            style={{\n              left: h.left,\n              top: h.top,\n              width: h.width,\n              height: 4 * fitScale,\n              background: h.kind === 'forbidden' ? 'rgba(239,68,68,0.85)' : 'rgba(34,197,94,0.75)',\n            }}\n          />\n        ))}\n        <div ref={containerRef} className=\"absolute inset-0\" />\n      </div>\n    </div>\n  );\n};\n\nexport function getSlidesCanvasApi() {\n  return (window as unknown as { __slidesCanvas?: {\n    addText: () => void;\n    addRect: () => void;\n    addCircle: () => void;\n    addImageFile: (f: File) => Promise<void>;\n    addMediaFromUrl: (url: string, name: string, mimeType?: string) => Promise<void>;\n    replaceSelectedImage: (\n      fileOrUrl: File | { url: string; name: string; mimeType?: string },\n    ) => Promise<void>;\n    setSelectedFontFamily: (fontFamily: string, opts?: { preview?: boolean }) => void;\n    getSelectedFontFamily: () => string | null;\n    setSelectedFontSize: (fontSize: number) => void;\n    getSelectedFontSize: () => number | null;\n    setSelectedFill: (fill: string) => void;\n    getSelectedFill: () => string | null;\n    nudgeSelected: (dx: number, dy: number) => void;\n    addChart: () => void;\n    setAltOnSelection: () => void;\n    bringSelectedForward: () => void;\n    sendSelectedBackward: () => void;\n    bringSelectedToFront: () => void;\n    sendSelectedToBack: () => void;\n    runAlign: (e: 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom') => void;\n    runDistribute: (a: 'horizontal' | 'vertical') => void;\n    runAutofit: () => void;\n    removeSelected: () => void;\n    duplicateSelected: () => void;\n    selectAll: () => void;\n    persist: () => void;\n    getCanvas: () => Canvas | null;\n  } }).__slidesCanvas;\n}\n", "import React, { useEffect, useState } from 'react';\nimport { FileVideo, Image as ImageIcon, Loader2, RefreshCw } from 'lucide-react';\nimport {\n  fetchRemoteMediaAsFile,\n  listMediaJobsWithS3,\n  type FileMediaItem,\n} from '../../services/imageJobsService';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport type { Slide } from '../../types/slides.types';\nimport { useTranslation } from '../../i18n';\nimport { getSlidesCanvasApi } from './SlideCanvas';\nimport { Button, IconButton, PanelBody, PanelSection, TextBody, TextTitle } from '../ui';\n\nconst libraryKey = 'we-slides-library';\nconst brandCompKey = 'we-slides-brand-components';\n\ntype BrandComponent = {\n  id: string;\n  name: string;\n  kind: 'cta' | 'quote' | 'kpi' | 'logo-lockup';\n  json: unknown;\n};\n\nfunction loadLibrary(): Slide[] {\n  try {\n    return JSON.parse(localStorage.getItem(libraryKey) || '[]') as Slide[];\n  } catch {\n    return [];\n  }\n}\n\nfunction saveLibrary(slides: Slide[]) {\n  localStorage.setItem(libraryKey, JSON.stringify(slides.slice(0, 40)));\n}\n\nfunction loadBrandComponents(): BrandComponent[] {\n  try {\n    return JSON.parse(localStorage.getItem(brandCompKey) || '[]') as BrandComponent[];\n  } catch {\n    return [];\n  }\n}\n\nfunction saveBrandComponents(items: BrandComponent[]) {\n  localStorage.setItem(brandCompKey, JSON.stringify(items.slice(0, 30)));\n}\n\nfunction defaultBrandComponents(\n  theme: ReturnType<typeof useSlidesStore.getState>['theme'],\n  labels: { cta: string; quote: string; kpi: string },\n): BrandComponent[] {\n  return [\n    {\n      id: 'cta',\n      name: labels.cta,\n      kind: 'cta',\n      json: {\n        type: 'Textbox',\n        text: labels.cta,\n        left: 200,\n        top: 820,\n        width: 520,\n        height: 80,\n        fontSize: 36,\n        fontFamily: theme.fonts.title,\n        fill: '#FFFFFF',\n        backgroundColor: theme.colors.accent,\n        id: 'brand_cta',\n        themeRole: 'accent',\n        alt: 'Call to action',\n      },\n    },\n    {\n      id: 'quote',\n      name: labels.quote,\n      kind: 'quote',\n      json: {\n        type: 'Textbox',\n        text: '\"\u2026\"',\n        left: 240,\n        top: 360,\n        width: 1440,\n        height: 200,\n        fontSize: 44,\n        fontFamily: theme.fonts.title,\n        fill: theme.colors.title,\n        id: 'brand_quote',\n        themeRole: 'title',\n      },\n    },\n    {\n      id: 'kpi',\n      name: labels.kpi,\n      kind: 'kpi',\n      json: {\n        type: 'Textbox',\n        text: '128%\\nYoY',\n        left: 200,\n        top: 300,\n        width: 700,\n        height: 280,\n        fontSize: 72,\n        fontFamily: theme.fonts.title,\n        fill: theme.colors.accent,\n        id: 'brand_kpi',\n        themeRole: 'accent',\n      },\n    },\n  ];\n}\n\nexport const LibraryPanel: React.FC = () => {\n  const t = useTranslation();\n  const lp = t.slides.libraryPanel;\n  const {\n    activeSlideId,\n    copySlideToLibrary,\n    pasteSlideFromLibrary,\n    addToast,\n    theme,\n    updateSlideJson,\n    slides,\n  } = useSlidesStore();\n  const [items, setItems] = useState<Slide[]>(() => loadLibrary());\n  const brandLabels = {\n    cta: lp.brandCta,\n    quote: lp.brandQuote,\n    kpi: lp.brandKpi,\n  };\n  const [brandItems, setBrandItems] = useState<BrandComponent[]>(() => {\n    const stored = loadBrandComponents();\n    return stored.length\n      ? stored\n      : defaultBrandComponents(useSlidesStore.getState().theme, brandLabels);\n  });\n  const [jobs, setJobs] = useState<FileMediaItem[]>([]);\n  const [jobsLoading, setJobsLoading] = useState(true);\n  const [jobsError, setJobsError] = useState<string | null>(null);\n  const [addingId, setAddingId] = useState<string | null>(null);\n  const [mediaFilter, setMediaFilter] = useState<'all' | 'image' | 'video'>('all');\n\n  const loadJobs = async (signal?: AbortSignal) => {\n    setJobsLoading(true);\n    setJobsError(null);\n    try {\n      const rows = await listMediaJobsWithS3({ signal });\n      if (signal?.aborted) return;\n      setJobs(rows.filter((r) => r.kind === 'image' || r.kind === 'video'));\n    } catch {\n      if (!signal?.aborted) {\n        setJobs([]);\n        setJobsError(lp.jobsLoadError);\n      }\n    } finally {\n      if (!signal?.aborted) setJobsLoading(false);\n    }\n  };\n\n  useEffect(() => {\n    const ac = new AbortController();\n    void loadJobs(ac.signal);\n    return () => ac.abort();\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  const saveCurrent = () => {\n    if (!activeSlideId) return;\n    const slide = copySlideToLibrary(activeSlideId);\n    if (!slide) return;\n    const next = [slide, ...items.filter((s) => s.id !== slide.id)];\n    setItems(next);\n    saveLibrary(next);\n    addToast(lp.slideSaved, 'success');\n  };\n\n  const insertBrand = (comp: BrandComponent) => {\n    const slide = slides.find((s) => s.id === activeSlideId);\n    if (!slide) {\n      addToast(lp.selectSlide, 'info');\n      return;\n    }\n    const json = structuredClone(slide.json) as { objects?: Array<Record<string, unknown>> };\n    const obj = {\n      ...(comp.json as Record<string, unknown>),\n      id: `obj_${Math.random().toString(36).slice(2, 10)}`,\n    };\n    json.objects = [...(json.objects || []), obj];\n    updateSlideJson(slide.id, json, true);\n    addToast(lp.componentInserted(comp.name), 'success');\n  };\n\n  const persistBrand = (next: BrandComponent[]) => {\n    setBrandItems(next);\n    saveBrandComponents(next);\n  };\n\n  const insertJob = async (item: FileMediaItem) => {\n    setAddingId(item.id);\n    try {\n      const api = getSlidesCanvasApi();\n      if (!api?.addMediaFromUrl && !api?.addImageFile) {\n        addToast(lp.selectSlide, 'info');\n        return;\n      }\n      const mime = item.kind === 'video' ? 'video/mp4' : 'image/png';\n      const downloaded = await fetchRemoteMediaAsFile(item.url, item.name, mime);\n      if (downloaded?.file && api.addImageFile) {\n        await api.addImageFile(downloaded.file);\n      } else {\n        await api.addMediaFromUrl?.(item.url, item.name, mime);\n      }\n      addToast(lp.mediaInserted(item.name), 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : lp.jobsInsertError, 'error');\n    } finally {\n      setAddingId(null);\n    }\n  };\n\n  const visibleJobs =\n    mediaFilter === 'all' ? jobs : jobs.filter((j) => j.kind === mediaFilter);\n\n  return (\n    <PanelBody className=\"h-full overflow-y-auto\">\n      <PanelSection\n        title={lp.jobsTitle}\n        description={lp.jobsHint}\n        trailing={\n          <IconButton\n            size=\"sm\"\n            variant=\"ghost\"\n            label={lp.jobsRefresh}\n            disabled={jobsLoading}\n            onClick={() => void loadJobs()}\n          >\n            <RefreshCw size={12} className={jobsLoading ? 'animate-spin' : ''} />\n          </IconButton>\n        }\n      >\n        <div\n          role=\"tablist\"\n          className=\"flex gap-1 rounded-xl bg-black-capsule p-0.5\"\n        >\n          {(\n            [\n              { id: 'all' as const, label: lp.filterAll },\n              { id: 'image' as const, label: lp.filterImage },\n              { id: 'video' as const, label: lp.filterVideo },\n            ] as const\n          ).map((opt) => {\n            const active = mediaFilter === opt.id;\n            return (\n              <button\n                key={opt.id}\n                type=\"button\"\n                role=\"tab\"\n                aria-selected={active}\n                onClick={() => setMediaFilter(opt.id)}\n                className={`flex-1 cursor-pointer rounded-lg px-1.5 py-1.5 text-[10px] font-bold uppercase tracking-wide transition-colors ${\n                  active\n                    ? 'bg-[var(--we-accent-capsule)] text-white'\n                    : 'text-white/80 hover:text-white'\n                }`}\n              >\n                {opt.label}\n              </button>\n            );\n          })}\n        </div>\n\n        {jobsLoading ? (\n          <div className=\"grid grid-cols-2 gap-2\" aria-busy>\n            {Array.from({ length: 6 }).map((_, i) => (\n              <div\n                key={i}\n                className=\"aspect-video animate-pulse rounded-xl border border-panel-border bg-black-capsule\"\n              />\n            ))}\n          </div>\n        ) : visibleJobs.length === 0 ? (\n          <TextBody as=\"p\" size=\"sm\" className=\"py-4 text-center text-white/80\">\n            {jobsError || lp.jobsEmpty}\n          </TextBody>\n        ) : (\n          <div className=\"max-h-56 overflow-y-auto overscroll-contain pr-0.5\">\n            <div className=\"grid grid-cols-2 gap-2\">\n              {visibleJobs.map((item) => (\n                <button\n                  key={item.id}\n                  type=\"button\"\n                  disabled={addingId === item.id}\n                  onClick={() => void insertJob(item)}\n                  className=\"group relative aspect-video overflow-hidden rounded-xl border border-panel-border bg-black-capsule text-left transition-colors hover:border-[color-mix(in_srgb,var(--we-accent)_40%,transparent)] disabled:opacity-60\"\n                  title={item.name}\n                >\n                  {item.kind === 'image' ? (\n                    <img src={item.url} alt=\"\" className=\"h-full w-full object-cover\" />\n                  ) : (\n                    <div className=\"flex h-full w-full items-center justify-center bg-black-capsule text-white/80\">\n                      <FileVideo size={22} />\n                    </div>\n                  )}\n                  <span className=\"absolute inset-x-0 bottom-0 flex items-center gap-1 bg-black/65 px-1.5 py-1 text-white\">\n                    {item.kind === 'image' ? <ImageIcon size={10} /> : <FileVideo size={10} />}\n                    <TextBody as=\"span\" size=\"sm\" className=\"min-w-0 truncate\">\n                      {item.name}\n                    </TextBody>\n                  </span>\n                  {addingId === item.id ? (\n                    <span className=\"absolute inset-0 flex items-center justify-center bg-black/50\">\n                      <Loader2 size={16} className=\"animate-spin text-white\" />\n                    </span>\n                  ) : null}\n                </button>\n              ))}\n            </div>\n          </div>\n        )}\n      </PanelSection>\n\n      <PanelSection\n        title={lp.brandComponentsTitle}\n        divided\n        trailing={\n          <button\n            type=\"button\"\n            onClick={() => persistBrand(defaultBrandComponents(theme, brandLabels))}\n            className=\"text-[var(--we-accent)]\"\n          ><TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">{lp.reset}</TextBody></button>\n        }\n      >\n        <div className=\"flex flex-col gap-1.5\">\n          {brandItems.map((c) => (\n            <div\n              key={c.id}\n              className=\"flex items-center justify-between gap-2 rounded-xl border border-panel-border bg-black-capsule px-2.5 py-2\"\n            >\n              <TextBody as=\"span\" size=\"sm\" className=\"min-w-0 truncate text-white\">\n                {c.name}\n              </TextBody>\n              <div className=\"flex shrink-0 items-center gap-1\">\n                <Button variant=\"ghost\" size=\"sm\" onClick={() => insertBrand(c)}>\n                  {lp.insert}\n                </Button>\n                <Button\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  className=\"text-red-400\"\n                  onClick={() => persistBrand(brandItems.filter((x) => x.id !== c.id))}\n                >\n                  {lp.delete}\n                </Button>\n              </div>\n            </div>\n          ))}\n        </div>\n      </PanelSection>\n\n      <PanelSection\n        title={lp.libraryTitle}\n        divided\n        trailing={\n          <button\n            type=\"button\"\n            onClick={saveCurrent}\n            className=\"text-[var(--we-accent)]\"\n          ><TextBody as=\"span\" size=\"sm\">{lp.saveActive}</TextBody></button>\n        }\n      >\n        <div className=\"flex flex-col gap-1.5\">\n          {items.map((s) => (\n            <div\n              key={s.id}\n              className=\"flex items-center justify-between gap-2 rounded-xl border border-panel-border bg-black-capsule px-2.5 py-2\"\n            >\n              <TextBody as=\"span\" size=\"sm\" className=\"min-w-0 truncate text-white\">\n                {s.name}\n              </TextBody>\n              <div className=\"flex shrink-0 items-center gap-1\">\n                <Button\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  onClick={() => {\n                    pasteSlideFromLibrary(s);\n                    addToast(lp.slideInserted, 'success');\n                  }}\n                >\n                  {lp.insert}\n                </Button>\n                <Button\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  className=\"text-red-400\"\n                  onClick={() => {\n                    const next = items.filter((x) => x.id !== s.id);\n                    setItems(next);\n                    saveLibrary(next);\n                  }}\n                >\n                  {lp.delete}\n                </Button>\n              </div>\n            </div>\n          ))}\n          {!items.length && (\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{lp.empty}</TextBody>\n          )}\n        </div>\n      </PanelSection>\n    </PanelBody>\n  );\n};\n", "import React from 'react';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { useTranslation } from '../../i18n';\nimport { PanelBody, PanelField, PanelSection, Switch, TextBody, TextTitle } from '../ui';\n\nconst INPUT =\n  'w-full rounded-xl border border-panel-border bg-black-capsule px-3 py-2 font-sans text-[12px] font-medium text-white outline-none placeholder:text-white/40 focus:border-[var(--we-accent)]';\n\n/** Master chrome controls \u2014 docked right-panel body (no floating chrome). */\nexport const MasterPanel: React.FC = () => {\n  const tr = useTranslation();\n  const mp = tr.slides.master;\n  const { masters, patchMasterChrome, theme } = useSlidesStore();\n  const master = masters[0];\n  const chrome = master?.chrome;\n\n  if (!chrome) {\n    return (\n      <TextBody as=\"p\" size=\"sm\" className=\"p-3 text-white/80\">\n        {mp.title('')}\n      </TextBody>\n    );\n  }\n\n  return (\n    <PanelBody className=\"h-full overflow-y-auto\">\n      <PanelSection title={mp.chromeSection} description={mp.chromeHint(theme.colors.background)}>\n        <PanelField\n          label={mp.showHeader}\n          trailing={\n            <Switch\n              checked={chrome.showHeader}\n              onChange={(v) => patchMasterChrome({ showHeader: v })}\n            />\n          }\n        />\n        <PanelField\n          label={mp.showFooter}\n          trailing={\n            <Switch\n              checked={chrome.showFooter}\n              onChange={(v) => patchMasterChrome({ showFooter: v })}\n            />\n          }\n        />\n        <PanelField\n          label={mp.showPageNumber}\n          trailing={\n            <Switch\n              checked={chrome.showPageNumber}\n              onChange={(v) => patchMasterChrome({ showPageNumber: v })}\n            />\n          }\n        />\n        <PanelField\n          label={mp.showLogo}\n          trailing={\n            <Switch\n              checked={chrome.showLogo}\n              onChange={(v) => patchMasterChrome({ showLogo: v })}\n            />\n          }\n        />\n      </PanelSection>\n\n      <PanelSection title={mp.contentSection} divided>\n        <label className=\"flex flex-col gap-1\">\n          <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n            {mp.headerTextPlaceholder}\n          </TextBody>\n          <input\n            value={chrome.headerText || ''}\n            onChange={(e) => patchMasterChrome({ headerText: e.target.value })}\n            placeholder={mp.headerTextPlaceholder}\n            className={INPUT}\n          />\n        </label>\n        <label className=\"flex flex-col gap-1\">\n          <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n            {mp.footerTextPlaceholder}\n          </TextBody>\n          <input\n            value={chrome.footerText}\n            onChange={(e) => patchMasterChrome({ footerText: e.target.value })}\n            placeholder={mp.footerTextPlaceholder}\n            className={INPUT}\n          />\n        </label>\n      </PanelSection>\n    </PanelBody>\n  );\n};\n", "import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n  Layers,\n  Library,\n  ListTree,\n  MessageCircle,\n  MessageSquare,\n  Mic2,\n  Palette,\n  RotateCcw,\n  Shield,\n  Sparkles,\n} from 'lucide-react';\nimport { useTranslation } from '../../i18n';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { useSlidesUiStore } from '../../store/useSlidesUiStore';\nimport type { SlidesRightTab } from '../../types/slides.types';\nimport { SlidesAiPanel } from './SlidesAiPanel';\nimport { SlidesChatPanel } from './SlidesChatPanel';\nimport { ThemePanel } from './ThemePanel';\nimport { DeckOutlinePanel } from './DeckOutlinePanel';\nimport { BuildsPanel } from './BuildsPanel';\nimport { CommentsPanel } from './CommentsPanel';\nimport { DesignCriticPanel } from './DesignCriticPanel';\nimport { CoachPanel } from './CoachPanel';\nimport { LibraryPanel } from './LibraryPanel';\nimport { MasterPanel } from './MasterPanel';\nimport { IconButton, TextBody, TextTitle } from '../ui';\n\nconst DEFAULT_WIDTH = 340;\nconst MIN_WIDTH = 280;\nconst MAX_WIDTH = 520;\n\nconst RAIL: {\n  id: SlidesRightTab;\n  icon: React.ReactNode;\n  labelKey:\n    | 'tabAi'\n    | 'tabChat'\n    | 'tabTheme'\n    | 'tabOutline'\n    | 'tabBuilds'\n    | 'tabComments'\n    | 'tabCritique'\n    | 'tabCoach'\n    | 'tabLibrary'\n    | 'tabMaster';\n  titleKey:\n    | 'titleAi'\n    | 'titleChat'\n    | 'titleTheme'\n    | 'titleOutline'\n    | 'titleBuilds'\n    | 'titleComments'\n    | 'titleCritique'\n    | 'titleCoach'\n    | 'titleLibrary'\n    | 'titleMaster';\n}[] = [\n  { id: 'ai', icon: <Sparkles size={17} />, labelKey: 'tabAi', titleKey: 'titleAi' },\n  { id: 'chat', icon: <MessageSquare size={17} />, labelKey: 'tabChat', titleKey: 'titleChat' },\n  { id: 'theme', icon: <Palette size={17} />, labelKey: 'tabTheme', titleKey: 'titleTheme' },\n  { id: 'master', icon: <Layers size={17} />, labelKey: 'tabMaster', titleKey: 'titleMaster' },\n  { id: 'outline', icon: <ListTree size={17} />, labelKey: 'tabOutline', titleKey: 'titleOutline' },\n  { id: 'builds', icon: <Layers size={17} />, labelKey: 'tabBuilds', titleKey: 'titleBuilds' },\n  { id: 'comments', icon: <MessageCircle size={17} />, labelKey: 'tabComments', titleKey: 'titleComments' },\n  { id: 'critique', icon: <Shield size={17} />, labelKey: 'tabCritique', titleKey: 'titleCritique' },\n  { id: 'coach', icon: <Mic2 size={17} />, labelKey: 'tabCoach', titleKey: 'titleCoach' },\n  { id: 'library', icon: <Library size={17} />, labelKey: 'tabLibrary', titleKey: 'titleLibrary' },\n];\n\nfunction PanelContent({ id }: { id: SlidesRightTab }) {\n  switch (id) {\n    case 'ai':\n      return <SlidesAiPanel />;\n    case 'chat':\n      return <SlidesChatPanel />;\n    case 'theme':\n      return <ThemePanel />;\n    case 'master':\n      return <MasterPanel />;\n    case 'outline':\n      return <DeckOutlinePanel />;\n    case 'builds':\n      return <BuildsPanel />;\n    case 'notes':\n      return null;\n    case 'comments':\n      return <CommentsPanel />;\n    case 'critique':\n      return <DesignCriticPanel />;\n    case 'coach':\n      return <CoachPanel />;\n    case 'library':\n      return <LibraryPanel />;\n  }\n}\n\n/** Right dock: tools rail + panel (text/audio pattern). */\nexport const SlidesRightSidebar: React.FC = () => {\n  const t = useTranslation();\n  const activeTab = useSlidesStore((s) => s.rightTab);\n  const setRightTab = useSlidesStore((s) => s.setRightTab);\n  const rightDockOpen = useSlidesUiStore((s) => s.rightDockOpen);\n  const setRightDockOpen = useSlidesUiStore((s) => s.setRightDockOpen);\n  const [panelWidth, setPanelWidth] = useState(DEFAULT_WIDTH);\n\n  const prevStoreTab = useRef(activeTab);\n  useEffect(() => {\n    if (activeTab !== prevStoreTab.current) {\n      prevStoreTab.current = activeTab;\n      setRightDockOpen(true);\n    }\n  }, [activeTab, setRightDockOpen]);\n\n  const onResizeStart = useCallback(\n    (e: React.MouseEvent) => {\n      e.preventDefault();\n      const startX = e.clientX;\n      const startW = panelWidth;\n      const onMove = (ev: MouseEvent) => {\n        setPanelWidth(Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, startW + (startX - ev.clientX))));\n      };\n      const onUp = () => {\n        window.removeEventListener('mousemove', onMove);\n        window.removeEventListener('mouseup', onUp);\n      };\n      window.addEventListener('mousemove', onMove);\n      window.addEventListener('mouseup', onUp);\n    },\n    [panelWidth],\n  );\n\n  const toggle = (id: SlidesRightTab) => {\n    if (rightDockOpen && activeTab === id) {\n      setRightDockOpen(false);\n      return;\n    }\n    setRightTab(id);\n    setRightDockOpen(true);\n  };\n\n  const titleKey = RAIL.find((p) => p.id === activeTab)?.titleKey ?? 'titleAi';\n\n  return (\n    <aside className=\"flex h-full min-h-0 shrink-0 select-none border-l border-panel-border bg-panel\">\n      {rightDockOpen && (\n        <div className=\"relative flex h-full min-h-0 flex-col\" style={{ width: panelWidth }}>\n          <div\n            role=\"separator\"\n            aria-orientation=\"vertical\"\n            aria-label={t.panel.resizeWidth}\n            onMouseDown={onResizeStart}\n            className=\"absolute inset-y-0 left-0 z-10 w-1.5 cursor-ew-resize group/hresize\"\n          >\n            <div className=\"absolute inset-y-0 left-0 w-0.5 rounded-r-full bg-transparent transition-colors group-hover/hresize:bg-[var(--we-accent-capsule)]\" />\n          </div>\n\n          <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-panel-border px-3 py-2 pl-4\">\n            <TextTitle as=\"h2\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n              {t.slides.sidebar[titleKey]}\n            </TextTitle>\n            {panelWidth !== DEFAULT_WIDTH && (\n              <IconButton\n                variant=\"ghost\"\n                size=\"sm\"\n                label={t.panel.resetWidth}\n                onClick={() => setPanelWidth(DEFAULT_WIDTH)}\n              >\n                <RotateCcw size={14} />\n              </IconButton>\n            )}\n          </div>\n\n          <div className=\"min-h-0 flex-1 overflow-y-auto\">\n            <PanelContent id={activeTab} />\n          </div>\n        </div>\n      )}\n\n      <div className=\"flex w-11 shrink-0 flex-col items-center border-l border-panel-border bg-panel py-2\">\n        <div className=\"flex flex-1 flex-col items-center gap-1.5 overflow-y-auto\">\n          {RAIL.map((item) => {\n            const isActive = rightDockOpen && activeTab === item.id;\n            return (\n              <button\n                key={item.id}\n                type=\"button\"\n                title={t.slides.sidebar[item.labelKey]}\n                onClick={() => toggle(item.id)}\n                className={`\n                  relative flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg\n                  transition-all duration-150 active:scale-90\n                  ${\n                    isActive\n                      ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--we-accent)_35%,transparent)]'\n                      : 'text-white/80 hover:bg-black-capsule hover:text-white'\n                  }\n                `}\n              >\n                {isActive && (\n                  <span className=\"absolute right-0 top-1/2 h-4 w-0.5 -translate-y-1/2 rounded-l-full bg-[var(--we-accent)]\" />\n                )}\n                {item.icon}\n              </button>\n            );\n          })}\n        </div>\n      </div>\n    </aside>\n  );\n};\n", "import React, { useState, useEffect, useRef } from 'react';\nimport { Eye, EyeOff, Copy, Trash2, GripVertical } from 'lucide-react';\nimport { Canvas as FabricCanvas } from 'fabric';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport type { Slide } from '../../types/slides.types';\nimport { useTranslation } from '../../i18n';\nimport { useDialog } from '../DialogModal';\nimport { TextBody, TextTitle } from '../ui';\n// \u2500\u2500 Mini preview canvas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Each slide thumbnail renders a real Fabric.js canvas scaled to fit the rail.\n// It loads the slide JSON and re-renders whenever the JSON changes.\nconst PREVIEW_W = 144; // px \u2014 thumbnail width in rail\nconst PREVIEW_H = Math.round(PREVIEW_W * (9 / 16)); // 81 px for 16:9\n\ninterface SlidePreviewProps {\n  slide: Slide;\n  deckWidth: number;\n  deckHeight: number;\n}\n\nconst SlidePreview: React.FC<SlidePreviewProps> = ({ slide, deckWidth, deckHeight }) => {\n  const containerRef = useRef<HTMLDivElement>(null);\n  const fabricRef    = useRef<FabricCanvas | null>(null);\n\n  // Scale factor: fit deck into thumbnail box\n  const scale = Math.min(PREVIEW_W / deckWidth, PREVIEW_H / deckHeight);\n  const canvasW = Math.round(deckWidth  * scale);\n  const canvasH = Math.round(deckHeight * scale);\n\n  // Mount Fabric canvas once\n  useEffect(() => {\n    if (!containerRef.current) return;\n\n    const el = document.createElement('canvas');\n    containerRef.current.appendChild(el);\n\n    const fc = new FabricCanvas(el, {\n      width:  canvasW,\n      height: canvasH,\n      selection: false,\n      interactive: false,\n      renderOnAddRemove: false,\n    });\n    fc.setZoom(scale);\n    fabricRef.current = fc;\n\n    return () => {\n      fabricRef.current = null;\n      fc.dispose();\n      if (el.parentNode) el.parentNode.removeChild(el);\n    };\n  }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n  // Resize when deck dimensions change\n  useEffect(() => {\n    const fc = fabricRef.current;\n    if (!fc) return;\n    fc.setDimensions({ width: canvasW, height: canvasH });\n    fc.setZoom(scale);\n    fc.requestRenderAll();\n  }, [canvasW, canvasH, scale]);\n\n  // Re-render whenever the slide JSON (content) changes\n  useEffect(() => {\n    const fc = fabricRef.current;\n    if (!fc) return;\n\n    let cancelled = false;\n    const json = slide.json as Record<string, unknown> | undefined;\n    const bg = (json as { background?: string } | undefined)?.background\n      ?? (slide as unknown as { theme?: { colors?: { background?: string } } })\n          ?.theme?.colors?.background\n      ?? '#FFFFFF';\n\n    void fc.loadFromJSON(json ?? { objects: [] }).then(() => {\n      // Thumbnail may have been unmounted while JSON was loading (e.g. AI regenerate).\n      if (cancelled || fabricRef.current !== fc) return;\n      const ctx = typeof fc.getContext === 'function' ? fc.getContext() : null;\n      if (!ctx) return;\n      fc.backgroundColor = bg;\n      fc.getObjects().forEach((o) => {\n        o.selectable = false;\n        o.evented = false;\n      });\n      fc.requestRenderAll();\n    }).catch(() => {\n      /* ignore dispose races */\n    });\n\n    return () => {\n      cancelled = true;\n    };\n  }, [slide.json, slide.historyIndex]); // eslint-disable-line react-hooks/exhaustive-deps\n\n  return (\n    <div\n      ref={containerRef}\n      style={{ width: canvasW, height: canvasH }}\n      className=\"pointer-events-none overflow-hidden rounded\"\n    />\n  );\n};\n\n// \u2500\u2500 Rail \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport const SlideRail: React.FC = () => {\n  const t = useTranslation();\n  const dialog = useDialog();\n  const {\n    slides,\n    size,\n    activeSlideId,\n    setActiveSlideId,\n    deleteSlide,\n    duplicateSlide,\n    moveSlide,\n    setSlideHidden,\n    renameSlide,\n  } = useSlidesStore();\n\n  const [dragId, setDragId] = useState<string | null>(null);\n\n  return (\n    <div className=\"p-2 space-y-2\">\n      {slides.map((slide, index) => {\n        const active = slide.id === activeSlideId;\n        return (\n          <div\n            key={slide.id}\n            draggable\n            onDragStart={() => setDragId(slide.id)}\n            onDragOver={(e) => e.preventDefault()}\n            onDrop={() => {\n              if (dragId) moveSlide(dragId, index);\n              setDragId(null);\n            }}\n            onClick={() => setActiveSlideId(slide.id)}\n            className={`group relative rounded-lg border p-1.5 cursor-pointer transition-all ${\n              active\n                ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)]'\n                : 'border-[#2A2A38] bg-[#13131A] hover:border-[color-mix(in_srgb,var(--we-accent)_40%,transparent)]'\n            } ${slide.hidden ? 'opacity-50' : ''}`}\n          >\n            <div className=\"flex items-start gap-1\">\n              <GripVertical size={12} className=\"text-[#55556A] mt-0.5 flex-shrink-0\" />\n              <div className=\"flex-1 min-w-0\">\n                {/* Slide number + name */}\n                <div className=\"flex items-center gap-1\">\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-[#8888A0] font-mono\">{index + 1}</TextBody>\n                  <input\n                    value={slide.name}\n                    onClick={(e) => e.stopPropagation()}\n                    onChange={(e) => renameSlide(slide.id, e.target.value)}\n                    className=\"bg-transparent text-[11px] font-semibold text-[#F0F0F5] w-full truncate outline-none\"\n                  />\n                </div>\n\n                {/* Live Fabric preview */}\n                <div className=\"pointer-events-none mt-1 flex w-full items-center justify-center overflow-hidden rounded border border-[#2A2A38] bg-white\">\n                  <SlidePreview\n                    slide={slide}\n                    deckWidth={size.width}\n                    deckHeight={size.height}\n                  />\n                </div>\n              </div>\n            </div>\n\n            {/* Hover actions */}\n            <div className=\"absolute top-1 right-1 flex gap-0.5 opacity-0 group-hover:opacity-100\">\n              <button\n                type=\"button\"\n                title={slide.hidden ? t.slides.slideRail.show : t.slides.slideRail.hide}\n                onClick={(e) => {\n                  e.stopPropagation();\n                  setSlideHidden(slide.id, !slide.hidden);\n                }}\n                className=\"w-5 h-5 rounded bg-black/50 text-white flex items-center justify-center\"\n              >\n                {slide.hidden ? <EyeOff size={10} /> : <Eye size={10} />}\n              </button>\n              <button\n                type=\"button\"\n                title={t.slides.slideRail.duplicate}\n                onClick={(e) => {\n                  e.stopPropagation();\n                  duplicateSlide(slide.id);\n                }}\n                className=\"w-5 h-5 rounded bg-black/50 text-white flex items-center justify-center\"\n              >\n                <Copy size={10} />\n              </button>\n              <button\n                type=\"button\"\n                title={t.slides.slideRail.remove}\n                onClick={async (e) => {\n                  e.stopPropagation();\n                  const ok = await dialog.confirm(\n                    t.slides.slideRail.deleteBody(slide.name),\n                    {\n                      title: t.slides.slideRail.deleteTitle,\n                      variant: 'danger',\n                      confirmText: t.slides.slideRail.deleteConfirm,\n                      cancelText: t.common.cancel,\n                    },\n                  );\n                  if (ok) deleteSlide(slide.id);\n                }}\n                className=\"w-5 h-5 rounded bg-black/50 text-white flex items-center justify-center\"\n              >\n                <Trash2 size={10} />\n              </button>\n            </div>\n          </div>\n        );\n      })}\n    </div>\n  );\n};\n", "import React, { useCallback, useState } from 'react';\nimport { Plus, RotateCcw } from 'lucide-react';\nimport { SlideRail } from './SlideRail';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { LAYOUT_CATALOG } from '../../lib/slides/layouts';\nimport { useTranslation } from '../../i18n';\nimport { IconButton, TextBody, TextTitle } from '../ui';\n\nconst DEFAULT_WIDTH = 220;\nconst MIN_WIDTH = 180;\nconst MAX_WIDTH = 320;\n\n/** Left dock: slide filmstrip (3-column shell). */\nexport const SlidesLeftPanel: React.FC = () => {\n  const t = useTranslation();\n  const { slides, activeSlideId, addSlide } = useSlidesStore();\n  const [panelWidth, setPanelWidth] = useState(DEFAULT_WIDTH);\n  const [layoutMenuOpen, setLayoutMenuOpen] = useState(false);\n\n  const onResizeStart = useCallback(\n    (e: React.MouseEvent) => {\n      e.preventDefault();\n      const startX = e.clientX;\n      const startW = panelWidth;\n      const onMove = (ev: MouseEvent) => {\n        setPanelWidth(Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, startW + (ev.clientX - startX))));\n      };\n      const onUp = () => {\n        window.removeEventListener('mousemove', onMove);\n        window.removeEventListener('mouseup', onUp);\n      };\n      window.addEventListener('mousemove', onMove);\n      window.addEventListener('mouseup', onUp);\n    },\n    [panelWidth],\n  );\n\n  return (\n    <aside\n      className=\"relative flex h-full min-h-0 shrink-0 flex-col border-r border-panel-border bg-panel\"\n      style={{ width: panelWidth }}\n    >\n      <div className=\"flex shrink-0 items-center justify-between gap-1 border-b border-panel-border px-2 py-2\">\n        <TextTitle as=\"h2\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n          {t.slides.floatingRail.title(slides.length)}\n        </TextTitle>\n        <div className=\"flex items-center gap-0.5\">\n          <div className=\"relative\">\n            <IconButton\n              variant=\"ghost\"\n              size=\"sm\"\n              label={t.slides.floatingRail.add}\n              onClick={() => setLayoutMenuOpen((v) => !v)}\n            >\n              <Plus size={14} />\n            </IconButton>\n            {layoutMenuOpen && (\n              <>\n                <div className=\"fixed inset-0 z-30\" onClick={() => setLayoutMenuOpen(false)} />\n                <div className=\"absolute left-0 top-8 z-40 max-h-64 w-44 overflow-auto rounded-xl border border-panel-border bg-panel py-1 shadow-xl\">\n                  {LAYOUT_CATALOG.map((l) => (\n                    <button\n                      key={l.id}\n                      type=\"button\"\n                      className=\"w-full px-3 py-1.5 text-left text-white hover:bg-[var(--we-accent-muted)]\"\n                      onClick={() => {\n                        addSlide(l.id, activeSlideId || undefined);\n                        setLayoutMenuOpen(false);\n                      }}\n                    >\n                      {l.name}\n                    </button>\n                  ))}\n                </div>\n              </>\n            )}\n          </div>\n          {panelWidth !== DEFAULT_WIDTH && (\n            <IconButton\n              variant=\"ghost\"\n              size=\"sm\"\n              label={t.panel.resetWidth}\n              onClick={() => setPanelWidth(DEFAULT_WIDTH)}\n            >\n              <RotateCcw size={14} />\n            </IconButton>\n          )}\n        </div>\n      </div>\n\n      <div className=\"min-h-0 flex-1 overflow-y-auto overflow-x-hidden\">\n        <SlideRail />\n      </div>\n\n      <div\n        role=\"separator\"\n        aria-orientation=\"vertical\"\n        aria-label={t.panel.resizeWidth}\n        onMouseDown={onResizeStart}\n        className=\"absolute inset-y-0 right-0 z-10 w-1.5 cursor-ew-resize group/hresize\"\n      >\n        <div className=\"absolute inset-y-0 right-0 w-0.5 rounded-l-full bg-transparent transition-colors group-hover/hresize:bg-[var(--we-accent-capsule)]\" />\n      </div>\n    </aside>\n  );\n};\n", "import React, { useRef, useState } from 'react';\nimport {\n  Type, Square, Circle, Image as ImageIcon,\n  BarChart3, Triangle, Minus,\n  ChevronDown,\n} from 'lucide-react';\nimport { useTranslation } from '../../i18n';\nimport { ViewportPortalMenu } from '../../utils/ViewportPortalMenu';\nimport { TextBody, TextTitle } from '../ui';\n\ntype ShapeKind = 'rect' | 'circle' | 'triangle' | 'line';\ntype ChartKind = 'bar' | 'line' | 'pie' | 'donut';\n\nconst SHAPE_OPTIONS: ReadonlyArray<{ id: ShapeKind; Icon: React.ComponentType<{ size?: number }> }> = [\n  { id: 'rect', Icon: Square },\n  { id: 'circle', Icon: Circle },\n  { id: 'triangle', Icon: Triangle },\n  { id: 'line', Icon: Minus },\n];\n\nconst CHART_OPTIONS: ReadonlyArray<{ id: ChartKind }> = [\n  { id: 'bar' },\n  { id: 'line' },\n  { id: 'pie' },\n  { id: 'donut' },\n];\n\ninterface SlidesCreationToolbarProps {\n  /** Receives the canvas API from the global window bridge. */\n  getApi: () => {\n    addText: () => void;\n    addRect: () => void;\n    addCircle: () => void;\n    addImageFile: (f: File) => Promise<void>;\n    addChart: () => void;\n    insertChart?: (data: {\n      chartType: ChartKind;\n      labels: string[];\n      series: Array<{ name: string; data: number[] }>;\n    }) => Promise<void>;\n  } | undefined;\n  /** Left of creation tools (e.g. undo/redo). */\n  leading?: React.ReactNode;\n  /** Right cluster (grid, snap, present\u2026) \u2014 space-between from creation tools. */\n  trailing?: React.ReactNode;\n}\n\nconst DEFAULT_CHART_DATA: Record<\n  ChartKind,\n  { labels: string[]; series: Array<{ name: string; data: number[] }> }\n> = {\n  bar: { labels: ['A', 'B', 'C', 'D'], series: [{ name: 'Serie 1', data: [12, 19, 8, 15] }] },\n  line: { labels: ['Ene', 'Feb', 'Mar', 'Abr'], series: [{ name: 'Tendencia', data: [5, 9, 14, 21] }] },\n  pie: { labels: ['A', 'B', 'C'], series: [{ name: 'Distribucion', data: [40, 35, 25] }] },\n  donut: { labels: ['A', 'B', 'C', 'D'], series: [{ name: 'Categorias', data: [30, 25, 25, 20] }] },\n};\n\nexport const SlidesCreationToolbar: React.FC<SlidesCreationToolbarProps> = ({\n  getApi,\n  leading,\n  trailing,\n}) => {\n  const t = useTranslation();\n  const [shapesOpen, setShapesOpen] = useState(false);\n  const [chartsOpen, setChartsOpen] = useState(false);\n  const shapesTriggerRef = useRef<HTMLButtonElement | null>(null);\n  const chartsTriggerRef = useRef<HTMLButtonElement | null>(null);\n  const imgInputRef = useRef<HTMLInputElement>(null);\n\n  const btnCls =\n    'relative group flex items-center justify-center w-10 h-10 rounded-xl ' +\n    'text-white/80 hover:text-white hover:bg-black-capsule transition-all active:scale-90';\n\n  const handleShape = (kind: ShapeKind) => {\n    const api = getApi();\n    if (!api) return;\n    if (kind === 'rect') api.addRect();\n    else if (kind === 'circle') api.addCircle();\n    setShapesOpen(false);\n  };\n\n  const handleChart = (kind: ChartKind) => {\n    const api = getApi();\n    if (!api) return;\n    const data = DEFAULT_CHART_DATA[kind];\n    if (api.insertChart) {\n      void api.insertChart({ chartType: kind, ...data });\n    } else {\n      api.addChart();\n    }\n    setChartsOpen(false);\n  };\n\n  return (\n    <div\n      data-testid=\"slides-creation-toolbar\"\n      className=\"flex w-full shrink-0 items-center justify-between gap-2 border-t border-panel-border bg-panel px-2 py-1.5\"\n    >\n      <div className=\"flex min-w-0 items-center gap-1\">\n        {leading}\n        <button\n          type=\"button\"\n          title={t.slides.creationToolbar.textTitle}\n          onClick={() => getApi()?.addText()}\n          className={btnCls}\n        >\n          <Type size={16} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full mb-2 left-1/2 -translate-x-1/2\">\n            {t.slides.creationToolbar.textTooltip}\n          </TextBody>\n        </button>\n\n        <div className=\"relative\">\n          <button\n            ref={shapesTriggerRef}\n            type=\"button\"\n            title={t.slides.creationToolbar.shapesTitle}\n            onClick={() => {\n              setShapesOpen((v) => !v);\n              setChartsOpen(false);\n            }}\n            aria-expanded={shapesOpen}\n            className={`${btnCls} ${shapesOpen ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)]' : ''}`}\n          >\n            <Square size={16} />\n            <ChevronDown size={10} className=\"absolute bottom-1 right-1 text-white/50\" />\n            <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full mb-2 left-1/2 -translate-x-1/2\">\n              {t.slides.creationToolbar.shapesTooltip}\n            </TextBody>\n          </button>\n          <ViewportPortalMenu\n            open={shapesOpen}\n            onClose={() => setShapesOpen(false)}\n            anchorRef={shapesTriggerRef}\n            prefer=\"above\"\n            zIndex={50}\n            className=\"flex w-44 flex-col gap-0.5 rounded-xl border border-panel-border bg-panel p-1.5 shadow-2xl shadow-black/60\"\n          >\n            <TextTitle as=\"p\" size=\"xs\" className=\"px-2.5 py-1 uppercase tracking-wider text-[var(--we-accent)]\">\n              {t.slides.creationToolbar.shapesHeader}\n            </TextTitle>\n            {SHAPE_OPTIONS.map(({ id, Icon }) => (\n              <button\n                key={id}\n                type=\"button\"\n                onClick={() => handleShape(id)}\n                className=\"flex cursor-pointer items-center gap-2.5 rounded-lg px-2.5 py-2 text-left text-xs font-semibold text-white transition-colors hover:bg-black-capsule\"\n              >\n                <Icon size={14} />\n                <TextBody as=\"span\" size=\"sm\">{t.slides.creationToolbar.shapes[id]}</TextBody>\n              </button>\n            ))}\n          </ViewportPortalMenu>\n        </div>\n\n        <button\n          type=\"button\"\n          title={t.slides.creationToolbar.imageTitle}\n          onClick={() => imgInputRef.current?.click()}\n          className={btnCls}\n        >\n          <ImageIcon size={16} />\n          <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full mb-2 left-1/2 -translate-x-1/2\">\n            {t.slides.creationToolbar.imageTooltip}\n          </TextBody>\n        </button>\n        <input\n          ref={imgInputRef}\n          type=\"file\"\n          accept=\"image/*\"\n          className=\"hidden\"\n          onChange={(e) => {\n            const f = e.target.files?.[0];\n            if (f) void getApi()?.addImageFile(f);\n            e.target.value = '';\n          }}\n        />\n\n        <div className=\"relative\">\n          <button\n            ref={chartsTriggerRef}\n            type=\"button\"\n            title={t.slides.creationToolbar.chartsTitle}\n            onClick={() => {\n              setChartsOpen((v) => !v);\n              setShapesOpen(false);\n            }}\n            aria-expanded={chartsOpen}\n            className={`${btnCls} ${chartsOpen ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)]' : ''}`}\n          >\n            <BarChart3 size={16} />\n            <ChevronDown size={10} className=\"absolute bottom-1 right-1 text-white/50\" />\n            <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble bottom-full mb-2 left-1/2 -translate-x-1/2\">\n              {t.slides.creationToolbar.chartsTooltip}\n            </TextBody>\n          </button>\n          <ViewportPortalMenu\n            open={chartsOpen}\n            onClose={() => setChartsOpen(false)}\n            anchorRef={chartsTriggerRef}\n            prefer=\"above\"\n            zIndex={50}\n            className=\"flex w-44 flex-col gap-0.5 rounded-xl border border-panel-border bg-panel p-1.5 shadow-2xl shadow-black/60\"\n          >\n            <TextTitle as=\"p\" size=\"xs\" className=\"px-2.5 py-1 uppercase tracking-wider text-[var(--we-accent)]\">\n              {t.slides.creationToolbar.chartsHeader}\n            </TextTitle>\n            {CHART_OPTIONS.map(({ id }) => (\n              <button\n                key={id}\n                type=\"button\"\n                onClick={() => handleChart(id)}\n                className=\"flex cursor-pointer items-center gap-2.5 rounded-lg px-2.5 py-2 text-left text-xs font-semibold text-white transition-colors hover:bg-black-capsule\"\n              >\n                <BarChart3 size={14} />\n                <TextBody as=\"span\" size=\"sm\">{t.slides.creationToolbar.charts[id]}</TextBody>\n              </button>\n            ))}\n          </ViewportPortalMenu>\n        </div>\n      </div>\n\n      {trailing ? <div className=\"flex shrink-0 items-center gap-1\">{trailing}</div> : null}\n    </div>\n  );\n};\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n  AlignLeft,\n  AlignCenter,\n  AlignRight,\n  ArrowDown,\n  ArrowDownToLine,\n  ArrowUp,\n  ArrowUpToLine,\n  Type,\n  Copy,\n  Trash2,\n  BarChart3,\n  Image as ImageIcon,\n  ChevronDown,\n  Upload,\n  FolderOpen,\n  Loader2,\n  X,\n} from 'lucide-react';\nimport { useTranslation } from '../../i18n';\nimport { modShortcut } from '../../utils/modKey';\nimport { GOOGLE_FONTS_CATALOG } from '../Sidebar';\nimport { loadGoogleFont } from '../editor/text/FontPicker';\nimport {\n  fetchRemoteMediaAsFile,\n  listMediaJobsWithS3,\n  type FileMediaItem,\n} from '../../services/imageJobsService';\nimport { modeAccentVars, useModeAccent } from '../../theme/modeAccent';\nimport { FontPickerFlyout, TextBody, TextTitle } from '../ui';\n\ntype SelectionKind = 'text' | 'shape' | 'chart' | 'image' | 'unknown';\n\ninterface SlidesContextToolbarProps {\n  getApi: () => {\n    runAlign: (edge: 'left' | 'center' | 'right') => void;\n    runAutofit: () => void;\n    removeSelected: () => void;\n    duplicateSelected: () => void;\n    setAltOnSelection: () => void;\n    bringSelectedForward?: () => void;\n    sendSelectedBackward?: () => void;\n    bringSelectedToFront?: () => void;\n    sendSelectedToBack?: () => void;\n    setSelectedFontFamily?: (fontFamily: string, opts?: { preview?: boolean }) => void;\n    getSelectedFontFamily?: () => string | null;\n    setSelectedFontSize?: (fontSize: number) => void;\n    getSelectedFontSize?: () => number | null;\n    setSelectedFill?: (fill: string) => void;\n    getSelectedFill?: () => string | null;\n    replaceSelectedImage?: (\n      fileOrUrl: File | { url: string; name: string; mimeType?: string },\n    ) => Promise<void>;\n  } | undefined;\n}\n\nconst btnCls =\n  'flex h-8 w-8 items-center justify-center rounded-lg text-white/80 ' +\n  'hover:bg-black-capsule hover:text-white transition-all active:scale-90 cursor-pointer';\n\nfunction detectKind(obj: { type?: string; name?: string } | null | undefined): SelectionKind {\n  if (!obj) return 'unknown';\n  const t = String(obj.type || '').toLowerCase();\n  const n = String(obj.name || '').toLowerCase();\n  if (t === 'textbox' || t === 'i-text' || t === 'text' || n === 'text') return 'text';\n  if (n === 'chart' || (t === 'image' && n === 'chart')) return 'chart';\n  if (t === 'image' || t === 'fabricimage') return 'image';\n  if (t === 'rect' || t === 'circle' || t === 'triangle' || t === 'line' || t === 'polygon' || t === 'path')\n    return 'shape';\n  return 'unknown';\n}\n\n/** Docked selection actions under the canvas (not a floating HUD). */\nexport const SlidesContextToolbar: React.FC<SlidesContextToolbarProps> = ({ getApi }) => {\n  const t = useTranslation();\n  const mode = useModeAccent();\n  const [count, setCount] = useState(0);\n  const [kind, setKind] = useState<SelectionKind>('unknown');\n  const [fontOpen, setFontOpen] = useState(false);\n  const [fontValue, setFontValue] = useState('Inter');\n  const [fontSize, setFontSize] = useState(24);\n  const [fillValue, setFillValue] = useState('#FFFFFF');\n  const fontCommitRef = useRef(fontValue);\n  const fontTriggerRef = useRef<HTMLButtonElement>(null);\n  const replaceInputRef = useRef<HTMLInputElement>(null);\n  const [jobsOpen, setJobsOpen] = useState(false);\n  const [jobs, setJobs] = useState<FileMediaItem[]>([]);\n  const [jobsLoading, setJobsLoading] = useState(false);\n  const [replacingId, setReplacingId] = useState<string | null>(null);\n\n  useEffect(() => {\n    const refresh = () => {\n      const canvas = (\n        window as unknown as { __slidesCanvas?: { getCanvas?: () => unknown } }\n      ).__slidesCanvas?.getCanvas?.();\n      if (!canvas) {\n        setCount(0);\n        return;\n      }\n      const list =\n        (canvas as { getActiveObjects?: () => unknown[] }).getActiveObjects?.() ?? [];\n      const active = (canvas as { getActiveObject?: () => unknown }).getActiveObject?.();\n      setCount(list.length);\n      const nextKind = list.length > 1 ? 'unknown' : detectKind(active as { type?: string; name?: string });\n      setKind(nextKind);\n      if (nextKind === 'text') {\n        const fam = getApi()?.getSelectedFontFamily?.() || 'Inter';\n        setFontValue(fam);\n        fontCommitRef.current = fam;\n        const size = getApi()?.getSelectedFontSize?.();\n        if (typeof size === 'number' && Number.isFinite(size)) setFontSize(Math.round(size));\n      } else {\n        setFontOpen(false);\n      }\n      if (nextKind === 'text' || nextKind === 'shape' || list.length > 1) {\n        const fill = getApi()?.getSelectedFill?.();\n        if (fill && /^#[0-9a-fA-F]{6}$/.test(fill)) setFillValue(fill);\n      }\n    };\n    window.addEventListener('slides-selection', refresh as EventListener);\n    refresh();\n    return () => window.removeEventListener('slides-selection', refresh as EventListener);\n  }, [getApi]);\n\n  useEffect(() => {\n    if (!jobsOpen) return;\n    const ac = new AbortController();\n    setJobsLoading(true);\n    void listMediaJobsWithS3({ signal: ac.signal })\n      .then((rows) => {\n        if (!ac.signal.aborted) {\n          setJobs(rows.filter((r) => r.kind === 'image' || r.kind === 'video'));\n        }\n      })\n      .catch(() => {\n        if (!ac.signal.aborted) setJobs([]);\n      })\n      .finally(() => {\n        if (!ac.signal.aborted) setJobsLoading(false);\n      });\n    return () => ac.abort();\n  }, [jobsOpen]);\n\n  if (count === 0) return null;\n\n  const api = getApi();\n  const isMulti = count > 1;\n  const showAlign = isMulti || kind === 'text';\n  const showAutofit = kind === 'text' && !isMulti;\n  const showFont = kind === 'text' && !isMulti;\n  const showFill = kind === 'text' || kind === 'shape' || isMulti;\n  const showAlt = (kind === 'image' || kind === 'chart') && !isMulti;\n  const showReplace = kind === 'image' && !isMulti;\n  const ct = t.slides.contextToolbar;\n\n  const replaceFromJob = async (item: FileMediaItem) => {\n    setReplacingId(item.id);\n    try {\n      const mime = item.kind === 'video' ? 'video/mp4' : 'image/png';\n      const downloaded = await fetchRemoteMediaAsFile(item.url, item.name, mime);\n      if (downloaded?.file) {\n        await api?.replaceSelectedImage?.(downloaded.file);\n      } else {\n        await api?.replaceSelectedImage?.({ url: item.url, name: item.name, mimeType: mime });\n      }\n      setJobsOpen(false);\n    } finally {\n      setReplacingId(null);\n    }\n  };\n\n  return (\n    <div\n      data-testid=\"slides-context-toolbar\"\n      className=\"flex shrink-0 flex-wrap items-center gap-1 border-t border-panel-border bg-[#0F0F16] px-2 py-1.5\"\n    >\n      <TextBody as=\"span\" size=\"sm\" className=\"mr-1 text-white/80\">\n        {count}\n      </TextBody>\n      {showAlign && (\n        <>\n          <button\n            type=\"button\"\n            title={ct.alignLeft}\n            className={btnCls}\n            disabled={!isMulti}\n            onClick={() => api?.runAlign('left')}\n          >\n            <AlignLeft size={15} />\n          </button>\n          <button\n            type=\"button\"\n            title={ct.alignCenter}\n            className={btnCls}\n            disabled={!isMulti}\n            onClick={() => api?.runAlign('center')}\n          >\n            <AlignCenter size={15} />\n          </button>\n          <button\n            type=\"button\"\n            title={ct.alignRight}\n            className={btnCls}\n            disabled={!isMulti}\n            onClick={() => api?.runAlign('right')}\n          >\n            <AlignRight size={15} />\n          </button>\n          <div className=\"mx-0.5 h-5 w-px bg-panel-border\" aria-hidden />\n        </>\n      )}\n      {showFont && (\n        <>\n          <button\n            ref={fontTriggerRef}\n            type=\"button\"\n            title={ct.fontFamily}\n            onClick={() => {\n              fontCommitRef.current = fontValue;\n              setFontOpen((v) => !v);\n            }}\n            className=\"inline-flex h-8 max-w-[11rem] items-center gap-1.5 rounded-lg bg-black-capsule px-2 text-white hover:bg-black-capsule-hover\"\n          >\n            <TextBody as=\"span\" size=\"sm\" className=\"min-w-0 flex-1 truncate\">\n              {fontValue}\n            </TextBody>\n            <ChevronDown\n              size={12}\n              className={`shrink-0 text-white/80 transition-transform ${fontOpen ? 'rotate-180' : ''}`}\n            />\n          </button>\n          <FontPickerFlyout\n            open={fontOpen}\n            onClose={() => {\n              loadGoogleFont(fontCommitRef.current);\n              api?.setSelectedFontFamily?.(fontCommitRef.current, { preview: true });\n              setFontValue(fontCommitRef.current);\n              setFontOpen(false);\n            }}\n            anchorRef={fontTriggerRef}\n            value={fontCommitRef.current}\n            fonts={GOOGLE_FONTS_CATALOG}\n            searchPlaceholder={ct.fontFamily}\n            onPreview={(name) => {\n              const family = name ?? fontCommitRef.current;\n              loadGoogleFont(family);\n              api?.setSelectedFontFamily?.(family, { preview: true });\n              setFontValue(family);\n            }}\n            onSelect={(name) => {\n              loadGoogleFont(name);\n              fontCommitRef.current = name;\n              setFontValue(name);\n              api?.setSelectedFontFamily?.(name);\n              setFontOpen(false);\n            }}\n          />\n          <div\n            className=\"inline-flex h-8 items-center overflow-hidden rounded-lg border border-panel-border bg-black-capsule\"\n            title={ct.fontSize}\n          >\n            <button\n              type=\"button\"\n              className=\"flex h-8 w-7 items-center justify-center text-white/80 hover:bg-black-capsule-hover hover:text-white\"\n              aria-label={ct.fontSizeDecrease}\n              onClick={() => {\n                const next = Math.max(8, fontSize - 1);\n                setFontSize(next);\n                api?.setSelectedFontSize?.(next);\n              }}\n            >\n              \u2212\n            </button>\n            <input\n              type=\"number\"\n              min={8}\n              max={240}\n              value={fontSize}\n              onChange={(e) => {\n                const n = Number(e.target.value);\n                if (!Number.isFinite(n)) return;\n                const next = Math.max(8, Math.min(240, Math.round(n)));\n                setFontSize(next);\n                api?.setSelectedFontSize?.(next);\n              }}\n              className=\"h-8 w-10 border-x border-panel-border bg-transparent text-center text-white outline-none [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none\"\n              aria-label={ct.fontSize}\n            />\n            <button\n              type=\"button\"\n              className=\"flex h-8 w-7 items-center justify-center text-white/80 hover:bg-black-capsule-hover hover:text-white\"\n              aria-label={ct.fontSizeIncrease}\n              onClick={() => {\n                const next = Math.min(240, fontSize + 1);\n                setFontSize(next);\n                api?.setSelectedFontSize?.(next);\n              }}\n            >\n              +\n            </button>\n          </div>\n        </>\n      )}\n      {showFill && (\n        <label\n          title={ct.fillColor}\n          className=\"relative inline-flex h-8 w-8 cursor-pointer items-center justify-center overflow-hidden rounded-lg border border-panel-border\"\n        >\n          <span className=\"absolute inset-1 rounded-md\" style={{ backgroundColor: fillValue }} aria-hidden />\n          <input\n            type=\"color\"\n            value={fillValue}\n            onChange={(e) => {\n              setFillValue(e.target.value);\n              api?.setSelectedFill?.(e.target.value);\n            }}\n            className=\"absolute inset-0 h-full w-full cursor-pointer opacity-0\"\n            aria-label={ct.fillColor}\n          />\n        </label>\n      )}\n      {showAutofit && (\n        <button\n          type=\"button\"\n          title={ct.autofitText}\n          className={btnCls}\n          onClick={() => api?.runAutofit()}\n        >\n          <Type size={15} />\n        </button>\n      )}\n      {showReplace && (\n        <>\n          <div className=\"mx-0.5 h-5 w-px bg-panel-border\" aria-hidden />\n          <button\n            type=\"button\"\n            title={ct.replaceUpload}\n            className={btnCls}\n            onClick={() => replaceInputRef.current?.click()}\n          >\n            <Upload size={15} />\n          </button>\n          <button\n            type=\"button\"\n            title={ct.replaceFromFiles}\n            className={btnCls}\n            onClick={() => setJobsOpen(true)}\n          >\n            <FolderOpen size={15} />\n          </button>\n          <input\n            ref={replaceInputRef}\n            type=\"file\"\n            accept=\"image/*,video/*\"\n            className=\"hidden\"\n            onChange={(e) => {\n              const f = e.target.files?.[0];\n              if (f) void api?.replaceSelectedImage?.(f);\n              e.target.value = '';\n            }}\n          />\n        </>\n      )}\n      {showAlt && (\n        <button\n          type=\"button\"\n          title={ct.altText}\n          className={btnCls}\n          onClick={() => api?.setAltOnSelection()}\n        >\n          {kind === 'image' ? <ImageIcon size={15} /> : <BarChart3 size={15} />}\n        </button>\n      )}\n      <div className=\"mx-0.5 h-5 w-px bg-panel-border\" aria-hidden />\n      <button\n        type=\"button\"\n        title={ct.bringForward}\n        className={btnCls}\n        onClick={() => api?.bringSelectedForward?.()}\n      >\n        <ArrowUp size={15} />\n      </button>\n      <button\n        type=\"button\"\n        title={ct.sendBackward}\n        className={btnCls}\n        onClick={() => api?.sendSelectedBackward?.()}\n      >\n        <ArrowDown size={15} />\n      </button>\n      <button\n        type=\"button\"\n        title={ct.bringToFront}\n        className={btnCls}\n        onClick={() => api?.bringSelectedToFront?.()}\n      >\n        <ArrowUpToLine size={15} />\n      </button>\n      <button\n        type=\"button\"\n        title={ct.sendToBack}\n        className={btnCls}\n        onClick={() => api?.sendSelectedToBack?.()}\n      >\n        <ArrowDownToLine size={15} />\n      </button>\n      <div className=\"mx-0.5 h-5 w-px bg-panel-border\" aria-hidden />\n      <button\n        type=\"button\"\n        title={ct.duplicate(modShortcut('D'))}\n        className={btnCls}\n        onClick={() => api?.duplicateSelected()}\n      >\n        <Copy size={15} />\n      </button>\n      <button\n        type=\"button\"\n        title={ct.remove('Del')}\n        className={btnCls}\n        onClick={() => api?.removeSelected()}\n      >\n        <Trash2 size={15} />\n      </button>\n\n      {jobsOpen &&\n        createPortal(\n          <div\n            className=\"fixed inset-0 z-[300] flex items-center justify-center bg-black/60 p-4\"\n            style={modeAccentVars(mode)}\n            data-we-mode={mode}\n          >\n            <button\n              type=\"button\"\n              className=\"absolute inset-0 cursor-default\"\n              aria-label=\"Close\"\n              onClick={() => setJobsOpen(false)}\n            />\n            <div className=\"relative z-[301] flex max-h-[min(80vh,32rem)] w-full max-w-lg flex-col overflow-hidden rounded-2xl border border-panel-border bg-panel shadow-2xl\">\n              <div className=\"flex items-center justify-between border-b border-panel-border px-4 py-3\">\n                <TextTitle as=\"h3\" size=\"sm\" className=\"text-white\">\n                  {ct.replaceFromFiles}\n                </TextTitle>\n                <button\n                  type=\"button\"\n                  className={btnCls}\n                  onClick={() => setJobsOpen(false)}\n                  aria-label=\"Close\"\n                >\n                  <X size={14} />\n                </button>\n              </div>\n              <div className=\"min-h-0 max-h-[min(60vh,22rem)] flex-1 overflow-y-auto overscroll-contain p-3\">\n                {jobsLoading ? (\n                  <div className=\"grid grid-cols-3 gap-2\">\n                    {Array.from({ length: 9 }).map((_, i) => (\n                      <div\n                        key={i}\n                        className=\"aspect-square animate-pulse rounded-xl border border-panel-border bg-black-capsule\"\n                      />\n                    ))}\n                  </div>\n                ) : jobs.length === 0 ? (\n                  <TextBody as=\"p\" size=\"sm\" className=\"py-8 text-center text-white/80\">\n                    {t.slides.libraryPanel.jobsEmpty}\n                  </TextBody>\n                ) : (\n                  <div className=\"grid grid-cols-3 gap-2\">\n                    {jobs.map((item) => (\n                      <button\n                        key={item.id}\n                        type=\"button\"\n                        disabled={replacingId === item.id}\n                        title={item.name}\n                        onClick={() => void replaceFromJob(item)}\n                        className=\"relative aspect-square overflow-hidden rounded-xl border border-panel-border bg-black-capsule hover:border-[var(--we-accent)]\"\n                      >\n                        {item.kind === 'image' ? (\n                          <img src={item.url} alt=\"\" className=\"h-full w-full object-cover\" />\n                        ) : (\n                          <TextBody as=\"span\" size=\"sm\" className=\"flex h-full w-full items-center justify-center text-white/80\">\n                            <ImageIcon size={20} />\n                          </TextBody>\n                        )}\n                        {replacingId === item.id ? (\n                          <TextBody as=\"span\" size=\"sm\" className=\"absolute inset-0 flex items-center justify-center bg-black/50\">\n                            <Loader2 size={16} className=\"animate-spin text-white\" />\n                          </TextBody>\n                        ) : null}\n                      </button>\n                    ))}\n                  </div>\n                )}\n              </div>\n            </div>\n          </div>,\n          document.body,\n        )}\n    </div>\n  );\n};\n\nexport default SlidesContextToolbar;\n", "import React, { useEffect, useLayoutEffect, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n  AlignCenter,\n  AlignLeft,\n  AlignRight,\n  ArrowDown,\n  ArrowDownToLine,\n  ArrowUp,\n  ArrowUpToLine,\n  Copy,\n  Magnet,\n  Trash2,\n  Type,\n} from 'lucide-react';\nimport { useTranslation } from '../../i18n';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { useSlidesUiStore } from '../../store/useSlidesUiStore';\nimport { modeAccentVars, useModeAccent } from '../../theme/modeAccent';\nimport { getSlidesCanvasApi } from './SlideCanvas';\nimport { TextBody, TextTitle } from '../ui';\n\ntype MenuAction = {\n  id: string;\n  label: string;\n  icon: React.ReactNode;\n  disabled?: boolean;\n  danger?: boolean;\n  dividerBefore?: boolean;\n  onClick: () => void;\n};\n\n/** Canvas right-click menu \u2014 layers, copy, delete, align, snap (same clamp pattern as image CanvasArea). */\nexport const SlidesContextMenu: React.FC = () => {\n  const t = useTranslation();\n  const mode = useModeAccent();\n  const pos = useSlidesUiStore((s) => s.contextMenu);\n  const setContextMenu = useSlidesUiStore((s) => s.setContextMenu);\n  const showGuides = useSlidesStore((s) => s.showGuides);\n  const setShowGuides = useSlidesStore((s) => s.setShowGuides);\n  const selectedCount = useSlidesStore((s) => s.selectedObjectIds.length);\n  const menuRef = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    if (!pos) return;\n    const onPointerDown = (e: PointerEvent) => {\n      const el = menuRef.current;\n      if (el && el.contains(e.target as Node)) return;\n      setContextMenu(null);\n    };\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') setContextMenu(null);\n    };\n    // Defer so the opening right-click does not immediately dismiss the menu.\n    const timer = window.setTimeout(() => {\n      window.addEventListener('pointerdown', onPointerDown, true);\n    }, 0);\n    window.addEventListener('keydown', onKey);\n    return () => {\n      window.clearTimeout(timer);\n      window.removeEventListener('pointerdown', onPointerDown, true);\n      window.removeEventListener('keydown', onKey);\n    };\n  }, [pos, setContextMenu]);\n\n  // Clamp inside the viewport before paint (no internal scroll, never clips).\n  useLayoutEffect(() => {\n    if (!pos) return;\n    const el = menuRef.current;\n    if (!el) return;\n    const margin = 8;\n    const menuW = el.offsetWidth;\n    const menuH = el.offsetHeight;\n    const x = Math.max(margin, Math.min(pos.x, window.innerWidth - menuW - margin));\n    const y = Math.max(margin, Math.min(pos.y, window.innerHeight - menuH - margin));\n    el.style.left = `${x}px`;\n    el.style.top = `${y}px`;\n  }, [pos, selectedCount, showGuides]);\n\n  if (!pos) return null;\n\n  const api = getSlidesCanvasApi();\n  const hasSel = selectedCount > 0;\n  const multi = selectedCount >= 2;\n  const ct = t.slides.contextToolbar;\n  const cm = t.slides.contextMenu;\n\n  const actions: MenuAction[] = [\n    {\n      id: 'bring-forward',\n      label: cm.bringForward,\n      icon: <ArrowUp size={14} />,\n      disabled: !hasSel,\n      onClick: () => api?.bringSelectedForward?.(),\n    },\n    {\n      id: 'send-backward',\n      label: cm.sendBackward,\n      icon: <ArrowDown size={14} />,\n      disabled: !hasSel,\n      onClick: () => api?.sendSelectedBackward?.(),\n    },\n    {\n      id: 'bring-front',\n      label: cm.bringToFront,\n      icon: <ArrowUpToLine size={14} />,\n      disabled: !hasSel,\n      onClick: () => api?.bringSelectedToFront?.(),\n    },\n    {\n      id: 'send-back',\n      label: cm.sendToBack,\n      icon: <ArrowDownToLine size={14} />,\n      disabled: !hasSel,\n      onClick: () => api?.sendSelectedToBack?.(),\n    },\n    {\n      id: 'align-left',\n      label: ct.alignLeft,\n      icon: <AlignLeft size={14} />,\n      disabled: !multi,\n      dividerBefore: true,\n      onClick: () => api?.runAlign('left'),\n    },\n    {\n      id: 'align-center',\n      label: ct.alignCenter,\n      icon: <AlignCenter size={14} />,\n      disabled: !multi,\n      onClick: () => api?.runAlign('center'),\n    },\n    {\n      id: 'align-right',\n      label: ct.alignRight,\n      icon: <AlignRight size={14} />,\n      disabled: !multi,\n      onClick: () => api?.runAlign('right'),\n    },\n    {\n      id: 'autofit',\n      label: ct.autofitText,\n      icon: <Type size={14} />,\n      disabled: !hasSel,\n      onClick: () => api?.runAutofit(),\n    },\n    {\n      id: 'duplicate',\n      label: cm.copy,\n      icon: <Copy size={14} />,\n      disabled: !hasSel,\n      dividerBefore: true,\n      onClick: () => api?.duplicateSelected(),\n    },\n    {\n      id: 'snap',\n      label: showGuides ? cm.snapOn : cm.snapOff,\n      icon: <Magnet size={14} />,\n      onClick: () => setShowGuides(!showGuides),\n    },\n    {\n      id: 'delete',\n      label: cm.delete,\n      icon: <Trash2 size={14} />,\n      disabled: !hasSel,\n      danger: true,\n      dividerBefore: true,\n      onClick: () => api?.removeSelected(),\n    },\n  ];\n\n  return createPortal(\n    <>\n      <div\n        className=\"fixed inset-0 z-[319] cursor-default\"\n        style={modeAccentVars(mode)}\n        data-we-mode={mode}\n        aria-hidden\n        onContextMenu={(e) => {\n          e.preventDefault();\n          setContextMenu(null);\n        }}\n      />\n      <div\n        ref={menuRef}\n        role=\"menu\"\n        data-slides-context-menu\n        data-we-mode={mode}\n        style={{\n          ...modeAccentVars(mode),\n          left: pos.x,\n          top: pos.y,\n        }}\n        className=\"fixed z-[320] flex min-w-[210px] flex-col gap-0.5 rounded-xl border border-panel-border bg-panel p-1.5 shadow-2xl shadow-black/50\"\n        onContextMenu={(e) => e.preventDefault()}\n      >\n        <TextTitle as=\"p\" size=\"xs\" className=\"px-2.5 py-1 uppercase tracking-wider text-white/80\">\n          {cm.title}\n        </TextTitle>\n        {actions.map((a) => (\n          <React.Fragment key={a.id}>\n            {a.dividerBefore ? (\n              <div className=\"mx-1.5 my-1 h-px bg-panel-border\" aria-hidden />\n            ) : null}\n            <button\n              type=\"button\"\n              role=\"menuitem\"\n              disabled={a.disabled}\n              onClick={() => {\n                a.onClick();\n                setContextMenu(null);\n              }}\n              className={`flex w-full items-center gap-2 rounded-lg px-2.5 py-1.5 text-left transition-colors disabled:opacity-40 ${\n                a.danger\n                  ? 'text-rose-300 hover:bg-rose-500/15'\n                  : 'text-white hover:bg-[var(--we-accent-muted)] hover:text-[var(--we-accent)]'\n              }`}\n            >\n              {a.icon}\n              <TextBody as=\"span\" size=\"sm\">\n                {a.label}\n              </TextBody>\n            </button>\n          </React.Fragment>\n        ))}\n      </div>\n    </>,\n    document.body,\n  );\n};\n", "import React, { useEffect, useState } from 'react';\nimport { useTranslation } from '../../i18n';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { useSlidesUiStore } from '../../store/useSlidesUiStore';\nimport { getSlidesCanvasApi } from './SlideCanvas';\nimport { Button, Modal, TextBody, TextTitle } from '../ui';\n\n/** Modal to edit accessibility alt text on the selected image/object. */\nexport const SlidesAltTextModal: React.FC = () => {\n  const t = useTranslation();\n  const at = t.slides.altTextModal;\n  const modal = useSlidesUiStore((s) => s.altTextModal);\n  const setAltTextModal = useSlidesUiStore((s) => s.setAltTextModal);\n  const activeSlideId = useSlidesStore((s) => s.activeSlideId);\n  const setObjectAlt = useSlidesStore((s) => s.setObjectAlt);\n  const [value, setValue] = useState('');\n\n  useEffect(() => {\n    setValue(modal?.value ?? '');\n  }, [modal]);\n\n  if (!modal) return null;\n\n  const close = () => setAltTextModal(null);\n\n  const save = () => {\n    if (!activeSlideId) {\n      close();\n      return;\n    }\n    const next = value.trim();\n    setObjectAlt(activeSlideId, modal.objectId, next);\n    const canvas = getSlidesCanvasApi()?.getCanvas?.();\n    const objs = canvas?.getObjects() ?? [];\n    for (const o of objs) {\n      const id = (o as { id?: string }).id;\n      if (id === modal.objectId) {\n        (o as { alt?: string }).alt = next;\n      }\n    }\n    getSlidesCanvasApi()?.persist?.();\n    canvas?.requestRenderAll();\n    close();\n  };\n\n  return (\n    <Modal isOpen title={at.title} onClose={close} size=\"sm\" bodyClassName=\"flex flex-col gap-3\">\n      <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{at.hint}</TextBody>\n      <textarea\n        value={value}\n        onChange={(e) => setValue(e.target.value)}\n        placeholder={at.placeholder}\n        rows={4}\n        className=\"w-full resize-y rounded-xl border border-panel-border bg-black-capsule px-3 py-2 font-sans text-[13px] font-medium text-white outline-none placeholder:text-white/40 focus:border-[var(--we-accent)]\"\n        autoFocus\n      />\n      <div className=\"flex justify-end gap-2\">\n        <Button variant=\"secondary\" size=\"sm\" onClick={close}>\n          {at.cancel}\n        </Button>\n        <Button variant=\"accent\" size=\"sm\" onClick={save}>\n          {at.save}\n        </Button>\n      </div>\n    </Modal>\n  );\n};\n", "import React, { useRef, useState } from 'react';\nimport { Magnet, Square, Image, Type, Frame } from 'lucide-react';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { useTranslation } from '../../i18n';\nimport { ViewportPortalMenu } from '../../utils/ViewportPortalMenu';\nimport { TextBody, TextTitle } from '../ui';\n\nconst SnapSwitchRow: React.FC<{\n  label: string;\n  icon: React.ReactNode;\n  checked: boolean;\n  disabled?: boolean;\n  onChange: (next: boolean) => void;\n}> = ({ label, icon, checked, disabled = false, onChange }) => (\n  <button\n    type=\"button\"\n    role=\"switch\"\n    aria-checked={checked}\n    disabled={disabled}\n    onClick={() => onChange(!checked)}\n    className={`flex items-center justify-between gap-3 rounded-lg p-2 text-left transition-colors ${\n      disabled\n        ? 'cursor-not-allowed text-white/80 opacity-40'\n        : 'cursor-pointer text-white hover:bg-black-capsule'\n    }`}\n  >\n    <span className=\"flex min-w-0 items-center gap-2.5\">\n      {icon}\n      <TextBody as=\"span\" size=\"sm\" className=\"truncate font-semibold\">\n        {label}\n      </TextBody>\n    </span>\n    <span\n      className={`relative inline-flex h-5 w-9 shrink-0 rounded-full transition-colors ${\n        checked ? 'bg-[var(--we-accent)]' : 'bg-black-capsule'\n      }`}\n    >\n      <span\n        className={`absolute top-0.5 left-0.5 h-4 w-4 rounded-full bg-white shadow transition-transform ${\n          checked ? 'translate-x-4' : 'translate-x-0'\n        }`}\n      />\n    </span>\n  </button>\n);\n\n/** Magnetic snap control for slides bottom toolbar (mirrors image SnapMagnetButton). */\nexport const SlidesSnapMagnetButton: React.FC = () => {\n  const t = useTranslation();\n  const [open, setOpen] = useState(false);\n  const triggerRef = useRef<HTMLButtonElement | null>(null);\n  const snapSettings = useSlidesStore((s) => s.snapSettings);\n  const setSnapSettings = useSlidesStore((s) => s.setSnapSettings);\n\n  return (\n    <div className=\"relative\">\n      <button\n        ref={triggerRef}\n        type=\"button\"\n        onClick={() => setOpen((o) => !o)}\n        title={t.toolbar.image.snapping}\n        aria-label={t.toolbar.image.snapping}\n        aria-expanded={open}\n        className={`relative flex h-8 w-8 items-center justify-center rounded-lg transition-all active:scale-90 ${\n          snapSettings.enabled || open\n            ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--we-accent)_35%,transparent)]'\n            : 'text-white/80 hover:bg-black-capsule hover:text-white'\n        }`}\n      >\n        <Magnet size={14} />\n      </button>\n\n      <ViewportPortalMenu\n        open={open}\n        onClose={() => setOpen(false)}\n        anchorRef={triggerRef}\n        prefer=\"above\"\n        zIndex={40}\n        className=\"flex w-56 flex-col gap-0.5 rounded-xl border border-panel-border bg-panel p-1.5 shadow-2xl animate-fade-in\"\n      >\n        <TextTitle as=\"p\" size=\"xs\" className=\"px-2.5 py-1 uppercase tracking-wider text-[var(--we-accent)]\">\n          {t.toolbar.image.snapping}\n        </TextTitle>\n        <SnapSwitchRow\n          label={t.toolbar.image.snapMaster}\n          icon={<Magnet size={13} className=\"text-white/80\" />}\n          checked={snapSettings.enabled}\n          onChange={(enabled) => setSnapSettings({ enabled })}\n        />\n        <div className=\"my-1 h-px bg-panel-border\" />\n        <SnapSwitchRow\n          label={t.toolbar.image.snapShapes}\n          icon={<Square size={13} className=\"text-white/80\" />}\n          checked={snapSettings.shapes}\n          disabled={!snapSettings.enabled}\n          onChange={(shapes) => setSnapSettings({ shapes })}\n        />\n        <SnapSwitchRow\n          label={t.toolbar.image.snapImages}\n          icon={<Image size={13} className=\"text-white/80\" />}\n          checked={snapSettings.images}\n          disabled={!snapSettings.enabled}\n          onChange={(images) => setSnapSettings({ images })}\n        />\n        <SnapSwitchRow\n          label={t.toolbar.image.snapText}\n          icon={<Type size={13} className=\"text-white/80\" />}\n          checked={snapSettings.text}\n          disabled={!snapSettings.enabled}\n          onChange={(text) => setSnapSettings({ text })}\n        />\n        <SnapSwitchRow\n          label={t.toolbar.image.snapCanvasEdges}\n          icon={<Frame size={13} className=\"text-white/80\" />}\n          checked={snapSettings.canvasEdges}\n          disabled={!snapSettings.enabled}\n          onChange={(canvasEdges) => setSnapSettings({ canvasEdges })}\n        />\n      </ViewportPortalMenu>\n    </div>\n  );\n};\n", "import React from 'react';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { useTranslation } from '../../i18n';\nimport { PanelBody, PanelSection, TextBody, TextTitle } from '../ui';\n\ntype NotesPanelProps = {\n  /** Compact strip under the canvas preview. */\n  variant?: 'panel' | 'dock';\n};\n\nexport const NotesPanel: React.FC<NotesPanelProps> = ({ variant = 'panel' }) => {\n  const t = useTranslation();\n  const { slides, activeSlideId, setSlideNotes } = useSlidesStore();\n  const slide = slides.find((s) => s.id === activeSlideId);\n\n  if (!slide) {\n    return (\n      <TextBody as=\"p\" size=\"sm\" className=\"p-3 text-white/80\">\n        {t.slides.notesPanel.noActiveSlide}\n      </TextBody>\n    );\n  }\n\n  const wordCount = slide.notes.trim().split(/\\s+/).filter(Boolean).length;\n\n  if (variant === 'dock') {\n    return (\n      <div className=\"flex h-28 shrink-0 flex-col border-t border-panel-border bg-panel px-3 py-2\">\n        <div className=\"mb-1 flex items-center justify-between gap-2\">\n          <TextTitle as=\"span\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n            {t.slides.notesPanel.label}\n          </TextTitle>\n          <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n            {t.slides.notesPanel.wordCount(wordCount)} \u00B7 {t.slides.notesPanel.estMinutes(wordCount)}\n          </TextBody>\n        </div>\n        <textarea\n          value={slide.notes}\n          onChange={(e) => setSlideNotes(slide.id, e.target.value)}\n          placeholder={t.slides.notesPanel.placeholder}\n          className=\"min-h-0 w-full flex-1 resize-none rounded-xl border border-panel-border bg-black-capsule px-3 py-2 font-sans text-[12px] font-medium leading-relaxed text-white outline-none placeholder:text-white/40 focus:border-[var(--we-accent)]\"\n        />\n      </div>\n    );\n  }\n\n  return (\n    <PanelBody className=\"h-full\">\n      <PanelSection title={t.slides.notesPanel.label} className=\"min-h-0 flex-1\">\n        <textarea\n          value={slide.notes}\n          onChange={(e) => setSlideNotes(slide.id, e.target.value)}\n          placeholder={t.slides.notesPanel.placeholder}\n          className=\"min-h-40 w-full flex-1 resize-none rounded-xl border border-panel-border bg-black-capsule px-3 py-2 font-sans text-[13px] font-medium leading-relaxed text-white outline-none placeholder:text-white/40 focus:border-[var(--we-accent)]\"\n        />\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n          {t.slides.notesPanel.wordCount(wordCount)} \u00B7 {t.slides.notesPanel.estMinutes(wordCount)}\n        </TextBody>\n      </PanelSection>\n    </PanelBody>\n  );\n};\n", "/** Unit conversions for PPTX (English Metric Units). 914400 EMU = 1 inch. @96dpi: 9525 EMU/px. */\n\nexport const EMU_PER_INCH = 914400;\nexport const PX_PER_INCH = 96;\nexport const EMU_PER_PX = EMU_PER_INCH / PX_PER_INCH; // 9525\n\nexport function pxToInches(px: number): number {\n  return px / PX_PER_INCH;\n}\n\nexport function inchesToPx(inches: number): number {\n  return inches * PX_PER_INCH;\n}\n\nexport function pxToEmu(px: number): number {\n  return Math.round(px * EMU_PER_PX);\n}\n\nexport function emuToPx(emu: number): number {\n  return emu / EMU_PER_PX;\n}\n\nexport function ptToPx(pt: number): number {\n  return (pt * PX_PER_INCH) / 72;\n}\n\nexport function pxToPt(px: number): number {\n  return (px * 72) / PX_PER_INCH;\n}\n", "import type pptxgen from 'pptxgenjs';\nimport { pxToInches, pxToPt } from './emu';\nimport { chartDataToPptxSeries, type SlideChartData } from '../chartBridge';\n\ntype PptxSlide = ReturnType<InstanceType<typeof pptxgen>['addSlide']>;\n\nfunction colorToHex(fill: unknown): string | undefined {\n  if (typeof fill !== 'string') return undefined;\n  if (fill.startsWith('#')) return fill.replace('#', '');\n  if (fill.startsWith('rgb')) {\n    const m = fill.match(/\\d+/g);\n    if (!m || m.length < 3) return undefined;\n    const [r, g, b] = m.map(Number);\n    return [r, g, b]\n      .map((n) => Math.max(0, Math.min(255, n || 0)).toString(16).padStart(2, '0'))\n      .join('');\n  }\n  return undefined;\n}\n\nexport function addFabricObjectToSlide(\n  slide: PptxSlide,\n  obj: Record<string, unknown>,\n  opts?: { fallbackRaster?: (o: Record<string, unknown>) => string | null }\n): 'native' | 'raster' | 'skipped' {\n  const type = String(obj.type || '');\n  const left = Number(obj.left || 0);\n  const top = Number(obj.top || 0);\n  const width = Number(obj.width || 0) * Number(obj.scaleX || 1);\n  const height = Number(obj.height || 0) * Number(obj.scaleY || 1);\n  const rotate = Number(obj.angle || 0);\n\n  if (type === 'Textbox' || type === 'IText' || type === 'Text') {\n    const text = String(obj.text || '');\n    const fontSize = pxToPt(Number(obj.fontSize || 18));\n    const color = colorToHex(obj.fill) || '000000';\n    const align =\n      obj.textAlign === 'center' ? 'center' : obj.textAlign === 'right' ? 'right' : 'left';\n    const bold = obj.fontWeight === 'bold' || Number(obj.fontWeight) >= 600;\n    const italic = obj.fontStyle === 'italic';\n    slide.addText(text, {\n      x: pxToInches(left),\n      y: pxToInches(top),\n      w: pxToInches(Math.max(width, 10)),\n      h: pxToInches(Math.max(height, 10)),\n      fontSize,\n      fontFace: String(obj.fontFamily || 'Arial'),\n      color,\n      bold,\n      italic,\n      align,\n      valign: 'top',\n      rotate,\n      wrap: true,\n    });\n    return 'native';\n  }\n\n  if (type === 'Rect' || type === 'Circle' || type === 'Ellipse' || type === 'Triangle' || type === 'Line') {\n    const fill = colorToHex(obj.fill);\n    const line = colorToHex(obj.stroke);\n    let shape: 'rect' | 'ellipse' | 'triangle' | 'line' = 'rect';\n    if (type === 'Circle' || type === 'Ellipse') shape = 'ellipse';\n    if (type === 'Triangle') shape = 'triangle';\n    if (type === 'Line') shape = 'line';\n    slide.addShape(shape, {\n      x: pxToInches(left),\n      y: pxToInches(top),\n      w: pxToInches(Math.max(width, 1)),\n      h: pxToInches(Math.max(height, 1)),\n      fill: fill ? { color: fill } : undefined,\n      line: line ? { color: line, width: Number(obj.strokeWidth || 1) } : { color: 'FFFFFF', width: 0 },\n      rotate,\n      rectRadius: type === 'Rect' ? pxToInches(Number(obj.rx || 0)) : undefined,\n    });\n    return 'native';\n  }\n\n  if (type === 'Image' || type === 'FabricImage') {\n    const chartData = obj.chartData as SlideChartData | undefined;\n    if (chartData?.labels?.length && chartData.series?.length) {\n      const mapped = chartDataToPptxSeries(chartData);\n      slide.addChart(\n        mapped.chartType,\n        mapped.series.map((s) => ({\n          name: s.name,\n          labels: mapped.labels,\n          values: s.values,\n        })),\n        {\n          x: pxToInches(left),\n          y: pxToInches(top),\n          w: pxToInches(Math.max(width, 1)),\n          h: pxToInches(Math.max(height, 1)),\n          showTitle: false,\n          showLegend: true,\n        }\n      );\n      return 'native';\n    }\n    const el = obj._element as { src?: string } | undefined;\n    const src = String(obj.src || el?.src || '');\n    if (src) {\n      slide.addImage({\n        data: src,\n        x: pxToInches(left),\n        y: pxToInches(top),\n        w: pxToInches(Math.max(width, 1)),\n        h: pxToInches(Math.max(height, 1)),\n        rotate,\n      });\n      return 'native';\n    }\n  }\n\n  if (type === 'Group' && Array.isArray(obj.objects)) {\n    for (const child of obj.objects as Record<string, unknown>[]) {\n      addFabricObjectToSlide(slide, {\n        ...child,\n        left: left + Number(child.left || 0),\n        top: top + Number(child.top || 0),\n      }, opts);\n    }\n    return 'native';\n  }\n\n  // Path / custom / filtered \u2192 raster fallback\n  const dataUrl = opts?.fallbackRaster?.(obj) || null;\n  if (dataUrl) {\n    slide.addImage({\n      data: dataUrl,\n      x: pxToInches(left),\n      y: pxToInches(top),\n      w: pxToInches(Math.max(width, 1)),\n      h: pxToInches(Math.max(height, 1)),\n    });\n    return 'raster';\n  }\n\n  return 'skipped';\n}\n", "/**\n * Editable PPTX export \u2014 maps Fabric objects to native pptxgenjs shapes.\n */\n\nimport pptxgen from 'pptxgenjs';\nimport type { SlideDeck } from '../../../types/slides.types';\nimport { composeSlideWithMaster } from '../layouts';\nimport { pxToInches } from './emu';\nimport { addFabricObjectToSlide } from './shapeMap';\nimport { modeExportBasename } from '../../../utils/exportDownloadName';\n\ntype ExportDeck = Pick<SlideDeck, 'name' | 'size' | 'slides' | 'theme' | 'masters'>;\n\nexport async function exportDeckToEditablePptx(\n  deck: ExportDeck,\n  fileName?: string\n): Promise<void> {\n  const pres = new pptxgen();\n  const wIn = pxToInches(deck.size.width);\n  const hIn = pxToInches(deck.size.height);\n  pres.defineLayout({ name: 'WIZARD_DECK', width: wIn, height: hIn });\n  pres.layout = 'WIZARD_DECK';\n\n  const visible = deck.slides.filter((s) => !s.hidden);\n  for (let i = 0; i < visible.length; i++) {\n    const slideData = visible[i]!;\n    const slide = pres.addSlide();\n    const bg = deck.theme.colors.background.replace('#', '');\n    slide.addShape(pres.ShapeType.rect, {\n      x: 0,\n      y: 0,\n      w: wIn,\n      h: hIn,\n      fill: { color: bg },\n      line: { color: bg, width: 0 },\n    });\n\n    const master =\n      deck.masters.find((m) => m.id === slideData.masterId) || deck.masters[0];\n    const composed = master\n      ? composeSlideWithMaster(\n          slideData.json,\n          master,\n          deck.theme,\n          i,\n          visible.length,\n          deck.size\n        )\n      : slideData.json;\n    const json = composed as { objects?: Array<Record<string, unknown>> };\n    for (const obj of json?.objects || []) {\n      addFabricObjectToSlide(slide, obj);\n    }\n\n    if (slideData.notes?.trim()) {\n      slide.addNotes(slideData.notes);\n    }\n  }\n\n  const base = fileName || modeExportBasename('slides');\n  await pres.writeFile({ fileName: `${base}.pptx` });\n}\n\n/** Raster fallback \u2014 one PNG per slide (max visual fidelity). */\nexport async function exportDeckToRasterPptx(\n  deck: Pick<SlideDeck, 'name' | 'size' | 'slides' | 'theme'>,\n  renderSlide: (slideId: string) => Promise<string>,\n  fileName?: string\n): Promise<void> {\n  const pres = new pptxgen();\n  const wIn = pxToInches(deck.size.width);\n  const hIn = pxToInches(deck.size.height);\n  pres.defineLayout({ name: 'WIZARD_DECK_R', width: wIn, height: hIn });\n  pres.layout = 'WIZARD_DECK_R';\n\n  for (const slideData of deck.slides) {\n    if (slideData.hidden) continue;\n    const slide = pres.addSlide();\n    const dataUrl = await renderSlide(slideData.id);\n    slide.addImage({ data: dataUrl, x: 0, y: 0, w: wIn, h: hIn });\n    if (slideData.notes?.trim()) slide.addNotes(slideData.notes);\n  }\n\n  const base = fileName || modeExportBasename('slides');\n  await pres.writeFile({ fileName: `${base}.pptx` });\n}\n", "/**\n * Export helpers for Slides Studio: PDF, HTML, PNG zip, MP4, handoffs.\n */\n\nimport { StaticCanvas } from 'fabric';\nimport { jsPDF } from 'jspdf';\nimport { zipSync, strToU8 } from 'fflate';\nimport type { ElementBuild, Slide, SlideDeck, SlideMaster } from '../types/slides.types';\nimport { composeSlideWithMaster } from '../lib/slides/layouts';\nimport { exportDeckToEditablePptx, exportDeckToRasterPptx } from '../lib/slides/pptx/exportPptx';\nimport { modeExportFilename } from './exportDownloadName';\n\nexport type ExportableDeck = Pick<SlideDeck, 'name' | 'size' | 'slides' | 'theme' | 'masters'>;\n\nasync function renderSlideDataUrl(\n  json: unknown,\n  width: number,\n  height: number,\n  bg: string,\n  format: 'png' | 'jpeg' = 'png'\n): Promise<string> {\n  const el = document.createElement('canvas');\n  const canvas = new StaticCanvas(el, { width, height, renderOnAddRemove: false });\n  await canvas.loadFromJSON(json || { objects: [] });\n  canvas.backgroundColor = bg;\n  canvas.requestRenderAll();\n  await new Promise((r) => setTimeout(r, 50));\n  const url = canvas.toDataURL({ format, quality: 0.92, multiplier: 1 });\n  canvas.dispose();\n  return url;\n}\n\nfunction visibleSlides(deck: ExportableDeck): Slide[] {\n  return deck.slides.filter((s) => !s.hidden);\n}\n\nfunction composedJsonForSlide(\n  deck: ExportableDeck,\n  slide: Slide,\n  pageIndex: number,\n  pageCount: number\n): unknown {\n  const master: SlideMaster | undefined =\n    deck.masters.find((m) => m.id === slide.masterId) || deck.masters[0];\n  if (!master) return slide.json;\n  return composeSlideWithMaster(\n    slide.json,\n    master,\n    deck.theme,\n    pageIndex,\n    pageCount,\n    deck.size\n  );\n}\n\n/** Hide build-gated objects until their step is reached. */\nexport function applyBuildVisibility(\n  json: unknown,\n  builds: ElementBuild[] | undefined,\n  step: number\n): unknown {\n  const doc = structuredClone(json || { objects: [] }) as {\n    objects?: Array<Record<string, unknown>>;\n  };\n  const ordered = [...(builds || [])].sort((a, b) => a.order - b.order);\n  if (!ordered.length) return doc;\n  const buildIds = new Set(ordered.map((b) => b.objectId));\n  const visibleIds = new Set(ordered.slice(0, Math.max(0, step)).map((b) => b.objectId));\n  for (const o of doc.objects || []) {\n    const id = String(o.id || '');\n    if (buildIds.has(id) && !visibleIds.has(id)) {\n      o.opacity = 0;\n    }\n  }\n  return doc;\n}\n\nfunction dataUrlToUint8(dataUrl: string): Uint8Array {\n  const b64 = dataUrl.split(',')[1] || '';\n  const bin = atob(b64);\n  const out = new Uint8Array(bin.length);\n  for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n  return out;\n}\n\nfunction downloadBlob(blob: Blob, filename: string) {\n  const a = document.createElement('a');\n  a.href = URL.createObjectURL(blob);\n  a.download = filename;\n  a.click();\n  URL.revokeObjectURL(a.href);\n}\n\nexport async function exportSlidesPdf(\n  deck: ExportableDeck,\n  mode: 'slides' | 'notes' | 'handout-2' | 'handout-4' | 'handout-6' = 'slides'\n): Promise<void> {\n  const visible = visibleSlides(deck);\n  if (!visible.length) return;\n\n  if (mode === 'slides' || mode === 'notes') {\n    const pdf = new jsPDF({\n      orientation: deck.size.width > deck.size.height ? 'landscape' : 'portrait',\n      unit: 'px',\n      format: [deck.size.width, deck.size.height],\n    });\n    for (let i = 0; i < visible.length; i++) {\n      const slide = visible[i]!;\n      const json = composedJsonForSlide(deck, slide, i, visible.length);\n      const dataUrl = await renderSlideDataUrl(\n        json,\n        deck.size.width,\n        deck.size.height,\n        deck.theme.colors.background,\n        'jpeg'\n      );\n      if (i > 0) pdf.addPage([deck.size.width, deck.size.height]);\n      pdf.addImage(dataUrl, 'JPEG', 0, 0, deck.size.width, deck.size.height);\n      if (mode === 'notes' && slide.notes) {\n        pdf.setFontSize(14);\n        pdf.setTextColor(40);\n        pdf.addPage([deck.size.width, deck.size.height]);\n        pdf.text(slide.notes, 40, 60, { maxWidth: deck.size.width - 80 });\n      }\n    }\n    pdf.save(modeExportFilename('slides', 'pdf'));\n    return;\n  }\n\n  const perPage = mode === 'handout-2' ? 2 : mode === 'handout-4' ? 4 : 6;\n  const cols = mode === 'handout-2' ? 1 : 2;\n  const rows = Math.ceil(perPage / cols);\n  const pageW = 842;\n  const pageH = 595;\n  const pdf = new jsPDF({ orientation: 'landscape', unit: 'px', format: [pageW, pageH] });\n  const cellW = (pageW - 40) / cols;\n  const cellH = (pageH - 40) / rows;\n\n  for (let i = 0; i < visible.length; i++) {\n    if (i > 0 && i % perPage === 0) pdf.addPage([pageW, pageH]);\n    const slot = i % perPage;\n    const col = slot % cols;\n    const row = Math.floor(slot / cols);\n    const slide = visible[i]!;\n    const dataUrl = await renderSlideDataUrl(\n      composedJsonForSlide(deck, slide, i, visible.length),\n      deck.size.width,\n      deck.size.height,\n      deck.theme.colors.background,\n      'jpeg'\n    );\n    pdf.addImage(dataUrl, 'JPEG', 20 + col * cellW, 20 + row * cellH, cellW - 10, cellH - 10);\n  }\n  pdf.save(modeExportFilename('slides', 'pdf'));\n}\n\nexport async function exportSlidesHtml(deck: ExportableDeck): Promise<void> {\n  const visible = visibleSlides(deck);\n  type Frame = { img: string; notes: string; transition: string; slideIndex: number };\n  const frames: Frame[] = [];\n\n  for (let i = 0; i < visible.length; i++) {\n    const s = visible[i]!;\n    const composed = composedJsonForSlide(deck, s, i, visible.length);\n    const builds = s.builds || [];\n    const steps = builds.length ? builds.length : 0;\n    // step 0 = base (no build objects); then reveal each build\n    for (let step = 0; step <= steps; step++) {\n      const json = applyBuildVisibility(composed, builds, step);\n      frames.push({\n        img: await renderSlideDataUrl(\n          json,\n          deck.size.width,\n          deck.size.height,\n          deck.theme.colors.background\n        ),\n        notes: s.notes || '',\n        transition: s.transition?.type || 'none',\n        slideIndex: i,\n      });\n    }\n  }\n\n  const html = `<!doctype html><html><head><meta charset=\"utf-8\"/><title>${escapeHtml(deck.name)}</title>\n<style>\nbody{margin:0;background:#0a0a0f;color:#f0f0f5;font-family:system-ui,sans-serif}\n#stage{display:flex;align-items:center;justify-content:center;height:100vh;position:relative;overflow:hidden}\nimg{max-width:100%;max-height:100vh;box-shadow:0 10px 40px #000;transition:opacity .28s ease}\nimg.fade{opacity:0}\n#hud{position:fixed;bottom:12px;right:16px;opacity:.55;font-size:12px}\n#notes{position:fixed;left:12px;bottom:12px;max-width:40vw;font-size:11px;opacity:.45}\n</style></head>\n<body>\n<div id=\"stage\"><img id=\"img\" src=\"${frames[0]?.img || ''}\"/></div>\n<div id=\"notes\"></div>\n<div id=\"hud\">1 / ${frames.length}</div>\n<script>\nconst frames=${JSON.stringify(frames)};\nlet i=0;\nconst img=document.getElementById('img');\nconst hud=document.getElementById('hud');\nconst notes=document.getElementById('notes');\nfunction paint(){\n  const f=frames[i]; if(!f) return;\n  img.className='';\n  requestAnimationFrame(()=>{ img.src=f.img; });\n  hud.textContent=(i+1)+' / '+frames.length+' \u00B7 slide '+(f.slideIndex+1);\n  notes.textContent=f.notes||'';\n}\nfunction next(){\n  if(i>=frames.length-1) return;\n  img.className='fade';\n  setTimeout(()=>{ i++; paint(); }, 220);\n}\nfunction prev(){ if(i<=0) return; i--; paint(); }\nwindow.onkeydown=e=>{\n  if(e.key==='ArrowRight'||e.key===' ') { e.preventDefault(); next(); }\n  if(e.key==='ArrowLeft') { e.preventDefault(); prev(); }\n};\npaint();\n</script></body></html>`;\n  downloadBlob(new Blob([html], { type: 'text/html' }), modeExportFilename('slides', 'html'));\n}\n\nfunction escapeHtml(s: string): string {\n  return String(s || '')\n    .replace(/&/g, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;')\n    .replace(/\"/g, '&quot;');\n}\n\nexport async function exportSlidesPngZip(deck: ExportableDeck): Promise<void> {\n  const visible = visibleSlides(deck);\n  const files: Record<string, Uint8Array> = {};\n  for (let i = 0; i < visible.length; i++) {\n    const s = visible[i]!;\n    const url = await renderSlideDataUrl(\n      composedJsonForSlide(deck, s, i, visible.length),\n      deck.size.width,\n      deck.size.height,\n      deck.theme.colors.background\n    );\n    files[`slide-${String(i + 1).padStart(2, '0')}.png`] = dataUrlToUint8(url);\n  }\n  files['manifest.json'] = strToU8(\n    JSON.stringify({ name: deck.name, count: visible.length, size: deck.size }, null, 2)\n  );\n  const zipped = zipSync(files);\n  downloadBlob(new Blob([zipped], { type: 'application/zip' }), modeExportFilename('slides', 'zip'));\n}\n\n/** Slideshow via MediaRecorder (WebM in Chromium). */\nexport async function exportSlidesMp4(\n  deck: ExportableDeck,\n  opts?: { secondsPerSlide?: number; onProgress?: (p: number) => void }\n): Promise<void> {\n  const visible = visibleSlides(deck);\n  if (!visible.length) throw new Error('No hay slides visibles');\n  const seconds = Math.max(1, opts?.secondsPerSlide ?? 3);\n  const w = Math.min(1280, deck.size.width);\n  const h = Math.round((w / deck.size.width) * deck.size.height);\n  const canvas = document.createElement('canvas');\n  canvas.width = w;\n  canvas.height = h;\n  const ctx = canvas.getContext('2d');\n  if (!ctx) throw new Error('Canvas 2D no disponible');\n\n  const stream = canvas.captureStream(30);\n  const mime = MediaRecorder.isTypeSupported('video/webm;codecs=vp9')\n    ? 'video/webm;codecs=vp9'\n    : MediaRecorder.isTypeSupported('video/webm')\n      ? 'video/webm'\n      : '';\n  if (!mime) throw new Error('MediaRecorder no soporta WebM en este navegador');\n\n  const chunks: BlobPart[] = [];\n  const recorder = new MediaRecorder(stream, { mimeType: mime, videoBitsPerSecond: 4_000_000 });\n  recorder.ondataavailable = (e) => {\n    if (e.data.size) chunks.push(e.data);\n  };\n  const done = new Promise<Blob>((resolve, reject) => {\n    recorder.onstop = () => resolve(new Blob(chunks, { type: mime }));\n    recorder.onerror = () => reject(new Error('Error grabando video'));\n  });\n  recorder.start(200);\n\n  for (let i = 0; i < visible.length; i++) {\n    const s = visible[i]!;\n    const url = await renderSlideDataUrl(\n      composedJsonForSlide(deck, s, i, visible.length),\n      deck.size.width,\n      deck.size.height,\n      deck.theme.colors.background,\n      'jpeg'\n    );\n    const img = await loadImage(url);\n    ctx.fillStyle = deck.theme.colors.background;\n    ctx.fillRect(0, 0, w, h);\n    ctx.drawImage(img, 0, 0, w, h);\n    opts?.onProgress?.((i + 1) / visible.length);\n    await sleep(seconds * 1000);\n  }\n\n  recorder.stop();\n  stream.getTracks().forEach((t) => t.stop());\n  const blob = await done;\n  downloadBlob(blob, modeExportFilename('slides', 'webm'));\n}\n\nfunction loadImage(src: string): Promise<HTMLImageElement> {\n  return new Promise((resolve, reject) => {\n    const img = new Image();\n    img.onload = () => resolve(img);\n    img.onerror = () => reject(new Error('No se pudo cargar frame'));\n    img.src = src;\n  });\n}\n\nfunction sleep(ms: number) {\n  return new Promise((r) => setTimeout(r, ms));\n}\n\nexport async function renderSlidesAsImageFiles(\n  deck: ExportableDeck\n): Promise<Array<{ file: File; duration: number; name: string }>> {\n  const visible = visibleSlides(deck);\n  const out: Array<{ file: File; duration: number; name: string }> = [];\n  for (let i = 0; i < visible.length; i++) {\n    const s = visible[i]!;\n    const url = await renderSlideDataUrl(\n      composedJsonForSlide(deck, s, i, visible.length),\n      deck.size.width,\n      deck.size.height,\n      deck.theme.colors.background,\n      'png'\n    );\n    const bytes = dataUrlToUint8(url);\n    const file = new File([new Uint8Array(bytes)], `slide-${String(i + 1).padStart(2, '0')}.png`, {\n      type: 'image/png',\n    });\n    out.push({\n      file,\n      duration: Math.max(2, s.builds?.length ? 2 + s.builds.length * 0.8 : 3),\n      name: s.name || `Slide ${i + 1}`,\n    });\n  }\n  return out;\n}\n\nexport { exportDeckToEditablePptx, exportDeckToRasterPptx, renderSlideDataUrl, composedJsonForSlide };\n", "import React, { useState } from 'react';\nimport {\n  Clapperboard,\n  Download,\n  FileArchive,\n  FileCode2,\n  FileImage,\n  FileSpreadsheet,\n  FileText,\n  Film,\n  Presentation,\n  TextCursorInput,\n} from 'lucide-react';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport {\n  exportSlidesPdf,\n  exportSlidesHtml,\n  exportSlidesPngZip,\n  exportSlidesMp4,\n  exportDeckToEditablePptx,\n  exportDeckToRasterPptx,\n  renderSlideDataUrl,\n  renderSlidesAsImageFiles,\n  composedJsonForSlide,\n} from '../../utils/slidesExport';\nimport {\n  exportProjectToWzrds,\n  slidesProjectFromStore,\n} from '../../utils/slidesProjectFile';\nimport { useVideoStore } from '../../store/useVideoStore';\nimport { useTextStore } from '../../store/useTextStore';\nimport type { EditorMode } from '../editor/EditorModeToggle';\nimport { useTranslation } from '../../i18n';\nimport { modeExportFilename } from '../../utils/exportDownloadName';\nimport { Button, Modal, TextBody, TextTitle } from '../ui';\n\ninterface SlidesExportModalProps {\n  onSwitchMode?: (mode: EditorMode) => void;\n}\n\ntype ExportItem = {\n  id: string;\n  title: string;\n  description: string;\n  icon: React.ReactNode;\n  run: () => Promise<void>;\n};\n\nfunction ExportRow({\n  item,\n  busyId,\n  disabled,\n  onClick,\n}: {\n  item: ExportItem;\n  busyId: string | null;\n  disabled: boolean;\n  onClick: () => void;\n}) {\n  const loading = busyId === item.id;\n  return (\n    <button\n      type=\"button\"\n      disabled={disabled}\n      onClick={onClick}\n      className=\"relative flex w-full cursor-pointer items-start gap-3 overflow-hidden rounded-xl border border-panel-border bg-black-capsule px-3 py-3 text-left transition-colors hover:border-[color-mix(in_srgb,var(--we-accent)_35%,transparent)] hover:bg-[var(--we-accent-muted)] active:scale-[0.99] disabled:pointer-events-none disabled:opacity-50\"\n    >\n      <span className=\"mt-0.5 flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-[var(--we-accent)] text-white\">\n        {item.icon}\n      </span>\n      <span className=\"min-w-0 flex-1\">\n        <TextTitle as=\"span\" size=\"sm\" className=\"block text-white\">\n          {item.title}\n        </TextTitle>\n        <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 block text-pretty leading-snug text-white/80\">\n          {item.description}\n        </TextBody>\n      </span>\n      {loading ? (\n        <span className=\"mt-1 shrink-0\">\n          <svg className=\"h-4 w-4 animate-spin text-[var(--we-accent)]\" fill=\"none\" viewBox=\"0 0 24 24\" aria-hidden>\n            <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n            <path\n              className=\"opacity-75\"\n              fill=\"currentColor\"\n              d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n            />\n          </svg>\n        </span>\n      ) : (\n        <Download size={14} className=\"mt-1 shrink-0 text-white/50\" aria-hidden />\n      )}\n    </button>\n  );\n}\n\nexport const SlidesExportModal: React.FC<SlidesExportModalProps> = ({ onSwitchMode }) => {\n  const tr = useTranslation();\n  const ex = tr.slides.export;\n  const {\n    exportModalOpen,\n    setExportModalOpen,\n    name,\n    size,\n    theme,\n    slides,\n    masters,\n    sections,\n    assets,\n    activeSlideId,\n    schemaVersion,\n    addToast,\n    getOutline,\n  } = useSlidesStore();\n  const [busyId, setBusyId] = useState<string | null>(null);\n\n  if (!exportModalOpen) return null;\n\n  const deck = { name, size, theme, slides, masters };\n  const busy = busyId !== null;\n\n  const run = async (id: string, fn: () => Promise<void>, okLabel: string) => {\n    if (busy) return;\n    setBusyId(id);\n    try {\n      await fn();\n      addToast(ex.toasts.ready(okLabel), 'success');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : ex.toasts.exportError, 'error');\n    } finally {\n      setBusyId(null);\n    }\n  };\n\n  const handoffVideo = async () => {\n    if (busy) return;\n    setBusyId('handoff-video');\n    try {\n      const frames = await renderSlidesAsImageFiles(deck);\n      const aspect = size.width >= size.height ? '16:9' : '9:16';\n      useVideoStore.getState().createVideoProject(name, aspect, theme.colors.background);\n      const vs = useVideoStore.getState();\n      const imageTrack = vs.tracks.find((t) => t.type === 'image');\n      if (!imageTrack) throw new Error(ex.toasts.noImageTrack);\n      let tt = 0;\n      for (const frame of frames) {\n        const assetId = `asset-slide-${Date.now()}-${tt}`;\n        const url = URL.createObjectURL(frame.file);\n        vs.addAsset({\n          id: assetId,\n          name: frame.name,\n          url,\n          type: 'image',\n          duration: frame.duration,\n          width: size.width,\n          height: size.height,\n          file: frame.file,\n          thumbnail: url,\n        });\n        vs.addImageClip({\n          trackId: imageTrack.id,\n          assetId,\n          startTime: tt,\n          duration: frame.duration,\n          trimIn: 0,\n          trimOut: frame.duration,\n          speed: 1,\n          volume: 1,\n          opacity: 1,\n          muted: true,\n          name: frame.name,\n          scaleX: 1,\n          scaleY: 1,\n        });\n        tt += frame.duration;\n      }\n      addToast(ex.toasts.handoffVideo(frames.length), 'success');\n      setExportModalOpen(false);\n      onSwitchMode?.('video');\n    } catch (err) {\n      addToast(err instanceof Error ? err.message : ex.toasts.handoffError, 'error');\n    } finally {\n      setBusyId(null);\n    }\n  };\n\n  const handoffText = () => {\n    if (busy) return;\n    const outline = getOutline();\n    const paragraphs = outline.flatMap((o) => [\n      o.title,\n      ...o.bullets,\n      slides.find((s) => s.id === o.slideId)?.notes || '',\n    ]);\n    useTextStore.getState().createTextProject(name, { docType: 'blog' });\n    useTextStore.getState().importTextProject({\n      name,\n      doc: {\n        type: 'doc',\n        content: paragraphs\n          .filter(Boolean)\n          .map((text, i) =>\n            i % 3 === 0\n              ? { type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text }] }\n              : { type: 'paragraph', content: [{ type: 'text', text }] }\n          ),\n      },\n    });\n    addToast(ex.toasts.handoffText, 'success');\n    setExportModalOpen(false);\n    window.setTimeout(() => onSwitchMode?.('text'), 0);\n  };\n\n  const officeItems: ExportItem[] = [\n    {\n      id: 'pptx-editable',\n      title: ex.formats.pptxEditable.title,\n      description: ex.formats.pptxEditable.description,\n      icon: <Presentation size={16} />,\n      run: () => exportDeckToEditablePptx(deck),\n    },\n    {\n      id: 'pptx-raster',\n      title: ex.formats.pptxRaster.title,\n      description: ex.formats.pptxRaster.description,\n      icon: <FileImage size={16} />,\n      run: () =>\n        exportDeckToRasterPptx(deck, async (id) => {\n          const visible = slides.filter((s) => !s.hidden);\n          const idx = visible.findIndex((x) => x.id === id);\n          const s = slides.find((x) => x.id === id)!;\n          return renderSlideDataUrl(\n            composedJsonForSlide(deck, s, Math.max(0, idx), visible.length),\n            size.width,\n            size.height,\n            theme.colors.background\n          );\n        }),\n    },\n  ];\n\n  const documentItems: ExportItem[] = [\n    {\n      id: 'pdf-slides',\n      title: ex.formats.pdfSlides.title,\n      description: ex.formats.pdfSlides.description,\n      icon: <FileText size={16} />,\n      run: () => exportSlidesPdf(deck, 'slides'),\n    },\n    {\n      id: 'pdf-notes',\n      title: ex.formats.pdfNotes.title,\n      description: ex.formats.pdfNotes.description,\n      icon: <FileSpreadsheet size={16} />,\n      run: () => exportSlidesPdf(deck, 'notes'),\n    },\n    {\n      id: 'pdf-handout',\n      title: ex.formats.pdfHandout4.title,\n      description: ex.formats.pdfHandout4.description,\n      icon: <FileText size={16} />,\n      run: () => exportSlidesPdf(deck, 'handout-4'),\n    },\n    {\n      id: 'html',\n      title: ex.formats.htmlBuilds.title,\n      description: ex.formats.htmlBuilds.description,\n      icon: <FileCode2 size={16} />,\n      run: () => exportSlidesHtml(deck),\n    },\n  ];\n\n  const mediaItems: ExportItem[] = [\n    {\n      id: 'zip-png',\n      title: ex.formats.zipPng.title,\n      description: ex.formats.zipPng.description,\n      icon: <FileArchive size={16} />,\n      run: () => exportSlidesPngZip(deck),\n    },\n    {\n      id: 'video',\n      title: ex.formats.videoWebm.title,\n      description: ex.formats.videoWebm.description,\n      icon: <Film size={16} />,\n      run: () => exportSlidesMp4(deck, { secondsPerSlide: 2.5 }),\n    },\n    {\n      id: 'project',\n      title: ex.formats.projectWzrds.title,\n      description: ex.formats.projectWzrds.description,\n      icon: <Download size={16} />,\n      run: async () => {\n        const blob = await exportProjectToWzrds(\n          slidesProjectFromStore({\n            id: 'export',\n            name,\n            size,\n            theme,\n            masters,\n            slides,\n            sections,\n            assets,\n            activeSlideId,\n            schemaVersion,\n            createdAt: Date.now(),\n            updatedAt: Date.now(),\n          })\n        );\n        const a = document.createElement('a');\n        a.href = URL.createObjectURL(blob);\n        a.download = modeExportFilename('slides', 'kais');\n        a.click();\n        URL.revokeObjectURL(a.href);\n      },\n    },\n  ];\n\n  const renderSection = (title: string, items: ExportItem[]) => (\n    <section className=\"flex flex-col gap-2\">\n      <TextTitle as=\"h4\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n        {title}\n      </TextTitle>\n      <div className=\"flex flex-col gap-1.5\">\n        {items.map((item) => (\n          <ExportRow\n            key={item.id}\n            item={item}\n            busyId={busyId}\n            disabled={busy}\n            onClick={() => void run(item.id, item.run, item.title)}\n          />\n        ))}\n      </div>\n    </section>\n  );\n\n  return (\n    <Modal\n      isOpen={exportModalOpen}\n      onClose={() => !busy && setExportModalOpen(false)}\n      title={ex.title}\n      size=\"lg\"\n      bodyClassName=\"!py-4\"\n    >\n      <div className=\"flex flex-col gap-5\">\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{ex.hint}</TextBody>\n\n        {renderSection(ex.sections.office, officeItems)}\n        {renderSection(ex.sections.documents, documentItems)}\n        {renderSection(ex.sections.media, mediaItems)}\n\n        <section className=\"flex flex-col gap-2\">\n          <TextTitle as=\"h4\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n            {ex.sections.continueIn}\n          </TextTitle>\n          <div className=\"grid grid-cols-1 gap-1.5 sm:grid-cols-2\">\n            <Button\n              variant=\"secondary\"\n              size=\"md\"\n              className=\"h-auto min-h-9 w-full justify-start gap-2 px-3 py-2.5\"\n              loading={busyId === 'handoff-video'}\n              disabled={busy}\n              icon={<Clapperboard size={15} />}\n              onClick={() => void handoffVideo()}\n            >\n              <span className=\"flex min-w-0 flex-col items-start text-left\">\n                <TextTitle as=\"span\" size=\"sm\" className=\"text-white\">\n                  {ex.handoffVideo.title}\n                </TextTitle>\n                <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                  {ex.handoffVideo.description}\n                </TextBody>\n              </span>\n            </Button>\n            <Button\n              variant=\"secondary\"\n              size=\"md\"\n              className=\"h-auto min-h-9 w-full justify-start gap-2 px-3 py-2.5\"\n              disabled={busy}\n              icon={<TextCursorInput size={15} />}\n              onClick={handoffText}\n            >\n              <span className=\"flex min-w-0 flex-col items-start text-left\">\n                <TextTitle as=\"span\" size=\"sm\" className=\"text-white\">\n                  {ex.handoffText.title}\n                </TextTitle>\n                <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                  {ex.handoffText.description}\n                </TextBody>\n              </span>\n            </Button>\n          </div>\n        </section>\n      </div>\n    </Modal>\n  );\n};\n", "/**\n * 2D canvas slide transitions for presenter (no WebGL dependency).\n * Covers the common TransitionType names used in the slides store.\n */\n\nexport type CanvasTransitionType =\n  | 'cut'\n  | 'cross-dissolve'\n  | 'fade-black'\n  | 'fade-white'\n  | 'slide-left'\n  | 'slide-right'\n  | 'slide-up'\n  | 'slide-down'\n  | 'push-left'\n  | 'push-right'\n  | 'zoom-in'\n  | 'blur-dissolve'\n  | 'morph-cut'\n  | string;\n\nfunction easeInOut(t: number): number {\n  return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;\n}\n\nexport async function runCanvasTransition(opts: {\n  ctx: CanvasRenderingContext2D;\n  from: HTMLCanvasElement | HTMLImageElement;\n  to: HTMLCanvasElement | HTMLImageElement;\n  type: CanvasTransitionType;\n  durationMs: number;\n  width: number;\n  height: number;\n  /** Called after each painted frame (e.g. blit buffer \u2192 display canvas). */\n  onFrame?: () => void;\n}): Promise<void> {\n  const { ctx, from, to, type, width, height, onFrame } = opts;\n  const durationMs = Math.max(80, opts.durationMs || 400);\n\n  if (type === 'cut' || durationMs < 100) {\n    ctx.clearRect(0, 0, width, height);\n    ctx.drawImage(to, 0, 0, width, height);\n    onFrame?.();\n    return;\n  }\n\n  const start = performance.now();\n  await new Promise<void>((resolve) => {\n    let cancelled = false;\n    const tick = (now: number) => {\n      if (cancelled) return;\n      // Defensive: if the captured `ctx` becomes invalid mid-animation\n      // (e.g. the presenter view unmounted and Konva disposed its wrapper),\n      // Konva 7 throws \"Cannot read properties of undefined (reading\n      // 'clearRect')\". Wrap each frame body in try/catch so the RAF loop\n      // stops cleanly instead of leaking an unhandled exception.\n      try {\n        const t = easeInOut(Math.min(1, (now - start) / durationMs));\n        ctx.clearRect(0, 0, width, height);\n\n        if (type === 'fade-black' || type === 'fade-white') {\n          const mid = type === 'fade-black' ? '#000' : '#fff';\n          if (t < 0.5) {\n            ctx.globalAlpha = 1;\n            ctx.drawImage(from, 0, 0, width, height);\n            ctx.fillStyle = mid;\n            ctx.globalAlpha = t * 2;\n            ctx.fillRect(0, 0, width, height);\n          } else {\n            ctx.fillStyle = mid;\n            ctx.globalAlpha = 1;\n            ctx.fillRect(0, 0, width, height);\n            ctx.globalAlpha = (t - 0.5) * 2;\n            ctx.drawImage(to, 0, 0, width, height);\n          }\n        } else if (type.startsWith('slide-') || type.startsWith('push-')) {\n          const dir = type.includes('left')\n            ? [-1, 0]\n            : type.includes('right')\n              ? [1, 0]\n              : type.includes('up')\n                ? [0, -1]\n                : [0, 1];\n          const ox = dir[0]! * width * t;\n          const oy = dir[1]! * height * t;\n          ctx.globalAlpha = 1;\n          ctx.drawImage(from, ox, oy, width, height);\n          ctx.drawImage(to, ox - dir[0]! * width, oy - dir[1]! * height, width, height);\n        } else if (type === 'zoom-in') {\n          const s = 1 + t * 0.2;\n          ctx.globalAlpha = 1 - t;\n          ctx.drawImage(from, (width - width * s) / 2, (height - height * s) / 2, width * s, height * s);\n          ctx.globalAlpha = t;\n          const s2 = 0.85 + t * 0.15;\n          ctx.drawImage(to, (width - width * s2) / 2, (height - height * s2) / 2, width * s2, height * s2);\n        } else {\n          // cross-dissolve / blur-dissolve / morph-cut fallback\n          ctx.globalAlpha = 1 - t;\n          ctx.drawImage(from, 0, 0, width, height);\n          ctx.globalAlpha = t;\n          ctx.drawImage(to, 0, 0, width, height);\n        }\n\n        ctx.globalAlpha = 1;\n        onFrame?.();\n        if (t < 1) {\n          requestAnimationFrame(tick);\n        } else {\n          resolve();\n        }\n      } catch {\n        // Stage/context disposed mid-transition. Stop the loop without\n        // surfacing an unhandled exception to the consumer.\n        cancelled = true;\n        resolve();\n      }\n    };\n    requestAnimationFrame(tick);\n  });\n}\n", "/**\n * Element build animation runtime for presenter mode.\n * Reuses TextAnimationPreset names + keyframe easings.\n */\n\nimport type { ElementBuild } from '../../types/slides.types';\nimport type { TextAnimationPreset } from '../../store/useVideoStore';\n\nfunction easeOut(t: number): number {\n  const x = Math.min(1, Math.max(0, t));\n  return x * (2 - x);\n}\n\nexport interface AnimatableObject {\n  id: string;\n  opacity: number;\n  left: number;\n  top: number;\n  scaleX: number;\n  scaleY: number;\n  angle: number;\n  set: (props: Record<string, number>) => void;\n}\n\nfunction presetTransform(\n  preset: TextAnimationPreset,\n  t: number,\n  base: { left: number; top: number; opacity: number; scaleX: number; scaleY: number }\n): Partial<AnimatableObject> {\n  const e = Math.min(1, Math.max(0, t));\n  switch (preset) {\n    case 'fade':\n      return { opacity: e };\n    case 'fade-up':\n    case 'slide-up':\n      return { opacity: e, top: base.top + (1 - e) * 40 };\n    case 'fade-down':\n    case 'slide-down':\n      return { opacity: e, top: base.top - (1 - e) * 40 };\n    case 'fade-left':\n    case 'slide-left':\n      return { opacity: e, left: base.left + (1 - e) * 40 };\n    case 'fade-right':\n    case 'slide-right':\n      return { opacity: e, left: base.left - (1 - e) * 40 };\n    case 'scale-in':\n      return { opacity: e, scaleX: 0.5 + e * 0.5, scaleY: 0.5 + e * 0.5 };\n    case 'bounce-in':\n    case 'elastic-in': {\n      const b = e < 1 ? Math.sin(e * Math.PI * 2.5) * (1 - e) * 0.15 + e : 1;\n      return { opacity: e, scaleX: b, scaleY: b };\n    }\n    case 'blur-in':\n    case 'rotate-in':\n      return { opacity: e, angle: (1 - e) * 15 };\n    default:\n      return { opacity: e };\n  }\n}\n\nexport class BuildAnimationController {\n  private builds: ElementBuild[];\n  private objects: Map<string, AnimatableObject>;\n  private bases = new Map<string, { left: number; top: number; opacity: number; scaleX: number; scaleY: number }>();\n  private step = 0;\n  private raf = 0;\n  private playing = false;\n\n  constructor(builds: ElementBuild[], objects: AnimatableObject[]) {\n    this.builds = [...builds].sort((a, b) => a.order - b.order);\n    this.objects = new Map(objects.map((o) => [o.id, o]));\n    for (const o of objects) {\n      this.bases.set(o.id, {\n        left: o.left,\n        top: o.top,\n        opacity: o.opacity,\n        scaleX: o.scaleX,\n        scaleY: o.scaleY,\n      });\n      // Hide build objects initially\n      if (this.builds.some((b) => b.objectId === o.id)) {\n        o.set({ opacity: 0 });\n      }\n    }\n  }\n\n  get hasMore(): boolean {\n    return this.step < this.builds.length;\n  }\n\n  /** Advance one click-group of builds. */\n  next(): Promise<void> {\n    if (!this.hasMore || this.playing) return Promise.resolve();\n    const group: ElementBuild[] = [];\n    const first = this.builds[this.step];\n    if (!first) return Promise.resolve();\n    group.push(first);\n    this.step += 1;\n    while (this.step < this.builds.length) {\n      const b = this.builds[this.step]!;\n      if (b.trigger === 'with-previous') {\n        group.push(b);\n        this.step += 1;\n      } else if (b.trigger === 'after-previous') {\n        // Chain after previous finishes \u2014 include in same promise chain\n        group.push(b);\n        this.step += 1;\n        break;\n      } else {\n        break;\n      }\n    }\n    return this.playGroup(group);\n  }\n\n  private playGroup(group: ElementBuild[]): Promise<void> {\n    this.playing = true;\n    return new Promise((resolve) => {\n      const start = performance.now();\n      const maxDur = Math.max(...group.map((b) => b.delayMs + b.durationMs), 300);\n\n      const tick = (now: number) => {\n        const elapsed = now - start;\n        for (const build of group) {\n          const obj = this.objects.get(build.objectId);\n          const base = this.bases.get(build.objectId);\n          if (!obj || !base) continue;\n          const local = elapsed - build.delayMs;\n          if (local < 0) continue;\n          const t = easeOut(local / Math.max(1, build.durationMs));\n          const props = presetTransform(build.animation, t, base);\n          obj.set(props as Record<string, number>);\n        }\n        if (elapsed < maxDur) {\n          this.raf = requestAnimationFrame(tick);\n        } else {\n          this.playing = false;\n          resolve();\n        }\n      };\n      this.raf = requestAnimationFrame(tick);\n    });\n  }\n\n  dispose() {\n    if (this.raf) cancelAnimationFrame(this.raf);\n  }\n}\n", "/**\n * Magic Move / morph \u2014 pair objects across slides and interpolate transforms.\n */\n\nexport interface MorphObject {\n  id: string;\n  morphSourceId?: string;\n  type: string;\n  text?: string;\n  left: number;\n  top: number;\n  width: number;\n  height: number;\n  scaleX: number;\n  scaleY: number;\n  angle: number;\n  opacity: number;\n  fill?: string;\n}\n\nexport interface MorphPair {\n  from: MorphObject;\n  to: MorphObject;\n  score: number;\n}\n\nfunction similarity(a: MorphObject, b: MorphObject): number {\n  if (a.morphSourceId && a.morphSourceId === b.id) return 1;\n  if (b.morphSourceId && b.morphSourceId === a.id) return 1;\n  if (a.id === b.id) return 0.95;\n  let score = 0;\n  if (a.type === b.type) score += 0.35;\n  if (a.text && b.text && a.text === b.text) score += 0.4;\n  else if (a.text && b.text && (a.text.includes(b.text) || b.text.includes(a.text))) score += 0.2;\n  const dx = Math.abs(a.left - b.left);\n  const dy = Math.abs(a.top - b.top);\n  score += Math.max(0, 0.25 - (dx + dy) / 4000);\n  return score;\n}\n\nexport function pairMorphObjects(from: MorphObject[], to: MorphObject[]): MorphPair[] {\n  const pairs: MorphPair[] = [];\n  const usedTo = new Set<string>();\n  const usedFrom = new Set<string>();\n\n  const candidates: MorphPair[] = [];\n  for (const a of from) {\n    for (const b of to) {\n      const score = similarity(a, b);\n      if (score >= 0.35) candidates.push({ from: a, to: b, score });\n    }\n  }\n  candidates.sort((x, y) => y.score - x.score);\n  for (const c of candidates) {\n    if (usedFrom.has(c.from.id) || usedTo.has(c.to.id)) continue;\n    usedFrom.add(c.from.id);\n    usedTo.add(c.to.id);\n    pairs.push(c);\n  }\n  return pairs;\n}\n\nexport function interpolateMorph(\n  pair: MorphPair,\n  t: number\n): Partial<MorphObject> {\n  const e = Math.min(1, Math.max(0, t));\n  const lerp = (a: number, b: number) => a + (b - a) * e;\n  return {\n    left: lerp(pair.from.left, pair.to.left),\n    top: lerp(pair.from.top, pair.to.top),\n    width: lerp(pair.from.width, pair.to.width),\n    height: lerp(pair.from.height, pair.to.height),\n    scaleX: lerp(pair.from.scaleX, pair.to.scaleX),\n    scaleY: lerp(pair.from.scaleY, pair.to.scaleY),\n    angle: lerp(pair.from.angle, pair.to.angle),\n    opacity: lerp(pair.from.opacity, pair.to.opacity),\n  };\n}\n", "import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport { StaticCanvas } from 'fabric';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { X, ChevronLeft, ChevronRight, Clock, Pencil, Eraser, Timer } from 'lucide-react';\nimport { composeSlideWithMaster } from '../../lib/slides/layouts';\nimport { runCanvasTransition } from '../../lib/slides/canvasTransition';\nimport { BuildAnimationController } from '../../lib/slides/animationRuntime';\nimport { pairMorphObjects, interpolateMorph, type MorphObject } from '../../lib/slides/morph';\nimport { useTranslation } from '../../i18n';\nimport { TextBody, TextTitle } from '../ui';\n\nconst CHANNEL = 'wizard-slides-presenter';\n\nfunction extractMorphObjects(json: unknown): MorphObject[] {\n  const objects = (json as { objects?: Array<Record<string, unknown>> })?.objects || [];\n  return objects.map((o) => ({\n    id: String(o.id || ''),\n    morphSourceId: typeof o.morphSourceId === 'string' ? o.morphSourceId : undefined,\n    type: String(o.type || ''),\n    text: typeof o.text === 'string' ? o.text : undefined,\n    left: Number(o.left || 0),\n    top: Number(o.top || 0),\n    width: Number(o.width || 0) * Number(o.scaleX || 1),\n    height: Number(o.height || 0) * Number(o.scaleY || 1),\n    scaleX: Number(o.scaleX || 1),\n    scaleY: Number(o.scaleY || 1),\n    angle: Number(o.angle || 0),\n    opacity: Number(o.opacity ?? 1),\n    fill: typeof o.fill === 'string' ? o.fill : undefined,\n  }));\n}\n\nexport const PresenterView: React.FC = () => {\n  const t = useTranslation();\n  const {\n    slides,\n    activeSlideId,\n    setActiveSlideId,\n    size,\n    theme,\n    masters,\n    setIsPresenting,\n    isPresenting,\n    setRehearsalTime,\n    rehearsalTimes,\n    clearRehearsalTimes,\n  } = useSlidesStore();\n\n  const visible = useMemo(() => slides.filter((s) => !s.hidden), [slides]);\n  const index = Math.max(0, visible.findIndex((s) => s.id === activeSlideId));\n  const current = visible[index];\n  const nextSlide = visible[index + 1];\n  const master = masters[0];\n\n  const stageRef = useRef<HTMLCanvasElement>(null);\n  const stageHostRef = useRef<HTMLDivElement>(null);\n  const nextRef = useRef<HTMLCanvasElement>(null);\n  /** Full-resolution buffer (design size). Display canvas is always fitted blit. */\n  const bufferRef = useRef<HTMLCanvasElement | null>(null);\n  const fabricMainRef = useRef<StaticCanvas | null>(null);\n  const buildCtrlRef = useRef<BuildAnimationController | null>(null);\n  const channelRef = useRef<BroadcastChannel | null>(null);\n  const slideEnteredAt = useRef(Date.now());\n  const transitioning = useRef(false);\n\n  const [elapsed, setElapsed] = useState(0);\n  const [laser, setLaser] = useState<{ x: number; y: number } | null>(null);\n  const [inkMode, setInkMode] = useState(false);\n  const [rehearsal, setRehearsal] = useState(false);\n  const inkPoints = useRef<Array<{ x: number; y: number }>>([]);\n  const startRef = useRef(Date.now());\n\n  const ensureBuffer = useCallback(() => {\n    let buf = bufferRef.current;\n    if (!buf) {\n      buf = document.createElement('canvas');\n      bufferRef.current = buf;\n    }\n    if (buf.width !== size.width || buf.height !== size.height) {\n      buf.width = size.width;\n      buf.height = size.height;\n    }\n    return buf;\n  }, [size.width, size.height]);\n\n  /**\n   * Size the visible stage to the left pane and copy the design-size buffer into it.\n   * Same pattern as the \"next\" preview \u2014 bitmap size === CSS size, so canvas.width\n   * can never inflate the layout to 1920px.\n   */\n  const blitStage = useCallback(() => {\n    const host = stageHostRef.current;\n    const stage = stageRef.current;\n    const buf = bufferRef.current;\n    if (!host || !stage || !buf) return;\n    const pad = 24;\n    const aw = Math.max(1, host.clientWidth - pad);\n    const ah = Math.max(1, host.clientHeight - pad);\n    const s = Math.min(aw / size.width, ah / size.height);\n    const dw = Math.max(1, Math.floor(size.width * s));\n    const dh = Math.max(1, Math.floor(size.height * s));\n    if (stage.width !== dw || stage.height !== dh) {\n      stage.width = dw;\n      stage.height = dh;\n    }\n    // Keep CSS locked to the bitmap \u2014 never leave presentation size at 1920.\n    stage.style.width = `${dw}px`;\n    stage.style.height = `${dh}px`;\n    const ctx = stage.getContext('2d');\n    if (!ctx) return;\n    ctx.clearRect(0, 0, dw, dh);\n    ctx.drawImage(buf, 0, 0, dw, dh);\n  }, [size.width, size.height]);\n\n  const composedJson = useCallback(\n    (slide: typeof current, idx: number) => {\n      if (!slide) return { objects: [] };\n      if (!master) return slide.json;\n      return composeSlideWithMaster(slide.json, master, theme, idx, visible.length, size);\n    },\n    [master, theme, visible.length, size]\n  );\n\n  const broadcastFrame = useCallback(async () => {\n    const buf = bufferRef.current;\n    if (!buf || !channelRef.current) return;\n    try {\n      const dataUrl = buf.toDataURL('image/jpeg', 0.7);\n      channelRef.current.postMessage({\n        type: 'frame',\n        slideId: current?.id,\n        index,\n        total: visible.length,\n        dataUrl,\n        notes: current?.notes || '',\n      });\n    } catch {\n      /* ignore */\n    }\n  }, [current?.id, current?.notes, index, visible.length]);\n\n  const loadMain = useCallback(\n    async (slideJson: unknown) => {\n      const buf = ensureBuffer();\n      const buildEl = document.createElement('canvas');\n      const buildSc = new StaticCanvas(buildEl, {\n        width: size.width,\n        height: size.height,\n        renderOnAddRemove: false,\n        // Retina would make the bitmap dpr\u00D7 larger; 1:1 blit into a 1920 buffer\n        // then crops the slide (~80% visible on 1.25dpr). Next-preview scales, so it looked fine.\n        enableRetinaScaling: false,\n      });\n      await buildSc.loadFromJSON(slideJson || { objects: [] });\n      buildSc.backgroundColor = theme.colors.background;\n      buildSc.renderAll();\n\n      const pushFrame = () => {\n        const bctx = buf.getContext('2d');\n        if (bctx) {\n          bctx.clearRect(0, 0, size.width, size.height);\n          // Scale full Fabric bitmap \u2192 design-size buffer (safe even if retina sneaks back).\n          const src = (buildSc.lowerCanvasEl as HTMLCanvasElement | undefined) ?? buildEl;\n          bctx.drawImage(\n            src,\n            0,\n            0,\n            src.width || size.width,\n            src.height || size.height,\n            0,\n            0,\n            size.width,\n            size.height\n          );\n        }\n        blitStage();\n      };\n      pushFrame();\n\n      fabricMainRef.current?.dispose();\n      fabricMainRef.current = buildSc;\n\n      buildCtrlRef.current?.dispose();\n      const objs = (\n        buildSc.getObjects() as Array<{\n          id?: string;\n          opacity?: number;\n          left?: number;\n          top?: number;\n          scaleX?: number;\n          scaleY?: number;\n          angle?: number;\n          set: (p: Record<string, number>) => void;\n        }>\n      ).map((o) => ({\n        id: String(o.id || ''),\n        opacity: o.opacity ?? 1,\n        left: o.left || 0,\n        top: o.top || 0,\n        scaleX: o.scaleX || 1,\n        scaleY: o.scaleY || 1,\n        angle: o.angle || 0,\n        set: (props: Record<string, number>) => {\n          o.set(props);\n          buildSc.requestRenderAll();\n          pushFrame();\n        },\n      }));\n      if (current?.builds?.length) {\n        buildCtrlRef.current = new BuildAnimationController(current.builds, objs);\n      } else {\n        buildCtrlRef.current = null;\n      }\n      return buildSc;\n    },\n    [size.width, size.height, theme.colors.background, current?.builds, ensureBuffer, blitStage]\n  );\n\n  const loadNextPreview = useCallback(\n    async (slideJson: unknown | null) => {\n      const el = nextRef.current;\n      if (!el) return;\n      const previewW = Math.max(1, Math.round(size.width / 4));\n      const previewH = Math.max(1, Math.round(size.height / 4));\n      if (el.width !== previewW || el.height !== previewH) {\n        el.width = previewW;\n        el.height = previewH;\n      }\n      const ctx = el.getContext('2d');\n      if (!ctx) return;\n      ctx.clearRect(0, 0, previewW, previewH);\n      if (!slideJson) {\n        ctx.fillStyle = '#13131A';\n        ctx.fillRect(0, 0, previewW, previewH);\n        return;\n      }\n      const off = document.createElement('canvas');\n      const sc = new StaticCanvas(off, {\n        width: size.width,\n        height: size.height,\n        renderOnAddRemove: false,\n        enableRetinaScaling: false,\n      });\n      try {\n        await sc.loadFromJSON(slideJson || { objects: [] });\n        sc.backgroundColor = theme.colors.background;\n        sc.renderAll();\n        const src = (sc.lowerCanvasEl as HTMLCanvasElement | undefined) ?? off;\n        ctx.drawImage(\n          src,\n          0,\n          0,\n          src.width || size.width,\n          src.height || size.height,\n          0,\n          0,\n          previewW,\n          previewH\n        );\n      } finally {\n        sc.dispose();\n      }\n    },\n    [size.width, size.height, theme.colors.background]\n  );\n\n  useEffect(() => {\n    if (!isPresenting) return;\n    startRef.current = Date.now();\n    slideEnteredAt.current = Date.now();\n    const iv = setInterval(() => setElapsed(Math.floor((Date.now() - startRef.current) / 1000)), 1000);\n    channelRef.current = new BroadcastChannel(CHANNEL);\n    return () => {\n      clearInterval(iv);\n      channelRef.current?.close();\n      buildCtrlRef.current?.dispose();\n      fabricMainRef.current?.dispose();\n    };\n  }, [isPresenting]);\n\n  // Refit display canvas when the left pane resizes.\n  useLayoutEffect(() => {\n    if (!isPresenting) return;\n    const host = stageHostRef.current;\n    if (!host) return;\n    blitStage();\n    const ro = new ResizeObserver(() => blitStage());\n    ro.observe(host);\n    return () => ro.disconnect();\n  }, [isPresenting, blitStage]);\n\n  useEffect(() => {\n    if (!isPresenting || !current) return;\n    let cancelled = false;\n    void (async () => {\n      await loadMain(composedJson(current, index));\n      if (cancelled) return;\n      await loadNextPreview(\n        nextSlide ? composedJson(nextSlide, index + 1) : null\n      );\n      if (cancelled) return;\n      void broadcastFrame();\n    })();\n    return () => {\n      cancelled = true;\n    };\n  }, [current?.id, nextSlide?.id, isPresenting, index]); // eslint-disable-line react-hooks/exhaustive-deps\n\n  const go = async (delta: number) => {\n    if (transitioning.current || !current) return;\n\n    // Advance builds first on forward\n    if (delta > 0 && buildCtrlRef.current?.hasMore) {\n      await buildCtrlRef.current.next();\n      void broadcastFrame();\n      return;\n    }\n\n    const nextIdx = Math.min(visible.length - 1, Math.max(0, index + delta));\n    if (nextIdx === index) return;\n    const target = visible[nextIdx];\n    if (!target) return;\n\n    if (rehearsal) {\n      const spent = (Date.now() - slideEnteredAt.current) / 1000;\n      setRehearsalTime(current.id, spent);\n    }\n\n    const buf = ensureBuffer();\n    const bufCtx = buf.getContext('2d');\n    if (bufCtx && delta > 0) {\n      transitioning.current = true;\n      const fromCanvas = document.createElement('canvas');\n      fromCanvas.width = size.width;\n      fromCanvas.height = size.height;\n      fromCanvas.getContext('2d')?.drawImage(buf, 0, 0);\n\n      const toOff = document.createElement('canvas');\n      const toSc = new StaticCanvas(toOff, {\n        width: size.width,\n        height: size.height,\n        renderOnAddRemove: false,\n        enableRetinaScaling: false,\n      });\n      const toJson = composedJson(target, nextIdx);\n      await toSc.loadFromJSON(toJson || {});\n      toSc.backgroundColor = theme.colors.background;\n      toSc.renderAll();\n      // Normalize to design-size canvas (guards against any Fabric size drift).\n      const toFrame = document.createElement('canvas');\n      toFrame.width = size.width;\n      toFrame.height = size.height;\n      {\n        const src = (toSc.lowerCanvasEl as HTMLCanvasElement | undefined) ?? toOff;\n        toFrame.getContext('2d')?.drawImage(\n          src,\n          0,\n          0,\n          src.width || size.width,\n          src.height || size.height,\n          0,\n          0,\n          size.width,\n          size.height\n        );\n      }\n\n      const paintBuf = () => {\n        blitStage();\n      };\n\n      // Morph preview when transition is morph-cut\n      if (target.transition.type === 'morph-cut' || current.transition.type === 'morph-cut') {\n        const pairs = pairMorphObjects(\n          extractMorphObjects(composedJson(current, index)),\n          extractMorphObjects(toJson)\n        );\n        if (pairs.length) {\n          const start = performance.now();\n          const dur = (target.transition.duration || 0.5) * 1000;\n          await new Promise<void>((resolve) => {\n            const tick = (now: number) => {\n              const t = Math.min(1, (now - start) / dur);\n              if (!bufferRef.current) {\n                resolve();\n                return;\n              }\n              const liveCtx = bufferRef.current.getContext('2d');\n              if (!liveCtx) {\n                resolve();\n                return;\n              }\n              liveCtx.clearRect(0, 0, size.width, size.height);\n              liveCtx.drawImage(toFrame, 0, 0);\n              liveCtx.save();\n              for (const pair of pairs) {\n                const m = interpolateMorph(pair, t);\n                liveCtx.globalAlpha = m.opacity ?? 1;\n                liveCtx.fillStyle = pair.to.fill || theme.colors.accent;\n                liveCtx.fillRect(m.left || 0, m.top || 0, m.width || 10, m.height || 10);\n              }\n              liveCtx.restore();\n              paintBuf();\n              if (t < 1) requestAnimationFrame(tick);\n              else resolve();\n            };\n            requestAnimationFrame(tick);\n          });\n        } else {\n          await runCanvasTransition({\n            ctx: bufCtx,\n            from: fromCanvas,\n            to: toFrame,\n            type: target.transition.type,\n            durationMs: (target.transition.duration || 0.4) * 1000,\n            width: size.width,\n            height: size.height,\n            onFrame: paintBuf,\n          });\n        }\n      } else {\n        await runCanvasTransition({\n          ctx: bufCtx,\n          from: fromCanvas,\n          to: toFrame,\n          type: target.transition.type,\n          durationMs: (target.transition.duration || 0.4) * 1000,\n          width: size.width,\n          height: size.height,\n          onFrame: paintBuf,\n        });\n      }\n      toSc.dispose();\n      // Final frame already in buffer from transition; keep it for the next loadMain.\n      blitStage();\n      transitioning.current = false;\n    }\n\n    setActiveSlideId(target.id);\n    slideEnteredAt.current = Date.now();\n    inkPoints.current = [];\n    channelRef.current?.postMessage({ type: 'goto', slideId: target.id });\n  };\n\n  useEffect(() => {\n    if (!isPresenting) return;\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'ArrowRight' || e.key === ' ' || e.key === 'PageDown') {\n        e.preventDefault();\n        void go(1);\n      }\n      if (e.key === 'ArrowLeft' || e.key === 'PageUp') {\n        e.preventDefault();\n        void go(-1);\n      }\n      if (e.key === 'Escape') {\n        if (rehearsal && current) {\n          setRehearsalTime(current.id, (Date.now() - slideEnteredAt.current) / 1000);\n        }\n        setIsPresenting(false);\n      }\n      if (e.key === 'b' || e.key === 'B') {\n        const buf = ensureBuffer();\n        const ctx = buf.getContext('2d');\n        if (ctx) {\n          ctx.fillStyle = '#000';\n          ctx.fillRect(0, 0, buf.width, buf.height);\n          blitStage();\n        }\n      }\n      if (/^[0-9]$/.test(e.key)) {\n        const n = Number(e.key);\n        if (n >= 1 && n <= visible.length) {\n          const s = visible[n - 1];\n          if (s) setActiveSlideId(s.id);\n        }\n      }\n    };\n    window.addEventListener('keydown', onKey);\n    return () => window.removeEventListener('keydown', onKey);\n  });\n\n  if (!isPresenting || !current) return null;\n\n  const mm = String(Math.floor(elapsed / 60)).padStart(2, '0');\n  const ss = String(elapsed % 60).padStart(2, '0');\n  const avgRehearsal =\n    Object.keys(rehearsalTimes).length > 0\n      ? Object.values(rehearsalTimes).reduce((a, b) => a + b, 0)\n      : 0;\n\n  return (\n    <div className=\"fixed inset-0 z-[400] bg-[#0A0A0F] flex flex-col\">\n      <div className=\"flex items-center justify-between px-4 py-2 border-b border-[#2A2A38]\">\n        <div className=\"flex items-center gap-3 text-[12px] text-[#C8C8D4]\">\n          <Clock size={14} className=\"text-[var(--we-accent)]\" />\n          <span className=\"font-mono\">\n            {mm}:{ss}\n          </span>\n          <span>\n            {index + 1} / {visible.length}\n          </span>\n          {rehearsal && (\n            <span className=\"text-amber-300 flex items-center gap-1\">\n              <Timer size={12} /> {t.slides.presenterView.rehearsalTotal(avgRehearsal)}\n            </span>\n          )}\n        </div>\n        <div className=\"flex items-center gap-2\">\n          <button\n            type=\"button\"\n            title={t.slides.presenterView.titleRehearsal}\n            onClick={() => {\n              if (rehearsal) {\n                if (current) {\n                  setRehearsalTime(\n                    current.id,\n                    (Date.now() - slideEnteredAt.current) / 1000\n                  );\n                }\n                setRehearsal(false);\n              } else {\n                clearRehearsalTimes();\n                setRehearsal(true);\n                slideEnteredAt.current = Date.now();\n              }\n            }}\n            className={`p-1.5 rounded ${rehearsal ? 'bg-amber-500/30 text-amber-200' : 'hover:bg-[#1C1C26] text-[#F0F0F5]'}`}\n          >\n            <Timer size={16} />\n          </button>\n          <button\n            type=\"button\"\n            title={t.slides.presenterView.titleInk}\n            onClick={() => setInkMode((v) => !v)}\n            className={`p-1.5 rounded ${inkMode ? 'bg-[var(--we-accent-muted)] text-white' : 'hover:bg-[#1C1C26] text-[#F0F0F5]'}`}\n          >\n            <Pencil size={16} />\n          </button>\n          <button\n            type=\"button\"\n            title={t.slides.presenterView.titleClearInk}\n            onClick={() => {\n              inkPoints.current = [];\n              const svg = document.querySelector<SVGSVGElement>('[data-presenter-ink] polyline');\n              if (svg) svg.setAttribute('points', '');\n              setLaser(null);\n            }}\n            className=\"p-1.5 rounded hover:bg-[#1C1C26] text-[#F0F0F5]\"\n          >\n            <Eraser size={16} />\n          </button>\n          <button type=\"button\" onClick={() => void go(-1)} className=\"p-1.5 rounded hover:bg-[#1C1C26] text-[#F0F0F5]\">\n            <ChevronLeft size={16} />\n          </button>\n          <button type=\"button\" onClick={() => void go(1)} className=\"p-1.5 rounded hover:bg-[#1C1C26] text-[#F0F0F5]\">\n            <ChevronRight size={16} />\n          </button>\n          <button\n            type=\"button\"\n            onClick={() => {\n              if (rehearsal && current) {\n                setRehearsalTime(\n                  current.id,\n                  (Date.now() - slideEnteredAt.current) / 1000\n                );\n              }\n              setIsPresenting(false);\n            }}\n            className=\"p-1.5 rounded hover:bg-[#1C1C26] text-[#F0F0F5]\"\n          >\n            <X size={16} />\n          </button>\n        </div>\n      </div>\n      <div className=\"flex min-h-0 flex-1\">\n        <div\n          ref={stageHostRef}\n          className=\"relative flex min-h-0 min-w-0 flex-1 items-center justify-center overflow-hidden p-3\"\n          style={{ cursor: inkMode ? 'crosshair' : 'none' }}\n          onMouseMove={(e) => {\n            const rect = e.currentTarget.getBoundingClientRect();\n            const pos = { x: e.clientX - rect.left, y: e.clientY - rect.top };\n            if (!inkMode) setLaser(pos);\n            if (inkMode && e.buttons === 1) {\n              inkPoints.current.push(pos);\n            }\n          }}\n          onMouseLeave={() => setLaser(null)}\n        >\n          {/*\n            Display canvas: bitmap size always equals CSS size (fitted blit).\n            No width/height React props \u2014 avoids 1920 CSS reset on re-render.\n          */}\n          <canvas ref={stageRef} className=\"block shadow-2xl\" />\n          {/* Ink overlay */}\n          <svg\n            data-presenter-ink\n            className=\"pointer-events-none absolute inset-0 h-full w-full\"\n            style={{ pointerEvents: inkMode ? 'auto' : 'none' }}\n            onMouseDown={(e) => {\n              if (!inkMode) return;\n              const rect = e.currentTarget.getBoundingClientRect();\n              inkPoints.current = [{ x: e.clientX - rect.left, y: e.clientY - rect.top }];\n            }}\n            onMouseMove={(e) => {\n              if (!inkMode || e.buttons !== 1) return;\n              const rect = e.currentTarget.getBoundingClientRect();\n              inkPoints.current.push({ x: e.clientX - rect.left, y: e.clientY - rect.top });\n              const path = e.currentTarget.querySelector('polyline');\n              if (path) {\n                path.setAttribute(\n                  'points',\n                  inkPoints.current.map((p) => `${p.x},${p.y}`).join(' ')\n                );\n              }\n            }}\n          >\n            <polyline fill=\"none\" stroke=\"#ef4444\" strokeWidth=\"3\" points=\"\" />\n          </svg>\n          {laser && !inkMode && (\n            <div\n              className=\"pointer-events-none absolute h-4 w-4 rounded-full bg-red-500/80 shadow-[0_0_12px_#ef4444]\"\n              style={{ left: laser.x - 8, top: laser.y - 8 }}\n            />\n          )}\n        </div>\n        <div className=\"flex w-[320px] shrink-0 flex-col gap-3 border-l border-[#2A2A38] bg-[#0F0F14] p-3\">\n          <div>\n            <TextBody as=\"p\" size=\"sm\" className=\"text-[#8888A0] uppercase mb-1\">{t.slides.presenterView.next}</TextBody>\n            <canvas\n              ref={nextRef}\n              className=\"w-full rounded border border-[#2A2A38] bg-[#13131A]\"\n            />\n            {!nextSlide && (\n              <TextBody as=\"p\" size=\"sm\" className=\"mt-2 text-[#8888A0]\">\n                {t.slides.presenterView.endOfPresentation}\n              </TextBody>\n            )}\n          </div>\n          <div className=\"flex-1 min-h-0 flex flex-col\">\n            <TextBody as=\"p\" size=\"sm\" className=\"text-[#8888A0] uppercase mb-1\">{t.slides.presenterView.teleprompter}</TextBody>\n            <div className=\"flex-1 overflow-y-auto text-[15px] text-[#F0F0F5] leading-relaxed whitespace-pre-wrap\">\n              {current.notes || t.slides.presenterView.noNotes}\n            </div>\n          </div>\n          {rehearsal && Object.keys(rehearsalTimes).length > 0 && (\n            <div className=\"text-[10px] text-[#8888A0] max-h-24 overflow-auto\">\n              {visible.map((s, i) =>\n                rehearsalTimes[s.id] != null ? (\n                  <div key={s.id}>\n                    {t.slides.presenterView.slideTiming(i, rehearsalTimes[s.id]!)}\n                  </div>\n                ) : null\n              )}\n            </div>\n          )}\n        </div>\n      </div>\n    </div>\n  );\n};\n\n/** Audience window \u2014 receives JPEG frames over BroadcastChannel. */\nexport function openAudienceWindow() {\n  const w = window.open('', 'wizard-slides-audience', 'popup=yes,width=1280,height=720');\n  if (!w) return;\n  w.document.write(`<!doctype html><html><head><title>Presentacion</title>\n<style>html,body{margin:0;background:#000;height:100%;overflow:hidden}\nimg{width:100%;height:100%;object-fit:contain;display:block}\n#meta{position:fixed;bottom:8px;right:12px;color:#fff;opacity:.4;font:12px sans-serif}\n</style></head><body>\n<img id=\"frame\" alt=\"slide\"/>\n<div id=\"meta\"></div>\n<script>\nconst ch = new BroadcastChannel('${CHANNEL}');\nconst img = document.getElementById('frame');\nconst meta = document.getElementById('meta');\nch.onmessage = (e) => {\n  const d = e.data || {};\n  if (d.type === 'frame' && d.dataUrl) {\n    img.src = d.dataUrl;\n    meta.textContent = ((d.index||0)+1) + ' / ' + (d.total||'?');\n  }\n};\n</script></body></html>`);\n  w.document.close();\n}\n", "/**\n * PPTX import L2 \u2014 unzip with fflate, parse OOXML with DOMParser.\n * Coverage: text, images, basic shapes, theme colors, notes, basic tables, alt text.\n * Degraded: SmartArt, native charts, OLE, animations.\n */\n\nimport { unzipSync } from 'fflate';\nimport type { Slide, SlideDeck, SlidesAsset } from '../../../types/slides.types';\nimport { SLIDES_SCHEMA_VERSION } from '../../../types/slides.types';\nimport { DEFAULT_THEME } from '../themes';\nimport { createDefaultMaster } from '../layouts';\nimport { emuToPx, ptToPx } from './emu';\n\nexport interface PptxImportReport {\n  degraded: string[];\n  slideCount: number;\n}\n\nexport interface PptxImportResult extends Omit<SlideDeck, 'id' | 'createdAt' | 'updatedAt'> {\n  importReport: PptxImportReport;\n}\n\nfunction uid(prefix: string): string {\n  return `${prefix}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction parseXml(text: string): Document {\n  return new DOMParser().parseFromString(text, 'application/xml');\n}\n\nfunction textContent(el: Element | null): string {\n  return el?.textContent?.trim() || '';\n}\n\nfunction attr(el: Element | null, name: string): string {\n  return el?.getAttribute(name) || '';\n}\n\nfunction resolveRels(relsXml: string): Map<string, string> {\n  const doc = parseXml(relsXml);\n  const map = new Map<string, string>();\n  doc.querySelectorAll('Relationship').forEach((rel) => {\n    map.set(attr(rel, 'Id'), attr(rel, 'Target'));\n  });\n  return map;\n}\n\nfunction bytesToDataUrl(bytes: Uint8Array, mime: string): string {\n  let bin = '';\n  for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]!);\n  return `data:${mime};base64,${btoa(bin)}`;\n}\n\nfunction guessMime(path: string): string {\n  if (path.endsWith('.png')) return 'image/png';\n  if (path.endsWith('.jpg') || path.endsWith('.jpeg')) return 'image/jpeg';\n  if (path.endsWith('.gif')) return 'image/gif';\n  if (path.endsWith('.webp')) return 'image/webp';\n  return 'application/octet-stream';\n}\n\nexport async function importPptxFile(file: Blob): Promise<PptxImportResult> {\n  const buf = new Uint8Array(await file.arrayBuffer());\n  const files = unzipSync(buf);\n  const degraded: string[] = [];\n\n  const getText = (path: string): string | null => {\n    const data = files[path];\n    if (!data) return null;\n    return new TextDecoder().decode(data);\n  };\n\n  // Presentation size\n  let width = 1920;\n  let height = 1080;\n  const presXml = getText('ppt/presentation.xml');\n  if (presXml) {\n    const doc = parseXml(presXml);\n    const sldSz = doc.querySelector('sldSz');\n    if (sldSz) {\n      width = Math.round(emuToPx(Number(attr(sldSz, 'cx') || 0))) || 1920;\n      height = Math.round(emuToPx(Number(attr(sldSz, 'cy') || 0))) || 1080;\n    }\n  }\n\n  // Theme colors (best-effort)\n  const theme = { ...DEFAULT_THEME, colors: { ...DEFAULT_THEME.colors } };\n  const themeXml = getText('ppt/theme/theme1.xml');\n  if (themeXml) {\n    const doc = parseXml(themeXml);\n    const scheme = doc.querySelector('clrScheme');\n    if (scheme) {\n      const pick = (name: string) => {\n        const node = scheme.querySelector(name);\n        const srgb = node?.querySelector('srgbClr');\n        const val = attr(srgb || null, 'val');\n        return val ? `#${val}` : undefined;\n      };\n      theme.colors.accent = pick('accent1') || theme.colors.accent;\n      theme.colors.title = pick('dk1') || pick('lt1') || theme.colors.title;\n      theme.colors.body = pick('dk2') || theme.colors.body;\n      theme.colors.background = pick('lt1') || pick('dk1') || theme.colors.background;\n    }\n  }\n\n  // Slide list from presentation.xml\n  const slidePaths: string[] = [];\n  if (presXml) {\n    const rels = getText('ppt/_rels/presentation.xml.rels');\n    const relMap = rels ? resolveRels(rels) : new Map();\n    const doc = parseXml(presXml);\n    doc.querySelectorAll('sldIdLst sldId, sldId').forEach((node) => {\n      const rid = attr(node, 'r:id') || attr(node, 'id');\n      // OOXML uses r:id in namespaced form \u2014 try both\n      const rid2 =\n        rid ||\n        Array.from(node.attributes).find((a) => a.name.endsWith('id') && a.name.includes('id'))\n          ?.value;\n      const target = rid2 ? relMap.get(rid2) : undefined;\n      if (target) {\n        const path = target.startsWith('/')\n          ? target.slice(1)\n          : `ppt/${target.replace(/^\\.\\.\\//, '')}`;\n        const normalized = path.includes('slides/')\n          ? path\n          : `ppt/slides/${target.split('/').pop()}`;\n        slidePaths.push(normalized.replace(/\\\\/g, '/'));\n      }\n    });\n  }\n\n  // Fallback: scan ppt/slides/slideN.xml\n  if (!slidePaths.length) {\n    Object.keys(files)\n      .filter((k) => /^ppt\\/slides\\/slide\\d+\\.xml$/i.test(k))\n      .sort((a, b) => {\n        const na = Number(a.match(/slide(\\d+)/i)?.[1] || 0);\n        const nb = Number(b.match(/slide(\\d+)/i)?.[1] || 0);\n        return na - nb;\n      })\n      .forEach((k) => slidePaths.push(k));\n  }\n\n  const master = createDefaultMaster(theme);\n  const assets: SlidesAsset[] = [];\n  const slides: Slide[] = [];\n\n  for (let i = 0; i < slidePaths.length; i++) {\n    const path = slidePaths[i]!;\n    const xml = getText(path);\n    if (!xml) continue;\n    const doc = parseXml(xml);\n    const objects: Record<string, unknown>[] = [];\n\n    // Detect unsupported features (charts/SmartArt stay degraded; tables parsed below)\n    if (doc.querySelector('graphicData[uri*=\"chart\"]') || doc.querySelector('chart')) {\n      degraded.push(`Slide ${i + 1}: chart nativo (rasterizado no disponible)`);\n    }\n    if (doc.querySelector('oleObj')) degraded.push(`Slide ${i + 1}: OLE embed`);\n\n    // Shapes / text\n    doc.querySelectorAll('sp').forEach((sp) => {\n      const xfrm = sp.querySelector('xfrm');\n      const off = xfrm?.querySelector('off');\n      const ext = xfrm?.querySelector('ext');\n      const left = emuToPx(Number(attr(off || null, 'x') || 0));\n      const top = emuToPx(Number(attr(off || null, 'y') || 0));\n      const w = emuToPx(Number(attr(ext || null, 'cx') || 0));\n      const h = emuToPx(Number(attr(ext || null, 'cy') || 0));\n      const cNvPr = sp.querySelector('cNvPr');\n      const alt = attr(cNvPr, 'descr') || attr(cNvPr, 'title') || undefined;\n      const texts = Array.from(sp.querySelectorAll('t'))\n        .map((t) => textContent(t))\n        .filter(Boolean);\n      const text = texts.join('\\n');\n      if (text) {\n        const sz = Number(attr(sp.querySelector('rPr') || sp.querySelector('defRPr'), 'sz') || 2200) / 100;\n        objects.push({\n          type: 'Textbox',\n          version: '6.0.0',\n          left,\n          top,\n          width: w || 400,\n          height: h || 80,\n          text,\n          fontSize: ptToPx(sz),\n          fontFamily: theme.fonts.body,\n          fill: theme.colors.body,\n          id: uid('obj'),\n          placeholderRole: 'body',\n          themeRole: 'body',\n          alt,\n        });\n      } else {\n        objects.push({\n          type: 'Rect',\n          version: '6.0.0',\n          left,\n          top,\n          width: w || 100,\n          height: h || 100,\n          fill: theme.colors.surface,\n          id: uid('obj'),\n          alt,\n        });\n      }\n    });\n\n    // Basic tables (graphicFrame > tbl) \u2192 text grid\n    doc.querySelectorAll('graphicFrame').forEach((frame) => {\n      const tbl = frame.querySelector('tbl');\n      if (!tbl) return;\n      const xfrm = frame.querySelector('xfrm');\n      const off = xfrm?.querySelector('off');\n      const ext = xfrm?.querySelector('ext');\n      const left = emuToPx(Number(attr(off || null, 'x') || 0));\n      const top = emuToPx(Number(attr(off || null, 'y') || 0));\n      const w = emuToPx(Number(attr(ext || null, 'cx') || 0)) || 800;\n      const h = emuToPx(Number(attr(ext || null, 'cy') || 0)) || 400;\n      const rows = Array.from(tbl.querySelectorAll('tr'));\n      if (!rows.length) return;\n      const rowH = h / rows.length;\n      rows.forEach((tr, ri) => {\n        const cells = Array.from(tr.querySelectorAll('tc'));\n        const colW = w / Math.max(cells.length, 1);\n        cells.forEach((tc, ci) => {\n          const cellText = Array.from(tc.querySelectorAll('t'))\n            .map((t) => textContent(t))\n            .filter(Boolean)\n            .join(' ');\n          objects.push({\n            type: 'Textbox',\n            version: '6.0.0',\n            left: left + ci * colW + 4,\n            top: top + ri * rowH + 4,\n            width: Math.max(40, colW - 8),\n            height: Math.max(24, rowH - 8),\n            text: cellText || ' ',\n            fontSize: 18,\n            fontFamily: theme.fonts.body,\n            fill: theme.colors.body,\n            id: uid('obj'),\n            placeholderRole: 'table-cell',\n            name: 'table-cell',\n            alt: `Celda ${ri + 1},${ci + 1}`,\n          });\n        });\n      });\n      // subtle table background\n      objects.unshift({\n        type: 'Rect',\n        version: '6.0.0',\n        left,\n        top,\n        width: w,\n        height: h,\n        fill: theme.colors.surface,\n        id: uid('obj'),\n        name: 'table-bg',\n        alt: 'Tabla',\n      });\n    });\n\n    // Pictures\n    const relsPath = path.replace('slides/', 'slides/_rels/') + '.rels';\n    const relMap = getText(relsPath) ? resolveRels(getText(relsPath)!) : new Map();\n    doc.querySelectorAll('pic').forEach((pic) => {\n      const xfrm = pic.querySelector('xfrm');\n      const off = xfrm?.querySelector('off');\n      const ext = xfrm?.querySelector('ext');\n      const left = emuToPx(Number(attr(off || null, 'x') || 0));\n      const top = emuToPx(Number(attr(off || null, 'y') || 0));\n      const w = emuToPx(Number(attr(ext || null, 'cx') || 0));\n      const h = emuToPx(Number(attr(ext || null, 'cy') || 0));\n      const blip = pic.querySelector('blip');\n      const embed =\n        attr(blip, 'r:embed') ||\n        Array.from(blip?.attributes || []).find((a) => a.name.endsWith('embed'))?.value ||\n        '';\n      const target = relMap.get(embed);\n      if (!target) return;\n      const mediaPath = target.startsWith('../')\n        ? `ppt/${target.replace(/^\\.\\.\\//, '')}`\n        : `ppt/slides/${target}`;\n      const bytes = files[mediaPath] || files[mediaPath.replace(/\\\\/g, '/')];\n      if (!bytes) return;\n      const mime = guessMime(mediaPath);\n      const dataUrl = bytesToDataUrl(bytes, mime);\n      const assetId = uid('asset');\n      const blob = new Blob([bytes], { type: mime });\n      const f = new File([blob], mediaPath.split('/').pop() || 'image.png', { type: mime });\n      assets.push({\n        id: assetId,\n        name: f.name,\n        mimeType: mime,\n        file: f,\n        url: URL.createObjectURL(f),\n        width: w,\n        height: h,\n      });\n      const cNvPr = pic.querySelector('cNvPr');\n      const alt = attr(cNvPr, 'descr') || attr(cNvPr, 'title') || f.name;\n      objects.push({\n        type: 'Image',\n        version: '6.0.0',\n        left,\n        top,\n        width: w,\n        height: h,\n        src: dataUrl,\n        id: uid('obj'),\n        assetId,\n        alt,\n      });\n    });\n\n    // Notes\n    let notes = '';\n    const notesPath = path\n      .replace('/slides/', '/notesSlides/')\n      .replace('slide', 'notesSlide');\n    const notesXml = getText(notesPath);\n    if (notesXml) {\n      const nDoc = parseXml(notesXml);\n      notes = Array.from(nDoc.querySelectorAll('t'))\n        .map((t) => textContent(t))\n        .filter(Boolean)\n        .join('\\n');\n    }\n\n    const json = {\n      version: '6.0.0',\n      objects,\n      background: theme.colors.background,\n    };\n\n    slides.push({\n      id: uid('slide'),\n      name: `Diapositiva ${i + 1}`,\n      masterId: master.id,\n      layoutId: 'blank',\n      json,\n      notes,\n      hidden: false,\n      transition: { type: 'cross-dissolve', duration: 0.4 },\n      builds: [],\n      comments: [],\n      history: [JSON.stringify(json)],\n      historyIndex: 0,\n    });\n  }\n\n  if (!slides.length) {\n    throw new Error('No se encontraron diapositivas en el PPTX');\n  }\n\n  return {\n    name: (file instanceof File ? file.name : 'Importado').replace(/\\.pptx$/i, ''),\n    size: { width, height },\n    theme,\n    masters: [master],\n    slides,\n    sections: [\n      {\n        id: uid('sec'),\n        name: 'Importado',\n        slideIds: slides.map((s) => s.id),\n      },\n    ],\n    assets,\n    activeSlideId: slides[0]!.id,\n    schemaVersion: SLIDES_SCHEMA_VERSION,\n    importReport: { degraded: [...new Set(degraded)], slideCount: slides.length },\n  };\n}\n", "import React, { useEffect, useRef, useState } from 'react';\nimport {\n  Grid3x3,\n  Play,\n  Undo2,\n  Redo2,\n} from 'lucide-react';\nimport { EditorShellHeader } from '../editor/EditorShellHeader';\nimport { ShellFileMenu } from '../editor/ShellFileMenu';\nimport { ModeProjectTabs } from '../editor/ModeProjectTabs';\nimport { modeAccentVars } from '../../theme/modeAccent';\nimport { SlidesRightSidebar } from './SlidesRightSidebar';\nimport { SlidesLeftPanel } from './SlidesLeftPanel';\nimport { SlidesCreationToolbar } from './SlidesCreationToolbar';\nimport { SlidesContextToolbar } from './SlidesContextToolbar';\nimport { SlidesContextMenu } from './SlidesContextMenu';\nimport { SlidesAltTextModal } from './SlidesAltTextModal';\nimport { SlidesSnapMagnetButton } from './SlidesSnapMagnetButton';\nimport { useSlidesStore } from '../../store/useSlidesStore';\nimport { SlideCanvas, getSlidesCanvasApi } from './SlideCanvas';\nimport { NotesPanel } from './NotesPanel';\nimport { SlidesExportModal } from './SlidesExportModal';\nimport { PresenterView, openAudienceWindow } from './PresenterView';\nimport {\n  exportProjectToWzrds,\n  importProjectFromWzrds,\n  slidesProjectFromStore,\n} from '../../utils/slidesProjectFile';\nimport { projectAccept } from '../../utils/projectExtensions';\nimport { importPptxFile } from '../../lib/slides/pptx/importPptx';\nimport { uploadCurrentProjectToCloudWithToast } from '../../utils/cloudSaveToast';\nimport { I18nProvider, type Locale, useTranslation } from '../../i18n';\nimport { EditorEmptyState } from '../editor/EditorEmptyState';\nimport type { EditorMode } from '../editor/EditorModeToggle';\nimport type { Editable } from '../../services/editableService';\nimport { TextBody, TextTitle } from '../ui';\ninterface SlidesEditorProps {\n  onSwitchMode?: (mode: EditorMode) => void;\n  onNewProject?: () => void;\n  backHref?: string;\n  backLinkText?: string;\n  locale?: Locale;\n  onBack?: () => void;\n  onOpenCloudProject?: (editable: Editable) => void;\n}\n\nexport const SlidesEditor: React.FC<SlidesEditorProps> = ({\n  onSwitchMode,\n  onNewProject,\n  backHref,\n  backLinkText,\n  locale,\n  onBack,\n  onOpenCloudProject,\n}) => {\n  const t = useTranslation();\n  const {\n    slidesProjects,\n    name,\n    setExportModalOpen,\n    undoSlide,\n    redoSlide,\n    canUndo,\n    canRedo,\n    showGrid,\n    setShowGrid,\n    setIsPresenting,\n    importSlidesProject,\n    addToast,\n    toasts,\n    removeToast,\n    size,\n    theme,\n    masters,\n    slides,\n    sections,\n    assets,\n    activeSlideId,\n    schemaVersion,\n  } = useSlidesStore();\n\n  const fileRef = useRef<HTMLInputElement>(null);\n  const [isSavingCloud, setIsSavingCloud] = useState(false);\n  const hasProject = slidesProjects.length > 0;\n\n  useEffect(() => {\n    if (!hasProject) return;\n    const onKey = (e: KeyboardEvent) => {\n      const tag = (e.target as HTMLElement)?.tagName;\n      const isEditingText =\n        tag === 'INPUT' ||\n        tag === 'TEXTAREA' ||\n        (e.target as HTMLElement)?.isContentEditable ||\n        (e.target as HTMLElement)?.getAttribute('role') === 'textbox';\n      const mod = e.metaKey || e.ctrlKey;\n      const key = e.key.toLowerCase();\n      const api = getSlidesCanvasApi();\n      const canvas = api?.getCanvas();\n      const fabricIsEditing = canvas && (canvas as unknown as { _isTextEditing?: boolean })._isTextEditing;\n\n      if (mod && key === 'z' && !e.shiftKey) {\n        e.preventDefault();\n        undoSlide();\n        return;\n      }\n      if ((mod && key === 'z' && e.shiftKey) || (mod && key === 'y')) {\n        e.preventDefault();\n        redoSlide();\n        return;\n      }\n      if (mod && key === 'd') {\n        e.preventDefault();\n        api?.duplicateSelected();\n        return;\n      }\n      if (mod && key === 'a') {\n        e.preventDefault();\n        api?.selectAll();\n        return;\n      }\n      if (!isEditingText && !fabricIsEditing && (key === 'delete' || key === 'backspace')) {\n        const hasSelection = canvas && canvas.getActiveObjects().length > 0;\n        if (hasSelection) {\n          e.preventDefault();\n          api?.removeSelected();\n        }\n        return;\n      }\n      if (\n        !isEditingText &&\n        !fabricIsEditing &&\n        !mod &&\n        (key === 'arrowleft' ||\n          key === 'arrowright' ||\n          key === 'arrowup' ||\n          key === 'arrowdown')\n      ) {\n        const hasSelection = canvas && canvas.getActiveObjects().length > 0;\n        if (hasSelection) {\n          e.preventDefault();\n          const step = e.shiftKey ? 10 : 1;\n          const dx =\n            key === 'arrowleft' ? -step : key === 'arrowright' ? step : 0;\n          const dy = key === 'arrowup' ? -step : key === 'arrowdown' ? step : 0;\n          api?.nudgeSelected?.(dx, dy);\n        }\n        return;\n      }\n      if (key === 'escape') {\n        if (canvas && canvas.getActiveObjects().length > 0) {\n          canvas.discardActiveObject();\n          canvas.requestRenderAll();\n        }\n      }\n    };\n    window.addEventListener('keydown', onKey);\n    return () => window.removeEventListener('keydown', onKey);\n  }, [hasProject, undoSlide, redoSlide]);\n\n  const saveToCloud = async () => {\n    if (isSavingCloud) return;\n    setIsSavingCloud(true);\n    try {\n      await uploadCurrentProjectToCloudWithToast('slides');\n    } catch {\n      // Error toast is already shown and stays until the user closes it.\n    } finally {\n      setIsSavingCloud(false);\n    }\n  };\n\n  const saveLocal = async () => {\n    const blob = await exportProjectToWzrds(\n      slidesProjectFromStore({\n        id: 'active',\n        name,\n        size,\n        theme,\n        masters,\n        slides,\n        sections,\n        assets,\n        activeSlideId,\n        schemaVersion,\n        createdAt: Date.now(),\n        updatedAt: Date.now(),\n      })\n    );\n    const a = document.createElement('a');\n    a.href = URL.createObjectURL(blob);\n    a.download = `${name || t.slides.editor.fallbackFilename}.kais`;\n    a.click();\n    URL.revokeObjectURL(a.href);\n  };\n\n  const openFile = async (file: File) => {\n    try {\n      const lower = file.name.toLowerCase();\n      if (lower.endsWith('.pptx')) {\n        const data = await importPptxFile(file);\n        importSlidesProject(data, file.name);\n        if (data.importReport.degraded.length) {\n          addToast(t.slides.editor.toasts.pptxImportedWithWarnings(data.importReport.degraded.length), 'warning');\n        } else {\n          addToast(t.slides.editor.toasts.pptxImported, 'success');\n        }\n        return;\n      }\n      const data = await importProjectFromWzrds(file);\n      importSlidesProject(data, file.name);\n      addToast(t.slides.editor.toasts.projectOpened, 'success');\n    } catch {\n      addToast(t.slides.editor.toasts.fileInvalid, 'error');\n    }\n  };\n\n  const shellHeader = (\n    <EditorShellHeader\n      mode=\"slides\"\n      onBack={onBack}\n      backHref={backHref}\n      backLabel={backLinkText}\n      onSwitchMode={(m) => onSwitchMode?.(m)}\n      onNewProject={onNewProject}\n      newProjectTitle={t.editor.newProject.slides}\n      onExport={hasProject ? () => setExportModalOpen(true) : undefined}\n      exportDisabled={!hasProject}\n      fileMenu={\n        <ShellFileMenu\n          onNew={onNewProject}\n          onOpen={() => fileRef.current?.click()}\n          onSave={hasProject ? () => void saveLocal() : undefined}\n          onSaveToCloud={hasProject ? () => void saveToCloud() : undefined}\n          isSavingCloud={isSavingCloud}\n        />\n      }\n      tabs={<ModeProjectTabs mode=\"slides\" />}\n    />\n  );\n\n  if (!hasProject) {\n    return (\n      <I18nProvider locale={locale}>\n        <div\n          data-we-mode=\"slides\"\n          style={modeAccentVars('slides')}\n          className=\"relative flex h-full w-full flex-col bg-[#0A0A0F]\"\n        >\n          {shellHeader}\n          <div className=\"relative min-h-0 flex-1\">\n            <EditorEmptyState\n              mode=\"Slides\"\n              onCreate={onNewProject ?? (() => {})}\n              onOpenCloud={onOpenCloudProject ?? (() => {})}\n            />\n          </div>\n        </div>\n      </I18nProvider>\n    );\n  }\n\n  const api = () => getSlidesCanvasApi();\n  const toolBtn = (active: boolean) =>\n    `flex h-8 w-8 items-center justify-center rounded-lg transition-all active:scale-90 ${\n      active\n        ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--we-accent)_35%,transparent)]'\n        : 'text-white/80 hover:bg-black-capsule hover:text-white'\n    }`;\n\n  return (\n    <I18nProvider locale={locale}>\n      <div\n        data-we-mode=\"slides\"\n        style={modeAccentVars('slides')}\n        className=\"relative flex h-full w-full flex-col bg-[#0A0A0F] text-white\"\n      >\n        {shellHeader}\n\n        <div className=\"flex min-h-0 w-full flex-1\">\n          <SlidesLeftPanel />\n\n          <div className=\"flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden\">\n            <div className=\"relative min-h-0 flex-1 overflow-hidden\">\n              <SlideCanvas />\n            </div>\n\n            <NotesPanel variant=\"dock\" />\n\n            <SlidesContextToolbar getApi={() => api()} />\n\n            <SlidesCreationToolbar\n              getApi={() => api()}\n              leading={\n                <>\n                  <button\n                    type=\"button\"\n                    title={t.toolbar.common.undo}\n                    disabled={!canUndo()}\n                    onClick={() => undoSlide()}\n                    className={`${toolBtn(false)} disabled:pointer-events-none disabled:opacity-30`}\n                  >\n                    <Undo2 size={14} />\n                  </button>\n                  <button\n                    type=\"button\"\n                    title={t.toolbar.common.redo}\n                    disabled={!canRedo()}\n                    onClick={() => redoSlide()}\n                    className={`${toolBtn(false)} disabled:pointer-events-none disabled:opacity-30`}\n                  >\n                    <Redo2 size={14} />\n                  </button>\n                  <div className=\"mx-0.5 h-5 w-px bg-panel-border\" aria-hidden />\n                </>\n              }\n              trailing={\n                <>\n                  <button\n                    type=\"button\"\n                    title={t.slides.editor.gridTitle}\n                    onClick={() => setShowGrid(!showGrid)}\n                    className={toolBtn(showGrid)}\n                  >\n                    <Grid3x3 size={14} />\n                  </button>\n                  <SlidesSnapMagnetButton />\n                  <div className=\"mx-0.5 h-5 w-px bg-panel-border\" aria-hidden />\n                  <button\n                    type=\"button\"\n                    title={t.slides.editor.presentButton}\n                    onClick={() => {\n                      setIsPresenting(true);\n                      openAudienceWindow();\n                    }}\n                    className={toolBtn(false)}\n                  >\n                    <Play size={14} />\n                  </button>\n                </>\n              }\n            />\n          </div>\n\n          <SlidesRightSidebar />\n        </div>\n\n        <SlidesContextMenu />\n        <SlidesAltTextModal />\n        <PresenterView />\n        <SlidesExportModal onSwitchMode={onSwitchMode} />\n\n        <input\n          ref={fileRef}\n          type=\"file\"\n          accept={projectAccept('slides', ['.pptx', '.json'])}\n          className=\"hidden\"\n          onChange={(e) => {\n            const f = e.target.files?.[0];\n            if (f) void openFile(f);\n            e.target.value = '';\n          }}\n        />\n\n        <div className=\"fixed bottom-4 right-20 z-[200] space-y-2\">\n          {toasts.map((toast) => (\n            <div\n              key={toast.id}\n              onClick={() => removeToast(toast.id)}\n              className={`cursor-pointer rounded-lg px-3 py-2 shadow-lg ${\n                toast.type === 'error'\n                  ? 'bg-red-500/90 text-white'\n                  : toast.type === 'success'\n                    ? 'bg-green-600/90 text-white'\n                    : toast.type === 'warning'\n                      ? 'bg-amber-500/90 text-black'\n                      : 'border border-panel-border bg-panel text-white'\n              }`}\n            >\n              <TextBody as=\"p\" size=\"sm\" className=\"font-semibold\">\n                {toast.message}\n              </TextBody>\n            </div>\n          ))}\n        </div>\n      </div>\n    </I18nProvider>\n  );\n};\n", "import React, { lazy, Suspense, useEffect, useState } from 'react';\nimport { ImageRightSidebar } from './components/ImageRightSidebar';\nimport { useEditorStore } from './store/useEditorStore';\nimport { useVideoStore } from './store/useVideoStore';\nimport { useAudioStore } from './store/useAudioStore';\nimport { ToastContainer } from './components/ToastContainer';\nimport { CloudSaveStatusStack } from './components/CloudSaveStatusStack';\nimport { CommandPalette } from './components/CommandPalette';\nimport { PresentationMode } from './components/editor/PresentationMode';\nimport { Loader2 } from 'lucide-react';\nimport { VideoEditor } from './components/editor/VideoEditor';\nimport { ImageEditorChrome } from './components/editor/ImageEditorChrome';\nimport { EditorEmptyState } from './components/editor/EditorEmptyState';\nimport { DialogProvider } from './components/DialogModal';\nimport { I18nProvider, useTranslation, type Locale } from './i18n';\nimport { BrandSelectionProvider } from './context/BrandSelectionContext';\nimport type { EditorBrandOption } from './types/brand.types';\nimport { QAVideo } from './components/video/agent-ui/QAVideo';\nimport { VariationsModal } from './components/ui/VariationsModal';\nimport { modeAccentVars, ModeAccentProvider } from './theme/modeAccent';\nimport { configureWizardApiClient } from './services/wizardApiClient';\nimport {\n  applyHostMediaImport,\n  clearHostMediaImportFromUrl,\n  readHostMediaImport,\n} from './services/hostMediaImport';\nimport {\n  getEditorIdentity,\n  hasEditorIdentity,\n  setEditorIdentity,\n} from './services/identity';\nimport { setActiveEditorBrand } from './services/activeEditorBrand';\nimport { readDevEnv } from './services/devEnv';\nimport {\n  bootstrapFromHostCookies,\n  isOpenedFromWizardHost,\n  readSelectedBrandFromCookie,\n} from './services/hostCookieBootstrap';\nimport { downloadEditableBinary, type Editable } from './services/editableService';\nimport { useTextStore } from './store/useTextStore';\nimport { useSlidesStore } from './store/useSlidesStore';\nimport { useProjectPersistence } from './hooks/useProjectPersistence';\nimport { importProjectFromWzrds } from './utils/slidesProjectFile';\nimport {\n  ProjectSetupModal,\n  type ImageCanvasConfig,\n  type VideoCanvasConfig,\n  type AudioCanvasConfig,\n  type TextCanvasConfig,\n  type SlidesCanvasConfig,\n} from './components/ProjectSetupModal';\n\nconst CanvasArea = lazy(() => import('./components/CanvasArea'));\n\nconst AudioEditor = lazy(() =>\n  import('./components/audio/AudioEditor').then((m) => ({ default: m.AudioEditor }))\n);\n\nconst TextEditor = lazy(() =>\n  import('./components/text/TextEditor').then((m) => ({ default: m.TextEditor }))\n);\n\nconst SlidesEditor = lazy(() =>\n  import('./components/slides/SlidesEditor').then((m) => ({ default: m.SlidesEditor }))\n);\n\n// Dev defaults. In production the host (Wizard) overrides these by calling\n// configureWizardApiClient + setEditorIdentity from its own bootstrap with\n// the real backend URL, JWT, accountId and brandId.\nconst DEV_ENV = readDevEnv();\nconst DEV_BACKEND_URL = DEV_ENV.VITE_BACKEND_URL ?? '';\nconst DEV_JWT = DEV_ENV.VITE_DEV_JWT ?? '';\nconst DEV_ACCOUNT_ID = Number(DEV_ENV.VITE_DEV_ACCOUNT_ID ?? '4');\nconst DEV_BRAND_ID = DEV_ENV.VITE_DEV_BRAND_ID ?? '48';\n\nconfigureWizardApiClient({ baseUrl: DEV_BACKEND_URL, devToken: DEV_JWT });\nsetEditorIdentity({ accountId: DEV_ACCOUNT_ID, brandId: DEV_BRAND_ID });\n\n/** Prefer Wizard localhost cookies when opened from `:3000` in dual-dev. */\nconst HOST_BOOTSTRAP = bootstrapFromHostCookies({\n  accountId: DEV_ACCOUNT_ID,\n  brandId: DEV_BRAND_ID,\n  backendUrl: DEV_BACKEND_URL,\n  devToken: DEV_JWT,\n});\n\n/** Standalone Vite (`pnpm dev` on :5173) \u2014 host passes real brands; here we seed demos. */\nconst STANDALONE_DEV_BRANDS: EditorBrandOption[] = [\n  {\n    id: DEV_BRAND_ID,\n    name: `Dev Brand ${DEV_BRAND_ID}`,\n    logoUrl: 'https://images.unsplash.com/photo-1611162617474-5b21e11e55d4?w=200',\n    brandLogos: [\n      {\n        logoUrl: 'https://images.unsplash.com/photo-1611162617474-5b21e11e55d4?w=200',\n        description: 'Logo principal',\n      },\n      {\n        logoUrl: 'https://images.unsplash.com/photo-1599305445671-ac291c95aaa9?w=200',\n        description: 'Logo alterno',\n      },\n    ],\n    primaryColors: [\n      { name: 'Rosa', hex: '#DB2777' },\n      { name: 'Coral', hex: '#F97316' },\n      { name: 'Crema', hex: '#FEF3C7' },\n      { name: 'Negro', hex: '#0F172A' },\n    ],\n    voice: { id: 'dev-voice', name: 'Cercana, creativa y directa' },\n    textBank: [\n      { id: 'tb1', text: 'Creamos magia visual sin perder claridad.', tag: 'tone' },\n      { id: 'tb2', text: 'Dise\u00F1o que vende, sin ruido de sobra.', tag: 'tone' },\n    ],\n    images: [\n      {\n        id: 'demo-1',\n        url: 'https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=400',\n        alt: 'Abstract demo',\n      },\n    ],\n  },\n  { id: '49', name: 'Dev Brand 49' },\n  { id: '50', name: 'Dev Brand 50' },\n];\nconst STANDALONE_DEV_BRAND =\n  STANDALONE_DEV_BRANDS.find((b) => b.id === DEV_BRAND_ID) ?? STANDALONE_DEV_BRANDS[0]!;\n\nclass ErrorBoundary extends React.Component<{children: React.ReactNode}, {hasError: boolean, error: any}> {\n  constructor(props: any) {\n    super(props);\n    this.state = { hasError: false, error: null };\n  }\n  static getDerivedStateFromError(error: any) {\n    return { hasError: true, error };\n  }\n  render() {\n    if (this.state.hasError) {\n      return (\n        <div className=\"h-screen w-screen bg-red-900 text-white p-10 font-mono text-xs overflow-auto z-[9999] relative\">\n          <h1 className=\"text-2xl mb-4 font-bold\">\u00A1Uy! El editor se rompi\u00F3 \uD83D\uDCA5</h1>\n          <p className=\"mb-4\">Por favor env\u00EDale este error a Antigravity para que lo arregle de inmediato:</p>\n          <pre className=\"bg-black/50 p-4 rounded whitespace-pre-wrap\">{String(this.state.error?.stack || this.state.error)}</pre>\n          <button className=\"mt-4 px-4 py-2 bg-white text-red-900 font-bold rounded\" onClick={() => window.location.reload()}>Recargar p\u00E1gina</button>\n        </div>\n      );\n    }\n    return this.props.children;\n  }\n}\n\ntype AppTab = 'video' | 'image' | 'audio' | 'text' | 'slides';\n\n// Read optional back-link params from the query string so the host (Wizard)\n// can inject them without touching the bundle (e.g. ?backHref=/dashboard&backText=Dashboard).\nfunction useBackLink() {\n  const params = new URLSearchParams(\n    typeof window !== 'undefined' ? window.location.search : ''\n  );\n  return {\n    backLinkHref: params.get('backHref') ?? undefined,\n    backLinkText: params.get('backText') ?? undefined,\n  };\n}\n\nexport interface EditorRootProps {\n  /** UI locale. Defaults to 'es'. */\n  locale?: Locale;\n  /**\n   * Called when the user clicks the persistent \"Back\" button. If omitted,\n   * the button falls back to `window.history.back()`. Hosts like Kaiman\n   * should pass this to route back to the dashboard cleanly.\n   */\n  onBack?: () => void;\n  /**\n   * Active brand for AI `brand_id` and the toolbar label.\n   * Host should keep this in sync with `wizard_selected_brand`.\n   */\n  brand?: EditorBrandOption | null;\n  /** Brands available for the in-toolbar switcher. */\n  brands?: EditorBrandOption[];\n  /**\n   * Fired when the user picks another brand in the toolbar.\n   * Host should update cookie/context; the editor already updates\n   * `setEditorIdentity` so subsequent AI calls use the new brand_id.\n   */\n  onBrandChange?: (brand: EditorBrandOption) => void;\n}\n\nfunction AppContent({\n  onBack,\n  brand: brandProp,\n  brands: brandsProp,\n  onBrandChange,\n}: EditorRootProps = {}) {\n  const t = useTranslation();\n  const { backLinkHref, backLinkText } = useBackLink();\n\n  const fromWizard = isOpenedFromWizardHost() || Boolean(HOST_BOOTSTRAP.brand);\n  const isViteStandalone =\n    Boolean(DEV_ENV.DEV) && brandProp === undefined && brandsProp === undefined;\n\n  const hostBrandsMissing =\n    !isViteStandalone && (!brandsProp || brandsProp.length === 0);\n\n  const [fetchedBrands, setFetchedBrands] = useState<EditorBrandOption[]>(() =>\n    HOST_BOOTSTRAP.brand ? [HOST_BOOTSTRAP.brand] : []\n  );\n\n  // Load brand list when the host omitted `brands`, or in Vite+Wizard dual-dev.\n  useEffect(() => {\n    const shouldFetch =\n      (isViteStandalone && fromWizard) || hostBrandsMissing;\n    if (!shouldFetch) return;\n    let cancelled = false;\n    (async () => {\n      try {\n        // Same-origin BFF (host Next or Vite proxy \u2192 Wizard).\n        const res = await fetch('/api/brands', { credentials: 'include' });\n        if (!res.ok || cancelled) return;\n        const data: unknown = await res.json();\n        const raw = Array.isArray(data) ? data : [];\n        const options: EditorBrandOption[] = [];\n        for (const item of raw) {\n          if (!item || typeof item !== 'object') continue;\n          const b = item as {\n            id?: string | number;\n            brandName?: string;\n            brandLogos?: { logoUrl?: string; description?: string }[];\n            primaryColors?: { name?: string; hex?: string }[];\n            images?: { id?: string; url?: string; alt?: string }[];\n          };\n          if (b.id == null || typeof b.brandName !== 'string') continue;\n          const brandLogos = Array.isArray(b.brandLogos)\n            ? b.brandLogos\n                .filter(\n                  (l): l is { logoUrl: string; description?: string } =>\n                    typeof l?.logoUrl === 'string' && l.logoUrl.length > 0,\n                )\n                .map((l) => ({\n                  logoUrl: l.logoUrl,\n                  description:\n                    typeof l.description === 'string' ? l.description : undefined,\n                }))\n            : undefined;\n          options.push({\n            id: String(b.id),\n            name: b.brandName,\n            logoUrl: brandLogos?.[0]?.logoUrl,\n            brandLogos,\n            primaryColors: Array.isArray(b.primaryColors)\n              ? b.primaryColors\n                  .filter(\n                    (c): c is { name: string; hex: string } =>\n                      typeof c?.hex === 'string' && c.hex.length > 0,\n                  )\n                  .map((c) => ({\n                    name: typeof c.name === 'string' ? c.name : c.hex,\n                    hex: c.hex,\n                  }))\n              : undefined,\n            images: Array.isArray(b.images)\n              ? b.images\n                  .filter(\n                    (img): img is { id: string; url: string; alt?: string } =>\n                      typeof img?.id === 'string' &&\n                      typeof img?.url === 'string' &&\n                      img.url.length > 0,\n                  )\n                  .map((img) => ({\n                    id: img.id,\n                    url: img.url,\n                    alt: typeof img.alt === 'string' ? img.alt : undefined,\n                  }))\n              : undefined,\n          });\n        }\n        if (!cancelled && options.length > 0) setFetchedBrands(options);\n      } catch {\n        // Keep cookie / prop fallback \u2014 brands BFF may be down.\n      }\n    })();\n    return () => {\n      cancelled = true;\n    };\n  }, [isViteStandalone, fromWizard, hostBrandsMissing]);\n\n  const preferredBrand =\n    brandProp ??\n    HOST_BOOTSTRAP.brand ??\n    readSelectedBrandFromCookie() ??\n    (isViteStandalone ? STANDALONE_DEV_BRAND : null);\n\n  const brands = !isViteStandalone\n    ? brandsProp && brandsProp.length > 0\n      ? brandsProp\n      : fetchedBrands.length > 0\n        ? fetchedBrands\n        : preferredBrand\n          ? [preferredBrand]\n          : []\n    : fetchedBrands.length > 0\n      ? fetchedBrands\n      : STANDALONE_DEV_BRANDS;\n\n  // Prefer list entry (logo/metadata) when cookie/prop only has id+name.\n  const brand = preferredBrand\n    ? (brands.find((b) => b.id === preferredBrand.id) ?? preferredBrand)\n    : null;\n\n  // Keep identity + AI brand kit aligned with the resolved selection even when\n  // the host mounts with `brand={null}` before BrandContext hydrates.\n  useEffect(() => {\n    if (!brand) return;\n    setActiveEditorBrand(brand);\n    if (!hasEditorIdentity()) return;\n    const current = getEditorIdentity();\n    if (current.brandId !== brand.id) {\n      setEditorIdentity({ ...current, brandId: brand.id });\n    }\n  }, [brand]);\n\n  const handleBrandChange = (next: EditorBrandOption) => {\n    onBrandChange?.(next);\n    // Keep Wizard cookie in sync when developing against :5173.\n    if (isViteStandalone && typeof document !== 'undefined') {\n      document.cookie = `wizard_selected_brand=${encodeURIComponent(\n        JSON.stringify({\n          id: next.id,\n          brandName: next.name,\n          logoUrl: next.logoUrl,\n        })\n      )}; path=/; SameSite=Lax`;\n    }\n  };\n\n  // Back-handler resolution order:\n  //   1. Host-provided `onBack` (explicit prop).\n  //   2. `?backHref=...` from the URL (the wizard injects this; same source\n  //      that drives the <*TabBar /> \"Volver\" link from Carlos's\n  //      cb7716f feature). Full reload so the dashboard layout resets\n  //      cleanly \u2014 the editor overrides body styles that would otherwise\n  //      stick on SPA navigation.\n  //   3. `window.history.back()` as a last resort so the dropdown item\n  //      is always present, even in the standalone dev server.\n  const resolvedOnBack = onBack\n    ?? (backLinkHref\n        ? () => {\n            if (typeof window !== 'undefined') {\n              window.location.assign(backLinkHref);\n            }\n          }\n        : () => {\n            if (typeof window !== 'undefined' && window.history.length > 1) {\n              window.history.back();\n            }\n          });\n  // Restore last-used tab from localStorage so reloads land on the right editor\n  const [activeTab, _setActiveTab] = useState<AppTab>(() => {\n    try {\n      const saved = localStorage.getItem('we-active-tab');\n      return (saved === 'image' || saved === 'video' || saved === 'audio' || saved === 'text' || saved === 'slides')\n        ? saved\n        : 'video';\n    } catch { return 'video'; }\n  });\n  const setActiveTab = (tab: AppTab) => {\n    _setActiveTab(tab);\n    try { localStorage.setItem('we-active-tab', tab); } catch { /* ignore */ }\n  };\n\n  // Image store\n  const {\n    loadProject,\n    isImageSetupOpen,\n    setIsImageSetupOpen,\n    createImageProject,\n    imageProjects,\n    isProjectLoading,\n  } = useEditorStore();\n\n  // Video store\n  const {\n    isVideoSetupOpen,\n    setIsVideoSetupOpen,\n    createVideoProject,\n    loadVideoProject,\n    isVideoProjectLoading,\n  } = useVideoStore();\n\n  // Audio store\n  const {\n    isAudioSetupOpen,\n    setIsAudioSetupOpen,\n    createAudioProject,\n    loadAudioProject,\n    isAudioProjectLoading,\n  } = useAudioStore();\n\n  // Text store\n  const {\n    isTextSetupOpen,\n    setIsTextSetupOpen,\n    createTextProject,\n    loadTextProject,\n    isTextProjectLoading,\n  } = useTextStore();\n\n  // Slides store\n  const {\n    isSlidesSetupOpen,\n    setIsSlidesSetupOpen,\n    createSlidesProject,\n    loadSlidesProject,\n    isSlidesProjectLoading,\n  } = useSlidesStore();\n\n  // Load stores from IndexedDB on startup\n  useEffect(() => {\n    loadProject();\n    loadVideoProject();\n    loadAudioProject();\n    loadTextProject();\n    loadSlidesProject();\n  }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n  // Shared persistence: IndexedDB (fast) \u2192 cloud (background), flush on hide.\n  // Controllers register themselves when each store module loads.\n  // Pause heartbeat until every mode finishes IndexedDB hydration.\n  const persistenceHydrated =\n    !isProjectLoading &&\n    !isVideoProjectLoading &&\n    !isAudioProjectLoading &&\n    !isTextProjectLoading &&\n    !isSlidesProjectLoading;\n  useProjectPersistence({ hydrated: persistenceHydrated });\n\n  // Wizard agent editor: ?importKind=&mediaUrl= seeds a canvas once stores hydrate.\n  // Timeout survives React strict-mode's setup/cleanup so the import runs once.\n  useEffect(() => {\n    if (!persistenceHydrated) return;\n    const payload = readHostMediaImport();\n    if (!payload) return;\n    const timer = window.setTimeout(() => {\n      clearHostMediaImportFromUrl();\n      void applyHostMediaImport(payload, setActiveTab);\n    }, 0);\n    return () => window.clearTimeout(timer);\n  }, [persistenceHydrated]);\n\n  // \u2500\u2500 Handlers for setup modal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n  const handleCreateImage = (config: ImageCanvasConfig) => {\n    createImageProject(config.name, config.width, config.height, config.backgroundColor);\n    setActiveTab('image');\n  };\n\n  const handleCreateVideo = (config: VideoCanvasConfig) => {\n    createVideoProject(config.name, config.aspectRatio as any, config.backgroundColor);\n    setActiveTab('video');\n  };\n\n  const handleCreateAudio = (config: AudioCanvasConfig) => {\n    createAudioProject(config.name, {\n      sampleRate: config.sampleRate,\n      bpm: config.bpm,\n      template: config.template,\n    });\n    setActiveTab('audio');\n  };\n\n  const handleCreateText = (config: TextCanvasConfig) => {\n    createTextProject(config.name, {\n      docType: config.docType,\n      language: config.language,\n      tone: config.tone,\n      targetChannel: config.targetChannel,\n    });\n    setActiveTab('text');\n  };\n\n  const handleCreateSlides = (config: SlidesCanvasConfig) => {\n    createSlidesProject(config.name, {\n      width: config.width,\n      height: config.height,\n      template: config.template,\n      backgroundColor: config.backgroundColor,\n    });\n    setActiveTab('slides');\n  };\n\n  const handleOpenFile = (file: File) => {\n    const lower = file.name.toLowerCase();\n    const isVideo = lower.endsWith('.kaiv') || lower.endsWith('.wzrdv');\n    const isAudio = lower.endsWith('.kaia') || lower.endsWith('.wzrda');\n    const isSlides =\n      lower.endsWith('.kais') ||\n      lower.endsWith('.wzrds') ||\n      lower.endsWith('.pptx');\n    const isText =\n      lower.endsWith('.kait') ||\n      lower.endsWith('.wzrdt') ||\n      (lower.endsWith('.md') && activeTab === 'text');\n    const isImage = lower.endsWith('.kai') || lower.endsWith('.wzrd');\n    if (isSlides) {\n      void (async () => {\n        try {\n          if (lower.endsWith('.pptx')) {\n            const { importPptxFile } = await import('./lib/slides/pptx/importPptx');\n            const data = await importPptxFile(file);\n            useSlidesStore.getState().importSlidesProject(data, file.name);\n          } else {\n            const { importProjectFromWzrds } = await import('./utils/slidesProjectFile');\n            try {\n              const data = await importProjectFromWzrds(file);\n              useSlidesStore.getState().importSlidesProject(data, file.name);\n            } catch {\n              const text = await file.text();\n              useSlidesStore.getState().importSlidesProject(JSON.parse(text), file.name);\n            }\n          }\n          setActiveTab('slides');\n        } catch {\n          console.error('Failed to open slides project:', file.name);\n        }\n      })();\n      return;\n    }\n    if (isAudio) {\n      void (async () => {\n        try {\n          const { importProjectFromWzrda } = await import('./utils/audioProjectFile');\n          // Try binary first; fall back to JSON text\n          try {\n            const data = await importProjectFromWzrda(file);\n            useAudioStore.getState().importAudioProject(data, file.name);\n          } catch {\n            const text = await file.text();\n            useAudioStore.getState().importAudioProject(JSON.parse(text), file.name);\n          }\n          setActiveTab('audio');\n        } catch {\n          console.error('Failed to open audio project:', file.name);\n        }\n      })();\n      return;\n    }\n    if (isText || (lower.endsWith('.md') && !isSlides)) {\n      void (async () => {\n        try {\n          const { importProjectFromWzrdt } = await import('./utils/textProjectFile');\n          if (lower.endsWith('.md')) {\n            const { markdownToHtml } = await import('./lib/text/markdown');\n            const md = await file.text();\n            const html = markdownToHtml(md);\n            useTextStore.getState().importTextProject(\n              {\n                name: file.name.replace(/\\.md$/i, ''),\n                doc: {\n                  type: 'doc',\n                  content: html\n                    .split(/<\\/p>/i)\n                    .map((chunk) => chunk.replace(/<[^>]+>/g, '').trim())\n                    .filter(Boolean)\n                    .map((text) => ({\n                      type: 'paragraph',\n                      content: [{ type: 'text', text }],\n                    })),\n                },\n              },\n              file.name\n            );\n          } else {\n            try {\n              const data = await importProjectFromWzrdt(file);\n              useTextStore.getState().importTextProject(data, file.name);\n            } catch {\n              const text = await file.text();\n              useTextStore.getState().importTextProject(JSON.parse(text), file.name);\n            }\n          }\n          setActiveTab('text');\n        } catch {\n          console.error('Failed to open text project:', file.name);\n        }\n      })();\n      return;\n    }\n    const reader = new FileReader();\n    reader.onload = (ev) => {\n      try {\n        const data = JSON.parse(ev.target?.result as string);\n        if (isVideo) {\n          useVideoStore.getState().importVideoProject(data, file.name);\n          setActiveTab('video');\n        } else {\n          useEditorStore.getState().importImageProject(data, file.name);\n          setActiveTab('image');\n        }\n      } catch {\n        console.error('Failed to open file:', file.name);\n      }\n    };\n    reader.readAsText(file);\n  };\n\n  /**\n   * Open a project that lives in the cloud (Recientes list). The .NET stores\n   * the file as JSON, so we download the blob, parse it, and dispatch the\n   * right import action. This mirrors `handleOpenFile` but skips the local\n   * file picker and adds the S3 fetch step.\n   */\n  const handleOpenCloudProject = async (editable: Editable) => {\n    try {\n      const blob = await downloadEditableBinary({ url: editable.url });\n      if (editable.mode === 'Slides') {\n        const data = await importProjectFromWzrds(blob);\n        useSlidesStore.getState().importSlidesProject(data, `${editable.name}.kais`, {\n          cloudEditableId: editable.id,\n        });\n        setActiveTab('slides');\n      } else if (editable.mode === 'Audio') {\n        // Prefer binary .wzrda (media embedded). Fall back to legacy JSON cloud saves.\n        try {\n          const { importProjectFromWzrda } = await import('./utils/audioProjectFile');\n          const data = await importProjectFromWzrda(blob);\n          useAudioStore.getState().importAudioProject(data, `${editable.name}.wzrda`, {\n            cloudEditableId: editable.id,\n          });\n        } catch (binErr) {\n          const text = await blob.text();\n          try {\n            const data = JSON.parse(text);\n            useAudioStore.getState().importAudioProject(data, `${editable.name}.kaia`, {\n              cloudEditableId: editable.id,\n            });\n          } catch {\n            throw binErr instanceof Error\n              ? binErr\n              : new Error('No se pudo abrir el proyecto de audio de la nube');\n          }\n        }\n        setActiveTab('audio');\n      } else if (editable.mode === 'Video') {\n        const data = JSON.parse(await blob.text());\n        useVideoStore.getState().importVideoProject(data, `${editable.name}.kaiv`, {\n          cloudEditableId: editable.id,\n        });\n        setActiveTab('video');\n      } else if (editable.mode === 'Text') {\n        // Text cloud saves are JSON; also accept binary wrappers if ever introduced.\n        const buf = await blob.arrayBuffer();\n        const asText = new TextDecoder().decode(buf);\n        try {\n          const data = JSON.parse(asText);\n          useTextStore.getState().importTextProject(data, `${editable.name}.kait`, {\n            cloudEditableId: editable.id,\n          });\n        } catch {\n          const { importProjectFromWzrdt } = await import('./utils/textProjectFile');\n          const data = await importProjectFromWzrdt(new Blob([buf]));\n          useTextStore.getState().importTextProject(data, `${editable.name}.kait`, {\n            cloudEditableId: editable.id,\n          });\n        }\n        setActiveTab('text');\n      } else {\n        // Image: JSON project. Reject HTML/error bodies early.\n        const text = await blob.text();\n        let data: unknown;\n        try {\n          data = JSON.parse(text);\n        } catch {\n          throw new Error(\n            'El archivo de imagen en la nube no es un proyecto .kai v\u00E1lido (JSON).'\n          );\n        }\n        useEditorStore.getState().importImageProject(data, `${editable.name}.kai`, {\n          cloudEditableId: editable.id,\n        });\n        setActiveTab('image');\n      }\n      // Close whichever setup modal was open. We don't know which, so close all.\n      setIsImageSetupOpen(false);\n      setIsVideoSetupOpen(false);\n      setIsAudioSetupOpen(false);\n      setIsTextSetupOpen(false);\n      setIsSlidesSetupOpen(false);\n    } catch (err) {\n      const msg = err instanceof Error ? err.message : String(err);\n      useEditorStore.getState().addToast(\n        `No se pudo abrir \"${editable.name}\" (${editable.mode}): ${msg}`,\n        'error',\n      );\n      throw err;\n    }\n  };\n\n  // Show setup modal only when explicitly requested via the store flag.\n  // The modal is always closeable \u2014 empty state handles the no-project case.\n  const showImageSetup = activeTab === 'image' && isImageSetupOpen;\n  const showVideoSetup = activeTab === 'video' && isVideoSetupOpen;\n  const showAudioSetup = activeTab === 'audio' && isAudioSetupOpen;\n  const showTextSetup = activeTab === 'text' && isTextSetupOpen;\n  const showSlidesSetup = activeTab === 'slides' && isSlidesSetupOpen;\n  const showAnySetup = showImageSetup || showVideoSetup || showAudioSetup || showTextSetup || showSlidesSetup;\n\n  // T-20260727-02: QA mode (?qa=video) monta la p\u00E1gina agent-ui/video\n  // para validar visualmente la copia sin levantar el editor completo.\n  // Se eval\u00FAa despu\u00E9s de los hooks para no violar las Rules of Hooks.\n  // El wrapper outer replica el contenedor h-screen/w-screen del editor\n  // (mismo que envuelve VideoEditor en el return principal), para que\n  // QAVideo use h-full igual que VideoEditor y el render sea id\u00E9ntico.\n  if (typeof window !== 'undefined' &&\n      new URLSearchParams(window.location.search).get('qa') === 'video') {\n    return (\n      <ModeAccentProvider mode=\"video\">\n        <DialogProvider>\n          <div className=\"flex flex-col h-screen w-screen overflow-hidden text-[#F0F0F5]\">\n            <QAVideo />\n          </div>\n        </DialogProvider>\n      </ModeAccentProvider>\n    );\n  }\n\n  // While IndexedDB is loading, show a minimal splash to prevent setup\n  // modals from flashing before we know if saved projects exist.\n  if (isProjectLoading || isVideoProjectLoading || isAudioProjectLoading || isTextProjectLoading || isSlidesProjectLoading) {\n    return (\n      <div className=\"flex h-dvh max-h-dvh w-screen items-center justify-center bg-[#0A0A0F]\">\n        <div className=\"flex flex-col items-center gap-3\">\n          <Loader2 size={28} className=\"text-feature-image animate-spin\" />\n          <span className=\"text-[12px] text-[#8888A0] font-medium tracking-wide\">{t.editor.loadingProject}</span>\n        </div>\n      </div>\n    );\n  }\n\n  return (\n    <ModeAccentProvider mode={activeTab}>\n    <DialogProvider>\n    <BrandSelectionProvider\n      brand={brand}\n      brands={brands}\n      onBrandChange={handleBrandChange}\n    >\n    <div className=\"flex flex-col h-dvh max-h-dvh w-screen overflow-hidden text-[#F0F0F5]\">\n\n      {/* Project Setup Modal \u2014 image or video depending on active tab */}\n      {showAnySetup && (\n        <ProjectSetupModal\n          mode={activeTab}\n          onCreateImage={handleCreateImage}\n          onCreateVideo={handleCreateVideo}\n          onCreateAudio={handleCreateAudio}\n          onCreateText={handleCreateText}\n          onCreateSlides={handleCreateSlides}\n          onOpenFile={handleOpenFile}\n          onOpenCloudProject={handleOpenCloudProject}\n          canClose={true}\n          onClose={() => {\n            if (activeTab === 'image') setIsImageSetupOpen(false);\n            else if (activeTab === 'audio') setIsAudioSetupOpen(false);\n            else if (activeTab === 'text') setIsTextSetupOpen(false);\n            else if (activeTab === 'slides') setIsSlidesSetupOpen(false);\n            else setIsVideoSetupOpen(false);\n          }}\n        />\n      )}\n\n      {/* \u2500\u2500 Persistent Studio Switcher \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Always visible regardless of activeTab. Allows the consumer\n           (and end users) to switch between all 5 modes at any time.\n           Position: top-center, z-[100] so it floats above editor content.\n      \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n\n      {/* Render Selected Workspace */}\n      <div className=\"flex-1 min-h-0 w-full overflow-hidden flex flex-col\">\n        <ErrorBoundary>\n        {activeTab === 'video' ? (\n          <VideoEditor\n            onSwitchToImage={() => setActiveTab('image')}\n            onSwitchToAudio={() => setActiveTab('audio')}\n            onSwitchToText={() => setActiveTab('text')}\n            onSwitchToSlides={() => setActiveTab('slides')}\n            onNewProject={() => setIsVideoSetupOpen(true)}\n            onBack={resolvedOnBack}\n            backHref={backLinkHref}\n            backLinkText={backLinkText}\n            onOpenCloudProject={handleOpenCloudProject}\n          />\n        ) : activeTab === 'audio' ? (\n          <Suspense\n            fallback={\n              <div className=\"flex h-full w-full items-center justify-center bg-[#0A0A0F]\">\n                <Loader2 size={28} className=\"text-[var(--we-accent)] animate-spin\" />\n              </div>\n            }\n          >\n            <AudioEditor\n              onSwitchMode={setActiveTab}\n              onNewProject={() => setIsAudioSetupOpen(true)}\n              onBack={resolvedOnBack}\n              backHref={backLinkHref}\n              backLinkText={backLinkText}\n              onOpenCloudProject={handleOpenCloudProject}\n            />\n          </Suspense>\n        ) : activeTab === 'text' ? (\n          <Suspense\n            fallback={\n              <div className=\"flex h-full w-full items-center justify-center bg-[#0A0A0F]\">\n                <Loader2 size={28} className=\"text-[var(--we-accent)] animate-spin\" />\n              </div>\n            }\n          >\n            <TextEditor\n              onSwitchMode={setActiveTab}\n              onNewProject={() => setIsTextSetupOpen(true)}\n              onBack={resolvedOnBack}\n              backHref={backLinkHref}\n              backLinkText={backLinkText}\n              onOpenCloudProject={handleOpenCloudProject}\n            />\n          </Suspense>\n        ) : activeTab === 'slides' ? (\n          <Suspense\n            fallback={\n              <div className=\"flex h-full w-full items-center justify-center bg-[#0A0A0F]\">\n                <Loader2 size={28} className=\"text-[var(--we-accent)] animate-spin\" />\n              </div>\n            }\n          >\n            <SlidesEditor\n              onSwitchMode={setActiveTab}\n              onNewProject={() => setIsSlidesSetupOpen(true)}\n              onBack={resolvedOnBack}\n              backHref={backLinkHref}\n              backLinkText={backLinkText}\n              onOpenCloudProject={handleOpenCloudProject}\n            />\n          </Suspense>\n        ) : (\n          <div\n            data-we-mode=\"image\"\n            style={modeAccentVars('image')}\n            className=\"flex flex-col h-full min-h-0 w-full overflow-hidden bg-dark-950 text-dark-100 relative\"\n          >\n            <ImageEditorChrome\n              onSwitchMode={setActiveTab}\n              onNewProject={() => setIsImageSetupOpen(true)}\n              onBack={resolvedOnBack}\n              backHref={backLinkHref}\n              backText={backLinkText}\n              hasProject={imageProjects.length > 0}\n            />\n\n            <div className=\"flex flex-col flex-1 min-h-0 overflow-hidden relative\">\n              {imageProjects.length > 0 ? (\n                <>\n                  <div className=\"flex flex-1 min-h-0 w-full overflow-hidden relative\">\n                    <div className=\"relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden\">\n                      <Suspense\n                        fallback={\n                          <div className=\"flex flex-1 items-center justify-center\">\n                            <Loader2 size={28} className=\"text-[var(--we-accent)] animate-spin\" />\n                          </div>\n                        }\n                      >\n                        <CanvasArea />\n                      </Suspense>\n                    </div>\n                    <ImageRightSidebar />\n                  </div>\n                </>\n              ) : (\n                <EditorEmptyState\n                  mode=\"Image\"\n                  onCreate={() => setIsImageSetupOpen(true)}\n                  onOpenCloud={handleOpenCloudProject}\n                />\n              )}\n            </div>\n\n            <CommandPalette />\n            <PresentationMode />\n            <VariationsModal />\n          </div>\n        )}\n        </ErrorBoundary>\n      </div>\n      <ToastContainer />\n      <CloudSaveStatusStack />\n    </div>\n    </BrandSelectionProvider>\n    </DialogProvider>\n    </ModeAccentProvider>\n  );\n}\n\nfunction App(props: EditorRootProps = {}) {\n  return (\n    <I18nProvider locale={props.locale}>\n      <AppContent {...props} />\n    </I18nProvider>\n  );\n}\n\nexport default App;\n", "import React, { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Settings2, Layers, RotateCcw } from 'lucide-react';\nimport { ObjectPropertiesPanel } from './ObjectPropertiesPanel';\nimport { LayersPanel } from './LayersPanel';\nimport { useEditorStore } from '../store/useEditorStore';\nimport { IMG_PANELS_LAYOUT_KEY, PANEL_LAYOUT_RESET_EVENT } from '../utils/panelLayoutReset';\nimport { useTranslation } from '../i18n';\nimport { IconButton, TextTitle, MasterColorPanel } from './ui';\n\ntype PanelId = 'edit' | 'layers';\n\nconst DEFAULT_WIDTH = 320;\nconst MIN_WIDTH = 260;\nconst MAX_WIDTH = 480;\n\ntype StoredLayout = { width?: number; activePanel?: PanelId | null };\n\nfunction loadWidth(): number {\n  try {\n    const raw = localStorage.getItem(IMG_PANELS_LAYOUT_KEY);\n    if (!raw) return DEFAULT_WIDTH;\n    const parsed = JSON.parse(raw) as StoredLayout & {\n      edit?: { width?: number };\n    };\n    // Prefer new shape; fall back to legacy floating-panel width.\n    const w = parsed.width ?? parsed.edit?.width;\n    if (typeof w === 'number' && Number.isFinite(w)) {\n      return Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, w));\n    }\n  } catch {\n    /* ignore */\n  }\n  return DEFAULT_WIDTH;\n}\n\nfunction saveWidth(width: number) {\n  try {\n    localStorage.setItem(IMG_PANELS_LAYOUT_KEY, JSON.stringify({ width } satisfies StoredLayout));\n  } catch {\n    /* quota */\n  }\n}\n\nconst getType = (obj?: { type?: string }) => obj?.type?.toLowerCase() || '';\n\nfunction PanelContent({ id }: { id: PanelId }) {\n  switch (id) {\n    case 'edit':\n      return <ObjectPropertiesPanel />;\n    case 'layers':\n      return <LayersPanel embedded />;\n  }\n}\n\n/**\n * Image right dock \u2014 content + icon rail (same shell pattern as video/slides).\n * Not floating: lives in the 3-column row next to the canvas.\n * One panel is always visible (default Layers) \u2014 never collapse the dock.\n */\nexport const ImageRightSidebar: React.FC = () => {\n  const t = useTranslation();\n  const { activeObject, activeTool, canvasInstance } = useEditorStore();\n  const [activePanel, setActivePanel] = useState<PanelId>('layers');\n  const [panelWidth, setPanelWidth] = useState(loadWidth);\n\n  const hasSelection = !!activeObject && getType(activeObject) !== 'activeselection';\n  const suppressEditPanel =\n    activeTool === 'magic-wand' ||\n    activeTool === 'select-rect' ||\n    activeTool === 'select-ellipse' ||\n    activeTool === 'pixel-lasso' ||\n    activeTool === 'polygon-lasso' ||\n    activeTool === 'eraser' ||\n    activeTool === 'clone-stamp';\n\n  const rail = useMemo(\n    () => [\n      { id: 'edit' as const, icon: <Settings2 size={17} />, label: t.panel.edit, title: t.panel.edit },\n      {\n        id: 'layers' as const,\n        icon: <Layers size={17} />,\n        label: t.panel.layersAndPages,\n        title: t.panel.layersShort,\n      },\n    ],\n    [t],\n  );\n\n  // Fall back to Layers when Edit is unavailable (no selection / pixel tools).\n  useEffect(() => {\n    if (suppressEditPanel || !hasSelection) {\n      setActivePanel((prev) => (prev === 'edit' ? 'layers' : prev));\n    }\n  }, [hasSelection, suppressEditPanel]);\n\n  // Double-click an object on the canvas \u2192 open Edit (single click only selects).\n  useEffect(() => {\n    const canvas = canvasInstance;\n    if (!canvas) return;\n    const onDblClick = (e: { target?: { type?: string } | null }) => {\n      if (suppressEditPanel) return;\n      const target = e?.target;\n      if (!target) return;\n      if (getType(target) === 'activeselection') return;\n      setActivePanel('edit');\n    };\n    canvas.on('mouse:dblclick', onDblClick);\n    return () => {\n      canvas.off('mouse:dblclick', onDblClick);\n    };\n  }, [canvasInstance, suppressEditPanel]);\n\n  useEffect(() => {\n    const onGlobalReset = () => setPanelWidth(DEFAULT_WIDTH);\n    window.addEventListener(PANEL_LAYOUT_RESET_EVENT, onGlobalReset);\n    return () => window.removeEventListener(PANEL_LAYOUT_RESET_EVENT, onGlobalReset);\n  }, []);\n\n  useEffect(() => {\n    saveWidth(panelWidth);\n  }, [panelWidth]);\n\n  const onResizeStart = useCallback(\n    (e: React.MouseEvent) => {\n      e.preventDefault();\n      const startX = e.clientX;\n      const startW = panelWidth;\n      const onMove = (ev: MouseEvent) => {\n        setPanelWidth(Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, startW + (startX - ev.clientX))));\n      };\n      const onUp = () => {\n        window.removeEventListener('mousemove', onMove);\n        window.removeEventListener('mouseup', onUp);\n      };\n      window.addEventListener('mousemove', onMove);\n      window.addEventListener('mouseup', onUp);\n    },\n    [panelWidth],\n  );\n\n  const selectPanel = (id: PanelId) => {\n    if (id === 'edit' && !hasSelection) return;\n    // Always keep one panel open \u2014 clicking the active tab is a no-op.\n    setActivePanel(id);\n  };\n\n  const title = rail.find((r) => r.id === activePanel)?.title ?? t.panel.layersShort;\n\n  return (\n    <aside className=\"flex h-full min-h-0 shrink-0 select-none border-l border-panel-border bg-panel\">\n      <div\n        className=\"relative flex h-full min-h-0 flex-col\"\n        style={{ width: panelWidth }}\n      >\n        <div\n          role=\"separator\"\n          aria-orientation=\"vertical\"\n          aria-label={t.panel.resizeWidth}\n          onMouseDown={onResizeStart}\n          className=\"absolute inset-y-0 left-0 z-10 w-1.5 cursor-ew-resize group/hresize\"\n        >\n          <div className=\"absolute inset-y-0 left-0 w-0.5 rounded-r-full bg-transparent transition-colors group-hover/hresize:bg-[var(--we-accent-capsule)]\" />\n        </div>\n\n        <MasterColorPanel />\n\n        <div className=\"flex min-h-0 flex-1 flex-col border-t border-panel-border\">\n          <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-panel-border px-3 py-2 pl-4\">\n            <TextTitle as=\"h2\" size=\"xs\" className=\"uppercase tracking-wider text-white\">\n              {title}\n            </TextTitle>\n            {panelWidth !== DEFAULT_WIDTH && (\n              <IconButton\n                variant=\"ghost\"\n                size=\"sm\"\n                label={t.panel.resetWidth}\n                onClick={() => setPanelWidth(DEFAULT_WIDTH)}\n              >\n                <RotateCcw size={14} />\n              </IconButton>\n            )}\n          </div>\n\n          <div className=\"min-h-0 flex-1 overflow-y-auto overflow-x-hidden\">\n            <PanelContent id={activePanel} />\n          </div>\n        </div>\n      </div>\n\n      <div className=\"flex w-11 shrink-0 flex-col items-center gap-1.5 border-l border-panel-border bg-panel py-2\">\n        {rail.map(({ id, icon, label }) => {\n          const isActive = activePanel === id;\n          const isDisabled = id === 'edit' && !hasSelection;\n          return (\n            <button\n              key={id}\n              type=\"button\"\n              onClick={() => selectPanel(id)}\n              title={label}\n              disabled={isDisabled}\n              aria-pressed={isActive}\n              className={`\n                relative group flex items-center justify-center w-8 h-8 rounded-lg\n                transition-all duration-150 select-none\n                ${\n                  isDisabled\n                    ? 'opacity-40 cursor-not-allowed'\n                    : isActive\n                      ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--we-accent)_35%,transparent)] active:scale-90'\n                      : 'text-[#8888A0] hover:text-white hover:bg-[#1C1C26] active:scale-90 cursor-pointer'\n                }\n              `}\n            >\n              {isActive && !isDisabled && (\n                <span className=\"absolute left-0 top-1/2 h-4 w-0.5 -translate-y-1/2 rounded-r-full bg-[var(--we-accent)]\" />\n              )}\n              {icon}\n              {!isActive && !isDisabled && (\n                <span className=\"tooltip-bubble right-full top-1/2 mr-3 -translate-y-1/2\">{label}</span>\n              )}\n              {isDisabled && (\n                <span className=\"tooltip-bubble right-full top-1/2 mr-3 -translate-y-1/2 whitespace-nowrap\">\n                  {t.panel.selectElement}\n                </span>\n              )}\n            </button>\n          );\n        })}\n      </div>\n    </aside>\n  );\n};\n\nexport default ImageRightSidebar;\n", "import React, { useState, useEffect, useRef } from 'react';\nimport { useEditorStore, fitTextboxToContent, isTextObject } from '../store/useEditorStore';\nimport { ChevronDown, Bold, Italic, Underline, AlignLeft, AlignCenter, AlignRight, Type, UploadCloud, Trash2, Link2, Link2Off } from 'lucide-react';\nimport { filters, Gradient, Shadow } from 'fabric';\nimport { LevelsFilter, LUTFilter, AdvancedHSLFilter } from '../utils/fabricCustomFilters';\nimport { applyFabricImageFilters } from '../utils/applyFabricImageFilters';\nimport {\n  applyIndependentCornerRadii,\n  applyLinkedCornerRadius,\n  cornersAreLinked,\n  installIndependentCornerRender,\n  readCornerRadii,\n  type CornerRadii,\n} from '../utils/roundedRectCorners';\nimport { HistogramLevels } from './editor/HistogramLevels';\nimport { CurvesEditor } from './editor/CurvesEditor';\nimport { GOOGLE_FONTS_CATALOG } from './Sidebar';\nimport { generateLoremIpsum } from '../utils/loremUtils';\nimport { useTranslation } from '../i18n';\nimport { Button, PanelField, PanelBody, PanelSection, AspectLockGroup, Switch, SelectDropdown, ColorInput, IconButton, FontPickerFlyout, TextBody, TextTitle } from './ui';\nimport type { FontPickerEntry } from './ui';\n\n// Re-export SOLID_PRESETS so other parts of the codebase can import from here as well\nexport const SOLID_PRESETS = [\n  '#ffffff', '#f3f4f6', '#e2e8f0', '#94a3b8', '#475569', '#0f172a',\n  '#000000', '#ef4444', '#f97316', '#f59e0b', '#10b981', '#06b6d4',\n  '#3b82f6', '#6366f1', '#8b5cf6', '#d946ef', '#ec4899', '#14b8a6'\n];\n\n// \u2500\u2500\u2500 helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Fabric v6 uses capitalized types (`Image`); always compare case-insensitively. */\nfunction isImageObject(obj: any): boolean {\n  return (obj?.type || '').toLowerCase() === 'image';\n}\n\n/** Normalise the active object type to one of the display buckets. */\nfunction getType(obj: any): 'image' | 'shape' | 'text' | null {\n  if (!obj) return null;\n  const t = (obj.type || '').toLowerCase();\n  if (t === 'image') return 'image';\n  if (['textbox', 'text'].includes(t) || obj?.constructor?.name === 'Textbox3D') return 'text';\n  if (['rect', 'circle', 'triangle', 'line', 'ellipse', 'polygon', 'path', 'group'].includes(t)) return 'shape';\n  return null;\n}\n\ntype ExportFormat = 'png' | 'jpg' | 'svg';\n\nfunction SelectionExportSection({\n  activeObject,\n  scale,\n  format,\n  revision,\n  onScaleChange,\n  onFormatChange,\n  onDownload,\n}: {\n  activeObject: { toDataURL?: (opts: Record<string, unknown>) => string; toSVG?: () => string; type?: string };\n  scale: number;\n  format: ExportFormat;\n  /** Bumps when the selection is edited so the thumbnail refreshes. */\n  revision: number;\n  onScaleChange: (n: number) => void;\n  onFormatChange: (f: ExportFormat) => void;\n  onDownload: () => void;\n}) {\n  const t = useTranslation();\n  const [previewUrl, setPreviewUrl] = useState<string | null>(null);\n\n  useEffect(() => {\n    if (!activeObject?.toDataURL) {\n      setPreviewUrl(null);\n      return;\n    }\n    try {\n      const url = activeObject.toDataURL({\n        format: 'png',\n        quality: 0.85,\n        multiplier: Math.min(2, Math.max(0.5, scale)),\n      });\n      setPreviewUrl(url);\n    } catch {\n      setPreviewUrl(null);\n    }\n  }, [activeObject, scale, format, revision]);\n\n  return (\n    <PanelSection title={t.properties.shape.export}>\n      <div className=\"flex items-center justify-center overflow-hidden rounded-xl bg-black-capsule p-3\">\n        {previewUrl ? (\n          <img\n            src={previewUrl}\n            alt={t.properties.shape.exportPreview}\n            className=\"max-h-28 max-w-full object-contain select-none\"\n          />\n        ) : (\n          <TextBody as=\"span\" size=\"sm\" className=\"py-6 text-white/80\">\n            {t.properties.shape.exportPreview}\n          </TextBody>\n        )}\n      </div>\n      <div className=\"flex items-center gap-1.5\">\n        <div className=\"min-w-0 flex-1\">\n          <SelectDropdown\n            ariaLabel={t.properties.shape.scale}\n            value={String(scale)}\n            onChange={(v) => onScaleChange(parseInt(v, 10))}\n            className=\"w-full rounded-xl bg-black-capsule px-3 py-1.5\"\n            options={[\n              { value: '1', label: t.properties.shape.scale1x },\n              { value: '2', label: t.properties.shape.scale2x },\n              { value: '3', label: t.properties.shape.scale3x },\n            ]}\n          />\n        </div>\n        <div className=\"min-w-0 flex-1\">\n          <SelectDropdown\n            ariaLabel={t.properties.shape.format}\n            value={format}\n            onChange={(v) => onFormatChange(v as ExportFormat)}\n            className=\"w-full rounded-xl bg-black-capsule px-3 py-1.5\"\n            options={[\n              { value: 'png', label: 'PNG' },\n              { value: 'jpg', label: 'JPG' },\n              { value: 'svg', label: 'SVG' },\n            ]}\n          />\n        </div>\n        <Button variant=\"accent\" size=\"sm\" className=\"shrink-0\" onClick={onDownload}>\n          {t.properties.shape.downloadLayer}\n        </Button>\n      </div>\n    </PanelSection>\n  );\n}\n\n// \u2500\u2500\u2500 TransformPanel (universal: posici\u00F3n, tama\u00F1o, rotaci\u00F3n) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction TransformPanel() {\n  const t = useTranslation();\n  const { activeObject, canvasInstance, saveHistoryState } = useEditorStore();\n  const [, setTick] = useState(0);\n  const [aspectLocked, setAspectLocked] = useState(true);\n  const aspectRatioRef = useRef(1);\n\n  useEffect(() => {\n    if (!canvasInstance) return;\n    const refresh = () => setTick((n) => n + 1);\n    canvasInstance.on('object:moving', refresh);\n    canvasInstance.on('object:scaling', refresh);\n    canvasInstance.on('object:rotating', refresh);\n    canvasInstance.on('object:modified', refresh);\n    return () => {\n      canvasInstance.off('object:moving', refresh);\n      canvasInstance.off('object:scaling', refresh);\n      canvasInstance.off('object:rotating', refresh);\n      canvasInstance.off('object:modified', refresh);\n    };\n  }, [canvasInstance]);\n\n  useEffect(() => {\n    if (aspectLocked || !activeObject) return;\n    const cw = Math.round((activeObject.width || 0) * (activeObject.scaleX || 1));\n    const ch = Math.round((activeObject.height || 0) * (activeObject.scaleY || 1));\n    if (cw > 0 && ch > 0) aspectRatioRef.current = cw / ch;\n  }, [aspectLocked, activeObject, activeObject?.width, activeObject?.height, activeObject?.scaleX, activeObject?.scaleY]);\n\n  if (!activeObject) return null;\n\n  const w = Math.round((activeObject.width || 0) * (activeObject.scaleX || 1));\n  const h = Math.round((activeObject.height || 0) * (activeObject.scaleY || 1));\n  const x = Math.round(activeObject.left || 0);\n  const y = Math.round(activeObject.top || 0);\n  const r = ((Math.round(activeObject.angle || 0) % 360) + 360) % 360;\n  const opacityPct = Math.round((activeObject.opacity ?? 1) * 100);\n  const isText = isTextObject(activeObject);\n\n  const paint = () => {\n    canvasInstance?.requestRenderAll();\n  };\n\n  const commit = () => {\n    canvasInstance?.requestRenderAll();\n    if (isTextObject(activeObject)) {\n      fitTextboxToContent(activeObject);\n      useEditorStore.getState().setActiveObject(activeObject);\n    }\n    saveHistoryState();\n    setTick((n) => n + 1);\n  };\n\n  const applyWidth = (next: number) => {\n    const v = Math.max(1, next);\n    if (isText) {\n      (activeObject as any).weTextAutoWidth = false;\n      activeObject.set({ width: v, scaleX: 1, dirty: true });\n      if (typeof activeObject.initDimensions === 'function') activeObject.initDimensions();\n      activeObject.setCoords();\n    } else {\n      activeObject.set({ scaleX: v / (activeObject.width || 1) });\n    }\n  };\n\n  const applyHeight = (next: number) => {\n    const v = Math.max(1, next);\n    if (isText) {\n      const curH = Math.max(1, (activeObject.height || 1) * (activeObject.scaleY || 1));\n      const ratio = v / curH;\n      activeObject.set({\n        fontSize: Math.max(1, (activeObject.fontSize || 40) * ratio),\n        width: Math.max(20, (activeObject.width || 0) * ratio),\n        scaleX: 1,\n        scaleY: 1,\n        dirty: true,\n      });\n      if (typeof activeObject.initDimensions === 'function') activeObject.initDimensions();\n      fitTextboxToContent(activeObject);\n      activeObject.setCoords();\n      useEditorStore.getState().setActiveObject(activeObject);\n    } else {\n      activeObject.set({ scaleY: v / (activeObject.height || 1) });\n    }\n  };\n\n  const setWidth = (v: number) => {\n    const next = Math.max(1, v);\n    applyWidth(next);\n    if (aspectLocked) {\n      const ratio = aspectRatioRef.current > 0 ? aspectRatioRef.current : w / Math.max(1, h);\n      applyHeight(Math.max(1, Math.round(next / ratio)));\n    }\n    paint();\n  };\n\n  const setHeight = (v: number) => {\n    const next = Math.max(1, v);\n    applyHeight(next);\n    if (aspectLocked) {\n      const ratio = aspectRatioRef.current > 0 ? aspectRatioRef.current : w / Math.max(1, h);\n      applyWidth(Math.max(1, Math.round(next * ratio)));\n    }\n    paint();\n  };\n\n  const handleAspectLockChange = (locked: boolean) => {\n    if (locked && w > 0 && h > 0) {\n      aspectRatioRef.current = w / h;\n    }\n    setAspectLocked(locked);\n  };\n\n  return (\n    <PanelSection title={t.properties.text.transformTitle} divided>\n      <AspectLockGroup\n        locked={aspectLocked}\n        onLockedChange={handleAspectLockChange}\n        lockLabel={t.canvas.sizePanel.lockRatio}\n        unlockLabel={t.canvas.sizePanel.unlockRatio}\n      >\n        <PanelField\n          variant=\"slide\"\n          label={t.properties.shape.width}\n          min={1}\n          max={4000}\n          step={1}\n          numericValue={w}\n          onChange={setWidth}\n          onCommit={commit}\n        />\n        <PanelField\n          variant=\"slide\"\n          label={t.properties.shape.height}\n          min={1}\n          max={4000}\n          step={1}\n          numericValue={h}\n          onChange={setHeight}\n          onCommit={commit}\n        />\n      </AspectLockGroup>\n\n      <PanelField\n        variant=\"slide\"\n        label={t.properties.shape.positionX}\n        min={-2000}\n        max={4000}\n        step={1}\n        numericValue={x}\n        onChange={(v) => {\n          activeObject.set({ left: v });\n          paint();\n        }}\n        onCommit={commit}\n      />\n      <PanelField\n        variant=\"slide\"\n        label={t.properties.shape.positionY}\n        min={-2000}\n        max={4000}\n        step={1}\n        numericValue={y}\n        onChange={(v) => {\n          activeObject.set({ top: v });\n          paint();\n        }}\n        onCommit={commit}\n      />\n      <PanelField\n        variant=\"slide\"\n        label={t.properties.text.rotation}\n        min={0}\n        max={360}\n        step={1}\n        numericValue={r}\n        formatValue={(n) => `${n}\u00B0`}\n        onChange={(v) => {\n          activeObject.set({ angle: v });\n          paint();\n        }}\n        onCommit={commit}\n      />\n      <PanelField\n        variant=\"slide\"\n        label={t.properties.shape.opacity}\n        min={0}\n        max={100}\n        step={1}\n        numericValue={opacityPct}\n        formatValue={(n) => `${n}%`}\n        onChange={(v) => {\n          activeObject.set({ opacity: Math.max(0, Math.min(100, v)) / 100 });\n          paint();\n        }}\n        onCommit={commit}\n      />\n    </PanelSection>\n  );\n}\n\n// \u2500\u2500\u2500 TextPropertiesPanel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction TextPropertiesPanel({ activeTab }: { activeTab: 'propiedades' | 'insertar' | 'lorem' | 'fuentes' }) {\n  const t = useTranslation();\n  const {\n    textSettings,\n    updateTextSettings,\n    activeObject,\n    canvasInstance,\n    customFonts,\n    addCustomFont,\n    deleteCustomFont,\n    setActiveTool,\n    saveHistoryState,\n  } = useEditorStore();\n\n  const [isFontDropdownOpen, setIsFontDropdownOpen] = useState(false);\n  const fontTriggerRef = useRef<HTMLButtonElement | null>(null);\n  const fontCommitRef = useRef(textSettings.fontFamily);\n  const [loremLength, setLoremLength] = useState<'words' | 'sentences' | 'paragraphs'>('paragraphs');\n  const [loremAmount, setLoremAmount] = useState(3);\n\n  const isTextSelected = isTextObject(activeObject);\n  const segmentActive = 'bg-[var(--we-accent-capsule)] text-white';\n  const segmentIdle = 'text-white/80 hover:text-white';\n\n  /** Live preview: store only \u2014 CanvasArea loads the face then remasures.\n   * Avoid Fabric `set({ fontFamily })` here: sync initDimensions against the\n   * fallback face shrinks the selection box before the real glyphs paint. */\n  const applyFontLive = (family: string) => {\n    if (!activeObject || !isTextObject(activeObject)) return;\n    useEditorStore.setState((s) => ({\n      textSettings: { ...s.textSettings, fontFamily: family },\n    }));\n  };\n\n  const previewFont = (name: string | null) => {\n    applyFontLive(name ?? fontCommitRef.current);\n  };\n\n  const styleBtn = (on: boolean) =>\n    `flex-1 cursor-pointer rounded-lg py-2 flex justify-center transition-colors ${\n      on ? segmentActive : segmentIdle\n    }`;\n\n  const fontEntries: FontPickerEntry[] = [\n    ...customFonts.map((f) => ({ name: f.name, custom: true as const })),\n    ...GOOGLE_FONTS_CATALOG.map((f) => ({ name: f.name, category: f.category })),\n  ];\n\n  const fontCategoryLabels: Record<string, string> = {\n    'Sans-Serif': t.properties.text.fontCategory.sansSerif,\n    Serif: t.properties.text.fontCategory.serif,\n    'Display / T\u00EDtulos': t.properties.text.fontCategory.display,\n    Escritura: t.properties.text.fontCategory.handwriting,\n    Monospace: t.properties.text.fontCategory.monospace,\n  };\n\n  return (\n    <>\n        {activeTab === 'propiedades' && (\n          <>\n            {isTextSelected ? (\n            <>\n              <PanelSection title={t.properties.text.typography}>\n                <PanelField\n                  label={t.properties.text.typography}\n                  trailing={\n                  <button\n                      ref={fontTriggerRef}\n                      type=\"button\"\n                      onClick={() => {\n                        fontCommitRef.current = textSettings.fontFamily;\n                        setIsFontDropdownOpen((v) => !v);\n                      }}\n                      aria-haspopup=\"listbox\"\n                      aria-expanded={isFontDropdownOpen}\n                      className=\"inline-flex max-w-[9.5rem] items-center gap-1 select-none rounded-lg py-0.5 text-ink-primary\"\n                    style={{ fontFamily: textSettings.fontFamily }}\n                  >\n                      <TextBody as=\"span\" size=\"sm\" className=\"min-w-0 truncate\">{textSettings.fontFamily}</TextBody>\n                      <ChevronDown\n                        size={12}\n                        strokeWidth={2.25}\n                        className={`shrink-0 text-white/80 transition-transform ${isFontDropdownOpen ? 'rotate-180' : ''}`}\n                      />\n                  </button>\n                  }\n                />\n                <FontPickerFlyout\n                  open={isFontDropdownOpen}\n                  onClose={() => setIsFontDropdownOpen(false)}\n                  anchorRef={fontTriggerRef}\n                  value={fontCommitRef.current}\n                  fonts={fontEntries}\n                  categoryLabels={fontCategoryLabels}\n                  customSectionLabel={t.properties.text.myFonts}\n                  searchPlaceholder={t.properties.text.searchFonts}\n                  deleteLabel={t.properties.text.deleteFontTitle}\n                  onPreview={previewFont}\n                  onSelect={(name) => {\n                    fontCommitRef.current = name;\n                    updateTextSettings({ fontFamily: name });\n                  }}\n                  onDeleteCustom={deleteCustomFont}\n                />\n\n                <PanelField\n                  variant=\"slide\"\n                  label={t.properties.text.fontSize}\n                  min={1}\n                  max={400}\n                  step={1}\n                  numericValue={textSettings.fontSize}\n                  formatValue={(n) => `${n}px`}\n                  onChange={(v) => updateTextSettings({ fontSize: Math.max(1, v) })}\n                />\n\n                <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{t.properties.text.style}</TextBody>\n                <div className=\"flex gap-1 rounded-xl bg-black-capsule p-1\">\n                  <button\n                    type=\"button\"\n                    title={t.properties.text.bold}\n                    onClick={() =>\n                      updateTextSettings({\n                        fontWeight: textSettings.fontWeight === 'bold' ? 'normal' : 'bold',\n                      })\n                    }\n                    className={styleBtn(textSettings.fontWeight === 'bold')}\n                  >\n                    <Bold size={15} />\n                  </button>\n                  <button\n                    type=\"button\"\n                    title={t.properties.text.italic}\n                    onClick={() =>\n                      updateTextSettings({\n                        fontStyle: textSettings.fontStyle === 'italic' ? 'normal' : 'italic',\n                      })\n                    }\n                    className={styleBtn(textSettings.fontStyle === 'italic')}\n                  >\n                    <Italic size={15} />\n                  </button>\n                  <button\n                    type=\"button\"\n                    title={t.properties.text.underline}\n                    onClick={() => updateTextSettings({ underline: !textSettings.underline })}\n                    className={styleBtn(!!textSettings.underline)}\n                  >\n                    <Underline size={15} />\n                  </button>\n                  <button\n                    type=\"button\"\n                    title={t.properties.text.strikethrough}\n                    onClick={() => updateTextSettings({ linethrough: !textSettings.linethrough })}\n                    className={styleBtn(!!textSettings.linethrough)}\n                  >\n                    <TextBody as=\"span\" size=\"sm\" className=\"font-bold line-through\">S</TextBody>\n                  </button>\n                  <button\n                    type=\"button\"\n                    title={t.properties.text.overline}\n                    onClick={() => updateTextSettings({ overline: !textSettings.overline })}\n                    className={styleBtn(!!textSettings.overline)}\n                  >\n                    <TextBody as=\"span\" size=\"sm\" className=\"font-bold [text-decoration:overline]\">T</TextBody>\n                  </button>\n                  </div>\n              </PanelSection>\n\n              <PanelSection title={t.properties.text.color}>\n                <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n                  {t.properties.text.usesMasterColor}\n                </TextBody>\n                <PanelField\n                  variant=\"slide\"\n                  label={t.properties.text.thickness}\n                  min={0}\n                  max={20}\n                  step={0.5}\n                  numericValue={textSettings.strokeWidth || 0}\n                  formatValue={(n) => `${n}`}\n                  onChange={(val) => {\n                    const masterStroke = useEditorStore.getState().masterColors.stroke;\n                    const patch: { strokeWidth: number; stroke?: string } = { strokeWidth: val };\n                    if (val > 0 && (!textSettings.stroke || textSettings.stroke === 'transparent')) {\n                      patch.stroke = masterStroke || '#000000';\n                    }\n                    updateTextSettings(patch);\n                  }}\n                />\n              </PanelSection>\n\n              <PanelSection title={t.properties.text.alignment}>\n                <div className=\"flex gap-1 rounded-xl bg-black-capsule p-1\">\n                  {(\n                    [\n                      { id: 'left', icon: <AlignLeft size={15} /> },\n                      { id: 'center', icon: <AlignCenter size={15} /> },\n                      { id: 'right', icon: <AlignRight size={15} /> },\n                    ] as const\n                  ).map((item) => (\n                    <button\n                      key={item.id}\n                      type=\"button\"\n                      onClick={() => updateTextSettings({ textAlign: item.id })}\n                      className={styleBtn(textSettings.textAlign === item.id)}\n                    >\n                      {item.icon}\n                    </button>\n                  ))}\n                  </div>\n                <PanelField\n                  variant=\"slide\"\n                  label={t.properties.text.lineHeight}\n                  min={0.8}\n                  max={3}\n                  step={0.05}\n                  numericValue={textSettings.lineHeight}\n                  formatValue={(n) => n.toFixed(2)}\n                  onChange={(v) => updateTextSettings({ lineHeight: v })}\n                />\n                <PanelField\n                  variant=\"slide\"\n                  label={t.properties.text.letterSpacing}\n                  min={-50}\n                  max={300}\n                  step={10}\n                  numericValue={textSettings.charSpacing}\n                  onChange={(v) => updateTextSettings({ charSpacing: v })}\n                />\n                <PanelField\n                  variant=\"slide\"\n                  label={t.properties.text.textCurvature}\n                  min={-100}\n                  max={100}\n                  step={5}\n                  numericValue={textSettings.curvature || 0}\n                  formatValue={(n) => `${n}%`}\n                  onChange={(v) => updateTextSettings({ curvature: v })}\n                />\n              </PanelSection>\n\n              <PanelSection title={t.properties.text.textShadow}>\n                <PanelField\n                  label={t.properties.text.textShadow}\n                  trailing={\n                    <Switch\n                      checked={!!textSettings.textShadowEnabled}\n                      ariaLabel={t.properties.text.textShadow}\n                      onChange={(enabled) => updateTextSettings({ textShadowEnabled: enabled })}\n                    />\n                  }\n                />\n                  {textSettings.textShadowEnabled && (\n                  <div className=\"flex flex-col gap-1.5\">\n                    <ColorInput\n                      label={t.properties.shape.shadowColor}\n                      opacityLabel={t.properties.shape.opacity}\n                      value={textSettings.textShadowColor || '#000000'}\n                      onChange={(css) => updateTextSettings({ textShadowColor: css })}\n                    />\n                    <PanelField\n                      variant=\"slide\"\n                      label={t.properties.text.blur}\n                      min={0}\n                      max={30}\n                      step={1}\n                      numericValue={textSettings.textShadowBlur || 0}\n                      formatValue={(n) => `${n}px`}\n                      onChange={(v) => updateTextSettings({ textShadowBlur: v })}\n                    />\n                    <PanelField\n                      variant=\"slide\"\n                      label={t.properties.text.offsetX}\n                      min={-20}\n                      max={20}\n                      step={1}\n                      numericValue={textSettings.textShadowOffsetX || 0}\n                      formatValue={(n) => `${n}px`}\n                      onChange={(v) => updateTextSettings({ textShadowOffsetX: v })}\n                    />\n                    <PanelField\n                      variant=\"slide\"\n                      label={t.properties.text.offsetY}\n                      min={-20}\n                      max={20}\n                      step={1}\n                      numericValue={textSettings.textShadowOffsetY || 0}\n                      formatValue={(n) => `${n}px`}\n                      onChange={(v) => updateTextSettings({ textShadowOffsetY: v })}\n                    />\n                    </div>\n                  )}\n              </PanelSection>\n            </>\n          ) : (\n            <div className=\"flex flex-col items-center justify-center gap-3 py-10 text-center\">\n              <Type size={28} className=\"text-white/40\" />\n              <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">{t.properties.text.noTextSelected}</TextBody>\n              <Button variant=\"accent\" size=\"sm\" onClick={() => setActiveTool('text')}>\n                {t.properties.text.activateTextTool}\n              </Button>\n              </div>\n            )}\n          </>\n        )}\n\n        {activeTab === 'insertar' && (\n        <PanelSection title={t.properties.text.addTextToCanvas}>\n          <button\n            type=\"button\"\n            onClick={() => {\n              updateTextSettings({ fontSize: 48, fontWeight: 'bold' });\n              setActiveTool('text');\n            }}\n            className=\"flex w-full cursor-pointer items-center justify-between rounded-xl bg-black-capsule px-4 py-3 transition-colors hover:bg-black-capsule-hover\"\n          >\n            <TextTitle as=\"span\" size=\"lg\">{t.properties.text.addTitle}</TextTitle>\n            {/* TODO i18n */}\n            <TextBody as=\"span\" size=\"sm\" className=\"tabular-nums text-white/80\">48px</TextBody>\n              </button>\n          <button\n            type=\"button\"\n            onClick={() => {\n              updateTextSettings({ fontSize: 28, fontWeight: 'bold' });\n              setActiveTool('text');\n            }}\n            className=\"flex w-full cursor-pointer items-center justify-between rounded-xl bg-black-capsule px-4 py-2.5 transition-colors hover:bg-black-capsule-hover\"\n          >\n            <TextBody as=\"span\" size=\"md\" className=\"text-ink-primary\">\n              {t.properties.text.addSubtitle}\n            </TextBody>\n            {/* TODO i18n */}\n            <TextBody as=\"span\" size=\"sm\" className=\"tabular-nums text-white/80\">28px</TextBody>\n              </button>\n          <button\n            type=\"button\"\n            onClick={() => {\n              updateTextSettings({ fontSize: 16, fontWeight: 'normal' });\n              setActiveTool('text');\n            }}\n            className=\"flex w-full cursor-pointer items-center justify-between rounded-xl bg-black-capsule px-4 py-2 transition-colors hover:bg-black-capsule-hover\"\n          >\n            <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n              {t.properties.text.addBodyText}\n            </TextBody>\n            {/* TODO i18n */}\n            <TextBody as=\"span\" size=\"sm\" className=\"tabular-nums text-white/80\">16px</TextBody>\n              </button>\n        </PanelSection>\n        )}\n\n        {activeTab === 'lorem' && (\n        <PanelSection title={t.properties.text.loremGenerator} description={t.properties.text.loremHint}>\n          <div className=\"flex flex-col gap-1.5\">\n            <SelectDropdown\n              ariaLabel={t.properties.text.loremGenerator}\n              value={loremLength}\n              onChange={(v) => setLoremLength(v as 'words' | 'sentences' | 'paragraphs')}\n              className=\"w-full rounded-xl bg-black-capsule px-3 py-1.5\"\n              options={[\n                { value: 'words', label: t.properties.text.loremWords },\n                { value: 'sentences', label: t.properties.text.loremSentences },\n                { value: 'paragraphs', label: t.properties.text.loremParagraphs },\n              ]}\n            />\n            <PanelField\n              variant=\"slide\"\n              label={t.properties.text.loremAmount}\n              min={1}\n              max={100}\n              step={1}\n              numericValue={loremAmount}\n              onChange={setLoremAmount}\n            />\n            </div>\n          <Button\n            variant=\"accent\"\n            className=\"w-full\"\n              onClick={() => {\n                const text = generateLoremIpsum(loremLength, loremAmount);\n                const canvas = canvasInstance;\n                if (!canvas) return;\n              const active = canvas.getActiveObject() as { type?: string; set?: (p: Record<string, unknown>) => void } | null;\n              if (active && isTextObject(active)) {\n                active.set?.({ text });\n                  canvas.requestRenderAll();\n                  saveHistoryState();\n                } else {\n                  updateTextSettings({ fontSize: 24, fontWeight: 'normal' });\n                  setActiveTool('text');\n                  setTimeout(() => {\n                  const a = canvas.getActiveObject() as { set?: (p: Record<string, unknown>) => void } | null;\n                  if (a?.set) {\n                    a.set({ text });\n                    canvas.requestRenderAll();\n                    saveHistoryState();\n                  }\n                  }, 200);\n                }\n              }}\n          >\n            {t.properties.text.loremApply}\n          </Button>\n        </PanelSection>\n      )}\n\n        {activeTab === 'fuentes' && (\n        <PanelSection title={t.properties.text.uploadFonts} description={t.properties.text.supportedFormats}>\n          <div className=\"relative flex cursor-pointer flex-col items-center justify-center rounded-xl border border-dashed border-panel-border bg-black-capsule px-4 py-5 transition-colors hover:border-[var(--we-accent)]/50 hover:bg-black-capsule-hover\">\n              <input\n              type=\"file\"\n              accept=\".ttf,.otf,.woff,.woff2\"\n                onChange={(e) => {\n                const file = e.target.files?.[0];\n                if (!file) return;\n                  const name = file.name.substring(0, file.name.lastIndexOf('.'));\n                  const reader = new FileReader();\n                reader.onload = (event) => {\n                  const dataUrl = event.target?.result as string;\n                  addCustomFont(name, dataUrl);\n                };\n                  reader.readAsDataURL(file);\n                }}\n              className=\"absolute inset-0 h-full w-full cursor-pointer opacity-0\"\n            />\n            <UploadCloud size={20} className=\"mb-1.5 text-white/80\" />\n            <TextBody as=\"span\" size=\"sm\" className=\"text-ink-primary\">{t.properties.text.uploadFontFile}</TextBody>\n            <TextBody as=\"span\" size=\"sm\" className=\"mt-1 text-white/80\">{t.properties.text.uploadHint}</TextBody>\n            </div>\n            {customFonts.length > 0 && (\n            <div className=\"flex flex-col gap-1\">\n              <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{t.properties.text.loadedFonts}</TextBody>\n                {customFonts.map((f) => (\n                <div\n                  key={f.name}\n                  className=\"group flex items-center justify-between rounded-xl bg-black-capsule px-3 py-2\"\n                >\n                  <span style={{ fontFamily: f.name }}>\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-ink-primary\">{f.name}</TextBody>\n                  </span>\n                  <button\n                    type=\"button\"\n                    onClick={() => deleteCustomFont(f.name)}\n                    className=\"cursor-pointer rounded p-1 text-white/40 transition-colors hover:bg-red-500/10 hover:text-red-400 group-hover:text-white/80\"\n                    title={t.properties.text.deleteFontTitle}\n                  >\n                    <Trash2 size={11} />\n                  </button>\n                  </div>\n                ))}\n              </div>\n            )}\n        </PanelSection>\n        )}\n    </>\n  );\n}\n\n// \u2500\u2500\u2500 TextEditorLayout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Composici\u00F3n: [Tabs] \u2192 PanelBody([TransformPanel?] + tab content)\n\ntype TextTab = 'propiedades' | 'insertar' | 'lorem' | 'fuentes';\nconst TEXT_TAB_IDS: TextTab[] = ['propiedades', 'insertar', 'lorem', 'fuentes'];\n\nfunction TextEditorLayout() {\n  const t = useTranslation();\n  const [activeTab, setActiveTab] = useState<TextTab>('propiedades');\n  const textTabLabels: Record<TextTab, string> = {\n    propiedades: t.properties.text.tabProperties,\n    insertar: t.properties.text.tabInsert,\n    lorem: t.properties.text.tabLorem,\n    fuentes: t.properties.text.tabFonts,\n  };\n  return (\n    <div className=\"flex w-full flex-col\">\n      <div className=\"flex shrink-0 gap-1 border-b border-panel-border p-1.5\">\n        {TEXT_TAB_IDS.map((id) => (\n          <button\n            key={id}\n            type=\"button\"\n            onClick={() => setActiveTab(id)}\n            className={`flex-1 cursor-pointer rounded-lg px-2 py-2 transition-colors ${\n              activeTab === id\n                ? 'bg-[var(--we-accent-capsule)] text-white'\n                : 'text-white/80 hover:bg-black-capsule hover:text-white'\n            }`}\n          >\n            <TextBody as=\"span\" size=\"sm\">{textTabLabels[id]}</TextBody>\n          </button>\n        ))}\n      </div>\n\n      <PanelBody>\n      {activeTab === 'propiedades' && <TransformPanel />}\n      <TextPropertiesPanel activeTab={activeTab} />\n      </PanelBody>\n    </div>\n  );\n}\n\n// \u2500\u2500\u2500 component \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const ObjectPropertiesPanel: React.FC = () => {\n  const t = useTranslation();\n\n  const filterApplyTimeoutRef = useRef<any>(null);\n\n  const {\n    activeObject,\n    canvasInstance,\n    imageSettings,\n    updateImageSettings,\n    saveHistoryState,\n    extractedColors,\n  } = useEditorStore();\n\n  // \u2500\u2500 Local shape/shadow state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  const [sidebarUpdateTrigger, setSidebarUpdateTrigger] = useState(0);\n  const [shapeFillTab, setShapeFillTab] = useState<'solid' | 'gradient' | 'none'>('solid');\n  const [shapeGradStart, setShapeGradStart] = useState('#3b82f6');\n  const [shapeGradEnd, setShapeGradEnd] = useState('#8b5cf6');\n  const [shapeGradAngle, setShapeGradAngle] = useState(90);\n  const [shapeStrokeStyle, setShapeStrokeStyle] = useState<'solid' | 'dashed' | 'dotted'>('solid');\n  const [shapeShadowEnabled, setShapeShadowEnabled] = useState(false);\n  const [shapeShadowColor, setShapeShadowColor] = useState('#000000');\n  const [shapeShadowBlur, setShapeShadowBlur] = useState(10);\n  const [shapeShadowOffsetX, setShapeShadowOffsetX] = useState(5);\n  const [shapeShadowOffsetY, setShapeShadowOffsetY] = useState(5);\n\n  // Export selection state\n  const [exportSelScale, setExportSelScale] = useState<number>(1);\n  const [exportSelFormat, setExportSelFormat] = useState<'png' | 'jpg' | 'svg'>('png');\n\n  // Compare state (image filters)\n  const [isComparing, setIsComparing] = useState(false);\n\n  // \u2500\u2500 Event listener: sync trigger on object interactions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  useEffect(() => {\n    if (!canvasInstance) return;\n\n    const handleObjectChange = () => {\n      setSidebarUpdateTrigger((prev) => prev + 1);\n    };\n\n    canvasInstance.on('object:moving', handleObjectChange);\n    canvasInstance.on('object:scaling', handleObjectChange);\n    canvasInstance.on('object:rotating', handleObjectChange);\n    canvasInstance.on('object:modified', handleObjectChange);\n    canvasInstance.on('selection:created', handleObjectChange);\n    canvasInstance.on('selection:updated', handleObjectChange);\n\n    return () => {\n      canvasInstance.off('object:moving', handleObjectChange);\n      canvasInstance.off('object:scaling', handleObjectChange);\n      canvasInstance.off('object:rotating', handleObjectChange);\n      canvasInstance.off('object:modified', handleObjectChange);\n      canvasInstance.off('selection:created', handleObjectChange);\n      canvasInstance.off('selection:updated', handleObjectChange);\n    };\n  }, [canvasInstance]);\n\n  // \u2500\u2500 Sync shape state from active object \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  useEffect(() => {\n    if (!activeObject) return;\n\n    // 1. Fill type\n    const fill = activeObject.fill;\n    if (!fill || fill === 'transparent') {\n      setShapeFillTab('none');\n    } else if (typeof fill === 'object' && fill !== null && (fill as any).type) {\n      setShapeFillTab('gradient');\n      const grad = fill as any;\n      if (grad.colorStops && grad.colorStops.length >= 2) {\n        setShapeGradStart(grad.colorStops[0].color);\n        setShapeGradEnd(grad.colorStops[1].color);\n      }\n      if (grad.coords) {\n        const coords = grad.coords;\n        const dx = (coords.x2 || 0) - (coords.x1 || 0);\n        const dy = (coords.y2 || 0) - (coords.y1 || 0);\n        const angle = Math.round((Math.atan2(dy, dx) * 180) / Math.PI);\n        setShapeGradAngle(angle < 0 ? angle + 360 : angle);\n      }\n    } else {\n      setShapeFillTab('solid');\n    }\n\n    // 2. Stroke style (dash array)\n    const dash = activeObject.strokeDashArray;\n    if (!dash) {\n      setShapeStrokeStyle('solid');\n    } else if (dash[0] === 8) {\n      setShapeStrokeStyle('dashed');\n    } else {\n      setShapeStrokeStyle('dotted');\n    }\n\n    // 3. Shadow status\n    const shadow = activeObject.shadow as any;\n    if (shadow && (shadow.blur > 0 || shadow.offsetX !== 0 || shadow.offsetY !== 0)) {\n      setShapeShadowEnabled(true);\n      setShapeShadowColor(shadow.color || '#000000');\n      setShapeShadowBlur(shadow.blur || 10);\n      setShapeShadowOffsetX(shadow.offsetX || 5);\n      setShapeShadowOffsetY(shadow.offsetY || 5);\n    } else {\n      setShapeShadowEnabled(false);\n    }\n  }, [activeObject, sidebarUpdateTrigger]);\n\n  // \u2500\u2500 Image filter functions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n  const applyImageFilter = (filterName: string, value: any) => {\n    if (!canvasInstance || !activeObject || !isImageObject(activeObject)) return;\n    const imgObj = activeObject as any;\n\n    if (!imgObj.filters) imgObj.filters = [];\n\n    let filterIndex = -1;\n\n    switch (filterName) {\n      case 'brightness':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Brightness);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.Brightness({ brightness: value });\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({ brightness: value, activePreset: 'custom' });\n        break;\n\n      case 'contrast':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Contrast);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.Contrast({ contrast: value });\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({ contrast: value, activePreset: 'custom' });\n        break;\n\n      case 'saturation':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Saturation);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.Saturation({ saturation: value });\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({ saturation: value, activePreset: 'custom' });\n        break;\n\n      case 'blur':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Blur);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.Blur({ blur: value });\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({ blur: value, activePreset: 'custom' });\n        break;\n\n      case 'hue':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.HueRotation);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.HueRotation({ rotation: value });\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({ hueRotation: value, activePreset: 'custom' });\n        break;\n\n      case 'exposure':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Gamma);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const gVal = 1 / (1 + value);\n          const filter = new filters.Gamma({ gamma: [gVal, gVal, gVal] });\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({ exposure: value, activePreset: 'custom' });\n        break;\n\n      case 'invert':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Invert);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.Invert();\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({ invert: value === 1, activePreset: 'custom' });\n        break;\n\n      case 'levels':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof LevelsFilter);\n        if (value.black === 0 && value.mid === 1 && value.white === 255) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new LevelsFilter(value);\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        updateImageSettings({\n          levelsBlack: value.black,\n          levelsMid: value.mid,\n          levelsWhite: value.white,\n          activePreset: 'custom'\n        });\n        break;\n\n      case 'curves':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof LUTFilter);\n        if (!value || value.length !== 256 || LUTFilter.isIdentityLut(value)) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n          updateImageSettings({ lut: undefined, activePreset: 'custom' });\n        } else {\n          const filter = new LUTFilter({ lut: value });\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n          updateImageSettings({ lut: value, activePreset: 'custom' });\n        }\n        break;\n\n      case 'grayscale':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Grayscale);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.Grayscale();\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        break;\n\n      case 'sepia':\n        filterIndex = imgObj.filters.findIndex((f: any) => f instanceof filters.Sepia);\n        if (value === 0) {\n          if (filterIndex > -1) imgObj.filters.splice(filterIndex, 1);\n        } else {\n          const filter = new filters.Sepia();\n          if (filterIndex > -1) imgObj.filters[filterIndex] = filter;\n          else imgObj.filters.push(filter);\n        }\n        break;\n    }\n\n    const hasCustomFilter = imgObj.filters.some((f: any) =>\n      f instanceof LevelsFilter || f instanceof LUTFilter || f instanceof AdvancedHSLFilter\n    );\n\n    if (filterApplyTimeoutRef.current) clearTimeout(filterApplyTimeoutRef.current);\n\n    const runApply = () => {\n      applyFabricImageFilters(imgObj, hasCustomFilter);\n      canvasInstance.requestRenderAll();\n    };\n\n    // Identity curves/levels must refresh the preview immediately (debounce left a stale bitmap).\n    const flushNow =\n      filterName === 'curves' ||\n      filterName === 'levels' ||\n      filterName === 'invert' ||\n      filterName === 'grayscale' ||\n      filterName === 'sepia';\n\n    if (flushNow) {\n      runApply();\n    } else {\n      filterApplyTimeoutRef.current = setTimeout(runApply, 100);\n    }\n  };\n\n  const reapplyAllFilters = (settings: typeof imageSettings) => {\n    if (!canvasInstance || !activeObject || !isImageObject(activeObject)) return;\n    const imgObj = activeObject as any;\n    imgObj.filters = [];\n\n    if (settings.activePreset && settings.activePreset !== 'original') {\n      switch (settings.activePreset) {\n        case 'grayscale':\n          imgObj.filters.push(new filters.Grayscale());\n          break;\n        case 'sepia':\n          imgObj.filters.push(new filters.Sepia());\n          break;\n        case 'vintage':\n          imgObj.filters.push(new filters.HueRotation({ rotation: 0.08 }));\n          imgObj.filters.push(new filters.Brightness({ brightness: 0.05 }));\n          imgObj.filters.push(new filters.Contrast({ contrast: -0.1 }));\n          imgObj.filters.push(new filters.Saturation({ saturation: -0.15 }));\n          break;\n        case 'cyberpunk':\n          imgObj.filters.push(new filters.HueRotation({ rotation: 0.55 }));\n          imgObj.filters.push(new filters.Contrast({ contrast: 0.15 }));\n          imgObj.filters.push(new filters.Saturation({ saturation: 0.25 }));\n          break;\n        case 'polar':\n          imgObj.filters.push(new filters.HueRotation({ rotation: -0.15 }));\n          imgObj.filters.push(new filters.Brightness({ brightness: -0.05 }));\n          imgObj.filters.push(new filters.Contrast({ contrast: 0.1 }));\n          imgObj.filters.push(new filters.Saturation({ saturation: -0.05 }));\n          break;\n        case 'sunset':\n          imgObj.filters.push(new filters.HueRotation({ rotation: 0.05 }));\n          imgObj.filters.push(new filters.Saturation({ saturation: 0.2 }));\n          imgObj.filters.push(new filters.Contrast({ contrast: 0.05 }));\n          break;\n        case 'fade':\n          imgObj.filters.push(new filters.Contrast({ contrast: -0.15 }));\n          imgObj.filters.push(new filters.Brightness({ brightness: 0.05 }));\n          imgObj.filters.push(new filters.Saturation({ saturation: -0.1 }));\n          break;\n        case 'noir':\n          imgObj.filters.push(new filters.Grayscale());\n          imgObj.filters.push(new filters.Contrast({ contrast: 0.25 }));\n          imgObj.filters.push(new filters.Brightness({ brightness: -0.05 }));\n          break;\n      }\n    }\n\n    if (settings.brightness !== 0) imgObj.filters.push(new filters.Brightness({ brightness: settings.brightness }));\n    if (settings.contrast !== 0) imgObj.filters.push(new filters.Contrast({ contrast: settings.contrast }));\n    if (settings.saturation !== 0) imgObj.filters.push(new filters.Saturation({ saturation: settings.saturation }));\n    if (settings.blur !== 0) imgObj.filters.push(new filters.Blur({ blur: settings.blur }));\n    if (settings.hueRotation !== 0) imgObj.filters.push(new filters.HueRotation({ rotation: settings.hueRotation }));\n    if (settings.exposure !== undefined && settings.exposure !== 0) {\n      const gVal = 1 / (1 + settings.exposure);\n      imgObj.filters.push(new filters.Gamma({ gamma: [gVal, gVal, gVal] }));\n    }\n    if (settings.invert) imgObj.filters.push(new filters.Invert());\n\n    if (\n      settings.levelsBlack !== undefined ||\n      settings.levelsMid !== undefined ||\n      settings.levelsWhite !== undefined\n    ) {\n      const black = settings.levelsBlack ?? 0;\n      const mid = settings.levelsMid ?? 1;\n      const white = settings.levelsWhite ?? 255;\n      if (!(black === 0 && mid === 1 && white === 255)) {\n        imgObj.filters.push(new LevelsFilter({ black, mid, white }));\n      }\n    }\n    if (settings.lut && settings.lut.length === 256) {\n      imgObj.filters.push(new LUTFilter({ lut: settings.lut }));\n    }\n\n    const hasCustomFilter = imgObj.filters.some((f: any) =>\n      f instanceof LevelsFilter || f instanceof LUTFilter || f instanceof AdvancedHSLFilter\n    );\n    applyFabricImageFilters(imgObj, hasCustomFilter);\n    canvasInstance.requestRenderAll();\n  };\n\n  const resetAllFilters = () => {\n    if (!canvasInstance || !activeObject || !isImageObject(activeObject)) return;\n    const imgObj = activeObject as any;\n\n    imgObj.filters = [];\n\n    imgObj.set({\n      shadow: null,\n      stroke: null,\n      strokeWidth: 0,\n      globalCompositeOperation: 'source-over',\n    });\n    setShapeShadowEnabled(false);\n\n    imgObj.applyFilters();\n    canvasInstance.requestRenderAll();\n\n    updateImageSettings({\n      brightness: 0,\n      contrast: 0,\n      saturation: 0,\n      blur: 0,\n      hueRotation: 0,\n      exposure: 0,\n      invert: false,\n      activePreset: 'original',\n    });\n  };\n\n  const startComparing = () => {\n    if (!canvasInstance || !activeObject || !isImageObject(activeObject)) return;\n    const imgObj = activeObject as any;\n\n    imgObj.__originalEffects = {\n      shadow: imgObj.shadow,\n      stroke: imgObj.stroke,\n      strokeWidth: imgObj.strokeWidth,\n      globalCompositeOperation: imgObj.globalCompositeOperation,\n    };\n\n    imgObj.set({\n      shadow: null,\n      stroke: null,\n      strokeWidth: 0,\n      globalCompositeOperation: 'source-over',\n    });\n\n    imgObj.filters = [];\n    imgObj.applyFilters();\n    canvasInstance.requestRenderAll();\n    setIsComparing(true);\n  };\n\n  const stopComparing = () => {\n    if (!isComparing) return;\n\n    if (activeObject && isImageObject(activeObject)) {\n      const imgObj = activeObject as any;\n      if (imgObj.__originalEffects) {\n        imgObj.set(imgObj.__originalEffects);\n        delete imgObj.__originalEffects;\n      }\n    }\n\n    reapplyAllFilters(imageSettings);\n    setIsComparing(false);\n  };\n\n  const saveFilterHistory = () => {\n    saveHistoryState();\n    setSidebarUpdateTrigger((n) => n + 1);\n  };\n\n  // Export selection helper\n  const handleExportSelection = () => {\n    if (!canvasInstance || !activeObject) return;\n\n    if (exportSelFormat === 'svg') {\n      try {\n        const svgCode = activeObject.toSVG();\n        const blob = new Blob([svgCode], { type: 'image/svg+xml;charset=utf-8' });\n        const url = URL.createObjectURL(blob);\n        const link = document.createElement('a');\n        link.href = url;\n        link.download = `${activeObject.type || 'layer'}-${Date.now()}.svg`;\n        link.click();\n        URL.revokeObjectURL(url);\n      } catch (err) {\n        console.error('Export selection to SVG failed:', err);\n      }\n      return;\n    }\n\n    try {\n      const dataUrl = activeObject.toDataURL({\n        format: exportSelFormat === 'png' ? 'png' : 'jpeg',\n        quality: 0.95,\n        multiplier: exportSelScale,\n      });\n\n      const link = document.createElement('a');\n      link.href = dataUrl;\n      link.download = `${activeObject.type || 'layer'}-${Date.now()}.${exportSelFormat}`;\n      link.click();\n    } catch (err) {\n      console.error('Export selection failed:', err);\n    }\n  };\n\n  // \u2500\u2500\u2500 Determine what to render \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  const type = getType(activeObject);\n\n  // \u2500\u2500\u2500 No selection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  if (!activeObject || type === null) {\n    return (\n      <div className=\"flex flex-col items-center justify-center p-6 text-center bg-dark-850 rounded-lg border border-dark-750\">\n        <TextBody as=\"p\" size=\"sm\" className=\"text-dark-400\">{t.panel.selectObjectForProps}</TextBody>\n      </div>\n    );\n  }\n\n  if (type === 'text') {\n    return <TextEditorLayout />;\n  }\n\n  if (type === 'image') {\n    return (\n      <PanelBody>\n        <TransformPanel />\n        <PanelSection\n          title={t.properties.image.photoAdjustments}\n          description={t.properties.image.photoFiltersSubtitle}\n        >\n          <PanelField\n            variant=\"slide\"\n            label={t.properties.image.exposure}\n            min={-80}\n            max={80}\n            step={4}\n            numericValue={Math.round((imageSettings.exposure || 0) * 100)}\n            defaultValue={0}\n            resetLabel={t.common.reset}\n            formatValue={(n) => `${n}%`}\n            onChange={(v) => applyImageFilter('exposure', v / 100)}\n            onCommit={saveFilterHistory}\n          />\n          <PanelField\n            variant=\"slide\"\n            label={t.properties.image.brightness}\n            min={-50}\n            max={50}\n            step={2}\n            numericValue={Math.round((imageSettings.brightness || 0) * 100)}\n            defaultValue={0}\n            resetLabel={t.common.reset}\n            formatValue={(n) => `${n}%`}\n            onChange={(v) => applyImageFilter('brightness', v / 100)}\n            onCommit={saveFilterHistory}\n          />\n          <PanelField\n            variant=\"slide\"\n            label={t.properties.image.contrast}\n            min={-50}\n            max={50}\n            step={2}\n            numericValue={Math.round((imageSettings.contrast || 0) * 100)}\n            defaultValue={0}\n            resetLabel={t.common.reset}\n            formatValue={(n) => `${n}%`}\n            onChange={(v) => applyImageFilter('contrast', v / 100)}\n            onCommit={saveFilterHistory}\n          />\n          <PanelField\n            variant=\"slide\"\n            label={t.properties.image.saturation}\n            min={-80}\n            max={80}\n            step={4}\n            numericValue={Math.round((imageSettings.saturation || 0) * 100)}\n            defaultValue={0}\n            resetLabel={t.common.reset}\n            formatValue={(n) => `${n}%`}\n            onChange={(v) => applyImageFilter('saturation', v / 100)}\n            onCommit={saveFilterHistory}\n          />\n          <PanelField\n            variant=\"slide\"\n            label={t.properties.image.hue}\n            min={-180}\n            max={180}\n            step={9}\n            numericValue={Math.round((imageSettings.hueRotation || 0) * 180)}\n            defaultValue={0}\n            resetLabel={t.common.reset}\n            formatValue={(n) => `${n}\u00B0`}\n            onChange={(v) => applyImageFilter('hue', v / 180)}\n            onCommit={saveFilterHistory}\n          />\n          <PanelField\n            variant=\"slide\"\n            label={t.properties.image.blur}\n            min={0}\n            max={60}\n            step={2}\n            numericValue={Math.round((imageSettings.blur || 0) * 100)}\n            defaultValue={0}\n            resetLabel={t.common.reset}\n            formatValue={(n) => `${n}%`}\n            onChange={(v) => applyImageFilter('blur', v / 100)}\n            onCommit={saveFilterHistory}\n          />\n          <PanelField\n            label={t.properties.image.invertColors}\n            trailing={\n              <Switch\n                checked={!!imageSettings.invert}\n                ariaLabel={t.properties.image.invertColors}\n                onChange={(next) => {\n                  applyImageFilter('invert', next ? 1 : 0);\n                  saveFilterHistory();\n                }}\n              />\n            }\n          />\n        </PanelSection>\n\n        <PanelSection title={t.properties.image.proAdjustments}>\n          <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{t.properties.image.levels}</TextBody>\n              <HistogramLevels\n                activeObject={activeObject}\n                currentLevels={{\n              black: imageSettings.levelsBlack ?? 0,\n              mid: imageSettings.levelsMid ?? 1,\n              white: imageSettings.levelsWhite ?? 255\n                }}\n                onLevelsChange={(black, mid, white) => {\n                  applyImageFilter('levels', { black, mid, white });\n                }}\n            onCommit={saveFilterHistory}\n              />\n              <CurvesEditor\n                onCurveChange={(lut) => {\n                  applyImageFilter('curves', lut);\n                  saveFilterHistory();\n                }}\n              />\n        </PanelSection>\n\n        <SelectionExportSection\n          activeObject={activeObject}\n          scale={exportSelScale}\n          format={exportSelFormat}\n          revision={sidebarUpdateTrigger}\n          onScaleChange={setExportSelScale}\n          onFormatChange={setExportSelFormat}\n          onDownload={handleExportSelection}\n        />\n      </PanelBody>\n    );\n  }\n\n  // \u2500\u2500\u2500 SHAPE PROPERTIES \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  const paintShape = () => {\n                    canvasInstance?.requestRenderAll();\n  };\n\n  const bumpShape = () => {\n    paintShape();\n                  saveHistoryState();\n    setSidebarUpdateTrigger((n) => n + 1);\n  };\n\n  const applyShapeLinearGradient = (start: string, end: string, angle: number) => {\n    const w = activeObject.width || 100;\n    const h = activeObject.height || 100;\n    const rad = (angle * Math.PI) / 180;\n    const coords = {\n      x1: w / 2 - Math.cos(rad) * (w / 2),\n      y1: h / 2 - Math.sin(rad) * (h / 2),\n      x2: w / 2 + Math.cos(rad) * (w / 2),\n      y2: h / 2 + Math.sin(rad) * (h / 2),\n    };\n                  activeObject.set({\n      fill: new Gradient({\n        type: 'linear',\n        coords,\n        colorStops: [\n          { offset: 0, color: start },\n          { offset: 1, color: end },\n        ],\n      }),\n    });\n  };\n\n  const segmentActive = 'bg-[var(--we-accent-capsule)] text-white';\n  const segmentIdle = 'text-white/80 hover:text-white';\n\n  return (\n    <PanelBody>\n      <PanelSection\n        title={t.properties.shape.adjustShape}\n        trailing={\n          <TextBody as=\"span\" size=\"sm\" className=\"rounded-lg border border-[var(--we-accent-muted)] bg-[var(--we-accent-muted)] px-1.5 py-0.5 capitalize text-[var(--we-accent)]\">{activeObject.type === 'path'\n              ? t.properties.shape.shapeBadge.vector\n              : activeObject.type === 'rect'\n                ? t.properties.shape.shapeBadge.rect\n                : activeObject.type === 'group'\n                  ? t.properties.shape.shapeBadge.frame\n                  : activeObject.type}</TextBody>\n        }\n      />\n      <TransformPanel />\n\n      {/* Fill */}\n      {activeObject.type !== 'line' && activeObject.type !== 'image' && (\n        <PanelSection title={t.properties.shape.shapeFill}>\n          <div className=\"flex gap-1 rounded-xl bg-black-capsule p-1\">\n            <button\n              type=\"button\"\n              onClick={() => {\n                setShapeFillTab('solid');\n                const fill = useEditorStore.getState().masterColors.fill;\n                activeObject.set({ fill });\n                setShapeGradStart(fill);\n                bumpShape();\n              }}\n              className={`flex-1 cursor-pointer rounded-lg py-2 transition-colors ${\n                shapeFillTab === 'solid' ? segmentActive : segmentIdle\n              }`}\n            >\n              <TextBody as=\"span\" size=\"sm\">{t.properties.shape.fillSolid}</TextBody>\n            </button>\n            <button\n              type=\"button\"\n              onClick={() => {\n                setShapeFillTab('gradient');\n                applyShapeLinearGradient(shapeGradStart, shapeGradEnd, shapeGradAngle);\n                bumpShape();\n              }}\n              className={`flex-1 cursor-pointer rounded-lg py-2 transition-colors ${\n                shapeFillTab === 'gradient' ? segmentActive : segmentIdle\n              }`}\n            >\n              <TextBody as=\"span\" size=\"sm\">{t.properties.shape.fillGradient}</TextBody>\n            </button>\n            <button\n              type=\"button\"\n              onClick={() => {\n                setShapeFillTab('none');\n                activeObject.set({ fill: 'transparent' });\n                bumpShape();\n              }}\n              className={`flex-1 cursor-pointer rounded-lg py-2 transition-colors ${\n                shapeFillTab === 'none' ? segmentActive : segmentIdle\n              }`}\n            >\n              <TextBody as=\"span\" size=\"sm\">{t.properties.shape.fillNone}</TextBody>\n            </button>\n          </div>\n\n          {shapeFillTab === 'solid' && (\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {t.properties.shape.usesMasterFill}\n            </TextBody>\n          )}\n\n          {shapeFillTab === 'gradient' && (\n            <div className=\"flex flex-col gap-1.5\">\n              <ColorInput\n                label={t.properties.shape.start}\n                opacityLabel={t.properties.shape.opacity}\n                      value={shapeGradStart}\n                onChange={(css) => {\n                  setShapeGradStart(css);\n                  applyShapeLinearGradient(css, shapeGradEnd, shapeGradAngle);\n                  paintShape();\n                }}\n                onCommit={bumpShape}\n              />\n              <ColorInput\n                label={t.properties.shape.end}\n                opacityLabel={t.properties.shape.opacity}\n                      value={shapeGradEnd}\n                onChange={(css) => {\n                  setShapeGradEnd(css);\n                  applyShapeLinearGradient(shapeGradStart, css, shapeGradAngle);\n                  paintShape();\n                }}\n                onCommit={bumpShape}\n              />\n              <PanelField\n                variant=\"slide\"\n                label={t.properties.shape.gradientAngle}\n                min={0}\n                max={360}\n                step={1}\n                numericValue={shapeGradAngle}\n                formatValue={(n) => `${n}\u00B0`}\n                onChange={(angle) => {\n                      setShapeGradAngle(angle);\n                  applyShapeLinearGradient(shapeGradStart, shapeGradEnd, angle);\n                  paintShape();\n                }}\n                onCommit={bumpShape}\n              />\n            </div>\n          )}\n\n          {shapeFillTab === 'none' && (\n            <TextBody as=\"p\" size=\"sm\" className=\"rounded-xl border border-dashed border-panel-border bg-black-capsule px-3 py-3 text-center text-white/80\">{t.properties.shape.fillNoneMessage}</TextBody>\n          )}\n        </PanelSection>\n      )}\n\n      {/* Stroke */}\n      <PanelSection title={t.properties.shape.stroke}>\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n          {t.properties.shape.usesMasterStroke}\n        </TextBody>\n\n        <PanelField\n          variant=\"slide\"\n          label={t.properties.shape.strokeThickness}\n          min={0}\n          max={30}\n          step={1}\n          numericValue={Math.round(activeObject.strokeWidth || 0)}\n          formatValue={(n) => `${n}px`}\n          onChange={(val) => {\n            const masterStroke = useEditorStore.getState().masterColors.stroke;\n            const patch: Record<string, unknown> = { strokeWidth: val };\n            // Fabric needs a stroke paint \u2014 thickness alone is invisible when stroke is null.\n            if (val > 0) {\n              const s = activeObject.stroke;\n              if (!s || s === 'transparent') {\n                patch.stroke = masterStroke || '#000000';\n              }\n            }\n            activeObject.set(patch);\n            paintShape();\n          }}\n          onCommit={bumpShape}\n        />\n\n        <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{t.properties.shape.strokeStyle}</TextBody>\n        <div className=\"flex gap-1 rounded-xl bg-black-capsule p-1\">\n            <button\n            type=\"button\"\n              onClick={() => {\n                setShapeStrokeStyle('solid');\n                activeObject.set({ strokeDashArray: null });\n              bumpShape();\n              }}\n            className={`flex-1 cursor-pointer rounded-lg py-2 transition-colors ${\n              shapeStrokeStyle === 'solid' ? segmentActive : segmentIdle\n              }`}\n            >\n              <TextBody as=\"span\" size=\"sm\">{t.properties.shape.strokeSolid}</TextBody>\n            </button>\n            <button\n            type=\"button\"\n              onClick={() => {\n                setShapeStrokeStyle('dashed');\n                activeObject.set({ strokeDashArray: [8, 8] });\n              bumpShape();\n              }}\n            className={`flex-1 cursor-pointer rounded-lg py-2 transition-colors ${\n              shapeStrokeStyle === 'dashed' ? segmentActive : segmentIdle\n              }`}\n            >\n              <TextBody as=\"span\" size=\"sm\">{t.properties.shape.strokeDashed}</TextBody>\n            </button>\n            <button\n            type=\"button\"\n              onClick={() => {\n                setShapeStrokeStyle('dotted');\n                activeObject.set({ strokeDashArray: [2, 6] });\n              bumpShape();\n              }}\n            className={`flex-1 cursor-pointer rounded-lg py-2 transition-colors ${\n              shapeStrokeStyle === 'dotted' ? segmentActive : segmentIdle\n              }`}\n            >\n              <TextBody as=\"span\" size=\"sm\">{t.properties.shape.strokeDotted}</TextBody>\n            </button>\n          </div>\n      </PanelSection>\n\n      {/* Corner radius (rects only) */}\n      {activeObject.type === 'rect' && (() => {\n        installIndependentCornerRender(activeObject);\n        const linked = cornersAreLinked(activeObject);\n        const corners = readCornerRadii(activeObject);\n        const setCorner = (key: keyof CornerRadii, val: number) => {\n          applyIndependentCornerRadii(activeObject, { ...corners, [key]: val });\n          paintShape();\n        };\n        return (\n          <PanelSection title={t.properties.shape.cornerRadius}>\n            <div className=\"flex items-center gap-1.5\">\n              <div className=\"min-w-0 flex-1\">\n                <PanelField\n                  variant=\"slide\"\n                  label={linked ? t.properties.shape.cornerRadius : t.properties.shape.cornerAll}\n                  min={0}\n                  max={100}\n                  step={1}\n                  numericValue={linked ? corners.tl : Math.round((corners.tl + corners.tr + corners.br + corners.bl) / 4)}\n                  formatValue={(n) => `${n}px`}\n                  onChange={(val) => {\n                    if (linked) {\n                      applyLinkedCornerRadius(activeObject, val);\n                    } else {\n                      applyIndependentCornerRadii(activeObject, {\n                        tl: val,\n                        tr: val,\n                        br: val,\n                        bl: val,\n                      });\n                    }\n                    paintShape();\n                  }}\n                  onCommit={bumpShape}\n                />\n          </div>\n              <IconButton\n                label={linked ? t.properties.shape.cornerUnlink : t.properties.shape.cornerLink}\n                size=\"sm\"\n                variant=\"ghost\"\n                active={!linked}\n                className=\"shrink-0\"\n                onClick={() => {\n                  if (linked) {\n                    applyIndependentCornerRadii(activeObject, corners);\n                  } else {\n                    applyLinkedCornerRadius(activeObject, corners.tl);\n                  }\n                  bumpShape();\n                }}\n              >\n                {linked ? <Link2 size={14} strokeWidth={2.25} /> : <Link2Off size={14} strokeWidth={2.25} />}\n              </IconButton>\n            </div>\n            {!linked && (\n              <div className=\"grid grid-cols-2 gap-1.5\">\n                <PanelField\n                  variant=\"slide\"\n                  label={t.properties.shape.cornerTL}\n                  min={0}\n                  max={100}\n                  step={1}\n                  numericValue={corners.tl}\n                  formatValue={(n) => `${n}px`}\n                  onChange={(val) => setCorner('tl', val)}\n                  onCommit={bumpShape}\n                />\n                <PanelField\n                  variant=\"slide\"\n                  label={t.properties.shape.cornerTR}\n                  min={0}\n                  max={100}\n                  step={1}\n                  numericValue={corners.tr}\n                  formatValue={(n) => `${n}px`}\n                  onChange={(val) => setCorner('tr', val)}\n                  onCommit={bumpShape}\n                />\n                <PanelField\n                  variant=\"slide\"\n                  label={t.properties.shape.cornerBL}\n                  min={0}\n                  max={100}\n                  step={1}\n                  numericValue={corners.bl}\n                  formatValue={(n) => `${n}px`}\n                  onChange={(val) => setCorner('bl', val)}\n                  onCommit={bumpShape}\n                />\n                <PanelField\n                  variant=\"slide\"\n                  label={t.properties.shape.cornerBR}\n                  min={0}\n                  max={100}\n                  step={1}\n                  numericValue={corners.br}\n                  formatValue={(n) => `${n}px`}\n                  onChange={(val) => setCorner('br', val)}\n                  onCommit={bumpShape}\n                />\n        </div>\n      )}\n          </PanelSection>\n        );\n      })()}\n\n      {/* Shadow */}\n      <PanelSection title={t.properties.shape.objectShadow}>\n        <PanelField\n          label={t.properties.shape.objectShadow}\n          trailing={\n            <Switch\n              checked={shapeShadowEnabled}\n              ariaLabel={t.properties.shape.objectShadow}\n              onChange={(enabled) => {\n                setShapeShadowEnabled(enabled);\n                if (enabled) {\n                  activeObject.set({\n                    shadow: new Shadow({\n                    color: shapeShadowColor,\n                    blur: shapeShadowBlur,\n                    offsetX: shapeShadowOffsetX,\n                      offsetY: shapeShadowOffsetY,\n                    }),\n                  });\n                } else {\n                  activeObject.set({ shadow: null });\n                }\n                bumpShape();\n              }}\n            />\n          }\n        />\n\n        {shapeShadowEnabled && (\n          <div className=\"flex flex-col gap-1.5\">\n            <ColorInput\n              label={t.properties.shape.shadowColor}\n              opacityLabel={t.properties.shape.opacity}\n                value={shapeShadowColor}\n              onChange={(css) => {\n                setShapeShadowColor(css);\n                activeObject.set({\n                  shadow: new Shadow({\n                    color: css,\n                    blur: shapeShadowBlur,\n                    offsetX: shapeShadowOffsetX,\n                    offsetY: shapeShadowOffsetY,\n                  }),\n                });\n                paintShape();\n              }}\n              onCommit={bumpShape}\n            />\n            <PanelField\n              variant=\"slide\"\n              label={t.properties.shape.shadowBlur}\n              min={0}\n              max={50}\n              step={1}\n              numericValue={shapeShadowBlur}\n              formatValue={(n) => `${n}px`}\n              onChange={(blur) => {\n                    setShapeShadowBlur(blur);\n                activeObject.set({\n                  shadow: new Shadow({\n                    color: shapeShadowColor,\n                    blur,\n                    offsetX: shapeShadowOffsetX,\n                    offsetY: shapeShadowOffsetY,\n                  }),\n                });\n                paintShape();\n              }}\n              onCommit={bumpShape}\n            />\n            <PanelField\n              variant=\"slide\"\n              label={t.properties.text.offsetX}\n              min={-30}\n              max={30}\n              step={1}\n              numericValue={shapeShadowOffsetX}\n              formatValue={(n) => `${n}px`}\n              onChange={(ox) => {\n                    setShapeShadowOffsetX(ox);\n                activeObject.set({\n                  shadow: new Shadow({\n                    color: shapeShadowColor,\n                    blur: shapeShadowBlur,\n                    offsetX: ox,\n                    offsetY: shapeShadowOffsetY,\n                  }),\n                });\n                paintShape();\n              }}\n              onCommit={bumpShape}\n            />\n            <PanelField\n              variant=\"slide\"\n              label={t.properties.text.offsetY}\n              min={-30}\n              max={30}\n              step={1}\n              numericValue={shapeShadowOffsetY}\n              formatValue={(n) => `${n}px`}\n              onChange={(oy) => {\n                    setShapeShadowOffsetY(oy);\n              activeObject.set({\n                  shadow: new Shadow({\n                    color: shapeShadowColor,\n                    blur: shapeShadowBlur,\n                    offsetX: shapeShadowOffsetX,\n                    offsetY: oy,\n                  }),\n                });\n                paintShape();\n              }}\n              onCommit={bumpShape}\n            />\n        </div>\n        )}\n      </PanelSection>\n\n      {/* Export */}\n      <SelectionExportSection\n        activeObject={activeObject}\n        scale={exportSelScale}\n        format={exportSelFormat}\n        revision={sidebarUpdateTrigger}\n        onScaleChange={setExportSelScale}\n        onFormatChange={setExportSelFormat}\n        onDownload={handleExportSelection}\n      />\n    </PanelBody>\n  );\n};\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { useEditorStore } from '../store/useEditorStore';\nimport {\n  Layers, Eye, EyeOff, Lock, Unlock, Trash2,\n  Image as ImageIcon, Brush, CornerDownRight, Folder, FolderOpen, ChevronRight, ChevronDown,\n  FolderPlus, FolderMinus, ChevronLeft, Link2, Plus, Copy, RefreshCw, Layout, Circle, Link as LinkIcon, Unlink, FilePlusCorner,\n  ArrowUp, ArrowDown, Type,\n} from 'lucide-react';\nimport { ActiveSelection, FabricObject } from 'fabric';\nimport { createPortal } from 'react-dom';\nimport { TransformPanel } from './editor/TransformPanel';\nimport { useDialog } from '../components/DialogModal';\nimport { useTranslation } from '../i18n';\nimport { PanelField, SelectDropdown, TextBody } from './ui';\nimport { isTextObject } from '../store/useEditorStore';\nimport {\n  isPixelLayer,\n  getPixelLayerThumbnailDataUrl,\n  getLayerMaskThumbnailDataUrl,\n  hasLayerMask,\n  isSoleCanvasLayer,\n  canClearOrDeleteLayer,\n  syncPixelLayerInteraction,\n} from '../utils/pixelLayer';\n\nconst getTopLevelGroup = (obj: FabricObject): FabricObject => {\n  let current = obj;\n  while ((current as any).group) {\n    current = (current as any).group;\n  }\n  return current;\n};\n\nconst getType = (obj?: any) => obj?.type?.toLowerCase() || '';\n\ntype LayerCtxMenu = {\n  x: number;\n  y: number;\n  layer: FabricObject;\n};\n\nexport const LayersPanel: React.FC<{ embedded?: boolean }> = ({ embedded = false }) => {\n  const t = useTranslation();\n  const dialog = useDialog();\n  const {\n    canvasInstance,\n    layers,\n    activeObject,\n    lastSelectedObjectId,\n    setActiveObject,\n    syncLayers,\n    saveHistoryState,\n    layersPanelCollapsed,\n    setLayersPanelCollapsed,\n    pages,\n    activePageId,\n    addPage,\n    deletePage,\n    duplicatePage,\n    movePage,\n    renamePage,\n    setActivePageId,\n    clearPage,\n    addBlankRasterLayer,\n    duplicateActiveLayer,\n    addPixelLayerMask,\n    removePixelLayerMask,\n    rasterizeLayer,\n    reorderLayer,\n    layerPaintTarget,\n    setLayerPaintTarget,\n  } = useEditorStore();\n\n  // Layer focus survives empty-canvas deselect (activeObject null, lastSelectedObjectId kept).\n  const focusedLayer: FabricObject | null = (() => {\n    if (activeObject) return activeObject;\n    if (!lastSelectedObjectId || !canvasInstance) return null;\n    return (\n      (canvasInstance.getObjects().find(\n        (o) => (o as FabricObject & { id?: string }).id === lastSelectedObjectId,\n      ) as FabricObject | undefined) ?? null\n    );\n  })();\n\n  const [editingLayer, setEditingLayer] = useState<FabricObject | null>(null);\n  const [editName, setEditName] = useState<string>('');\n  const [expandedGroups, setExpandedGroups] = useState<Record<string, boolean>>({});\n  const [activeTab, setActiveTab] = useState<'layers' | 'pages'>('layers');\n  const [ctxMenu, setCtxMenu] = useState<LayerCtxMenu | null>(null);\n  const [dragId, setDragId] = useState<string | null>(null);\n  const [dragOverId, setDragOverId] = useState<string | null>(null);\n  /** Anchor for Shift+click range selection in the layers list. */\n  const rangeAnchorRef = useRef<FabricObject | null>(null);\n\n  useEffect(() => {\n    if (!ctxMenu) return;\n    const close = () => setCtxMenu(null);\n    window.addEventListener('pointerdown', close);\n    window.addEventListener('scroll', close, true);\n    window.addEventListener('keydown', (e) => {\n      if (e.key === 'Escape') close();\n    });\n    return () => {\n      window.removeEventListener('pointerdown', close);\n      window.removeEventListener('scroll', close, true);\n    };\n  }, [ctxMenu]);\n\n  const activePage = pages.find((p) => p.id === activePageId) || pages[0];\n\n  const toggleGroupExpand = (groupId: string, e: React.MouseEvent) => {\n    e.stopPropagation();\n    setExpandedGroups(prev => ({\n      ...prev,\n      [groupId]: !prev[groupId]\n    }));\n  };\n\n  const getLayerName = (layer: FabricObject) => {\n    if ((layer as any).name) return (layer as any).name;\n\n    if (isPixelLayer(layer)) return t.layers.pixelLayerBase;\n\n    switch (getType(layer)) {\n      case 'group':\n        return t.layers.layerType.group;\n      case 'textbox':\n      case 'text':\n        const textVal = (layer as any).text || '';\n        return textVal.length > 18 ? t.layers.layerType.textTruncated(textVal.substring(0, 15)) : t.layers.layerType.text(textVal);\n      case 'image':\n        return t.layers.layerType.image;\n      case 'rect':\n        return t.layers.layerType.rect;\n      case 'circle':\n        return t.layers.layerType.circle;\n      case 'triangle':\n        return t.layers.layerType.triangle;\n      case 'path':\n        return t.layers.layerType.path;\n      case 'line':\n        return t.layers.layerType.line;\n      default:\n        return t.layers.layerType.element;\n    }\n  };\n\n  const getImgSrc = (layer: FabricObject) => {\n    const el = (layer as any)._element;\n    if (el && el.src) return el.src;\n    if ((layer as any).src) return (layer as any).src;\n    return null;\n  };\n\n  const getShapeStyles = (layer: FabricObject) => {\n    const fill = typeof layer.fill === 'string' ? layer.fill : '';\n    const stroke = typeof layer.stroke === 'string' ? layer.stroke : '';\n    const bgColor = fill && fill !== 'transparent' ? fill : (stroke && stroke !== 'transparent' ? stroke : '#3b82f6');\n    const borderColor = stroke && stroke !== 'transparent' ? stroke : 'transparent';\n    return { bgColor, borderColor };\n  };\n\n  const renderThumbnail = (layer: FabricObject) => {\n    const thumbBox =\n      'size-10 rounded object-cover flex-shrink-0 border border-dark-750 bg-[repeating-conic-gradient(#3f3f46_0%_25%,#27272a_0%_50%)] bg-[length:8px_8px]';\n    switch (getType(layer)) {\n      case 'group': {\n        const isExpanded = expandedGroups[(layer as any).id] !== false;\n        return (\n          <div className={`${thumbBox} flex items-center justify-center bg-dark-800`}>\n            {isExpanded \n              ? <FolderOpen size={16} className=\"text-amber-400\" />\n              : <Folder size={16} className=\"text-amber-500\" />}\n          </div>\n        );\n      }\n      case 'textbox':\n      case 'text': {\n        const fill = typeof layer.fill === 'string' ? layer.fill : '#ffffff';\n        return (\n          <div \n            className={`${thumbBox} flex items-center justify-center bg-dark-800`}\n            style={{ color: fill }}\n          >\n            <TextBody as=\"span\" size=\"sm\" className=\"font-bold\">\n              Ag\n            </TextBody>\n          </div>\n        );\n      }\n      case 'image': {\n        if (isPixelLayer(layer)) {\n          const preview = getPixelLayerThumbnailDataUrl(layer, 80);\n          if (preview) {\n            return (\n              <img\n                src={preview}\n                alt=\"\"\n                className={thumbBox}\n              />\n            );\n          }\n          return <div className={thumbBox} />;\n        }\n        const imgSrc = getImgSrc(layer);\n        if (imgSrc) {\n          return (\n            <img \n              src={imgSrc} \n              alt=\"\" \n              className={thumbBox}\n            />\n          );\n        }\n        return (\n          <div className={`${thumbBox} flex items-center justify-center bg-dark-800`}>\n            <ImageIcon size={16} className=\"text-sky-400\" />\n          </div>\n        );\n      }\n      case 'rect': {\n        const styles = getShapeStyles(layer);\n        return (\n          <div \n            className={thumbBox}\n            style={{ \n              backgroundColor: styles.bgColor, \n              borderColor: styles.borderColor,\n              borderWidth: styles.borderColor !== 'transparent' ? '1px' : undefined,\n            }} \n          />\n        );\n      }\n      case 'circle': {\n        const styles = getShapeStyles(layer);\n        return (\n          <div \n            className={`${thumbBox} !rounded-full`}\n            style={{ \n              backgroundColor: styles.bgColor, \n              borderColor: styles.borderColor,\n              borderWidth: styles.borderColor !== 'transparent' ? '1px' : undefined,\n            }} \n          />\n        );\n      }\n      case 'triangle': {\n        const styles = getShapeStyles(layer);\n        return (\n          <div className={`${thumbBox} flex items-center justify-center bg-dark-800`}>\n            <svg className=\"size-6\" viewBox=\"0 0 24 24\">\n              <polygon \n                points=\"12,3 2,21 22,21\" \n                fill={styles.bgColor} \n                stroke={styles.borderColor !== 'transparent' ? styles.borderColor : 'none'} \n                strokeWidth={styles.borderColor !== 'transparent' ? 2 : 0}\n              />\n            </svg>\n          </div>\n        );\n      }\n      case 'path': {\n        const styles = getShapeStyles(layer);\n        return (\n          <div className={`${thumbBox} flex items-center justify-center bg-dark-800`}>\n            <Brush size={16} style={{ color: styles.bgColor }} />\n          </div>\n        );\n      }\n      case 'line': {\n        const styles = getShapeStyles(layer);\n        return (\n          <div className={`${thumbBox} flex items-center justify-center bg-dark-800`}>\n            <div className=\"h-0.5 w-6 rounded\" style={{ backgroundColor: styles.bgColor }} />\n          </div>\n        );\n      }\n      default:\n        return (\n          <div className={`${thumbBox} flex items-center justify-center bg-dark-800`}>\n            <Layers size={16} className=\"text-white/50\" />\n          </div>\n        );\n    }\n  };\n\n  const startEditing = (layer: FabricObject, e: React.MouseEvent) => {\n    e.stopPropagation();\n    setEditingLayer(layer);\n    setEditName(getLayerName(layer));\n  };\n\n  const finishEditing = (layer: FabricObject) => {\n    if (!canvasInstance) return;\n    const trimmed = editName.trim();\n    if (trimmed) {\n      (layer as any).name = trimmed;\n      canvasInstance.requestRenderAll();\n      syncLayers();\n      saveHistoryState();\n    }\n    setEditingLayer(null);\n  };\n\n  const applyMultiSelection = (objects: FabricObject[]) => {\n    if (!canvasInstance) return;\n    const unlocked = objects.filter((o) => !(o as { locked?: boolean }).locked);\n    const list = unlocked.length > 0 ? unlocked : objects.slice(0, 1);\n    canvasInstance.discardActiveObject();\n    if (list.length === 1) {\n      const only = list[0]!;\n      canvasInstance.setActiveObject(only);\n      setActiveObject(only);\n    } else if (list.length > 1) {\n      const sel = new ActiveSelection(list, { canvas: canvasInstance });\n      sel.setCoords();\n      canvasInstance.setActiveObject(sel);\n      setActiveObject(sel);\n    }\n    canvasInstance.requestRenderAll();\n  };\n\n  const selectLayer = (layer: FabricObject, e?: React.MouseEvent) => {\n    if (!canvasInstance) return;\n\n    const targetSelectObj = (layer as any).group ? getTopLevelGroup(layer) : layer;\n    const isLocked = (targetSelectObj as any).locked === true;\n\n    // Shift: select contiguous range in the panel list (anchor \u2192 clicked).\n    if (e?.shiftKey) {\n      if (isLocked) return;\n      // `layers` is panel order (top \u2192 bottom), matching the CAPAS list.\n      const clickIdx = layers.indexOf(targetSelectObj);\n      if (clickIdx < 0) return;\n\n      let anchor = rangeAnchorRef.current;\n      if (!anchor || !layers.includes(anchor)) {\n        const activeObjs = canvasInstance.getActiveObjects();\n        anchor =\n          activeObjs.find((o) => layers.includes(o)) ||\n          layers[clickIdx] ||\n          targetSelectObj;\n      }\n      const anchorIdx = layers.indexOf(anchor);\n      if (anchorIdx < 0) {\n        rangeAnchorRef.current = targetSelectObj;\n        applyMultiSelection([targetSelectObj]);\n        return;\n      }\n\n      const from = Math.min(anchorIdx, clickIdx);\n      const to = Math.max(anchorIdx, clickIdx);\n      applyMultiSelection(layers.slice(from, to + 1));\n      return;\n    }\n\n    // Ctrl/Cmd: toggle layer in/out of the current selection.\n    if (e && (e.ctrlKey || e.metaKey)) {\n      if (isLocked) return;\n      const activeObjs = canvasInstance.getActiveObjects();\n      let newObjects: FabricObject[] = [];\n      if (activeObjs.includes(targetSelectObj)) {\n        newObjects = activeObjs.filter((o) => o !== targetSelectObj);\n      } else {\n        newObjects = [...activeObjs, targetSelectObj];\n      }\n      rangeAnchorRef.current = targetSelectObj;\n      if (newObjects.length === 0) {\n        applyMultiSelection([targetSelectObj]);\n      } else {\n        applyMultiSelection(newObjects);\n      }\n      return;\n    }\n\n    rangeAnchorRef.current = targetSelectObj;\n    targetSelectObj.set({\n      hasControls: false,\n      hasBorders: false,\n      borderColor: 'transparent',\n      cornerColor: 'transparent',\n      cornerStrokeColor: 'transparent',\n    });\n    canvasInstance.setActiveObject(targetSelectObj);\n    canvasInstance.requestRenderAll();\n    setActiveObject(targetSelectObj);\n  };\n\n  const toggleVisibility = (layer: FabricObject, e?: React.MouseEvent) => {\n    e?.stopPropagation();\n    if (!canvasInstance) return;\n    \n    const isVisible = !layer.visible;\n    layer.set({ visible: isVisible });\n    \n    if ((layer as any).group) {\n      (layer as any).group.set({ dirty: true });\n    }\n    \n    canvasInstance.requestRenderAll();\n    syncLayers();\n    saveHistoryState();\n  };\n\n  const toggleLock = (layer: FabricObject, e?: React.MouseEvent) => {\n    e?.stopPropagation();\n    if (!canvasInstance) return;\n\n    const isLocked = !layer.lockMovementX;\n    (layer as any).locked = isLocked;\n\n    if (isPixelLayer(layer)) {\n      if (isLocked) {\n        layer.set({\n          lockMovementX: true,\n          lockMovementY: true,\n          lockScalingX: true,\n          lockScalingY: true,\n          lockRotation: true,\n          hasControls: false,\n          hasBorders: false,\n          borderColor: '#f59e0b',\n          cornerColor: '#f59e0b',\n          cornerStrokeColor: '#d97706',\n        });\n      } else {\n        syncPixelLayerInteraction(layer);\n      }\n    } else {\n      layer.set({\n        lockMovementX: isLocked,\n        lockMovementY: isLocked,\n        lockScalingX: isLocked,\n        lockScalingY: isLocked,\n        lockRotation: isLocked,\n        hasControls: false,\n        hasBorders: false,\n        selectable: true,\n        borderColor: 'transparent',\n        cornerColor: 'transparent',\n        cornerStrokeColor: 'transparent',\n      });\n    }\n\n    if ((layer as any).group) {\n      (layer as any).group.set({ dirty: true });\n    } else {\n      canvasInstance.setActiveObject(layer);\n      setActiveObject(layer);\n    }\n\n    canvasInstance.requestRenderAll();\n    syncLayers();\n    saveHistoryState();\n  };\n\n  const deleteLayer = (layer: FabricObject, e?: React.MouseEvent) => {\n    e?.stopPropagation();\n    if (!canvasInstance) return;\n\n    // Sole layer with content: clear pixels (empty layer OK). Already empty: block.\n    if (isSoleCanvasLayer(canvasInstance)) {\n      const result = useEditorStore.getState().deleteLayerOrClear(layer);\n      if (result === 'blocked') {\n        useEditorStore.getState().addToast(t.layers.cannotDeleteLastLayer, 'warning');\n      }\n      return;\n    }\n\n    const objs = canvasInstance.getObjects();\n    const idx = objs.indexOf(layer);\n    const fallback =\n      objs[idx + 1] ||\n      objs[idx - 1] ||\n      objs.find((o) => o !== layer) ||\n      null;\n\n    if ((layer as any).group) {\n      const parentGroup = (layer as any).group as any;\n      parentGroup.remove(layer);\n      parentGroup.set({ dirty: true });\n      if (parentGroup.getObjects().length === 0) {\n        canvasInstance.remove(parentGroup);\n      }\n    } else {\n      canvasInstance.remove(layer);\n    }\n\n    if (fallback && canvasInstance.getObjects().includes(fallback)) {\n      canvasInstance.setActiveObject(fallback);\n      setActiveObject(fallback);\n    } else {\n      setActiveObject(null);\n    }\n    canvasInstance.requestRenderAll();\n    syncLayers();\n    saveHistoryState();\n  };\n\n  const selectContentThumb = (layer: FabricObject, e: React.MouseEvent) => {\n    e.stopPropagation();\n    selectLayer(layer);\n    setLayerPaintTarget('content');\n  };\n\n  const selectMaskThumb = (layer: FabricObject, e: React.MouseEvent) => {\n    e.stopPropagation();\n    if (!isPixelLayer(layer) || !hasLayerMask(layer)) return;\n    selectLayer(layer);\n    setLayerPaintTarget('mask');\n  };\n\n  const handleAddMask = (layer: FabricObject, e?: React.MouseEvent) => {\n    e?.stopPropagation();\n    if (getType(layer) === 'activeselection') return;\n    if (isPixelLayer(layer) && hasLayerMask(layer)) {\n      selectLayer(layer);\n      setLayerPaintTarget('mask');\n      return;\n    }\n    addPixelLayerMask(layer);\n  };\n\n  const handleRemoveMask = (layer: FabricObject, e?: React.MouseEvent) => {\n    e?.stopPropagation();\n    if (!isPixelLayer(layer) || !hasLayerMask(layer)) return;\n    removePixelLayerMask(layer);\n  };\n\n  const handleRasterize = (layer: FabricObject, e?: React.MouseEvent) => {\n    e?.stopPropagation();\n    if (!isTextObject(layer) || isPixelLayer(layer)) return;\n    rasterizeLayer(layer);\n  };\n\n  const openLayerCtx = (layer: FabricObject, e: React.MouseEvent) => {\n    e.preventDefault();\n    e.stopPropagation();\n    selectLayer(layer);\n    setCtxMenu({ x: e.clientX, y: e.clientY, layer });\n  };\n\n  const renderLayer = (layer: FabricObject, idx: number, depth: number = 0): React.ReactNode => {\n    const isGroup = getType(layer) === 'group';\n    const isExpandableGroup = isGroup && !['canva-frame', 'canva-frame-clipped'].includes((layer as any).name);\n    let groupId = (layer as any).id;\n    if (!groupId) {\n      groupId = `layer-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n      (layer as any).id = groupId;\n    }\n    const isExpanded = expandedGroups[groupId] !== false;\n\n    const isSelected = focusedLayer === layer || (\n      focusedLayer &&\n      getType(focusedLayer) === 'activeselection' &&\n      (focusedLayer as any).getObjects().includes(layer)\n    ) || (\n      focusedLayer &&\n      getType(focusedLayer) === 'group' &&\n      (focusedLayer === layer || (focusedLayer as any).getObjects().includes(layer))\n    ) || (\n      !activeObject &&\n      !!lastSelectedObjectId &&\n      (layer as FabricObject & { id?: string }).id === lastSelectedObjectId\n    );\n\n    const isVisible = layer.visible !== false;\n    const isLocked = (layer as any).locked === true;\n    const isClipped = !!(layer as any).clippedToLayerId;\n    const pixel = isPixelLayer(layer);\n    const maskOn = pixel && hasLayerMask(layer);\n    const paintingMask = isSelected && layerPaintTarget === 'mask' && maskOn;\n    const paintingContent = isSelected && (!paintingMask);\n\n    return (\n      <React.Fragment key={groupId}>\n        <div\n          draggable={depth === 0}\n          onDragStart={(e) => {\n            if (depth !== 0) return;\n            setDragId(groupId);\n            e.dataTransfer.effectAllowed = 'move';\n            e.dataTransfer.setData('text/plain', groupId);\n          }}\n          onDragOver={(e) => {\n            if (depth !== 0 || !dragId || dragId === groupId) return;\n            e.preventDefault();\n            e.dataTransfer.dropEffect = 'move';\n            setDragOverId(groupId);\n          }}\n          onDragLeave={() => {\n            if (dragOverId === groupId) setDragOverId(null);\n          }}\n          onDrop={(e) => {\n            e.preventDefault();\n            if (depth !== 0 || !dragId) return;\n            reorderLayer(dragId, groupId);\n            setDragId(null);\n            setDragOverId(null);\n          }}\n          onDragEnd={() => {\n            setDragId(null);\n            setDragOverId(null);\n          }}\n          onClick={(e) => selectLayer(layer, e)}\n          onContextMenu={(e) => openLayerCtx(layer, e)}\n          style={{ paddingLeft: `${8 + depth * 16}px` }}\n          className={`relative flex items-center gap-1.5 px-2 py-1.5 rounded-md border cursor-pointer select-none ${\n            isSelected \n              ? 'bg-[var(--we-accent-muted)] border-[var(--we-accent)]/50 text-white font-bold z-[1]' \n              : 'bg-transparent border-transparent text-dark-300 font-medium'\n          } ${!isVisible ? 'opacity-50' : ''} ${\n            dragOverId === groupId ? 'border-[var(--we-accent)] border-dashed' : ''\n          } ${dragId === groupId ? 'opacity-40' : ''}`}\n        >\n          {/* Visibility \u2014 always left */}\n          <button\n            type=\"button\"\n            onClick={(e) => toggleVisibility(layer, e)}\n            className={`shrink-0 p-0.5 rounded cursor-pointer ${isVisible ? 'text-white/70' : 'text-[var(--we-accent)]'}`}\n            title={isVisible ? t.layers.tooltip.hide : t.layers.tooltip.show}\n            aria-label={isVisible ? t.layers.tooltip.hide : t.layers.tooltip.show}\n          >\n            {isVisible ? <Eye size={13} /> : <EyeOff size={13} />}\n          </button>\n\n          {isExpandableGroup && (\n            <button\n              type=\"button\"\n              onClick={(e) => toggleGroupExpand(groupId, e)}\n              className=\"p-0.5 rounded text-dark-400 cursor-pointer shrink-0\"\n            >\n              {isExpanded ? <ChevronDown size={11} /> : <ChevronRight size={11} />}\n            </button>\n          )}\n          {isClipped && (\n            <CornerDownRight size={12} className=\"text-[var(--we-accent)] flex-shrink-0\" />\n          )}\n\n          {/* Content preview */}\n          <button\n            type=\"button\"\n            onClick={(e) => selectContentThumb(layer, e)}\n            className={`shrink-0 rounded overflow-hidden border ${\n              paintingContent ? 'border-[var(--we-accent)] ring-1 ring-[var(--we-accent)]/50' : 'border-dark-750'\n            }`}\n            title={t.layers.tooltip.paintContent}\n          >\n            {renderThumbnail(layer)}\n          </button>\n\n          {/* Mask chain + preview */}\n          {maskOn && (\n            <>\n              <LinkIcon\n                size={11}\n                className={`shrink-0 ${(layer as any).weMaskLinked !== false ? 'text-[var(--we-accent)]' : 'text-white/40'}`}\n                aria-hidden\n              />\n              <button\n                type=\"button\"\n                onClick={(e) => selectMaskThumb(layer, e)}\n                className={`shrink-0 size-10 rounded overflow-hidden border ${\n                  paintingMask ? 'border-[var(--we-accent)] ring-1 ring-[var(--we-accent)]/50' : 'border-dark-750'\n                } bg-[repeating-conic-gradient(#3f3f46_0%_25%,#27272a_0%_50%)] bg-[length:8px_8px]`}\n                title={t.layers.tooltip.paintMask}\n              >\n                {(() => {\n                  const src = getLayerMaskThumbnailDataUrl(layer, 80);\n                  return src ? (\n                    <img src={src} alt=\"\" className=\"size-full object-cover\" />\n                  ) : (\n                    <span className=\"block size-full bg-white\" />\n                  );\n                })()}\n              </button>\n            </>\n          )}\n\n          {/* Name */}\n          <div\n            className=\"flex items-center gap-1.5 truncate flex-1 min-w-0\"\n            onDoubleClick={(e) => startEditing(layer, e)}\n            title={t.layers.tooltip.rename}\n          >\n            {editingLayer === layer ? (\n              <input\n                value={editName}\n                onChange={(e) => setEditName(e.target.value)}\n                onBlur={() => finishEditing(layer)}\n                onKeyDown={(e) => {\n                  if (e.key === 'Enter') finishEditing(layer);\n                  if (e.key === 'Escape') setEditingLayer(null);\n                }}\n                className=\"bg-dark-800 text-white font-sans text-xs font-medium px-1.5 py-0.5 rounded border border-[var(--we-accent)] focus:outline-none w-full\"\n                autoFocus\n                onClick={(e) => e.stopPropagation()}\n              />\n            ) : (\n              <TextBody as=\"span\" size=\"sm\" className={`truncate ${!isVisible ? 'italic' : ''} min-w-0`}>\n                {getLayerName(layer)}\n              </TextBody>\n            )}\n          </div>\n\n          {isLocked && (\n            <Lock size={11} className=\"text-amber-500 shrink-0\" aria-hidden />\n          )}\n        </div>\n\n        {isExpandableGroup && isExpanded && (layer as any).getObjects && (\n          <div className=\"flex flex-col gap-0.5 mt-0.5 border-l border-dark-800 ml-3.5\">\n            {((layer as any).getObjects() as FabricObject[]).map((childObj, childIdx) => \n              renderLayer(childObj, childIdx, depth + 1)\n            )}\n          </div>\n        )}\n      </React.Fragment>\n    );\n  };\n\n  return (\n    <div \n      className={`flex-shrink-0 bg-dark-900 text-dark-200 select-none flex flex-col h-full transition-all duration-300 ease-in-out ${\n        embedded\n          ? 'w-full'\n          : `z-30 lg:relative absolute right-0 top-0 bottom-0 ${\n              layersPanelCollapsed ? 'w-0 border-l-0' : 'w-64 border-l border-dark-850 shadow-2xl lg:shadow-none'\n            }`\n      }`}\n    >\n      <div \n        className=\"w-full h-full flex flex-col transition-all duration-300 ease-in-out\"\n        style={embedded ? { overflow: 'hidden' } : {\n          width: layersPanelCollapsed ? '0px' : '256px',\n          opacity: layersPanelCollapsed ? 0 : 1,\n          pointerEvents: layersPanelCollapsed ? 'none' : 'auto',\n          overflow: 'hidden'\n        }}\n      >\n        {/* Transform Panel \u2014 solo en modo standalone (en modo embedded lo gestiona el panel de Edici\u00F3n) */}\n        {!embedded && activeObject && getType(activeObject) !== 'activeselection' && (\n          <TransformPanel />\n        )}\n\n        {/* Blend mode \u2014 always visible on Layers tab; ghost PanelField + SelectDropdown */}\n        {activeTab === 'layers' && (\n          <div className=\"shrink-0 border-b border-dark-850 px-3\">\n            <PanelField\n              variant=\"ghost\"\n              label={t.properties.image.blendMode}\n              disabled={!focusedLayer || getType(focusedLayer) === 'activeselection'}\n              trailing={\n                <SelectDropdown\n                  ariaLabel={t.properties.image.blendMode}\n                  disabled={!focusedLayer || getType(focusedLayer) === 'activeselection'}\n                  value={\n                    focusedLayer && getType(focusedLayer) !== 'activeselection'\n                      ? focusedLayer.globalCompositeOperation || 'source-over'\n                      : 'source-over'\n                  }\n                  onChange={(v) => {\n                    if (!focusedLayer || getType(focusedLayer) === 'activeselection') return;\n                    focusedLayer.set({ globalCompositeOperation: v });\n                    canvasInstance?.requestRenderAll();\n                    saveHistoryState();\n                  }}\n                  options={[\n                    { value: 'source-over', label: t.properties.image.blend.normal },\n                    { value: 'multiply', label: t.properties.image.blend.multiply },\n                    { value: 'screen', label: t.properties.image.blend.screen },\n                    { value: 'overlay', label: t.properties.image.blend.overlay },\n                    { value: 'darken', label: t.properties.image.blend.darken },\n                    { value: 'lighten', label: t.properties.image.blend.lighten },\n                    { value: 'difference', label: t.properties.image.blend.difference },\n                    { value: 'exclusion', label: t.properties.image.blend.exclusion },\n                    { value: 'color-dodge', label: t.properties.image.blend.colorDodge },\n                    { value: 'color-burn', label: t.properties.image.blend.colorBurn },\n                  ]}\n                />\n              }\n            />\n          </div>\n        )}\n\n        {/* Tab switcher: Capas | P\u00E1ginas */}\n        <div className=\"relative z-20 h-12 px-2 border-b border-dark-850 flex items-center justify-between bg-dark-900 flex-shrink-0 gap-2\">\n          <div className=\"flex items-center bg-dark-900 border border-dark-850 rounded-lg p-0.5 flex-1\">\n            <button\n              onClick={() => setActiveTab('layers')}\n              className={`flex-1 flex items-center justify-center gap-1.5 px-2 py-1 rounded transition-colors ${\n                activeTab === 'layers'\n                  ? 'bg-[var(--we-accent)] text-white'\n                  : 'text-dark-400 hover:text-white'\n              }`}\n              aria-pressed={activeTab === 'layers'}\n            >\n              <Layers size={11} />\n              <TextBody as=\"span\" size=\"sm\" className=\"font-bold uppercase tracking-wider\">\n                {t.layers.tabLayers} ({layers.length})\n              </TextBody>\n            </button>\n            <button\n              onClick={() => setActiveTab('pages')}\n              className={`flex-1 flex items-center justify-center gap-1.5 px-2 py-1 rounded transition-colors ${\n                activeTab === 'pages'\n                  ? 'bg-[var(--we-accent)] text-white'\n                  : 'text-dark-400 hover:text-white'\n              }`}\n              aria-pressed={activeTab === 'pages'}\n            >\n              <Layout size={11} />\n              <TextBody as=\"span\" size=\"sm\" className=\"font-bold uppercase tracking-wider\">\n                {t.layers.tabPages} ({pages.length})\n              </TextBody>\n            </button>\n          </div>\n          {/* Visual Group/Ungroup Action Buttons (solo en tab Capas) */}\n          {activeTab === 'layers' && activeObject && (\n            <div className=\"flex items-center gap-1 animate-fade-in\">\n              {getType(activeObject) === 'activeselection' && (\n                <button\n                  type=\"button\"\n                  title={t.layers.groupTooltip}\n                  aria-label={t.layers.group}\n                  onClick={() => {\n                    const store = useEditorStore.getState();\n                    store.groupSelectedObjects();\n                  }}\n                  className=\"relative z-[10002] flex size-7 cursor-pointer items-center justify-center rounded-md bg-[var(--we-accent)] text-white transition-all hover:bg-[var(--we-accent-hover)] active:scale-95\"\n                >\n                  <FolderPlus size={14} />\n                </button>\n              )}\n              {getType(activeObject) === 'group' && !['canva-frame', 'canva-frame-clipped'].includes((activeObject as any).name) && (\n                <button\n                  type=\"button\"\n                  title={t.layers.ungroupTooltip}\n                  aria-label={t.layers.ungroup}\n                  onClick={() => {\n                    const store = useEditorStore.getState();\n                    store.ungroupObjects();\n                  }}\n                  className=\"relative z-[10002] flex size-7 cursor-pointer items-center justify-center rounded-md bg-amber-600 text-white transition-all hover:bg-amber-500 active:scale-95\"\n                >\n                  <FolderMinus size={14} />\n                </button>\n              )}\n            </div>\n          )}\n        </div>\n\n        {/* Content: layers list OR pages list */}\n        {activeTab === 'layers' ? (\n          <div className=\"relative z-10 flex-1 flex flex-col overflow-hidden\">\n            <div className=\"flex-1 overflow-y-auto p-3 pt-4 flex flex-col gap-1\">\n              {layers.length > 0 ? (\n                layers.map((layer, idx) => renderLayer(layer, idx, 0))\n              ) : (\n                <div className=\"h-full flex flex-col items-center justify-center text-center p-6 mt-10\">\n                  <Layers size={24} className=\"text-dark-500 mb-2 opacity-55 animate-pulse\" />\n                  <TextBody as=\"p\" size=\"sm\" className=\"text-dark-500\">\n                    {t.layers.noLayers}\n                  </TextBody>\n                  <TextBody as=\"p\" size=\"sm\" className=\"text-dark-600 mt-1\">\n                    {t.layers.noLayersHint}\n                  </TextBody>\n                </div>\n              )}\n            </div>\n            <div className=\"flex-shrink-0 border-t border-dark-850 p-2 flex items-center justify-end gap-1\">\n              <button\n                type=\"button\"\n                onClick={() => addBlankRasterLayer()}\n                className=\"flex size-8 items-center justify-center rounded-lg bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] text-white cursor-pointer transition-all active:scale-95\"\n                title={t.layers.newLayerTitle}\n                aria-label={t.layers.newLayer}\n              >\n                <FilePlusCorner size={13} />\n              </button>\n              <button\n                type=\"button\"\n                disabled={!focusedLayer || getType(focusedLayer) === 'activeselection'}\n                onClick={() => { void duplicateActiveLayer(); }}\n                className=\"flex size-8 items-center justify-center rounded-lg border border-panel-border bg-dark-850 text-white/80 hover:text-white hover:border-[var(--we-accent)]/40 cursor-pointer transition-all disabled:opacity-30 disabled:pointer-events-none\"\n                title={t.layers.duplicateLayerTitle}\n              >\n                <Copy size={13} />\n              </button>\n              <button\n                type=\"button\"\n                disabled={!focusedLayer || getType(focusedLayer) === 'activeselection'}\n                onClick={() => {\n                  if (focusedLayer && getType(focusedLayer) !== 'activeselection') {\n                    handleAddMask(focusedLayer);\n                  }\n                }}\n                className=\"flex size-8 items-center justify-center rounded-lg border border-panel-border bg-dark-850 text-white/80 hover:text-white hover:border-[var(--we-accent)]/40 cursor-pointer transition-all disabled:opacity-30 disabled:pointer-events-none\"\n                title={t.layers.tooltip.addMask}\n                aria-label={t.layers.tooltip.addMask}\n              >\n                <Circle size={13} />\n              </button>\n              <button\n                type=\"button\"\n                disabled={\n                  !focusedLayer ||\n                  getType(focusedLayer) === 'activeselection' ||\n                  !isTextObject(focusedLayer) ||\n                  isPixelLayer(focusedLayer)\n                }\n                onClick={() => {\n                  if (focusedLayer) handleRasterize(focusedLayer);\n                }}\n                className=\"flex size-8 items-center justify-center rounded-lg border border-panel-border bg-dark-850 text-white/80 hover:text-white hover:border-[var(--we-accent)]/40 cursor-pointer transition-all disabled:opacity-30 disabled:pointer-events-none\"\n                title={t.layers.rasterizeTitle}\n                aria-label={t.layers.rasterize}\n              >\n                <Type size={13} />\n              </button>\n              <button\n                type=\"button\"\n                disabled={!focusedLayer || getType(focusedLayer) === 'activeselection'}\n                onClick={() => {\n                  if (focusedLayer && getType(focusedLayer) !== 'activeselection') {\n                    toggleLock(focusedLayer);\n                  }\n                }}\n                className=\"flex size-8 items-center justify-center rounded-lg border border-panel-border bg-dark-850 text-white/80 hover:text-white hover:border-[var(--we-accent)]/40 cursor-pointer transition-all disabled:opacity-30 disabled:pointer-events-none\"\n                title={\n                  focusedLayer && (focusedLayer as { locked?: boolean }).locked\n                    ? t.layers.tooltip.unlock\n                    : t.layers.tooltip.lock\n                }\n                aria-label={t.layers.tooltip.lock}\n              >\n                {focusedLayer && (focusedLayer as { locked?: boolean }).locked ? (\n                  <Lock size={13} />\n                ) : (\n                  <Unlock size={13} />\n                )}\n              </button>\n              <button\n                type=\"button\"\n                disabled={\n                  !focusedLayer ||\n                  getType(focusedLayer) === 'activeselection' ||\n                  !!(\n                    canvasInstance &&\n                    focusedLayer &&\n                    !canClearOrDeleteLayer(canvasInstance, focusedLayer)\n                  )\n                }\n                onClick={() => {\n                  if (focusedLayer && getType(focusedLayer) !== 'activeselection') {\n                    deleteLayer(focusedLayer);\n                  }\n                }}\n                className=\"flex size-8 items-center justify-center rounded-lg border border-panel-border bg-dark-850 text-white/80 hover:text-red-400 hover:border-red-400/40 cursor-pointer transition-all disabled:opacity-30 disabled:pointer-events-none\"\n                title={\n                  canvasInstance &&\n                  focusedLayer &&\n                  !canClearOrDeleteLayer(canvasInstance, focusedLayer)\n                    ? t.layers.cannotDeleteLastLayer\n                    : t.layers.tooltip.delete\n                }\n                aria-label={t.layers.tooltip.delete}\n              >\n                <Trash2 size={13} />\n              </button>\n            </div>\n          </div>\n        ) : (\n          <div className=\"flex-1 flex flex-col overflow-hidden\">\n            {/* Pages list (arriba) */}\n            <div className=\"flex-1 overflow-y-auto p-3 flex flex-col gap-2\">\n              {pages.map((p, index) => {\n                const isActive = p.id === activePageId;\n                return (\n                  <div\n                    key={p.id}\n                    role=\"button\"\n                    tabIndex={0}\n                    onClick={() => setActivePageId(p.id)}\n                    onKeyDown={(e) => {\n                      if (e.key === 'Enter' || e.key === ' ') {\n                        e.preventDefault();\n                        setActivePageId(p.id);\n                      }\n                    }}\n                    className={`group relative flex cursor-pointer flex-col gap-2 rounded-xl border p-2.5 transition-all ${\n                      isActive\n                        ? 'bg-[var(--we-accent-muted)] border-[var(--we-accent)] shadow-[0_4px_20px_color-mix(in_srgb,var(--we-accent)_20%,transparent)] text-white'\n                        : 'bg-black-capsule border-panel-border hover:bg-black-capsule-hover hover:border-[var(--we-accent)]/35 text-white'\n                    }`}\n                  >\n                    <div className=\"flex items-center gap-2\">\n                      <TextBody\n                        as=\"span\"\n                        size=\"sm\"\n                        className={`font-bold px-1.5 py-0.5 rounded ${\n                          isActive\n                            ? 'bg-[var(--we-accent)] text-white'\n                            : 'bg-black-stroke text-white/80'\n                        }`}\n                      >\n                        {String(index + 1).padStart(2, '0')}\n                      </TextBody>\n                      <input\n                        type=\"text\"\n                        value={p.name}\n                        onClick={(e) => e.stopPropagation()}\n                        onChange={(e) => renamePage(p.id, e.target.value)}\n                        className=\"bg-transparent border-none font-sans text-xs font-medium text-white placeholder:text-white/50 focus:outline-none focus:ring-1 focus:ring-[var(--we-accent)]/50 rounded px-1 flex-1 min-w-0\"\n                      />\n                    </div>\n\n                    <div className=\"flex gap-3\">\n                      <div\n                        className={`relative flex h-12 w-16 flex-shrink-0 items-center justify-center overflow-hidden rounded-lg border bg-[#0A0A0F] ${\n                          isActive\n                            ? 'border-[var(--we-accent)]/50'\n                            : 'border-panel-border group-hover:border-[var(--we-accent)]/40'\n                        }`}\n                      >\n                        {p.thumbnail ? (\n                          <img src={p.thumbnail} alt={p.name} className=\"h-full w-full object-cover\" />\n                        ) : (\n                          <div\n                            className=\"flex h-full w-full items-center justify-center\"\n                            style={{\n                              background: p.backgroundColor.startsWith('{')\n                                ? (() => {\n                                    try {\n                                      const parsed = JSON.parse(p.backgroundColor);\n                                      return `linear-gradient(${parsed.angle}deg, ${parsed.colorStops[0].color}, ${parsed.colorStops[parsed.colorStops.length - 1].color})`;\n                                    } catch (e) { return '#ffffff'; }\n                                  })()\n                                : p.backgroundColor\n                            }}\n                          >\n                            <Layout size={12} className=\"text-white/50\" />\n                          </div>\n                        )}\n                      </div>\n\n                      <div className=\"flex flex-1 flex-col justify-between\">\n                        <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                          {t.layers.pages.sizeLabel(p.width, p.height)}\n                        </TextBody>\n                        <div className=\"flex items-center gap-1\" onClick={(e) => e.stopPropagation()}>\n                          <button\n                            type=\"button\"\n                            disabled={index === 0}\n                            onClick={() => movePage(p.id, 'up')}\n                            className={`cursor-pointer rounded p-1 text-white/70 transition-colors hover:bg-black-stroke hover:text-white ${index === 0 ? 'pointer-events-none opacity-20' : ''}`}\n                            title={t.layers.pages.moveUp}\n                          >\n                            <ArrowUp size={11} />\n                          </button>\n                          <button\n                            type=\"button\"\n                            disabled={index === pages.length - 1}\n                            onClick={() => movePage(p.id, 'down')}\n                            className={`cursor-pointer rounded p-1 text-white/70 transition-colors hover:bg-black-stroke hover:text-white ${index === pages.length - 1 ? 'pointer-events-none opacity-20' : ''}`}\n                            title={t.layers.pages.moveDown}\n                          >\n                            <ArrowDown size={11} />\n                          </button>\n                          <div className=\"mx-0.5 h-3 w-px bg-panel-border\" />\n                          <button\n                            type=\"button\"\n                            onClick={() => duplicatePage(p.id)}\n                            className=\"cursor-pointer rounded p-1 text-white/70 transition-colors hover:bg-black-stroke hover:text-white\"\n                            title={t.layers.pages.duplicate}\n                          >\n                            <Copy size={11} />\n                          </button>\n                          <button\n                            type=\"button\"\n                            onClick={async () => {\n                              const ok = await dialog.confirm(\n                                t.layers.pages.clearCanvasBody,\n                                { title: t.layers.pages.clearCanvasTitle, variant: 'danger', confirmText: t.layers.pages.clearCanvasConfirm, cancelText: t.common.cancel }\n                              );\n                              if (ok) clearPage(p.id);\n                            }}\n                            className=\"cursor-pointer rounded p-1 text-white/70 transition-colors hover:bg-black-stroke hover:text-amber-400\"\n                            title={t.layers.pages.clear}\n                          >\n                            <RefreshCw size={11} />\n                          </button>\n                          {pages.length > 1 && (\n                            <button\n                              type=\"button\"\n                              onClick={async () => {\n                                const ok = await dialog.confirm(\n                                  t.layers.pages.deleteBody(p.name),\n                                  {\n                                    title: t.layers.pages.deleteTitle,\n                                    variant: 'danger',\n                                    confirmText: t.layers.pages.deleteConfirm,\n                                    cancelText: t.common.cancel,\n                                  },\n                                );\n                                if (ok) deletePage(p.id);\n                              }}\n                              className=\"ml-auto cursor-pointer rounded p-1 text-white/60 transition-colors hover:bg-black-stroke hover:text-red-400\"\n                              title={t.layers.pages.delete}\n                            >\n                              <Trash2 size={11} />\n                            </button>\n                          )}\n                        </div>\n                      </div>\n                    </div>\n                  </div>\n                );\n              })}\n            </div>\n            {/* Bot\u00F3n crear p\u00E1gina (abajo) */}\n            <div className=\"p-3 border-t border-dark-850 flex-shrink-0\">\n              <button\n                onClick={() => addPage(activePage.width, activePage.height)}\n                className=\"w-full flex items-center justify-center gap-2 py-1.5 bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] text-white rounded-lg cursor-pointer transition-all active:scale-95\"\n                title={t.layers.pages.addNewTitle}\n              >\n                <Plus size={13} />\n                <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-white\">\n                  {t.layers.pages.addNew}\n                </TextBody>\n              </button>\n            </div>\n          </div>\n        )}\n      </div>\n\n      {/* Collapse Handle Button \u2014 solo en modo standalone */}\n      {!embedded && (\n        <div className=\"absolute left-[-12px] top-1/2 -translate-y-1/2 z-40\">\n          <button\n            onClick={() => setLayersPanelCollapsed(!layersPanelCollapsed)}\n            className=\"w-6 h-12 rounded-l-lg border-y border-l border-dark-800 bg-dark-900/90 hover:bg-dark-850 hover:text-white backdrop-blur-md flex items-center justify-center text-dark-400 cursor-pointer shadow-md shadow-black/20 hover:shadow-[0_0_12px_color-mix(in_srgb,var(--we-accent)_12%,transparent)] hover:border-[var(--we-accent)]/30 transition-all select-none group relative\"\n          >\n            {layersPanelCollapsed ? (\n              <ChevronLeft size={13} className=\"text-zinc-400 group-hover:text-[var(--we-accent)] transition-colors animate-pulse\" />\n            ) : (\n              <ChevronRight size={13} className=\"text-zinc-400 group-hover:text-[var(--we-accent)] transition-colors\" />\n            )}\n            <TextBody as=\"span\" size=\"sm\" className=\"tooltip-bubble right-full top-1/2 -translate-y-1/2 mr-2\">{layersPanelCollapsed ? t.layers.collapse.show : t.layers.collapse.hide}</TextBody>\n          </button>\n        </div>\n      )}\n\n      {ctxMenu &&\n        createPortal(\n          <div\n            role=\"menu\"\n            data-we-no-deselect\n            className=\"fixed z-[99999] min-w-[11rem] rounded-xl border border-panel-border bg-panel p-1.5 shadow-xl\"\n            style={{ top: ctxMenu.y, left: ctxMenu.x }}\n            onPointerDown={(e) => e.stopPropagation()}\n          >\n            {getType(ctxMenu.layer) !== 'activeselection' && (\n              <button\n                type=\"button\"\n                role=\"menuitem\"\n                className=\"flex w-full cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-left text-white/90 hover:bg-black-capsule\"\n                onClick={() => {\n                  handleAddMask(ctxMenu.layer);\n                  setCtxMenu(null);\n                }}\n              >\n                <Circle size={13} className=\"shrink-0 text-white/70\" />\n                <TextBody as=\"span\" size=\"sm\">\n                  {isPixelLayer(ctxMenu.layer) && hasLayerMask(ctxMenu.layer)\n                    ? t.layers.tooltip.paintMask\n                    : t.layers.tooltip.addMask}\n                </TextBody>\n              </button>\n            )}\n            {isPixelLayer(ctxMenu.layer) && hasLayerMask(ctxMenu.layer) && (\n              <button\n                type=\"button\"\n                role=\"menuitem\"\n                className=\"flex w-full cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-left text-white/90 hover:bg-black-capsule\"\n                onClick={() => {\n                  handleRemoveMask(ctxMenu.layer);\n                  setCtxMenu(null);\n                }}\n              >\n                <Unlink size={13} className=\"shrink-0 text-white/70\" />\n                <TextBody as=\"span\" size=\"sm\">\n                  {t.layers.tooltip.removeMask}\n                </TextBody>\n              </button>\n            )}\n            {isTextObject(ctxMenu.layer) && !isPixelLayer(ctxMenu.layer) && (\n              <button\n                type=\"button\"\n                role=\"menuitem\"\n                className=\"flex w-full cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-left text-white/90 hover:bg-black-capsule\"\n                onClick={() => {\n                  handleRasterize(ctxMenu.layer);\n                  setCtxMenu(null);\n                }}\n              >\n                <ImageIcon size={13} className=\"shrink-0 text-white/70\" />\n                <TextBody as=\"span\" size=\"sm\">\n                  {t.layers.rasterize}\n                </TextBody>\n              </button>\n            )}\n            <button\n              type=\"button\"\n              role=\"menuitem\"\n              className=\"flex w-full cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-left text-white/90 hover:bg-black-capsule\"\n              onClick={() => {\n                toggleLock(ctxMenu.layer);\n                setCtxMenu(null);\n              }}\n            >\n              {(ctxMenu.layer as { locked?: boolean }).locked ? (\n                <Unlock size={13} className=\"shrink-0 text-white/70\" />\n              ) : (\n                <Lock size={13} className=\"shrink-0 text-white/70\" />\n              )}\n              <TextBody as=\"span\" size=\"sm\">\n                {(ctxMenu.layer as { locked?: boolean }).locked\n                  ? t.layers.tooltip.unlock\n                  : t.layers.tooltip.lock}\n              </TextBody>\n            </button>\n            <button\n              type=\"button\"\n              role=\"menuitem\"\n              className=\"flex w-full cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-left text-white/90 hover:bg-black-capsule\"\n              onClick={() => {\n                toggleVisibility(ctxMenu.layer);\n                setCtxMenu(null);\n              }}\n            >\n              {ctxMenu.layer.visible === false ? (\n                <Eye size={13} className=\"shrink-0 text-white/70\" />\n              ) : (\n                <EyeOff size={13} className=\"shrink-0 text-white/70\" />\n              )}\n              <TextBody as=\"span\" size=\"sm\">\n                {ctxMenu.layer.visible === false\n                  ? t.layers.tooltip.show\n                  : t.layers.tooltip.hide}\n              </TextBody>\n            </button>\n            <div className=\"my-1 h-px bg-panel-border\" />\n            <button\n              type=\"button\"\n              role=\"menuitem\"\n              disabled={\n                !!(\n                  canvasInstance &&\n                  !canClearOrDeleteLayer(canvasInstance, ctxMenu.layer)\n                )\n              }\n              className=\"flex w-full cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-left text-red-400 hover:bg-black-capsule disabled:cursor-not-allowed disabled:opacity-40\"\n              onClick={() => {\n                deleteLayer(ctxMenu.layer);\n                setCtxMenu(null);\n              }}\n            >\n              <Trash2 size={13} className=\"shrink-0\" />\n              <TextBody as=\"span\" size=\"sm\">\n                {canvasInstance &&\n                !canClearOrDeleteLayer(canvasInstance, ctxMenu.layer)\n                  ? t.layers.cannotDeleteLastLayer\n                  : t.layers.tooltip.delete}\n              </TextBody>\n            </button>\n          </div>,\n          document.body,\n        )}\n    </div>\n  );\n};\n", "import React, { useState, useEffect } from 'react';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { TextBody } from '../ui';\n\nexport const TransformPanel: React.FC = () => {\n  const { activeObject, canvasInstance, saveHistoryState } = useEditorStore();\n\n  const [x, setX] = useState<number | string>(0);\n  const [y, setY] = useState<number | string>(0);\n  const [w, setW] = useState<number | string>(0);\n  const [h, setH] = useState<number | string>(0);\n  const [angle, setAngle] = useState<number | string>(0);\n\n  useEffect(() => {\n    if (!activeObject) return;\n\n    const updateValues = () => {\n      setX(Math.round(activeObject.left || 0));\n      setY(Math.round(activeObject.top || 0));\n      setW(Math.round((activeObject.width || 0) * (activeObject.scaleX || 1)));\n      setH(Math.round((activeObject.height || 0) * (activeObject.scaleY || 1)));\n\n      let currentAngle = Math.round(activeObject.angle || 0);\n      if (currentAngle < 0) currentAngle += 360;\n      setAngle(currentAngle % 360);\n    };\n\n    updateValues();\n\n    if (canvasInstance) {\n      canvasInstance.on('object:modified', updateValues);\n      canvasInstance.on('object:moving', updateValues);\n      canvasInstance.on('object:scaling', updateValues);\n      canvasInstance.on('object:rotating', updateValues);\n\n      return () => {\n        canvasInstance.off('object:modified', updateValues);\n        canvasInstance.off('object:moving', updateValues);\n        canvasInstance.off('object:scaling', updateValues);\n        canvasInstance.off('object:rotating', updateValues);\n      };\n    }\n  }, [activeObject, canvasInstance]);\n\n  if (!activeObject || activeObject.type === 'activeselection') return null;\n\n  const handleCommit = (key: string, val: number | string) => {\n    if (!activeObject || !canvasInstance) return;\n\n    const numVal = Number(val);\n    if (isNaN(numVal)) return;\n\n    switch (key) {\n      case 'x':\n        activeObject.set('left', numVal);\n        break;\n      case 'y':\n        activeObject.set('top', numVal);\n        break;\n      case 'w':\n        activeObject.set('scaleX', numVal / (activeObject.width || 1));\n        break;\n      case 'h':\n        activeObject.set('scaleY', numVal / (activeObject.height || 1));\n        break;\n      case 'angle':\n        activeObject.set('angle', numVal);\n        break;\n    }\n    activeObject.setCoords();\n    canvasInstance.requestRenderAll();\n    saveHistoryState();\n  };\n\n  const inputCls =\n    'w-full rounded border border-dark-800 bg-dark-950/50 px-2 py-1.5 font-mono text-white transition-all focus:border-[var(--we-accent)] focus:outline-none focus:ring-1 focus:ring-[var(--we-accent)]/50';\n\n  return (\n    <div className=\"grid grid-cols-2 gap-3 border-b border-dark-850 bg-dark-900 p-3\">\n      <div className=\"flex items-center gap-1.5\">\n        <TextBody as=\"span\" size=\"sm\" className=\"w-3 font-mono text-dark-400\">\n          X\n        </TextBody>\n        <input\n          type=\"number\"\n          value={x}\n          onChange={(e) => setX(e.target.value)}\n          onBlur={() => handleCommit('x', x)}\n          onKeyDown={(e) => {\n            if (e.key === 'Enter') {\n              handleCommit('x', x);\n              e.currentTarget.blur();\n            }\n          }}\n          className={inputCls}\n        />\n      </div>\n      <div className=\"flex items-center gap-1.5\">\n        <TextBody as=\"span\" size=\"sm\" className=\"w-3 font-mono text-dark-400\">\n          Y\n        </TextBody>\n        <input\n          type=\"number\"\n          value={y}\n          onChange={(e) => setY(e.target.value)}\n          onBlur={() => handleCommit('y', y)}\n          onKeyDown={(e) => {\n            if (e.key === 'Enter') {\n              handleCommit('y', y);\n              e.currentTarget.blur();\n            }\n          }}\n          className={inputCls}\n        />\n      </div>\n      <div className=\"flex items-center gap-1.5\">\n        <TextBody as=\"span\" size=\"sm\" className=\"w-3 font-mono text-dark-400\">\n          W\n        </TextBody>\n        <input\n          type=\"number\"\n          value={w}\n          onChange={(e) => setW(e.target.value)}\n          onBlur={() => handleCommit('w', w)}\n          onKeyDown={(e) => {\n            if (e.key === 'Enter') {\n              handleCommit('w', w);\n              e.currentTarget.blur();\n            }\n          }}\n          className={inputCls}\n        />\n      </div>\n      <div className=\"flex items-center gap-1.5\">\n        <TextBody as=\"span\" size=\"sm\" className=\"w-3 font-mono text-dark-400\">\n          H\n        </TextBody>\n        <input\n          type=\"number\"\n          value={h}\n          onChange={(e) => setH(e.target.value)}\n          onBlur={() => handleCommit('h', h)}\n          onKeyDown={(e) => {\n            if (e.key === 'Enter') {\n              handleCommit('h', h);\n              e.currentTarget.blur();\n            }\n          }}\n          className={inputCls}\n        />\n      </div>\n      <div className=\"col-span-2 flex items-center gap-1.5\">\n        <TextBody as=\"span\" size=\"sm\" className=\"w-3 font-mono text-dark-400\">\n          \u2220\n        </TextBody>\n        <input\n          type=\"number\"\n          value={angle}\n          onChange={(e) => setAngle(e.target.value)}\n          onBlur={() => handleCommit('angle', angle)}\n          onKeyDown={(e) => {\n            if (e.key === 'Enter') {\n              handleCommit('angle', angle);\n              e.currentTarget.blur();\n            }\n          }}\n          className={inputCls}\n        />\n      </div>\n    </div>\n  );\n};\n", "import React from 'react';\nimport { useEditorStore } from '../store/useEditorStore';\nimport type { Toast } from '../store/useEditorStore';\nimport { CheckCircle2, AlertTriangle, AlertCircle, Info, X } from 'lucide-react';\nimport { useTranslation } from '../i18n';\nimport { sanitizeUserFacingMessage } from '../utils/userFacingError';\nimport { TextBody } from './ui';\n\nexport const ToastContainer: React.FC = () => {\n  const t = useTranslation();\n  const { toasts, removeToast } = useEditorStore();\n\n  if (toasts.length === 0) return null;\n\n  const getIcon = (type: Toast['type']) => {\n    switch (type) {\n      case 'success':\n        return <CheckCircle2 size={18} className=\"text-emerald-400\" />;\n      case 'error':\n        return <AlertCircle size={18} className=\"text-rose-400\" />;\n      case 'warning':\n        return <AlertTriangle size={18} className=\"text-amber-400\" />;\n      case 'info':\n      default:\n        return <Info size={18} className=\"text-sky-400\" />;\n    }\n  };\n\n  const getBorderColor = (type: Toast['type']) => {\n    switch (type) {\n      case 'success':\n        return 'border-emerald-500/30 shadow-emerald-950/20';\n      case 'error':\n        return 'border-rose-500/30 shadow-rose-950/20';\n      case 'warning':\n        return 'border-amber-500/30 shadow-amber-950/20';\n      case 'info':\n      default:\n        return 'border-sky-500/30 shadow-sky-950/20';\n    }\n  };\n\n  const getProgressColor = (type: Toast['type']) => {\n    switch (type) {\n      case 'success':\n        return 'bg-emerald-400';\n      case 'error':\n        return 'bg-rose-400';\n      case 'warning':\n        return 'bg-amber-400';\n      case 'info':\n      default:\n        return 'bg-sky-400';\n    }\n  };\n\n  return (\n    <div className=\"fixed bottom-6 right-20 z-[9999] flex max-w-sm w-full flex-col gap-3 pointer-events-none sm:w-80\">\n      {toasts.map((toast) => (\n        <div\n          key={toast.id}\n          className={`pointer-events-auto flex items-start gap-3 p-4 rounded-2xl border bg-dark-900/90 backdrop-blur-md shadow-2xl transition-all duration-300 transform translate-y-0 scale-100 hover:scale-[1.02] ${getBorderColor(\n            toast.type\n          )} animate-slide-in`}\n          role=\"alert\"\n        >\n          <div className=\"flex-shrink-0 mt-0.5\">{getIcon(toast.type)}</div>\n          <div className=\"flex-1 min-w-0 pr-2\">\n            <TextBody as=\"p\" size=\"sm\" className=\"leading-relaxed text-dark-100\">\n              {toast.type === 'error'\n                ? sanitizeUserFacingMessage(toast.message, {\n                    context: 'toast-render',\n                    log: false,\n                  })\n                : toast.message}\n            </TextBody>\n            {typeof toast.progress === 'number' && (\n              <div\n                className=\"mt-2.5 h-1 rounded-full bg-white/10 overflow-hidden\"\n                role=\"progressbar\"\n                aria-valuemin={0}\n                aria-valuemax={100}\n                aria-valuenow={Math.round(toast.progress)}\n              >\n                <div\n                  className={`h-full rounded-full transition-[width] duration-200 ease-out ${getProgressColor(toast.type)}`}\n                  style={{ width: `${Math.max(0, Math.min(100, toast.progress))}%` }}\n                />\n              </div>\n            )}\n          </div>\n          <button\n            onClick={() => removeToast(toast.id)}\n            className=\"flex-shrink-0 text-dark-400 hover:text-dark-100 transition-colors p-0.5 rounded-lg hover:bg-dark-800\"\n            aria-label={t.common.closeNotification}\n          >\n            <X size={14} />\n          </button>\n        </div>\n      ))}\n    </div>\n  );\n};\n", "import React, { useSyncExternalStore } from 'react';\nimport { FileCheckCorner, FileXCorner, Loader2 } from 'lucide-react';\nimport {\n  getCloudSaveChips,\n  removeCloudSaveChip,\n  subscribeCloudSaveChips,\n  type CloudSaveChip,\n  type CloudSaveChipStatus,\n} from '../utils/cloudSaveStatus';\n\nfunction statusIcon(status: CloudSaveChipStatus) {\n  switch (status) {\n    case 'success':\n      return (\n        <FileCheckCorner size={18} strokeWidth={2} className=\"text-emerald-400\" aria-hidden />\n      );\n    case 'error':\n      return <FileXCorner size={18} strokeWidth={2} className=\"text-rose-400\" aria-hidden />;\n    case 'saving':\n    default:\n      return (\n        <Loader2\n          size={18}\n          strokeWidth={2.5}\n          className=\"animate-spin text-[var(--we-accent)]\"\n          aria-hidden\n        />\n      );\n  }\n}\n\nfunction chipClass(status: CloudSaveChipStatus): string {\n  switch (status) {\n    case 'success':\n      return 'border-emerald-500/40 bg-dark-900/95';\n    case 'error':\n      return 'border-rose-500/40 bg-dark-900/95';\n    case 'saving':\n    default:\n      return 'border-[color-mix(in_srgb,var(--we-accent)_45%,transparent)] bg-dark-900/95';\n  }\n}\n\nfunction ChipButton({ chip }: { chip: CloudSaveChip }) {\n  const clickable = chip.status !== 'saving';\n  return (\n    <button\n      type=\"button\"\n      title={chip.label}\n      aria-label={chip.label}\n      disabled={!clickable}\n      onClick={() => {\n        if (clickable) removeCloudSaveChip(chip.id);\n      }}\n      className={`flex h-10 w-10 shrink-0 items-center justify-center rounded-xl border shadow-lg backdrop-blur-md transition-transform hover:scale-105 disabled:pointer-events-none ${chipClass(chip.status)}`}\n    >\n      {statusIcon(chip.status)}\n    </button>\n  );\n}\n\n/**\n * Icon-only cloud save feedback (spinner / check / X). Max 3 chips.\n * Mount once at app root so all modes share the same stack.\n */\nexport const CloudSaveStatusStack: React.FC = () => {\n  const chips = useSyncExternalStore(\n    subscribeCloudSaveChips,\n    getCloudSaveChips,\n    getCloudSaveChips,\n  );\n\n  if (chips.length === 0) return null;\n\n  return (\n    <div\n      className=\"pointer-events-none fixed bottom-6 right-6 z-[10000] flex flex-col-reverse gap-2\"\n      aria-live=\"polite\"\n    >\n      {chips.map((chip) => (\n        <div key={chip.id} className=\"pointer-events-auto\">\n          <ChipButton chip={chip} />\n        </div>\n      ))}\n    </div>\n  );\n};\n", "import React, { useState, useEffect, useRef } from 'react';\nimport { Command, ArrowRight, X, Sparkles, Filter, Layout, Settings, Move, Type, Square, Hand, Crop, Play, Circle, Triangle, Star, PenTool, Eraser, Trash2, Copy } from 'lucide-react';\nimport { useEditorStore } from '../store/useEditorStore';\nimport { filters } from 'fabric';\nimport { useDialog } from '../components/DialogModal';\nimport { useTranslation } from '../i18n';\nimport { TextBody } from './ui';\n\ninterface CommandItem {\n  id: string;\n  name: string;\n  icon: React.ReactNode;\n  category: string;\n  action: () => void;\n}\n\nexport const CommandPalette: React.FC = () => {\n  const dialog = useDialog();\n  const t = useTranslation();\n  const {\n    isCommandPaletteOpen,\n    setCommandPaletteOpen,\n    activeObject,\n    canvasInstance,\n    pages,\n    activePageId,\n    setActiveTool,\n    updatePageDimensions,\n    rulersEnabled,\n    setRulersEnabled,\n    guidesEnabled,\n    setGuidesEnabled,\n    setPlayingSlideshow,\n    undo,\n    redo,\n    deletePage,\n    clearPage,\n    layoutGridEnabled,\n    setLayoutGridEnabled\n  } = useEditorStore();\n\n  const [query, setQuery] = useState('');\n  const [selectedIndex, setSelectedIndex] = useState(0);\n  const inputRef = useRef<HTMLInputElement>(null);\n  const listRef = useRef<HTMLDivElement>(null);\n\n  // Command definitions\n  const commands: CommandItem[] = [\n    // Tools\n    { id: 'tool-select', name: t.commandPalette.commands.toolSelect, category: t.commandPalette.categories.tools, icon: <Move size={14} />, action: () => setActiveTool('select') },\n    { id: 'tool-pan', name: t.commandPalette.commands.toolPan, category: t.commandPalette.categories.tools, icon: <Hand size={14} />, action: () => setActiveTool('pan') },\n    { id: 'tool-text', name: t.commandPalette.commands.toolText, category: t.commandPalette.categories.tools, icon: <Type size={14} />, action: () => setActiveTool('text') },\n    { id: 'tool-rect', name: t.commandPalette.commands.toolRect, category: t.commandPalette.categories.tools, icon: <Square size={14} />, action: () => setActiveTool('rect') },\n    { id: 'tool-circle', name: t.commandPalette.commands.toolCircle, category: t.commandPalette.categories.tools, icon: <Circle size={14} />, action: () => setActiveTool('circle') },\n    { id: 'tool-triangle', name: t.commandPalette.commands.toolTriangle, category: t.commandPalette.categories.tools, icon: <Triangle size={14} />, action: () => setActiveTool('triangle') },\n    { id: 'tool-star', name: t.commandPalette.commands.toolStar, category: t.commandPalette.categories.tools, icon: <Star size={14} />, action: () => setActiveTool('star') },\n    { id: 'tool-crop', name: t.commandPalette.commands.toolCrop, category: t.commandPalette.categories.tools, icon: <Crop size={14} />, action: () => setActiveTool('crop') },\n    { id: 'tool-pencil', name: t.commandPalette.commands.toolPencil, category: t.commandPalette.categories.tools, icon: <PenTool size={14} />, action: () => setActiveTool('brush') },\n    { id: 'tool-frame-mobile', name: t.commandPalette.commands.toolFrameMobile, category: t.commandPalette.categories.tools, icon: <Layout size={14} />, action: () => setActiveTool('frame-mobile') },\n\n    // Actions\n    { id: 'action-undo', name: t.commandPalette.commands.actionUndo, category: t.commandPalette.categories.actions, icon: <ArrowRight size={14} style={{ transform: 'rotate(180deg)' }} />, action: () => undo() },\n    { id: 'action-redo', name: t.commandPalette.commands.actionRedo, category: t.commandPalette.categories.actions, icon: <ArrowRight size={14} />, action: () => redo() },\n    { id: 'action-delete', name: t.commandPalette.commands.actionDelete, category: t.commandPalette.categories.actions, icon: <Trash2 size={14} />, action: () => {\n      if (activeObject && canvasInstance) {\n        if ((activeObject as any).type === 'activeselection') {\n          (activeObject as any).forEachObject((obj: any) => canvasInstance.remove(obj));\n        } else {\n          canvasInstance.remove(activeObject);\n        }\n        canvasInstance.discardActiveObject();\n        canvasInstance.requestRenderAll();\n      }\n    }},\n    { id: 'action-copy', name: t.commandPalette.commands.actionCopy, category: t.commandPalette.categories.actions, icon: <Copy size={14} />, action: () => {\n      if (activeObject) {\n        activeObject.clone(['linkId']).then((cloned: any) => {\n          (window as any).clipboard = cloned;\n        });\n      }\n    }},\n\n    // Actions\n    { id: 'action-rotate-90', name: t.commandPalette.commands.actionRotate90, category: t.commandPalette.categories.actions, icon: <Sparkles size={14} />, action: () => {\n      if (activeObject && canvasInstance) {\n        activeObject.rotate((activeObject.angle || 0) + 90);\n        canvasInstance.requestRenderAll();\n      }\n    }},\n    { id: 'action-export-png', name: t.commandPalette.commands.actionExportPng, category: t.commandPalette.categories.actions, icon: <ArrowRight size={14} />, action: () => {\n      // Find the export button in DOM and click it\n      const exportBtn = document.querySelector('[data-export-btn]') as HTMLButtonElement;\n      if (exportBtn) exportBtn.click();\n    }},\n    { id: 'action-slideshow', name: t.commandPalette.commands.actionSlideshow, category: t.commandPalette.categories.actions, icon: <Play size={14} />, action: () => setPlayingSlideshow(true) },\n    { id: 'action-duplicate-page', name: t.commandPalette.commands.actionDuplicatePage, category: t.commandPalette.categories.pages, icon: <Copy size={14} />, action: () => {\n      const currentPage = pages.find(p => p.id === activePageId);\n      if (currentPage) {\n        useEditorStore.getState().duplicatePage(activePageId);\n      }\n    }},\n    { id: 'action-delete-page', name: t.commandPalette.commands.actionDeletePage, category: t.commandPalette.categories.pages, icon: <Trash2 size={14} />, action: async () => {\n      if (pages.length <= 1) return;\n      const page = pages.find((p) => p.id === activePageId);\n      const ok = await dialog.confirm(\n        t.layers.pages.deleteBody(page?.name ?? ''),\n        {\n          title: t.layers.pages.deleteTitle,\n          variant: 'danger',\n          confirmText: t.layers.pages.deleteConfirm,\n          cancelText: t.common.cancel,\n        },\n      );\n      if (ok) deletePage(activePageId);\n    }},\n    { id: 'action-clear-page', name: t.commandPalette.commands.actionClearPage, category: t.commandPalette.categories.pages, icon: <Eraser size={14} />, action: async () => {\n      const ok = await dialog.confirm(t.layers.pages.clearCanvasBody, {\n        title: t.layers.pages.clearCanvasTitle,\n        variant: 'danger',\n        confirmText: t.layers.pages.clearCanvasConfirm,\n        cancelText: t.common.cancel,\n      });\n      if (ok) clearPage(activePageId);\n    }},\n    { id: 'action-resize-1080', name: t.commandPalette.commands.actionResize1080, category: t.commandPalette.categories.pages, icon: <Layout size={14} />, action: () => {\n      updatePageDimensions(activePageId, 1080, 1080);\n    }},\n    { id: 'action-resize-1920', name: t.commandPalette.commands.actionResize1920, category: t.commandPalette.categories.pages, icon: <Layout size={14} />, action: () => {\n      updatePageDimensions(activePageId, 1920, 1080);\n    }},\n\n    // Settings\n    { id: 'setting-rulers', name: t.commandPalette.commands.settingRulers, category: t.commandPalette.categories.settings, icon: <Settings size={14} />, action: () => setRulersEnabled(!rulersEnabled) },\n    { id: 'setting-guides', name: t.commandPalette.commands.settingGuides, category: t.commandPalette.categories.settings, icon: <Settings size={14} />, action: () => setGuidesEnabled(!guidesEnabled) },\n    { id: 'setting-grid', name: t.commandPalette.commands.settingGrid, category: t.commandPalette.categories.settings, icon: <Settings size={14} />, action: () => setLayoutGridEnabled(!layoutGridEnabled) },\n\n    // Filters (requires activeImage)\n    { id: 'filter-sepia', name: t.commandPalette.commands.filterSepia, category: t.commandPalette.categories.filters, icon: <Filter size={14} />, action: () => {\n      if (activeObject && activeObject.type === 'image' && canvasInstance) {\n        const img = activeObject as any;\n        img.filters.push(new filters.Sepia());\n        img.applyFilters();\n        canvasInstance.requestRenderAll();\n      } else {\n        dialog.alert(t.commandPalette.selectImageFirst, { title: t.commandPalette.noSelectionTitle, variant: \"warning\" });\n      }\n    }},\n    { id: 'filter-vintage', name: t.commandPalette.commands.filterVintage, category: t.commandPalette.categories.filters, icon: <Filter size={14} />, action: () => {\n      if (activeObject && activeObject.type === 'image' && canvasInstance) {\n        const img = activeObject as any;\n        img.filters.push(new filters.Vintage());\n        img.applyFilters();\n        canvasInstance.requestRenderAll();\n      } else {\n        dialog.alert(t.commandPalette.selectImageFirst, { title: t.commandPalette.noSelectionTitle, variant: \"warning\" });\n      }\n    }},\n    { id: 'filter-grayscale', name: t.commandPalette.commands.filterGrayscale, category: t.commandPalette.categories.filters, icon: <Filter size={14} />, action: () => {\n      if (activeObject && activeObject.type === 'image' && canvasInstance) {\n        const img = activeObject as any;\n        img.filters.push(new filters.Grayscale());\n        img.applyFilters();\n        canvasInstance.requestRenderAll();\n      } else {\n        dialog.alert(t.commandPalette.selectImageFirst, { title: t.commandPalette.noSelectionTitle, variant: \"warning\" });\n      }\n    }},\n    { id: 'filter-invert', name: t.commandPalette.commands.filterInvert, category: t.commandPalette.categories.filters, icon: <Filter size={14} />, action: () => {\n      if (activeObject && activeObject.type === 'image' && canvasInstance) {\n        const img = activeObject as any;\n        img.filters.push(new filters.Invert());\n        img.applyFilters();\n        canvasInstance.requestRenderAll();\n      } else {\n        dialog.alert(t.commandPalette.selectImageFirst, { title: t.commandPalette.noSelectionTitle, variant: \"warning\" });\n      }\n    }},\n  ];\n\n  // Filtering\n  const filteredCommands = query === '' \n    ? commands \n    : commands.filter(c => c.name.toLowerCase().includes(query.toLowerCase()) || c.category.toLowerCase().includes(query.toLowerCase()));\n\n  // Reset index when query changes\n  useEffect(() => {\n    setSelectedIndex(0);\n  }, [query]);\n\n  // Global Keydown for Cmd+K\n  useEffect(() => {\n    const handleGlobalKeyDown = (e: KeyboardEvent) => {\n      if ((e.metaKey || e.ctrlKey) && e.key === 'k') {\n        e.preventDefault();\n        setCommandPaletteOpen(true);\n      }\n    };\n    window.addEventListener('keydown', handleGlobalKeyDown);\n    return () => window.removeEventListener('keydown', handleGlobalKeyDown);\n  }, [setCommandPaletteOpen]);\n\n  // Modal Keydown\n  useEffect(() => {\n    if (!isCommandPaletteOpen) return;\n\n    const handleModalKeyDown = (e: KeyboardEvent) => {\n      if (e.key === 'ArrowDown') {\n        e.preventDefault();\n        setSelectedIndex(prev => (prev < filteredCommands.length - 1 ? prev + 1 : prev));\n      } else if (e.key === 'ArrowUp') {\n        e.preventDefault();\n        setSelectedIndex(prev => (prev > 0 ? prev - 1 : prev));\n      } else if (e.key === 'Enter') {\n        e.preventDefault();\n        if (filteredCommands[selectedIndex]) {\n          executeCommand(filteredCommands[selectedIndex]);\n        }\n      } else if (e.key === 'Escape') {\n        e.preventDefault();\n        setCommandPaletteOpen(false);\n      }\n    };\n\n    window.addEventListener('keydown', handleModalKeyDown);\n    return () => window.removeEventListener('keydown', handleModalKeyDown);\n  }, [isCommandPaletteOpen, filteredCommands, selectedIndex, setCommandPaletteOpen]);\n\n  // Focus input when opened\n  useEffect(() => {\n    if (isCommandPaletteOpen) {\n      setTimeout(() => inputRef.current?.focus(), 50);\n    } else {\n      setQuery('');\n    }\n  }, [isCommandPaletteOpen]);\n\n  // Scroll active item into view\n  useEffect(() => {\n    if (isCommandPaletteOpen && listRef.current) {\n      const activeEl = listRef.current.children[selectedIndex] as HTMLElement;\n      if (activeEl) {\n        activeEl.scrollIntoView({ block: 'nearest' });\n      }\n    }\n  }, [selectedIndex, isCommandPaletteOpen]);\n\n  const executeCommand = (cmd: CommandItem) => {\n    cmd.action();\n    setCommandPaletteOpen(false);\n  };\n\n  if (!isCommandPaletteOpen) return null;\n\n  return (\n    <div className=\"fixed inset-0 z-[9999] bg-black/60 backdrop-blur-sm flex items-start justify-center pt-[15vh]\">\n      <div \n        className=\"w-full max-w-2xl bg-dark-900 border border-dark-700 rounded-2xl shadow-[0_0_50px_rgba(0,0,0,0.5)] overflow-hidden flex flex-col\"\n        onClick={(e) => e.stopPropagation()}\n      >\n        {/* Header / Input */}\n        <div className=\"flex items-center px-4 py-3 border-b border-dark-700 gap-3\">\n          <Command size={20} className=\"text-dark-400\" />\n          <input\n            ref={inputRef}\n            type=\"text\"\n            placeholder={t.commandPalette.placeholder}\n            value={query}\n            onChange={(e) => setQuery(e.target.value)}\n            className=\"flex-1 bg-transparent text-lg text-white font-medium focus:outline-none placeholder-dark-500\"\n          />\n          <div className=\"flex items-center gap-2\">\n            <TextBody\n              as=\"span\"\n              size=\"sm\"\n              className=\"hidden sm:inline-flex items-center gap-1 px-2 py-1 bg-dark-800 border border-dark-600 rounded font-bold text-dark-300\"\n            >\n              ESC\n            </TextBody>\n            <button \n              onClick={() => setCommandPaletteOpen(false)}\n              className=\"text-dark-400 hover:text-white transition-colors\"\n            >\n              <X size={20} />\n            </button>\n          </div>\n        </div>\n\n        {/* Results List */}\n        <div \n          ref={listRef}\n          className=\"max-h-[400px] overflow-y-auto p-2\"\n        >\n          {filteredCommands.length === 0 ? (\n            <TextBody as=\"p\" size=\"md\" className=\"py-8 text-center text-dark-400\">\n              {t.commandPalette.noResults(query)}\n            </TextBody>\n          ) : (\n            filteredCommands.map((cmd, i) => (\n              <div\n                key={cmd.id}\n                onClick={() => executeCommand(cmd)}\n                className={`flex items-center gap-3 px-4 py-3 rounded-xl cursor-pointer transition-colors ${\n                  i === selectedIndex ? 'bg-brand-500 text-white' : 'hover:bg-dark-800 text-dark-300'\n                }`}\n                onMouseEnter={() => setSelectedIndex(i)}\n              >\n                <div className={`p-1.5 rounded-lg ${i === selectedIndex ? 'bg-white/20' : 'bg-dark-800'}`}>\n                  {cmd.icon}\n                </div>\n                <div className=\"flex-1 flex flex-col\">\n                  <TextBody\n                    as=\"span\"\n                    size=\"md\"\n                    className={`font-semibold ${i === selectedIndex ? 'text-white' : 'text-white'}`}\n                  >\n                    {cmd.name}\n                  </TextBody>\n                  <TextBody\n                    as=\"span\"\n                    size=\"sm\"\n                    className={`uppercase tracking-wider font-bold ${i === selectedIndex ? 'text-brand-200' : 'text-dark-500'}`}\n                  >\n                    {cmd.category}\n                  </TextBody>\n                </div>\n                {i === selectedIndex && (\n                  <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-brand-200 flex items-center gap-1\">\n                    {t.commandPalette.pressEnter} <kbd className=\"px-1.5 py-0.5 bg-brand-600 rounded\">Enter</kbd>\n                  </TextBody>\n                )}\n              </div>\n            ))\n          )}\n        </div>\n        \n        {/* Footer */}\n        <div className=\"bg-dark-850 px-4 py-2 flex items-center justify-between border-t border-dark-700\">\n          <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400\">\n            {t.commandPalette.navigateHint}\n          </TextBody>\n          <TextBody as=\"span\" size=\"sm\" className=\"text-dark-400 flex items-center gap-1\">\n            <Command size={10} /> {t.commandPalette.title}\n          </TextBody>\n        </div>\n      </div>\n    </div>\n  );\n};\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { StaticCanvas } from 'fabric';\nimport { ChevronLeft, ChevronRight, X, Play, Pause, Maximize } from 'lucide-react';\nimport { TextBody } from '../ui';\nimport { useTranslation } from '../../i18n';\n\nexport const PresentationMode: React.FC = () => {\n  const t = useTranslation();\n  const { isPlayingSlideshow, setPlayingSlideshow, pages } = useEditorStore();\n\n  const [currentIndex, setCurrentIndex] = useState(0);\n  const [autoAdvance, setAutoAdvance] = useState(false);\n  const [transitionState, setTransitionState] = useState<'idle' | 'entering' | 'leaving'>('idle');\n\n  const canvasRef = useRef<HTMLCanvasElement>(null);\n  const staticCanvasRef = useRef<StaticCanvas | null>(null);\n  const autoAdvanceIntervalRef = useRef<NodeJS.Timeout | null>(null);\n\n  const exitPresentation = () => {\n    if (document.fullscreenElement) document.exitFullscreen().catch(() => {});\n    setAutoAdvance(false);\n    setPlayingSlideshow(false);\n  };\n\n  // Reset slide index when opening presentation.\n  useEffect(() => {\n    if (isPlayingSlideshow) {\n      setCurrentIndex(0);\n      setAutoAdvance(false);\n      setTransitionState('idle');\n    }\n  }, [isPlayingSlideshow]);\n\n  // Initialize Static Canvas\n  useEffect(() => {\n    if (!isPlayingSlideshow || !canvasRef.current) return;\n\n    if (!staticCanvasRef.current) {\n      staticCanvasRef.current = new StaticCanvas(canvasRef.current, {\n        renderOnAddRemove: false,\n      });\n    }\n\n    return () => {\n      if (staticCanvasRef.current) {\n        staticCanvasRef.current.dispose();\n        staticCanvasRef.current = null;\n      }\n    };\n  }, [isPlayingSlideshow]);\n\n  // Load current page\n  useEffect(() => {\n    if (!isPlayingSlideshow || !staticCanvasRef.current || !pages[currentIndex]) return;\n\n    const page = pages[currentIndex];\n\n    const loadPage = async () => {\n      setTransitionState('leaving');\n\n      await new Promise((r) => setTimeout(r, 200));\n\n      const screenWidth = window.innerWidth;\n      const screenHeight = window.innerHeight;\n      const scaleX = screenWidth / page.width;\n      const scaleY = screenHeight / page.height;\n      const scale = Math.min(scaleX, scaleY) * 0.9;\n\n      staticCanvasRef.current?.setDimensions({\n        width: page.width * scale,\n        height: page.height * scale,\n      });\n      staticCanvasRef.current?.setZoom(scale);\n\n      await staticCanvasRef.current?.loadFromJSON(page.json || {});\n      if (staticCanvasRef.current) {\n        staticCanvasRef.current.backgroundColor = page.backgroundColor;\n        staticCanvasRef.current.requestRenderAll();\n      }\n\n      setTransitionState('entering');\n      await new Promise((r) => setTimeout(r, 50));\n      setTransitionState('idle');\n    };\n\n    void loadPage();\n  }, [currentIndex, pages, isPlayingSlideshow]);\n\n  // Keyboard navigation\n  useEffect(() => {\n    if (!isPlayingSlideshow) return;\n\n    const handleKeyDown = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') {\n        exitPresentation();\n      } else if (e.key === 'ArrowRight' || e.key === ' ') {\n        if (e.key === ' ') e.preventDefault();\n        setCurrentIndex((prev) => (prev < pages.length - 1 ? prev + 1 : prev));\n      } else if (e.key === 'ArrowLeft') {\n        setCurrentIndex((prev) => (prev > 0 ? prev - 1 : prev));\n      } else if (e.key === 'f' || e.key === 'F') {\n        if (!document.fullscreenElement) {\n          document.documentElement.requestFullscreen().catch(() => {});\n        } else {\n          document.exitFullscreen().catch(() => {});\n        }\n      }\n    };\n\n    window.addEventListener('keydown', handleKeyDown);\n    return () => window.removeEventListener('keydown', handleKeyDown);\n  }, [isPlayingSlideshow, pages.length, setPlayingSlideshow]);\n\n  // Auto advance loop\n  useEffect(() => {\n    if (autoAdvance && isPlayingSlideshow) {\n      autoAdvanceIntervalRef.current = setInterval(() => {\n        setCurrentIndex((prev) => {\n          if (prev < pages.length - 1) return prev + 1;\n          setAutoAdvance(false);\n          return prev;\n        });\n      }, 3000);\n    } else if (autoAdvanceIntervalRef.current) {\n      clearInterval(autoAdvanceIntervalRef.current);\n    }\n\n    return () => {\n      if (autoAdvanceIntervalRef.current) clearInterval(autoAdvanceIntervalRef.current);\n    };\n  }, [autoAdvance, isPlayingSlideshow, pages.length]);\n\n  if (!isPlayingSlideshow) return null;\n\n  return (\n    <div className=\"fixed inset-0 z-[100000] bg-black flex items-center justify-center\">\n      {/* Always-visible exit \u2014 hover-only chrome was easy to miss */}\n      <button\n        type=\"button\"\n        onClick={exitPresentation}\n        className=\"absolute top-5 right-5 z-10 flex size-11 items-center justify-center rounded-full border border-white/20 bg-black/70 text-white shadow-lg backdrop-blur-md transition-colors hover:bg-red-500/80 hover:border-red-400/50\"\n        title={t.toolbar.image.exitPresentation}\n        aria-label={t.toolbar.image.exitPresentation}\n      >\n        <X size={22} />\n      </button>\n\n      <div\n        className={`transition-all duration-300 transform ${\n          transitionState === 'leaving'\n            ? 'opacity-0 scale-95'\n            : transitionState === 'entering'\n              ? 'opacity-0 scale-105'\n              : 'opacity-100 scale-100'\n        }`}\n      >\n        <div className=\"shadow-2xl shadow-black/50\">\n          <canvas ref={canvasRef} />\n        </div>\n      </div>\n\n      <div className=\"absolute bottom-0 left-0 right-0 p-8 flex justify-center\">\n        <div className=\"bg-dark-900/90 backdrop-blur-md border border-dark-700 p-2 rounded-2xl flex items-center gap-2 shadow-xl\">\n          <TextBody as=\"span\" size=\"sm\" className=\"px-3 font-bold font-mono text-dark-300\">\n            {currentIndex + 1} / {pages.length}\n          </TextBody>\n\n          <div className=\"h-4 w-px bg-dark-700 mx-1\" />\n\n          <button\n            type=\"button\"\n            onClick={() => setCurrentIndex((prev) => Math.max(0, prev - 1))}\n            disabled={currentIndex === 0}\n            className=\"p-2 rounded-xl text-white hover:bg-dark-700 disabled:opacity-30 transition-colors\"\n          >\n            <ChevronLeft size={20} />\n          </button>\n\n          <button\n            type=\"button\"\n            onClick={() => setAutoAdvance(!autoAdvance)}\n            className={`p-2 rounded-xl transition-colors ${autoAdvance ? 'text-[var(--we-accent)] bg-[var(--we-accent-muted)]' : 'text-white hover:bg-dark-700'}`}\n            title={autoAdvance ? t.videoEditor.playback.pause : t.videoEditor.playback.play}\n          >\n            {autoAdvance ? <Pause size={20} /> : <Play size={20} />}\n          </button>\n\n          <button\n            type=\"button\"\n            onClick={() => setCurrentIndex((prev) => Math.min(pages.length - 1, prev + 1))}\n            disabled={currentIndex === pages.length - 1}\n            className=\"p-2 rounded-xl text-white hover:bg-dark-700 disabled:opacity-30 transition-colors\"\n          >\n            <ChevronRight size={20} />\n          </button>\n\n          <div className=\"h-4 w-px bg-dark-700 mx-1\" />\n\n          <button\n            type=\"button\"\n            onClick={() => {\n              if (!document.fullscreenElement) {\n                document.documentElement.requestFullscreen().catch(() => {});\n              } else {\n                document.exitFullscreen().catch(() => {});\n              }\n            }}\n            className=\"p-2 rounded-xl text-white hover:bg-dark-700 transition-colors\"\n            title={t.videoEditor.playback.fullscreen}\n            aria-label={t.videoEditor.playback.fullscreen}\n          >\n            <Maximize size={20} />\n          </button>\n\n          <button\n            type=\"button\"\n            onClick={exitPresentation}\n            className=\"p-2 rounded-xl text-red-400 hover:bg-red-500/20 transition-colors\"\n            title={t.toolbar.image.exitPresentation}\n            aria-label={t.toolbar.image.exitPresentation}\n          >\n            <X size={20} />\n          </button>\n        </div>\n      </div>\n    </div>\n  );\n};\n", "import React, { useCallback, useRef, useState } from 'react';\nimport { Sparkles } from 'lucide-react';\nimport { LeftPanel } from './LeftPanel';\nimport { VideoPreview } from './VideoPreview';\nimport { RightSidebar } from './RightSidebar';\nimport { TrackControls } from './TrackControls';\nimport { Timeline } from './Timeline';\nimport { TimelineToolbar, TIMELINE_BASE_TRACK_HEIGHT } from './TimelineToolbar';\nimport { EditorEmptyState } from './EditorEmptyState';\nimport { EditorShellHeader } from './EditorShellHeader';\nimport { ShellFileMenu, DropdownItem, DropdownDivider } from './ShellFileMenu';\nimport { ModeProjectTabs } from './ModeProjectTabs';\nimport { ExportModal } from './ExportModal';\nimport { AiContentModal } from './AiContentModal';\nimport { VideoAiGenerateModal } from './VideoAiGenerateModal';\nimport { useVideoStore } from '../../store/useVideoStore';\nimport { useVideoUiStore } from '../../store/useVideoUiStore';\nimport { modeAccentVars } from '../../theme/modeAccent';\nimport { useTranslation } from '../../i18n';\nimport { useDialog } from '../DialogModal';\nimport { exportProjectToWzrdv, importProjectFromWzrdv } from '../../utils/projectFileHelper';\nimport { projectAccept, projectExtDot, safeProjectBasename } from '../../utils/projectExtensions';\nimport { uploadCurrentProjectToCloudWithToast } from '../../utils/cloudSaveToast';\nimport type { Editable } from '../../services/editableService';\nimport type { EditorMode } from './EditorModeToggle';\n\ninterface VideoEditorProps {\n  onSwitchToImage?: () => void;\n  onSwitchToAudio?: () => void;\n  onSwitchToText?: () => void;\n  onSwitchToSlides?: () => void;\n  onNewProject?: () => void;\n  /** Persistent \"Back\" button handler. Falls back to window.history.back(). */\n  onBack?: () => void;\n  backHref?: string;\n  backLinkText?: string;\n  /** Called when the user clicks a recent cloud canvas in the empty state. */\n  onOpenCloudProject?: (editable: Editable) => void;\n}\nconst TIMELINE_TRACK_HEIGHT_MIN = Math.round(TIMELINE_BASE_TRACK_HEIGHT * 0.6);\nconst TIMELINE_DEFAULT_WRAPPER_HEIGHT = 180;\nconst TIMELINE_WRAPPER_MIN = 120;\nconst TIMELINE_WRAPPER_MAX = 720;\n\nexport const VideoEditor: React.FC<VideoEditorProps> = ({\n  onSwitchToImage,\n  onSwitchToAudio,\n  onSwitchToText,\n  onSwitchToSlides,\n  onNewProject,\n  onBack,\n  backHref,\n  backLinkText,\n  onOpenCloudProject,\n}) => {\n  const t = useTranslation();\n  const dialog = useDialog();\n  const { videoProjects } = useVideoStore();\n  const hasProject = videoProjects.length > 0;\n  const [isLeftPanelVisible, setIsLeftPanelVisible] = useState(true);\n  const [isTimelineCollapsed, setIsTimelineCollapsed] = useState(false);\n  const [trackHeightScale, setTrackHeightScale] = useState(1);\n  const [wrapperHeight, setWrapperHeight] = useState(TIMELINE_DEFAULT_WRAPPER_HEIGHT);\n  const [isFullscreen, setIsFullscreen] = useState(false);\n  const [trackControlsWidth, setTrackControlsWidth] = useState(180);\n  const [isExportOpen, setIsExportOpen] = useState(false);\n  const [isMarketingOpen, setIsMarketingOpen] = useState(false);\n  const aiGenerateTool = useVideoUiStore((s) => s.aiGenerateTool);\n  const closeAiGenerateTool = useVideoUiStore((s) => s.closeAiGenerateTool);\n  const [isSavingCloud, setIsSavingCloud] = useState(false);\n  const [isSaving, setIsSaving] = useState(false);\n  const [isLoading, setIsLoading] = useState(false);\n  const fileInputRef = useRef<HTMLInputElement>(null);\n  const savedWrapperHeightRef = useRef<number | null>(null);\n  const isResizingRef = useRef(false);\n  const isHResizingRef = useRef(false);\n\n  const handleSwitchMode = (mode: EditorMode) => {\n    if (mode === 'image') onSwitchToImage?.();\n    else if (mode === 'audio') onSwitchToAudio?.();\n    else if (mode === 'text') onSwitchToText?.();\n    else if (mode === 'slides') onSwitchToSlides?.();\n  };\n\n  const handleSaveProject = async () => {\n    const state = useVideoStore.getState();\n    const tabName =\n      state.videoProjects.find((p) => p.id === state.activeVideoProjectId)?.name ||\n      t.dialog.projectNamePrompt.fallbackName;\n    const safeProjectName = safeProjectBasename(tabName, t.dialog.projectNamePrompt.fallbackName);\n\n    setIsSaving(true);\n    try {\n      const projectBlob = await exportProjectToWzrdv(\n        state.aspectRatio,\n        state.tracks,\n        state.transitions,\n        state.assets\n      );\n      const downloadUrl = URL.createObjectURL(projectBlob);\n      const a = document.createElement('a');\n      a.href = downloadUrl;\n      a.download = `${safeProjectName}${projectExtDot('video')}`;\n      document.body.appendChild(a);\n      a.click();\n      document.body.removeChild(a);\n      URL.revokeObjectURL(downloadUrl);\n    } catch (err: unknown) {\n      const message = err instanceof Error ? err.message : String(err);\n      dialog.alert(t.dialog.saveError.message(message), { title: t.dialog.saveError.title, variant: 'error' });\n    } finally {\n      setIsSaving(false);\n    }\n  };\n\n  const handleSaveToCloud = async () => {\n    if (isSavingCloud) return;\n    setIsSavingCloud(true);\n    try {\n      await uploadCurrentProjectToCloudWithToast('video');\n    } catch {\n      // toast already shown\n    } finally {\n      setIsSavingCloud(false);\n    }\n  };\n\n  const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {\n    const file = e.target.files?.[0];\n    if (!file) return;\n    setIsLoading(true);\n    try {\n      const projectData = await importProjectFromWzrdv(file);\n      useVideoStore.getState().importVideoProject(projectData, file.name);\n      e.target.value = '';\n      dialog.alert(t.dialog.projectOpened.message, { title: t.dialog.projectOpened.title, variant: 'info' });\n    } catch (err: unknown) {\n      const message = err instanceof Error ? err.message : String(err);\n      dialog.alert(t.dialog.projectLoadError.message(message), { title: t.dialog.projectLoadError.title, variant: 'error' });\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  // \u2500\u2500 Canvas zoom & pan (shared between TimelineToolbar controls and VideoPreview)\n  const CANVAS_ZOOM_MIN  = 0.25;\n  const CANVAS_ZOOM_MAX  = 4;\n  const CANVAS_ZOOM_STEP = 0.25;\n  const [canvasZoom,   setCanvasZoom]   = useState(1);\n  const [canvasOffset, setCanvasOffset] = useState({ x: 0, y: 0 });\n  /** Preview render quality 50\u2013100 (100 = full project resolution). */\n  const [previewQuality, setPreviewQuality] = useState(100);\n\n  const clampCanvasZoom = (v: number) => Math.max(CANVAS_ZOOM_MIN, Math.min(CANVAS_ZOOM_MAX, v));\n\n  const handleCanvasZoomIn  = useCallback(() => setCanvasZoom((z) => clampCanvasZoom(Math.round((z + CANVAS_ZOOM_STEP) * 100) / 100)), []);\n  const handleCanvasZoomOut = useCallback(() => setCanvasZoom((z) => clampCanvasZoom(Math.round((z - CANVAS_ZOOM_STEP) * 100) / 100)), []);\n  const handleCanvasZoomReset = useCallback(() => { setCanvasZoom(1); setCanvasOffset({ x: 0, y: 0 }); }, []);\n\n  const trackHeight = Math.max(\n    TIMELINE_TRACK_HEIGHT_MIN,\n    Math.round(TIMELINE_BASE_TRACK_HEIGHT * trackHeightScale),\n  );\n\n  const handleToggleFullscreen = useCallback(() => {\n    setIsFullscreen((prev) => {\n      if (prev) {\n        if (savedWrapperHeightRef.current !== null) {\n          setWrapperHeight(savedWrapperHeightRef.current);\n        }\n        return false;\n      }\n      savedWrapperHeightRef.current = wrapperHeight;\n      return true;\n    });\n  }, [wrapperHeight]);\n\n  const handleResizeStart = useCallback(\n    (e: React.MouseEvent) => {\n      if (isFullscreen) return;\n      e.preventDefault();\n      const startY = e.clientY;\n      const startHeight = wrapperHeight;\n      isResizingRef.current = true;\n\n      const handleMove = (moveEvent: MouseEvent) => {\n        if (!isResizingRef.current) return;\n        const deltaY = startY - moveEvent.clientY;\n        const nextHeight = Math.max(\n          TIMELINE_WRAPPER_MIN,\n          Math.min(TIMELINE_WRAPPER_MAX, startHeight + deltaY),\n        );\n        setWrapperHeight(nextHeight);\n      };\n\n      const handleEnd = () => {\n        isResizingRef.current = false;\n        window.removeEventListener('mousemove', handleMove);\n        window.removeEventListener('mouseup', handleEnd);\n        document.body.style.userSelect = '';\n        document.body.style.cursor = '';\n      };\n\n      document.body.style.userSelect = 'none';\n      document.body.style.cursor = 'ns-resize';\n      window.addEventListener('mousemove', handleMove);\n      window.addEventListener('mouseup', handleEnd);\n    },\n    [isFullscreen, wrapperHeight],\n  );\n\n  const TRACK_CONTROLS_MIN = 120;\n  const TRACK_CONTROLS_MAX = 360;\n\n  const handleHResizeStart = useCallback(\n    (e: React.MouseEvent) => {\n      e.preventDefault();\n      const startX = e.clientX;\n      const startWidth = trackControlsWidth;\n      isHResizingRef.current = true;\n\n      const handleMove = (moveEvent: MouseEvent) => {\n        if (!isHResizingRef.current) return;\n        const deltaX = moveEvent.clientX - startX;\n        const nextWidth = Math.max(\n          TRACK_CONTROLS_MIN,\n          Math.min(TRACK_CONTROLS_MAX, startWidth + deltaX),\n        );\n        setTrackControlsWidth(nextWidth);\n      };\n\n      const handleEnd = () => {\n        isHResizingRef.current = false;\n        window.removeEventListener('mousemove', handleMove);\n        window.removeEventListener('mouseup', handleEnd);\n        document.body.style.userSelect = '';\n        document.body.style.cursor = '';\n      };\n\n      document.body.style.userSelect = 'none';\n      document.body.style.cursor = 'ew-resize';\n      window.addEventListener('mousemove', handleMove);\n      window.addEventListener('mouseup', handleEnd);\n    },\n    [trackControlsWidth],\n  );\n\n  const handleResetLayout = useCallback(() => {\n    setWrapperHeight(TIMELINE_DEFAULT_WRAPPER_HEIGHT);\n    setTrackControlsWidth(180);\n  }, []);\n\n  const effectiveWrapperStyle: React.CSSProperties = isFullscreen\n    ? { flex: '1 1 auto', minHeight: 0 }\n    : {\n        height: isTimelineCollapsed ? '0px' : `${wrapperHeight}px`,\n      };\n\n  const effectiveBlockStyle: React.CSSProperties = isFullscreen\n    ? { flex: '1 1 auto', minHeight: 0 }\n    : { flexShrink: 0 };\n\n  return (\n    <div\n      data-we-mode=\"video\"\n      style={modeAccentVars('video')}\n      className=\"flex flex-col h-full w-full overflow-hidden text-ink-primary relative\"\n    >\n      <EditorShellHeader\n        mode=\"video\"\n        onBack={onBack}\n        backHref={backHref}\n        backLabel={backLinkText}\n        onSwitchMode={handleSwitchMode}\n        onNewProject={onNewProject}\n        newProjectTitle={t.editor.newProject.video}\n        onExport={hasProject ? () => setIsExportOpen(true) : undefined}\n        exportDisabled={!hasProject}\n        fileMenu={\n          <ShellFileMenu\n            onNew={onNewProject}\n            onOpen={() => fileInputRef.current?.click()}\n            onSave={hasProject ? handleSaveProject : undefined}\n            onSaveToCloud={hasProject ? handleSaveToCloud : undefined}\n            isSavingCloud={isSavingCloud}\n            newLabel={t.toolbar.video.newCanvas}\n            openLabel={isLoading ? t.toolbar.video.importProjectLoading : t.toolbar.video.importProjectIdle}\n            saveLabel={isSaving ? t.toolbar.video.saveProjectSaving : t.toolbar.video.saveProjectIdle}\n            extras={\n              hasProject ? (\n                <>\n                  <DropdownDivider />\n                  <DropdownItem\n                    icon={<Sparkles size={15} strokeWidth={2.25} />}\n                    onClick={() => setIsMarketingOpen(true)}\n                    description={t.toolbar.video.aiAssistantHint}\n                  >\n                    {t.toolbar.video.aiAssistant}\n                  </DropdownItem>\n                </>\n              ) : undefined\n            }\n          />\n        }\n        tabs={<ModeProjectTabs mode=\"video\" />}\n      />\n\n      <input\n        ref={fileInputRef}\n        type=\"file\"\n        accept={projectAccept('video')}\n        className=\"hidden\"\n        onChange={handleFileChange}\n      />\n      <ExportModal isOpen={isExportOpen} onClose={() => setIsExportOpen(false)} />\n      <AiContentModal isOpen={isMarketingOpen} onClose={() => setIsMarketingOpen(false)} />\n      <VideoAiGenerateModal\n        tool={aiGenerateTool}\n        onClose={closeAiGenerateTool}\n      />\n\n      <div className=\"relative flex min-h-0 flex-1 flex-col\">\n        {hasProject ? (\n          <>\n            {/* 3 columns: left dock | preview | right dock */}\n            <div\n              className={`min-h-0 w-full flex-1 ${\n                isFullscreen ? 'hidden' : 'flex'\n              }`}\n            >\n              <LeftPanel\n                contentOpen={isLeftPanelVisible}\n                onContentOpenChange={setIsLeftPanelVisible}\n                canvasZoom={canvasZoom}\n                setCanvasZoom={setCanvasZoom}\n                canvasOffset={canvasOffset}\n                onCanvasZoomIn={handleCanvasZoomIn}\n                onCanvasZoomOut={handleCanvasZoomOut}\n                onCanvasZoomReset={handleCanvasZoomReset}\n                canvasZoomMin={CANVAS_ZOOM_MIN}\n                canvasZoomMax={CANVAS_ZOOM_MAX}\n                previewQuality={previewQuality}\n                setPreviewQuality={setPreviewQuality}\n              />\n              <div className=\"relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden\">\n                <VideoPreview\n                  canvasZoom={canvasZoom}\n                  setCanvasZoom={setCanvasZoom}\n                  canvasOffset={canvasOffset}\n                  setCanvasOffset={setCanvasOffset}\n                  canvasZoomMin={CANVAS_ZOOM_MIN}\n                  canvasZoomMax={CANVAS_ZOOM_MAX}\n                  canvasZoomStep={CANVAS_ZOOM_STEP}\n                  previewQuality={previewQuality}\n                />\n              </div>\n              <RightSidebar />\n            </div>\n\n            <div\n              className={`relative z-60 flex flex-col border-t border-[#2A2A38] bg-[#13131A] ${\n                isFullscreen ? 'min-h-0 flex-1' : ''\n              }`}\n              style={isFullscreen ? undefined : effectiveBlockStyle}\n            >\n              {!isFullscreen && (\n                <div\n                  role=\"separator\"\n                  aria-label={t.videoEditor.resizeTimeline}\n                  aria-orientation=\"horizontal\"\n                  onMouseDown={handleResizeStart}\n                  className=\"absolute left-0 right-0 top-0 z-20 h-1.5 -translate-y-1/2 cursor-ns-resize bg-transparent transition-colors hover:bg-[var(--we-accent-muted)] group\"\n                >\n                  <div className=\"absolute inset-x-0 top-1/2 -translate-y-1/2 transition-colors group-hover:bg-[var(--we-accent-hover)]\" />\n                </div>\n              )}\n              <TimelineToolbar\n                trackHeightScale={trackHeightScale}\n                setTrackHeightScale={setTrackHeightScale}\n                onResetLayout={handleResetLayout}\n                isCollapsed={isTimelineCollapsed}\n                onToggleCollapsed={() => setIsTimelineCollapsed((v) => !v)}\n                isFullscreen={isFullscreen}\n                onToggleFullscreen={handleToggleFullscreen}\n              />\n              <div\n                className=\"flex flex-row overflow-hidden transition-[height] duration-200 ease-out\"\n                style={effectiveWrapperStyle}\n              >\n                <TrackControls\n                  trackHeight={trackHeight}\n                  width={trackControlsWidth}\n                  onHResizeStart={handleHResizeStart}\n                />\n                <Timeline trackHeight={trackHeight} />\n              </div>\n            </div>\n          </>\n        ) : (\n          <EditorEmptyState\n            mode=\"Video\"\n            onCreate={onNewProject ?? (() => {})}\n            onOpenCloud={onOpenCloudProject ?? (() => {})}\n          />\n        )}\n      </div>\n    </div>\n  );\n};\n\nexport default VideoEditor;\n", "import React, { useCallback, useState } from 'react';\nimport { Folder, Files, Ratio, RotateCcw, Sparkles } from 'lucide-react';\nimport { AssetPanel } from './AssetPanel';\nimport { MyFilesPanel } from './MyFilesPanel';\nimport { VideoCanvasPanel } from './VideoCanvasPanel';\nimport { VideoAiToolsPanel } from './VideoAiToolsPanel';\nimport { useTranslation } from '../../i18n';\nimport { IconButton, TextTitle } from '../ui';\n\nexport type LeftDockTab = 'assets' | 'myFiles' | 'ai' | 'canvas';\n\nconst DEFAULT_WIDTH = 280;\nconst MIN_WIDTH = 220;\nconst MAX_WIDTH = 420;\n\nconst RAIL: {\n  id: LeftDockTab;\n  icon: React.ReactNode;\n  labelKey: 'assets' | 'myFiles' | 'ai' | 'canvas';\n}[] = [\n  { id: 'assets', icon: <Folder size={17} />, labelKey: 'assets' },\n  { id: 'myFiles', icon: <Files size={17} />, labelKey: 'myFiles' },\n  { id: 'ai', icon: <Sparkles size={17} />, labelKey: 'ai' },\n  { id: 'canvas', icon: <Ratio size={17} />, labelKey: 'canvas' },\n];\n\nexport interface LeftPanelProps {\n  /** When false, only the icon rail stays (content collapsed). */\n  contentOpen?: boolean;\n  onContentOpenChange?: (open: boolean) => void;\n  canvasZoom: number;\n  setCanvasZoom: (z: number) => void;\n  canvasOffset: { x: number; y: number };\n  onCanvasZoomIn: () => void;\n  onCanvasZoomOut: () => void;\n  onCanvasZoomReset: () => void;\n  canvasZoomMin: number;\n  canvasZoomMax: number;\n  previewQuality: number;\n  setPreviewQuality: (q: number) => void;\n}\n\n/**\n * Video left dock: thin icon rail + content column for the active tool.\n * Assets / My Files / AI / Canvas (aspect, size, zoom).\n */\nexport const LeftPanel: React.FC<LeftPanelProps> = ({\n  contentOpen: contentOpenProp,\n  onContentOpenChange,\n  canvasZoom,\n  setCanvasZoom,\n  canvasOffset,\n  onCanvasZoomIn,\n  onCanvasZoomOut,\n  onCanvasZoomReset,\n  canvasZoomMin,\n  canvasZoomMax,\n  previewQuality,\n  setPreviewQuality,\n}) => {\n  const t = useTranslation();\n  const [activeTab, setActiveTab] = useState<LeftDockTab>('assets');\n  const [internalOpen, setInternalOpen] = useState(true);\n  const [panelWidth, setPanelWidth] = useState(DEFAULT_WIDTH);\n\n  const contentOpen = contentOpenProp ?? internalOpen;\n  const setContentOpen = (open: boolean) => {\n    onContentOpenChange?.(open);\n    if (contentOpenProp === undefined) setInternalOpen(open);\n  };\n\n  const isResized = panelWidth !== DEFAULT_WIDTH;\n\n  const selectTab = (id: LeftDockTab) => {\n    if (contentOpen && activeTab === id) {\n      setContentOpen(false);\n      return;\n    }\n    setActiveTab(id);\n    setContentOpen(true);\n  };\n\n  const onResizeStart = useCallback(\n    (e: React.MouseEvent) => {\n      e.preventDefault();\n      const startX = e.clientX;\n      const startW = panelWidth;\n      const onMove = (ev: MouseEvent) => {\n        setPanelWidth(Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, startW + (ev.clientX - startX))));\n      };\n      const onUp = () => {\n        window.removeEventListener('mousemove', onMove);\n        window.removeEventListener('mouseup', onUp);\n      };\n      window.addEventListener('mousemove', onMove);\n      window.addEventListener('mouseup', onUp);\n    },\n    [panelWidth],\n  );\n\n  const title =\n    activeTab === 'assets'\n      ? t.leftPanel.assets\n      : activeTab === 'myFiles'\n        ? t.leftPanel.myFiles\n        : activeTab === 'ai'\n          ? t.leftPanel.ai\n          : t.leftPanel.canvas;\n\n  return (\n    <aside className=\"flex h-full min-h-0 shrink-0 select-none border-r border-panel-border bg-panel\">\n      <div className=\"flex w-11 shrink-0 flex-col items-center gap-1.5 border-r border-panel-border bg-panel py-2\">\n        {RAIL.map((item) => {\n          const isActive = contentOpen && activeTab === item.id;\n          return (\n            <button\n              key={item.id}\n              type=\"button\"\n              title={t.leftPanel[item.labelKey]}\n              onClick={() => selectTab(item.id)}\n              className={`\n                relative flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg\n                transition-all duration-150 active:scale-90\n                ${\n                  isActive\n                    ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--we-accent)_35%,transparent)]'\n                    : 'text-white/80 hover:bg-black-capsule hover:text-white'\n                }\n              `}\n            >\n              {isActive && (\n                <span className=\"absolute left-0 top-1/2 h-4 w-0.5 -translate-y-1/2 rounded-r-full bg-[var(--we-accent)]\" />\n              )}\n              {item.icon}\n            </button>\n          );\n        })}\n      </div>\n\n      {contentOpen && (\n        <div\n          className=\"relative flex h-full min-h-0 flex-col\"\n          style={{ width: panelWidth }}\n        >\n          <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-panel-border px-3 py-2\">\n            <TextTitle as=\"h2\" size=\"xs\" className=\"uppercase tracking-wider\">\n              {title}\n            </TextTitle>\n            <IconButton\n              size=\"sm\"\n              variant=\"ghost\"\n              disabled={!isResized}\n              label={t.panel.resetWidth}\n              onClick={() => setPanelWidth(DEFAULT_WIDTH)}\n              className={!isResized ? 'pointer-events-none opacity-30' : ''}\n            >\n              <RotateCcw size={12} />\n            </IconButton>\n          </div>\n\n          <div className=\"min-h-0 flex-1 overflow-hidden\">\n            {activeTab === 'assets' && <AssetPanel />}\n            {activeTab === 'myFiles' && <MyFilesPanel />}\n            {activeTab === 'ai' && <VideoAiToolsPanel />}\n            {activeTab === 'canvas' && (\n              <VideoCanvasPanel\n                canvasZoom={canvasZoom}\n                setCanvasZoom={setCanvasZoom}\n                canvasOffset={canvasOffset}\n                onCanvasZoomIn={onCanvasZoomIn}\n                onCanvasZoomOut={onCanvasZoomOut}\n                onCanvasZoomReset={onCanvasZoomReset}\n                canvasZoomMin={canvasZoomMin}\n                canvasZoomMax={canvasZoomMax}\n                previewQuality={previewQuality}\n                setPreviewQuality={setPreviewQuality}\n              />\n            )}\n          </div>\n\n          <div\n            role=\"separator\"\n            aria-orientation=\"vertical\"\n            aria-label={t.panel.resizeWidth}\n            onMouseDown={onResizeStart}\n            className=\"absolute inset-y-0 right-0 z-10 w-1.5 cursor-ew-resize group/resize\"\n          >\n            <div className=\"absolute inset-y-0 right-0 w-0.5 rounded-l-full bg-transparent transition-colors group-hover/resize:bg-[var(--we-accent-capsule)]\" />\n          </div>\n        </div>\n      )}\n    </aside>\n  );\n};\n\nexport default LeftPanel;\n", "import React, { useMemo, useRef, useState } from 'react';\nimport { Upload, Film, Music, FileVideo, Plus, Sparkles, Trash2 } from 'lucide-react';\nimport { useVideoStore, type Asset } from '../../store/useVideoStore';\nimport { formatFriendlyDuration } from '../../utils/timelineUtils';\nimport { AiImageModal } from './AiImageModal';\nimport { useTranslation } from '../../i18n';\nimport { PanelBody, PanelSection, TextBody } from '../ui';\n\nconst ACCEPT =\n  'video/*,audio/*,image/*,.mp4,.mov,.webm,.mp3,.wav,.aac,.m4a,.ogg,.flac,.png,.jpg,.jpeg,.webp,.gif';\n\ntype AssetFilter = 'all' | 'image' | 'video' | 'audio';\n\nfunction processImageFile(file: File): Promise<Omit<Asset, 'id'>> {\n  return new Promise((resolve, reject) => {\n    const url = URL.createObjectURL(file);\n    const img = new window.Image();\n    img.onload = () => {\n      resolve({\n        name: file.name,\n        url,\n        type: 'image',\n        duration: 5,\n        width: img.naturalWidth,\n        height: img.naturalHeight,\n        file,\n        thumbnail: url,\n      });\n    };\n    img.onerror = () => reject(new Error('Failed to load image'));\n    img.src = url;\n  });\n}\n\nfunction processVideoFile(file: File): Promise<Omit<Asset, 'id'>> {\n  return new Promise((resolve, reject) => {\n    const url = URL.createObjectURL(file);\n    const video = document.createElement('video');\n    video.src = url;\n    video.preload = 'metadata';\n    video.muted = true;\n    video.playsInline = true;\n\n    video.onloadedmetadata = () => {\n      video.currentTime = Math.min(1.0, video.duration / 2);\n    };\n\n    video.onseeked = () => {\n      const canvas = document.createElement('canvas');\n      const vw = video.videoWidth || 160;\n      const vh = video.videoHeight || 90;\n      const maxEdge = 160;\n      const scale = Math.min(1, maxEdge / Math.max(vw, vh));\n      canvas.width = Math.max(1, Math.round(vw * scale));\n      canvas.height = Math.max(1, Math.round(vh * scale));\n      const ctx = canvas.getContext('2d');\n      if (ctx) ctx.drawImage(video, 0, 0, canvas.width, canvas.height);\n      const thumbnailUrl = canvas.toDataURL('image/jpeg');\n      resolve({\n        name: file.name,\n        url,\n        type: 'video',\n        duration: video.duration || 5,\n        width: video.videoWidth,\n        height: video.videoHeight,\n        file,\n        thumbnail: thumbnailUrl,\n      });\n      video.src = '';\n      video.load();\n    };\n\n    video.onerror = () => reject(new Error('Failed to load video metadata'));\n  });\n}\n\nfunction processAudioFile(file: File): Promise<Omit<Asset, 'id'>> {\n  return new Promise((resolve, reject) => {\n    const url = URL.createObjectURL(file);\n    const audio = document.createElement('audio');\n    audio.src = url;\n    audio.preload = 'metadata';\n    audio.onloadedmetadata = () => {\n      resolve({\n        name: file.name,\n        url,\n        type: 'audio',\n        duration: audio.duration || 5,\n        file,\n      });\n    };\n    audio.onerror = () => reject(new Error('Failed to load audio metadata'));\n  });\n}\n\n/**\n * Unified local media library: upload video, image, and audio into one list.\n */\nexport const AssetPanel: React.FC = () => {\n  const t = useTranslation();\n  const tp = t.videoEditor.assetPanel;\n  const fileInputRef = useRef<HTMLInputElement>(null);\n  const [isDragging, setIsDragging] = useState(false);\n  const [isAiImageOpen, setIsAiImageOpen] = useState(false);\n  const [filter, setFilter] = useState<AssetFilter>('all');\n  const { assets, addAsset, removeAsset, addClip, addImageClip, playheadTime, tracks } =\n    useVideoStore();\n\n  // Newest first (addAsset appends; reverse for display).\n  const orderedAssets = useMemo(() => [...assets].reverse(), [assets]);\n  const visibleAssets = useMemo(\n    () =>\n      filter === 'all' ? orderedAssets : orderedAssets.filter((a) => a.type === filter),\n    [orderedAssets, filter],\n  );\n\n  const filterOptions: { id: AssetFilter; label: string }[] = [\n    { id: 'all', label: tp.filterAll },\n    { id: 'image', label: tp.filterImage },\n    { id: 'video', label: tp.filterVideo },\n    { id: 'audio', label: tp.filterAudio },\n  ];\n\n  const processFile = async (file: File): Promise<Omit<Asset, 'id'> | null> => {\n    const extension = file.name.split('.').pop()?.toLowerCase() || '';\n    const videoExt = ['mp4', 'mov', 'avi', 'mkv', 'webm', 'm4v'];\n    const audioExt = ['mp3', 'wav', 'aac', 'm4a', 'ogg', 'flac'];\n    const imageExt = ['png', 'jpg', 'jpeg', 'webp', 'gif', 'bmp', 'avif'];\n\n    const isVideo = file.type.startsWith('video/') || videoExt.includes(extension);\n    const isAudio = file.type.startsWith('audio/') || audioExt.includes(extension);\n    const isImage = file.type.startsWith('image/') || imageExt.includes(extension);\n\n    if (isImage) return processImageFile(file);\n    if (isVideo) return processVideoFile(file);\n    if (isAudio) return processAudioFile(file);\n    return null;\n  };\n\n  const handleFiles = async (fileList: FileList) => {\n    for (let i = 0; i < fileList.length; i++) {\n      const file = fileList[i];\n      if (!file) continue;\n      try {\n        const assetData = await processFile(file);\n        if (!assetData) continue;\n        addAsset({\n          ...assetData,\n          id: `asset_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,\n        });\n      } catch (err) {\n        console.error('Error importing file:', err);\n      }\n    }\n  };\n\n  const ensureTrack = (type: 'video' | 'audio' | 'image') => {\n    let track = tracks.find((tr) => tr.type === type);\n    if (!track) {\n      const name =\n        type === 'video' ? 'Video 1' : type === 'audio' ? 'Audio 1' : 'Image 1';\n      useVideoStore.getState().addTrack(name, type);\n      track = useVideoStore.getState().tracks.find((tr) => tr.type === type);\n    }\n    return track?.id ?? (type === 'image' ? 'i1' : type === 'video' ? 'v1' : 'a1');\n  };\n\n  const handleDoubleClickAsset = (asset: Asset) => {\n    if (asset.type === 'image') {\n      const trackId = ensureTrack('image');\n      addImageClip({\n        trackId,\n        assetId: asset.id,\n        startTime: playheadTime,\n        duration: asset.duration || 5,\n        trimIn: 0,\n        trimOut: 0,\n        speed: 1,\n        volume: 1,\n        opacity: 1,\n        muted: false,\n      });\n      return;\n    }\n\n    const type = asset.type === 'video' ? 'video' : 'audio';\n    const trackId = ensureTrack(type);\n    addClip(trackId, {\n      trackId,\n      assetId: asset.id,\n      startTime: playheadTime,\n      duration: asset.duration,\n      trimIn: 0,\n      trimOut: 0,\n      speed: 1,\n      volume: 1,\n      opacity: 1,\n      muted: false,\n      type: asset.type,\n    });\n  };\n\n  return (\n    <div className=\"flex h-full min-h-0 w-full flex-col overflow-hidden bg-panel\">\n      <div className=\"flex shrink-0 items-center justify-end gap-1 border-b border-panel-border px-2 py-1.5\">\n        <button\n          type=\"button\"\n          onClick={() => setIsAiImageOpen(true)}\n          className=\"cursor-pointer rounded-lg p-1.5 text-[var(--we-accent)] transition-colors hover:bg-[var(--we-accent-muted)] hover:text-white\"\n          title={tp.aiBrollTitle}\n        >\n          <Sparkles size={13} />\n        </button>\n        <button\n          type=\"button\"\n          onClick={() => fileInputRef.current?.click()}\n          className=\"cursor-pointer rounded-lg p-1.5 text-white/80 transition-colors hover:bg-black-capsule hover:text-[var(--we-accent)]\"\n          title={tp.importMediaTitle}\n        >\n          <Plus size={14} />\n        </button>\n        <input\n          type=\"file\"\n          ref={fileInputRef}\n          onChange={(e) => {\n            if (e.target.files) void handleFiles(e.target.files);\n            e.target.value = '';\n          }}\n          multiple\n          accept={ACCEPT}\n          className=\"hidden\"\n        />\n      </div>\n\n      <PanelBody className=\"min-h-0 flex-1 overflow-y-auto\">\n        <div\n          role=\"button\"\n          tabIndex={0}\n          onDragOver={(e) => {\n            e.preventDefault();\n            setIsDragging(true);\n          }}\n          onDragLeave={() => setIsDragging(false)}\n          onDrop={(e) => {\n            e.preventDefault();\n            setIsDragging(false);\n            if (e.dataTransfer.files) void handleFiles(e.dataTransfer.files);\n          }}\n          onClick={() => fileInputRef.current?.click()}\n          onKeyDown={(e) => {\n            if (e.key === 'Enter' || e.key === ' ') fileInputRef.current?.click();\n          }}\n          className={`flex cursor-pointer flex-col items-center justify-center rounded-xl border border-dashed px-3 py-5 text-center transition-all ${\n            isDragging\n              ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)] text-white'\n              : 'border-panel-border bg-black-capsule/40 text-white/80 hover:border-[var(--we-accent)]/40'\n          }`}\n        >\n          <Upload size={20} className=\"mb-2 text-[var(--we-accent)]\" />\n          <TextBody as=\"span\" size=\"sm\">\n            {tp.dragDrop}\n          </TextBody>\n          <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 text-white/80\">\n            {tp.supports}\n          </TextBody>\n        </div>\n\n        <div\n          role=\"tablist\"\n          aria-label={tp.filterAria}\n          className=\"flex gap-1 rounded-xl bg-black-capsule p-0.5\"\n        >\n          {filterOptions.map((opt) => {\n            const active = filter === opt.id;\n            return (\n              <button\n                key={opt.id}\n                type=\"button\"\n                role=\"tab\"\n                aria-selected={active}\n                onClick={() => setFilter(opt.id)}\n                className={`flex-1 cursor-pointer rounded-lg px-1.5 py-1.5 transition-colors ${\n                  active\n                    ? 'bg-[var(--we-accent-capsule)] text-white'\n                    : 'text-white/80 hover:text-white'\n                }`}\n              >\n                <TextBody as=\"span\" size=\"sm\" className=\"font-bold uppercase tracking-wide\">\n                  {opt.label}\n                </TextBody>\n              </button>\n            );\n          })}\n        </div>\n\n        <PanelSection title={tp.libraryTitle(visibleAssets.length)}>\n          {assets.length === 0 ? (\n            <div className=\"flex flex-col items-center justify-center py-10 text-center\">\n              <Film size={24} className=\"mb-2 opacity-30\" />\n              <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                {tp.libraryEmpty}\n              </TextBody>\n              <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 opacity-70 text-white/80\">\n                {tp.importMediaHint}\n              </TextBody>\n            </div>\n          ) : visibleAssets.length === 0 ? (\n            <TextBody as=\"p\" size=\"sm\" className=\"py-8 text-center text-white/80\">\n              {tp.emptyFilter}\n            </TextBody>\n          ) : (\n            <div className=\"flex flex-col gap-1.5\">\n              {visibleAssets.map((asset) => (\n                <div\n                  key={asset.id}\n                  onDoubleClick={() => handleDoubleClickAsset(asset)}\n                  className=\"group relative flex cursor-pointer select-none gap-2 rounded-xl border border-panel-border bg-black-capsule p-1.5 transition-colors hover:bg-black-capsule-hover\"\n                  title={tp.doubleClickHint}\n                >\n                  <div className=\"relative flex h-10 w-16 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-black/60\">\n                    {asset.type === 'image' ? (\n                      <img\n                        src={asset.thumbnail || asset.url}\n                        className=\"max-h-full max-w-full object-contain\"\n                        alt={tp.altAiBroll}\n                      />\n                    ) : asset.type === 'video' && asset.thumbnail ? (\n                      <img\n                        src={asset.thumbnail}\n                        className=\"max-h-full max-w-full object-contain\"\n                        alt={tp.altThumbnail}\n                      />\n                    ) : asset.type === 'video' ? (\n                      <FileVideo size={16} className=\"text-[var(--we-accent)]\" />\n                    ) : (\n                      <Music size={16} className=\"text-teal-400\" />\n                    )}\n                    <TextBody\n                      as=\"span\"\n                      size=\"sm\"\n                      className=\"absolute bottom-0.5 right-0.5 rounded bg-black/80 px-0.5 py-px font-mono text-white\"\n                    >\n                      {formatFriendlyDuration(asset.duration)}\n                    </TextBody>\n                  </div>\n\n                  <div className=\"flex min-w-0 flex-1 flex-col justify-center\">\n                    <TextBody as=\"span\" size=\"sm\" className=\"block truncate text-white\">\n                      {asset.name}\n                    </TextBody>\n                    <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 block uppercase text-white/80\">\n                      {asset.type}\n                      {asset.width ? ` \u00B7 ${asset.width}\u00D7${asset.height}` : ''}\n                    </TextBody>\n                  </div>\n\n                  <button\n                    type=\"button\"\n                    onClick={(e) => {\n                      e.stopPropagation();\n                      removeAsset(asset.id);\n                    }}\n                    className=\"absolute right-1.5 top-1.5 cursor-pointer rounded p-0.5 text-white opacity-0 transition-opacity hover:bg-red-600 group-hover:opacity-100\"\n                    title={tp.removeAssetTitle}\n                  >\n                    <Trash2 size={11} />\n                  </button>\n                </div>\n              ))}\n            </div>\n          )}\n        </PanelSection>\n      </PanelBody>\n\n      <AiImageModal isOpen={isAiImageOpen} onClose={() => setIsAiImageOpen(false)} />\n    </div>\n  );\n};\n", "import React, { useState } from 'react';\nimport { Modal } from '../ui/Modal';\nimport { Button } from '../ui/Button';\nimport { Sparkles, Loader, Plus, Download } from 'lucide-react';\nimport { useVideoStore, type Asset } from '../../store/useVideoStore';\nimport { generateImageFromGemini } from '../../services/aiService';\nimport { useTranslation } from '../../i18n';\nimport { TextBody } from '../ui';\n\n\ninterface AiImageModalProps {\n  isOpen: boolean;\n  onClose: () => void;\n}\n\nexport const AiImageModal: React.FC<AiImageModalProps> = ({ isOpen, onClose }) => {\n  const t = useTranslation();\n  const { addAsset, addClip, playheadTime, tracks } = useVideoStore();\n  const [prompt, setPrompt] = useState('');\n  const [isGenerating, setIsGenerating] = useState(false);\n  const [generatedBlob, setGeneratedBlob] = useState<Blob | null>(null);\n  const [previewUrl, setPreviewUrl] = useState<string | null>(null);\n  const [error, setError] = useState<string | null>(null);\n  const [loadingText, setLoadingText] = useState(t.aiImage.loadingInitial);\n\n  const handleGenerate = async () => {\n    if (!prompt.trim()) return;\n\n    setIsGenerating(true);\n    setError(null);\n    setGeneratedBlob(null);\n    if (previewUrl) {\n      URL.revokeObjectURL(previewUrl);\n      setPreviewUrl(null);\n    }\n\n    const texts = t.aiImage.loadingSteps;\n    setLoadingText(texts[0] ?? t.aiImage.loadingInitial);\n\n    let step = 0;\n    const textInterval = setInterval(() => {\n      if (step < texts.length - 1) {\n        step++;\n        setLoadingText(texts[step]);\n      }\n    }, 1200);\n\n    try {\n      const blob = await generateImageFromGemini(prompt);\n      const url = URL.createObjectURL(blob);\n      setGeneratedBlob(blob);\n      setPreviewUrl(url);\n    } catch (err: any) {\n      console.error(err);\n      setError(err.message || t.aiImage.unknownError);\n    } finally {\n      clearInterval(textInterval);\n      setIsGenerating(false);\n    }\n  };\n\n  const handleAddToTimeline = () => {\n    if (!generatedBlob || !previewUrl) return;\n\n    // 1. Create native File from Blob\n    const filename = `ai_broll_${Date.now()}.png`;\n    const file = new File([generatedBlob], filename, { type: 'image/png' });\n\n    // 2. Register asset in global library\n    const assetId = `asset_ai_${Date.now()}`;\n    const newAsset: Asset = {\n      id: assetId,\n      name: filename,\n      url: previewUrl,\n      type: 'image',\n      duration: 5.0, // Default duration for image overlays\n      width: 1024,\n      height: 1024,\n      file: file,\n      thumbnail: previewUrl\n    };\n    addAsset(newAsset);\n\n    // 3. Find or create an 'image' track in the timeline\n    let imageTrack = tracks.find((t) => t.type === 'image');\n    if (!imageTrack) {\n      useVideoStore.getState().addTrack('AI B-Roll Overlays', 'image');\n      // Re-fetch to get updated state\n      imageTrack = useVideoStore.getState().tracks.find((t) => t.type === 'image');\n    }\n    const targetTrackId = imageTrack ? imageTrack.id : 'image_track_default';\n\n    // 4. Add clip to timeline at current playhead position\n    addClip(targetTrackId, {\n      trackId: targetTrackId,\n      assetId: assetId,\n      startTime: playheadTime,\n      duration: 5.0,\n      trimIn: 0,\n      trimOut: 0,\n      speed: 1.0,\n      volume: 1.0,\n      opacity: 1.0,\n      muted: false,\n      type: 'image',\n      name: filename\n    });\n\n    onClose();\n  };\n\n  const handleDownload = () => {\n    if (!previewUrl) return;\n    const a = document.createElement('a');\n    a.href = previewUrl;\n    a.download = `gemini_broll_${Date.now()}.png`;\n    document.body.appendChild(a);\n    a.click();\n    document.body.removeChild(a);\n  };\n\n  return (\n    <Modal isOpen={isOpen} onClose={onClose} title={t.aiImage.title} size=\"lg\">\n      <div className=\"space-y-5\">\n        {/* Prompt Input area */}\n        <div className=\"space-y-2\">\n          <TextBody as=\"label\" size=\"sm\" className=\"text-[#8888A0] uppercase tracking-wider block\">\n            {t.aiImage.promptLabel}\n          </TextBody>\n          <textarea\n            value={prompt}\n            onChange={(e) => setPrompt(e.target.value)}\n            disabled={isGenerating}\n            placeholder={t.aiImage.promptPlaceholder}\n            className=\"w-full h-24 bg-[#0A0A0F]/80 border border-[#2A2A38] rounded-lg p-3 text-xs text-[#F0F0F5] placeholder-[#8888A0]/60 focus:outline-none focus:border-[var(--we-accent)] transition-all resize-none disabled:opacity-50\"\n          />\n        </div>\n\n        {/* Action Buttons */}\n        <div className=\"flex justify-end gap-2\">\n          <Button variant=\"ghost\" onClick={onClose} disabled={isGenerating}>\n            <TextBody as=\"span\" size=\"sm\">{t.common.cancel}</TextBody>\n          </Button>\n          <Button\n            onClick={handleGenerate}\n            disabled={isGenerating || !prompt.trim()}\n            className=\"bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] disabled:opacity-50 text-white flex items-center gap-1.5\"\n          >\n            {isGenerating ? (\n              <>\n                <Loader size={14} className=\"animate-spin\" />\n                <TextBody as=\"span\" size=\"sm\">{t.aiImage.generating}</TextBody>\n              </>\n            ) : (\n              <>\n                <Sparkles size={14} />\n                <TextBody as=\"span\" size=\"sm\">{t.aiImage.generate}</TextBody>\n              </>\n            )}\n          </Button>\n        </div>\n\n        {/* Error Message */}\n        {error && (\n          <div className=\"rounded-lg border border-red-900/40 bg-red-950/40 p-3\">\n            <TextBody as=\"p\" size=\"sm\" className=\"text-red-200\">\n              {error}\n            </TextBody>\n          </div>\n        )}\n\n        {/* Loading State or Preview Area */}\n        {(isGenerating || previewUrl) && (\n          <div className=\"border border-[#2A2A38] rounded-lg bg-[#0A0A0F]/50 overflow-hidden flex flex-col items-center justify-center min-h-[320px] relative\">\n            {isGenerating ? (\n              <div className=\"flex flex-col items-center justify-center p-8 space-y-3\">\n                <div className=\"relative w-12 h-12 flex items-center justify-center\">\n                  <div className=\"absolute inset-0 rounded-full border-4 border-[var(--we-accent)]/20 border-t-[var(--we-accent)] animate-spin\" />\n                  <Sparkles className=\"text-[var(--we-accent)] animate-pulse\" size={18} />\n                </div>\n                <TextBody as=\"span\" size=\"sm\" className=\"text-[#F0F0F5]\">{loadingText}</TextBody>\n                <TextBody as=\"span\" size=\"sm\" className=\"text-[#8888A0]\">{t.aiImage.firstRenderHint}</TextBody>\n              </div>\n            ) : previewUrl ? (\n              <div className=\"w-full flex flex-col\">\n                <div className=\"flex-1 bg-black/60 flex items-center justify-center p-4\">\n                  <img\n                    src={previewUrl}\n                    alt={t.aiImage.previewAlt}\n                    className=\"max-h-[300px] object-contain rounded border border-[#2A2A38] shadow-2xl\"\n                  />\n                </div>\n                \n                {/* Actions on generated image */}\n                <div className=\"p-3 bg-[#13131A] border-t border-[#2A2A38] flex justify-between items-center\">\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-[#8888A0] font-mono\">1024x1024 PNG</TextBody>\n                  <div className=\"flex gap-2\">\n                    <Button variant=\"ghost\" onClick={handleDownload} className=\"text-xs flex items-center gap-1\">\n                      <Download size={12} />\n                      <TextBody as=\"span\" size=\"sm\">{t.aiImage.saveImage}</TextBody>\n                    </Button>\n                    <Button onClick={handleAddToTimeline} className=\"text-xs flex items-center gap-1 bg-[#00E676] hover:bg-[#00C853] text-black font-semibold\">\n                      <Plus size={12} />\n                      <TextBody as=\"span\" size=\"sm\">{t.aiImage.addBroll}</TextBody>\n                    </Button>\n                  </div>\n                </div>\n              </div>\n            ) : null}\n          </div>\n        )}\n      </div>\n    </Modal>\n  );\n};\n", "import React, { useEffect, useState } from 'react';\nimport { FileVideo, Image as ImageIcon, Loader2, Music, RefreshCw } from 'lucide-react';\nimport {\n  fetchRemoteMediaAsFile,\n  listMediaJobsWithS3,\n  type FileMediaItem,\n  type FileMediaKind,\n} from '../../services/imageJobsService';\nimport { useVideoStore, type Asset } from '../../store/useVideoStore';\nimport { useTranslation } from '../../i18n';\nimport { IconButton, PanelBody, PanelSection, TextBody } from '../ui';\n\nfunction extForKind(kind: FileMediaKind): string {\n  if (kind === 'video') return 'mp4';\n  if (kind === 'audio') return 'mp3';\n  return 'png';\n}\n\nfunction mimeForKind(kind: FileMediaKind): string {\n  if (kind === 'video') return 'video/mp4';\n  if (kind === 'audio') return 'audio/mpeg';\n  return 'image/png';\n}\n\nfunction readImageSize(url: string): Promise<{ width: number; height: number }> {\n  return new Promise((resolve) => {\n    const img = new window.Image();\n    img.onload = () => {\n      const finish = () =>\n        resolve({ width: img.naturalWidth || 0, height: img.naturalHeight || 0 });\n      if (typeof img.decode === 'function') {\n        void img.decode().then(finish).catch(finish);\n      } else {\n        finish();\n      }\n    };\n    img.onerror = () => resolve({ width: 0, height: 0 });\n    img.src = url;\n  });\n}\n\nfunction readVideoMeta(url: string): Promise<{ duration: number; width: number; height: number; thumb?: string }> {\n  return new Promise((resolve) => {\n    const video = document.createElement('video');\n    video.preload = 'metadata';\n    video.muted = true;\n    video.playsInline = true;\n    video.src = url;\n    video.onloadedmetadata = () => {\n      const duration = Number.isFinite(video.duration) ? video.duration : 5;\n      const width = video.videoWidth || 0;\n      const height = video.videoHeight || 0;\n      const seekTo = Math.min(1, duration / 2);\n      const finish = (thumb?: string) => {\n        resolve({ duration, width, height, thumb });\n        video.src = '';\n        video.load();\n      };\n      video.onseeked = () => {\n        try {\n          const canvas = document.createElement('canvas');\n          const vw = width || 160;\n          const vh = height || 90;\n          const maxEdge = 160;\n          const scale = Math.min(1, maxEdge / Math.max(vw, vh));\n          canvas.width = Math.max(1, Math.round(vw * scale));\n          canvas.height = Math.max(1, Math.round(vh * scale));\n          const ctx = canvas.getContext('2d');\n          if (ctx) ctx.drawImage(video, 0, 0, canvas.width, canvas.height);\n          finish(canvas.toDataURL('image/jpeg'));\n        } catch {\n          finish();\n        }\n      };\n      video.onerror = () => finish();\n      try {\n        video.currentTime = seekTo;\n      } catch {\n        finish();\n      }\n    };\n    video.onerror = () => resolve({ duration: 5, width: 0, height: 0 });\n  });\n}\n\nfunction readAudioDuration(url: string): Promise<number> {\n  return new Promise((resolve) => {\n    const audio = document.createElement('audio');\n    audio.preload = 'metadata';\n    audio.src = url;\n    audio.onloadedmetadata = () => {\n      resolve(Number.isFinite(audio.duration) ? audio.duration : 5);\n      audio.src = '';\n      audio.load();\n    };\n    audio.onerror = () => resolve(5);\n  });\n}\n\n/**\n * Cloud / AI jobs (image + video + audio) for adding media onto the timeline.\n */\nexport const MyFilesPanel: React.FC = () => {\n  const t = useTranslation();\n  const tp = t.videoEditor.myFilesPanel;\n  const { addAsset, addClip, addImageClip, playheadTime, tracks, assets } = useVideoStore();\n  const [items, setItems] = useState<FileMediaItem[]>([]);\n  const [filter, setFilter] = useState<'all' | FileMediaKind>('all');\n  const [loading, setLoading] = useState(true);\n  const [addingId, setAddingId] = useState<string | null>(null);\n  const [error, setError] = useState<string | null>(null);\n\n  const load = async (signal?: AbortSignal) => {\n    setLoading(true);\n    setError(null);\n    try {\n      const rows = await listMediaJobsWithS3({ signal });\n      if (!signal?.aborted) setItems(rows);\n    } catch {\n      if (!signal?.aborted) {\n        setItems([]);\n        setError(tp.loadError);\n      }\n    } finally {\n      if (!signal?.aborted) setLoading(false);\n    }\n  };\n\n  useEffect(() => {\n    const ac = new AbortController();\n    void load(ac.signal);\n    return () => ac.abort();\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  const ensureTrack = (type: 'video' | 'image' | 'audio') => {\n    let track = tracks.find((tr) => tr.type === type);\n    if (!track) {\n      const name =\n        type === 'video' ? 'Video 1' : type === 'audio' ? 'Audio 1' : 'Image 1';\n      useVideoStore.getState().addTrack(name, type);\n      track = useVideoStore.getState().tracks.find((tr) => tr.type === type);\n    }\n    return track?.id ?? (type === 'image' ? 'i1' : type === 'audio' ? 'a1' : 'v1');\n  };\n\n  const addToTimeline = async (item: FileMediaItem) => {\n    setAddingId(item.id);\n    try {\n      const safeName = `${item.name.replace(/[^\\w.\\-]+/g, '_').slice(0, 40)}.${extForKind(item.kind)}`;\n      const downloaded = await fetchRemoteMediaAsFile(\n        item.url,\n        safeName,\n        mimeForKind(item.kind),\n      );\n      if (!downloaded) throw new Error(tp.fetchError);\n\n      // Always use the downloaded blob URL so intrinsic W\u00D7H are reliable (no remote CORS/layout collapse).\n      const objectUrl = downloaded.objectUrl;\n\n      const existing = assets.find(\n        (a) => a.remoteUrl === item.url || a.url === item.url,\n      );\n      let assetId = existing?.id;\n\n      if (!assetId) {\n        if (item.kind === 'image') {\n          const size = await readImageSize(objectUrl);\n          if (!size.width || !size.height) {\n            throw new Error(tp.fetchError);\n          }\n          const asset: Asset = {\n            id: `job_img_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,\n            name: item.name,\n            url: objectUrl,\n            type: 'image',\n            duration: 5,\n            width: size.width,\n            height: size.height,\n            file: downloaded.file,\n            thumbnail: objectUrl,\n            remoteUrl: item.url,\n          };\n          addAsset(asset);\n          assetId = asset.id;\n        } else if (item.kind === 'audio') {\n          const duration = await readAudioDuration(objectUrl);\n          const asset: Asset = {\n            id: `job_aud_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,\n            name: item.name,\n            url: objectUrl,\n            type: 'audio',\n            duration: duration || 5,\n            file: downloaded.file,\n            remoteUrl: item.url,\n          };\n          addAsset(asset);\n          assetId = asset.id;\n        } else {\n          const meta = await readVideoMeta(objectUrl);\n          const asset: Asset = {\n            id: `job_vid_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,\n            name: item.name,\n            url: objectUrl,\n            type: 'video',\n            duration: meta.duration || 5,\n            width: meta.width,\n            height: meta.height,\n            file: downloaded.file,\n            thumbnail: meta.thumb,\n            remoteUrl: item.url,\n          };\n          addAsset(asset);\n          assetId = asset.id;\n        }\n      }\n\n      if (item.kind === 'image') {\n        const trackId = ensureTrack('image');\n        addImageClip({\n          trackId,\n          assetId: assetId!,\n          startTime: playheadTime,\n          duration: 5,\n          trimIn: 0,\n          trimOut: 0,\n          speed: 1,\n          volume: 1,\n          opacity: 1,\n          muted: false,\n        });\n      } else if (item.kind === 'audio') {\n        const trackId = ensureTrack('audio');\n        const asset = useVideoStore.getState().assets.find((a) => a.id === assetId);\n        addClip(trackId, {\n          trackId,\n          assetId: assetId!,\n          startTime: playheadTime,\n          duration: asset?.duration || 5,\n          trimIn: 0,\n          trimOut: 0,\n          speed: 1,\n          volume: 1,\n          opacity: 1,\n          muted: false,\n          type: 'audio',\n        });\n      } else {\n        const trackId = ensureTrack('video');\n        const asset = useVideoStore.getState().assets.find((a) => a.id === assetId);\n        addClip(trackId, {\n          trackId,\n          assetId: assetId!,\n          startTime: playheadTime,\n          duration: asset?.duration || 5,\n          trimIn: 0,\n          trimOut: 0,\n          speed: 1,\n          volume: 1,\n          opacity: 1,\n          muted: false,\n          type: 'video',\n        });\n      }\n    } catch (err) {\n      console.error(err);\n      setError(err instanceof Error ? err.message : tp.fetchError);\n    } finally {\n      setAddingId(null);\n    }\n  };\n\n  const kindIcon = (kind: FileMediaKind) => {\n    if (kind === 'image') return <ImageIcon size={10} className=\"shrink-0 text-white/80\" />;\n    if (kind === 'audio') return <Music size={10} className=\"shrink-0 text-teal-300\" />;\n    return <FileVideo size={10} className=\"shrink-0 text-white/80\" />;\n  };\n\n  const filterOptions: { id: 'all' | FileMediaKind; label: string }[] = [\n    { id: 'all', label: tp.filterAll },\n    { id: 'image', label: tp.filterImage },\n    { id: 'video', label: tp.filterVideo },\n    { id: 'audio', label: tp.filterAudio },\n  ];\n\n  const visibleItems =\n    filter === 'all' ? items : items.filter((item) => item.kind === filter);\n\n  return (\n    <div className=\"flex h-full min-h-0 w-full flex-col overflow-hidden bg-panel\">\n      <div className=\"flex shrink-0 items-center justify-end border-b border-panel-border px-2 py-1.5\">\n        <IconButton\n          size=\"sm\"\n          variant=\"ghost\"\n          label={tp.refresh}\n          disabled={loading}\n          onClick={() => void load()}\n        >\n          <RefreshCw size={12} className={loading ? 'animate-spin' : ''} />\n        </IconButton>\n      </div>\n\n      <PanelBody className=\"min-h-0 flex-1 overflow-y-auto\">\n        <div\n          role=\"tablist\"\n          aria-label={tp.filterAria}\n          className=\"flex gap-1 rounded-xl bg-black-capsule p-0.5\"\n        >\n          {filterOptions.map((opt) => {\n            const active = filter === opt.id;\n            return (\n              <button\n                key={opt.id}\n                type=\"button\"\n                role=\"tab\"\n                aria-selected={active}\n                onClick={() => setFilter(opt.id)}\n                className={`flex-1 cursor-pointer rounded-lg px-1.5 py-1.5 uppercase tracking-wide transition-colors ${\n                  active\n                    ? 'bg-[var(--we-accent-capsule)] text-white'\n                    : 'text-white/80 hover:text-white'\n                }`}\n              >\n                <TextBody as=\"span\" size=\"sm\" className=\"font-bold uppercase\">\n                  {opt.label}\n                </TextBody>\n              </button>\n            );\n          })}\n        </div>\n\n        <PanelSection title={tp.jobsHeader} description={tp.hint}>\n          {loading ? (\n            <div\n              className=\"grid grid-cols-2 gap-2\"\n              aria-busy\n              aria-label={tp.loading}\n            >\n              {Array.from({ length: 8 }).map((_, i) => (\n                <div\n                  key={i}\n                  className=\"aspect-video animate-pulse rounded-xl border border-panel-border bg-black-capsule\"\n                />\n              ))}\n            </div>\n          ) : items.length === 0 ? (\n            <TextBody as=\"p\" size=\"sm\" className=\"py-8 text-center text-white/80\">\n              {error || tp.empty}\n            </TextBody>\n          ) : visibleItems.length === 0 ? (\n            <TextBody as=\"p\" size=\"sm\" className=\"py-8 text-center text-white/80\">\n              {tp.emptyFilter}\n            </TextBody>\n          ) : (\n            <div className=\"grid grid-cols-2 gap-2\">\n              {visibleItems.map((item) => {\n                const busy = addingId === item.id;\n                return (\n                  <button\n                    key={`${item.kind}-${item.id}`}\n                    type=\"button\"\n                    disabled={busy}\n                    title={tp.addHint}\n                    onClick={() => void addToTimeline(item)}\n                    className=\"group relative aspect-video cursor-pointer overflow-hidden rounded-xl border border-panel-border bg-black-capsule transition-colors hover:border-[var(--we-accent)]/50 disabled:opacity-60\"\n                  >\n                    {item.kind === 'image' ? (\n                      <img\n                        src={item.url}\n                        alt={item.name}\n                        className=\"h-full w-full object-cover transition-transform group-hover:scale-105\"\n                      />\n                    ) : (\n                      <div className=\"flex h-full w-full flex-col items-center justify-center gap-1.5 bg-panel\">\n                        <span className=\"flex h-10 w-10 items-center justify-center rounded-xl bg-[var(--we-accent-capsule)]\">\n                          {item.kind === 'audio' ? (\n                            <Music size={20} className=\"text-[var(--we-accent)]\" />\n                          ) : (\n                            <FileVideo size={20} className=\"text-[var(--we-accent)]\" />\n                          )}\n                        </span>\n                        <TextBody as=\"span\" size=\"sm\" className=\"max-w-[90%] truncate px-1 text-white\">\n                          {item.kind === 'audio'\n                            ? item.category?.trim() || item.name\n                            : item.name}\n                        </TextBody>\n                      </div>\n                    )}\n                    <div className=\"absolute inset-x-0 bottom-0 flex items-center justify-between gap-1 bg-black-capsule px-1.5 py-1.5\">\n                      <TextBody as=\"span\" size=\"sm\" className=\"truncate text-white\">\n                        {item.kind === 'audio'\n                          ? item.category?.trim() || item.name\n                          : item.name}\n                      </TextBody>\n                      {kindIcon(item.kind)}\n                    </div>\n                    {busy && (\n                      <div className=\"absolute inset-0 flex items-center justify-center bg-black/50\">\n                        <Loader2 size={16} className=\"animate-spin text-white\" />\n                      </div>\n                    )}\n                  </button>\n                );\n              })}\n            </div>\n          )}\n        </PanelSection>\n      </PanelBody>\n    </div>\n  );\n};\n\nexport default MyFilesPanel;\n", "import React, { useEffect, useState } from 'react';\nimport { RotateCcw, ZoomIn, ZoomOut } from 'lucide-react';\nimport { useVideoStore, type VideoProject } from '../../store/useVideoStore';\nimport { useTranslation, type Messages } from '../../i18n';\nimport { dimensionsForAspect } from '../../utils/videoCanvasSize';\nimport { IconButton, PanelBody, PanelField, PanelSection, SelectDropdown, Switch, TextBody } from '../ui';\n\ntype Aspect = VideoProject['aspectRatio'];\n\nconst ASPECT_OPTIONS: Aspect[] = ['16:9', '9:16', '1:1', '4:3', '3:4', '21:9'];\n\nconst SIZE_PRESETS: {\n  id: string;\n  aspect: Aspect;\n  width: number;\n  height: number;\n  label: (tp: Messages['videoEditor']['canvasPanel']) => string;\n}[] = [\n  { id: '1080-16x9', aspect: '16:9', width: 1920, height: 1080, label: (tp) => tp.size1080p },\n  { id: '720-16x9', aspect: '16:9', width: 1280, height: 720, label: (tp) => tp.size720p },\n  { id: '1080-9x16', aspect: '9:16', width: 1080, height: 1920, label: (tp) => tp.sizeVertical1080 },\n  { id: '1080-1x1', aspect: '1:1', width: 1080, height: 1080, label: (tp) => tp.sizeSquare1080 },\n  { id: '1080-4x3', aspect: '4:3', width: 1440, height: 1080, label: (tp) => tp.size4x3 },\n  { id: '1080-3x4', aspect: '3:4', width: 1080, height: 1440, label: (tp) => tp.size3x4 },\n  { id: '1080-21x9', aspect: '21:9', width: 2560, height: 1080, label: (tp) => tp.sizeUltrawide },\n  { id: 'custom', aspect: '16:9', width: 0, height: 0, label: (tp) => tp.sizeCustom },\n];\n\nexport interface VideoCanvasPanelProps {\n  canvasZoom: number;\n  setCanvasZoom: (z: number) => void;\n  canvasOffset: { x: number; y: number };\n  onCanvasZoomIn: () => void;\n  onCanvasZoomOut: () => void;\n  onCanvasZoomReset: () => void;\n  canvasZoomMin: number;\n  canvasZoomMax: number;\n  previewQuality: number;\n  setPreviewQuality: (q: number) => void;\n}\n\n/**\n * Left-dock \"Canvas\" tool: aspect / size / preview quality + view zoom.\n */\nexport const VideoCanvasPanel: React.FC<VideoCanvasPanelProps> = ({\n  canvasZoom,\n  setCanvasZoom,\n  canvasOffset,\n  onCanvasZoomIn,\n  onCanvasZoomOut,\n  onCanvasZoomReset,\n  canvasZoomMin,\n  canvasZoomMax,\n  previewQuality,\n  setPreviewQuality,\n}) => {\n  const t = useTranslation();\n  const tp = t.videoEditor.canvasPanel;\n  const {\n    aspectRatio,\n    setAspectRatio,\n    canvasWidth,\n    canvasHeight,\n    setCanvasSize,\n    snapEnabled,\n    setSnapEnabled,\n  } = useVideoStore();\n  const canResetZoom = canvasZoom !== 1 || canvasOffset.x !== 0 || canvasOffset.y !== 0;\n\n  const matchingPreset = SIZE_PRESETS.find(\n    (p) =>\n      p.id !== 'custom' &&\n      p.width === canvasWidth &&\n      p.height === canvasHeight,\n  );\n  const activeSizeId = matchingPreset?.id ?? 'custom';\n\n  const [widthDraft, setWidthDraft] = useState(String(canvasWidth));\n  const [heightDraft, setHeightDraft] = useState(String(canvasHeight));\n\n  useEffect(() => {\n    setWidthDraft(String(canvasWidth));\n    setHeightDraft(String(canvasHeight));\n  }, [canvasWidth, canvasHeight]);\n\n  const commitCustomSize = () => {\n    const w = Number.parseInt(widthDraft, 10);\n    const h = Number.parseInt(heightDraft, 10);\n    if (!Number.isFinite(w) || !Number.isFinite(h)) {\n      setWidthDraft(String(canvasWidth));\n      setHeightDraft(String(canvasHeight));\n      return;\n    }\n    setCanvasSize(w, h);\n  };\n\n  const aspectSelectOptions = ASPECT_OPTIONS.map((value) => ({\n    value,\n    label: tp.aspectLabels[value] ?? value,\n  }));\n\n  const sizeSelectOptions = SIZE_PRESETS.map((p) => ({\n    value: p.id,\n    label:\n      p.id === 'custom'\n        ? p.label(tp)\n        : `${p.label(tp)} \u00B7 ${p.width}\u00D7${p.height}`,\n  }));\n\n  return (\n    <div className=\"flex h-full min-h-0 w-full flex-col overflow-hidden bg-panel\">\n      <PanelBody className=\"min-h-0 flex-1 overflow-y-auto\">\n        <PanelSection title={tp.aspectSection} description={tp.aspectHint}>\n          <PanelField\n            label={tp.aspectLabel}\n            trailing={\n              <SelectDropdown\n                value={aspectRatio}\n                options={aspectSelectOptions}\n                onChange={(v) => setAspectRatio(v as Aspect)}\n                ariaLabel={tp.aspectLabel}\n              />\n            }\n          />\n          <PanelField\n            label={tp.sizeLabel}\n            trailing={\n              <SelectDropdown\n                value={activeSizeId}\n                options={sizeSelectOptions}\n                onChange={(id) => {\n                  if (id === 'custom') return;\n                  const preset = SIZE_PRESETS.find((p) => p.id === id);\n                  if (!preset) return;\n                  // Only setCanvasSize \u2014 setAspectRatio() always forces the\n                  // default tier for that ratio (16:9 \u2192 1920\u00D71080), which\n                  // overwrote 720p before setCanvasSize could run.\n                  setCanvasSize(preset.width, preset.height);\n                }}\n                ariaLabel={tp.sizeLabel}\n              />\n            }\n          />\n\n          <div className=\"flex items-center gap-2\">\n            <label className=\"flex min-w-0 flex-1 flex-col gap-1\">\n              <TextBody as=\"span\" size=\"sm\" className=\"uppercase tracking-wide text-white/80\">\n                {tp.customWidth}\n              </TextBody>\n              <input\n                type=\"number\"\n                min={16}\n                max={7680}\n                value={widthDraft}\n                onChange={(e) => setWidthDraft(e.target.value)}\n                onBlur={commitCustomSize}\n                onKeyDown={(e) => {\n                  if (e.key === 'Enter') {\n                    e.currentTarget.blur();\n                  }\n                }}\n                className=\"w-full rounded-lg border border-panel-border bg-black-capsule px-2 py-1.5 text-xs font-medium tabular-nums text-white outline-none focus:border-[var(--we-accent)]\"\n              />\n            </label>\n            <TextBody as=\"span\" size=\"sm\" className=\"mt-5 text-white/80\">\n              \u00D7\n            </TextBody>\n            <label className=\"flex min-w-0 flex-1 flex-col gap-1\">\n              <TextBody as=\"span\" size=\"sm\" className=\"uppercase tracking-wide text-white/80\">\n                {tp.customHeight}\n              </TextBody>\n              <input\n                type=\"number\"\n                min={16}\n                max={7680}\n                value={heightDraft}\n                onChange={(e) => setHeightDraft(e.target.value)}\n                onBlur={commitCustomSize}\n                onKeyDown={(e) => {\n                  if (e.key === 'Enter') {\n                    e.currentTarget.blur();\n                  }\n                }}\n                className=\"w-full rounded-lg border border-panel-border bg-black-capsule px-2 py-1.5 text-xs font-medium tabular-nums text-white outline-none focus:border-[var(--we-accent)]\"\n              />\n            </label>\n          </div>\n\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n            {tp.canvasSize}: {canvasWidth}\u00D7{canvasHeight}px\n            {activeSizeId === 'custom' ? ` \u00B7 ${tp.sizeCustom}` : ''}\n          </TextBody>\n        </PanelSection>\n\n        <PanelSection title={tp.snapSection} description={tp.snapHint}>\n          <PanelField\n            label={tp.snapLabel}\n            trailing={\n              <Switch\n                checked={snapEnabled}\n                onChange={setSnapEnabled}\n                ariaLabel={tp.snapLabel}\n              />\n            }\n          />\n        </PanelSection>\n\n        <PanelSection title={tp.qualitySection} description={tp.qualityHint}>\n          <PanelField\n            label={tp.qualityLabel}\n            variant=\"slide\"\n            min={50}\n            max={100}\n            step={5}\n            numericValue={previewQuality}\n            onChange={(n) => setPreviewQuality(Math.round(n))}\n            formatValue={(n) => `${Math.round(n)}%`}\n            defaultValue={100}\n            resetLabel={tp.qualityReset}\n          />\n        </PanelSection>\n\n        <PanelSection title={tp.zoomSection} description={tp.zoomHint}>\n          <div className=\"flex items-center gap-1\">\n            <IconButton\n              size=\"sm\"\n              variant=\"ghost\"\n              label={tp.zoomOut}\n              disabled={canvasZoom <= canvasZoomMin}\n              onClick={onCanvasZoomOut}\n            >\n              <ZoomOut size={14} />\n            </IconButton>\n            <PanelField\n              label={tp.zoomLabel}\n              variant=\"slide\"\n              min={canvasZoomMin}\n              max={canvasZoomMax}\n              step={0.25}\n              numericValue={canvasZoom}\n              onChange={setCanvasZoom}\n              formatValue={(n) => `${Math.round(n * 100)}%`}\n              className=\"min-w-0 flex-1\"\n            />\n            <IconButton\n              size=\"sm\"\n              variant=\"ghost\"\n              label={tp.zoomIn}\n              disabled={canvasZoom >= canvasZoomMax}\n              onClick={onCanvasZoomIn}\n            >\n              <ZoomIn size={14} />\n            </IconButton>\n            <IconButton\n              size=\"sm\"\n              variant=\"ghost\"\n              label={tp.zoomReset}\n              disabled={!canResetZoom}\n              onClick={onCanvasZoomReset}\n              className={!canResetZoom ? 'pointer-events-none opacity-30' : ''}\n            >\n              <RotateCcw size={13} />\n            </IconButton>\n          </div>\n        </PanelSection>\n      </PanelBody>\n    </div>\n  );\n};\n\n/** @deprecated Prefer previewBufferFromCanvas \u2014 kept for callers that only have aspect. */\nexport function previewBufferForAspect(aspect: Aspect): { width: number; height: number } {\n  const dims = dimensionsForAspect(aspect);\n  const maxEdge = 1280;\n  const scale = Math.min(1, maxEdge / Math.max(dims.width, dims.height));\n  return {\n    width: Math.max(1, Math.round(dims.width * scale)),\n    height: Math.max(1, Math.round(dims.height * scale)),\n  };\n}\n\nexport default VideoCanvasPanel;\n", "import React from 'react';\nimport {\n  Clapperboard,\n  Images,\n  Languages,\n  Mic,\n  Palette,\n  PenLine,\n  Sparkles,\n  Type,\n  Wand2,\n} from 'lucide-react';\nimport { PanelBody, PanelSection, SubtitleAiLoader, TextBody, TextTitle } from '../ui';\nimport { useTranslation } from '../../i18n';\nimport { useVideoStore } from '../../store/useVideoStore';\nimport { useVideoUiStore } from '../../store/useVideoUiStore';\nimport type { VideoAiToolId } from '../../store/useVideoUiStore';\n\ntype ToolNameKey =\n  | 'translate'\n  | 'subtitleStyle'\n  | 'voiceover'\n  | 'colorGrading'\n  | 'designPreset'\n  | 'videoProperties'\n  | 'generateCopy'\n  | 'copySuggestions'\n  | 'marketing'\n  | 'stock';\n\ntype ToolDef = {\n  id: VideoAiToolId;\n  icon: React.ReactNode;\n  nameKey: ToolNameKey;\n  descKey: `${ToolNameKey}Desc`;\n};\n\nconst SUBTITLE_TOOLS: ToolDef[] = [\n  {\n    id: 'translate',\n    icon: <Languages size={16} />,\n    nameKey: 'translate',\n    descKey: 'translateDesc',\n  },\n  {\n    id: 'subtitleStyle',\n    icon: <Wand2 size={16} />,\n    nameKey: 'subtitleStyle',\n    descKey: 'subtitleStyleDesc',\n  },\n  {\n    id: 'voiceover',\n    icon: <Mic size={16} />,\n    nameKey: 'voiceover',\n    descKey: 'voiceoverDesc',\n  },\n];\n\nconst LOOK_TOOLS: ToolDef[] = [\n  {\n    id: 'colorGrading',\n    icon: <Palette size={16} />,\n    nameKey: 'colorGrading',\n    descKey: 'colorGradingDesc',\n  },\n  {\n    id: 'designPreset',\n    icon: <Sparkles size={16} />,\n    nameKey: 'designPreset',\n    descKey: 'designPresetDesc',\n  },\n  {\n    id: 'videoProperties',\n    icon: <Clapperboard size={16} />,\n    nameKey: 'videoProperties',\n    descKey: 'videoPropertiesDesc',\n  },\n];\n\nconst COPY_TOOLS: ToolDef[] = [\n  {\n    id: 'generateCopy',\n    icon: <Type size={16} />,\n    nameKey: 'generateCopy',\n    descKey: 'generateCopyDesc',\n  },\n  {\n    id: 'copySuggestions',\n    icon: <PenLine size={16} />,\n    nameKey: 'copySuggestions',\n    descKey: 'copySuggestionsDesc',\n  },\n  {\n    id: 'marketing',\n    icon: <Sparkles size={16} />,\n    nameKey: 'marketing',\n    descKey: 'marketingDesc',\n  },\n];\n\nconst MEDIA_TOOLS: ToolDef[] = [\n  {\n    id: 'stock',\n    icon: <Images size={16} />,\n    nameKey: 'stock',\n    descKey: 'stockDesc',\n  },\n];\n\nfunction ToolButton({\n  tool,\n  name,\n  description,\n  onClick,\n  isBusy,\n  busyLabel,\n}: {\n  tool: ToolDef;\n  name: string;\n  description: string;\n  onClick: () => void;\n  isBusy: boolean;\n  busyLabel: string;\n}) {\n  return (\n    <button\n      type=\"button\"\n      onClick={onClick}\n      disabled={isBusy}\n      className=\"relative flex w-full cursor-pointer items-start gap-2.5 overflow-hidden rounded-xl border border-transparent bg-black-capsule px-2.5 py-2.5 text-left transition-colors hover:border-[color-mix(in_srgb,var(--we-accent)_35%,transparent)] hover:bg-[var(--we-accent-muted)] active:scale-[0.99] disabled:cursor-wait\"\n    >\n      <span className=\"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-[var(--we-accent-muted)] text-[var(--we-accent)]\">\n        {tool.icon}\n      </span>\n      <span className=\"min-w-0 flex-1\">\n        <TextTitle as=\"span\" size=\"xs\" className=\"block font-semibold\">\n          {name}\n        </TextTitle>\n        <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 block text-pretty leading-snug text-white/80\">\n          {description}\n        </TextBody>\n      </span>\n      {isBusy ? (\n        <div className=\"absolute inset-0 z-10\">\n          <SubtitleAiLoader label={busyLabel} variant=\"clip\" className=\"h-full rounded-xl\" />\n        </div>\n      ) : null}\n    </button>\n  );\n}\n\n/** Left-dock catalog of video-editor AI tools (subtitles, look, copy, stock). */\nexport const VideoAiToolsPanel: React.FC = () => {\n  const t = useTranslation();\n  const tp = t.videoEditor.aiTools;\n  const openAiGenerateTool = useVideoUiStore((s) => s.openAiGenerateTool);\n  const aiBusyToolId = useVideoStore((s) => s.aiBusyToolId);\n\n  const renderTools = (tools: ToolDef[]) => (\n    <div className=\"flex flex-col gap-1.5\">\n      {tools.map((tool) => (\n        <ToolButton\n          key={tool.id}\n          tool={tool}\n          name={tp.tools[tool.nameKey]}\n          description={tp.tools[tool.descKey]}\n          onClick={() => openAiGenerateTool(tool.id)}\n          isBusy={aiBusyToolId === tool.id}\n          busyLabel={tp.modal.statusWorking}\n        />\n      ))}\n    </div>\n  );\n\n  return (\n    <PanelBody className=\"h-full overflow-y-auto\">\n      <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n        {tp.hint}\n      </TextBody>\n\n      <PanelSection title={tp.sectionSubtitles} description={tp.sectionSubtitlesHint}>\n        {renderTools(SUBTITLE_TOOLS)}\n      </PanelSection>\n\n      <PanelSection title={tp.sectionLook} description={tp.sectionLookHint} divided>\n        {renderTools(LOOK_TOOLS)}\n      </PanelSection>\n\n      <PanelSection title={tp.sectionCopy} description={tp.sectionCopyHint} divided>\n        {renderTools(COPY_TOOLS)}\n      </PanelSection>\n\n      <PanelSection title={tp.sectionMedia} description={tp.sectionMediaHint} divided>\n        {renderTools(MEDIA_TOOLS)}\n      </PanelSection>\n    </PanelBody>\n  );\n};\n\nexport default VideoAiToolsPanel;\n", "import { create } from 'zustand';\n\nexport type VideoAiToolId =\n  | 'transcribe'\n  | 'translate'\n  | 'subtitleStyle'\n  | 'voiceover'\n  | 'colorGrading'\n  | 'designPreset'\n  | 'videoProperties'\n  | 'generateCopy'\n  | 'copySuggestions'\n  | 'marketing'\n  | 'stock';\n\nexport type VideoRightPanelId = 'inspector' | 'transitions' | 'effects' | 'text';\n\n/** Where a transition should be applied when picking from the transitions panel. */\nexport type TransitionEdgeIntent =\n  | { kind: 'start'; clipId: string }\n  | { kind: 'end'; clipId: string }\n  | { kind: 'between'; fromClipId: string; toClipId: string };\n\n/** Junction editor when two abutting clips both carry edge transitions. */\nexport type TransitionJunctionState = {\n  fromClipId: string;\n  toClipId: string;\n};\n\ntype VideoUiState = {\n  rightPanel: VideoRightPanelId | null;\n  setRightPanel: (id: VideoRightPanelId | null) => void;\n  toggleRightPanel: (id: VideoRightPanelId) => void;\n\n  transitionIntent: TransitionEdgeIntent | null;\n  setTransitionIntent: (intent: TransitionEdgeIntent | null) => void;\n  openTransitionsForEdge: (intent: TransitionEdgeIntent) => void;\n  clearTransitionIntent: () => void;\n\n  transitionJunction: TransitionJunctionState | null;\n  openTransitionJunction: (junction: TransitionJunctionState) => void;\n  closeTransitionJunction: () => void;\n\n  /** Shared AI generate modal (timeline context menu + AI tools panel). */\n  aiGenerateTool: VideoAiToolId | null;\n  openAiGenerateTool: (tool: VideoAiToolId) => void;\n  closeAiGenerateTool: () => void;\n};\n\nexport const useVideoUiStore = create<VideoUiState>((set) => ({\n  rightPanel: 'inspector',\n  setRightPanel: (id) => set({ rightPanel: id }),\n  toggleRightPanel: (id) =>\n    set((s) => ({ rightPanel: s.rightPanel === id ? null : id })),\n\n  transitionIntent: null,\n  setTransitionIntent: (intent) => set({ transitionIntent: intent }),\n  openTransitionsForEdge: (intent) =>\n    set({\n      transitionIntent: intent,\n      rightPanel: 'transitions',\n      transitionJunction: null,\n    }),\n  clearTransitionIntent: () => set({ transitionIntent: null }),\n\n  transitionJunction: null,\n  openTransitionJunction: (junction) =>\n    set({\n      transitionJunction: junction,\n      transitionIntent: null,\n    }),\n  closeTransitionJunction: () => set({ transitionJunction: null }),\n\n  aiGenerateTool: null,\n  openAiGenerateTool: (tool) => set({ aiGenerateTool: tool }),\n  closeAiGenerateTool: () => set({ aiGenerateTool: null }),\n}));\n", "import React, { useRef, useEffect, useCallback, useState } from 'react';\nimport {\n  Play,\n  Pause,\n  ChevronsLeft,\n  ChevronsRight,\n  Rewind,\n  FastForward,\n  Maximize,\n  Minimize,\n  Repeat,\n} from 'lucide-react';\nimport { useVideoStore, type Clip } from '../../store/useVideoStore';\nimport { SubtitleAiLoader } from '../ui';\nimport { WebGLVideoRenderer } from '../../lib/effects/webglRenderer';\nimport { getMotionTransform } from '../../lib/effects/motionUtils';\nimport { drawTextClipToCanvas } from '../../lib/effects/textRenderer';\nimport { getOverlayTransitionOpacity, isOverlayVisibleAtPlayhead, getBetweenTransitionWindow } from '../../lib/effects/overlayTransition';\nimport { CropTool } from './images/CropTool';\nimport { useTranslation } from '../../i18n';\nimport { hitTestPreviewClip } from '../../utils/previewHitTest';\n\nconst dummyBlackCanvas = typeof document !== 'undefined' ? (() => {\n  const c = document.createElement('canvas');\n  c.width = 32;\n  c.height = 32;\n  const ctx = c.getContext('2d');\n  if (ctx) {\n    ctx.fillStyle = '#000000';\n    ctx.fillRect(0, 0, 32, 32);\n  }\n  return c;\n})() : null;\n\nconst dummyWhiteCanvas = typeof document !== 'undefined' ? (() => {\n  const c = document.createElement('canvas');\n  c.width = 32;\n  c.height = 32;\n  const ctx = c.getContext('2d');\n  if (ctx) {\n    ctx.fillStyle = '#ffffff';\n    ctx.fillRect(0, 0, 32, 32);\n  }\n  return c;\n})() : null;\n\nconst dummyTransparentCanvas = typeof document !== 'undefined' ? (() => {\n  const c = document.createElement('canvas');\n  c.width = 32;\n  c.height = 32;\n  const ctx = c.getContext('2d');\n  if (ctx) {\n    ctx.clearRect(0, 0, 32, 32);\n  }\n  return c;\n})() : null;\n\ninterface VideoPreviewProps {\n  canvasZoom?: number;\n  setCanvasZoom?: (z: number) => void;\n  canvasOffset?: { x: number; y: number };\n  setCanvasOffset?: (offset: { x: number; y: number }) => void;\n  canvasZoomMin?: number;\n  canvasZoomMax?: number;\n  canvasZoomStep?: number;\n  /** 50\u2013100; 100 = draw at full project canvas resolution. */\n  previewQuality?: number;\n}\n\nfunction timelineContentEnd(\n  tracks: { clips: { startTime: number; duration: number }[] }[],\n): number {\n  let maxEnd = 0;\n  for (const track of tracks) {\n    for (const clip of track.clips) {\n      const end = clip.startTime + clip.duration;\n      if (end > maxEnd) maxEnd = end;\n    }\n  }\n  return maxEnd;\n}\n\nexport const VideoPreview: React.FC<VideoPreviewProps> = ({\n  canvasZoom    = 1,\n  setCanvasZoom,\n  canvasOffset  = { x: 0, y: 0 },\n  setCanvasOffset,\n  canvasZoomMin  = 0.25,\n  canvasZoomMax  = 4,\n  canvasZoomStep = 0.25,\n  previewQuality = 100,\n}) => {\n  const t = useTranslation();\n  const tp = t.videoEditor.playback;\n  const rootRef = useRef<HTMLDivElement>(null);\n  const canvasRef = useRef<HTMLCanvasElement>(null);\n  const containerRef = useRef<HTMLDivElement>(null);\n  // WebGL Renderer cache\n  const webglRendererRef = useRef<WebGLVideoRenderer | null>(null);\n  const offscreenTextCanvasRef = useRef<HTMLCanvasElement | null>(null);\n  const initializedClipsRef = useRef<Set<string>>(new Set());\n  const lastPlayheadTimeRef = useRef<number>(0);\n  const loopRef = useRef(false);\n  /** Coalesce scrub seeks so we never stack seeks (main flicker source). */\n  const pendingSeekByAssetIdRef = useRef<Map<string, number>>(new Map());\n  /** Per-asset scrub rate limit \u2014 shared timer made A/B transition seeks alternate. */\n  const lastScrubSeekMsByAssetRef = useRef<Map<string, number>>(new Map());\n  /** Skip clear-to-black while a seek is in flight if we already painted a frame. */\n  const holdPreviewFrameRef = useRef(false);\n  /** When paused, skip GL redraws if playhead has not moved since last paint (stops transition flicker). */\n  const lastPaintedPausedPlayheadRef = useRef<number | null>(null);\n  const glContextRef = useRef<WebGL2RenderingContext | null>(null);\n\n  const [isLooping, setIsLooping] = useState(false);\n  const [isPreviewFullscreen, setIsPreviewFullscreen] = useState(false);\n\n  const isPanningRef   = useRef(false);\n  const panStartRef    = useRef({ x: 0, y: 0, ox: 0, oy: 0 });\n\n  // Keep zoom props in refs so the non-passive wheel listener stays fresh.\n  const zoomRef = useRef({ canvasZoom, canvasZoomStep, canvasZoomMin, canvasZoomMax, setCanvasZoom });\n  zoomRef.current = { canvasZoom, canvasZoomStep, canvasZoomMin, canvasZoomMax, setCanvasZoom };\n\n  useEffect(() => {\n    loopRef.current = isLooping;\n  }, [isLooping]);\n\n  useEffect(() => {\n    const onChange = () => setIsPreviewFullscreen(!!document.fullscreenElement);\n    document.addEventListener('fullscreenchange', onChange);\n    return () => document.removeEventListener('fullscreenchange', onChange);\n  }, []);\n\n  const handleToggleFullscreen = useCallback(() => {\n    if (document.fullscreenElement) {\n      void document.exitFullscreen();\n    } else {\n      void rootRef.current?.requestFullscreen?.();\n    }\n  }, []);\n\n  // Ctrl+wheel zoom \u2014 must be non-passive so preventDefault can stop browser page zoom.\n  useEffect(() => {\n    const el = containerRef.current;\n    if (!el) return;\n    const onWheel = (e: WheelEvent) => {\n      if (!e.ctrlKey) return;\n      e.preventDefault();\n      const z = zoomRef.current;\n      const delta = e.deltaY < 0 ? z.canvasZoomStep : -z.canvasZoomStep;\n      const next = Math.max(\n        z.canvasZoomMin,\n        Math.min(z.canvasZoomMax, Math.round((z.canvasZoom + delta) * 100) / 100),\n      );\n      z.setCanvasZoom?.(next);\n    };\n    el.addEventListener('wheel', onWheel, { passive: false });\n    return () => el.removeEventListener('wheel', onWheel);\n  }, []);\n\n  // Drag pan (middle-click or Alt+drag) \u2014 canvas only, never transform clips.\n  const handlePanStart = useCallback((e: React.MouseEvent) => {\n    if (e.button !== 1 && !(e.button === 0 && e.altKey)) return;\n    e.preventDefault();\n    e.stopPropagation();\n    isPanningRef.current = true;\n    panStartRef.current = { x: e.clientX, y: e.clientY, ox: canvasOffset.x, oy: canvasOffset.y };\n\n    const onMove = (ev: MouseEvent) => {\n      if (!isPanningRef.current) return;\n      setCanvasOffset?.({\n        x: panStartRef.current.ox + (ev.clientX - panStartRef.current.x),\n        y: panStartRef.current.oy + (ev.clientY - panStartRef.current.y),\n      });\n    };\n    const onUp = () => {\n      isPanningRef.current = false;\n      window.removeEventListener('mousemove', onMove);\n      window.removeEventListener('mouseup',   onUp);\n    };\n    window.addEventListener('mousemove', onMove);\n    window.addEventListener('mouseup',   onUp);\n  }, [canvasOffset, setCanvasOffset]);\n\n  const {\n    tracks,\n    assets,\n    playheadTime,\n    setPlayhead,\n    isPlaying,\n    setIsPlaying,\n    transitions,\n    selectedClipIds,\n    selectClip,\n    clearSelection,\n    aspectRatio: aspect,\n    canvasWidth,\n    canvasHeight,\n    projectDuration,\n    aiSubtitleJob,\n    aiBusyToolId,\n  } = useVideoStore();\n  const tAi = useTranslation();\n  const tTimeline = tAi.videoEditor.timeline;\n  const tmAi = tAi.videoEditor.aiTools.modal;\n\n  // After each seek settles, apply the latest scrub target if the playhead moved again.\n  useEffect(() => {\n    const cleanups: Array<() => void> = [];\n    for (const asset of assets) {\n      if (asset.type !== 'video' && asset.type !== 'audio') continue;\n      const el = document.getElementById(`preview-media-${asset.id}`) as HTMLMediaElement | null;\n      if (!el) continue;\n      const onSeeked = () => {\n        const pending = pendingSeekByAssetIdRef.current.get(asset.id);\n        if (pending == null) return;\n        if (Math.abs(el.currentTime - pending) > 0.15) {\n          try {\n            el.currentTime = pending;\n          } catch {\n            pendingSeekByAssetIdRef.current.delete(asset.id);\n          }\n        } else {\n          pendingSeekByAssetIdRef.current.delete(asset.id);\n        }\n      };\n      el.addEventListener('seeked', onSeeked);\n      cleanups.push(() => el.removeEventListener('seeked', onSeeked));\n    }\n    return () => cleanups.forEach((fn) => fn());\n  }, [assets]);\n\n  const [displaySize, setDisplaySize] = useState({\n    width: 1280,\n    height: 720,\n    cssWidth: 640,\n    cssHeight: 360,\n  });\n\n  // Fit CSS size to the preview column; draw buffer scales with previewQuality\n  // (50% \u2248 display\u00D7dpr, 100% = full project canvas resolution).\n  useEffect(() => {\n    const el = containerRef.current;\n    if (!el) return;\n    const update = () => {\n      const cw = Math.max(1, canvasWidth || 1920);\n      const ch = Math.max(1, canvasHeight || 1080);\n      const projectAspect = cw / ch;\n      const pad = 16;\n      const availW = Math.max(120, el.clientWidth - pad);\n      const availH = Math.max(120, el.clientHeight - pad);\n      let cssW = availW;\n      let cssH = cssW / projectAspect;\n      if (cssH > availH) {\n        cssH = availH;\n        cssW = cssH * projectAspect;\n      }\n      const dpr = Math.min(window.devicePixelRatio || 1, 2);\n      const quality = Math.max(50, Math.min(100, previewQuality)) / 100;\n      // 50 \u2192 low (CSS\u00D7dpr), 100 \u2192 full project resolution\n      const t = (quality - 0.5) / 0.5;\n      const lowW = Math.max(1, Math.round(cssW * dpr));\n      const lowH = Math.max(1, Math.round(cssH * dpr));\n      const targetW = Math.max(1, Math.round(lowW + (cw - lowW) * t));\n      const targetH = Math.max(1, Math.round(lowH + (ch - lowH) * t));\n      setDisplaySize({\n        width: targetW,\n        height: targetH,\n        cssWidth: Math.max(1, Math.round(cssW)),\n        cssHeight: Math.max(1, Math.round(cssH)),\n      });\n    };\n    update();\n    const ro = new ResizeObserver(update);\n    ro.observe(el);\n    return () => ro.disconnect();\n  }, [canvasWidth, canvasHeight, isPreviewFullscreen, previewQuality]);\n\n  // Keyboard Shortcuts (Space, Prev Frame, Next Frame)\n  useEffect(() => {\n    const handleKeyDown = (e: KeyboardEvent) => {\n      if (['INPUT', 'TEXTAREA'].includes((e.target as HTMLElement).tagName)) {\n        return;\n      }\n\n      if (e.code === 'Space') {\n        e.preventDefault();\n        setIsPlaying(!isPlaying);\n      } else if (e.key === ',') {\n        setPlayhead(Math.max(0, playheadTime - 1/30));\n      } else if (e.key === '.') {\n        setPlayhead(playheadTime + 1/30);\n      }\n    };\n\n    window.addEventListener('keydown', handleKeyDown);\n    return () => window.removeEventListener('keydown', handleKeyDown);\n  }, [isPlaying, playheadTime, setIsPlaying, setPlayhead]);\n\n  // Main WebGL rendering loop\n  useEffect(() => {\n    let animationFrameId: number;\n    let lastTime = performance.now();\n\n    // Reset initialization tracking when the playback setup changes\n    initializedClipsRef.current.clear();\n    lastPaintedPausedPlayheadRef.current = null;\n    glContextRef.current = null;\n\n    const renderTick = async () => {\n      const now = performance.now();\n      const deltaSec = (now - lastTime) / 1000;\n      lastTime = now;\n      \n      const storeState = useVideoStore.getState();\n      const currentIsPlaying = storeState.isPlaying;\n      let currentPlayhead = storeState.playheadTime;\n      \n      // Update time if playing, using direct store state to bypass React state synchronization lag/jitter\n      if (currentIsPlaying) {\n        currentPlayhead = currentPlayhead + deltaSec;\n        const contentEnd = timelineContentEnd(storeState.tracks);\n        const end = contentEnd > 0 ? contentEnd : storeState.projectDuration;\n        if (currentPlayhead >= end) {\n          if (loopRef.current) {\n            currentPlayhead = 0;\n            initializedClipsRef.current.clear();\n          } else {\n            currentPlayhead = end;\n            setIsPlaying(false);\n          }\n        }\n        setPlayhead(currentPlayhead);\n        lastPaintedPausedPlayheadRef.current = null;\n      }\n\n      // Manual scrub while paused should not wipe init state every frame (causes re-seek storms).\n      const expectedPlayhead = lastPlayheadTimeRef.current + (currentIsPlaying ? deltaSec : 0);\n      const playheadJumped = Math.abs(currentPlayhead - expectedPlayhead) > 0.2;\n      if (currentIsPlaying && playheadJumped) {\n        initializedClipsRef.current.clear();\n      }\n      if (\n        !currentIsPlaying &&\n        lastPaintedPausedPlayheadRef.current != null &&\n        Math.abs(currentPlayhead - lastPaintedPausedPlayheadRef.current) > 0.001\n      ) {\n        // Playhead moved while paused (scrub) \u2014 allow a fresh paint.\n        lastPaintedPausedPlayheadRef.current = null;\n      }\n      lastPlayheadTimeRef.current = currentPlayhead;\n\n      // Freeze preview while paused at a stable playhead. Continuous 60fps\n      // texImage2D + clear during transitions was the remaining flicker source.\n      if (\n        !currentIsPlaying &&\n        holdPreviewFrameRef.current &&\n        lastPaintedPausedPlayheadRef.current != null &&\n        Math.abs(currentPlayhead - lastPaintedPausedPlayheadRef.current) <= 0.001\n      ) {\n        animationFrameId = requestAnimationFrame(renderTick);\n        return;\n      }\n\n      const scrubSeekMedia = (\n        assetId: string,\n        mediaEl: HTMLMediaElement,\n        targetTime: number,\n      ) => {\n        const drift = Math.abs(mediaEl.currentTime - targetTime);\n        // Wider deadzone while paused \u2014 video currentTime often jitters ~50\u2013150ms.\n        const deadzone = currentIsPlaying ? 0.1 : 0.2;\n        if (drift < deadzone && mediaEl.readyState >= 2) {\n          pendingSeekByAssetIdRef.current.delete(assetId);\n          return;\n        }\n        pendingSeekByAssetIdRef.current.set(assetId, targetTime);\n        if (mediaEl.seeking) return;\n        const nowMs = performance.now();\n        const lastMs = lastScrubSeekMsByAssetRef.current.get(assetId) ?? 0;\n        if (nowMs - lastMs < (currentIsPlaying ? 50 : 100)) return;\n        lastScrubSeekMsByAssetRef.current.set(assetId, nowMs);\n        try {\n          mediaEl.currentTime = targetTime;\n        } catch {\n          /* Ignore InvalidStateError while metadata loads */\n        }\n      };\n\n      // Draw onto WebGL canvas\n      const canvas = canvasRef.current;\n      if (canvas) {\n        let gl = glContextRef.current;\n        if (!gl || gl.isContextLost()) {\n          gl = canvas.getContext('webgl2', {\n            premultipliedAlpha: false,\n            preserveDrawingBuffer: true,\n          });\n          glContextRef.current = gl;\n          webglRendererRef.current = null;\n        }\n        if (gl) {\n          if (!webglRendererRef.current) {\n            webglRendererRef.current = new WebGLVideoRenderer(gl);\n          }\n          const renderer = webglRendererRef.current;\n\n          // Get active video clips first so we know whether to clear or hold\n          // Keep muted video tracks visible; mute only their audio (see videoEl.muted below).\n          const videoTracks = tracks.filter((t) => t.type === 'video');\n          const activeClips: { clip: Clip; videoEl: HTMLVideoElement }[] = [];\n\n          videoTracks.forEach((track) => {\n            track.clips.forEach((clip) => {\n              if (currentPlayhead >= clip.startTime && currentPlayhead < clip.startTime + clip.duration) {\n                const videoEl = document.getElementById(`preview-media-${clip.assetId}`) as HTMLVideoElement;\n                if (videoEl) {\n                  activeClips.push({ clip, videoEl });\n                }\n              }\n            });\n          });\n\n          const hasDrawableVideo = activeClips.some(\n            ({ videoEl }) => videoEl.readyState >= 2,\n          );\n\n          const mediaBusy = (assetId: string, el: HTMLMediaElement | null) =>\n            Boolean(\n              el &&\n                (el.seeking ||\n                  pendingSeekByAssetIdRef.current.has(assetId) ||\n                  el.readyState < 2),\n            );\n\n          let pauseHoldTransitionFrame = false;\n          if (!currentIsPlaying && holdPreviewFrameRef.current) {\n            for (const betweenTrans of transitions) {\n              if (betweenTrans.fromClipId === 'none' || betweenTrans.toClipId === 'none') continue;\n              let fromClip: Clip | null = null;\n              let toClip: Clip | null = null;\n              for (const tr of tracks) {\n                if (!fromClip) {\n                  fromClip = tr.clips.find((c) => c.id === betweenTrans.fromClipId) ?? null;\n                }\n                if (!toClip) {\n                  toClip = tr.clips.find((c) => c.id === betweenTrans.toClipId) ?? null;\n                }\n              }\n              if (!fromClip) continue;\n              const { start: transStart, end: transEnd } = getBetweenTransitionWindow(\n                fromClip,\n                betweenTrans.duration,\n              );\n              if (currentPlayhead < transStart || currentPlayhead > transEnd) continue;\n              if (!toClip) continue;\n              const fromEl = document.getElementById(\n                `preview-media-${fromClip.assetId}`,\n              ) as HTMLVideoElement | null;\n              const toEl = document.getElementById(\n                `preview-media-${toClip.assetId}`,\n              ) as HTMLVideoElement | null;\n              if (mediaBusy(fromClip.assetId, fromEl) || mediaBusy(toClip.assetId, toEl)) {\n                pauseHoldTransitionFrame = true;\n                break;\n              }\n            }\n          }\n\n          // Hold last painted frame while the decoder catches up (no black flash)\n          const shouldClear =\n            !pauseHoldTransitionFrame &&\n            (hasDrawableVideo || !holdPreviewFrameRef.current || activeClips.length === 0);\n\n          gl.viewport(0, 0, canvas.width, canvas.height);\n          if (shouldClear) {\n            gl.clearColor(0.04, 0.04, 0.06, 1.0); // #0A0A0F matching background\n            gl.clear(gl.COLOR_BUFFER_BIT);\n          }\n          gl.enable(gl.BLEND);\n          gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n\n          // Sync Audio Elements (Only for audio track types to avoid double-seeking video layers)\n          const audioTracks = tracks.filter((t) => t.type === 'audio');\n          audioTracks.forEach((track) => {\n            track.clips.forEach((clip) => {\n              const mediaId = `preview-media-${clip.assetId}`;\n              const mediaEl = document.getElementById(mediaId) as HTMLMediaElement;\n              if (!mediaEl) return;\n\n              const isClipActive = currentPlayhead >= clip.startTime && currentPlayhead < clip.startTime + clip.duration;\n              const isTrackMuted = track.muted;\n              const isClipMuted = clip.muted;\n\n              if (isClipActive && !isTrackMuted && !isClipMuted) {\n                mediaEl.volume = Math.max(0, Math.min(1, clip.volume));\n                mediaEl.muted = false;\n                const mediaOffset = (currentPlayhead - clip.startTime) * clip.speed + clip.trimIn;\n\n                if (currentIsPlaying) {\n                  if (mediaEl.paused && !mediaEl.seeking) {\n                    mediaEl.play().catch(() => {});\n                  }\n                  mediaEl.playbackRate = clip.speed;\n\n                  // Seek once when clip first becomes active during playback\n                  if (!initializedClipsRef.current.has(clip.id)) {\n                    if (!mediaEl.seeking && Math.abs(mediaEl.currentTime - mediaOffset) / clip.speed > 0.1) {\n                      mediaEl.currentTime = mediaOffset;\n                    }\n                    initializedClipsRef.current.add(clip.id);\n                  } else {\n                    // Drift catch-up guard for long plays (evaluated in real-time seconds)\n                    if (!mediaEl.seeking && Math.abs(mediaEl.currentTime - mediaOffset) / clip.speed > 1.5) {\n                      initializedClipsRef.current.delete(clip.id);\n                    }\n                  }\n                } else {\n                  // Paused/Scrubbing\n                  if (!mediaEl.paused) {\n                    mediaEl.pause();\n                  }\n                  scrubSeekMedia(clip.assetId, mediaEl, mediaOffset);\n                }\n              } else {\n                if (!mediaEl.paused) {\n                  mediaEl.pause();\n                }\n                mediaEl.muted = true;\n              }\n            });\n          });\n\n          // Bottom timeline track first (back), top track last (front).\n          const trackStackIndex = (trackId: string) => {\n            const i = tracks.findIndex((t) => t.id === trackId);\n            return i < 0 ? 999 : i;\n          };\n          activeClips.sort(\n            (a, b) => trackStackIndex(b.clip.trackId) - trackStackIndex(a.clip.trackId),\n          );\n\n          const findClipById = (id: string): Clip | null => {\n            for (const tr of tracks) {\n              const found = tr.clips.find((c) => c.id === id);\n              if (found) return found;\n            }\n            return null;\n          };\n\n          const clampClipMediaTime = (clip: Clip, playhead: number): number => {\n            const raw = (playhead - clip.startTime) * clip.speed + clip.trimIn;\n            const minT = clip.trimIn;\n            const maxT = clip.trimIn + Math.max(0, clip.duration) * clip.speed;\n            return Math.max(minT, Math.min(maxT, raw));\n          };\n\n          const syncPreviewVideo = (\n            clip: Clip,\n            videoEl: HTMLVideoElement,\n            mediaTime: number,\n            initKey: string,\n          ) => {\n            if (currentIsPlaying) {\n              if (videoEl.paused && !videoEl.seeking) {\n                videoEl.play().catch(() => {});\n              }\n              videoEl.playbackRate = clip.speed;\n              videoEl.preservesPitch = true;\n              if ((videoEl as any).webkitPreservesPitch !== undefined) {\n                (videoEl as any).webkitPreservesPitch = true;\n              }\n              const isTrackMuted = tracks.find((tr) => tr.id === clip.trackId)?.muted;\n              videoEl.muted = Boolean(isTrackMuted || clip.muted);\n              videoEl.volume = Math.max(0, Math.min(1, clip.volume));\n\n              if (!initializedClipsRef.current.has(initKey)) {\n                if (!videoEl.seeking && Math.abs(videoEl.currentTime - mediaTime) / clip.speed > 0.1) {\n                  videoEl.currentTime = mediaTime;\n                }\n                initializedClipsRef.current.add(initKey);\n              } else if (\n                !videoEl.seeking &&\n                Math.abs(videoEl.currentTime - mediaTime) / clip.speed > 1.5\n              ) {\n                initializedClipsRef.current.delete(initKey);\n              }\n            } else {\n              if (!videoEl.paused) videoEl.pause();\n              videoEl.muted = true;\n              scrubSeekMedia(clip.assetId, videoEl, mediaTime);\n            }\n          };\n\n          let paintedVideo = false;\n          // Between transitions span BOTH clips (cut \u00B1 duration/2). Draw them\n          // first so the second half still composites after the outgoing clip ends.\n          const clipsInBetween = new Set<string>();\n          const betweenAssetIds = new Set<string>();\n\n          for (const betweenTrans of transitions) {\n            if (betweenTrans.fromClipId === 'none' || betweenTrans.toClipId === 'none') continue;\n            const fromClip = findClipById(betweenTrans.fromClipId);\n            if (!fromClip) continue;\n            const { start: transStart, end: transEnd } = getBetweenTransitionWindow(\n              fromClip,\n              betweenTrans.duration,\n            );\n            if (currentPlayhead < transStart || currentPlayhead > transEnd) continue;\n\n            const toClip = findClipById(betweenTrans.toClipId);\n            if (!toClip) continue;\n\n            const fromVideoEl = document.getElementById(\n              `preview-media-${fromClip.assetId}`,\n            ) as HTMLVideoElement | null;\n            const toVideoEl = document.getElementById(\n              `preview-media-${toClip.assetId}`,\n            ) as HTMLVideoElement | null;\n            if (!fromVideoEl || !toVideoEl) continue;\n\n            const fromOffsetTime = clampClipMediaTime(fromClip, currentPlayhead);\n            const toOffsetTime = clampClipMediaTime(toClip, currentPlayhead);\n            syncPreviewVideo(\n              fromClip,\n              fromVideoEl,\n              fromOffsetTime,\n              `between-from-${betweenTrans.id}-${fromClip.id}`,\n            );\n            syncPreviewVideo(\n              toClip,\n              toVideoEl,\n              toOffsetTime,\n              `between-to-${betweenTrans.id}-${toClip.id}`,\n            );\n\n            const progress = Math.max(\n              0,\n              Math.min(1, (currentPlayhead - transStart) / betweenTrans.duration),\n            );\n\n            const bothReady =\n              fromVideoEl.readyState >= 2 &&\n              toVideoEl.readyState >= 2 &&\n              !fromVideoEl.seeking &&\n              !toVideoEl.seeking &&\n              !pendingSeekByAssetIdRef.current.has(fromClip.assetId) &&\n              !pendingSeekByAssetIdRef.current.has(toClip.assetId);\n\n            // Paused + decoder catching up: keep last composite (preserveDrawingBuffer).\n            if (pauseHoldTransitionFrame || (!currentIsPlaying && !bothReady && holdPreviewFrameRef.current)) {\n              clipsInBetween.add(fromClip.id);\n              clipsInBetween.add(toClip.id);\n              betweenAssetIds.add(fromClip.assetId);\n              betweenAssetIds.add(toClip.assetId);\n              continue;\n            }\n\n            if (bothReady) {\n              renderer.drawTransition(\n                fromVideoEl,\n                toVideoEl,\n                betweenTrans.type,\n                progress,\n                canvas.width,\n                canvas.height,\n              );\n              paintedVideo = true;\n            } else if (\n              currentIsPlaying &&\n              fromVideoEl.readyState >= 2 &&\n              !fromVideoEl.seeking\n            ) {\n              renderer.drawLayer(fromVideoEl, fromClip, fromOffsetTime, canvas.width, canvas.height);\n              paintedVideo = true;\n            } else if (\n              currentIsPlaying &&\n              toVideoEl.readyState >= 2 &&\n              !toVideoEl.seeking\n            ) {\n              renderer.drawLayer(toVideoEl, toClip, toOffsetTime, canvas.width, canvas.height);\n              paintedVideo = true;\n            }\n\n            clipsInBetween.add(fromClip.id);\n            clipsInBetween.add(toClip.id);\n            betweenAssetIds.add(fromClip.assetId);\n            betweenAssetIds.add(toClip.assetId);\n          }\n\n          // Prepare offscreen canvas for text/subtitle overlays\n          if (!offscreenTextCanvasRef.current) {\n            offscreenTextCanvasRef.current = document.createElement('canvas');\n          }\n          const textCanvas = offscreenTextCanvasRef.current;\n          textCanvas.width = canvas.width;\n          textCanvas.height = canvas.height;\n          const textCtx = textCanvas.getContext('2d');\n\n          const flushTextOverlay = (idSuffix: string) => {\n            if (!textCtx || !renderer) return;\n            const dummyTextClip: Clip = {\n              id: `dummy_text_overlay_${idSuffix}`,\n              trackId: '',\n              assetId: '',\n              startTime: 0,\n              duration: 9999,\n              trimIn: 0,\n              trimOut: 0,\n              speed: 1.0,\n              volume: 1.0,\n              opacity: 1.0,\n              muted: false,\n              type: 'text',\n            };\n            renderer.drawLayer(textCanvas, dummyTextClip, 0, canvas.width, canvas.height);\n            textCtx.clearRect(0, 0, textCanvas.width, textCanvas.height);\n          };\n\n          // Visual stack: timeline bottom \u2192 top (tracks[n-1] \u2026 tracks[0] = back \u2192 front).\n          // Any type can sit above/below any other type.\n          for (let ti = tracks.length - 1; ti >= 0; ti--) {\n            const track = tracks[ti];\n            if (!track || track.muted || track.type === 'audio') continue;\n\n            if (track.type === 'video') {\n              for (let i = 0; i < activeClips.length; i++) {\n                const entry = activeClips[i];\n                if (!entry || entry.clip.trackId !== track.id) continue;\n                const { clip, videoEl } = entry;\n                if (clipsInBetween.has(clip.id)) continue;\n\n                const clipOffsetTime = (currentPlayhead - clip.startTime) * clip.speed + clip.trimIn;\n                syncPreviewVideo(clip, videoEl, clipOffsetTime, clip.id);\n\n                const startTrans = transitions.find((t) =>\n                  t.toClipId === clip.id &&\n                  t.fromClipId === 'none' &&\n                  currentPlayhead >= clip.startTime &&\n                  currentPlayhead <= clip.startTime + t.duration\n                );\n\n                const endTrans = transitions.find((t) =>\n                  t.fromClipId === clip.id &&\n                  t.toClipId === 'none' &&\n                  currentPlayhead >= (clip.startTime + clip.duration - t.duration) &&\n                  currentPlayhead <= (clip.startTime + clip.duration)\n                );\n\n                if (startTrans) {\n                  const colorType = startTrans.params.targetColor || (startTrans.type === 'fade-white' ? 'white' : 'black');\n                  const dummyCanvas = colorType === 'white' ? dummyWhiteCanvas : colorType === 'transparent' ? dummyTransparentCanvas : dummyBlackCanvas;\n                  const progress = (currentPlayhead - clip.startTime) / startTrans.duration;\n                  const clampedProgress = Math.max(0, Math.min(1, progress));\n                  const edgeReady =\n                    videoEl.readyState >= 2 &&\n                    !videoEl.seeking &&\n                    !pendingSeekByAssetIdRef.current.has(clip.assetId);\n                  if (\n                    pauseHoldTransitionFrame ||\n                    (!currentIsPlaying && !edgeReady && holdPreviewFrameRef.current)\n                  ) {\n                    continue;\n                  }\n                  if (edgeReady && dummyCanvas) {\n                    renderer.drawTransition(\n                      dummyCanvas,\n                      videoEl,\n                      startTrans.type,\n                      clampedProgress,\n                      canvas.width,\n                      canvas.height\n                    );\n                    paintedVideo = true;\n                  } else if (edgeReady) {\n                    renderer.drawLayer(videoEl, clip, clipOffsetTime, canvas.width, canvas.height);\n                    paintedVideo = true;\n                  }\n                  continue;\n                }\n\n                if (endTrans) {\n                  const colorType = endTrans.params.targetColor || (endTrans.type === 'fade-white' ? 'white' : 'black');\n                  const dummyCanvas = colorType === 'white' ? dummyWhiteCanvas : colorType === 'transparent' ? dummyTransparentCanvas : dummyBlackCanvas;\n                  const transStart = clip.startTime + clip.duration - endTrans.duration;\n                  const progress = (currentPlayhead - transStart) / endTrans.duration;\n                  const clampedProgress = Math.max(0, Math.min(1, progress));\n                  const edgeReady =\n                    videoEl.readyState >= 2 &&\n                    !videoEl.seeking &&\n                    !pendingSeekByAssetIdRef.current.has(clip.assetId);\n                  if (\n                    pauseHoldTransitionFrame ||\n                    (!currentIsPlaying && !edgeReady && holdPreviewFrameRef.current)\n                  ) {\n                    continue;\n                  }\n                  if (edgeReady && dummyCanvas) {\n                    renderer.drawTransition(\n                      videoEl,\n                      dummyCanvas,\n                      endTrans.type,\n                      clampedProgress,\n                      canvas.width,\n                      canvas.height\n                    );\n                    paintedVideo = true;\n                  } else if (edgeReady) {\n                    renderer.drawLayer(videoEl, clip, clipOffsetTime, canvas.width, canvas.height);\n                    paintedVideo = true;\n                  }\n                  continue;\n                }\n\n                if (videoEl.readyState >= 2) {\n                  renderer.drawLayer(videoEl, clip, clipOffsetTime, canvas.width, canvas.height);\n                  paintedVideo = true;\n                }\n              }\n              continue;\n            }\n\n            if (track.type === 'image') {\n              track.clips.forEach((clip) => {\n                if (!isOverlayVisibleAtPlayhead(clip, transitions, currentPlayhead)) return;\n                const imgEl = document.getElementById(`preview-media-${clip.assetId}`) as HTMLImageElement;\n                if (!imgEl || !imgEl.complete) return;\n                const clipOffsetTime = Math.max(\n                  0,\n                  Math.min(clip.duration, currentPlayhead - clip.startTime),\n                );\n                const motion = getMotionTransform(clip, clipOffsetTime);\n                const duration = clip.duration || 5.0;\n                const progressIn = clipOffsetTime;\n                const progressOut = duration - clipOffsetTime;\n                const animIn = clip.animationIn;\n                const animInDur = clip.animationInDuration || 0.5;\n                const animOut = clip.animationOut;\n                const animOutDur = clip.animationOutDuration || 0.5;\n                let opacity = clip.opacity !== undefined ? clip.opacity * motion.scale : motion.scale;\n                opacity *= getOverlayTransitionOpacity(clip, transitions, currentPlayhead);\n                let x = (clip.x ?? 0.5) + motion.xOffset;\n                let y = (clip.y ?? 0.5) + motion.yOffset;\n                let scaleX = clip.scaleX !== undefined ? clip.scaleX : 1.0;\n                let scaleY = clip.scaleY !== undefined ? clip.scaleY : 1.0;\n                let rotation = (clip.rotation || 0) + motion.rotationOffset;\n                let tempEffects = [...(clip.effects || [])];\n                if (animIn && progressIn < animInDur) {\n                  const t = progressIn / animInDur;\n                  if (animIn === 'fade') opacity *= t;\n                  else if (animIn === 'slide-up') { y += (1 - t) * 0.15; opacity *= t; }\n                  else if (animIn === 'slide-down') { y -= (1 - t) * 0.15; opacity *= t; }\n                  else if (animIn === 'slide-left') { x += (1 - t) * 0.15; opacity *= t; }\n                  else if (animIn === 'slide-right') { x -= (1 - t) * 0.15; opacity *= t; }\n                  else if (animIn === 'scale-in') { scaleX *= t; scaleY *= t; opacity *= t; }\n                  else if (animIn === 'blur-in') {\n                    opacity *= t;\n                    tempEffects.push({\n                      id: 'temp-blur-in', clipId: clip.id, effectType: 'blur-gaussian', enabled: true,\n                      order: tempEffects.length, keyframes: [], startTime: 0, endTime: clip.duration,\n                      params: { radius: (1 - t) * 20 },\n                    });\n                  } else if (animIn === 'rotate-in') { rotation += (1 - t) * 90; opacity *= t; }\n                }\n                if (animOut && progressOut < animOutDur) {\n                  const t = progressOut / animOutDur;\n                  if (animOut === 'fade') opacity *= t;\n                  else if (animOut === 'slide-up') { y -= (1 - t) * 0.15; opacity *= t; }\n                  else if (animOut === 'slide-down') { y += (1 - t) * 0.15; opacity *= t; }\n                  else if (animOut === 'slide-left') { x -= (1 - t) * 0.15; opacity *= t; }\n                  else if (animOut === 'slide-right') { x += (1 - t) * 0.15; opacity *= t; }\n                  else if (animOut === 'scale-out') { scaleX *= t; scaleY *= t; opacity *= t; }\n                  else if (animOut === 'blur-out') {\n                    opacity *= t;\n                    tempEffects.push({\n                      id: 'temp-blur-out', clipId: clip.id, effectType: 'blur-gaussian', enabled: true,\n                      order: tempEffects.length, keyframes: [], startTime: 0, endTime: clip.duration,\n                      params: { radius: (1 - t) * 20 },\n                    });\n                  }\n                }\n                renderer.drawLayer(\n                  imgEl,\n                  { ...clip, opacity, x, y, scaleX, scaleY, rotation, effects: tempEffects },\n                  clipOffsetTime,\n                  canvas.width,\n                  canvas.height,\n                );\n              });\n              continue;\n            }\n\n            if (track.type === 'text' && textCtx) {\n              let drew = false;\n              track.clips.forEach((clip) => {\n                if (!isOverlayVisibleAtPlayhead(clip, transitions, currentPlayhead)) return;\n                const clipOffsetTime = Math.max(\n                  0,\n                  Math.min(clip.duration, currentPlayhead - clip.startTime),\n                );\n                const transOpacity = getOverlayTransitionOpacity(clip, transitions, currentPlayhead);\n                const overlayClip =\n                  transOpacity < 1\n                    ? { ...clip, opacity: (clip.opacity ?? 1) * transOpacity }\n                    : clip;\n                drawTextClipToCanvas(\n                  textCtx,\n                  overlayClip,\n                  clipOffsetTime,\n                  textCanvas.width,\n                  textCanvas.height,\n                );\n                drew = true;\n              });\n              if (drew) flushTextOverlay(`text-${track.id}`);\n              continue;\n            }\n\n            if (track.type === 'subtitle' && textCtx) {\n              const activeSubtitle = track.clips.find((clip) =>\n                isOverlayVisibleAtPlayhead(clip, transitions, currentPlayhead),\n              );\n              if (activeSubtitle?.text) {\n                const clipOffsetTime = Math.max(\n                  0,\n                  Math.min(activeSubtitle.duration, currentPlayhead - activeSubtitle.startTime),\n                );\n                const transOpacity = getOverlayTransitionOpacity(\n                  activeSubtitle,\n                  transitions,\n                  currentPlayhead,\n                );\n                const overlayClip =\n                  transOpacity < 1\n                    ? {\n                        ...activeSubtitle,\n                        opacity: (activeSubtitle.opacity ?? 1) * transOpacity,\n                      }\n                    : activeSubtitle;\n                drawTextClipToCanvas(\n                  textCtx,\n                  overlayClip,\n                  clipOffsetTime,\n                  textCanvas.width,\n                  textCanvas.height,\n                );\n                flushTextOverlay(`sub-${track.id}`);\n              }\n            }\n          }\n\n          if (paintedVideo) {\n            holdPreviewFrameRef.current = true;\n            if (!currentIsPlaying) {\n              lastPaintedPausedPlayheadRef.current = currentPlayhead;\n            }\n          }\n\n          // Pause and mute all video elements that are not active\n          assets.forEach((asset) => {\n            if (asset.type === 'video') {\n              const isActive =\n                activeClips.some((ac) => ac.clip.assetId === asset.id) ||\n                betweenAssetIds.has(asset.id);\n              if (!isActive) {\n                const videoEl = document.getElementById(`preview-media-${asset.id}`) as HTMLVideoElement;\n                if (videoEl) {\n                  if (!videoEl.paused) videoEl.pause();\n                  videoEl.muted = true;\n                }\n              }\n            }\n          });\n\n        }\n      }\n\n      animationFrameId = requestAnimationFrame(renderTick);\n    };\n\n    renderTick();\n\n    return () => {\n      cancelAnimationFrame(animationFrameId);\n    };\n  }, [isPlaying, tracks, aspect, canvasWidth, canvasHeight, displaySize.width, displaySize.height, setPlayhead, transitions]);\n\n  const canvasDim = displaySize;\n\n  const handlePreviewPointerDown = useCallback(\n    (e: React.MouseEvent<HTMLDivElement>) => {\n      // Pan gestures (middle / Alt+drag) stay on capture handler\n      if (e.button !== 0 || e.altKey) return;\n\n      const frame = e.currentTarget;\n      const rect = frame.getBoundingClientRect();\n      if (rect.width <= 0 || rect.height <= 0) return;\n\n      // Map into unscaled CSS canvas coords (frame has zoom+offset transform)\n      const localX = ((e.clientX - rect.left) / rect.width) * canvasDim.cssWidth;\n      const localY = ((e.clientY - rect.top) / rect.height) * canvasDim.cssHeight;\n\n      const hit = hitTestPreviewClip(\n        tracks,\n        assets,\n        playheadTime,\n        localX,\n        localY,\n        canvasDim.cssWidth,\n        canvasDim.cssHeight,\n        canvasDim.width,\n        canvasDim.height,\n      );\n\n      if (hit) {\n        selectClip(hit.id, e.shiftKey);\n      } else {\n        clearSelection();\n      }\n    },\n    [\n      tracks,\n      assets,\n      playheadTime,\n      canvasDim.cssWidth,\n      canvasDim.cssHeight,\n      canvasDim.width,\n      canvasDim.height,\n      selectClip,\n      clearSelection,\n    ],\n  );\n\n  return (\n    <div\n      ref={rootRef}\n      className=\"relative flex h-full min-h-0 flex-1 flex-col items-center justify-between overflow-hidden bg-[#16161a] p-4 select-none border-b border-[#2A2A38]\"\n    >\n      {/* Hidden Asset Media Cache Elements */}\n      <div \n        style={{\n          position: 'fixed',\n          top: 0,\n          left: 0,\n          width: '1px',\n          height: '1px',\n          opacity: 0.001,\n          pointerEvents: 'none',\n          overflow: 'hidden',\n          zIndex: -100\n        }}\n      >\n        {assets.map((asset) => {\n          // Skip assets whose blob URL hasn't been recovered yet (e.g. right after reload)\n          if (!asset.url) return null;\n          if (asset.type === 'image') {\n            return (\n              <img\n                key={`${asset.id}-${asset.url}`}\n                id={`preview-media-${asset.id}`}\n                src={asset.url}\n                alt={asset.name}\n                className=\"max-w-none h-auto\"\n              />\n            );\n          }\n          return (\n            <video\n              key={`${asset.id}-${asset.url}`}\n              id={`preview-media-${asset.id}`}\n              src={asset.url}\n              preload=\"auto\"\n              muted={true}\n              playsInline\n              className=\"max-w-none h-auto\"\n            />\n          );\n        })}\n      </div>\n\n\n\n      {/* Interactive Bounding Frame wrapper */}\n      <div\n        ref={containerRef}\n        className=\"flex min-h-0 w-full flex-1 items-center justify-center overflow-hidden\"\n        onMouseDownCapture={handlePanStart}\n        onMouseDown={(e) => {\n          // Click on the letterbox around the frame deselects\n          if (e.target === e.currentTarget) clearSelection();\n        }}\n        style={{ cursor: canvasZoom > 1 ? 'grab' : 'default' }}\n      >\n        <div\n          className=\"relative shadow-2xl rounded overflow-visible border border-[#2A2A38]/50\"\n          onMouseDown={handlePreviewPointerDown}\n          style={{\n            transform: `scale(${canvasZoom}) translate(${canvasOffset.x / canvasZoom}px, ${canvasOffset.y / canvasZoom}px)`,\n            transformOrigin: 'center center',\n            transition: isPanningRef.current ? 'none' : 'transform 0.1s ease-out',\n          }}\n        >\n          <canvas\n            id=\"we-video-preview-canvas\"\n            ref={canvasRef}\n            width={canvasDim.width}\n            height={canvasDim.height}\n            className=\"block bg-[#0A0A0F]\"\n            style={{\n              width: canvasDim.cssWidth,\n              height: canvasDim.cssHeight,\n            }}\n          />\n          \n          {/* CropTool Floating coordinate overlays handles */}\n          {selectedClipIds.length > 0 && (\n            <CropTool\n              clipId={selectedClipIds[0]}\n              canvasWidth={canvasDim.cssWidth}\n              canvasHeight={canvasDim.cssHeight}\n              bufferWidth={canvasDim.width}\n              bufferHeight={canvasDim.height}\n            />\n          )}\n\n          {(aiSubtitleJob || aiBusyToolId) && (\n            <div className=\"pointer-events-none absolute inset-x-3 bottom-3 z-30\">\n              <SubtitleAiLoader\n                variant=\"card\"\n                label={\n                  aiSubtitleJob?.kind === 'generate'\n                    ? tTimeline.generatingSubtitles\n                    : aiSubtitleJob?.kind === 'translate'\n                      ? tTimeline.translatingSubtitles\n                      : aiSubtitleJob?.kind === 'style'\n                        ? tTimeline.stylingSubtitles\n                        : aiSubtitleJob?.kind === 'voiceover'\n                          ? tTimeline.generatingVoiceover\n                          : aiSubtitleJob?.kind === 'copy'\n                            ? tTimeline.generatingCopy\n                            : aiSubtitleJob?.kind === 'clipEdit'\n                              ? aiSubtitleJob.label\n                              : tmAi.statusWorking\n                }\n                hint={tmAi.previewGeneratingHint}\n              />\n            </div>\n          )}\n        </div>\n      </div>\n\n      {/* Playback Controls \u2014 loop left of transport, fullscreen on the right */}\n      <div className=\"z-10 flex shrink-0 select-none items-center gap-3 rounded-full border border-[#2A2A38] bg-[#13131A] px-5 py-2 shadow-lg\">\n        <div className=\"flex items-center gap-3\">\n          <button\n            type=\"button\"\n            onClick={() => setIsLooping((v) => !v)}\n            aria-label={tp.loop}\n            aria-pressed={isLooping}\n            title={tp.loop}\n            className={`rounded-lg p-1.5 transition-colors ${\n              isLooping\n                ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)]'\n                : 'text-[#8888A0] hover:text-[#F0F0F5]'\n            }`}\n          >\n            <Repeat size={15} />\n          </button>\n\n          <span className=\"mx-0.5 h-4 w-px bg-[#2A2A38]\" aria-hidden />\n\n          <button\n            type=\"button\"\n            onClick={() => setPlayhead(0)}\n            aria-label={tp.toStart}\n            title={tp.toStart}\n            className=\"p-1 text-[#8888A0] transition-colors hover:text-[#F0F0F5]\"\n          >\n            <ChevronsLeft size={16} />\n          </button>\n\n          <button\n            type=\"button\"\n            onClick={() => setPlayhead(Math.max(0, playheadTime - 1))}\n            aria-label={tp.rewind}\n            title={tp.rewind}\n            className=\"p-1 text-[#8888A0] transition-colors hover:text-[#F0F0F5]\"\n          >\n            <Rewind size={16} />\n          </button>\n\n          <button\n            type=\"button\"\n            onClick={() => setIsPlaying(!isPlaying)}\n            aria-label={isPlaying ? tp.pause : tp.play}\n            title={isPlaying ? tp.pause : tp.play}\n            className=\"flex h-9 w-9 items-center justify-center rounded-full bg-[var(--we-accent)] text-white shadow-md shadow-[color-mix(in_srgb,var(--we-accent)_30%,transparent)] transition-all hover:scale-105 hover:bg-[var(--we-accent-hover)] active:scale-95\"\n          >\n            {isPlaying ? (\n              <Pause size={15} fill=\"currentColor\" />\n            ) : (\n              <Play size={15} fill=\"currentColor\" className=\"ml-0.5\" />\n            )}\n          </button>\n\n          <button\n            type=\"button\"\n            onClick={() => setPlayhead(Math.min(projectDuration, playheadTime + 1))}\n            aria-label={tp.forward}\n            title={tp.forward}\n            className=\"p-1 text-[#8888A0] transition-colors hover:text-[#F0F0F5]\"\n          >\n            <FastForward size={16} />\n          </button>\n\n          <button\n            type=\"button\"\n            onClick={() => setPlayhead(projectDuration)}\n            aria-label={tp.toEnd}\n            title={tp.toEnd}\n            className=\"p-1 text-[#8888A0] transition-colors hover:text-[#F0F0F5]\"\n          >\n            <ChevronsRight size={16} />\n          </button>\n\n          <span className=\"mx-0.5 h-4 w-px bg-[#2A2A38]\" aria-hidden />\n\n          <button\n            type=\"button\"\n            onClick={handleToggleFullscreen}\n            aria-label={isPreviewFullscreen ? tp.exitFullscreen : tp.fullscreen}\n            title={isPreviewFullscreen ? tp.exitFullscreen : tp.fullscreen}\n            className=\"p-1.5 text-[#8888A0] transition-colors hover:text-[#F0F0F5]\"\n          >\n            {isPreviewFullscreen ? <Minimize size={15} /> : <Maximize size={15} />}\n          </button>\n        </div>\n      </div>\n\n    </div>\n  );\n};\nexport default VideoPreview;\n", "import type { TransitionClip } from '../../store/useVideoStore';\n\ntype ClipTiming = {\n  id: string;\n  startTime: number;\n  duration: number;\n};\n\nfunction clamp01(n: number): number {\n  return Math.max(0, Math.min(1, n));\n}\n\n/** Centered between-transition window on the cut after `fromClip`. */\nexport function getBetweenTransitionWindow(\n  fromClip: ClipTiming,\n  duration: number,\n): { cut: number; start: number; end: number } {\n  const cut = fromClip.startTime + fromClip.duration;\n  return {\n    cut,\n    start: cut - duration / 2,\n    end: cut + duration / 2,\n  };\n}\n\n/**\n * Keep overlay drawn for the full between window: outgoing past its end,\n * incoming before its start.\n */\nexport function isOverlayVisibleAtPlayhead(\n  clip: ClipTiming,\n  transitions: TransitionClip[],\n  playhead: number,\n): boolean {\n  if (playhead >= clip.startTime && playhead < clip.startTime + clip.duration) {\n    return true;\n  }\n\n  for (const t of transitions) {\n    if (t.toClipId === 'none' || t.fromClipId === 'none') continue;\n\n    if (t.fromClipId === clip.id) {\n      const { end } = getBetweenTransitionWindow(clip, t.duration);\n      if (playhead >= clip.startTime + clip.duration && playhead <= end) return true;\n    }\n\n    if (t.toClipId === clip.id) {\n      const start = clip.startTime - t.duration / 2;\n      if (playhead >= start && playhead < clip.startTime) return true;\n    }\n  }\n\n  return false;\n}\n\n/**\n * Opacity multiplier (0\u20131) for image/text/subtitle overlays during a\n * transition. Full-frame WebGL wipes still apply to video; overlays use\n * dissolve-style opacity so placement (x/y/scale) stays intact.\n */\nexport function getOverlayTransitionOpacity(\n  clip: ClipTiming,\n  transitions: TransitionClip[],\n  playhead: number,\n): number {\n  const betweenOut = transitions.find(\n    (t) =>\n      t.fromClipId === clip.id &&\n      t.toClipId !== 'none' &&\n      playhead >= clip.startTime + clip.duration - t.duration / 2 &&\n      playhead <= clip.startTime + clip.duration + t.duration / 2,\n  );\n  if (betweenOut) {\n    const start = clip.startTime + clip.duration - betweenOut.duration / 2;\n    return 1 - clamp01((playhead - start) / betweenOut.duration);\n  }\n\n  const betweenIn = transitions.find(\n    (t) =>\n      t.toClipId === clip.id &&\n      t.fromClipId !== 'none' &&\n      playhead >= clip.startTime - t.duration / 2 &&\n      playhead <= clip.startTime + t.duration / 2,\n  );\n  if (betweenIn) {\n    const start = clip.startTime - betweenIn.duration / 2;\n    return clamp01((playhead - start) / betweenIn.duration);\n  }\n\n  const startTrans = transitions.find(\n    (t) =>\n      t.toClipId === clip.id &&\n      t.fromClipId === 'none' &&\n      playhead >= clip.startTime &&\n      playhead <= clip.startTime + t.duration,\n  );\n  if (startTrans) {\n    return clamp01((playhead - clip.startTime) / startTrans.duration);\n  }\n\n  const endTrans = transitions.find(\n    (t) =>\n      t.fromClipId === clip.id &&\n      t.toClipId === 'none' &&\n      playhead >= clip.startTime + clip.duration - t.duration &&\n      playhead <= clip.startTime + clip.duration,\n  );\n  if (endTrans) {\n    const start = clip.startTime + clip.duration - endTrans.duration;\n    return 1 - clamp01((playhead - start) / endTrans.duration);\n  }\n\n  return 1;\n}\n", "import React, { useRef, useState, useEffect, useMemo } from 'react';\nimport {\n  PREVIEW_IMAGE_BOX as IMAGE_BOX,\n  fittedImageBox,\n  measureTextClipUnscaledBox,\n} from '../../../utils/previewHitTest';\nimport { useVideoStore } from '../../../store/useVideoStore';\n\ninterface CropToolProps {\n  clipId: string;\n  /** CSS display size of the preview canvas (overlay coordinate space). */\n  canvasWidth: number;\n  canvasHeight: number;\n  /** WebGL drawing-buffer size (image box of 200px is defined in this space). */\n  bufferWidth: number;\n  bufferHeight: number;\n}\n\n/** Normalized snap threshold (~2.5% of canvas). */\nconst PREVIEW_SNAP = 0.025;\n\nfunction snapToNearest(\n  value: number,\n  targets: number[],\n  threshold: number,\n): { value: number; snapped: boolean; guide?: number } {\n  let best = value;\n  let bestDist = threshold;\n  let snapped = false;\n  for (const t of targets) {\n    const d = Math.abs(value - t);\n    if (d < bestDist) {\n      bestDist = d;\n      best = t;\n      snapped = true;\n    }\n  }\n  return snapped ? { value: best, snapped: true, guide: best } : { value, snapped: false };\n}\n\nexport const CropTool: React.FC<CropToolProps> = ({\n  clipId,\n  canvasWidth,\n  canvasHeight,\n  bufferWidth,\n  bufferHeight,\n}) => {\n  const { tracks, assets, updateClipProperties, snapEnabled } = useVideoStore();\n  const overlayRef = useRef<HTMLDivElement>(null);\n  const [isDragging, setIsDragging] = useState(false);\n  const [dragMode, setDragMode] = useState<\n    'translate' | 'resize-br' | 'resize-tr' | 'resize-bl' | 'resize-tl' | 'rotate'\n  >('translate');\n  const [startPos, setStartPos] = useState({ x: 0, y: 0 });\n  const [startProps, setStartProps] = useState({ x: 0.5, y: 0.5, scaleX: 1, scaleY: 1, rotation: 0 });\n  const [guides, setGuides] = useState<{ v?: number; h?: number } | null>(null);\n  /** Bump after webfont load so text/subtitle boxes remasure with real metrics. */\n  const [fontEpoch, setFontEpoch] = useState(0);\n\n  const clip = useMemo(() => {\n    for (const track of tracks) {\n      const found = track.clips.find((c) => c.id === clipId);\n      if (found) return found;\n    }\n    return null;\n  }, [tracks, clipId]);\n\n  const asset = useMemo(\n    () => (clip ? assets.find((a) => a.id === clip.assetId) : undefined),\n    [assets, clip],\n  );\n\n  useEffect(() => {\n    if (!clip || (clip.type !== 'text' && clip.type !== 'subtitle')) return;\n    const family = clip.fontFamily || 'Inter';\n    const weight = clip.fontWeight || 500;\n    const size = clip.fontSize || 48;\n    const style = clip.fontStyle || 'normal';\n    let cancelled = false;\n    const run = async () => {\n      try {\n        if (document.fonts?.load) {\n          await document.fonts.load(`${style} ${weight} ${size}px \"${family}\"`);\n        }\n      } catch {\n        /* ignore missing faces */\n      }\n      if (!cancelled) setFontEpoch((n) => n + 1);\n    };\n    void run();\n    return () => {\n      cancelled = true;\n    };\n  }, [\n    clip?.id,\n    clip?.type,\n    clip?.fontFamily,\n    clip?.fontWeight,\n    clip?.fontSize,\n    clip?.fontStyle,\n    clip?.text,\n  ]);\n\n  const baseBox = useMemo(() => {\n    if (!clip) return { w: IMAGE_BOX, h: IMAGE_BOX };\n    if (clip.type === 'text' || clip.type === 'subtitle') {\n      return measureTextClipUnscaledBox(clip);\n    }\n    if (clip.type === 'image') {\n      const srcW = asset?.width || 0;\n      const srcH = asset?.height || 0;\n      return fittedImageBox(srcW, srcH, clip.fitMode);\n    }\n    // Video: match WebGL fit (NDC scale \u00D7 buffer size)\n    let baseScaleX = 1;\n    let baseScaleY = 1;\n    // Prefer live media intrinsic size when asset metadata is missing\n    let srcW = asset?.width || 0;\n    let srcH = asset?.height || 0;\n    if (!(srcW > 0 && srcH > 0) && asset) {\n      const el = document.getElementById(`preview-media-${asset.id}`);\n      if (el instanceof HTMLVideoElement && el.videoWidth > 0) {\n        srcW = el.videoWidth;\n        srcH = el.videoHeight;\n      }\n    }\n    if (srcW > 0 && srcH > 0 && bufferWidth > 0 && bufferHeight > 0) {\n      const imageAspect = srcW / srcH;\n      const canvasAspect = bufferWidth / bufferHeight;\n      const fitMode = clip.fitMode || 'fit';\n      if (fitMode === 'fit') {\n        if (imageAspect > canvasAspect) {\n          baseScaleX = 1;\n          baseScaleY = canvasAspect / imageAspect;\n        } else {\n          baseScaleX = imageAspect / canvasAspect;\n          baseScaleY = 1;\n        }\n      } else if (fitMode === 'crop') {\n        if (imageAspect > canvasAspect) {\n          baseScaleX = imageAspect / canvasAspect;\n          baseScaleY = 1;\n        } else {\n          baseScaleX = 1;\n          baseScaleY = canvasAspect / imageAspect;\n        }\n      }\n    }\n    return { w: baseScaleX * bufferWidth, h: baseScaleY * bufferHeight };\n  }, [clip, asset, bufferWidth, bufferHeight, fontEpoch]);\n\n  // WebGL sizes the image/video box in buffer pixels; overlay lives in CSS pixels.\n  const bufferToCssX = bufferWidth > 0 ? canvasWidth / bufferWidth : 1;\n  const bufferToCssY = bufferHeight > 0 ? canvasHeight / bufferHeight : 1;\n\n  useEffect(() => {\n    if (!clip || clip.type === 'audio') return;\n\n    const handleMouseMove = (e: MouseEvent) => {\n      if (!isDragging || !overlayRef.current) return;\n\n      const deltaX = e.clientX - startPos.x;\n      const deltaY = e.clientY - startPos.y;\n\n      if (dragMode === 'translate') {\n        const normDeltaX = deltaX / canvasWidth;\n        const normDeltaY = deltaY / canvasHeight;\n        let nx = Math.max(-0.5, Math.min(1.5, startProps.x + normDeltaX));\n        let ny = Math.max(-0.5, Math.min(1.5, startProps.y + normDeltaY));\n\n        if (snapEnabled && canvasWidth > 0 && canvasHeight > 0) {\n          const halfW =\n            (baseBox.w * startProps.scaleX * bufferToCssX) / (2 * canvasWidth);\n          const halfH =\n            (baseBox.h * startProps.scaleY * bufferToCssY) / (2 * canvasHeight);\n\n          const xTargets = [0.5, halfW, 1 - halfW];\n          const yTargets = [0.5, halfH, 1 - halfH];\n\n          for (const track of tracks) {\n            for (const other of track.clips) {\n              if (other.id === clipId) continue;\n              if (other.type === 'audio') continue;\n              if (typeof other.x === 'number') xTargets.push(other.x);\n              if (typeof other.y === 'number') yTargets.push(other.y);\n            }\n          }\n\n          const sx = snapToNearest(nx, xTargets, PREVIEW_SNAP);\n          const sy = snapToNearest(ny, yTargets, PREVIEW_SNAP);\n          nx = sx.value;\n          ny = sy.value;\n          setGuides({\n            v: sx.guide,\n            h: sy.guide,\n          });\n        } else {\n          setGuides(null);\n        }\n\n        updateClipProperties(clipId, { x: nx, y: ny });\n      } else if (dragMode === 'rotate') {\n        const rect = overlayRef.current.getBoundingClientRect();\n        const cx = (clip.x ?? 0.5) * canvasWidth;\n        const cy = (clip.y ?? 0.5) * canvasHeight;\n        const scale =\n          canvasWidth > 0 ? rect.width / canvasWidth : 1;\n        const rectCenterX = rect.left + cx * scale;\n        const rectCenterY = rect.top + cy * scale;\n\n        const dx = e.clientX - rectCenterX;\n        const dy = e.clientY - rectCenterY;\n        const angleRad = Math.atan2(dy, dx);\n        let angleDeg = (angleRad * 180) / Math.PI + 90;\n        angleDeg = (angleDeg + 360) % 360;\n\n        updateClipProperties(clipId, {\n          rotation: Math.round(angleDeg),\n        });\n      } else {\n        // Project pointer delta into the clip's local axes (CSS Y-down + rotate()).\n        const rotRad = ((startProps.rotation || 0) * Math.PI) / 180;\n        const cos = Math.cos(rotRad);\n        const sin = Math.sin(rotRad);\n        const localDx = deltaX * cos + deltaY * sin;\n        const localDy = -deltaX * sin + deltaY * cos;\n\n        let factorX = 1;\n        let factorY = 1;\n        const bw = baseBox.w * bufferToCssX;\n        const bh = baseBox.h * bufferToCssY;\n\n        if (dragMode === 'resize-br') {\n          factorX = 1 + (localDx * 2) / (bw * startProps.scaleX);\n          factorY = 1 + (localDy * 2) / (bh * startProps.scaleY);\n        } else if (dragMode === 'resize-bl') {\n          factorX = 1 - (localDx * 2) / (bw * startProps.scaleX);\n          factorY = 1 + (localDy * 2) / (bh * startProps.scaleY);\n        } else if (dragMode === 'resize-tr') {\n          factorX = 1 + (localDx * 2) / (bw * startProps.scaleX);\n          factorY = 1 - (localDy * 2) / (bh * startProps.scaleY);\n        } else if (dragMode === 'resize-tl') {\n          factorX = 1 - (localDx * 2) / (bw * startProps.scaleX);\n          factorY = 1 - (localDy * 2) / (bh * startProps.scaleY);\n        }\n\n        const uniformFactor = Math.max(factorX, factorY);\n        // Clamp absolute scale (not relative factor) so a continuous drag can grow past 5\u00D7 start\n        const SCALE_MIN = 0.05;\n        const SCALE_MAX = 40;\n        const nextScale = Math.max(\n          SCALE_MIN,\n          Math.min(SCALE_MAX, startProps.scaleX * uniformFactor),\n        );\n\n        updateClipProperties(clipId, {\n          scaleX: nextScale,\n          scaleY: nextScale,\n        });\n      }\n    };\n\n    const handleMouseUp = () => {\n      setIsDragging(false);\n      setGuides(null);\n    };\n\n    if (isDragging) {\n      window.addEventListener('mousemove', handleMouseMove);\n      window.addEventListener('mouseup', handleMouseUp);\n    }\n\n    return () => {\n      window.removeEventListener('mousemove', handleMouseMove);\n      window.removeEventListener('mouseup', handleMouseUp);\n    };\n  }, [\n    isDragging,\n    dragMode,\n    startPos,\n    startProps,\n    canvasWidth,\n    canvasHeight,\n    bufferToCssX,\n    bufferToCssY,\n    clipId,\n    clip,\n    baseBox,\n    updateClipProperties,\n    snapEnabled,\n    tracks,\n  ]);\n\n  if (!clip || clip.type === 'audio') {\n    return null;\n  }\n\n  const cx = (clip.x ?? 0.5) * canvasWidth;\n  const cy = (clip.y ?? 0.5) * canvasHeight;\n  const w = baseBox.w * (clip.scaleX ?? 1.0) * bufferToCssX;\n  const h = baseBox.h * (clip.scaleY ?? 1.0) * bufferToCssY;\n  const rectLeft = cx - w / 2;\n  const rectTop = cy - h / 2;\n\n  const handleMouseDown = (mode: typeof dragMode, e: React.MouseEvent) => {\n    if (e.button === 1) return;\n    e.stopPropagation();\n    e.preventDefault();\n    setIsDragging(true);\n    setDragMode(mode);\n    setStartPos({ x: e.clientX, y: e.clientY });\n    setStartProps({\n      x: clip.x ?? 0.5,\n      y: clip.y ?? 0.5,\n      scaleX: clip.scaleX ?? 1.0,\n      scaleY: clip.scaleY ?? 1.0,\n      rotation: clip.rotation || 0,\n    });\n  };\n\n  return (\n    <div\n      ref={overlayRef}\n      className=\"absolute pointer-events-none\"\n      style={{\n        left: 0,\n        top: 0,\n        width: canvasWidth,\n        height: canvasHeight,\n      }}\n    >\n      {guides?.v != null && (\n        <div\n          className=\"absolute top-0 bottom-0 w-px bg-[var(--we-accent)] pointer-events-none opacity-80\"\n          style={{ left: guides.v * canvasWidth }}\n        />\n      )}\n      {guides?.h != null && (\n        <div\n          className=\"absolute left-0 right-0 h-px bg-[var(--we-accent)] pointer-events-none opacity-80\"\n          style={{ top: guides.h * canvasHeight }}\n        />\n      )}\n      <div\n        className=\"absolute pointer-events-auto border-2 border-[var(--we-accent)] bg-[color-mix(in_srgb,var(--we-accent)_18%,transparent)] cursor-move group select-none\"\n        style={{\n          left: rectLeft,\n          top: rectTop,\n          width: w,\n          height: h,\n          transform: `rotate(${clip.rotation ?? 0}deg)`,\n          transformOrigin: 'center center',\n        }}\n        onMouseDown={(e) => {\n          if (e.button === 1) return;\n          handleMouseDown('translate', e);\n        }}\n      >\n        <div\n          onMouseDown={(e) => handleMouseDown('rotate', e)}\n          title=\"Drag to rotate\"\n          className=\"absolute left-1/2 -top-6 -translate-x-1/2 w-3.5 h-3.5 bg-white border-2 border-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] hover:scale-125 rounded-full cursor-grab active:cursor-grabbing flex items-center justify-center pointer-events-auto transition-transform\"\n        >\n          <div className=\"absolute top-3.5 h-3 w-0.5 bg-[var(--we-accent)]\" />\n        </div>\n        <div\n          onMouseDown={(e) => handleMouseDown('resize-tl', e)}\n          className=\"absolute -left-1.5 -top-1.5 h-3.5 w-3.5 rounded-full border-2 border-[var(--we-accent)] bg-white cursor-nwse-resize pointer-events-auto transition-transform hover:scale-125\"\n        />\n        <div\n          onMouseDown={(e) => handleMouseDown('resize-tr', e)}\n          className=\"absolute -right-1.5 -top-1.5 h-3.5 w-3.5 rounded-full border-2 border-[var(--we-accent)] bg-white cursor-nesw-resize pointer-events-auto transition-transform hover:scale-125\"\n        />\n        <div\n          onMouseDown={(e) => handleMouseDown('resize-bl', e)}\n          className=\"absolute -left-1.5 -bottom-1.5 h-3.5 w-3.5 rounded-full border-2 border-[var(--we-accent)] bg-white cursor-nesw-resize pointer-events-auto transition-transform hover:scale-125\"\n        />\n        <div\n          onMouseDown={(e) => handleMouseDown('resize-br', e)}\n          className=\"absolute -right-1.5 -bottom-1.5 h-3.5 w-3.5 rounded-full border-2 border-[var(--we-accent)] bg-white cursor-nwse-resize pointer-events-auto transition-transform hover:scale-125\"\n        />\n      </div>\n    </div>\n  );\n};\n\nexport default CropTool;\n", "import React, { useCallback, useState } from 'react';\nimport {\n  Settings2,\n  Shuffle,\n  Sparkles,\n  Type,\n  RotateCcw,\n} from 'lucide-react';\nimport { PropertiesPanel } from './PropertiesPanel';\nimport { EffectsPanel } from './effects/EffectsPanel';\nimport { TransitionPanel } from './transitions/TransitionPanel';\nimport { TextPanel } from './text/TextPanel';\nimport { TransitionJunctionModal } from './transitions/TransitionJunctionModal';\nimport { useTranslation } from '../../i18n';\nimport { IconButton, TextTitle } from '../ui';\nimport {\n  useVideoUiStore,\n  type VideoRightPanelId,\n} from '../../store/useVideoUiStore';\n\nconst DEFAULT_WIDTH = 320;\nconst MIN_WIDTH = 260;\nconst MAX_WIDTH = 480;\n\nconst RAIL: {\n  id: VideoRightPanelId;\n  icon: React.ReactNode;\n  labelKey: 'inspector' | 'transitions' | 'effects' | 'text';\n}[] = [\n  { id: 'inspector', icon: <Settings2 size={17} />, labelKey: 'inspector' },\n  { id: 'transitions', icon: <Shuffle size={17} />, labelKey: 'transitions' },\n  { id: 'effects', icon: <Sparkles size={17} />, labelKey: 'effects' },\n  { id: 'text', icon: <Type size={17} />, labelKey: 'text' },\n];\n\nfunction PanelContent({ id }: { id: VideoRightPanelId }) {\n  switch (id) {\n    case 'inspector':\n      return <PropertiesPanel />;\n    case 'transitions':\n      return <TransitionPanel />;\n    case 'effects':\n      return <EffectsPanel />;\n    case 'text':\n      return <TextPanel />;\n  }\n}\n\n/**\n * Video right dock: content for the selected clip/tool + thin icon rail.\n * Default opens Inspector so the 3-column shell shows selected-clip props.\n */\nexport const RightSidebar: React.FC = () => {\n  const t = useTranslation();\n  const activePanel = useVideoUiStore((s) => s.rightPanel);\n  const toggleRightPanel = useVideoUiStore((s) => s.toggleRightPanel);\n  const [panelWidth, setPanelWidth] = useState(DEFAULT_WIDTH);\n\n  const isResized = panelWidth !== DEFAULT_WIDTH;\n\n  const onResizeStart = useCallback(\n    (e: React.MouseEvent) => {\n      e.preventDefault();\n      const startX = e.clientX;\n      const startW = panelWidth;\n      const onMove = (ev: MouseEvent) => {\n        setPanelWidth(Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, startW + (startX - ev.clientX))));\n      };\n      const onUp = () => {\n        window.removeEventListener('mousemove', onMove);\n        window.removeEventListener('mouseup', onUp);\n      };\n      window.addEventListener('mousemove', onMove);\n      window.addEventListener('mouseup', onUp);\n    },\n    [panelWidth],\n  );\n\n  const titleKey = RAIL.find((p) => p.id === activePanel)?.labelKey ?? 'inspector';\n\n  return (\n    <aside className=\"flex h-full min-h-0 shrink-0 select-none border-l border-panel-border bg-panel\">\n      {activePanel && (\n        <div\n          className=\"relative flex h-full min-h-0 flex-col\"\n          style={{ width: panelWidth }}\n        >\n          <div\n            role=\"separator\"\n            aria-orientation=\"vertical\"\n            aria-label={t.panel.resizeWidth}\n            onMouseDown={onResizeStart}\n            className=\"absolute inset-y-0 left-0 z-10 w-1.5 cursor-ew-resize group/hresize\"\n          >\n            <div className=\"absolute inset-y-0 left-0 w-0.5 rounded-r-full bg-transparent transition-colors group-hover/hresize:bg-[var(--we-accent-capsule)]\" />\n          </div>\n\n          <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-panel-border px-3 py-2 pl-4\">\n            <TextTitle as=\"h2\" size=\"xs\" className=\"uppercase tracking-wider\">\n              {t.panel[titleKey]}\n            </TextTitle>\n            <IconButton\n              size=\"sm\"\n              variant=\"ghost\"\n              disabled={!isResized}\n              label={t.panel.resetSize}\n              onClick={() => setPanelWidth(DEFAULT_WIDTH)}\n              className={!isResized ? 'opacity-30 pointer-events-none' : ''}\n            >\n              <RotateCcw size={12} />\n            </IconButton>\n          </div>\n\n          <div className=\"min-h-0 flex-1 overflow-y-auto overflow-x-hidden\">\n            <PanelContent id={activePanel} />\n          </div>\n        </div>\n      )}\n\n      <div className=\"flex w-11 shrink-0 flex-col items-center gap-1.5 border-l border-panel-border bg-panel py-2\">\n        {RAIL.map((panel) => {\n          const isActive = activePanel === panel.id;\n          return (\n            <button\n              key={panel.id}\n              type=\"button\"\n              title={t.panel[panel.labelKey]}\n              onClick={() => toggleRightPanel(panel.id)}\n              className={`\n                relative flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg\n                transition-all duration-150 active:scale-90\n                ${\n                  isActive\n                    ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--we-accent)_35%,transparent)]'\n                    : 'text-white/80 hover:bg-black-capsule hover:text-white'\n                }\n              `}\n            >\n              {isActive && (\n                <span className=\"absolute right-0 top-1/2 h-4 w-0.5 -translate-y-1/2 rounded-l-full bg-[var(--we-accent)]\" />\n              )}\n              {panel.icon}\n            </button>\n          );\n        })}\n      </div>\n\n      <TransitionJunctionModal />\n    </aside>\n  );\n};\n\nexport default RightSidebar;\n", "import React, { useState, useRef } from 'react';\nimport { useVideoStore } from '../../store/useVideoStore';\nimport { formatTimecode } from '../../utils/timelineUtils';\nimport {\n  Button,\n  PanelBody,\n  PanelSection,\n  PanelField,\n  SelectDropdown,\n  Switch,\n  ColorInput,\n  FontPickerFlyout,\n  SubtitleAiLoader,\n  TextBody,\n} from '../ui';\nimport type { FontPickerEntry } from '../ui';\nimport { loadGoogleFont } from './text/FontPicker';\nimport { GOOGLE_FONTS_CATALOG } from '../Sidebar';\nimport { useTranslation } from '../../i18n';\nimport { ColorGradingPanel } from './images/ColorGradingPanel';\nimport { EffectStack } from './effects/EffectStack';\nimport {\n  translateSubtitles,\n  generateSubtitleStylePreset,\n  generateColorGradingPreset,\n  type ColorGradingPreset,\n} from '../../services/aiService';\nimport {\n\n  Sliders,\n  Layers,\n  Palette,\n  AlignLeft,\n  AlignCenter,\n  AlignRight,\n  Italic,\n  Underline,\n  Move,\n  Sparkles,\n  Loader,\n  ChevronDown,\n} from 'lucide-react';\n\ntype ActiveTab = 'layout' | 'color' | 'effects';\n\nconst GRADIENT_DEFAULT_A = '#EA580C';\nconst GRADIENT_DEFAULT_B = '#FF4081';\n\nconst pct = (v: number) => `${Math.round(v * 100)}%`;\nconst px = (v: number) => `${v}px`;\nconst deg = (v: number) => `${v}\u00B0`;\nconst sec = (v: number) => `${v.toFixed(1)}s`;\n\nconst segmentActive = 'bg-[var(--we-accent-capsule)] text-white';\nconst segmentIdle = 'text-white/80 hover:text-white';\nconst segmentBtn = (on: boolean) =>\n  `flex-1 cursor-pointer rounded-lg py-1.5 flex items-center justify-center transition-colors ${\n    on ? segmentActive : segmentIdle\n  }`;\n\nconst swatchClass =\n  'h-6 w-8 cursor-pointer rounded border-0 bg-transparent';\n\nconst fieldInputClass =\n  'w-24 bg-transparent text-right font-mono text-[11px] font-medium text-ink-primary focus:outline-none';\n\nconst textAreaClass =\n  'w-full resize-none rounded-xl bg-black-capsule px-2.5 py-2 font-sans text-xs font-medium text-ink-primary placeholder:text-white/40 focus:outline-none focus:ring-1 focus:ring-[var(--we-accent)]/50';\n\nconst promptInputClass =\n  'w-full rounded-xl bg-black-capsule px-2.5 py-2 font-sans text-xs font-medium text-ink-primary placeholder:text-white/40 focus:outline-none focus:ring-1 focus:ring-[var(--we-accent)]/50';\n\nexport const PropertiesPanel: React.FC = () => {\n  const t = useTranslation();\n  const tp = t.videoEditor.propertiesPanel;\n  const {\n    tracks,\n    selectedClipIds,\n    updateClipProperties,\n    updateColorGrading,\n  } = useVideoStore();\n  const [activeTab, setActiveTab] = useState<ActiveTab>('layout');\n\n  const [targetLang, setTargetLang] = useState('English');\n  const [isTranslating, setIsTranslating] = useState(false);\n  const [stylePrompt, setStylePrompt] = useState('');\n  const [isStyling, setIsStyling] = useState(false);\n  const [aiError, setAiError] = useState<string | null>(null);\n\n  const [textStylePrompt, setTextStylePrompt] = useState('');\n  const [isStylingText, setIsStylingText] = useState(false);\n  const [aiTextError, setAiTextError] = useState<string | null>(null);\n\n  const [imageGradingPrompt, setImageGradingPrompt] = useState('');\n  const [isGradingImage, setIsGradingImage] = useState(false);\n  const [aiImageGradingError, setAiImageGradingError] = useState<string | null>(null);\n  const [isFontDropdownOpen, setIsFontDropdownOpen] = useState(false);\n  const fontTriggerRef = useRef<HTMLButtonElement | null>(null);\n  const fontCommitRef = useRef('Inter');\n\n  let selectedClip: any = null;\n  for (const track of tracks) {\n    const found = track.clips.find((c) => selectedClipIds.includes(c.id));\n    if (found) {\n      selectedClip = found;\n      break;\n    }\n  }\n\n  const handleTranslateAllSubtitles = async () => {\n    const subtitleClips: { id: string; text: string }[] = [];\n    tracks.forEach((tr) => {\n      tr.clips.forEach((c) => {\n        if (c.type === 'subtitle' && c.text) {\n          subtitleClips.push({ id: c.id, text: c.text });\n        }\n      });\n    });\n\n    if (subtitleClips.length === 0) {\n      setAiError(tp.noSubtitlesError);\n      return;\n    }\n\n    setIsTranslating(true);\n    setAiError(null);\n    useVideoStore.getState().setAiSubtitleJob({\n      kind: 'translate',\n      clipIds: subtitleClips.map((c) => c.id),\n    });\n\n    try {\n      const payload = JSON.stringify(subtitleClips);\n      const translatedClips = await translateSubtitles(payload, targetLang);\n\n      if (Array.isArray(translatedClips) && translatedClips.length > 0) {\n        translatedClips.forEach((item) => {\n          if (item.id && item.text) {\n            updateClipProperties(item.id, { text: item.text });\n          }\n        });\n      } else {\n        throw new Error(tp.translateShapeError);\n      }\n    } catch (err: any) {\n      console.error(err);\n      setAiError(err.message || t.store.toasts.editor.translateSubtitlesError);\n    } finally {\n      setIsTranslating(false);\n      useVideoStore.getState().setAiSubtitleJob(null);\n    }\n  };\n\n  const handleApplyAiStylePreset = async () => {\n    if (!stylePrompt.trim()) return;\n\n    const targetIds: string[] = [];\n    tracks.forEach((tr) => {\n      tr.clips.forEach((c) => {\n        if (c.type === 'subtitle') targetIds.push(c.id);\n      });\n    });\n    if (selectedClip?.type === 'text') targetIds.push(selectedClip.id);\n\n    if (targetIds.length === 0) {\n      setAiError(t.videoEditor.aiTools.modal.needSubtitlesForStyle);\n      return;\n    }\n\n    setIsStyling(true);\n    setAiError(null);\n    useVideoStore.getState().setAiSubtitleJob({ kind: 'style', clipIds: targetIds });\n\n    try {\n      const preset = await generateSubtitleStylePreset(stylePrompt);\n      if (Object.keys(preset).length === 0) {\n        throw new Error(t.videoEditor.aiTools.modal.emptyStylePreset);\n      }\n\n      targetIds.forEach((id) => {\n        updateClipProperties(id, preset);\n      });\n    } catch (err: any) {\n      console.error(err);\n      setAiError(err.message || t.store.toasts.editor.aiStyleError);\n    } finally {\n      setIsStyling(false);\n      useVideoStore.getState().setAiSubtitleJob(null);\n    }\n  };\n\n  const handleApplyAiTextStylePreset = async () => {\n    if (!textStylePrompt.trim()) return;\n    if (!selectedClip || selectedClip.type !== 'text') return;\n\n    setIsStylingText(true);\n    setAiTextError(null);\n    useVideoStore.getState().setAiSubtitleJob({\n      kind: 'style',\n      clipIds: [selectedClip.id],\n    });\n\n    try {\n      const preset = await generateSubtitleStylePreset(textStylePrompt);\n      if (Object.keys(preset).length === 0) {\n        throw new Error(t.videoEditor.aiTools.modal.emptyStylePreset);\n      }\n      updateClipProperties(selectedClip.id, preset);\n    } catch (err: any) {\n      console.error(err);\n      setAiTextError(err.message || t.store.toasts.editor.aiStyleError);\n    } finally {\n      setIsStylingText(false);\n      useVideoStore.getState().setAiSubtitleJob(null);\n    }\n  };\n\n  const handleApplyAiImageGrading = async () => {\n    if (!imageGradingPrompt.trim()) return;\n    if (!selectedClip || selectedClip.type !== 'image') return;\n\n    setIsGradingImage(true);\n    setAiImageGradingError(null);\n\n    try {\n      const preset = await generateColorGradingPreset(imageGradingPrompt);\n\n      const cleanPreset: any = {};\n      const allowedKeys: (keyof ColorGradingPreset)[] = [\n        'exposure',\n        'contrast',\n        'highlights',\n        'shadows',\n        'whites',\n        'blacks',\n        'temperature',\n        'tint',\n        'vibrance',\n        'saturation',\n        'hue',\n        'vignetteEnabled',\n        'vignetteAmount',\n      ];\n\n      allowedKeys.forEach((k) => {\n        if (preset[k] !== undefined) {\n          cleanPreset[k] = preset[k];\n        }\n      });\n\n      updateColorGrading(selectedClip.id, cleanPreset);\n    } catch (err: any) {\n      console.error(err);\n      setAiImageGradingError(err.message || t.store.toasts.editor.aiColorGradingError);\n    } finally {\n      setIsGradingImage(false);\n    }\n  };\n\n  if (!selectedClip) {\n    return (\n      <div className=\"flex h-full w-full flex-col items-center justify-center select-none text-center\">\n        <PanelBody className=\"items-center justify-center text-center\">\n          <Sliders size={28} className=\"mb-1 opacity-30 text-white/80\" />\n          <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n            {tp.noClipSelected}\n          </TextBody>\n          <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 text-white/50\">\n            {tp.noClipSelectedBody}\n          </TextBody>\n        </PanelBody>\n      </div>\n    );\n  }\n\n  const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n    updateClipProperties(selectedClip.id, { name: e.target.value });\n  };\n\n  const handleStartTimeChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const val = parseFloat(e.target.value);\n    if (!isNaN(val) && val >= 0) {\n      updateClipProperties(selectedClip.id, { startTime: val });\n    }\n  };\n\n  const handleTrimInChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const val = parseFloat(e.target.value);\n    if (!isNaN(val) && val >= 0) {\n      updateClipProperties(selectedClip.id, { trimIn: val });\n    }\n  };\n\n  const handleTrimOutChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const val = parseFloat(e.target.value);\n    if (!isNaN(val) && val >= 0) {\n      updateClipProperties(selectedClip.id, { trimOut: val });\n    }\n  };\n\n  const handleSpeedChange = (value: string) => {\n    updateClipProperties(selectedClip.id, { speed: parseFloat(value) });\n  };\n\n  const handleTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n    updateClipProperties(selectedClip.id, { text: e.target.value });\n  };\n\n  const hasColorGrading = selectedClip.type === 'video' || selectedClip.type === 'image';\n  const hasEffects = selectedClip.type === 'video' || selectedClip.type === 'image';\n  const hasTransform =\n    selectedClip.type === 'text' ||\n    selectedClip.type === 'subtitle' ||\n    selectedClip.type === 'image' ||\n    selectedClip.type === 'video';\n  const hasScale = selectedClip.type === 'image' || selectedClip.type === 'video';\n  const hasFlips = selectedClip.type === 'image' || selectedClip.type === 'video';\n\n  const langOptions = [\n    { value: 'English', label: tp.langEnglish },\n    { value: 'Spanish', label: tp.langSpanish },\n    { value: 'Portuguese', label: tp.langPortuguese },\n    { value: 'French', label: tp.langFrench },\n    { value: 'German', label: tp.langGerman },\n    { value: 'Italian', label: tp.langItalian },\n  ];\n\n  const weightOptions = [\n    { value: '300', label: tp.weightLight },\n    { value: '400', label: tp.weightRegular },\n    { value: '500', label: tp.weightMedium },\n    { value: '600', label: tp.weightSemiBold },\n    { value: '700', label: tp.weightBold },\n    { value: '800', label: tp.weightExtraBold },\n  ];\n\n  const speedOptions = [\n    { value: '0.25', label: tp.speed025 },\n    { value: '0.5', label: tp.speed05 },\n    { value: '1', label: tp.speed1 },\n    { value: '1.5', label: tp.speed15 },\n    { value: '2', label: tp.speed2 },\n    { value: '4', label: tp.speed4 },\n  ];\n\n  const fillTypeOptions = [\n    { value: 'solid', label: tp.fillSolid },\n    { value: 'gradient', label: tp.fillGradient },\n  ];\n\n  const textIntroOptions = [\n    { value: '', label: tp.animNone },\n    { value: 'fade', label: tp.animFadeIn },\n    { value: 'slide-up', label: tp.animSlideUp },\n    { value: 'scale-in', label: tp.animScaleIn },\n    { value: 'typewriter', label: tp.animTypewriter },\n    { value: 'blur-in', label: tp.animBlurIn },\n  ];\n\n  const textOutroOptions = [\n    { value: '', label: tp.animNone },\n    { value: 'fade', label: tp.animFadeOut },\n    { value: 'slide-down', label: tp.animSlideDown },\n    { value: 'scale-out', label: tp.animScaleOut },\n    { value: 'blur-out', label: tp.animBlurOut },\n  ];\n\n  const imageIntroOptions = [\n    { value: '', label: tp.animNone },\n    { value: 'fade', label: tp.animFadeIn },\n    { value: 'slide-up', label: tp.animSlideUp },\n    { value: 'slide-down', label: tp.animSlideDown },\n    { value: 'slide-left', label: tp.animSlideLeft },\n    { value: 'slide-right', label: tp.animSlideRight },\n    { value: 'scale-in', label: tp.animScaleIn },\n    { value: 'blur-in', label: tp.animBlurIn },\n    { value: 'rotate-in', label: tp.animRotateIn },\n  ];\n\n  const imageOutroOptions = [\n    { value: '', label: tp.animNone },\n    { value: 'fade', label: tp.animFadeOut },\n    { value: 'slide-up', label: tp.animSlideUp },\n    { value: 'slide-down', label: tp.animSlideDown },\n    { value: 'slide-left', label: tp.animSlideLeft },\n    { value: 'slide-right', label: tp.animSlideRight },\n    { value: 'scale-out', label: tp.animScaleOut },\n    { value: 'blur-out', label: tp.animBlurOut },\n  ];\n\n  const fitModeOptions = [\n    { value: 'fit', label: tp.fitFrame },\n    { value: 'fill', label: tp.fillStretch },\n    { value: 'crop', label: tp.zoomCrop },\n  ];\n\n  const blendModeOptions = [\n    { value: 'normal', label: tp.blendNormal },\n    { value: 'screen', label: tp.blendScreen },\n    { value: 'multiply', label: tp.blendMultiply },\n    { value: 'overlay', label: tp.blendOverlay },\n    { value: 'difference', label: tp.blendDifference },\n    { value: 'luminosity', label: tp.blendLuminosity },\n  ];\n\n  const fontEntries: FontPickerEntry[] = GOOGLE_FONTS_CATALOG.map((f) => ({\n    name: f.name,\n    category: f.category,\n  }));\n\n  const fontCategoryLabels: Record<string, string> = {\n    'Sans-Serif': t.properties.text.fontCategory.sansSerif,\n    Serif: t.properties.text.fontCategory.serif,\n    'Display / T\u00EDtulos': t.properties.text.fontCategory.display,\n    Escritura: t.properties.text.fontCategory.handwriting,\n    Monospace: t.properties.text.fontCategory.monospace,\n  };\n\n  const gradientColors = selectedClip.gradientColors || [GRADIENT_DEFAULT_A, GRADIENT_DEFAULT_B];\n\n  return (\n    <div className=\"flex h-full w-full flex-col overflow-hidden\">\n      <div className=\"sticky top-0 z-10 flex shrink-0 gap-1 border-b border-panel-border bg-panel p-1\">\n        <button\n          type=\"button\"\n          onClick={() => setActiveTab('layout')}\n          className={`flex flex-1 items-center justify-center gap-1 rounded-lg py-1.5 uppercase transition-all ${\n            activeTab === 'layout'\n              ? 'bg-[var(--we-accent-capsule)] text-white'\n              : 'text-white/80 hover:bg-black-capsule hover:text-white'\n          }`}\n        >\n          <Move size={11} />\n          <TextBody as=\"span\" size=\"sm\" className=\"font-bold uppercase text-inherit\">{tp.tabLayout}</TextBody>\n        </button>\n        {hasColorGrading && (\n          <button\n            type=\"button\"\n            onClick={() => setActiveTab('color')}\n            className={`flex flex-1 items-center justify-center gap-1 rounded-lg py-1.5 uppercase transition-all ${\n              activeTab === 'color'\n                ? 'bg-[var(--we-accent-capsule)] text-white'\n                : 'text-white/80 hover:bg-black-capsule hover:text-white'\n            }`}\n          >\n            <Palette size={11} />\n            <TextBody as=\"span\" size=\"sm\" className=\"font-bold uppercase text-inherit\">{tp.tabColor}</TextBody>\n          </button>\n        )}\n        {hasEffects && (\n          <button\n            type=\"button\"\n            onClick={() => setActiveTab('effects')}\n            className={`flex flex-1 items-center justify-center gap-1 rounded-lg py-1.5 uppercase transition-all ${\n              activeTab === 'effects'\n                ? 'bg-[var(--we-accent-capsule)] text-white'\n                : 'text-white/80 hover:bg-black-capsule hover:text-white'\n            }`}\n          >\n            <Layers size={11} />\n            <TextBody as=\"span\" size=\"sm\" className=\"font-bold uppercase text-inherit\">{tp.tabEffects}</TextBody>\n          </button>\n        )}\n      </div>\n\n      <div className=\"min-h-0 flex-1 overflow-y-auto\">\n        {activeTab === 'layout' && (\n          <PanelBody>\n            {hasTransform && (\n              <PanelSection title={tp.sectionTransform}>\n                <PanelField\n                  variant=\"slide\"\n                  label={tp.positionX}\n                  min={0}\n                  max={1}\n                  step={0.01}\n                  numericValue={selectedClip.x !== undefined ? selectedClip.x : 0.5}\n                  formatValue={pct}\n                  defaultValue={0.5}\n                  resetLabel={tp.reset}\n                  onChange={(v) => updateClipProperties(selectedClip.id, { x: v })}\n                />\n                <PanelField\n                  variant=\"slide\"\n                  label={tp.positionY}\n                  min={0}\n                  max={1}\n                  step={0.01}\n                  numericValue={selectedClip.y !== undefined ? selectedClip.y : 0.5}\n                  formatValue={pct}\n                  defaultValue={0.5}\n                  resetLabel={tp.reset}\n                  onChange={(v) => updateClipProperties(selectedClip.id, { y: v })}\n                />\n                {hasScale && (\n                  <PanelField\n                    variant=\"slide\"\n                    label={tp.scale}\n                    min={0.05}\n                    max={40}\n                    step={0.01}\n                    numericValue={selectedClip.scaleX ?? 1}\n                    formatValue={pct}\n                    defaultValue={0.5}\n                    resetLabel={tp.reset}\n                    onChange={(v) =>\n                      updateClipProperties(selectedClip.id, { scaleX: v, scaleY: v })\n                    }\n                  />\n                )}\n                <PanelField\n                  variant=\"slide\"\n                  label={tp.rotation}\n                  min={-180}\n                  max={180}\n                  step={1}\n                  numericValue={selectedClip.rotation || 0}\n                  formatValue={deg}\n                  defaultValue={0}\n                  resetLabel={tp.reset}\n                  onChange={(v) => updateClipProperties(selectedClip.id, { rotation: v })}\n                />\n                {hasFlips && (\n                  <>\n                    <PanelField\n                      label={tp.flipHorizontal}\n                      trailing={\n                        <Switch\n                          checked={!!selectedClip.flipX}\n                          onChange={(checked) =>\n                            updateClipProperties(selectedClip.id, { flipX: checked })\n                          }\n                          ariaLabel={tp.flipHorizontal}\n                        />\n                      }\n                    />\n                    <PanelField\n                      label={tp.flipVertical}\n                      trailing={\n                        <Switch\n                          checked={!!selectedClip.flipY}\n                          onChange={(checked) =>\n                            updateClipProperties(selectedClip.id, { flipY: checked })\n                          }\n                          ariaLabel={tp.flipVertical}\n                        />\n                      }\n                    />\n                  </>\n                )}\n              </PanelSection>\n            )}\n\n            <PanelSection title={tp.sectionGeneral}>\n              <PanelField\n                label={tp.clipName}\n                trailing={\n                  <input\n                    type=\"text\"\n                    value={selectedClip.name || selectedClip.id}\n                    onChange={handleNameChange}\n                    className=\"w-32 bg-transparent text-right text-[11px] font-medium text-ink-primary focus:outline-none\"\n                  />\n                }\n              />\n\n              <PanelField\n                label={tp.startSec}\n                trailing={\n                  <input\n                    type=\"number\"\n                    step=\"0.1\"\n                    min=\"0\"\n                    value={selectedClip.startTime.toFixed(2)}\n                    onChange={handleStartTimeChange}\n                    className={fieldInputClass}\n                  />\n                }\n              />\n              <PanelField label={tp.duration} value={formatTimecode(selectedClip.duration)} />\n\n              {(selectedClip.type === 'video' || selectedClip.type === 'audio') && (\n                <>\n                  <PanelField\n                    label={tp.trimIn}\n                    trailing={\n                      <input\n                        type=\"number\"\n                        step=\"0.1\"\n                        min=\"0\"\n                        value={selectedClip.trimIn.toFixed(2)}\n                        onChange={handleTrimInChange}\n                        className={fieldInputClass}\n                      />\n                    }\n                  />\n                  <PanelField\n                    label={tp.trimOut}\n                    trailing={\n                      <input\n                        type=\"number\"\n                        step=\"0.1\"\n                        min=\"0\"\n                        value={selectedClip.trimOut.toFixed(2)}\n                        onChange={handleTrimOutChange}\n                        className={fieldInputClass}\n                      />\n                    }\n                  />\n                  <PanelField\n                    label={tp.playbackSpeed}\n                    trailing={\n                      <SelectDropdown\n                        ariaLabel={tp.playbackSpeed}\n                        value={String(selectedClip.speed)}\n                        onChange={handleSpeedChange}\n                        options={speedOptions}\n                      />\n                    }\n                  />\n                  <PanelField\n                    variant=\"slide\"\n                    label={tp.volume}\n                    min={0}\n                    max={2}\n                    step={0.05}\n                    numericValue={selectedClip.volume}\n                    formatValue={pct}\n                    defaultValue={1}\n                    resetLabel={tp.reset}\n                    onChange={(val) => updateClipProperties(selectedClip.id, { volume: val })}\n                  />\n                </>\n              )}\n            </PanelSection>\n\n            {(selectedClip.type === 'text' || selectedClip.type === 'subtitle') && (\n              <>\n                {selectedClip.type === 'subtitle' && (\n                  <PanelSection title={tp.sectionAiBatch}>\n                    {isTranslating || isStyling ? (\n                      <SubtitleAiLoader\n                        variant=\"card\"\n                        label={\n                          isStyling\n                            ? t.videoEditor.timeline.stylingSubtitles\n                            : t.videoEditor.timeline.translatingSubtitles\n                        }\n                        hint={\n                          isStyling\n                            ? t.videoEditor.timeline.stylingSubtitlesHint\n                            : t.videoEditor.timeline.translatingSubtitlesHint\n                        }\n                      />\n                    ) : (\n                      <>\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                      {tp.aiTranslate}\n                    </TextBody>\n                    <div className=\"flex min-h-9 items-stretch gap-1.5\">\n                      <div className=\"flex min-h-9 min-w-0 flex-1 items-center rounded-xl bg-black-capsule px-3 py-2\">\n                        <SelectDropdown\n                          ariaLabel={tp.aiTranslate}\n                          value={targetLang}\n                          onChange={setTargetLang}\n                          options={langOptions}\n                          size=\"md\"\n                          className=\"w-full\"\n                        />\n                      </div>\n                      <Button\n                        type=\"button\"\n                        variant=\"accent\"\n                        size=\"sm\"\n                        className=\"min-h-9 shrink-0 self-stretch px-3\"\n                        disabled={isTranslating}\n                        onClick={handleTranslateAllSubtitles}\n                      >\n                        {isTranslating ? <Loader size={12} className=\"animate-spin\" /> : tp.aiTranslateBtn}\n                      </Button>\n                    </div>\n\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                      {tp.aiCreativeDesign}\n                    </TextBody>\n                    <input\n                      type=\"text\"\n                      value={stylePrompt}\n                      onChange={(e) => setStylePrompt(e.target.value)}\n                      placeholder={tp.aiStylePlaceholder}\n                      className={promptInputClass}\n                    />\n                    <Button\n                      type=\"button\"\n                      variant=\"accent\"\n                      className=\"w-full\"\n                      disabled={isStyling || !stylePrompt.trim()}\n                      onClick={handleApplyAiStylePreset}\n                    >\n                      {isStyling ? (\n                        <Loader size={12} className=\"animate-spin\" />\n                      ) : (\n                        <>\n                          <Sparkles size={12} />\n                          {tp.aiApplyStyle}\n                        </>\n                      )}\n                    </Button>\n\n                    {aiError && (\n                      <TextBody as=\"p\" size=\"sm\" className=\"text-red-400\">\n                        {aiError}\n                      </TextBody>\n                    )}\n                      </>\n                    )}\n                  </PanelSection>\n                )}\n\n                {selectedClip.type === 'text' && (\n                  <PanelSection title={tp.sectionAiTextDesigner}>\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                      {tp.aiCreativeDesign}\n                    </TextBody>\n                    <input\n                      type=\"text\"\n                      value={textStylePrompt}\n                      onChange={(e) => setTextStylePrompt(e.target.value)}\n                      placeholder={tp.aiTextStylePlaceholder}\n                      className={promptInputClass}\n                    />\n                    <Button\n                      type=\"button\"\n                      variant=\"accent\"\n                      className=\"w-full\"\n                      disabled={isStylingText || !textStylePrompt.trim()}\n                      onClick={handleApplyAiTextStylePreset}\n                    >\n                      {isStylingText ? (\n                        <Loader size={12} className=\"animate-spin\" />\n                      ) : (\n                        <>\n                          <Sparkles size={12} />\n                          {tp.aiApplyStyle}\n                        </>\n                      )}\n                    </Button>\n                    {aiTextError && (\n                      <TextBody as=\"p\" size=\"sm\" className=\"text-red-400\">\n                        {aiTextError}\n                      </TextBody>\n                    )}\n                  </PanelSection>\n                )}\n\n                <PanelSection title={tp.sectionTypography}>\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                    {tp.textContent}\n                  </TextBody>\n                  <textarea\n                    rows={3}\n                    value={selectedClip.text || ''}\n                    onChange={handleTextChange}\n                    className={textAreaClass}\n                    placeholder={tp.textPlaceholder}\n                  />\n\n                  <PanelField\n                    label={tp.fontFamily}\n                    trailing={\n                      <button\n                        ref={fontTriggerRef}\n                        type=\"button\"\n                        onClick={() => {\n                          fontCommitRef.current = selectedClip.fontFamily || 'Inter';\n                          setIsFontDropdownOpen((v) => !v);\n                        }}\n                        aria-haspopup=\"listbox\"\n                        aria-expanded={isFontDropdownOpen}\n                        className=\"inline-flex w-[9.5rem] shrink-0 cursor-pointer items-center gap-1 select-none rounded-lg py-0.5 text-ink-primary\"\n                        title={selectedClip.fontFamily || 'Inter'}\n                      >\n                        <TextBody as=\"span\" size=\"sm\" className=\"min-w-0 flex-1 truncate text-left text-ink-primary\">\n                          {selectedClip.fontFamily || 'Inter'}\n                        </TextBody>\n                        <ChevronDown\n                          size={12}\n                          strokeWidth={2.25}\n                          className={`shrink-0 text-white/80 transition-transform ${isFontDropdownOpen ? 'rotate-180' : ''}`}\n                        />\n                      </button>\n                    }\n                  />\n                  <FontPickerFlyout\n                    open={isFontDropdownOpen}\n                    onClose={() => setIsFontDropdownOpen(false)}\n                    anchorRef={fontTriggerRef}\n                    value={fontCommitRef.current}\n                    fonts={fontEntries}\n                    categoryLabels={fontCategoryLabels}\n                    customSectionLabel={t.properties.text.myFonts}\n                    searchPlaceholder={t.properties.text.searchFonts}\n                    onPreview={(name) => {\n                      const family = name ?? fontCommitRef.current;\n                      loadGoogleFont(family);\n                      updateClipProperties(selectedClip.id, { fontFamily: family });\n                    }}\n                    onSelect={(name) => {\n                      fontCommitRef.current = name;\n                      loadGoogleFont(name);\n                      updateClipProperties(selectedClip.id, { fontFamily: name });\n                    }}\n                  />\n\n                  <PanelField\n                    label={tp.weight}\n                    trailing={\n                      <SelectDropdown\n                        ariaLabel={tp.weight}\n                        value={String(selectedClip.fontWeight || 500)}\n                        onChange={(v) =>\n                          updateClipProperties(selectedClip.id, { fontWeight: Number(v) })\n                        }\n                        options={weightOptions}\n                      />\n                    }\n                  />\n\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{tp.align}</TextBody>\n                  <div className=\"flex rounded-xl bg-black-capsule p-0.5\">\n                    {(['left', 'center', 'right'] as const).map((align) => (\n                      <button\n                        key={align}\n                        type=\"button\"\n                        onClick={() => updateClipProperties(selectedClip.id, { textAlign: align })}\n                        className={segmentBtn((selectedClip.textAlign || 'center') === align)}\n                      >\n                        {align === 'left' && <AlignLeft size={12} />}\n                        {align === 'center' && <AlignCenter size={12} />}\n                        {align === 'right' && <AlignRight size={12} />}\n                      </button>\n                    ))}\n                  </div>\n\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{tp.style}</TextBody>\n                  <div className=\"flex rounded-xl bg-black-capsule p-0.5\">\n                    <button\n                      type=\"button\"\n                      title={tp.italic}\n                      onClick={() =>\n                        updateClipProperties(selectedClip.id, {\n                          fontStyle: selectedClip.fontStyle === 'italic' ? 'normal' : 'italic',\n                        })\n                      }\n                      className={segmentBtn(selectedClip.fontStyle === 'italic')}\n                    >\n                      <Italic size={12} />\n                    </button>\n                    <button\n                      type=\"button\"\n                      title={tp.underline}\n                      onClick={() =>\n                        updateClipProperties(selectedClip.id, {\n                          underlineEnabled: !selectedClip.underlineEnabled,\n                        })\n                      }\n                      className={segmentBtn(!!selectedClip.underlineEnabled)}\n                    >\n                      <Underline size={12} />\n                    </button>\n                  </div>\n\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{tp.case}</TextBody>\n                  <div className=\"flex rounded-xl bg-black-capsule p-0.5\">\n                    {(\n                      [\n                        { value: 'none', label: 'Ab' },\n                        { value: 'uppercase', label: 'AA' },\n                        { value: 'lowercase', label: 'aa' },\n                        { value: 'capitalize', label: 'Aa' },\n                      ] as const\n                    ).map((caseOpt) => (\n                      <button\n                        key={caseOpt.value}\n                        type=\"button\"\n                        title={caseOpt.value.toUpperCase()}\n                        onClick={() =>\n                          updateClipProperties(selectedClip.id, { textTransform: caseOpt.value })\n                        }\n                        className={segmentBtn(\n                          (selectedClip.textTransform || 'none') === caseOpt.value,\n                        )}\n                      >\n                        <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-inherit\">\n                          {caseOpt.label}\n                        </TextBody>\n                      </button>\n                    ))}\n                  </div>\n\n                  <PanelField\n                    variant=\"slide\"\n                    label={tp.fontSize}\n                    min={10}\n                    max={120}\n                    step={1}\n                    numericValue={selectedClip.fontSize || 48}\n                    formatValue={px}\n                    defaultValue={48}\n                    resetLabel={tp.reset}\n                    onChange={(v) => updateClipProperties(selectedClip.id, { fontSize: v })}\n                  />\n                  <PanelField\n                    variant=\"slide\"\n                    label={tp.letterSpacing}\n                    min={0}\n                    max={24}\n                    step={1}\n                    numericValue={selectedClip.letterSpacing || 0}\n                    formatValue={px}\n                    defaultValue={0}\n                    resetLabel={tp.reset}\n                    onChange={(v) => updateClipProperties(selectedClip.id, { letterSpacing: v })}\n                  />\n                  <PanelField\n                    variant=\"slide\"\n                    label={tp.opacity}\n                    min={0}\n                    max={1}\n                    step={0.01}\n                    numericValue={selectedClip.opacity !== undefined ? selectedClip.opacity : 1.0}\n                    formatValue={pct}\n                    defaultValue={1}\n                    resetLabel={tp.reset}\n                    onChange={(v) => updateClipProperties(selectedClip.id, { opacity: v })}\n                  />\n                </PanelSection>\n\n                <PanelSection title={tp.sectionFill}>\n                  <PanelField\n                    label={tp.fillType}\n                    trailing={\n                      <SelectDropdown\n                        ariaLabel={tp.fillType}\n                        value={selectedClip.fillType || 'solid'}\n                        onChange={(v) =>\n                          updateClipProperties(selectedClip.id, { fillType: v as any })\n                        }\n                        options={fillTypeOptions}\n                      />\n                    }\n                  />\n\n                  {(selectedClip.fillType || 'solid') === 'solid' && (\n                    <ColorInput\n                      label={tp.textColor}\n                      opacityLabel={tp.opacity}\n                      value={selectedClip.fillColor || '#FFFFFF'}\n                      onChange={(css) =>\n                        updateClipProperties(selectedClip.id, {\n                          fillColor: css,\n                          fillType: 'solid',\n                        })\n                      }\n                      showEyedropper={false}\n                    />\n                  )}\n\n                  {selectedClip.fillType === 'gradient' && (\n                    <>\n                      <ColorInput\n                        label={tp.gradientColor1}\n                        opacityLabel={tp.opacity}\n                        value={gradientColors[0] || GRADIENT_DEFAULT_A}\n                        onChange={(css) => {\n                          updateClipProperties(selectedClip.id, {\n                            gradientColors: [css, gradientColors[1] || GRADIENT_DEFAULT_B],\n                          });\n                        }}\n                        showEyedropper={false}\n                      />\n                      <ColorInput\n                        label={tp.gradientColor2}\n                        opacityLabel={tp.opacity}\n                        value={gradientColors[1] || GRADIENT_DEFAULT_B}\n                        onChange={(css) => {\n                          updateClipProperties(selectedClip.id, {\n                            gradientColors: [gradientColors[0] || GRADIENT_DEFAULT_A, css],\n                          });\n                        }}\n                        showEyedropper={false}\n                      />\n                      <PanelField\n                        variant=\"slide\"\n                        label={tp.gradientAngle}\n                        min={0}\n                        max={360}\n                        step={1}\n                        numericValue={selectedClip.gradientAngle || 90}\n                        formatValue={deg}\n                        defaultValue={90}\n                        resetLabel={tp.reset}\n                        onChange={(val) =>\n                          updateClipProperties(selectedClip.id, { gradientAngle: val })\n                        }\n                      />\n                    </>\n                  )}\n                </PanelSection>\n\n                <PanelSection title={tp.sectionOutline}>\n                  <PanelField\n                    label={tp.outlineEnable}\n                    trailing={\n                      <Switch\n                        checked={!!selectedClip.strokeEnabled}\n                        onChange={(checked) =>\n                          updateClipProperties(selectedClip.id, { strokeEnabled: checked })\n                        }\n                        ariaLabel={tp.outlineEnable}\n                      />\n                    }\n                  />\n                  {selectedClip.strokeEnabled && (\n                    <>\n                      <ColorInput\n                        label={tp.sectionOutline}\n                        opacityLabel={tp.opacity}\n                        value={selectedClip.strokeColor || '#000000'}\n                        onChange={(css) =>\n                          updateClipProperties(selectedClip.id, { strokeColor: css })\n                        }\n                        showEyedropper={false}\n                      />\n                      <PanelField\n                        variant=\"slide\"\n                        label={tp.outlineSize}\n                        min={1}\n                        max={12}\n                        step={0.5}\n                        numericValue={selectedClip.strokeWidth || 2}\n                        formatValue={px}\n                        defaultValue={2}\n                        resetLabel={tp.reset}\n                        onChange={(v) => updateClipProperties(selectedClip.id, { strokeWidth: v })}\n                      />\n                    </>\n                  )}\n                </PanelSection>\n\n                <PanelSection title={tp.sectionShadow}>\n                  <PanelField\n                    label={tp.dropShadow}\n                    trailing={\n                      <Switch\n                        checked={!!selectedClip.shadowEnabled}\n                        onChange={(checked) =>\n                          updateClipProperties(selectedClip.id, { shadowEnabled: checked })\n                        }\n                        ariaLabel={tp.dropShadow}\n                      />\n                    }\n                  />\n                  {selectedClip.shadowEnabled && (\n                    <>\n                      <PanelField\n                        label={tp.shadowColor}\n                        trailing={\n                          <input\n                            type=\"color\"\n                            value={selectedClip.shadowColor || '#000000'}\n                            onChange={(e) =>\n                              updateClipProperties(selectedClip.id, {\n                                shadowColor: e.target.value,\n                              })\n                            }\n                            className={swatchClass}\n                          />\n                        }\n                      />\n                      <PanelField\n                        variant=\"slide\"\n                        label={tp.shadowOpacity}\n                        min={0}\n                        max={1}\n                        step={0.05}\n                        numericValue={\n                          selectedClip.shadowOpacity !== undefined\n                            ? selectedClip.shadowOpacity\n                            : 0.5\n                        }\n                        formatValue={pct}\n                        defaultValue={0.5}\n                        resetLabel={tp.reset}\n                        onChange={(v) =>\n                          updateClipProperties(selectedClip.id, { shadowOpacity: v })\n                        }\n                      />\n                      <PanelField\n                        variant=\"slide\"\n                        label={tp.blurRadius}\n                        min={0}\n                        max={30}\n                        step={1}\n                        numericValue={\n                          selectedClip.shadowBlur !== undefined ? selectedClip.shadowBlur : 4\n                        }\n                        formatValue={px}\n                        defaultValue={4}\n                        resetLabel={tp.reset}\n                        onChange={(v) => updateClipProperties(selectedClip.id, { shadowBlur: v })}\n                      />\n                      <PanelField\n                        variant=\"slide\"\n                        label={tp.offsetX}\n                        min={-30}\n                        max={30}\n                        step={1}\n                        numericValue={\n                          selectedClip.shadowOffsetX !== undefined\n                            ? selectedClip.shadowOffsetX\n                            : 2\n                        }\n                        formatValue={px}\n                        defaultValue={2}\n                        resetLabel={tp.reset}\n                        onChange={(v) =>\n                          updateClipProperties(selectedClip.id, { shadowOffsetX: v })\n                        }\n                      />\n                      <PanelField\n                        variant=\"slide\"\n                        label={tp.offsetY}\n                        min={-30}\n                        max={30}\n                        step={1}\n                        numericValue={\n                          selectedClip.shadowOffsetY !== undefined\n                            ? selectedClip.shadowOffsetY\n                            : 2\n                        }\n                        formatValue={px}\n                        defaultValue={2}\n                        resetLabel={tp.reset}\n                        onChange={(v) =>\n                          updateClipProperties(selectedClip.id, { shadowOffsetY: v })\n                        }\n                      />\n                    </>\n                  )}\n                </PanelSection>\n\n                <PanelSection title={tp.sectionPlate}>\n                  <PanelField\n                    label={tp.backgroundPlate}\n                    trailing={\n                      <Switch\n                        checked={!!selectedClip.backgroundEnabled}\n                        onChange={(checked) =>\n                          updateClipProperties(selectedClip.id, { backgroundEnabled: checked })\n                        }\n                        ariaLabel={tp.backgroundPlate}\n                      />\n                    }\n                  />\n                  {selectedClip.backgroundEnabled && (\n                    <>\n                      <PanelField\n                        label={tp.plateColor}\n                        trailing={\n                          <input\n                            type=\"color\"\n                            value={selectedClip.backgroundColor || '#000000'}\n                            onChange={(e) =>\n                              updateClipProperties(selectedClip.id, {\n                                backgroundColor: e.target.value,\n                              })\n                            }\n                            className={swatchClass}\n                          />\n                        }\n                      />\n                      <PanelField\n                        variant=\"slide\"\n                        label={tp.plateOpacity}\n                        min={0}\n                        max={1}\n                        step={0.05}\n                        numericValue={\n                          selectedClip.backgroundOpacity !== undefined\n                            ? selectedClip.backgroundOpacity\n                            : 0.6\n                        }\n                        formatValue={pct}\n                        defaultValue={0.6}\n                        resetLabel={tp.reset}\n                        onChange={(v) =>\n                          updateClipProperties(selectedClip.id, { backgroundOpacity: v })\n                        }\n                      />\n                      <PanelField\n                        variant=\"slide\"\n                        label={tp.platePadding}\n                        min={0}\n                        max={40}\n                        step={1}\n                        numericValue={selectedClip.backgroundPadding || 8}\n                        formatValue={px}\n                        defaultValue={8}\n                        resetLabel={tp.reset}\n                        onChange={(v) =>\n                          updateClipProperties(selectedClip.id, { backgroundPadding: v })\n                        }\n                      />\n                      <PanelField\n                        label={tp.borderColor}\n                        trailing={\n                          <input\n                            type=\"color\"\n                            value={selectedClip.backgroundBorderColor || '#FFFFFF'}\n                            onChange={(e) =>\n                              updateClipProperties(selectedClip.id, {\n                                backgroundBorderColor: e.target.value,\n                              })\n                            }\n                            className={swatchClass}\n                          />\n                        }\n                      />\n                      <PanelField\n                        variant=\"slide\"\n                        label={tp.borderWidth}\n                        min={0}\n                        max={8}\n                        step={0.5}\n                        numericValue={\n                          selectedClip.backgroundBorderWidth !== undefined\n                            ? selectedClip.backgroundBorderWidth\n                            : 0\n                        }\n                        formatValue={px}\n                        defaultValue={0}\n                        resetLabel={tp.reset}\n                        onChange={(v) =>\n                          updateClipProperties(selectedClip.id, { backgroundBorderWidth: v })\n                        }\n                      />\n                      <PanelField\n                        variant=\"slide\"\n                        label={tp.borderRadius}\n                        min={0}\n                        max={30}\n                        step={1}\n                        numericValue={\n                          selectedClip.backgroundBorderRadius !== undefined\n                            ? selectedClip.backgroundBorderRadius\n                            : 4\n                        }\n                        formatValue={px}\n                        defaultValue={4}\n                        resetLabel={tp.reset}\n                        onChange={(v) =>\n                          updateClipProperties(selectedClip.id, { backgroundBorderRadius: v })\n                        }\n                      />\n                    </>\n                  )}\n                </PanelSection>\n\n                <PanelSection title={tp.sectionAnimations}>\n                  <PanelField\n                    label={tp.introAnimation}\n                    trailing={\n                      <SelectDropdown\n                        ariaLabel={tp.introAnimation}\n                        value={selectedClip.animationIn || ''}\n                        onChange={(v) =>\n                          updateClipProperties(selectedClip.id, {\n                            animationIn: (v || null) as any,\n                          })\n                        }\n                        options={textIntroOptions}\n                      />\n                    }\n                  />\n                  {selectedClip.animationIn && (\n                    <PanelField\n                      variant=\"slide\"\n                      label={tp.introDuration}\n                      min={0.1}\n                      max={3}\n                      step={0.1}\n                      numericValue={selectedClip.animationInDuration || 0.5}\n                      formatValue={sec}\n                      defaultValue={0.5}\n                      resetLabel={tp.reset}\n                      onChange={(v) =>\n                        updateClipProperties(selectedClip.id, { animationInDuration: v })\n                      }\n                    />\n                  )}\n                  <PanelField\n                    label={tp.outroAnimation}\n                    trailing={\n                      <SelectDropdown\n                        ariaLabel={tp.outroAnimation}\n                        value={selectedClip.animationOut || ''}\n                        onChange={(v) =>\n                          updateClipProperties(selectedClip.id, {\n                            animationOut: (v || null) as any,\n                          })\n                        }\n                        options={textOutroOptions}\n                      />\n                    }\n                  />\n                  {selectedClip.animationOut && (\n                    <PanelField\n                      variant=\"slide\"\n                      label={tp.outroDuration}\n                      min={0.1}\n                      max={3}\n                      step={0.1}\n                      numericValue={selectedClip.animationOutDuration || 0.5}\n                      formatValue={sec}\n                      defaultValue={0.5}\n                      resetLabel={tp.reset}\n                      onChange={(v) =>\n                        updateClipProperties(selectedClip.id, { animationOutDuration: v })\n                      }\n                    />\n                  )}\n                </PanelSection>\n              </>\n            )}\n\n            {selectedClip.type === 'image' && (\n              <>\n                <PanelSection title={tp.sectionAiCinematic}>\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                    {tp.aiColorFilter}\n                  </TextBody>\n                  <input\n                    type=\"text\"\n                    value={imageGradingPrompt}\n                    onChange={(e) => setImageGradingPrompt(e.target.value)}\n                    placeholder={tp.aiGradingPlaceholder}\n                    className={promptInputClass}\n                  />\n                  <Button\n                    type=\"button\"\n                    variant=\"accent\"\n                    className=\"w-full\"\n                    disabled={isGradingImage || !imageGradingPrompt.trim()}\n                    onClick={handleApplyAiImageGrading}\n                  >\n                    {isGradingImage ? (\n                      <Loader size={12} className=\"animate-spin\" />\n                    ) : (\n                      <>\n                        <Sparkles size={12} />\n                        {tp.aiApplyPreset}\n                      </>\n                    )}\n                  </Button>\n                  {aiImageGradingError && (\n                    <TextBody as=\"p\" size=\"sm\" className=\"text-red-400\">\n                      {aiImageGradingError}\n                    </TextBody>\n                  )}\n                </PanelSection>\n\n                <PanelSection title={tp.sectionImage}>\n                  <PanelField\n                    label={tp.sizingMode}\n                    trailing={\n                      <SelectDropdown\n                        ariaLabel={tp.sizingMode}\n                        value={selectedClip.fitMode || 'fit'}\n                        onChange={(v) =>\n                          updateClipProperties(selectedClip.id, { fitMode: v as any })\n                        }\n                        options={fitModeOptions}\n                      />\n                    }\n                  />\n                  <PanelField\n                    label={tp.blendMode}\n                    trailing={\n                      <SelectDropdown\n                        ariaLabel={tp.blendMode}\n                        value={selectedClip.blendMode || 'normal'}\n                        onChange={(v) =>\n                          updateClipProperties(selectedClip.id, { blendMode: v as any })\n                        }\n                        options={blendModeOptions}\n                      />\n                    }\n                  />\n                  <PanelField\n                    variant=\"slide\"\n                    label={tp.opacity}\n                    min={0}\n                    max={1}\n                    step={0.01}\n                    numericValue={selectedClip.opacity !== undefined ? selectedClip.opacity : 1.0}\n                    formatValue={pct}\n                    defaultValue={1}\n                    resetLabel={tp.reset}\n                    onChange={(v) => updateClipProperties(selectedClip.id, { opacity: v })}\n                  />\n                </PanelSection>\n\n                <PanelSection title={tp.sectionAnimations}>\n                  <PanelField\n                    label={tp.introAnimation}\n                    trailing={\n                      <SelectDropdown\n                        ariaLabel={tp.introAnimation}\n                        value={selectedClip.animationIn || ''}\n                        onChange={(v) =>\n                          updateClipProperties(selectedClip.id, {\n                            animationIn: (v || null) as any,\n                          })\n                        }\n                        options={imageIntroOptions}\n                      />\n                    }\n                  />\n                  {selectedClip.animationIn && (\n                    <PanelField\n                      variant=\"slide\"\n                      label={tp.introDuration}\n                      min={0.1}\n                      max={3}\n                      step={0.1}\n                      numericValue={selectedClip.animationInDuration || 0.5}\n                      formatValue={sec}\n                      defaultValue={0.5}\n                      resetLabel={tp.reset}\n                      onChange={(v) =>\n                        updateClipProperties(selectedClip.id, { animationInDuration: v })\n                      }\n                    />\n                  )}\n                  <PanelField\n                    label={tp.outroAnimation}\n                    trailing={\n                      <SelectDropdown\n                        ariaLabel={tp.outroAnimation}\n                        value={selectedClip.animationOut || ''}\n                        onChange={(v) =>\n                          updateClipProperties(selectedClip.id, {\n                            animationOut: (v || null) as any,\n                          })\n                        }\n                        options={imageOutroOptions}\n                      />\n                    }\n                  />\n                  {selectedClip.animationOut && (\n                    <PanelField\n                      variant=\"slide\"\n                      label={tp.outroDuration}\n                      min={0.1}\n                      max={3}\n                      step={0.1}\n                      numericValue={selectedClip.animationOutDuration || 0.5}\n                      formatValue={sec}\n                      defaultValue={0.5}\n                      resetLabel={tp.reset}\n                      onChange={(v) =>\n                        updateClipProperties(selectedClip.id, { animationOutDuration: v })\n                      }\n                    />\n                  )}\n                </PanelSection>\n              </>\n            )}\n\n            {selectedClip.type === 'video' && (\n              <PanelSection title={tp.sectionVideo}>\n                <PanelField\n                  variant=\"slide\"\n                  label={tp.opacity}\n                  min={0}\n                  max={1}\n                  step={0.01}\n                  numericValue={selectedClip.opacity}\n                  formatValue={pct}\n                  defaultValue={1}\n                  resetLabel={tp.reset}\n                  onChange={(val) => updateClipProperties(selectedClip.id, { opacity: val })}\n                />\n              </PanelSection>\n            )}\n          </PanelBody>\n        )}\n\n        {activeTab === 'color' && hasColorGrading && (\n          <div className=\"flex h-full flex-col overflow-hidden\">\n            <ColorGradingPanel\n              clipId={selectedClip.id}\n              colorGrading={\n                selectedClip.colorGrading || {\n                  exposure: 0,\n                  contrast: 0,\n                  highlights: 0,\n                  shadows: 0,\n                  whites: 0,\n                  blacks: 0,\n                  temperature: 0,\n                  tint: 0,\n                  vibrance: 0,\n                  saturation: 0,\n                  hue: 0,\n                  sharpness: 0,\n                  blur: 0,\n                  noiseReduction: 0,\n                  hslAdjustments: {\n                    red: { hue: 0, saturation: 0, luminance: 0 },\n                    orange: { hue: 0, saturation: 0, luminance: 0 },\n                    yellow: { hue: 0, saturation: 0, luminance: 0 },\n                    green: { hue: 0, saturation: 0, luminance: 0 },\n                    aqua: { hue: 0, saturation: 0, luminance: 0 },\n                    blue: { hue: 0, saturation: 0, luminance: 0 },\n                    purple: { hue: 0, saturation: 0, luminance: 0 },\n                    magenta: { hue: 0, saturation: 0, luminance: 0 },\n                  },\n                  curves: {\n                    master: [\n                      { x: 0, y: 0 },\n                      { x: 1, y: 1 },\n                    ],\n                    red: [\n                      { x: 0, y: 0 },\n                      { x: 1, y: 1 },\n                    ],\n                    green: [\n                      { x: 0, y: 0 },\n                      { x: 1, y: 1 },\n                    ],\n                    blue: [\n                      { x: 0, y: 0 },\n                      { x: 1, y: 1 },\n                    ],\n                  },\n                  vignetteEnabled: false,\n                  vignetteAmount: 0,\n                  vignetteMidpoint: 50,\n                  vignetteFeather: 50,\n                }\n              }\n            />\n          </div>\n        )}\n\n        {activeTab === 'effects' && hasEffects && (\n          <PanelBody className=\"h-full\">\n            <PanelSection title={tp.sectionEffects}>\n              <EffectStack clipId={selectedClip.id} effects={selectedClip.effects || []} />\n            </PanelSection>\n          </PanelBody>\n        )}\n      </div>\n    </div>\n  );\n};\n", "import React, { useState } from 'react';\nimport {\n  useVideoStore,\n  type ColorGradingSettings,\n  type CurvePoint,\n} from '../../../store/useVideoStore';\nimport { ColorCurves } from '../effects/ColorCurves';\nimport { Sliders, Sun, Palette, CircleDot, Sparkles, Loader } from 'lucide-react';\nimport { generateColorGradingPreset } from '../../../services/aiService';\nimport { useTranslation } from '../../../i18n';\nimport { toUserFacingError } from '../../../utils/userFacingError';\nimport {\n  Button,\n  PanelBody,\n  PanelField,\n  PanelSection,\n  Switch,\n  TextBody,\n} from '../../ui';\n\ninterface ColorGradingPanelProps {\n  clipId: string;\n  colorGrading: ColorGradingSettings;\n}\n\ntype GradingTab = 'basic' | 'curves' | 'hsl' | 'vignette';\ntype CurveChannel = 'master' | 'red' | 'green' | 'blue';\n\nconst pct = (v: number) => `${Math.round(v)}%`;\nconst signed = (v: number) => (v > 0 ? `+${v}` : `${v}`);\nconst exposureFmt = (v: number) => (v > 0 ? `+${v.toFixed(1)}` : v.toFixed(1));\n\nexport const ColorGradingPanel: React.FC<ColorGradingPanelProps> = ({\n  clipId,\n  colorGrading,\n}) => {\n  const t = useTranslation();\n  const tp = t.videoEditor.colorGrading;\n  const tm = t.videoEditor.ai.modal;\n  const { updateColorGrading } = useVideoStore();\n  const [activeTab, setActiveTab] = useState<GradingTab>('basic');\n  const [curveChannel, setCurveChannel] = useState<CurveChannel>('master');\n  const [hslMode, setHslMode] = useState<'hue' | 'saturation' | 'luminance'>('hue');\n  const [aiPrompt, setAiPrompt] = useState('');\n  const [isGenerating, setIsGenerating] = useState(false);\n  const [aiError, setAiError] = useState<string | null>(null);\n\n  const handleApplyAiGrading = async () => {\n    if (!aiPrompt.trim()) return;\n\n    setIsGenerating(true);\n    setAiError(null);\n\n    try {\n      const preset = await generateColorGradingPreset(aiPrompt);\n      const cleanPreset: Record<string, unknown> = {};\n      const allowedKeys = [\n        'exposure',\n        'contrast',\n        'highlights',\n        'shadows',\n        'whites',\n        'blacks',\n        'temperature',\n        'tint',\n        'vibrance',\n        'saturation',\n        'hue',\n        'vignetteEnabled',\n        'vignetteAmount',\n      ];\n      allowedKeys.forEach((k) => {\n        if ((preset as Record<string, unknown>)[k] !== undefined) {\n          cleanPreset[k] = (preset as Record<string, unknown>)[k];\n        }\n      });\n      if (Object.keys(cleanPreset).length === 0) {\n        setAiError(tm.emptyGradingPreset);\n        return;\n      }\n      updateColorGrading(clipId, cleanPreset as Partial<ColorGradingSettings>);\n      setAiPrompt('');\n    } catch (err: unknown) {\n      setAiError(\n        toUserFacingError(err, {\n          context: 'color-grading-panel',\n          fallback: tm.emptyGradingPreset,\n        }),\n      );\n    } finally {\n      setIsGenerating(false);\n    }\n  };\n\n  const updateSetting = (key: keyof ColorGradingSettings, value: unknown) => {\n    updateColorGrading(clipId, { [key]: value } as Partial<ColorGradingSettings>);\n  };\n\n  const handleCurveChange = (newPoints: CurvePoint[]) => {\n    updateSetting('curves', { ...colorGrading.curves, [curveChannel]: newPoints });\n  };\n\n  const handleHslChange = (\n    color: string,\n    field: 'hue' | 'saturation' | 'luminance',\n    val: number,\n  ) => {\n    const hsl = { ...colorGrading.hslAdjustments };\n    hsl[color] = { ...hsl[color], [field]: val };\n    updateSetting('hslAdjustments', hsl);\n  };\n\n  const tabs: { id: GradingTab; label: string; icon: React.ReactNode }[] = [\n    { id: 'basic', label: tp.tabBasic, icon: <Sun size={11} /> },\n    { id: 'curves', label: tp.tabCurves, icon: <Palette size={11} /> },\n    { id: 'hsl', label: tp.tabHsl, icon: <Sliders size={11} /> },\n    { id: 'vignette', label: tp.tabVignette, icon: <CircleDot size={11} /> },\n  ];\n\n  const channelLabel = (chan: CurveChannel) => {\n    if (chan === 'red') return tp.channelRed;\n    if (chan === 'green') return tp.channelGreen;\n    if (chan === 'blue') return tp.channelBlue;\n    return tp.channelMaster;\n  };\n\n  return (\n    <div className=\"flex h-full min-h-0 flex-col overflow-hidden bg-panel select-none\">\n      <div className=\"flex shrink-0 gap-1 border-b border-panel-border bg-panel p-1\">\n        {tabs.map((tab) => (\n          <button\n            key={tab.id}\n            type=\"button\"\n            onClick={() => setActiveTab(tab.id)}\n            className={`flex flex-1 cursor-pointer items-center justify-center gap-1 rounded-lg py-1.5 uppercase transition-all ${\n              activeTab === tab.id\n                ? 'bg-[var(--we-accent-capsule)] text-white'\n                : 'text-white/80 hover:bg-black-capsule hover:text-white'\n            }`}\n          >\n            {tab.icon}\n            <TextBody as=\"span\" size=\"sm\" className=\"font-bold uppercase text-inherit\">{tab.label}</TextBody>\n          </button>\n        ))}\n      </div>\n\n      <div className=\"min-h-0 flex-1 overflow-y-auto\">\n        <PanelBody>\n          {activeTab === 'basic' && (\n            <>\n              <PanelSection title={tp.aiTitle}>\n                <div className=\"flex gap-1.5\">\n                  <input\n                    type=\"text\"\n                    value={aiPrompt}\n                    onChange={(e) => setAiPrompt(e.target.value)}\n                    disabled={isGenerating}\n                    placeholder={tp.aiPlaceholder}\n                    className=\"min-w-0 flex-1 rounded-xl bg-black-capsule px-2.5 py-2 font-sans text-xs font-medium text-white placeholder:text-white/40 outline-none focus:ring-1 focus:ring-[var(--we-accent)]/50 disabled:opacity-50\"\n                  />\n                  <Button\n                    type=\"button\"\n                    variant=\"accent\"\n                    size=\"sm\"\n                    disabled={isGenerating || !aiPrompt.trim()}\n                    onClick={handleApplyAiGrading}\n                  >\n                    {isGenerating ? (\n                      <Loader size={12} className=\"animate-spin\" />\n                    ) : (\n                      <>\n                        <Sparkles size={12} />\n                        <TextBody as=\"span\" size=\"sm\">{tp.aiApply}</TextBody>\n                      </>\n                    )}\n                  </Button>\n                </div>\n                {aiError && (\n                  <TextBody as=\"p\" size=\"sm\" className=\"text-red-400\">\n                    {aiError}\n                  </TextBody>\n                )}\n              </PanelSection>\n\n              <PanelSection title={tp.tabBasic}>\n                <PanelField\n                  variant=\"slide\"\n                  label={tp.exposure}\n                  min={-5}\n                  max={5}\n                  step={0.1}\n                  numericValue={colorGrading.exposure}\n                  formatValue={exposureFmt}\n                  defaultValue={0}\n                  resetLabel={t.videoEditor.propertiesPanel.reset}\n                  onChange={(v) => updateSetting('exposure', v)}\n                />\n                <PanelField\n                  variant=\"slide\"\n                  label={tp.contrast}\n                  min={-100}\n                  max={100}\n                  step={1}\n                  numericValue={colorGrading.contrast}\n                  formatValue={pct}\n                  defaultValue={0}\n                  resetLabel={t.videoEditor.propertiesPanel.reset}\n                  onChange={(v) => updateSetting('contrast', v)}\n                />\n                <PanelField\n                  variant=\"slide\"\n                  label={tp.highlights}\n                  min={-100}\n                  max={100}\n                  step={1}\n                  numericValue={colorGrading.highlights}\n                  formatValue={pct}\n                  defaultValue={0}\n                  resetLabel={t.videoEditor.propertiesPanel.reset}\n                  onChange={(v) => updateSetting('highlights', v)}\n                />\n                <PanelField\n                  variant=\"slide\"\n                  label={tp.shadows}\n                  min={-100}\n                  max={100}\n                  step={1}\n                  numericValue={colorGrading.shadows}\n                  formatValue={pct}\n                  defaultValue={0}\n                  resetLabel={t.videoEditor.propertiesPanel.reset}\n                  onChange={(v) => updateSetting('shadows', v)}\n                />\n                <PanelField\n                  variant=\"slide\"\n                  label={tp.temperature}\n                  min={-100}\n                  max={100}\n                  step={1}\n                  numericValue={colorGrading.temperature}\n                  formatValue={signed}\n                  defaultValue={0}\n                  resetLabel={t.videoEditor.propertiesPanel.reset}\n                  onChange={(v) => updateSetting('temperature', v)}\n                />\n                <PanelField\n                  variant=\"slide\"\n                  label={tp.tint}\n                  min={-100}\n                  max={100}\n                  step={1}\n                  numericValue={colorGrading.tint}\n                  formatValue={signed}\n                  defaultValue={0}\n                  resetLabel={t.videoEditor.propertiesPanel.reset}\n                  onChange={(v) => updateSetting('tint', v)}\n                />\n                <PanelField\n                  variant=\"slide\"\n                  label={tp.vibrance}\n                  min={-100}\n                  max={100}\n                  step={1}\n                  numericValue={colorGrading.vibrance}\n                  formatValue={pct}\n                  defaultValue={0}\n                  resetLabel={t.videoEditor.propertiesPanel.reset}\n                  onChange={(v) => updateSetting('vibrance', v)}\n                />\n                <PanelField\n                  variant=\"slide\"\n                  label={tp.saturation}\n                  min={-100}\n                  max={100}\n                  step={1}\n                  numericValue={colorGrading.saturation}\n                  formatValue={pct}\n                  defaultValue={0}\n                  resetLabel={t.videoEditor.propertiesPanel.reset}\n                  onChange={(v) => updateSetting('saturation', v)}\n                />\n              </PanelSection>\n            </>\n          )}\n\n          {activeTab === 'curves' && (\n            <PanelSection\n              title={tp.tabCurves}\n              trailing={\n                <button\n                  type=\"button\"\n                  onClick={() =>\n                    handleCurveChange([\n                      { x: 0, y: 0 },\n                      { x: 1, y: 1 },\n                    ])\n                  }\n                  className=\"cursor-pointer select-none text-white/80 transition-colors hover:text-white\"\n                >\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-inherit\">{t.videoEditor.propertiesPanel.reset}</TextBody>\n                </button>\n              }\n            >\n              <div className=\"flex gap-1 rounded-xl bg-black-capsule p-1\">\n                {(['master', 'red', 'green', 'blue'] as CurveChannel[]).map((chan) => (\n                  <button\n                    key={chan}\n                    type=\"button\"\n                    onClick={() => setCurveChannel(chan)}\n                    className={`flex-1 cursor-pointer rounded-lg py-1.5 uppercase transition-colors ${\n                      curveChannel === chan\n                        ? chan === 'red'\n                          ? 'bg-red-500/25 text-red-300'\n                          : chan === 'green'\n                            ? 'bg-green-500/25 text-green-300'\n                            : chan === 'blue'\n                              ? 'bg-blue-500/25 text-blue-300'\n                              : 'bg-[var(--we-accent-capsule)] text-white'\n                        : 'text-white/80 hover:text-white'\n                    }`}\n                  >\n                    <TextBody as=\"span\" size=\"sm\" className=\"font-bold uppercase text-inherit\">\n                      {channelLabel(chan)}\n                    </TextBody>\n                  </button>\n                ))}\n              </div>\n              <ColorCurves\n                points={colorGrading.curves[curveChannel]}\n                onChange={handleCurveChange}\n                color={\n                  curveChannel === 'red'\n                    ? '#FF4A4A'\n                    : curveChannel === 'green'\n                      ? '#4AFF4A'\n                      : curveChannel === 'blue'\n                        ? '#4A4AFF'\n                        : '#FFFFFF'\n                }\n              />\n            </PanelSection>\n          )}\n\n          {activeTab === 'hsl' && (\n            <PanelSection title={tp.tabHsl}>\n              <div className=\"flex gap-1 rounded-xl bg-black-capsule p-1\">\n                {(\n                  [\n                    ['hue', tp.hslHue],\n                    ['saturation', tp.hslSaturation],\n                    ['luminance', tp.hslLuminance],\n                  ] as const\n                ).map(([id, label]) => (\n                  <button\n                    key={id}\n                    type=\"button\"\n                    onClick={() => setHslMode(id)}\n                    className={`flex-1 cursor-pointer rounded-lg py-1.5 uppercase transition-colors ${\n                      hslMode === id\n                        ? 'bg-[var(--we-accent-capsule)] text-white'\n                        : 'text-white/80 hover:text-white'\n                    }`}\n                  >\n                    <TextBody as=\"span\" size=\"sm\" className=\"font-bold uppercase text-inherit\">\n                      {label}\n                    </TextBody>\n                  </button>\n                ))}\n              </div>\n              {Object.keys(colorGrading.hslAdjustments).map((colorName) => {\n                const adj = colorGrading.hslAdjustments[colorName];\n                const val = adj[hslMode];\n                return (\n                  <PanelField\n                    key={colorName}\n                    variant=\"slide\"\n                    label={colorName.charAt(0).toUpperCase() + colorName.slice(1)}\n                    min={hslMode === 'hue' ? -180 : -100}\n                    max={hslMode === 'hue' ? 180 : 100}\n                    step={1}\n                    numericValue={val}\n                    formatValue={signed}\n                    defaultValue={0}\n                    resetLabel={t.videoEditor.propertiesPanel.reset}\n                    onChange={(v) => handleHslChange(colorName, hslMode, v)}\n                  />\n                );\n              })}\n            </PanelSection>\n          )}\n\n          {activeTab === 'vignette' && (\n            <PanelSection title={tp.tabVignette}>\n              <PanelField\n                label={tp.enableVignette}\n                trailing={\n                  <Switch\n                    checked={colorGrading.vignetteEnabled}\n                    onChange={(checked) => updateSetting('vignetteEnabled', checked)}\n                    ariaLabel={tp.enableVignette}\n                  />\n                }\n              />\n              {colorGrading.vignetteEnabled && (\n                <>\n                  <PanelField\n                    variant=\"slide\"\n                    label={tp.vignetteAmount}\n                    min={-100}\n                    max={100}\n                    step={1}\n                    numericValue={colorGrading.vignetteAmount}\n                    formatValue={pct}\n                    defaultValue={0}\n                    resetLabel={t.videoEditor.propertiesPanel.reset}\n                    onChange={(v) => updateSetting('vignetteAmount', v)}\n                  />\n                  <PanelField\n                    variant=\"slide\"\n                    label={tp.vignetteMidpoint}\n                    min={0}\n                    max={100}\n                    step={1}\n                    numericValue={colorGrading.vignetteMidpoint}\n                    formatValue={pct}\n                    defaultValue={50}\n                    resetLabel={t.videoEditor.propertiesPanel.reset}\n                    onChange={(v) => updateSetting('vignetteMidpoint', v)}\n                  />\n                  <PanelField\n                    variant=\"slide\"\n                    label={tp.vignetteFeather}\n                    min={0}\n                    max={100}\n                    step={1}\n                    numericValue={colorGrading.vignetteFeather}\n                    formatValue={pct}\n                    defaultValue={50}\n                    resetLabel={t.videoEditor.propertiesPanel.reset}\n                    onChange={(v) => updateSetting('vignetteFeather', v)}\n                  />\n                </>\n              )}\n            </PanelSection>\n          )}\n        </PanelBody>\n      </div>\n    </div>\n  );\n};\n\nexport default ColorGradingPanel;\n", "import React, { useRef, useState, useEffect } from 'react';\nimport { type CurvePoint } from '../../../store/useVideoStore';\nimport { useTranslation } from '../../../i18n';\nimport { TextBody } from '../../ui';\n\n\ninterface ColorCurvesProps {\n  points: CurvePoint[];\n  onChange: (points: CurvePoint[]) => void;\n  color: string; // Hex color for the curve line\n}\n\nexport const ColorCurves: React.FC<ColorCurvesProps> = ({ points, onChange, color }) => {\n  const t = useTranslation();\n  const svgRef = useRef<SVGSVGElement>(null);\n  const [draggedIndex, setDraggedIndex] = useState<number | null>(null);\n\n  // Sort points to make sure x is ascending\n  const sortedPoints = [...points].sort((a, b) => a.x - b.x);\n\n  const getSvgCoordinates = (e: React.MouseEvent<SVGSVGElement> | MouseEvent) => {\n    if (!svgRef.current) return { x: 0, y: 0 };\n    const rect = svgRef.current.getBoundingClientRect();\n    // Normalize coordinates to 0.0 - 1.0\n    // SVG coordinates have (0,0) at top-left. Color curve has (0,0) at bottom-left and (1,1) at top-right.\n    const x = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));\n    const y = Math.max(0, Math.min(1, 1 - (e.clientY - rect.top) / rect.height));\n    return { x, y };\n  };\n\n  const handleMouseDown = (index: number) => {\n    setDraggedIndex(index);\n  };\n\n  const handleSvgMouseDown = (e: React.MouseEvent<SVGSVGElement>) => {\n    // Check if clicked near any existing point\n    if (!svgRef.current) return;\n    const { x, y } = getSvgCoordinates(e);\n\n    // Find if clicked near an existing point (within tolerance)\n    const tolerance = 0.05;\n    const existingIdx = sortedPoints.findIndex(\n      (p) => Math.abs(p.x - x) < tolerance && Math.abs(p.y - y) < tolerance\n    );\n\n    if (existingIdx !== -1) {\n      setDraggedIndex(existingIdx);\n    } else {\n      // Create new point (except don't add outside bounds, and insert sorted)\n      const newPoint: CurvePoint = { x, y };\n      const newPoints = [...sortedPoints, newPoint].sort((a, b) => a.x - b.x);\n      const newIdx = newPoints.findIndex((p) => p.x === x && p.y === y);\n      onChange(newPoints);\n      setDraggedIndex(newIdx);\n    }\n  };\n\n  const handleDoubleClick = (index: number, e: React.MouseEvent) => {\n    e.stopPropagation();\n    // Don't delete endpoints (x=0 and x=1)\n    const p = sortedPoints[index];\n    if (p.x === 0 || p.x === 1) return;\n\n    const newPoints = sortedPoints.filter((_, idx) => idx !== index);\n    onChange(newPoints);\n    setDraggedIndex(null);\n  };\n\n  useEffect(() => {\n    const handleMouseMove = (e: MouseEvent) => {\n      if (draggedIndex === null) return;\n\n      const { x, y } = getSvgCoordinates(e);\n      const updatedPoints = [...sortedPoints];\n\n      // Endpoints constraints: x is locked to 0 or 1, y is free\n      if (draggedIndex === 0) {\n        updatedPoints[0] = { x: 0, y };\n      } else if (draggedIndex === sortedPoints.length - 1) {\n        updatedPoints[sortedPoints.length - 1] = { x: 1, y };\n      } else {\n        // Middle points: x must stay between neighbors to prevent overlapping\n        const prevX = sortedPoints[draggedIndex - 1].x;\n        const nextX = sortedPoints[draggedIndex + 1].x;\n        const clampedX = Math.max(prevX + 0.01, Math.min(nextX - 0.01, x));\n        updatedPoints[draggedIndex] = { x: clampedX, y };\n      }\n\n      onChange(updatedPoints);\n    };\n\n    const handleMouseUp = () => {\n      setDraggedIndex(null);\n    };\n\n    if (draggedIndex !== null) {\n      window.addEventListener('mousemove', handleMouseMove);\n      window.addEventListener('mouseup', handleMouseUp);\n    }\n\n    return () => {\n      window.removeEventListener('mousemove', handleMouseMove);\n      window.removeEventListener('mouseup', handleMouseUp);\n    };\n  }, [draggedIndex, sortedPoints, onChange]);\n\n  // Construct SVG Path (smooth bezier curve or straight segments)\n  // For color curves, drawing straight lines or simple cubic splines. Let's do simple bezier-like pathing.\n  // Creating a path using Bezier curves: for simplicity, we can do linear segments, or generate a smooth cubic spline.\n  // Straight lines look great and are very reliable, but splines are smoother. Let's draw linear segments first\n  // for absolute accuracy, with clean SVG paths.\n  const pathD = sortedPoints\n    .map((p, idx) => {\n      const svgX = p.x * 100;\n      const svgY = (1 - p.y) * 100;\n      return `${idx === 0 ? 'M' : 'L'} ${svgX} ${svgY}`;\n    })\n    .join(' ');\n\n  return (\n    <div className=\"flex w-full flex-col gap-1.5\">\n      <div className=\"relative aspect-square w-full cursor-crosshair select-none overflow-hidden rounded-xl border border-panel-border bg-black-capsule\">\n        {/* Grid lines */}\n        <div className=\"pointer-events-none absolute inset-0 grid grid-cols-4 grid-rows-4 opacity-10\">\n          <div className=\"h-full border-r border-white\" />\n          <div className=\"h-full border-r border-white\" />\n          <div className=\"h-full border-r border-white\" />\n          <div className=\"w-full border-b border-white\" />\n          <div className=\"w-full border-b border-white\" />\n          <div className=\"w-full border-b border-white\" />\n        </div>\n\n        {/* Diagonal identity reference line */}\n        <svg\n          className=\"pointer-events-none absolute inset-0 h-full w-full opacity-20\"\n          viewBox=\"0 0 100 100\"\n          preserveAspectRatio=\"none\"\n        >\n          <line\n            x1=\"0\"\n            y1=\"100\"\n            x2=\"100\"\n            y2=\"0\"\n            stroke=\"#8888A0\"\n            strokeWidth=\"0.5\"\n            strokeDasharray=\"2\"\n          />\n        </svg>\n\n        <svg\n          ref={svgRef}\n          className=\"absolute inset-0 h-full w-full\"\n          viewBox=\"0 0 100 100\"\n          preserveAspectRatio=\"none\"\n          onMouseDown={handleSvgMouseDown}\n        >\n          <path d={pathD} fill=\"none\" stroke={color} strokeWidth=\"1.5\" />\n\n          {sortedPoints.map((p, idx) => (\n            <circle\n              key={idx}\n              cx={p.x * 100}\n              cy={(1 - p.y) * 100}\n              r=\"3.5\"\n              fill={draggedIndex === idx ? '#FFFFFF' : color}\n              stroke=\"#0A0A0F\"\n              strokeWidth=\"1\"\n              className=\"cursor-pointer\"\n              onMouseDown={(e) => {\n                e.stopPropagation();\n                handleMouseDown(idx);\n              }}\n              onDoubleClick={(e) => handleDoubleClick(idx, e)}\n            />\n          ))}\n        </svg>\n      </div>\n      <TextBody as=\"span\" size=\"sm\" className=\"text-center text-white/80\">\n        {t.videoEditor.colorGrading.doubleClickDeletePoint}\n      </TextBody>\n    </div>\n  );\n};\n", "import React, { useState } from 'react';\nimport { useVideoStore, type AppliedEffect, type EffectType } from '../../../store/useVideoStore';\nimport { Eye, EyeOff, Trash2, ChevronUp, ChevronDown, Sparkles, Key } from 'lucide-react';\nimport { useTranslation } from '../../../i18n';\nimport { PanelField, TextBody, TextTitle } from '../../ui';\ninterface EffectStackProps {\n  clipId: string;\n  effects: AppliedEffect[];\n}\n\nexport const EffectStack: React.FC<EffectStackProps> = ({ clipId, effects = [] }) => {\n  const t = useTranslation();\n  const te = t.videoEditor.effectStack;\n  const {\n    removeEffect,\n    reorderEffects,\n    toggleEffect,\n    updateEffect,\n    addKeyframe,\n    removeKeyframe,\n    playheadTime,\n    tracks\n  } = useVideoStore();\n\n  const [expandedEffectId, setExpandedEffectId] = useState<string | null>(null);\n\n  // Find clip to calculate relative time\n  let selectedClip: any = null;\n  for (const track of tracks) {\n    const found = track.clips.find((c) => c.id === clipId);\n    if (found) {\n      selectedClip = found;\n      break;\n    }\n  }\n\n  const clipRelativeTime = selectedClip ? Math.max(0, playheadTime - selectedClip.startTime) : 0;\n\n  const sortedEffects = [...effects].sort((a, b) => a.order - b.order);\n\n  const handleToggleExpand = (id: string) => {\n    setExpandedEffectId(expandedEffectId === id ? null : id);\n  };\n\n  const handleParamChange = (effectId: string, paramName: string, value: any) => {\n    updateEffect(clipId, effectId, { [paramName]: value });\n  };\n\n  // Helper to check if a keyframe exists at the current clip time for a given property in the effect\n  const hasKeyframe = (fx: AppliedEffect, propertyName: string) => {\n    const track = fx.keyframes?.find((t) => t.property === propertyName);\n    if (!track) return false;\n    // Check if keyframe exists within 0.1s threshold of clipRelativeTime\n    return track.keyframes.some((k) => Math.abs(k.time - clipRelativeTime) < 0.05);\n  };\n\n  const handleToggleKeyframe = (fx: AppliedEffect, propertyName: string, currentValue: number) => {\n    const track = fx.keyframes?.find((t) => t.property === propertyName);\n    const existing = track?.keyframes.find((k) => Math.abs(k.time - clipRelativeTime) < 0.05);\n\n    if (existing) {\n      // Remove keyframe\n      // In our store, we have removeKeyframe action for clip properties, but what about effect keyframes?\n      // Wait! Let's check: useVideoStore has keyframe actions for clip properties.\n      // Wait, look at useVideoStore.ts:\n      // addKeyframe: (clipId, property, keyframeData)\n      // Wait, is there support for effect-specific keyframes? \n      // The store has `addKeyframe` which adds to `clip.keyframes`. If we prefix the property name like `effectId:paramName` (e.g. `fx_123:radius`),\n      // we can save effect keyframes directly in the clip's standard keyframe list! This is a simple and extremely elegant design!\n      // Yes! In `useVideoStore.ts`, `addKeyframe` is implemented for `clip.keyframes`. So if we use `effectId:paramName` as the property string,\n      // it works automatically without changing any store actions!\n      removeKeyframe(clipId, `${fx.id}:${propertyName}`, existing.id);\n    } else {\n      // Add keyframe\n      addKeyframe(clipId, `${fx.id}:${propertyName}`, {\n        time: clipRelativeTime,\n        value: currentValue,\n        easing: 'linear'\n      });\n    }\n  };\n\n  const getEffectKeyframeTrack = (fx: AppliedEffect, propertyName: string) => {\n    if (!selectedClip || !selectedClip.keyframes) return null;\n    return selectedClip.keyframes.find((t: any) => t.property === `${fx.id}:${propertyName}`);\n  };\n\n  const isKeyframeEnabledForParam = (fx: AppliedEffect, propertyName: string) => {\n    const track = getEffectKeyframeTrack(fx, propertyName);\n    return track && track.keyframes.length > 0;\n  };\n\n  const getEffectName = (type: EffectType) => {\n    return te.names[type as keyof typeof te.names] || type;\n  };\n\n  const renderEffectControls = (fx: AppliedEffect) => {\n    const params = fx.params || {};\n    const p = te.params;\n\n    const renderSliderWithKeyframe = (\n      label: string,\n      paramName: string,\n      min: number,\n      max: number,\n      step = 1,\n      formatVal?: (v: number) => string\n    ) => {\n      const val = params[paramName] !== undefined ? params[paramName] : min;\n      const kfActive = hasKeyframe(fx, paramName);\n      const isKfEnabled = isKeyframeEnabledForParam(fx, paramName);\n\n      return (\n        <div className=\"flex items-end gap-1.5\">\n          <div className=\"min-w-0 flex-1\">\n            <PanelField\n              variant=\"slide\"\n              label={label}\n              min={min}\n              max={max}\n              step={step}\n              numericValue={val}\n              formatValue={formatVal}\n              onChange={(v) => handleParamChange(fx.id, paramName, v)}\n            />\n          </div>\n          <button\n            type=\"button\"\n            onClick={() => handleToggleKeyframe(fx, paramName, val)}\n            className={`mb-0.5 cursor-pointer rounded-lg border p-1.5 transition-all ${\n              kfActive\n                ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)] text-[var(--we-accent)]'\n                : isKfEnabled\n                  ? 'border-[var(--we-accent)]/30 bg-[var(--we-accent-muted)]/40 text-[var(--we-accent)]/70 hover:text-[var(--we-accent)]'\n                  : 'border-panel-border bg-black-capsule text-white/50 hover:text-white'\n            }`}\n            title={kfActive ? te.removeKeyframe : te.addKeyframe}\n          >\n            <Key size={12} />\n          </button>\n        </div>\n      );\n    };\n\n    switch (fx.effectType) {\n      case 'exposure':\n        return (\n          <div className=\"space-y-2 pt-1\">\n            {renderSliderWithKeyframe(p.exposure, 'exposure', -5, 5, 0.1, (v) => `${v > 0 ? '+' : ''}${v.toFixed(1)}`)}\n          </div>\n        );\n\n      case 'brightness-contrast':\n        return (\n          <div className=\"space-y-2 pt-1\">\n            {renderSliderWithKeyframe(p.brightness, 'brightness', -100, 100, 1, (v) => `${v > 0 ? '+' : ''}${v}%`)}\n            {renderSliderWithKeyframe(p.contrast, 'contrast', -100, 100, 1, (v) => `${v > 0 ? '+' : ''}${v}%`)}\n          </div>\n        );\n\n      case 'hue-saturation':\n        return (\n          <div className=\"space-y-2 pt-1\">\n            {renderSliderWithKeyframe(p.saturation, 'saturation', -100, 100, 1, (v) => `${v > 0 ? '+' : ''}${v}%`)}\n          </div>\n        );\n\n      case 'color-temperature':\n        return (\n          <div className=\"space-y-2 pt-1\">\n            {renderSliderWithKeyframe(p.temperature, 'temperature', -100, 100, 1, (v) => `${v > 0 ? '+' : ''}${v}%`)}\n            {renderSliderWithKeyframe(p.tint, 'tint', -100, 100, 1, (v) => `${v > 0 ? '+' : ''}${v}%`)}\n          </div>\n        );\n\n      case 'blur-gaussian':\n        return (\n          <div className=\"space-y-2 pt-1\">\n            {renderSliderWithKeyframe(p.radius, 'radius', 0, 100, 1, (v) => `${v}px`)}\n          </div>\n        );\n\n      case 'vhs':\n        return (\n          <div className=\"space-y-2 pt-1\">\n            {renderSliderWithKeyframe(p.trackingNoise, 'trackingNoise', 0, 100, 1, (v) => `${v}%`)}\n            {renderSliderWithKeyframe(p.colorBleed, 'colorBleed', 0, 100, 1, (v) => `${v}%`)}\n            {renderSliderWithKeyframe(p.scanLines, 'scanLines', 0, 100, 1, (v) => `${v}%`)}\n            {renderSliderWithKeyframe(p.analogBrightness, 'brightness', 0, 100, 1, (v) => `${v}%`)}\n          </div>\n        );\n\n      case 'chromatic-aberration':\n        return (\n          <div className=\"space-y-2 pt-1\">\n            {renderSliderWithKeyframe(p.amount, 'amount', 0, 50, 0.5, (v) => `${v}px`)}\n          </div>\n        );\n\n      case 'pixelate':\n        return (\n          <div className=\"space-y-2 pt-1\">\n            {renderSliderWithKeyframe(p.blockSize, 'blockSize', 1, 64, 1, (v) => `${v}px`)}\n          </div>\n        );\n\n      case 'old-film':\n        return (\n          <div className=\"space-y-2 pt-1\">\n            {renderSliderWithKeyframe(p.sepiaIntensity, 'sepiaIntensity', 0, 100, 1, (v) => `${v}%`)}\n            {renderSliderWithKeyframe(p.scratchIntensity, 'scratchIntensity', 0, 100, 1, (v) => `${v}%`)}\n            {renderSliderWithKeyframe(p.jitter, 'jitter', 0, 100, 1, (v) => `${v}%`)}\n          </div>\n        );\n\n      case 'ken-burns':\n        return (\n          <div className=\"space-y-2 pt-1\">\n            {renderSliderWithKeyframe(p.startScale, 'startScale', 100, 300, 1, (v) => `${v}%`)}\n            {renderSliderWithKeyframe(p.endScale, 'endScale', 100, 300, 1, (v) => `${v}%`)}\n            {renderSliderWithKeyframe(p.startX, 'startX', -100, 100, 1, (v) => `${v}%`)}\n            {renderSliderWithKeyframe(p.startY, 'startY', -100, 100, 1, (v) => `${v}%`)}\n            {renderSliderWithKeyframe(p.endX, 'endX', -100, 100, 1, (v) => `${v}%`)}\n            {renderSliderWithKeyframe(p.endY, 'endY', -100, 100, 1, (v) => `${v}%`)}\n          </div>\n        );\n\n      case 'camera-shake':\n        return (\n          <div className=\"space-y-2 pt-1\">\n            {renderSliderWithKeyframe(p.frequency, 'frequency', 1, 30, 0.5, (v) => `${v} Hz`)}\n            {renderSliderWithKeyframe(p.intensity, 'intensity', 0, 100, 1, (v) => `${v}px`)}\n          </div>\n        );\n\n      case 'zoom-dynamic':\n        return (\n          <div className=\"space-y-2 pt-1\">\n            {renderSliderWithKeyframe(p.zoomPeak, 'amount', 100, 300, 1, (v) => `${v}%`)}\n            <PanelField\n              variant=\"normal\"\n              label={te.direction}\n              trailing={\n                <select\n                  value={params.direction || 'in'}\n                  onChange={(e) => handleParamChange(fx.id, 'direction', e.target.value)}\n                  className=\"cursor-pointer rounded-lg border border-panel-border bg-black-capsule px-2 py-1 font-sans text-[11px] font-medium text-white outline-none focus:border-[var(--we-accent)]\"\n                >\n                  <option value=\"in\">{te.zoomIn}</option>\n                  <option value=\"out\">{te.zoomOut}</option>\n                </select>\n              }\n            />\n            {renderSliderWithKeyframe(p.centerX, 'centerX', 0, 1, 0.05, (v) => `${Math.round(v * 100)}%`)}\n            {renderSliderWithKeyframe(p.centerY, 'centerY', 0, 1, 0.05, (v) => `${Math.round(v * 100)}%`)}\n          </div>\n        );\n\n      case 'mirror':\n        return (\n          <div className=\"space-y-2 pt-1\">\n            <PanelField\n              variant=\"normal\"\n              label={te.reflection}\n              trailing={\n                <select\n                  value={params.reflection || 'horizontal'}\n                  onChange={(e) => handleParamChange(fx.id, 'reflection', e.target.value)}\n                  className=\"cursor-pointer rounded-lg border border-panel-border bg-black-capsule px-2 py-1 font-sans text-[11px] font-medium text-white outline-none focus:border-[var(--we-accent)]\"\n                >\n                  <option value=\"horizontal\">{te.reflectionH}</option>\n                  <option value=\"vertical\">{te.reflectionV}</option>\n                  <option value=\"quad\">{te.reflectionQuad}</option>\n                </select>\n              }\n            />\n          </div>\n        );\n\n      default:\n        return (\n          <TextBody as=\"span\" size=\"sm\" className=\"block pt-1 italic text-white/80\">\n            {te.hardwareNote}\n          </TextBody>\n        );\n    }\n  };\n\n  return (\n    <div className=\"flex h-full min-h-0 flex-1 flex-col overflow-hidden\">\n      {effects.length === 0 ? (\n        <div className=\"flex flex-1 flex-col items-center justify-center p-4 text-center select-none\">\n          <Sparkles size={24} className=\"mb-2 text-white/25\" />\n          <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{te.emptyTitle}</TextBody>\n          <TextBody as=\"span\" size=\"sm\" className=\"mt-1 max-w-[220px] text-white/80\">\n            {te.emptyHint}\n          </TextBody>\n        </div>\n      ) : (\n        <div className=\"min-h-0 flex-1 space-y-2 overflow-y-auto p-0.5\">\n          {sortedEffects.map((fx, idx) => {\n            const isExpanded = expandedEffectId === fx.id;\n            return (\n              <div\n                key={fx.id}\n                className=\"flex flex-col overflow-hidden rounded-xl border border-panel-border bg-black-capsule transition-all\"\n              >\n                <div className=\"flex select-none items-center justify-between gap-2 border-b border-panel-border/60 bg-panel px-3 py-2\">\n                  <button\n                    type=\"button\"\n                    onClick={() => handleToggleExpand(fx.id)}\n                    className=\"min-w-0 flex-1 cursor-pointer truncate text-left text-white transition-colors hover:text-[var(--we-accent)]\"\n                  >\n                    <TextBody as=\"span\" size=\"sm\" className=\"truncate font-bold text-white\">\n                      {getEffectName(fx.effectType)}\n                    </TextBody>\n                  </button>\n\n                  <div className=\"flex shrink-0 items-center gap-0.5\">\n                    <button\n                      type=\"button\"\n                      onClick={() => toggleEffect(clipId, fx.id)}\n                      className={`cursor-pointer rounded-lg p-1 transition-colors hover:bg-black-capsule ${\n                        fx.enabled ? 'text-[var(--we-accent)]' : 'text-white/50'\n                      }`}\n                      title={fx.enabled ? te.disable : te.enable}\n                    >\n                      {fx.enabled ? <Eye size={12} /> : <EyeOff size={12} />}\n                    </button>\n                    <button\n                      type=\"button\"\n                      onClick={() => idx > 0 && reorderEffects(clipId, idx, idx - 1)}\n                      disabled={idx === 0}\n                      className=\"cursor-pointer rounded-lg p-1 text-white/80 transition-colors hover:bg-black-capsule hover:text-white disabled:pointer-events-none disabled:opacity-30\"\n                    >\n                      <ChevronUp size={12} />\n                    </button>\n                    <button\n                      type=\"button\"\n                      onClick={() =>\n                        idx < sortedEffects.length - 1 && reorderEffects(clipId, idx, idx + 1)\n                      }\n                      disabled={idx === sortedEffects.length - 1}\n                      className=\"cursor-pointer rounded-lg p-1 text-white/80 transition-colors hover:bg-black-capsule hover:text-white disabled:pointer-events-none disabled:opacity-30\"\n                    >\n                      <ChevronDown size={12} />\n                    </button>\n                    <button\n                      type=\"button\"\n                      onClick={() => removeEffect(clipId, fx.id)}\n                      className=\"cursor-pointer rounded-lg p-1 text-red-400 transition-colors hover:bg-red-500/15 hover:text-red-300\"\n                      title={te.remove}\n                    >\n                      <Trash2 size={12} />\n                    </button>\n                  </div>\n                </div>\n\n                {isExpanded && (\n                  <div className=\"space-y-3 border-t border-panel-border/40 bg-black-capsule p-3\">\n                    <div className=\"mb-1 space-y-2 border-b border-panel-border/50 pb-2.5\">\n                      <TextTitle as=\"h4\" size=\"xs\" className=\"uppercase tracking-wider\">\n                        {te.activeRange}\n                      </TextTitle>\n                      <PanelField\n                        variant=\"slide\"\n                        label={te.startTime}\n                        min={0}\n                        max={selectedClip ? selectedClip.duration : 10}\n                        step={0.1}\n                        numericValue={fx.startTime !== undefined ? fx.startTime : 0}\n                        formatValue={(v) => `${v.toFixed(1)}s`}\n                        onChange={(v) => updateEffect(clipId, fx.id, { startTime: v })}\n                      />\n                      <PanelField\n                        variant=\"slide\"\n                        label={te.endTime}\n                        min={fx.startTime !== undefined ? fx.startTime : 0}\n                        max={selectedClip ? selectedClip.duration : 10}\n                        step={0.1}\n                        numericValue={\n                          fx.endTime !== undefined\n                            ? fx.endTime\n                            : selectedClip\n                              ? selectedClip.duration\n                              : 10\n                        }\n                        formatValue={(v) => `${v.toFixed(1)}s`}\n                        onChange={(v) => updateEffect(clipId, fx.id, { endTime: v })}\n                      />\n                    </div>\n\n                    {renderEffectControls(fx)}\n                  </div>\n                )}\n              </div>\n            );\n          })}\n        </div>\n      )}\n    </div>\n  );\n};\nexport default EffectStack;\n", "import React, { useMemo, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Sparkles, Search, Sliders, Film, Move, Plus, Trash2 } from 'lucide-react';\nimport { useVideoStore, type EffectType } from '../../../store/useVideoStore';\nimport { PanelField, SelectDropdown, TextBody, TextTitle } from '../../ui';\nimport { useDialog } from '../../../components/DialogModal';\nimport { useTranslation } from '../../../i18n';\nimport { modeAccentVars, useModeAccent } from '../../../theme/modeAccent';\n\n\ntype EffectCategory = 'Color' | 'Stylistic' | 'Motion' | 'Transform';\n\ntype EffectItem = {\n  type: EffectType;\n  name: string;\n  desc: string;\n  category: EffectCategory;\n  params?: Record<string, unknown>;\n  isCustom?: boolean;\n};\n\nexport const EffectsPanel: React.FC = () => {\n  const t = useTranslation();\n  const te = t.videoEditor.effectsLibrary;\n  const tp = t.videoEditor.effectStack.params;\n  const tn = t.videoEditor.effectStack.names;\n  const [search, setSearch] = useState('');\n  const [activeCategory, setActiveCategory] = useState<\n    'All' | EffectCategory | 'Custom'\n  >('All');\n\n  const [customEffects, setCustomEffects] = useState<EffectItem[]>(() => {\n    if (typeof window !== 'undefined') {\n      const saved = localStorage.getItem('cutflow_custom_effects');\n      return saved ? JSON.parse(saved) : [];\n    }\n    return [];\n  });\n\n  const [showCreateModal, setShowCreateModal] = useState(false);\n  const [presetName, setPresetName] = useState('');\n  const [presetDesc, setPresetDesc] = useState('');\n  const [presetCategory, setPresetCategory] = useState<EffectCategory>('Color');\n  const [baseType, setBaseType] = useState<EffectType>('blur-gaussian');\n  const [presetParams, setPresetParams] = useState<Record<string, unknown>>({ radius: 25 });\n\n  const dialog = useDialog();\n  const mode = useModeAccent();\n  const { tracks, selectedClipIds, addEffect } = useVideoStore();\n\n  const builtInEffects = useMemo<EffectItem[]>(\n    () => [\n      { type: 'exposure', name: te.items.exposure.name, desc: te.items.exposure.desc, category: 'Color' },\n      { type: 'brightness-contrast', name: te.items.brightnessContrast.name, desc: te.items.brightnessContrast.desc, category: 'Color' },\n      { type: 'hue-saturation', name: te.items.hueSaturation.name, desc: te.items.hueSaturation.desc, category: 'Color' },\n      { type: 'color-temperature', name: te.items.colorTemperature.name, desc: te.items.colorTemperature.desc, category: 'Color' },\n      { type: 'blur-gaussian', name: te.items.blurGaussian.name, desc: te.items.blurGaussian.desc, category: 'Stylistic' },\n      { type: 'vhs', name: te.items.vhs.name, desc: te.items.vhs.desc, category: 'Stylistic' },\n      { type: 'old-film', name: te.items.oldFilm.name, desc: te.items.oldFilm.desc, category: 'Stylistic' },\n      { type: 'pixelate', name: te.items.pixelate.name, desc: te.items.pixelate.desc, category: 'Stylistic' },\n      { type: 'chromatic-aberration', name: te.items.chromaticAberration.name, desc: te.items.chromaticAberration.desc, category: 'Stylistic' },\n      { type: 'ken-burns', name: te.items.kenBurns.name, desc: te.items.kenBurns.desc, category: 'Motion' },\n      { type: 'camera-shake', name: te.items.cameraShake.name, desc: te.items.cameraShake.desc, category: 'Motion' },\n      { type: 'zoom-dynamic', name: te.items.zoomDynamic.name, desc: te.items.zoomDynamic.desc, category: 'Motion' },\n      { type: 'mirror', name: te.items.mirror.name, desc: te.items.mirror.desc, category: 'Transform' },\n    ],\n    [te.items],\n  );\n\n  const categoryLabel = (cat: 'All' | EffectCategory | 'Custom') => {\n    if (cat === 'All') return te.catAll;\n    if (cat === 'Color') return te.catColor;\n    if (cat === 'Stylistic') return te.catStylistic;\n    if (cat === 'Motion') return te.catMotion;\n    if (cat === 'Transform') return te.catTransform;\n    return te.catCustom;\n  };\n\n  const handleApplyEffect = (fx: EffectItem) => {\n    let selectedClipId: string | null = null;\n    for (const track of tracks) {\n      const found = track.clips.find((c) => selectedClipIds.includes(c.id));\n      if (found) {\n        selectedClipId = found.id;\n        break;\n      }\n    }\n\n    if (!selectedClipId) {\n      dialog.alert(te.noClipBody, { title: te.noClipTitle, variant: 'warning' });\n      return;\n    }\n\n    addEffect(selectedClipId, fx.type, fx.isCustom ? fx.params : undefined);\n  };\n\n  const handleBaseTypeChange = (type: EffectType) => {\n    setBaseType(type);\n    if (type === 'blur-gaussian') {\n      setPresetParams({ radius: 25 });\n    } else if (type === 'vhs') {\n      setPresetParams({ trackingNoise: 30, colorBleed: 40, scanLines: 50, brightness: 20 });\n    } else if (type === 'chromatic-aberration') {\n      setPresetParams({ amount: 15 });\n    } else if (type === 'pixelate') {\n      setPresetParams({ blockSize: 12 });\n    } else if (type === 'old-film') {\n      setPresetParams({ sepiaIntensity: 60, scratchIntensity: 40, jitter: 20 });\n    } else if (type === 'mirror') {\n      setPresetParams({ reflection: 'horizontal' });\n    } else if (type === 'camera-shake') {\n      setPresetParams({ intensity: 20, frequency: 12 });\n    } else if (type === 'exposure') {\n      setPresetParams({ exposure: 1.0 });\n    } else if (type === 'brightness-contrast') {\n      setPresetParams({ brightness: 20, contrast: 20 });\n    } else if (type === 'hue-saturation') {\n      setPresetParams({ saturation: 40 });\n    } else if (type === 'color-temperature') {\n      setPresetParams({ temperature: 30, tint: 10 });\n    } else {\n      setPresetParams({});\n    }\n  };\n\n  const handleSaveCustomEffect = () => {\n    if (!presetName.trim()) {\n      dialog.alert(te.nameRequiredBody, { title: te.nameRequiredTitle, variant: 'warning' });\n      return;\n    }\n\n    const newCustomEffect: EffectItem = {\n      type: baseType,\n      name: presetName.trim(),\n      desc: presetDesc.trim() || te.customPresetFallback(baseType),\n      category: presetCategory,\n      params: presetParams,\n      isCustom: true,\n    };\n\n    const updated = [newCustomEffect, ...customEffects];\n    setCustomEffects(updated);\n    if (typeof window !== 'undefined') {\n      localStorage.setItem('cutflow_custom_effects', JSON.stringify(updated));\n    }\n\n    setPresetName('');\n    setPresetDesc('');\n    setShowCreateModal(false);\n  };\n\n  const handleDeleteCustomEffect = (name: string, e: React.MouseEvent) => {\n    e.stopPropagation();\n    const updated = customEffects.filter((fx) => fx.name !== name);\n    setCustomEffects(updated);\n    if (typeof window !== 'undefined') {\n      localStorage.setItem('cutflow_custom_effects', JSON.stringify(updated));\n    }\n  };\n\n  const allEffects = [...customEffects, ...builtInEffects.map((fx) => ({ ...fx, isCustom: false }))];\n\n  const filtered = allEffects.filter((fx) => {\n    const q = search.toLowerCase();\n    const matchSearch =\n      fx.name.toLowerCase().includes(q) || fx.desc.toLowerCase().includes(q);\n    const matchCat =\n      activeCategory === 'All' ||\n      (activeCategory === 'Custom' && fx.isCustom) ||\n      (!fx.isCustom && fx.category === activeCategory);\n    return matchSearch && matchCat;\n  });\n\n  const getCategoryIcon = (category: string) => {\n    if (category === 'Color') return <Sliders size={12} className=\"text-[var(--we-accent)]\" />;\n    if (category === 'Stylistic') return <Film size={12} className=\"text-[var(--we-accent)]\" />;\n    if (category === 'Motion') return <Move size={12} className=\"text-[var(--we-accent)]\" />;\n    return <Sparkles size={12} className=\"text-[var(--we-accent)]\" />;\n  };\n\n  const num = (key: string, fallback: number) => {\n    const v = presetParams[key];\n    return typeof v === 'number' ? v : fallback;\n  };\n\n  const renderPresetParameterSliders = () => {\n    const handleSliderChange = (key: string, val: number) => {\n      setPresetParams((prev) => ({ ...prev, [key]: val }));\n    };\n\n    switch (baseType) {\n      case 'blur-gaussian':\n        return (\n          <PanelField\n            variant=\"slide\"\n            label={tp.radius}\n            min={0}\n            max={100}\n            numericValue={num('radius', 25)}\n            onChange={(v) => handleSliderChange('radius', v)}\n            formatValue={(v) => `${v}px`}\n          />\n        );\n      case 'vhs':\n        return (\n          <div className=\"space-y-2\">\n            <PanelField variant=\"slide\" label={tp.trackingNoise} min={0} max={100} numericValue={num('trackingNoise', 30)} onChange={(v) => handleSliderChange('trackingNoise', v)} formatValue={(v) => `${v}%`} />\n            <PanelField variant=\"slide\" label={tp.colorBleed} min={0} max={100} numericValue={num('colorBleed', 40)} onChange={(v) => handleSliderChange('colorBleed', v)} formatValue={(v) => `${v}%`} />\n            <PanelField variant=\"slide\" label={tp.scanLines} min={0} max={100} numericValue={num('scanLines', 50)} onChange={(v) => handleSliderChange('scanLines', v)} formatValue={(v) => `${v}%`} />\n          </div>\n        );\n      case 'chromatic-aberration':\n        return (\n          <PanelField variant=\"slide\" label={tp.amount} min={0} max={50} numericValue={num('amount', 15)} onChange={(v) => handleSliderChange('amount', v)} formatValue={(v) => `${v}px`} />\n        );\n      case 'pixelate':\n        return (\n          <PanelField variant=\"slide\" label={tp.blockSize} min={1} max={64} numericValue={num('blockSize', 12)} onChange={(v) => handleSliderChange('blockSize', v)} formatValue={(v) => `${v}px`} />\n        );\n      case 'old-film':\n        return (\n          <div className=\"space-y-2\">\n            <PanelField variant=\"slide\" label={tp.sepiaIntensity} min={0} max={100} numericValue={num('sepiaIntensity', 60)} onChange={(v) => handleSliderChange('sepiaIntensity', v)} formatValue={(v) => `${v}%`} />\n            <PanelField variant=\"slide\" label={tp.scratchIntensity} min={0} max={100} numericValue={num('scratchIntensity', 40)} onChange={(v) => handleSliderChange('scratchIntensity', v)} formatValue={(v) => `${v}%`} />\n            <PanelField variant=\"slide\" label={tp.jitter} min={0} max={100} numericValue={num('jitter', 20)} onChange={(v) => handleSliderChange('jitter', v)} formatValue={(v) => `${v}%`} />\n          </div>\n        );\n      case 'mirror':\n        return (\n          <PanelField\n            variant=\"normal\"\n            label={t.videoEditor.effectStack.reflection}\n            trailing={\n              <SelectDropdown\n                value={String(presetParams.reflection || 'horizontal')}\n                options={[\n                  { value: 'horizontal', label: t.videoEditor.effectStack.reflectionH },\n                  { value: 'vertical', label: t.videoEditor.effectStack.reflectionV },\n                  { value: 'quad', label: t.videoEditor.effectStack.reflectionQuad },\n                ]}\n                onChange={(v) => setPresetParams((prev) => ({ ...prev, reflection: v }))}\n              />\n            }\n          />\n        );\n      case 'camera-shake':\n        return (\n          <div className=\"space-y-2\">\n            <PanelField variant=\"slide\" label={tp.frequency} min={1} max={30} step={0.5} numericValue={num('frequency', 12)} onChange={(v) => handleSliderChange('frequency', v)} formatValue={(v) => `${v} Hz`} />\n            <PanelField variant=\"slide\" label={tp.intensity} min={0} max={100} numericValue={num('intensity', 20)} onChange={(v) => handleSliderChange('intensity', v)} formatValue={(v) => `${v}px`} />\n          </div>\n        );\n      case 'exposure':\n        return (\n          <PanelField variant=\"slide\" label={tp.exposure} min={-5} max={5} step={0.1} numericValue={num('exposure', 1)} onChange={(v) => handleSliderChange('exposure', v)} formatValue={(v) => `${v > 0 ? '+' : ''}${v.toFixed(1)}`} />\n        );\n      case 'brightness-contrast':\n        return (\n          <div className=\"space-y-2\">\n            <PanelField variant=\"slide\" label={tp.brightness} min={-100} max={100} numericValue={num('brightness', 20)} onChange={(v) => handleSliderChange('brightness', v)} formatValue={(v) => `${v > 0 ? '+' : ''}${v}%`} />\n            <PanelField variant=\"slide\" label={tp.contrast} min={-100} max={100} numericValue={num('contrast', 20)} onChange={(v) => handleSliderChange('contrast', v)} formatValue={(v) => `${v > 0 ? '+' : ''}${v}%`} />\n          </div>\n        );\n      case 'hue-saturation':\n        return (\n          <PanelField variant=\"slide\" label={tp.saturation} min={-100} max={100} numericValue={num('saturation', 40)} onChange={(v) => handleSliderChange('saturation', v)} formatValue={(v) => `${v > 0 ? '+' : ''}${v}%`} />\n        );\n      case 'color-temperature':\n        return (\n          <div className=\"space-y-2\">\n            <PanelField variant=\"slide\" label={tp.temperature} min={-100} max={100} numericValue={num('temperature', 30)} onChange={(v) => handleSliderChange('temperature', v)} formatValue={(v) => `${v > 0 ? '+' : ''}${v}%`} />\n            <PanelField variant=\"slide\" label={tp.tint} min={-100} max={100} numericValue={num('tint', 10)} onChange={(v) => handleSliderChange('tint', v)} formatValue={(v) => `${v > 0 ? '+' : ''}${v}%`} />\n          </div>\n        );\n      default:\n        return null;\n    }\n  };\n\n  const baseEngineOptions = [\n    { value: 'exposure', label: tn.exposure },\n    { value: 'brightness-contrast', label: tn['brightness-contrast'] },\n    { value: 'hue-saturation', label: tn['hue-saturation'] },\n    { value: 'color-temperature', label: tn['color-temperature'] },\n    { value: 'blur-gaussian', label: tn['blur-gaussian'] },\n    { value: 'vhs', label: tn.vhs },\n    { value: 'old-film', label: tn['old-film'] },\n    { value: 'pixelate', label: tn.pixelate },\n    { value: 'chromatic-aberration', label: tn['chromatic-aberration'] },\n    { value: 'mirror', label: tn.mirror },\n    { value: 'camera-shake', label: tn['camera-shake'] },\n  ];\n\n  return (\n    <div className=\"relative flex h-full min-h-0 flex-1 flex-col overflow-hidden bg-panel\">\n      <div className=\"shrink-0 border-b border-panel-border px-3 py-3\">\n        <div className=\"flex items-center gap-2\">\n          <div className=\"relative flex-1\">\n            <Search\n              size={12}\n              className=\"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-white/50\"\n            />\n            <input\n              type=\"text\"\n              placeholder={te.searchPlaceholder}\n              value={search}\n              onChange={(e) => setSearch(e.target.value)}\n              className=\"w-full rounded-xl border border-panel-border bg-black-capsule py-1.5 pl-8 pr-3 font-sans text-xs font-medium text-white outline-none placeholder:text-white/40 focus:border-[var(--we-accent)]\"\n            />\n          </div>\n          <button\n            type=\"button\"\n            onClick={() => {\n              handleBaseTypeChange('blur-gaussian');\n              setShowCreateModal(true);\n            }}\n            title={te.createCustomTitle}\n            className=\"flex h-7 w-7 shrink-0 cursor-pointer items-center justify-center rounded-xl bg-[var(--we-accent)] text-white transition-all hover:bg-[var(--we-accent-hover)] active:scale-95\"\n          >\n            <Plus size={13} />\n          </button>\n        </div>\n      </div>\n\n      <div className=\"flex shrink-0 gap-1 overflow-x-auto border-b border-panel-border/60 bg-panel px-3 py-2 scrollbar-none\">\n        {(['All', 'Color', 'Stylistic', 'Motion', 'Transform', 'Custom'] as const).map((cat) => (\n          <button\n            key={cat}\n            type=\"button\"\n            onClick={() => setActiveCategory(cat)}\n            className={`cursor-pointer whitespace-nowrap rounded-lg px-2.5 py-1 transition-all ${\n              activeCategory === cat\n                ? 'bg-[var(--we-accent-capsule)] text-white'\n                : 'text-white/80 hover:bg-black-capsule hover:text-white'\n            }`}\n          >\n            <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-inherit\">\n              {categoryLabel(cat)}\n            </TextBody>\n          </button>\n        ))}\n      </div>\n\n      <div className=\"min-h-0 flex-1 space-y-1.5 overflow-y-auto p-3\">\n        {filtered.length === 0 ? (\n          <div className=\"flex h-40 flex-col items-center justify-center text-center\">\n            <Sparkles size={20} className=\"mb-2 text-white/25\" />\n            <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n              {te.noResults}\n            </TextBody>\n          </div>\n        ) : (\n          filtered.map((fx) => (\n            <div\n              key={fx.isCustom ? `custom_${fx.name}` : fx.type}\n              onDoubleClick={() => handleApplyEffect(fx)}\n              className=\"group flex cursor-pointer select-none items-center justify-between rounded-xl border border-panel-border bg-black-capsule p-2 transition-all hover:border-[var(--we-accent)]/40 hover:bg-black-capsule-hover\"\n              title={te.applyHint}\n            >\n              <div className=\"flex min-w-0 items-start gap-2.5\">\n                <div className=\"mt-0.5 flex shrink-0 rounded-lg bg-panel p-1.5\">\n                  {getCategoryIcon(fx.isCustom ? 'Custom' : fx.category)}\n                </div>\n                <div className=\"flex min-w-0 flex-col\">\n                  <TextBody as=\"span\" size=\"sm\" className=\"flex items-center gap-1.5 truncate text-white\">\n                    {fx.name}\n                    {fx.isCustom && (\n                      <TextBody as=\"span\" size=\"sm\" className=\"rounded-md border border-[var(--we-accent)]/25 bg-[var(--we-accent-muted)] px-1 py-0.5 font-extrabold text-[var(--we-accent)] uppercase\">\n                        {te.presetBadge}\n                      </TextBody>\n                    )}\n                  </TextBody>\n                  <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 truncate text-white/80\">\n                    {fx.desc}\n                  </TextBody>\n                </div>\n              </div>\n\n              <div className=\"flex items-center gap-1.5\">\n                {fx.isCustom && (\n                  <button\n                    type=\"button\"\n                    onClick={(e) => handleDeleteCustomEffect(fx.name, e)}\n                    className=\"cursor-pointer rounded-lg bg-red-500/10 p-1 text-red-400 opacity-0 transition-colors hover:bg-red-500 hover:text-white group-hover:opacity-100\"\n                    title={te.deletePreset}\n                  >\n                    <Trash2 size={11} />\n                  </button>\n                )}\n                <button\n                  type=\"button\"\n                  onClick={() => handleApplyEffect(fx)}\n                  className=\"cursor-pointer rounded-lg bg-[var(--we-accent)] px-2 py-1 text-[var(--we-accent-dark)] opacity-0 transition-all hover:opacity-80 group-hover:opacity-100 active:scale-95\"\n                >\n                  <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-[var(--we-accent-dark)]\">{te.apply}</TextBody>\n                </button>\n              </div>\n            </div>\n          ))\n        )}\n      </div>\n\n      {showCreateModal &&\n        createPortal(\n          <div\n            className=\"fixed inset-0 z-[110] flex animate-fadeIn items-center justify-center bg-black/75 p-4 backdrop-blur-sm\"\n            data-we-mode={mode}\n            style={modeAccentVars(mode)}\n            onWheel={(e) => e.stopPropagation()}\n          >\n            <div\n              className=\"absolute inset-0 cursor-default\"\n              onClick={() => setShowCreateModal(false)}\n            />\n            <div className=\"relative z-[111] flex max-h-[min(90vh,720px)] w-full max-w-lg flex-col overflow-hidden rounded-2xl border border-panel-border bg-panel shadow-2xl\">\n              <div className=\"border-b border-panel-border px-5 py-4\">\n                <TextTitle as=\"span\" size=\"sm\" className=\"flex items-center gap-1.5 tracking-wider text-white uppercase\">\n                  <Sparkles size={14} className=\"text-[var(--we-accent)]\" />\n                  {te.createCustomTitle}\n                </TextTitle>\n              </div>\n\n              <div className=\"min-h-0 flex-1 space-y-4 overflow-y-auto p-5\">\n                <div className=\"space-y-1.5\">\n                  <TextBody as=\"label\" size=\"sm\" className=\"block text-white uppercase\">\n                    {te.presetName}\n                  </TextBody>\n                  <input\n                    type=\"text\"\n                    placeholder={te.presetNamePlaceholder}\n                    value={presetName}\n                    onChange={(e) => setPresetName(e.target.value)}\n                    className=\"w-full rounded-xl border border-panel-border bg-black-capsule px-3 py-2 font-sans text-xs font-medium text-white outline-none placeholder:text-white/40 focus:border-[var(--we-accent)]\"\n                  />\n                </div>\n\n                <div className=\"space-y-1.5\">\n                  <TextBody as=\"label\" size=\"sm\" className=\"block text-white uppercase\">\n                    {te.description}\n                  </TextBody>\n                  <input\n                    type=\"text\"\n                    placeholder={te.descriptionPlaceholder}\n                    value={presetDesc}\n                    onChange={(e) => setPresetDesc(e.target.value)}\n                    className=\"w-full rounded-xl border border-panel-border bg-black-capsule px-3 py-2 font-sans text-xs font-medium text-white outline-none placeholder:text-white/40 focus:border-[var(--we-accent)]\"\n                  />\n                </div>\n\n                <PanelField\n                  variant=\"normal\"\n                  label={te.category}\n                  trailing={\n                    <SelectDropdown\n                      value={presetCategory}\n                      options={[\n                        { value: 'Color', label: te.catColorFull },\n                        { value: 'Stylistic', label: te.catStylisticFull },\n                        { value: 'Motion', label: te.catMotionFull },\n                        { value: 'Transform', label: te.catTransformFull },\n                      ]}\n                      onChange={(v) => setPresetCategory(v as EffectCategory)}\n                    />\n                  }\n                />\n\n                <PanelField\n                  variant=\"normal\"\n                  label={te.baseEngine}\n                  trailing={\n                    <SelectDropdown\n                      value={baseType}\n                      options={baseEngineOptions}\n                      onChange={(v) => handleBaseTypeChange(v as EffectType)}\n                    />\n                  }\n                />\n\n                <div className=\"space-y-2 border-t border-panel-border/50 pt-3\">\n                  <TextTitle as=\"h4\" size=\"xs\" className=\"tracking-wider uppercase\">\n                    {te.configureParams}\n                  </TextTitle>\n                  {renderPresetParameterSliders()}\n                </div>\n              </div>\n\n              <div className=\"flex gap-2 border-t border-panel-border bg-black-capsule p-4\">\n                <button\n                  type=\"button\"\n                  onClick={() => setShowCreateModal(false)}\n                  className=\"flex-1 cursor-pointer rounded-xl bg-panel py-2 text-white transition-all hover:bg-black-capsule-hover\"\n                >\n                  <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-white\">{te.cancel}</TextBody>\n                </button>\n                <button\n                  type=\"button\"\n                  onClick={handleSaveCustomEffect}\n                  className=\"flex-1 cursor-pointer rounded-xl bg-[var(--we-accent)] py-2 text-[var(--we-accent-dark)] transition-all hover:opacity-80\"\n                >\n                  <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-[var(--we-accent-dark)]\">{te.createEffect}</TextBody>\n                </button>\n              </div>\n            </div>\n          </div>,\n          document.body,\n        )}\n    </div>\n  );\n};\n\nexport default EffectsPanel;\n", "import React, { useMemo, useState } from 'react';\nimport { Shuffle, Search, X } from 'lucide-react';\nimport { useVideoStore, type TransitionType } from '../../../store/useVideoStore';\nimport { useVideoUiStore } from '../../../store/useVideoUiStore';\nimport { useTranslation } from '../../../i18n';\nimport { Button, Modal, TextBody } from '../../ui';\n\ntype TransitionCategory = 'Dissolve' | 'Wipe' | 'Slide' | 'Stylized';\n\ntype TransitionItem = {\n  type: TransitionType;\n  name: string;\n  desc: string;\n  category: TransitionCategory;\n};\n\nexport const TransitionPanel: React.FC = () => {\n  const t = useTranslation();\n  const tt = t.transition;\n  const [search, setSearch] = useState('');\n  const [activeCategory, setActiveCategory] = useState<'All' | TransitionCategory>('All');\n  const [showNoSelectionModal, setShowNoSelectionModal] = useState(false);\n  const [showUnsupportedModal, setShowUnsupportedModal] = useState(false);\n  const [pendingType, setPendingType] = useState<TransitionType | null>(null);\n  const [clipInfo, setClipInfo] = useState<{\n    clip: { id: string; type: string; startTime: number; duration: number };\n    track: { clips: Array<{ id: string; startTime: number; duration: number }> };\n    adjacentPrev: { id: string } | null;\n    adjacentNext: { id: string } | null;\n  } | null>(null);\n\n  const { tracks, selectedClipIds, addTransition, selectClip } = useVideoStore();\n  const transitionIntent = useVideoUiStore((s) => s.transitionIntent);\n  const clearTransitionIntent = useVideoUiStore((s) => s.clearTransitionIntent);\n\n  const transitionsList = useMemo<TransitionItem[]>(\n    () => [\n      { type: 'cross-dissolve', name: tt.items.crossDissolve.name, desc: tt.items.crossDissolve.desc, category: 'Dissolve' },\n      { type: 'fade-black', name: tt.items.fadeBlack.name, desc: tt.items.fadeBlack.desc, category: 'Dissolve' },\n      { type: 'fade-white', name: tt.items.fadeWhite.name, desc: tt.items.fadeWhite.desc, category: 'Dissolve' },\n      { type: 'additive-dissolve', name: tt.items.additiveDissolve.name, desc: tt.items.additiveDissolve.desc, category: 'Dissolve' },\n      { type: 'wipe-left', name: tt.items.wipeLeft.name, desc: tt.items.wipeLeft.desc, category: 'Wipe' },\n      { type: 'wipe-right', name: tt.items.wipeRight.name, desc: tt.items.wipeRight.desc, category: 'Wipe' },\n      { type: 'wipe-up', name: tt.items.wipeUp.name, desc: tt.items.wipeUp.desc, category: 'Wipe' },\n      { type: 'wipe-down', name: tt.items.wipeDown.name, desc: tt.items.wipeDown.desc, category: 'Wipe' },\n      { type: 'iris-circle', name: tt.items.irisCircle.name, desc: tt.items.irisCircle.desc, category: 'Wipe' },\n      { type: 'slide-left', name: tt.items.slideLeft.name, desc: tt.items.slideLeft.desc, category: 'Slide' },\n      { type: 'slide-right', name: tt.items.slideRight.name, desc: tt.items.slideRight.desc, category: 'Slide' },\n      { type: 'push-left', name: tt.items.pushLeft.name, desc: tt.items.pushLeft.desc, category: 'Slide' },\n      { type: 'push-right', name: tt.items.pushRight.name, desc: tt.items.pushRight.desc, category: 'Slide' },\n      { type: 'glitch', name: tt.items.glitch.name, desc: tt.items.glitch.desc, category: 'Stylized' },\n      { type: 'blur-dissolve', name: tt.items.blurDissolve.name, desc: tt.items.blurDissolve.desc, category: 'Stylized' },\n      { type: 'pixelate', name: tt.items.pixelate.name, desc: tt.items.pixelate.desc, category: 'Stylized' },\n      { type: 'film-burn', name: tt.items.filmBurn.name, desc: tt.items.filmBurn.desc, category: 'Stylized' },\n    ],\n    [tt.items],\n  );\n\n  const categoryLabel = (cat: 'All' | TransitionCategory) => {\n    if (cat === 'All') return tt.catAll;\n    if (cat === 'Dissolve') return tt.catDissolve;\n    if (cat === 'Wipe') return tt.catWipe;\n    if (cat === 'Slide') return tt.catSlide;\n    return tt.catStylized;\n  };\n\n  const handleApplyTransition = (type: TransitionType) => {\n    if (transitionIntent) {\n      if (transitionIntent.kind === 'start') {\n        selectClip(transitionIntent.clipId, false);\n        addTransition({\n          type,\n          fromClipId: 'none',\n          toClipId: transitionIntent.clipId,\n          duration: 0.8,\n          params: {},\n          easing: 'linear',\n          reverse: false,\n        });\n      } else if (transitionIntent.kind === 'end') {\n        selectClip(transitionIntent.clipId, false);\n        addTransition({\n          type,\n          fromClipId: transitionIntent.clipId,\n          toClipId: 'none',\n          duration: 0.8,\n          params: {},\n          easing: 'linear',\n          reverse: false,\n        });\n      } else {\n        selectClip(transitionIntent.fromClipId, false);\n        addTransition({\n          type,\n          fromClipId: transitionIntent.fromClipId,\n          toClipId: transitionIntent.toClipId,\n          duration: 0.8,\n          params: {},\n          easing: 'linear',\n          reverse: false,\n        });\n      }\n      clearTransitionIntent();\n      return;\n    }\n\n    let selectedClip: {\n      id: string;\n      type: string;\n      startTime: number;\n      duration: number;\n    } | null = null;\n    let clipTrack: { clips: Array<{ id: string; startTime: number; duration: number }> } | null =\n      null;\n\n    for (const track of tracks) {\n      const found = track.clips.find((c) => selectedClipIds.includes(c.id));\n      if (found) {\n        selectedClip = found;\n        clipTrack = track;\n        break;\n      }\n    }\n\n    if (!selectedClip || !clipTrack) {\n      setShowNoSelectionModal(true);\n      return;\n    }\n\n    if (selectedClip.type === 'audio') {\n      setShowUnsupportedModal(true);\n      return;\n    }\n\n    const sorted = [...clipTrack.clips].sort((a, b) => a.startTime - b.startTime);\n    const index = sorted.findIndex((c) => c.id === selectedClip.id);\n\n    let adjacentPrev: { id: string } | null = null;\n    let adjacentNext: { id: string } | null = null;\n\n    if (index > 0) {\n      const prev = sorted[index - 1];\n      if (prev) {\n        const gap = selectedClip.startTime - (prev.startTime + prev.duration);\n        if (gap <= 0.5) adjacentPrev = prev;\n      }\n    }\n\n    if (index < sorted.length - 1) {\n      const next = sorted[index + 1];\n      if (next) {\n        const gap = next.startTime - (selectedClip.startTime + selectedClip.duration);\n        if (gap <= 0.5) adjacentNext = next;\n      }\n    }\n\n    setPendingType(type);\n    setClipInfo({\n      clip: selectedClip,\n      track: clipTrack,\n      adjacentPrev,\n      adjacentNext,\n    });\n  };\n\n  const applyTransitionAction = (fromClipId: string, toClipId: string) => {\n    if (!pendingType) return;\n\n    addTransition({\n      type: pendingType,\n      fromClipId,\n      toClipId,\n      duration: 0.8,\n      params: {},\n      easing: 'linear',\n      reverse: false,\n    });\n\n    clearTransitionIntent();\n    setPendingType(null);\n    setClipInfo(null);\n  };\n\n  const filtered = transitionsList.filter((item) => {\n    const q = search.toLowerCase();\n    const matchSearch =\n      item.name.toLowerCase().includes(q) || item.desc.toLowerCase().includes(q);\n    const matchCat = activeCategory === 'All' || item.category === activeCategory;\n    return matchSearch && matchCat;\n  });\n\n  const pendingName =\n    transitionsList.find((item) => item.type === pendingType)?.name ?? '';\n\n  return (\n    <div className=\"flex h-full min-h-0 flex-1 flex-col overflow-hidden bg-panel\">\n      {transitionIntent && (\n        <div className=\"flex shrink-0 items-start justify-between gap-2 border-b border-[var(--we-accent)]/30 bg-[var(--we-accent-muted)] px-3 py-2\">\n          <TextBody as=\"p\" size=\"sm\" className=\"text-white\">\n            {tt.intentBanner}\n          </TextBody>\n          <button\n            type=\"button\"\n            onClick={clearTransitionIntent}\n            className=\"flex shrink-0 cursor-pointer items-center gap-1 rounded-md px-1.5 py-0.5 text-white/80 hover:bg-black-capsule hover:text-white\"\n          >\n            <X size={11} />\n            <TextBody as=\"span\" size=\"sm\" className=\"font-bold\">\n              {tt.intentClear}\n            </TextBody>\n          </button>\n        </div>\n      )}\n\n      <div className=\"shrink-0 border-b border-panel-border px-3 py-3\">\n        <div className=\"relative\">\n          <Search\n            size={12}\n            className=\"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-white/50\"\n          />\n          <input\n            type=\"text\"\n            placeholder={tt.searchPlaceholder}\n            value={search}\n            onChange={(e) => setSearch(e.target.value)}\n            className=\"w-full rounded-xl border border-panel-border bg-black-capsule py-1.5 pl-8 pr-3 font-sans text-xs font-medium text-white outline-none placeholder:text-white/40 focus:border-[var(--we-accent)]\"\n          />\n        </div>\n      </div>\n\n      <div className=\"flex shrink-0 gap-1 overflow-x-auto border-b border-panel-border/60 bg-panel px-3 py-2 scrollbar-none\">\n        {(['All', 'Dissolve', 'Wipe', 'Slide', 'Stylized'] as const).map((cat) => (\n          <button\n            key={cat}\n            type=\"button\"\n            onClick={() => setActiveCategory(cat)}\n            className={`cursor-pointer whitespace-nowrap rounded-lg px-2.5 py-1 transition-all ${\n              activeCategory === cat\n                ? 'bg-[var(--we-accent-capsule)] text-white'\n                : 'text-white/80 hover:bg-black-capsule hover:text-white'\n            }`}\n          >\n            <TextBody as=\"span\" size=\"sm\" className=\"font-bold\">\n              {categoryLabel(cat)}\n            </TextBody>\n          </button>\n        ))}\n      </div>\n\n      <div className=\"min-h-0 flex-1 space-y-1.5 overflow-y-auto p-3\">\n        {filtered.map((tr) => (\n          <div\n            key={tr.type}\n            onDoubleClick={() => handleApplyTransition(tr.type)}\n            className=\"group flex cursor-pointer select-none items-center justify-between rounded-xl border border-panel-border bg-black-capsule p-2 transition-all hover:border-[var(--we-accent)]/40 hover:bg-black-capsule-hover\"\n            title={tt.doubleClickHint}\n          >\n            <div className=\"flex min-w-0 items-start gap-2.5\">\n              <div className=\"mt-0.5 flex shrink-0 rounded-lg bg-panel p-1.5\">\n                <Shuffle size={12} className=\"text-[var(--we-accent)]\" />\n              </div>\n              <div className=\"flex min-w-0 flex-col\">\n                <TextBody as=\"span\" size=\"sm\" className=\"truncate text-white\">\n                  {tr.name}\n                </TextBody>\n                <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 truncate text-white/80\">\n                  {tr.desc}\n                </TextBody>\n              </div>\n            </div>\n            <button\n              type=\"button\"\n              onClick={() => handleApplyTransition(tr.type)}\n              className=\"cursor-pointer rounded-lg bg-[var(--we-accent)] px-2 py-1 text-[var(--we-accent-dark)] opacity-0 transition-all hover:opacity-80 group-hover:opacity-100 active:scale-95\"\n            >\n              <TextBody as=\"span\" size=\"sm\" className=\"font-bold\">\n                {tt.apply}\n              </TextBody>\n            </button>\n          </div>\n        ))}\n      </div>\n\n      <Modal\n        isOpen={showNoSelectionModal}\n        onClose={() => setShowNoSelectionModal(false)}\n        title={tt.noClipSelected}\n        size=\"sm\"\n      >\n        <div className=\"flex flex-col gap-5\">\n          <TextBody as=\"p\" size=\"sm\" className=\"leading-relaxed text-white/80\">\n            {tt.noClipSelectedBody}\n          </TextBody>\n          <Button\n            type=\"button\"\n            variant=\"accent\"\n            size=\"sm\"\n            className=\"w-full\"\n            onClick={() => setShowNoSelectionModal(false)}\n          >\n            {t.common.understood}\n          </Button>\n        </div>\n      </Modal>\n\n      <Modal\n        isOpen={Boolean(pendingType && clipInfo)}\n        onClose={() => {\n          setPendingType(null);\n          setClipInfo(null);\n        }}\n        title={tt.applyTransitionTitle}\n        size=\"sm\"\n      >\n        {clipInfo && (\n          <div className=\"flex flex-col gap-5\">\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {tt.applyTransitionBody(pendingName)}\n            </TextBody>\n\n            <div className=\"flex flex-col gap-2\">\n              <Button\n                type=\"button\"\n                variant=\"outline\"\n                size=\"sm\"\n                className=\"h-auto w-full justify-between px-4 py-2.5\"\n                onClick={() => applyTransitionAction('none', clipInfo.clip.id)}\n              >\n                <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                  {tt.fadeIn}\n                </TextBody>\n                <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{tt.fadeInShort}</TextBody>\n              </Button>\n\n              <Button\n                type=\"button\"\n                variant=\"outline\"\n                size=\"sm\"\n                className=\"h-auto w-full justify-between px-4 py-2.5\"\n                onClick={() => applyTransitionAction(clipInfo.clip.id, 'none')}\n              >\n                <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                  {tt.fadeOut}\n                </TextBody>\n                <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{tt.fadeOutShort}</TextBody>\n              </Button>\n\n              {clipInfo.adjacentPrev && (\n                <Button\n                  type=\"button\"\n                  variant=\"outline\"\n                  size=\"sm\"\n                  className=\"h-auto w-full justify-between px-4 py-2.5\"\n                  onClick={() =>\n                    applyTransitionAction(clipInfo.adjacentPrev!.id, clipInfo.clip.id)\n                  }\n                >\n                  <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                    {tt.betweenPrev}\n                  </TextBody>\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{tt.cut}</TextBody>\n                </Button>\n              )}\n\n              {clipInfo.adjacentNext && (\n                <Button\n                  type=\"button\"\n                  variant=\"outline\"\n                  size=\"sm\"\n                  className=\"h-auto w-full justify-between px-4 py-2.5\"\n                  onClick={() =>\n                    applyTransitionAction(clipInfo.clip.id, clipInfo.adjacentNext!.id)\n                  }\n                >\n                  <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                    {tt.betweenNext}\n                  </TextBody>\n                  <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">{tt.cut}</TextBody>\n                </Button>\n              )}\n            </div>\n\n            <div className=\"flex justify-end\">\n              <Button\n                type=\"button\"\n                variant=\"secondary\"\n                size=\"sm\"\n                onClick={() => {\n                  setPendingType(null);\n                  setClipInfo(null);\n                }}\n              >\n                {t.common.cancel}\n              </Button>\n            </div>\n          </div>\n        )}\n      </Modal>\n\n      <Modal\n        isOpen={showUnsupportedModal}\n        onClose={() => setShowUnsupportedModal(false)}\n        title={tt.notAllowedTitle}\n        size=\"sm\"\n      >\n        <div className=\"flex flex-col gap-5\">\n          <TextBody as=\"p\" size=\"sm\" className=\"leading-relaxed text-white/80\">\n            {tt.notAllowedAudioBody}\n          </TextBody>\n          <Button\n            type=\"button\"\n            variant=\"accent\"\n            size=\"sm\"\n            className=\"w-full\"\n            onClick={() => setShowUnsupportedModal(false)}\n          >\n            {t.common.understood}\n          </Button>\n        </div>\n      </Modal>\n    </div>\n  );\n};\n\nexport default TransitionPanel;\n", "import React, { useMemo } from 'react';\nimport { useVideoStore } from '../../../store/useVideoStore';\nimport { useTranslation } from '../../../i18n';\nimport { TextBody, TextTitle } from '../../ui';\n\ntype TextPresetCategory = 'Lower Third' | 'Title' | 'Social' | 'Info';\n\ntype TextPreset = {\n  id: string;\n  name: string;\n  category: TextPresetCategory;\n  desc: string;\n};\n\nexport const TextPanel: React.FC = () => {\n  const t = useTranslation();\n  const tp = t.videoEditor.textPanel;\n  const { tracks, addTextClip, playheadTime } = useVideoStore();\n\n  const presets = useMemo<TextPreset[]>(\n    () => [\n      { id: 'lowerThirdClassic', name: tp.presets.lowerThirdClassic.name, category: 'Lower Third', desc: tp.presets.lowerThirdClassic.desc },\n      { id: 'lowerThirdModern', name: tp.presets.lowerThirdModern.name, category: 'Lower Third', desc: tp.presets.lowerThirdModern.desc },\n      { id: 'lowerThirdMinimal', name: tp.presets.lowerThirdMinimal.name, category: 'Lower Third', desc: tp.presets.lowerThirdMinimal.desc },\n      { id: 'bigTitle', name: tp.presets.bigTitle.name, category: 'Title', desc: tp.presets.bigTitle.desc },\n      { id: 'subtitlePair', name: tp.presets.subtitlePair.name, category: 'Title', desc: tp.presets.subtitlePair.desc },\n      { id: 'centeredMinimal', name: tp.presets.centeredMinimal.name, category: 'Title', desc: tp.presets.centeredMinimal.desc },\n      { id: 'tiktokCaption', name: tp.presets.tiktokCaption.name, category: 'Social', desc: tp.presets.tiktokCaption.desc },\n      { id: 'youtubeChapter', name: tp.presets.youtubeChapter.name, category: 'Social', desc: tp.presets.youtubeChapter.desc },\n      { id: 'instagramQuote', name: tp.presets.instagramQuote.name, category: 'Social', desc: tp.presets.instagramQuote.desc },\n      { id: 'callOutBox', name: tp.presets.callOutBox.name, category: 'Info', desc: tp.presets.callOutBox.desc },\n      { id: 'quoteCard', name: tp.presets.quoteCard.name, category: 'Info', desc: tp.presets.quoteCard.desc },\n    ],\n    [tp.presets],\n  );\n\n  const getOrCreateTextTrackId = () => {\n    let firstTextTrack = tracks.find((tr) => tr.type === 'text');\n    if (!firstTextTrack) {\n      useVideoStore.getState().addTrack(tp.trackName, 'text');\n      firstTextTrack = useVideoStore.getState().tracks.find((tr) => tr.type === 'text');\n    }\n    return firstTextTrack ? firstTextTrack.id : 't1';\n  };\n\n  const handleAddPreset = (preset: TextPreset) => {\n    const presetProps: Record<string, unknown> = {\n      text: preset.name,\n      fontSize: 48,\n      fontFamily: 'Inter',\n      fillColor: '#FFFFFF',\n      fontWeight: 600,\n    };\n\n    if (preset.category === 'Lower Third') {\n      presetProps.y = 0.8;\n      presetProps.fontSize = 32;\n      presetProps.backgroundEnabled = true;\n      presetProps.backgroundColor = '#13131A';\n      presetProps.backgroundOpacity = 0.8;\n      presetProps.backgroundPadding = 8;\n    } else if (preset.category === 'Social') {\n      presetProps.fillColor = '#FFEB3B';\n      presetProps.strokeEnabled = true;\n      presetProps.strokeColor = '#000000';\n      presetProps.strokeWidth = 4;\n      presetProps.y = 0.75;\n    } else if (preset.category === 'Title') {\n      presetProps.fontSize = 72;\n      presetProps.fontWeight = 800;\n      presetProps.textTransform = 'uppercase';\n      presetProps.fillType = 'gradient';\n      presetProps.gradientColors = ['var(--we-accent)', '#FF4081'];\n    }\n\n    const targetTrackId = getOrCreateTextTrackId();\n    addTextClip({\n      trackId: targetTrackId,\n      assetId: '',\n      startTime: playheadTime,\n      duration: 5.0,\n      trimIn: 0,\n      trimOut: 0,\n      speed: 1.0,\n      volume: 1.0,\n      opacity: 1.0,\n      muted: false,\n      ...presetProps,\n    });\n  };\n\n  return (\n    <div className=\"flex h-full min-h-0 flex-1 flex-col overflow-hidden bg-panel\">\n      <div className=\"min-h-0 flex-1 space-y-2 overflow-y-auto p-3\">\n        <TextTitle as=\"span\" size=\"xs\" className=\"mb-1 block uppercase tracking-wider\">\n          {tp.presetsTitle}\n        </TextTitle>\n        <div className=\"space-y-1.5\">\n          {presets.map((preset) => (\n            <div\n              key={preset.id}\n              onClick={() => handleAddPreset(preset)}\n              className=\"group flex cursor-pointer select-none items-center justify-between rounded-xl border border-panel-border bg-black-capsule p-2 transition-colors hover:bg-black-capsule-hover\"\n            >\n              <div className=\"flex flex-col\">\n                <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-white\">\n                  {preset.name}\n                </TextBody>\n                <TextBody as=\"span\" size=\"sm\" className=\"mt-0.5 text-white/80\">\n                  {preset.desc}\n                </TextBody>\n              </div>\n              <TextBody\n                as=\"span\"\n                size=\"sm\"\n                className=\"rounded-lg bg-[var(--we-accent)] px-1.5 py-0.5 font-bold text-[var(--we-accent-dark)] opacity-0 transition-opacity group-hover:opacity-100\"\n              >\n                {tp.add}\n              </TextBody>\n            </div>\n          ))}\n        </div>\n      </div>\n    </div>\n  );\n};\n\nexport default TextPanel;\n\n/** @deprecated Prefer building presets via i18n inside TextPanel. Kept for any external imports. */\nexport const TEXT_PRESETS = [\n  { name: 'Lower Third Classic', category: 'Lower Third', desc: 'Elegant lower third' },\n  { name: 'Lower Third Modern', category: 'Lower Third', desc: 'Clean sans-serif strip' },\n  { name: 'Lower Third Minimal', category: 'Lower Third', desc: 'Simple text line' },\n  { name: 'Big Title', category: 'Title', desc: 'Huge bold title card' },\n  { name: 'Subtitle Pair', category: 'Title', desc: 'Header + secondary subtitle' },\n  { name: 'Centered Minimal', category: 'Title', desc: 'Centered thin font' },\n  { name: 'TikTok Caption', category: 'Social', desc: 'Bright yellow centered cap' },\n  { name: 'YouTube Chapter', category: 'Social', desc: 'Top left corner chapter tag' },\n  { name: 'Instagram Quote', category: 'Social', desc: 'Italic quote block' },\n  { name: 'Call Out Box', category: 'Info', desc: 'Framed pointer box' },\n  { name: 'Quote Card', category: 'Info', desc: 'Text in block backing' },\n];\n", "import React, { useMemo } from 'react';\nimport {\n  useVideoStore,\n  type TransitionType,\n} from '../../../store/useVideoStore';\nimport { useVideoUiStore } from '../../../store/useVideoUiStore';\nimport { useTranslation } from '../../../i18n';\nimport { Button, Modal, PanelField, SelectDropdown, TextBody } from '../../ui';\n\nconst NONE = '__none__';\n\nfunction transitionOptions(tt: ReturnType<typeof useTranslation>['transition']) {\n  return [\n    { value: NONE, label: tt.junctionNone },\n    { value: 'cross-dissolve', label: tt.items.crossDissolve.name },\n    { value: 'fade-black', label: tt.items.fadeBlack.name },\n    { value: 'fade-white', label: tt.items.fadeWhite.name },\n    { value: 'additive-dissolve', label: tt.items.additiveDissolve.name },\n    { value: 'wipe-left', label: tt.items.wipeLeft.name },\n    { value: 'wipe-right', label: tt.items.wipeRight.name },\n    { value: 'wipe-up', label: tt.items.wipeUp.name },\n    { value: 'wipe-down', label: tt.items.wipeDown.name },\n    { value: 'iris-circle', label: tt.items.irisCircle.name },\n    { value: 'slide-left', label: tt.items.slideLeft.name },\n    { value: 'slide-right', label: tt.items.slideRight.name },\n    { value: 'push-left', label: tt.items.pushLeft.name },\n    { value: 'push-right', label: tt.items.pushRight.name },\n    { value: 'glitch', label: tt.items.glitch.name },\n    { value: 'blur-dissolve', label: tt.items.blurDissolve.name },\n    { value: 'pixelate', label: tt.items.pixelate.name },\n    { value: 'film-burn', label: tt.items.filmBurn.name },\n  ];\n}\n\nfunction clipLabel(\n  clipId: string,\n  tracks: ReturnType<typeof useVideoStore.getState>['tracks'],\n  assets: ReturnType<typeof useVideoStore.getState>['assets'],\n): string {\n  for (const track of tracks) {\n    const clip = track.clips.find((c) => c.id === clipId);\n    if (!clip) continue;\n    const asset = assets.find((a) => a.id === clip.assetId);\n    return clip.text || asset?.name || clipId.slice(0, 10);\n  }\n  return clipId.slice(0, 10);\n}\n\n/**\n * Resolve / edit transitions at a clip junction (after split or abutting move).\n * Uses design-system Modal / Button / PanelField / SelectDropdown.\n */\nexport const TransitionJunctionModal: React.FC = () => {\n  const t = useTranslation();\n  const tt = t.transition;\n  const junction = useVideoUiStore((s) => s.transitionJunction);\n  const close = useVideoUiStore((s) => s.closeTransitionJunction);\n  const { tracks, assets, transitions, addTransition, removeTransition } =\n    useVideoStore();\n\n  const options = useMemo(() => transitionOptions(tt), [tt]);\n\n  const fromClipId = junction?.fromClipId ?? '';\n  const toClipId = junction?.toClipId ?? '';\n  const fromName = junction ? clipLabel(fromClipId, tracks, assets) : '';\n  const toName = junction ? clipLabel(toClipId, tracks, assets) : '';\n\n  const between = transitions.find(\n    (tr) => tr.fromClipId === fromClipId && tr.toClipId === toClipId,\n  );\n  const leftEnd = transitions.find(\n    (tr) => tr.fromClipId === fromClipId && tr.toClipId === 'none',\n  );\n  const rightStart = transitions.find(\n    (tr) => tr.fromClipId === 'none' && tr.toClipId === toClipId,\n  );\n\n  const leftValue = between?.type ?? leftEnd?.type ?? NONE;\n  const rightValue = between?.type ?? rightStart?.type ?? NONE;\n  const isConflict = Boolean(junction && !between && leftEnd && rightStart);\n\n  const clearJunctionTransitions = () => {\n    if (between) removeTransition(between.id);\n    if (leftEnd) removeTransition(leftEnd.id);\n    if (rightStart) removeTransition(rightStart.id);\n  };\n\n  const applySides = (left: string, right: string) => {\n    const leftDur = between?.duration ?? leftEnd?.duration ?? 0.8;\n    const rightDur = between?.duration ?? rightStart?.duration ?? 0.8;\n    clearJunctionTransitions();\n\n    if (left === NONE && right === NONE) return;\n\n    if (left !== NONE && right !== NONE && left === right) {\n      addTransition({\n        type: left as TransitionType,\n        fromClipId,\n        toClipId,\n        duration: leftDur,\n        params: {},\n        easing: 'linear',\n        reverse: false,\n      });\n      return;\n    }\n\n    if (left !== NONE && right !== NONE) {\n      addTransition({\n        type: left as TransitionType,\n        fromClipId,\n        toClipId: 'none',\n        duration: leftDur,\n        params: {},\n        easing: 'linear',\n        reverse: false,\n      });\n      addTransition({\n        type: right as TransitionType,\n        fromClipId: 'none',\n        toClipId,\n        duration: rightDur,\n        params: {},\n        easing: 'linear',\n        reverse: false,\n      });\n      return;\n    }\n\n    if (left !== NONE) {\n      addTransition({\n        type: left as TransitionType,\n        fromClipId,\n        toClipId: 'none',\n        duration: leftDur,\n        params: {},\n        easing: 'linear',\n        reverse: false,\n      });\n    }\n    if (right !== NONE) {\n      addTransition({\n        type: right as TransitionType,\n        fromClipId: 'none',\n        toClipId,\n        duration: rightDur,\n        params: {},\n        easing: 'linear',\n        reverse: false,\n      });\n    }\n  };\n\n  const removeBoth = () => {\n    clearJunctionTransitions();\n    close();\n  };\n\n  return (\n    <Modal\n      isOpen={Boolean(junction)}\n      onClose={close}\n      title={tt.junctionTitle}\n      size=\"md\"\n    >\n      <div className=\"flex flex-col gap-5\">\n        <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n          {isConflict ? tt.junctionConflictHint : tt.junctionHint}\n        </TextBody>\n\n        <div className=\"grid grid-cols-2 gap-3\">\n          <div className=\"flex flex-col gap-3 rounded-xl border border-panel-border bg-black-capsule p-3\">\n            <div className=\"flex aspect-video items-center justify-center rounded-lg border border-panel-border bg-panel px-2\">\n              <TextBody as=\"span\" size=\"sm\" className=\"line-clamp-2 text-center text-white\">\n                {fromName}\n              </TextBody>\n            </div>\n            <PanelField\n              label={tt.junctionLeft}\n              trailing={\n                <SelectDropdown\n                  value={String(leftValue)}\n                  options={options}\n                  onChange={(v) => applySides(v, String(rightValue))}\n                />\n              }\n            />\n          </div>\n\n          <div className=\"flex flex-col gap-3 rounded-xl border border-panel-border bg-black-capsule p-3\">\n            <div className=\"flex aspect-video items-center justify-center rounded-lg border border-panel-border bg-panel px-2\">\n              <TextBody as=\"span\" size=\"sm\" className=\"line-clamp-2 text-center text-white\">\n                {toName}\n              </TextBody>\n            </div>\n            <PanelField\n              label={tt.junctionRight}\n              trailing={\n                <SelectDropdown\n                  value={String(rightValue)}\n                  options={options}\n                  onChange={(v) => applySides(String(leftValue), v)}\n                />\n              }\n            />\n          </div>\n        </div>\n\n        <div className=\"flex gap-2 pt-1\">\n          <Button\n            type=\"button\"\n            variant=\"secondary\"\n            size=\"sm\"\n            className=\"flex-1\"\n            onClick={removeBoth}\n          >\n            {tt.junctionRemoveBoth}\n          </Button>\n          <Button\n            type=\"button\"\n            variant=\"accent\"\n            size=\"sm\"\n            className=\"flex-1\"\n            onClick={close}\n          >\n            {tt.junctionDone}\n          </Button>\n        </div>\n      </div>\n    </Modal>\n  );\n};\n\nexport default TransitionJunctionModal;\n", "import React, { useRef, useState } from 'react';\nimport {\n  Eye,\n  EyeOff,\n  Volume2,\n  VolumeX,\n  Lock,\n  Unlock,\n  Trash2,\n  Plus,\n  ChevronUp,\n  ChevronDown,\n} from 'lucide-react';\nimport { useVideoStore, type Track } from '../../store/useVideoStore';\nimport { useTranslation } from '../../i18n';\nimport { getVisibleTimelineTracks } from '../../utils/timelineUtils';\nimport { ViewportPortalMenu } from '../../utils/ViewportPortalMenu';\nimport { TextBody, TextTitle } from '../ui';\n\ninterface TrackControlsProps {\n  trackHeight?: number;\n  width?: number;\n  onHResizeStart?: (e: React.MouseEvent) => void;\n}\n\nexport const TrackControls: React.FC<TrackControlsProps> = ({\n  trackHeight = 60,\n  width = 180,\n  onHResizeStart,\n}) => {\n  const t = useTranslation();\n  const tp = t.videoEditor.timeline;\n  const {\n    tracks,\n    toggleTrackMute,\n    toggleTrackLock,\n    scrollTop,\n    addTrack,\n    removeTrack,\n    reorderTrack,\n  } = useVideoStore();\n  const [showAddMenu, setShowAddMenu] = useState(false);\n  const addMenuTriggerRef = useRef<HTMLButtonElement | null>(null);\n\n  const visibleTracks = getVisibleTimelineTracks(tracks);\n\n  const getTrackIcon = (track: Track) => {\n    // Video + audio: mute silences playback. Image/text/subtitle: hide layer.\n    if (track.type === 'audio' || track.type === 'video') {\n      return track.muted ? <VolumeX size={13} /> : <Volume2 size={13} />;\n    }\n    return track.muted ? <EyeOff size={13} /> : <Eye size={13} />;\n  };\n\n  const getMuteTooltip = (track: Track) => {\n    if (track.type === 'audio' || track.type === 'video') {\n      return track.muted ? tp.unmuteTrack : tp.muteTrack;\n    }\n    return track.muted ? tp.showTrack : tp.hideTrack;\n  };\n\n  const handleCreateTrack = (\n    type: 'text' | 'image' | 'video' | 'audio' | 'subtitle',\n  ) => {\n    const existingCount = tracks.filter((tr) => tr.type === type).length;\n    const name =\n      type === 'subtitle'\n        ? `Subtitles ${existingCount + 1}`\n        : `${type.charAt(0).toUpperCase() + type.slice(1)} ${existingCount + 1}`;\n    addTrack(name, type);\n    setShowAddMenu(false);\n  };\n\n  const canReorder = (track: Track, direction: 'up' | 'down') => {\n    const idx = visibleTracks.findIndex((tr) => tr.id === track.id);\n    if (idx < 0) return false;\n    return direction === 'up' ? idx > 0 : idx < visibleTracks.length - 1;\n  };\n\n  return (\n    <div\n      className=\"relative flex shrink-0 select-none flex-col border-r border-panel-border bg-panel\"\n      style={{ width: `${width}px` }}\n    >\n      {onHResizeStart && (\n        <div\n          role=\"separator\"\n          aria-label={tp.resizeTracks}\n          aria-orientation=\"vertical\"\n          onMouseDown={onHResizeStart}\n          className=\"absolute bottom-0 right-0 top-0 z-20 w-1.5 cursor-ew-resize bg-transparent transition-colors hover:bg-[var(--we-accent-muted)] group\"\n        >\n          <div className=\"absolute inset-y-0 left-1/2 w-0.5 -translate-x-1/2 bg-panel-border transition-colors group-hover:bg-[var(--we-accent)]\" />\n        </div>\n      )}\n\n      <div className=\"relative flex h-10 items-center justify-between gap-2 border-b border-panel-border bg-[#0A0A0F]/80 px-3\">\n        <TextTitle as=\"span\" size=\"xs\" className=\"uppercase tracking-wider text-white/80\">\n          {tp.tracksLabel}\n        </TextTitle>\n\n        <div className=\"relative\">\n          <button\n            ref={addMenuTriggerRef}\n            type=\"button\"\n            onClick={() => setShowAddMenu(!showAddMenu)}\n            className=\"flex cursor-pointer items-center gap-0.5 rounded-lg bg-[var(--we-accent-muted)] px-1.5 py-0.5 uppercase tracking-wider text-[var(--we-accent)] transition-colors hover:text-white\"\n            title={tp.addLayerTitle}\n          >\n            <Plus size={10} />\n            <TextBody as=\"span\" size=\"sm\" className=\"font-bold uppercase tracking-wider\">\n              {tp.addLayer}\n            </TextBody>\n          </button>\n\n          <ViewportPortalMenu\n            open={showAddMenu}\n            onClose={() => setShowAddMenu(false)}\n            anchorRef={addMenuTriggerRef}\n            prefer=\"below\"\n            align=\"right\"\n            zIndex={50}\n            className=\"flex min-w-[120px] flex-col rounded-xl border border-panel-border bg-panel py-1 shadow-2xl\"\n          >\n            {(\n              [\n                ['text', tp.addTextLayer],\n                ['subtitle', tp.addSubtitleLayer],\n                ['image', tp.addImageLayer],\n                ['video', tp.addVideoLayer],\n                ['audio', tp.addAudioLayer],\n              ] as const\n            ).map(([type, label]) => (\n              <button\n                key={type}\n                type=\"button\"\n                onClick={() => handleCreateTrack(type)}\n                className=\"w-full cursor-pointer px-2.5 py-1.5 text-left text-white transition-colors hover:bg-[var(--we-accent-muted)]\"\n              >\n                <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                  {label}\n                </TextBody>\n              </button>\n            ))}\n          </ViewportPortalMenu>\n        </div>\n      </div>\n\n      <div className=\"relative flex-1 overflow-hidden py-1\">\n        <div\n          className=\"flex flex-col space-y-1.5\"\n          style={{ transform: `translateY(${-scrollTop}px)` }}\n        >\n          {visibleTracks.map((track) => (\n            <div\n              key={track.id}\n              style={{ height: `${trackHeight}px` }}\n              className={`flex shrink-0 items-center justify-between border-y border-panel-border/50 bg-[#1C1C26]/40 px-2 ${\n                track.locked ? 'opacity-55' : ''\n              }`}\n            >\n              <div className=\"flex min-w-0 flex-col\">\n                <TextBody\n                  as=\"span\"\n                  size=\"sm\"\n                  className=\"max-w-[64px] truncate font-semibold text-white\"\n                  title={track.name}\n                >\n                  {track.name}\n                </TextBody>\n                <TextBody as=\"span\" size=\"sm\" className=\"uppercase tracking-wider text-white/80\">\n                  {track.type}\n                </TextBody>\n              </div>\n\n              <div className=\"flex items-center gap-0.5\">\n                <div className=\"mr-0.5 flex flex-col\">\n                  <button\n                    type=\"button\"\n                    disabled={!canReorder(track, 'up')}\n                    onClick={() => reorderTrack(track.id, 'up')}\n                    className=\"cursor-pointer rounded p-0.5 text-white/80 transition-colors hover:bg-black-capsule hover:text-white disabled:cursor-not-allowed disabled:opacity-30\"\n                    title={tp.reorderLayerUp}\n                  >\n                    <ChevronUp size={12} />\n                  </button>\n                  <button\n                    type=\"button\"\n                    disabled={!canReorder(track, 'down')}\n                    onClick={() => reorderTrack(track.id, 'down')}\n                    className=\"cursor-pointer rounded p-0.5 text-white/80 transition-colors hover:bg-black-capsule hover:text-white disabled:cursor-not-allowed disabled:opacity-30\"\n                    title={tp.reorderLayerDown}\n                  >\n                    <ChevronDown size={12} />\n                  </button>\n                </div>\n\n                <button\n                  type=\"button\"\n                  onClick={() => toggleTrackMute(track.id)}\n                  className={`cursor-pointer rounded p-1 transition-colors ${\n                    track.muted\n                      ? 'bg-red-500/10 text-red-500'\n                      : 'text-white/80 hover:bg-black-capsule hover:text-white'\n                  }`}\n                  title={getMuteTooltip(track)}\n                >\n                  {getTrackIcon(track)}\n                </button>\n\n                <button\n                  type=\"button\"\n                  onClick={() => toggleTrackLock(track.id)}\n                  className={`cursor-pointer rounded p-1 transition-colors ${\n                    track.locked\n                      ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)]'\n                      : 'text-white/80 hover:bg-black-capsule hover:text-white'\n                  }`}\n                  title={track.locked ? tp.unlockTrack : tp.lockTrack}\n                >\n                  {track.locked ? <Lock size={13} /> : <Unlock size={13} />}\n                </button>\n\n                <button\n                  type=\"button\"\n                  onClick={() => removeTrack(track.id)}\n                  className=\"cursor-pointer rounded p-1 text-white/80 transition-colors hover:bg-black-capsule hover:text-red-500\"\n                  title={tp.deleteTrack}\n                >\n                  <Trash2 size={13} />\n                </button>\n              </div>\n            </div>\n          ))}\n        </div>\n      </div>\n    </div>\n  );\n};\n", "import React, { useRef, useState, useEffect, useCallback, useLayoutEffect, useMemo } from 'react';\nimport { Stage, Layer, Rect, Text, Line, Group } from 'react-konva';\nimport { useVideoStore, type TransitionClip } from '../../store/useVideoStore';\nimport { TIMELINE_SNAP_THRESHOLD_PX, findAlignmentGuideX } from '../../utils/timelineSnap';\nimport {\n  formatTimecode,\n  getVisibleTimelineTracks,\n  buildTimelineRulerTicks,\n  framesToSeconds,\n} from '../../utils/timelineUtils';\nimport { transcribeAudio } from '../../services/aiService';\nimport { Sparkles, ArrowUp, ArrowDown, Scissors, Plus, Languages, Wand2, Palette, Clapperboard } from 'lucide-react';\nimport { TransitionBuilder } from './transitions/TransitionBuilder';\nimport { useDialog } from '../../components/DialogModal';\nimport { useTranslation } from '../../i18n';\nimport { FEATURE_HEX } from '../../theme/modeAccent';\nimport { SubtitleAiLoader, TextBody, TextTitle } from '../ui';\nimport {\n  useVideoUiStore,\n  type TransitionEdgeIntent,\n  type VideoAiToolId,\n} from '../../store/useVideoUiStore';\n\n\nconst RULER_HEIGHT = 40;\nconst DEFAULT_TRACK_HEIGHT = 60;\nconst TRACK_SPACING = 6;\nconst SNAP_THRESHOLD_PX = TIMELINE_SNAP_THRESHOLD_PX;\nconst TRIM_HIT_WIDTH = 8;\nconst TRIM_EDGE_IDLE = 2;\nconst TRIM_EDGE_HOVER = 6;\n/** Full-height playhead grab zone (half-width each side of the line). */\nconst PLAYHEAD_HIT_HALF = 7;\n/** Min gap from clip edges before hover-split is offered (seconds, floored by px). */\nconst SPLIT_EDGE_MARGIN_PX = 8;\nconst SPLIT_HOVER_DELAY_MS = 1000;\n/** Px from playhead to start the split hover timer. */\nconst SPLIT_PLAYHEAD_HIT_PX = 40;\n/** Once armed/ready, keep while pointer stays within this wider band (or on the clip). */\nconst SPLIT_PLAYHEAD_KEEP_PX = 72;\n/** Delay before clearing when leaving clip \u2192 HTML button. */\nconst SPLIT_LEAVE_MS = 280;\n/** Hover zone at clip start/end for the add-transition (+) chip. */\nconst EDGE_HOVER_PX = 18;\nconst EDGE_HOVER_DELAY_MS = 1000;\n/** Video studio accent \u2014 always orange on the timeline (not CSS-var lookup). */\nconst VIDEO_ACCENT = FEATURE_HEX.video;\n/** Cap decorative audio waveform bars so zoom-in does not spawn thousands of Konva nodes. */\nconst MAX_WAVEFORM_BARS = 80;\nconst TIMELINE_NUDGE_FPS = 30;\n/** How long to keep the dashed alignment guide after a keyboard nudge. */\nconst ALIGN_GUIDE_HOLD_MS = 600;\n\nfunction setStageCursor(stage: { container: () => HTMLDivElement } | null, cursor: string) {\n  if (!stage) return;\n  stage.container().style.cursor = cursor;\n}\n\ninterface TimelineProps {\n  trackHeight?: number;\n}\n\nexport const Timeline: React.FC<TimelineProps> = ({ trackHeight = DEFAULT_TRACK_HEIGHT }) => {\n  const t = useTranslation();\n  const tp = t.videoEditor.timeline;\n  const containerRef = useRef<HTMLDivElement>(null);\n  const contextMenuRef = useRef<HTMLDivElement>(null);\n  const [scrollLeft, setScrollLeft] = useState(0);\n  const [dimensions, setDimensions] = useState({ width: 800, height: 350 });\n  const [snapLineX, setSnapLineX] = useState<number | null>(null);\n  const [trimHover, setTrimHover] = useState<{ clipId: string; edge: 'left' | 'right' } | null>(\n    null,\n  );\n  /** Hover-to-split: only when playhead crosses the clip and cursor is on that line. */\n  const [splitHover, setSplitHover] = useState<{\n    clipId: string;\n    ready: boolean;\n  } | null>(null);\n  const splitHoverTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const splitHoverLeaveRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const splitHoverClipRef = useRef<string | null>(null);\n  const splitHoverReadyRef = useRef(false);\n  /** Edge hover (+) for adding / resolving transitions at start, end, or cut. */\n  const [edgeHover, setEdgeHover] = useState<{\n    key: string;\n    intent: TransitionEdgeIntent;\n    openJunction: boolean;\n    clientX: number;\n    clientY: number;\n    ready: boolean;\n  } | null>(null);\n  const edgeHoverTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const edgeHoverLeaveRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const edgeHoverKeyRef = useRef<string | null>(null);\n  const edgeHoverReadyRef = useRef(false);\n  const zoomRafRef = useRef<number | null>(null);\n  const pendingZoomRef = useRef<number | null>(null);\n  const scrollLeftRef = useRef(0);\n  const playheadTimeRef = useRef(0);\n  const prevZoomRef = useRef<number | null>(null);\n  const alignGuideClearRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const panRef = useRef<{\n    x: number;\n    y: number;\n    scrollLeft: number;\n    scrollTop: number;\n  } | null>(null);\n  const [isPanning, setIsPanning] = useState(false);\n  /** Snap guide X updated from dragBoundFunc; applied in onDragMove (not during Konva layout). */\n  const pendingSnapLineRef = useRef<number | null>(null);\n  /** Live time offset while dragging a multi-selection (followers follow the leader). */\n  const [groupDragDeltaSec, setGroupDragDeltaSec] = useState(0);\n  const [groupDragLeaderId, setGroupDragLeaderId] = useState<string | null>(null);\n  /** Marquee rubber-band in stage coords (y includes scroll offset space of track group). */\n  const [marquee, setMarquee] = useState<{\n    x0: number;\n    y0: number;\n    x1: number;\n    y1: number;\n    additive: boolean;\n  } | null>(null);\n  const marqueeActiveRef = useRef(false);\n  /** Latest marquee box \u2014 finish handlers must not call store setters inside setState updaters. */\n  const marqueeRef = useRef<{\n    x0: number;\n    y0: number;\n    x1: number;\n    y1: number;\n    additive: boolean;\n  } | null>(null);\n\n  // Context menu\n  const [contextMenu, setContextMenu] = useState<{ visible: boolean; x: number; y: number; clipId: string } | null>(null);\n  const [editingTransition, setEditingTransition] = useState<TransitionClip | null>(null);\n\n  const dialog = useDialog();\n  const {\n    tracks,\n    assets,\n    playheadTime,\n    setPlayhead,\n    zoom,\n    setZoom,\n    selectedClipIds,\n    selectClip,\n    selectClips,\n    clearSelection,\n    moveClip,\n    moveClipsByDelta,\n    moveClipLayer,\n    updateClipProperties,\n    addClip,\n    projectDuration,\n    transitions,\n    scrollTop,\n    setScrollTop,\n    aiSubtitleJob,\n    setAiSubtitleJob,\n    snapEnabled,\n    splitClip,\n  } = useVideoStore();\n\n  playheadTimeRef.current = playheadTime;\n  scrollLeftRef.current = scrollLeft;\n\n  // Keep the playhead fixed in the viewport when timeline zoom changes (toolbar / Alt+wheel).\n  useLayoutEffect(() => {\n    const prev = prevZoomRef.current;\n    prevZoomRef.current = zoom;\n    if (prev == null || prev === zoom) return;\n\n    const nextScroll = Math.max(0, scrollLeftRef.current + playheadTimeRef.current * (zoom - prev));\n    scrollLeftRef.current = nextScroll;\n    setScrollLeft(nextScroll);\n    if (containerRef.current) {\n      containerRef.current.scrollLeft = nextScroll;\n    }\n  }, [zoom]);\n\n  const openTransitionsForEdge = useVideoUiStore((s) => s.openTransitionsForEdge);\n  const openTransitionJunction = useVideoUiStore((s) => s.openTransitionJunction);\n  const openAiGenerateTool = useVideoUiStore((s) => s.openAiGenerateTool);\n\n  // UI-only filter: first video lane + lanes with clips + user-created empty layers\n  const visibleTracks = getVisibleTimelineTracks(tracks);\n\n  useEffect(() => {\n    if (!snapEnabled) setSnapLineX(null);\n  }, [snapEnabled]);\n\n  // Arrow-key nudge: move by frames, show dashed guide when edges align (no auto-snap).\n  useEffect(() => {\n    const onKeyDown = (e: KeyboardEvent) => {\n      const tag = (e.target as HTMLElement | null)?.tagName;\n      if (tag === 'INPUT' || tag === 'TEXTAREA' || (e.target as HTMLElement)?.isContentEditable) {\n        return;\n      }\n      if (e.metaKey || e.ctrlKey) return;\n      if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;\n      if (selectedClipIds.length === 0) return;\n\n      e.preventDefault();\n      const frames = e.shiftKey ? 10 : 1;\n      const deltaSec = framesToSeconds(frames, TIMELINE_NUDGE_FPS);\n      moveClipsByDelta(selectedClipIds, e.key === 'ArrowLeft' ? -deltaSec : deltaSec);\n\n      if (!snapEnabled) {\n        setSnapLineX(null);\n        return;\n      }\n\n      // Read post-move positions from the store.\n      const state = useVideoStore.getState();\n      const guideX = findAlignmentGuideX({\n        clipIds: state.selectedClipIds,\n        tracks: state.tracks,\n        playheadTime: state.playheadTime,\n        zoom: state.zoom,\n        fps: TIMELINE_NUDGE_FPS,\n      });\n      setSnapLineX(guideX);\n      if (alignGuideClearRef.current) clearTimeout(alignGuideClearRef.current);\n      alignGuideClearRef.current = setTimeout(() => {\n        alignGuideClearRef.current = null;\n        setSnapLineX(null);\n      }, ALIGN_GUIDE_HOLD_MS);\n    };\n\n    window.addEventListener('keydown', onKeyDown);\n    return () => {\n      window.removeEventListener('keydown', onKeyDown);\n      if (alignGuideClearRef.current) clearTimeout(alignGuideClearRef.current);\n    };\n  }, [selectedClipIds, moveClipsByDelta, snapEnabled]);\n\n  const clearSplitHover = useCallback(() => {\n    if (splitHoverTimerRef.current) {\n      clearTimeout(splitHoverTimerRef.current);\n      splitHoverTimerRef.current = null;\n    }\n    if (splitHoverLeaveRef.current) {\n      clearTimeout(splitHoverLeaveRef.current);\n      splitHoverLeaveRef.current = null;\n    }\n    splitHoverClipRef.current = null;\n    splitHoverReadyRef.current = false;\n    setSplitHover(null);\n  }, []);\n\n  useEffect(() => () => clearSplitHover(), [clearSplitHover]);\n\n  const scheduleSplitHoverClear = useCallback(() => {\n    if (splitHoverLeaveRef.current) clearTimeout(splitHoverLeaveRef.current);\n    splitHoverLeaveRef.current = setTimeout(() => {\n      splitHoverLeaveRef.current = null;\n      clearSplitHover();\n    }, SPLIT_LEAVE_MS);\n  }, [clearSplitHover]);\n\n  const cancelSplitHoverClear = useCallback(() => {\n    if (splitHoverLeaveRef.current) {\n      clearTimeout(splitHoverLeaveRef.current);\n      splitHoverLeaveRef.current = null;\n    }\n  }, []);\n\n  const armSplitHoverOnClip = useCallback(\n    (\n      clip: { id: string; startTime: number; duration: number },\n      locked: boolean,\n      pointerX?: number,\n    ) => {\n      if (locked || groupDragLeaderId != null) {\n        clearSplitHover();\n        return;\n      }\n\n      const margin = Math.max(0.05, SPLIT_EDGE_MARGIN_PX / zoom);\n      const playheadOnClip =\n        playheadTime > clip.startTime + margin &&\n        playheadTime < clip.startTime + clip.duration - margin;\n      if (!playheadOnClip) {\n        clearSplitHover();\n        return;\n      }\n\n      const sameClip = splitHoverClipRef.current === clip.id;\n      if (sameClip && splitHoverReadyRef.current) {\n        cancelSplitHoverClear();\n        return;\n      }\n\n      // When hovering the clip body, require proximity to the playhead X.\n      // When hovering the playhead hit zone itself, pointerX is omitted.\n      if (pointerX != null) {\n        const playheadX = playheadTime * zoom;\n        const hitPx = sameClip ? SPLIT_PLAYHEAD_KEEP_PX : SPLIT_PLAYHEAD_HIT_PX;\n        if (Math.abs(pointerX - playheadX) > hitPx) {\n          clearSplitHover();\n          return;\n        }\n      }\n\n      cancelSplitHoverClear();\n\n      if (!sameClip) {\n        if (splitHoverTimerRef.current) {\n          clearTimeout(splitHoverTimerRef.current);\n          splitHoverTimerRef.current = null;\n        }\n        splitHoverClipRef.current = clip.id;\n        splitHoverReadyRef.current = false;\n        setSplitHover({ clipId: clip.id, ready: false });\n        splitHoverTimerRef.current = setTimeout(() => {\n          splitHoverTimerRef.current = null;\n          splitHoverReadyRef.current = true;\n          if (splitHoverLeaveRef.current) {\n            clearTimeout(splitHoverLeaveRef.current);\n            splitHoverLeaveRef.current = null;\n          }\n          setSplitHover((prev) =>\n            prev && prev.clipId === clip.id ? { ...prev, ready: true } : prev,\n          );\n        }, SPLIT_HOVER_DELAY_MS);\n      }\n    },\n    [\n      cancelSplitHoverClear,\n      clearSplitHover,\n      groupDragLeaderId,\n      playheadTime,\n      zoom,\n    ],\n  );\n\n  const syncSplitHoverFromPointer = useCallback(\n    (\n      clip: { id: string; startTime: number; duration: number },\n      locked: boolean,\n      e: {\n        target: {\n          name: () => string;\n          getStage: () => {\n            getPointerPosition: () => { x: number; y: number } | null;\n            container: () => HTMLDivElement;\n          } | null;\n        };\n      },\n    ) => {\n      const targetName = e.target.name?.() ?? '';\n      if (targetName === 'trim-left' || targetName === 'trim-right') {\n        clearSplitHover();\n        return;\n      }\n      const stage = e.target.getStage();\n      const pointer = stage?.getPointerPosition();\n      if (!pointer) return;\n      armSplitHoverOnClip(clip, locked, pointer.x);\n    },\n    [armSplitHoverOnClip, clearSplitHover],\n  );\n\n  /** Playhead grab strip sits above clips \u2014 still arm split for the clip under the cursor. */\n  const syncSplitHoverFromPlayhead = useCallback(\n    (e: {\n      target: {\n        getStage: () => {\n          getPointerPosition: () => { x: number; y: number } | null;\n        } | null;\n      };\n    }) => {\n      if (groupDragLeaderId != null) {\n        clearSplitHover();\n        return;\n      }\n      const stage = e.target.getStage();\n      const pointer = stage?.getPointerPosition();\n      if (!pointer) return;\n\n      const lanes = getVisibleTimelineTracks(tracks);\n      const yInContent = pointer.y + scrollTop;\n      const trackIndex = Math.floor(\n        (yInContent - RULER_HEIGHT) / (trackHeight + TRACK_SPACING),\n      );\n      if (trackIndex < 0 || trackIndex >= lanes.length) {\n        if (!splitHoverReadyRef.current) clearSplitHover();\n        return;\n      }\n\n      const track = lanes[trackIndex];\n      if (!track || track.locked) {\n        clearSplitHover();\n        return;\n      }\n\n      const margin = Math.max(0.05, SPLIT_EDGE_MARGIN_PX / zoom);\n      const clip = track.clips.find(\n        (c) =>\n          playheadTime > c.startTime + margin &&\n          playheadTime < c.startTime + c.duration - margin,\n      );\n      if (!clip) {\n        if (!splitHoverReadyRef.current) clearSplitHover();\n        return;\n      }\n\n      armSplitHoverOnClip(clip, false);\n    },\n    [\n      armSplitHoverOnClip,\n      clearSplitHover,\n      groupDragLeaderId,\n      playheadTime,\n      scrollTop,\n      trackHeight,\n      tracks,\n      zoom,\n    ],\n  );\n\n\n  const clearEdgeHover = useCallback(() => {\n    if (edgeHoverTimerRef.current) {\n      clearTimeout(edgeHoverTimerRef.current);\n      edgeHoverTimerRef.current = null;\n    }\n    if (edgeHoverLeaveRef.current) {\n      clearTimeout(edgeHoverLeaveRef.current);\n      edgeHoverLeaveRef.current = null;\n    }\n    edgeHoverKeyRef.current = null;\n    edgeHoverReadyRef.current = false;\n    setEdgeHover(null);\n  }, []);\n\n  const scheduleEdgeHoverClear = useCallback(() => {\n    if (edgeHoverLeaveRef.current) clearTimeout(edgeHoverLeaveRef.current);\n    edgeHoverLeaveRef.current = setTimeout(() => {\n      edgeHoverLeaveRef.current = null;\n      clearEdgeHover();\n    }, SPLIT_LEAVE_MS);\n  }, [clearEdgeHover]);\n\n  const cancelEdgeHoverClear = useCallback(() => {\n    if (edgeHoverLeaveRef.current) {\n      clearTimeout(edgeHoverLeaveRef.current);\n      edgeHoverLeaveRef.current = null;\n    }\n  }, []);\n\n  const junctionNeedsEditor = useCallback(\n    (fromClipId: string, toClipId: string) => {\n      const between = transitions.some(\n        (tr) => tr.fromClipId === fromClipId && tr.toClipId === toClipId,\n      );\n      const leftEnd = transitions.some(\n        (tr) => tr.fromClipId === fromClipId && tr.toClipId === 'none',\n      );\n      const rightStart = transitions.some(\n        (tr) => tr.fromClipId === 'none' && tr.toClipId === toClipId,\n      );\n      return between || leftEnd || rightStart;\n    },\n    [transitions],\n  );\n\n  const syncEdgeHoverFromClip = useCallback(\n    (\n      clip: { id: string; startTime: number; duration: number; type: string },\n      track: { id: string; locked: boolean; clips: Array<{ id: string; startTime: number; duration: number }> },\n      e: {\n        target: {\n          name: () => string;\n          getStage: () => {\n            getPointerPosition: () => { x: number; y: number } | null;\n            container: () => HTMLDivElement;\n          } | null;\n        };\n      },\n    ) => {\n      // Audio has no visual frame; transitions apply to video/image/text/subtitle.\n      if (track.locked || clip.type === 'audio') {\n        clearEdgeHover();\n        return false;\n      }\n      const targetName = e.target.name?.() ?? '';\n      if (targetName === 'trim-left' || targetName === 'trim-right') {\n        clearEdgeHover();\n        return false;\n      }\n      const stage = e.target.getStage();\n      const pointer = stage?.getPointerPosition();\n      if (!stage || !pointer) return false;\n\n      const localX = pointer.x - clip.startTime * zoom;\n      const clipW = clip.duration * zoom;\n      const nearStart = localX >= 0 && localX <= EDGE_HOVER_PX;\n      const nearEnd = localX >= clipW - EDGE_HOVER_PX && localX <= clipW;\n      if (!nearStart && !nearEnd) {\n        if (edgeHoverReadyRef.current) {\n          cancelEdgeHoverClear();\n          return true;\n        }\n        clearEdgeHover();\n        return false;\n      }\n\n      // Prefer split when playhead is mid-clip near the cursor (not on this edge).\n      const playheadX = playheadTime * zoom;\n      const onPlayhead = Math.abs(pointer.x - playheadX) <= SPLIT_PLAYHEAD_HIT_PX;\n      const playheadAtThisEdge =\n        (nearStart && Math.abs(playheadTime - clip.startTime) < 0.05) ||\n        (nearEnd && Math.abs(playheadTime - (clip.startTime + clip.duration)) < 0.05);\n      if (onPlayhead && !playheadAtThisEdge) {\n        clearEdgeHover();\n        return false;\n      }\n\n      const sorted = [...track.clips].sort((a, b) => a.startTime - b.startTime);\n      const index = sorted.findIndex((c) => c.id === clip.id);\n      let intent: TransitionEdgeIntent | null = null;\n      let openJunction = false;\n\n      if (nearStart) {\n        const prev = index > 0 ? sorted[index - 1] : null;\n        if (prev) {\n          const gap = clip.startTime - (prev.startTime + prev.duration);\n          if (gap <= 0.5) {\n            intent = { kind: 'between', fromClipId: prev.id, toClipId: clip.id };\n            openJunction = junctionNeedsEditor(prev.id, clip.id);\n          }\n        }\n        if (!intent) intent = { kind: 'start', clipId: clip.id };\n      } else if (nearEnd) {\n        const next = index >= 0 && index < sorted.length - 1 ? sorted[index + 1] : null;\n        if (next) {\n          const gap = next.startTime - (clip.startTime + clip.duration);\n          if (gap <= 0.5) {\n            intent = { kind: 'between', fromClipId: clip.id, toClipId: next.id };\n            openJunction = junctionNeedsEditor(clip.id, next.id);\n          }\n        }\n        if (!intent) intent = { kind: 'end', clipId: clip.id };\n      }\n\n      if (!intent) {\n        clearEdgeHover();\n        return false;\n      }\n\n      const key =\n        intent.kind === 'between'\n          ? `between:${intent.fromClipId}:${intent.toClipId}`\n          : `${intent.kind}:${intent.clipId}`;\n\n      cancelEdgeHoverClear();\n      clearSplitHover();\n\n      const box = stage.container().getBoundingClientRect();\n      const clientX = box.left + pointer.x;\n      const clientY = box.top + pointer.y;\n\n      if (edgeHoverKeyRef.current !== key) {\n        if (edgeHoverTimerRef.current) {\n          clearTimeout(edgeHoverTimerRef.current);\n          edgeHoverTimerRef.current = null;\n        }\n        edgeHoverKeyRef.current = key;\n        edgeHoverReadyRef.current = false;\n        setEdgeHover({\n          key,\n          intent,\n          openJunction,\n          clientX,\n          clientY,\n          ready: false,\n        });\n        edgeHoverTimerRef.current = setTimeout(() => {\n          edgeHoverTimerRef.current = null;\n          edgeHoverReadyRef.current = true;\n          if (edgeHoverLeaveRef.current) {\n            clearTimeout(edgeHoverLeaveRef.current);\n            edgeHoverLeaveRef.current = null;\n          }\n          setEdgeHover((prev) =>\n            prev && prev.key === key ? { ...prev, ready: true, openJunction } : prev,\n          );\n        }, EDGE_HOVER_DELAY_MS);\n      } else {\n        setEdgeHover((prev) =>\n          prev ? { ...prev, intent, openJunction, clientX, clientY } : prev,\n        );\n      }\n      return true;\n    },\n    [\n      cancelEdgeHoverClear,\n      clearEdgeHover,\n      clearSplitHover,\n      junctionNeedsEditor,\n      playheadTime,\n      zoom,\n    ],\n  );\n\n  // Drop the affordance if the playhead leaves the hovered clip.\n  useEffect(() => {\n    if (!splitHover) return;\n    let clip: { startTime: number; duration: number } | undefined;\n    for (const tr of tracks) {\n      const found = tr.clips.find((c) => c.id === splitHover.clipId);\n      if (found) {\n        clip = found;\n        break;\n      }\n    }\n    if (!clip) {\n      clearSplitHover();\n      return;\n    }\n    const margin = Math.max(0.05, SPLIT_EDGE_MARGIN_PX / zoom);\n    if (\n      playheadTime <= clip.startTime + margin ||\n      playheadTime >= clip.startTime + clip.duration - margin\n    ) {\n      clearSplitHover();\n    }\n  }, [clearSplitHover, playheadTime, splitHover, tracks, zoom]);\n\n  // Clamp context menu inside the viewport (same pattern as image CanvasArea).\n  useLayoutEffect(() => {\n    if (!contextMenu?.visible) return;\n    const el = contextMenuRef.current;\n    if (!el) return;\n    const margin = 8;\n    const menuW = el.offsetWidth;\n    const menuH = el.offsetHeight;\n    const x = Math.max(margin, Math.min(contextMenu.x, window.innerWidth - menuW - margin));\n    const y = Math.max(margin, Math.min(contextMenu.y, window.innerHeight - menuH - margin));\n    el.style.left = `${x}px`;\n    el.style.top = `${y}px`;\n  }, [contextMenu?.visible, contextMenu?.x, contextMenu?.y, contextMenu?.clipId]);\n\n  // Filmstrip: cache asset thumbnails / images for Konva fillPatternImage (repeat-x).\n  const [thumbnails, setThumbnails] = useState<Map<string, HTMLImageElement>>(new Map());\n  useEffect(() => {\n    let cancelled = false;\n\n    const commit = (assetId: string, img: HTMLImageElement) => {\n      if (cancelled) return;\n      setThumbnails((prev) => {\n        if (prev.has(assetId)) return prev;\n        const next = new Map(prev);\n        next.set(assetId, img);\n        return next;\n      });\n    };\n\n    const loadImageSrc = (assetId: string, src: string, fallback?: string) => {\n      const img = new window.Image();\n      img.onload = () => commit(assetId, img);\n      img.onerror = () => {\n        if (fallback && fallback !== src) loadImageSrc(assetId, fallback);\n      };\n      img.src = src;\n    };\n\n    assets.forEach((asset) => {\n      if (thumbnails.has(asset.id)) return;\n      if (asset.type === 'image') {\n        const primary = asset.thumbnail || asset.url;\n        const fallback =\n          asset.url && asset.url !== asset.thumbnail ? asset.url : undefined;\n        if (primary) loadImageSrc(asset.id, primary, fallback);\n        return;\n      }\n      if (asset.type !== 'video') return;\n      if (asset.thumbnail) {\n        loadImageSrc(asset.id, asset.thumbnail, asset.url || undefined);\n        return;\n      }\n      if (!asset.url) return;\n      // Capture a mid-frame when the asset has no stored thumbnail.\n      const video = document.createElement('video');\n      video.preload = 'metadata';\n      video.muted = true;\n      video.playsInline = true;\n      video.src = asset.url;\n      video.onloadedmetadata = () => {\n        try {\n          video.currentTime = Math.min(1, (video.duration || 2) / 2);\n        } catch {\n          /* ignore */\n        }\n      };\n      video.onseeked = () => {\n        try {\n          const canvas = document.createElement('canvas');\n          const vw = video.videoWidth || 160;\n          const vh = video.videoHeight || 90;\n          const maxEdge = 160;\n          const scale = Math.min(1, maxEdge / Math.max(vw, vh));\n          canvas.width = Math.max(1, Math.round(vw * scale));\n          canvas.height = Math.max(1, Math.round(vh * scale));\n          const ctx = canvas.getContext('2d');\n          if (ctx) ctx.drawImage(video, 0, 0, canvas.width, canvas.height);\n          loadImageSrc(asset.id, canvas.toDataURL('image/jpeg'));\n        } catch {\n          /* ignore */\n        }\n        video.src = '';\n        video.load();\n      };\n    });\n\n    return () => {\n      cancelled = true;\n    };\n  }, [assets, thumbnails]);\n\n  useEffect(() => {\n    const handleGlobalClick = () => {\n      setContextMenu(null);\n    };\n    window.addEventListener('click', handleGlobalClick);\n    return () => window.removeEventListener('click', handleGlobalClick);\n  }, []);\n\n  const handleGenerateSubtitles = async (clipId: string) => {\n    setContextMenu(null);\n    const clip = tracks.flatMap((t) => t.clips).find((c) => c.id === clipId);\n    if (!clip) return;\n\n    const asset = assets.find((a) => a.id === clip.assetId);\n    if (!asset || !asset.file) {\n      dialog.alert('No se encontr\u00F3 el archivo de media asociado.', { title: 'Archivo no encontrado', variant: 'error' });\n      return;\n    }\n\n    const { aspectRatio } = useVideoStore.getState();\n\n    setAiSubtitleJob({\n      kind: 'generate',\n      sourceClipId: clip.id,\n      startTime: clip.startTime,\n      duration: Math.max(0.5, clip.duration),\n    });\n\n    try {\n      const segments = await transcribeAudio(asset.file);\n      \n      const aspect = aspectRatio || '16:9';\n      let defaultY = 0.85;\n      if (aspect === '9:16') {\n        defaultY = 0.65; // Place higher to avoid TikTok/Reels overlays\n      } else if (aspect === '1:1') {\n        defaultY = 0.75;\n      }\n\n      const subtitleTrack =\n        tracks.find((tr) => tr.type === 'subtitle') ||\n        tracks.find((tr) => tr.id === 'sub' || tr.id.startsWith('sub-'));\n      const subTrackId = subtitleTrack?.id ?? 'sub';\n\n      segments.forEach((segment) => {\n        // Map timestamps matching clip speed and timeline startTime\n        const startTime = clip.startTime + (segment.start / clip.speed);\n        const duration = (segment.end - segment.start) / clip.speed;\n\n        addClip(subTrackId, {\n          trackId: subTrackId,\n          assetId: clip.assetId,\n          startTime,\n          duration,\n          trimIn: 0,\n          trimOut: 0,\n          speed: clip.speed,\n          volume: 1.0,\n          opacity: 1.0,\n          muted: false,\n          type: 'subtitle',\n          text: segment.text.trim(),\n          \n          // Typography / customizability defaults\n          fontFamily: 'Inter',\n          fontSize: aspect === '9:16' ? 24 : 28,\n          fillColor: '#FFFFFF',\n          fontWeight: 600,\n          fontStyle: 'normal',\n          textAlign: 'center',\n          textTransform: 'none',\n          letterSpacing: 0,\n          \n          // Background box\n          backgroundEnabled: true,\n          backgroundColor: '#000000',\n          backgroundOpacity: 0.6,\n          backgroundPadding: 8,\n          backgroundBorderRadius: 4,\n          \n          // Shadows\n          shadowEnabled: true,\n          shadowColor: '#000000',\n          shadowBlur: 6,\n          shadowOffsetX: 2,\n          shadowOffsetY: 2,\n          shadowOpacity: 0.8,\n          \n          // Position and layout\n          x: 0.5,\n          y: defaultY,\n          rotation: 0,\n          scaleX: 1.0,\n          scaleY: 1.0,\n          \n          // Transitions\n          animationIn: null,\n          animationOut: null,\n          animationInDuration: 0.5,\n          animationOutDuration: 0.5\n        });\n      });\n    } catch (err: unknown) {\n      const { toUserFacingError } = await import('../../utils/userFacingError');\n      const raw = err instanceof Error ? err.message : '';\n      const friendly = toUserFacingError(err, {\n        context: 'timeline:transcribe',\n        fallback: /unsupported file format/i.test(raw)\n          ? tp.transcribeUnsupportedFormat\n          : undefined,\n      });\n      dialog.alert(friendly, {\n        title: t.store.toasts.editor.subtitlesErrorTitle,\n        variant: 'error',\n      });\n    } finally {\n      setAiSubtitleJob(null);\n    }\n  };\n\n  // ResizeObserver to track timeline viewport width/height\n  useEffect(() => {\n    if (!containerRef.current) return;\n    const observer = new ResizeObserver((entries) => {\n      for (const entry of entries) {\n        setDimensions({\n          width: entry.contentRect.width,\n          height: entry.contentRect.height,\n        });\n      }\n    });\n    observer.observe(containerRef.current);\n    return () => observer.disconnect();\n  }, []);\n\n  const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {\n    setScrollLeft(e.currentTarget.scrollLeft);\n  };\n\n  // Zooming with Alt+scroll (T-20260707-13: era Ctrl+scroll pero conflictuaba con el\n  // zoom nativo del navegador; Alt no tiene binding por defecto), otherwise scroll vertically\n  const handleWheel = (e: React.WheelEvent) => {\n    // Ignore wheels from portaled overlays that are not under this DOM node.\n    const target = e.target;\n    if (!(target instanceof Node) || !e.currentTarget.contains(target)) return;\n\n    if (e.altKey) {\n      e.preventDefault();\n      const zoomFactor = 1.1;\n      const base = pendingZoomRef.current ?? zoom;\n      const next = Math.min(100, Math.max(2, e.deltaY < 0 ? base * zoomFactor : base / zoomFactor));\n      pendingZoomRef.current = next;\n      // Coalesce wheel bursts to one store update per frame (avoids Konva thrash).\n      if (zoomRafRef.current == null) {\n        zoomRafRef.current = requestAnimationFrame(() => {\n          zoomRafRef.current = null;\n          const pending = pendingZoomRef.current;\n          pendingZoomRef.current = null;\n          if (pending != null) setZoom(pending);\n        });\n      }\n    } else {\n      // Scroll vertically based on visible track layout (same math as middle-mouse pan).\n      const trackCount = visibleTracks.length;\n      const lastBottom =\n        trackCount <= 0\n          ? 0\n          : RULER_HEIGHT +\n            (trackCount - 1) * (trackHeight + TRACK_SPACING) +\n            4 +\n            trackHeight;\n      const maxScroll = Math.max(0, lastBottom - dimensions.height);\n      const newScrollTop = Math.max(0, Math.min(scrollTop + e.deltaY, maxScroll));\n      setScrollTop(newScrollTop);\n    }\n  };\n\n  // Click / press on time ruler to seek playhead (stage X already includes horizontal scroll)\n  const handleRulerSeek = (e: any) => {\n    const stage = e.target.getStage();\n    if (!stage) return;\n    const pointer = stage.getPointerPosition();\n    if (!pointer || pointer.y > RULER_HEIGHT) return;\n    setPlayhead(Math.max(0, pointer.x / zoom));\n  };\n\n  // Dragging the playhead group\n  const handlePlayheadDrag = (e: any) => {\n    setPlayhead(Math.max(0, e.target.x() / zoom));\n  };\n\n  const setPlayheadCursor = (\n    stage: { container: () => HTMLDivElement } | null,\n    active: boolean,\n  ) => {\n    setStageCursor(stage, active ? 'ew-resize' : 'default');\n  };\n\n  const syncSnapLineFromDrag = useCallback(() => {\n    const next = pendingSnapLineRef.current;\n    setSnapLineX((prev) => (prev === next ? prev : next));\n  }, []);\n\n  const collectSnapCandidatesX = (excludeClipId: string): number[] => {\n    const snapCandidates: number[] = [playheadTime * zoom];\n    tracks.forEach((track) => {\n      track.clips.forEach((clip) => {\n        if (clip.id === excludeClipId) return;\n        snapCandidates.push(clip.startTime * zoom);\n        snapCandidates.push((clip.startTime + clip.duration) * zoom);\n      });\n    });\n    return snapCandidates;\n  };\n\n  /** Snap a single edge (left or right) to playhead / other clip edges. */\n  const computeSnapEdgeX = (\n    edgeX: number,\n    excludeClipId: string,\n  ): { x: number; snapLineX: number | null } => {\n    if (!snapEnabled) {\n      return { x: edgeX, snapLineX: null };\n    }\n    for (const snapPoint of collectSnapCandidatesX(excludeClipId)) {\n      if (Math.abs(edgeX - snapPoint) < SNAP_THRESHOLD_PX) {\n        return { x: snapPoint, snapLineX: snapPoint };\n      }\n    }\n    return { x: edgeX, snapLineX: null };\n  };\n\n  // Snapping logic during dragging (pure \u2014 no React setState; Konva calls this from dragBoundFunc).\n  const computeSnapPosition = (\n    x: number,\n    width: number,\n    draggingClipId: string,\n  ): { x: number; snapLineX: number | null } => {\n    if (!snapEnabled) {\n      return { x, snapLineX: null };\n    }\n\n    const snapCandidates = collectSnapCandidatesX(draggingClipId);\n\n    for (const snapPoint of snapCandidates) {\n      if (Math.abs(x - snapPoint) < SNAP_THRESHOLD_PX) {\n        return { x: snapPoint, snapLineX: snapPoint };\n      }\n    }\n\n    for (const snapPoint of snapCandidates) {\n      if (Math.abs(x + width - snapPoint) < SNAP_THRESHOLD_PX) {\n        return { x: snapPoint - width, snapLineX: snapPoint };\n      }\n    }\n\n    return { x, snapLineX: null };\n  };\n\n  // Calculate track Y coordinate\n  const getTrackY = (trackIndex: number) => {\n    return RULER_HEIGHT + trackIndex * (trackHeight + TRACK_SPACING) + 4;\n  };\n\n  // While the split chip is visible, Konva mouseleave is unreliable (chip covers\n  // the canvas). Keep/dismiss from window pointer position instead.\n  useEffect(() => {\n    if (!splitHover?.ready) return;\n    cancelSplitHoverClear();\n\n    const isPointerStillOnSplit = (clientX: number, clientY: number) => {\n      const under = document.elementFromPoint(clientX, clientY);\n      if (under?.closest?.('[data-we-split-chip]')) return true;\n\n      const host = containerRef.current;\n      if (!host) return false;\n      const rect = host.getBoundingClientRect();\n      if (\n        clientX < rect.left ||\n        clientX > rect.right ||\n        clientY < rect.top ||\n        clientY > rect.bottom\n      ) {\n        return false;\n      }\n\n      const stageX = clientX - rect.left + scrollLeft;\n      const stageY = clientY - rect.top + scrollTop;\n      const lanes = getVisibleTimelineTracks(tracks);\n      const trackIndex = lanes.findIndex((tr) =>\n        tr.clips.some((c) => c.id === splitHover.clipId),\n      );\n      if (trackIndex < 0) return false;\n      const track = lanes[trackIndex];\n      const clip = track?.clips.find((c) => c.id === splitHover.clipId);\n      if (!clip) return false;\n\n      const top = RULER_HEIGHT + trackIndex * (trackHeight + TRACK_SPACING) + 4;\n      const bottom = top + trackHeight;\n      const left = clip.startTime * zoom;\n      const right = (clip.startTime + clip.duration) * zoom;\n      return stageX >= left && stageX <= right && stageY >= top && stageY <= bottom;\n    };\n\n    const onMove = (ev: MouseEvent) => {\n      if (isPointerStillOnSplit(ev.clientX, ev.clientY)) {\n        cancelSplitHoverClear();\n      } else {\n        scheduleSplitHoverClear();\n      }\n    };\n\n    window.addEventListener('mousemove', onMove);\n    return () => window.removeEventListener('mousemove', onMove);\n  }, [\n    splitHover?.ready,\n    splitHover?.clipId,\n    cancelSplitHoverClear,\n    scheduleSplitHoverClear,\n    scrollLeft,\n    scrollTop,\n    zoom,\n    tracks,\n    trackHeight,\n  ]);\n\n  useEffect(() => {\n    if (!edgeHover?.ready) return;\n    cancelEdgeHoverClear();\n    const onMove = (ev: MouseEvent) => {\n      const under = document.elementFromPoint(ev.clientX, ev.clientY);\n      if (under?.closest?.('[data-we-edge-chip]')) {\n        cancelEdgeHoverClear();\n        return;\n      }\n      const host = containerRef.current;\n      if (!host) {\n        scheduleEdgeHoverClear();\n        return;\n      }\n      const rect = host.getBoundingClientRect();\n      // Keep while pointer stays over the timeline (chip or clip under Konva).\n      if (\n        ev.clientX >= rect.left &&\n        ev.clientX <= rect.right &&\n        ev.clientY >= rect.top &&\n        ev.clientY <= rect.bottom\n      ) {\n        cancelEdgeHoverClear();\n        return;\n      }\n      scheduleEdgeHoverClear();\n    };\n    window.addEventListener('mousemove', onMove);\n    return () => window.removeEventListener('mousemove', onMove);\n  }, [edgeHover?.ready, cancelEdgeHoverClear, scheduleEdgeHoverClear]);\n\n  const isMultiModifier = (evt: MouseEvent | PointerEvent) =>\n    evt.shiftKey || evt.ctrlKey || evt.metaKey;\n\n  const clipsIntersectingMarquee = useCallback(\n    (box: { x0: number; y0: number; x1: number; y1: number }) => {\n      const left = Math.min(box.x0, box.x1);\n      const right = Math.max(box.x0, box.x1);\n      const top = Math.min(box.y0, box.y1);\n      const bottom = Math.max(box.y0, box.y1);\n      const ids: string[] = [];\n      visibleTracks.forEach((track, trackIndex) => {\n        if (track.locked) return;\n        const trackTop = getTrackY(trackIndex);\n        const trackBottom = trackTop + trackHeight;\n        if (trackBottom < top || trackTop > bottom) return;\n        for (const clip of track.clips) {\n          const clipLeft = clip.startTime * zoom;\n          const clipRight = clipLeft + clip.duration * zoom;\n          if (clipRight < left || clipLeft > right) continue;\n          ids.push(clip.id);\n        }\n      });\n      return ids;\n    },\n    // getTrackY depends on trackHeight; visibleTracks/zoom listed\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n    [visibleTracks, zoom, trackHeight, scrollTop],\n  );\n\n  const finishMarquee = useCallback(\n    (box: { x0: number; y0: number; x1: number; y1: number; additive: boolean } | null) => {\n      marqueeActiveRef.current = false;\n      marqueeRef.current = null;\n      setMarquee(null);\n      if (!box) return;\n      const w = Math.abs(box.x1 - box.x0);\n      const h = Math.abs(box.y1 - box.y0);\n      if (w < 3 && h < 3) {\n        if (!box.additive) clearSelection();\n        return;\n      }\n      const ids = clipsIntersectingMarquee(box);\n      if (ids.length === 0) {\n        if (!box.additive) clearSelection();\n        return;\n      }\n      selectClips(ids, box.additive);\n    },\n    [clearSelection, clipsIntersectingMarquee, selectClips],\n  );\n\n  useEffect(() => {\n    if (!marquee) return;\n    const onMove = (ev: MouseEvent) => {\n      if (!marqueeActiveRef.current || !containerRef.current) return;\n      const rect = containerRef.current.getBoundingClientRect();\n      const x = ev.clientX - rect.left + scrollLeft;\n      const y = ev.clientY - rect.top + scrollTop;\n      setMarquee((prev) => {\n        if (!prev) return null;\n        const next = { ...prev, x1: x, y1: y };\n        marqueeRef.current = next;\n        return next;\n      });\n    };\n    // Must not call Zustand setters inside a React setState updater (was: finishMarquee in setMarquee).\n    const onUp = () => {\n      finishMarquee(marqueeRef.current);\n    };\n    window.addEventListener('mousemove', onMove);\n    window.addEventListener('mouseup', onUp);\n    return () => {\n      window.removeEventListener('mousemove', onMove);\n      window.removeEventListener('mouseup', onUp);\n    };\n  }, [marquee, scrollLeft, scrollTop, finishMarquee]);\n\n  const stageWidth = Math.max(dimensions.width, projectDuration * zoom);\n\n  const rulerTicks = useMemo(\n    () =>\n      buildTimelineRulerTicks({\n        zoom,\n        scrollLeft,\n        viewWidth: dimensions.width,\n        stageWidth,\n      }),\n    [zoom, scrollLeft, dimensions.width, stageWidth],\n  );\n\n  useEffect(() => {\n    return () => {\n      if (zoomRafRef.current != null) cancelAnimationFrame(zoomRafRef.current);\n    };\n  }, []);\n\n  // Middle-mouse drag to pan the timeline in all directions.\n  useEffect(() => {\n    const el = containerRef.current;\n    if (!el) return;\n\n    const maxScrollY = (trackCount: number, viewHeight: number) => {\n      if (trackCount <= 0) return 0;\n      const lastBottom =\n        RULER_HEIGHT +\n        (trackCount - 1) * (trackHeight + TRACK_SPACING) +\n        4 +\n        trackHeight;\n      return Math.max(0, lastBottom - viewHeight);\n    };\n\n    const onDown = (e: MouseEvent) => {\n      if (e.button !== 1) return;\n      e.preventDefault();\n      e.stopPropagation();\n      panRef.current = {\n        x: e.clientX,\n        y: e.clientY,\n        scrollLeft: el.scrollLeft,\n        scrollTop: useVideoStore.getState().scrollTop,\n      };\n      setIsPanning(true);\n    };\n    const onMove = (e: MouseEvent) => {\n      const pan = panRef.current;\n      if (!pan) return;\n      e.preventDefault();\n      const dx = e.clientX - pan.x;\n      const dy = e.clientY - pan.y;\n\n      const nextLeft = Math.max(0, pan.scrollLeft - dx);\n      if (el.scrollLeft !== nextLeft) {\n        el.scrollLeft = nextLeft;\n      }\n      scrollLeftRef.current = nextLeft;\n      setScrollLeft(nextLeft);\n\n      const trackCount = getVisibleTimelineTracks(useVideoStore.getState().tracks).length;\n      const maxY = maxScrollY(trackCount, el.clientHeight);\n      setScrollTop(Math.max(0, Math.min(maxY, pan.scrollTop - dy)));\n    };\n    const onUp = (e: MouseEvent) => {\n      if (e.button !== 1 && panRef.current == null) return;\n      if (!panRef.current) return;\n      panRef.current = null;\n      setIsPanning(false);\n    };\n    const preventAutoScroll = (e: MouseEvent) => {\n      if (e.button === 1) e.preventDefault();\n    };\n\n    el.addEventListener('mousedown', onDown, true);\n    window.addEventListener('mousemove', onMove);\n    window.addEventListener('mouseup', onUp);\n    el.addEventListener('auxclick', preventAutoScroll);\n    return () => {\n      el.removeEventListener('mousedown', onDown, true);\n      window.removeEventListener('mousemove', onMove);\n      window.removeEventListener('mouseup', onUp);\n      el.removeEventListener('auxclick', preventAutoScroll);\n    };\n  }, [trackHeight, setScrollTop]);\n\n  return (\n    <div\n      ref={containerRef}\n      onWheel={handleWheel}\n      className={`flex-1 bg-[#0A0A0F] overflow-y-hidden overflow-x-auto relative scrollbar-none ${\n        isPanning ? 'cursor-grabbing' : ''\n      }`}\n      onScroll={handleScroll}\n      style={{ minHeight: '260px' }}\n    >\n      <Stage\n        width={stageWidth}\n        height={dimensions.height}\n        className=\"absolute top-0 left-0\"\n        onClick={(e) => {\n          // Empty stage (not a clip / track chrome that cancelBubble) clears selection\n          if (e.target === e.target.getStage()) {\n            clearSelection();\n          }\n        }}\n      >\n        <Layer>\n          {/* Timeline Time Ruler Background */}\n          <Rect\n            x={0}\n            y={0}\n            width={stageWidth}\n            height={RULER_HEIGHT}\n            fill=\"#13131A\"\n            stroke=\"#2A2A38\"\n            strokeWidth={1}\n            onMouseDown={handleRulerSeek}\n          />\n\n          {/* Time Ruler Ticks & Timecodes \u2014 viewport-culled; non-listening so seek hits the ruler Rect */}\n          {rulerTicks.map((tick) => (\n            <Group key={tick.timeSec} x={tick.x} y={0} listening={false}>\n              <Line points={[0, 20, 0, 40]} stroke=\"#2A2A38\" strokeWidth={1} />\n              <Text\n                text={formatTimecode(tick.timeSec)}\n                fontSize={9}\n                fill=\"#8888A0\"\n                fontFamily=\"monospace\"\n                x={5}\n                y={25}\n              />\n              {tick.minors.map((mx) => (\n                <Line\n                  key={mx}\n                  points={[mx, 32, mx, 40]}\n                  stroke=\"#2A2A38\"\n                  strokeWidth={0.5}\n                />\n              ))}\n            </Group>\n          ))}\n\n          {/* Scrolling Tracks Group */}\n          <Group\n            y={-scrollTop}\n            clipFunc={(ctx) => {\n              ctx.rect(0, RULER_HEIGHT + scrollTop, stageWidth, dimensions.height - RULER_HEIGHT);\n            }}\n          >\n            {/* Render Tracks Lane Backgrounds */}\n            {visibleTracks.map((track, trackIndex) => {\n              const y = getTrackY(trackIndex);\n              return (\n                <Group key={track.id} y={y}>\n                  {/* Track Row Background \u2014 empty drag starts marquee */}\n                  <Rect\n                    x={0}\n                    y={0}\n                    width={stageWidth}\n                    height={trackHeight}\n                    fill=\"#1C1C26\"\n                    opacity={0.3}\n                    stroke=\"#2A2A38\"\n                    strokeWidth={0.5}\n                    onMouseDown={(e) => {\n                      if (e.evt.button !== 0) return;\n                      e.cancelBubble = true;\n                      const stage = e.target.getStage();\n                      const pointer = stage?.getPointerPosition();\n                      if (!pointer) return;\n                      const x = pointer.x;\n                      const y = pointer.y + scrollTop;\n                      marqueeActiveRef.current = true;\n                      const box = {\n                        x0: x,\n                        y0: y,\n                        x1: x,\n                        y1: y,\n                        additive: isMultiModifier(e.evt),\n                      };\n                      marqueeRef.current = box;\n                      setMarquee(box);\n                    }}\n                  />\n\n                  {/* Render Clips inside this track */}\n                  {track.clips.map((clip) => {\n                    const isGroupFollower =\n                      groupDragLeaderId != null &&\n                      groupDragLeaderId !== clip.id &&\n                      selectedClipIds.includes(clip.id);\n                    const dragOffsetSec = isGroupFollower ? groupDragDeltaSec : 0;\n                    const clipX = (clip.startTime + dragOffsetSec) * zoom;\n                    const clipWidth = clip.duration * zoom;\n                    const isSelected = selectedClipIds.includes(clip.id);\n\n                    // Colors: video = blue, audio = green, image = teal, text = purple, subtitle = dark purple\n                    let clipColor = '#3D5AFE'; // video\n                    if (clip.type === 'audio') clipColor = '#00E676';\n                    else if (clip.type === 'image') clipColor = '#00BFA5';\n                    else if (clip.type === 'text') clipColor = '#AA00FF';\n                    else if (clip.type === 'subtitle') clipColor = '#8000FF';\n\n                    const asset = assets.find((a) => a.id === clip.assetId);\n                    const clipName = clip.text || asset?.name || 'Media Clip';\n                    const clipH = trackHeight - 8;\n                    const clipThumb =\n                      clip.type === 'video' || clip.type === 'image'\n                        ? thumbnails.get(clip.assetId)\n                        : undefined;\n                    const patternScale =\n                      clipThumb && clipThumb.naturalHeight > 0\n                        ? clipH / clipThumb.naturalHeight\n                        : 1;\n\n                    return (\n                      <Group\n                        key={clip.id}\n                        x={clipX}\n                        y={4}\n                        clipX={0}\n                        clipY={0}\n                        clipWidth={Math.max(0, clipWidth)}\n                        clipHeight={clipH}\n                        draggable={!track.locked}\n                        dragBoundFunc={(pos) => {\n                          const { x: snappedX, snapLineX: nextSnapLine } = computeSnapPosition(\n                            pos.x,\n                            clipWidth,\n                            clip.id,\n                          );\n                          pendingSnapLineRef.current = nextSnapLine;\n                          // Limit vertical drag between the top and bottom of the tracks container\n                          const minY = RULER_HEIGHT - scrollTop;\n                          const maxY =\n                            RULER_HEIGHT +\n                            visibleTracks.length * (trackHeight + TRACK_SPACING) -\n                            scrollTop -\n                            trackHeight;\n                          // Multi-drag stays on the same track row (time only)\n                          const isMulti =\n                            selectedClipIds.includes(clip.id) && selectedClipIds.length > 1;\n                          if (isMulti) {\n                            return { x: snappedX, y: 4 };\n                          }\n                          const clampedY = Math.max(minY, Math.min(maxY, pos.y));\n                          return {\n                            x: snappedX,\n                            y: clampedY,\n                          };\n                        }}\n                        onDragStart={(e) => {\n                          clearSplitHover();\n                          clearEdgeHover();\n                          e.cancelBubble = true;\n                          const multi = isMultiModifier(e.evt);\n                          const already = selectedClipIds.includes(clip.id);\n                          if (multi) {\n                            if (!already) selectClip(clip.id, true);\n                          } else if (!already) {\n                            selectClip(clip.id, false);\n                          }\n                          // Keep multi-selection when dragging an already-selected clip\n                          const ids = useVideoStore.getState().selectedClipIds;\n                          if (ids.includes(clip.id) && ids.length > 1) {\n                            setGroupDragLeaderId(clip.id);\n                            setGroupDragDeltaSec(0);\n                          } else {\n                            setGroupDragLeaderId(null);\n                            setGroupDragDeltaSec(0);\n                          }\n                        }}\n                        onMouseEnter={(e) => {\n                          if (!syncEdgeHoverFromClip(clip, track, e)) {\n                            syncSplitHoverFromPointer(clip, track.locked, e);\n                          }\n                        }}\n                        onMouseMove={(e) => {\n                          if (!syncEdgeHoverFromClip(clip, track, e)) {\n                            syncSplitHoverFromPointer(clip, track.locked, e);\n                          }\n                        }}\n                        onMouseLeave={() => {\n                          // Same as split: chip under cursor steals the Konva hit target.\n                          // Ignore leave while ready; window mousemove owns dismiss.\n                          if (edgeHoverReadyRef.current) return;\n                          if (edgeHoverKeyRef.current) {\n                            scheduleEdgeHoverClear();\n                            return;\n                          }\n                          if (splitHoverReadyRef.current) return;\n                          scheduleSplitHoverClear();\n                        }}\n                        onDragMove={(e) => {\n                          syncSnapLineFromDrag();\n                          const ids = useVideoStore.getState().selectedClipIds;\n                          if (ids.includes(clip.id) && ids.length > 1) {\n                            const deltaSec = e.target.x() / zoom - clip.startTime;\n                            setGroupDragDeltaSec(deltaSec);\n                            setGroupDragLeaderId(clip.id);\n                          }\n                        }}\n                        onDragEnd={(e) => {\n                          const newX = e.target.x();\n                          const newStartTime = newX / zoom;\n                          const deltaSec = newStartTime - clip.startTime;\n                          const ids = useVideoStore.getState().selectedClipIds;\n                          const isMulti = ids.includes(clip.id) && ids.length > 1;\n\n                          setGroupDragLeaderId(null);\n                          setGroupDragDeltaSec(0);\n\n                          if (isMulti) {\n                            moveClipsByDelta(ids, deltaSec);\n                            setSnapLineX(null);\n                            e.target.y(4);\n                            return;\n                          }\n\n                          // Single clip: allow track change\n                          const stage = e.target.getStage();\n                          if (stage) {\n                            const pointer = stage.getPointerPosition();\n                            if (pointer) {\n                              const pointerY = pointer.y + scrollTop;\n                              const relativeY = pointerY - RULER_HEIGHT;\n                              const trackIndex = Math.floor(relativeY / (trackHeight + TRACK_SPACING));\n                              \n                              if (trackIndex >= 0 && trackIndex < visibleTracks.length) {\n                                const targetTrack = visibleTracks[trackIndex];\n                                // Restrict movement to tracks of the SAME type and unlocked\n                                if (targetTrack && targetTrack.type === track.type && !targetTrack.locked) {\n                                  moveClip(clip.id, newStartTime, targetTrack.id);\n                                  setSnapLineX(null);\n                                  e.target.y(4);\n                                  return;\n                                }\n                              }\n                            }\n                          }\n                          \n                          // Fallback to original track\n                          moveClip(clip.id, newStartTime, track.id);\n                          setSnapLineX(null);\n                          e.target.y(4);\n                        }}\n                        onClick={(e) => {\n                          e.cancelBubble = true; // prevent timeline deselection\n                          const multi = isMultiModifier(e.evt);\n                          // After a drag, Konva still fires click \u2014 skip if we just group-dragged\n                          if (!multi && selectedClipIds.includes(clip.id) && selectedClipIds.length > 1) {\n                            return;\n                          }\n                          selectClip(clip.id, multi);\n                        }}\n                        onContextMenu={(e) => {\n                          e.evt.preventDefault();\n                          e.cancelBubble = true;\n                          if (!selectedClipIds.includes(clip.id)) {\n                            selectClip(clip.id, false);\n                          }\n                          const stage = e.target.getStage();\n                          if (!stage) return;\n                          const pointer = stage.getPointerPosition();\n                          if (!pointer) return;\n                          const stageBox = stage.container().getBoundingClientRect();\n                          setContextMenu({\n                            visible: true,\n                            x: stageBox.left + pointer.x,\n                            y: stageBox.top + pointer.y,\n                            clipId: clip.id,\n                          });\n                        }}\n                      >\n                        {/* Clip Body \u2014 filmstrip for video/image via fillPatternRepeat */}\n                        <Rect\n                          name=\"clip-body\"\n                          x={0}\n                          y={0}\n                          width={clipWidth}\n                          height={clipH}\n                          fill={clipThumb ? undefined : clipColor}\n                          fillPatternImage={clipThumb}\n                          fillPatternRepeat=\"repeat-x\"\n                          fillPatternScale={\n                            clipThumb\n                              ? { x: patternScale, y: patternScale }\n                              : undefined\n                          }\n                          cornerRadius={4}\n                          opacity={isSelected ? 0.95 : 0.85}\n                          stroke=\"#2A2A38\"\n                          strokeWidth={1}\n                        />\n                        {/* Selection ring on top so accent is never covered by fill/pattern */}\n                        {isSelected && (\n                          <Rect\n                            x={0}\n                            y={0}\n                            width={clipWidth}\n                            height={clipH}\n                            fillEnabled={false}\n                            stroke={VIDEO_ACCENT}\n                            strokeWidth={2}\n                            cornerRadius={4}\n                            listening={false}\n                          />\n                        )}\n                        {/* Scrim so the clip name stays readable over the filmstrip */}\n                        {clipThumb && (\n                          <Rect\n                            name=\"clip-scrim\"\n                            x={0}\n                            y={0}\n                            width={clipWidth}\n                            height={22}\n                            fill=\"rgba(0,0,0,0.45)\"\n                            cornerRadius={[4, 4, 0, 0]}\n                            listening={false}\n                          />\n                        )}\n                        {/* Display Waveforms on Audio Clips */}\n                        {clip.type === 'audio' && (\n                          <Group x={4} y={(trackHeight - 8) / 2} listening={false}>\n                            {(() => {\n                              const innerW = Math.max(0, clipWidth - 8);\n                              const barCount = Math.min(\n                                MAX_WAVEFORM_BARS,\n                                Math.max(4, Math.ceil(innerW / 4)),\n                              );\n                              const gap = innerW / barCount;\n                              return Array.from({ length: barCount }).map((_, waveIdx) => {\n                                const waveHeight =\n                                  6 + Math.sin(waveIdx * 0.4) * 14 + Math.cos(waveIdx * 0.2) * 6;\n                                const x = waveIdx * gap;\n                                return (\n                                  <Line\n                                    key={waveIdx}\n                                    points={[x, -waveHeight / 2, x, waveHeight / 2]}\n                                    stroke=\"#13131A\"\n                                    strokeWidth={1.5}\n                                    opacity={0.6}\n                                  />\n                                );\n                              });\n                            })()}\n                          </Group>\n                        )}\n\n                        {/* Clip Name Label \u2014 single line + ellipsis; Group clipWidth clips overflow */}\n                        <Text\n                          name=\"clip-label\"\n                          text={clipName}\n                          fontSize={10}\n                          fill=\"#F0F0F5\"\n                          fontFamily=\"sans-serif\"\n                          fontStyle=\"bold\"\n                          x={8}\n                          y={8}\n                          width={Math.max(0, clipWidth - 16)}\n                          height={14}\n                          wrap=\"none\"\n                          ellipsis={true}\n                          listening={false}\n                        />\n\n                        {/* Display Speed Badge if not 1.0 */}\n                        {clip.speed !== 1.0 && (\n                          <Text\n                            text={`${clip.speed}x`}\n                            fontSize={8}\n                            fill=\"#FFB300\"\n                            fontStyle=\"bold\"\n                            x={8}\n                            y={34}\n                            listening={false}\n                          />\n                        )}\n\n                        {/* Left Trim Handle \u2014 hit zone + feature accent edge */}\n                        {isSelected && !track.locked && (\n                          <>\n                            <Rect\n                              name=\"trim-edge-left\"\n                              listening={false}\n                              x={0}\n                              y={0}\n                              width={\n                                trimHover?.clipId === clip.id && trimHover.edge === 'left'\n                                  ? TRIM_EDGE_HOVER\n                                  : TRIM_EDGE_IDLE\n                              }\n                              height={clipH}\n                              fill={VIDEO_ACCENT}\n                              opacity={1}\n                              cornerRadius={[4, 0, 0, 4]}\n                            />\n                            <Rect\n                              name=\"trim-left\"\n                              x={0}\n                              y={0}\n                              width={TRIM_HIT_WIDTH}\n                              height={clipH}\n                              fill=\"rgba(0,0,0,0.001)\"\n                              onMouseEnter={(e) => {\n                                setTrimHover({ clipId: clip.id, edge: 'left' });\n                                setStageCursor(e.target.getStage(), 'ew-resize');\n                              }}\n                              onMouseLeave={(e) => {\n                                setTrimHover((prev) =>\n                                  prev?.clipId === clip.id && prev.edge === 'left' ? null : prev,\n                                );\n                                setStageCursor(e.target.getStage(), 'default');\n                              }}\n                              onMouseDown={(e) => {\n                              e.cancelBubble = true;\n                              e.evt.preventDefault();\n                              e.evt.stopPropagation();\n\n                              const group = e.target.getParent();\n                              if (!group) return;\n                              group.draggable(false);\n                              setStageCursor(e.target.getStage(), 'ew-resize');\n\n                              const body = group.findOne('.clip-body');\n                              const scrim = group.findOne('.clip-scrim');\n                              const label = group.findOne('.clip-label');\n                              const edgeRight = group.findOne('.trim-edge-right');\n                              const handleRight = group.findOne('.trim-right');\n\n                              const originClientX = e.evt.clientX;\n                              const startClipX = clipX;\n                              const startWidth = clipWidth;\n                              const startStartTime = clip.startTime;\n                              const startDuration = clip.duration;\n                              const startTrimIn = clip.trimIn;\n                              const speed = clip.speed || 1;\n                              const z = zoom;\n                              const locked = track.locked;\n                              const isMedia = clip.type === 'video' || clip.type === 'audio';\n                              // Media can only reveal source already trimmed away (trimIn > 0).\n                              const maxExtendLeftPx = isMedia\n                                ? Math.min(startClipX, (startTrimIn / speed) * z)\n                                : startClipX;\n\n                              const clampDx = (dx: number) => {\n                                const minDx = -maxExtendLeftPx;\n                                const maxDx = startWidth - 10;\n                                return Math.max(minDx, Math.min(maxDx, dx));\n                              };\n\n                              const layoutAtWidth = (leftX: number, newWidth: number) => {\n                                group.x(leftX);\n                                group.clipWidth(newWidth);\n                                body?.width(newWidth);\n                                scrim?.width(newWidth);\n                                label?.width(Math.max(0, newWidth - 16));\n                                const edgeW = edgeRight?.width() ?? TRIM_EDGE_IDLE;\n                                edgeRight?.x(Math.max(0, newWidth - edgeW));\n                                handleRight?.x(Math.max(0, newWidth - TRIM_HIT_WIDTH));\n                              };\n\n                              const resolveLeft = (clientX: number) => {\n                                const rawDx = clientX - originClientX;\n                                const rawLeftX = startClipX + clampDx(rawDx);\n                                const snapped = computeSnapEdgeX(rawLeftX, clip.id);\n                                const clamped = clampDx(snapped.x - startClipX);\n                                const leftX = startClipX + clamped;\n                                const newWidth = startWidth - clamped;\n                                const guideX =\n                                  snapped.snapLineX !== null && Math.abs(leftX - snapped.snapLineX) < 0.5\n                                    ? snapped.snapLineX\n                                    : null;\n                                return { leftX, newWidth, guideX, clamped };\n                              };\n\n                              const applyVisual = (clientX: number) => {\n                                const { leftX, newWidth, guideX } = resolveLeft(clientX);\n                                layoutAtWidth(leftX, newWidth);\n                                setSnapLineX(guideX);\n                              };\n\n                              const onMove = (ev: MouseEvent) => {\n                                applyVisual(ev.clientX);\n                              };\n\n                              const onUp = (ev: MouseEvent) => {\n                                window.removeEventListener('mousemove', onMove);\n                                window.removeEventListener('mouseup', onUp);\n                                const { leftX, newWidth, clamped } = resolveLeft(ev.clientX);\n                                const deltaSec = clamped / z;\n                                const newStartTime = Math.max(0, startStartTime + deltaSec);\n                                const newDuration = Math.max(0.1, startDuration - deltaSec);\n                                const newTrimIn = isMedia\n                                  ? Math.max(0, startTrimIn + deltaSec * speed)\n                                  : startTrimIn;\n                                layoutAtWidth(leftX, newWidth);\n                                updateClipProperties(clip.id, {\n                                  startTime: newStartTime,\n                                  duration: newDuration,\n                                  ...(isMedia ? { trimIn: newTrimIn } : {}),\n                                });\n                                group.draggable(!locked);\n                                setStageCursor(e.target.getStage(), 'default');\n                                setSnapLineX(null);\n                              };\n\n                              window.addEventListener('mousemove', onMove);\n                              window.addEventListener('mouseup', onUp);\n                            }}\n                            />\n                          </>\n                        )}\n\n                        {/* Right Trim Handle \u2014 hit zone + feature accent edge */}\n                        {isSelected && !track.locked && (\n                          <>\n                            <Rect\n                              name=\"trim-edge-right\"\n                              listening={false}\n                              x={\n                                clipWidth -\n                                (trimHover?.clipId === clip.id && trimHover.edge === 'right'\n                                  ? TRIM_EDGE_HOVER\n                                  : TRIM_EDGE_IDLE)\n                              }\n                              y={0}\n                              width={\n                                trimHover?.clipId === clip.id && trimHover.edge === 'right'\n                                  ? TRIM_EDGE_HOVER\n                                  : TRIM_EDGE_IDLE\n                              }\n                              height={clipH}\n                              fill={VIDEO_ACCENT}\n                              opacity={1}\n                              cornerRadius={[0, 4, 4, 0]}\n                            />\n                            <Rect\n                              name=\"trim-right\"\n                              x={clipWidth - TRIM_HIT_WIDTH}\n                              y={0}\n                              width={TRIM_HIT_WIDTH}\n                              height={clipH}\n                              fill=\"rgba(0,0,0,0.001)\"\n                              onMouseEnter={(e) => {\n                                setTrimHover({ clipId: clip.id, edge: 'right' });\n                                setStageCursor(e.target.getStage(), 'ew-resize');\n                              }}\n                              onMouseLeave={(e) => {\n                                setTrimHover((prev) =>\n                                  prev?.clipId === clip.id && prev.edge === 'right' ? null : prev,\n                                );\n                                setStageCursor(e.target.getStage(), 'default');\n                              }}\n                              onMouseDown={(e) => {\n                              e.cancelBubble = true;\n                              e.evt.preventDefault();\n                              e.evt.stopPropagation();\n\n                              const group = e.target.getParent();\n                              if (!group) return;\n                              // Prevent the clip Group from interpreting this as a move\n                              group.draggable(false);\n                              setStageCursor(e.target.getStage(), 'ew-resize');\n\n                              const body = group.findOne('.clip-body');\n                              const scrim = group.findOne('.clip-scrim');\n                              const label = group.findOne('.clip-label');\n                              const edgeRight = group.findOne('.trim-edge-right');\n                              const handleRight = group.findOne('.trim-right');\n\n                              const originClientX = e.evt.clientX;\n                              const startWidth = clipWidth;\n                              const startGroupX = clipX;\n                              const startTrimIn = clip.trimIn || 0;\n                              const startTrimOut = clip.trimOut || 0;\n                              const speed = clip.speed || 1;\n                              const z = zoom;\n                              const locked = track.locked;\n                              const isMedia = clip.type === 'video' || clip.type === 'audio';\n                              const assetDur = asset?.duration ?? 0;\n                              // Grow right only into remaining source (or freely for image/text).\n                              const maxWidthPx = isMedia\n                                ? Math.max(\n                                    10,\n                                    ((assetDur - startTrimIn - startTrimOut) / speed) * z,\n                                  )\n                                : Number.POSITIVE_INFINITY;\n\n                              const layoutAtWidth = (newWidth: number) => {\n                                group.x(startGroupX);\n                                group.clipWidth(newWidth);\n                                body?.width(newWidth);\n                                scrim?.width(newWidth);\n                                label?.width(Math.max(0, newWidth - 16));\n                                const edgeW = edgeRight?.width() ?? TRIM_EDGE_IDLE;\n                                edgeRight?.x(Math.max(0, newWidth - edgeW));\n                                handleRight?.x(Math.max(0, newWidth - TRIM_HIT_WIDTH));\n                              };\n\n                              const resolveRight = (clientX: number) => {\n                                const rawEndX = startGroupX + startWidth + (clientX - originClientX);\n                                const snapped = computeSnapEdgeX(rawEndX, clip.id);\n                                let newWidth = Math.max(10, snapped.x - startGroupX);\n                                newWidth = Math.min(newWidth, maxWidthPx);\n                                const endX = startGroupX + newWidth;\n                                const guideX =\n                                  snapped.snapLineX !== null &&\n                                  Math.abs(endX - snapped.snapLineX) < 0.5\n                                    ? snapped.snapLineX\n                                    : null;\n                                return { newWidth, guideX };\n                              };\n\n                              const applyVisual = (clientX: number) => {\n                                const { newWidth, guideX } = resolveRight(clientX);\n                                layoutAtWidth(newWidth);\n                                setSnapLineX(guideX);\n                              };\n\n                              const onMove = (ev: MouseEvent) => {\n                                applyVisual(ev.clientX);\n                              };\n\n                              const onUp = (ev: MouseEvent) => {\n                                window.removeEventListener('mousemove', onMove);\n                                window.removeEventListener('mouseup', onUp);\n                                const { newWidth } = resolveRight(ev.clientX);\n                                const newDuration = Math.max(0.1, newWidth / z);\n                                layoutAtWidth(newWidth);\n                                if (isMedia) {\n                                  // Keep source window: trimOut absorbs right-edge shorten/extend.\n                                  const usedSource = newDuration * speed;\n                                  const newTrimOut = Math.max(\n                                    0,\n                                    assetDur - startTrimIn - usedSource,\n                                  );\n                                  updateClipProperties(clip.id, {\n                                    duration: newDuration,\n                                    trimOut: newTrimOut,\n                                  });\n                                } else {\n                                  updateClipProperties(clip.id, {\n                                    duration: newDuration,\n                                  });\n                                }\n                                group.draggable(!locked);\n                                setStageCursor(e.target.getStage(), 'default');\n                                setSnapLineX(null);\n                              };\n\n                              window.addEventListener('mousemove', onMove);\n                              window.addEventListener('mouseup', onUp);\n                            }}\n                            />\n                          </>\n                        )}\n                      </Group>\n                    );\n                  })}\n                </Group>\n              );\n            })}\n\n            {/* Render Transitions Overlays */}\n            {transitions.map((trans) => {\n              let clip: any = null;\n              let trackIndex = -1;\n              const isStart = trans.fromClipId === 'none';\n              const isEnd = trans.toClipId === 'none';\n              const targetClipId = isStart ? trans.toClipId : trans.fromClipId;\n              \n              for (let tIdx = 0; tIdx < visibleTracks.length; tIdx++) {\n                const found = visibleTracks[tIdx].clips.find((c) => c.id === targetClipId);\n                if (found) {\n                  clip = found;\n                  trackIndex = tIdx;\n                  break;\n                }\n              }\n\n              if (!clip || trackIndex === -1) return null;\n\n              let transX = 0;\n              const transWidth = trans.duration * zoom;\n\n              if (isStart) {\n                // Start transition (Fade In) - placed at the beginning of the clip\n                transX = clip.startTime * zoom;\n              } else if (isEnd) {\n                // End transition (Fade Out) - placed at the end of the clip\n                transX = (clip.startTime + clip.duration - trans.duration) * zoom;\n              } else {\n                // Between clips transition - centered at the clip cuts\n                const cutTime = clip.startTime + clip.duration;\n                transX = (cutTime - trans.duration / 2) * zoom;\n              }\n\n              const transY = getTrackY(trackIndex) + (trackHeight - 18) / 2;\n              const fillColor = isStart ? '#4CAF50' : isEnd ? '#F44336' : '#FF6D00'; // Green for Start, Red for End, Orange for Between\n              \n              let labelText = trans.type.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');\n              if (isStart) labelText += ' In';\n              if (isEnd) labelText += ' Out';\n\n              return (\n                <Group\n                  key={trans.id}\n                  x={transX}\n                  y={transY}\n                  onClick={(e) => {\n                    e.cancelBubble = true;\n                    setEditingTransition(trans);\n                  }}\n                >\n                  <Rect\n                    x={0}\n                    y={0}\n                    width={transWidth}\n                    height={18}\n                    fill={fillColor}\n                    opacity={0.95}\n                    cornerRadius={3}\n                    stroke=\"#13131A\"\n                    strokeWidth={1}\n                  />\n                  <Text\n                    text={labelText}\n                    fontSize={8}\n                    fill=\"#FFFFFF\"\n                    fontFamily=\"sans-serif\"\n                    fontStyle=\"bold\"\n                    x={4}\n                    y={5}\n                    width={transWidth - 8}\n                    wrap=\"none\"\n                    ellipsis={true}\n                    align=\"center\"\n                  />\n                </Group>\n              );\n            })}\n\n            {marquee && (\n              <Rect\n                x={Math.min(marquee.x0, marquee.x1)}\n                y={Math.min(marquee.y0, marquee.y1)}\n                width={Math.abs(marquee.x1 - marquee.x0)}\n                height={Math.abs(marquee.y1 - marquee.y0)}\n                fill=\"rgba(234, 88, 12, 0.18)\"\n                stroke={VIDEO_ACCENT}\n                strokeWidth={1}\n                dash={[4, 3]}\n                listening={false}\n              />\n            )}\n          </Group>\n\n          {/* Yellow vertical snapping line */}\n          {snapLineX !== null && (\n            <Line\n              points={[snapLineX, 0, snapLineX, dimensions.height]}\n              stroke={VIDEO_ACCENT}\n              strokeWidth={1.5}\n              dash={[4, 4]}\n              listening={false}\n            />\n          )}\n\n          {/* Playhead \u2014 full-height hit zone; drag horizontally along the timeline */}\n          <Group\n            x={playheadTime * zoom}\n            y={0}\n            draggable\n            dragBoundFunc={(pos) => ({\n              x: Math.max(0, pos.x),\n              y: 0,\n            })}\n            onMouseEnter={(e) => {\n              setPlayheadCursor(e.target.getStage(), true);\n              syncSplitHoverFromPlayhead(e);\n            }}\n            onMouseMove={(e) => {\n              setPlayheadCursor(e.target.getStage(), true);\n              syncSplitHoverFromPlayhead(e);\n            }}\n            onMouseLeave={(e) => {\n              setPlayheadCursor(e.target.getStage(), false);\n              if (!splitHoverReadyRef.current) {\n                scheduleSplitHoverClear();\n              }\n            }}\n            onDragStart={(e) => {\n              clearSplitHover();\n              clearEdgeHover();\n              setPlayheadCursor(e.target.getStage(), true);\n              e.cancelBubble = true;\n            }}\n            onDragMove={handlePlayheadDrag}\n            onDragEnd={(e) => {\n              handlePlayheadDrag(e);\n              setPlayheadCursor(e.target.getStage(), true);\n            }}\n          >\n            {/* Invisible grab strip for the whole vertical line */}\n            <Rect\n              x={-PLAYHEAD_HIT_HALF}\n              y={0}\n              width={PLAYHEAD_HIT_HALF * 2}\n              height={dimensions.height}\n              fill=\"rgba(0,0,0,0.001)\"\n            />\n            <Line\n              points={[0, 0, 0, dimensions.height]}\n              stroke={VIDEO_ACCENT}\n              strokeWidth={1.5}\n              listening={false}\n            />\n            <Rect\n              x={-6}\n              y={0}\n              width={12}\n              height={16}\n              fill={VIDEO_ACCENT}\n              cornerRadius={[0, 0, 3, 3]}\n              listening={false}\n            />\n          </Group>\n        </Layer>\n      </Stage>\n\n\n      {/* Edge (+) chip \u2014 add / resolve transition at start, end, or cut */}\n      {edgeHover?.ready && (\n        <button\n          type=\"button\"\n          data-we-edge-chip\n          className=\"fixed z-[60] flex -translate-x-1/2 -translate-y-1/2 cursor-pointer items-center gap-1.5 rounded-lg border border-panel-border bg-panel px-2.5 py-1.5 font-sans text-xs font-semibold text-white shadow-2xl transition-opacity hover:opacity-80\"\n          style={{\n            left: edgeHover.clientX,\n            top: edgeHover.clientY,\n          }}\n          onMouseEnter={cancelEdgeHoverClear}\n          onMouseLeave={scheduleEdgeHoverClear}\n          onClick={(e) => {\n            e.preventDefault();\n            e.stopPropagation();\n            const intent = edgeHover.intent;\n            if (intent.kind === 'between' && edgeHover.openJunction) {\n              openTransitionJunction({\n                fromClipId: intent.fromClipId,\n                toClipId: intent.toClipId,\n              });\n            } else {\n              if (intent.kind === 'start' || intent.kind === 'end') {\n                selectClip(intent.clipId, false);\n              } else {\n                selectClip(intent.fromClipId, false);\n              }\n              openTransitionsForEdge(intent);\n            }\n            clearEdgeHover();\n          }}\n        >\n          <Plus size={12} className=\"text-[var(--we-accent)]\" />\n          <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n            {t.transition.addTransition}\n          </TextBody>\n        </button>\n      )}\n\n      {/* Hover-split chip \u2014 on playhead \u2229 clip after hover on that intersection */}\n      {splitHover?.ready &&\n        (() => {\n          const trackIndex = visibleTracks.findIndex((tr) =>\n            tr.clips.some((c) => c.id === splitHover.clipId),\n          );\n          const track = trackIndex >= 0 ? visibleTracks[trackIndex] : undefined;\n          const clip = track?.clips.find((c) => c.id === splitHover.clipId);\n          const host = containerRef.current;\n          if (!clip || !host || trackIndex < 0) return null;\n\n          const hostRect = host.getBoundingClientRect();\n          const clipH = trackHeight - 8;\n          const playheadX = playheadTime * zoom - scrollLeft;\n          const centerY =\n            getTrackY(trackIndex) - scrollTop + 4 + clipH / 2;\n\n          return (\n            <button\n              type=\"button\"\n              data-we-split-chip\n              className=\"fixed z-[60] flex -translate-x-1/2 -translate-y-1/2 cursor-pointer items-center gap-1.5 rounded-lg border border-panel-border bg-panel px-2.5 py-1.5 font-sans text-xs font-semibold text-white shadow-2xl transition-opacity hover:opacity-80\"\n              style={{\n                left: hostRect.left + playheadX,\n                top: hostRect.top + centerY,\n              }}\n              onMouseEnter={cancelSplitHoverClear}\n              onMouseLeave={scheduleSplitHoverClear}\n              onClick={(e) => {\n                e.preventDefault();\n                e.stopPropagation();\n                splitClip(splitHover.clipId, playheadTime);\n                clearSplitHover();\n              }}\n            >\n              <Scissors size={12} className=\"text-[var(--we-accent)]\" />\n              <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                {tp.split}\n              </TextBody>\n            </button>\n          );\n        })()}\n\n      {/* Clip Right-Click Context Menu \u2014 fixed + clamped to viewport */}\n      {contextMenu && contextMenu.visible && (() => {\n        const menuClip = tracks\n          .flatMap((tr) => tr.clips.map((c) => ({ clip: c, track: tr })))\n          .find((x) => x.clip.id === contextMenu.clipId);\n        const canLayer = menuClip && menuClip.track.type !== 'subtitle' && !menuClip.track.locked;\n        const clipType = menuClip?.clip.type;\n        const tai = t.videoEditor.aiTools.tools;\n\n        const openAiTool = (tool: VideoAiToolId) => {\n          selectClip(contextMenu.clipId, false);\n          openAiGenerateTool(tool);\n          setContextMenu(null);\n        };\n\n        const menuBtnClass =\n          'flex w-full cursor-pointer items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[var(--we-accent-muted)]';\n\n        return (\n          <div\n            ref={contextMenuRef}\n            className=\"fixed z-50 min-w-[200px] rounded-xl border border-panel-border bg-panel py-1 font-sans text-xs font-medium text-white shadow-2xl\"\n            style={{\n              top: contextMenu.y,\n              left: contextMenu.x,\n            }}\n            onClick={(e) => e.stopPropagation()}\n          >\n            <TextTitle as=\"span\" size=\"xs\" className=\"block px-3 py-1 uppercase tracking-wider text-[var(--we-accent)]\">\n              {tp.contextTitle}\n            </TextTitle>\n            {canLayer && (\n              <>\n                <button\n                  type=\"button\"\n                  onClick={() => {\n                    moveClipLayer(contextMenu.clipId, 'up');\n                    setContextMenu(null);\n                  }}\n                  className={menuBtnClass}\n                >\n                  <ArrowUp size={12} className=\"text-[var(--we-accent)]\" />\n                  <TextBody as=\"span\" size=\"sm\">{tp.moveLayerUp}</TextBody>\n                </button>\n                <button\n                  type=\"button\"\n                  onClick={() => {\n                    moveClipLayer(contextMenu.clipId, 'down');\n                    setContextMenu(null);\n                  }}\n                  className={menuBtnClass}\n                >\n                  <ArrowDown size={12} className=\"text-[var(--we-accent)]\" />\n                  <TextBody as=\"span\" size=\"sm\">{tp.moveLayerDown}</TextBody>\n                </button>\n              </>\n            )}\n            {clipType === 'video' && (\n              <>\n                <button\n                  type=\"button\"\n                  onClick={() => handleGenerateSubtitles(contextMenu.clipId)}\n                  className={`${menuBtnClass} border-t border-panel-border`}\n                >\n                  <Sparkles size={11} className=\"text-[var(--we-accent)]\" />\n                  <TextBody as=\"span\" size=\"sm\">{tp.generateSubtitles}</TextBody>\n                </button>\n                <button\n                  type=\"button\"\n                  onClick={() => openAiTool('videoProperties')}\n                  className={menuBtnClass}\n                >\n                  <Clapperboard size={11} className=\"text-[var(--we-accent)]\" />\n                  <TextBody as=\"span\" size=\"sm\">{tai.videoProperties}</TextBody>\n                </button>\n                <button\n                  type=\"button\"\n                  onClick={() => openAiTool('colorGrading')}\n                  className={menuBtnClass}\n                >\n                  <Palette size={11} className=\"text-[var(--we-accent)]\" />\n                  <TextBody as=\"span\" size=\"sm\">{tai.colorGrading}</TextBody>\n                </button>\n              </>\n            )}\n            {clipType === 'image' && (\n              <button\n                type=\"button\"\n                onClick={() => openAiTool('designPreset')}\n                className={`${menuBtnClass} border-t border-panel-border`}\n              >\n                <Sparkles size={11} className=\"text-[var(--we-accent)]\" />\n                <TextBody as=\"span\" size=\"sm\">{tai.designPreset}</TextBody>\n              </button>\n            )}\n            {(clipType === 'subtitle' || clipType === 'text') && (\n              <>\n                <button\n                  type=\"button\"\n                  onClick={() => openAiTool('subtitleStyle')}\n                  className={`${menuBtnClass} border-t border-panel-border`}\n                >\n                  <Wand2 size={11} className=\"text-[var(--we-accent)]\" />\n                  <TextBody as=\"span\" size=\"sm\">{tai.subtitleStyle}</TextBody>\n                </button>\n                {clipType === 'subtitle' && (\n                  <button\n                    type=\"button\"\n                    onClick={() => openAiTool('translate')}\n                    className={menuBtnClass}\n                  >\n                    <Languages size={11} className=\"text-[var(--we-accent)]\" />\n                    <TextBody as=\"span\" size=\"sm\">{tai.translate}</TextBody>\n                  </button>\n                )}\n                <button\n                  type=\"button\"\n                  onClick={() => openAiTool('designPreset')}\n                  className={menuBtnClass}\n                >\n                  <Sparkles size={11} className=\"text-[var(--we-accent)]\" />\n                  <TextBody as=\"span\" size=\"sm\">{tai.designPreset}</TextBody>\n                </button>\n              </>\n            )}\n          </div>\n        );\n      })()}\n\n      {/* AI subtitle / voiceover loaders \u2014 HTML overlay aligned to timeline slots */}\n      {aiSubtitleJob && (() => {\n        const clipH = trackHeight - 8;\n\n        if (aiSubtitleJob.kind === 'voiceover' || aiSubtitleJob.kind === 'copy') {\n          const laneIndex = Math.max(\n            0,\n            visibleTracks.findIndex((tr) => tr.id === aiSubtitleJob.trackId),\n          );\n          const laneTop = getTrackY(laneIndex) - scrollTop;\n          const left = aiSubtitleJob.startTime * zoom;\n          const width = Math.max(48, aiSubtitleJob.duration * zoom);\n          const label =\n            aiSubtitleJob.kind === 'copy' ? tp.generatingCopy : tp.generatingVoiceover;\n          const hint =\n            aiSubtitleJob.kind === 'copy' ? tp.generatingCopyHint : tp.generatingVoiceoverHint;\n          return (\n            <div\n              className=\"pointer-events-none absolute left-0 top-0 z-40\"\n              style={{ width: stageWidth, height: dimensions.height }}\n            >\n              <div\n                className=\"absolute\"\n                style={{\n                  left,\n                  top: Math.max(RULER_HEIGHT, laneTop + 4),\n                  width,\n                  height: clipH,\n                }}\n              >\n                <SubtitleAiLoader label={label} hint={hint} variant=\"clip\" />\n              </div>\n            </div>\n          );\n        }\n\n        const subTrackIndex = visibleTracks.findIndex((tr) => tr.type === 'subtitle');\n        const laneIndex = subTrackIndex >= 0 ? subTrackIndex : 0;\n        const laneTop = getTrackY(laneIndex) - scrollTop;\n\n        if (aiSubtitleJob.kind === 'generate') {\n          const left = aiSubtitleJob.startTime * zoom;\n          const width = Math.max(48, aiSubtitleJob.duration * zoom);\n          return (\n            <div\n              className=\"pointer-events-none absolute left-0 top-0 z-40\"\n              style={{ width: stageWidth, height: dimensions.height }}\n              aria-hidden={false}\n            >\n              <div\n                className=\"absolute\"\n                style={{\n                  left,\n                  top: Math.max(RULER_HEIGHT, laneTop + 4),\n                  width,\n                  height: clipH,\n                }}\n              >\n                <SubtitleAiLoader\n                  label={tp.generatingSubtitles}\n                  hint={tp.generatingSubtitlesHint}\n                  variant=\"clip\"\n                />\n              </div>\n            </div>\n          );\n        }\n\n        const pendingIds = new Set(aiSubtitleJob.clipIds);\n        const pendingLabel =\n          aiSubtitleJob.kind === 'style'\n            ? tp.stylingSubtitles\n            : aiSubtitleJob.kind === 'clipEdit'\n              ? aiSubtitleJob.label\n              : tp.translatingSubtitles;\n        const cards: React.ReactNode[] = [];\n        visibleTracks.forEach((track, trackIndex) => {\n          if (\n            aiSubtitleJob.kind !== 'clipEdit' &&\n            track.type !== 'subtitle' &&\n            track.type !== 'text'\n          ) {\n            return;\n          }\n          const y = getTrackY(trackIndex) - scrollTop + 4;\n          track.clips.forEach((clip) => {\n            if (!pendingIds.has(clip.id)) return;\n            cards.push(\n              <div\n                key={clip.id}\n                className=\"absolute\"\n                style={{\n                  left: clip.startTime * zoom,\n                  top: Math.max(RULER_HEIGHT, y),\n                  width: Math.max(36, clip.duration * zoom),\n                  height: clipH,\n                }}\n              >\n                <SubtitleAiLoader label={pendingLabel} variant=\"clip\" />\n              </div>,\n            );\n          });\n        });\n\n        if (cards.length === 0) return null;\n        return (\n          <div\n            className=\"pointer-events-none absolute left-0 top-0 z-40\"\n            style={{ width: stageWidth, height: dimensions.height }}\n          >\n            {cards}\n          </div>\n        );\n      })()}\n\n      {/* Transition Builder Settings Modal */}\n      {editingTransition && (\n        <TransitionBuilder\n          transition={editingTransition}\n          onClose={() => setEditingTransition(null)}\n        />\n      )}\n    </div>\n  );\n};\n", "/** Pixel threshold for timeline drag snap (Konva dragBoundFunc). */\nexport const TIMELINE_SNAP_THRESHOLD_PX = 8;\n\ntype SnapClip = { id: string; startTime: number; duration: number };\ntype SnapTrack = { locked?: boolean; clips: SnapClip[] };\n\nfunction toFrame(timeSec: number, fps: number): number {\n  return Math.round(timeSec * fps);\n}\n\n/**\n * If any selected clip edge sits on the exact same frame as the playhead or\n * another clip edge, returns that guide's X in timeline pixels.\n * Visual feedback only \u2014 does not move clips.\n */\nexport function findAlignmentGuideX(opts: {\n  clipIds: readonly string[];\n  tracks: readonly SnapTrack[];\n  playheadTime: number;\n  zoom: number;\n  /** Frame grid used for exact alignment (must match keyboard nudge fps). */\n  fps?: number;\n}): number | null {\n  const { clipIds, tracks, playheadTime, zoom, fps = 30 } = opts;\n  if (!(zoom > 0) || !(fps > 0) || clipIds.length === 0) return null;\n\n  const idSet = new Set(clipIds);\n  const snapTimes: number[] = [playheadTime];\n\n  for (const track of tracks) {\n    for (const clip of track.clips) {\n      if (idSet.has(clip.id)) continue;\n      snapTimes.push(clip.startTime, clip.startTime + clip.duration);\n    }\n  }\n\n  for (const track of tracks) {\n    if (track.locked) continue;\n    for (const clip of track.clips) {\n      if (!idSet.has(clip.id)) continue;\n      const edges = [clip.startTime, clip.startTime + clip.duration];\n      for (const edge of edges) {\n        const edgeFrame = toFrame(edge, fps);\n        for (const snap of snapTimes) {\n          if (toFrame(snap, fps) === edgeFrame) {\n            return snap * zoom;\n          }\n        }\n      }\n    }\n  }\n\n  return null;\n}\n", "import React, { useMemo } from 'react';\nimport {\n  useVideoStore,\n  type TransitionClip,\n  type TransitionType,\n} from '../../../store/useVideoStore';\nimport { useTranslation } from '../../../i18n';\nimport { Button, Modal, PanelField, SelectDropdown } from '../../ui';\n\ninterface TransitionBuilderProps {\n  transition: TransitionClip;\n  onClose: () => void;\n}\n\ntype ClipLike = { id: string; duration: number } | null;\n\nexport const TransitionBuilder: React.FC<TransitionBuilderProps> = ({\n  transition: seed,\n  onClose,\n}) => {\n  const t = useTranslation();\n  const tt = t.transition;\n  const tracks = useVideoStore((s) => s.tracks);\n  const updateTransition = useVideoStore((s) => s.updateTransition);\n  const removeTransition = useVideoStore((s) => s.removeTransition);\n  // Live store row \u2014 Timeline only passes a click-time snapshot.\n  const transition =\n    useVideoStore((s) => s.transitions.find((tr) => tr.id === seed.id)) ?? seed;\n\n  const isStart = transition.fromClipId === 'none';\n  const isEnd = transition.toClipId === 'none';\n\n  let fromClip: ClipLike = null;\n  let toClip: ClipLike = null;\n\n  for (const track of tracks) {\n    if (!fromClip) {\n      const found = track.clips.find((c) => c.id === transition.fromClipId);\n      if (found) fromClip = found;\n    }\n    if (!toClip) {\n      const found = track.clips.find((c) => c.id === transition.toClipId);\n      if (found) toClip = found;\n    }\n    if (fromClip && toClip) break;\n  }\n\n  let maxDuration = 3.0;\n  let contextName = tt.builderContextBetween;\n\n  if (isStart && toClip) {\n    maxDuration = toClip.duration;\n    contextName = tt.builderContextStart;\n  } else if (isEnd && fromClip) {\n    maxDuration = fromClip.duration;\n    contextName = tt.builderContextEnd;\n  } else if (fromClip && toClip) {\n    maxDuration = 2 * Math.min(fromClip.duration, toClip.duration);\n    contextName = tt.builderContextBetween;\n  }\n\n  const typeOptions = useMemo(\n    () => [\n      { value: 'cross-dissolve', label: tt.items.crossDissolve.name },\n      { value: 'fade-black', label: tt.items.fadeBlack.name },\n      { value: 'fade-white', label: tt.items.fadeWhite.name },\n      { value: 'wipe-left', label: tt.items.wipeLeft.name },\n      { value: 'wipe-right', label: tt.items.wipeRight.name },\n      { value: 'wipe-up', label: tt.items.wipeUp.name },\n      { value: 'wipe-down', label: tt.items.wipeDown.name },\n      { value: 'slide-left', label: tt.items.slideLeft.name },\n      { value: 'slide-right', label: tt.items.slideRight.name },\n      { value: 'push-left', label: tt.items.pushLeft.name },\n      { value: 'push-right', label: tt.items.pushRight.name },\n      { value: 'iris-circle', label: tt.items.irisCircle.name },\n      { value: 'clock-wipe', label: tt.builderTypes.clockWipe },\n      { value: 'zoom-in', label: tt.builderTypes.zoomIn },\n      { value: 'zoom-punch', label: tt.builderTypes.zoomPunch },\n      { value: 'spin-zoom', label: tt.builderTypes.spinZoom },\n      { value: 'blur-dissolve', label: tt.items.blurDissolve.name },\n      { value: 'pixelate', label: tt.items.pixelate.name },\n      { value: 'glitch', label: tt.items.glitch.name },\n      { value: 'film-burn', label: tt.items.filmBurn.name },\n    ],\n    [tt],\n  );\n\n  const colorOptions = useMemo(\n    () => [\n      { value: 'black', label: tt.builderBgBlack },\n      { value: 'white', label: tt.builderBgWhite },\n      { value: 'transparent', label: tt.builderBgTransparent },\n    ],\n    [tt],\n  );\n\n  const easingOptions = useMemo(\n    () => [\n      { value: 'linear', label: tt.builderEasingLinear },\n      { value: 'ease-in', label: tt.builderEasingIn },\n      { value: 'ease-out', label: tt.builderEasingOut },\n      { value: 'ease-in-out', label: tt.builderEasingInOut },\n    ],\n    [tt],\n  );\n\n  const handleDelete = () => {\n    removeTransition(transition.id);\n    onClose();\n  };\n\n  return (\n    <Modal\n      isOpen\n      onClose={onClose}\n      title={`${tt.builderTitle}: ${contextName}`}\n      size=\"sm\"\n    >\n      <div className=\"flex flex-col gap-4\">\n        <PanelField\n          label={tt.builderType}\n          trailing={\n            <SelectDropdown\n              value={transition.type}\n              options={typeOptions}\n              onChange={(v) =>\n                updateTransition(transition.id, { type: v as TransitionType })\n              }\n            />\n          }\n        />\n\n        <PanelField\n          variant=\"slide\"\n          label={tt.builderDuration}\n          min={0.1}\n          max={parseFloat(maxDuration.toFixed(2))}\n          step={0.05}\n          numericValue={Math.min(transition.duration, maxDuration)}\n          onChange={(val) =>\n            updateTransition(\n              transition.id,\n              { duration: Math.min(val, maxDuration) },\n              { history: false },\n            )\n          }\n          onCommit={() =>\n            updateTransition(transition.id, {}, { history: true })\n          }\n          formatValue={(v) => `${v.toFixed(2)}s`}\n        />\n\n        {(isStart || isEnd) && (\n          <PanelField\n            label={tt.builderBg}\n            trailing={\n              <SelectDropdown\n                value={String(transition.params.targetColor || 'black')}\n                options={colorOptions}\n                onChange={(v) =>\n                  updateTransition(transition.id, {\n                    params: { ...transition.params, targetColor: v },\n                  })\n                }\n              />\n            }\n          />\n        )}\n\n        <div className=\"grid grid-cols-2 gap-3\">\n          <PanelField\n            label={tt.builderEasing}\n            trailing={\n              <SelectDropdown\n                value={transition.easing}\n                options={easingOptions}\n                onChange={(v) =>\n                  updateTransition(transition.id, {\n                    easing: v as TransitionClip['easing'],\n                  })\n                }\n              />\n            }\n          />\n          <PanelField\n            label={tt.builderDirection}\n            trailing={\n              <Button\n                type=\"button\"\n                size=\"xs\"\n                variant={transition.reverse ? 'accent' : 'secondary'}\n                onClick={() =>\n                  updateTransition(transition.id, { reverse: !transition.reverse })\n                }\n              >\n                {transition.reverse ? tt.builderReversed : tt.builderForward}\n              </Button>\n            }\n          />\n        </div>\n\n        <div className=\"flex gap-2 pt-1\">\n          <Button\n            type=\"button\"\n            variant=\"danger\"\n            size=\"sm\"\n            className=\"flex-1\"\n            onClick={handleDelete}\n          >\n            {tt.builderDelete}\n          </Button>\n          <Button\n            type=\"button\"\n            variant=\"accent\"\n            size=\"sm\"\n            className=\"flex-1\"\n            onClick={onClose}\n          >\n            {tt.builderApply}\n          </Button>\n        </div>\n      </div>\n    </Modal>\n  );\n};\n\nexport default TransitionBuilder;\n", "import React, { useEffect, useMemo, useState } from 'react';\nimport {\n  Trash2,\n  ZoomIn,\n  ZoomOut,\n  RotateCcw,\n  Undo2,\n  Redo2,\n  ChevronDown,\n  ChevronUp,\n  Maximize2,\n  Minimize2,\n  Scissors,\n} from 'lucide-react';\nimport { useVideoStore, type Clip } from '../../store/useVideoStore';\nimport { Modal } from '../ui/Modal';\nimport { TextBody } from '../ui';\nimport { formatTimecode } from '../../utils/timelineUtils';\nimport { useTranslation } from '../../i18n';\n\n\nconst BASE_TRACK_HEIGHT = 60;\nconst TRACK_SCALE_MIN = 0.6;\nconst TRACK_SCALE_MAX = 1.6;\nconst TRACK_SCALE_STEP = 0.1;\nconst TRACK_SCALE_DEFAULT = 1;\n\nconst VIDEO_ZOOM_MIN = 2;\nconst VIDEO_ZOOM_MAX = 100;\nconst VIDEO_ZOOM_FACTOR = 1.2;\n\ninterface TimelineToolbarProps {\n  trackHeightScale: number;\n  setTrackHeightScale: (value: number) => void;\n  /** Resets wrapperHeight, trackControlsWidth AND trackHeightScale to defaults */\n  onResetLayout?: () => void;\n  isCollapsed?: boolean;\n  onToggleCollapsed?: () => void;\n  isFullscreen?: boolean;\n  onToggleFullscreen?: () => void;\n}\n\nconst clampScale = (value: number) =>\n  Math.max(TRACK_SCALE_MIN, Math.min(TRACK_SCALE_MAX, value));\n\nconst getClipDisplayName = (clip: Clip, fallbackName: string): string => {\n  if (clip.text) return clip.text.trim() || fallbackName;\n  return fallbackName;\n};\n\nexport const TimelineToolbar: React.FC<TimelineToolbarProps> = ({\n  trackHeightScale,\n  setTrackHeightScale,\n  onResetLayout,\n  isCollapsed = false,\n  onToggleCollapsed,\n  isFullscreen = false,\n  onToggleFullscreen,\n}) => {\n  const {\n    selectedClipIds,\n    tracks,\n    assets,\n    removeClip,\n    splitClip,\n    undo,\n    redo,\n    historyIndex,\n    history,\n    playheadTime,\n    zoom: videoZoom,\n    setZoom: setVideoZoom,\n  } = useVideoStore();\n  const t = useTranslation();\n  const tt = t.videoEditor.timelineToolbar;\n  const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);\n\n  const selectedClips = useMemo<Clip[]>(() => {\n    if (selectedClipIds.length === 0) return [];\n    const lookup = new Map<string, Clip>();\n    tracks.forEach((track) => {\n      track.clips.forEach((clip) => lookup.set(clip.id, clip));\n    });\n    return selectedClipIds\n      .map((id) => lookup.get(id))\n      .filter((clip): clip is Clip => Boolean(clip));\n  }, [selectedClipIds, tracks]);\n\n  const hasSelection = selectedClips.length > 0;\n  const trackHeight = Math.round(BASE_TRACK_HEIGHT * trackHeightScale);\n  const canUndo = historyIndex > 0;\n  const canRedo = historyIndex < history.length - 1;\n\n  const handleTrackZoomOut = () => {\n    setTrackHeightScale(\n      clampScale(Math.round((trackHeightScale - TRACK_SCALE_STEP) * 10) / 10),\n    );\n  };\n  const handleTrackZoomIn = () => {\n    setTrackHeightScale(\n      clampScale(Math.round((trackHeightScale + TRACK_SCALE_STEP) * 10) / 10),\n    );\n  };\n  const handleTrackSliderChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n    setTrackHeightScale(clampScale(parseFloat(e.target.value)));\n  };\n  const handleTrackReset = () => {\n    setTrackHeightScale(TRACK_SCALE_DEFAULT);\n    onResetLayout?.();\n  };\n\n  const handleVideoZoomIn = () =>\n    setVideoZoom(Math.min(VIDEO_ZOOM_MAX, videoZoom * VIDEO_ZOOM_FACTOR));\n  const handleVideoZoomOut = () =>\n    setVideoZoom(Math.max(VIDEO_ZOOM_MIN, videoZoom / VIDEO_ZOOM_FACTOR));\n  const handleVideoSliderChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n    setVideoZoom(parseFloat(e.target.value));\n  };\n\n  const handleDeleteConfirm = () => {\n    selectedClips.forEach((clip) => removeClip(clip.id));\n    setIsDeleteModalOpen(false);\n  };\n\n  useEffect(() => {\n    const onKeyDown = (e: KeyboardEvent) => {\n      const tag = (e.target as HTMLElement | null)?.tagName;\n      if (tag === 'INPUT' || tag === 'TEXTAREA' || (e.target as HTMLElement)?.isContentEditable) {\n        return;\n      }\n\n      const mod = e.metaKey || e.ctrlKey;\n      if (mod && e.key.toLowerCase() === 'z' && !e.shiftKey) {\n        e.preventDefault();\n        undo();\n        return;\n      }\n      if (mod && (e.key.toLowerCase() === 'y' || (e.key.toLowerCase() === 'z' && e.shiftKey))) {\n        e.preventDefault();\n        redo();\n        return;\n      }\n\n      if (e.key !== 'Delete' && e.key !== 'Backspace') return;\n      if (selectedClipIds.length === 0) return;\n      e.preventDefault();\n      setIsDeleteModalOpen(true);\n    };\n    window.addEventListener('keydown', onKeyDown);\n    return () => window.removeEventListener('keydown', onKeyDown);\n  }, [selectedClipIds.length, undo, redo]);\n\n  const buildDeleteMessage = (): string => {\n    if (selectedClips.length === 0) return '';\n    if (selectedClips.length === 1) {\n      const clip = selectedClips[0];\n      const asset = assets.find((a) => a.id === clip.assetId);\n      const name = getClipDisplayName(clip, asset?.name ?? tt.unnamedClip);\n      return tt.deleteOne(name);\n    }\n    const names = selectedClips\n      .map((clip) => {\n        const asset = assets.find((a) => a.id === clip.assetId);\n        return getClipDisplayName(clip, asset?.name ?? tt.unnamedClip);\n      })\n      .join('\", \"');\n    return tt.deleteMany(selectedClips.length, names);\n  };\n\n  const baseButtonClass =\n    'h-7 w-7 rounded-md flex items-center justify-center text-[var(--we-accent-soft)] hover:text-white hover:bg-[var(--we-accent-muted)] transition-colors';\n\n  const disabledButtonClass = `${baseButtonClass} opacity-40 cursor-not-allowed hover:bg-transparent hover:text-[var(--we-accent-soft)]`;\n\n  return (\n    <div className=\"bg-panel border-el border-panel-border h-9 px-3 py-1 flex items-center gap-1 select-none font-sans\">\n      {/* Time counter */}\n      <TextBody\n        as=\"span\"\n        size=\"sm\"\n        className=\"px-2 font-mono tabular-nums text-white\"\n        title={tt.currentTimeTitle(formatTimecode(playheadTime))}\n      >\n        {formatTimecode(playheadTime)}\n      </TextBody>\n\n      <div className=\"w-px h-5 bg-panel-border mx-1\" aria-hidden />\n\n      {/* Collapse / Fullscreen */}\n      {onToggleCollapsed && (\n        <button\n          type=\"button\"\n          onClick={onToggleCollapsed}\n          aria-label={isCollapsed ? tt.expandTimeline : tt.collapseTimeline}\n          aria-pressed={isCollapsed}\n          title={isCollapsed ? tt.expandTimeline : tt.collapseTimeline}\n          className={baseButtonClass}\n        >\n          {isCollapsed ? <ChevronUp size={14} /> : <ChevronDown size={14} />}\n        </button>\n      )}\n      {onToggleFullscreen && (\n        <button\n          type=\"button\"\n          onClick={onToggleFullscreen}\n          aria-label={isFullscreen ? tt.restoreSize : tt.expandFullscreen}\n          aria-pressed={isFullscreen}\n          title={isFullscreen ? tt.restoreSize : tt.expandFullscreen}\n          className={baseButtonClass}\n        >\n          {isFullscreen ? <Minimize2 size={14} /> : <Maximize2 size={14} />}\n        </button>\n      )}\n\n      <div className=\"w-px h-5 bg-panel-border mx-1\" aria-hidden />\n\n      {/* Undo / Redo */}\n      <button\n        type=\"button\"\n        onClick={undo}\n        disabled={!canUndo}\n        aria-label={tt.undo}\n        title={canUndo ? tt.undoTitle : tt.undoEmpty}\n        className={canUndo ? baseButtonClass : disabledButtonClass}\n      >\n        <Undo2 size={14} />\n      </button>\n      <button\n        type=\"button\"\n        onClick={redo}\n        disabled={!canRedo}\n        aria-label={tt.redo}\n        title={canRedo ? tt.redoTitle : tt.redoEmpty}\n        className={canRedo ? baseButtonClass : disabledButtonClass}\n      >\n        <Redo2 size={14} />\n      </button>\n\n      <div className=\"w-px h-5 bg-panel-border mx-1\" aria-hidden />\n\n      {/* Split */}\n      <button\n        type=\"button\"\n        onClick={() => {\n          if (!hasSelection) return;\n          selectedClips.forEach((clip) => splitClip(clip.id, playheadTime));\n        }}\n        disabled={!hasSelection}\n        aria-label={tt.split}\n        title={hasSelection ? tt.splitTitle : tt.splitDisabled}\n        className={hasSelection ? baseButtonClass : disabledButtonClass}\n      >\n        <Scissors size={14} />\n      </button>\n\n      <div className=\"w-px h-5 bg-panel-border mx-1\" aria-hidden />\n\n      {/* Trash */}\n      <button\n        type=\"button\"\n        onClick={() => hasSelection && setIsDeleteModalOpen(true)}\n        disabled={!hasSelection}\n        aria-label={tt.delete}\n        title={hasSelection ? tt.delete : tt.deleteDisabled}\n        className={\n          hasSelection\n            ? `${baseButtonClass} hover:bg-error/30 hover:text-error`\n            : disabledButtonClass\n        }\n      >\n        <Trash2 size={14} />\n      </button>\n\n      <div className=\"ml-auto flex items-center gap-1\">\n        {/* Video horizontal zoom (T-20260707-08: replaces the previous collapse /\n            fullscreen arrows. Controls the existing `zoom` (pixels/second) in\n            the store, which is the same dimension as Ctrl+wheel.) */}\n        <button\n          type=\"button\"\n          onClick={handleVideoZoomOut}\n          disabled={videoZoom <= VIDEO_ZOOM_MIN}\n          aria-label={tt.zoomOutVideo}\n          title={tt.zoomOutVideo}\n          className={\n            videoZoom <= VIDEO_ZOOM_MIN ? disabledButtonClass : baseButtonClass\n          }\n        >\n          <ZoomOut size={14} />\n        </button>\n        <input\n          type=\"range\"\n          min={VIDEO_ZOOM_MIN}\n          max={VIDEO_ZOOM_MAX}\n          step={1}\n          value={videoZoom}\n          onChange={handleVideoSliderChange}\n          aria-label={tt.zoomHorizontal}\n          title={tt.zoomHorizontalTitle(videoZoom.toFixed(0))}\n          className=\"w-24 h-1 bg-[var(--we-accent)] rounded-full appearance-none cursor-pointer accent-[var(--we-accent)] focus:outline-none\"\n        />\n        <TextBody as=\"span\" size=\"sm\" className=\"w-12 text-right tabular-nums text-[var(--we-accent-soft)]\">\n          {videoZoom.toFixed(0)}px/s\n        </TextBody>\n        <button\n          type=\"button\"\n          onClick={handleVideoZoomIn}\n          disabled={videoZoom >= VIDEO_ZOOM_MAX}\n          aria-label={tt.zoomInVideo}\n          title={tt.zoomInVideo}\n          className={\n            videoZoom >= VIDEO_ZOOM_MAX ? disabledButtonClass : baseButtonClass\n          }\n        >\n          <ZoomIn size={14} />\n        </button>\n\n        <div className=\"w-px h-5 bg-panel-border mx-1\" aria-hidden />\n\n        {/* Track height zoom \u2014 VERTICAL (alto de pista) */}\n        <button\n          type=\"button\"\n          onClick={handleTrackZoomOut}\n          disabled={trackHeightScale <= TRACK_SCALE_MIN}\n          aria-label={tt.zoomOutTracks}\n          title={tt.zoomOutTracks}\n          className={\n            trackHeightScale <= TRACK_SCALE_MIN ? disabledButtonClass : baseButtonClass\n          }\n        >\n          <ZoomOut size={14} />\n        </button>\n        <input\n          type=\"range\"\n          min={TRACK_SCALE_MIN}\n          max={TRACK_SCALE_MAX}\n          step={TRACK_SCALE_STEP}\n          value={trackHeightScale}\n          onChange={handleTrackSliderChange}\n          aria-label={tt.zoomVertical}\n          title={tt.zoomVerticalTitle(trackHeight)}\n          className=\"w-24 h-1 bg-[var(--we-accent)] rounded-full appearance-none cursor-pointer accent-[var(--we-accent)] focus:outline-none\"\n        />\n        <TextBody as=\"span\" size=\"sm\" className=\"w-10 text-right tabular-nums text-[var(--we-accent-soft)]\">\n          {trackHeight}px\n        </TextBody>\n        <button\n          type=\"button\"\n          onClick={handleTrackZoomIn}\n          disabled={trackHeightScale >= TRACK_SCALE_MAX}\n          aria-label={tt.zoomInTracks}\n          title={tt.zoomInTracks}\n          className={\n            trackHeightScale >= TRACK_SCALE_MAX ? disabledButtonClass : baseButtonClass\n          }\n        >\n          <ZoomIn size={14} />\n        </button>\n        <button\n          type=\"button\"\n          onClick={handleTrackReset}\n          aria-label={tt.resetTrackHeight}\n          title={tt.resetTrackHeight}\n          className={baseButtonClass}\n        >\n          <RotateCcw size={14} />\n        </button>\n      </div>\n\n      <Modal\n        isOpen={isDeleteModalOpen}\n        onClose={() => setIsDeleteModalOpen(false)}\n        title={tt.deleteTitle}\n        size=\"sm\"\n      >\n        <div className=\"space-y-4\">\n          <TextBody as=\"p\" size=\"md\" className=\"text-white\">\n            {buildDeleteMessage()}\n          </TextBody>\n          <div className=\"flex justify-end gap-2 pt-2\">\n            <button\n              type=\"button\"\n              onClick={() => setIsDeleteModalOpen(false)}\n              className=\"rounded border border-[var(--we-accent-stroke)] bg-[var(--we-accent-panel)] px-4 py-2 text-white transition-colors hover:bg-[var(--we-accent-hover)]\"\n            >\n              <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                {tt.cancel}\n              </TextBody>\n            </button>\n            <button\n              type=\"button\"\n              onClick={handleDeleteConfirm}\n              className=\"rounded bg-error px-4 py-2 text-[var(--we-accent-soft)] transition-colors hover:opacity-90\"\n            >\n              <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                {tt.confirmDelete}\n              </TextBody>\n            </button>\n          </div>\n        </div>\n      </Modal>\n    </div>\n  );\n};\n\nexport const TIMELINE_BASE_TRACK_HEIGHT = BASE_TRACK_HEIGHT;\n", "import React, { useState } from 'react';\nimport { Modal } from '../ui/Modal';\nimport { Download, Monitor, Smartphone, Grid, Sparkles, Loader } from 'lucide-react';\nimport { useVideoStore } from '../../store/useVideoStore';\nimport { exportVideo } from '../../services/ffmpegService';\nimport { useDialog } from '../../components/DialogModal';\nimport { useTranslation } from '../../i18n';\nimport { modeExportBasename, modeExportFilename } from '../../utils/exportDownloadName';\nimport { Button, Switch, TextBody, TextTitle } from '../ui';\n\n\ninterface ExportModalProps {\n  isOpen: boolean;\n  onClose: () => void;\n}\n\n\nexport const ExportModal: React.FC<ExportModalProps> = ({ isOpen, onClose }) => {\n  const t = useTranslation();\n  const tv = t.modal.videoExport;\n  const [format, setFormat] = useState<'mp4' | 'webm'>('mp4');\n  const [resolution, setResolution] = useState<'720p' | '1080p' | '4k'>('1080p');\n  const [aspectRatio, setAspectRatio] = useState<'16:9' | '9:16' | '1:1'>('16:9');\n  const [quality, setQuality] = useState<'low' | 'medium' | 'high' | 'lossless'>('high');\n  const [frameRate, setFrameRate] = useState<24 | 30 | 60>(30);\n  const [multiFormat, setMultiFormat] = useState(false);\n  \n  const dialog = useDialog();\n  const { tracks, assets } = useVideoStore();\n  \n  const [isExporting, setIsExporting] = useState(false);\n  const [progress, setProgress] = useState(0);\n  const [exportStep, setExportStep] = useState('');\n\n  const handleStartExport = async () => {\n    setIsExporting(true);\n    setProgress(0);\n\n    // If there are no assets loaded, fallback to mock simulation so the UI can still be previewed\n    const hasMedia = tracks.some(t => t.clips.length > 0);\n    if (!hasMedia) {\n      setExportStep(tv.demoExport);\n      let currentProgress = 0;\n      const interval = setInterval(() => {\n        currentProgress += 5;\n        setProgress(currentProgress);\n        if (currentProgress >= 100) {\n          clearInterval(interval);\n          setIsExporting(false);\n          triggerSimulatedDownloads(multiFormat ? 3 : 1);\n        }\n      }, 100);\n      return;\n    }\n\n    try {\n      // Calculate active timeline duration\n      let maxDuration = 10; // default minimum\n      tracks.forEach(track => {\n        track.clips.forEach(clip => {\n          const end = clip.startTime + clip.duration;\n          if (end > maxDuration) maxDuration = end;\n        });\n      });\n\n      setExportStep(tv.initCompiler);\n      const finalBlob = await exportVideo(\n        tracks,\n        assets,\n        maxDuration,\n        resolution,\n        frameRate,\n        (prog, step) => {\n          setProgress(prog);\n          setExportStep(step);\n        }\n      );\n\n      // Trigger download of the actual compiled file\n      const downloadUrl = URL.createObjectURL(finalBlob);\n      const a = document.createElement('a');\n      a.href = downloadUrl;\n      a.download = modeExportFilename('video', format === 'webm' ? 'webm' : 'mp4');\n      document.body.appendChild(a);\n      a.click();\n      document.body.removeChild(a);\n      URL.revokeObjectURL(downloadUrl);\n      setIsExporting(false);\n    } catch (err: any) {\n      console.error(err);\n      dialog.alert(`Error al exportar: ${err.message || t.store.toasts.editor.exportUnknownError}`, { title: t.store.toasts.editor.exportErrorTitle, variant: 'error' });\n      setIsExporting(false);\n    }\n  };\n\n  const triggerSimulatedDownloads = (count: number) => {\n    // Generate empty mock text files to trigger browser downloads\n    for (let i = 0; i < count; i++) {\n      const ext = format === 'mp4' ? 'mp4' : 'webm';\n      let name = modeExportBasename('video');\n      if (count === 3) {\n        const formats = ['16_9_youtube', '9_16_tiktok_cropped', '1_1_feed_cropped'];\n        name += `_${formats[i]}`;\n      } else {\n        name += `_${aspectRatio.replace(':', '_')}`;\n      }\n\n      const blob = new Blob([`Mock video file export data for: ${name}`], { type: 'video/mp4' });\n      const downloadUrl = URL.createObjectURL(blob);\n      const a = document.createElement('a');\n      a.href = downloadUrl;\n      a.download = `${name}.${ext}`;\n      document.body.appendChild(a);\n      a.click();\n      document.body.removeChild(a);\n      URL.revokeObjectURL(downloadUrl);\n    }\n  };\n\n  return (\n    <Modal isOpen={isOpen} onClose={onClose} title={tv.title} size=\"xl\">\n      <div className=\"grid grid-cols-1 lg:grid-cols-5 gap-6\">\n        \n        {/* Left Side: Export Parameters (Columns 1-3) */}\n        <div className=\"lg:col-span-3 space-y-5\">\n          {isExporting ? (\n            <div className=\"h-64 flex flex-col justify-center items-center text-center space-y-4\">\n              <Loader size={36} className=\"text-[var(--we-accent)] animate-spin\" />\n              <div className=\"space-y-1\">\n                <TextBody as=\"span\" size=\"md\" className=\"font-semibold text-[#F0F0F5]\">{exportStep}</TextBody>\n                <TextBody as=\"span\" size=\"sm\" className=\"block text-[#8888A0]\">{tv.doNotClose}</TextBody>\n              </div>\n              <div className=\"w-full max-w-sm bg-[#1C1C26] rounded-full h-2 overflow-hidden border border-[#2A2A38]\">\n                <div \n                  className=\"bg-gradient-to-r from-[var(--we-accent)] to-[#00E676] h-full rounded-full transition-all duration-300\"\n                  style={{ width: `${progress}%` }}\n                />\n              </div>\n              <TextBody as=\"span\" size=\"sm\" className=\"font-mono font-bold text-[#F0F0F5]\">{progress}%</TextBody>\n            </div>\n          ) : (\n            <>\n              {/* Format selection */}\n              <div className=\"space-y-2\">\n                <TextBody as=\"label\" size=\"sm\" className=\"text-[#8888A0] uppercase tracking-wider block\">\n                  {tv.exportFormat}\n                </TextBody>\n                <div className=\"grid grid-cols-2 gap-2\">\n                  <button\n                    onClick={() => setFormat('mp4')}\n                    className={`px-4 py-2 text-xs font-medium rounded border transition-all ${\n                      format === 'mp4'\n                        ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)] text-white'\n                        : 'border-[#2A2A38] bg-[#0A0A0F] text-[#8888A0] hover:text-white'\n                    }`}\n                  >\n                    MP4 (H.264 / AAC)\n                  </button>\n                  <button\n                    onClick={() => setFormat('webm')}\n                    className={`px-4 py-2 text-xs font-medium rounded border transition-all ${\n                      format === 'webm'\n                        ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)] text-white'\n                        : 'border-[#2A2A38] bg-[#0A0A0F] text-[#8888A0] hover:text-white'\n                    }`}\n                  >\n                    WebM (VP9 / Opus)\n                  </button>\n                </div>\n              </div>\n\n              {/* Multi-Format Switch */}\n              <div className=\"flex items-center justify-between bg-black-capsule border border-panel-border p-3 rounded-xl\">\n                <div className=\"flex items-center gap-2.5\">\n                  <div className=\"p-1.5 bg-[var(--we-accent-muted)] text-[var(--we-accent)] rounded-lg\">\n                    <Sparkles size={16} />\n                  </div>\n                  <div>\n                    <TextBody as=\"span\" size=\"sm\" className=\"block font-bold text-white\">\n                      {tv.multiFormat}\n                    </TextBody>\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                      {tv.multiFormatHint}\n                    </TextBody>\n                  </div>\n                </div>\n                <Switch\n                  checked={multiFormat}\n                  onChange={setMultiFormat}\n                  ariaLabel={tv.multiFormat}\n                />\n              </div>\n\n              {/* Single Aspect Selection (Hide if Multi-Format is enabled) */}\n              {!multiFormat && (\n                <div className=\"space-y-2\">\n                  <TextBody as=\"label\" size=\"sm\" className=\"text-[#8888A0] uppercase tracking-wider block\">\n                    {tv.aspectRatio}\n                  </TextBody>\n                  <div className=\"grid grid-cols-3 gap-2\">\n                    <button\n                      onClick={() => setAspectRatio('16:9')}\n                      className={`flex items-center justify-center gap-1.5 py-1.5 text-[11px] font-medium rounded border transition-all ${\n                        aspectRatio === '16:9'\n                          ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)] text-white'\n                          : 'border-[#2A2A38] bg-[#0A0A0F] text-[#8888A0] hover:text-white'\n                      }`}\n                    >\n                      <Monitor size={12} />\n                      {tv.landscape}\n                    </button>\n                    <button\n                      onClick={() => setAspectRatio('9:16')}\n                      className={`flex items-center justify-center gap-1.5 py-1.5 text-[11px] font-medium rounded border transition-all ${\n                        aspectRatio === '9:16'\n                          ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)] text-white'\n                          : 'border-[#2A2A38] bg-[#0A0A0F] text-[#8888A0] hover:text-white'\n                      }`}\n                    >\n                      <Smartphone size={12} />\n                      {tv.portrait}\n                    </button>\n                    <button\n                      onClick={() => setAspectRatio('1:1')}\n                      className={`flex items-center justify-center gap-1.5 py-1.5 text-[11px] font-medium rounded border transition-all ${\n                        aspectRatio === '1:1'\n                          ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)] text-white'\n                          : 'border-[#2A2A38] bg-[#0A0A0F] text-[#8888A0] hover:text-white'\n                      }`}\n                    >\n                      <Grid size={12} />\n                      {tv.square}\n                    </button>\n                  </div>\n                </div>\n              )}\n\n              {/* Grid selectors for resolution and frame rate */}\n              <div className=\"grid grid-cols-2 gap-4\">\n                <div className=\"space-y-2\">\n                  <TextBody as=\"label\" size=\"sm\" className=\"text-[#8888A0] uppercase tracking-wider block\">\n                    {tv.resolution}\n                  </TextBody>\n                  <select\n                    value={resolution}\n                    onChange={(e) => setResolution(e.target.value as any)}\n                    className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded px-3 py-2 text-xs text-[#F0F0F5]\"\n                  >\n                    <option value=\"720p\">720p (HD)</option>\n                    <option value=\"1080p\">1080p (Full HD)</option>\n                    <option value=\"4k\">4K (Ultra HD)</option>\n                  </select>\n                </div>\n                <div className=\"space-y-2\">\n                  <TextBody as=\"label\" size=\"sm\" className=\"text-[#8888A0] uppercase tracking-wider block\">\n                    {tv.frameRate}\n                  </TextBody>\n                  <select\n                    value={frameRate}\n                    onChange={(e) => setFrameRate(Number(e.target.value) as any)}\n                    className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded px-3 py-2 text-xs text-[#F0F0F5]\"\n                  >\n                    <option value=\"24\">24 fps (Cinema)</option>\n                    <option value=\"30\">30 fps (Broadcast)</option>\n                    <option value=\"60\">60 fps (Smooth)</option>\n                  </select>\n                </div>\n              </div>\n\n              {/* Quality Preset Selection */}\n              <div className=\"space-y-2\">\n                <TextBody as=\"label\" size=\"sm\" className=\"text-[#8888A0] uppercase tracking-wider block\">\n                  {tv.bitrate}\n                </TextBody>\n                <div className=\"grid grid-cols-4 gap-2\">\n                  {(['low', 'medium', 'high', 'lossless'] as const).map((q) => (\n                    <button\n                      key={q}\n                      onClick={() => setQuality(q)}\n                      className={`py-1.5 text-[10px] font-semibold rounded border uppercase tracking-wider transition-all ${\n                        quality === q\n                          ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)] text-white'\n                          : 'border-[#2A2A38] bg-[#0A0A0F] text-[#8888A0] hover:text-white'\n                      }`}\n                    >\n                      {q}\n                    </button>\n                  ))}\n                </div>\n              </div>\n\n              {/* Buttons footer */}\n              <div className=\"flex gap-3 pt-3 border-t border-panel-border\">\n                <Button variant=\"ghost\" onClick={onClose} className=\"w-1/2\">\n                  {tv.cancel}\n                </Button>\n                <Button\n                  variant=\"accent\"\n                  onClick={handleStartExport}\n                  icon={<Download size={14} />}\n                  className=\"w-1/2\"\n                >\n                  {tv.startExport}\n                </Button>\n              </div>\n            </>\n          )}\n        </div>\n\n        {/* Right Side: Aspect Ratio Previews (Columns 4-5) */}\n        <div className=\"lg:col-span-2 border-t lg:border-t-0 lg:border-l border-[#2A2A38] pt-6 lg:pt-0 lg:pl-6 flex flex-col justify-between\">\n          <div className=\"space-y-3\">\n            <TextBody as=\"span\" size=\"sm\" className=\"text-[#8888A0] uppercase tracking-wider block\">\n              {tv.outputPreviews}\n            </TextBody>\n\n            {multiFormat ? (\n              // 3 Simultaneous layout boxes\n              <div className=\"space-y-3.5\">\n                {/* 16:9 */}\n                <div className=\"bg-[#0A0A0F] border border-[#2A2A38] rounded p-2 flex items-center justify-between\">\n                  <div className=\"flex items-center gap-2\">\n                    <Monitor size={14} className=\"text-[var(--we-accent)]\" />\n                    <TextBody as=\"span\" size=\"sm\" className=\"font-semibold text-[#F0F0F5]\">16:9 YouTube</TextBody>\n                  </div>\n                  <div className=\"w-16 h-9 bg-[#1C1C26] rounded border border-[#2A2A38] flex items-center justify-center text-[9px] font-mono text-[#8888A0]\">\n                    {tv.fit}\n                  </div>\n                </div>\n\n                {/* 9:16 */}\n                <div className=\"bg-[#0A0A0F] border border-[#2A2A38] rounded p-2 flex items-center justify-between relative overflow-hidden\">\n                  {/* Neon scan glowing overlay to simulate active tracking */}\n                  <div className=\"absolute inset-0 bg-[var(--we-accent-muted)] animate-pulse\" />\n                  <div className=\"flex items-center gap-2 z-10\">\n                    <Smartphone size={14} className=\"text-[#00E676]\" />\n                    <div className=\"flex flex-col\">\n                      <TextBody as=\"span\" size=\"sm\" className=\"flex items-center gap-1 font-semibold text-[#F0F0F5]\">\n                        9:16 TikTok\n                        <TextBody as=\"span\" size=\"sm\" className=\"rounded bg-[#00E676]/10 px-1 text-[#00E676]\">{tv.faceTrack}</TextBody>\n                      </TextBody>\n                    </div>\n                  </div>\n                  <div className=\"w-8 h-12 bg-[#1C1C26] rounded border border-[#2A2A38] flex items-center justify-center text-[9px] font-mono text-[#8888A0] z-10 relative overflow-hidden\">\n                    {/* Face tracking marker */}\n                    <div className=\"absolute w-4 h-4 rounded-full border border-dashed border-[#00E676] animate-ping opacity-60\" />\n                    {tv.crop}\n                  </div>\n                </div>\n\n                {/* 1:1 */}\n                <div className=\"bg-[#0A0A0F] border border-[#2A2A38] rounded p-2 flex items-center justify-between\">\n                  <div className=\"flex items-center gap-2\">\n                    <Grid size={14} className=\"text-[#FF4081]\" />\n                    <TextBody as=\"span\" size=\"sm\" className=\"flex items-center gap-1 font-semibold text-[#F0F0F5]\">\n                      1:1 Instagram\n                      <TextBody as=\"span\" size=\"sm\" className=\"rounded bg-[#FF4081]/10 px-1 text-[#FF4081]\">{tv.faceTrack}</TextBody>\n                    </TextBody>\n                  </div>\n                  <div className=\"w-10 h-10 bg-[#1C1C26] rounded border border-[#2A2A38] flex items-center justify-center text-[9px] font-mono text-[#8888A0]\">\n                    {tv.crop}\n                  </div>\n                </div>\n              </div>\n            ) : (\n              // Single Layout visualizer\n              <div className=\"bg-[#0A0A0F] border border-[#2A2A38] rounded-lg p-4 flex flex-col items-center justify-center h-48 select-none\">\n                {aspectRatio === '16:9' && (\n                  <div className=\"w-full max-w-[200px] aspect-video bg-[#1C1C26] rounded border border-[#2A2A38] flex flex-col items-center justify-center text-xs font-mono text-[#8888A0] gap-1\">\n                    <Monitor size={20} />\n                    <span>{tv.landscape}</span>\n                  </div>\n                )}\n                {aspectRatio === '9:16' && (\n                  <div className=\"h-full max-h-[170px] aspect-[9/16] bg-[#1C1C26] rounded border border-[#2A2A38] flex flex-col items-center justify-center text-xs font-mono text-[#8888A0] gap-1\">\n                    <Smartphone size={20} />\n                    <span>{tv.portrait}</span>\n                  </div>\n                )}\n                {aspectRatio === '1:1' && (\n                  <div className=\"w-36 h-36 bg-[#1C1C26] rounded border border-[#2A2A38] flex flex-col items-center justify-center text-xs font-mono text-[#8888A0] gap-1\">\n                    <Grid size={20} />\n                    <span>{tv.square}</span>\n                  </div>\n                )}\n              </div>\n            )}\n          </div>\n\n          <div className=\"mt-4 text-[10px] text-[#8888A0] bg-[#0A0A0F]/50 border border-[#2A2A38]/30 rounded p-2.5\">\n            <strong>FFmpeg WASM Renderer:</strong> This processes frames inside a browser Web Worker. Output resolution and frame rate determine rendering speed.\n          </div>\n        </div>\n        \n      </div>\n    </Modal>\n  );\n};\n", "import React, { useState } from 'react';\nimport { Copy, Check, Flame, Loader2, MessageSquare, Plus, Sparkles } from 'lucide-react';\nimport { Modal } from '../ui/Modal';\nimport { Button } from '../ui/Button';\nimport { TextBody } from '../ui';\nimport { useVideoStore } from '../../store/useVideoStore';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { generateMarketingAssistant, type MarketingContent } from '../../services/aiService';\nimport { useTranslation } from '../../i18n';\n\ninterface AiContentModalProps {\n  isOpen: boolean;\n  onClose: () => void;\n}\n\ntype TabType = 'titles' | 'hooks' | 'copy';\n\nfunction ensureTextTrack(fallbackName: string): string {\n  const state = useVideoStore.getState();\n  let track = state.tracks.find((tr) => tr.type === 'text');\n  if (!track) {\n    state.addTrack(fallbackName, 'text');\n    track = useVideoStore.getState().tracks.find((tr) => tr.type === 'text');\n  }\n  return track?.id ?? 't1';\n}\n\nfunction estimateTextDuration(text: string, kind: TabType): number {\n  if (kind === 'titles') return 3;\n  if (kind === 'hooks') return 3.5;\n  const chars = text.trim().length;\n  return Math.max(5, Math.min(24, Math.round(chars * 0.05)));\n}\n\nexport const AiContentModal: React.FC<AiContentModalProps> = ({ isOpen, onClose }) => {\n  const t = useTranslation();\n  const tm = t.videoEditor.aiTools.marketing;\n  const addToast = useEditorStore((s) => s.addToast);\n  const { tracks } = useVideoStore();\n  const [activeTab, setActiveTab] = useState<TabType>('titles');\n  const [isAnalyzing, setIsAnalyzing] = useState(false);\n  const [content, setContent] = useState<MarketingContent | null>(null);\n  const [error, setError] = useState<string | null>(null);\n  const [copiedId, setCopiedId] = useState<string | null>(null);\n  const [addedId, setAddedId] = useState<string | null>(null);\n\n  const compileTranscript = (): string => {\n    const texts: { start: number; text: string }[] = [];\n    tracks.forEach((track) => {\n      track.clips.forEach((clip) => {\n        if ((clip.type === 'subtitle' || clip.type === 'text') && clip.text) {\n          texts.push({ start: clip.startTime, text: clip.text });\n        }\n      });\n    });\n    if (texts.length === 0) return '';\n    texts.sort((a, b) => a.start - b.start);\n    return texts.map((item) => item.text).join(' ');\n  };\n\n  const transcriptText = compileTranscript();\n  const wordCount = transcriptText.split(/\\s+/).filter(Boolean).length;\n\n  const handleAnalyze = async () => {\n    if (!transcriptText) return;\n    setIsAnalyzing(true);\n    setError(null);\n    setContent(null);\n    try {\n      const data = await generateMarketingAssistant(transcriptText);\n      const empty =\n        (!data.titles || data.titles.length === 0) &&\n        (!data.hooks || data.hooks.length === 0) &&\n        !data.copy;\n      if (empty) {\n        setError(tm.emptyResult);\n        setContent(null);\n        return;\n      }\n      setContent(data);\n    } catch (err: unknown) {\n      console.error(err);\n      setError(\n        err instanceof Error\n          ? err.message\n          : t.store.toasts.editor.transcriptAnalysisError,\n      );\n    } finally {\n      setIsAnalyzing(false);\n    }\n  };\n\n  const handleCopy = (text: string, id: string) => {\n    void navigator.clipboard.writeText(text);\n    setCopiedId(id);\n    window.setTimeout(() => setCopiedId(null), 2000);\n  };\n\n  const handleAddToTimeline = (text: string, kind: TabType, id: string) => {\n    const trimmed = text.trim();\n    if (!trimmed) return;\n\n    const store = useVideoStore.getState();\n    const trackId = ensureTextTrack('Text AI');\n    const duration = estimateTextDuration(trimmed, kind);\n    const startTime = store.playheadTime;\n\n    store.addTextClip({\n      trackId,\n      assetId: '',\n      startTime,\n      duration,\n      trimIn: 0,\n      trimOut: 0,\n      speed: 1,\n      volume: 1,\n      opacity: 1,\n      muted: false,\n      name: trimmed.slice(0, 32),\n      text: trimmed,\n    });\n\n    // Advance playhead so the next insert lands after this clip.\n    store.setPlayhead(startTime + duration);\n\n    setAddedId(id);\n    window.setTimeout(() => setAddedId(null), 1600);\n    addToast(tm.toastAdded, 'success');\n  };\n\n  const tabs: { id: TabType; label: string; icon: React.ReactNode }[] = [\n    { id: 'titles', label: tm.tabTitles, icon: <Flame size={14} /> },\n    { id: 'hooks', label: tm.tabHooks, icon: <Sparkles size={14} /> },\n    { id: 'copy', label: tm.tabCopy, icon: <MessageSquare size={14} /> },\n  ];\n\n  return (\n    <Modal isOpen={isOpen} onClose={onClose} title={tm.title} size=\"lg\">\n      <div className=\"space-y-4\">\n        <TextBody as=\"p\" size=\"sm\" className=\"leading-relaxed text-white/80\">\n          {tm.intro}\n        </TextBody>\n        <div className=\"space-y-1.5 rounded-lg border border-panel-border bg-black-capsule/60 p-3\">\n          <div className=\"flex items-center justify-between\">\n            <TextBody as=\"span\" size=\"sm\" className=\"font-semibold uppercase tracking-wider text-white/80\">\n              {tm.scriptLabel}\n            </TextBody>\n            <TextBody as=\"span\" size=\"sm\" className=\"font-mono lowercase text-[var(--we-accent)]\">\n              {wordCount} {tm.words}\n            </TextBody>\n          </div>\n          {transcriptText ? (\n            <TextBody\n              as=\"p\"\n              size=\"sm\"\n              className=\"max-h-24 overflow-y-auto rounded border border-panel-border bg-black/20 p-2 italic leading-relaxed text-white/80\"\n            >\n              {transcriptText}\n            </TextBody>\n          ) : (\n            <TextBody as=\"p\" size=\"sm\" className=\"py-2 text-white/80\">\n              {tm.emptyScript}\n            </TextBody>\n          )}\n        </div>\n\n        {transcriptText && (\n          <div className=\"flex justify-center py-1\">\n            <Button\n              onClick={() => void handleAnalyze()}\n              disabled={isAnalyzing}\n              className=\"bg-[var(--we-accent)] px-6 font-semibold text-white hover:bg-[var(--we-accent-hover)] disabled:opacity-50\"\n            >\n              {isAnalyzing ? (\n                <>\n                  <Loader2 size={16} className=\"animate-spin\" />\n                  <TextBody as=\"span\" size=\"sm\" className=\"ml-1.5\">\n                    {tm.analyzing}\n                  </TextBody>\n                </>\n              ) : (\n                <>\n                  <Sparkles size={16} />\n                  <TextBody as=\"span\" size=\"sm\" className=\"ml-1.5\">\n                    {content ? tm.reanalyze : tm.analyze}\n                  </TextBody>\n                </>\n              )}\n            </Button>\n          </div>\n        )}\n\n        {error && (\n          <TextBody\n            as=\"p\"\n            size=\"sm\"\n            className=\"rounded-lg border border-red-900/40 bg-red-950/40 p-3 text-red-200\"\n          >\n            {error}\n          </TextBody>\n        )}\n\n        {content && (\n          <div className=\"flex min-h-[280px] flex-col overflow-hidden rounded-lg border border-panel-border bg-panel\">\n            <div className=\"flex border-b border-panel-border bg-black-capsule\">\n              {tabs.map((tab) => (\n                <button\n                  key={tab.id}\n                  type=\"button\"\n                  onClick={() => setActiveTab(tab.id)}\n                  className={`flex flex-1 items-center justify-center gap-1.5 py-3 transition-colors ${\n                    activeTab === tab.id\n                      ? 'border-b-2 border-[var(--we-accent)] bg-panel text-[var(--we-accent)]'\n                      : 'text-white/80 hover:text-white'\n                  }`}\n                >\n                  {tab.icon}\n                  <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                    {tab.label}\n                  </TextBody>\n                </button>\n              ))}\n            </div>\n\n            <div className=\"flex-1 p-4\">\n              {activeTab === 'titles' && (\n                <div className=\"space-y-3\">\n                  <TextBody as=\"span\" size=\"sm\" className=\"block font-semibold uppercase text-white/80\">\n                    {tm.titlesHint}\n                  </TextBody>\n                  {(content.titles ?? []).map((title, idx) => {\n                    const id = `title-${idx}`;\n                    return (\n                      <div\n                        key={id}\n                        className=\"flex items-center justify-between gap-3 rounded-lg border border-panel-border bg-black-capsule p-2.5 transition-colors hover:border-[var(--we-accent)]/50\"\n                      >\n                        <TextBody as=\"span\" size=\"sm\" className=\"leading-normal text-white\">\n                          {title}\n                        </TextBody>\n                        <div className=\"flex shrink-0 items-center gap-1\">\n                          <button\n                            type=\"button\"\n                            onClick={() => handleCopy(title, id)}\n                            className=\"rounded p-1.5 text-white/80 transition-colors hover:bg-panel hover:text-white\"\n                            title={tm.copyItem}\n                          >\n                            {copiedId === id ? (\n                              <Check size={14} className=\"text-emerald-400\" />\n                            ) : (\n                              <Copy size={14} />\n                            )}\n                          </button>\n                          <button\n                            type=\"button\"\n                            onClick={() => handleAddToTimeline(title, 'titles', id)}\n                            className=\"inline-flex items-center gap-1 rounded-lg bg-[var(--we-accent-muted)] px-2 py-1 text-[var(--we-accent)] transition-colors hover:bg-[var(--we-accent)] hover:text-white\"\n                            title={tm.addToTimeline}\n                          >\n                            {addedId === id ? <Check size={12} /> : <Plus size={12} />}\n                            <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                              {tm.addToTimeline}\n                            </TextBody>\n                          </button>\n                        </div>\n                      </div>\n                    );\n                  })}\n                </div>\n              )}\n\n              {activeTab === 'hooks' && (\n                <div className=\"space-y-3\">\n                  <TextBody as=\"span\" size=\"sm\" className=\"block font-semibold uppercase text-white/80\">\n                    {tm.hooksHint}\n                  </TextBody>\n                  {(content.hooks ?? []).map((hook, idx) => {\n                    const id = `hook-${idx}`;\n                    return (\n                      <div\n                        key={id}\n                        className=\"flex items-center justify-between gap-3 rounded-lg border border-panel-border bg-black-capsule p-2.5 transition-colors hover:border-[var(--we-accent)]/50\"\n                      >\n                        <TextBody as=\"span\" size=\"sm\" className=\"italic leading-normal text-white\">\n                          {hook}\n                        </TextBody>\n                        <div className=\"flex shrink-0 items-center gap-1\">\n                          <button\n                            type=\"button\"\n                            onClick={() => handleCopy(hook, id)}\n                            className=\"rounded p-1.5 text-white/80 transition-colors hover:bg-panel hover:text-white\"\n                            title={tm.copyItem}\n                          >\n                            {copiedId === id ? (\n                              <Check size={14} className=\"text-emerald-400\" />\n                            ) : (\n                              <Copy size={14} />\n                            )}\n                          </button>\n                          <button\n                            type=\"button\"\n                            onClick={() => handleAddToTimeline(hook, 'hooks', id)}\n                            className=\"inline-flex items-center gap-1 rounded-lg bg-[var(--we-accent-muted)] px-2 py-1 text-[var(--we-accent)] transition-colors hover:bg-[var(--we-accent)] hover:text-white\"\n                            title={tm.addToTimeline}\n                          >\n                            {addedId === id ? <Check size={12} /> : <Plus size={12} />}\n                            <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                              {tm.addToTimeline}\n                            </TextBody>\n                          </button>\n                        </div>\n                      </div>\n                    );\n                  })}\n                </div>\n              )}\n\n              {activeTab === 'copy' && content.copy && (\n                <div className=\"space-y-3\">\n                  <div className=\"flex items-center justify-between gap-2\">\n                    <TextBody as=\"span\" size=\"sm\" className=\"font-semibold uppercase text-white/80\">\n                      {tm.copyHint}\n                    </TextBody>\n                    <div className=\"flex items-center gap-2\">\n                      <button\n                        type=\"button\"\n                        onClick={() => handleCopy(content.copy, 'main-copy')}\n                        className=\"inline-flex items-center gap-1 text-[var(--we-accent)] hover:opacity-90\"\n                      >\n                        {copiedId === 'main-copy' ? (\n                          <>\n                            <Check size={12} className=\"text-emerald-400\" />\n                            <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                              {tm.copied}\n                            </TextBody>\n                          </>\n                        ) : (\n                          <>\n                            <Copy size={12} />\n                            <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                              {tm.copyAll}\n                            </TextBody>\n                          </>\n                        )}\n                      </button>\n                      <Button\n                        onClick={() => handleAddToTimeline(content.copy, 'copy', 'main-copy')}\n                        className=\"bg-[var(--we-accent)] text-white hover:bg-[var(--we-accent-hover)]\"\n                      >\n                        {addedId === 'main-copy' ? <Check size={14} /> : <Plus size={14} />}\n                        <TextBody as=\"span\" size=\"sm\" className=\"ml-1.5\">\n                          {tm.addCopyToTimeline}\n                        </TextBody>\n                      </Button>\n                    </div>\n                  </div>\n                  <textarea\n                    readOnly\n                    value={content.copy}\n                    className=\"h-40 w-full resize-none rounded-lg border border-panel-border bg-black-capsule p-3 font-sans text-xs font-medium leading-relaxed text-white focus:outline-none\"\n                  />\n                </div>\n              )}\n            </div>\n          </div>\n        )}\n      </div>\n    </Modal>\n  );\n};\n", "import React, { useEffect, useMemo, useRef, useState } from 'react';\nimport {\n  Captions,\n  Languages,\n  Loader2,\n  Search,\n  Sparkles,\n  Wand2,\n} from 'lucide-react';\nimport { Modal } from '../ui/Modal';\nimport { Button, PanelField, SelectDropdown, TextBody, TextTitle } from '../ui';\nimport { useTranslation } from '../../i18n';\nimport { useVideoStore, type Asset, type Clip } from '../../store/useVideoStore';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport type { VideoAiToolId } from '../../store/useVideoUiStore';\nimport {\n  generateColorGradingPreset,\n  generateCopy,\n  generateCopywritingSuggestions,\n  generateImageDesignPreset,\n  generateSubtitleStylePreset,\n  generateVideoProperties,\n  searchStock,\n  translateSubtitles,\n  transcribeAudio,\n  type StockPhoto,\n} from '../../services/aiService';\nimport { downloadStockPhoto } from '../../services/stockService';\nimport { mapDesignPresetToClipPatch } from '../../utils/videoAiPresetMap';\nimport { applyVideoEditPlan } from '../../utils/videoEditPlan';\nimport { toUserFacingError } from '../../utils/userFacingError';\nimport { AiVoiceoverModal } from './AiVoiceoverModal';\nimport { AiContentModal } from './AiContentModal';\n\n\nexport type { VideoAiToolId } from '../../store/useVideoUiStore';\n\nexport interface VideoAiGenerateModalProps {\n  tool: VideoAiToolId | null;\n  onClose: () => void;\n}\n\nconst LANGS = [\n  { value: 'English', labelKey: 'langEnglish' as const },\n  { value: 'Spanish', labelKey: 'langSpanish' as const },\n  { value: 'French', labelKey: 'langFrench' as const },\n  { value: 'Portuguese', labelKey: 'langPortuguese' as const },\n  { value: 'German', labelKey: 'langGerman' as const },\n  { value: 'Italian', labelKey: 'langItalian' as const },\n];\n\nfunction ensureTrack(type: 'text' | 'image' | 'subtitle', fallbackName: string): string {\n  const state = useVideoStore.getState();\n  const trackType = type === 'subtitle' ? 'text' : type;\n  if (type === 'subtitle') {\n    const sub = state.tracks.find((tr) => tr.type === 'subtitle');\n    if (sub) return sub.id;\n  }\n  let track = state.tracks.find((tr) => tr.type === trackType);\n  if (!track) {\n    state.addTrack(fallbackName, trackType === 'text' ? 'text' : trackType);\n    track = useVideoStore.getState().tracks.find((tr) => tr.type === trackType);\n  }\n  return track?.id ?? (type === 'image' ? 'i1' : 't1');\n}\n\nfunction pickSelectedClip(): Clip | null {\n  const { tracks, selectedClipIds } = useVideoStore.getState();\n  for (const tr of tracks) {\n    const found = tr.clips.find((c) => selectedClipIds.includes(c.id));\n    if (found) return found;\n  }\n  return null;\n}\n\nfunction readImageSize(url: string): Promise<{ width: number; height: number }> {\n  return new Promise((resolve) => {\n    const img = new window.Image();\n    img.onload = () =>\n      resolve({ width: img.naturalWidth || 1024, height: img.naturalHeight || 1024 });\n    img.onerror = () => resolve({ width: 1024, height: 1024 });\n    img.src = url;\n  });\n}\n\nexport const VideoAiGenerateModal: React.FC<VideoAiGenerateModalProps> = ({\n  tool,\n  onClose,\n}) => {\n  const t = useTranslation();\n  const tm = t.videoEditor.aiTools.modal;\n  const addToast = useEditorStore((s) => s.addToast);\n  const {\n    tracks,\n    playheadTime,\n    addAsset,\n    addImageClip,\n  } = useVideoStore();\n\n  const [prompt, setPrompt] = useState('');\n  const [targetLang, setTargetLang] = useState('English');\n  const [clipId, setClipId] = useState('');\n  const [stockQuery, setStockQuery] = useState('');\n  const [stockPhotos, setStockPhotos] = useState<StockPhoto[]>([]);\n  const [suggestions, setSuggestions] = useState<{\n    comercial: string;\n    creativa: string;\n    directa: string;\n  } | null>(null);\n  const [isBusy, setIsBusy] = useState(false);\n  const [statusLabel, setStatusLabel] = useState('');\n  const [error, setError] = useState<string | null>(null);\n  const abortRef = useRef<AbortController | null>(null);\n\n  const mediaClips = useMemo(() => {\n    const out: { id: string; label: string; assetId?: string }[] = [];\n    for (const tr of tracks) {\n      for (const c of tr.clips) {\n        if (c.type === 'video' || c.type === 'audio') {\n          out.push({\n            id: c.id,\n            label: `${c.name || c.type} \u00B7 ${c.startTime.toFixed(1)}s`,\n            assetId: c.assetId,\n          });\n        }\n      }\n    }\n    return out;\n  }, [tracks]);\n\n  useEffect(() => {\n    if (!tool) return;\n    setPrompt('');\n    setStockQuery('');\n    setStockPhotos([]);\n    setSuggestions(null);\n    setError(null);\n    setIsBusy(false);\n    setStatusLabel('');\n    abortRef.current?.abort();\n    abortRef.current = null;\n    const selected = pickSelectedClip();\n    if (selected && (selected.type === 'video' || selected.type === 'audio')) {\n      setClipId(selected.id);\n    } else {\n      setClipId(mediaClips[0]?.id ?? '');\n    }\n  }, [tool, mediaClips]);\n\n  useEffect(() => () => abortRef.current?.abort(), []);\n\n  if (!tool) return null;\n\n  // Dedicated existing modals\n  if (tool === 'voiceover') {\n    return <AiVoiceoverModal isOpen onClose={onClose} />;\n  }\n  if (tool === 'marketing') {\n    return <AiContentModal isOpen onClose={onClose} />;\n  }\n\n  const titles: Record<Exclude<VideoAiToolId, 'voiceover' | 'marketing'>, string> = {\n    transcribe: tm.transcribeTitle,\n    translate: tm.translateTitle,\n    subtitleStyle: tm.subtitleStyleTitle,\n    colorGrading: tm.colorGradingTitle,\n    designPreset: tm.designPresetTitle,\n    videoProperties: tm.videoPropertiesTitle,\n    generateCopy: tm.generateCopyTitle,\n    copySuggestions: tm.copySuggestionsTitle,\n    stock: tm.stockTitle,\n  };\n\n  const handleClose = () => {\n    // Only abort in-modal work (prompt tools). Fire-and-forget jobs clear abortRef first.\n    abortRef.current?.abort();\n    abortRef.current = null;\n    onClose();\n  };\n\n  /** Keep modal open while work runs (tools that show results in the dialog). */\n  const withBusy = async (label: string, fn: (signal: AbortSignal) => Promise<void>) => {\n    const ac = new AbortController();\n    abortRef.current = ac;\n    setIsBusy(true);\n    setError(null);\n    setStatusLabel(label);\n    try {\n      await fn(ac.signal);\n    } catch (err: unknown) {\n      if (ac.signal.aborted) return;\n      setError(toUserFacingError(err, { context: 'video-ai-modal' }));\n    } finally {\n      setIsBusy(false);\n      setStatusLabel('');\n      if (abortRef.current === ac) abortRef.current = null;\n      useVideoStore.getState().setAiSubtitleJob(null);\n      useVideoStore.getState().setAiBusyToolId(null);\n    }\n  };\n\n  /**\n   * Close immediately and keep the job running (timeline / preview loaders own the UX).\n   * Detach abortRef so unmount does not cancel the request.\n   */\n  const runAndClose = (toolId: VideoAiToolId, fn: () => Promise<void>) => {\n    abortRef.current = null;\n    useVideoStore.getState().setAiBusyToolId(toolId);\n    onClose();\n    void fn()\n      .catch((err: unknown) => {\n        addToast(toUserFacingError(err, { context: 'video-ai-tool' }), 'error');\n      })\n      .finally(() => {\n        useVideoStore.getState().setAiSubtitleJob(null);\n        useVideoStore.getState().setAiBusyToolId(null);\n      });\n  };\n\n  const insertTextOverlay = (text: string) => {\n    const trackId = ensureTrack('text', 'Text AI');\n    useVideoStore.getState().addTextClip({\n      trackId,\n      assetId: '',\n      startTime: useVideoStore.getState().playheadTime,\n      duration: 4,\n      trimIn: 0,\n      trimOut: 0,\n      speed: 1,\n      volume: 1,\n      opacity: 1,\n      muted: false,\n      name: text.slice(0, 32),\n      text,\n    });\n  };\n\n  const handleTranscribe = () => {\n    if (!clipId) return;\n    runAndClose('transcribe', async () => {\n      const clip = useVideoStore.getState().tracks.flatMap((tr) => tr.clips).find((c) => c.id === clipId);\n      if (!clip) throw new Error(tm.needMediaClip);\n      const asset = useVideoStore.getState().assets.find((a) => a.id === clip.assetId);\n      if (!asset?.file) throw new Error(tm.needMediaFile);\n\n      useVideoStore.getState().setAiSubtitleJob({\n        kind: 'generate',\n        sourceClipId: clip.id,\n        startTime: clip.startTime,\n        duration: Math.max(0.5, clip.duration),\n      });\n\n      const segments = await transcribeAudio(asset.file);\n      const aspect = useVideoStore.getState().aspectRatio || '16:9';\n      let defaultY = 0.85;\n      if (aspect === '9:16') defaultY = 0.65;\n      else if (aspect === '1:1') defaultY = 0.75;\n\n      const liveTracks = useVideoStore.getState().tracks;\n      const subTrackId =\n        liveTracks.find((tr) => tr.type === 'subtitle')?.id ??\n        ensureTrack('subtitle', 'Subtitles');\n\n      segments.forEach((segment) => {\n        const startTime = clip.startTime + segment.start / (clip.speed || 1);\n        const duration = (segment.end - segment.start) / (clip.speed || 1);\n        useVideoStore.getState().addClip(subTrackId, {\n          trackId: subTrackId,\n          assetId: clip.assetId,\n          startTime,\n          duration,\n          trimIn: 0,\n          trimOut: 0,\n          speed: clip.speed,\n          volume: 1,\n          opacity: 1,\n          muted: false,\n          type: 'subtitle',\n          text: segment.text.trim(),\n          fontFamily: 'Inter',\n          fontSize: aspect === '9:16' ? 24 : 28,\n          fillColor: '#FFFFFF',\n          fontWeight: 600,\n          textAlign: 'center',\n          backgroundEnabled: true,\n          backgroundColor: '#000000',\n          backgroundOpacity: 0.6,\n          backgroundPadding: 8,\n          backgroundBorderRadius: 4,\n          shadowEnabled: true,\n          shadowColor: '#000000',\n          shadowBlur: 6,\n          shadowOffsetX: 2,\n          shadowOffsetY: 2,\n          shadowOpacity: 0.8,\n          x: 0.5,\n          y: defaultY,\n          scaleX: 1,\n          scaleY: 1,\n          rotation: 0,\n        });\n      });\n      addToast(tm.toastSubtitlesAdded, 'success');\n    });\n  };\n\n  const handleTranslate = () => {\n    runAndClose('translate', async () => {\n      const subtitleClips: { id: string; text: string }[] = [];\n      useVideoStore.getState().tracks.forEach((tr) => {\n        tr.clips.forEach((c) => {\n          if (c.type === 'subtitle' && c.text) {\n            subtitleClips.push({ id: c.id, text: c.text });\n          }\n        });\n      });\n      if (subtitleClips.length === 0) throw new Error(tm.needSubtitles);\n      useVideoStore.getState().setAiSubtitleJob({\n        kind: 'translate',\n        clipIds: subtitleClips.map((c) => c.id),\n      });\n      const translatedClips = await translateSubtitles(\n        JSON.stringify(subtitleClips),\n        targetLang,\n      );\n      if (!Array.isArray(translatedClips) || translatedClips.length === 0) {\n        throw new Error(tm.unknownError);\n      }\n      translatedClips.forEach((item) => {\n        if (item.id && item.text) {\n          useVideoStore.getState().updateClipProperties(item.id, { text: item.text });\n        }\n      });\n      addToast(tm.toastTranslated, 'success');\n    });\n  };\n\n  const handleSubtitleStyle = () => {\n    if (!prompt.trim()) return;\n    runAndClose('subtitleStyle', async () => {\n      const live = useVideoStore.getState();\n      const targetIds: string[] = [];\n      live.tracks.forEach((tr) => {\n        tr.clips.forEach((c) => {\n          if (c.type === 'subtitle' || c.type === 'text') targetIds.push(c.id);\n        });\n      });\n      if (targetIds.length === 0) throw new Error(tm.needSubtitlesForStyle);\n\n      live.setAiSubtitleJob({ kind: 'style', clipIds: targetIds });\n      const preset = await generateSubtitleStylePreset(prompt.trim());\n      if (Object.keys(preset).length === 0) throw new Error(tm.emptyStylePreset);\n      targetIds.forEach((id) => {\n        useVideoStore.getState().updateClipProperties(id, preset);\n      });\n      addToast(tm.toastStyleApplied, 'success');\n    });\n  };\n\n  const handleColorGrading = () => {\n    if (!prompt.trim()) return;\n    runAndClose('colorGrading', async () => {\n      const selected = pickSelectedClip();\n      if (!selected || (selected.type !== 'video' && selected.type !== 'image')) {\n        throw new Error(tm.needVideoOrImage);\n      }\n      useVideoStore.getState().setAiSubtitleJob({\n        kind: 'clipEdit',\n        clipIds: [selected.id],\n        label: tm.statusApplyingGrading,\n      });\n      const preset = await generateColorGradingPreset(prompt.trim());\n      useVideoStore.getState().updateColorGrading(selected.id, preset);\n      addToast(tm.toastGradingApplied, 'success');\n    });\n  };\n\n  const handleDesignPreset = () => {\n    if (!prompt.trim()) return;\n    runAndClose('designPreset', async () => {\n      const selected = pickSelectedClip();\n      if (!selected || (selected.type !== 'image' && selected.type !== 'video' && selected.type !== 'text' && selected.type !== 'subtitle')) {\n        throw new Error(tm.needDesignTarget);\n      }\n      const objectType: 'image' | 'text' =\n        selected.type === 'image' || selected.type === 'video' ? 'image' : 'text';\n\n      useVideoStore.getState().setAiSubtitleJob({\n        kind: 'clipEdit',\n        clipIds: [selected.id],\n        label: tm.statusApplyingDesign,\n      });\n\n      const preset = await generateImageDesignPreset(prompt.trim(), objectType);\n      const liveClip =\n        useVideoStore\n          .getState()\n          .tracks.flatMap((tr) => tr.clips)\n          .find((c) => c.id === selected.id) ?? selected;\n      const patch = mapDesignPresetToClipPatch(preset, liveClip);\n      if (Object.keys(patch).length === 0) {\n        throw new Error(tm.emptyDesignPreset);\n      }\n      useVideoStore.getState().updateClipProperties(selected.id, patch);\n      addToast(tm.toastDesignApplied, 'success');\n    });\n  };\n\n  const handleVideoProperties = () => {\n    if (!prompt.trim()) return;\n    runAndClose('videoProperties', async () => {\n      const selected = pickSelectedClip();\n      if (!selected || (selected.type !== 'video' && selected.type !== 'image' && selected.type !== 'audio')) {\n        throw new Error(tm.needMediaClip);\n      }\n      useVideoStore.getState().setAiSubtitleJob({\n        kind: 'clipEdit',\n        clipIds: [selected.id],\n        label: tm.statusApplyingProperties,\n      });\n      const plan = await generateVideoProperties(prompt.trim(), selected.type);\n      // Ensure $selected resolves to the clip we validated (not a stale multi-select).\n      useVideoStore.getState().selectClip(selected.id, false);\n      const { applied, summary } = applyVideoEditPlan(plan);\n      if (applied === 0) {\n        throw new Error(tm.emptyPropertiesPreset);\n      }\n      addToast(summary?.trim() || tm.toastPropertiesApplied, 'success');\n    });\n  };\n\n  const handleGenerateCopy = () => {\n    if (!prompt.trim()) return;\n    runAndClose('generateCopy', async () => {\n      const startTime = useVideoStore.getState().playheadTime;\n      const trackId = ensureTrack('text', 'Text AI');\n      useVideoStore.getState().setAiSubtitleJob({\n        kind: 'copy',\n        startTime,\n        duration: 4,\n        trackId,\n      });\n      const text = await generateCopy(prompt.trim());\n      useVideoStore.getState().addTextClip({\n        trackId,\n        assetId: '',\n        startTime,\n        duration: 4,\n        trimIn: 0,\n        trimOut: 0,\n        speed: 1,\n        volume: 1,\n        opacity: 1,\n        muted: false,\n        name: text.slice(0, 32),\n        text,\n      });\n      addToast(tm.toastCopyAdded, 'success');\n    });\n  };\n\n  const handleCopySuggestions = () =>\n    withBusy(tm.statusWorking, async () => {\n      if (!prompt.trim()) return;\n      useVideoStore.getState().setAiBusyToolId('copySuggestions');\n      const result = await generateCopywritingSuggestions(prompt.trim());\n      setSuggestions(result);\n    });\n\n  const handleStockSearch = () =>\n    withBusy(tm.statusSearching, async (signal) => {\n      if (!stockQuery.trim()) return;\n      useVideoStore.getState().setAiBusyToolId('stock');\n      const result = await searchStock({\n        q: stockQuery.trim(),\n        page: 1,\n        perPage: 18,\n        signal,\n      });\n      setStockPhotos(result.photos);\n      if (result.photos.length === 0) setError(tm.stockEmpty);\n    });\n\n  const submitPromptTool = () => {\n    if (isBusy || !prompt.trim()) return;\n    if (tool === 'subtitleStyle') void handleSubtitleStyle();\n    else if (tool === 'colorGrading') void handleColorGrading();\n    else if (tool === 'designPreset') void handleDesignPreset();\n    else if (tool === 'videoProperties') void handleVideoProperties();\n    else if (tool === 'generateCopy') void handleGenerateCopy();\n    else if (tool === 'copySuggestions') void handleCopySuggestions();\n  };\n\n  const onPromptKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement | HTMLInputElement>) => {\n    if (e.key !== 'Enter') return;\n    // Allow Shift+Enter for newlines in textarea\n    if (e.shiftKey && e.currentTarget.tagName === 'TEXTAREA') return;\n    e.preventDefault();\n    submitPromptTool();\n  };\n\n  const handleAddStock = (photo: StockPhoto) =>\n    withBusy(tm.statusDownloading, async (signal) => {\n      const downloaded = await downloadStockPhoto(photo, { signal });\n      const size = await readImageSize(downloaded.objectUrl);\n      const assetId = `ai_stock_${Date.now()}`;\n      const asset: Asset = {\n        id: assetId,\n        name: photo.alt || `Stock ${photo.id}`,\n        url: downloaded.objectUrl,\n        type: 'image',\n        duration: 5,\n        width: size.width,\n        height: size.height,\n        file: downloaded.file,\n        thumbnail: downloaded.objectUrl,\n        remoteUrl: downloaded.sourceUrl,\n      };\n      addAsset(asset);\n      const trackId = ensureTrack('image', 'Image AI');\n      addImageClip({\n        trackId,\n        assetId,\n        startTime: playheadTime,\n        duration: 5,\n        trimIn: 0,\n        trimOut: 0,\n        speed: 1,\n        volume: 1,\n        opacity: 1,\n        muted: false,\n        name: asset.name,\n      });\n      addToast(tm.toastImageAdded, 'success');\n      onClose();\n    });\n\n  return (\n    <Modal isOpen={Boolean(tool)} onClose={handleClose} title={titles[tool]} size=\"lg\">\n      <div className=\"relative space-y-4\">\n        {isBusy && tool !== 'transcribe' && tool !== 'translate' && (\n          <div className=\"absolute inset-0 z-20 flex flex-col items-center justify-center gap-3 rounded-xl bg-panel/90 backdrop-blur-sm\">\n            <div className=\"relative flex h-14 w-14 items-center justify-center\">\n              <div className=\"absolute inset-0 animate-spin rounded-full border-4 border-[var(--we-accent)]/20 border-t-[var(--we-accent)]\" />\n              <Sparkles className=\"animate-pulse text-[var(--we-accent)]\" size={20} />\n            </div>\n            <TextBody as=\"p\" size=\"md\" className=\"text-white\">\n              {statusLabel || tm.statusWorking}\n            </TextBody>\n            <Button variant=\"ghost\" onClick={handleClose} className=\"mt-2 text-xs\">\n              {tm.cancel}\n            </Button>\n          </div>\n        )}\n\n        {tool === 'transcribe' && (\n          <>\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {tm.transcribeHint}\n            </TextBody>\n            {mediaClips.length === 0 ? (\n              <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n                {tm.needMediaClip}\n              </TextBody>\n            ) : (\n              <PanelField\n                label={tm.clipLabel}\n                trailing={\n                  <SelectDropdown\n                    value={clipId}\n                    onChange={setClipId}\n                    options={mediaClips.map((c) => ({ value: c.id, label: c.label }))}\n                  />\n                }\n              />\n            )}\n            <div className=\"flex justify-end gap-2\">\n              <Button variant=\"ghost\" onClick={handleClose}>\n                {tm.cancel}\n              </Button>\n              <Button\n                onClick={() => handleTranscribe()}\n                disabled={!clipId}\n                className=\"bg-[var(--we-accent)] text-white hover:bg-[var(--we-accent-hover)] disabled:opacity-50\"\n              >\n                <Captions size={14} />\n                <TextBody as=\"span\" size=\"sm\" className=\"ml-1.5\">\n                  {tm.runTranscribe}\n                </TextBody>\n              </Button>\n            </div>\n          </>\n        )}\n\n        {tool === 'translate' && (\n          <>\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {tm.translateHint}\n            </TextBody>\n            <PanelField\n              label={tm.languageLabel}\n              trailing={\n                <SelectDropdown\n                  value={targetLang}\n                  onChange={setTargetLang}\n                  options={LANGS.map((l) => ({\n                    value: l.value,\n                    label: tm[l.labelKey],\n                  }))}\n                />\n              }\n            />\n            <div className=\"flex justify-end gap-2\">\n              <Button variant=\"ghost\" onClick={handleClose}>\n                {tm.cancel}\n              </Button>\n              <Button\n                onClick={() => handleTranslate()}\n                className=\"bg-[var(--we-accent)] text-white hover:bg-[var(--we-accent-hover)] disabled:opacity-50\"\n              >\n                <Languages size={14} />\n                <TextBody as=\"span\" size=\"sm\" className=\"ml-1.5\">\n                  {tm.runTranslate}\n                </TextBody>\n              </Button>\n            </div>\n          </>\n        )}\n\n        {(tool === 'subtitleStyle' ||\n          tool === 'colorGrading' ||\n          tool === 'designPreset' ||\n          tool === 'videoProperties' ||\n          tool === 'generateCopy' ||\n          tool === 'copySuggestions') && (\n          <>\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {tool === 'subtitleStyle'\n                ? tm.subtitleStyleHint\n                : tool === 'colorGrading'\n                  ? tm.colorGradingHint\n                  : tool === 'designPreset'\n                    ? tm.designPresetHint\n                    : tool === 'videoProperties'\n                      ? tm.videoPropertiesHint\n                      : tool === 'generateCopy'\n                        ? tm.generateCopyHint\n                        : tm.copySuggestionsHint}\n            </TextBody>\n            <textarea\n              value={prompt}\n              onChange={(e) => setPrompt(e.target.value)}\n              onKeyDown={onPromptKeyDown}\n              disabled={isBusy}\n              placeholder={\n                tool === 'subtitleStyle'\n                  ? tm.subtitleStylePlaceholder\n                  : tool === 'colorGrading'\n                    ? tm.colorGradingPlaceholder\n                    : tool === 'designPreset'\n                      ? tm.designPresetPlaceholder\n                      : tool === 'videoProperties'\n                        ? tm.videoPropertiesPlaceholder\n                        : tool === 'generateCopy'\n                          ? tm.generateCopyPlaceholder\n                          : tm.copySuggestionsPlaceholder\n              }\n              className=\"h-24 w-full resize-none rounded-xl border border-panel-border bg-black-capsule p-3 font-sans text-xs font-medium text-white placeholder:text-white/40 focus:border-[var(--we-accent)] focus:outline-none disabled:opacity-50\"\n            />\n            <div className=\"flex justify-end gap-2\">\n              <Button variant=\"ghost\" onClick={handleClose}>\n                {tm.cancel}\n              </Button>\n              <Button\n                onClick={() => submitPromptTool()}\n                disabled={isBusy || !prompt.trim()}\n                className=\"bg-[var(--we-accent)] text-white hover:bg-[var(--we-accent-hover)] disabled:opacity-50\"\n              >\n                {isBusy ? <Loader2 size={14} className=\"animate-spin\" /> : <Wand2 size={14} />}\n                <TextBody as=\"span\" size=\"sm\" className=\"ml-1.5\">\n                  {tool === 'subtitleStyle'\n                    ? tm.runApplyStyle\n                    : tool === 'colorGrading'\n                      ? tm.runApplyGrading\n                      : tool === 'designPreset'\n                        ? tm.runApplyDesign\n                        : tool === 'videoProperties'\n                          ? tm.runApplyProperties\n                          : tool === 'generateCopy'\n                            ? tm.runGenerateCopy\n                            : tm.runCopySuggestions}\n                </TextBody>\n              </Button>\n            </div>\n\n            {suggestions && (\n              <div className=\"flex flex-col gap-2\">\n                {(\n                  [\n                    { key: 'comercial' as const, text: suggestions.comercial, label: tm.toneComercial },\n                    { key: 'creativa' as const, text: suggestions.creativa, label: tm.toneCreativa },\n                    { key: 'directa' as const, text: suggestions.directa, label: tm.toneDirecta },\n                  ]\n                ).map(({ key, text, label }) => (\n                  <button\n                    key={key}\n                    type=\"button\"\n                    onClick={() => {\n                      insertTextOverlay(text);\n                      addToast(tm.toastCopyAdded, 'success');\n                      onClose();\n                    }}\n                    className=\"rounded-xl border border-transparent bg-black-capsule px-3 py-2.5 text-left hover:border-[color-mix(in_srgb,var(--we-accent)_35%,transparent)] hover:bg-[var(--we-accent-muted)]\"\n                  >\n                    <TextTitle as=\"span\" size=\"xs\" className=\"block uppercase tracking-wide text-[var(--we-accent)]\">\n                      {label}\n                    </TextTitle>\n                    <TextBody as=\"span\" size=\"sm\" className=\"mt-1 block text-white\">\n                      {text}\n                    </TextBody>\n                  </button>\n                ))}\n              </div>\n            )}\n          </>\n        )}\n\n        {tool === 'stock' && (\n          <>\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {tm.stockHint}\n            </TextBody>\n            <div className=\"flex gap-2\">\n              <input\n                value={stockQuery}\n                onChange={(e) => setStockQuery(e.target.value)}\n                onKeyDown={(e) => {\n                  if (e.key === 'Enter') void handleStockSearch();\n                }}\n                disabled={isBusy}\n                placeholder={tm.stockPlaceholder}\n                className=\"min-w-0 flex-1 rounded-xl border border-panel-border bg-black-capsule px-3 py-2 font-sans text-xs font-medium text-white placeholder:text-white/40 focus:border-[var(--we-accent)] focus:outline-none disabled:opacity-50\"\n              />\n              <Button\n                onClick={() => void handleStockSearch()}\n                disabled={isBusy || !stockQuery.trim()}\n                className=\"bg-[var(--we-accent)] text-white hover:bg-[var(--we-accent-hover)] disabled:opacity-50\"\n              >\n                <Search size={14} />\n                <TextBody as=\"span\" size=\"sm\" className=\"ml-1.5\">\n                  {tm.search}\n                </TextBody>\n              </Button>\n            </div>\n            {stockPhotos.length > 0 && (\n              <div className=\"grid max-h-72 grid-cols-3 gap-2 overflow-y-auto\">\n                {stockPhotos.map((photo) => (\n                  <button\n                    key={photo.id}\n                    type=\"button\"\n                    disabled={isBusy}\n                    onClick={() => void handleAddStock(photo)}\n                    className=\"group relative aspect-video overflow-hidden rounded-lg border border-transparent bg-black-capsule hover:border-[var(--we-accent)]/50 disabled:opacity-50\"\n                  >\n                    <img\n                      src={photo.thumbnailUrl}\n                      alt={photo.alt || photo.photographer}\n                      className=\"h-full w-full object-cover transition-transform group-hover:scale-105\"\n                    />\n                  </button>\n                ))}\n              </div>\n            )}\n          </>\n        )}\n\n        {error && (\n          <TextBody\n            as=\"p\"\n            size=\"sm\"\n            className=\"rounded-lg border border-red-900/40 bg-red-950/40 p-3 text-red-200\"\n          >\n            {error}\n          </TextBody>\n        )}\n      </div>\n    </Modal>\n  );\n};\n\nexport default VideoAiGenerateModal;\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { Modal } from '../ui/Modal';\nimport { Button } from '../ui/Button';\nimport { Volume2, Loader, Play, Pause } from 'lucide-react';\nimport { useVideoStore, type Asset } from '../../store/useVideoStore';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { TTS_VOICES } from '../../services/aiService';\nimport { generateVoiceover } from '../../services/voiceoverService';\nimport { useTranslation } from '../../i18n';\nimport { PanelField, SelectDropdown, TextBody, TextTitle } from '../ui';\n\ninterface AiVoiceoverModalProps {\n  isOpen: boolean;\n  onClose: () => void;\n}\n\n/** Short line used when synthesizing a voice demo via the TTS API. */\nconst VOICE_DEMO_SCRIPT =\n  'Hola, esta es una muestra de mi voz para tu proyecto.';\n\n/** Session cache: voiceId \u2192 object URL (static file or synthesized). */\nconst voiceDemoUrlCache = new Map<string, string>();\n\n/** Rough timeline placeholder width until real MP3 duration is known (~150 wpm). */\nfunction estimateVoiceoverDurationSec(text: string, speed: number): number {\n  const words = text.trim().split(/\\s+/).filter(Boolean).length;\n  const safeSpeed = speed > 0 ? speed : 1;\n  return Math.min(90, Math.max(4, words / (2.5 * safeSpeed)));\n}\n\nfunction readAudioDuration(url: string): Promise<number> {\n  return new Promise((resolve, reject) => {\n    const audio = new Audio(url);\n    audio.preload = 'metadata';\n    audio.onloadedmetadata = () => {\n      const d = audio.duration;\n      resolve(Number.isFinite(d) && d > 0 ? d : 5);\n    };\n    audio.onerror = () => reject(new Error('decode'));\n  });\n}\n\nexport const AiVoiceoverModal: React.FC<AiVoiceoverModalProps> = ({ isOpen, onClose }) => {\n  const t = useTranslation();\n  const tv = t.modal.aiVoiceover;\n  const addToast = useEditorStore((s) => s.addToast);\n  const { playheadTime } = useVideoStore();\n  const [text, setText] = useState('');\n  const [voice, setVoice] = useState<string>(TTS_VOICES[0]?.id ?? '');\n  const [speed, setSpeed] = useState(1.0);\n  const [isSubmitting, setIsSubmitting] = useState(false);\n  const [error, setError] = useState<string | null>(null);\n  const [isDemoPlaying, setIsDemoPlaying] = useState(false);\n  const [isDemoLoading, setIsDemoLoading] = useState(false);\n\n  const demoAudioRef = useRef<HTMLAudioElement | null>(null);\n  const demoAbortRef = useRef<AbortController | null>(null);\n\n  useEffect(() => {\n    return () => {\n      demoAbortRef.current?.abort();\n      demoAudioRef.current?.pause();\n    };\n  }, []);\n\n  useEffect(() => {\n    demoAbortRef.current?.abort();\n    demoAbortRef.current = null;\n    if (demoAudioRef.current) {\n      demoAudioRef.current.pause();\n      demoAudioRef.current = null;\n    }\n    setIsDemoPlaying(false);\n    setIsDemoLoading(false);\n  }, [voice]);\n\n  const resolveDemoUrl = async (voiceId: string, signal: AbortSignal): Promise<string> => {\n    const cached = voiceDemoUrlCache.get(voiceId);\n    if (cached) return cached;\n\n    const catalog = TTS_VOICES.find((v) => v.id === voiceId);\n    if (catalog?.previewUrl) {\n      try {\n        const res = await fetch(catalog.previewUrl, { signal });\n        if (res.ok) {\n          voiceDemoUrlCache.set(voiceId, catalog.previewUrl);\n          return catalog.previewUrl;\n        }\n      } catch {\n        /* Fall through to TTS sample */\n      }\n    }\n\n    const blob = await generateVoiceover({\n      text: VOICE_DEMO_SCRIPT,\n      voice: voiceId,\n      speed: 1,\n      signal,\n    });\n    const url = URL.createObjectURL(blob);\n    voiceDemoUrlCache.set(voiceId, url);\n    return url;\n  };\n\n  const handlePlayVoiceDemo = async () => {\n    if (!voice || isSubmitting) return;\n\n    if (isDemoPlaying && demoAudioRef.current) {\n      demoAudioRef.current.pause();\n      setIsDemoPlaying(false);\n      return;\n    }\n\n    demoAbortRef.current?.abort();\n    const ac = new AbortController();\n    demoAbortRef.current = ac;\n    setIsDemoLoading(true);\n    setError(null);\n\n    try {\n      const url = await resolveDemoUrl(voice, ac.signal);\n      if (ac.signal.aborted) return;\n\n      if (demoAudioRef.current) {\n        demoAudioRef.current.pause();\n      }\n      const audio = new Audio(url);\n      demoAudioRef.current = audio;\n      audio.onended = () => setIsDemoPlaying(false);\n      audio.onpause = () => setIsDemoPlaying(false);\n      await audio.play();\n      setIsDemoPlaying(true);\n    } catch (err: unknown) {\n      if (ac.signal.aborted) return;\n      console.error(err);\n      setError(err instanceof Error ? err.message : tv.demoError);\n    } finally {\n      if (demoAbortRef.current === ac) {\n        setIsDemoLoading(false);\n        demoAbortRef.current = null;\n      }\n    }\n  };\n\n  const ensureVoiceoverTrackId = (): string => {\n    const live = useVideoStore.getState();\n    let voiceTrack = live.tracks.find(\n      (tr) => tr.type === 'audio' && tr.name.includes('Voiceover'),\n    );\n    if (!voiceTrack) {\n      live.addTrack(tv.trackName, 'audio');\n      voiceTrack = useVideoStore\n        .getState()\n        .tracks.find((tr) => tr.type === 'audio' && tr.name.includes('Voiceover'));\n    }\n    return (\n      voiceTrack?.id ||\n      useVideoStore.getState().tracks.find((tr) => tr.type === 'audio')?.id ||\n      'audio_track_default'\n    );\n  };\n\n  const handleGenerate = () => {\n    if (!text.trim() || !voice || isSubmitting) return;\n\n    demoAudioRef.current?.pause();\n    setIsDemoPlaying(false);\n    setError(null);\n    setIsSubmitting(true);\n\n    const script = text.trim();\n    const startTime = playheadTime;\n    const estimatedDuration = estimateVoiceoverDurationSec(script, speed);\n    const trackId = ensureVoiceoverTrackId();\n\n    useVideoStore.getState().setAiSubtitleJob({\n      kind: 'voiceover',\n      startTime,\n      duration: estimatedDuration,\n      trackId,\n    });\n    useVideoStore.getState().setAiBusyToolId('voiceover');\n\n    // Same UX as subtitle AI: close immediately; timeline loader owns progress.\n    onClose();\n    setIsSubmitting(false);\n\n    void (async () => {\n      try {\n        const blob = await generateVoiceover({ text: script, voice, speed });\n        const url = URL.createObjectURL(blob);\n        let duration = estimatedDuration;\n        try {\n          duration = await readAudioDuration(url);\n        } catch {\n          /* keep estimate */\n        }\n\n        const filename = `ai_voiceover_${Date.now()}.mp3`;\n        const file = new File([blob], filename, { type: 'audio/mpeg' });\n        const assetId = `asset_voice_${Date.now()}`;\n        const newAsset: Asset = {\n          id: assetId,\n          name: filename,\n          url,\n          type: 'audio',\n          duration,\n          file,\n        };\n\n        const store = useVideoStore.getState();\n        store.addAsset(newAsset);\n        store.addClip(trackId, {\n          trackId,\n          assetId,\n          startTime,\n          duration,\n          trimIn: 0,\n          trimOut: 0,\n          speed: 1.0,\n          volume: 1.0,\n          opacity: 1.0,\n          muted: false,\n          type: 'audio',\n          name: tv.clipName(script.substring(0, 15)),\n        });\n        store.setAiSubtitleJob(null);\n        store.setAiBusyToolId(null);\n        addToast(tv.addedToast, 'success');\n      } catch (err: unknown) {\n        console.error(err);\n        useVideoStore.getState().setAiSubtitleJob(null);\n        useVideoStore.getState().setAiBusyToolId(null);\n        addToast(\n          err instanceof Error ? err.message : t.store.toasts.editor.voiceoverUnknownError,\n          'error',\n        );\n      }\n    })();\n  };\n\n  return (\n    <Modal isOpen={isOpen} onClose={onClose} title={tv.title} size=\"lg\">\n      <div className=\"space-y-4\">\n        <div className=\"space-y-1.5\">\n          <TextTitle as=\"label\" size=\"xs\" className=\"block tracking-wider uppercase\">\n            {tv.scriptLabel}\n          </TextTitle>\n          <textarea\n            value={text}\n            onChange={(e) => setText(e.target.value)}\n            disabled={isSubmitting}\n            placeholder={tv.placeholder}\n            className=\"h-28 w-full resize-none rounded-xl border border-panel-border bg-black-capsule p-3 font-sans text-xs font-medium text-white placeholder:text-white/40 outline-none transition-all focus:border-[var(--we-accent)] disabled:opacity-50\"\n          />\n        </div>\n\n        <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2\">\n          <div className=\"space-y-1.5\">\n            <TextTitle as=\"label\" size=\"xs\" className=\"block tracking-wider uppercase\">\n              {tv.voiceLabel}\n            </TextTitle>\n            <div className=\"flex min-h-9 items-stretch gap-1.5\">\n              <div className=\"flex min-h-9 min-w-0 flex-1 items-center rounded-xl bg-black-capsule px-3 py-2\">\n                <SelectDropdown\n                  value={voice}\n                  disabled={isSubmitting || isDemoLoading}\n                  size=\"md\"\n                  className=\"w-full\"\n                  ariaLabel={tv.voiceLabel}\n                  options={TTS_VOICES.map((v) => ({ value: v.id, label: v.label }))}\n                  onChange={setVoice}\n                />\n              </div>\n              <button\n                type=\"button\"\n                onClick={() => void handlePlayVoiceDemo()}\n                disabled={isSubmitting || !voice}\n                title={tv.playDemo}\n                aria-label={tv.playDemo}\n                className=\"flex min-h-9 w-9 shrink-0 cursor-pointer items-center justify-center rounded-xl bg-black-capsule text-[var(--we-accent)] transition-colors hover:bg-[var(--we-accent-muted)] hover:text-white disabled:cursor-not-allowed disabled:opacity-40\"\n              >\n                {isDemoLoading ? (\n                  <Loader size={14} className=\"animate-spin\" />\n                ) : isDemoPlaying ? (\n                  <Pause size={14} />\n                ) : (\n                  <Play size={14} className=\"ml-0.5\" />\n                )}\n              </button>\n            </div>\n            <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n              {tv.playDemoHint}\n            </TextBody>\n          </div>\n\n          <PanelField\n            variant=\"slide\"\n            label={tv.speedLabel}\n            min={0.25}\n            max={4}\n            step={0.05}\n            numericValue={speed}\n            formatValue={(v) => `${v.toFixed(2)}x`}\n            disabled={isSubmitting}\n            onChange={setSpeed}\n          />\n        </div>\n\n        {error && (\n          <TextBody\n            as=\"p\"\n            size=\"sm\"\n            className=\"rounded-xl border border-red-900/40 bg-red-950/40 p-3 text-red-200\"\n          >\n            {error}\n          </TextBody>\n        )}\n\n        <div className=\"flex justify-end gap-2 pt-2\">\n          <Button variant=\"ghost\" onClick={onClose} disabled={isSubmitting}>\n            {tv.cancel}\n          </Button>\n          <Button\n            onClick={handleGenerate}\n            disabled={isSubmitting || !text.trim()}\n            className=\"flex items-center gap-1.5 bg-[var(--we-accent)] font-bold text-black hover:bg-[var(--we-accent-hover)] disabled:opacity-50\"\n          >\n            {isSubmitting ? (\n              <>\n                <Loader size={14} className=\"animate-spin text-black\" />\n                <TextBody as=\"span\" size=\"sm\">\n                  {tv.synthesizing}\n                </TextBody>\n              </>\n            ) : (\n              <>\n                <Volume2 size={14} />\n                <TextBody as=\"span\" size=\"sm\">\n                  {tv.generate}\n                </TextBody>\n              </>\n            )}\n          </Button>\n        </div>\n      </div>\n    </Modal>\n  );\n};\n", "import { type Track, type Asset, type TransitionClip } from '../store/useVideoStore';\n\nexport interface ProjectData {\n  aspectRatio: '16:9' | '9:16' | '1:1';\n  tracks: Track[];\n  transitions: TransitionClip[];\n  assets: Asset[];\n}\n\n/**\n * Encodes string to Uint8Array\n */\nfunction encodeString(str: string): Uint8Array {\n  return new TextEncoder().encode(str);\n}\n\n/**\n * Decodes Uint8Array to string\n */\nfunction decodeString(bytes: Uint8Array): string {\n  return new TextDecoder().decode(bytes);\n}\n\n/**\n * Serializes the editor state (aspect ratio, tracks, transitions, assets)\n * and active media files into a single binary Blob (.wzrdv).\n */\nexport async function exportProjectToWzrdv(\n  aspectRatio: '16:9' | '9:16' | '1:1' | '4:3' | '3:4' | '21:9',\n  tracks: Track[],\n  transitions: TransitionClip[],\n  assets: Asset[]\n): Promise<Blob> {\n  // 1. Prepare JSON metadata\n  const metadata = {\n    aspectRatio,\n    tracks,\n    transitions,\n    assets: assets.map((a) => ({\n      id: a.id,\n      name: a.name,\n      type: a.type,\n      duration: a.duration\n    }))\n  };\n\n  const jsonStr = JSON.stringify(metadata);\n  const jsonBytes = encodeString(jsonStr);\n\n  // 2. Gather binary files associated with the assets\n  const filesToPack: { id: string; file: File; name: string; type: string }[] = [];\n  for (const asset of assets) {\n    if (asset.file) {\n      filesToPack.push({\n        id: asset.id,\n        file: asset.file,\n        name: asset.name,\n        type: asset.file.type || (asset.type === 'video' ? 'video/mp4' : asset.type === 'audio' ? 'audio/mpeg' : 'image/png')\n      });\n    }\n  }\n\n  const headerParts: any[] = [];\n\n  // Write Magic Number (8 bytes)\n  const magic = encodeString(\"WZRDPROJ\");\n  headerParts.push(magic);\n\n  // Write JSON Metadata length (4 bytes, Uint32)\n  const jsonLenBuf = new ArrayBuffer(4);\n  new DataView(jsonLenBuf).setUint32(0, jsonBytes.length, true);\n  headerParts.push(jsonLenBuf);\n\n  // Write JSON Metadata bytes\n  headerParts.push(jsonBytes);\n\n  // Write Number of files (4 bytes, Uint32)\n  const numFilesBuf = new ArrayBuffer(4);\n  new DataView(numFilesBuf).setUint32(0, filesToPack.length, true);\n  headerParts.push(numFilesBuf);\n\n  const fileBlobs: Blob[] = [];\n\n  // Write headers for each file, and prepare file data body\n  for (const f of filesToPack) {\n    const idBytes = encodeString(f.id);\n    const nameBytes = encodeString(f.name);\n    const typeBytes = encodeString(f.type);\n\n    // Header layout for each file (16 bytes):\n    // - Asset ID length (Uint32)\n    // - File Name length (Uint32)\n    // - File Type length (Uint32)\n    // - File Content size (Uint32)\n    const fileHeaderBuf = new ArrayBuffer(16);\n    const view = new DataView(fileHeaderBuf);\n    view.setUint32(0, idBytes.length, true);\n    view.setUint32(4, nameBytes.length, true);\n    view.setUint32(8, typeBytes.length, true);\n    view.setUint32(12, f.file.size, true);\n\n    headerParts.push(fileHeaderBuf);\n    headerParts.push(idBytes);\n    headerParts.push(nameBytes);\n    headerParts.push(typeBytes);\n\n    fileBlobs.push(f.file);\n  }\n\n  // Package all parts sequentially into a single octet stream Blob\n  return new Blob([...headerParts, ...fileBlobs], { type: 'application/octet-stream' });\n}\n\n/**\n * Parses a binary Blob (.wzrdv) and reconstructs the metadata and assets,\n * regenerating Local Object URLs for visual rendering.\n */\nexport async function importProjectFromWzrdv(fileBlob: Blob): Promise<ProjectData> {\n  const arrayBuffer = await fileBlob.arrayBuffer();\n  const view = new DataView(arrayBuffer);\n\n  // 1. Verify Magic Number\n  if (arrayBuffer.byteLength < 8) {\n    throw new Error('El archivo es demasiado peque\u00F1o para ser un proyecto v\u00E1lido.');\n  }\n  const magic = decodeString(new Uint8Array(arrayBuffer, 0, 8));\n  if (magic !== \"WZRDPROJ\") {\n    throw new Error('Firma de archivo inv\u00E1lida. Por favor sube un archivo de proyecto (.wzrdv) v\u00E1lido.');\n  }\n\n  // 2. Read JSON Length\n  if (arrayBuffer.byteLength < 12) {\n    throw new Error('El archivo est\u00E1 incompleto o corrupto.');\n  }\n  const jsonLen = view.getUint32(8, true);\n\n  // 3. Extract and parse JSON Metadata\n  if (arrayBuffer.byteLength < 12 + jsonLen) {\n    throw new Error('El archivo de metadatos del proyecto est\u00E1 truncado.');\n  }\n  const jsonBytes = new Uint8Array(arrayBuffer, 12, jsonLen);\n  const jsonStr = decodeString(jsonBytes);\n  const metadata = JSON.parse(jsonStr);\n\n  // 4. Read Number of files\n  let offset = 12 + jsonLen;\n  if (arrayBuffer.byteLength < offset + 4) {\n    throw new Error('Archivo corrupto al leer el contador de recursos.');\n  }\n  const numFiles = view.getUint32(offset, true);\n  offset += 4;\n\n  const fileMetadata: { id: string; name: string; type: string; size: number }[] = [];\n\n  // 5. Parse headers of files\n  for (let i = 0; i < numFiles; i++) {\n    if (arrayBuffer.byteLength < offset + 16) {\n      throw new Error('El archivo del proyecto est\u00E1 corrupto en las cabeceras de archivos.');\n    }\n    const idLen = view.getUint32(offset, true);\n    const nameLen = view.getUint32(offset + 4, true);\n    const typeLen = view.getUint32(offset + 8, true);\n    const size = view.getUint32(offset + 12, true);\n    offset += 16;\n\n    if (arrayBuffer.byteLength < offset + idLen + nameLen + typeLen) {\n      throw new Error('El archivo est\u00E1 corrupto al leer las rutas de archivos.');\n    }\n\n    const id = decodeString(new Uint8Array(arrayBuffer, offset, idLen));\n    offset += idLen;\n\n    const name = decodeString(new Uint8Array(arrayBuffer, offset, nameLen));\n    offset += nameLen;\n\n    const type = decodeString(new Uint8Array(arrayBuffer, offset, typeLen));\n    offset += typeLen;\n\n    fileMetadata.push({ id, name, type, size });\n  }\n\n  // 6. Slice raw binary contents and map them back to Assets\n  const fileMap = new Map<string, { file: File; url: string }>();\n  for (const meta of fileMetadata) {\n    if (arrayBuffer.byteLength < offset + meta.size) {\n      throw new Error(`Los datos binarios para el archivo \"${meta.name}\" est\u00E1n truncados.`);\n    }\n\n    // Slice binary array buffer\n    const fileBytes = new Uint8Array(arrayBuffer, offset, meta.size);\n    offset += meta.size;\n\n    // Reconstruct File and URL\n    const restoredBlob = new Blob([fileBytes], { type: meta.type });\n    const restoredFile = new File([restoredBlob], meta.name, { type: meta.type });\n    const restoredUrl = URL.createObjectURL(restoredFile);\n\n    fileMap.set(meta.id, { file: restoredFile, url: restoredUrl });\n  }\n\n  // 7. Map back metadata assets list and populate with regenerated Blobs\n  const restoredAssets: Asset[] = [];\n  for (const assetMeta of (metadata.assets || [])) {\n    const fileInfo = fileMap.get(assetMeta.id);\n    if (fileInfo) {\n      restoredAssets.push({\n        ...assetMeta,\n        file: fileInfo.file,\n        url: fileInfo.url\n      });\n    } else {\n      // Preserve metadata asset but empty url (in case it is an external link)\n      restoredAssets.push({\n        ...assetMeta,\n        url: ''\n      });\n    }\n  }\n\n  return {\n    aspectRatio: metadata.aspectRatio || '16:9',\n    tracks: metadata.tracks || [],\n    transitions: metadata.transitions || [],\n    assets: restoredAssets\n  };\n}\n", "import React, { useEffect, useRef, useState } from 'react';\nimport { Clock, HelpCircle } from 'lucide-react';\nimport { useEditorStore } from '../../store/useEditorStore';\nimport { uploadCurrentProjectToCloudWithToast } from '../../utils/cloudSaveToast';\nimport { IMAGE_FILTER_PRESET_IDS } from '../../utils/imageFilterPresets';\nimport { useDialog } from '../DialogModal';\nimport { useTranslation } from '../../i18n';\nimport { EditorShellHeader } from './EditorShellHeader';\nimport {\n  ShellFileMenu,\n  DropdownItem,\n  DropdownDivider,\n} from './ShellFileMenu';\nimport { DropdownSubmenu, TextBody, TextTitle } from '../ui';\nimport { ModeProjectTabs } from './ModeProjectTabs';\nimport { ExportModal } from '../ExportModal';\nimport { VersionHistoryModal } from '../VersionHistoryModal';\nimport { projectAccept, projectExtDot, safeProjectBasename } from '../../utils/projectExtensions';\nimport type { EditorMode } from './EditorModeToggle';\nimport { isApplePlatform, modShortcut } from '../../utils/modKey';\n\ninterface ImageEditorChromeProps {\n  onSwitchMode: (mode: EditorMode) => void;\n  onNewProject: () => void;\n  onBack?: () => void;\n  backHref?: string;\n  backText?: string;\n  hasProject: boolean;\n}\n\nexport const ImageEditorChrome: React.FC<ImageEditorChromeProps> = ({\n  onSwitchMode,\n  onNewProject,\n  onBack,\n  backHref,\n  backText,\n  hasProject,\n}) => {\n  const t = useTranslation();\n  const dialog = useDialog();\n  const fileImportRef = useRef<HTMLInputElement | null>(null);\n  const [isSavingCloud, setIsSavingCloud] = useState(false);\n  const [isExportOpen, setIsExportOpen] = useState(false);\n  const [isVersionHistoryOpen, setIsVersionHistoryOpen] = useState(false);\n  const [isHelpOpen, setIsHelpOpen] = useState(false);\n\n  const {\n    pages,\n    activePageId,\n    activeObject,\n    imageSettings,\n    applyImagePreset,\n  } = useEditorStore();\n  const activePage = pages.find((p) => p.id === activePageId) || pages[0];\n  const imageSelected = !!activeObject && (activeObject.type || '').toLowerCase() === 'image';\n  const activePreset = imageSettings.activePreset || 'original';\n\n  useEffect(() => {\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === '?' && !e.metaKey && !e.ctrlKey && !e.altKey) {\n        const tag = (e.target as HTMLElement)?.tagName;\n        if (tag === 'INPUT' || tag === 'TEXTAREA' || (e.target as HTMLElement)?.isContentEditable) {\n          return;\n        }\n        e.preventDefault();\n        setIsHelpOpen((open) => !open);\n      }\n      if (e.key === 'Escape' && isHelpOpen) setIsHelpOpen(false);\n    };\n    window.addEventListener('keydown', onKey);\n    return () => window.removeEventListener('keydown', onKey);\n  }, [isHelpOpen]);\n\n  const handleSaveProject = () => {\n    const store = useEditorStore.getState();\n    const canvas = store.canvasInstance;\n    if (!canvas) return;\n    const data = {\n      version: '1.0.0',\n      pages: store.pages,\n      activePageId: store.activePageId,\n      canvasJSON: canvas.toJSON(),\n    };\n    const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });\n    const url = URL.createObjectURL(blob);\n    const a = document.createElement('a');\n    a.href = url;\n    const projectName =\n      store.imageProjects.find((p) => p.id === store.activeImageProjectId)?.name ||\n      activePage?.name ||\n      'proyecto';\n    a.download = `${safeProjectBasename(projectName)}${projectExtDot('image')}`;\n    a.click();\n    URL.revokeObjectURL(url);\n  };\n\n  const handleSaveToCloud = async () => {\n    if (isSavingCloud) return;\n    setIsSavingCloud(true);\n    try {\n      await uploadCurrentProjectToCloudWithToast('image');\n    } catch {\n      // toast already shown\n    } finally {\n      setIsSavingCloud(false);\n    }\n  };\n\n  const handleImport = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const file = e.target.files?.[0];\n    if (!file) return;\n    const reader = new FileReader();\n    reader.onload = (ev) => {\n      try {\n        const data = JSON.parse(ev.target?.result as string);\n        useEditorStore.getState().importImageProject(data, file.name);\n      } catch {\n        dialog.alert(t.dialog.loadError.message, {\n          title: t.dialog.loadError.title,\n          variant: 'error',\n        });\n      }\n    };\n    reader.readAsText(file);\n    e.target.value = '';\n  };\n\n  return (\n    <>\n      <EditorShellHeader\n        mode=\"image\"\n        onBack={onBack}\n        backHref={backHref}\n        backLabel={backText}\n        onSwitchMode={onSwitchMode}\n        onNewProject={onNewProject}\n        newProjectTitle={t.editor.newProject.image}\n        onExport={hasProject ? () => setIsExportOpen(true) : undefined}\n        exportDisabled={!hasProject}\n        onPlay={\n          hasProject\n            ? () => useEditorStore.getState().setPlayingSlideshow(true)\n            : undefined\n        }\n        playDisabled={!hasProject}\n        fileMenu={\n          <ShellFileMenu\n            onNew={onNewProject}\n            onOpen={() => fileImportRef.current?.click()}\n            onSave={hasProject ? handleSaveProject : undefined}\n            onSaveToCloud={hasProject ? handleSaveToCloud : undefined}\n            isSavingCloud={isSavingCloud}\n            newLabel={t.toolbar.image.newCanvas}\n            openLabel={t.toolbar.image.openProject}\n            saveLabel={t.toolbar.image.saveProject}\n            extras={\n              <>\n                <DropdownDivider />\n                <DropdownItem\n                  icon={<Clock size={15} strokeWidth={2.25} />}\n                  disabled={!hasProject}\n                  onClick={() => setIsVersionHistoryOpen(true)}\n                >\n                  {t.toolbar.image.versionHistory}\n                </DropdownItem>\n                <DropdownDivider />\n                <DropdownSubmenu\n                  label={t.toolbar.image.filters}\n                  disabled={!imageSelected}\n                  title={\n                    imageSelected\n                      ? t.toolbar.image.filters\n                      : t.toolbar.image.filtersSelectImage\n                  }\n                >\n                  {IMAGE_FILTER_PRESET_IDS.map((id) => {\n                    const isActive = activePreset === id;\n                    const label =\n                      t.properties.image.preset[id as keyof typeof t.properties.image.preset];\n                    return (\n                      <DropdownItem\n                        key={id}\n                        onClick={() => applyImagePreset(id)}\n                        className={\n                          isActive\n                            ? 'bg-[var(--we-accent-muted)] text-[var(--we-accent)] hover:bg-[var(--we-accent-muted)]'\n                            : ''\n                        }\n                      >\n                        {label}\n                      </DropdownItem>\n                    );\n                  })}\n                </DropdownSubmenu>\n                <DropdownDivider />\n                <DropdownItem\n                  icon={<HelpCircle size={15} strokeWidth={2.25} />}\n                  onClick={() => setIsHelpOpen(true)}\n                >\n                  {t.keyboardHelp.title}\n                </DropdownItem>\n              </>\n            }\n          />\n        }\n        tabs={<ModeProjectTabs mode=\"image\" />}\n      />\n      <input\n        ref={fileImportRef}\n        type=\"file\"\n        accept={projectAccept('image')}\n        className=\"hidden\"\n        onChange={handleImport}\n      />\n      <ExportModal isOpen={isExportOpen} onClose={() => setIsExportOpen(false)} />\n      {isVersionHistoryOpen ? (\n        <VersionHistoryModal onClose={() => setIsVersionHistoryOpen(false)} />\n      ) : null}\n\n      {isHelpOpen && (\n        <>\n          <div\n            className=\"fixed inset-0 z-[200] bg-black/60 backdrop-blur-sm\"\n            onClick={() => setIsHelpOpen(false)}\n            aria-hidden\n          />\n          <div className=\"fixed top-1/2 left-1/2 z-[201] max-h-[80vh] w-[420px] -translate-x-1/2 -translate-y-1/2 overflow-y-auto rounded-2xl border border-panel-border bg-panel p-6 shadow-2xl animate-fade-in\">\n            <div className=\"mb-4 flex items-center justify-between\">\n              <TextTitle as=\"h2\" size=\"sm\" className=\"text-white\">\n                {t.keyboardHelp.title}\n              </TextTitle>\n              <button\n                type=\"button\"\n                onClick={() => setIsHelpOpen(false)}\n                className=\"text-lg leading-none text-white/80 transition-colors hover:text-white\"\n                aria-label={t.common.close}\n              >\n                \u00D7\n              </button>\n            </div>\n            {(\n              [\n                [t.keyboardHelp.select, 'V'],\n                [t.keyboardHelp.hand, 'H'],\n                [t.keyboardHelp.text, 'T'],\n                [t.keyboardHelp.rect, 'R'],\n                [t.keyboardHelp.ellipse, 'E'],\n                [t.keyboardHelp.undo, modShortcut('Z')],\n                [\n                  t.keyboardHelp.redo,\n                  isApplePlatform() ? '\u2318\u21E7Z' : 'Ctrl+Shift+Z',\n                ],\n                [t.keyboardHelp.copy, modShortcut('C')],\n                [t.keyboardHelp.paste, modShortcut('V')],\n                [t.keyboardHelp.delete, 'Delete / Backspace'],\n                [\n                  t.keyboardHelp.zoomIn,\n                  isApplePlatform() ? '\u2318+' : 'Ctrl+=',\n                ],\n                [\n                  t.keyboardHelp.zoomOut,\n                  isApplePlatform() ? '\u2318\u2212' : 'Ctrl+\u2212',\n                ],\n                [t.keyboardHelp.fitCanvas, modShortcut('0')],\n                [t.keyboardHelp.thisPanel, '?'],\n              ] as const\n            ).map(([action, key]) => (\n              <div\n                key={action}\n                className=\"flex items-center justify-between border-b border-panel-border py-1.5 last:border-0\"\n              >\n                <TextBody as=\"span\" size=\"sm\" className=\"text-white/80\">\n                  {action}\n                </TextBody>\n                <TextBody\n                  as=\"span\"\n                  size=\"sm\"\n                  className=\"rounded border border-panel-border bg-black-capsule px-2 py-0.5 font-mono font-bold text-white\"\n                >\n                  {key}\n                </TextBody>\n              </div>\n            ))}\n          </div>\n        </>\n      )}\n    </>\n  );\n};\n", "import React, { useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n  X,\n  Download,\n  Upload,\n  FileImage,\n  FileText,\n  Code,\n} from 'lucide-react';\nimport { advancedExport, type AdvancedExportOptions } from '../utils/exportUtils';\nimport { useDialog } from '../components/DialogModal';\nimport { useTranslation } from '../i18n';\nimport { modeAccentVars, useModeAccent } from '../theme/modeAccent';\nimport {\n  Button,\n  IconButton,\n  PanelField,\n  PanelSection,\n  Switch,\n  TextBody,\n  TextTitle,\n} from './ui';\n\ninterface ExportModalProps {\n  isOpen: boolean;\n  onClose: () => void;\n}\n\ntype ExportFormat = AdvancedExportOptions['format'];\n\nconst FORMATS: {\n  id: ExportFormat;\n  icon: typeof FileImage;\n  label: string;\n}[] = [\n  { id: 'png', icon: FileImage, label: 'PNG' },\n  { id: 'jpeg', icon: FileImage, label: 'JPEG' },\n  { id: 'svg', icon: Code, label: 'SVG' },\n  { id: 'pdf', icon: FileText, label: 'PDF' },\n  { id: 'pptx', icon: FileText, label: 'PPTX' },\n  { id: 'html', icon: Code, label: 'HTML' },\n];\n\nexport const ExportModal: React.FC<ExportModalProps> = ({ isOpen, onClose }) => {\n  const t = useTranslation();\n  const mode = useModeAccent();\n  const te = t.modal.imageExport;\n  const dialog = useDialog();\n  const [format, setFormat] = useState<ExportFormat>('png');\n  const [scale, setScale] = useState(1);\n  const [includeBleed, setIncludeBleed] = useState(false);\n  const [bleedMm, setBleedMm] = useState(3);\n  const [includeCropMarks, setIncludeCropMarks] = useState(false);\n\n  const [watermarkEnabled, setWatermarkEnabled] = useState(false);\n  const [watermarkType, setWatermarkType] = useState<'text' | 'image'>('text');\n  const [watermarkText, setWatermarkText] = useState(te.watermarkDefault);\n  const [watermarkOpacity, setWatermarkOpacity] = useState(0.2);\n  const [watermarkImage, setWatermarkImage] = useState<string | null>(null);\n\n  const [isExporting, setIsExporting] = useState(false);\n\n  useEffect(() => {\n    if (!isOpen) return;\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') onClose();\n    };\n    document.addEventListener('keydown', onKey);\n    const prev = document.body.style.overflow;\n    document.body.style.overflow = 'hidden';\n    return () => {\n      document.removeEventListener('keydown', onKey);\n      document.body.style.overflow = prev;\n    };\n  }, [isOpen, onClose]);\n\n  if (!isOpen || typeof document === 'undefined') return null;\n\n  const showScale = format === 'png' || format === 'jpeg';\n  const showPrint = format === 'pdf' || format === 'png' || format === 'jpeg';\n  const showWatermark =\n    format === 'png' || format === 'jpeg' || format === 'pdf' || format === 'html';\n\n  const handleImageUpload = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const file = e.target.files?.[0];\n    if (!file) return;\n    const reader = new FileReader();\n    reader.onload = (ev) => {\n      if (ev.target?.result) setWatermarkImage(ev.target.result as string);\n    };\n    reader.readAsDataURL(file);\n  };\n\n  const handleExport = async () => {\n    setIsExporting(true);\n    const options: AdvancedExportOptions = {\n      format,\n      scale,\n      bleed: includeBleed ? bleedMm : 0,\n      cropMarks: includeCropMarks,\n      watermark: {\n        enabled: watermarkEnabled,\n        type: watermarkType,\n        text: watermarkText,\n        imageUrl: watermarkImage || undefined,\n        opacity: watermarkOpacity,\n      },\n    };\n\n    try {\n      await advancedExport(options);\n      onClose();\n    } catch (e) {\n      console.error('Export Error', e);\n      dialog.alert(te.errorMessage, { title: te.errorTitle, variant: 'error' });\n    } finally {\n      setIsExporting(false);\n    }\n  };\n\n  const segmentActive = 'bg-[var(--we-accent-capsule)] text-white';\n  const segmentIdle = 'text-white/80 hover:text-white';\n\n  return createPortal(\n    <div\n      className=\"fixed inset-0 z-[100] flex items-center justify-center bg-black/75 p-4 backdrop-blur-sm animate-fade-in-opacity\"\n      style={modeAccentVars(mode)}\n      data-we-mode={mode}\n    >\n      <div className=\"absolute inset-0 cursor-default\" onClick={onClose} aria-hidden />\n      <div\n        role=\"dialog\"\n        aria-modal\n        aria-label={te.title}\n        className=\"relative z-[101] flex max-h-[90vh] w-full max-w-3xl flex-col overflow-hidden rounded-2xl border border-panel-border bg-panel shadow-2xl shadow-black/60 animate-slide-in\"\n      >\n        {/* Header */}\n        <div className=\"flex shrink-0 items-center justify-between gap-3 border-b border-panel-border px-4 py-3\">\n          <TextTitle as=\"h2\" size=\"sm\" className=\"flex items-center gap-2 uppercase tracking-wider\">\n            <Download size={16} className=\"text-[var(--we-accent)]\" aria-hidden />\n            {te.title}\n          </TextTitle>\n          <IconButton label={t.common.close} size=\"sm\" variant=\"ghost\" onClick={onClose}>\n            <X size={16} />\n          </IconButton>\n        </div>\n\n        {/* Body \u2014 two columns */}\n        <div className=\"flex min-h-0 flex-1 flex-col md:flex-row overflow-hidden\">\n          {/* Left: formats */}\n          <aside className=\"flex w-full shrink-0 flex-col gap-2 border-b border-panel-border p-4 md:w-52 md:border-b-0 md:border-r md:overflow-y-auto\">\n            <TextTitle as=\"h3\" size=\"xs\" className=\"mb-1 uppercase tracking-wider\">\n              {te.outputFormat}\n            </TextTitle>\n            <div className=\"flex flex-row gap-1.5 overflow-x-auto md:flex-col md:overflow-visible\">\n              {FORMATS.map((f) => {\n                const active = format === f.id;\n                const Icon = f.icon;\n                return (\n                  <button\n                    key={f.id}\n                    type=\"button\"\n                    onClick={() => setFormat(f.id)}\n                    className={`flex shrink-0 items-center gap-2.5 rounded-xl border px-3 py-2.5 text-left transition-colors select-none md:w-full ${\n                      active\n                        ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)] text-[var(--we-accent)]'\n                        : 'border-panel-border bg-black-capsule text-white/80 hover:border-[var(--we-accent)]/40 hover:bg-black-capsule-hover hover:text-white'\n                    }`}\n                    aria-pressed={active}\n                  >\n                    <Icon size={15} className=\"shrink-0\" aria-hidden />\n                    <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                      {f.label}\n                    </TextBody>\n                  </button>\n                );\n              })}\n            </div>\n          </aside>\n\n          {/* Right: options */}\n          <div className=\"flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto p-4\">\n            {showScale && (\n              <PanelSection title={te.resolutionScale}>\n                <div className=\"flex gap-1 rounded-xl bg-black-capsule p-1\">\n                  {[1, 2, 3].map((s) => (\n                    <button\n                      key={s}\n                      type=\"button\"\n                      onClick={() => setScale(s)}\n                      className={`flex-1 rounded-lg py-1.5 select-none transition-colors ${\n                        scale === s ? segmentActive : segmentIdle\n                      }`}\n                      aria-pressed={scale === s}\n                    >\n                      <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                        {s}x\n                      </TextBody>\n                    </button>\n                  ))}\n                </div>\n              </PanelSection>\n            )}\n\n            {showPrint && (\n              <PanelSection title={te.printSettings}>\n                <PanelField\n                  label={te.includeBleed}\n                  trailing={\n                    <Switch\n                      checked={includeBleed}\n                      onChange={setIncludeBleed}\n                      ariaLabel={te.includeBleed}\n                    />\n                  }\n                />\n                <TextBody as=\"p\" size=\"sm\" className=\"-mt-0.5 px-0.5 text-white/80\">\n                  {te.includeBleedHint}\n                </TextBody>\n                {includeBleed && (\n                  <PanelField\n                    label={te.bleedSizeMm}\n                    trailing={\n                      <input\n                        type=\"number\"\n                        min={1}\n                        max={20}\n                        value={bleedMm}\n                        onChange={(e) => setBleedMm(Number(e.target.value) || 3)}\n                        className=\"w-14 bg-transparent text-right text-[11px] font-medium tabular-nums text-ink-primary focus:outline-none\"\n                      />\n                    }\n                  />\n                )}\n                <PanelField\n                  label={te.cropMarks}\n                  trailing={\n                    <Switch\n                      checked={includeCropMarks}\n                      onChange={(on) => {\n                        setIncludeCropMarks(on);\n                        if (on && !includeBleed) setIncludeBleed(true);\n                      }}\n                      ariaLabel={te.cropMarks}\n                    />\n                  }\n                />\n                <TextBody as=\"p\" size=\"sm\" className=\"-mt-0.5 px-0.5 text-white/80\">\n                  {te.cropMarksHint}\n                </TextBody>\n              </PanelSection>\n            )}\n\n            {showWatermark && (\n              <PanelSection title={te.watermark}>\n                <PanelField\n                  label={te.enableWatermark}\n                  trailing={\n                    <Switch\n                      checked={watermarkEnabled}\n                      onChange={setWatermarkEnabled}\n                      ariaLabel={te.enableWatermark}\n                    />\n                  }\n                />\n\n                {watermarkEnabled && (\n                  <div className=\"flex flex-col gap-2\">\n                    <div className=\"flex gap-1 rounded-xl bg-black-capsule p-1\">\n                      <button\n                        type=\"button\"\n                        onClick={() => setWatermarkType('text')}\n                        className={`flex-1 rounded-lg py-1.5 select-none transition-colors ${\n                          watermarkType === 'text' ? segmentActive : segmentIdle\n                        }`}\n                        aria-pressed={watermarkType === 'text'}\n                      >\n                        <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                          {te.watermarkText}\n                        </TextBody>\n                      </button>\n                      <button\n                        type=\"button\"\n                        onClick={() => setWatermarkType('image')}\n                        className={`flex-1 rounded-lg py-1.5 select-none transition-colors ${\n                          watermarkType === 'image' ? segmentActive : segmentIdle\n                        }`}\n                        aria-pressed={watermarkType === 'image'}\n                      >\n                        <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                          {te.watermarkLogo}\n                        </TextBody>\n                      </button>\n                    </div>\n\n                    {watermarkType === 'text' ? (\n                      <input\n                        type=\"text\"\n                        value={watermarkText}\n                        onChange={(e) => setWatermarkText(e.target.value)}\n                        placeholder={te.watermarkPlaceholder}\n                        className=\"w-full rounded-xl border border-panel-border bg-black-capsule px-3 py-2 text-[11px] font-medium text-ink-primary placeholder:text-white/40 focus:outline-none focus:border-[var(--we-accent)]\"\n                      />\n                    ) : (\n                      <div className=\"flex flex-col gap-2\">\n                        <label className=\"flex cursor-pointer flex-col items-center justify-center gap-2 rounded-xl border-2 border-dashed border-panel-border bg-black-capsule px-4 py-5 transition-colors hover:border-[var(--we-accent)]/50 hover:bg-black-capsule-hover\">\n                          <Upload size={18} className=\"text-[var(--we-accent)]\" aria-hidden />\n                          <TextBody as=\"span\" size=\"sm\" className=\"text-center text-white/80\">\n                            {te.uploadLogo}\n                          </TextBody>\n                          <input\n                            type=\"file\"\n                            accept=\"image/*\"\n                            onChange={handleImageUpload}\n                            className=\"hidden\"\n                          />\n                        </label>\n                        {watermarkImage && (\n                          <div className=\"flex justify-center rounded-xl border border-panel-border bg-black-capsule p-2\">\n                            <img\n                              src={watermarkImage}\n                              alt=\"\"\n                              className=\"max-h-16 object-contain\"\n                            />\n                          </div>\n                        )}\n                      </div>\n                    )}\n\n                    <PanelField\n                      variant=\"slide\"\n                      label={te.opacity}\n                      min={5}\n                      max={100}\n                      step={5}\n                      numericValue={Math.round(watermarkOpacity * 100)}\n                      formatValue={(n) => `${n}%`}\n                      onChange={(n) => setWatermarkOpacity(n / 100)}\n                    />\n                  </div>\n                )}\n              </PanelSection>\n            )}\n\n            {!showScale && !showPrint && !showWatermark && (\n              <TextBody as=\"p\" size=\"sm\" className=\"text-white/80\">\n                {te.exportProject}\n              </TextBody>\n            )}\n          </div>\n        </div>\n\n        {/* Footer */}\n        <div className=\"flex shrink-0 items-center justify-end gap-2 border-t border-panel-border px-4 py-3\">\n          <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={onClose}>\n            {te.cancel}\n          </Button>\n          <Button\n            type=\"button\"\n            variant=\"accent\"\n            size=\"sm\"\n            loading={isExporting}\n            disabled={\n              isExporting ||\n              (watermarkEnabled && watermarkType === 'image' && !watermarkImage)\n            }\n            icon={!isExporting ? <Download size={14} /> : undefined}\n            onClick={handleExport}\n          >\n            {isExporting ? te.exporting : te.exportProject}\n          </Button>\n        </div>\n      </div>\n    </div>,\n    document.body,\n  );\n};\n", "import React from 'react';\nimport { Film } from 'lucide-react';\nimport { VideoPlayer } from './VideoPlayer';\nimport { Timeline } from './Timeline';\nimport { TextBody } from '../../ui';\n\n\nconst BASE_TRACK_HEIGHT = 60;\n\nexport const QAVideo: React.FC = () => {\n  const handleExit = () => {\n    window.location.href = window.location.pathname;\n  };\n\n  return (\n    <div className=\"flex flex-col h-full w-full overflow-hidden text-[#F0F0F5] relative\">\n      {/* QA pill \u2014 mismo patr\u00F3n visual que el SaveStatus badge del editor.\n          Click para volver al editor (limpia ?qa=video). */}\n      <button\n        onClick={handleExit}\n        title=\"Salir de QA \u00B7 volver al editor\"\n        className=\"fixed top-3 right-3 z-50 flex items-center gap-1.5 px-2 py-1 rounded-lg bg-panel border border-panel-border shadow-lg shadow-black/40 backdrop-blur-md select-none hover:bg-[#1C1C26] transition-colors\"\n      >\n        <Film size={12} className=\"text-[var(--we-accent)]\" />\n        <TextBody as=\"span\" size=\"sm\" className=\"text-[#8888A0]\">QA \u00B7 agent-ui/video</TextBody>\n      </button>\n\n      {/* Middle Row \u2014 preview + transport (sin LeftPanel, sin RightSidebar, sin Toolbar) */}\n      <div className=\"flex-1 min-h-0 w-full relative\">\n        <VideoPlayer />\n      </div>\n\n      {/* Bottom Timeline \u2014 sin TimelineToolbar, sin TrackControls */}\n      <div className=\"bg-[#13131A] z-60 border-t border-[#2A2A38] flex-shrink-0\">\n        <Timeline trackHeight={BASE_TRACK_HEIGHT} />\n      </div>\n    </div>\n  );\n};\n\nexport default QAVideo;", "import React, { useRef, useEffect, useCallback, useState } from 'react';\nimport {\n  Play,\n  Pause,\n  ChevronsLeft,\n  ChevronsRight,\n  Rewind,\n  FastForward,\n  Volume2,\n  VolumeX,\n  Maximize,\n} from 'lucide-react';\nimport { useVideoStore, type Clip } from '../../../store/useVideoStore';\nimport { WebGLVideoRenderer } from '../../../lib/effects/webglRenderer';\nimport { getMotionTransform } from '../../../lib/effects/motionUtils';\nimport { drawTextClipToCanvas } from '../../../lib/effects/textRenderer';\nimport { formatTimecodeShort } from '../../../utils/timelineUtils';\nimport { TextBody } from '../../ui';\n\n\nconst dummyBlackCanvas = typeof document !== 'undefined' ? (() => {\n  const c = document.createElement('canvas');\n  c.width = 32;\n  c.height = 32;\n  const ctx = c.getContext('2d');\n  if (ctx) {\n    ctx.fillStyle = '#000000';\n    ctx.fillRect(0, 0, 32, 32);\n  }\n  return c;\n})() : null;\n\nconst dummyWhiteCanvas = typeof document !== 'undefined' ? (() => {\n  const c = document.createElement('canvas');\n  c.width = 32;\n  c.height = 32;\n  const ctx = c.getContext('2d');\n  if (ctx) {\n    ctx.fillStyle = '#ffffff';\n    ctx.fillRect(0, 0, 32, 32);\n  }\n  return c;\n})() : null;\n\nconst dummyTransparentCanvas = typeof document !== 'undefined' ? (() => {\n  const c = document.createElement('canvas');\n  c.width = 32;\n  c.height = 32;\n  const ctx = c.getContext('2d');\n  if (ctx) {\n    ctx.clearRect(0, 0, 32, 32);\n  }\n  return c;\n})() : null;\n\nexport interface VideoPlayerProps {\n  canvasZoom?: number;\n  setCanvasZoom?: (z: number) => void;\n  canvasOffset?: { x: number; y: number };\n  setCanvasOffset?: (offset: { x: number; y: number }) => void;\n  canvasZoomMin?: number;\n  canvasZoomMax?: number;\n  canvasZoomStep?: number;\n}\n\nexport const VideoPlayer: React.FC<VideoPlayerProps> = ({\n  canvasZoom    = 1,\n  setCanvasZoom,\n  canvasOffset  = { x: 0, y: 0 },\n  setCanvasOffset,\n  canvasZoomMin  = 0.25,\n  canvasZoomMax  = 4,\n  canvasZoomStep = 0.25,\n}) => {\n  const canvasRef = useRef<HTMLCanvasElement>(null);\n  const containerRef = useRef<HTMLDivElement>(null);\n  // Contenedor del preview + transport; target del Fullscreen API.\n  const previewContainerRef = useRef<HTMLDivElement>(null);\n  // WebGL Renderer cache\n  const webglRendererRef = useRef<WebGLVideoRenderer | null>(null);\n  const offscreenTextCanvasRef = useRef<HTMLCanvasElement | null>(null);\n  const initializedClipsRef = useRef<Set<string>>(new Set());\n  const lastPlayheadTimeRef = useRef<number>(0);\n\n  const isPanningRef   = useRef(false);\n  const panStartRef    = useRef({ x: 0, y: 0, ox: 0, oy: 0 });\n\n  const clampZoom = (v: number) => Math.max(canvasZoomMin, Math.min(canvasZoomMax, v));\n\n  // Wheel zoom (Ctrl + wheel) on the preview area\n  const handleWheelZoom = useCallback((e: React.WheelEvent) => {\n    if (!e.ctrlKey) return;\n    e.preventDefault();\n    const delta = e.deltaY < 0 ? canvasZoomStep : -canvasZoomStep;\n    setCanvasZoom?.(clampZoom(Math.round((canvasZoom + delta) * 100) / 100));\n  }, [canvasZoom, canvasZoomStep, canvasZoomMin, canvasZoomMax]);\n\n  // Drag pan (middle-click or Alt+drag)\n  const handlePanStart = useCallback((e: React.MouseEvent) => {\n    if (e.button !== 1 && !(e.button === 0 && e.altKey)) return;\n    e.preventDefault();\n    isPanningRef.current = true;\n    panStartRef.current = { x: e.clientX, y: e.clientY, ox: canvasOffset.x, oy: canvasOffset.y };\n\n    const onMove = (ev: MouseEvent) => {\n      if (!isPanningRef.current) return;\n      setCanvasOffset?.({\n        x: panStartRef.current.ox + (ev.clientX - panStartRef.current.x),\n        y: panStartRef.current.oy + (ev.clientY - panStartRef.current.y),\n      });\n    };\n    const onUp = () => {\n      isPanningRef.current = false;\n      window.removeEventListener('mousemove', onMove);\n      window.removeEventListener('mouseup',   onUp);\n    };\n    window.addEventListener('mousemove', onMove);\n    window.addEventListener('mouseup',   onUp);\n  }, [canvasOffset]);\n\nconst {\n    tracks,\n    assets,\n    playheadTime,\nsetPlayhead,\n    isPlaying,\n    setIsPlaying,\n    transitions,\n    aspectRatio: aspect,\n    projectDuration,\n  } = useVideoStore();\n\n  // T-20260727-02: duraci\u00F3n REAL del video = max(startTime + duration de\n  // los clips de VIDEO \u00FAnicamente). Audio/subtitle/text no se cuentan para\n  // la duraci\u00F3n del \"video\" que se muestra al usuario. Si no hay clips\n  // de video, devuelve 0.\n  const videoDuration = (() => {\n    let maxEnd = 0;\n    tracks.forEach((track) => {\n      if (track.type !== 'video') return;\n      track.clips.forEach((clip) => {\n        const end = clip.startTime + clip.duration;\n        if (end > maxEnd) maxEnd = end;\n      });\n    });\n    return maxEnd;\n  })();\n\n  // T-20260727-02 refinamiento: estado local del control de reproducci\u00F3n\n  // del editor ag\u00E9ntico. El mute es UI-only (el consumidor cablea su propia\n  // l\u00F3gica de audio global). La duraci\u00F3n del timeline ya no es editable\n  // \u2014 el Timeline la auto-deriva del contenido (max end + 10s) y el pill\n  // solo la muestra en formato MM:SS:CC (HH:MM:SS:CC si > 59min).\n  const [isMuted, setIsMuted] = useState(false);\n\n  const [isFullscreen, setIsFullscreen] = useState(false);\n  useEffect(() => {\n    const onChange = () => setIsFullscreen(!!document.fullscreenElement);\n    document.addEventListener('fullscreenchange', onChange);\n    return () => document.removeEventListener('fullscreenchange', onChange);\n  }, []);\n\n  // T-20260727-02 refinamiento: buffer del canvas en HiDPI (1:1 con el\n  // display). El drawing buffer se ajusta a `displaySize * dpr` (cap a 2x)\n  // para que el WebGL renderice a la resoluci\u00F3n final visible \u2014 sin upscale\n  // borroso, sin pixelaci\u00F3n. Se re-observa en cada cambio de modo\n  // (normal / fullscreen). El render loop lee `canvas.width/height` cada\n  // frame, as\u00ED que el siguiente frame ya usa el nuevo viewport.\n  useEffect(() => {\n    const canvas = canvasRef.current;\n    if (!canvas) return;\n    const dpr = Math.min(window.devicePixelRatio || 1, 2);\n    const update = () => {\n      const rect = canvas.getBoundingClientRect();\n      if (rect.width === 0 || rect.height === 0) return;\n      const w = Math.max(1, Math.round(rect.width * dpr));\n      const h = Math.max(1, Math.round(rect.height * dpr));\n      if (canvas.width !== w || canvas.height !== h) {\n        canvas.width = w;\n        canvas.height = h;\n      }\n    };\n    update();\n    const observer = new ResizeObserver(update);\n    observer.observe(canvas);\n    return () => observer.disconnect();\n  }, [isFullscreen]);\n\n  const handleFullscreen = useCallback(() => {\n    if (document.fullscreenElement) {\n      void document.exitFullscreen();\n    } else {\n      // Fullscreen sobre el contenedor del preview (canvas + transport),\n      // no sobre el documento entero (eso incluir\u00EDa la UI del navegador).\n      void previewContainerRef.current?.requestFullscreen?.();\n    }\n  }, []);\n\n  // T-20260727-02: auto-hide de los controles en fullscreen tras 5s de\n  // inactividad del mouse. Al mover el mouse, vuelven a aparecer\n  // instant\u00E1neamente. En modo normal los controles siempre est\u00E1n visibles.\n  const [controlsVisible, setControlsVisible] = useState(true);\n  const idleTimerRef = useRef<number | null>(null);\n  useEffect(() => {\n    if (!isFullscreen) {\n      if (idleTimerRef.current !== null) {\n        window.clearTimeout(idleTimerRef.current);\n        idleTimerRef.current = null;\n      }\n      // Garantizar que al salir de fullscreen los controles son visibles.\n      // Lo hacemos con un microtask para evitar el lint de cascading renders.\n      queueMicrotask(() => setControlsVisible(true));\n      return;\n    }\n    const onMove = () => {\n      setControlsVisible(true);\n      if (idleTimerRef.current !== null) {\n        window.clearTimeout(idleTimerRef.current);\n      }\n      idleTimerRef.current = window.setTimeout(() => {\n        setControlsVisible(false);\n        idleTimerRef.current = null;\n      }, 3000);\n    };\n    // Activar inmediatamente al entrar a fullscreen (arranca el timer).\n    onMove();\n    window.addEventListener('mousemove', onMove);\n    return () => {\n      window.removeEventListener('mousemove', onMove);\n      if (idleTimerRef.current !== null) {\n        window.clearTimeout(idleTimerRef.current);\n        idleTimerRef.current = null;\n      }\n    };\n  }, [isFullscreen]);\n\n  // Keyboard Shortcuts (Space, Prev Frame, Next Frame)\n  useEffect(() => {\n    const handleKeyDown = (e: KeyboardEvent) => {\n      if (['INPUT', 'TEXTAREA'].includes((e.target as HTMLElement).tagName)) {\n        return;\n      }\n\n      if (e.code === 'Space') {\n        e.preventDefault();\n        setIsPlaying(!isPlaying);\n      } else if (e.key === ',') {\n        setPlayhead(Math.max(0, playheadTime - 1/30));\n      } else if (e.key === '.') {\n        setPlayhead(playheadTime + 1/30);\n      }\n    };\n\n    window.addEventListener('keydown', handleKeyDown);\n    return () => window.removeEventListener('keydown', handleKeyDown);\n  }, [isPlaying, playheadTime, setIsPlaying, setPlayhead]);\n\n  // Main WebGL rendering loop\n  useEffect(() => {\n    let animationFrameId: number;\n    let lastTime = performance.now();\n\n    // Reset initialization tracking when the playback setup changes\n    initializedClipsRef.current.clear();\n\n    const renderTick = async () => {\n      const now = performance.now();\n      const deltaSec = (now - lastTime) / 1000;\n      lastTime = now;\n      \n      const storeState = useVideoStore.getState();\n      const currentIsPlaying = storeState.isPlaying;\n      let currentPlayhead = storeState.playheadTime;\n      \n      // Update time if playing, using direct store state to bypass React state synchronization lag/jitter\n      if (currentIsPlaying) {\n        currentPlayhead = currentPlayhead + deltaSec;\n        setPlayhead(currentPlayhead);\n      }\n\n      // Handle playhead jumps (manual scrubbing) or pausing\n      const expectedPlayhead = lastPlayheadTimeRef.current + (currentIsPlaying ? deltaSec : 0);\n      const playheadJumped = Math.abs(currentPlayhead - expectedPlayhead) > 0.2;\n      \n      if (playheadJumped || !currentIsPlaying) {\n        initializedClipsRef.current.clear();\n      }\n      lastPlayheadTimeRef.current = currentPlayhead;\n\n      // Draw onto WebGL canvas\n      const canvas = canvasRef.current;\n      if (canvas) {\n        // Initialize WebGL renderer on demand\n        let gl = canvas.getContext('webgl2', { premultipliedAlpha: false });\n        if (gl) {\n          if (!webglRendererRef.current) {\n            webglRendererRef.current = new WebGLVideoRenderer(gl);\n          }\n          const renderer = webglRendererRef.current;\n\n          // Enable alpha blending\n          gl.viewport(0, 0, canvas.width, canvas.height);\n          gl.clearColor(0.04, 0.04, 0.06, 1.0); // #0A0A0F matching background\n          gl.clear(gl.COLOR_BUFFER_BIT);\n          gl.enable(gl.BLEND);\n          gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n\n          // Get active video clips\n          // Keep muted video tracks visible; mute only their audio.\n          const videoTracks = tracks.filter((t) => t.type === 'video');\n          const activeClips: { clip: Clip; videoEl: HTMLVideoElement }[] = [];\n\n          videoTracks.forEach((track) => {\n            track.clips.forEach((clip) => {\n              if (currentPlayhead >= clip.startTime && currentPlayhead < clip.startTime + clip.duration) {\n                const videoEl = document.getElementById(`preview-media-${clip.assetId}`) as HTMLVideoElement;\n                if (videoEl) {\n                  activeClips.push({ clip, videoEl });\n                }\n              }\n            });\n          });\n\n          // Sync Audio Elements (Only for audio track types to avoid double-seeking video layers)\n          const audioTracks = tracks.filter((t) => t.type === 'audio');\n          audioTracks.forEach((track) => {\n            track.clips.forEach((clip) => {\n              const mediaId = `preview-media-${clip.assetId}`;\n              const mediaEl = document.getElementById(mediaId) as HTMLMediaElement;\n              if (!mediaEl) return;\n\n              const isClipActive = currentPlayhead >= clip.startTime && currentPlayhead < clip.startTime + clip.duration;\n              const isTrackMuted = track.muted;\n              const isClipMuted = clip.muted;\n\n              if (isClipActive && !isTrackMuted && !isClipMuted) {\n                mediaEl.volume = Math.max(0, Math.min(1, clip.volume));\n                mediaEl.muted = false;\n                const mediaOffset = (currentPlayhead - clip.startTime) * clip.speed + clip.trimIn;\n\n                if (currentIsPlaying) {\n                  if (mediaEl.paused && !mediaEl.seeking) {\n                    mediaEl.play().catch(() => {});\n                  }\n                  mediaEl.playbackRate = clip.speed;\n\n                  // Seek once when clip first becomes active during playback\n                  if (!initializedClipsRef.current.has(clip.id)) {\n                    if (!mediaEl.seeking && Math.abs(mediaEl.currentTime - mediaOffset) / clip.speed > 0.1) {\n                      mediaEl.currentTime = mediaOffset;\n                    }\n                    initializedClipsRef.current.add(clip.id);\n                  } else {\n                    // Drift catch-up guard for long plays (evaluated in real-time seconds)\n                    if (!mediaEl.seeking && Math.abs(mediaEl.currentTime - mediaOffset) / clip.speed > 1.5) {\n                      initializedClipsRef.current.delete(clip.id);\n                    }\n                  }\n                } else {\n                  // Paused/Scrubbing\n                  if (!mediaEl.paused) {\n                    mediaEl.pause();\n                  }\n                  if (!mediaEl.seeking && Math.abs(mediaEl.currentTime - mediaOffset) / clip.speed > 0.05) {\n                    mediaEl.currentTime = mediaOffset;\n                  }\n                }\n              } else {\n                if (!mediaEl.paused) {\n                  mediaEl.pause();\n                }\n                mediaEl.muted = true;\n              }\n            });\n          });\n\n          // Sort active video layers\n          activeClips.sort((a, b) => {\n            const trackOrder = ['v1', 'v2'];\n            return trackOrder.indexOf(a.clip.trackId) - trackOrder.indexOf(b.clip.trackId);\n          });\n\n          // Draw active video frames or cross-transition overlays\n          for (let i = 0; i < activeClips.length; i++) {\n            const { clip, videoEl } = activeClips[i];\n            const clipOffsetTime = (currentPlayhead - clip.startTime) * clip.speed + clip.trimIn;\n            \n            if (currentIsPlaying) {\n              if (videoEl.paused && !videoEl.seeking) {\n                videoEl.play().catch(() => {});\n              }\n              videoEl.playbackRate = clip.speed;\n              videoEl.preservesPitch = true;\n              if ((videoEl as any).webkitPreservesPitch !== undefined) {\n                (videoEl as any).webkitPreservesPitch = true;\n              }\n              const isTrackMuted = tracks.find((t) => t.id === clip.trackId)?.muted;\n              videoEl.muted = isTrackMuted || clip.muted;\n              videoEl.volume = Math.max(0, Math.min(1, clip.volume));\n\n              // Seek once when clip first becomes active during playback\n              if (!initializedClipsRef.current.has(clip.id)) {\n                if (!videoEl.seeking && Math.abs(videoEl.currentTime - clipOffsetTime) / clip.speed > 0.1) {\n                  videoEl.currentTime = clipOffsetTime;\n                }\n                initializedClipsRef.current.add(clip.id);\n              } else {\n                // Drift catch-up guard for long plays (evaluated in real-time seconds)\n                if (!videoEl.seeking && Math.abs(videoEl.currentTime - clipOffsetTime) / clip.speed > 1.5) {\n                  initializedClipsRef.current.delete(clip.id);\n                }\n              }\n            } else {\n              if (!videoEl.paused) videoEl.pause();\n              videoEl.muted = true;\n\n              // Continuous sync when scrubbing/paused, or force load if not ready\n              const needsInitialFrameLoad = videoEl.readyState < 2;\n              const shouldSeek = (!videoEl.seeking && Math.abs(videoEl.currentTime - clipOffsetTime) / clip.speed > 0.05) || (needsInitialFrameLoad && !videoEl.seeking);\n              if (shouldSeek) {\n                videoEl.currentTime = clipOffsetTime;\n              }\n            }\n\n            // Face tracking removed\n\n            // Check if there is an active transition at this playhead\n            // Priority:\n            // 1. Between clips transition (fromClipId === clip.id && toClipId !== 'none')\n            // 2. Start transition (Fade In) (fromClipId === 'none' && toClipId === clip.id)\n            // 3. End transition (Fade Out) (fromClipId === clip.id && toClipId === 'none')\n\n            const betweenTrans = transitions.find((t) => \n              t.fromClipId === clip.id && \n              t.toClipId !== 'none' &&\n              currentPlayhead >= (clip.startTime + clip.duration - t.duration / 2) &&\n              currentPlayhead <= (clip.startTime + clip.duration + t.duration / 2)\n            );\n\n            const startTrans = transitions.find((t) =>\n              t.toClipId === clip.id &&\n              t.fromClipId === 'none' &&\n              currentPlayhead >= clip.startTime &&\n              currentPlayhead <= clip.startTime + t.duration\n            );\n\n            const endTrans = transitions.find((t) =>\n              t.fromClipId === clip.id &&\n              t.toClipId === 'none' &&\n              currentPlayhead >= (clip.startTime + clip.duration - t.duration) &&\n              currentPlayhead <= (clip.startTime + clip.duration)\n            );\n\n            if (betweenTrans) {\n              // Fetch toClip\n              let toClip: Clip | null = null;\n              for (const tr of tracks) {\n                const found = tr.clips.find((c) => c.id === betweenTrans.toClipId);\n                if (found) {\n                  toClip = found;\n                  break;\n                }\n              }\n\n              const toVideoEl = toClip ? document.getElementById(`preview-media-${toClip.assetId}`) as HTMLVideoElement : null;\n              if (toVideoEl && toClip) {\n                const toOffsetTime = (currentPlayhead - toClip.startTime) * toClip.speed + toClip.trimIn;\n\n                // Sync toVideoEl playback state\n                if (currentIsPlaying) {\n                  if (toVideoEl.paused && !toVideoEl.seeking) {\n                    toVideoEl.play().catch(() => {});\n                  }\n                  toVideoEl.playbackRate = toClip.speed;\n                  toVideoEl.preservesPitch = true;\n                  if ((toVideoEl as any).webkitPreservesPitch !== undefined) {\n                    (toVideoEl as any).webkitPreservesPitch = true;\n                  }\n                  const isTrackMuted = tracks.find((t) => t.id === toClip!.trackId)?.muted;\n                  toVideoEl.muted = isTrackMuted || toClip.muted;\n                  toVideoEl.volume = Math.max(0, Math.min(1, toClip.volume));\n\n                  // Seek once when transition starts during playback\n                  const transInitKey = `trans-${betweenTrans.id}-${toClip.id}`;\n                  if (!initializedClipsRef.current.has(transInitKey)) {\n                    if (!toVideoEl.seeking && Math.abs(toVideoEl.currentTime - toOffsetTime) / toClip.speed > 0.1) {\n                      toVideoEl.currentTime = toOffsetTime;\n                    }\n                    initializedClipsRef.current.add(transInitKey);\n                  } else {\n                    // Drift catch-up guard for transitions (evaluated in real-time seconds)\n                    if (!toVideoEl.seeking && Math.abs(toVideoEl.currentTime - toOffsetTime) / toClip.speed > 1.5) {\n                      initializedClipsRef.current.delete(transInitKey);\n                    }\n                  }\n                } else {\n                  if (!toVideoEl.paused) toVideoEl.pause();\n                  toVideoEl.muted = true;\n\n                  // Continuous sync when scrubbing/paused, or force load if not ready\n                  const toNeedsLoad = toVideoEl.readyState < 2;\n                  const shouldSeek = (!toVideoEl.seeking && Math.abs(toVideoEl.currentTime - toOffsetTime) / toClip.speed > 0.05) || (toNeedsLoad && !toVideoEl.seeking);\n                  if (shouldSeek) {\n                    toVideoEl.currentTime = toOffsetTime;\n                  }\n                }\n\n                const transStart = clip.startTime + clip.duration - betweenTrans.duration / 2;\n                const progress = (currentPlayhead - transStart) / betweenTrans.duration;\n                const clampedProgress = Math.max(0, Math.min(1, progress));\n\n                // Only draw transition if BOTH video elements are ready\n                if (videoEl.readyState >= 2 && toVideoEl.readyState >= 2) {\n                  renderer.drawTransition(\n                    videoEl,\n                    toVideoEl,\n                    betweenTrans.type,\n                    clampedProgress,\n                    canvas.width,\n                    canvas.height\n                  );\n                } else if (videoEl.readyState >= 2) {\n                  renderer.drawLayer(videoEl, clip, clipOffsetTime, canvas.width, canvas.height);\n                } else if (toVideoEl.readyState >= 2) {\n                  renderer.drawLayer(toVideoEl, toClip, toOffsetTime, canvas.width, canvas.height);\n                }\n                continue; // skip drawing standard layer\n              }\n            } else if (startTrans) {\n              // Fade In (From Black/White/Transparent canvas to selected clip)\n              const colorType = startTrans.params.targetColor || (startTrans.type === 'fade-white' ? 'white' : 'black');\n              const dummyCanvas = colorType === 'white' ? dummyWhiteCanvas : colorType === 'transparent' ? dummyTransparentCanvas : dummyBlackCanvas;\n              \n              const progress = (currentPlayhead - clip.startTime) / startTrans.duration;\n              const clampedProgress = Math.max(0, Math.min(1, progress));\n\n              if (videoEl.readyState >= 2 && dummyCanvas) {\n                renderer.drawTransition(\n                  dummyCanvas,\n                  videoEl,\n                  startTrans.type,\n                  clampedProgress,\n                  canvas.width,\n                  canvas.height\n                );\n              } else if (videoEl.readyState >= 2) {\n                renderer.drawLayer(videoEl, clip, clipOffsetTime, canvas.width, canvas.height);\n              }\n              continue;\n            } else if (endTrans) {\n              // Fade Out (From selected clip to Black/White/Transparent canvas)\n              const colorType = endTrans.params.targetColor || (endTrans.type === 'fade-white' ? 'white' : 'black');\n              const dummyCanvas = colorType === 'white' ? dummyWhiteCanvas : colorType === 'transparent' ? dummyTransparentCanvas : dummyBlackCanvas;\n              \n              const transStart = clip.startTime + clip.duration - endTrans.duration;\n              const progress = (currentPlayhead - transStart) / endTrans.duration;\n              const clampedProgress = Math.max(0, Math.min(1, progress));\n\n              if (videoEl.readyState >= 2 && dummyCanvas) {\n                renderer.drawTransition(\n                  videoEl,\n                  dummyCanvas,\n                  endTrans.type,\n                  clampedProgress,\n                  canvas.width,\n                  canvas.height\n                );\n              } else if (videoEl.readyState >= 2) {\n                renderer.drawLayer(videoEl, clip, clipOffsetTime, canvas.width, canvas.height);\n              }\n              continue;\n            }\n\n            // Draw regular WebGL layer only if the video element is ready (readyState >= 2)\n            if (videoEl.readyState >= 2) {\n              renderer.drawLayer(videoEl, clip, clipOffsetTime, canvas.width, canvas.height);\n            }\n          }\n\n          // Pause and mute all video elements that are not active\n          assets.forEach((asset) => {\n            if (asset.type === 'video') {\n              const isActive = activeClips.some((ac) => ac.clip.assetId === asset.id);\n              if (!isActive) {\n                const videoEl = document.getElementById(`preview-media-${asset.id}`) as HTMLVideoElement;\n                if (videoEl) {\n                  if (!videoEl.paused) videoEl.pause();\n                  videoEl.muted = true;\n                }\n              }\n            }\n          });\n\n          // Render Image Graphics overlays\n          const imageTracks = tracks.filter((t) => t.type === 'image' && !t.muted);\n          imageTracks.forEach((track) => {\n            track.clips.forEach((clip) => {\n              if (currentPlayhead >= clip.startTime && currentPlayhead < clip.startTime + clip.duration) {\n                const imgEl = document.getElementById(`preview-media-${clip.assetId}`) as HTMLImageElement;\n                if (imgEl && imgEl.complete) {\n                  const clipOffsetTime = currentPlayhead - clip.startTime;\n                  \n                  // Compute dynamic motions: Ken Burns/shake\n                  const motion = getMotionTransform(clip, clipOffsetTime);\n                  \n                  const duration = clip.duration || 5.0;\n                  const progressIn = clipOffsetTime; // time from start\n                  const progressOut = duration - clipOffsetTime; // time to end\n\n                  const animIn = clip.animationIn;\n                  const animInDur = clip.animationInDuration || 0.5;\n                  const animOut = clip.animationOut;\n                  const animOutDur = clip.animationOutDuration || 0.5;\n\n                  let opacity = clip.opacity !== undefined ? clip.opacity * motion.scale : motion.scale;\n                  let x = (clip.x ?? 0.5) + motion.xOffset;\n                  let y = (clip.y ?? 0.5) + motion.yOffset;\n                  let scaleX = clip.scaleX !== undefined ? clip.scaleX : 1.0;\n                  let scaleY = clip.scaleY !== undefined ? clip.scaleY : 1.0;\n                  let rotation = (clip.rotation || 0) + motion.rotationOffset;\n                  let tempEffects = [...(clip.effects || [])];\n\n                  // Intro Animation\n                  if (animIn && progressIn < animInDur) {\n                    const t = progressIn / animInDur; // 0 to 1\n                    if (animIn === 'fade') {\n                      opacity *= t;\n                    } else if (animIn === 'slide-up') {\n                      y += (1 - t) * 0.15;\n                      opacity *= t;\n                    } else if (animIn === 'slide-down') {\n                      y -= (1 - t) * 0.15;\n                      opacity *= t;\n                    } else if (animIn === 'slide-left') {\n                      x += (1 - t) * 0.15;\n                      opacity *= t;\n                    } else if (animIn === 'slide-right') {\n                      x -= (1 - t) * 0.15;\n                      opacity *= t;\n                    } else if (animIn === 'scale-in') {\n                      scaleX *= t;\n                      scaleY *= t;\n                      opacity *= t;\n                    } else if (animIn === 'blur-in') {\n                      opacity *= t;\n                      tempEffects.push({\n                        id: 'temp-blur-in',\n                        clipId: clip.id,\n                        effectType: 'blur-gaussian',\n                        enabled: true,\n                        order: tempEffects.length,\n                        keyframes: [],\n                        startTime: 0,\n                        endTime: clip.duration,\n                        params: {\n                          radius: (1 - t) * 20\n                        }\n                      });\n                    } else if (animIn === 'rotate-in') {\n                      rotation += (1 - t) * 90;\n                      opacity *= t;\n                    }\n                  }\n\n                  // Outro Animation\n                  if (animOut && progressOut < animOutDur) {\n                    const t = progressOut / animOutDur; // 1 to 0\n                    if (animOut === 'fade') {\n                      opacity *= t;\n                    } else if (animOut === 'slide-up') {\n                      y -= (1 - t) * 0.15;\n                      opacity *= t;\n                    } else if (animOut === 'slide-down') {\n                      y += (1 - t) * 0.15;\n                      opacity *= t;\n                    } else if (animOut === 'slide-left') {\n                      x -= (1 - t) * 0.15;\n                      opacity *= t;\n                    } else if (animOut === 'slide-right') {\n                      x += (1 - t) * 0.15;\n                      opacity *= t;\n                    } else if (animOut === 'scale-out') {\n                      scaleX *= t;\n                      scaleY *= t;\n                      opacity *= t;\n                    } else if (animOut === 'blur-out') {\n                      opacity *= t;\n                      tempEffects.push({\n                        id: 'temp-blur-out',\n                        clipId: clip.id,\n                        effectType: 'blur-gaussian',\n                        enabled: true,\n                        order: tempEffects.length,\n                        keyframes: [],\n                        startTime: 0,\n                        endTime: clip.duration,\n                        params: {\n                          radius: (1 - t) * 20\n                        }\n                      });\n                    }\n                  }\n\n                  // Temporarily update position/scale in properties block for WebGL layer placement\n                  const animatedClip = {\n                    ...clip,\n                    opacity,\n                    x,\n                    y,\n                    scaleX,\n                    scaleY,\n                    rotation,\n                    effects: tempEffects\n                  };\n\n                  renderer.drawLayer(imgEl, animatedClip, clipOffsetTime, canvas.width, canvas.height);\n                }\n              }\n            });\n          });\n\n          // Draw Text overlays onto secondary 2D canvas, then upload to WebGL\n          const textTracks = tracks.filter((t) => t.type === 'text' && !t.muted);\n          let hasActiveText = false;\n\n          // Prepare offscreen canvas\n          if (!offscreenTextCanvasRef.current) {\n            offscreenTextCanvasRef.current = document.createElement('canvas');\n          }\n          const textCanvas = offscreenTextCanvasRef.current;\n          textCanvas.width = canvas.width;\n          textCanvas.height = canvas.height;\n          const textCtx = textCanvas.getContext('2d');\n\n          if (textCtx) {\n            textCtx.clearRect(0, 0, textCanvas.width, textCanvas.height);\n            \n            textTracks.forEach((track) => {\n              track.clips.forEach((clip) => {\n                if (currentPlayhead >= clip.startTime && currentPlayhead < clip.startTime + clip.duration) {\n                  const clipOffsetTime = currentPlayhead - clip.startTime;\n                  drawTextClipToCanvas(textCtx, clip, clipOffsetTime, textCanvas.width, textCanvas.height);\n                  hasActiveText = true;\n                }\n              });\n            });\n\n            // Upload to WebGL as transparent overlay\n            if (hasActiveText) {\n              const dummyTextClip: Clip = {\n                id: 'dummy_text_overlay',\n                trackId: '',\n                assetId: '',\n                startTime: 0,\n                duration: 9999,\n                trimIn: 0,\n                trimOut: 0,\n                speed: 1.0,\n                volume: 1.0,\n                opacity: 1.0,\n                muted: false,\n                type: 'text'\n              };\n              renderer.drawLayer(textCanvas, dummyTextClip, 0, canvas.width, canvas.height);\n            }\n          }\n\n          // Draw standard subtitles 2D context directly on top if any\n          const subtitleTrack = tracks.find((t) => t.id === 'sub' && !t.muted);\n          if (subtitleTrack) {\n            const activeSubtitle = subtitleTrack.clips.find(\n              (clip) => currentPlayhead >= clip.startTime && currentPlayhead < clip.startTime + clip.duration\n            );\n\n            if (activeSubtitle && activeSubtitle.text) {\n              if (textCtx) {\n                const clipOffsetTime = currentPlayhead - activeSubtitle.startTime;\n                drawTextClipToCanvas(textCtx, activeSubtitle, clipOffsetTime, textCanvas.width, textCanvas.height);\n\n                // Re-draw textCanvas to pick up subtitles\n                const dummyTextClip: Clip = {\n                  id: 'dummy_text_overlay_subs',\n                  trackId: '',\n                  assetId: '',\n                  startTime: 0,\n                  duration: 9999,\n                  trimIn: 0,\n                  trimOut: 0,\n                  speed: 1.0,\n                  volume: 1.0,\n                  opacity: 1.0,\n                  muted: false,\n                  type: 'text'\n                };\n                renderer.drawLayer(textCanvas, dummyTextClip, 0, canvas.width, canvas.height);\n              }\n            }\n          }\n        }\n      }\n\n      animationFrameId = requestAnimationFrame(renderTick);\n    };\n\n    renderTick();\n\n    return () => {\n      cancelAnimationFrame(animationFrameId);\n    };\n  }, [isPlaying, tracks, aspect, setPlayhead, transitions]);\n\n  const getCanvasDimensions = () => {\n    if (aspect === '16:9') return { width: 640, height: 360 };\n    if (aspect === '9:16') return { width: 270, height: 480 };\n    return { width: 400, height: 400 };\n  };\n\n  const canvasDim = getCanvasDimensions();\n\n  return (\n    <div className=\"flex-1 bg-[#16161a] border-b border-[#2A2A38] flex flex-col items-center justify-between p-4 relative select-none\">\n      \n      {/* Hidden Asset Media Cache Elements */}\n      <div \n        style={{\n          position: 'fixed',\n          top: 0,\n          left: 0,\n          width: '1px',\n          height: '1px',\n          opacity: 0.001,\n          pointerEvents: 'none',\n          overflow: 'hidden',\n          zIndex: -100\n        }}\n      >\n        {assets.map((asset) => {\n          // Skip assets whose blob URL hasn't been recovered yet (e.g. right after reload)\n          if (!asset.url) return null;\n          if (asset.type === 'image') {\n            return (\n              <img\n                key={`${asset.id}-${asset.url}`}\n                id={`preview-media-${asset.id}`}\n                src={asset.url}\n                alt={asset.name}\n                className=\"max-w-none h-auto\"\n              />\n            );\n          }\n          return (\n            <video\n              key={`${asset.id}-${asset.url}`}\n              id={`preview-media-${asset.id}`}\n              src={asset.url}\n              preload=\"auto\"\n              muted={true}\n              playsInline\n              className=\"max-w-none h-auto\"\n            />\n          );\n        })}\n      </div>\n\n\n\n      {/* Preview + Controls container \u2014 target del Fullscreen API.\n            Envuelve solo el canvas y la transport pill (no la cach\u00E9 de\n            medios oculta), de modo que al entrar en pantalla completa se\n            vea exactamente el preview del video con sus controles, sin la\n            UI del navegador ni del editor. */}\n      <div\n        ref={previewContainerRef}\n        className={`flex-1 flex flex-col items-center justify-between w-full relative ${\n          isFullscreen ? 'bg-[#0A0A0F]' : ''\n        }`}\n      >\n\n      {/* Interactive Bounding Frame wrapper */}\n      <div\n        ref={containerRef}\n        className={`flex-1 flex items-center justify-center w-full ${\n          isFullscreen ? '' : 'max-h-[72%] my-4'\n        }`}\n        onWheel={handleWheelZoom}\n        onMouseDown={handlePanStart}\n        style={{ cursor: canvasZoom > 1 ? 'grab' : 'default' }}\n      >\n        <div\n          className={`relative shadow-2xl rounded overflow-visible border border-[#2A2A38]/50 ${\n            isFullscreen ? 'w-full h-full' : ''\n          }`}\n          style={{\n            transform: `scale(${canvasZoom}) translate(${canvasOffset.x / canvasZoom}px, ${canvasOffset.y / canvasZoom}px)`,\n            transformOrigin: 'center center',\n            transition: isPanningRef.current ? 'none' : 'transform 0.1s ease-out',\n          }}\n        >\n          <canvas\n            ref={canvasRef}\n            width={canvasDim.width}\n            height={canvasDim.height}\n            className={`block bg-[#0A0A0F] ${\n              isFullscreen\n                ? 'w-full h-full object-contain'\n                : 'max-w-full max-h-[420px]'\n            }`}\n          />\n        </div>\n      </div>\n\n      {/* Playback Controls */}\n      {/* Transport controls pill \u2014 layout para el editor ag\u00E9ntico:\n            [Vol] \u2502 [<][-1s]   [current] [\u25B6] [duration \u2195]   [+1s][>] \u2502 [\u26F6]\n          En fullscreen se posiciona absolute sobre el video (overlay\n          bottom-center con backdrop-blur) para que el usuario pueda\n          pausar/reproducir sin salir del modo pantalla completa.\n          Auto-hide tras 5s sin movimiento del mouse en fullscreen. */}\n      <div\n        className={`bg-[#13131A]/90 border border-[#2A2A38] rounded-full px-3 py-2 flex items-center gap-2 select-none shadow-2xl ${\n          isFullscreen\n            ? `absolute bottom-4 left-1/2 -translate-x-1/2 z-20 backdrop-blur-md transition-opacity duration-300 ${\n                controlsVisible ? 'opacity-100' : 'opacity-0 pointer-events-none'\n              }`\n            : 'z-10'\n        }`}\n      >\n\n        {/* 1. Volumen general */}\n        <button\n          onClick={() => setIsMuted((v) => !v)}\n          aria-label={isMuted ? 'Activar sonido' : 'Silenciar'}\n          title={isMuted ? 'Activar sonido' : 'Silenciar'}\n          className=\"text-[#8888A0] hover:text-[#F0F0F5] transition-colors p-1\"\n        >\n          {isMuted ? <VolumeX size={16} /> : <Volume2 size={16} />}\n        </button>\n\n        {/* Divisor vertical */}\n        <div className=\"w-px h-6 bg-[#2A2A38]\" aria-hidden />\n\n        {/* 2. Botones existentes \u2014 mitad izquierda */}\n        <button\n          onClick={() => setPlayhead(0)}\n          aria-label=\"Ir al inicio\"\n          title=\"Ir al inicio\"\n          className=\"text-[#8888A0] hover:text-[#F0F0F5] transition-colors p-1\"\n        >\n          <ChevronsLeft size={16} />\n        </button>\n\n        <button\n          onClick={() => setPlayhead(Math.max(0, playheadTime - 1))}\n          aria-label=\"Retroceder 1 segundo\"\n          title=\"Retroceder 1 segundo\"\n          className=\"text-[#8888A0] hover:text-[#F0F0F5] transition-colors p-1\"\n        >\n          <Rewind size={16} />\n        </button>\n\n        {/* 3. Timer del tiempo (current time, read-only, MM:SS.MS / HH:MM:SS.MS) */}\n        <TextBody as=\"span\" size=\"sm\" className=\"font-mono text-[#8888A0] tabular-nums min-w-[78px] text-center px-1\">\n          {formatTimecodeShort(playheadTime)}\n        </TextBody>\n\n        {/* 4. Play (centrado, prominente) */}\n        <button\n          onClick={() => setIsPlaying(!isPlaying)}\n          aria-label={isPlaying ? 'Pausar' : 'Reproducir'}\n          title={isPlaying ? 'Pausar' : 'Reproducir'}\n          className=\"w-9 h-9 rounded-full bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] text-white flex items-center justify-center transition-all hover:scale-105 active:scale-95 shadow-md shadow-[color-mix(in_srgb,var(--we-accent)_30%,transparent)]\"\n        >\n          {isPlaying ? (\n            <Pause size={15} fill=\"currentColor\" />\n          ) : (\n            <Play size={15} fill=\"currentColor\" className=\"ml-0.5\" />\n          )}\n        </button>\n\n        {/* 5. Timer del final (read-only, muestra la duraci\u00F3n REAL del video\n            computada desde el contenido, no el projectDuration del timeline). */}\n        <TextBody as=\"span\" size=\"sm\" className=\"font-mono text-[#F0F0F5] tabular-nums min-w-[78px] text-center px-1\">\n          {formatTimecodeShort(videoDuration)}\n        </TextBody>\n\n        {/* 6. Botones existentes \u2014 mitad derecha */}\n        <button\n          onClick={() => setPlayhead(Math.min(projectDuration, playheadTime + 1))}\n          aria-label=\"Adelantar 1 segundo\"\n          title=\"Adelantar 1 segundo\"\n          className=\"text-[#8888A0] hover:text-[#F0F0F5] transition-colors p-1\"\n        >\n          <FastForward size={16} />\n        </button>\n\n        <button\n          onClick={() => setPlayhead(projectDuration)}\n          aria-label=\"Ir al final\"\n          title=\"Ir al final\"\n          className=\"text-[#8888A0] hover:text-[#F0F0F5] transition-colors p-1\"\n        >\n          <ChevronsRight size={16} />\n        </button>\n\n        {/* Divisor vertical */}\n        <div className=\"w-px h-6 bg-[#2A2A38]\" aria-hidden />\n\n        {/* 7. Pantalla completa */}\n        <button\n          onClick={handleFullscreen}\n          aria-label=\"Pantalla completa\"\n          title=\"Pantalla completa\"\n          className=\"text-[#8888A0] hover:text-[#F0F0F5] transition-colors p-1\"\n        >\n          <Maximize size={16} />\n        </button>\n\n      </div>\n\n      </div>\n      {/* /previewContainerRef */}\n\n    </div>\n  );\n};\nexport default VideoPlayer;\n", "import React, { useRef, useState, useEffect } from 'react';\nimport { Stage, Layer, Rect, Text, Line, Group } from 'react-konva';\nimport {\n  useVideoStore,\n  type TransitionClip,\n  type Clip as StoreClip,\n  type Asset as StoreAsset,\n} from '../../../store/useVideoStore';\nimport {\n  Download,\n  Copy,\n  ClipboardPaste,\n  Trash2,\n  Video,\n  Upload,\n  ZoomIn,\n  ZoomOut,\n  ChevronLeft,\n  ChevronRight,\n} from 'lucide-react';\nimport { TransitionBuilder } from './TransitionBuilder';\nimport { useDialog } from '../../../components/DialogModal';\nimport { TextBody } from '../../ui';\n\n\ninterface AddClipPrompt {\n  clipId: string;\n  side: 'start' | 'end';\n  x: number;\n  y: number;\n}\n\ninterface MenuPosition {\n  x: number;\n  y: number;\n}\n\n\nconst RULER_HEIGHT = 40;\nconst DEFAULT_TRACK_HEIGHT = 60;\nconst TRACK_SPACING = 6;\nconst SNAP_THRESHOLD_PX = 8;\n\ninterface TimelineProps {\n  trackHeight?: number;\n}\n\nexport const Timeline: React.FC<TimelineProps> = ({ trackHeight = DEFAULT_TRACK_HEIGHT }) => {\n  const containerRef = useRef<HTMLDivElement>(null);\n  const fileInputRef = useRef<HTMLInputElement>(null);\n  const [scrollLeft, setScrollLeft] = useState(0);\n  const [dimensions, setDimensions] = useState({ width: 800, height: 350 });\n  const [snapLineX, setSnapLineX] = useState<number | null>(null);\n\n  // T-20260727-02 refinamiento: men\u00FA contextual del clip (Download / Copy /\n  // Paste / Delete), men\u00FA de background (Upload video) y estado del prompt\n  // \"+ Add Media\" en bordes del clip. El men\u00FA de clip es per-clip; el +\n  // abre un modal (estilizado como context menu) que permite agregar video\n  // al inicio o al final del clip clickeado.\n  const [contextMenu, setContextMenu] = useState<{ x: number; y: number; clipId: string } | null>(null);\n  const [backgroundMenu, setBackgroundMenu] = useState<MenuPosition | null>(null);\n  const [copiedClip, setCopiedClip] = useState<StoreClip | null>(null);\n  const [addClipPrompt, setAddClipPrompt] = useState<AddClipPrompt | null>(null);\n  const [editingTransition, setEditingTransition] = useState<TransitionClip | null>(null);\n\n  const dialog = useDialog();\n  const {\n    tracks,\n    assets,\n    playheadTime,\n    setPlayhead,\n    zoom,\n    setZoom,\n    selectedClipIds,\n    selectClip,\n    moveClip,\n    trimClip,\n    updateClipProperties,\n    addClip,\n    removeClip,\n    addAsset,\n    projectDuration,\n    setProjectDuration,\n    transitions,\n    scrollTop,\n    setScrollTop\n  } = useVideoStore();\n\n  // T-20260727-02 refinamiento: cach\u00E9 de thumbnails de assets. Se carga una\n  // sola vez por assetId y se reusa como `fillPatternImage` en los clips de\n  // tipo video (repeat horizontal, full height). Si el asset no tiene\n  // thumbnail, se cae al color s\u00F3lido.\n  const [thumbnails, setThumbnails] = useState<Map<string, HTMLImageElement>>(new Map());\n  useEffect(() => {\n    let cancelled = false;\n    assets.forEach((asset) => {\n      if (!asset.thumbnail || thumbnails.has(asset.id)) return;\n      const img = new window.Image();\n      img.onload = () => {\n        if (cancelled) return;\n        setThumbnails((prev) => {\n          if (prev.has(asset.id)) return prev;\n          const next = new Map(prev);\n          next.set(asset.id, img);\n          return next;\n        });\n      };\n      img.onerror = () => {\n        // Silencioso: cae al color s\u00F3lido del tipo de clip.\n      };\n      img.src = asset.thumbnail;\n    });\n    return () => {\n      cancelled = true;\n    };\n  }, [assets, thumbnails]);\n\n  // T-20260727-02 refinamiento: el projectDuration se auto-deriva SOLO de\n  // los clips de VIDEO (no audio/subtitle) \u2014 max(endTime) + 10s de\n  // padding, o 30s si no hay clips. Esto hace que la l\u00EDnea del timeline\n  // refleje la duraci\u00F3n del video + margen, y que el timer del controlador\n  // muestre la duraci\u00F3n del video (sin padding) en MM:SS:CC.\n  useEffect(() => {\n    let maxEnd = 0;\n    tracks.forEach((track) => {\n      if (track.type !== 'video') return;\n      track.clips.forEach((clip) => {\n        const end = clip.startTime + clip.duration;\n        if (end > maxEnd) maxEnd = end;\n      });\n    });\n    const desired = maxEnd > 0 ? Math.ceil(maxEnd + 10) : 30;\n    if (Math.abs(projectDuration - desired) > 0.01) {\n      setProjectDuration(desired);\n    }\n  }, [tracks, setProjectDuration, projectDuration]);\n\n  // UI-only filter: always show the first video track; all other tracks only if they have clips.\n  const firstVideoId = tracks.find((t) => t.type === 'video')?.id;\n  const visibleTracks = tracks.filter((t) => t.id === firstVideoId || t.clips.length > 0);\n\n  useEffect(() => {\n    const handleGlobalClick = () => {\n      setContextMenu(null);\n      setBackgroundMenu(null);\n    };\n    window.addEventListener('click', handleGlobalClick);\n    return () => window.removeEventListener('click', handleGlobalClick);\n  }, []);\n\n  const handleDownload = (clipId: string) => {\n    const clip = tracks.flatMap((t) => t.clips).find((c) => c.id === clipId);\n    if (!clip) return;\n    const asset = assets.find((a) => a.id === clip.assetId);\n    if (!asset || !asset.url) {\n      dialog.alert('No asset URL available for this clip.', { title: 'Download unavailable', variant: 'error' });\n      return;\n    }\n    const a = document.createElement('a');\n    a.href = asset.url;\n    a.download = asset.name || `${clip.name ?? 'clip'}.${asset.type === 'video' ? 'mp4' : asset.type === 'audio' ? 'mp3' : 'png'}`;\n    document.body.appendChild(a);\n    a.click();\n    a.remove();\n  };\n\n  const handleCopy = (clipId: string) => {\n    const clip = tracks.flatMap((t) => t.clips).find((c) => c.id === clipId);\n    if (!clip) return;\n    // Clonar para evitar aliasing del state al pegar.\n    setCopiedClip({ ...clip });\n  };\n\n  const handlePaste = (clipId: string) => {\n    if (!copiedClip) return;\n    const targetClip = tracks.flatMap((t) => t.clips).find((c) => c.id === clipId);\n    if (!targetClip) return;\n    // Se pega justo despu\u00E9s del clip target en la misma pista. Si ya hay un\n    // clip all\u00ED, addClip empuja el startTime para evitar solapamiento.\n    const newStartTime = targetClip.startTime + targetClip.duration;\n    addClip(targetClip.trackId, {\n      ...copiedClip,\n      trackId: targetClip.trackId,\n      startTime: newStartTime,\n      // Sin id: addClip lo genera. Sin trackId duplicado.\n    } as Omit<StoreClip, 'id'>);\n  };\n\n  // T-20260727-02: paste desde el men\u00FA de background. Pega en la primera\n  // pista de video al tiempo del playhead. Si no hay pista de video, usa\n  // la primera pista.\n  const handlePasteToPlayhead = () => {\n    if (!copiedClip) return;\n    const targetTrack =\n      tracks.find((t) => t.type === 'video') ?? tracks[0];\n    if (!targetTrack) return;\n    addClip(targetTrack.id, {\n      ...copiedClip,\n      trackId: targetTrack.id,\n      startTime: playheadTime,\n    } as Omit<StoreClip, 'id'>);\n  };\n\n  const handleDeleteClip = (clipId: string) => {\n    removeClip(clipId);\n  };\n\n  const handleAddMediaClick = (clipId: string, side: 'start' | 'end', x: number, y: number) => {\n    setAddClipPrompt({ clipId, side, x, y });\n  };\n\n  const handleFileSelected = async (e: React.ChangeEvent<HTMLInputElement>) => {\n    const file = e.target.files?.[0];\n    e.target.value = '';\n    if (!file || !addClipPrompt) return;\n    if (!file.type.startsWith('video/')) {\n      dialog.alert('Only video files are supported in this prototype.', { title: 'Unsupported file', variant: 'error' });\n      setAddClipPrompt(null);\n      return;\n    }\n\n    const targetClip = tracks.flatMap((t) => t.clips).find((c) => c.id === addClipPrompt.clipId);\n    if (!targetClip) {\n      setAddClipPrompt(null);\n      return;\n    }\n\n    // Crear blob URL y leer metadata del video + capturar thumbnail (frame 0)\n    const url = URL.createObjectURL(file);\n    let duration: number;\n    let width: number | undefined;\n    let height: number | undefined;\n    let thumbnail: string | undefined;\n    try {\n      const meta = await new Promise<{ duration: number; width: number; height: number; thumbnail: string }>((resolve, reject) => {\n        const v = document.createElement('video');\n        v.preload = 'auto';\n        v.muted = true;\n        v.playsInline = true;\n        v.src = url;\n        v.onloadeddata = () => {\n          // Saltar al primer frame para que el canvas no salga negro.\n          v.currentTime = 0;\n        };\n        v.onseeked = () => {\n          try {\n            const THUMB_W = 160;\n            const aspect = (v.videoWidth || 16) / (v.videoHeight || 9);\n            const THUMB_H = Math.max(1, Math.round(THUMB_W / aspect));\n            const c = document.createElement('canvas');\n            c.width = THUMB_W;\n            c.height = THUMB_H;\n            const ctx = c.getContext('2d');\n            if (ctx) {\n              ctx.drawImage(v, 0, 0, THUMB_W, THUMB_H);\n            }\n            const thumb = c.toDataURL('image/jpeg', 0.6);\n            resolve({ duration: v.duration || 0, width: v.videoWidth || 0, height: v.videoHeight || 0, thumbnail: thumb });\n          } catch {\n            // Si el canvas es tainted (CORS), devolvemos sin thumbnail.\n            resolve({ duration: v.duration || 0, width: v.videoWidth || 0, height: v.videoHeight || 0, thumbnail: '' });\n          }\n        };\n        v.onerror = () => reject(new Error('Failed to read video metadata'));\n      });\n      duration = meta.duration;\n      width = meta.width || undefined;\n      height = meta.height || undefined;\n      thumbnail = meta.thumbnail || undefined;\n    } catch (err) {\n      console.error(err);\n      dialog.alert('Could not read video metadata.', { title: 'Invalid video', variant: 'error' });\n      URL.revokeObjectURL(url);\n      setAddClipPrompt(null);\n      return;\n    }\n\n    const assetId = `asset_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;\n    const asset: StoreAsset = {\n      id: assetId,\n      name: file.name,\n      url,\n      type: 'video',\n      duration,\n      width,\n      height,\n      file,\n      ...(thumbnail ? { thumbnail } : {}),\n    };\n    addAsset(asset);\n\n    // Calcular startTime seg\u00FAn el lado del + clickeado.\n    // - 'start': el nuevo clip termina justo donde empieza el existente.\n    //   Si no hay espacio antes, se clipea a 0 y se ajusta la duraci\u00F3n.\n    // - 'end': el nuevo clip comienza justo donde termina el existente.\n    let newStartTime: number;\n    let newDuration: number;\n    if (addClipPrompt.side === 'start') {\n      const desiredStart = targetClip.startTime - duration;\n      if (desiredStart >= 0) {\n        newStartTime = desiredStart;\n        newDuration = duration;\n      } else {\n        newStartTime = 0;\n        newDuration = targetClip.startTime; // parcial si no hay espacio\n      }\n    } else {\n      newStartTime = targetClip.startTime + targetClip.duration;\n      newDuration = duration;\n    }\n\n    addClip(targetClip.trackId, {\n      trackId: targetClip.trackId,\n      assetId,\n      startTime: newStartTime,\n      duration: newDuration,\n      trimIn: 0,\n      trimOut: newDuration,\n      speed: 1,\n      volume: 1,\n      opacity: 1,\n      muted: false,\n      type: 'video',\n      name: file.name,\n    } as Omit<StoreClip, 'id'>);\n\n    setAddClipPrompt(null);\n  };\n\n  // ResizeObserver to track timeline viewport width/height\n  useEffect(() => {\n    if (!containerRef.current) return;\n    const observer = new ResizeObserver((entries) => {\n      for (const entry of entries) {\n        setDimensions({\n          width: entry.contentRect.width,\n          height: entry.contentRect.height,\n        });\n      }\n    });\n    observer.observe(containerRef.current);\n    return () => observer.disconnect();\n  }, []);\n\n  const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {\n    setScrollLeft(e.currentTarget.scrollLeft);\n  };\n\n  // T-20260727-02: scroll por botones (\u25C0 \u25B6) \u2014 desplaza el contenedor del\n  // timeline en pasos de ~200px. El browser hace no-op si no hay overflow.\n  const scrollTimeline = (direction: -1 | 1) => {\n    const el = containerRef.current;\n    if (!el) return;\n    el.scrollBy({ left: direction * 200, behavior: 'smooth' });\n  };\n\n  // Zooming with Alt+scroll (T-20260707-13: era Ctrl+scroll pero conflictuaba con el\n  // zoom nativo del navegador; Alt no tiene binding por defecto), otherwise scroll vertically\n  const handleWheel = (e: React.WheelEvent) => {\n    if (e.altKey) {\n      e.preventDefault();\n      const zoomFactor = 1.1;\n      const newZoom = e.deltaY < 0 ? zoom * zoomFactor : zoom / zoomFactor;\n      setZoom(newZoom);\n    } else {\n      // Scroll vertically dynamically based on track count\n      const totalTracksHeight = tracks.length * trackHeight + (tracks.length - 1) * TRACK_SPACING + 8;\n      const maxScroll = Math.max(0, totalTracksHeight - (dimensions.height - RULER_HEIGHT));\n      const newScrollTop = Math.max(0, Math.min(scrollTop + e.deltaY, maxScroll));\n      setScrollTop(newScrollTop);\n    }\n  };\n\n  // Click on time ruler to seek playhead\n  const handleRulerClick = (e: any) => {\n    const stage = e.target.getStage();\n    if (!stage) return;\n    const pointer = stage.getPointerPosition();\n    if (pointer) {\n      const clickX = pointer.x + scrollLeft;\n      setPlayhead(clickX / zoom);\n    }\n  };\n\n  // Dragging the playhead line\n  const handlePlayheadDrag = (e: any) => {\n    const newX = e.target.x();\n    setPlayhead(newX / zoom);\n  };\n\n  // Snapping logic during dragging\n  const getSnapPosition = (x: number, width: number, draggingClipId: string): number => {\n    let snappedX = x;\n    let foundSnap = false;\n    let snapTargetX = 0;\n\n    const currentPlayheadX = playheadTime * zoom;\n    const snapCandidates: number[] = [currentPlayheadX];\n\n    // Collect edges of all other clips as snap points\n    tracks.forEach((track) => {\n      track.clips.forEach((clip) => {\n        if (clip.id !== draggingClipId) {\n          snapCandidates.push(clip.startTime * zoom);\n          snapCandidates.push((clip.startTime + clip.duration) * zoom);\n        }\n      });\n    });\n\n    // Check snapping for Left Edge (x)\n    for (const snapPoint of snapCandidates) {\n      if (Math.abs(x - snapPoint) < SNAP_THRESHOLD_PX) {\n        snappedX = snapPoint;\n        foundSnap = true;\n        snapTargetX = snapPoint;\n        break;\n      }\n    }\n\n    // Check snapping for Right Edge (x + width)\n    if (!foundSnap) {\n      for (const snapPoint of snapCandidates) {\n        if (Math.abs((x + width) - snapPoint) < SNAP_THRESHOLD_PX) {\n          snappedX = snapPoint - width;\n          foundSnap = true;\n          snapTargetX = snapPoint;\n          break;\n        }\n      }\n    }\n\n    if (foundSnap) {\n      setSnapLineX(snapTargetX);\n    } else {\n      setSnapLineX(null);\n    }\n\n    return snappedX;\n  };\n\n  // Calculate track Y coordinate\n  const getTrackY = (trackIndex: number) => {\n    return RULER_HEIGHT + trackIndex * (trackHeight + TRACK_SPACING) + 4;\n  };\n\n  const stageWidth = Math.max(dimensions.width, projectDuration * zoom);\n\n  return (\n    <div className=\"relative flex-1 flex flex-col\">\n      {/* T-20260727-02: scrollbar m\u00E1s visible (10px, brand color) para que\n          sea discoverable cuando hay overflow horizontal. */}\n      <style>{`\n        .we-timeline-scroll { scrollbar-width: thin; scrollbar-color: var(--we-accent) #13131A; }\n        .we-timeline-scroll::-webkit-scrollbar { height: 10px; }\n        .we-timeline-scroll::-webkit-scrollbar-track { background: #13131A; }\n        .we-timeline-scroll::-webkit-scrollbar-thumb { background: var(--we-accent); border-radius: 5px; }\n        .we-timeline-scroll::-webkit-scrollbar-thumb:hover { background: var(--we-accent-hover); }\n      `}</style>\n      {/* T-20260727-02: floating zoom in/out (horizontal axis only).\n            Posicionado arriba a la derecha del timeline. */}\n      <div className=\"absolute top-1 right-1 z-30 flex items-center gap-1 bg-panel border border-panel-border rounded-md shadow-lg p-0.5\">\n        <button\n          onClick={() => setZoom(Math.max(2, zoom / 1.2))}\n          aria-label=\"Zoom out timeline\"\n          title=\"Zoom out\"\n          className=\"w-6 h-6 flex items-center justify-center text-[#8888A0] hover:text-[#F0F0F5] hover:bg-[#1C1C26] rounded transition-colors\"\n        >\n          <ZoomOut size={12} />\n        </button>\n        <button\n          onClick={() => setZoom(Math.min(200, zoom * 1.2))}\n          aria-label=\"Zoom in timeline\"\n          title=\"Zoom in\"\n          className=\"w-6 h-6 flex items-center justify-center text-[#8888A0] hover:text-[#F0F0F5] hover:bg-[#1C1C26] rounded transition-colors\"\n        >\n          <ZoomIn size={12} />\n        </button>\n      </div>\n\n      {/* T-20260727-02: scroll horizontal buttons (\u25C0 \u25B6) arriba a la\n          izquierda del timeline. M\u00E1s discoverable que el scrollbar\n          nativo y permite moverse sin usar el mouse wheel ni la barra. */}\n      <div className=\"absolute top-1 left-1 z-30 flex items-center gap-1 bg-panel border border-panel-border rounded-md shadow-lg p-0.5\">\n        <button\n          onClick={() => scrollTimeline(-1)}\n          aria-label=\"Scroll timeline left\"\n          title=\"Scroll left\"\n          className=\"w-6 h-6 flex items-center justify-center text-[#8888A0] hover:text-[#F0F0F5] hover:bg-[#1C1C26] rounded transition-colors\"\n        >\n          <ChevronLeft size={12} />\n        </button>\n        <button\n          onClick={() => scrollTimeline(1)}\n          aria-label=\"Scroll timeline right\"\n          title=\"Scroll right\"\n          className=\"w-6 h-6 flex items-center justify-center text-[#8888A0] hover:text-[#F0F0F5] hover:bg-[#1C1C26] rounded transition-colors\"\n        >\n          <ChevronRight size={12} />\n        </button>\n      </div>\n\n    <div\n      ref={containerRef}\n      onWheel={handleWheel}\n      className=\"we-timeline-scroll flex-1 bg-[#0A0A0F] overflow-y-hidden overflow-x-auto relative\"\n      onScroll={handleScroll}\n      style={{ minHeight: '260px' }}\n    >\n      <Stage\n        width={stageWidth}\n        height={dimensions.height}\n        className=\"absolute top-0 left-0\"\n        onContextMenu={(e) => {\n          // T-20260727-02: right-click en el background del timeline (no\n          // sobre un clip ni sobre el playhead) abre un men\u00FA con \"Upload\n          // video\". El handler del clip ya hace e.cancelBubble en el\n          // onContextMenu del Rect, as\u00ED que este solo dispara si el target\n          // es el Stage o un shape sin handler propio (ruler, track lane).\n          e.evt.preventDefault();\n          const stage = e.target.getStage();\n          if (!stage || !containerRef.current) return;\n          const pointer = stage.getPointerPosition();\n          if (!pointer) return;\n          const containerRect = containerRef.current.getBoundingClientRect();\n          setBackgroundMenu({\n            x: pointer.x + containerRect.left - scrollLeft,\n            y: pointer.y + containerRect.top,\n          });\n        }}\n      >\n        <Layer>\n          {/* Timeline Time Ruler Background */}\n          <Rect\n            x={0}\n            y={0}\n            width={stageWidth}\n            height={RULER_HEIGHT}\n            fill=\"#13131A\"\n            stroke=\"#2A2A38\"\n            strokeWidth={1}\n            onClick={handleRulerClick}\n          />\n\n          {/* Time Ruler Ticks & Timecodes \u2014 solo segundos, intervalo adaptativo */}\n          {(() => {\n            // T-20260727-02: el usuario quiere labels simples en segundos\n            // (01, 02, 03 ... 60, 61, 62 ...). Adaptive interval para\n            // evitar overlap a zooms bajos.\n            const labelIntervalSec =\n              zoom >= 30 ? 1 :\n              zoom >= 15 ? 2 :\n              zoom >= 8  ? 5 :\n              zoom >= 4  ? 10 : 30;\n            const tickCount = Math.ceil(stageWidth / (zoom * labelIntervalSec)) + 1;\n            return Array.from({ length: tickCount }).map((_, i) => {\n              const timeSec = i * labelIntervalSec;\n              const x = timeSec * zoom;\n              return (\n                <Group key={i} x={x} y={0}>\n                  {/* Major tick mark */}\n                  <Line points={[0, 20, 0, 40]} stroke=\"#2A2A38\" strokeWidth={1} />\n                  <Text\n                    text={String(timeSec).padStart(2, '0')}\n                    fontSize={9}\n                    fill=\"#8888A0\"\n                    fontFamily=\"monospace\"\n                    x={5}\n                    y={25}\n                  />\n                  {/* Intermediate tick marks (entre labels) */}\n                  {labelIntervalSec >= 2 && Array.from({ length: labelIntervalSec - 1 }).map((_, j) => (\n                    <Line\n                      key={j}\n                      points={[(j + 1) * (zoom * (labelIntervalSec / labelIntervalSec)), 32, (j + 1) * (zoom * (labelIntervalSec / labelIntervalSec)), 40]}\n                      stroke=\"#2A2A38\"\n                      strokeWidth={0.5}\n                    />\n                  ))}\n                </Group>\n              );\n            });\n          })()}\n\n          {/* Scrolling Tracks Group */}\n          <Group\n            y={-scrollTop}\n            clipFunc={(ctx) => {\n              ctx.rect(0, RULER_HEIGHT + scrollTop, stageWidth, dimensions.height - RULER_HEIGHT);\n            }}\n          >\n            {/* Render Tracks Lane Backgrounds */}\n            {visibleTracks.map((track, trackIndex) => {\n              const y = getTrackY(trackIndex);\n              return (\n                <Group key={track.id} y={y}>\n                  {/* Track Row Background */}\n                  <Rect\n                    x={0}\n                    y={0}\n                    width={stageWidth}\n                    height={trackHeight}\n                    fill=\"#1C1C26\"\n                    opacity={0.3}\n                    stroke=\"#2A2A38\"\n                    strokeWidth={0.5}\n                  />\n\n                  {/* Render Clips inside this track */}\n                  {track.clips.map((clip) => {\n                    const clipX = clip.startTime * zoom;\n                    const clipWidth = clip.duration * zoom;\n                    const isSelected = selectedClipIds.includes(clip.id);\n\n                    // Colors: video = blue, audio = green, image = teal, text = purple, subtitle = dark purple\n                    let clipColor = '#3D5AFE'; // video\n                    if (clip.type === 'audio') clipColor = '#00E676';\n                    else if (clip.type === 'image') clipColor = '#00BFA5';\n                    else if (clip.type === 'text') clipColor = '#AA00FF';\n                    else if (clip.type === 'subtitle') clipColor = '#8000FF';\n\n                    const asset = assets.find((a) => a.id === clip.assetId);\n                    const clipName = clip.text || asset?.name || 'Media Clip';\n                    // T-20260727-02: thumbnail del asset como fill repetido\n                    // horizontalmente, full height. Solo para video clips\n                    // con thumbnail cargada; los dem\u00E1s tipos (audio, image,\n                    // text, subtitle) mantienen su color s\u00F3lido.\n                    const clipThumb = clip.type === 'video' ? thumbnails.get(clip.assetId) : undefined;\n\n                    return (\n                      <Group\n                        key={clip.id}\n                        x={clipX}\n                        y={4}\n                        draggable={!track.locked}\n                        dragBoundFunc={(pos) => {\n                          // Snapping left/right\n                          const snappedX = getSnapPosition(pos.x, clipWidth, clip.id);\n                          // Limit vertical drag between the top and bottom of the tracks container\n                          const minY = RULER_HEIGHT - scrollTop;\n                          const maxY = RULER_HEIGHT + tracks.length * (trackHeight + TRACK_SPACING) - scrollTop - trackHeight;\n                          const clampedY = Math.max(minY, Math.min(maxY, pos.y));\n                          return {\n                            x: snappedX,\n                            y: clampedY,\n                          };\n                        }}\n                        onDragEnd={(e) => {\n                          const newX = e.target.x();\n                          const newStartTime = newX / zoom;\n                          \n                          // Determine target track under cursor\n                          const stage = e.target.getStage();\n                          if (stage) {\n                            const pointer = stage.getPointerPosition();\n                            if (pointer) {\n                              const pointerY = pointer.y + scrollTop;\n                              const relativeY = pointerY - RULER_HEIGHT;\n                              const trackIndex = Math.floor(relativeY / (trackHeight + TRACK_SPACING));\n                              \n                              if (trackIndex >= 0 && trackIndex < tracks.length) {\n                                const targetTrack = tracks[trackIndex];\n                                // Restrict movement to tracks of the SAME type (e.g. video to video, text to text) and unlocked\n                                if (targetTrack && targetTrack.type === track.type && !targetTrack.locked) {\n                                  moveClip(clip.id, newStartTime, targetTrack.id);\n                                  setSnapLineX(null);\n                                  e.target.y(4);\n                                  return;\n                                }\n                              }\n                            }\n                          }\n                          \n                          // Fallback to original track\n                          moveClip(clip.id, newStartTime, track.id);\n                          setSnapLineX(null);\n                          e.target.y(4);\n                        }}\n                        onClick={(e) => {\n                          e.cancelBubble = true; // prevent timeline deselection\n                          selectClip(clip.id, e.evt.shiftKey);\n                        }}\n                        onContextMenu={(e) => {\n                          e.evt.preventDefault();\n                          e.cancelBubble = true; // no propagar al Stage (background menu)\n                          const stage = e.target.getStage();\n                          if (!stage) return;\n                          const pointer = stage.getPointerPosition();\n                          if (pointer && containerRef.current) {\n                            const containerRect = containerRef.current.getBoundingClientRect();\n                            setContextMenu({\n                              x: pointer.x + containerRect.left - scrollLeft,\n                              y: pointer.y + containerRect.top,\n                              clipId: clip.id,\n                            });\n                          }\n                        }}\n                      >\n                        {/* Clip Body */}\n                        <Rect\n                          x={0}\n                          y={0}\n                          width={clipWidth}\n                          height={trackHeight - 8}\n                          fill={clipThumb ? undefined : clipColor}\n                          fillPatternImage={clipThumb}\n                          fillPatternRepeat=\"repeat\"\n                          cornerRadius={4}\n                          opacity={isSelected ? 0.95 : 0.75}\n                          stroke={isSelected ? '#FF4081' : '#2A2A38'}\n                          strokeWidth={isSelected ? 1.5 : 1}\n                        />\n\n                        {/* Display Waveforms on Audio Clips */}\n                        {clip.type === 'audio' && (\n                          <Group x={4} y={(trackHeight - 8) / 2}>\n                            {Array.from({ length: Math.ceil(clipWidth / 4) }).map((_, waveIdx) => {\n                              const waveHeight = 6 + Math.sin(waveIdx * 0.4) * 14 + Math.cos(waveIdx * 0.2) * 6;\n                              return (\n                                <Line\n                                  key={waveIdx}\n                                  points={[waveIdx * 4, -waveHeight / 2, waveIdx * 4, waveHeight / 2]}\n                                  stroke=\"#13131A\"\n                                  strokeWidth={1.5}\n                                  opacity={0.6}\n                                />\n                              );\n                            })}\n                          </Group>\n                        )}\n\n                        {/* Clip Name Label */}\n                        <Text\n                          text={clipName}\n                          fontSize={10}\n                          fill=\"#F0F0F5\"\n                          fontFamily=\"sans-serif\"\n                          fontStyle=\"bold\"\n                          x={8}\n                          y={8}\n                          width={clipWidth - 16}\n                          wrap=\"char\"\n                          ellipsis={true}\n                        />\n\n                        {/* Display Speed Badge if not 1.0 */}\n                        {clip.speed !== 1.0 && (\n                          <Text\n                            text={`${clip.speed}x`}\n                            fontSize={8}\n                            fill=\"#FFB300\"\n                            fontStyle=\"bold\"\n                            x={8}\n                            y={34}\n                          />\n                        )}\n\n                        {/* Left Trim Handle (only if selected) */}\n                        {isSelected && !track.locked && (\n                          <Rect\n                            x={0}\n                            y={0}\n                            width={6}\n                            height={trackHeight - 8}\n                            fill=\"#FF4081\"\n                            cornerRadius={[4, 0, 0, 4]}\n                            draggable\n                            dragBoundFunc={(pos) => {\n                              // pos.x is in stage coords\n                              // Max: can't go past right edge - 10px\n                              const maxL = clipX + clipWidth - 10;\n                              const clampedX = Math.max(0, Math.min(pos.x, maxL));\n                              return { x: clampedX, y: y + 4 };\n                            }}\n                            onDragMove={(e) => {\n                              // e.target.x() is LOCAL to the Group (starts at 0 = clip left edge)\n                              // But dragBoundFunc returns stage coords, so Konva repositions the node\n                              // in stage space. We need the stage x to compute delta.\n                              const stageX = e.target.getAbsolutePosition().x;\n                              const deltaX = stageX - clipX;\n                              const deltaSec = deltaX / zoom;\n                              const newTrimIn = clip.trimIn + deltaSec * clip.speed;\n                              trimClip(clip.id, newTrimIn, clip.trimOut, clip.startTime + deltaSec);\n                            }}\n                          />\n                        )}\n\n                        {/* Right Trim Handle (only if selected) */}\n                        {isSelected && !track.locked && (\n                          <Rect\n                            x={clipWidth - 6}\n                            y={0}\n                            width={6}\n                            height={trackHeight - 8}\n                            fill=\"#FF4081\"\n                            cornerRadius={[0, 4, 4, 0]}\n                            draggable\n                            dragBoundFunc={(pos) => {\n                              // pos.x is stage-absolute. Convert to group-local.\n                              const localX = pos.x - clipX;\n                              // Minimum clip width = 10px\n                              const clampedLocalX = Math.max(10, localX);\n                              return { x: clampedLocalX + clipX, y: y + 4 };\n                            }}\n                            onDragMove={(e) => {\n                              // e.target.x() is local to the Group (0 = clip left edge)\n                              // new clip width = handle left edge + handle width (6)\n                              const newWidth = Math.max(1, e.target.x() + 6);\n                              const newDuration = Math.max(0.1, newWidth / zoom);\n                              // Only change duration \u2014 startTime is untouched\n                              updateClipProperties(clip.id, { duration: newDuration });\n                            }}\n                          />\n                        )}\n\n                        {/* T-20260727-02 refinamiento: bot\u00F3n flotante \"+\" al inicio\n                            del clip. Click \u2192 modal \"Add Media\".\n                            v2: 28x28px, corner radius 10px, fondo blanco, icono primary. */}\n                        {!track.locked && (\n                          <Group\n                            x={-14}\n                            y={(trackHeight - 28) / 2}\n                            onClick={(e) => {\n                              e.cancelBubble = true;\n                              handleAddMediaClick(clip.id, 'start', e.evt.clientX, e.evt.clientY);\n                            }}\n                            onMouseEnter={(e) => {\n                              const stage = e.target.getStage();\n                              if (stage) stage.container().style.cursor = 'pointer';\n                            }}\n                            onMouseLeave={(e) => {\n                              const stage = e.target.getStage();\n                              if (stage) stage.container().style.cursor = 'default';\n                            }}\n                          >\n                            <Rect\n                              x={0}\n                              y={0}\n                              width={28}\n                              height={28}\n                              cornerRadius={10}\n                              fill=\"#FFFFFF\"\n                              shadowColor=\"#000000\"\n                              shadowBlur={6}\n                              shadowOpacity={0.5}\n                            />\n                            <Text\n                              text=\"+\"\n                              x={9}\n                              y={5}\n                              fontSize={20}\n                              fontStyle=\"bold\"\n                              fill=\"var(--we-accent)\"\n                              fontFamily=\"sans-serif\"\n                            />\n                          </Group>\n                        )}\n\n                        {/* T-20260727-02 refinamiento: bot\u00F3n flotante \"+\" al final\n                            del clip. Click \u2192 modal \"Add Media\".\n                            v2: 28x28px, corner radius 10px, fondo blanco, icono primary. */}\n                        {!track.locked && (\n                          <Group\n                            x={clipWidth + 1}\n                            y={(trackHeight - 28) / 2}\n                            onClick={(e) => {\n                              e.cancelBubble = true;\n                              handleAddMediaClick(clip.id, 'end', e.evt.clientX, e.evt.clientY);\n                            }}\n                            onMouseEnter={(e) => {\n                              const stage = e.target.getStage();\n                              if (stage) stage.container().style.cursor = 'pointer';\n                            }}\n                            onMouseLeave={(e) => {\n                              const stage = e.target.getStage();\n                              if (stage) stage.container().style.cursor = 'default';\n                            }}\n                          >\n                            <Rect\n                              x={0}\n                              y={0}\n                              width={28}\n                              height={28}\n                              cornerRadius={10}\n                              fill=\"#FFFFFF\"\n                              shadowColor=\"#000000\"\n                              shadowBlur={6}\n                              shadowOpacity={0.5}\n                            />\n                            <Text\n                              text=\"+\"\n                              x={9}\n                              y={5}\n                              fontSize={20}\n                              fontStyle=\"bold\"\n                              fill=\"var(--we-accent)\"\n                              fontFamily=\"sans-serif\"\n                            />\n                          </Group>\n                        )}\n                      </Group>\n                    );\n                  })}\n                </Group>\n              );\n            })}\n\n            {/* Render Transitions Overlays */}\n            {transitions.map((trans) => {\n              let clip: any = null;\n              let trackIndex = -1;\n              const isStart = trans.fromClipId === 'none';\n              const isEnd = trans.toClipId === 'none';\n              const targetClipId = isStart ? trans.toClipId : trans.fromClipId;\n              \n              for (let tIdx = 0; tIdx < visibleTracks.length; tIdx++) {\n                const found = visibleTracks[tIdx].clips.find((c) => c.id === targetClipId);\n                if (found) {\n                  clip = found;\n                  trackIndex = tIdx;\n                  break;\n                }\n              }\n\n              if (!clip || trackIndex === -1) return null;\n\n              let transX = 0;\n              const transWidth = trans.duration * zoom;\n\n              if (isStart) {\n                // Start transition (Fade In) - placed at the beginning of the clip\n                transX = clip.startTime * zoom;\n              } else if (isEnd) {\n                // End transition (Fade Out) - placed at the end of the clip\n                transX = (clip.startTime + clip.duration - trans.duration) * zoom;\n              } else {\n                // Between clips transition - centered at the clip cuts\n                const cutTime = clip.startTime + clip.duration;\n                transX = (cutTime - trans.duration / 2) * zoom;\n              }\n\n              const transY = getTrackY(trackIndex) + (trackHeight - 18) / 2;\n              const fillColor = isStart ? '#4CAF50' : isEnd ? '#F44336' : '#FF6D00'; // Green for Start, Red for End, Orange for Between\n              \n              let labelText = trans.type.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');\n              if (isStart) labelText += ' In';\n              if (isEnd) labelText += ' Out';\n\n              return (\n                <Group\n                  key={trans.id}\n                  x={transX}\n                  y={transY}\n                  onClick={(e) => {\n                    e.cancelBubble = true;\n                    setEditingTransition(trans);\n                  }}\n                >\n                  <Rect\n                    x={0}\n                    y={0}\n                    width={transWidth}\n                    height={18}\n                    fill={fillColor}\n                    opacity={0.95}\n                    cornerRadius={3}\n                    stroke=\"#13131A\"\n                    strokeWidth={1}\n                  />\n                  <Text\n                    text={labelText}\n                    fontSize={8}\n                    fill=\"#FFFFFF\"\n                    fontFamily=\"sans-serif\"\n                    fontStyle=\"bold\"\n                    x={4}\n                    y={5}\n                    width={transWidth - 8}\n                    wrap=\"none\"\n                    ellipsis={true}\n                    align=\"center\"\n                  />\n                </Group>\n              );\n            })}\n          </Group>\n\n          {/* Yellow vertical snapping line */}\n          {snapLineX !== null && (\n            <Line\n              points={[snapLineX, 0, snapLineX, dimensions.height]}\n              stroke=\"#FFB300\"\n              strokeWidth={1.5}\n              dash={[4, 4]}\n            />\n          )}\n\n          {/* Playhead Vertical Line */}\n          <Group\n            x={playheadTime * zoom}\n            y={0}\n            draggable\n            dragBoundFunc={(pos) => ({\n              x: Math.max(0, pos.x),\n              y: 0,\n            })}\n            onDragMove={handlePlayheadDrag}\n          >\n            {/* Red playhead line extending down the entire stage */}\n            <Line\n              points={[0, 0, 0, dimensions.height]}\n              stroke=\"#FF4081\"\n              strokeWidth={1.5}\n            />\n            {/* Playhead Handle Pointer (Rectangle block at ruler level) */}\n            <Rect\n              x={-5}\n              y={0}\n              width={10}\n              height={15}\n              fill=\"#FF4081\"\n              cornerRadius={[0, 0, 3, 3]}\n            />\n          </Group>\n        </Layer>\n      </Stage>\n\n      {/* Clip Right-Click Context Menu \u2014 Download / Copy / Paste / Delete */}\n      {contextMenu && (\n        <div\n          className=\"absolute bg-[#13131A] border border-[#2A2A38] rounded-md shadow-2xl py-1 z-50 text-xs text-[#F0F0F5] min-w-[160px]\"\n          style={{\n            top: contextMenu.y - (containerRef.current?.getBoundingClientRect().top || 0),\n            left: contextMenu.x - (containerRef.current?.getBoundingClientRect().left || 0),\n          }}\n          onClick={(e) => e.stopPropagation()}\n        >\n          <button\n            onClick={() => {\n              handleDownload(contextMenu.clipId);\n              setContextMenu(null);\n            }}\n            className=\"w-full text-left px-3 py-2 hover:bg-[var(--we-accent-hover)] hover:text-white transition-colors flex items-center gap-1.5\"\n          >\n            <Download size={11} className=\"text-[var(--we-accent)] hover:text-white\" />\n            <TextBody as=\"span\" size=\"sm\">Download</TextBody>\n          </button>\n          <button\n            onClick={() => {\n              handleCopy(contextMenu.clipId);\n              setContextMenu(null);\n            }}\n            className=\"w-full text-left px-3 py-2 hover:bg-[var(--we-accent-hover)] hover:text-white transition-colors flex items-center gap-1.5\"\n          >\n            <Copy size={11} className=\"text-[var(--we-accent)] hover:text-white\" />\n            <TextBody as=\"span\" size=\"sm\">Copy</TextBody>\n          </button>\n          <button\n            onClick={() => {\n              if (copiedClip) {\n                handlePaste(contextMenu.clipId);\n                setContextMenu(null);\n              }\n            }}\n            disabled={!copiedClip}\n            className={`w-full text-left px-3 py-2 transition-colors flex items-center gap-1.5 ${\n              copiedClip\n                ? 'hover:bg-[var(--we-accent-hover)] hover:text-white'\n                : 'opacity-40 cursor-not-allowed'\n            }`}\n            title={copiedClip ? 'Paste at playhead' : 'Copy a clip first to enable paste'}\n          >\n            <ClipboardPaste size={11} className={`${copiedClip ? 'text-[var(--we-accent)]' : 'text-[#8888A0]'} hover:text-white`} />\n            <TextBody as=\"span\" size=\"sm\">Paste</TextBody>\n          </button>\n          <div className=\"border-t border-[#2A2A38] my-1\" />\n          <button\n            onClick={() => {\n              handleDeleteClip(contextMenu.clipId);\n              setContextMenu(null);\n            }}\n            className=\"w-full text-left px-3 py-2 hover:bg-[#FF4081] hover:text-white transition-colors flex items-center gap-1.5\"\n          >\n            <Trash2 size={11} className=\"text-[#FF4081] hover:text-white\" />\n            <TextBody as=\"span\" size=\"sm\">Delete</TextBody>\n          </button>\n        </div>\n      )}\n\n      {/* Hidden file input for \"Add Video\" \u2014 triggered by modal button */}\n      <input\n        ref={fileInputRef}\n        type=\"file\"\n        accept=\"video/*\"\n        onChange={handleFileSelected}\n        style={{ display: 'none' }}\n      />\n\n      {/* Add Media Modal \u2014 triggered by floating + buttons at clip edges.\n          T-20260727-02: mismo estilo que el context menu (dropdown small,\n          bg-[#13131A] + border + rounded-md), anclado cerca del + que se\n          clicke\u00F3. Click fuera cierra. */}\n      {addClipPrompt && (\n        <div\n          className=\"absolute inset-0 z-[70]\"\n          onClick={() => setAddClipPrompt(null)}\n        >\n          <div\n            className=\"absolute bg-[#13131A] border border-[#2A2A38] rounded-md shadow-2xl py-1 text-xs text-[#F0F0F5] min-w-[160px]\"\n            style={{\n              top: addClipPrompt.y - (containerRef.current?.getBoundingClientRect().top || 0),\n              left: addClipPrompt.x - (containerRef.current?.getBoundingClientRect().left || 0),\n            }}\n            onClick={(e) => e.stopPropagation()}\n          >\n            <button\n              onClick={() => fileInputRef.current?.click()}\n              className=\"w-full text-left px-3 py-2 hover:bg-[var(--we-accent-hover)] hover:text-white transition-colors flex items-center gap-1.5\"\n            >\n              <Video size={11} className=\"text-[var(--we-accent)] hover:text-white\" />\n              <TextBody as=\"span\" size=\"sm\">Add Video</TextBody>\n            </button>\n            <div className=\"border-t border-[#2A2A38] my-1\" />\n            <TextBody as=\"p\" size=\"sm\" className=\"px-3 py-1.5 text-[#8888A0]\">\n              Will be inserted {addClipPrompt.side === 'start' ? 'before' : 'after'} the selected clip.\n            </TextBody>\n          </div>\n        </div>\n      )}\n\n      {/* Background right-click menu \u2014 Upload video / Paste */}\n      {backgroundMenu && (\n        <div\n          className=\"absolute bg-[#13131A] border border-[#2A2A38] rounded-md shadow-2xl py-1 z-50 text-xs text-[#F0F0F5] min-w-[160px]\"\n          style={{\n            top: backgroundMenu.y - (containerRef.current?.getBoundingClientRect().top || 0),\n            left: backgroundMenu.x - (containerRef.current?.getBoundingClientRect().left || 0),\n          }}\n          onClick={(e) => e.stopPropagation()}\n        >\n          <button\n            onClick={() => {\n              setBackgroundMenu(null);\n              fileInputRef.current?.click();\n            }}\n            className=\"w-full text-left px-3 py-2 hover:bg-[var(--we-accent-hover)] hover:text-white transition-colors flex items-center gap-1.5\"\n          >\n            <Upload size={11} className=\"text-[var(--we-accent)] hover:text-white\" />\n            <TextBody as=\"span\" size=\"sm\">Upload video</TextBody>\n          </button>\n          <button\n            onClick={() => {\n              if (copiedClip) {\n                handlePasteToPlayhead();\n                setBackgroundMenu(null);\n              }\n            }}\n            disabled={!copiedClip}\n            className={`w-full text-left px-3 py-2 transition-colors flex items-center gap-1.5 ${\n              copiedClip\n                ? 'hover:bg-[var(--we-accent-hover)] hover:text-white'\n                : 'opacity-40 cursor-not-allowed'\n            }`}\n            title={copiedClip ? 'Paste at playhead' : 'Copy a clip first to enable paste'}\n          >\n            <ClipboardPaste size={11} className={`${copiedClip ? 'text-[var(--we-accent)]' : 'text-[#8888A0]'} hover:text-white`} />\n            <TextBody as=\"span\" size=\"sm\">Paste</TextBody>\n          </button>\n        </div>\n      )}\n\n      {/* Transition Builder Settings Modal */}\n      {editingTransition && (\n        <TransitionBuilder\n          transition={editingTransition}\n          onClose={() => setEditingTransition(null)}\n        />\n      )}\n    </div>\n    </div>\n  );\n};\n", "import React from 'react';\nimport { useVideoStore, type TransitionClip, type TransitionType } from '../../../store/useVideoStore';\nimport { Slider } from '../../../components/ui/Slider';\nimport { X, Save } from 'lucide-react';\nimport { TextBody, TextTitle } from '../../ui';\n\n\ninterface TransitionBuilderProps {\n  transition: TransitionClip;\n  onClose: () => void;\n}\n\nexport const TransitionBuilder: React.FC<TransitionBuilderProps> = ({ transition, onClose }) => {\n  const { tracks, updateTransition, removeTransition } = useVideoStore();\n\n  const isStart = transition.fromClipId === 'none';\n  const isEnd = transition.toClipId === 'none';\n\n  // Find associated clips\n  let fromClip: any = null;\n  let toClip: any = null;\n\n  for (const track of tracks) {\n    if (!fromClip) fromClip = track.clips.find((c) => c.id === transition.fromClipId);\n    if (!toClip) toClip = track.clips.find((c) => c.id === transition.toClipId);\n    if (fromClip && toClip) break;\n  }\n\n  // Calculate dynamic constraints and labels\n  let maxDuration = 3.0;\n  let contextName = 'Between Clips';\n\n  if (isStart && toClip) {\n    maxDuration = toClip.duration;\n    contextName = 'Clip Start (Fade In)';\n  } else if (isEnd && fromClip) {\n    maxDuration = fromClip.duration;\n    contextName = 'Clip End (Fade Out)';\n  } else if (fromClip && toClip) {\n    maxDuration = 2 * Math.min(fromClip.duration, toClip.duration);\n    contextName = 'Between Clips';\n  }\n\n  const handleTypeChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n    updateTransition(transition.id, { type: e.target.value as TransitionType });\n  };\n\n  const handleDurationChange = (val: number) => {\n    // Keep duration clamped within the dynamic maximum\n    const clampedVal = Math.min(val, maxDuration);\n    updateTransition(transition.id, { duration: clampedVal });\n  };\n\n  const handleReverseToggle = () => {\n    updateTransition(transition.id, { reverse: !transition.reverse });\n  };\n\n  const handleEasingChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n    updateTransition(transition.id, { easing: e.target.value as any });\n  };\n\n  const handleDelete = () => {\n    removeTransition(transition.id);\n    onClose();\n  };\n\n  return (\n    <div className=\"fixed inset-0 bg-black/60 backdrop-blur-xs flex items-center justify-center z-[100] select-none\">\n      <div className=\"bg-[#13131A] border border-[#2A2A38] rounded-lg w-full max-w-md shadow-2xl flex flex-col overflow-hidden animate-fadeIn\">\n        \n        {/* Header */}\n        <div className=\"px-4 py-3 border-b border-[#2A2A38] flex justify-between items-center bg-[#0A0A0F]\">\n          <TextTitle as=\"span\" size=\"xs\" className=\"uppercase tracking-wider text-[#F0F0F5]\">\n            Transition: {contextName}\n          </TextTitle>\n          <button onClick={onClose} className=\"text-[#8888A0] hover:text-white transition-colors\">\n            <X size={14} />\n          </button>\n        </div>\n\n        {/* Form Body */}\n        <div className=\"p-4 space-y-4\">\n          {/* Transition Type */}\n          <div className=\"flex flex-col gap-1.5\">\n            <TextBody as=\"label\" size=\"sm\" className=\"text-[#8888A0] uppercase tracking-wider\">\n              Transition Type\n            </TextBody>\n            <select\n              value={transition.type}\n              onChange={handleTypeChange}\n              className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded px-2.5 py-1.5 text-xs text-[#F0F0F5] focus:outline-none focus:border-[var(--we-accent)]\"\n            >\n              <option value=\"cross-dissolve\">Cross Dissolve</option>\n              <option value=\"fade-black\">Dip to Black</option>\n              <option value=\"fade-white\">Dip to White</option>\n              <option value=\"wipe-left\">Wipe Left</option>\n              <option value=\"wipe-right\">Wipe Right</option>\n              <option value=\"wipe-up\">Wipe Up</option>\n              <option value=\"wipe-down\">Wipe Down</option>\n              <option value=\"slide-left\">Slide Left</option>\n              <option value=\"slide-right\">Slide Right</option>\n              <option value=\"push-left\">Push Left</option>\n              <option value=\"push-right\">Push Right</option>\n              <option value=\"iris-circle\">Circle Iris Wipe</option>\n              <option value=\"clock-wipe\">Clock Wipe</option>\n              <option value=\"zoom-in\">Zoom In</option>\n              <option value=\"zoom-punch\">Zoom Punch</option>\n              <option value=\"spin-zoom\">Spin Zoom</option>\n              <option value=\"blur-dissolve\">Blur Dissolve</option>\n              <option value=\"pixelate\">Pixelate Dissolve</option>\n              <option value=\"glitch\">Digital Glitch</option>\n              <option value=\"film-burn\">Film Burn Leak</option>\n            </select>\n          </div>\n\n          {/* Duration Slider */}\n          <Slider\n            label=\"Duration\"\n            min={0.1}\n            max={parseFloat(maxDuration.toFixed(2))}\n            step={0.05}\n            value={Math.min(transition.duration, maxDuration)}\n            onChange={handleDurationChange}\n            formatValue={(v) => `${v.toFixed(2)}s`}\n          />\n\n          {/* Target Background Color (only for Start/End transitions) */}\n          {(isStart || isEnd) && (\n            <div className=\"flex flex-col gap-1.5\">\n              <TextBody as=\"label\" size=\"sm\" className=\"text-[#8888A0] uppercase tracking-wider\">\n                Fondo de Transici\u00F3n\n              </TextBody>\n              <select\n                value={transition.params.targetColor || 'black'}\n                onChange={(e) => {\n                  updateTransition(transition.id, {\n                    params: {\n                      ...transition.params,\n                      targetColor: e.target.value\n                    }\n                  });\n                }}\n                className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded px-2.5 py-1.5 text-xs text-[#F0F0F5] focus:outline-none focus:border-[var(--we-accent)]\"\n              >\n                <option value=\"black\">Fundido a negro</option>\n                <option value=\"white\">Fundido a blanco</option>\n                <option value=\"transparent\">Fundido a transparente</option>\n              </select>\n            </div>\n          )}\n\n          {/* Easing Profile */}\n          <div className=\"grid grid-cols-2 gap-3\">\n            <div className=\"flex flex-col gap-1.5\">\n              <TextBody as=\"label\" size=\"sm\" className=\"text-[#8888A0] uppercase tracking-wider\">\n                Easing Curve\n              </TextBody>\n              <select\n                value={transition.easing}\n                onChange={handleEasingChange}\n                className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded px-2.5 py-1.5 text-xs text-[#F0F0F5] focus:outline-none\"\n              >\n                <option value=\"linear\">Linear</option>\n                <option value=\"ease-in\">Ease In</option>\n                <option value=\"ease-out\">Ease Out</option>\n                <option value=\"ease-in-out\">Ease In Out</option>\n              </select>\n            </div>\n\n            <div className=\"flex flex-col gap-1.5\">\n              <TextBody as=\"label\" size=\"sm\" className=\"text-[#8888A0] uppercase tracking-wider\">\n                Direction\n              </TextBody>\n              <button\n                onClick={handleReverseToggle}\n                className={`w-full py-1.5 rounded text-xs font-semibold border transition-all ${\n                  transition.reverse\n                    ? 'bg-[var(--we-accent-muted)] border-[var(--we-accent)] text-[var(--we-accent)]'\n                    : 'bg-[#0A0A0F] border-[#2A2A38] text-[#8888A0] hover:text-white'\n                }`}\n              >\n                <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                  {transition.reverse ? 'Reversed' : 'Forward'}\n                </TextBody>\n              </button>\n            </div>\n          </div>\n        </div>\n\n        {/* Footer Actions */}\n        <div className=\"px-4 py-3 bg-[#0A0A0F]/60 border-t border-[#2A2A38] flex gap-2 justify-end\">\n          <button\n            onClick={handleDelete}\n            className=\"px-3 py-1.5 rounded bg-red-500/10 text-red-400 hover:bg-red-500 hover:text-white text-xs font-semibold transition-all active:scale-95\"\n          >\n            <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">Delete</TextBody>\n          </button>\n          <button\n            onClick={onClose}\n            className=\"flex items-center gap-1 rounded bg-[var(--we-accent)] px-3 py-1.5 text-white transition-all hover:bg-[var(--we-accent-hover)] active:scale-95\"\n          >\n            <Save size={12} />\n            <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">Apply Settings</TextBody>\n          </button>\n        </div>\n\n      </div>\n    </div>\n  );\n};\nexport default TransitionBuilder;\n", "/**\n * Wizard agent editors open the studio with:\n *   ?importKind=image|audio|video&mediaUrl=...&mediaName=...\n *\n * Image \u2192 new canvas at the image's pixel size, image placed on it.\n * Audio \u2192 an existing preset canvas (the open project, or the voiceover preset).\n * Video \u2192 new canvas at the video's pixel size, clip on the video track.\n */\n\nimport { useEditorStore } from '../store/useEditorStore';\nimport {\n  useVideoStore,\n  type Asset,\n} from '../store/useVideoStore';\nimport {\n  createAudioClip,\n  useAudioStore,\n} from '../store/useAudioStore';\nimport { closestAspect } from '../utils/videoCanvasSize';\nimport {\n  fetchRemoteMediaAsFile,\n  resolveImageSrcForCanvas,\n} from './imageJobsService';\nimport { decodeAudioBlob, extractPeaks } from '../lib/audio/peaks';\n\nexport type HostMediaKind = 'image' | 'audio' | 'video';\n\nexport interface HostMediaImport {\n  kind: HostMediaKind;\n  url: string;\n  name: string;\n}\n\ntype StudioTab = 'video' | 'image' | 'audio' | 'text' | 'slides';\n\nconst PARAM_KIND = 'importKind';\nconst PARAM_URL = 'mediaUrl';\nconst PARAM_NAME = 'mediaName';\n\nfunction fileNameFromUrl(url: string, kind: HostMediaKind): string {\n  try {\n    const path = new URL(url, window.location.origin).pathname;\n    const base = path.split('/').filter(Boolean).pop();\n    if (base) return decodeURIComponent(base).slice(0, 80);\n  } catch {\n    /* keep fallback */\n  }\n  if (kind === 'audio') return 'Audio';\n  if (kind === 'video') return 'Video';\n  return 'Image';\n}\n\nexport function readHostMediaImport(): HostMediaImport | null {\n  if (typeof window === 'undefined') return null;\n  const params = new URLSearchParams(window.location.search);\n  const kind = params.get(PARAM_KIND);\n  const url = params.get(PARAM_URL)?.trim() ?? '';\n  if (kind !== 'image' && kind !== 'audio' && kind !== 'video') return null;\n  if (!url) return null;\n  const name = params.get(PARAM_NAME)?.trim() || fileNameFromUrl(url, kind);\n  return { kind, url, name };\n}\n\nexport function clearHostMediaImportFromUrl(): void {\n  if (typeof window === 'undefined') return;\n  const url = new URL(window.location.href);\n  url.searchParams.delete(PARAM_KIND);\n  url.searchParams.delete(PARAM_URL);\n  url.searchParams.delete(PARAM_NAME);\n  window.history.replaceState(window.history.state, '', url.toString());\n}\n\nfunction loadHtmlImage(src: string): Promise<HTMLImageElement> {\n  return new Promise((resolve, reject) => {\n    const img = new Image();\n    img.onload = () => resolve(img);\n    img.onerror = () => reject(new Error('Image decode failed'));\n    if (/^https?:\\/\\//i.test(src)) img.crossOrigin = 'anonymous';\n    img.src = src;\n  });\n}\n\nfunction readVideoMeta(url: string): Promise<{ duration: number; width: number; height: number; thumb?: string }> {\n  return new Promise((resolve) => {\n    const video = document.createElement('video');\n    video.preload = 'metadata';\n    video.muted = true;\n    video.playsInline = true;\n    const finish = (thumb?: string) => {\n      const duration = Number.isFinite(video.duration) ? video.duration : 5;\n      resolve({\n        duration,\n        width: video.videoWidth || 1920,\n        height: video.videoHeight || 1080,\n        thumb,\n      });\n      video.src = '';\n      video.load();\n    };\n    video.onloadedmetadata = () => {\n      const duration = Number.isFinite(video.duration) ? video.duration : 5;\n      const seekTo = Math.min(0.1, Math.max(0, duration / 2));\n      video.onseeked = () => {\n        try {\n          const canvas = document.createElement('canvas');\n          const vw = video.videoWidth || 160;\n          const vh = video.videoHeight || 90;\n          const scale = Math.min(1, 160 / Math.max(vw, vh));\n          canvas.width = Math.max(1, Math.round(vw * scale));\n          canvas.height = Math.max(1, Math.round(vh * scale));\n          const ctx = canvas.getContext('2d');\n          if (ctx) ctx.drawImage(video, 0, 0, canvas.width, canvas.height);\n          finish(canvas.toDataURL('image/jpeg', 0.7));\n        } catch {\n          finish();\n        }\n      };\n      try {\n        video.currentTime = seekTo;\n      } catch {\n        finish();\n      }\n    };\n    video.onerror = () => resolve({ duration: 5, width: 1920, height: 1080 });\n    video.src = url;\n  });\n}\n\nasync function waitForImageCanvas(width: number, height: number): Promise<boolean> {\n  const deadline = Date.now() + 8000;\n  while (Date.now() < deadline) {\n    const canvas = useEditorStore.getState().canvasInstance;\n    const w = canvas?.getWidth?.() ?? 0;\n    const h = canvas?.getHeight?.() ?? 0;\n    if (canvas && Math.abs(w - width) <= 2 && Math.abs(h - height) <= 2) return true;\n    await new Promise((resolve) => window.setTimeout(resolve, 50));\n  }\n  return false;\n}\n\nasync function importImage(item: HostMediaImport, setTab: (tab: StudioTab) => void): Promise<void> {\n  const src = await resolveImageSrcForCanvas(item.url);\n  const element = await loadHtmlImage(src);\n  const width = Math.max(16, element.naturalWidth || 1080);\n  const height = Math.max(16, element.naturalHeight || 1080);\n\n  useEditorStore.getState().createImageProject(item.name, width, height, '#ffffff');\n  setTab('image');\n\n  const ready = await waitForImageCanvas(width, height);\n  if (!ready) return;\n\n  const store = useEditorStore.getState();\n  // Import as a single content-sized layer (do not pre-create an empty file layer).\n  await store.stampImageOntoActivePixelLayer(src, { name: item.name });\n}\n\nasync function importAudio(item: HostMediaImport, setTab: (tab: StudioTab) => void): Promise<void> {\n  const audio = useAudioStore.getState();\n  if (audio.audioProjects.length > 0 && audio.activeAudioProjectId) {\n    setTab('audio');\n  } else if (audio.audioProjects.length > 0) {\n    const latest = [...audio.audioProjects].sort((a, b) => b.createdAt - a.createdAt)[0];\n    if (latest) useAudioStore.getState().switchAudioProject(latest.id);\n    setTab('audio');\n  } else {\n    useAudioStore.getState().createAudioProject(item.name, { template: 'voiceover' });\n    setTab('audio');\n  }\n\n  const safeName = item.name.replace(/[^\\w.\\-]+/g, '_').slice(0, 40) || 'audio';\n  const downloaded = await fetchRemoteMediaAsFile(item.url, `${safeName}.mp3`, 'audio/mpeg');\n  if (!downloaded) return;\n\n  const buffer = await decodeAudioBlob(downloaded.file);\n  const peaks = await extractPeaks(buffer);\n  const assetId = `host_aud_${Date.now()}`;\n  useAudioStore.getState().addAsset({\n    id: assetId,\n    name: item.name,\n    url: downloaded.objectUrl,\n    duration: buffer.duration,\n    sampleRate: buffer.sampleRate,\n    channels: buffer.numberOfChannels,\n    file: downloaded.file,\n    peaks: peaks.peaks,\n    peaksSampleRate: peaks.peaksSampleRate,\n  });\n\n  let trackId = useAudioStore.getState().tracks.find((track) => track.type === 'audio')?.id;\n  if (!trackId) trackId = useAudioStore.getState().addTrack('Audio', 'audio');\n\n  useAudioStore.getState().addClip(\n    createAudioClip({\n      trackId,\n      assetId,\n      startTime: 0,\n      duration: buffer.duration || 5,\n      name: item.name,\n    }),\n  );\n}\n\nasync function importVideo(item: HostMediaImport, setTab: (tab: StudioTab) => void): Promise<void> {\n  const safeName = item.name.replace(/[^\\w.\\-]+/g, '_').slice(0, 40) || 'video';\n  const downloaded = await fetchRemoteMediaAsFile(item.url, `${safeName}.mp4`, 'video/mp4');\n  if (!downloaded) return;\n\n  const meta = await readVideoMeta(downloaded.objectUrl);\n  const width = Math.max(16, meta.width || 1920);\n  const height = Math.max(16, meta.height || 1080);\n\n  useVideoStore.getState().createVideoProject(item.name, closestAspect(width, height), '#000000');\n  useVideoStore.getState().setCanvasSize(width, height);\n  setTab('video');\n\n  const assetId = `host_vid_${Date.now()}`;\n  const asset: Asset = {\n    id: assetId,\n    name: item.name,\n    url: downloaded.objectUrl,\n    type: 'video',\n    duration: meta.duration || 5,\n    width,\n    height,\n    file: downloaded.file,\n    thumbnail: meta.thumb,\n    remoteUrl: item.url,\n  };\n  useVideoStore.getState().addAsset(asset);\n\n  const trackId =\n    useVideoStore.getState().tracks.find((track) => track.type === 'video')?.id ??\n    `v1-${useVideoStore.getState().activeVideoProjectId ?? 'import'}`;\n\n  useVideoStore.getState().addClip(trackId, {\n    trackId,\n    assetId,\n    startTime: 0,\n    duration: meta.duration || 5,\n    trimIn: 0,\n    trimOut: 0,\n    speed: 1,\n    volume: 1,\n    opacity: 1,\n    muted: false,\n    type: 'video',\n    name: item.name,\n  });\n}\n\nexport async function applyHostMediaImport(\n  item: HostMediaImport,\n  setTab: (tab: StudioTab) => void,\n): Promise<void> {\n  setTab(item.kind);\n  if (item.kind === 'image') {\n    await importImage(item, setTab);\n    return;\n  }\n  if (item.kind === 'audio') {\n    await importAudio(item, setTab);\n    return;\n  }\n  await importVideo(item, setTab);\n}\n", "/**\n * Bootstrap identity + API auth from Wizard cookies when the editor runs\n * as the Vite SPA on localhost:5173 (opened from Wizard in development).\n *\n * Cookie names mirror Wizard-AI-FrontEnd AuthContext / BrandContext:\n *   - kaiman_session       \u2192 accountId\n *   - wizard_selected_brand \u2192 active brand { id, brandName, logoUrl? }\n *\n * Cookies for `localhost` are not port-scoped, so values set on :3000\n * are readable from document.cookie on :5173 (js-cookie, not HttpOnly).\n * Cloud editables (`/api/kaiman/*`) auth via those cookies through the\n * Wizard BFF proxy \u2014 not Bearer to .NET directly.\n */\n\nimport { configureWizardApiClient } from './wizardApiClient';\nimport { setEditorIdentity } from './identity';\nimport { setActiveEditorBrand } from './activeEditorBrand';\nimport type { EditorBrandOption } from '../types/brand.types';\n\nconst TOKEN_COOKIE = 'wizard_access_token';\nconst SESSION_COOKIE = 'kaiman_session';\nconst BRAND_COOKIE = 'wizard_selected_brand';\n\nexport type HostCookieBootstrap = {\n  brand: EditorBrandOption | null;\n  accountId: number | null;\n  hasToken: boolean;\n};\n\nfunction readCookie(name: string): string | null {\n  if (typeof document === 'undefined') return null;\n  const prefix = `${encodeURIComponent(name)}=`;\n  const parts = document.cookie.split(';');\n  for (const part of parts) {\n    const trimmed = part.trim();\n    if (trimmed.startsWith(prefix)) {\n      return decodeURIComponent(trimmed.slice(prefix.length));\n    }\n  }\n  // js-cookie may store without encodeURIComponent on the name\n  const rawPrefix = `${name}=`;\n  for (const part of parts) {\n    const trimmed = part.trim();\n    if (trimmed.startsWith(rawPrefix)) {\n      try {\n        return decodeURIComponent(trimmed.slice(rawPrefix.length));\n      } catch {\n        return trimmed.slice(rawPrefix.length);\n      }\n    }\n  }\n  return null;\n}\n\nfunction parseJsonCookie<T>(raw: string | null): T | null {\n  if (!raw) return null;\n  try {\n    return JSON.parse(raw) as T;\n  } catch {\n    return null;\n  }\n}\n\ntype SessionShape = {\n  id?: number;\n  accountId?: number;\n  accountType?: string;\n};\n\ntype BrandCookieShape = {\n  id?: string | number;\n  brandName?: string;\n  logoUrl?: string;\n};\n\nfunction resolveAccountId(session: SessionShape | null): number | null {\n  if (!session) return null;\n  if (session.accountType === 'MASTER' && typeof session.id === 'number') {\n    return session.id;\n  }\n  if (typeof session.accountId === 'number') return session.accountId;\n  if (typeof session.id === 'number') return session.id;\n  return null;\n}\n\nexport function parseBrandCookieValue(raw: string | null): EditorBrandOption | null {\n  const brandRaw = parseJsonCookie<BrandCookieShape>(raw);\n  if (brandRaw?.id == null || typeof brandRaw.brandName !== 'string') {\n    return null;\n  }\n  return {\n    id: String(brandRaw.id),\n    name: brandRaw.brandName,\n    logoUrl: typeof brandRaw.logoUrl === 'string' ? brandRaw.logoUrl : undefined,\n  };\n}\n\n/** Read `wizard_selected_brand` from document.cookie (js-cookie compatible). */\nexport function readSelectedBrandFromCookie(): EditorBrandOption | null {\n  return parseBrandCookieValue(readCookie(BRAND_COOKIE));\n}\n\n/**\n * Apply Wizard cookies to the editor HTTP client + identity singleton.\n * Returns the parsed brand (if any) for the toolbar provider.\n *\n * Dual-dev routing (Vite :5173 opened from Wizard :3000):\n *   - `/api/kaiman/*`, `/api/brands`, `/api/ai/*`, `/api/stock`, `/api/jobs`,\n *     `/api/download`, `/api/audio/*`, `/api/text/*`, `/api/slides/*`\n *     \u2192 Wizard BFF (vite proxy \u2192 :3000).\n *     Cookie auth (BFF attaches Bearer from HttpOnly `wizard_access_token`).\n *     Audio uses DAW paths (`generate-music`, \u2026), not chat micros (`music-compose`).\n *   - Other `/api/*` \u2192 .NET via Bearer when readable from document.cookie.\n */\nexport function bootstrapFromHostCookies(fallback: {\n  accountId: number;\n  brandId: string;\n  backendUrl: string;\n  devToken: string;\n}): HostCookieBootstrap {\n  const fromWizard = isOpenedFromWizardHost();\n  const token = readCookie(TOKEN_COOKIE);\n  const session = parseJsonCookie<SessionShape>(readCookie(SESSION_COOKIE));\n  const brand = readSelectedBrandFromCookie();\n\n  const accountId = resolveAccountId(session) ?? fallback.accountId;\n  const brandId = brand?.id ?? fallback.brandId;\n  const hasSession = session !== null || brand !== null || Boolean(token);\n\n  // Prefer live Wizard access token. Keep env JWT only for true standalone\n  // (no Wizard cookies) \u2014 a stale VITE_DEV_JWT against .NET yields 401/403.\n  const devToken =\n    token || (!fromWizard && !hasSession ? fallback.devToken : undefined) || undefined;\n\n  configureWizardApiClient({\n    baseUrl: fromWizard || hasSession ? '' : fallback.backendUrl,\n    // Audio/AI BFFs use cookies via Wizard proxy; Bearer still helps\n    // catch-all .NET routes when the token cookie is readable.\n    devToken,\n  });\n  setEditorIdentity({ accountId, brandId });\n  if (brand) setActiveEditorBrand(brand);\n\n  return { brand, accountId, hasToken: Boolean(token || devToken) };\n}\n\n/** True when Wizard opened this Vite SPA (`?fromWizard=1`). */\nexport function isOpenedFromWizardHost(): boolean {\n  if (typeof window === 'undefined') return false;\n  return new URLSearchParams(window.location.search).get('fromWizard') === '1';\n}\n", "import { useEffect } from 'react';\nimport {\n  flushAllProjectPersistence,\n  getAllProjectPersistence,\n  type ProjectPersistenceController,\n} from '../lib/persistence/projectPersistence';\n\nconst HEARTBEAT_MS = 5000;\n\nexport type UseProjectPersistenceOptions = {\n  /** Controllers to host; defaults to the global registry. */\n  controllers?: ProjectPersistenceController[];\n  /**\n   * False while IndexedDB hydration is in progress. Heartbeat must not\n   * flushLocal until stores have finished load \u2014 otherwise empty/default\n   * state can overwrite the last good project (especially audio).\n   */\n  hydrated?: boolean;\n};\n\n/**\n * App-level persistence host (image-editor pattern, all modes):\n * - Heartbeat: persist IndexedDB every 5s even if debounce was cancelled oddly\n * - visibilitychange / pagehide: flush local \u2192 cloud for every registered mode\n *\n * Controllers must be registered by each store at module init via\n * `registerProjectPersistence(createProjectPersistence(...))`.\n */\nexport function useProjectPersistence(\n  options: UseProjectPersistenceOptions | ProjectPersistenceController[] = {}\n): void {\n  const normalized: UseProjectPersistenceOptions = Array.isArray(options)\n    ? { controllers: options, hydrated: true }\n    : options;\n  const { controllers, hydrated = true } = normalized;\n\n  useEffect(() => {\n    if (!hydrated) return;\n\n    const list = () =>\n      controllers && controllers.length > 0\n        ? controllers\n        : getAllProjectPersistence();\n\n    const heartbeat = window.setInterval(() => {\n      for (const c of list()) {\n        void c.flushLocal();\n      }\n    }, HEARTBEAT_MS);\n\n    const onHide = () => {\n      if (document.visibilityState !== 'hidden') return;\n      void flushAllProjectPersistence();\n    };\n\n    const onPageHide = () => {\n      void flushAllProjectPersistence();\n    };\n\n    document.addEventListener('visibilitychange', onHide);\n    window.addEventListener('pagehide', onPageHide);\n\n    return () => {\n      window.clearInterval(heartbeat);\n      document.removeEventListener('visibilitychange', onHide);\n      window.removeEventListener('pagehide', onPageHide);\n    };\n  }, [controllers, hydrated]);\n}\n", "import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';\nimport {\n  X, Plus, Film, Image as ImageIcon, Music2, FileText, Presentation,\n  Home, Printer, Monitor, Camera, AlignHorizontalJustifyCenter,\n  FolderOpen, LayoutGrid, RotateCcw,\n  RefreshCw, AlertCircle, Loader2\n} from 'lucide-react';\nimport {\n  listEditables,\n  deleteEditable,\n  type Editable,\n  type EditableMode,\n} from '../services/editableService';\nimport {\n  loadLocalRecentProjects,\n  reopenLocalRecentProject,\n  type LocalRecentProject,\n} from '../lib/persistence/localRecentProjects';\nimport type { SlidesCanvasConfig, SlidesTemplateId } from '../types/slides.types';\nimport { EditorModeToggle } from './editor/EditorModeToggle';\nimport { modeAccentVars } from '../theme/modeAccent';\nimport { CloudEditableCard } from './editor/CloudEditableCard';\nimport { projectAccept } from '../utils/projectExtensions';\nimport { useTranslation, useLocale, type Locale } from '../i18n';\nimport { TextBody, TextTitle } from './ui';\n\nexport type { SlidesCanvasConfig };\n\n// \u2500\u2500\u2500 TYPES \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface ImageCanvasConfig {\n  name: string;\n  width: number;\n  height: number;\n  backgroundColor: string;\n  orientation: 'landscape' | 'portrait';\n}\n\nexport interface VideoCanvasConfig {\n  name: string;\n  aspectRatio: '16:9' | '9:16' | '1:1' | '4:3' | '3:4' | '21:9';\n  backgroundColor: string;\n}\n\nexport interface AudioCanvasConfig {\n  name: string;\n  sampleRate: number;\n  bpm: number;\n  template: 'empty' | 'podcast' | 'music' | 'voiceover';\n}\n\nexport interface TextCanvasConfig {\n  name: string;\n  docType: 'blank' | 'blog' | 'script' | 'newsletter' | 'landing' | 'social';\n  pageSize: 'letter' | 'legal' | 'a4' | 'a5';\n  orientation: 'portrait' | 'landscape';\n  columns: number;\n  language: string;\n  tone: 'neutral' | 'formal' | 'casual' | 'persuasive' | 'technical' | 'friendly';\n  targetChannel: 'blog' | 'instagram' | 'linkedin' | 'x' | 'email' | 'ad' | 'youtube';\n}\n\nexport interface TextPreset {\n  id: string;\n  name: string;\n  docType: TextCanvasConfig['docType'];\n  tone: TextCanvasConfig['tone'];\n  targetChannel: TextCanvasConfig['targetChannel'];\n}\n\nexport const TEXT_PRESETS: TextPreset[] = [\n  { id: 't-blank', name: 'Documento en blanco', docType: 'blank', tone: 'neutral', targetChannel: 'blog' },\n  { id: 't-blog', name: 'Articulo de blog', docType: 'blog', tone: 'friendly', targetChannel: 'blog' },\n  { id: 't-script', name: 'Guion', docType: 'script', tone: 'persuasive', targetChannel: 'youtube' },\n  { id: 't-news', name: 'Newsletter', docType: 'newsletter', tone: 'casual', targetChannel: 'email' },\n  { id: 't-landing', name: 'Landing copy', docType: 'landing', tone: 'persuasive', targetChannel: 'ad' },\n  { id: 't-social', name: 'Post social', docType: 'social', tone: 'casual', targetChannel: 'instagram' },\n];\n\nexport interface SlidesPreset {\n  id: string;\n  name: string;\n  template: SlidesTemplateId;\n  width: number;\n  height: number;\n}\n\nexport const SLIDES_PRESETS: SlidesPreset[] = [\n  { id: 's-blank', name: 'Presentacion en blanco', template: 'blank', width: 1920, height: 1080 },\n  { id: 's-pitch', name: 'Pitch deck', template: 'pitch', width: 1920, height: 1080 },\n  { id: 's-qbr', name: 'QBR / Business review', template: 'qbr', width: 1920, height: 1080 },\n  { id: 's-course', name: 'Curso / Workshop', template: 'course', width: 1920, height: 1080 },\n  { id: 's-report', name: 'Informe', template: 'report', width: 1920, height: 1080 },\n  { id: 's-keynote', name: 'Keynote', template: 'keynote', width: 1920, height: 1080 },\n  { id: 's-43', name: '4:3 clasico', template: 'blank', width: 1440, height: 1080 },\n  { id: 's-916', name: 'Stories / Reels 9:16', template: 'blank', width: 1080, height: 1920 },\n  { id: 's-a4', name: 'A4 landscape', template: 'report', width: 1754, height: 1240 },\n];\n\nexport interface ProjectSetupModalProps {\n  /** Which editor mode triggered the modal */\n  mode: 'image' | 'video' | 'audio' | 'text' | 'slides';\n  /** Called when user creates a canvas via config form or preset */\n  onCreateImage: (config: ImageCanvasConfig) => void;\n  onCreateVideo: (config: VideoCanvasConfig) => void;\n  onCreateAudio?: (config: AudioCanvasConfig) => void;\n  onCreateText?: (config: TextCanvasConfig) => void;\n  onCreateSlides?: (config: SlidesCanvasConfig) => void;\n  /** Called to dismiss the modal (only if there's already an active project) */\n  onClose?: () => void;\n  /** Whether there's already at least one open project (shows the \u00D7 button) */\n  canClose?: boolean;\n  /** Called when the user uploads a .wzrd / .kaiv / .kaia / .kait file */\n  onOpenFile?: (file: File) => void;\n  /**\n   * Called when the user opens a project from the \"Recientes\" cloud list.\n   * The host downloads the binary, parses it, and dispatches the right\n   * importVideoProject / importImageProject action.\n   */\n  onOpenCloudProject?: (editable: Editable) => Promise<void>;\n}\n\n// \u2500\u2500\u2500 PRESET DATA \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** SVG thumbnail factory \u2014 renders a proportional rectangle icon */\nconst PresetThumb: React.FC<{ w: number; h: number; color?: string }> = ({ w, h, color = 'var(--we-accent)' }) => {\n  const maxDim = 28;\n  const ratio = w / h;\n  let tw = maxDim, th = maxDim;\n  if (ratio > 1) { th = Math.round(maxDim / ratio); } else { tw = Math.round(maxDim * ratio); }\n  return (\n    <svg width={maxDim} height={maxDim} viewBox={`0 0 ${maxDim} ${maxDim}`} fill=\"none\">\n      <rect\n        x={(maxDim - tw) / 2} y={(maxDim - th) / 2}\n        width={tw} height={th}\n        rx=\"2\" fill={color} fillOpacity=\"0.15\" stroke={color} strokeWidth=\"1.5\"\n      />\n    </svg>\n  );\n};\n\n/**\n * Format an ISO timestamp from the .NET as a short human-readable label.\n * Falls back to \"\u2014\" for the zero-value timestamp the POST response sends\n * before the row is actually persisted.\n */\nfunction formatRecentDate(iso: string, locale: Locale): string {\n  const t = new Date(iso).getTime();\n  if (!Number.isFinite(t) || t <= 0) return '\u2014';\n  const d = new Date(t);\n  return d.toLocaleDateString(locale === 'en' ? 'en-US' : 'es-CO', {\n    day: '2-digit',\n    month: 'short',\n    year: 'numeric',\n  });\n}\n\nconst EDITOR_MODE_TO_EDITABLE = {\n  image: 'Image',\n  video: 'Video',\n  audio: 'Audio',\n  text: 'Text',\n  slides: 'Slides',\n} as const satisfies Record<'image' | 'video' | 'audio' | 'text' | 'slides', EditableMode>;\n\nexport interface ImagePreset {\n  id: string;\n  name: string;\n  category: 'home' | 'photo' | 'social' | 'print' | 'web';\n  width: number;\n  height: number;\n  label?: string; // e.g. \"Instagram Post\"\n}\n\nexport interface VideoPreset {\n  id: string;\n  name: string;\n  category: 'home' | 'social' | 'cinema';\n  aspectRatio: '16:9' | '9:16' | '1:1' | '4:3' | '3:4' | '21:9';\n  label?: string;\n}\n\n/** Complete preset list \u2014 easy to extend */\nexport const IMAGE_PRESETS: ImagePreset[] = [\n  // Home (most popular)\n  { id: 'ig-post',       name: 'Instagram Post',     category: 'home',   width: 1080, height: 1080 },\n  { id: 'yt-thumb',      name: 'YouTube Thumbnail',  category: 'home',   width: 1280, height: 720  },\n  { id: 'a4',            name: 'A4',                  category: 'home',   width: 2480, height: 3508 },\n  { id: 'fb-cover',      name: 'Facebook Cover',      category: 'home',   width: 851,  height: 315  },\n  { id: 'pres-16-9',     name: 'Presentation 16:9',  category: 'home',   width: 1920, height: 1080 },\n  { id: 'twitter-post',  name: 'Twitter Post',        category: 'home',   width: 1200, height: 675  },\n  // Photo\n  { id: 'photo-4x6',    name: '4\u00D76 in Photo',        category: 'photo',  width: 1800, height: 1200 },\n  { id: 'photo-5x7',    name: '5\u00D77 in Photo',        category: 'photo',  width: 2100, height: 1500 },\n  { id: 'photo-8x10',   name: '8\u00D710 in Photo',       category: 'photo',  width: 2400, height: 3000 },\n  { id: 'photo-sq',     name: 'Square Photo',         category: 'photo',  width: 2400, height: 2400 },\n  { id: 'photo-pan',    name: 'Panoramic',            category: 'photo',  width: 4800, height: 1600 },\n  { id: 'photo-port',   name: 'Portrait 2:3',         category: 'photo',  width: 2400, height: 3600 },\n  // Social Media\n  { id: 'ig-story',     name: 'Instagram Story',      category: 'social', width: 1080, height: 1920 },\n  { id: 'ig-reel',      name: 'Instagram Reel',       category: 'social', width: 1080, height: 1920 },\n  { id: 'fb-post',      name: 'Facebook Post',        category: 'social', width: 1200, height: 630  },\n  { id: 'tw-header',    name: 'Twitter Header',       category: 'social', width: 1500, height: 500  },\n  { id: 'li-banner',    name: 'LinkedIn Banner',      category: 'social', width: 1584, height: 396  },\n  { id: 'tiktok',       name: 'TikTok Cover',         category: 'social', width: 1080, height: 1920 },\n  { id: 'yt-banner',    name: 'YouTube Banner',       category: 'social', width: 2560, height: 1440 },\n  { id: 'pin-post',     name: 'Pinterest Pin',        category: 'social', width: 1000, height: 1500 },\n  // Print\n  { id: 'print-a4',    name: 'A4',                    category: 'print',  width: 2480, height: 3508 },\n  { id: 'print-a3',    name: 'A3',                    category: 'print',  width: 3508, height: 4961 },\n  { id: 'print-letter', name: 'Letter (US)',          category: 'print',  width: 2550, height: 3300 },\n  { id: 'biz-card',    name: 'Business Card',         category: 'print',  width: 1050, height: 600  },\n  { id: 'poster-a2',   name: 'Poster A2',             category: 'print',  width: 4961, height: 7016 },\n  { id: 'flyer',       name: 'Flyer A5',              category: 'print',  width: 1748, height: 2480 },\n  // Web\n  { id: 'web-fhd',     name: 'Full HD (1920\u00D71080)',   category: 'web',    width: 1920, height: 1080 },\n  { id: 'web-hd',      name: 'HD (1280\u00D7720)',         category: 'web',    width: 1280, height: 720  },\n  { id: 'web-banner',  name: 'Web Banner',            category: 'web',    width: 728,  height: 90   },\n  { id: 'web-email',   name: 'Email Header',          category: 'web',    width: 600,  height: 200  },\n  { id: 'web-blog',    name: 'Blog Featured',         category: 'web',    width: 1200, height: 628  },\n  { id: 'web-og',      name: 'OG Image',              category: 'web',    width: 1200, height: 630  },\n];\n\nexport const VIDEO_PRESETS: VideoPreset[] = [\n  // Home\n  { id: 'v-yt',         name: 'YouTube (16:9)',        category: 'home',   aspectRatio: '16:9' },\n  { id: 'v-tiktok',     name: 'TikTok / Reels',       category: 'home',   aspectRatio: '9:16' },\n  { id: 'v-sq',         name: 'Square',               category: 'home',   aspectRatio: '1:1'  },\n  { id: 'v-film',       name: 'Cinemascope',          category: 'home',   aspectRatio: '21:9' },\n  { id: 'v-tv',         name: 'Classic TV (4:3)',     category: 'home',   aspectRatio: '4:3'  },\n  { id: 'v-portrait',   name: 'Portrait (3:4)',       category: 'home',   aspectRatio: '3:4'  },\n  // Social\n  { id: 'v-ig-story',   name: 'IG Story',             category: 'social', aspectRatio: '9:16' },\n  { id: 'v-ig-feed',    name: 'IG Feed',              category: 'social', aspectRatio: '1:1'  },\n  { id: 'v-fb-video',   name: 'Facebook Video',       category: 'social', aspectRatio: '16:9' },\n  { id: 'v-tw-video',   name: 'Twitter Video',        category: 'social', aspectRatio: '16:9' },\n  // Cinema\n  { id: 'v-cinema',     name: 'Cinema Wide',          category: 'cinema', aspectRatio: '21:9' },\n  { id: 'v-std',        name: 'Standard (4:3)',       category: 'cinema', aspectRatio: '4:3'  },\n];\n\n// \u2500\u2500\u2500 CATEGORY TABS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ntype CategoryTab = 'home' | 'photo' | 'social' | 'print' | 'web';\ntype VideoCategoryTab = 'home' | 'social' | 'cinema';\n\nconst IMG_TAB_IDS: CategoryTab[] = ['home', 'photo', 'social', 'print', 'web'];\nconst VID_TAB_IDS: VideoCategoryTab[] = ['home', 'social', 'cinema'];\n\nconst IMG_TAB_ICONS: Record<CategoryTab, React.ReactNode> = {\n  home: <Home size={13} />,\n  photo: <Camera size={13} />,\n  social: <LayoutGrid size={13} />,\n  print: <Printer size={13} />,\n  web: <Monitor size={13} />,\n};\n\nconst VID_TAB_ICONS: Record<VideoCategoryTab, React.ReactNode> = {\n  home: <Home size={13} />,\n  social: <LayoutGrid size={13} />,\n  cinema: <Film size={13} />,\n};\n\nconst ASPECT_RATIO_DIMS: Record<string, { w: number; h: number }> = {\n  '16:9': { w: 16, h: 9 },\n  '9:16': { w: 9, h: 16 },\n  '1:1':  { w: 1, h: 1 },\n  '4:3':  { w: 4, h: 3 },\n  '3:4':  { w: 3, h: 4 },\n  '21:9': { w: 21, h: 9 },\n};\n\n// \u2500\u2500\u2500 PRESET CARD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst ImagePresetCard: React.FC<{\n  preset: ImagePreset;\n  displayName: string;\n  tooltip: string;\n  onDoubleClick: () => void;\n  onClick: () => void;\n  selected: boolean;\n}> = ({ preset, displayName, tooltip, onDoubleClick, onClick, selected }) => (\n  <button\n    onDoubleClick={onDoubleClick}\n    onClick={onClick}\n    title={tooltip}\n    className={`flex flex-col items-center gap-1.5 p-2.5 rounded-lg border transition-all cursor-pointer select-none text-center group\n      ${selected\n        ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)]'\n        : 'border-[#2A2A38] bg-[#13131A] hover:border-[var(--we-accent)]/50 hover:bg-[#1C1C26]'\n      }`}\n  >\n    <div className=\"w-9 h-9 flex items-center justify-center rounded-md bg-[#0A0A0F]\">\n      <PresetThumb w={preset.width} h={preset.height} color={selected ? 'var(--we-accent)' : '#8888A0'} />\n    </div>\n    <TextBody as=\"span\" size=\"sm\" className={`leading-tight font-semibold ${selected ? 'text-[var(--we-accent)]' : 'text-[#F0F0F5]'}`}>\n      {displayName}\n    </TextBody>\n    <TextBody as=\"span\" size=\"sm\" className=\"font-mono leading-none text-[#8888A0]\">\n      {preset.width}\u00D7{preset.height}\n    </TextBody>\n  </button>\n);\n\nconst VideoPresetCard: React.FC<{\n  preset: VideoPreset;\n  displayName: string;\n  tooltip: string;\n  onDoubleClick: () => void;\n  onClick: () => void;\n  selected: boolean;\n}> = ({ preset, displayName, tooltip, onDoubleClick, onClick, selected }) => {\n  const d = ASPECT_RATIO_DIMS[preset.aspectRatio] || { w: 16, h: 9 };\n  return (\n    <button\n      onDoubleClick={onDoubleClick}\n      onClick={onClick}\n      title={tooltip}\n      className={`flex flex-col items-center gap-1.5 p-2.5 rounded-lg border transition-all cursor-pointer select-none text-center\n        ${selected\n          ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)]'\n          : 'border-[#2A2A38] bg-[#13131A] hover:border-[var(--we-accent)]/50 hover:bg-[#1C1C26]'\n        }`}\n    >\n      <div className=\"w-9 h-9 flex items-center justify-center rounded-md bg-[#0A0A0F]\">\n        <PresetThumb w={d.w} h={d.h} color={selected ? 'var(--we-accent)' : '#8888A0'} />\n      </div>\n      <TextBody as=\"span\" size=\"sm\" className={`leading-tight font-semibold ${selected ? 'text-[var(--we-accent)]' : 'text-[#F0F0F5]'}`}>\n        {displayName}\n      </TextBody>\n      <TextBody as=\"span\" size=\"sm\" className=\"font-mono leading-none text-[#8888A0]\">\n        {preset.aspectRatio}\n      </TextBody>\n    </button>\n  );\n};\n\n// \u2500\u2500\u2500 MAIN COMPONENT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const ProjectSetupModal: React.FC<ProjectSetupModalProps> = ({\n  mode,\n  onCreateImage,\n  onCreateVideo,\n  onCreateAudio,\n  onCreateText,\n  onCreateSlides,\n  onClose,\n  canClose = false,\n  onOpenFile,\n  onOpenCloudProject,\n}) => {\n  const t = useTranslation();\n  const locale = useLocale();\n  const ps = t.projectSetup;\n\n  const presetDisplayName = useCallback(\n    (id: string, fallback: string) => ps.presetNames[id as keyof typeof ps.presetNames] ?? fallback,\n    [ps.presetNames],\n  );\n\n  const imgTabs = useMemo(\n    () =>\n      IMG_TAB_IDS.map((id) => ({\n        id,\n        label: ps.categoryTabs[id],\n        icon: IMG_TAB_ICONS[id],\n      })),\n    [ps.categoryTabs],\n  );\n\n  const vidTabs = useMemo(\n    () =>\n      VID_TAB_IDS.map((id) => ({\n        id,\n        label: ps.categoryTabs[id],\n        icon: VID_TAB_ICONS[id],\n      })),\n    [ps.categoryTabs],\n  );\n\n  // \u2500\u2500 Active mode: initialized from the mode prop, switchable via the toggle\n  const [activeMode, setActiveMode] = useState<'image' | 'video' | 'audio' | 'text' | 'slides'>(mode);\n  useEffect(() => {\n    setActiveMode(mode);\n  }, [mode]);\n  const isImageMode = activeMode === 'image';\n  const isAudioMode = activeMode === 'audio';\n  const isTextMode = activeMode === 'text';\n  const isSlidesMode = activeMode === 'slides';\n\n  const uploadExtension =\n    isAudioMode ? '.kaia' : isTextMode ? '.kait' : isSlidesMode ? '.kais' : isImageMode ? '.kai' : '.kaiv';\n\n  const activeModeLabel = t.modes[activeMode];\n\n  // \u2500\u2500 Category tabs\n  const [imgTab, setImgTab] = useState<CategoryTab>('home');\n  const [vidTab, setVidTab] = useState<VideoCategoryTab>('home');\n\n  // \u2500\u2500 Selected preset (for highlighting)\n  const [selectedImgPreset, setSelectedImgPreset] = useState<string | null>(null);\n  const [selectedVidPreset, setSelectedVidPreset] = useState<string | null>(null);\n\n  // \u2500\u2500 Right panel: image form\n  const [imgName, setImgName]   = useState('Sin t\u00EDtulo');\n  const [imgWidth, setImgWidth] = useState(1080);\n  const [imgHeight, setImgHeight] = useState(1080);\n  const [imgOrientation, setImgOrientation] = useState<'portrait' | 'landscape'>('portrait');\n  const [imgBg, setImgBg] = useState('#ffffff');\n\n  // \u2500\u2500 Right panel: video form\n  const [vidName, setVidName]               = useState('Sin t\u00EDtulo');\n  const [vidAspect, setVidAspect]           = useState<'16:9' | '9:16' | '1:1' | '4:3' | '3:4' | '21:9'>('16:9');\n  const [vidBg, setVidBg]                   = useState('#000000');\n\n  // \u2500\u2500 Right panel: audio form\n  const [audioName, setAudioName] = useState('Sin t\u00EDtulo');\n  const [audioSampleRate, setAudioSampleRate] = useState(48000);\n  const [audioBpm, setAudioBpm] = useState(120);\n  const [audioTemplate, setAudioTemplate] = useState<'empty' | 'podcast' | 'music' | 'voiceover'>('empty');\n\n  // \u2500\u2500 Right panel: text form\n  const [textName, setTextName] = useState('Sin t\u00EDtulo');\n  const [textDocType, setTextDocType] = useState<TextCanvasConfig['docType']>('blank');\n  const [textPageSize, setTextPageSize] = useState<TextCanvasConfig['pageSize']>('letter');\n  const [textOrientation, setTextOrientation] = useState<'portrait' | 'landscape'>('portrait');\n  const [textColumns, setTextColumns] = useState(1);\n  const [textTone, setTextTone] = useState<TextCanvasConfig['tone']>('neutral');\n  const [textChannel, setTextChannel] = useState<TextCanvasConfig['targetChannel']>('blog');\n  const [textLanguage, setTextLanguage] = useState('es');\n  const [selectedTextPreset, setSelectedTextPreset] = useState<string | null>(null);\n\n  const fileInputRef = useRef<HTMLInputElement>(null);\n\n  // \u2500\u2500 Resolve orientation when width/height change\n  const handleWidthChange = (v: number) => {\n    setImgWidth(v);\n    setImgOrientation(v >= imgHeight ? 'landscape' : 'portrait');\n  };\n  const handleHeightChange = (v: number) => {\n    setImgHeight(v);\n    setImgOrientation(imgWidth >= v ? 'landscape' : 'portrait');\n  };\n  const flipOrientation = () => {\n    setImgWidth(imgHeight);\n    setImgHeight(imgWidth);\n    setImgOrientation(o => o === 'landscape' ? 'portrait' : 'landscape');\n  };\n\n  // \u2500\u2500 Apply image preset \u2192 fill form\n  const applyImagePreset = (preset: ImagePreset) => {\n    setSelectedImgPreset(preset.id);\n    setImgName(presetDisplayName(preset.id, preset.name));\n    setImgWidth(preset.width);\n    setImgHeight(preset.height);\n    setImgOrientation(preset.width >= preset.height ? 'landscape' : 'portrait');\n  };\n\n  // \u2500\u2500 Apply video preset \u2192 fill form\n  const applyVideoPreset = (preset: VideoPreset) => {\n    setSelectedVidPreset(preset.id);\n    setVidName(presetDisplayName(preset.id, preset.name));\n    setVidAspect(preset.aspectRatio as any);\n  };\n\n  // \u2500\u2500 Create actions\n  const handleCreateImage = () => {\n    onCreateImage({\n      name: imgName || ps.untitled,\n      width: imgWidth,\n      height: imgHeight,\n      backgroundColor: imgBg,\n      orientation: imgOrientation,\n    });\n  };\n\n  const handleCreateVideo = () => {\n    onCreateVideo({\n      name: vidName || ps.untitled,\n      aspectRatio: vidAspect,\n      backgroundColor: vidBg,\n    });\n  };\n\n  const handleCreateAudio = () => {\n    onCreateAudio?.({\n      name: audioName || ps.untitled,\n      sampleRate: audioSampleRate,\n      bpm: audioTemplate === 'podcast' ? 0 : audioBpm,\n      template: audioTemplate,\n    });\n  };\n\n  const handleCreateText = () => {\n    onCreateText?.({\n      name: textName || ps.untitled,\n      docType: textDocType,\n      pageSize: textPageSize,\n      orientation: textOrientation,\n      columns: textColumns,\n      language: textLanguage,\n      tone: textTone,\n      targetChannel: textChannel,\n    });\n  };\n\n  const [slidesName, setSlidesName] = useState('Nueva presentacion');\n  const [slidesTemplate, setSlidesTemplate] = useState<SlidesTemplateId>('blank');\n  const [slidesWidth, setSlidesWidth] = useState(1920);\n  const [slidesHeight, setSlidesHeight] = useState(1080);\n  const [selectedSlidesPreset, setSelectedSlidesPreset] = useState<string | null>(null);\n\n  const handleCreateSlides = () => {\n    onCreateSlides?.({\n      name: slidesName || ps.untitled,\n      width: slidesWidth,\n      height: slidesHeight,\n      template: slidesTemplate,\n    });\n  };\n\n  const applySlidesPreset = (preset: SlidesPreset) => {\n    setSelectedSlidesPreset(preset.id);\n    setSlidesName(presetDisplayName(preset.id, preset.name));\n    setSlidesTemplate(preset.template);\n    setSlidesWidth(preset.width);\n    setSlidesHeight(preset.height);\n  };\n\n  const applyTextPreset = (preset: TextPreset) => {\n    setSelectedTextPreset(preset.id);\n    setTextName(presetDisplayName(preset.id, preset.name));\n    setTextDocType(preset.docType);\n    setTextTone(preset.tone);\n    setTextChannel(preset.targetChannel);\n  };\n\n  // \u2500\u2500 File upload\n  const handleFileInput = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const file = e.target.files?.[0];\n    if (!file) return;\n    onOpenFile?.(file);\n    e.target.value = '';\n  };\n\n  // \u2500\u2500 Filtered presets (follow active toggle)\n  const filteredImgPresets = IMAGE_PRESETS.filter(p => p.category === imgTab);\n  const filteredVidPresets = VIDEO_PRESETS.filter(p => p.category === vidTab);\n\n  // \u2500\u2500 Cloud editables (Recientes) \u2014 fetched from /api/kaiman/editables.\n  // We store the raw list (all editables the user has) and derive the\n  // filtered view via `useMemo` keyed on `activeMode`, so the list updates\n  // instantly when the user switches modes in the toggle.\n  const [allRecentEditables, setAllRecentEditables] = useState<Editable[]>([]);\n  const [localRecents, setLocalRecents] = useState<LocalRecentProject[]>([]);\n  const [recentLoading, setRecentLoading] = useState(false);\n  const [recentError, setRecentError] = useState<string | null>(null);\n  const [openingId, setOpeningId] = useState<number | null>(null);\n  const [openingLocalId, setOpeningLocalId] = useState<string | null>(null);\n  const [deletingId, setDeletingId] = useState<number | null>(null);\n\n  const recentEditables = useMemo(\n    () => allRecentEditables.filter((e) => e.mode === EDITOR_MODE_TO_EDITABLE[activeMode]),\n    [allRecentEditables, activeMode]\n  );\n\n  const cloudIds = useMemo(\n    () => new Set(recentEditables.map((e) => e.id)),\n    [recentEditables]\n  );\n\n  const localEditables = useMemo(\n    () =>\n      localRecents.filter(\n        (p) =>\n          p.mode === EDITOR_MODE_TO_EDITABLE[activeMode] &&\n          (p.cloudEditableId == null || !cloudIds.has(p.cloudEditableId))\n      ),\n    [localRecents, activeMode, cloudIds]\n  );\n\n  const otherTypesCount =\n    allRecentEditables.length - recentEditables.length +\n    localRecents.filter((p) => p.mode !== EDITOR_MODE_TO_EDITABLE[activeMode]).length;\n\n  const hasAnyRecents = recentEditables.length > 0 || localEditables.length > 0;\n\n  const fetchRecents = useCallback(async () => {\n    setRecentLoading(true);\n    setRecentError(null);\n    const mode = EDITOR_MODE_TO_EDITABLE[activeMode];\n    try {\n      const locals = await loadLocalRecentProjects(mode);\n      setLocalRecents(locals);\n\n      const { hasEditorIdentity } = await import('../services/identity');\n      if (!hasEditorIdentity()) {\n        setRecentError(ps.errors.sessionNotConfigured);\n        setAllRecentEditables([]);\n        return;\n      }\n\n      // Prefer account-wide list so brand cookie mismatches don't hide files.\n      let items = await listEditables({ scope: 'account' });\n      if (items.length === 0) {\n        items = await listEditables({ scope: 'brand' });\n      }\n      const sorted = [...items].sort((a, b) => {\n        const ta = new Date(a.createdAt).getTime();\n        const tb = new Date(b.createdAt).getTime();\n        if (!Number.isFinite(ta) || !Number.isFinite(tb)) return b.id - a.id;\n        return tb - ta;\n      });\n      setAllRecentEditables(sorted);\n    } catch (err) {\n      const name = err && typeof err === 'object' && 'name' in err ? String((err as { name: string }).name) : '';\n      const msg =\n        name === 'AuthError'\n          ? ps.errors.sessionExpired\n          : err instanceof Error\n            ? err.message\n            : String(err);\n      setRecentError(msg);\n      setAllRecentEditables([]);\n      // Keep whatever local list we managed to load.\n    } finally {\n      setRecentLoading(false);\n    }\n  }, [activeMode, ps.errors.sessionExpired, ps.errors.sessionNotConfigured]);\n\n  useEffect(() => {\n    // eslint-disable-next-line react-hooks/set-state-in-effect\n    fetchRecents();\n  }, [fetchRecents]);\n\n  const handleOpenLocal = useCallback(async (item: LocalRecentProject) => {\n    setOpeningLocalId(item.id);\n    try {\n      await reopenLocalRecentProject(item);\n    } catch (err) {\n      const msg = err instanceof Error ? err.message : String(err);\n      setRecentError(ps.errors.openFailed(item.name, msg));\n    } finally {\n      setOpeningLocalId(null);\n    }\n  }, [ps.errors]);\n\n  const handleOpenCloud = useCallback(\n    async (editable: Editable) => {\n      if (!onOpenCloudProject) return;\n      setOpeningId(editable.id);\n      try {\n        const { getEditable } = await import('../services/editableService');\n        const fresh = await getEditable({ id: editable.id });\n        await onOpenCloudProject(fresh);\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        setRecentError(ps.errors.openFailed(editable.name, msg));\n      } finally {\n        setOpeningId(null);\n      }\n    },\n    [onOpenCloudProject, ps.errors]\n  );\n\n  const handleDeleteCloud = useCallback(\n    async (editable: Editable) => {\n      const ok = window.confirm(ps.confirmDeleteCloud(editable.name));\n      if (!ok) return;\n      setDeletingId(editable.id);\n      try {\n        await deleteEditable({ id: editable.id });\n        setAllRecentEditables((prev) => prev.filter((e) => e.id !== editable.id));\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        setRecentError(ps.errors.deleteFailed(editable.name, msg));\n      } finally {\n        setDeletingId(null);\n      }\n    },\n    [ps.confirmDeleteCloud, ps.errors]\n  );\n\n  // NOTE: isImageMode is now derived from activeMode, not from the prop\n\n  return (\n    <>\n      {/* Backdrop */}\n      <div\n        className=\"fixed inset-0 z-[300] bg-black/50 backdrop-blur-sm\"\n        onClick={canClose ? onClose : undefined}\n      />\n\n      {/* Modal */}\n      <div className=\"fixed inset-0 z-[301] flex items-center justify-center p-4 pointer-events-none\">\n        <div\n          className=\"pointer-events-auto flex h-[min(94vh,1080px)] w-[min(96vw,1600px)] max-w-none flex-col overflow-hidden rounded-2xl border border-panel-border bg-panel shadow-2xl shadow-black/80 animate-fade-in\"\n          style={modeAccentVars(activeMode)}\n          data-we-mode={activeMode}\n          onClick={e => e.stopPropagation()}\n        >\n          {/* \u2500\u2500 Header with category tabs \u2500\u2500 */}\n          <div className=\"flex items-center justify-between px-5 py-2 border-b border-panel-border flex-shrink-0\">\n            <div className=\"flex items-center gap-1\">\n              {isSlidesMode ? (\n                <div className=\"flex items-center gap-1.5 border-b-2 border-[var(--we-accent)] px-3 py-2 text-[var(--we-accent)]\">\n                  <Presentation size={12} />\n                  <TextTitle as=\"span\" size=\"xs\" className=\"text-[var(--we-accent)]\">{ps.templateHeaders.slides}</TextTitle>\n                </div>\n              ) : isTextMode ? (\n                <div className=\"flex items-center gap-1.5 border-b-2 border-[var(--we-accent)] px-3 py-2 text-[var(--we-accent)]\">\n                  <FileText size={12} />\n                  <TextTitle as=\"span\" size=\"xs\" className=\"text-[var(--we-accent)]\">{ps.templateHeaders.text}</TextTitle>\n                </div>\n              ) : isAudioMode ? (\n                <div className=\"flex items-center gap-1.5 border-b-2 border-[var(--we-accent)] px-3 py-2 text-[var(--we-accent)]\">\n                  <Music2 size={12} />\n                  <TextTitle as=\"span\" size=\"xs\" className=\"text-[var(--we-accent)]\">{ps.templateHeaders.audio}</TextTitle>\n                </div>\n              ) : isImageMode\n                ? imgTabs.map(tab => (\n                  <button\n                    key={tab.id}\n                    onClick={() => setImgTab(tab.id as CategoryTab)}\n                    className={`-mb-px flex items-center gap-1.5 rounded-t-lg border-b-2 px-3 py-2 transition-all\n                      ${imgTab === tab.id\n                        ? 'border-[var(--we-accent)] text-[var(--we-accent)]'\n                        : 'border-transparent text-[#8888A0] hover:text-[#F0F0F5]'\n                      }`}\n                  >\n                    {tab.icon}\n                    <TextBody as=\"span\" size=\"sm\" className=\"font-bold\">{tab.label}</TextBody>\n                  </button>\n                ))\n                : vidTabs.map(tab => (\n                  <button\n                    key={tab.id}\n                    onClick={() => setVidTab(tab.id as VideoCategoryTab)}\n                    className={`-mb-px flex items-center gap-1.5 rounded-t-lg border-b-2 px-3 py-2 transition-all\n                      ${vidTab === tab.id\n                        ? 'border-[var(--we-accent)] text-[var(--we-accent)]'\n                        : 'border-transparent text-[#8888A0] hover:text-[#F0F0F5]'\n                      }`}\n                  >\n                    {tab.icon}\n                    <TextBody as=\"span\" size=\"sm\" className=\"font-bold\">{tab.label}</TextBody>\n                  </button>\n                ))\n              }\n            </div>\n\n            {/* Close button \u2014 always visible; disabled if no open project to return to */}\n            <button\n              onClick={canClose ? onClose : undefined}\n              disabled={!canClose}\n              className={`flex items-center justify-center w-8 h-8 rounded-lg transition-all flex-shrink-0 ml-4\n                ${canClose\n                  ? 'text-[#8888A0] hover:text-[#F0F0F5] hover:bg-[#1C1C26] cursor-pointer'\n                  : 'text-[#3A3A48] cursor-not-allowed'\n                }`}\n              title={canClose ? ps.close : ps.closeDisabled}\n            >\n              <X size={16} />\n            </button>\n          </div>\n\n          {/* \u2500\u2500 Body: left panel + right panel \u2500\u2500 */}\n          <div className=\"flex flex-1 min-h-0 overflow-hidden\">\n\n            {/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500 LEFT PANEL \u2014 70% \u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n            <div className=\"w-[70%] flex-shrink-0 flex flex-col border-r border-panel-border overflow-hidden\">\n              <div className=\"flex-1 overflow-y-auto p-4 space-y-5 scrollbar-none\">\n\n                {/* Recent files \u2014 API-ready section */}\n                <section>\n                  <div className=\"flex items-center justify-between mb-2.5\">\n                    <TextTitle as=\"h3\" size=\"xs\" className=\"uppercase tracking-wider text-[#8888A0]\">\n                      {ps.recents}\n                    </TextTitle>\n                    <div className=\"flex items-center gap-2\">\n                      {recentError && (\n                        <TextBody as=\"span\" size=\"sm\" className=\"flex items-center gap-1 text-red-400 max-w-[200px] truncate\">\n                          <AlertCircle size={11} />\n                          {recentError}\n                        </TextBody>\n                      )}\n                      <button\n                        onClick={fetchRecents}\n                        disabled={recentLoading}\n                        title={ps.refreshList}\n                        className=\"flex items-center justify-center w-6 h-6 rounded-md text-[#8888A0] hover:text-[#F0F0F5] hover:bg-[#1C1C26] disabled:opacity-40 disabled:cursor-not-allowed transition-all\"\n                      >\n                        <RefreshCw size={11} className={recentLoading ? 'animate-spin' : ''} />\n                      </button>\n                    </div>\n                  </div>\n\n                  <div className=\"flex gap-2 h-50 overflow-x-auto pb-1 scrollbar-none\">\n                    {/* Upload button \u2014 square tile in the carousel */}\n                    <button\n                      type=\"button\"\n                      onClick={() => fileInputRef.current?.click()}\n                      className=\"flex aspect-square h-full w-auto shrink-0 cursor-pointer flex-col items-center justify-center gap-1 rounded-xl border border-[var(--we-accent)] bg-[var(--we-accent)] px-2.5 py-2 transition-all hover:bg-[var(--we-accent-hover)] group active:scale-95\"\n                      title={`${ps.upload.verb} ${uploadExtension} \u2014 ${ps.upload.hint}`}\n                    >\n                      <Plus size={22} className=\"shrink-0 text-white\" strokeWidth={2.5} />\n                      <TextBody as=\"span\" size=\"sm\" className=\"select-none px-2 text-center text-white\">\n                        {ps.upload.verb}{' '}\n                        <span className=\"font-bold\">{uploadExtension}</span>\n                      </TextBody>\n                      <TextBody as=\"span\" size=\"sm\" className=\"select-none px-0.5 text-center text-white/95\">\n                        {ps.upload.hint}\n                      </TextBody>\n                    </button>\n\n                    {/* Recent file cards \u2014 loading */}\n                    {recentLoading && !hasAnyRecents && (\n                      <div className=\"flex aspect-square h-full w-auto shrink-0 flex-col items-center justify-center gap-1.5 rounded-xl border border-dashed border-[#2A2A38] text-center px-2\">\n                        <Loader2 size={16} className=\"animate-spin text-[var(--we-accent)]\" />\n                        <TextBody as=\"span\" size=\"sm\" className=\"text-[#8888A0]\">\n                          {ps.loadingProjects}\n                        </TextBody>\n                      </div>\n                    )}\n\n                    {/* Recent file cards \u2014 empty */}\n                    {!recentLoading && !hasAnyRecents && !recentError && (\n                      <div className=\"flex aspect-square h-full w-auto shrink-0 flex-col items-center justify-center gap-1 rounded-xl border border-dashed border-[#2A2A38] px-2 text-center\">\n                        <FolderOpen size={16} className=\"mb-1 text-[#8888A0]\" />\n                        {otherTypesCount > 0 ? (\n                          <>\n                            <TextBody as=\"span\" size=\"sm\" className=\"leading-tight text-[#8888A0]\">\n                              {ps.noProjectsForMode(activeModeLabel)}\n                            </TextBody>\n                            <TextBody as=\"span\" size=\"sm\" className=\"text-[var(--we-accent)]\">\n                              {ps.projectsInOtherModes(otherTypesCount)}\n                            </TextBody>\n                          </>\n                        ) : (\n                          <TextBody as=\"span\" size=\"sm\" className=\"text-[#8888A0]\">\n                            {ps.noRecentFiles}\n                          </TextBody>\n                        )}\n                      </div>\n                    )}\n\n                    {/* Recent file cards \u2014 error (still show local if any) */}\n                    {!recentLoading && !hasAnyRecents && recentError && (\n                      <button\n                        type=\"button\"\n                        onClick={fetchRecents}\n                        className=\"flex aspect-square h-full w-auto shrink-0 cursor-pointer flex-col items-center justify-center gap-1 rounded-xl border border-dashed border-red-500/30 px-2 text-center transition-colors hover:bg-red-500/5\"\n                      >\n                        <AlertCircle size={16} className=\"text-red-400\" />\n                        <TextBody as=\"span\" size=\"sm\" className=\"text-red-300\">\n                          {ps.retry}\n                        </TextBody>\n                      </button>\n                    )}\n\n                    {/* Local IndexedDB projects (survive closing tabs) */}\n                    {localEditables.map((item) => {\n                      const isOpening = openingLocalId === item.id;\n                      const showRaster =\n                        Boolean(item.thumbnail) &&\n                        (item.mode === 'Image' ||\n                          item.mode === 'Video' ||\n                          item.mode === 'Slides');\n                      const ModeIcon =\n                        item.mode === 'Video'\n                          ? Film\n                          : item.mode === 'Audio'\n                            ? Music2\n                            : item.mode === 'Text'\n                              ? FileText\n                              : item.mode === 'Slides'\n                                ? Presentation\n                                : ImageIcon;\n                      return (\n                        <button\n                          key={`local-${item.id}`}\n                          type=\"button\"\n                          disabled={isOpening}\n                          onClick={() => void handleOpenLocal(item)}\n                          className=\"group relative flex aspect-square h-full w-auto shrink-0 cursor-pointer flex-col overflow-hidden rounded-xl border border-panel-border bg-[#0A0A0F] text-left transition-all hover:border-[var(--we-accent)] disabled:cursor-wait disabled:opacity-60\"\n                          title={\n                            item.cloudEditableId\n                              ? `${item.name} (${t.editor.localAndCloud})`\n                              : `${item.name} (${t.editor.localOnly})`\n                          }\n                        >\n                          <div className=\"relative flex flex-1 items-center justify-center overflow-hidden bg-[#13131A]\">\n                            {isOpening ? (\n                              <Loader2 size={18} className=\"animate-spin text-[var(--we-accent)]\" />\n                            ) : showRaster ? (\n                              <img\n                                src={item.thumbnail}\n                                alt=\"\"\n                                className=\"h-full w-full object-cover\"\n                              />\n                            ) : (\n                              <ModeIcon size={28} className=\"text-[var(--we-accent)]\" />\n                            )}\n                          </div>\n                          <div className=\"border-t border-panel-border px-2 py-1.5\">\n                            <TextBody as=\"p\" size=\"sm\" className=\"truncate font-bold text-[#F0F0F5]\">\n                              {item.name}\n                            </TextBody>\n                            <TextBody as=\"p\" size=\"sm\" className=\"text-[#8888A0]\">\n                              {item.cloudEditableId != null ? t.editor.localAndCloud : t.editor.localOnly}\n                            </TextBody>\n                          </div>\n                        </button>\n                      );\n                    })}\n\n                    {/* Cloud Recientes */}\n                    {recentEditables.map((editable) => {\n                      const isOpening = openingId === editable.id;\n                      const isDeleting = deletingId === editable.id;\n                      return (\n                        <CloudEditableCard\n                          key={editable.id}\n                          editable={editable}\n                          aspect=\"square\"\n                          formattedDate={formatRecentDate(editable.createdAt, locale)}\n                          disabled={isOpening || isDeleting}\n                          onOpen={() => handleOpenCloud(editable)}\n                          onDelete={\n                            onOpenCloudProject\n                              ? () => handleDeleteCloud(editable)\n                              : undefined\n                          }\n                        />\n                      );\n                    })}\n                  </div>\n\n                  <input\n                    ref={fileInputRef}\n                    type=\"file\"\n                    accept={\n                      isSlidesMode\n                        ? projectAccept('slides', ['.pptx', '.md', '.json'])\n                        : isTextMode\n                          ? projectAccept('text', ['.md', '.json'])\n                          : isAudioMode\n                            ? projectAccept('audio', ['.json'])\n                            : isImageMode\n                              ? projectAccept('image')\n                              : projectAccept('video')\n                    }\n                    className=\"hidden\"\n                    onChange={handleFileInput}\n                  />\n                </section>\n\n                {/* Presets section */}\n                <section>\n                  <div className=\"flex items-center justify-between mb-2.5\">\n                    <TextTitle as=\"h3\" size=\"xs\" className=\"uppercase tracking-wider text-[#8888A0]\">\n                      {isSlidesMode\n                        ? ps.templateHeaders.slides\n                        : isTextMode\n                          ? ps.templateHeaders.text\n                          : isAudioMode\n                            ? ps.templateHeaders.audio\n                            : ps.presetsTitle(isImageMode ? filteredImgPresets.length : filteredVidPresets.length)}\n                    </TextTitle>\n                    <TextBody as=\"span\" size=\"sm\" className=\"text-[#8888A0]\">\n                      {isAudioMode || isTextMode || isSlidesMode ? ps.presetsHintQuick : ps.presetsHintCreate}\n                    </TextBody>\n                  </div>\n\n                  <div className=\"grid grid-cols-3 gap-1.5\">\n                    {isSlidesMode\n                      ? SLIDES_PRESETS.map((p) => (\n                        <button\n                          key={p.id}\n                          type=\"button\"\n                          onClick={() => applySlidesPreset(p)}\n                          onDoubleClick={() => {\n                            applySlidesPreset(p);\n                            onCreateSlides?.({\n                              name: presetDisplayName(p.id, p.name),\n                              width: p.width,\n                              height: p.height,\n                              template: p.template,\n                            });\n                          }}\n                          className={`flex flex-col items-center gap-1 p-2.5 rounded-lg border text-center ${\n                            selectedSlidesPreset === p.id\n                              ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)]'\n                              : 'border-[#2A2A38] bg-[#13131A] hover:border-[var(--we-accent)]/50'\n                          }`}\n                        >\n                          <Presentation size={16} className=\"text-[var(--we-accent)]\" />\n                          <TextBody as=\"span\" size=\"sm\" className=\"text-[#F0F0F5]\">{presetDisplayName(p.id, p.name)}</TextBody>\n                          <TextBody as=\"span\" size=\"sm\" className=\"text-[#8888A0]\">{p.width}x{p.height}</TextBody>\n                        </button>\n                      ))\n                      : isTextMode\n                      ? TEXT_PRESETS.map((p) => (\n                        <button\n                          key={p.id}\n                          type=\"button\"\n                          onClick={() => applyTextPreset(p)}\n                          onDoubleClick={() => {\n                            applyTextPreset(p);\n                            onCreateText?.({\n                              name: presetDisplayName(p.id, p.name),\n                              docType: p.docType,\n                              language: textLanguage,\n                              tone: p.tone,\n                              targetChannel: p.targetChannel,\n                            });\n                          }}\n                          className={`flex flex-col items-center gap-1 p-2.5 rounded-lg border text-center ${\n                            selectedTextPreset === p.id\n                              ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)]'\n                              : 'border-[#2A2A38] bg-[#13131A] hover:border-[var(--we-accent)]/50'\n                          }`}\n                        >\n                          <FileText size={16} className=\"text-[var(--we-accent)]\" />\n                          <TextBody as=\"span\" size=\"sm\" className=\"text-[#F0F0F5]\">{presetDisplayName(p.id, p.name)}</TextBody>\n                          <TextBody as=\"span\" size=\"sm\" className=\"text-[#8888A0]\">{ps.docTypes[p.docType]}</TextBody>\n                        </button>\n                      ))\n                      : isAudioMode\n                      ? (\n                        ['empty', 'podcast', 'music', 'voiceover'] as const\n                      ).map((id) => {\n                        const tpl = ps.audioTemplates[id];\n                        return (\n                        <button\n                          key={id}\n                          type=\"button\"\n                          onClick={() => setAudioTemplate(id)}\n                          onDoubleClick={() => {\n                            setAudioTemplate(id);\n                            onCreateAudio?.({\n                              name: tpl.label,\n                              sampleRate: audioSampleRate,\n                              bpm: id === 'podcast' ? 0 : audioBpm,\n                              template: id,\n                            });\n                          }}\n                          className={`flex flex-col items-start gap-1 p-3 rounded-lg border text-left transition-all ${\n                            audioTemplate === id\n                              ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)]'\n                              : 'border-[#2A2A38] bg-[#0A0A0F] hover:border-[var(--we-accent)]/50'\n                          }`}\n                        >\n                          <Music2 size={14} className={audioTemplate === id ? 'text-[var(--we-accent)]' : 'text-[#8888A0]'} />\n                          <TextBody as=\"span\" size=\"sm\" className=\"font-bold text-[#F0F0F5]\">{tpl.label}</TextBody>\n                          <TextBody as=\"span\" size=\"sm\" className=\"text-[#666680]\">{tpl.sub}</TextBody>\n                        </button>\n                        );\n                      })\n                      : isImageMode\n                      ? filteredImgPresets.map(preset => {\n                        const displayName = presetDisplayName(preset.id, preset.name);\n                        return (\n                        <ImagePresetCard\n                          key={preset.id}\n                          preset={preset}\n                          displayName={displayName}\n                          tooltip={ps.presetTooltipImage(displayName, preset.width, preset.height)}\n                          selected={selectedImgPreset === preset.id}\n                          onClick={() => applyImagePreset(preset)}\n                          onDoubleClick={() => {\n                            applyImagePreset(preset);\n                            onCreateImage({\n                              name: displayName,\n                              width: preset.width,\n                              height: preset.height,\n                              backgroundColor: imgBg,\n                              orientation: preset.width >= preset.height ? 'landscape' : 'portrait',\n                            });\n                          }}\n                        />\n                        );\n                      })\n                      : filteredVidPresets.map(preset => {\n                        const displayName = presetDisplayName(preset.id, preset.name);\n                        return (\n                        <VideoPresetCard\n                          key={preset.id}\n                          preset={preset}\n                          displayName={displayName}\n                          tooltip={ps.presetTooltipVideo(displayName, preset.aspectRatio)}\n                          selected={selectedVidPreset === preset.id}\n                          onClick={() => applyVideoPreset(preset)}\n                          onDoubleClick={() => {\n                            applyVideoPreset(preset);\n                            onCreateVideo({\n                              name: displayName,\n                              aspectRatio: preset.aspectRatio as any,\n                              backgroundColor: vidBg,\n                            });\n                          }}\n                        />\n                        );\n                      })\n                    }\n                  </div>\n                </section>\n              </div>\n            </div>\n\n            {/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500 RIGHT PANEL \u2014 30% \u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n            <div className=\"flex w-[30%] min-w-0 flex-col overflow-visible\">\n              {/* Mode toggle \u2014 switches both the preset list and the creation form.\n                  overflow-visible so the modes menu is not clipped; z keeps it above the form. */}\n              <div className=\"relative z-[410] flex flex-shrink-0 items-center gap-2 border-b border-panel-border px-4 py-3\">\n                <EditorModeToggle\n                  activeMode={activeMode}\n                  onSwitchToImage={() => setActiveMode('image')}\n                  onSwitchToVideo={() => setActiveMode('video')}\n                  onSwitchToAudio={() => setActiveMode('audio')}\n                  onSwitchToText={() => setActiveMode('text')}\n                  onSwitchToSlides={() => setActiveMode('slides')}\n                />\n              </div>\n\n              <div className=\"flex-1 overflow-y-auto p-5 scrollbar-none\">\n                {/* \u2500\u2500 IMAGE CREATION FORM \u2500\u2500 */}\n                {isImageMode && (\n                  <div className=\"flex flex-col gap-5 max-w-sm\">\n                    {/* Filename */}\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.fileName}\n                      </TextBody>\n                      <input\n                        type=\"text\"\n                        value={imgName}\n                        onChange={e => setImgName(e.target.value)}\n                        className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5] placeholder-[#8888A0] focus:outline-none focus:border-[var(--we-accent)] transition-colors\"\n                        placeholder={ps.untitled}\n                      />\n                    </div>\n\n                    {/* Dimensions */}\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.dimensions}\n                      </TextBody>\n                      <div className=\"flex items-center gap-2\">\n                        <div className=\"flex-1\">\n                          <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] mb-1\">{ps.form.widthPx}</TextBody>\n                          <input\n                            type=\"number\"\n                            value={imgWidth}\n                            min={1}\n                            max={10000}\n                            onChange={e => handleWidthChange(Number(e.target.value))}\n                            className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5] focus:outline-none focus:border-[var(--we-accent)] transition-colors font-mono\"\n                          />\n                        </div>\n                        <button\n                          onClick={flipOrientation}\n                          className=\"mt-5 w-8 h-8 flex items-center justify-center rounded-lg bg-[#1C1C26] border border-[#2A2A38] hover:bg-[#2A2A38] text-[#8888A0] hover:text-[#F0F0F5] transition-all\"\n                          title={ps.form.swapOrientation}\n                        >\n                          <AlignHorizontalJustifyCenter size={13} />\n                        </button>\n                        <div className=\"flex-1\">\n                          <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] mb-1\">{ps.form.heightPx}</TextBody>\n                          <input\n                            type=\"number\"\n                            value={imgHeight}\n                            min={1}\n                            max={10000}\n                            onChange={e => handleHeightChange(Number(e.target.value))}\n                            className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5] focus:outline-none focus:border-[var(--we-accent)] transition-colors font-mono\"\n                          />\n                        </div>\n                      </div>\n                    </div>\n\n                    {/* Orientation */}\n                    <div>\n                      <TextTitle as=\"label\" size=\"xs\" className=\"mb-1.5 block uppercase tracking-wider text-[#8888A0]\">\n                        {ps.form.orientation}\n                      </TextTitle>\n                      <div className=\"flex gap-2\">\n                        {(['portrait', 'landscape'] as const).map(o => (\n                          <button\n                            key={o}\n                            onClick={() => {\n                              if (imgOrientation !== o) flipOrientation();\n                            }}\n                            className={`flex-1 flex items-center justify-center gap-2 py-2 rounded-lg border transition-all\n                              ${imgOrientation === o\n                                ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)] text-[var(--we-accent)]'\n                                : 'border-[#2A2A38] bg-[#0A0A0F] text-[#8888A0] hover:border-[var(--we-accent)]/50'\n                              }`}\n                          >\n                            {o === 'portrait' ? (\n                              <svg width=\"10\" height=\"14\" viewBox=\"0 0 10 14\" fill=\"none\">\n                                <rect x=\"0.5\" y=\"0.5\" width=\"9\" height=\"13\" rx=\"1.5\" stroke=\"currentColor\" strokeWidth=\"1.5\"/>\n                              </svg>\n                            ) : (\n                              <svg width=\"14\" height=\"10\" viewBox=\"0 0 14 10\" fill=\"none\">\n                                <rect x=\"0.5\" y=\"0.5\" width=\"13\" height=\"9\" rx=\"1.5\" stroke=\"currentColor\" strokeWidth=\"1.5\"/>\n                              </svg>\n                            )}\n                            <TextBody as=\"span\" size=\"sm\" className=\"font-semibold\">\n                              {o === 'portrait' ? ps.form.portrait : ps.form.landscape}\n                            </TextBody>\n                          </button>\n                        ))}\n                      </div>\n                    </div>\n\n                    {/* Background color */}\n                    <div>\n                      <TextTitle as=\"label\" size=\"xs\" className=\"mb-1.5 block uppercase tracking-wider text-[#8888A0]\">\n                        {ps.form.backgroundColor}\n                      </TextTitle>\n                      <div className=\"flex items-center gap-2\">\n                        {/* Color swatch \u2014 opens native picker */}\n                        <div className=\"relative w-8 h-8 rounded-lg border border-[#2A2A38] overflow-hidden cursor-pointer flex-shrink-0\" style={{ backgroundColor: imgBg }}>\n                          <input type=\"color\" value={imgBg} onChange={e => setImgBg(e.target.value)} className=\"absolute inset-0 opacity-0 cursor-pointer w-full h-full\" />\n                        </div>\n                        {/* Hex input */}\n                        <input\n                          type=\"text\"\n                          value={imgBg}\n                          onChange={e => setImgBg(e.target.value)}\n                          className=\"flex-1 bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5] focus:outline-none focus:border-[var(--we-accent)] transition-colors font-mono uppercase\"\n                          maxLength={7}\n                          placeholder=\"#ffffff\"\n                        />\n                        {/* Reset to default */}\n                        <button\n                          onClick={() => setImgBg('#ffffff')}\n                          title={ps.form.resetColor}\n                        >\n                          <RotateCcw size={13} />\n                        </button>\n                      </div>\n                    </div>\n                  </div>\n                )}\n\n                {/* \u2500\u2500 VIDEO CREATION FORM \u2500\u2500 */}\n                {activeMode === 'video' && (\n                  <div className=\"flex flex-col gap-5 max-w-sm\">\n                    {/* Filename */}\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.fileName}\n                      </TextBody>\n                      <input\n                        type=\"text\"\n                        value={vidName}\n                        onChange={e => setVidName(e.target.value)}\n                        className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5] placeholder-[#8888A0] focus:outline-none focus:border-[var(--we-accent)] transition-colors\"\n                        placeholder={ps.untitled}\n                      />\n                    </div>\n\n                    {/* Aspect ratio */}\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.aspectRatio}\n                      </TextBody>\n                      <div className=\"grid grid-cols-3 gap-2\">\n                        {(Object.keys(ASPECT_RATIO_DIMS) as Array<keyof typeof ASPECT_RATIO_DIMS>).map(ar => {\n                          const d = ASPECT_RATIO_DIMS[ar];\n                          return (\n                            <button\n                              key={ar}\n                              onClick={() => setVidAspect(ar as any)}\n                              className={`flex flex-col items-center gap-1.5 py-2.5 rounded-lg border transition-all text-[10px] font-semibold\n                                ${vidAspect === ar\n                                  ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)] text-[var(--we-accent)]'\n                                  : 'border-[#2A2A38] bg-[#0A0A0F] text-[#8888A0] hover:border-[var(--we-accent)]/50 hover:text-[#F0F0F5]'\n                                }`}\n                            >\n                              <PresetThumb w={d.w} h={d.h} color={vidAspect === ar ? 'var(--we-accent)' : '#8888A0'} />\n                              <TextBody as=\"span\" size=\"sm\" className=\"font-mono\">{ar}</TextBody>\n                            </button>\n                          );\n                        })}\n                      </div>\n                    </div>\n\n                    {/* Background color */}\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.backgroundColor}\n                      </TextBody>\n                      <div className=\"flex items-center gap-2\">\n                        {/* Color swatch \u2014 opens native picker */}\n                        <div className=\"relative w-8 h-8 rounded-lg border border-[#2A2A38] overflow-hidden cursor-pointer flex-shrink-0\" style={{ backgroundColor: vidBg }}>\n                          <input type=\"color\" value={vidBg} onChange={e => setVidBg(e.target.value)} className=\"absolute inset-0 opacity-0 cursor-pointer w-full h-full\" />\n                        </div>\n                        {/* Hex input */}\n                        <input\n                          type=\"text\"\n                          value={vidBg}\n                          onChange={e => setVidBg(e.target.value)}\n                          className=\"flex-1 bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5] focus:outline-none focus:border-[var(--we-accent)] transition-colors font-mono uppercase\"\n                          maxLength={7}\n                          placeholder=\"#000000\"\n                        />\n                        {/* Reset to default */}\n                        <button\n                          onClick={() => setVidBg('#000000')}\n                          className=\"\"\n                          title={ps.form.resetColor}\n                        >\n                          <RotateCcw size={13} />\n                        </button>\n                      </div>\n                    </div>\n                  </div>\n                )}\n\n                {/* \u2500\u2500 AUDIO CREATION FORM \u2500\u2500 */}\n                {isAudioMode && (\n                  <div className=\"flex flex-col gap-5 max-w-sm\">\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.projectName}\n                      </TextBody>\n                      <input\n                        type=\"text\"\n                        value={audioName}\n                        onChange={(e) => setAudioName(e.target.value)}\n                        className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5] placeholder-[#8888A0] focus:outline-none focus:border-[var(--we-accent)] transition-colors\"\n                        placeholder={ps.untitled}\n                      />\n                    </div>\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.template}\n                      </TextBody>\n                      <div className=\"grid grid-cols-2 gap-2\">\n                        {(['empty', 'podcast', 'music', 'voiceover'] as const).map((id) => (\n                          <button\n                            key={id}\n                            type=\"button\"\n                            onClick={() => setAudioTemplate(id)}\n                            className={`py-2.5 rounded-lg border text-[11px] font-semibold transition-all ${\n                              audioTemplate === id\n                                ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)] text-[var(--we-accent)]'\n                                : 'border-[#2A2A38] bg-[#0A0A0F] text-[#8888A0] hover:border-[var(--we-accent)]/50'\n                            }`}\n                          >\n                            {ps.audioTemplates[id].label}\n                          </button>\n                        ))}\n                      </div>\n                    </div>\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.sampleRate}\n                      </TextBody>\n                      <select\n                        value={audioSampleRate}\n                        onChange={(e) => setAudioSampleRate(Number(e.target.value))}\n                        className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5] focus:outline-none focus:border-[var(--we-accent)]\"\n                      >\n                        <option value={44100}>44.1 kHz</option>\n                        <option value={48000}>48 kHz</option>\n                        <option value={96000}>96 kHz</option>\n                      </select>\n                    </div>\n                    {audioTemplate !== 'podcast' && (\n                      <div>\n                        <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                          {ps.form.bpm}\n                        </TextBody>\n                        <input\n                          type=\"number\"\n                          value={audioBpm}\n                          onChange={(e) => setAudioBpm(Number(e.target.value) || 0)}\n                          className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5] focus:outline-none focus:border-[var(--we-accent)]\"\n                        />\n                      </div>\n                    )}\n                  </div>\n                )}\n\n                {/* \u2500\u2500 TEXT CREATION FORM \u2500\u2500 */}\n                {isSlidesMode && (\n                  <div className=\"flex flex-col gap-5 max-w-sm\">\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.deckName}\n                      </TextBody>\n                      <input\n                        type=\"text\"\n                        value={slidesName}\n                        onChange={(e) => setSlidesName(e.target.value)}\n                        className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5] focus:outline-none focus:border-[var(--we-accent)]\"\n                        placeholder={ps.untitled}\n                      />\n                    </div>\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.template}\n                      </TextBody>\n                      <select\n                        value={slidesTemplate}\n                        onChange={(e) => setSlidesTemplate(e.target.value as SlidesTemplateId)}\n                        className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5]\"\n                      >\n                        {(['blank', 'pitch', 'qbr', 'course', 'report', 'keynote'] as SlidesTemplateId[]).map((tplId) => (\n                          <option key={tplId} value={tplId}>{ps.slidesTemplates[tplId]}</option>\n                        ))}\n                      </select>\n                    </div>\n                    <div className=\"grid grid-cols-2 gap-2\">\n                      <div>\n                        <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">{ps.form.width}</TextBody>\n                        <input\n                          type=\"number\"\n                          value={slidesWidth}\n                          onChange={(e) => setSlidesWidth(Number(e.target.value) || 1920)}\n                          className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5]\"\n                        />\n                      </div>\n                      <div>\n                        <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">{ps.form.height}</TextBody>\n                        <input\n                          type=\"number\"\n                          value={slidesHeight}\n                          onChange={(e) => setSlidesHeight(Number(e.target.value) || 1080)}\n                          className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5]\"\n                        />\n                      </div>\n                    </div>\n                  </div>\n                )}\n\n                {isTextMode && (\n                  <div className=\"flex flex-col gap-5 max-w-sm\">\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.documentName}\n                      </TextBody>\n                      <input\n                        type=\"text\"\n                        value={textName}\n                        onChange={(e) => setTextName(e.target.value)}\n                        className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5] focus:outline-none focus:border-[var(--we-accent)]\"\n                        placeholder={ps.untitled}\n                      />\n                    </div>\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.template}\n                      </TextBody>\n                      <div className=\"grid grid-cols-2 gap-2\">\n                        {TEXT_PRESETS.map((p) => (\n                          <button\n                            key={p.id}\n                            type=\"button\"\n                            onClick={() => applyTextPreset(p)}\n                            onDoubleClick={() => {\n                              applyTextPreset(p);\n                              onCreateText?.({\n                                name: presetDisplayName(p.id, p.name),\n                                docType: p.docType,\n                                language: textLanguage,\n                                tone: p.tone,\n                                targetChannel: p.targetChannel,\n                              });\n                            }}\n                            className={`py-2.5 rounded-lg border text-[11px] font-semibold transition-all ${\n                              selectedTextPreset === p.id || textDocType === p.docType\n                                ? 'border-[var(--we-accent)] bg-[var(--we-accent-muted)] text-[var(--we-accent)]'\n                                : 'border-[#2A2A38] bg-[#0A0A0F] text-[#8888A0] hover:border-[var(--we-accent)]/50'\n                            }`}\n                          >\n                            {presetDisplayName(p.id, p.name)}\n                          </button>\n                        ))}\n                      </div>\n                    </div>\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.language}\n                      </TextBody>\n                      <select\n                        value={textLanguage}\n                        onChange={(e) => setTextLanguage(e.target.value)}\n                        className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5]\"\n                      >\n                        <option value=\"es\">{ps.languages.es}</option>\n                        <option value=\"en\">{ps.languages.en}</option>\n                        <option value=\"pt\">{ps.languages.pt}</option>\n                      </select>\n                    </div>\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.tone}\n                      </TextBody>\n                      <select\n                        value={textTone}\n                        onChange={(e) => setTextTone(e.target.value as TextCanvasConfig['tone'])}\n                        className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5]\"\n                      >\n                        {(['neutral', 'formal', 'casual', 'persuasive', 'technical', 'friendly'] as const).map((toneId) => (\n                          <option key={toneId} value={toneId}>{ps.tones[toneId]}</option>\n                        ))}\n                      </select>\n                    </div>\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.targetChannel}\n                      </TextBody>\n                      <select\n                        value={textChannel}\n                        onChange={(e) => setTextChannel(e.target.value as TextCanvasConfig['targetChannel'])}\n                        className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5]\"\n                      >\n                        {(['blog', 'instagram', 'linkedin', 'x', 'email', 'ad', 'youtube'] as const).map((channelId) => (\n                          <option key={channelId} value={channelId}>{ps.channels[channelId]}</option>\n                        ))}\n                      </select>\n                    </div>\n                    <div>\n                      <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                        {ps.form.pageSize}\n                      </TextBody>\n                      <select\n                        value={textPageSize}\n                        onChange={(e) => setTextPageSize(e.target.value as TextCanvasConfig['pageSize'])}\n                        className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-3 py-2 text-sm text-[#F0F0F5]\"\n                      >\n                        <option value=\"letter\">{ps.pageSizes.letter}</option>\n                        <option value=\"legal\">{ps.pageSizes.legal}</option>\n                        <option value=\"a4\">{ps.pageSizes.a4}</option>\n                        <option value=\"a5\">{ps.pageSizes.a5}</option>\n                      </select>\n                    </div>\n                    <div className=\"grid grid-cols-2 gap-2\">\n                      <div>\n                        <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                          {ps.form.orientation}\n                        </TextBody>\n                        <select\n                          value={textOrientation}\n                          onChange={(e) => setTextOrientation(e.target.value as 'portrait' | 'landscape')}\n                          className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-2 py-2 text-sm text-[#F0F0F5]\"\n                        >\n                          <option value=\"portrait\">{ps.form.portrait}</option>\n                          <option value=\"landscape\">{ps.form.landscape}</option>\n                        </select>\n                      </div>\n                      <div>\n                        <TextBody as=\"label\" size=\"sm\" className=\"block text-[#8888A0] uppercase tracking-wider mb-1.5\">\n                          {ps.form.columns}\n                        </TextBody>\n                        <select\n                          value={textColumns}\n                          onChange={(e) => setTextColumns(Number(e.target.value))}\n                          className=\"w-full bg-[#0A0A0F] border border-[#2A2A38] rounded-lg px-2 py-2 text-sm text-[#F0F0F5]\"\n                        >\n                          <option value=\"1\">1</option>\n                          <option value=\"2\">2</option>\n                          <option value=\"3\">3</option>\n                        </select>\n                      </div>\n                    </div>\n                  </div>\n                )}\n              </div>\n\n              {/* \u2500\u2500 Create button \u2500\u2500 */}\n              <div className=\"p-4 border-t border-panel-border flex-shrink-0\">\n                <button\n                  onClick={\n                    isSlidesMode\n                      ? handleCreateSlides\n                      : isTextMode\n                        ? handleCreateText\n                        : isAudioMode\n                          ? handleCreateAudio\n                          : isImageMode\n                            ? handleCreateImage\n                            : handleCreateVideo\n                  }\n                  className=\"w-full h-10 rounded-xl bg-[var(--we-accent)] hover:bg-[var(--we-accent-hover)] text-white text-sm font-bold transition-all active:scale-[0.98] shadow-lg shadow-[color-mix(in_srgb,var(--we-accent)_30%,transparent)] flex items-center justify-center gap-2\"\n                >\n                  {isSlidesMode ? <Presentation size={14} /> : isTextMode ? <FileText size={14} /> : isAudioMode ? <Music2 size={14} /> : isImageMode ? <ImageIcon size={14} /> : <Film size={14} />}\n                  {isSlidesMode\n                    ? ps.create.slides\n                    : isTextMode\n                      ? ps.create.text\n                      : isAudioMode\n                        ? ps.create.audio\n                        : isImageMode\n                          ? ps.create.image\n                          : ps.create.video}\n                </button>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </>\n  );\n};\n\nexport default ProjectSetupModal;\n", "/**\n * alerta-wizard-editor \u2014 Public Package Entry Point\n *\n * Exports are organised in three tiers:\n *\n *   1. Primary component   \u2014 <Editor /> (full app with built-in mode switcher)\n *   2. Mode editors        \u2014 <TextEditor />, <SlidesEditor />, <AudioEditor />\n *                            (mount individual modes without the shell)\n *   3. Services & types    \u2014 HTTP client, error classes, public TS types\n *\n * CSS is auto-injected into <head> the first time any export from this\n * package is imported (handled by the inlineCSSPlugin in vite.config.ts).\n *\n * Usage (host \u2014 wizard-ai-frontend):\n *\n *   import { Editor } from 'alerta-wizard-editor';\n *   // or individual editors:\n *   import { TextEditor, SlidesEditor, AudioEditor } from 'alerta-wizard-editor';\n *   // or just types / services:\n *   import type { BrandContext, EditorSavePayload } from 'alerta-wizard-editor';\n *\n * The <Editor /> component MUST be mounted with ssr: false in Next.js:\n *   const Editor = dynamic(() => import('alerta-wizard-editor').then(m => m.Editor), { ssr: false })\n */\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// 1. Primary editor shell  (includes mode picker: Image, Video, Audio, Text, Slides)\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport { default as Editor, type EditorRootProps } from './App';\n/** @deprecated Use `Editor` instead */\nexport { default as WizardEditor } from './App';\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// 2. Individual mode editors\n//    Mount these directly if you want a single-mode experience without the\n//    full shell and mode-switcher toolbar.\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport { TextEditor }   from './components/text/TextEditor';\nexport { SlidesEditor } from './components/slides/SlidesEditor';\nexport { AudioEditor }  from './components/audio/AudioEditor';\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// 1.5. i18n \u2014 internal locale switcher\n//    Pass `locale` to <Editor /> (or any individual editor) to switch UI language.\n//    Default is 'es' if omitted or unknown. Add a new locale by creating\n//    src/i18n/<code>.ts and registering it in src/i18n/index.ts.\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport type { Locale, Messages } from './i18n';\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// 3. HTTP client & bootstrap helpers\n//    Call configureWizardApiClient() + setEditorIdentity() before rendering\n//    any editor component in your host app (once, at startup).\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport {\n  configureWizardApiClient,\n  getWizardApiClient,\n  resetWizardApiClient,\n  // Error classes \u2014 use these in catch blocks in the host\n  NotImplementedError,\n  AuthError,\n  NetworkError,\n  ApiError,\n} from './services/wizardApiClient';\n\nexport {\n  setEditorIdentity,\n} from './services/identity';\n\nexport type { EditorIdentity } from './services/identity';\n\nexport type { EditorBrandOption } from './types/brand.types';\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// 4. Public TypeScript types\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n// Wizard API client types\nexport type {\n  WizardApiClientConfig,\n  FieldValue,\n} from './services/wizardApiClient';\n\n// Slides domain types\nexport type {\n  DeckTheme,\n  Slide,\n  SlideDeck,\n  SlideTransition,\n  SlideComment,\n  SlidesCanvasConfig,\n} from './types/slides.types';\n\n// Brand domain types (passed as readonly props from the host)\nexport type {\n  BrandContext,\n  BrandLogo,\n  BrandColor,\n  BrandVoice,\n  BrandTextBankEntry,\n  BrandImage,\n} from './types/brand.types';\n\n// Editable / save-payload types (shared across all modes)\nexport type { Editable } from './services/editableService';\n\n// Project-setup config types (passed as props to <Editor />)\nexport type {\n  ImageCanvasConfig,\n  VideoCanvasConfig,\n  AudioCanvasConfig,\n  TextCanvasConfig,\n  SlidesCanvasConfig as SlidesProjectConfig,\n} from './components/ProjectSetupModal';\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// 5. Slides theme presets (host can pass these via the `brand` / theme prop)\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport {\n  DEFAULT_THEME,\n  DARK_THEME,\n  PITCH_THEME,\n  THEME_PRESETS,\n  cloneTheme,\n} from './lib/slides/themes';\n"],
  "mappings": "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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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",
  "names": ["key", "removeBackground", "sketchToImage", "magicEraser", "generateText", "formatActiveBrandForPrompt", "getActiveEditorBrand", "px", "key", "key", "React", "window", "useAudioStore", "key", "copy", "syncEngineFromStore", "openUploadsDB", "hasEditorIdentity", "uploadCurrentProjectToCloud", "decodeAudioBlob", "extractPeaks", "offset", "newDur", "create", "uid", "syncActiveIntoProjects", "applyProjectToRoot", "hasEditorIdentity", "uploadCurrentProjectToCloud", "uid", "ctx", "pct", "Chart", "registerables", "uid", "uid", "normalizeSlide", "key", "normalizeGenerateDeckResponse", "key", "asRecord", "translateSubtitles", "create", "uid", "syncActiveIntoProjects", "applyProjectToRoot", "scheduleAutosave", "pickFirstSlideForThumbnail", "renderSlideThumbnail", "hasEditorIdentity", "FEATURE_CLOUD_SLIDES", "state", "uploadCurrentProjectToCloud", "sec", "copy", "buildDeckFromGeneratedResponse", "buildGenerateDeckBrandContext", "offset", "encodeString", "decodeString", "copy", "data", "encodeString", "decodeString", "copy", "offset", "key", "store", "project", "name", "data", "file", "exportProjectToWzrda", "compactFabricJsonImages", "num", "sec", "create", "pushToHistory", "captureVideoProjectThumbnail", "openUploadsDB", "hasEditorIdentity", "uploadCurrentProjectToCloud", "durableThumb", "key", "track", "key", "asRecord", "n", "pct", "asRecord", "key", "generateCopywritingSuggestions", "tryParseJsonObject", "key", "asRecord", "copy", "normalizeColorGradingPreset", "inferColorGradingFromProse", "normalizeVideoPropertiesPreset", "parseVideoEditPlan", "buildVideoProjectSnapshot", "translateSubtitles", "generateSubtitleStylePreset", "generateMarketingAssistant", "generateColorGradingPreset", "generateVideoProperties", "generateCopy", "generateCopywritingSuggestions", "transcribeAudio", "searchStock", "measureCtx", "getMeasureCtx", "FabricImage", "px", "Point", "offset", "filters", "p", "q", "create", "Rect", "Point", "FabricImage", "applyMaskDelete", "applyMaskFill", "extractMaskToFullDataUrl", "fabricImageObjectToImageData", "fabricImageToImageData", "imageDataHasOpaquePixels", "imageDataToCanvas", "parseCssColor", "type", "key", "hasEditorIdentity", "uploadCurrentProjectToCloud", "target", "removeBackground", "img", "sketchToImage", "magicEraser", "filters", "LevelsFilter", "applyFabricImageFilters", "React", "React", "React", "React", "sizeCls", "React", "sizeCls", "React", "React", "useCallback", "useEffect", "useState", "pct", "React", "placement", "left", "top", "useState", "useCallback", "px", "createContext", "useContext", "React", "useEffect", "useRef", "useState", "hex6", "pct", "React", "px", "React", "useEffect", "useLayoutEffect", "useRef", "useState", "createPortal", "React", "useState", "key", "React", "useCallback", "useEffect", "useLayoutEffect", "useRef", "useState", "RotateCcw", "x", "y", "React", "createContext", "useCallback", "useContext", "useEffect", "useMemo", "useState", "React", "useEffect", "useRef", "useState", "Textbox", "classRegistry", "Point", "React", "useState", "useEffect", "useRef", "X", "filters", "Gradient", "Shadow", "React", "useEffect", "useRef", "useState", "UploadCloud", "React", "useEffect", "useState", "createPortal", "X", "segmentActive", "segmentIdle", "React", "useLayoutEffect", "useMemo", "useRef", "useState", "ChevronDown", "React", "useEffect", "useRef", "useState", "Pipette", "React", "useEffect", "useLayoutEffect", "useRef", "useState", "createPortal", "ChevronRight", "flyout", "React", "useEffect", "useId", "useMemo", "useRef", "useState", "createPortal", "Search", "Trash2", "React", "React", "React", "React", "React", "useState", "React", "useEffect", "X", "React", "React", "X", "Check", "FabricImage", "React", "useEffect", "useRef", "useState", "pct", "React", "createContext", "useContext", "useState", "useCallback", "useRef", "useEffect", "createPortal", "Trash2", "X", "init_Button", "key", "getWizardApiClient", "NotImplementedError", "AuthError", "getEditorIdentity", "React", "useEffect", "useLayoutEffect", "useState", "React", "useEffect", "useRef", "createPortal", "renderSlideThumbnail", "theme", "bg", "useEffect", "useRef", "useState", "React", "Film", "ImageIcon", "Loader2", "Trash2", "Type", "key", "row", "list", "s", "React", "useEffect", "useState", "AlertTriangle", "Film", "ImageIcon", "Loader2", "Mic2", "Presentation", "Type", "modeIcon", "React", "Plus", "Film", "ImageIcon", "Music2", "Presentation", "copy", "React", "useEffect", "useRef", "useState", "createPortal", "ChevronDown", "Check", "React", "useEffect", "useMemo", "useRef", "useState", "createPortal", "Film", "ImageIcon", "Music2", "FileText", "Presentation", "ChevronDown", "Check", "React", "useState", "Play", "Plus", "React", "Languages", "Check", "React", "FolderOpen", "Loader2", "Sparkles", "Key", "React", "useEffect", "useRef", "useState", "Plus", "React", "Film", "ImageIcon", "Music2", "FileText", "Presentation", "offset", "StaticCanvas", "FabricImage", "Line", "exportProjectToPPTX", "StaticCanvas", "jsPDF", "React", "useState", "createPortal", "Clock", "Download", "Trash2", "X", "key", "React", "FabricImage", "Point", "Rect", "React", "useEffect", "useRef", "useState", "Check", "X", "React", "useEffect", "useRef", "Circle", "Line", "Path", "React", "Path", "Point", "React", "useEffect", "useRef", "Group", "util", "React", "useEffect", "useRef", "useState", "ActiveSelection", "Point", "pointInPoly", "isDedicatedMarquee", "isSelectTool", "useEffect", "useRef", "useEffect", "useRef", "Point", "isFabricImage", "px", "useEffect", "useRef", "Point", "px", "React", "useEffect", "useRef", "useState", "Point", "isFabricImage", "resolveSelectionImage", "resolveCombineMode", "px", "React", "useEffect", "useRef", "useState", "Point", "isFabricImage", "resolveSelectionImage", "resolveCombineMode", "px", "React", "useEffect", "useRef", "useState", "Point", "isFabricImage", "resolveCombineMode", "pts", "first", "px", "useEffect", "useRef", "Point", "isFabricImage", "px", "useEffect", "useRef", "React", "useCallback", "useEffect", "useMemo", "useRef", "useState", "React", "React", "useEffect", "useRef", "useState", "Group", "Rect", "Circle", "Polygon", "Path", "Textbox", "Shadow", "Path", "Path", "React", "key", "React", "React", "useEffect", "useMemo", "useRef", "useState", "createPortal", "Plus", "Trash2", "UploadCloud", "X", "React", "React", "React", "Eraser", "Layers2", "Plus", "X", "React", "React", "React", "React", "useRef", "useState", "Square", "Image", "Type", "React", "useEffect", "useMemo", "useRef", "useState", "Palette", "Plus", "Trash2", "ChevronLeft", "ChevronRight", "Edit2", "X", "toolBtn", "key", "React", "useRef", "useState", "ZoomIn", "ZoomOut", "Maximize", "ChevronDown", "Undo2", "Redo2", "React", "React", "useState", "useEffect", "X", "Plus", "Trash2", "Check", "Settings2", "Point", "util", "React", "useEffect", "useLayoutEffect", "useRef", "useState", "Point", "React", "useEffect", "useState", "React", "useEffect", "useLayoutEffect", "useRef", "useState", "useCallback", "createPortal", "Canvas", "Rect", "Textbox", "Line", "FabricObject", "FabricImage", "Polygon", "Path", "Shadow", "Point", "Group", "ActiveSelection", "ChevronDown", "Copy", "Trash2", "Lock", "Unlock", "ChevronUp", "Grid", "RefreshCw", "Hand", "Scissors", "Brush", "FolderPlus", "FolderMinus", "Sparkles", "PenTool", "Link2", "Unlink", "Type", "PaintBucket", "LayoutGrid", "Eye", "UploadCloud", "Bold", "Italic", "Underline", "AlignLeft", "AlignCenter", "AlignRight", "X", "Plus", "Wand2", "Eraser", "Check", "getType", "key", "handlePointerMove", "mode", "zoom", "guideX", "guideY", "minDiffX", "minDiffY", "diff", "loadGoogleFont", "hexToRgba", "getStarPoints", "handlePaste", "Pattern", "t", "offset", "px", "React", "useRef", "useState", "Minus", "Plus", "React", "Magnet", "Pause", "Play", "Redo2", "Repeat", "Square", "Undo2", "ZoomIn", "ZoomOut", "formatTimecode", "sec", "create", "React", "useState", "offset", "buildStemBlobs", "window", "encodeWav", "React", "useEffect", "useRef", "useState", "Captions", "ChevronDown", "ChevronLeft", "ChevronUp", "Copy", "Loader2", "Mic2", "Music2", "Pause", "Play", "Scissors", "Sparkles", "Volume2", "Wand2", "voiceDemoUrlCache", "text", "React", "sec", "React", "useEffect", "useRef", "useState", "Save", "Trash2", "key", "React", "useEffect", "useRef", "React", "Trash2", "analyzeBuffer", "getAudioEngine", "React", "useRef", "useState", "Loader2", "Undo2", "React", "useRef", "useState", "Circle", "Square", "t", "React", "useState", "Loader2", "Scissors", "Type", "Volume2", "React", "useEffect", "useRef", "useState", "Loader2", "Music", "Pause", "Play", "RefreshCw", "React", "useCallback", "useState", "Folder", "MessageSquare", "Mic2", "Music2", "RotateCcw", "Scissors", "SlidersHorizontal", "Upload", "PanelContent", "DEFAULT_WIDTH", "MIN_WIDTH", "MAX_WIDTH", "RAIL", "React", "Lock", "Mic", "Plus", "Trash2", "VolumeX", "React", "useCallback", "useEffect", "useMemo", "useRef", "useState", "Stage", "Layer", "Rect", "Line", "Text", "Group", "ClipboardPaste", "Copy", "EyeOff", "Folder", "Link2", "Lock", "Plus", "Scissors", "Sparkles", "Trash2", "Upload", "setStageCursor", "RULER_HEIGHT", "PLAYHEAD_HIT_HALF", "SNAP_THRESHOLD_PX", "SPLIT_EDGE_MARGIN_PX", "SPLIT_HOVER_DELAY_MS", "SPLIT_PLAYHEAD_HIT_PX", "SPLIT_PLAYHEAD_KEEP_PX", "SPLIT_LEAVE_MS", "MAX_WAVEFORM_BARS", "t", "px", "sec", "React", "ClipboardPaste", "Copy", "Scissors", "key", "blob", "React", "useState", "React", "useCallback", "useEffect", "useRef", "useState", "Upload", "init_Button", "t", "Mark", "mergeAttributes", "Node", "mergeAttributes", "Mark", "mergeAttributes", "Extension", "PluginKey", "React", "useCallback", "useRef", "Image", "mergeAttributes", "Extension", "Mark", "mergeAttributes", "Extension", "markInputRule", "markPasteRule", "Text", "Plugin", "PluginKey", "Decoration", "DecorationSet", "offset", "create", "React", "useEffect", "useRef", "ClipboardPaste", "Copy", "Scissors", "React", "useEffect", "useState", "React", "useEffect", "useState", "React", "useEffect", "useState", "React", "useEffect", "useState", "Minus", "Plus", "Trash2", "React", "useEffect", "useCallback", "useState", "useRef", "useMemo", "Extension", "Bold", "Italic", "MessageSquarePlus", "Volume2", "Superscript", "LinkIcon", "AlignLeft", "AlignCenter", "AlignRight", "Indent", "ChevronDown", "MM_TO_PX", "editor", "tr", "px", "React", "React", "useEffect", "useState", "FileText", "Loader2", "RefreshCw", "React", "useCallback", "useRef", "useState", "HardDrive", "Redo2", "RotateCcw", "Settings2", "Undo2", "DEFAULT_WIDTH", "MIN_WIDTH", "MAX_WIDTH", "second", "marked", "Table", "TableRow", "TableCell", "textOf", "content", "React", "useMemo", "React", "useState", "ChevronLeft", "FileText", "ListTree", "Mic", "PenLine", "Plus", "Scissors", "Sparkles", "Trash2", "Wand2", "ToolRow", "ALL_TOOLS", "sec", "COSTLY_TOOLS", "init_tools", "executeOne", "sec", "presentComplianceFlags", "complianceOutcome", "getActiveLocale", "executeToolCalls", "COSTLY_TOOLS", "executeConfirmedTool", "init_executor", "init_tools", "React", "useRef", "useState", "Loader2", "Send", "MAX_AGENT_ROUNDS", "init_tools", "init_executor", "executeToolCalls", "executeConfirmedTool", "React", "useState", "RefreshCw", "React", "useState", "Check", "RotateCcw", "Trash2", "React", "useState", "React", "useMemo", "useState", "key", "React", "useCallback", "useEffect", "useRef", "useState", "Layers", "MessageSquare", "RotateCcw", "Sparkles", "PanelContent", "DEFAULT_WIDTH", "MIN_WIDTH", "MAX_WIDTH", "RAIL", "React", "escapeHtml", "React", "useState", "X", "Film", "Music2", "jsPDF", "t", "sec", "React", "useEffect", "useMemo", "useState", "React", "useEffect", "useState", "React", "useRef", "useState", "create", "React", "useState", "ChevronLeft", "LayoutTemplate", "Languages", "PenLine", "Sparkles", "ToolRow", "ALL_TOOLS", "COSTLY_TOOLS", "init_tools", "uid", "flushSlidesPersistence", "init_executor", "React", "useRef", "useState", "init_tools", "init_executor", "COSTLY_TOOLS", "React", "React", "useMemo", "useState", "TEXTAREA", "React", "transitionOptions", "React", "useState", "Check", "Trash2", "CommentsPanel", "init_CommentsPanel", "React", "useState", "AlertTriangle", "ChevronLeft", "Info", "LayoutTemplate", "Type", "ToolRow", "ALL_TOOLS", "React", "useMemo", "useState", "span", "gap", "React", "useEffect", "useRef", "useCallback", "useState", "Canvas", "Textbox", "Rect", "Circle", "FabricImage", "ActiveSelection", "uid", "t", "diff", "guessMime", "size", "React", "useEffect", "useState", "FileVideo", "ImageIcon", "Loader2", "RefreshCw", "React", "React", "useCallback", "useEffect", "useRef", "useState", "Layers", "ListTree", "MessageCircle", "MessageSquare", "Mic2", "Palette", "RotateCcw", "Shield", "Sparkles", "PanelContent", "CommentsPanel", "DEFAULT_WIDTH", "MIN_WIDTH", "MAX_WIDTH", "RAIL", "init_CommentsPanel", "React", "useState", "useEffect", "useRef", "Eye", "EyeOff", "Copy", "Trash2", "React", "useCallback", "useState", "Plus", "RotateCcw", "DEFAULT_WIDTH", "MIN_WIDTH", "MAX_WIDTH", "React", "useRef", "useState", "Type", "Square", "Circle", "ImageIcon", "BarChart3", "Triangle", "Minus", "ChevronDown", "btnCls", "React", "useEffect", "useRef", "useState", "createPortal", "AlignLeft", "AlignCenter", "AlignRight", "ArrowDown", "ArrowUp", "Type", "Copy", "Trash2", "BarChart3", "ImageIcon", "ChevronDown", "Upload", "FolderOpen", "Loader2", "X", "btnCls", "React", "useEffect", "useLayoutEffect", "useRef", "createPortal", "AlignCenter", "AlignLeft", "AlignRight", "ArrowDown", "ArrowDownToLine", "ArrowUp", "ArrowUpToLine", "Copy", "Magnet", "Trash2", "Type", "React", "useEffect", "useState", "React", "useRef", "useState", "Magnet", "Square", "Image", "Type", "Frame", "SnapSwitchRow", "React", "px", "pptxgen", "StaticCanvas", "jsPDF", "pdf", "escapeHtml", "loadImage", "sleep", "React", "useState", "Clapperboard", "Download", "FileImage", "FileText", "Film", "Presentation", "s", "React", "useCallback", "useEffect", "useLayoutEffect", "useMemo", "useRef", "useState", "StaticCanvas", "X", "ChevronLeft", "ChevronRight", "Clock", "Eraser", "toFrame", "t", "uid", "React", "useEffect", "useRef", "useState", "Play", "Undo2", "Redo2", "key", "api", "data", "toolBtn", "React", "useEffect", "useState", "React", "useCallback", "useEffect", "useMemo", "useState", "Layers", "RotateCcw", "React", "useState", "useEffect", "useRef", "ChevronDown", "UploadCloud", "Trash2", "filters", "Gradient", "Shadow", "useState", "useEffect", "React", "useRef", "segmentActive", "segmentIdle", "ChevronDown", "UploadCloud", "Trash2", "filters", "Gradient", "key", "Shadow", "React", "useEffect", "useRef", "useState", "Lock", "Unlock", "Trash2", "ImageIcon", "Brush", "ChevronRight", "ChevronDown", "ChevronLeft", "Plus", "Circle", "Type", "createPortal", "React", "useState", "useEffect", "TransformPanel", "key", "getType", "useState", "useRef", "useEffect", "React", "ImageIcon", "Brush", "ChevronDown", "ChevronRight", "Lock", "TransformPanel", "Circle", "Type", "Unlock", "Trash2", "Plus", "ChevronLeft", "createPortal", "getType", "React", "useState", "useMemo", "Layers", "useEffect", "useCallback", "RotateCcw", "React", "AlertTriangle", "Info", "X", "React", "Loader2", "chips", "React", "useState", "useEffect", "useRef", "X", "Sparkles", "Layout", "Settings", "Type", "Square", "Circle", "Triangle", "Trash2", "Copy", "filters", "React", "useEffect", "useRef", "useState", "StaticCanvas", "ChevronLeft", "ChevronRight", "X", "Play", "Loader2", "React", "useCallback", "useRef", "useState", "Sparkles", "React", "useCallback", "useState", "Folder", "RotateCcw", "Sparkles", "React", "useMemo", "useRef", "useState", "Plus", "Sparkles", "Trash2", "init_Button", "React", "useState", "Sparkles", "Plus", "Download", "t", "useRef", "useState", "useMemo", "ensureTrack", "trackId", "React", "Sparkles", "Plus", "Trash2", "React", "useEffect", "useState", "FileVideo", "ImageIcon", "Loader2", "Music", "RefreshCw", "ensureTrack", "React", "useEffect", "useState", "RotateCcw", "React", "Palette", "Sparkles", "Type", "create", "React", "Palette", "Sparkles", "Type", "DEFAULT_WIDTH", "MIN_WIDTH", "MAX_WIDTH", "React", "Folder", "Sparkles", "useState", "useCallback", "RotateCcw", "React", "useRef", "useEffect", "useCallback", "useState", "Play", "Pause", "Maximize", "clamp01", "React", "useRef", "useState", "useEffect", "useMemo", "srcW", "srcH", "cx", "cy", "useRef", "useState", "useEffect", "useCallback", "t", "React", "Pause", "Play", "Maximize", "React", "useCallback", "useState", "Settings2", "Shuffle", "Sparkles", "Type", "RotateCcw", "React", "useState", "useRef", "React", "useState", "React", "useRef", "useState", "useEffect", "Sliders", "Palette", "Sparkles", "Loader", "useState", "generateColorGradingPreset", "key", "React", "React", "useState", "Eye", "EyeOff", "Trash2", "ChevronDown", "Sparkles", "t", "Sliders", "Layers", "Palette", "AlignLeft", "AlignCenter", "AlignRight", "Italic", "Underline", "Move", "Sparkles", "Loader", "ChevronDown", "pct", "useState", "useRef", "translateSubtitles", "generateSubtitleStylePreset", "generateColorGradingPreset", "React", "React", "useMemo", "useState", "createPortal", "Sparkles", "Search", "Sliders", "Film", "Move", "Plus", "Trash2", "num", "key", "React", "useMemo", "useState", "Search", "X", "useState", "useMemo", "React", "X", "Search", "React", "useMemo", "React", "useMemo", "useMemo", "React", "DEFAULT_WIDTH", "MIN_WIDTH", "MAX_WIDTH", "RAIL", "React", "Settings2", "Shuffle", "Sparkles", "Type", "PanelContent", "useState", "useCallback", "RotateCcw", "React", "useRef", "useState", "Eye", "EyeOff", "Lock", "Unlock", "Trash2", "Plus", "ChevronUp", "ChevronDown", "React", "useRef", "useState", "useEffect", "useCallback", "useLayoutEffect", "useMemo", "Rect", "Group", "Sparkles", "ArrowUp", "ArrowDown", "Plus", "Languages", "Wand2", "Palette", "Clapperboard", "React", "useMemo", "useRef", "useState", "useLayoutEffect", "useEffect", "useCallback", "key", "t", "transcribeAudio", "toUserFacingError", "useMemo", "React", "Rect", "Group", "y", "trackIndex", "Plus", "ArrowUp", "ArrowDown", "Sparkles", "Clapperboard", "Palette", "Wand2", "Languages", "laneIndex", "laneTop", "React", "useEffect", "useMemo", "useState", "Trash2", "ZoomIn", "ZoomOut", "RotateCcw", "ChevronDown", "ChevronUp", "Maximize2", "Scissors", "React", "useState", "Download", "Sparkles", "Loader", "t", "init_Button", "React", "useState", "Copy", "Check", "Loader2", "Plus", "Sparkles", "generateMarketingAssistant", "React", "useEffect", "useMemo", "useRef", "useState", "Languages", "Loader2", "Search", "Sparkles", "Wand2", "init_Button", "React", "useEffect", "useRef", "useState", "Volume2", "Loader", "Play", "Pause", "readAudioDuration", "readImageSize", "useState", "useRef", "useMemo", "useEffect", "React", "transcribeAudio", "translateSubtitles", "generateSubtitleStylePreset", "generateColorGradingPreset", "generateVideoProperties", "generateCopy", "generateCopywritingSuggestions", "searchStock", "Sparkles", "Languages", "Loader2", "Wand2", "key", "Search", "encodeString", "decodeString", "offset", "useState", "useRef", "useCallback", "React", "Sparkles", "React", "useEffect", "useRef", "useState", "Clock", "React", "useEffect", "useState", "createPortal", "X", "Download", "Upload", "FileText", "ExportModal", "segmentActive", "segmentIdle", "useRef", "useState", "useEffect", "React", "Clock", "ExportModal", "key", "React", "Film", "React", "useRef", "useEffect", "useCallback", "useState", "Play", "Pause", "ChevronsLeft", "ChevronsRight", "Rewind", "FastForward", "Volume2", "VolumeX", "Maximize", "dummyBlackCanvas", "dummyWhiteCanvas", "dummyTransparentCanvas", "React", "useRef", "useState", "useEffect", "Stage", "Layer", "Rect", "Text", "Line", "Group", "Download", "Copy", "Trash2", "Upload", "ZoomIn", "ZoomOut", "ChevronLeft", "ChevronRight", "React", "X", "Save", "TransitionBuilder", "RULER_HEIGHT", "DEFAULT_TRACK_HEIGHT", "TRACK_SPACING", "SNAP_THRESHOLD_PX", "Timeline", "useRef", "useState", "useEffect", "a", "React", "ZoomOut", "ZoomIn", "ChevronLeft", "ChevronRight", "Stage", "Layer", "Rect", "Group", "Line", "Text", "_", "trackIndex", "Download", "Copy", "Trash2", "Upload", "TransitionBuilder", "BASE_TRACK_HEIGHT", "React", "Film", "Timeline", "readVideoMeta", "useEffect", "React", "useState", "useRef", "useEffect", "useCallback", "useMemo", "X", "Plus", "Film", "ImageIcon", "Music2", "FileText", "Presentation", "Monitor", "FolderOpen", "RotateCcw", "RefreshCw", "AlertCircle", "Loader2", "mode", "hasEditorIdentity", "getEditable", "CanvasArea", "AudioEditor", "TextEditor", "SlidesEditor", "React", "useState", "useEffect", "importPptxFile", "importProjectFromWzrds", "importProjectFromWzrda", "importProjectFromWzrdt", "markdownToHtml", "Loader2"]
}
