@nice2dev/ui-graphics 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +147 -1
- package/dist/cjs/animation/AnimatedPerson.js +2 -2
- package/dist/cjs/animation/AnimatedPerson.js.map +1 -1
- package/dist/cjs/animation/AnimationEditor.js +11 -6
- package/dist/cjs/animation/AnimationEditor.js.map +1 -1
- package/dist/cjs/animation/Audience.js +4 -3
- package/dist/cjs/animation/Audience.js.map +1 -1
- package/dist/cjs/animation/BodyRenderer.js +5 -2
- package/dist/cjs/animation/BodyRenderer.js.map +1 -1
- package/dist/cjs/animation/rig/RigPlayer.js +2 -2
- package/dist/cjs/animation/rig/RigPlayer.js.map +1 -1
- package/dist/cjs/animation/rig/RiggedBody.js +2 -2
- package/dist/cjs/animation/rig/RiggedBody.js.map +1 -1
- package/dist/cjs/animation/shapes/heads.js +4 -1
- package/dist/cjs/animation/shapes/heads.js.map +1 -1
- package/dist/cjs/core/LocalUI.js +1 -1
- package/dist/cjs/core/NiceBrushEngine.js +446 -0
- package/dist/cjs/core/NiceBrushEngine.js.map +1 -0
- package/dist/cjs/core/yjsCollaboration.js +292 -0
- package/dist/cjs/core/yjsCollaboration.js.map +1 -0
- package/dist/cjs/font/NiceFontEditor.js +89 -85
- package/dist/cjs/font/NiceFontEditor.js.map +1 -1
- package/dist/cjs/font/fontFormatUtils.js +468 -0
- package/dist/cjs/font/fontFormatUtils.js.map +1 -0
- package/dist/cjs/game/GameAsset2dEditor.js +38 -24
- package/dist/cjs/game/GameAsset2dEditor.js.map +1 -1
- package/dist/cjs/icon/NiceIconEditor.js +218 -133
- package/dist/cjs/icon/NiceIconEditor.js.map +1 -1
- package/dist/cjs/index.js +83 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/nice2dev-ui-graphics.css +1 -1
- package/dist/cjs/photo/NiceAITools.js +446 -0
- package/dist/cjs/photo/NiceAITools.js.map +1 -0
- package/dist/cjs/photo/PhotoEditor.js +2 -2
- package/dist/cjs/photo/PhotoEditor.js.map +1 -1
- package/dist/cjs/pixel/PixelEditor.js +16 -5
- package/dist/cjs/pixel/PixelEditor.js.map +1 -1
- package/dist/cjs/pixel/PixelEditor.module.css.js +1 -1
- package/dist/cjs/pixel/PixelEditorMenuBar.js +2 -1
- package/dist/cjs/pixel/PixelEditorMenuBar.js.map +1 -1
- package/dist/cjs/pixel/PixelEditorRightPanel.js +3 -2
- package/dist/cjs/pixel/PixelEditorRightPanel.js.map +1 -1
- package/dist/cjs/pixel/PixelEditorTimeline.js +2 -1
- package/dist/cjs/pixel/PixelEditorTimeline.js.map +1 -1
- package/dist/cjs/pixel/PixelEditorToolbar.js +2 -1
- package/dist/cjs/pixel/PixelEditorToolbar.js.map +1 -1
- package/dist/cjs/pixel/SpriteGeneratorPanel.js +224 -0
- package/dist/cjs/pixel/SpriteGeneratorPanel.js.map +1 -0
- package/dist/cjs/pixel/animalGeneratorPresets.js +654 -0
- package/dist/cjs/pixel/animalGeneratorPresets.js.map +1 -0
- package/dist/cjs/pixel/buildingGeneratorPresets.js +573 -0
- package/dist/cjs/pixel/buildingGeneratorPresets.js.map +1 -0
- package/dist/cjs/pixel/characterGeneratorPresets.js +563 -0
- package/dist/cjs/pixel/characterGeneratorPresets.js.map +1 -0
- package/dist/cjs/pixel/spriteGeneratorCore.js +297 -0
- package/dist/cjs/pixel/spriteGeneratorCore.js.map +1 -0
- package/dist/cjs/pixel/usePixelEditor.js +16 -0
- package/dist/cjs/pixel/usePixelEditor.js.map +1 -1
- package/dist/cjs/texture/Nice3DTexturePainter.js +123 -79
- package/dist/cjs/texture/Nice3DTexturePainter.js.map +1 -1
- package/dist/cjs/ui/NiceUIDesigner.js +175 -62
- package/dist/cjs/ui/NiceUIDesigner.js.map +1 -1
- package/dist/cjs/ui/dist/index.js +50089 -0
- package/dist/cjs/ui/dist/index.js.map +1 -0
- package/dist/cjs/vector/NiceSvgToCode.js +427 -0
- package/dist/cjs/vector/NiceSvgToCode.js.map +1 -0
- package/dist/cjs/vector/VectorEditor.js +7 -3
- package/dist/cjs/vector/VectorEditor.js.map +1 -1
- package/dist/cjs/vector/VectorEditor.module.css.js +1 -1
- package/dist/cjs/vector/VectorEditorMenuBar.js +5 -1
- package/dist/cjs/vector/VectorEditorMenuBar.js.map +1 -1
- package/dist/cjs/vector/VectorEditorRightPanel.js +23 -19
- package/dist/cjs/vector/VectorEditorRightPanel.js.map +1 -1
- package/dist/esm/animation/AnimatedPerson.js +2 -2
- package/dist/esm/animation/AnimatedPerson.js.map +1 -1
- package/dist/esm/animation/AnimationEditor.js +12 -8
- package/dist/esm/animation/AnimationEditor.js.map +1 -1
- package/dist/esm/animation/Audience.js +5 -4
- package/dist/esm/animation/Audience.js.map +1 -1
- package/dist/esm/animation/BodyRenderer.js +4 -2
- package/dist/esm/animation/BodyRenderer.js.map +1 -1
- package/dist/esm/animation/rig/RigPlayer.js +4 -4
- package/dist/esm/animation/rig/RigPlayer.js.map +1 -1
- package/dist/esm/animation/rig/RiggedBody.js +2 -2
- package/dist/esm/animation/rig/RiggedBody.js.map +1 -1
- package/dist/esm/animation/shapes/heads.js +4 -2
- package/dist/esm/animation/shapes/heads.js.map +1 -1
- package/dist/esm/core/LocalUI.js +4 -4
- package/dist/esm/core/NiceBrushEngine.js +442 -0
- package/dist/esm/core/NiceBrushEngine.js.map +1 -0
- package/dist/esm/core/yjsCollaboration.js +283 -0
- package/dist/esm/core/yjsCollaboration.js.map +1 -0
- package/dist/esm/font/NiceFontEditor.js +89 -85
- package/dist/esm/font/NiceFontEditor.js.map +1 -1
- package/dist/esm/font/fontFormatUtils.js +461 -0
- package/dist/esm/font/fontFormatUtils.js.map +1 -0
- package/dist/esm/game/GameAsset2dEditor.js +38 -25
- package/dist/esm/game/GameAsset2dEditor.js.map +1 -1
- package/dist/esm/icon/NiceIconEditor.js +218 -133
- package/dist/esm/icon/NiceIconEditor.js.map +1 -1
- package/dist/esm/index.js +21 -11
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/nice2dev-ui-graphics.css +1 -1
- package/dist/esm/photo/NiceAITools.js +439 -0
- package/dist/esm/photo/NiceAITools.js.map +1 -0
- package/dist/esm/photo/PhotoEditor.js +2 -2
- package/dist/esm/photo/PhotoEditor.js.map +1 -1
- package/dist/esm/pixel/PixelEditor.js +16 -6
- package/dist/esm/pixel/PixelEditor.js.map +1 -1
- package/dist/esm/pixel/PixelEditor.module.css.js +1 -1
- package/dist/esm/pixel/PixelEditorMenuBar.js +2 -1
- package/dist/esm/pixel/PixelEditorMenuBar.js.map +1 -1
- package/dist/esm/pixel/PixelEditorRightPanel.js +3 -2
- package/dist/esm/pixel/PixelEditorRightPanel.js.map +1 -1
- package/dist/esm/pixel/PixelEditorTimeline.js +2 -1
- package/dist/esm/pixel/PixelEditorTimeline.js.map +1 -1
- package/dist/esm/pixel/PixelEditorToolbar.js +2 -1
- package/dist/esm/pixel/PixelEditorToolbar.js.map +1 -1
- package/dist/esm/pixel/SpriteGeneratorPanel.js +222 -0
- package/dist/esm/pixel/SpriteGeneratorPanel.js.map +1 -0
- package/dist/esm/pixel/animalGeneratorPresets.js +647 -0
- package/dist/esm/pixel/animalGeneratorPresets.js.map +1 -0
- package/dist/esm/pixel/buildingGeneratorPresets.js +566 -0
- package/dist/esm/pixel/buildingGeneratorPresets.js.map +1 -0
- package/dist/esm/pixel/characterGeneratorPresets.js +556 -0
- package/dist/esm/pixel/characterGeneratorPresets.js.map +1 -0
- package/dist/esm/pixel/spriteGeneratorCore.js +279 -0
- package/dist/esm/pixel/spriteGeneratorCore.js.map +1 -0
- package/dist/esm/pixel/usePixelEditor.js +16 -0
- package/dist/esm/pixel/usePixelEditor.js.map +1 -1
- package/dist/esm/texture/Nice3DTexturePainter.js +123 -79
- package/dist/esm/texture/Nice3DTexturePainter.js.map +1 -1
- package/dist/esm/ui/NiceUIDesigner.js +175 -62
- package/dist/esm/ui/NiceUIDesigner.js.map +1 -1
- package/dist/esm/ui/dist/index.js +49686 -0
- package/dist/esm/ui/dist/index.js.map +1 -0
- package/dist/esm/vector/NiceSvgToCode.js +423 -0
- package/dist/esm/vector/NiceSvgToCode.js.map +1 -0
- package/dist/esm/vector/VectorEditor.js +7 -4
- package/dist/esm/vector/VectorEditor.js.map +1 -1
- package/dist/esm/vector/VectorEditor.module.css.js +1 -1
- package/dist/esm/vector/VectorEditorMenuBar.js +5 -1
- package/dist/esm/vector/VectorEditorMenuBar.js.map +1 -1
- package/dist/esm/vector/VectorEditorRightPanel.js +23 -19
- package/dist/esm/vector/VectorEditorRightPanel.js.map +1 -1
- package/package.json +3 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
.PixelEditor-module_root__3gidG{background:var(--editor-bg-deep);color:var(--gray-200);display:flex;flex-direction:column;font-family:Segoe UI,Consolas,monospace;font-size:12px;height:100%;overflow:hidden;user-select:none}.PixelEditor-module_menuBar__8JFld{align-items:center;background:var(--editor-bg-deeper);border-bottom:1px solid var(--editor-bg-dark);display:flex;flex-shrink:0;gap:0;height:28px;padding:0 4px}.PixelEditor-module_menuBtn__w-GQC{background:none;border:none;border-radius:3px;color:var(--editor-text-light);cursor:pointer;font-size:11px;padding:4px 10px}.PixelEditor-module_menuBtn__w-GQC:hover{background:var(--editor-bg-dark);color:var(--color-white)}.PixelEditor-module_menuSep__pNZsR{background:var(--gray-850);height:16px;margin:0 4px;width:1px}.PixelEditor-module_toolbar__paCGq{background:var(--editor-panel);border-right:1px solid var(--editor-bg-dark);display:flex;flex-direction:column;flex-shrink:0;gap:2px;overflow-y:auto;padding:4px 2px;width:38px}.PixelEditor-module_toolBtn__wD1Kj{align-items:center;background:none;border:1px solid transparent;border-radius:4px;color:var(--editor-text-muted);cursor:pointer;display:flex;font-size:16px;height:32px;justify-content:center;transition:all .1s;width:32px}.PixelEditor-module_toolBtn__wD1Kj:hover{background:var(--editor-bg-dark);color:var(--gray-300)}.PixelEditor-module_toolBtnActive__R51U0{background:var(--editor-bg-mid)!important;border-color:var(--editor-accent)!important;color:var(--color-white)!important}.PixelEditor-module_mainArea__Z0x6l{display:flex;flex:1;min-height:0}.PixelEditor-module_canvasContainer__8z2AY{background:var(--editor-bg-deepest);cursor:crosshair;flex:1;overflow:hidden;position:relative}.PixelEditor-module_canvasContainer__8z2AY canvas{image-rendering:pixelated;position:absolute}.PixelEditor-module_rightPanel__ZjrCh{background:var(--editor-bg-deep);border-left:1px solid var(--editor-bg-dark);display:flex;flex-direction:column;flex-shrink:0;overflow-y:auto;width:220px}.PixelEditor-module_panelSection__3l225{border-bottom:1px solid var(--editor-bg-dark);padding:6px 8px}.PixelEditor-module_panelTitle__vYyeO{align-items:center;color:var(--editor-text-secondary);display:flex;font-size:10px;justify-content:space-between;letter-spacing:.5px;margin-bottom:4px;text-transform:uppercase}.PixelEditor-module_panelTitle__vYyeO button{background:none;border:none;color:var(--editor-text-secondary);cursor:pointer;font-size:14px;line-height:1;padding:0 2px}.PixelEditor-module_panelTitle__vYyeO button:hover{color:var(--gray-500)}.PixelEditor-module_layerItem__J-gtn{align-items:center;border-radius:3px;cursor:pointer;display:flex;font-size:11px;gap:4px;padding:3px 4px}.PixelEditor-module_layerItem__J-gtn:hover{background:hsla(0,0%,100%,.04)}.PixelEditor-module_layerItemActive__yPt29{background:var(--editor-surface)!important;border:1px solid var(--accent-blue-dark)}.PixelEditor-module_layerVis__Uj7n2{align-items:center;cursor:pointer;display:flex;flex-shrink:0;font-size:10px;height:16px;justify-content:center;opacity:.6;width:16px}.PixelEditor-module_layerVis__Uj7n2:hover{opacity:1}.PixelEditor-module_layerName__HovwJ{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.PixelEditor-module_layerOpacity__qmWvu{color:var(--gray-600);font-size:10px;text-align:right;width:36px}.PixelEditor-module_paletteGrid__knY-n{display:grid;gap:2px;grid-template-columns:repeat(8,1fr)}.PixelEditor-module_paletteSwatch__MUbha{aspect-ratio:1;border:1px solid hsla(0,0%,100%,.08);border-radius:2px;cursor:pointer;transition:transform .1s}.PixelEditor-module_paletteSwatch__MUbha:hover{transform:scale(1.15);z-index:1}.PixelEditor-module_paletteSwatchActive__wDR4T{border-color:var(--color-white)!important;box-shadow:0 0 0 1px var(--editor-accent)}.PixelEditor-module_colorPickers__sQlBN{align-items:center;display:flex;gap:6px;margin-top:6px}.PixelEditor-module_colorSample__GN7Rd{border:2px solid hsla(0,0%,100%,.2);border-radius:4px;height:28px;width:28px}.PixelEditor-module_bottomPanel__rviLF{background:var(--editor-bg-deeper);border-top:1px solid var(--editor-bg-dark);display:flex;flex-direction:column;flex-shrink:0;height:80px}.PixelEditor-module_timelineControls__Laroq{align-items:center;border-bottom:1px solid #224;display:flex;font-size:11px;gap:6px;padding:2px 8px}.PixelEditor-module_timelineControls__Laroq button{background:var(--editor-bg-dark);border:none;border-radius:3px;color:var(--gray-500);cursor:pointer;font-size:11px;padding:2px 8px}.PixelEditor-module_timelineControls__Laroq button:hover{background:var(--editor-bg-mid);color:var(--color-white)}.PixelEditor-module_timelineControls__Laroq label{color:var(--gray-700)}.PixelEditor-module_timelineControls__Laroq input[type=number]{background:var(--gray-950);border:1px solid var(--gray-850);border-radius:3px;color:var(--gray-200);font-size:11px;padding:1px 4px;text-align:center;width:40px}.PixelEditor-module_timelineControls__Laroq input[type=checkbox]{accent-color:var(--editor-accent)}.PixelEditor-module_timelineFrames__dw06F{align-items:stretch;display:flex;flex:1;gap:2px;overflow-x:auto;padding:4px 8px}.PixelEditor-module_frameThumb__2E9mG{align-items:center;background:var(--gray-900);border:2px solid transparent;border-radius:4px;cursor:pointer;display:flex;flex-direction:column;justify-content:center;min-width:44px;overflow:hidden;position:relative;width:44px}.PixelEditor-module_frameThumb__2E9mG canvas{height:36px;image-rendering:pixelated;object-fit:contain;width:36px}.PixelEditor-module_frameThumb__2E9mG:hover{border-color:var(--gray-800)}.PixelEditor-module_frameThumbActive__Z0eK4{background:var(--editor-surface);border-color:var(--editor-accent)!important}.PixelEditor-module_frameNum__PoGQC{bottom:1px;color:var(--gray-700);font-size:8px;position:absolute;right:3px}.PixelEditor-module_statusBar__QnphD{align-items:center;background:var(--gray-950);border-top:1px solid var(--gray-900);color:var(--gray-700);display:flex;flex-shrink:0;font-size:10px;gap:12px;height:20px;padding:2px 8px}.PixelEditor-module_dialogOverlay__IgyFy{align-items:center;background:rgba(0,0,0,.6);display:flex;inset:0;justify-content:center;position:absolute;z-index:100}.PixelEditor-module_dialog__OnkAG{background:var(--editor-panel);border:1px solid var(--editor-bg-mid);border-radius:8px;box-shadow:0 8px 32px rgba(0,0,0,.5);min-width:300px;padding:20px}.PixelEditor-module_dialog__OnkAG h3{color:var(--gray-300);font-size:14px;margin:0 0 12px}.PixelEditor-module_dialog__OnkAG label{color:var(--gray-600);display:block;font-size:11px;margin:8px 0 2px}.PixelEditor-module_dialog__OnkAG input,.PixelEditor-module_dialog__OnkAG select{background:var(--gray-950);border:1px solid var(--gray-850);border-radius:4px;color:var(--gray-200);font-size:12px;padding:4px 8px;width:100%}.PixelEditor-module_dialogActions__fOa7a{display:flex;gap:8px;justify-content:flex-end;margin-top:16px}.PixelEditor-module_dialogActions__fOa7a button{border:none;border-radius:4px;cursor:pointer;font-size:12px;padding:4px 16px}.PixelEditor-module_btnPrimary__FYlTy{background:var(--editor-accent);color:var(--color-white)}.PixelEditor-module_btnPrimary__FYlTy:hover{background:#67d}.PixelEditor-module_btnSecondary__qLfyJ{background:var(--gray-850);color:var(--gray-500)}.PixelEditor-module_btnSecondary__qLfyJ:hover{background:var(--gray-800);color:var(--gray-200)}.PixelEditor-module_brushSlider__UxQ38{align-items:center;border-bottom:1px solid var(--editor-bg-dark);display:flex;gap:4px;padding:4px 8px}.PixelEditor-module_brushSlider__UxQ38 label{color:var(--gray-700);font-size:10px}.PixelEditor-module_brushSlider__UxQ38 input[type=range]{accent-color:var(--editor-accent);flex:1;height:4px}.PixelEditor-module_brushSlider__UxQ38 span{color:var(--gray-500);font-size:10px;min-width:16px;text-align:center}.PixelEditor-module_toolSep__YIu-E{background:var(--gray-850);height:1px;margin:4px 2px;width:28px}.PixelEditor-module_toolGroup__xA2lN{display:flex;flex-direction:column;gap:1px;padding:2px 0}.PixelEditor-module_miniBtn__tg5N0{align-items:center;background:hsla(0,0%,100%,.04);border:1px solid transparent;border-radius:3px;color:var(--editor-text-muted);cursor:pointer;display:flex;font-size:10px;height:20px;justify-content:center;transition:all .1s;width:32px}.PixelEditor-module_miniBtn__tg5N0:hover{background:var(--editor-bg-dark);color:var(--gray-300)}.PixelEditor-module_miniBtnActive__gpveu{background:var(--editor-bg-mid)!important;border-color:var(--editor-accent)!important;color:var(--color-white)!important}.PixelEditor-module_colorSwatches__jFuRX{align-items:center;border-top:1px solid var(--gray-850);display:flex;flex-direction:column;gap:4px;margin-top:4px;padding:6px 0}.PixelEditor-module_brushShapes__2bBfl{display:flex;flex-wrap:wrap;gap:2px;padding:2px 0}.PixelEditor-module_pressureToggles__AITuh{display:flex;flex-direction:column;gap:2px;padding:4px 0}.PixelEditor-module_checkLabel__-d-TA{align-items:center;color:var(--gray-550);cursor:pointer;display:flex;font-size:10px;gap:4px}.PixelEditor-module_checkLabel__-d-TA input[type=checkbox]{accent-color:var(--editor-accent);height:12px;width:12px}.PixelEditor-module_hsvPicker__0ERIh{display:flex;flex-direction:column;gap:4px;padding:4px 0}.PixelEditor-module_hsvRow__M3fhN{align-items:center;display:flex;gap:4px}.PixelEditor-module_hsvLabel__O2MkX{color:var(--gray-700);font-size:9px;min-width:16px;text-align:right}.PixelEditor-module_hsvSlider__KKMMJ{accent-color:var(--editor-accent);cursor:pointer;flex:1;height:6px;min-width:0}.PixelEditor-module_hsvVal__MgQ8W{color:var(--gray-500);font-size:9px;min-width:28px;text-align:right}.PixelEditor-module_hsvNumInput__Wn4kG{text-align:center;width:36px}.PixelEditor-module_hsvHexInput__MU5Ms,.PixelEditor-module_hsvNumInput__Wn4kG{background:var(--gray-950);border:1px solid var(--gray-850);border-radius:3px;color:var(--gray-200);font-size:10px;padding:1px 4px}.PixelEditor-module_hsvHexInput__MU5Ms{flex:1}.PixelEditor-module_layerLock__xeWnc{align-items:center;cursor:pointer;display:flex;flex-shrink:0;font-size:10px;height:16px;justify-content:center;opacity:.6;width:16px}.PixelEditor-module_layerLock__xeWnc:hover{opacity:1}.PixelEditor-module_layerNameInput__ZiOKv{background:var(--gray-950);border:1px solid var(--editor-accent);border-radius:2px;color:var(--gray-100);flex:1;font-size:11px;min-width:0;outline:none;padding:0 4px}.PixelEditor-module_layerControls__MrpXo{align-items:center;border-top:1px solid hsla(0,0%,100%,.05);display:flex;gap:4px;margin-top:4px;padding:4px 4px 2px}.PixelEditor-module_blendSelect__QCwns{background:var(--gray-950);border:1px solid var(--gray-850);border-radius:3px;color:var(--gray-300);cursor:pointer;flex:1;font-size:10px;padding:1px 4px}.PixelEditor-module_layerOpSlider__Vw-qs{accent-color:var(--editor-accent);cursor:pointer;height:4px;width:60px}.VectorEditor-module_root__rtRWo{background:var(--editor-bg-deep);color:var(--gray-200);display:flex;flex-direction:column;font-family:Segoe UI,Consolas,monospace;font-size:12px;height:100%;overflow:hidden;user-select:none}.VectorEditor-module_menuBar__o25XM{align-items:center;background:var(--editor-bg-deeper);border-bottom:1px solid var(--editor-bg-dark);display:flex;flex-shrink:0;gap:0;height:28px;padding:0 4px}.VectorEditor-module_menuBtn__aP4vp{background:none;border:none;border-radius:3px;color:var(--editor-text-light);cursor:pointer;font-size:11px;padding:4px 10px}.VectorEditor-module_menuBtn__aP4vp:hover{background:var(--editor-bg-dark);color:var(--color-white)}.VectorEditor-module_menuSep__3-kTv{background:var(--gray-850);height:16px;margin:0 4px;width:1px}.VectorEditor-module_menuLabel__Bsm0e{align-items:center;color:var(--gray-600);cursor:pointer;display:flex;font-size:10px;gap:2px;padding:0 4px}.VectorEditor-module_toolbar__fakYL{background:var(--editor-panel);border-right:1px solid var(--editor-bg-dark);display:flex;flex-direction:column;flex-shrink:0;gap:2px;padding:4px 2px;width:38px}.VectorEditor-module_toolBtn__Zh7D3{align-items:center;background:none;border:1px solid transparent;border-radius:4px;color:var(--editor-text-muted);cursor:pointer;display:flex;font-size:16px;height:32px;justify-content:center;transition:all .1s;width:32px}.VectorEditor-module_toolBtn__Zh7D3:hover{background:var(--editor-bg-dark);color:var(--gray-300)}.VectorEditor-module_toolBtnActive__0xZlr{background:var(--editor-bg-mid)!important;border-color:var(--editor-accent)!important;color:var(--color-white)!important}.VectorEditor-module_mainArea__3o89F{display:flex;flex:1;min-height:0}.VectorEditor-module_canvasContainer__hOUAx{background:var(--editor-bg-deepest);flex:1;overflow:hidden;position:relative}.VectorEditor-module_canvasContainer__hOUAx svg{height:100%;inset:0;position:absolute;width:100%}.VectorEditor-module_rightPanel__3hzcS{background:var(--editor-bg-deep);border-left:1px solid var(--editor-bg-dark);display:flex;flex-direction:column;flex-shrink:0;overflow-y:auto;width:220px}.VectorEditor-module_panelSection__uteDQ{border-bottom:1px solid var(--editor-bg-dark);padding:6px 8px}.VectorEditor-module_panelTitle__WBUxr{align-items:center;color:var(--editor-text-secondary);display:flex;font-size:10px;justify-content:space-between;letter-spacing:.5px;margin-bottom:4px;text-transform:uppercase}.VectorEditor-module_panelTitle__WBUxr button{background:none;border:none;color:var(--editor-text-secondary);cursor:pointer;font-size:14px;line-height:1;padding:0 2px}.VectorEditor-module_panelTitle__WBUxr button:hover{color:var(--gray-500)}.VectorEditor-module_shapeItem__bu2E2{align-items:center;border-radius:3px;cursor:pointer;display:flex;font-size:11px;gap:6px;padding:3px 4px}.VectorEditor-module_shapeItem__bu2E2:hover{background:hsla(0,0%,100%,.04)}.VectorEditor-module_shapeItemActive__E2lK7{background:var(--editor-surface)!important;border:1px solid var(--accent-blue-dark)}.VectorEditor-module_shapeIcon__M4j6X{flex-shrink:0;font-size:14px;opacity:.7}.VectorEditor-module_shapeName__2QctO{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.VectorEditor-module_propRow__Alc4S{align-items:center;display:flex;gap:6px;margin-bottom:4px}.VectorEditor-module_propLabel__J0lxK{color:var(--gray-600);font-size:10px;min-width:40px}.VectorEditor-module_propInput__3my2d{background:var(--gray-950);border:1px solid var(--gray-850);border-radius:3px;color:var(--gray-200);flex:1;font-size:11px;padding:2px 4px}.VectorEditor-module_propColorSwatch__JL97Z{border:1px solid hsla(0,0%,100%,.15);border-radius:3px;cursor:pointer;height:24px;position:relative;width:24px}.VectorEditor-module_propColorSwatch__JL97Z input{cursor:pointer;height:100%;inset:0;opacity:0;position:absolute;width:100%}.VectorEditor-module_statusBar__jMwan{align-items:center;background:var(--gray-950);border-top:1px solid var(--gray-900);color:var(--gray-700);display:flex;flex-shrink:0;font-size:10px;gap:12px;height:20px;padding:2px 8px}.VectorEditor-module_dialogOverlay__NLiCg{align-items:center;background:rgba(0,0,0,.6);display:flex;inset:0;justify-content:center;position:absolute;z-index:100}.VectorEditor-module_dialog__NDNK2{background:var(--editor-panel);border:1px solid var(--editor-bg-mid);border-radius:8px;box-shadow:0 8px 32px rgba(0,0,0,.5);max-width:500px;min-width:300px;padding:20px}.VectorEditor-module_dialog__NDNK2 h3{color:var(--gray-300);font-size:14px;margin:0 0 12px}.VectorEditor-module_dialog__NDNK2 label{color:var(--gray-600);display:block;font-size:11px;margin:8px 0 2px}.VectorEditor-module_dialog__NDNK2 input,.VectorEditor-module_dialog__NDNK2 select,.VectorEditor-module_dialog__NDNK2 textarea{background:var(--gray-950);border:1px solid var(--gray-850);border-radius:4px;color:var(--gray-200);font-size:12px;padding:4px 8px;width:100%}.VectorEditor-module_dialog__NDNK2 textarea{font-family:monospace;min-height:120px;resize:vertical}.VectorEditor-module_dialogActions__0Sy4X{display:flex;gap:8px;justify-content:flex-end;margin-top:16px}.VectorEditor-module_dialogActions__0Sy4X button{border:none;border-radius:4px;cursor:pointer;font-size:12px;padding:4px 16px}.VectorEditor-module_btnPrimary__f9AaS{background:var(--editor-accent);color:var(--color-white)}.VectorEditor-module_btnPrimary__f9AaS:hover{background:#67d}.VectorEditor-module_btnSecondary__wDps2{background:var(--gray-850);color:var(--gray-500)}.VectorEditor-module_btnSecondary__wDps2:hover{background:var(--gray-800);color:var(--gray-200)}.VectorEditor-module_handleGroup__sMkQj circle{fill:var(--editor-accent);stroke:var(--color-white);stroke-width:1;cursor:pointer}.VectorEditor-module_handleGroup__sMkQj circle:hover{fill:#78e}.PhotoEditor-module_wrapper__jrHYj{background:#1a1a1e;border-radius:12px;color:#eee;display:flex;flex-direction:column;font-family:Segoe UI,sans-serif;font-size:13px;max-height:85vh;overflow:hidden;width:100%}.PhotoEditor-module_loadingWrap__QUTon{align-items:center;color:#aaa;display:flex;justify-content:center;min-height:400px;width:100%}.PhotoEditor-module_mainContent__TCVxf{display:flex;flex:1;min-height:0;overflow:hidden}.PhotoEditor-module_toolbar__RY-Ty{align-items:center;background:#222226;border-bottom:1px solid #333;display:flex;justify-content:space-between;padding:8px 14px}.PhotoEditor-module_toolbarGroup__PXw0-{display:flex;gap:6.5px}.PhotoEditor-module_toolbarDivider__o3kFV{background:#444;margin:0 4px;width:1px}.PhotoEditor-module_toolbarTitle__P1o18{font-size:14px;font-weight:700}.PhotoEditor-module_leftPanel__DnHLU{background:#222226;border-right:1px solid #333;display:flex;flex-direction:column;min-width:280px;overflow:hidden;width:280px}.PhotoEditor-module_tabBar__DZ3MG{border-bottom:1px solid #333;display:flex;flex-wrap:wrap}.PhotoEditor-module_tabButton__BLi97{align-items:center;background:transparent;border:none;border-bottom:2px solid transparent;color:#888;cursor:pointer;display:flex;flex:1 0 auto;flex-direction:column;font-size:10px;font-weight:600;gap:1px;min-width:34px;padding:8px 0;transition:all .15s}.PhotoEditor-module_tabButtonActive__KlQG0{background:#2a2a30}.PhotoEditor-module_tabIcon__-Mq19{font-size:14px}.PhotoEditor-module_panelContent__l5i5t{flex:1;overflow-y:auto;padding:10px 12px}.PhotoEditor-module_sectionTitle__tMvCm{font-size:12px;font-weight:600;margin-bottom:6px}.PhotoEditor-module_sectionTitleMb8__PQ-lV{margin-bottom:8px}.PhotoEditor-module_sectionInfo__bWxW5{color:#aaa;font-size:11px}.PhotoEditor-module_sectionInfoMb__Hk6V-{margin-bottom:10px}.PhotoEditor-module_pillRow__DGJUb{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:10px}.PhotoEditor-module_pillRowMb8__AQrth{margin-bottom:8px}.PhotoEditor-module_pillRowGap3__Y46Vu{display:flex;flex-wrap:wrap;gap:3px;margin-bottom:8px}.PhotoEditor-module_pill__wTFac{background:transparent;border:1px solid #444;border-radius:12px;color:#aaa;cursor:pointer;font-size:11px;font-weight:600;padding:3px 10px}.PhotoEditor-module_pillActive__AfdZR{color:#fff}.PhotoEditor-module_pillCrop__Nsisp{border-radius:6px;padding:4px 12px}.PhotoEditor-module_pillCropActive__p6csO{color:#fff}.PhotoEditor-module_pillEmoji__I42DJ{border-radius:10px;padding:2px 8px}.PhotoEditor-module_pillEmojiActive__0-EM7{color:#fff}.PhotoEditor-module_filterGrid__-29PS{display:grid;gap:6px;grid-template-columns:repeat(3,1fr)}.PhotoEditor-module_emojiGrid__whqqK{display:grid;gap:2px;grid-template-columns:repeat(6,1fr);max-height:260px;overflow-y:auto}.PhotoEditor-module_shapeGrid__TawIy{margin-bottom:16px}.PhotoEditor-module_frameGrid__R09dd,.PhotoEditor-module_shapeGrid__TawIy{display:grid;gap:4px;grid-template-columns:repeat(5,1fr)}.PhotoEditor-module_sliderRow__jsWDQ{align-items:center;display:flex;gap:6px;margin-bottom:8px}.PhotoEditor-module_sliderLabel__zOZ49{color:#aaa;font-size:11px}.PhotoEditor-module_sliderLabelSelf__EwYKU{align-self:center;margin-right:4px}.PhotoEditor-module_sliderValue__qFuTw{font-size:11px;font-weight:600;min-width:28px}.PhotoEditor-module_sliderValueSm__U7FrJ{font-size:10px;min-width:28px}.PhotoEditor-module_adjustColumn__y---T{display:flex;flex-direction:column;gap:8px}.PhotoEditor-module_adjustHeader__6s9zV{display:flex;font-size:11px;justify-content:space-between;margin-bottom:2px}.PhotoEditor-module_adjustIcon__d56rY{text-align:center;width:14px}.PhotoEditor-module_adjustValue__aUUmg{cursor:pointer;font-weight:600;min-width:30px;text-align:right}.PhotoEditor-module_intensitySection__dhe5h{margin-top:12px;padding:8px 0}.PhotoEditor-module_intensityHeader__-KKu6{display:flex;font-size:11px;justify-content:space-between;margin-bottom:4px}.PhotoEditor-module_colorInput__xkF1h{border:none;cursor:pointer;height:28px;padding:0;width:28px}.PhotoEditor-module_colorInputLg__W2KrK{border:none;cursor:pointer;height:30px;padding:0;width:32px}.PhotoEditor-module_colorInputDraw__KYcdG{border:none;cursor:pointer;height:28px;padding:0;width:32px}.PhotoEditor-module_overlayToolbar__hfspp{border-bottom:1px solid #333;display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px;padding:6px 0}.PhotoEditor-module_overlayToolbarLabel__mc4pU{align-self:center;color:#aaa;font-size:11px;margin-right:4px}.PhotoEditor-module_overlayToolbarBtn__AdTmZ{font-size:11px;padding:2px 6px}.PhotoEditor-module_overlaySection__IIl4r{border-top:1px solid #333;margin-top:12px;padding-top:8px}.PhotoEditor-module_overlaySectionTitle__FRx3e{color:#aaa;font-size:11px;font-weight:600;margin-bottom:4px}.PhotoEditor-module_overlayItem__DGUCN{align-items:center;background:transparent;border-radius:4px;color:#ccc;cursor:pointer;display:flex;font-size:11px;gap:6px;margin-bottom:2px;padding:3px 6px}.PhotoEditor-module_overlayIcon__G0pFk{text-align:center;width:18px}.PhotoEditor-module_overlayName__JVh64{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.PhotoEditor-module_overlayDeleteBtn__Ontxv{background:none;border:none;color:#f55;cursor:pointer;font-size:11px;padding:0}.PhotoEditor-module_emojiBtn__jxG9m{background:transparent;border:none;border-radius:6px;cursor:pointer;font-size:22px;line-height:1;padding:4px 0}.PhotoEditor-module_shapeBtn__xZdSV{font-size:20px}.PhotoEditor-module_frameBtn__coMkZ,.PhotoEditor-module_shapeBtn__xZdSV{background:transparent;border:1px solid #444;border-radius:6px;color:#eee;cursor:pointer;line-height:1;padding:6px 0}.PhotoEditor-module_frameBtn__coMkZ{font-size:18px}.PhotoEditor-module_removeFrameBtn__oCuua{background:transparent;border:1px solid #444;border-radius:6px;color:#f55;cursor:pointer;font-size:14px;padding:6px 0}.PhotoEditor-module_textFormatBtn__7Z9RJ{min-width:32px}.PhotoEditor-module_textFormatBtnSm__3ptcG{min-width:28px}.PhotoEditor-module_drawActionBtn__teYz4{flex:1}.PhotoEditor-module_textArea__sBGlB{background:#2a2a30;border:1px solid #444;border-radius:6px;color:#eee;font-size:13px;margin-bottom:8px;resize:none}.PhotoEditor-module_textAreaSm__6xZnY{font-size:12px;margin-bottom:0}.PhotoEditor-module_textBtnRow__AcEnd{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px}.PhotoEditor-module_textGapRow__Dq2uz{display:flex;gap:4px;margin-top:6px}.PhotoEditor-module_editSelectedSection__bgNEh{border-top:1px solid #333;margin-top:12px;padding-top:8px}.PhotoEditor-module_editSelectedLabel__u2rmS{color:#aaa;font-size:11px;margin-bottom:4px}.PhotoEditor-module_shapeColorRow__ip5--{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px}.PhotoEditor-module_shapeColorLabel__nVcbU{align-self:center;color:#aaa;font-size:11px;margin-right:2px}.PhotoEditor-module_shapeColorLabelMl__KiM2d{margin-left:4px}.PhotoEditor-module_shapeFillToggle__BXJ8C{font-size:10px;padding:2px 6px}.PhotoEditor-module_frameColorRow__KRAHz{display:flex;gap:4px;margin-bottom:8px}.PhotoEditor-module_frameThicknessWrap__lXCoC{align-items:center;display:flex;flex:1;gap:4px}.PhotoEditor-module_frameThicknessValue__SAEuc{font-size:10px}.PhotoEditor-module_drawPreview__WPbiv{display:flex;justify-content:center;margin-bottom:12px}.PhotoEditor-module_drawActionRow__CUSWS{display:flex;gap:4px}.PhotoEditor-module_quickColorRow__DTy5E{align-items:center;display:flex;gap:6px;margin-bottom:8px}.PhotoEditor-module_quickColorSwatch__ZjgoA{border:1px solid #555;border-radius:3px;cursor:pointer;height:18px;width:18px}.PhotoEditor-module_transformRow__LKRjS{display:flex;gap:6px;margin-bottom:16px}.PhotoEditor-module_transformZoomRow__h2NlB{align-items:center;display:flex;gap:8px}.PhotoEditor-module_transformZoomValue__LXa51{font-size:11px;font-weight:600;min-width:40px}.PhotoEditor-module_transformInfo__zXP9l{background:#2a2a30;border-radius:8px;color:#aaa;font-size:11px;margin-top:16px;padding:10px}.PhotoEditor-module_canvasViewport__OMBIL{align-items:center;background:#111115;display:flex;flex:1;justify-content:center;overflow:auto;padding:20px;position:relative}.PhotoEditor-module_zoomWrap__JjfiJ{max-height:100%;max-width:100%;position:relative;transform-origin:center center;transition:transform .15s ease}.PhotoEditor-module_compareWrap__-J5ku{cursor:ew-resize;display:inline-block;position:relative}.PhotoEditor-module_canvasOriginal__Apf91{max-width:100%}.PhotoEditor-module_canvasEdited__Eroz7,.PhotoEditor-module_canvasOriginal__Apf91{display:block;max-height:60vh;object-fit:contain}.PhotoEditor-module_compareClip__5qG2I{bottom:0;left:0;overflow:hidden;position:absolute;top:0}.PhotoEditor-module_compareSlider__OIIIK{bottom:0;position:absolute;top:0;transform:translateX(-50%);width:3px}.PhotoEditor-module_compareSliderKnob__VohI9{align-items:center;border-radius:50%;box-shadow:0 2px 8px rgba(0,0,0,.4);display:flex;height:28px;justify-content:center;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);width:28px}.PhotoEditor-module_compareSliderIcon__pXcct{color:#fff;font-size:12px}.PhotoEditor-module_compareLabelOriginal__GaBoj{background:rgba(0,0,0,.6);left:8px}.PhotoEditor-module_compareLabelEdited__Fr836,.PhotoEditor-module_compareLabelOriginal__GaBoj{border-radius:4px;color:#fff;font-size:11px;font-weight:600;padding:2px 8px;position:absolute;top:8px}.PhotoEditor-module_compareLabelEdited__Fr836{right:8px}.PhotoEditor-module_regularWrap__8umPV{display:inline-block;position:relative}.PhotoEditor-module_canvasRegular__wxapL{border-radius:6px;box-shadow:0 4px 20px rgba(0,0,0,.4);display:block;max-height:60vh;max-width:100%;object-fit:contain}.PhotoEditor-module_cropOverlay__MJk1Y{inset:0;pointer-events:none;position:absolute;z-index:2}.PhotoEditor-module_cropDarkBg__m3axV{background:rgba(0,0,0,.55);inset:0;position:absolute}.PhotoEditor-module_cropGridContainer__NfHdT{inset:0;position:absolute}.PhotoEditor-module_cropSizeLabel__fV2mF{background:rgba(0,0,0,.75);border-radius:3px;bottom:-24px;color:#fff;font-size:10px;left:50%;padding:2px 8px;position:absolute;transform:translateX(-50%);white-space:nowrap}.PhotoEditor-module_cropInfo__Z1SCE{color:#aaa;font-size:11px;margin-bottom:10px}.PhotoEditor-module_cropAspectLabel__dieL-{font-size:12px;font-weight:600;margin-bottom:6px}.PhotoEditor-module_cropAspectRow__scRj3{display:flex;flex-wrap:wrap;gap:4px}.PhotoEditor-module_accentBtn__tgaEx{color:#fff;font-weight:600;width:100%}.GameAsset2dEditor-module_root__WVJBM{background:#1a1a2e;color:#e0e0e0;display:flex;flex-direction:column;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:13px;height:100%;min-height:600px;user-select:none}.GameAsset2dEditor-module_menuBar__WaEaU{align-items:center;background:#16213e;border-bottom:1px solid #0f3460;display:flex;gap:8px;padding:6px 12px}.GameAsset2dEditor-module_menuBar__WaEaU h3{color:#ffd369;font-size:14px;font-weight:600;margin:0}.GameAsset2dEditor-module_menuGroup__EOreB{display:flex;gap:2px}.GameAsset2dEditor-module_menuBtn__JYWXn{align-items:center;background:transparent;border:none;border-radius:4px;color:#b0b0b0;cursor:pointer;display:flex;font-size:12px;gap:4px;padding:4px 8px;transition:all .15s}.GameAsset2dEditor-module_menuBtn__JYWXn:hover{background:hsla(0,0%,100%,.1);color:#fff}.GameAsset2dEditor-module_menuBtn__JYWXn:disabled{cursor:not-allowed;opacity:.4}.GameAsset2dEditor-module_spacer__fPVeq{flex:1}.GameAsset2dEditor-module_modeTabs__iKh7C{background:#1f2940;border-bottom:1px solid #0f3460;display:flex;gap:2px;padding:4px 12px}.GameAsset2dEditor-module_modeTab__C12zt{background:transparent;border:none;border-radius:4px 4px 0 0;color:#8892a8;cursor:pointer;font-size:12px;font-weight:500;padding:6px 16px;transition:all .15s}.GameAsset2dEditor-module_modeTab__C12zt:hover{background:hsla(0,0%,100%,.05);color:#c0c8d8}.GameAsset2dEditor-module_modeTab__C12zt.GameAsset2dEditor-module_active__DUroI{background:#1a1a2e;color:#ffd369}.GameAsset2dEditor-module_mainArea__jwDUa{display:flex;flex:1;overflow:hidden}.GameAsset2dEditor-module_leftPanel__xxAg5{background:#16213e;border-right:1px solid #0f3460;display:flex;flex-direction:column;overflow:hidden;width:220px}.GameAsset2dEditor-module_centerArea__xr-Hn{display:flex;flex:1;flex-direction:column;overflow:hidden}.GameAsset2dEditor-module_rightPanel__YoNuc{background:#16213e;border-left:1px solid #0f3460;display:flex;flex-direction:column;overflow:hidden;width:260px}.GameAsset2dEditor-module_toolbar__hEC9S{align-items:center;background:#1f2940;border-bottom:1px solid #0f3460;display:flex;gap:8px;padding:6px 12px}.GameAsset2dEditor-module_toolGroup__Zbn47{background:rgba(0,0,0,.2);border-radius:4px;display:flex;gap:2px;padding:2px}.GameAsset2dEditor-module_toolBtn__5U7Rw{align-items:center;background:transparent;border:none;border-radius:3px;color:#8892a8;cursor:pointer;display:flex;font-size:14px;height:28px;justify-content:center;transition:all .15s;width:28px}.GameAsset2dEditor-module_toolBtn__5U7Rw:hover{background:hsla(0,0%,100%,.1);color:#fff}.GameAsset2dEditor-module_toolBtn__5U7Rw.GameAsset2dEditor-module_active__DUroI{background:#0f3460;color:#ffd369}.GameAsset2dEditor-module_toolBtn__5U7Rw:disabled{cursor:not-allowed;opacity:.3}.GameAsset2dEditor-module_viewport__vEKEv{background:#0a0a14;flex:1;overflow:hidden;position:relative}.GameAsset2dEditor-module_viewportCanvas__FJ5qA{image-rendering:pixelated;image-rendering:crisp-edges;left:50%;position:absolute;top:50%}.GameAsset2dEditor-module_gridOverlay__K8B97{bottom:0;left:0;pointer-events:none;position:absolute;right:0;top:0}.GameAsset2dEditor-module_panelHeader__xm2As{align-items:center;background:#0f3460;color:#8892a8;display:flex;font-size:11px;font-weight:600;justify-content:space-between;letter-spacing:.5px;padding:8px 12px;text-transform:uppercase}.GameAsset2dEditor-module_panelContent__dvOGq{flex:1;overflow-y:auto;padding:8px}.GameAsset2dEditor-module_panelSection__RQQDr{margin-bottom:16px}.GameAsset2dEditor-module_panelLabel__Ks-Wa{color:#8892a8;display:block;font-size:11px;letter-spacing:.5px;margin-bottom:6px;text-transform:uppercase}.GameAsset2dEditor-module_panelInput__cxNiG{background:#0a0a14;border:1px solid #2a3a5e;border-radius:4px;color:#e0e0e0;font-size:12px;padding:6px 8px;width:100%}.GameAsset2dEditor-module_panelInput__cxNiG:focus{border-color:#ffd369;outline:none}.GameAsset2dEditor-module_tilePalette__OpzmV{display:grid;gap:4px;grid-template-columns:repeat(auto-fill,minmax(40px,1fr));padding:8px}.GameAsset2dEditor-module_tileItem__uWNS9{aspect-ratio:1;background:#0a0a14;border:2px solid transparent;border-radius:4px;cursor:pointer;overflow:hidden;transition:all .15s}.GameAsset2dEditor-module_tileItem__uWNS9:hover{border-color:#4a5a7e}.GameAsset2dEditor-module_tileItem__uWNS9.GameAsset2dEditor-module_selected__216IN{border-color:#ffd369}.GameAsset2dEditor-module_tileItem__uWNS9 img{height:100%;image-rendering:pixelated;object-fit:contain;width:100%}.GameAsset2dEditor-module_layersList__anFaG{display:flex;flex-direction:column;gap:2px}.GameAsset2dEditor-module_layerItem__XSGlu{align-items:center;background:#1f2940;border-radius:4px;cursor:pointer;display:flex;gap:8px;padding:6px 8px;transition:all .15s}.GameAsset2dEditor-module_layerItem__XSGlu:hover{background:#2a3a5e}.GameAsset2dEditor-module_layerItem__XSGlu.GameAsset2dEditor-module_selected__216IN{background:#0f3460;border-left:3px solid #ffd369}.GameAsset2dEditor-module_layerVisibility__RpHjV{align-items:center;background:transparent;border:none;border-radius:3px;color:#8892a8;cursor:pointer;display:flex;height:20px;justify-content:center;width:20px}.GameAsset2dEditor-module_layerVisibility__RpHjV:hover{background:hsla(0,0%,100%,.1)}.GameAsset2dEditor-module_layerVisibility__RpHjV.GameAsset2dEditor-module_hidden__mukOG{opacity:.4}.GameAsset2dEditor-module_layerName__WBxq5{color:#c0c8d8;flex:1;font-size:12px}.GameAsset2dEditor-module_layerOpacity__FpzL-{color:#8892a8;font-size:10px;text-align:right;width:40px}.GameAsset2dEditor-module_framesList__vg1oO{display:grid;gap:8px;grid-template-columns:repeat(auto-fill,minmax(60px,1fr));padding:8px}.GameAsset2dEditor-module_frameItem__fkEfb{aspect-ratio:1;background:#0a0a14;border:2px solid transparent;border-radius:4px;cursor:pointer;overflow:hidden;position:relative;transition:all .15s}.GameAsset2dEditor-module_frameItem__fkEfb:hover{border-color:#4a5a7e}.GameAsset2dEditor-module_frameItem__fkEfb.GameAsset2dEditor-module_selected__216IN{border-color:#ffd369}.GameAsset2dEditor-module_frameItem__fkEfb canvas{height:100%;image-rendering:pixelated;object-fit:contain;width:100%}.GameAsset2dEditor-module_frameLabel__5IGW8{background:rgba(0,0,0,.7);bottom:0;color:#b0b0b0;font-size:9px;left:0;padding:2px 4px;position:absolute;right:0;text-align:center}.GameAsset2dEditor-module_timeline__dPJk6{background:#16213e;border-top:1px solid #0f3460;padding:8px}.GameAsset2dEditor-module_timelineTrack__mr20w{background:#0a0a14;border-radius:4px;display:flex;gap:4px;overflow-x:auto;padding:4px}.GameAsset2dEditor-module_timelineFrame__AQyGe{background:#1f2940;border:2px solid transparent;border-radius:4px;cursor:pointer;flex-shrink:0;height:48px;overflow:hidden;width:48px}.GameAsset2dEditor-module_timelineFrame__AQyGe:hover{border-color:#4a5a7e}.GameAsset2dEditor-module_timelineFrame__AQyGe.GameAsset2dEditor-module_current__3sAfL{border-color:#ffd369}.GameAsset2dEditor-module_stateGraph__qAWlU{background:#0a0a14;flex:1;overflow:hidden;position:relative}.GameAsset2dEditor-module_stateNode__W9Z-g{background:#1f2940;border:2px solid #2a3a5e;border-radius:8px;cursor:move;min-width:120px;padding:8px 12px;position:absolute;transition:border-color .15s}.GameAsset2dEditor-module_stateNode__W9Z-g:hover{border-color:#4a5a7e}.GameAsset2dEditor-module_stateNode__W9Z-g.GameAsset2dEditor-module_selected__216IN{border-color:#ffd369}.GameAsset2dEditor-module_stateNode__W9Z-g.GameAsset2dEditor-module_entry__cmA9n{border-color:#4ade80}.GameAsset2dEditor-module_stateNodeName__TK5vs{color:#e0e0e0;font-size:12px;font-weight:500;text-align:center}.GameAsset2dEditor-module_stateNodeAnim__VGwnV{color:#8892a8;font-size:10px;margin-top:4px;text-align:center}.GameAsset2dEditor-module_transition__FBbno{stroke:#4a5a7e;stroke-width:2;fill:none;marker-end:url(#arrowhead)}.GameAsset2dEditor-module_transition__FBbno:hover{stroke:#ffd369}.GameAsset2dEditor-module_effectsList__vHq4I{display:flex;flex-direction:column;gap:8px}.GameAsset2dEditor-module_effectItem__6-1li{background:#1f2940;border-radius:6px;overflow:hidden}.GameAsset2dEditor-module_effectHeader__cgVN-{align-items:center;cursor:pointer;display:flex;gap:8px;padding:8px}.GameAsset2dEditor-module_effectToggle__lKE36{background:#0a0a14;border:1px solid #2a3a5e;border-radius:3px;cursor:pointer;height:18px;width:18px}.GameAsset2dEditor-module_effectToggle__lKE36.GameAsset2dEditor-module_enabled__wgDzp{background:#ffd369;border-color:#ffd369}.GameAsset2dEditor-module_effectName__NQCWj{color:#c0c8d8;flex:1;font-size:12px}.GameAsset2dEditor-module_effectRemove__TSSdI{align-items:center;background:transparent;border:none;border-radius:3px;color:#8892a8;cursor:pointer;display:flex;height:20px;justify-content:center;width:20px}.GameAsset2dEditor-module_effectRemove__TSSdI:hover{background:#ef4444;color:#fff}.GameAsset2dEditor-module_effectParams__UqTBd{background:rgba(0,0,0,.2);padding:8px}.GameAsset2dEditor-module_effectParam__hEsVY{align-items:center;display:flex;gap:8px;margin-bottom:8px}.GameAsset2dEditor-module_effectParam__hEsVY:last-child{margin-bottom:0}.GameAsset2dEditor-module_effectParamLabel__u0Qoc{color:#8892a8;flex:0 0 80px;font-size:11px}.GameAsset2dEditor-module_effectParamInput__aqxdv{background:#0a0a14;border:1px solid #2a3a5e;border-radius:3px;color:#e0e0e0;flex:1;font-size:11px;height:24px;padding:0 8px}.GameAsset2dEditor-module_statusBar__eOrNe{align-items:center;background:#0f3460;color:#8892a8;display:flex;font-size:11px;gap:16px;padding:4px 12px}.GameAsset2dEditor-module_statusItem__kKLHF{align-items:center;display:flex;gap:4px}.GameAsset2dEditor-module_zoomControl__4YD9G{align-items:center;display:flex;gap:4px;margin-left:auto}.GameAsset2dEditor-module_zoomBtn__hxYik{align-items:center;background:transparent;border:none;border-radius:3px;color:#8892a8;cursor:pointer;display:flex;height:20px;justify-content:center;width:20px}.GameAsset2dEditor-module_zoomBtn__hxYik:hover{background:hsla(0,0%,100%,.1);color:#fff}.GameAsset2dEditor-module_dialogOverlay__dZYwO{align-items:center;background:rgba(0,0,0,.6);bottom:0;display:flex;justify-content:center;left:0;position:fixed;right:0;top:0;z-index:1000}.GameAsset2dEditor-module_dialog__mfLFL{background:#16213e;border-radius:8px;box-shadow:0 8px 32px rgba(0,0,0,.4);max-width:500px;min-width:300px;padding:24px}.GameAsset2dEditor-module_dialog__mfLFL h3{color:#ffd369;font-size:16px;margin:0 0 16px}.GameAsset2dEditor-module_dialogActions__vhDXe{display:flex;gap:8px;justify-content:flex-end;margin-top:20px}.GameAsset2dEditor-module_btnPrimary__Gzc25{background:#ffd369;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;font-size:12px;font-weight:600;padding:8px 16px;transition:all .15s}.GameAsset2dEditor-module_btnPrimary__Gzc25:hover{background:#ffe599}.GameAsset2dEditor-module_btnSecondary__G5nK5{background:transparent;border:1px solid #4a5a7e;border-radius:4px;color:#c0c8d8;cursor:pointer;font-size:12px;padding:8px 16px;transition:all .15s}.GameAsset2dEditor-module_btnSecondary__G5nK5:hover{background:hsla(0,0%,100%,.05);border-color:#6a7a9e}.GameAsset2dEditor-module_panelContent__dvOGq::-webkit-scrollbar{width:6px}.GameAsset2dEditor-module_panelContent__dvOGq::-webkit-scrollbar-track{background:#0a0a14}.GameAsset2dEditor-module_panelContent__dvOGq::-webkit-scrollbar-thumb{background:#2a3a5e;border-radius:3px}.GameAsset2dEditor-module_panelContent__dvOGq::-webkit-scrollbar-thumb:hover{background:#4a5a7e}.GameAsset2dEditor-module_dropZone__Z7sYz{border:2px dashed #4a5a7e;border-radius:8px;color:#8892a8;cursor:pointer;padding:24px;text-align:center;transition:all .15s}.GameAsset2dEditor-module_dropZone__Z7sYz:hover{border-color:#ffd369;color:#c0c8d8}.GameAsset2dEditor-module_dropZone__Z7sYz.GameAsset2dEditor-module_active__DUroI{background:rgba(255,211,105,.1);border-color:#ffd369}.GameAsset2dEditor-module_emptyState__3wryk{align-items:center;color:#8892a8;display:flex;flex-direction:column;justify-content:center;padding:32px;text-align:center}.GameAsset2dEditor-module_emptyState__3wryk svg{height:48px;margin-bottom:12px;opacity:.5;width:48px}.GameAsset2dEditor-module_emptyStateText__Q5V1a{font-size:12px;margin-bottom:12px}
|
|
1
|
+
.PixelEditor-module_root__3gidG{background:var(--editor-bg-deep);color:var(--gray-200);display:flex;flex-direction:column;font-family:Segoe UI,Consolas,monospace;font-size:12px;height:100%;overflow:hidden;user-select:none}.PixelEditor-module_menuBar__8JFld{align-items:center;background:var(--editor-bg-deeper);border-bottom:1px solid var(--editor-bg-dark);display:flex;flex-shrink:0;gap:0;height:28px;padding:0 4px}.PixelEditor-module_menuBtn__w-GQC{background:none;border:none;border-radius:3px;color:var(--editor-text-light);cursor:pointer;font-size:11px;padding:4px 10px}.PixelEditor-module_menuBtn__w-GQC:hover{background:var(--editor-bg-dark);color:var(--color-white)}.PixelEditor-module_menuSep__pNZsR{background:var(--gray-850);height:16px;margin:0 4px;width:1px}.PixelEditor-module_toolbar__paCGq{background:var(--editor-panel);border-right:1px solid var(--editor-bg-dark);display:flex;flex-direction:column;flex-shrink:0;gap:2px;overflow-y:auto;padding:4px 2px;width:38px}.PixelEditor-module_toolBtn__wD1Kj{align-items:center;background:none;border:1px solid transparent;border-radius:4px;color:var(--editor-text-muted);cursor:pointer;display:flex;font-size:16px;height:32px;justify-content:center;transition:all .1s;width:32px}.PixelEditor-module_toolBtn__wD1Kj:hover{background:var(--editor-bg-dark);color:var(--gray-300)}.PixelEditor-module_toolBtnActive__R51U0{background:var(--editor-bg-mid)!important;border-color:var(--editor-accent)!important;color:var(--color-white)!important}.PixelEditor-module_mainArea__Z0x6l{display:flex;flex:1;min-height:0}.PixelEditor-module_canvasContainer__8z2AY{background:var(--editor-bg-deepest);cursor:crosshair;flex:1;overflow:hidden;position:relative}.PixelEditor-module_canvasContainer__8z2AY canvas{image-rendering:pixelated;position:absolute}.PixelEditor-module_rightPanel__ZjrCh{background:var(--editor-bg-deep);border-left:1px solid var(--editor-bg-dark);display:flex;flex-direction:column;flex-shrink:0;overflow-y:auto;width:220px}.PixelEditor-module_panelSection__3l225{border-bottom:1px solid var(--editor-bg-dark);padding:6px 8px}.PixelEditor-module_panelTitle__vYyeO{align-items:center;color:var(--editor-text-secondary);display:flex;font-size:10px;justify-content:space-between;letter-spacing:.5px;margin-bottom:4px;text-transform:uppercase}.PixelEditor-module_panelTitle__vYyeO button{background:none;border:none;color:var(--editor-text-secondary);cursor:pointer;font-size:14px;line-height:1;padding:0 2px}.PixelEditor-module_panelTitle__vYyeO button:hover{color:var(--gray-500)}.PixelEditor-module_layerItem__J-gtn{align-items:center;border-radius:3px;cursor:pointer;display:flex;font-size:11px;gap:4px;padding:3px 4px}.PixelEditor-module_layerItem__J-gtn:hover{background:hsla(0,0%,100%,.04)}.PixelEditor-module_layerItemActive__yPt29{background:var(--editor-surface)!important;border:1px solid var(--accent-blue-dark)}.PixelEditor-module_layerVis__Uj7n2{align-items:center;cursor:pointer;display:flex;flex-shrink:0;font-size:10px;height:16px;justify-content:center;opacity:.6;width:16px}.PixelEditor-module_layerVis__Uj7n2:hover{opacity:1}.PixelEditor-module_layerName__HovwJ{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.PixelEditor-module_layerOpacity__qmWvu{color:var(--gray-600);font-size:10px;text-align:right;width:36px}.PixelEditor-module_paletteGrid__knY-n{display:grid;gap:2px;grid-template-columns:repeat(8,1fr)}.PixelEditor-module_paletteSwatch__MUbha{aspect-ratio:1;border:1px solid hsla(0,0%,100%,.08);border-radius:2px;cursor:pointer;transition:transform .1s}.PixelEditor-module_paletteSwatch__MUbha:hover{transform:scale(1.15);z-index:1}.PixelEditor-module_paletteSwatchActive__wDR4T{border-color:var(--color-white)!important;box-shadow:0 0 0 1px var(--editor-accent)}.PixelEditor-module_colorPickers__sQlBN{align-items:center;display:flex;gap:6px;margin-top:6px}.PixelEditor-module_colorSample__GN7Rd{border:2px solid hsla(0,0%,100%,.2);border-radius:4px;height:28px;width:28px}.PixelEditor-module_bottomPanel__rviLF{background:var(--editor-bg-deeper);border-top:1px solid var(--editor-bg-dark);display:flex;flex-direction:column;flex-shrink:0;height:80px}.PixelEditor-module_timelineControls__Laroq{align-items:center;border-bottom:1px solid #224;display:flex;font-size:11px;gap:6px;padding:2px 8px}.PixelEditor-module_timelineControls__Laroq button{background:var(--editor-bg-dark);border:none;border-radius:3px;color:var(--gray-500);cursor:pointer;font-size:11px;padding:2px 8px}.PixelEditor-module_timelineControls__Laroq button:hover{background:var(--editor-bg-mid);color:var(--color-white)}.PixelEditor-module_timelineControls__Laroq label{color:var(--gray-700)}.PixelEditor-module_timelineControls__Laroq input[type=number]{background:var(--gray-950);border:1px solid var(--gray-850);border-radius:3px;color:var(--gray-200);font-size:11px;padding:1px 4px;text-align:center;width:40px}.PixelEditor-module_timelineControls__Laroq input[type=checkbox]{accent-color:var(--editor-accent)}.PixelEditor-module_timelineFrames__dw06F{align-items:stretch;display:flex;flex:1;gap:2px;overflow-x:auto;padding:4px 8px}.PixelEditor-module_frameThumb__2E9mG{align-items:center;background:var(--gray-900);border:2px solid transparent;border-radius:4px;cursor:pointer;display:flex;flex-direction:column;justify-content:center;min-width:44px;overflow:hidden;position:relative;width:44px}.PixelEditor-module_frameThumb__2E9mG canvas{height:36px;image-rendering:pixelated;object-fit:contain;width:36px}.PixelEditor-module_frameThumb__2E9mG:hover{border-color:var(--gray-800)}.PixelEditor-module_frameThumbActive__Z0eK4{background:var(--editor-surface);border-color:var(--editor-accent)!important}.PixelEditor-module_frameNum__PoGQC{bottom:1px;color:var(--gray-700);font-size:8px;position:absolute;right:3px}.PixelEditor-module_statusBar__QnphD{align-items:center;background:var(--gray-950);border-top:1px solid var(--gray-900);color:var(--gray-700);display:flex;flex-shrink:0;font-size:10px;gap:12px;height:20px;padding:2px 8px}.PixelEditor-module_dialogOverlay__IgyFy{align-items:center;background:rgba(0,0,0,.6);display:flex;inset:0;justify-content:center;position:absolute;z-index:100}.PixelEditor-module_dialog__OnkAG{background:var(--editor-panel);border:1px solid var(--editor-bg-mid);border-radius:8px;box-shadow:0 8px 32px rgba(0,0,0,.5);min-width:300px;padding:20px}.PixelEditor-module_dialog__OnkAG h3{color:var(--gray-300);font-size:14px;margin:0 0 12px}.PixelEditor-module_dialog__OnkAG label{color:var(--gray-600);display:block;font-size:11px;margin:8px 0 2px}.PixelEditor-module_dialog__OnkAG input,.PixelEditor-module_dialog__OnkAG select{background:var(--gray-950);border:1px solid var(--gray-850);border-radius:4px;color:var(--gray-200);font-size:12px;padding:4px 8px;width:100%}.PixelEditor-module_dialogActions__fOa7a{display:flex;gap:8px;justify-content:flex-end;margin-top:16px}.PixelEditor-module_dialogActions__fOa7a button{border:none;border-radius:4px;cursor:pointer;font-size:12px;padding:4px 16px}.PixelEditor-module_btnPrimary__FYlTy{background:var(--editor-accent);color:var(--color-white)}.PixelEditor-module_btnPrimary__FYlTy:hover{background:#67d}.PixelEditor-module_btnSecondary__qLfyJ{background:var(--gray-850);color:var(--gray-500)}.PixelEditor-module_btnSecondary__qLfyJ:hover{background:var(--gray-800);color:var(--gray-200)}.PixelEditor-module_brushSlider__UxQ38{align-items:center;border-bottom:1px solid var(--editor-bg-dark);display:flex;gap:4px;padding:4px 8px}.PixelEditor-module_brushSlider__UxQ38 label{color:var(--gray-700);font-size:10px}.PixelEditor-module_brushSlider__UxQ38 input[type=range]{accent-color:var(--editor-accent);flex:1;height:4px}.PixelEditor-module_brushSlider__UxQ38 span{color:var(--gray-500);font-size:10px;min-width:16px;text-align:center}.PixelEditor-module_toolSep__YIu-E{background:var(--gray-850);height:1px;margin:4px 2px;width:28px}.PixelEditor-module_toolGroup__xA2lN{display:flex;flex-direction:column;gap:1px;padding:2px 0}.PixelEditor-module_miniBtn__tg5N0{align-items:center;background:hsla(0,0%,100%,.04);border:1px solid transparent;border-radius:3px;color:var(--editor-text-muted);cursor:pointer;display:flex;font-size:10px;height:20px;justify-content:center;transition:all .1s;width:32px}.PixelEditor-module_miniBtn__tg5N0:hover{background:var(--editor-bg-dark);color:var(--gray-300)}.PixelEditor-module_miniBtnActive__gpveu{background:var(--editor-bg-mid)!important;border-color:var(--editor-accent)!important;color:var(--color-white)!important}.PixelEditor-module_colorSwatches__jFuRX{align-items:center;border-top:1px solid var(--gray-850);display:flex;flex-direction:column;gap:4px;margin-top:4px;padding:6px 0}.PixelEditor-module_brushShapes__2bBfl{display:flex;flex-wrap:wrap;gap:2px;padding:2px 0}.PixelEditor-module_pressureToggles__AITuh{display:flex;flex-direction:column;gap:2px;padding:4px 0}.PixelEditor-module_checkLabel__-d-TA{align-items:center;color:var(--gray-550);cursor:pointer;display:flex;font-size:10px;gap:4px}.PixelEditor-module_checkLabel__-d-TA input[type=checkbox]{accent-color:var(--editor-accent);height:12px;width:12px}.PixelEditor-module_hsvPicker__0ERIh{display:flex;flex-direction:column;gap:4px;padding:4px 0}.PixelEditor-module_hsvRow__M3fhN{align-items:center;display:flex;gap:4px}.PixelEditor-module_hsvLabel__O2MkX{color:var(--gray-700);font-size:9px;min-width:16px;text-align:right}.PixelEditor-module_hsvSlider__KKMMJ{accent-color:var(--editor-accent);cursor:pointer;flex:1;height:6px;min-width:0}.PixelEditor-module_hsvVal__MgQ8W{color:var(--gray-500);font-size:9px;min-width:28px;text-align:right}.PixelEditor-module_hsvNumInput__Wn4kG{text-align:center;width:36px}.PixelEditor-module_hsvHexInput__MU5Ms,.PixelEditor-module_hsvNumInput__Wn4kG{background:var(--gray-950);border:1px solid var(--gray-850);border-radius:3px;color:var(--gray-200);font-size:10px;padding:1px 4px}.PixelEditor-module_hsvHexInput__MU5Ms{flex:1}.PixelEditor-module_layerLock__xeWnc{align-items:center;cursor:pointer;display:flex;flex-shrink:0;font-size:10px;height:16px;justify-content:center;opacity:.6;width:16px}.PixelEditor-module_layerLock__xeWnc:hover{opacity:1}.PixelEditor-module_layerNameInput__ZiOKv{background:var(--gray-950);border:1px solid var(--editor-accent);border-radius:2px;color:var(--gray-100);flex:1;font-size:11px;min-width:0;outline:none;padding:0 4px}.PixelEditor-module_layerControls__MrpXo{align-items:center;border-top:1px solid hsla(0,0%,100%,.05);display:flex;gap:4px;margin-top:4px;padding:4px 4px 2px}.PixelEditor-module_blendSelect__QCwns{background:var(--gray-950);border:1px solid var(--gray-850);border-radius:3px;color:var(--gray-300);cursor:pointer;flex:1;font-size:10px;padding:1px 4px}.PixelEditor-module_layerOpSlider__Vw-qs{accent-color:var(--editor-accent);cursor:pointer;height:4px;width:60px}.PixelEditor-module_genPanel__99Md8{background:var(--editor-panel);border:1px solid var(--editor-bg-mid);border-radius:10px;box-shadow:0 12px 48px rgba(0,0,0,.6);display:flex;flex-direction:column;height:600px;max-height:85vh;max-width:95vw;overflow:hidden;width:820px}.PixelEditor-module_genHeader__xN4FZ{align-items:center;border-bottom:1px solid var(--editor-bg-dark);display:flex;flex-shrink:0;justify-content:space-between;padding:10px 16px}.PixelEditor-module_genHeader__xN4FZ h3{color:var(--gray-300);font-size:14px;margin:0}.PixelEditor-module_genTabs__No5Za{background:var(--editor-bg-deeper);border-bottom:1px solid var(--editor-bg-dark);display:flex;flex-shrink:0}.PixelEditor-module_genTabBtn__e2VhB{background:none;border:none;border-bottom:2px solid transparent;color:var(--editor-text-secondary);cursor:pointer;flex:1;font-size:11px;padding:6px 8px;transition:all .15s}.PixelEditor-module_genTabBtn__e2VhB:hover{background:var(--editor-panel);color:var(--gray-500)}.PixelEditor-module_genTabBtnActive__Rt3jQ{background:var(--editor-panel)!important;border-bottom-color:var(--editor-accent)!important;color:var(--color-white)!important}.PixelEditor-module_genBody__MuiQy{display:flex;flex:1;min-height:0;overflow:hidden}.PixelEditor-module_genLeft__JdEw6{border-right:1px solid var(--editor-bg-dark);display:flex;flex-direction:column;flex-shrink:0;overflow-y:auto;width:200px}.PixelEditor-module_genCenter__c5X0S{align-items:center;display:flex;flex:1;flex-direction:column;gap:8px;overflow-y:auto;padding:8px}.PixelEditor-module_genRight__qFz11{border-left:1px solid var(--editor-bg-dark);display:flex;flex-direction:column;flex-shrink:0;overflow-y:auto;width:200px}.PixelEditor-module_genPreviewWrap__360F-{align-items:center;background:var(--editor-bg-deepest);border:1px solid var(--editor-bg-dark);border-radius:6px;display:flex;flex:1;justify-content:center;min-height:120px;overflow:hidden;width:100%}.PixelEditor-module_genPreviewCanvas__75Lw2{image-rendering:pixelated;max-height:100%;max-width:100%;min-height:64px;min-width:64px;object-fit:contain}.PixelEditor-module_genDirGrid__xjEp7{display:flex;flex-wrap:wrap;gap:2px;justify-content:center}.PixelEditor-module_genRow__awCw9{align-items:center;display:flex;gap:4px;width:100%}.PixelEditor-module_genPresetGrid__f9XK6{display:flex;flex-wrap:wrap;gap:2px}.PixelEditor-module_genPresetBtn__5C2We{background:hsla(0,0%,100%,.04);border:1px solid transparent;border-radius:3px;color:var(--editor-text-muted);cursor:pointer;font-size:9px;padding:3px 6px;transition:all .1s}.PixelEditor-module_genPresetBtn__5C2We:hover{background:var(--editor-bg-dark);color:var(--gray-300)}.PixelEditor-module_genPresetBtnActive__WAGew{background:var(--editor-bg-mid)!important;border-color:var(--editor-accent)!important;color:var(--color-white)!important}.PixelEditor-module_genPartGrid__l17oc{display:flex;flex-wrap:wrap;gap:2px}.PixelEditor-module_genColorSwatches__acI6q{display:flex;gap:2px;margin-top:2px}.PixelEditor-module_genColorSwatch__JE8BO{border:1px solid hsla(0,0%,100%,.1);border-radius:2px;height:16px;width:16px}.PixelEditor-module_genAssemblyItem__zNL2P{align-items:center;border-radius:3px;display:flex;font-size:10px;gap:4px;padding:2px 4px}.PixelEditor-module_genAssemblyItem__zNL2P:hover{background:hsla(0,0%,100%,.04)}.PixelEditor-module_genAssemblyName__GU-kr{color:var(--gray-400);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.PixelEditor-module_genFooter__WkyJp{border-top:1px solid var(--editor-bg-dark);display:flex;flex-shrink:0;gap:8px;justify-content:flex-end;padding:10px 16px}.PixelEditor-module_btnIcon__O59l9{background:none;border:none;color:var(--gray-600);cursor:pointer;font-size:14px;line-height:1;padding:2px}.PixelEditor-module_btnIcon__O59l9:hover{color:var(--gray-300)}.PixelEditor-module_propSelect__4P0Qi{flex:1}.PixelEditor-module_propInput__Q-kr2,.PixelEditor-module_propSelect__4P0Qi{background:var(--gray-950);border:1px solid var(--gray-850);border-radius:3px;color:var(--gray-200);font-size:11px;min-width:0;padding:2px 4px}.VectorEditor-module_root__rtRWo{background:var(--editor-bg-deep);color:var(--gray-200);display:flex;flex-direction:column;font-family:Segoe UI,Consolas,monospace;font-size:12px;height:100%;overflow:hidden;user-select:none}.VectorEditor-module_menuBar__o25XM{align-items:center;background:var(--editor-bg-deeper);border-bottom:1px solid var(--editor-bg-dark);display:flex;flex-shrink:0;gap:0;height:28px;padding:0 4px}.VectorEditor-module_menuBtn__aP4vp{background:none;border:none;border-radius:3px;color:var(--editor-text-light);cursor:pointer;font-size:11px;padding:4px 10px}.VectorEditor-module_menuBtn__aP4vp:hover{background:var(--editor-bg-dark);color:var(--color-white)}.VectorEditor-module_menuSep__3-kTv{background:var(--gray-850);height:16px;margin:0 4px;width:1px}.VectorEditor-module_menuLabel__Bsm0e{align-items:center;color:var(--gray-600);cursor:pointer;display:flex;font-size:10px;gap:2px;padding:0 4px}.VectorEditor-module_toolbar__fakYL{background:var(--editor-panel);border-right:1px solid var(--editor-bg-dark);display:flex;flex-direction:column;flex-shrink:0;gap:2px;padding:4px 2px;width:38px}.VectorEditor-module_toolBtn__Zh7D3{align-items:center;background:none;border:1px solid transparent;border-radius:4px;color:var(--editor-text-muted);cursor:pointer;display:flex;font-size:16px;height:32px;justify-content:center;transition:all .1s;width:32px}.VectorEditor-module_toolBtn__Zh7D3:hover{background:var(--editor-bg-dark);color:var(--gray-300)}.VectorEditor-module_toolBtnActive__0xZlr{background:var(--editor-bg-mid)!important;border-color:var(--editor-accent)!important;color:var(--color-white)!important}.VectorEditor-module_mainArea__3o89F{display:flex;flex:1;min-height:0}.VectorEditor-module_canvasContainer__hOUAx{background:var(--editor-bg-deepest);flex:1;overflow:hidden;position:relative}.VectorEditor-module_canvasContainer__hOUAx svg{height:100%;inset:0;position:absolute;width:100%}.VectorEditor-module_rightPanel__3hzcS{background:var(--editor-bg-deep);border-left:1px solid var(--editor-bg-dark);display:flex;flex-direction:column;flex-shrink:0;overflow-y:auto;width:220px}.VectorEditor-module_panelSection__uteDQ{border-bottom:1px solid var(--editor-bg-dark);padding:6px 8px}.VectorEditor-module_panelTitle__WBUxr{align-items:center;color:var(--editor-text-secondary);display:flex;font-size:10px;justify-content:space-between;letter-spacing:.5px;margin-bottom:4px;text-transform:uppercase}.VectorEditor-module_panelTitle__WBUxr button{background:none;border:none;color:var(--editor-text-secondary);cursor:pointer;font-size:14px;line-height:1;padding:0 2px}.VectorEditor-module_panelTitle__WBUxr button:hover{color:var(--gray-500)}.VectorEditor-module_shapeItem__bu2E2{align-items:center;border-radius:3px;cursor:pointer;display:flex;font-size:11px;gap:6px;padding:3px 4px}.VectorEditor-module_shapeItem__bu2E2:hover{background:hsla(0,0%,100%,.04)}.VectorEditor-module_shapeItemActive__E2lK7{background:var(--editor-surface)!important;border:1px solid var(--accent-blue-dark)}.VectorEditor-module_shapeIcon__M4j6X{flex-shrink:0;font-size:14px;opacity:.7}.VectorEditor-module_shapeName__2QctO{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.VectorEditor-module_propRow__Alc4S{align-items:center;display:flex;gap:6px;margin-bottom:4px}.VectorEditor-module_propLabel__J0lxK{color:var(--gray-600);font-size:10px;min-width:40px}.VectorEditor-module_propInput__3my2d{background:var(--gray-950);border:1px solid var(--gray-850);border-radius:3px;color:var(--gray-200);flex:1;font-size:11px;padding:2px 4px}.VectorEditor-module_propColorSwatch__JL97Z{border:1px solid hsla(0,0%,100%,.15);border-radius:3px;cursor:pointer;height:24px;position:relative;width:24px}.VectorEditor-module_propColorSwatch__JL97Z input{cursor:pointer;height:100%;inset:0;opacity:0;position:absolute;width:100%}.VectorEditor-module_statusBar__jMwan{align-items:center;background:var(--gray-950);border-top:1px solid var(--gray-900);color:var(--gray-700);display:flex;flex-shrink:0;font-size:10px;gap:12px;height:20px;padding:2px 8px}.VectorEditor-module_dialogOverlay__NLiCg{align-items:center;background:rgba(0,0,0,.6);display:flex;inset:0;justify-content:center;position:absolute;z-index:100}.VectorEditor-module_dialog__NDNK2{background:var(--editor-panel);border:1px solid var(--editor-bg-mid);border-radius:8px;box-shadow:0 8px 32px rgba(0,0,0,.5);max-width:500px;min-width:300px;padding:20px}.VectorEditor-module_dialog__NDNK2 h3{color:var(--gray-300);font-size:14px;margin:0 0 12px}.VectorEditor-module_dialog__NDNK2 label{color:var(--gray-600);display:block;font-size:11px;margin:8px 0 2px}.VectorEditor-module_dialog__NDNK2 input,.VectorEditor-module_dialog__NDNK2 select,.VectorEditor-module_dialog__NDNK2 textarea{background:var(--gray-950);border:1px solid var(--gray-850);border-radius:4px;color:var(--gray-200);font-size:12px;padding:4px 8px;width:100%}.VectorEditor-module_dialog__NDNK2 textarea{font-family:monospace;min-height:120px;resize:vertical}.VectorEditor-module_dialogActions__0Sy4X{display:flex;gap:8px;justify-content:flex-end;margin-top:16px}.VectorEditor-module_dialogActions__0Sy4X button{border:none;border-radius:4px;cursor:pointer;font-size:12px;padding:4px 16px}.VectorEditor-module_btnPrimary__f9AaS{background:var(--editor-accent);color:var(--color-white)}.VectorEditor-module_btnPrimary__f9AaS:hover{background:#67d}.VectorEditor-module_btnSecondary__wDps2{background:var(--gray-850);color:var(--gray-500)}.VectorEditor-module_btnSecondary__wDps2:hover{background:var(--gray-800);color:var(--gray-200)}.VectorEditor-module_handleGroup__sMkQj circle{fill:var(--editor-accent);stroke:var(--color-white);stroke-width:1;cursor:pointer}.VectorEditor-module_handleGroup__sMkQj circle:hover{fill:#78e}.PhotoEditor-module_wrapper__jrHYj{background:#1a1a1e;border-radius:12px;color:#eee;display:flex;flex-direction:column;font-family:Segoe UI,sans-serif;font-size:13px;max-height:85vh;overflow:hidden;width:100%}.PhotoEditor-module_loadingWrap__QUTon{align-items:center;color:#aaa;display:flex;justify-content:center;min-height:400px;width:100%}.PhotoEditor-module_mainContent__TCVxf{display:flex;flex:1;min-height:0;overflow:hidden}.PhotoEditor-module_toolbar__RY-Ty{align-items:center;background:#222226;border-bottom:1px solid #333;display:flex;justify-content:space-between;padding:8px 14px}.PhotoEditor-module_toolbarGroup__PXw0-{display:flex;gap:6.5px}.PhotoEditor-module_toolbarDivider__o3kFV{background:#444;margin:0 4px;width:1px}.PhotoEditor-module_toolbarTitle__P1o18{font-size:14px;font-weight:700}.PhotoEditor-module_leftPanel__DnHLU{background:#222226;border-right:1px solid #333;display:flex;flex-direction:column;min-width:280px;overflow:hidden;width:280px}.PhotoEditor-module_tabBar__DZ3MG{border-bottom:1px solid #333;display:flex;flex-wrap:wrap}.PhotoEditor-module_tabButton__BLi97{align-items:center;background:transparent;border:none;border-bottom:2px solid transparent;color:#888;cursor:pointer;display:flex;flex:1 0 auto;flex-direction:column;font-size:10px;font-weight:600;gap:1px;min-width:34px;padding:8px 0;transition:all .15s}.PhotoEditor-module_tabButtonActive__KlQG0{background:#2a2a30}.PhotoEditor-module_tabIcon__-Mq19{font-size:14px}.PhotoEditor-module_panelContent__l5i5t{flex:1;overflow-y:auto;padding:10px 12px}.PhotoEditor-module_sectionTitle__tMvCm{font-size:12px;font-weight:600;margin-bottom:6px}.PhotoEditor-module_sectionTitleMb8__PQ-lV{margin-bottom:8px}.PhotoEditor-module_sectionInfo__bWxW5{color:#aaa;font-size:11px}.PhotoEditor-module_sectionInfoMb__Hk6V-{margin-bottom:10px}.PhotoEditor-module_pillRow__DGJUb{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:10px}.PhotoEditor-module_pillRowMb8__AQrth{margin-bottom:8px}.PhotoEditor-module_pillRowGap3__Y46Vu{display:flex;flex-wrap:wrap;gap:3px;margin-bottom:8px}.PhotoEditor-module_pill__wTFac{background:transparent;border:1px solid #444;border-radius:12px;color:#aaa;cursor:pointer;font-size:11px;font-weight:600;padding:3px 10px}.PhotoEditor-module_pillActive__AfdZR{color:#fff}.PhotoEditor-module_pillCrop__Nsisp{border-radius:6px;padding:4px 12px}.PhotoEditor-module_pillCropActive__p6csO{color:#fff}.PhotoEditor-module_pillEmoji__I42DJ{border-radius:10px;padding:2px 8px}.PhotoEditor-module_pillEmojiActive__0-EM7{color:#fff}.PhotoEditor-module_filterGrid__-29PS{display:grid;gap:6px;grid-template-columns:repeat(3,1fr)}.PhotoEditor-module_emojiGrid__whqqK{display:grid;gap:2px;grid-template-columns:repeat(6,1fr);max-height:260px;overflow-y:auto}.PhotoEditor-module_shapeGrid__TawIy{margin-bottom:16px}.PhotoEditor-module_frameGrid__R09dd,.PhotoEditor-module_shapeGrid__TawIy{display:grid;gap:4px;grid-template-columns:repeat(5,1fr)}.PhotoEditor-module_sliderRow__jsWDQ{align-items:center;display:flex;gap:6px;margin-bottom:8px}.PhotoEditor-module_sliderLabel__zOZ49{color:#aaa;font-size:11px}.PhotoEditor-module_sliderLabelSelf__EwYKU{align-self:center;margin-right:4px}.PhotoEditor-module_sliderValue__qFuTw{font-size:11px;font-weight:600;min-width:28px}.PhotoEditor-module_sliderValueSm__U7FrJ{font-size:10px;min-width:28px}.PhotoEditor-module_adjustColumn__y---T{display:flex;flex-direction:column;gap:8px}.PhotoEditor-module_adjustHeader__6s9zV{display:flex;font-size:11px;justify-content:space-between;margin-bottom:2px}.PhotoEditor-module_adjustIcon__d56rY{text-align:center;width:14px}.PhotoEditor-module_adjustValue__aUUmg{cursor:pointer;font-weight:600;min-width:30px;text-align:right}.PhotoEditor-module_intensitySection__dhe5h{margin-top:12px;padding:8px 0}.PhotoEditor-module_intensityHeader__-KKu6{display:flex;font-size:11px;justify-content:space-between;margin-bottom:4px}.PhotoEditor-module_colorInput__xkF1h{border:none;cursor:pointer;height:28px;padding:0;width:28px}.PhotoEditor-module_colorInputLg__W2KrK{border:none;cursor:pointer;height:30px;padding:0;width:32px}.PhotoEditor-module_colorInputDraw__KYcdG{border:none;cursor:pointer;height:28px;padding:0;width:32px}.PhotoEditor-module_overlayToolbar__hfspp{border-bottom:1px solid #333;display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px;padding:6px 0}.PhotoEditor-module_overlayToolbarLabel__mc4pU{align-self:center;color:#aaa;font-size:11px;margin-right:4px}.PhotoEditor-module_overlayToolbarBtn__AdTmZ{font-size:11px;padding:2px 6px}.PhotoEditor-module_overlaySection__IIl4r{border-top:1px solid #333;margin-top:12px;padding-top:8px}.PhotoEditor-module_overlaySectionTitle__FRx3e{color:#aaa;font-size:11px;font-weight:600;margin-bottom:4px}.PhotoEditor-module_overlayItem__DGUCN{align-items:center;background:transparent;border-radius:4px;color:#ccc;cursor:pointer;display:flex;font-size:11px;gap:6px;margin-bottom:2px;padding:3px 6px}.PhotoEditor-module_overlayIcon__G0pFk{text-align:center;width:18px}.PhotoEditor-module_overlayName__JVh64{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.PhotoEditor-module_overlayDeleteBtn__Ontxv{background:none;border:none;color:#f55;cursor:pointer;font-size:11px;padding:0}.PhotoEditor-module_emojiBtn__jxG9m{background:transparent;border:none;border-radius:6px;cursor:pointer;font-size:22px;line-height:1;padding:4px 0}.PhotoEditor-module_shapeBtn__xZdSV{font-size:20px}.PhotoEditor-module_frameBtn__coMkZ,.PhotoEditor-module_shapeBtn__xZdSV{background:transparent;border:1px solid #444;border-radius:6px;color:#eee;cursor:pointer;line-height:1;padding:6px 0}.PhotoEditor-module_frameBtn__coMkZ{font-size:18px}.PhotoEditor-module_removeFrameBtn__oCuua{background:transparent;border:1px solid #444;border-radius:6px;color:#f55;cursor:pointer;font-size:14px;padding:6px 0}.PhotoEditor-module_textFormatBtn__7Z9RJ{min-width:32px}.PhotoEditor-module_textFormatBtnSm__3ptcG{min-width:28px}.PhotoEditor-module_drawActionBtn__teYz4{flex:1}.PhotoEditor-module_textArea__sBGlB{background:#2a2a30;border:1px solid #444;border-radius:6px;color:#eee;font-size:13px;margin-bottom:8px;resize:none}.PhotoEditor-module_textAreaSm__6xZnY{font-size:12px;margin-bottom:0}.PhotoEditor-module_textBtnRow__AcEnd{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px}.PhotoEditor-module_textGapRow__Dq2uz{display:flex;gap:4px;margin-top:6px}.PhotoEditor-module_editSelectedSection__bgNEh{border-top:1px solid #333;margin-top:12px;padding-top:8px}.PhotoEditor-module_editSelectedLabel__u2rmS{color:#aaa;font-size:11px;margin-bottom:4px}.PhotoEditor-module_shapeColorRow__ip5--{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px}.PhotoEditor-module_shapeColorLabel__nVcbU{align-self:center;color:#aaa;font-size:11px;margin-right:2px}.PhotoEditor-module_shapeColorLabelMl__KiM2d{margin-left:4px}.PhotoEditor-module_shapeFillToggle__BXJ8C{font-size:10px;padding:2px 6px}.PhotoEditor-module_frameColorRow__KRAHz{display:flex;gap:4px;margin-bottom:8px}.PhotoEditor-module_frameThicknessWrap__lXCoC{align-items:center;display:flex;flex:1;gap:4px}.PhotoEditor-module_frameThicknessValue__SAEuc{font-size:10px}.PhotoEditor-module_drawPreview__WPbiv{display:flex;justify-content:center;margin-bottom:12px}.PhotoEditor-module_drawActionRow__CUSWS{display:flex;gap:4px}.PhotoEditor-module_quickColorRow__DTy5E{align-items:center;display:flex;gap:6px;margin-bottom:8px}.PhotoEditor-module_quickColorSwatch__ZjgoA{border:1px solid #555;border-radius:3px;cursor:pointer;height:18px;width:18px}.PhotoEditor-module_transformRow__LKRjS{display:flex;gap:6px;margin-bottom:16px}.PhotoEditor-module_transformZoomRow__h2NlB{align-items:center;display:flex;gap:8px}.PhotoEditor-module_transformZoomValue__LXa51{font-size:11px;font-weight:600;min-width:40px}.PhotoEditor-module_transformInfo__zXP9l{background:#2a2a30;border-radius:8px;color:#aaa;font-size:11px;margin-top:16px;padding:10px}.PhotoEditor-module_canvasViewport__OMBIL{align-items:center;background:#111115;display:flex;flex:1;justify-content:center;overflow:auto;padding:20px;position:relative}.PhotoEditor-module_zoomWrap__JjfiJ{max-height:100%;max-width:100%;position:relative;transform-origin:center center;transition:transform .15s ease}.PhotoEditor-module_compareWrap__-J5ku{cursor:ew-resize;display:inline-block;position:relative}.PhotoEditor-module_canvasOriginal__Apf91{max-width:100%}.PhotoEditor-module_canvasEdited__Eroz7,.PhotoEditor-module_canvasOriginal__Apf91{display:block;max-height:60vh;object-fit:contain}.PhotoEditor-module_compareClip__5qG2I{bottom:0;left:0;overflow:hidden;position:absolute;top:0}.PhotoEditor-module_compareSlider__OIIIK{bottom:0;position:absolute;top:0;transform:translateX(-50%);width:3px}.PhotoEditor-module_compareSliderKnob__VohI9{align-items:center;border-radius:50%;box-shadow:0 2px 8px rgba(0,0,0,.4);display:flex;height:28px;justify-content:center;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);width:28px}.PhotoEditor-module_compareSliderIcon__pXcct{color:#fff;font-size:12px}.PhotoEditor-module_compareLabelOriginal__GaBoj{background:rgba(0,0,0,.6);left:8px}.PhotoEditor-module_compareLabelEdited__Fr836,.PhotoEditor-module_compareLabelOriginal__GaBoj{border-radius:4px;color:#fff;font-size:11px;font-weight:600;padding:2px 8px;position:absolute;top:8px}.PhotoEditor-module_compareLabelEdited__Fr836{right:8px}.PhotoEditor-module_regularWrap__8umPV{display:inline-block;position:relative}.PhotoEditor-module_canvasRegular__wxapL{border-radius:6px;box-shadow:0 4px 20px rgba(0,0,0,.4);display:block;max-height:60vh;max-width:100%;object-fit:contain}.PhotoEditor-module_cropOverlay__MJk1Y{inset:0;pointer-events:none;position:absolute;z-index:2}.PhotoEditor-module_cropDarkBg__m3axV{background:rgba(0,0,0,.55);inset:0;position:absolute}.PhotoEditor-module_cropGridContainer__NfHdT{inset:0;position:absolute}.PhotoEditor-module_cropSizeLabel__fV2mF{background:rgba(0,0,0,.75);border-radius:3px;bottom:-24px;color:#fff;font-size:10px;left:50%;padding:2px 8px;position:absolute;transform:translateX(-50%);white-space:nowrap}.PhotoEditor-module_cropInfo__Z1SCE{color:#aaa;font-size:11px;margin-bottom:10px}.PhotoEditor-module_cropAspectLabel__dieL-{font-size:12px;font-weight:600;margin-bottom:6px}.PhotoEditor-module_cropAspectRow__scRj3{display:flex;flex-wrap:wrap;gap:4px}.PhotoEditor-module_accentBtn__tgaEx{color:#fff;font-weight:600;width:100%}.GameAsset2dEditor-module_root__WVJBM{background:#1a1a2e;color:#e0e0e0;display:flex;flex-direction:column;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:13px;height:100%;min-height:600px;user-select:none}.GameAsset2dEditor-module_menuBar__WaEaU{align-items:center;background:#16213e;border-bottom:1px solid #0f3460;display:flex;gap:8px;padding:6px 12px}.GameAsset2dEditor-module_menuBar__WaEaU h3{color:#ffd369;font-size:14px;font-weight:600;margin:0}.GameAsset2dEditor-module_menuGroup__EOreB{display:flex;gap:2px}.GameAsset2dEditor-module_menuBtn__JYWXn{align-items:center;background:transparent;border:none;border-radius:4px;color:#b0b0b0;cursor:pointer;display:flex;font-size:12px;gap:4px;padding:4px 8px;transition:all .15s}.GameAsset2dEditor-module_menuBtn__JYWXn:hover{background:hsla(0,0%,100%,.1);color:#fff}.GameAsset2dEditor-module_menuBtn__JYWXn:disabled{cursor:not-allowed;opacity:.4}.GameAsset2dEditor-module_spacer__fPVeq{flex:1}.GameAsset2dEditor-module_modeTabs__iKh7C{background:#1f2940;border-bottom:1px solid #0f3460;display:flex;gap:2px;padding:4px 12px}.GameAsset2dEditor-module_modeTab__C12zt{background:transparent;border:none;border-radius:4px 4px 0 0;color:#8892a8;cursor:pointer;font-size:12px;font-weight:500;padding:6px 16px;transition:all .15s}.GameAsset2dEditor-module_modeTab__C12zt:hover{background:hsla(0,0%,100%,.05);color:#c0c8d8}.GameAsset2dEditor-module_modeTab__C12zt.GameAsset2dEditor-module_active__DUroI{background:#1a1a2e;color:#ffd369}.GameAsset2dEditor-module_mainArea__jwDUa{display:flex;flex:1;overflow:hidden}.GameAsset2dEditor-module_leftPanel__xxAg5{background:#16213e;border-right:1px solid #0f3460;display:flex;flex-direction:column;overflow:hidden;width:220px}.GameAsset2dEditor-module_centerArea__xr-Hn{display:flex;flex:1;flex-direction:column;overflow:hidden}.GameAsset2dEditor-module_rightPanel__YoNuc{background:#16213e;border-left:1px solid #0f3460;display:flex;flex-direction:column;overflow:hidden;width:260px}.GameAsset2dEditor-module_toolbar__hEC9S{align-items:center;background:#1f2940;border-bottom:1px solid #0f3460;display:flex;gap:8px;padding:6px 12px}.GameAsset2dEditor-module_toolGroup__Zbn47{background:rgba(0,0,0,.2);border-radius:4px;display:flex;gap:2px;padding:2px}.GameAsset2dEditor-module_toolBtn__5U7Rw{align-items:center;background:transparent;border:none;border-radius:3px;color:#8892a8;cursor:pointer;display:flex;font-size:14px;height:28px;justify-content:center;transition:all .15s;width:28px}.GameAsset2dEditor-module_toolBtn__5U7Rw:hover{background:hsla(0,0%,100%,.1);color:#fff}.GameAsset2dEditor-module_toolBtn__5U7Rw.GameAsset2dEditor-module_active__DUroI{background:#0f3460;color:#ffd369}.GameAsset2dEditor-module_toolBtn__5U7Rw:disabled{cursor:not-allowed;opacity:.3}.GameAsset2dEditor-module_viewport__vEKEv{background:#0a0a14;flex:1;overflow:hidden;position:relative}.GameAsset2dEditor-module_viewportCanvas__FJ5qA{image-rendering:pixelated;image-rendering:crisp-edges;left:50%;position:absolute;top:50%}.GameAsset2dEditor-module_gridOverlay__K8B97{bottom:0;left:0;pointer-events:none;position:absolute;right:0;top:0}.GameAsset2dEditor-module_panelHeader__xm2As{align-items:center;background:#0f3460;color:#8892a8;display:flex;font-size:11px;font-weight:600;justify-content:space-between;letter-spacing:.5px;padding:8px 12px;text-transform:uppercase}.GameAsset2dEditor-module_panelContent__dvOGq{flex:1;overflow-y:auto;padding:8px}.GameAsset2dEditor-module_panelSection__RQQDr{margin-bottom:16px}.GameAsset2dEditor-module_panelLabel__Ks-Wa{color:#8892a8;display:block;font-size:11px;letter-spacing:.5px;margin-bottom:6px;text-transform:uppercase}.GameAsset2dEditor-module_panelInput__cxNiG{background:#0a0a14;border:1px solid #2a3a5e;border-radius:4px;color:#e0e0e0;font-size:12px;padding:6px 8px;width:100%}.GameAsset2dEditor-module_panelInput__cxNiG:focus{border-color:#ffd369;outline:none}.GameAsset2dEditor-module_tilePalette__OpzmV{display:grid;gap:4px;grid-template-columns:repeat(auto-fill,minmax(40px,1fr));padding:8px}.GameAsset2dEditor-module_tileItem__uWNS9{aspect-ratio:1;background:#0a0a14;border:2px solid transparent;border-radius:4px;cursor:pointer;overflow:hidden;transition:all .15s}.GameAsset2dEditor-module_tileItem__uWNS9:hover{border-color:#4a5a7e}.GameAsset2dEditor-module_tileItem__uWNS9.GameAsset2dEditor-module_selected__216IN{border-color:#ffd369}.GameAsset2dEditor-module_tileItem__uWNS9 img{height:100%;image-rendering:pixelated;object-fit:contain;width:100%}.GameAsset2dEditor-module_layersList__anFaG{display:flex;flex-direction:column;gap:2px}.GameAsset2dEditor-module_layerItem__XSGlu{align-items:center;background:#1f2940;border-radius:4px;cursor:pointer;display:flex;gap:8px;padding:6px 8px;transition:all .15s}.GameAsset2dEditor-module_layerItem__XSGlu:hover{background:#2a3a5e}.GameAsset2dEditor-module_layerItem__XSGlu.GameAsset2dEditor-module_selected__216IN{background:#0f3460;border-left:3px solid #ffd369}.GameAsset2dEditor-module_layerVisibility__RpHjV{align-items:center;background:transparent;border:none;border-radius:3px;color:#8892a8;cursor:pointer;display:flex;height:20px;justify-content:center;width:20px}.GameAsset2dEditor-module_layerVisibility__RpHjV:hover{background:hsla(0,0%,100%,.1)}.GameAsset2dEditor-module_layerVisibility__RpHjV.GameAsset2dEditor-module_hidden__mukOG{opacity:.4}.GameAsset2dEditor-module_layerName__WBxq5{color:#c0c8d8;flex:1;font-size:12px}.GameAsset2dEditor-module_layerOpacity__FpzL-{color:#8892a8;font-size:10px;text-align:right;width:40px}.GameAsset2dEditor-module_framesList__vg1oO{display:grid;gap:8px;grid-template-columns:repeat(auto-fill,minmax(60px,1fr));padding:8px}.GameAsset2dEditor-module_frameItem__fkEfb{aspect-ratio:1;background:#0a0a14;border:2px solid transparent;border-radius:4px;cursor:pointer;overflow:hidden;position:relative;transition:all .15s}.GameAsset2dEditor-module_frameItem__fkEfb:hover{border-color:#4a5a7e}.GameAsset2dEditor-module_frameItem__fkEfb.GameAsset2dEditor-module_selected__216IN{border-color:#ffd369}.GameAsset2dEditor-module_frameItem__fkEfb canvas{height:100%;image-rendering:pixelated;object-fit:contain;width:100%}.GameAsset2dEditor-module_frameLabel__5IGW8{background:rgba(0,0,0,.7);bottom:0;color:#b0b0b0;font-size:9px;left:0;padding:2px 4px;position:absolute;right:0;text-align:center}.GameAsset2dEditor-module_timeline__dPJk6{background:#16213e;border-top:1px solid #0f3460;padding:8px}.GameAsset2dEditor-module_timelineTrack__mr20w{background:#0a0a14;border-radius:4px;display:flex;gap:4px;overflow-x:auto;padding:4px}.GameAsset2dEditor-module_timelineFrame__AQyGe{background:#1f2940;border:2px solid transparent;border-radius:4px;cursor:pointer;flex-shrink:0;height:48px;overflow:hidden;width:48px}.GameAsset2dEditor-module_timelineFrame__AQyGe:hover{border-color:#4a5a7e}.GameAsset2dEditor-module_timelineFrame__AQyGe.GameAsset2dEditor-module_current__3sAfL{border-color:#ffd369}.GameAsset2dEditor-module_stateGraph__qAWlU{background:#0a0a14;flex:1;overflow:hidden;position:relative}.GameAsset2dEditor-module_stateNode__W9Z-g{background:#1f2940;border:2px solid #2a3a5e;border-radius:8px;cursor:move;min-width:120px;padding:8px 12px;position:absolute;transition:border-color .15s}.GameAsset2dEditor-module_stateNode__W9Z-g:hover{border-color:#4a5a7e}.GameAsset2dEditor-module_stateNode__W9Z-g.GameAsset2dEditor-module_selected__216IN{border-color:#ffd369}.GameAsset2dEditor-module_stateNode__W9Z-g.GameAsset2dEditor-module_entry__cmA9n{border-color:#4ade80}.GameAsset2dEditor-module_stateNodeName__TK5vs{color:#e0e0e0;font-size:12px;font-weight:500;text-align:center}.GameAsset2dEditor-module_stateNodeAnim__VGwnV{color:#8892a8;font-size:10px;margin-top:4px;text-align:center}.GameAsset2dEditor-module_transition__FBbno{stroke:#4a5a7e;stroke-width:2;fill:none;marker-end:url(#arrowhead)}.GameAsset2dEditor-module_transition__FBbno:hover{stroke:#ffd369}.GameAsset2dEditor-module_effectsList__vHq4I{display:flex;flex-direction:column;gap:8px}.GameAsset2dEditor-module_effectItem__6-1li{background:#1f2940;border-radius:6px;overflow:hidden}.GameAsset2dEditor-module_effectHeader__cgVN-{align-items:center;cursor:pointer;display:flex;gap:8px;padding:8px}.GameAsset2dEditor-module_effectToggle__lKE36{background:#0a0a14;border:1px solid #2a3a5e;border-radius:3px;cursor:pointer;height:18px;width:18px}.GameAsset2dEditor-module_effectToggle__lKE36.GameAsset2dEditor-module_enabled__wgDzp{background:#ffd369;border-color:#ffd369}.GameAsset2dEditor-module_effectName__NQCWj{color:#c0c8d8;flex:1;font-size:12px}.GameAsset2dEditor-module_effectRemove__TSSdI{align-items:center;background:transparent;border:none;border-radius:3px;color:#8892a8;cursor:pointer;display:flex;height:20px;justify-content:center;width:20px}.GameAsset2dEditor-module_effectRemove__TSSdI:hover{background:#ef4444;color:#fff}.GameAsset2dEditor-module_effectParams__UqTBd{background:rgba(0,0,0,.2);padding:8px}.GameAsset2dEditor-module_effectParam__hEsVY{align-items:center;display:flex;gap:8px;margin-bottom:8px}.GameAsset2dEditor-module_effectParam__hEsVY:last-child{margin-bottom:0}.GameAsset2dEditor-module_effectParamLabel__u0Qoc{color:#8892a8;flex:0 0 80px;font-size:11px}.GameAsset2dEditor-module_effectParamInput__aqxdv{background:#0a0a14;border:1px solid #2a3a5e;border-radius:3px;color:#e0e0e0;flex:1;font-size:11px;height:24px;padding:0 8px}.GameAsset2dEditor-module_statusBar__eOrNe{align-items:center;background:#0f3460;color:#8892a8;display:flex;font-size:11px;gap:16px;padding:4px 12px}.GameAsset2dEditor-module_statusItem__kKLHF{align-items:center;display:flex;gap:4px}.GameAsset2dEditor-module_zoomControl__4YD9G{align-items:center;display:flex;gap:4px;margin-left:auto}.GameAsset2dEditor-module_zoomBtn__hxYik{align-items:center;background:transparent;border:none;border-radius:3px;color:#8892a8;cursor:pointer;display:flex;height:20px;justify-content:center;width:20px}.GameAsset2dEditor-module_zoomBtn__hxYik:hover{background:hsla(0,0%,100%,.1);color:#fff}.GameAsset2dEditor-module_dialogOverlay__dZYwO{align-items:center;background:rgba(0,0,0,.6);bottom:0;display:flex;justify-content:center;left:0;position:fixed;right:0;top:0;z-index:1000}.GameAsset2dEditor-module_dialog__mfLFL{background:#16213e;border-radius:8px;box-shadow:0 8px 32px rgba(0,0,0,.4);max-width:500px;min-width:300px;padding:24px}.GameAsset2dEditor-module_dialog__mfLFL h3{color:#ffd369;font-size:16px;margin:0 0 16px}.GameAsset2dEditor-module_dialogActions__vhDXe{display:flex;gap:8px;justify-content:flex-end;margin-top:20px}.GameAsset2dEditor-module_btnPrimary__Gzc25{background:#ffd369;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;font-size:12px;font-weight:600;padding:8px 16px;transition:all .15s}.GameAsset2dEditor-module_btnPrimary__Gzc25:hover{background:#ffe599}.GameAsset2dEditor-module_btnSecondary__G5nK5{background:transparent;border:1px solid #4a5a7e;border-radius:4px;color:#c0c8d8;cursor:pointer;font-size:12px;padding:8px 16px;transition:all .15s}.GameAsset2dEditor-module_btnSecondary__G5nK5:hover{background:hsla(0,0%,100%,.05);border-color:#6a7a9e}.GameAsset2dEditor-module_panelContent__dvOGq::-webkit-scrollbar{width:6px}.GameAsset2dEditor-module_panelContent__dvOGq::-webkit-scrollbar-track{background:#0a0a14}.GameAsset2dEditor-module_panelContent__dvOGq::-webkit-scrollbar-thumb{background:#2a3a5e;border-radius:3px}.GameAsset2dEditor-module_panelContent__dvOGq::-webkit-scrollbar-thumb:hover{background:#4a5a7e}.GameAsset2dEditor-module_dropZone__Z7sYz{border:2px dashed #4a5a7e;border-radius:8px;color:#8892a8;cursor:pointer;padding:24px;text-align:center;transition:all .15s}.GameAsset2dEditor-module_dropZone__Z7sYz:hover{border-color:#ffd369;color:#c0c8d8}.GameAsset2dEditor-module_dropZone__Z7sYz.GameAsset2dEditor-module_active__DUroI{background:rgba(255,211,105,.1);border-color:#ffd369}.GameAsset2dEditor-module_emptyState__3wryk{align-items:center;color:#8892a8;display:flex;flex-direction:column;justify-content:center;padding:32px;text-align:center}.GameAsset2dEditor-module_emptyState__3wryk svg{height:48px;margin-bottom:12px;opacity:.5;width:48px}.GameAsset2dEditor-module_emptyStateText__Q5V1a{font-size:12px;margin-bottom:12px}
|
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useCallback } from 'react';
|
|
3
|
+
|
|
4
|
+
function luminance(r, g, b) {
|
|
5
|
+
return 0.299 * r + 0.587 * g + 0.114 * b;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Auto-colorize a grayscale image using heuristic color mapping.
|
|
9
|
+
* Maps luminance regions to plausible colors (sky-blue for bright areas,
|
|
10
|
+
* earth tones for dark areas, greens for mid-tones).
|
|
11
|
+
*/
|
|
12
|
+
function autoColorize(source, options) {
|
|
13
|
+
const { intensity, temperature, saturation } = options;
|
|
14
|
+
const result = new ImageData(new Uint8ClampedArray(source.data), source.width, source.height);
|
|
15
|
+
const data = result.data;
|
|
16
|
+
// Temperature bias
|
|
17
|
+
const tempBias = temperature === 'warm' ? [20, 5, -15] : temperature === 'cool' ? [-10, 0, 15] : [0, 0, 0];
|
|
18
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
19
|
+
const lum = luminance(data[i], data[i + 1], data[i + 2]);
|
|
20
|
+
const isGray = Math.abs(data[i] - data[i + 1]) < 15 && Math.abs(data[i + 1] - data[i + 2]) < 15;
|
|
21
|
+
if (isGray) {
|
|
22
|
+
// Map grayscale to heuristic colors based on luminance
|
|
23
|
+
let cr, cg, cb;
|
|
24
|
+
if (lum > 200) {
|
|
25
|
+
// Very bright → sky blue / white
|
|
26
|
+
cr = 200 + (lum - 200) * 0.8;
|
|
27
|
+
cg = 210 + (lum - 200) * 0.6;
|
|
28
|
+
cb = 230;
|
|
29
|
+
}
|
|
30
|
+
else if (lum > 140) {
|
|
31
|
+
// Upper mid → warm tones
|
|
32
|
+
cr = lum * 1.05;
|
|
33
|
+
cg = lum * 0.95;
|
|
34
|
+
cb = lum * 0.85;
|
|
35
|
+
}
|
|
36
|
+
else if (lum > 80) {
|
|
37
|
+
// Mid tones → greenish
|
|
38
|
+
cr = lum * 0.85;
|
|
39
|
+
cg = lum * 1.1;
|
|
40
|
+
cb = lum * 0.8;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// Dark → earth/brown
|
|
44
|
+
cr = lum * 1.15;
|
|
45
|
+
cg = lum * 0.9;
|
|
46
|
+
cb = lum * 0.7;
|
|
47
|
+
}
|
|
48
|
+
// Apply temperature bias
|
|
49
|
+
cr = Math.max(0, Math.min(255, cr + tempBias[0]));
|
|
50
|
+
cg = Math.max(0, Math.min(255, cg + tempBias[1]));
|
|
51
|
+
cb = Math.max(0, Math.min(255, cb + tempBias[2]));
|
|
52
|
+
// Apply saturation
|
|
53
|
+
const avg = (cr + cg + cb) / 3;
|
|
54
|
+
cr = avg + (cr - avg) * saturation;
|
|
55
|
+
cg = avg + (cg - avg) * saturation;
|
|
56
|
+
cb = avg + (cb - avg) * saturation;
|
|
57
|
+
// Blend with original based on intensity
|
|
58
|
+
data[i] = Math.max(0, Math.min(255, data[i] * (1 - intensity) + cr * intensity));
|
|
59
|
+
data[i + 1] = Math.max(0, Math.min(255, data[i + 1] * (1 - intensity) + cg * intensity));
|
|
60
|
+
data[i + 2] = Math.max(0, Math.min(255, data[i + 2] * (1 - intensity) + cb * intensity));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Remove background using edge-based foreground detection.
|
|
67
|
+
* Uses Sobel edge detection + flood fill from edges to find background.
|
|
68
|
+
*/
|
|
69
|
+
function removeBackground(source, options) {
|
|
70
|
+
const { threshold, iterations, featherRadius, replacementColor } = options;
|
|
71
|
+
const w = source.width;
|
|
72
|
+
const h = source.height;
|
|
73
|
+
const result = new ImageData(new Uint8ClampedArray(source.data), w, h);
|
|
74
|
+
const data = result.data;
|
|
75
|
+
// 1. Compute edge magnitude (Sobel)
|
|
76
|
+
const edges = new Float32Array(w * h);
|
|
77
|
+
for (let y = 1; y < h - 1; y++) {
|
|
78
|
+
for (let x = 1; x < w - 1; x++) {
|
|
79
|
+
const idx = (y * w + x) * 4;
|
|
80
|
+
const tl = luminance(source.data[idx - w * 4 - 4], source.data[idx - w * 4 - 3], source.data[idx - w * 4 - 2]);
|
|
81
|
+
const tc = luminance(source.data[idx - w * 4], source.data[idx - w * 4 + 1], source.data[idx - w * 4 + 2]);
|
|
82
|
+
const tr = luminance(source.data[idx - w * 4 + 4], source.data[idx - w * 4 + 5], source.data[idx - w * 4 + 6]);
|
|
83
|
+
const ml = luminance(source.data[idx - 4], source.data[idx - 3], source.data[idx - 2]);
|
|
84
|
+
const mr = luminance(source.data[idx + 4], source.data[idx + 5], source.data[idx + 6]);
|
|
85
|
+
const bl = luminance(source.data[idx + w * 4 - 4], source.data[idx + w * 4 - 3], source.data[idx + w * 4 - 2]);
|
|
86
|
+
const bc = luminance(source.data[idx + w * 4], source.data[idx + w * 4 + 1], source.data[idx + w * 4 + 2]);
|
|
87
|
+
const br = luminance(source.data[idx + w * 4 + 4], source.data[idx + w * 4 + 5], source.data[idx + w * 4 + 6]);
|
|
88
|
+
const gx = -tl - 2 * ml - bl + tr + 2 * mr + br;
|
|
89
|
+
const gy = -tl - 2 * tc - tr + bl + 2 * bc + br;
|
|
90
|
+
edges[y * w + x] = Math.sqrt(gx * gx + gy * gy) / 255;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// 2. Create foreground mask from edge density
|
|
94
|
+
const mask = new Float32Array(w * h);
|
|
95
|
+
const edgeThreshold = threshold * 0.5;
|
|
96
|
+
// Mark edges as definite foreground
|
|
97
|
+
for (let i = 0; i < edges.length; i++) {
|
|
98
|
+
mask[i] = edges[i] > edgeThreshold ? 1 : 0;
|
|
99
|
+
}
|
|
100
|
+
// 3. Dilate foreground mask (iterations)
|
|
101
|
+
for (let iter = 0; iter < iterations; iter++) {
|
|
102
|
+
const temp = new Float32Array(mask);
|
|
103
|
+
for (let y = 1; y < h - 1; y++) {
|
|
104
|
+
for (let x = 1; x < w - 1; x++) {
|
|
105
|
+
const idx = y * w + x;
|
|
106
|
+
if (temp[idx] > 0)
|
|
107
|
+
continue;
|
|
108
|
+
// Check 4-neighbors
|
|
109
|
+
if (temp[idx - 1] > 0 || temp[idx + 1] > 0 || temp[idx - w] > 0 || temp[idx + w] > 0) {
|
|
110
|
+
// Check color similarity with neighbor
|
|
111
|
+
const pi = idx * 4;
|
|
112
|
+
let isFg = false;
|
|
113
|
+
for (const ni of [idx - 1, idx + 1, idx - w, idx + w]) {
|
|
114
|
+
if (temp[ni] > 0) {
|
|
115
|
+
const npi = ni * 4;
|
|
116
|
+
const diff = (Math.abs(source.data[pi] - source.data[npi]) +
|
|
117
|
+
Math.abs(source.data[pi + 1] - source.data[npi + 1]) +
|
|
118
|
+
Math.abs(source.data[pi + 2] - source.data[npi + 2])) / 3;
|
|
119
|
+
if (diff < threshold * 255) {
|
|
120
|
+
isFg = true;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (isFg)
|
|
126
|
+
mask[idx] = 1;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// 4. Flood fill from border pixels as background (anything not foreground and reachable from edge)
|
|
132
|
+
const visited = new Uint8Array(w * h);
|
|
133
|
+
const queue = [];
|
|
134
|
+
// Seed from border
|
|
135
|
+
for (let x = 0; x < w; x++) {
|
|
136
|
+
if (mask[x] === 0) {
|
|
137
|
+
queue.push(x);
|
|
138
|
+
visited[x] = 1;
|
|
139
|
+
}
|
|
140
|
+
const bi = (h - 1) * w + x;
|
|
141
|
+
if (mask[bi] === 0) {
|
|
142
|
+
queue.push(bi);
|
|
143
|
+
visited[bi] = 1;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
for (let y = 0; y < h; y++) {
|
|
147
|
+
const li = y * w;
|
|
148
|
+
if (mask[li] === 0) {
|
|
149
|
+
queue.push(li);
|
|
150
|
+
visited[li] = 1;
|
|
151
|
+
}
|
|
152
|
+
const ri = y * w + w - 1;
|
|
153
|
+
if (mask[ri] === 0) {
|
|
154
|
+
queue.push(ri);
|
|
155
|
+
visited[ri] = 1;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// BFS flood fill
|
|
159
|
+
let head = 0;
|
|
160
|
+
while (head < queue.length) {
|
|
161
|
+
const idx = queue[head++];
|
|
162
|
+
const x = idx % w;
|
|
163
|
+
const y = (idx - x) / w;
|
|
164
|
+
for (const [dx, dy] of [[0, -1], [0, 1], [-1, 0], [1, 0]]) {
|
|
165
|
+
const nx = x + dx;
|
|
166
|
+
const ny = y + dy;
|
|
167
|
+
if (nx < 0 || nx >= w || ny < 0 || ny >= h)
|
|
168
|
+
continue;
|
|
169
|
+
const ni = ny * w + nx;
|
|
170
|
+
if (visited[ni] || mask[ni] > 0)
|
|
171
|
+
continue;
|
|
172
|
+
visited[ni] = 1;
|
|
173
|
+
queue.push(ni);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// 5. Apply mask with optional feathering
|
|
177
|
+
const replacement = replacementColor ? hexToRGB(replacementColor) : null;
|
|
178
|
+
for (let i = 0; i < w * h; i++) {
|
|
179
|
+
let alpha = visited[i] ? 0 : 1; // background = 0, foreground = 1
|
|
180
|
+
// Feather edges
|
|
181
|
+
if (featherRadius > 0 && alpha > 0) {
|
|
182
|
+
const x = i % w;
|
|
183
|
+
const y = (i - x) / w;
|
|
184
|
+
let minDistSq = featherRadius * featherRadius + 1;
|
|
185
|
+
for (let fy = -featherRadius; fy <= featherRadius; fy++) {
|
|
186
|
+
for (let fx = -featherRadius; fx <= featherRadius; fx++) {
|
|
187
|
+
const nx = x + fx;
|
|
188
|
+
const ny = y + fy;
|
|
189
|
+
if (nx >= 0 && nx < w && ny >= 0 && ny < h) {
|
|
190
|
+
if (visited[ny * w + nx]) {
|
|
191
|
+
const d = fx * fx + fy * fy;
|
|
192
|
+
if (d < minDistSq)
|
|
193
|
+
minDistSq = d;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (minDistSq <= featherRadius * featherRadius) {
|
|
199
|
+
alpha = Math.sqrt(minDistSq) / featherRadius;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const pi = i * 4;
|
|
203
|
+
if (replacement) {
|
|
204
|
+
data[pi] = Math.round(data[pi] * alpha + replacement[0] * (1 - alpha));
|
|
205
|
+
data[pi + 1] = Math.round(data[pi + 1] * alpha + replacement[1] * (1 - alpha));
|
|
206
|
+
data[pi + 2] = Math.round(data[pi + 2] * alpha + replacement[2] * (1 - alpha));
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
data[pi + 3] = Math.round(alpha * 255);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return result;
|
|
213
|
+
}
|
|
214
|
+
function hexToRGB(hex) {
|
|
215
|
+
const h = hex.replace('#', '');
|
|
216
|
+
return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)];
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Upscale image using Lanczos interpolation.
|
|
220
|
+
*/
|
|
221
|
+
function upscaleImage(source, options) {
|
|
222
|
+
const { scale, sharpen } = options;
|
|
223
|
+
const sw = source.width;
|
|
224
|
+
const sh = source.height;
|
|
225
|
+
const dw = sw * scale;
|
|
226
|
+
const dh = sh * scale;
|
|
227
|
+
const result = new ImageData(dw, dh);
|
|
228
|
+
const srcData = source.data;
|
|
229
|
+
const dstData = result.data;
|
|
230
|
+
// Lanczos kernel
|
|
231
|
+
const a = 3; // Lanczos-3
|
|
232
|
+
function lanczos(x) {
|
|
233
|
+
if (x === 0)
|
|
234
|
+
return 1;
|
|
235
|
+
if (Math.abs(x) >= a)
|
|
236
|
+
return 0;
|
|
237
|
+
const pix = Math.PI * x;
|
|
238
|
+
return (a * Math.sin(pix) * Math.sin(pix / a)) / (pix * pix);
|
|
239
|
+
}
|
|
240
|
+
// Bicubic Lanczos resampling
|
|
241
|
+
for (let dy = 0; dy < dh; dy++) {
|
|
242
|
+
const sy = (dy + 0.5) / scale - 0.5;
|
|
243
|
+
const sy0 = Math.floor(sy) - a + 1;
|
|
244
|
+
const sy1 = Math.floor(sy) + a;
|
|
245
|
+
for (let dx = 0; dx < dw; dx++) {
|
|
246
|
+
const sx = (dx + 0.5) / scale - 0.5;
|
|
247
|
+
const sx0 = Math.floor(sx) - a + 1;
|
|
248
|
+
const sx1 = Math.floor(sx) + a;
|
|
249
|
+
let r = 0, g = 0, b = 0, aa = 0, wSum = 0;
|
|
250
|
+
for (let iy = sy0; iy <= sy1; iy++) {
|
|
251
|
+
const wy = lanczos(sy - iy);
|
|
252
|
+
const cy = Math.max(0, Math.min(sh - 1, iy));
|
|
253
|
+
for (let ix = sx0; ix <= sx1; ix++) {
|
|
254
|
+
const wx = lanczos(sx - ix);
|
|
255
|
+
const w = wx * wy;
|
|
256
|
+
const cx = Math.max(0, Math.min(sw - 1, ix));
|
|
257
|
+
const si = (cy * sw + cx) * 4;
|
|
258
|
+
r += srcData[si] * w;
|
|
259
|
+
g += srcData[si + 1] * w;
|
|
260
|
+
b += srcData[si + 2] * w;
|
|
261
|
+
aa += srcData[si + 3] * w;
|
|
262
|
+
wSum += w;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const di = (dy * dw + dx) * 4;
|
|
266
|
+
if (wSum > 0) {
|
|
267
|
+
dstData[di] = Math.max(0, Math.min(255, r / wSum));
|
|
268
|
+
dstData[di + 1] = Math.max(0, Math.min(255, g / wSum));
|
|
269
|
+
dstData[di + 2] = Math.max(0, Math.min(255, b / wSum));
|
|
270
|
+
dstData[di + 3] = Math.max(0, Math.min(255, aa / wSum));
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// Post-sharpen with unsharp mask
|
|
275
|
+
if (sharpen > 0) {
|
|
276
|
+
const blurred = new Float32Array(dw * dh * 4);
|
|
277
|
+
// Quick box blur
|
|
278
|
+
for (let y = 1; y < dh - 1; y++) {
|
|
279
|
+
for (let x = 1; x < dw - 1; x++) {
|
|
280
|
+
const di = (y * dw + x) * 4;
|
|
281
|
+
for (let c = 0; c < 3; c++) {
|
|
282
|
+
blurred[di + c] = (dstData[di + c - dw * 4] +
|
|
283
|
+
dstData[di + c + dw * 4] +
|
|
284
|
+
dstData[di + c - 4] +
|
|
285
|
+
dstData[di + c + 4] +
|
|
286
|
+
dstData[di + c] * 4) / 8;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
// Apply unsharp mask
|
|
291
|
+
for (let i = 0; i < dstData.length; i += 4) {
|
|
292
|
+
for (let c = 0; c < 3; c++) {
|
|
293
|
+
const sharp = dstData[i + c] + (dstData[i + c] - blurred[i + c]) * sharpen * 2;
|
|
294
|
+
dstData[i + c] = Math.max(0, Math.min(255, sharp));
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return result;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Denoise image using bilateral filter approximation.
|
|
302
|
+
*/
|
|
303
|
+
function denoiseImage(source, options) {
|
|
304
|
+
const { strength, detailPreservation, luminanceWeight } = options;
|
|
305
|
+
const w = source.width;
|
|
306
|
+
const h = source.height;
|
|
307
|
+
const result = new ImageData(new Uint8ClampedArray(source.data), w, h);
|
|
308
|
+
const data = result.data;
|
|
309
|
+
const radius = Math.max(1, Math.round(strength * 5));
|
|
310
|
+
const sigmaSpace = radius * 0.5;
|
|
311
|
+
const sigmaColor = (1 - detailPreservation) * 150 + 10;
|
|
312
|
+
for (let y = 0; y < h; y++) {
|
|
313
|
+
for (let x = 0; x < w; x++) {
|
|
314
|
+
const ci = (y * w + x) * 4;
|
|
315
|
+
let rSum = 0, gSum = 0, bSum = 0, wSum = 0;
|
|
316
|
+
for (let dy = -radius; dy <= radius; dy++) {
|
|
317
|
+
for (let dx = -radius; dx <= radius; dx++) {
|
|
318
|
+
const nx = x + dx;
|
|
319
|
+
const ny = y + dy;
|
|
320
|
+
if (nx < 0 || nx >= w || ny < 0 || ny >= h)
|
|
321
|
+
continue;
|
|
322
|
+
const ni = (ny * w + nx) * 4;
|
|
323
|
+
const spatialDist = Math.sqrt(dx * dx + dy * dy);
|
|
324
|
+
const spatialW = Math.exp(-(spatialDist * spatialDist) / (2 * sigmaSpace * sigmaSpace));
|
|
325
|
+
// Color distance (weighted luminance vs chroma)
|
|
326
|
+
const lumDiff = luminance(source.data[ni], source.data[ni + 1], source.data[ni + 2]) -
|
|
327
|
+
luminance(source.data[ci], source.data[ci + 1], source.data[ci + 2]);
|
|
328
|
+
const chromaDiff = Math.sqrt((source.data[ni] - source.data[ci]) ** 2 +
|
|
329
|
+
(source.data[ni + 1] - source.data[ci + 1]) ** 2 +
|
|
330
|
+
(source.data[ni + 2] - source.data[ci + 2]) ** 2);
|
|
331
|
+
const colorDiff = lumDiff * luminanceWeight + chromaDiff * (1 - luminanceWeight);
|
|
332
|
+
const colorW = Math.exp(-(colorDiff * colorDiff) / (2 * sigmaColor * sigmaColor));
|
|
333
|
+
const weight = spatialW * colorW;
|
|
334
|
+
rSum += source.data[ni] * weight;
|
|
335
|
+
gSum += source.data[ni + 1] * weight;
|
|
336
|
+
bSum += source.data[ni + 2] * weight;
|
|
337
|
+
wSum += weight;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
if (wSum > 0) {
|
|
341
|
+
data[ci] = Math.round(rSum / wSum);
|
|
342
|
+
data[ci + 1] = Math.round(gSum / wSum);
|
|
343
|
+
data[ci + 2] = Math.round(bSum / wSum);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return result;
|
|
348
|
+
}
|
|
349
|
+
/* ── Hook ── */
|
|
350
|
+
function useAITools(sourceImage) {
|
|
351
|
+
const [isProcessing, setIsProcessing] = useState(false);
|
|
352
|
+
const [activeTool, setActiveTool] = useState('colorize');
|
|
353
|
+
const [lastResult, setLastResult] = useState(null);
|
|
354
|
+
const [colorizeOptions, setColorizeOptions] = useState({
|
|
355
|
+
intensity: 0.7, temperature: 'neutral', saturation: 1.2,
|
|
356
|
+
});
|
|
357
|
+
const [bgRemoveOptions, setBgRemoveOptions] = useState({
|
|
358
|
+
edgeSoftness: 2, threshold: 0.35, iterations: 8, featherRadius: 3, replacementColor: null,
|
|
359
|
+
});
|
|
360
|
+
const [upscaleOptions, setUpscaleOptions] = useState({
|
|
361
|
+
scale: 2, method: 'lanczos', sharpen: 0.3,
|
|
362
|
+
});
|
|
363
|
+
const [denoiseOptions, setDenoiseOptions] = useState({
|
|
364
|
+
strength: 0.5, detailPreservation: 0.6, luminanceWeight: 0.7,
|
|
365
|
+
});
|
|
366
|
+
const process = useCallback(async () => {
|
|
367
|
+
if (!sourceImage)
|
|
368
|
+
return null;
|
|
369
|
+
setIsProcessing(true);
|
|
370
|
+
const start = performance.now();
|
|
371
|
+
let imageData;
|
|
372
|
+
try {
|
|
373
|
+
switch (activeTool) {
|
|
374
|
+
case 'colorize':
|
|
375
|
+
imageData = autoColorize(sourceImage, colorizeOptions);
|
|
376
|
+
break;
|
|
377
|
+
case 'background-remove':
|
|
378
|
+
imageData = removeBackground(sourceImage, bgRemoveOptions);
|
|
379
|
+
break;
|
|
380
|
+
case 'upscale':
|
|
381
|
+
imageData = upscaleImage(sourceImage, upscaleOptions);
|
|
382
|
+
break;
|
|
383
|
+
case 'denoise':
|
|
384
|
+
imageData = denoiseImage(sourceImage, denoiseOptions);
|
|
385
|
+
break;
|
|
386
|
+
default:
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
const result = {
|
|
390
|
+
imageData,
|
|
391
|
+
processingTimeMs: performance.now() - start,
|
|
392
|
+
tool: activeTool,
|
|
393
|
+
};
|
|
394
|
+
setLastResult(result);
|
|
395
|
+
return result;
|
|
396
|
+
}
|
|
397
|
+
finally {
|
|
398
|
+
setIsProcessing(false);
|
|
399
|
+
}
|
|
400
|
+
}, [sourceImage, activeTool, colorizeOptions, bgRemoveOptions, upscaleOptions, denoiseOptions]);
|
|
401
|
+
return {
|
|
402
|
+
activeTool, setActiveTool,
|
|
403
|
+
colorizeOptions, setColorizeOptions,
|
|
404
|
+
bgRemoveOptions, setBgRemoveOptions,
|
|
405
|
+
upscaleOptions, setUpscaleOptions,
|
|
406
|
+
denoiseOptions, setDenoiseOptions,
|
|
407
|
+
process, isProcessing, lastResult,
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
/* ── Component ── */
|
|
411
|
+
const TOOL_LABELS = {
|
|
412
|
+
colorize: '🎨 Auto-Colorize',
|
|
413
|
+
'background-remove': '✂️ Remove Background',
|
|
414
|
+
upscale: '🔍 Upscale (ESRGAN)',
|
|
415
|
+
denoise: '🔇 Denoise',
|
|
416
|
+
};
|
|
417
|
+
const NiceAITools = ({ sourceImage, onResult, className = '' }) => {
|
|
418
|
+
var _a;
|
|
419
|
+
const ai = useAITools(sourceImage);
|
|
420
|
+
const handleProcess = async () => {
|
|
421
|
+
const result = await ai.process();
|
|
422
|
+
if (result && onResult)
|
|
423
|
+
onResult(result);
|
|
424
|
+
};
|
|
425
|
+
return (jsxs("div", { className: `nice-ai-tools ${className}`, style: { display: 'grid', gap: 8, fontSize: 13 }, children: [jsx("strong", { children: "\uD83E\uDD16 AI Tools" }), jsx("div", { style: { display: 'flex', gap: 2, flexWrap: 'wrap' }, children: Object.entries(TOOL_LABELS).map(([key, label]) => (jsx("button", { type: "button", onClick: () => ai.setActiveTool(key), style: {
|
|
426
|
+
flex: 1, padding: '4px 6px', fontSize: 11, cursor: 'pointer', borderRadius: 4,
|
|
427
|
+
border: '1px solid var(--border, #e2e8f0)',
|
|
428
|
+
background: ai.activeTool === key ? 'var(--accent, #6366f1)' : 'transparent',
|
|
429
|
+
color: ai.activeTool === key ? '#fff' : 'inherit',
|
|
430
|
+
minWidth: 100,
|
|
431
|
+
}, children: label }, key))) }), ai.activeTool === 'colorize' && (jsxs("div", { style: { display: 'grid', gap: 4 }, children: [jsxs("label", { children: ["Intensity: ", ai.colorizeOptions.intensity.toFixed(2), jsx("input", { type: "range", min: 0, max: 1, step: 0.05, value: ai.colorizeOptions.intensity, onChange: (e) => ai.setColorizeOptions({ ...ai.colorizeOptions, intensity: +e.target.value }), style: { width: '100%' } })] }), jsxs("label", { children: ["Saturation: ", ai.colorizeOptions.saturation.toFixed(1), jsx("input", { type: "range", min: 0, max: 2, step: 0.1, value: ai.colorizeOptions.saturation, onChange: (e) => ai.setColorizeOptions({ ...ai.colorizeOptions, saturation: +e.target.value }), style: { width: '100%' } })] }), jsxs("label", { children: ["Temperature:", jsxs("select", { value: ai.colorizeOptions.temperature, onChange: (e) => ai.setColorizeOptions({ ...ai.colorizeOptions, temperature: e.target.value }), style: { width: '100%' }, children: [jsx("option", { value: "warm", children: "Warm" }), jsx("option", { value: "neutral", children: "Neutral" }), jsx("option", { value: "cool", children: "Cool" })] })] })] })), ai.activeTool === 'background-remove' && (jsxs("div", { style: { display: 'grid', gap: 4 }, children: [jsxs("label", { children: ["Threshold: ", ai.bgRemoveOptions.threshold.toFixed(2), jsx("input", { type: "range", min: 0.1, max: 0.9, step: 0.05, value: ai.bgRemoveOptions.threshold, onChange: (e) => ai.setBgRemoveOptions({ ...ai.bgRemoveOptions, threshold: +e.target.value }), style: { width: '100%' } })] }), jsxs("label", { children: ["Iterations: ", ai.bgRemoveOptions.iterations, jsx("input", { type: "range", min: 1, max: 20, step: 1, value: ai.bgRemoveOptions.iterations, onChange: (e) => ai.setBgRemoveOptions({ ...ai.bgRemoveOptions, iterations: +e.target.value }), style: { width: '100%' } })] }), jsxs("label", { children: ["Feather: ", ai.bgRemoveOptions.featherRadius, "px", jsx("input", { type: "range", min: 0, max: 10, step: 1, value: ai.bgRemoveOptions.featherRadius, onChange: (e) => ai.setBgRemoveOptions({ ...ai.bgRemoveOptions, featherRadius: +e.target.value }), style: { width: '100%' } })] }), jsxs("label", { style: { display: 'flex', gap: 4, alignItems: 'center' }, children: ["Replace BG:", jsx("input", { type: "color", value: (_a = ai.bgRemoveOptions.replacementColor) !== null && _a !== void 0 ? _a : '#ffffff', onChange: (e) => ai.setBgRemoveOptions({ ...ai.bgRemoveOptions, replacementColor: e.target.value }) }), jsx("button", { type: "button", onClick: () => ai.setBgRemoveOptions({ ...ai.bgRemoveOptions, replacementColor: null }), style: { fontSize: 10 }, children: "Transparent" })] })] })), ai.activeTool === 'upscale' && (jsxs("div", { style: { display: 'grid', gap: 4 }, children: [jsxs("label", { children: ["Scale:", jsxs("select", { value: ai.upscaleOptions.scale, onChange: (e) => ai.setUpscaleOptions({ ...ai.upscaleOptions, scale: +e.target.value }), style: { width: '100%' }, children: [jsx("option", { value: 2, children: "2x" }), jsx("option", { value: 3, children: "3x" }), jsx("option", { value: 4, children: "4x" })] })] }), jsxs("label", { children: ["Sharpen: ", ai.upscaleOptions.sharpen.toFixed(2), jsx("input", { type: "range", min: 0, max: 1, step: 0.05, value: ai.upscaleOptions.sharpen, onChange: (e) => ai.setUpscaleOptions({ ...ai.upscaleOptions, sharpen: +e.target.value }), style: { width: '100%' } })] })] })), ai.activeTool === 'denoise' && (jsxs("div", { style: { display: 'grid', gap: 4 }, children: [jsxs("label", { children: ["Strength: ", ai.denoiseOptions.strength.toFixed(2), jsx("input", { type: "range", min: 0, max: 1, step: 0.05, value: ai.denoiseOptions.strength, onChange: (e) => ai.setDenoiseOptions({ ...ai.denoiseOptions, strength: +e.target.value }), style: { width: '100%' } })] }), jsxs("label", { children: ["Detail: ", ai.denoiseOptions.detailPreservation.toFixed(2), jsx("input", { type: "range", min: 0, max: 1, step: 0.05, value: ai.denoiseOptions.detailPreservation, onChange: (e) => ai.setDenoiseOptions({ ...ai.denoiseOptions, detailPreservation: +e.target.value }), style: { width: '100%' } })] })] })), jsx("button", { type: "button", onClick: handleProcess, disabled: ai.isProcessing || !sourceImage, style: {
|
|
432
|
+
background: ai.isProcessing ? '#94a3b8' : 'var(--accent, #6366f1)',
|
|
433
|
+
color: '#fff', border: 'none', borderRadius: 4, padding: '8px 12px',
|
|
434
|
+
cursor: ai.isProcessing ? 'wait' : 'pointer',
|
|
435
|
+
}, children: ai.isProcessing ? '⏳ Processing…' : `▶️ ${TOOL_LABELS[ai.activeTool]}` }), ai.lastResult && (jsxs("div", { style: { fontSize: 11, color: 'var(--muted, #64748b)' }, children: ["Processed in ", ai.lastResult.processingTimeMs.toFixed(0), "ms", ai.activeTool === 'upscale' && ` → ${ai.lastResult.imageData.width}×${ai.lastResult.imageData.height}`] }))] }));
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
export { NiceAITools, autoColorize, denoiseImage, removeBackground, upscaleImage, useAITools };
|
|
439
|
+
//# sourceMappingURL=NiceAITools.js.map
|