@dickpy/dsh-imagegen 1.5.8 → 1.5.9

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/lib/client.js CHANGED
@@ -499,10 +499,16 @@ window.__ModuleLoader__.load({
499
499
  "canvas.background": "画布背景",
500
500
  "canvas.backgroundDots": "点阵",
501
501
  "canvas.backgroundLines": "网格线",
502
- "canvas.backgroundDiagonal": "斜线",
503
- "canvas.backgroundChecker": "棋盘格",
502
+ "canvas.backgroundWaves": "波浪线",
503
+ "canvas.backgroundShapeGrid": "滚动方格",
504
+ "canvas.backgroundDotField": "点场",
505
+ "canvas.backgroundDotGrid": "互动点阵",
506
+ "canvas.backgroundFloatingLines": "浮动线条",
504
507
  "canvas.backgroundFlow": "流体扰动",
505
- "canvas.backgroundAurora": "极光",
508
+ "canvas.backgroundLiquid": "液态以太",
509
+ "canvas.backgroundFaultyTerminal": "故障终端",
510
+ "canvas.backgroundSilk": "丝绸",
511
+ "canvas.backgroundGalaxy": "星系",
506
512
  "canvas.backgroundBlank": "空白",
507
513
  "canvas.backgroundUpload": "上传自定义背景…",
508
514
  "canvas.backgroundRemove": "移除自定义背景",
@@ -995,10 +1001,16 @@ window.__ModuleLoader__.load({
995
1001
  "canvas.background": "Canvas background",
996
1002
  "canvas.backgroundDots": "Dots",
997
1003
  "canvas.backgroundLines": "Grid lines",
998
- "canvas.backgroundDiagonal": "Diagonal",
999
- "canvas.backgroundChecker": "Checkerboard",
1004
+ "canvas.backgroundWaves": "Waves",
1005
+ "canvas.backgroundShapeGrid": "Scrolling grid",
1006
+ "canvas.backgroundDotField": "Dot field",
1007
+ "canvas.backgroundDotGrid": "Interactive dots",
1008
+ "canvas.backgroundFloatingLines": "Floating lines",
1000
1009
  "canvas.backgroundFlow": "Fluid flow",
1001
- "canvas.backgroundAurora": "Aurora",
1010
+ "canvas.backgroundLiquid": "Liquid ether",
1011
+ "canvas.backgroundFaultyTerminal": "Faulty terminal",
1012
+ "canvas.backgroundSilk": "Silk",
1013
+ "canvas.backgroundGalaxy": "Galaxy",
1002
1014
  "canvas.backgroundBlank": "Blank",
1003
1015
  "canvas.backgroundUpload": "Upload custom background…",
1004
1016
  "canvas.backgroundRemove": "Remove custom background",
@@ -1492,10 +1504,16 @@ window.__ModuleLoader__.load({
1492
1504
  "canvas.background": "Фон холста",
1493
1505
  "canvas.backgroundDots": "Точки",
1494
1506
  "canvas.backgroundLines": "Сетка",
1495
- "canvas.backgroundDiagonal": "Диагональ",
1496
- "canvas.backgroundChecker": "Шахматка",
1507
+ "canvas.backgroundWaves": "Волны",
1508
+ "canvas.backgroundShapeGrid": "Бегущая сетка",
1509
+ "canvas.backgroundDotField": "Поле точек",
1510
+ "canvas.backgroundDotGrid": "Интерактивные точки",
1511
+ "canvas.backgroundFloatingLines": "Плавающие линии",
1497
1512
  "canvas.backgroundFlow": "Жидкостный поток",
1498
- "canvas.backgroundAurora": "Аврора",
1513
+ "canvas.backgroundLiquid": "Жидкий эфир",
1514
+ "canvas.backgroundFaultyTerminal": "Сбойный терминал",
1515
+ "canvas.backgroundSilk": "Шёлк",
1516
+ "canvas.backgroundGalaxy": "Галактика",
1499
1517
  "canvas.backgroundBlank": "Пустой",
1500
1518
  "canvas.backgroundUpload": "Загрузить свой фон…",
1501
1519
  "canvas.backgroundRemove": "Убрать свой фон",
@@ -2020,51 +2038,51 @@ window.__ModuleLoader__.load({
2020
2038
  document.head.appendChild(tag);
2021
2039
  }
2022
2040
  var templates_module_css_default = {
2023
- "headerActions": "o0mAxG_headerActions",
2024
- "search": "o0mAxG_search",
2041
+ "detailInfo": "o0mAxG_detailInfo",
2042
+ "categoryRow": "o0mAxG_categoryRow",
2043
+ "overlay": "o0mAxG_overlay",
2044
+ "detailPrompt": "o0mAxG_detailPrompt",
2045
+ "cardTitle": "o0mAxG_cardTitle",
2046
+ "footer": "o0mAxG_footer",
2025
2047
  "state": "o0mAxG_state",
2026
- "detailTitle": "o0mAxG_detailTitle",
2027
- "detailMeta": "o0mAxG_detailMeta",
2048
+ "meta": "o0mAxG_meta",
2049
+ "headerActions": "o0mAxG_headerActions",
2050
+ "spinner": "o0mAxG_spinner",
2051
+ "dsh-imagegen-templates-spin": "o0mAxG_dsh-imagegen-templates-spin",
2052
+ "attribution": "o0mAxG_attribution",
2028
2053
  "sourceLink": "o0mAxG_sourceLink",
2029
- "detailActions": "o0mAxG_detailActions",
2030
- "categoryPill": "o0mAxG_categoryPill",
2031
- "title": "o0mAxG_title",
2032
- "detailLink": "o0mAxG_detailLink",
2033
- "featuredBadge": "o0mAxG_featuredBadge",
2034
- "detailOverlay": "o0mAxG_detailOverlay",
2054
+ "detailMeta": "o0mAxG_detailMeta",
2055
+ "cardCategory": "o0mAxG_cardCategory",
2056
+ "close": "o0mAxG_close",
2057
+ "body": "o0mAxG_body",
2035
2058
  "cardMeta": "o0mAxG_cardMeta",
2036
- "toolbar": "o0mAxG_toolbar",
2037
- "shell": "o0mAxG_shell",
2038
- "notice": "o0mAxG_notice",
2039
2059
  "grid": "o0mAxG_grid",
2060
+ "detailMedia": "o0mAxG_detailMedia",
2061
+ "detailLink": "o0mAxG_detailLink",
2062
+ "sourceTabCount": "o0mAxG_sourceTabCount",
2063
+ "cardSource": "o0mAxG_cardSource",
2040
2064
  "detailImage": "o0mAxG_detailImage",
2041
- "heading": "o0mAxG_heading",
2065
+ "notice": "o0mAxG_notice",
2066
+ "detailOverlay": "o0mAxG_detailOverlay",
2067
+ "categoryPill": "o0mAxG_categoryPill",
2068
+ "featuredBadge": "o0mAxG_featuredBadge",
2069
+ "shell": "o0mAxG_shell",
2070
+ "card": "o0mAxG_card",
2042
2071
  "favStar": "o0mAxG_favStar",
2043
- "cardTitle": "o0mAxG_cardTitle",
2044
- "cardBody": "o0mAxG_cardBody",
2045
- "detailMedia": "o0mAxG_detailMedia",
2046
- "sourceTabs": "o0mAxG_sourceTabs",
2047
- "detailInfo": "o0mAxG_detailInfo",
2048
- "thumbWrap": "o0mAxG_thumbWrap",
2049
- "header": "o0mAxG_header",
2050
- "dsh-imagegen-templates-spin": "o0mAxG_dsh-imagegen-templates-spin",
2051
- "categoryRow": "o0mAxG_categoryRow",
2052
- "overlay": "o0mAxG_overlay",
2053
- "spinner": "o0mAxG_spinner",
2054
- "footer": "o0mAxG_footer",
2072
+ "search": "o0mAxG_search",
2055
2073
  "sourceTab": "o0mAxG_sourceTab",
2074
+ "detailTitle": "o0mAxG_detailTitle",
2075
+ "sourceTabs": "o0mAxG_sourceTabs",
2056
2076
  "detail": "o0mAxG_detail",
2057
- "cardSource": "o0mAxG_cardSource",
2058
- "detailPrompt": "o0mAxG_detailPrompt",
2059
- "card": "o0mAxG_card",
2077
+ "detailActions": "o0mAxG_detailActions",
2060
2078
  "thumb": "o0mAxG_thumb",
2079
+ "thumbWrap": "o0mAxG_thumbWrap",
2080
+ "header": "o0mAxG_header",
2061
2081
  "thumbPlaceholder": "o0mAxG_thumbPlaceholder",
2062
- "body": "o0mAxG_body",
2063
- "meta": "o0mAxG_meta",
2064
- "close": "o0mAxG_close",
2065
- "sourceTabCount": "o0mAxG_sourceTabCount",
2066
- "cardCategory": "o0mAxG_cardCategory",
2067
- "attribution": "o0mAxG_attribution"
2082
+ "toolbar": "o0mAxG_toolbar",
2083
+ "cardBody": "o0mAxG_cardBody",
2084
+ "title": "o0mAxG_title",
2085
+ "heading": "o0mAxG_heading"
2068
2086
  };
2069
2087
  //#endregion
2070
2088
  //#region src/client/TemplateLibrary.tsx
@@ -2692,19 +2710,19 @@ window.__ModuleLoader__.load({
2692
2710
  document.head.appendChild(tag);
2693
2711
  }
2694
2712
  var inspiration_module_css_default = {
2695
- "thumbFallback": "IgRnJG_thumbFallback",
2696
- "thumbTitle": "IgRnJG_thumbTitle",
2697
- "emptyIcon": "IgRnJG_emptyIcon",
2713
+ "emptyHint": "IgRnJG_emptyHint",
2698
2714
  "emptyTitle": "IgRnJG_emptyTitle",
2715
+ "grid": "IgRnJG_grid",
2716
+ "emptyIcon": "IgRnJG_emptyIcon",
2699
2717
  "thumb": "IgRnJG_thumb",
2700
- "thumbWrap": "IgRnJG_thumbWrap",
2718
+ "thumbFallback": "IgRnJG_thumbFallback",
2701
2719
  "spinner": "IgRnJG_spinner",
2702
2720
  "dsh-imagegen-inspiration-spin": "IgRnJG_dsh-imagegen-inspiration-spin",
2703
- "wrap": "IgRnJG_wrap",
2721
+ "thumbTitle": "IgRnJG_thumbTitle",
2722
+ "thumbWrap": "IgRnJG_thumbWrap",
2704
2723
  "title": "IgRnJG_title",
2705
- "grid": "IgRnJG_grid",
2706
- "tile": "IgRnJG_tile",
2707
- "emptyHint": "IgRnJG_emptyHint"
2724
+ "wrap": "IgRnJG_wrap",
2725
+ "tile": "IgRnJG_tile"
2708
2726
  };
2709
2727
  //#endregion
2710
2728
  //#region src/client/InspirationGallery.tsx
@@ -37975,7 +37993,7 @@ window.__ModuleLoader__.load({
37975
37993
  exports.Wallpaper = Wallpaper;
37976
37994
  exports.X = X;
37977
37995
  })))();
37978
- const css$3 = "._0yZr2a_root{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);min-width:0;height:100%;min-height:0;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-family,inherit);user-select:none;border-radius:10px;flex-direction:column;flex:auto;display:flex;position:relative;overflow:hidden}._0yZr2a_selectCursor{cursor:default}._0yZr2a_panCursor{cursor:grab}._0yZr2a_panCursor:active{cursor:grabbing}._0yZr2a_topBar{border-bottom:1px solid var(--dsw-alias-border-l1);z-index:40;background:var(--dsw-alias-bg-layer-1);flex:none;align-items:center;gap:8px;padding:8px 12px;display:flex}._0yZr2a_projectSelect{border:1px solid var(--dsw-alias-border-l1);max-width:180px;height:30px;color:var(--dsw-alias-label-primary);background:0 0;border-radius:8px;padding:0 8px;font-size:12.5px}._0yZr2a_titleButton{height:30px;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;cursor:text;background:0 0;border:1px solid #0000;border-radius:8px;max-width:260px;padding:0 10px;font-size:13px;font-weight:600;overflow:hidden}._0yZr2a_titleButton:hover{border-color:var(--dsw-alias-border-l1)}._0yZr2a_titleInput{border:1px solid var(--dsw-alias-brand-primary);height:30px;color:var(--dsw-alias-label-primary);background:0 0;border-radius:8px;outline:none;width:240px;padding:0 10px;font-size:13px;font-weight:600}._0yZr2a_topBarSpacer{flex:1}._0yZr2a_saveState{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-size:11.5px}._0yZr2a_saveState[data-state=error]{color:var(--dsw-alias-label-error)}._0yZr2a_saveState[data-state=saving]{color:var(--dsw-alias-state-warn-primary,var(--dsw-alias-label-secondary))}._0yZr2a_iconButton{width:30px;height:30px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:8px;flex:none;justify-content:center;align-items:center;gap:5px;padding:0;display:inline-flex}._0yZr2a_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._0yZr2a_iconButton[data-active]{background:color-mix(in srgb, var(--dsw-alias-brand-primary) 16%, transparent);color:var(--dsw-alias-brand-primary)}._0yZr2a_iconButton:disabled{opacity:.35;cursor:not-allowed}._0yZr2a_iconButton:disabled:hover{color:var(--dsw-alias-label-secondary);background:0 0}._0yZr2a_viewport{touch-action:none;flex:1;min-height:0;position:relative;overflow:hidden}._0yZr2a_grid{pointer-events:none;opacity:.5;position:absolute;inset:0}._0yZr2a_flowCanvas{width:100%;height:100%;position:absolute;inset:0}._0yZr2a_grid[data-mode=flow],._0yZr2a_grid[data-mode=aurora]{opacity:1}._0yZr2a_grid[data-mode=aurora]{background-image:radial-gradient(560px 380px at 22% 28%, color-mix(in srgb, var(--dsw-alias-brand-primary) 24%, transparent), transparent 72%), radial-gradient(680px 480px at 78% 62%, #a78bfa33, transparent 72%), radial-gradient(520px 400px at 48% 88%, #22d3ee2b, transparent 74%);background-position:0 0;background-size:220% 220%;animation:20s ease-in-out infinite alternate _0yZr2a_auroraDrift}@keyframes _0yZr2a_auroraDrift{0%{background-position:0 0}to{background-position:100% 100%}}@media (prefers-reduced-motion:reduce){._0yZr2a_grid[data-mode=aurora]{animation:none}}._0yZr2a_grid[data-mode=dots]{background-image:radial-gradient(circle, color-mix(in srgb, var(--dsw-alias-label-primary) 30%, transparent) 1.1px, transparent 1.4px)}._0yZr2a_grid[data-mode=lines]{background-image:linear-gradient(color-mix(in srgb, var(--dsw-alias-label-primary) 9%, transparent) 1px, transparent 1px), linear-gradient(90deg, color-mix(in srgb, var(--dsw-alias-label-primary) 9%, transparent) 1px, transparent 1px)}._0yZr2a_grid[data-mode=blank]{background-image:none}._0yZr2a_grid[data-mode=diagonal]{background-image:repeating-linear-gradient(45deg, color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent) 0 1px, transparent 1px 16px)}._0yZr2a_grid[data-mode=checker]{background-image:conic-gradient(color-mix(in srgb, var(--dsw-alias-label-primary) 7%, transparent) 90deg, transparent 90deg 180deg, color-mix(in srgb, var(--dsw-alias-label-primary) 7%, transparent) 180deg 270deg, transparent 270deg);background-size:48px 48px}._0yZr2a_grid[data-mode=image]{background-image:none}._0yZr2a_gridScrim{background:var(--dsw-alias-bg-layer-1);opacity:.6;position:absolute;inset:0}._0yZr2a_backgroundMenu{z-index:45;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 96%, transparent);border-radius:11px;flex-direction:column;min-width:168px;padding:5px;display:flex;position:absolute;transform:translate(-50%,-100%);box-shadow:0 16px 40px #0f172a33}._0yZr2a_backgroundMenu button{color:var(--dsw-alias-label-primary);cursor:pointer;text-align:left;background:0 0;border:none;border-radius:7px;justify-content:flex-start;align-items:center;padding:7px 10px;font-size:12.5px;display:flex}._0yZr2a_backgroundMenu button:hover{background:var(--dsw-alias-interactive-bg-hover)}._0yZr2a_backgroundMenu button[data-active]{color:var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 12%, transparent)}._0yZr2a_backgroundMenuDivider{background:var(--dsw-alias-border-l1);height:1px;margin:4px 6px}._0yZr2a_world{transform-origin:0 0;position:absolute;top:0;left:0}._0yZr2a_marquee{z-index:20;border:1px solid var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 8%, transparent);pointer-events:none;border-radius:4px;position:absolute}._0yZr2a_node{border:1.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);cursor:grab;touch-action:none;border-radius:14px;flex-direction:column;display:flex;position:absolute;overflow:visible;box-shadow:0 8px 24px #0f172a1f}._0yZr2a_node:active{cursor:grabbing}._0yZr2a_nodeGlow{pointer-events:none;opacity:0;border-radius:18px;transition:opacity .15s;position:absolute;inset:-6px}._0yZr2a_nodeSelected{border-color:var(--dsw-alias-brand-primary);z-index:2}._0yZr2a_nodeSelected ._0yZr2a_nodeGlow{opacity:1;box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-brand-primary) 22%, transparent)}._0yZr2a_nodeRelated{border-color:color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, transparent)}._0yZr2a_nodeConnectTarget{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 4px color-mix(in srgb, var(--dsw-alias-brand-primary) 26%, transparent)}._0yZr2a_nodeHeader{color:var(--dsw-alias-label-secondary);cursor:inherit;flex:none;align-items:center;gap:6px;padding:7px 12px 5px;font-size:11.5px;display:flex}._0yZr2a_nodeTitle{text-overflow:ellipsis;white-space:nowrap;font-weight:600;overflow:hidden}._0yZr2a_nodeSize{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;margin-left:auto;font-size:10.5px}._0yZr2a_nodeSpinner{border:1.5px solid color-mix(in srgb, var(--dsw-alias-brand-primary) 30%, transparent);border-top-color:var(--dsw-alias-brand-primary);border-radius:50%;flex:none;width:11px;height:11px;animation:.8s linear infinite _0yZr2a_canvasSpin}._0yZr2a_nodeBody{background:color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent);pointer-events:none;border-radius:9px;flex:1;justify-content:center;align-items:center;min-height:0;margin:0 8px 8px;display:flex;overflow:hidden}._0yZr2a_nodeBody img{object-fit:contain;width:100%;height:100%;display:block}._0yZr2a_imageInfo{z-index:2;background:color-mix(in srgb, var(--dsw-alias-label-primary) 62%, transparent);color:var(--dsw-alias-bg-layer-1);pointer-events:none;backdrop-filter:blur(3px);text-overflow:ellipsis;white-space:nowrap;border-radius:6px;max-width:calc(100% - 90px);padding:3px 8px;font-size:10.5px;line-height:1.4;position:absolute;top:6px;overflow:hidden}._0yZr2a_imageInfoLeft{font-weight:600;left:6px}._0yZr2a_imageInfoRight{font-variant-numeric:tabular-nums;opacity:.85;left:auto;right:6px}._0yZr2a_nodeState,._0yZr2a_nodeStateError{color:var(--dsw-alias-label-secondary);text-align:center;pointer-events:auto;flex-direction:column;align-items:center;gap:8px;padding:12px;font-size:12px;display:flex}._0yZr2a_nodeStateError{color:var(--dsw-alias-label-error)}._0yZr2a_nodeStateError button{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);cursor:pointer;border:none;border-radius:7px;padding:4px 12px;font-size:12px}._0yZr2a_nodeEmpty{border:1.5px dashed color-mix(in srgb, var(--dsw-alias-label-primary) 24%, transparent);color:var(--dsw-alias-label-tertiary);cursor:pointer;pointer-events:auto;background:0 0;border-radius:9px;flex-direction:column;align-items:center;gap:8px;margin:6px;padding:14px;font-size:12px;display:flex}._0yZr2a_nodeEmpty:hover{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary)}._0yZr2a_textNode{cursor:default}._0yZr2a_imageNode ._0yZr2a_nodeBody{margin:6px}._0yZr2a_textArea{resize:none;min-height:0;color:var(--dsw-alias-label-primary);cursor:text;pointer-events:auto;background:0 0;border:none;outline:none;flex:1;margin:0 8px 8px;padding:4px 6px;font-size:13px;line-height:1.55}._0yZr2a_textArea::placeholder{color:var(--dsw-alias-label-tertiary)}._0yZr2a_dock{z-index:30;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 92%, transparent);backdrop-filter:blur(10px);border-radius:13px;align-items:center;gap:2px;padding:6px;display:flex;position:absolute;bottom:14px;left:50%;transform:translate(-50%);box-shadow:0 10px 30px #0f172a24}._0yZr2a_dock ._0yZr2a_iconButton{width:40px;height:40px;transform:translateY(var(--dock-lift,0px)) scale(var(--dock-scale,1));transform-origin:50% 100%;border-radius:11px;transition:transform .16s cubic-bezier(.33,1,.68,1),background .15s,color .15s,box-shadow .18s;position:relative}._0yZr2a_dock ._0yZr2a_iconButton:not(:disabled):hover{z-index:2;box-shadow:0 6px 14px color-mix(in srgb, var(--dsw-alias-label-primary) 20%, transparent)}._0yZr2a_dock ._0yZr2a_iconButton:not(:disabled):active{transform:translateY(var(--dock-lift,0px)) scale(.94)}._0yZr2a_dock ._0yZr2a_iconButton[data-active],._0yZr2a_dock ._0yZr2a_iconButton[data-active]:hover{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-1)}._0yZr2a_dockDivider{background:var(--dsw-alias-border-l1);width:1px;height:18px;margin:0 4px}._0yZr2a_composer{z-index:35;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 96%, transparent);backdrop-filter:blur(10px);border-radius:14px;flex-direction:column;gap:8px;width:560px;padding:10px;display:flex;position:absolute;box-shadow:0 16px 44px #0f172a2e}._0yZr2a_composerPrompt{resize:none;width:100%;min-height:38px;max-height:120px;color:var(--dsw-alias-label-primary);cursor:text;background:0 0;border:none;outline:none;padding:2px 4px;font-size:13px;line-height:1.5}._0yZr2a_composerPrompt::placeholder{color:var(--dsw-alias-label-tertiary)}._0yZr2a_composerMeta{display:flex}._0yZr2a_composerChip{border:1px solid color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, transparent);color:var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 8%, transparent);border-radius:999px;align-items:center;gap:5px;padding:2px 9px;font-size:11px;display:inline-flex}._0yZr2a_composerControls{align-items:center;gap:6px;display:flex}._0yZr2a_composerControls select{border:1px solid var(--dsw-alias-border-l1);height:28px;color:var(--dsw-alias-label-primary);background:0 0;border-radius:999px;min-width:0;max-width:128px;padding:0 8px;font-size:11.5px}._0yZr2a_composerSelect{border:1px solid var(--dsw-alias-border-l1);height:28px;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:999px;align-items:center;gap:6px;min-width:0;max-width:138px;padding:0 8px 0 11px;font-size:11.5px;transition:background .15s,border-color .15s;display:inline-flex}._0yZr2a_composerSelect:hover{background:var(--dsw-alias-interactive-bg-hover)}._0yZr2a_composerSelect[data-open]{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary)}._0yZr2a_composerSelect svg{opacity:.65;flex:none}._0yZr2a_composerSelect[data-open] svg{opacity:.9}._0yZr2a_composerSelectValue{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}._0yZr2a_composerSelectMenu{z-index:95;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 97%, transparent);backdrop-filter:blur(10px);border-radius:11px;max-height:264px;padding:5px;position:fixed;overflow:auto;box-shadow:0 14px 38px #0f172a2e}._0yZr2a_composerSelectMenu button{width:100%;color:var(--dsw-alias-label-primary);cursor:pointer;text-align:left;white-space:nowrap;background:0 0;border:none;border-radius:7px;padding:7px 10px;font-size:12.5px;line-height:1.45;display:block}._0yZr2a_composerSelectMenu button:hover{background:var(--dsw-alias-interactive-bg-hover)}._0yZr2a_composerSelectMenu button[data-selected]{color:var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 12%, transparent)}._0yZr2a_composerSend{background:var(--dsw-alias-label-primary);width:34px;height:34px;color:var(--dsw-alias-bg-layer-1);cursor:pointer;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;margin-left:auto;display:inline-flex}._0yZr2a_composerSend:hover{opacity:.88}._0yZr2a_composerSend:disabled{opacity:.35;cursor:not-allowed}._0yZr2a_configNode{cursor:grab;padding:0 14px 14px}._0yZr2a_configNode ._0yZr2a_nodeHeader{padding:10px 2px 6px;font-size:12px}._0yZr2a_configLinks{flex:none;align-items:center;margin:4px 0 10px;display:flex}._0yZr2a_configLinks ._0yZr2a_composerChip{padding:3px 10px;font-size:11px}._0yZr2a_configHint{min-height:0;color:var(--dsw-alias-label-tertiary);flex:1;margin:0;font-size:11.5px;line-height:1.7;overflow:auto}._0yZr2a_handle{background:var(--dsw-alias-bg-layer-1);border:2px solid var(--dsw-alias-brand-primary);opacity:0;cursor:crosshair;z-index:3;border-radius:50%;width:12px;height:12px;transition:opacity .12s,transform .12s;position:absolute;top:50%;transform:translateY(-50%)scale(.6)}._0yZr2a_handleLeft{left:-7px}._0yZr2a_handleRight{right:-7px}._0yZr2a_node:hover ._0yZr2a_handle,._0yZr2a_nodeSelected ._0yZr2a_handle,._0yZr2a_nodeConnectTarget ._0yZr2a_handle{opacity:1;transform:translateY(-50%)scale(1)}._0yZr2a_handle:hover{background:var(--dsw-alias-brand-primary)}._0yZr2a_handleRight{width:20px;height:20px;color:var(--dsw-alias-brand-primary);justify-content:center;align-items:center;font-size:13px;font-weight:600;line-height:1;display:flex;right:-10px}._0yZr2a_handleRight:after{content:\"+\"}._0yZr2a_handleRight:hover{color:var(--dsw-alias-bg-layer-1);transform:translateY(-50%)scale(1.12)}._0yZr2a_resizeHandle{background:var(--dsw-alias-brand-primary);border:2px solid var(--dsw-alias-bg-layer-1);cursor:nwse-resize;z-index:3;border-radius:4px;width:14px;height:14px;position:absolute;bottom:-5px;right:-5px}._0yZr2a_hoverToolbar{border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 92%, transparent);opacity:0;pointer-events:none;z-index:4;border-radius:10px;gap:2px;padding:4px;transition:opacity .12s;display:flex;position:absolute;top:-36px;left:50%;transform:translate(-50%);box-shadow:0 8px 22px #0f172a24}._0yZr2a_node:hover ._0yZr2a_hoverToolbar,._0yZr2a_nodeSelected ._0yZr2a_hoverToolbar{opacity:1;pointer-events:auto}._0yZr2a_connectionLayer{pointer-events:none;z-index:0;position:absolute;overflow:visible}._0yZr2a_connectionPath{fill:none;stroke-width:1.8px;stroke-opacity:.9;pointer-events:none}._0yZr2a_connectionActive{stroke-width:2.6px;stroke-opacity:1;filter:drop-shadow(0 0 6px color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, transparent))}._0yZr2a_connectionPreview{fill:none;stroke:var(--dsw-alias-brand-primary);stroke-width:2px;stroke-dasharray:5 5;pointer-events:none}._0yZr2a_connectionFlow{fill:none;stroke:var(--dsw-alias-brand-primary);stroke-width:2px;stroke-linecap:round;stroke-dasharray:30 90;opacity:.4;pointer-events:none;animation:1.6s linear infinite _0yZr2a_connectionFlow}._0yZr2a_connectionFlowActive{stroke:var(--dsw-alias-brand-primary);opacity:.85}@keyframes _0yZr2a_connectionFlow{to{stroke-dashoffset:-120px}}@media (prefers-reduced-motion:reduce){._0yZr2a_connectionFlow{opacity:.35;animation:none}}._0yZr2a_emptyHint{text-align:center;color:var(--dsw-alias-label-tertiary);pointer-events:none;z-index:5;flex-direction:column;align-items:center;gap:6px;display:flex;position:absolute;top:44%;left:50%;transform:translate(-50%,-50%)}._0yZr2a_emptyHint strong{color:var(--dsw-alias-label-secondary);font-size:16px}._0yZr2a_emptyHint span{max-width:320px;font-size:12.5px;line-height:1.6}._0yZr2a_zoomDock{z-index:30;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 88%, transparent);backdrop-filter:blur(10px);border-radius:12px;align-items:center;gap:6px;padding:6px 8px;display:flex;position:absolute;bottom:14px;left:14px;box-shadow:0 10px 30px #0f172a1f}._0yZr2a_zoomDock input[type=range]{width:96px;accent-color:var(--dsw-alias-brand-primary)}._0yZr2a_zoomValue{text-align:right;width:40px;color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;font-size:11.5px}._0yZr2a_minimap{z-index:30;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 88%, transparent);backdrop-filter:blur(10px);border-radius:12px;width:220px;height:150px;position:absolute;bottom:62px;left:14px;overflow:hidden;box-shadow:0 10px 30px #0f172a1f}._0yZr2a_minimapCanvas{cursor:crosshair;width:100%;height:100%;position:relative}._0yZr2a_minimapNode{opacity:.8;border-radius:2px;position:absolute}._0yZr2a_minimapImage{background:var(--dsw-alias-brand-primary)}._0yZr2a_minimapText{background:color-mix(in srgb, var(--dsw-alias-label-primary) 40%, transparent)}._0yZr2a_minimapSelected{outline:1.5px solid var(--dsw-alias-brand-primary)}._0yZr2a_minimapViewport{border:1.5px solid var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 10%, transparent);pointer-events:none;border-radius:2px;position:absolute}._0yZr2a_inspectorRow{gap:8px;display:flex}._0yZr2a_inspectorRow>*{flex:1;min-width:0}._0yZr2a_contextMenu{z-index:90;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 96%, transparent);border-radius:11px;flex-direction:column;min-width:176px;padding:5px;display:flex;position:fixed;box-shadow:0 16px 40px #0f172a33}._0yZr2a_contextMenu button{color:var(--dsw-alias-label-primary);cursor:pointer;text-align:left;background:0 0;border:none;border-radius:7px;align-items:center;gap:8px;padding:7px 10px;font-size:12.5px;display:flex}._0yZr2a_contextMenu button:hover{background:var(--dsw-alias-interactive-bg-hover)}._0yZr2a_contextMenu button[data-danger]{color:var(--dsw-alias-label-error)}._0yZr2a_errorToast{z-index:60;border:1px solid color-mix(in srgb, var(--dsw-alias-label-error) 35%, transparent);background:color-mix(in srgb, var(--dsw-alias-label-error) 12%, var(--dsw-alias-bg-layer-1));max-width:min(560px,80%);color:var(--dsw-alias-label-error);border-radius:10px;align-items:center;gap:10px;padding:9px 12px;font-size:12.5px;display:flex;position:absolute;bottom:18px;left:50%;transform:translate(-50%);box-shadow:0 12px 30px #0f172a2e}._0yZr2a_errorToast button{color:inherit;cursor:pointer;background:0 0;border:none;flex:none;padding:2px;display:inline-flex}._0yZr2a_modalBackdrop{z-index:70;background:color-mix(in srgb, var(--dsw-alias-label-primary) 32%, transparent);justify-content:center;align-items:center;display:flex;position:absolute;inset:0}._0yZr2a_picker{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:14px;flex-direction:column;width:min(720px,92%);max-height:84%;display:flex;overflow:hidden;box-shadow:0 24px 60px #0f172a42}._0yZr2a_pickerHeader{border-bottom:1px solid var(--dsw-alias-border-l1);justify-content:space-between;align-items:center;padding:12px 14px;font-size:14px;display:flex}._0yZr2a_pickerHeader button{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0 4px;font-size:18px}._0yZr2a_pickerTabs{gap:4px;padding:10px 14px 0;display:flex}._0yZr2a_pickerTabs button{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:8px 8px 0 0;padding:7px 12px;font-size:12.5px}._0yZr2a_pickerTabs button[data-active]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-brand-primary)}._0yZr2a_pickerBody{flex:1;min-height:0;padding:14px;overflow:auto}._0yZr2a_pickerGrid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px;display:grid}._0yZr2a_pickerCard{border:1.5px solid var(--dsw-alias-border-l1);cursor:pointer;text-align:left;color:var(--dsw-alias-label-primary);background:0 0;border-radius:10px;flex-direction:column;gap:6px;padding:6px;display:flex}._0yZr2a_pickerCard[data-selected]{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 2px color-mix(in srgb, var(--dsw-alias-brand-primary) 25%, transparent)}._0yZr2a_pickerCard img{object-fit:cover;border-radius:7px;width:100%;height:110px}._0yZr2a_pickerCardPrompt{text-overflow:ellipsis;white-space:nowrap;font-size:11.5px;overflow:hidden}._0yZr2a_pickerCard small{color:var(--dsw-alias-label-tertiary);font-size:10.5px}._0yZr2a_pickerFooter{color:var(--dsw-alias-label-secondary);justify-content:space-between;align-items:center;padding-top:12px;font-size:12.5px;display:flex}._0yZr2a_pickerFooter button,._0yZr2a_generateForm button{background:var(--dsw-alias-brand-primary);height:32px;color:var(--dsw-alias-bg-base,#fff);cursor:pointer;border:none;border-radius:8px;align-items:center;gap:6px;padding:0 16px;font-size:12.5px;font-weight:600;display:inline-flex}._0yZr2a_pickerFooter button:disabled,._0yZr2a_generateForm button:disabled{opacity:.45;cursor:not-allowed}._0yZr2a_uploadBox{border:1.5px dashed color-mix(in srgb, var(--dsw-alias-label-primary) 22%, transparent);min-height:220px;color:var(--dsw-alias-label-secondary);cursor:pointer;text-align:center;border-radius:12px;flex-direction:column;justify-content:center;align-items:center;gap:8px;display:flex}._0yZr2a_uploadBox:hover{border-color:var(--dsw-alias-brand-primary)}._0yZr2a_uploadBox input{display:none}._0yZr2a_uploadBox small{color:var(--dsw-alias-label-tertiary);font-size:11px}._0yZr2a_uploadIcon{color:var(--dsw-alias-brand-primary)}._0yZr2a_generateForm{flex-direction:column;gap:10px;display:flex}._0yZr2a_generateForm textarea{resize:vertical;border:1px solid var(--dsw-alias-border-l1);min-height:110px;color:var(--dsw-alias-label-primary);background:0 0;border-radius:9px;outline:none;padding:8px 10px;font-size:12.5px}._0yZr2a_generateForm select{border:1px solid var(--dsw-alias-border-l1);height:30px;color:var(--dsw-alias-label-primary);background:0 0;border-radius:8px;padding:0 8px;font-size:12.5px}@keyframes _0yZr2a_canvasSpin{to{transform:rotate(360deg)}}";
37996
+ const css$3 = "._0yZr2a_root{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);min-width:0;height:100%;min-height:0;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-family,inherit);user-select:none;border-radius:10px;flex-direction:column;flex:auto;display:flex;position:relative;overflow:hidden}._0yZr2a_selectCursor{cursor:default}._0yZr2a_panCursor{cursor:grab}._0yZr2a_panCursor:active{cursor:grabbing}._0yZr2a_topBar{border-bottom:1px solid var(--dsw-alias-border-l1);z-index:40;background:var(--dsw-alias-bg-layer-1);flex:none;align-items:center;gap:8px;padding:8px 12px;display:flex}._0yZr2a_projectSelect{border:1px solid var(--dsw-alias-border-l1);max-width:180px;height:30px;color:var(--dsw-alias-label-primary);background:0 0;border-radius:8px;padding:0 8px;font-size:12.5px}._0yZr2a_titleButton{height:30px;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;cursor:text;background:0 0;border:1px solid #0000;border-radius:8px;max-width:260px;padding:0 10px;font-size:13px;font-weight:600;overflow:hidden}._0yZr2a_titleButton:hover{border-color:var(--dsw-alias-border-l1)}._0yZr2a_titleInput{border:1px solid var(--dsw-alias-brand-primary);height:30px;color:var(--dsw-alias-label-primary);background:0 0;border-radius:8px;outline:none;width:240px;padding:0 10px;font-size:13px;font-weight:600}._0yZr2a_topBarSpacer{flex:1}._0yZr2a_saveState{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-size:11.5px}._0yZr2a_saveState[data-state=error]{color:var(--dsw-alias-label-error)}._0yZr2a_saveState[data-state=saving]{color:var(--dsw-alias-state-warn-primary,var(--dsw-alias-label-secondary))}._0yZr2a_iconButton{width:30px;height:30px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:8px;flex:none;justify-content:center;align-items:center;gap:5px;padding:0;display:inline-flex}._0yZr2a_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._0yZr2a_iconButton[data-active]{background:color-mix(in srgb, var(--dsw-alias-brand-primary) 16%, transparent);color:var(--dsw-alias-brand-primary)}._0yZr2a_iconButton:disabled{opacity:.35;cursor:not-allowed}._0yZr2a_iconButton:disabled:hover{color:var(--dsw-alias-label-secondary);background:0 0}._0yZr2a_viewport{touch-action:none;flex:1;min-height:0;position:relative;overflow:hidden}._0yZr2a_grid{pointer-events:none;opacity:.5;position:absolute;inset:0}._0yZr2a_flowCanvas,._0yZr2a_liquidCanvas,._0yZr2a_sceneCanvas{width:100%;height:100%;position:absolute;inset:0}._0yZr2a_grid[data-mode=flow],._0yZr2a_grid[data-mode=liquid],._0yZr2a_grid[data-mode=floatingLines],._0yZr2a_grid[data-mode=galaxy],._0yZr2a_grid[data-mode=silk],._0yZr2a_grid[data-mode=waves],._0yZr2a_grid[data-mode=faultyTerminal],._0yZr2a_grid[data-mode=dotField],._0yZr2a_grid[data-mode=dotGrid],._0yZr2a_grid[data-mode=shapeGrid]{opacity:1}._0yZr2a_grid[data-mode=dots]{background-image:radial-gradient(circle, color-mix(in srgb, var(--dsw-alias-label-primary) 30%, transparent) 1.1px, transparent 1.4px)}._0yZr2a_grid[data-mode=lines]{background-image:linear-gradient(color-mix(in srgb, var(--dsw-alias-label-primary) 9%, transparent) 1px, transparent 1px), linear-gradient(90deg, color-mix(in srgb, var(--dsw-alias-label-primary) 9%, transparent) 1px, transparent 1px)}._0yZr2a_grid[data-mode=blank],._0yZr2a_grid[data-mode=image]{background-image:none}._0yZr2a_gridScrim{background:var(--dsw-alias-bg-layer-1);opacity:.6;position:absolute;inset:0}._0yZr2a_backgroundMenu{z-index:45;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 96%, transparent);border-radius:11px;flex-direction:column;min-width:168px;padding:5px;display:flex;position:absolute;transform:translate(-50%,-100%);box-shadow:0 16px 40px #0f172a33}._0yZr2a_backgroundMenu button{color:var(--dsw-alias-label-primary);cursor:pointer;text-align:left;background:0 0;border:none;border-radius:7px;justify-content:flex-start;align-items:center;padding:7px 10px;font-size:12.5px;display:flex}._0yZr2a_backgroundMenu button:hover{background:var(--dsw-alias-interactive-bg-hover)}._0yZr2a_backgroundMenu button[data-active]{color:var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 12%, transparent)}._0yZr2a_backgroundMenuDivider{background:var(--dsw-alias-border-l1);height:1px;margin:4px 6px}._0yZr2a_world{transform-origin:0 0;position:absolute;top:0;left:0}._0yZr2a_marquee{z-index:20;border:1px solid var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 8%, transparent);pointer-events:none;border-radius:4px;position:absolute}._0yZr2a_node{border:1.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);cursor:grab;touch-action:none;border-radius:14px;flex-direction:column;display:flex;position:absolute;overflow:visible;box-shadow:0 8px 24px #0f172a1f}._0yZr2a_node:active{cursor:grabbing}._0yZr2a_nodeGlow{pointer-events:none;opacity:0;border-radius:18px;transition:opacity .15s;position:absolute;inset:-6px}._0yZr2a_nodeSelected{border-color:var(--dsw-alias-brand-primary);z-index:2}._0yZr2a_nodeSelected ._0yZr2a_nodeGlow{opacity:1;box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-brand-primary) 22%, transparent)}._0yZr2a_nodeRelated{border-color:color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, transparent)}._0yZr2a_nodeConnectTarget{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 4px color-mix(in srgb, var(--dsw-alias-brand-primary) 26%, transparent)}._0yZr2a_nodeHeader{color:var(--dsw-alias-label-secondary);cursor:inherit;flex:none;align-items:center;gap:6px;padding:7px 12px 5px;font-size:11.5px;display:flex}._0yZr2a_nodeTitle{text-overflow:ellipsis;white-space:nowrap;font-weight:600;overflow:hidden}._0yZr2a_nodeSize{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;margin-left:auto;font-size:10.5px}._0yZr2a_nodeSpinner{border:1.5px solid color-mix(in srgb, var(--dsw-alias-brand-primary) 30%, transparent);border-top-color:var(--dsw-alias-brand-primary);border-radius:50%;flex:none;width:11px;height:11px;animation:.8s linear infinite _0yZr2a_canvasSpin}._0yZr2a_nodeBody{background:color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent);pointer-events:none;border-radius:9px;flex:1;justify-content:center;align-items:center;min-height:0;margin:0 8px 8px;display:flex;overflow:hidden}._0yZr2a_nodeBody img{object-fit:contain;width:100%;height:100%;display:block}._0yZr2a_imageInfo{z-index:2;background:color-mix(in srgb, var(--dsw-alias-label-primary) 62%, transparent);color:var(--dsw-alias-bg-layer-1);pointer-events:none;backdrop-filter:blur(3px);text-overflow:ellipsis;white-space:nowrap;border-radius:6px;max-width:calc(100% - 90px);padding:3px 8px;font-size:10.5px;line-height:1.4;position:absolute;top:6px;overflow:hidden}._0yZr2a_imageInfoLeft{font-weight:600;left:6px}._0yZr2a_imageInfoRight{font-variant-numeric:tabular-nums;opacity:.85;left:auto;right:6px}._0yZr2a_nodeState,._0yZr2a_nodeStateError{color:var(--dsw-alias-label-secondary);text-align:center;pointer-events:auto;flex-direction:column;align-items:center;gap:8px;padding:12px;font-size:12px;display:flex}._0yZr2a_nodeStateError{color:var(--dsw-alias-label-error)}._0yZr2a_nodeStateError button{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);cursor:pointer;border:none;border-radius:7px;padding:4px 12px;font-size:12px}._0yZr2a_nodeEmpty{border:1.5px dashed color-mix(in srgb, var(--dsw-alias-label-primary) 24%, transparent);color:var(--dsw-alias-label-tertiary);cursor:pointer;pointer-events:auto;background:0 0;border-radius:9px;flex-direction:column;align-items:center;gap:8px;margin:6px;padding:14px;font-size:12px;display:flex}._0yZr2a_nodeEmpty:hover{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary)}._0yZr2a_textNode{cursor:default}._0yZr2a_imageNode ._0yZr2a_nodeBody{margin:6px}._0yZr2a_textArea{resize:none;min-height:0;color:var(--dsw-alias-label-primary);cursor:text;pointer-events:auto;background:0 0;border:none;outline:none;flex:1;margin:0 8px 8px;padding:4px 6px;font-size:13px;line-height:1.55}._0yZr2a_textArea::placeholder{color:var(--dsw-alias-label-tertiary)}._0yZr2a_dock{z-index:30;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 92%, transparent);backdrop-filter:blur(10px);border-radius:13px;align-items:center;gap:2px;padding:6px;display:flex;position:absolute;bottom:14px;left:50%;transform:translate(-50%);box-shadow:0 10px 30px #0f172a24}._0yZr2a_dock ._0yZr2a_iconButton{width:40px;height:40px;transform:translateY(var(--dock-lift,0px)) scale(var(--dock-scale,1));transform-origin:50% 100%;border-radius:11px;transition:transform .16s cubic-bezier(.33,1,.68,1),background .15s,color .15s,box-shadow .18s;position:relative}._0yZr2a_dock ._0yZr2a_iconButton:not(:disabled):hover{z-index:2;box-shadow:0 6px 14px color-mix(in srgb, var(--dsw-alias-label-primary) 20%, transparent)}._0yZr2a_dock ._0yZr2a_iconButton:not(:disabled):active{transform:translateY(var(--dock-lift,0px)) scale(.94)}._0yZr2a_dock ._0yZr2a_iconButton[data-active],._0yZr2a_dock ._0yZr2a_iconButton[data-active]:hover{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-1)}._0yZr2a_dockDivider{background:var(--dsw-alias-border-l1);width:1px;height:18px;margin:0 4px}._0yZr2a_composer{z-index:35;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 96%, transparent);backdrop-filter:blur(10px);border-radius:14px;flex-direction:column;gap:8px;width:560px;padding:10px;display:flex;position:absolute;box-shadow:0 16px 44px #0f172a2e}._0yZr2a_composerPrompt{resize:none;width:100%;min-height:38px;max-height:120px;color:var(--dsw-alias-label-primary);cursor:text;background:0 0;border:none;outline:none;padding:2px 4px;font-size:13px;line-height:1.5}._0yZr2a_composerPrompt::placeholder{color:var(--dsw-alias-label-tertiary)}._0yZr2a_composerMeta{display:flex}._0yZr2a_composerChip{border:1px solid color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, transparent);color:var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 8%, transparent);border-radius:999px;align-items:center;gap:5px;padding:2px 9px;font-size:11px;display:inline-flex}._0yZr2a_composerControls{align-items:center;gap:6px;display:flex}._0yZr2a_composerControls select{border:1px solid var(--dsw-alias-border-l1);height:28px;color:var(--dsw-alias-label-primary);background:0 0;border-radius:999px;min-width:0;max-width:128px;padding:0 8px;font-size:11.5px}._0yZr2a_composerSelect{border:1px solid var(--dsw-alias-border-l1);height:28px;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:999px;align-items:center;gap:6px;min-width:0;max-width:138px;padding:0 8px 0 11px;font-size:11.5px;transition:background .15s,border-color .15s;display:inline-flex}._0yZr2a_composerSelect:hover{background:var(--dsw-alias-interactive-bg-hover)}._0yZr2a_composerSelect[data-open]{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary)}._0yZr2a_composerSelect svg{opacity:.65;flex:none}._0yZr2a_composerSelect[data-open] svg{opacity:.9}._0yZr2a_composerSelectValue{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}._0yZr2a_composerSelectMenu{z-index:95;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 97%, transparent);backdrop-filter:blur(10px);border-radius:11px;max-height:264px;padding:5px;position:fixed;overflow:auto;box-shadow:0 14px 38px #0f172a2e}._0yZr2a_composerSelectMenu button{width:100%;color:var(--dsw-alias-label-primary);cursor:pointer;text-align:left;white-space:nowrap;background:0 0;border:none;border-radius:7px;padding:7px 10px;font-size:12.5px;line-height:1.45;display:block}._0yZr2a_composerSelectMenu button:hover{background:var(--dsw-alias-interactive-bg-hover)}._0yZr2a_composerSelectMenu button[data-selected]{color:var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 12%, transparent)}._0yZr2a_composerSend{background:var(--dsw-alias-label-primary);width:34px;height:34px;color:var(--dsw-alias-bg-layer-1);cursor:pointer;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;margin-left:auto;display:inline-flex}._0yZr2a_composerSend:hover{opacity:.88}._0yZr2a_composerSend:disabled{opacity:.35;cursor:not-allowed}._0yZr2a_configNode{cursor:grab;padding:0 14px 14px}._0yZr2a_configNode ._0yZr2a_nodeHeader{padding:10px 2px 6px;font-size:12px}._0yZr2a_configLinks{flex:none;align-items:center;margin:4px 0 10px;display:flex}._0yZr2a_configLinks ._0yZr2a_composerChip{padding:3px 10px;font-size:11px}._0yZr2a_configHint{min-height:0;color:var(--dsw-alias-label-tertiary);flex:1;margin:0;font-size:11.5px;line-height:1.7;overflow:auto}._0yZr2a_handle{background:var(--dsw-alias-bg-layer-1);border:2px solid var(--dsw-alias-brand-primary);opacity:0;cursor:crosshair;z-index:3;border-radius:50%;width:12px;height:12px;transition:opacity .12s,transform .12s;position:absolute;top:50%;transform:translateY(-50%)scale(.6)}._0yZr2a_handleLeft{left:-7px}._0yZr2a_handleRight{right:-7px}._0yZr2a_node:hover ._0yZr2a_handle,._0yZr2a_nodeSelected ._0yZr2a_handle,._0yZr2a_nodeConnectTarget ._0yZr2a_handle{opacity:1;transform:translateY(-50%)scale(1)}._0yZr2a_handle:hover{background:var(--dsw-alias-brand-primary)}._0yZr2a_handleRight{width:20px;height:20px;color:var(--dsw-alias-brand-primary);justify-content:center;align-items:center;font-size:13px;font-weight:600;line-height:1;display:flex;right:-10px}._0yZr2a_handleRight:after{content:\"+\"}._0yZr2a_handleRight:hover{color:var(--dsw-alias-bg-layer-1);transform:translateY(-50%)scale(1.12)}._0yZr2a_resizeHandle{background:var(--dsw-alias-brand-primary);border:2px solid var(--dsw-alias-bg-layer-1);cursor:nwse-resize;z-index:3;border-radius:4px;width:14px;height:14px;position:absolute;bottom:-5px;right:-5px}._0yZr2a_hoverToolbar{border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 92%, transparent);opacity:0;pointer-events:none;z-index:4;border-radius:10px;gap:2px;padding:4px;transition:opacity .12s;display:flex;position:absolute;top:-36px;left:50%;transform:translate(-50%);box-shadow:0 8px 22px #0f172a24}._0yZr2a_node:hover ._0yZr2a_hoverToolbar,._0yZr2a_nodeSelected ._0yZr2a_hoverToolbar{opacity:1;pointer-events:auto}._0yZr2a_connectionLayer{pointer-events:none;z-index:0;position:absolute;overflow:visible}._0yZr2a_connectionPath{fill:none;stroke-width:1.8px;stroke-opacity:.9;pointer-events:none}._0yZr2a_connectionActive{stroke-width:2.6px;stroke-opacity:1;filter:drop-shadow(0 0 6px color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, transparent))}._0yZr2a_connectionPreview{fill:none;stroke:var(--dsw-alias-brand-primary);stroke-width:2px;stroke-dasharray:5 5;pointer-events:none}._0yZr2a_connectionFlow{fill:none;stroke:var(--dsw-alias-brand-primary);stroke-width:2px;stroke-linecap:round;stroke-dasharray:30 90;opacity:.4;pointer-events:none;animation:1.6s linear infinite _0yZr2a_connectionFlow}._0yZr2a_connectionFlowActive{stroke:var(--dsw-alias-brand-primary);opacity:.85}@keyframes _0yZr2a_connectionFlow{to{stroke-dashoffset:-120px}}@media (prefers-reduced-motion:reduce){._0yZr2a_connectionFlow{opacity:.35;animation:none}}._0yZr2a_emptyHint{text-align:center;color:var(--dsw-alias-label-tertiary);pointer-events:none;z-index:5;flex-direction:column;align-items:center;gap:6px;display:flex;position:absolute;top:44%;left:50%;transform:translate(-50%,-50%)}._0yZr2a_emptyHint strong{color:var(--dsw-alias-label-secondary);font-size:16px}._0yZr2a_emptyHint span{max-width:320px;font-size:12.5px;line-height:1.6}._0yZr2a_zoomDock{z-index:30;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 88%, transparent);backdrop-filter:blur(10px);border-radius:12px;align-items:center;gap:6px;padding:6px 8px;display:flex;position:absolute;bottom:14px;left:14px;box-shadow:0 10px 30px #0f172a1f}._0yZr2a_zoomDock input[type=range]{width:96px;accent-color:var(--dsw-alias-brand-primary)}._0yZr2a_zoomValue{text-align:right;width:40px;color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;font-size:11.5px}._0yZr2a_minimap{z-index:30;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 88%, transparent);backdrop-filter:blur(10px);border-radius:12px;width:220px;height:150px;position:absolute;bottom:62px;left:14px;overflow:hidden;box-shadow:0 10px 30px #0f172a1f}._0yZr2a_minimapCanvas{cursor:crosshair;width:100%;height:100%;position:relative}._0yZr2a_minimapNode{opacity:.8;border-radius:2px;position:absolute}._0yZr2a_minimapImage{background:var(--dsw-alias-brand-primary)}._0yZr2a_minimapText{background:color-mix(in srgb, var(--dsw-alias-label-primary) 40%, transparent)}._0yZr2a_minimapSelected{outline:1.5px solid var(--dsw-alias-brand-primary)}._0yZr2a_minimapViewport{border:1.5px solid var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 10%, transparent);pointer-events:none;border-radius:2px;position:absolute}._0yZr2a_inspectorRow{gap:8px;display:flex}._0yZr2a_inspectorRow>*{flex:1;min-width:0}._0yZr2a_contextMenu{z-index:90;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 96%, transparent);border-radius:11px;flex-direction:column;min-width:176px;padding:5px;display:flex;position:fixed;box-shadow:0 16px 40px #0f172a33}._0yZr2a_contextMenu button{color:var(--dsw-alias-label-primary);cursor:pointer;text-align:left;background:0 0;border:none;border-radius:7px;align-items:center;gap:8px;padding:7px 10px;font-size:12.5px;display:flex}._0yZr2a_contextMenu button:hover{background:var(--dsw-alias-interactive-bg-hover)}._0yZr2a_contextMenu button[data-danger]{color:var(--dsw-alias-label-error)}._0yZr2a_errorToast{z-index:60;border:1px solid color-mix(in srgb, var(--dsw-alias-label-error) 35%, transparent);background:color-mix(in srgb, var(--dsw-alias-label-error) 12%, var(--dsw-alias-bg-layer-1));max-width:min(560px,80%);color:var(--dsw-alias-label-error);border-radius:10px;align-items:center;gap:10px;padding:9px 12px;font-size:12.5px;display:flex;position:absolute;bottom:18px;left:50%;transform:translate(-50%);box-shadow:0 12px 30px #0f172a2e}._0yZr2a_errorToast button{color:inherit;cursor:pointer;background:0 0;border:none;flex:none;padding:2px;display:inline-flex}._0yZr2a_modalBackdrop{z-index:70;background:color-mix(in srgb, var(--dsw-alias-label-primary) 32%, transparent);justify-content:center;align-items:center;display:flex;position:absolute;inset:0}._0yZr2a_picker{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:14px;flex-direction:column;width:min(720px,92%);max-height:84%;display:flex;overflow:hidden;box-shadow:0 24px 60px #0f172a42}._0yZr2a_pickerHeader{border-bottom:1px solid var(--dsw-alias-border-l1);justify-content:space-between;align-items:center;padding:12px 14px;font-size:14px;display:flex}._0yZr2a_pickerHeader button{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0 4px;font-size:18px}._0yZr2a_pickerTabs{gap:4px;padding:10px 14px 0;display:flex}._0yZr2a_pickerTabs button{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:8px 8px 0 0;padding:7px 12px;font-size:12.5px}._0yZr2a_pickerTabs button[data-active]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-brand-primary)}._0yZr2a_pickerBody{flex:1;min-height:0;padding:14px;overflow:auto}._0yZr2a_pickerGrid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px;display:grid}._0yZr2a_pickerCard{border:1.5px solid var(--dsw-alias-border-l1);cursor:pointer;text-align:left;color:var(--dsw-alias-label-primary);background:0 0;border-radius:10px;flex-direction:column;gap:6px;padding:6px;display:flex}._0yZr2a_pickerCard[data-selected]{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 2px color-mix(in srgb, var(--dsw-alias-brand-primary) 25%, transparent)}._0yZr2a_pickerCard img{object-fit:cover;border-radius:7px;width:100%;height:110px}._0yZr2a_pickerCardPrompt{text-overflow:ellipsis;white-space:nowrap;font-size:11.5px;overflow:hidden}._0yZr2a_pickerCard small{color:var(--dsw-alias-label-tertiary);font-size:10.5px}._0yZr2a_pickerFooter{color:var(--dsw-alias-label-secondary);justify-content:space-between;align-items:center;padding-top:12px;font-size:12.5px;display:flex}._0yZr2a_pickerFooter button,._0yZr2a_generateForm button{background:var(--dsw-alias-brand-primary);height:32px;color:var(--dsw-alias-bg-base,#fff);cursor:pointer;border:none;border-radius:8px;align-items:center;gap:6px;padding:0 16px;font-size:12.5px;font-weight:600;display:inline-flex}._0yZr2a_pickerFooter button:disabled,._0yZr2a_generateForm button:disabled{opacity:.45;cursor:not-allowed}._0yZr2a_uploadBox{border:1.5px dashed color-mix(in srgb, var(--dsw-alias-label-primary) 22%, transparent);min-height:220px;color:var(--dsw-alias-label-secondary);cursor:pointer;text-align:center;border-radius:12px;flex-direction:column;justify-content:center;align-items:center;gap:8px;display:flex}._0yZr2a_uploadBox:hover{border-color:var(--dsw-alias-brand-primary)}._0yZr2a_uploadBox input{display:none}._0yZr2a_uploadBox small{color:var(--dsw-alias-label-tertiary);font-size:11px}._0yZr2a_uploadIcon{color:var(--dsw-alias-brand-primary)}._0yZr2a_generateForm{flex-direction:column;gap:10px;display:flex}._0yZr2a_generateForm textarea{resize:vertical;border:1px solid var(--dsw-alias-border-l1);min-height:110px;color:var(--dsw-alias-label-primary);background:0 0;border-radius:9px;outline:none;padding:8px 10px;font-size:12.5px}._0yZr2a_generateForm select{border:1px solid var(--dsw-alias-border-l1);height:30px;color:var(--dsw-alias-label-primary);background:0 0;border-radius:8px;padding:0 8px;font-size:12.5px}@keyframes _0yZr2a_canvasSpin{to{transform:rotate(360deg)}}";
37979
37997
  const tagId$3 = "@dickpy/dsh-imagegen/canvas-workspace.module.css";
37980
37998
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
37981
37999
  const tag = document.createElement("style");
@@ -37985,188 +38003,2341 @@ window.__ModuleLoader__.load({
37985
38003
  document.head.appendChild(tag);
37986
38004
  }
37987
38005
  var canvas_workspace_module_css_default = {
37988
- "nodeState": "_0yZr2a_nodeState",
37989
- "minimapText": "_0yZr2a_minimapText",
37990
- "nodeBody": "_0yZr2a_nodeBody",
37991
- "textNode": "_0yZr2a_textNode",
37992
- "textArea": "_0yZr2a_textArea",
37993
- "minimapCanvas": "_0yZr2a_minimapCanvas",
37994
38006
  "nodeSelected": "_0yZr2a_nodeSelected",
37995
- "modalBackdrop": "_0yZr2a_modalBackdrop",
37996
- "marquee": "_0yZr2a_marquee",
37997
- "handleLeft": "_0yZr2a_handleLeft",
37998
- "projectSelect": "_0yZr2a_projectSelect",
37999
- "imageInfo": "_0yZr2a_imageInfo",
38000
- "handle": "_0yZr2a_handle",
38001
- "connectionActive": "_0yZr2a_connectionActive",
38002
- "minimapNode": "_0yZr2a_minimapNode",
38003
- "inspectorRow": "_0yZr2a_inspectorRow",
38004
- "nodeRelated": "_0yZr2a_nodeRelated",
38005
- "errorToast": "_0yZr2a_errorToast",
38006
- "backgroundMenu": "_0yZr2a_backgroundMenu",
38007
- "connectionLayer": "_0yZr2a_connectionLayer",
38008
- "connectionPreview": "_0yZr2a_connectionPreview",
38009
38007
  "dockDivider": "_0yZr2a_dockDivider",
38010
- "configNode": "_0yZr2a_configNode",
38011
- "zoomDock": "_0yZr2a_zoomDock",
38012
- "picker": "_0yZr2a_picker",
38008
+ "composerSend": "_0yZr2a_composerSend",
38009
+ "pickerCardPrompt": "_0yZr2a_pickerCardPrompt",
38010
+ "nodeRelated": "_0yZr2a_nodeRelated",
38011
+ "liquidCanvas": "_0yZr2a_liquidCanvas",
38012
+ "textArea": "_0yZr2a_textArea",
38013
38013
  "topBar": "_0yZr2a_topBar",
38014
- "imageNode": "_0yZr2a_imageNode",
38014
+ "titleButton": "_0yZr2a_titleButton",
38015
+ "backgroundMenu": "_0yZr2a_backgroundMenu",
38016
+ "nodeBody": "_0yZr2a_nodeBody",
38015
38017
  "handleRight": "_0yZr2a_handleRight",
38018
+ "connectionPreview": "_0yZr2a_connectionPreview",
38019
+ "handle": "_0yZr2a_handle",
38020
+ "contextMenu": "_0yZr2a_contextMenu",
38021
+ "canvasSpin": "_0yZr2a_canvasSpin",
38022
+ "textNode": "_0yZr2a_textNode",
38023
+ "minimapViewport": "_0yZr2a_minimapViewport",
38024
+ "uploadBox": "_0yZr2a_uploadBox",
38025
+ "sceneCanvas": "_0yZr2a_sceneCanvas",
38026
+ "viewport": "_0yZr2a_viewport",
38027
+ "root": "_0yZr2a_root",
38016
38028
  "panCursor": "_0yZr2a_panCursor",
38017
- "grid": "_0yZr2a_grid",
38018
- "composer": "_0yZr2a_composer",
38019
- "composerControls": "_0yZr2a_composerControls",
38020
- "connectionFlow": "_0yZr2a_connectionFlow",
38029
+ "marquee": "_0yZr2a_marquee",
38021
38030
  "saveState": "_0yZr2a_saveState",
38022
- "zoomValue": "_0yZr2a_zoomValue",
38031
+ "grid": "_0yZr2a_grid",
38032
+ "nodeGlow": "_0yZr2a_nodeGlow",
38033
+ "iconButton": "_0yZr2a_iconButton",
38034
+ "composerPrompt": "_0yZr2a_composerPrompt",
38035
+ "composerMeta": "_0yZr2a_composerMeta",
38036
+ "nodeConnectTarget": "_0yZr2a_nodeConnectTarget",
38037
+ "dock": "_0yZr2a_dock",
38023
38038
  "composerSelectValue": "_0yZr2a_composerSelectValue",
38024
- "minimapViewport": "_0yZr2a_minimapViewport",
38025
- "flowCanvas": "_0yZr2a_flowCanvas",
38039
+ "world": "_0yZr2a_world",
38040
+ "hoverToolbar": "_0yZr2a_hoverToolbar",
38041
+ "connectionActive": "_0yZr2a_connectionActive",
38042
+ "nodeEmpty": "_0yZr2a_nodeEmpty",
38043
+ "configHint": "_0yZr2a_configHint",
38044
+ "composerSelect": "_0yZr2a_composerSelect",
38045
+ "emptyHint": "_0yZr2a_emptyHint",
38046
+ "zoomDock": "_0yZr2a_zoomDock",
38026
38047
  "pickerTabs": "_0yZr2a_pickerTabs",
38027
- "uploadBox": "_0yZr2a_uploadBox",
38028
38048
  "topBarSpacer": "_0yZr2a_topBarSpacer",
38029
- "root": "_0yZr2a_root",
38049
+ "uploadIcon": "_0yZr2a_uploadIcon",
38050
+ "composer": "_0yZr2a_composer",
38051
+ "pickerFooter": "_0yZr2a_pickerFooter",
38052
+ "picker": "_0yZr2a_picker",
38053
+ "nodeStateError": "_0yZr2a_nodeStateError",
38054
+ "connectionPath": "_0yZr2a_connectionPath",
38055
+ "pickerHeader": "_0yZr2a_pickerHeader",
38056
+ "nodeSize": "_0yZr2a_nodeSize",
38057
+ "imageNode": "_0yZr2a_imageNode",
38058
+ "minimapCanvas": "_0yZr2a_minimapCanvas",
38059
+ "node": "_0yZr2a_node",
38060
+ "connectionLayer": "_0yZr2a_connectionLayer",
38061
+ "configLinks": "_0yZr2a_configLinks",
38030
38062
  "gridScrim": "_0yZr2a_gridScrim",
38063
+ "connectionFlow": "_0yZr2a_connectionFlow",
38064
+ "nodeState": "_0yZr2a_nodeState",
38065
+ "zoomValue": "_0yZr2a_zoomValue",
38066
+ "imageInfo": "_0yZr2a_imageInfo",
38067
+ "minimapText": "_0yZr2a_minimapText",
38031
38068
  "resizeHandle": "_0yZr2a_resizeHandle",
38032
- "nodeTitle": "_0yZr2a_nodeTitle",
38069
+ "titleInput": "_0yZr2a_titleInput",
38070
+ "minimap": "_0yZr2a_minimap",
38071
+ "pickerGrid": "_0yZr2a_pickerGrid",
38072
+ "pickerCard": "_0yZr2a_pickerCard",
38073
+ "inspectorRow": "_0yZr2a_inspectorRow",
38033
38074
  "pickerBody": "_0yZr2a_pickerBody",
38034
- "backgroundMenuDivider": "_0yZr2a_backgroundMenuDivider",
38075
+ "imageInfoLeft": "_0yZr2a_imageInfoLeft",
38076
+ "generateForm": "_0yZr2a_generateForm",
38035
38077
  "nodeHeader": "_0yZr2a_nodeHeader",
38036
- "canvasSpin": "_0yZr2a_canvasSpin",
38037
- "imageInfoRight": "_0yZr2a_imageInfoRight",
38038
- "composerChip": "_0yZr2a_composerChip",
38039
- "composerSelect": "_0yZr2a_composerSelect",
38040
- "nodeEmpty": "_0yZr2a_nodeEmpty",
38041
- "composerMeta": "_0yZr2a_composerMeta",
38042
- "titleButton": "_0yZr2a_titleButton",
38043
- "hoverToolbar": "_0yZr2a_hoverToolbar",
38044
- "pickerCard": "_0yZr2a_pickerCard",
38045
- "pickerFooter": "_0yZr2a_pickerFooter",
38046
- "nodeSize": "_0yZr2a_nodeSize",
38047
- "emptyHint": "_0yZr2a_emptyHint",
38048
- "pickerGrid": "_0yZr2a_pickerGrid",
38049
- "composerPrompt": "_0yZr2a_composerPrompt",
38050
- "nodeSpinner": "_0yZr2a_nodeSpinner",
38051
- "nodeGlow": "_0yZr2a_nodeGlow",
38052
- "nodeStateError": "_0yZr2a_nodeStateError",
38053
38078
  "composerSelectMenu": "_0yZr2a_composerSelectMenu",
38054
- "configLinks": "_0yZr2a_configLinks",
38055
- "connectionPath": "_0yZr2a_connectionPath",
38056
38079
  "minimapSelected": "_0yZr2a_minimapSelected",
38057
- "auroraDrift": "_0yZr2a_auroraDrift",
38058
- "configHint": "_0yZr2a_configHint",
38059
- "contextMenu": "_0yZr2a_contextMenu",
38060
- "imageInfoLeft": "_0yZr2a_imageInfoLeft",
38061
- "generateForm": "_0yZr2a_generateForm",
38062
- "node": "_0yZr2a_node",
38063
- "titleInput": "_0yZr2a_titleInput",
38064
- "pickerCardPrompt": "_0yZr2a_pickerCardPrompt",
38065
- "iconButton": "_0yZr2a_iconButton",
38066
- "viewport": "_0yZr2a_viewport",
38067
- "uploadIcon": "_0yZr2a_uploadIcon",
38068
- "pickerHeader": "_0yZr2a_pickerHeader",
38080
+ "handleLeft": "_0yZr2a_handleLeft",
38069
38081
  "selectCursor": "_0yZr2a_selectCursor",
38070
- "world": "_0yZr2a_world",
38071
- "composerSend": "_0yZr2a_composerSend",
38082
+ "nodeSpinner": "_0yZr2a_nodeSpinner",
38083
+ "composerChip": "_0yZr2a_composerChip",
38084
+ "errorToast": "_0yZr2a_errorToast",
38085
+ "minimapNode": "_0yZr2a_minimapNode",
38086
+ "modalBackdrop": "_0yZr2a_modalBackdrop",
38087
+ "imageInfoRight": "_0yZr2a_imageInfoRight",
38088
+ "flowCanvas": "_0yZr2a_flowCanvas",
38089
+ "configNode": "_0yZr2a_configNode",
38090
+ "nodeTitle": "_0yZr2a_nodeTitle",
38072
38091
  "connectionFlowActive": "_0yZr2a_connectionFlowActive",
38073
- "minimap": "_0yZr2a_minimap",
38074
- "dock": "_0yZr2a_dock",
38075
- "nodeConnectTarget": "_0yZr2a_nodeConnectTarget",
38076
- "minimapImage": "_0yZr2a_minimapImage"
38092
+ "composerControls": "_0yZr2a_composerControls",
38093
+ "minimapImage": "_0yZr2a_minimapImage",
38094
+ "backgroundMenuDivider": "_0yZr2a_backgroundMenuDivider",
38095
+ "projectSelect": "_0yZr2a_projectSelect"
38077
38096
  };
38078
38097
  //#endregion
38079
- //#region src/client/CanvasWorkspace.tsx
38080
- /** Infinite canvas workspace, rebuilt after the node-graph model of
38081
- * basketikun/infinite-canvas: free nodes (image/text), drag-to-connect edges,
38082
- * marquee + multi selection, context menus, minimap, undo/redo and a floating
38083
- * generation composer. Selecting a node pops the composer: the prompt is typed
38084
- * there (or supplied by connected text nodes), every upstream image node joins
38085
- * as a reference, and results land as new image nodes on the right. */
38086
- const MIN_SCALE = .05;
38087
- const MAX_SCALE = 5;
38088
- const GRID_SIZE = 48;
38089
- const IMAGE_NODE_SIZE = {
38090
- width: 240,
38091
- height: 240
38092
- };
38093
- const TEXT_NODE_SIZE = {
38094
- width: 280,
38095
- height: 150
38096
- };
38097
- const CONFIG_NODE_SIZE = {
38098
- width: 320,
38099
- height: 190
38100
- };
38101
- const LEGACY_CONFIG_NODE_SIZE = {
38102
- width: 240,
38103
- height: 96
38104
- };
38105
- const WORLD_PAD = 12e3;
38106
- function newId(prefix) {
38107
- return `${prefix}-${globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`}`;
38108
- }
38109
- function imageDataUrl(image) {
38110
- return `data:${image.mime};base64,${image.b64}`;
38111
- }
38112
- function readImageSize(src) {
38113
- return new Promise((resolve, reject) => {
38114
- const image = new Image();
38115
- image.onload = () => resolve({
38116
- width: image.naturalWidth || 1,
38117
- height: image.naturalHeight || 1
38118
- });
38119
- image.onerror = () => reject(/* @__PURE__ */ new Error("无法读取图片尺寸"));
38120
- image.src = src;
38098
+ //#region src/client/CanvasBackgrounds.tsx
38099
+ /** Animated canvas backdrops for the infinite canvas workspace, ported from
38100
+ * reactbits.dev backgrounds. They render inside the grid layer, which never
38101
+ * receives pointer events, so every listener observes the viewport element. */
38102
+ /** Interactive flowmap-style dot field ("fluid distortion"): the pointer's
38103
+ * velocity pushes dots sideways like a fluid; they spring back home when it
38104
+ * moves on, with a barely-visible idle drift keeping the field alive. */
38105
+ function FlowBackground() {
38106
+ const canvasRef = (0, react.useRef)(null);
38107
+ (0, react.useEffect)(() => {
38108
+ const canvas = canvasRef.current;
38109
+ const viewport = (canvas?.parentElement)?.parentElement;
38110
+ if (canvas === null || canvas === void 0 || viewport === null || viewport === void 0) return;
38111
+ const ctx = canvas.getContext("2d");
38112
+ if (ctx === null) return;
38113
+ const pointer = {
38114
+ x: -1e4,
38115
+ y: -1e4,
38116
+ vx: 0,
38117
+ vy: 0,
38118
+ seen: false
38119
+ };
38120
+ const SPACING = 44;
38121
+ const RADIUS = 120;
38122
+ let width = 0;
38123
+ let height = 0;
38124
+ let points = [];
38125
+ const rebuild = () => {
38126
+ const rect = viewport.getBoundingClientRect();
38127
+ const dpr = Math.max(1, Math.min(2, window.devicePixelRatio ?? 1));
38128
+ width = Math.max(1, Math.round(rect.width));
38129
+ height = Math.max(1, Math.round(rect.height));
38130
+ canvas.width = Math.round(width * dpr);
38131
+ canvas.height = Math.round(height * dpr);
38132
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
38133
+ points = [];
38134
+ for (let y = SPACING / 2; y < height; y += SPACING) for (let x = SPACING / 2; x < width; x += SPACING) points.push({
38135
+ hx: x,
38136
+ hy: y,
38137
+ x,
38138
+ y,
38139
+ vx: 0,
38140
+ vy: 0
38141
+ });
38142
+ };
38143
+ rebuild();
38144
+ const observer = new ResizeObserver(rebuild);
38145
+ observer.observe(viewport);
38146
+ const onMove = (event) => {
38147
+ const rect = viewport.getBoundingClientRect();
38148
+ const x = event.clientX - rect.left;
38149
+ const y = event.clientY - rect.top;
38150
+ if (pointer.seen) {
38151
+ pointer.vx = pointer.vx * .6 + (x - pointer.x) * .4;
38152
+ pointer.vy = pointer.vy * .6 + (y - pointer.y) * .4;
38153
+ }
38154
+ pointer.x = x;
38155
+ pointer.y = y;
38156
+ pointer.seen = true;
38157
+ };
38158
+ const onLeave = () => {
38159
+ pointer.x = -1e4;
38160
+ pointer.y = -1e4;
38161
+ pointer.vx = 0;
38162
+ pointer.vy = 0;
38163
+ };
38164
+ viewport.addEventListener("pointermove", onMove, true);
38165
+ viewport.addEventListener("pointerleave", onLeave);
38166
+ let frame = 0;
38167
+ let time = 0;
38168
+ const tick = () => {
38169
+ time += .016;
38170
+ for (const p of points) {
38171
+ p.vx += (p.hx + Math.sin(time * 1.3 + p.hy * .055) * .5 - p.x) * .03;
38172
+ p.vy += (p.hy + Math.cos(time * 1.1 + p.hx * .055) * .5 - p.y) * .03;
38173
+ const dx = p.x - pointer.x;
38174
+ const dy = p.y - pointer.y;
38175
+ const d2 = dx * dx + dy * dy;
38176
+ if (d2 < RADIUS * RADIUS && d2 > .01) {
38177
+ const d = Math.sqrt(d2);
38178
+ const force = (1 - d / RADIUS) * .9;
38179
+ p.vx += pointer.vx * force + dx / d * force * 2.2;
38180
+ p.vy += pointer.vy * force + dy / d * force * 2.2;
38181
+ }
38182
+ p.vx *= .86;
38183
+ p.vy *= .86;
38184
+ p.x += p.vx;
38185
+ p.y += p.vy;
38186
+ }
38187
+ ctx.clearRect(0, 0, width, height);
38188
+ for (const p of points) {
38189
+ const speed = Math.min(4, Math.hypot(p.vx, p.vy));
38190
+ ctx.fillStyle = `rgba(96, 125, 255, ${(.16 + speed * .16).toFixed(3)})`;
38191
+ ctx.beginPath();
38192
+ ctx.arc(p.x, p.y, 1.4 + Math.min(1.8, speed * .5), 0, Math.PI * 2);
38193
+ ctx.fill();
38194
+ }
38195
+ frame = window.requestAnimationFrame(tick);
38196
+ };
38197
+ frame = window.requestAnimationFrame(tick);
38198
+ return () => {
38199
+ window.cancelAnimationFrame(frame);
38200
+ observer.disconnect();
38201
+ viewport.removeEventListener("pointermove", onMove);
38202
+ viewport.removeEventListener("pointerleave", onLeave);
38203
+ };
38204
+ }, []);
38205
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
38206
+ ref: canvasRef,
38207
+ className: canvas_workspace_module_css_default.flowCanvas,
38208
+ "aria-hidden": "true"
38121
38209
  });
38122
38210
  }
38123
- async function assetToDataUrl(asset) {
38124
- if (asset.url.startsWith("data:")) return asset.url;
38125
- const response = await fetch(asset.url);
38126
- if (!response.ok) throw new Error("读取画布图片失败");
38127
- const blob = await response.blob();
38128
- return await new Promise((resolve, reject) => {
38129
- const reader = new FileReader();
38130
- reader.onload = () => resolve(String(reader.result));
38131
- reader.onerror = () => reject(/* @__PURE__ */ new Error("读取画布图片失败"));
38132
- reader.readAsDataURL(blob);
38211
+ /** "Liquid ether" background in the reactbits.dev style: a GPU stable-fluids
38212
+ * velocity simulation whose speed is mapped through a three-stop palette
38213
+ * (raw WebGL, no dependencies). Pointer movement stirs the fluid; after a
38214
+ * second of stillness an auto-driven virtual pointer resumes wandering so
38215
+ * the field keeps breathing on its own and blends back to the real pointer
38216
+ * on input. Unlike the original, the auto driver keeps running while the
38217
+ * pointer merely rests inside — on a working canvas it usually does. */
38218
+ function LiquidEtherBackground() {
38219
+ const canvasRef = (0, react.useRef)(null);
38220
+ (0, react.useEffect)(() => {
38221
+ const canvas = canvasRef.current;
38222
+ const viewport = (canvas?.parentElement)?.parentElement;
38223
+ if (canvas === null || canvas === void 0 || viewport === null || viewport === void 0) return;
38224
+ const gl = canvas.getContext("webgl", {
38225
+ alpha: true,
38226
+ antialias: false,
38227
+ depth: false,
38228
+ stencil: false
38229
+ });
38230
+ if (gl === null) return;
38231
+ const MOUSE_FORCE = 20;
38232
+ const CURSOR_SIZE = 100;
38233
+ const DT = .014;
38234
+ const RESOLUTION = .5;
38235
+ const POISSON_ITERATIONS = 32;
38236
+ const AUTO_SPEED = .5;
38237
+ const AUTO_INTENSITY = 2.2;
38238
+ const AUTO_RESUME_DELAY = 1e3;
38239
+ const AUTO_RAMP = 600;
38240
+ const TAKEOVER_DURATION = 250;
38241
+ const PALETTE = [
38242
+ "#5227FF",
38243
+ "#FF9FFC",
38244
+ "#B497CF"
38245
+ ];
38246
+ const quadVertex = `
38247
+ precision highp float;
38248
+ attribute vec3 position;
38249
+ uniform vec2 uScale;
38250
+ varying vec2 uv;
38251
+ void main() {
38252
+ vec3 pos = position;
38253
+ pos.xy *= uScale;
38254
+ uv = vec2(0.5) + pos.xy * 0.5;
38255
+ gl_Position = vec4(pos, 1.0);
38256
+ }
38257
+ `;
38258
+ const advectionFragment = `
38259
+ precision highp float;
38260
+ uniform sampler2D uVelocity;
38261
+ uniform float uDt;
38262
+ uniform vec2 uFboSize;
38263
+ varying vec2 uv;
38264
+ void main() {
38265
+ vec2 ratio = max(uFboSize.x, uFboSize.y) / uFboSize;
38266
+ vec2 velOld = texture2D(uVelocity, uv).xy;
38267
+ vec2 spotOld = uv - velOld * uDt * ratio;
38268
+ vec2 velNew = texture2D(uVelocity, spotOld).xy;
38269
+ vec2 spotAgain = spotOld + velNew * uDt * ratio;
38270
+ vec2 spotMid = uv - (spotAgain - uv) * 0.5;
38271
+ vec2 velMid = texture2D(uVelocity, spotMid).xy;
38272
+ vec2 spotOld2 = spotMid - velMid * uDt * ratio;
38273
+ gl_FragColor = vec4(texture2D(uVelocity, spotOld2).xy, 0.0, 0.0);
38274
+ }
38275
+ `;
38276
+ const divergenceFragment = `
38277
+ precision highp float;
38278
+ uniform sampler2D uVelocity;
38279
+ uniform float uDt;
38280
+ uniform vec2 uPx;
38281
+ varying vec2 uv;
38282
+ void main() {
38283
+ float x0 = texture2D(uVelocity, uv - vec2(uPx.x, 0.0)).x;
38284
+ float x1 = texture2D(uVelocity, uv + vec2(uPx.x, 0.0)).x;
38285
+ float y0 = texture2D(uVelocity, uv - vec2(0.0, uPx.y)).y;
38286
+ float y1 = texture2D(uVelocity, uv + vec2(0.0, uPx.y)).y;
38287
+ gl_FragColor = vec4((x1 - x0 + y1 - y0) / 2.0 / uDt);
38288
+ }
38289
+ `;
38290
+ const poissonFragment = `
38291
+ precision highp float;
38292
+ uniform sampler2D uPressure;
38293
+ uniform sampler2D uDivergence;
38294
+ uniform vec2 uPx;
38295
+ varying vec2 uv;
38296
+ void main() {
38297
+ float p0 = texture2D(uPressure, uv + vec2(uPx.x * 2.0, 0.0)).r;
38298
+ float p1 = texture2D(uPressure, uv - vec2(uPx.x * 2.0, 0.0)).r;
38299
+ float p2 = texture2D(uPressure, uv + vec2(0.0, uPx.y * 2.0)).r;
38300
+ float p3 = texture2D(uPressure, uv - vec2(0.0, uPx.y * 2.0)).r;
38301
+ float div = texture2D(uDivergence, uv).r;
38302
+ gl_FragColor = vec4((p0 + p1 + p2 + p3) / 4.0 - div);
38303
+ }
38304
+ `;
38305
+ const pressureFragment = `
38306
+ precision highp float;
38307
+ uniform sampler2D uPressure;
38308
+ uniform sampler2D uVelocity;
38309
+ uniform float uDt;
38310
+ uniform vec2 uPx;
38311
+ varying vec2 uv;
38312
+ void main() {
38313
+ float p0 = texture2D(uPressure, uv + vec2(uPx.x, 0.0)).r;
38314
+ float p1 = texture2D(uPressure, uv - vec2(uPx.x, 0.0)).r;
38315
+ float p2 = texture2D(uPressure, uv + vec2(0.0, uPx.y)).r;
38316
+ float p3 = texture2D(uPressure, uv - vec2(0.0, uPx.y)).r;
38317
+ vec2 gradient = vec2(p0 - p1, p2 - p3) * 0.5;
38318
+ gl_FragColor = vec4(texture2D(uVelocity, uv).xy - gradient * uDt, 0.0, 1.0);
38319
+ }
38320
+ `;
38321
+ const splatFragment = `
38322
+ precision highp float;
38323
+ uniform vec2 uCenter;
38324
+ uniform vec2 uRadius;
38325
+ uniform vec2 uForce;
38326
+ varying vec2 uv;
38327
+ void main() {
38328
+ vec2 offset = (uv - uCenter) / uRadius;
38329
+ float weight = 1.0 - min(length(offset), 1.0);
38330
+ gl_FragColor = vec4(uForce * weight * weight, 0.0, 0.0);
38331
+ }
38332
+ `;
38333
+ const displayFragment = `
38334
+ precision highp float;
38335
+ uniform sampler2D uVelocity;
38336
+ uniform sampler2D uPalette;
38337
+ varying vec2 uv;
38338
+ void main() {
38339
+ float speed = clamp(length(texture2D(uVelocity, uv).xy), 0.0, 1.0);
38340
+ vec3 ink = texture2D(uPalette, vec2(speed, 0.5)).rgb;
38341
+ gl_FragColor = vec4(ink * speed, speed);
38342
+ }
38343
+ `;
38344
+ const createProgram = (fragmentSource) => {
38345
+ const compile = (type, source) => {
38346
+ const shader = gl.createShader(type);
38347
+ if (shader === null) throw new Error("webgl: shader alloc failed");
38348
+ gl.shaderSource(shader, source);
38349
+ gl.compileShader(shader);
38350
+ if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) !== true) throw new Error(gl.getShaderInfoLog(shader) ?? "webgl: shader compile failed");
38351
+ return shader;
38352
+ };
38353
+ const program = gl.createProgram();
38354
+ if (program === null) throw new Error("webgl: program alloc failed");
38355
+ gl.attachShader(program, compile(gl.VERTEX_SHADER, quadVertex));
38356
+ gl.attachShader(program, compile(gl.FRAGMENT_SHADER, fragmentSource));
38357
+ gl.bindAttribLocation(program, 0, "position");
38358
+ gl.linkProgram(program);
38359
+ if (gl.getProgramParameter(program, gl.LINK_STATUS) !== true) throw new Error(gl.getProgramInfoLog(program) ?? "webgl: program link failed");
38360
+ for (const shader of gl.getAttachedShaders(program) ?? []) {
38361
+ gl.detachShader(program, shader);
38362
+ gl.deleteShader(shader);
38363
+ }
38364
+ const uniforms = {};
38365
+ const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
38366
+ for (let index = 0; index < count; index++) {
38367
+ const info = gl.getActiveUniform(program, index);
38368
+ const location = info !== null ? gl.getUniformLocation(program, info.name) : null;
38369
+ if (info !== null && location !== null) uniforms[info.name] = location;
38370
+ }
38371
+ return {
38372
+ program,
38373
+ uniforms
38374
+ };
38375
+ };
38376
+ const createSimTexture = (width, height, type, filter) => {
38377
+ const texture = gl.createTexture();
38378
+ if (texture === null) throw new Error("webgl: texture alloc failed");
38379
+ gl.activeTexture(gl.TEXTURE0);
38380
+ gl.bindTexture(gl.TEXTURE_2D, texture);
38381
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
38382
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
38383
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
38384
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
38385
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, type, null);
38386
+ const fbo = gl.createFramebuffer();
38387
+ if (fbo === null) throw new Error("webgl: framebuffer alloc failed");
38388
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
38389
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
38390
+ gl.clearColor(0, 0, 0, 0);
38391
+ gl.clear(gl.COLOR_BUFFER_BIT);
38392
+ return {
38393
+ texture,
38394
+ fbo,
38395
+ width,
38396
+ height
38397
+ };
38398
+ };
38399
+ const chooseSimFormat = () => {
38400
+ const halfFloat = gl.getExtension("OES_texture_half_float");
38401
+ const halfLinear = gl.getExtension("OES_texture_half_float_linear");
38402
+ const fullFloat = gl.getExtension("OES_texture_float");
38403
+ const fullLinear = gl.getExtension("OES_texture_float_linear");
38404
+ const candidates = [];
38405
+ if (halfFloat !== null && halfLinear !== null) candidates.push({
38406
+ type: halfFloat.HALF_FLOAT_OES,
38407
+ filter: gl.LINEAR
38408
+ });
38409
+ if (fullFloat !== null && fullLinear !== null) candidates.push({
38410
+ type: gl.FLOAT,
38411
+ filter: gl.LINEAR
38412
+ });
38413
+ if (halfFloat !== null) candidates.push({
38414
+ type: halfFloat.HALF_FLOAT_OES,
38415
+ filter: gl.NEAREST
38416
+ });
38417
+ if (fullFloat !== null) candidates.push({
38418
+ type: gl.FLOAT,
38419
+ filter: gl.NEAREST
38420
+ });
38421
+ for (const candidate of candidates) {
38422
+ const probe = createSimTexture(4, 4, candidate.type, candidate.filter);
38423
+ const complete = gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE;
38424
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
38425
+ gl.deleteTexture(probe.texture);
38426
+ gl.deleteFramebuffer(probe.fbo);
38427
+ if (complete) return candidate;
38428
+ }
38429
+ return null;
38430
+ };
38431
+ const simFormat = chooseSimFormat();
38432
+ if (simFormat === null) return;
38433
+ const advectionPass = createProgram(advectionFragment);
38434
+ const splatPass = createProgram(splatFragment);
38435
+ const divergencePass = createProgram(divergenceFragment);
38436
+ const poissonPass = createProgram(poissonFragment);
38437
+ const pressurePass = createProgram(pressureFragment);
38438
+ const displayPass = createProgram(displayFragment);
38439
+ const quadBuffer = gl.createBuffer();
38440
+ if (quadBuffer === null) return;
38441
+ gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
38442
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
38443
+ -1,
38444
+ -1,
38445
+ 0,
38446
+ 1,
38447
+ -1,
38448
+ 0,
38449
+ -1,
38450
+ 1,
38451
+ 0,
38452
+ 1,
38453
+ 1,
38454
+ 0
38455
+ ]), gl.STATIC_DRAW);
38456
+ gl.enableVertexAttribArray(0);
38457
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
38458
+ const paletteTexture = gl.createTexture();
38459
+ if (paletteTexture === null) return;
38460
+ gl.activeTexture(gl.TEXTURE0);
38461
+ gl.bindTexture(gl.TEXTURE_2D, paletteTexture);
38462
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
38463
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
38464
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
38465
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
38466
+ const paletteData = new Uint8Array(PALETTE.length * 4);
38467
+ for (const [index, hex] of PALETTE.entries()) {
38468
+ paletteData[index * 4 + 0] = parseInt(hex.slice(1, 3), 16);
38469
+ paletteData[index * 4 + 1] = parseInt(hex.slice(3, 5), 16);
38470
+ paletteData[index * 4 + 2] = parseInt(hex.slice(5, 7), 16);
38471
+ paletteData[index * 4 + 3] = 255;
38472
+ }
38473
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, PALETTE.length, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, paletteData);
38474
+ let velocities = null;
38475
+ let divergenceTex = null;
38476
+ let pressures = null;
38477
+ const destroySimTexture = (texture) => {
38478
+ gl.deleteTexture(texture.texture);
38479
+ gl.deleteFramebuffer(texture.fbo);
38480
+ };
38481
+ const resizeCanvas = () => {
38482
+ const rect = viewport.getBoundingClientRect();
38483
+ const dpr = Math.max(1, Math.min(2, window.devicePixelRatio ?? 1));
38484
+ canvas.width = Math.max(1, Math.round(rect.width * dpr));
38485
+ canvas.height = Math.max(1, Math.round(rect.height * dpr));
38486
+ for (const texture of [
38487
+ ...velocities ?? [],
38488
+ ...divergenceTex !== null ? [divergenceTex] : [],
38489
+ ...pressures ?? []
38490
+ ]) destroySimTexture(texture);
38491
+ velocities = null;
38492
+ divergenceTex = null;
38493
+ pressures = null;
38494
+ if (rect.width < 1 || rect.height < 1) return;
38495
+ const simWidth = Math.max(1, Math.round(RESOLUTION * rect.width));
38496
+ const simHeight = Math.max(1, Math.round(RESOLUTION * rect.height));
38497
+ velocities = [createSimTexture(simWidth, simHeight, simFormat.type, simFormat.filter), createSimTexture(simWidth, simHeight, simFormat.type, simFormat.filter)];
38498
+ divergenceTex = createSimTexture(simWidth, simHeight, simFormat.type, simFormat.filter);
38499
+ pressures = [createSimTexture(simWidth, simHeight, simFormat.type, simFormat.filter), createSimTexture(simWidth, simHeight, simFormat.type, simFormat.filter)];
38500
+ };
38501
+ const reducedMotion = globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true;
38502
+ const pointer = {
38503
+ x: 0,
38504
+ y: 0,
38505
+ oldX: 0,
38506
+ oldY: 0,
38507
+ diffX: 0,
38508
+ diffY: 0,
38509
+ seen: false,
38510
+ lastInteract: performance.now(),
38511
+ autoActive: false,
38512
+ takeover: false,
38513
+ takeoverStart: 0,
38514
+ fromX: 0,
38515
+ fromY: 0,
38516
+ toX: 0,
38517
+ toY: 0
38518
+ };
38519
+ const auto = {
38520
+ active: false,
38521
+ x: 0,
38522
+ y: 0,
38523
+ targetX: 0,
38524
+ targetY: 0,
38525
+ last: 0,
38526
+ started: 0
38527
+ };
38528
+ const stopAuto = () => {
38529
+ auto.active = false;
38530
+ pointer.autoActive = false;
38531
+ };
38532
+ const pickTarget = () => {
38533
+ const margin = .2;
38534
+ auto.targetX = (Math.random() * 2 - 1) * (1 - margin);
38535
+ auto.targetY = (Math.random() * 2 - 1) * (1 - margin);
38536
+ };
38537
+ const onPointerMove = (event) => {
38538
+ const rect = viewport.getBoundingClientRect();
38539
+ if (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom) return;
38540
+ if (rect.width === 0 || rect.height === 0) return;
38541
+ const x = (event.clientX - rect.left) / rect.width * 2 - 1;
38542
+ const y = -((event.clientY - rect.top) / rect.height * 2 - 1);
38543
+ pointer.lastInteract = performance.now();
38544
+ if (pointer.autoActive && !pointer.takeover) {
38545
+ pointer.takeover = true;
38546
+ pointer.takeoverStart = performance.now();
38547
+ pointer.fromX = pointer.x;
38548
+ pointer.fromY = pointer.y;
38549
+ pointer.toX = x;
38550
+ pointer.toY = y;
38551
+ pointer.autoActive = false;
38552
+ return;
38553
+ }
38554
+ if (!pointer.seen) {
38555
+ pointer.oldX = x;
38556
+ pointer.oldY = y;
38557
+ pointer.seen = true;
38558
+ }
38559
+ pointer.x = x;
38560
+ pointer.y = y;
38561
+ };
38562
+ const onPointerLeave = () => {
38563
+ pointer.seen = false;
38564
+ };
38565
+ const updateAuto = (now) => {
38566
+ if (reducedMotion) return;
38567
+ if (now - pointer.lastInteract < AUTO_RESUME_DELAY) {
38568
+ if (auto.active) stopAuto();
38569
+ return;
38570
+ }
38571
+ if (!auto.active) {
38572
+ auto.active = true;
38573
+ auto.x = pointer.x;
38574
+ auto.y = pointer.y;
38575
+ auto.last = now;
38576
+ auto.started = now;
38577
+ pickTarget();
38578
+ }
38579
+ pointer.autoActive = true;
38580
+ let dtSec = (now - auto.last) / 1e3;
38581
+ auto.last = now;
38582
+ if (dtSec > .2) dtSec = .016;
38583
+ const dx = auto.targetX - auto.x;
38584
+ const dy = auto.targetY - auto.y;
38585
+ const dist = Math.hypot(dx, dy);
38586
+ if (dist < .01) {
38587
+ pickTarget();
38588
+ return;
38589
+ }
38590
+ const t = Math.min(1, (now - auto.started) / AUTO_RAMP);
38591
+ const ramp = t * t * (3 - 2 * t);
38592
+ const step = Math.min(AUTO_SPEED * dtSec * ramp, dist);
38593
+ auto.x += dx / dist * step;
38594
+ auto.y += dy / dist * step;
38595
+ pointer.x = auto.x;
38596
+ pointer.y = auto.y;
38597
+ };
38598
+ const updatePointer = (now) => {
38599
+ if (pointer.takeover) {
38600
+ const t = (now - pointer.takeoverStart) / TAKEOVER_DURATION;
38601
+ if (t >= 1) {
38602
+ pointer.takeover = false;
38603
+ pointer.x = pointer.toX;
38604
+ pointer.y = pointer.toY;
38605
+ pointer.oldX = pointer.x;
38606
+ pointer.oldY = pointer.y;
38607
+ pointer.diffX = 0;
38608
+ pointer.diffY = 0;
38609
+ return;
38610
+ }
38611
+ const k = t * t * (3 - 2 * t);
38612
+ pointer.x = pointer.fromX + (pointer.toX - pointer.fromX) * k;
38613
+ pointer.y = pointer.fromY + (pointer.toY - pointer.fromY) * k;
38614
+ }
38615
+ pointer.diffX = pointer.x - pointer.oldX;
38616
+ pointer.diffY = pointer.y - pointer.oldY;
38617
+ pointer.oldX = pointer.x;
38618
+ pointer.oldY = pointer.y;
38619
+ if (pointer.autoActive && !pointer.takeover) {
38620
+ pointer.diffX *= AUTO_INTENSITY;
38621
+ pointer.diffY *= AUTO_INTENSITY;
38622
+ }
38623
+ };
38624
+ const bindTarget = (target) => {
38625
+ if (target === null) {
38626
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
38627
+ gl.viewport(0, 0, canvas.width, canvas.height);
38628
+ } else {
38629
+ gl.bindFramebuffer(gl.FRAMEBUFFER, target.fbo);
38630
+ gl.viewport(0, 0, target.width, target.height);
38631
+ }
38632
+ };
38633
+ const bindTexture = (unit, texture) => {
38634
+ gl.activeTexture(gl.TEXTURE0 + unit);
38635
+ gl.bindTexture(gl.TEXTURE_2D, texture);
38636
+ };
38637
+ const drawQuad = () => {
38638
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
38639
+ };
38640
+ const step = (now) => {
38641
+ if (velocities === null || divergenceTex === null || pressures === null) return;
38642
+ updateAuto(now);
38643
+ updatePointer(now);
38644
+ const velocity = velocities[0];
38645
+ const pxX = 1 / velocity.width;
38646
+ const pxY = 1 / velocity.height;
38647
+ const scaleX = 1 - pxX * 2;
38648
+ const scaleY = 1 - pxY * 2;
38649
+ bindTarget(velocities[1]);
38650
+ gl.useProgram(advectionPass.program);
38651
+ gl.uniform2f(advectionPass.uniforms.uScale, scaleX, scaleY);
38652
+ bindTexture(0, velocity.texture);
38653
+ gl.uniform1i(advectionPass.uniforms.uVelocity, 0);
38654
+ gl.uniform1f(advectionPass.uniforms.uDt, DT);
38655
+ gl.uniform2f(advectionPass.uniforms.uFboSize, velocity.width, velocity.height);
38656
+ drawQuad();
38657
+ if (Math.abs(pointer.diffX) > 1e-5 || Math.abs(pointer.diffY) > 1e-5) {
38658
+ const radiusU = CURSOR_SIZE * pxX * .5;
38659
+ const radiusV = CURSOR_SIZE * pxY * .5;
38660
+ const centerX = Math.min(Math.max((pointer.x + 1) / 2, radiusU + pxX), 1 - radiusU - pxX);
38661
+ const centerY = Math.min(Math.max((pointer.y + 1) / 2, radiusV + pxY), 1 - radiusV - pxY);
38662
+ gl.enable(gl.BLEND);
38663
+ gl.blendFunc(gl.ONE, gl.ONE);
38664
+ gl.useProgram(splatPass.program);
38665
+ gl.uniform2f(splatPass.uniforms.uScale, 1, 1);
38666
+ gl.uniform2f(splatPass.uniforms.uCenter, centerX, centerY);
38667
+ gl.uniform2f(splatPass.uniforms.uRadius, radiusU, radiusV);
38668
+ gl.uniform2f(splatPass.uniforms.uForce, pointer.diffX / 2 * MOUSE_FORCE, pointer.diffY / 2 * MOUSE_FORCE);
38669
+ drawQuad();
38670
+ gl.disable(gl.BLEND);
38671
+ }
38672
+ bindTarget(divergenceTex);
38673
+ gl.useProgram(divergencePass.program);
38674
+ gl.uniform2f(divergencePass.uniforms.uScale, scaleX, scaleY);
38675
+ bindTexture(0, velocities[1].texture);
38676
+ gl.uniform1i(divergencePass.uniforms.uVelocity, 0);
38677
+ gl.uniform1f(divergencePass.uniforms.uDt, DT);
38678
+ gl.uniform2f(divergencePass.uniforms.uPx, pxX, pxY);
38679
+ drawQuad();
38680
+ gl.useProgram(poissonPass.program);
38681
+ gl.uniform2f(poissonPass.uniforms.uScale, scaleX, scaleY);
38682
+ gl.uniform2f(poissonPass.uniforms.uPx, pxX, pxY);
38683
+ bindTexture(1, divergenceTex.texture);
38684
+ gl.uniform1i(poissonPass.uniforms.uDivergence, 1);
38685
+ let pressureOut = pressures[0];
38686
+ for (let iteration = 0; iteration < POISSON_ITERATIONS; iteration++) {
38687
+ const source = pressures[iteration % 2];
38688
+ pressureOut = pressures[(iteration + 1) % 2];
38689
+ bindTarget(pressureOut);
38690
+ bindTexture(0, source.texture);
38691
+ gl.uniform1i(poissonPass.uniforms.uPressure, 0);
38692
+ drawQuad();
38693
+ }
38694
+ bindTarget(velocities[0]);
38695
+ gl.useProgram(pressurePass.program);
38696
+ gl.uniform2f(pressurePass.uniforms.uScale, scaleX, scaleY);
38697
+ bindTexture(0, pressureOut.texture);
38698
+ gl.uniform1i(pressurePass.uniforms.uPressure, 0);
38699
+ bindTexture(1, velocities[1].texture);
38700
+ gl.uniform1i(pressurePass.uniforms.uVelocity, 1);
38701
+ gl.uniform1f(pressurePass.uniforms.uDt, DT);
38702
+ gl.uniform2f(pressurePass.uniforms.uPx, pxX, pxY);
38703
+ drawQuad();
38704
+ bindTarget(null);
38705
+ gl.clearColor(0, 0, 0, 0);
38706
+ gl.clear(gl.COLOR_BUFFER_BIT);
38707
+ gl.useProgram(displayPass.program);
38708
+ gl.uniform2f(displayPass.uniforms.uScale, 1, 1);
38709
+ bindTexture(0, velocity.texture);
38710
+ gl.uniform1i(displayPass.uniforms.uVelocity, 0);
38711
+ bindTexture(1, paletteTexture);
38712
+ gl.uniform1i(displayPass.uniforms.uPalette, 1);
38713
+ drawQuad();
38714
+ };
38715
+ let frame = window.requestAnimationFrame(function tick() {
38716
+ step(performance.now());
38717
+ frame = window.requestAnimationFrame(tick);
38718
+ });
38719
+ resizeCanvas();
38720
+ let resizeFrame = 0;
38721
+ const observer = new ResizeObserver(() => {
38722
+ if (resizeFrame !== 0) window.cancelAnimationFrame(resizeFrame);
38723
+ resizeFrame = window.requestAnimationFrame(() => {
38724
+ resizeFrame = 0;
38725
+ resizeCanvas();
38726
+ });
38727
+ });
38728
+ observer.observe(viewport);
38729
+ viewport.addEventListener("pointermove", onPointerMove, true);
38730
+ viewport.addEventListener("pointerleave", onPointerLeave);
38731
+ return () => {
38732
+ window.cancelAnimationFrame(frame);
38733
+ if (resizeFrame !== 0) window.cancelAnimationFrame(resizeFrame);
38734
+ observer.disconnect();
38735
+ viewport.removeEventListener("pointermove", onPointerMove);
38736
+ viewport.removeEventListener("pointerleave", onPointerLeave);
38737
+ for (const texture of [
38738
+ ...velocities ?? [],
38739
+ ...divergenceTex !== null ? [divergenceTex] : [],
38740
+ ...pressures ?? []
38741
+ ]) destroySimTexture(texture);
38742
+ gl.deleteTexture(paletteTexture);
38743
+ gl.deleteBuffer(quadBuffer);
38744
+ for (const pass of [
38745
+ advectionPass,
38746
+ splatPass,
38747
+ divergencePass,
38748
+ poissonPass,
38749
+ pressurePass,
38750
+ displayPass
38751
+ ]) gl.deleteProgram(pass.program);
38752
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
38753
+ gl.getExtension("WEBGL_lose_context")?.loseContext();
38754
+ };
38755
+ }, []);
38756
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
38757
+ ref: canvasRef,
38758
+ className: canvas_workspace_module_css_default.liquidCanvas,
38759
+ "aria-hidden": "true"
38133
38760
  });
38134
38761
  }
38135
- function clampScale(scale) {
38136
- return Math.min(MAX_SCALE, Math.max(MIN_SCALE, scale));
38137
- }
38138
- function sizeForAsset(asset) {
38139
- const ratio = asset.width > 0 && asset.height > 0 ? asset.width / asset.height : 1;
38140
- if (ratio >= 1) return {
38141
- width: IMAGE_NODE_SIZE.width,
38142
- height: Math.max(160, Math.round(IMAGE_NODE_SIZE.width / ratio))
38143
- };
38144
- return {
38145
- width: Math.max(200, Math.round(IMAGE_NODE_SIZE.height * ratio)),
38146
- height: IMAGE_NODE_SIZE.height
38147
- };
38762
+ const SHADER_QUAD_VERTEX = `
38763
+ precision highp float;
38764
+ attribute vec3 position;
38765
+ varying vec2 vUv;
38766
+ void main() {
38767
+ vUv = position.xy * 0.5 + 0.5;
38768
+ gl_Position = vec4(position, 1.0);
38769
+ }
38770
+ `;
38771
+ /** Walk up from the grid layer to the first opaque surface and decide
38772
+ * light vs dark, so the shader backdrops can pick their lightMode ink. */
38773
+ function detectLightSurface(element) {
38774
+ let node = element;
38775
+ while (node !== null) {
38776
+ const match = getComputedStyle(node).backgroundColor.match(/rgba?\(\s*([\d.]+)[\s,]+([\d.]+)[\s,]+([\d.]+)(?:[\s,]+([\d.]+))?\s*\)/);
38777
+ if (match !== null) {
38778
+ if ((match[4] !== void 0 ? Number(match[4]) : 1) >= .5) return (.2126 * Number(match[1]) + .7152 * Number(match[2]) + .0722 * Number(match[3])) / 255 > .55;
38779
+ }
38780
+ node = node.parentElement;
38781
+ }
38782
+ return false;
38148
38783
  }
38149
- /** Node footprint for a generation size ratio such as '1:1' or '16:9'. */
38150
- function nodeSizeFromRatio(size, spec) {
38151
- const match = /^(\d+):(\d+)$/.exec(size ?? "");
38152
- if (match === null) return { ...spec };
38153
- const width = Number(match[1]);
38154
- const height = Number(match[2]);
38155
- if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return { ...spec };
38156
- const ratio = width / height;
38157
- return ratio >= 1 ? {
38158
- width: spec.width,
38159
- height: Math.max(160, Math.round(spec.width / ratio))
38160
- } : {
38161
- width: Math.max(200, Math.round(spec.height * ratio)),
38162
- height: spec.height
38784
+ /** Shared engine for the fullscreen-shader backdrops: compiles one program,
38785
+ * owns the DPR-sized canvas, the rAF loop, viewport resize and smoothed
38786
+ * pointer tracking. `frame` sets uniforms and calls draw(). WebGL2 is
38787
+ * preferred (floating lines needs dynamic-ish GLSL); returns the detected
38788
+ * theme plus a dispose function, or null when WebGL is unavailable. */
38789
+ function startShaderCanvas(canvas, viewport, fragmentSource, frame) {
38790
+ const contextAttributes = {
38791
+ alpha: true,
38792
+ antialias: false,
38793
+ depth: false,
38794
+ stencil: false
38163
38795
  };
38796
+ const gl = canvas.getContext("webgl2", contextAttributes) ?? canvas.getContext("webgl", contextAttributes);
38797
+ if (gl === null) return null;
38798
+ try {
38799
+ const compile = (type, source) => {
38800
+ const shader = gl.createShader(type);
38801
+ if (shader === null) throw new Error("webgl: shader alloc failed");
38802
+ gl.shaderSource(shader, source);
38803
+ gl.compileShader(shader);
38804
+ if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) !== true) throw new Error(gl.getShaderInfoLog(shader) ?? "webgl: shader compile failed");
38805
+ return shader;
38806
+ };
38807
+ const program = gl.createProgram();
38808
+ if (program === null) return null;
38809
+ gl.attachShader(program, compile(gl.VERTEX_SHADER, SHADER_QUAD_VERTEX));
38810
+ gl.attachShader(program, compile(gl.FRAGMENT_SHADER, fragmentSource));
38811
+ gl.bindAttribLocation(program, 0, "position");
38812
+ gl.linkProgram(program);
38813
+ if (gl.getProgramParameter(program, gl.LINK_STATUS) !== true) throw new Error(gl.getProgramInfoLog(program) ?? "webgl: program link failed");
38814
+ for (const shader of gl.getAttachedShaders(program) ?? []) {
38815
+ gl.detachShader(program, shader);
38816
+ gl.deleteShader(shader);
38817
+ }
38818
+ const uniforms = {};
38819
+ const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
38820
+ for (let index = 0; index < count; index++) {
38821
+ const info = gl.getActiveUniform(program, index);
38822
+ const location = info !== null ? gl.getUniformLocation(program, info.name) : null;
38823
+ if (info !== null && location !== null) uniforms[info.name] = location;
38824
+ }
38825
+ const quad = gl.createBuffer();
38826
+ if (quad === null) return null;
38827
+ gl.bindBuffer(gl.ARRAY_BUFFER, quad);
38828
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
38829
+ -1,
38830
+ -1,
38831
+ 0,
38832
+ 1,
38833
+ -1,
38834
+ 0,
38835
+ -1,
38836
+ 1,
38837
+ 0,
38838
+ 1,
38839
+ 1,
38840
+ 0
38841
+ ]), gl.STATIC_DRAW);
38842
+ gl.enableVertexAttribArray(0);
38843
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
38844
+ const state = {
38845
+ gl,
38846
+ program,
38847
+ uniforms,
38848
+ time: 0,
38849
+ width: 1,
38850
+ height: 1,
38851
+ dpr: 1,
38852
+ light: detectLightSurface(viewport),
38853
+ pointer: {
38854
+ x: 0,
38855
+ y: 0,
38856
+ active: 0
38857
+ },
38858
+ draw: () => {
38859
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
38860
+ }
38861
+ };
38862
+ const pointerTarget = {
38863
+ x: 0,
38864
+ y: 0,
38865
+ active: 0
38866
+ };
38867
+ const resize = () => {
38868
+ const rect = viewport.getBoundingClientRect();
38869
+ const dpr = Math.max(1, Math.min(2, window.devicePixelRatio ?? 1));
38870
+ canvas.width = Math.max(1, Math.round(rect.width * dpr));
38871
+ canvas.height = Math.max(1, Math.round(rect.height * dpr));
38872
+ gl.viewport(0, 0, canvas.width, canvas.height);
38873
+ state.width = canvas.width;
38874
+ state.height = canvas.height;
38875
+ state.dpr = dpr;
38876
+ pointerTarget.x = rect.width / 2;
38877
+ pointerTarget.y = rect.height / 2;
38878
+ };
38879
+ const onPointerMove = (event) => {
38880
+ const rect = viewport.getBoundingClientRect();
38881
+ pointerTarget.x = event.clientX - rect.left;
38882
+ pointerTarget.y = event.clientY - rect.top;
38883
+ pointerTarget.active = 1;
38884
+ };
38885
+ const onPointerLeave = () => {
38886
+ pointerTarget.active = 0;
38887
+ };
38888
+ const disposeGl = () => {
38889
+ gl.deleteBuffer(quad);
38890
+ gl.deleteProgram(program);
38891
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
38892
+ gl.getExtension("WEBGL_lose_context")?.loseContext();
38893
+ };
38894
+ resize();
38895
+ if (globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true) {
38896
+ frame(state);
38897
+ gl.deleteBuffer(quad);
38898
+ gl.deleteProgram(program);
38899
+ return null;
38900
+ }
38901
+ const start = performance.now();
38902
+ let frameHandle = 0;
38903
+ const tick = () => {
38904
+ state.time = (performance.now() - start) / 1e3;
38905
+ state.pointer.x += (pointerTarget.x - state.pointer.x) * .05;
38906
+ state.pointer.y += (pointerTarget.y - state.pointer.y) * .05;
38907
+ state.pointer.active += (pointerTarget.active - state.pointer.active) * .05;
38908
+ frame(state);
38909
+ frameHandle = window.requestAnimationFrame(tick);
38910
+ };
38911
+ frameHandle = window.requestAnimationFrame(tick);
38912
+ const observer = new ResizeObserver(resize);
38913
+ observer.observe(viewport);
38914
+ viewport.addEventListener("pointermove", onPointerMove, true);
38915
+ viewport.addEventListener("pointerleave", onPointerLeave);
38916
+ return {
38917
+ light: state.light,
38918
+ dispose: () => {
38919
+ window.cancelAnimationFrame(frameHandle);
38920
+ observer.disconnect();
38921
+ viewport.removeEventListener("pointermove", onPointerMove);
38922
+ viewport.removeEventListener("pointerleave", onPointerLeave);
38923
+ disposeGl();
38924
+ }
38925
+ };
38926
+ } catch {
38927
+ gl.getExtension("WEBGL_lose_context")?.loseContext();
38928
+ return null;
38929
+ }
38164
38930
  }
38165
- function nodesBounds(nodes) {
38166
- return nodes.reduce((acc, node) => ({
38167
- minX: Math.min(acc.minX, node.x),
38168
- minY: Math.min(acc.minY, node.y),
38169
- maxX: Math.max(acc.maxX, node.x + node.width),
38931
+ /** reactbits.dev "FloatingLines": three fields of glowing sine waves drawn by
38932
+ * a single fragment shader and screen-blended over the canvas surface; the
38933
+ * pointer bends nearby waves and shifts a slight parallax. */
38934
+ function FloatingLinesBackground() {
38935
+ const canvasRef = (0, react.useRef)(null);
38936
+ (0, react.useEffect)(() => {
38937
+ const canvas = canvasRef.current;
38938
+ const viewport = (canvas?.parentElement)?.parentElement;
38939
+ if (canvas === null || canvas === void 0 || viewport === null || viewport === void 0) return;
38940
+ const handle = startShaderCanvas(canvas, viewport, `
38941
+ precision highp float;
38942
+ uniform float iTime;
38943
+ uniform vec3 iResolution;
38944
+ uniform vec2 iMouse;
38945
+ uniform float bendInfluence;
38946
+ uniform vec2 parallaxOffset;
38947
+ uniform float uLightMode;
38948
+ const vec3 BLACK = vec3(0.0);
38949
+ const vec3 PINK = vec3(233.0, 71.0, 245.0) / 255.0;
38950
+ const vec3 BLUE = vec3(47.0, 75.0, 162.0) / 255.0;
38951
+ // reactbits defaults: three fields of six lines, offsets baked below.
38952
+ const vec3 TOP_POS = vec3(10.0, 0.5, -0.4);
38953
+ const vec3 MIDDLE_POS = vec3(5.0, 0.0, 0.2);
38954
+ const vec3 BOTTOM_POS = vec3(2.0, -0.7, 0.4);
38955
+ const float LINE_DISTANCE = 0.05;
38956
+ const float BEND_RADIUS = 5.0;
38957
+ const float BEND_STRENGTH = -0.5;
38958
+ mat2 rotate2(float r) { return mat2(cos(r), sin(r), -sin(r), cos(r)); }
38959
+ vec3 backgroundColor(vec2 uv) {
38960
+ vec3 col = vec3(0.0);
38961
+ float y = sin(uv.x - 0.2) * 0.3 - 0.1;
38962
+ float m = uv.y - y;
38963
+ col += mix(BLUE, BLACK, smoothstep(0.0, 1.0, abs(m)));
38964
+ col += mix(PINK, BLACK, smoothstep(0.0, 1.0, abs(m - 0.8)));
38965
+ return col * 0.5;
38966
+ }
38967
+ float wave(vec2 uv, float offset, vec2 screenUv, vec2 mouseUv) {
38968
+ float xMovement = iTime * 0.1;
38969
+ float amp = sin(offset + iTime * 0.2) * 0.3;
38970
+ float y = sin(uv.x + offset + xMovement) * amp;
38971
+ vec2 d = screenUv - mouseUv;
38972
+ float influence = exp(-dot(d, d) * BEND_RADIUS);
38973
+ y += (mouseUv.y - screenUv.y) * influence * BEND_STRENGTH * bendInfluence;
38974
+ float m = uv.y - y;
38975
+ return 0.0175 / max(abs(m) + 0.01, 1e-3) + 0.01;
38976
+ }
38977
+ void main() {
38978
+ vec2 baseUv = (2.0 * gl_FragCoord.xy - iResolution.xy) / iResolution.y;
38979
+ baseUv.y *= -1.0;
38980
+ baseUv += parallaxOffset;
38981
+ vec3 col = vec3(0.0);
38982
+ vec3 lineCol = backgroundColor(baseUv);
38983
+ vec2 mouseUv = (2.0 * iMouse - iResolution.xy) / iResolution.y;
38984
+ mouseUv.y *= -1.0;
38985
+ for (int i = 0; i < 6; ++i) {
38986
+ float fi = float(i);
38987
+ vec2 ruv = baseUv * rotate2(BOTTOM_POS.z * log(length(baseUv) + 1.0));
38988
+ col += lineCol * wave(ruv + vec2(LINE_DISTANCE * fi + BOTTOM_POS.x, BOTTOM_POS.y), 1.5 + 0.2 * fi, baseUv, mouseUv) * 0.2;
38989
+ }
38990
+ for (int i = 0; i < 6; ++i) {
38991
+ float fi = float(i);
38992
+ vec2 ruv = baseUv * rotate2(MIDDLE_POS.z * log(length(baseUv) + 1.0));
38993
+ col += lineCol * wave(ruv + vec2(LINE_DISTANCE * fi + MIDDLE_POS.x, MIDDLE_POS.y), 2.0 + 0.15 * fi, baseUv, mouseUv);
38994
+ }
38995
+ for (int i = 0; i < 6; ++i) {
38996
+ float fi = float(i);
38997
+ vec2 ruv = baseUv * rotate2(TOP_POS.z * log(length(baseUv) + 1.0));
38998
+ ruv.x *= -1.0;
38999
+ col += lineCol * wave(ruv + vec2(LINE_DISTANCE * fi + TOP_POS.x, TOP_POS.y), 1.0 + 0.2 * fi, baseUv, mouseUv) * 0.1;
39000
+ }
39001
+ if (uLightMode > 0.5) {
39002
+ vec3 energy = max(col, vec3(0.0));
39003
+ float peak = max(energy.r, max(energy.g, energy.b));
39004
+ float coverage = smoothstep(0.018, 0.5, peak);
39005
+ vec3 chroma = clamp(energy / max(peak, 0.0001), 0.0, 1.0);
39006
+ chroma = pow(chroma, vec3(1.35));
39007
+ float chromaPeak = max(chroma.r, max(chroma.g, chroma.b));
39008
+ chroma /= max(chromaPeak, 0.0001);
39009
+ vec3 ink = mix(chroma, clamp(chroma * 0.82, 0.0, 1.0), smoothstep(0.5, 1.0, coverage));
39010
+ gl_FragColor = vec4(mix(vec3(1.0), ink, coverage * 0.94), 1.0);
39011
+ } else {
39012
+ gl_FragColor = vec4(col, 1.0);
39013
+ }
39014
+ }
39015
+ `, (state) => {
39016
+ const { gl, uniforms, time, width, height, dpr, pointer } = state;
39017
+ gl.useProgram(state.program);
39018
+ gl.uniform1f(uniforms.iTime, time);
39019
+ gl.uniform3f(uniforms.iResolution, width, height, 1);
39020
+ gl.uniform2f(uniforms.iMouse, pointer.x * dpr, (height / dpr - pointer.y) * dpr);
39021
+ gl.uniform1f(uniforms.bendInfluence, pointer.active);
39022
+ gl.uniform2f(uniforms.parallaxOffset, (pointer.x / Math.max(1, width / dpr) - .5) * .2, -(pointer.y / Math.max(1, height / dpr) - .5) * .2);
39023
+ gl.uniform1f(uniforms.uLightMode, state.light ? 1 : 0);
39024
+ state.draw();
39025
+ });
39026
+ if (handle === null) return;
39027
+ canvas.style.mixBlendMode = handle.light ? "normal" : "screen";
39028
+ return () => {
39029
+ handle.dispose();
39030
+ };
39031
+ }, []);
39032
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
39033
+ ref: canvasRef,
39034
+ className: canvas_workspace_module_css_default.sceneCanvas,
39035
+ "aria-hidden": "true"
39036
+ });
39037
+ }
39038
+ /** reactbits.dev "Galaxy": four parallax layers of twinkling stars flying
39039
+ * outward, pushed away from the pointer (single transparent fragment shader). */
39040
+ function GalaxyBackground() {
39041
+ const canvasRef = (0, react.useRef)(null);
39042
+ (0, react.useEffect)(() => {
39043
+ const canvas = canvasRef.current;
39044
+ const viewport = (canvas?.parentElement)?.parentElement;
39045
+ if (canvas === null || canvas === void 0 || viewport === null || viewport === void 0) return;
39046
+ const handle = startShaderCanvas(canvas, viewport, `
39047
+ precision highp float;
39048
+ uniform float uTime;
39049
+ uniform vec3 uResolution;
39050
+ uniform float uStarSpeed;
39051
+ uniform vec2 uMouse;
39052
+ uniform float uMouseActiveFactor;
39053
+ uniform float uLightMode;
39054
+ varying vec2 vUv;
39055
+ const float NUM_LAYER = 4.0;
39056
+ const float STAR_COLOR_CUTOFF = 0.2;
39057
+ const mat2 MAT45 = mat2(0.7071, -0.7071, 0.7071, 0.7071);
39058
+ const float PERIOD = 3.0;
39059
+ // reactbits Galaxy defaults, baked.
39060
+ const vec2 FOCAL = vec2(0.5, 0.5);
39061
+ const vec2 ROTATION = vec2(1.0, 0.0);
39062
+ const float DENSITY = 1.0;
39063
+ const float HUE_SHIFT = 140.0;
39064
+ const float SPEED = 1.0;
39065
+ const float GLOW = 0.3;
39066
+ const float SATURATION = 0.0;
39067
+ const float TWINKLE = 0.3;
39068
+ const float ROTATION_SPEED = 0.1;
39069
+ const float REPULSION = 2.0;
39070
+ float Hash21(vec2 p) {
39071
+ p = fract(p * vec2(123.34, 456.21));
39072
+ p += dot(p, p + 45.32);
39073
+ return fract(p.x * p.y);
39074
+ }
39075
+ float tri(float x) { return abs(fract(x) * 2.0 - 1.0); }
39076
+ float tris(float x) {
39077
+ float t = fract(x);
39078
+ return 1.0 - smoothstep(0.0, 1.0, abs(2.0 * t - 1.0));
39079
+ }
39080
+ float trisn(float x) {
39081
+ float t = fract(x);
39082
+ return 2.0 * (1.0 - smoothstep(0.0, 1.0, abs(2.0 * t - 1.0))) - 1.0;
39083
+ }
39084
+ vec3 hsv2rgb(vec3 c) {
39085
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
39086
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
39087
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
39088
+ }
39089
+ float Star(vec2 uv, float flare) {
39090
+ float d = length(uv);
39091
+ float m = (0.05 * GLOW) / d;
39092
+ float rays = smoothstep(0.0, 1.0, 1.0 - abs(uv.x * uv.y * 1000.0));
39093
+ m += rays * flare * GLOW;
39094
+ uv *= MAT45;
39095
+ rays = smoothstep(0.0, 1.0, 1.0 - abs(uv.x * uv.y * 1000.0));
39096
+ m += rays * 0.3 * flare * GLOW;
39097
+ m *= smoothstep(1.0, 0.2, d);
39098
+ return m;
39099
+ }
39100
+ vec3 StarLayer(vec2 uv) {
39101
+ vec3 col = vec3(0.0);
39102
+ vec2 gv = fract(uv) - 0.5;
39103
+ vec2 id = floor(uv);
39104
+ for (int y = -1; y <= 1; y++) {
39105
+ for (int x = -1; x <= 1; x++) {
39106
+ vec2 si = id + vec2(float(x), float(y));
39107
+ float seed = Hash21(si);
39108
+ float size = fract(seed * 345.32);
39109
+ float glossLocal = tri(uStarSpeed / (PERIOD * seed + 1.0));
39110
+ float flareSize = smoothstep(0.9, 1.0, size) * glossLocal;
39111
+ float red = smoothstep(STAR_COLOR_CUTOFF, 1.0, Hash21(si + 1.0)) + STAR_COLOR_CUTOFF;
39112
+ float blu = smoothstep(STAR_COLOR_CUTOFF, 1.0, Hash21(si + 3.0)) + STAR_COLOR_CUTOFF;
39113
+ float grn = min(red, blu) * seed;
39114
+ vec3 base = vec3(red, grn, blu);
39115
+ float hue = atan(base.g - base.r, base.b - base.r) / (2.0 * 3.14159) + 0.5;
39116
+ hue = fract(hue + HUE_SHIFT / 360.0);
39117
+ float sat = length(base - vec3(dot(base, vec3(0.299, 0.587, 0.114)))) * SATURATION;
39118
+ float val = max(max(base.r, base.g), base.b);
39119
+ base = hsv2rgb(vec3(hue, sat, val));
39120
+ vec2 pad = vec2(tris(seed * 34.0 + uTime * SPEED / 10.0), tris(seed * 38.0 + uTime * SPEED / 30.0)) - 0.5;
39121
+ float star = Star(gv - vec2(float(x), float(y)) - pad, flareSize);
39122
+ float twinkle = trisn(uTime * SPEED + seed * 6.2831) * 0.5 + 1.0;
39123
+ twinkle = mix(1.0, twinkle, TWINKLE);
39124
+ star *= twinkle;
39125
+ col += star * size * base;
39126
+ }
39127
+ }
39128
+ return col;
39129
+ }
39130
+ void main() {
39131
+ vec2 focalPx = FOCAL * uResolution.xy;
39132
+ vec2 uv = (vUv * uResolution.xy - focalPx) / uResolution.y;
39133
+ // mouse repulsion (reactbits mouseRepulsion default)
39134
+ vec2 mousePosUV = (uMouse * uResolution.xy - focalPx) / uResolution.y;
39135
+ float mouseDist = length(uv - mousePosUV);
39136
+ vec2 repulsion = normalize(uv - mousePosUV) * (REPULSION / (mouseDist + 0.1));
39137
+ uv += repulsion * 0.05 * uMouseActiveFactor;
39138
+ float autoRotAngle = uTime * ROTATION_SPEED;
39139
+ uv = mat2(cos(autoRotAngle), -sin(autoRotAngle), sin(autoRotAngle), cos(autoRotAngle)) * uv;
39140
+ uv = mat2(ROTATION.x, -ROTATION.y, ROTATION.y, ROTATION.x) * uv;
39141
+ vec3 col = vec3(0.0);
39142
+ for (float i = 0.0; i < 1.0; i += 1.0 / NUM_LAYER) {
39143
+ float depth = fract(i + uStarSpeed * SPEED);
39144
+ float scale = mix(20.0 * DENSITY, 0.5 * DENSITY, depth);
39145
+ float fade = depth * smoothstep(1.0, 0.9, depth);
39146
+ col += StarLayer(uv * scale + i * 453.32) * fade;
39147
+ }
39148
+ // transparent path, premultiplied for the canvas compositor
39149
+ if (uLightMode > 0.5) {
39150
+ float energy = max(max(col.r, col.g), col.b);
39151
+ float coverage = clamp(smoothstep(0.0, 0.42, energy) * 0.92, 0.0, 0.92);
39152
+ vec3 ink = clamp(col * 0.48, 0.0, 0.82);
39153
+ gl_FragColor = vec4(mix(vec3(1.0), ink, coverage), 1.0);
39154
+ } else {
39155
+ float alpha = smoothstep(0.0, 0.3, length(col));
39156
+ gl_FragColor = vec4(col * alpha, alpha);
39157
+ }
39158
+ }
39159
+ `, (state) => {
39160
+ const { gl, uniforms, time, width, height, dpr, pointer } = state;
39161
+ gl.useProgram(state.program);
39162
+ gl.uniform1f(uniforms.uTime, time);
39163
+ gl.uniform3f(uniforms.uResolution, width, height, width / Math.max(1, height));
39164
+ gl.uniform1f(uniforms.uStarSpeed, time * .05);
39165
+ gl.uniform2f(uniforms.uMouse, pointer.x / Math.max(1, width / dpr), 1 - pointer.y / Math.max(1, height / dpr));
39166
+ gl.uniform1f(uniforms.uMouseActiveFactor, pointer.active);
39167
+ gl.uniform1f(uniforms.uLightMode, state.light ? 1 : 0);
39168
+ state.draw();
39169
+ });
39170
+ if (handle === null) return;
39171
+ return () => {
39172
+ handle.dispose();
39173
+ };
39174
+ }, []);
39175
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
39176
+ ref: canvasRef,
39177
+ className: canvas_workspace_module_css_default.sceneCanvas,
39178
+ "aria-hidden": "true"
39179
+ });
39180
+ }
39181
+ /** reactbits.dev "Silk": slow flowing fabric sheen (single opaque fragment
39182
+ * shader in the reactbits default #7B7481 mauve). */
39183
+ function SilkBackground() {
39184
+ const canvasRef = (0, react.useRef)(null);
39185
+ (0, react.useEffect)(() => {
39186
+ const canvas = canvasRef.current;
39187
+ const viewport = (canvas?.parentElement)?.parentElement;
39188
+ if (canvas === null || canvas === void 0 || viewport === null || viewport === void 0) return;
39189
+ const handle = startShaderCanvas(canvas, viewport, `
39190
+ precision highp float;
39191
+ varying vec2 vUv;
39192
+ uniform float uTime;
39193
+ uniform float uLightMode;
39194
+ const vec3 COLOR = vec3(123.0, 116.0, 129.0) / 255.0; // reactbits default #7B7481
39195
+ const float e = 2.71828182845904523536;
39196
+ float noise(vec2 texCoord) {
39197
+ vec2 r = e * sin(e * texCoord);
39198
+ return fract(r.x * r.y * (1.0 + texCoord.x));
39199
+ }
39200
+ void main() {
39201
+ float rnd = noise(gl_FragCoord.xy);
39202
+ vec2 tex = vUv;
39203
+ float tOffset = 5.0 * uTime;
39204
+ tex.y += 0.03 * sin(8.0 * tex.x - tOffset);
39205
+ float pattern = 0.6 +
39206
+ 0.4 * sin(5.0 * (tex.x + tex.y +
39207
+ cos(3.0 * tex.x + 5.0 * tex.y) +
39208
+ 0.02 * tOffset) +
39209
+ sin(20.0 * (tex.x + tex.y - 0.1 * tOffset)));
39210
+ float grain = rnd / 15.0 * 1.5;
39211
+ vec3 result = COLOR * pattern - vec3(grain);
39212
+ if (uLightMode > 0.5) {
39213
+ float fold = smoothstep(0.28, 0.9, pattern);
39214
+ float specular = smoothstep(0.72, 0.98, pattern);
39215
+ vec3 lightBase = mix(COLOR * 0.72, min(COLOR * 1.18, vec3(1.0)), fold);
39216
+ lightBase = mix(lightBase, vec3(1.0), specular * 0.92);
39217
+ float fineNoise = noise(gl_FragCoord.xy * 0.63 + vec2(17.0, 41.0));
39218
+ result = lightBase + (rnd + fineNoise - 1.0) * clamp(1.5 * 0.038, 0.0, 0.16);
39219
+ }
39220
+ gl_FragColor = vec4(clamp(result, 0.0, 1.0), 1.0);
39221
+ }
39222
+ `, (state) => {
39223
+ const { gl, uniforms, time } = state;
39224
+ gl.useProgram(state.program);
39225
+ gl.uniform1f(uniforms.uTime, time * .1);
39226
+ gl.uniform1f(uniforms.uLightMode, state.light ? 1 : 0);
39227
+ state.draw();
39228
+ });
39229
+ if (handle === null) return;
39230
+ return () => {
39231
+ handle.dispose();
39232
+ };
39233
+ }, []);
39234
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
39235
+ ref: canvasRef,
39236
+ className: canvas_workspace_module_css_default.sceneCanvas,
39237
+ "aria-hidden": "true"
39238
+ });
39239
+ }
39240
+ /** reactbits.dev "Waves": vertical perlin-noise wave lines that spring away
39241
+ * from the pointer (canvas 2D port; strokes follow the theme label color). */
39242
+ function WavesBackground() {
39243
+ const canvasRef = (0, react.useRef)(null);
39244
+ (0, react.useEffect)(() => {
39245
+ const canvas = canvasRef.current;
39246
+ const viewport = (canvas?.parentElement)?.parentElement;
39247
+ if (canvas === null || canvas === void 0 || viewport === null || viewport === void 0) return;
39248
+ const ctx = canvas.getContext("2d");
39249
+ if (ctx === null) return;
39250
+ const GRAD3 = [
39251
+ [1, 1],
39252
+ [-1, 1],
39253
+ [1, -1],
39254
+ [-1, -1],
39255
+ [1, 0],
39256
+ [-1, 0],
39257
+ [1, 0],
39258
+ [-1, 0],
39259
+ [0, 1],
39260
+ [0, -1],
39261
+ [0, 1],
39262
+ [0, -1]
39263
+ ];
39264
+ const PERM_TABLE = [
39265
+ 151,
39266
+ 160,
39267
+ 137,
39268
+ 91,
39269
+ 90,
39270
+ 15,
39271
+ 131,
39272
+ 13,
39273
+ 201,
39274
+ 95,
39275
+ 96,
39276
+ 53,
39277
+ 194,
39278
+ 233,
39279
+ 7,
39280
+ 225,
39281
+ 140,
39282
+ 36,
39283
+ 103,
39284
+ 30,
39285
+ 69,
39286
+ 142,
39287
+ 8,
39288
+ 99,
39289
+ 37,
39290
+ 240,
39291
+ 21,
39292
+ 10,
39293
+ 23,
39294
+ 190,
39295
+ 6,
39296
+ 148,
39297
+ 247,
39298
+ 120,
39299
+ 234,
39300
+ 75,
39301
+ 0,
39302
+ 26,
39303
+ 197,
39304
+ 62,
39305
+ 94,
39306
+ 252,
39307
+ 219,
39308
+ 203,
39309
+ 117,
39310
+ 35,
39311
+ 11,
39312
+ 32,
39313
+ 57,
39314
+ 177,
39315
+ 33,
39316
+ 88,
39317
+ 237,
39318
+ 149,
39319
+ 56,
39320
+ 87,
39321
+ 174,
39322
+ 20,
39323
+ 125,
39324
+ 136,
39325
+ 171,
39326
+ 168,
39327
+ 68,
39328
+ 175,
39329
+ 74,
39330
+ 165,
39331
+ 71,
39332
+ 134,
39333
+ 139,
39334
+ 48,
39335
+ 27,
39336
+ 166,
39337
+ 77,
39338
+ 146,
39339
+ 158,
39340
+ 231,
39341
+ 83,
39342
+ 111,
39343
+ 229,
39344
+ 122,
39345
+ 60,
39346
+ 211,
39347
+ 133,
39348
+ 230,
39349
+ 220,
39350
+ 105,
39351
+ 92,
39352
+ 41,
39353
+ 55,
39354
+ 46,
39355
+ 245,
39356
+ 40,
39357
+ 244,
39358
+ 102,
39359
+ 143,
39360
+ 54,
39361
+ 65,
39362
+ 25,
39363
+ 63,
39364
+ 161,
39365
+ 1,
39366
+ 216,
39367
+ 80,
39368
+ 73,
39369
+ 209,
39370
+ 76,
39371
+ 132,
39372
+ 187,
39373
+ 208,
39374
+ 89,
39375
+ 18,
39376
+ 169,
39377
+ 200,
39378
+ 196,
39379
+ 135,
39380
+ 130,
39381
+ 116,
39382
+ 188,
39383
+ 159,
39384
+ 86,
39385
+ 164,
39386
+ 100,
39387
+ 109,
39388
+ 198,
39389
+ 173,
39390
+ 186,
39391
+ 3,
39392
+ 64,
39393
+ 52,
39394
+ 217,
39395
+ 226,
39396
+ 250,
39397
+ 124,
39398
+ 123,
39399
+ 5,
39400
+ 202,
39401
+ 38,
39402
+ 147,
39403
+ 118,
39404
+ 126,
39405
+ 255,
39406
+ 82,
39407
+ 85,
39408
+ 212,
39409
+ 207,
39410
+ 206,
39411
+ 59,
39412
+ 227,
39413
+ 47,
39414
+ 16,
39415
+ 58,
39416
+ 17,
39417
+ 182,
39418
+ 189,
39419
+ 28,
39420
+ 42,
39421
+ 223,
39422
+ 183,
39423
+ 170,
39424
+ 213,
39425
+ 119,
39426
+ 248,
39427
+ 152,
39428
+ 2,
39429
+ 44,
39430
+ 154,
39431
+ 163,
39432
+ 70,
39433
+ 221,
39434
+ 153,
39435
+ 101,
39436
+ 155,
39437
+ 167,
39438
+ 43,
39439
+ 172,
39440
+ 9,
39441
+ 129,
39442
+ 22,
39443
+ 39,
39444
+ 253,
39445
+ 19,
39446
+ 98,
39447
+ 108,
39448
+ 110,
39449
+ 79,
39450
+ 113,
39451
+ 224,
39452
+ 232,
39453
+ 178,
39454
+ 185,
39455
+ 112,
39456
+ 104,
39457
+ 218,
39458
+ 246,
39459
+ 97,
39460
+ 228,
39461
+ 251,
39462
+ 34,
39463
+ 242,
39464
+ 193,
39465
+ 238,
39466
+ 210,
39467
+ 144,
39468
+ 12,
39469
+ 191,
39470
+ 179,
39471
+ 162,
39472
+ 241,
39473
+ 81,
39474
+ 51,
39475
+ 145,
39476
+ 235,
39477
+ 249,
39478
+ 14,
39479
+ 239,
39480
+ 107,
39481
+ 49,
39482
+ 192,
39483
+ 214,
39484
+ 31,
39485
+ 181,
39486
+ 199,
39487
+ 106,
39488
+ 157,
39489
+ 184,
39490
+ 84,
39491
+ 204,
39492
+ 176,
39493
+ 115,
39494
+ 121,
39495
+ 50,
39496
+ 45,
39497
+ 127,
39498
+ 4,
39499
+ 150,
39500
+ 254,
39501
+ 138,
39502
+ 236,
39503
+ 205,
39504
+ 93,
39505
+ 222,
39506
+ 114,
39507
+ 67,
39508
+ 29,
39509
+ 24,
39510
+ 72,
39511
+ 243,
39512
+ 141,
39513
+ 128,
39514
+ 195,
39515
+ 78,
39516
+ 66,
39517
+ 215,
39518
+ 61,
39519
+ 156,
39520
+ 180
39521
+ ];
39522
+ const perm = /* @__PURE__ */ new Int32Array(512);
39523
+ const permShift = Math.floor(Math.random() * 256);
39524
+ for (let i = 0; i < 512; i++) perm[i] = PERM_TABLE[i + permShift & 255];
39525
+ const fade = (t) => t * t * t * (t * (t * 6 - 15) + 10);
39526
+ const mixNum = (a, b, t) => (1 - t) * a + t * b;
39527
+ const gradDot = (hash, x, y) => {
39528
+ const g = GRAD3[hash % 12];
39529
+ return g[0] * x + g[1] * y;
39530
+ };
39531
+ const perlin2 = (x, y) => {
39532
+ let xi = Math.floor(x);
39533
+ let yi = Math.floor(y);
39534
+ x -= xi;
39535
+ y -= yi;
39536
+ xi &= 255;
39537
+ yi &= 255;
39538
+ const n00 = gradDot(perm[xi + perm[yi]], x, y);
39539
+ const n01 = gradDot(perm[xi + perm[yi + 1]], x, y - 1);
39540
+ const n10 = gradDot(perm[xi + 1 + perm[yi]], x - 1, y);
39541
+ const n11 = gradDot(perm[xi + 1 + perm[yi + 1]], x - 1, y - 1);
39542
+ const u = fade(x);
39543
+ return mixNum(mixNum(n00, n10, u), mixNum(n01, n11, u), fade(y));
39544
+ };
39545
+ const WAVE = {
39546
+ speedX: .0125,
39547
+ speedY: .005,
39548
+ ampX: 32,
39549
+ ampY: 16,
39550
+ xGap: 10,
39551
+ yGap: 32,
39552
+ friction: .925,
39553
+ tension: .005,
39554
+ maxMove: 100
39555
+ };
39556
+ let lines = [];
39557
+ let width = 0;
39558
+ let height = 0;
39559
+ const dpr = Math.max(1, Math.min(2, window.devicePixelRatio ?? 1));
39560
+ const rebuild = () => {
39561
+ const rect = viewport.getBoundingClientRect();
39562
+ width = Math.max(1, Math.round(rect.width));
39563
+ height = Math.max(1, Math.round(rect.height));
39564
+ canvas.width = Math.round(width * dpr);
39565
+ canvas.height = Math.round(height * dpr);
39566
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
39567
+ lines = [];
39568
+ const totalLines = Math.ceil((width + 200) / WAVE.xGap);
39569
+ const totalPoints = Math.ceil((height + 30) / WAVE.yGap);
39570
+ const xStart = (width - WAVE.xGap * totalLines) / 2;
39571
+ const yStart = (height - WAVE.yGap * totalPoints) / 2;
39572
+ for (let i = 0; i <= totalLines; i++) {
39573
+ const points = [];
39574
+ for (let j = 0; j <= totalPoints; j++) points.push({
39575
+ x: xStart + WAVE.xGap * i,
39576
+ y: yStart + WAVE.yGap * j,
39577
+ wx: 0,
39578
+ wy: 0,
39579
+ cx: 0,
39580
+ cy: 0,
39581
+ vx: 0,
39582
+ vy: 0
39583
+ });
39584
+ lines.push(points);
39585
+ }
39586
+ };
39587
+ const lineColor = getComputedStyle(viewport).getPropertyValue("--dsw-alias-label-primary").trim() || "#94a3b8";
39588
+ const mouse = {
39589
+ x: -10,
39590
+ y: 0,
39591
+ sx: 0,
39592
+ sy: 0,
39593
+ lx: 0,
39594
+ ly: 0,
39595
+ vs: 0,
39596
+ angle: 0,
39597
+ set: false
39598
+ };
39599
+ const onPointerMove = (event) => {
39600
+ const rect = viewport.getBoundingClientRect();
39601
+ mouse.x = event.clientX - rect.left;
39602
+ mouse.y = event.clientY - rect.top;
39603
+ if (!mouse.set) {
39604
+ mouse.sx = mouse.x;
39605
+ mouse.sy = mouse.y;
39606
+ mouse.lx = mouse.x;
39607
+ mouse.ly = mouse.y;
39608
+ mouse.set = true;
39609
+ }
39610
+ };
39611
+ const movePoints = (time) => {
39612
+ for (const points of lines) for (const point of points) {
39613
+ const move = perlin2((point.x + time * WAVE.speedX) * .002, (point.y + time * WAVE.speedY) * .0015) * 12;
39614
+ point.wx = Math.cos(move) * WAVE.ampX;
39615
+ point.wy = Math.sin(move) * WAVE.ampY;
39616
+ const dx = point.x - mouse.sx;
39617
+ const dy = point.y - mouse.sy;
39618
+ const dist = Math.hypot(dx, dy);
39619
+ const l = Math.max(175, mouse.vs);
39620
+ if (dist < l) {
39621
+ const s = 1 - dist / l;
39622
+ const f = Math.cos(dist * .001) * s;
39623
+ point.vx += Math.cos(mouse.angle) * f * l * mouse.vs * 65e-5;
39624
+ point.vy += Math.sin(mouse.angle) * f * l * mouse.vs * 65e-5;
39625
+ }
39626
+ point.vx += (0 - point.cx) * WAVE.tension;
39627
+ point.vy += (0 - point.cy) * WAVE.tension;
39628
+ point.vx *= WAVE.friction;
39629
+ point.vy *= WAVE.friction;
39630
+ point.cx += point.vx * 2;
39631
+ point.cy += point.vy * 2;
39632
+ point.cx = Math.min(WAVE.maxMove, Math.max(-WAVE.maxMove, point.cx));
39633
+ point.cy = Math.min(WAVE.maxMove, Math.max(-WAVE.maxMove, point.cy));
39634
+ }
39635
+ };
39636
+ const draw = () => {
39637
+ ctx.clearRect(0, 0, width, height);
39638
+ ctx.beginPath();
39639
+ ctx.strokeStyle = lineColor;
39640
+ ctx.lineWidth = 1;
39641
+ ctx.globalAlpha = .35;
39642
+ for (const points of lines) {
39643
+ const first = points[0];
39644
+ if (first === void 0) continue;
39645
+ ctx.moveTo(first.x + first.wx, first.y + first.wy);
39646
+ for (let idx = 0; idx < points.length; idx++) {
39647
+ const point = points[idx];
39648
+ const isLast = idx === points.length - 1;
39649
+ const cursor = isLast ? 0 : point.cx;
39650
+ const cursorY = isLast ? 0 : point.cy;
39651
+ ctx.lineTo(point.x + point.wx + cursor, point.y + point.wy + cursorY);
39652
+ }
39653
+ }
39654
+ ctx.stroke();
39655
+ ctx.globalAlpha = 1;
39656
+ };
39657
+ const tick = (time) => {
39658
+ mouse.sx += (mouse.x - mouse.sx) * .1;
39659
+ mouse.sy += (mouse.y - mouse.sy) * .1;
39660
+ const dx = mouse.x - mouse.lx;
39661
+ const dy = mouse.y - mouse.ly;
39662
+ mouse.vs += (Math.hypot(dx, dy) - mouse.vs) * .1;
39663
+ mouse.vs = Math.min(100, mouse.vs);
39664
+ mouse.lx = mouse.x;
39665
+ mouse.ly = mouse.y;
39666
+ mouse.angle = Math.atan2(dy, dx);
39667
+ movePoints(time);
39668
+ draw();
39669
+ frame = window.requestAnimationFrame(tick);
39670
+ };
39671
+ rebuild();
39672
+ let frame = 0;
39673
+ if (globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true) {
39674
+ movePoints(0);
39675
+ draw();
39676
+ } else {
39677
+ frame = window.requestAnimationFrame(tick);
39678
+ viewport.addEventListener("pointermove", onPointerMove, true);
39679
+ }
39680
+ const observer = new ResizeObserver(rebuild);
39681
+ observer.observe(viewport);
39682
+ return () => {
39683
+ window.cancelAnimationFrame(frame);
39684
+ observer.disconnect();
39685
+ viewport.removeEventListener("pointermove", onPointerMove);
39686
+ };
39687
+ }, []);
39688
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
39689
+ ref: canvasRef,
39690
+ className: canvas_workspace_module_css_default.sceneCanvas,
39691
+ "aria-hidden": "true"
39692
+ });
39693
+ }
39694
+ /** reactbits.dev "FaultyTerminal": a glowing CRT terminal of random digits
39695
+ * with scanlines, glitch displacement and flicker; the pointer ripples the
39696
+ * character grid (single opaque fragment shader). */
39697
+ function FaultyTerminalBackground() {
39698
+ const canvasRef = (0, react.useRef)(null);
39699
+ (0, react.useEffect)(() => {
39700
+ const canvas = canvasRef.current;
39701
+ const viewport = (canvas?.parentElement)?.parentElement;
39702
+ if (canvas === null || canvas === void 0 || viewport === null || viewport === void 0) return;
39703
+ const fragment = `
39704
+ precision mediump float;
39705
+ varying vec2 vUv;
39706
+ uniform float iTime;
39707
+ uniform vec3 iResolution;
39708
+ uniform vec2 uMouse;
39709
+ uniform float uPageLoadProgress;
39710
+ uniform float uLightMode;
39711
+ // reactbits FaultyTerminal defaults, baked (timeScale 0.3 folded in below).
39712
+ const float TIME_SCALE = 0.333333;
39713
+ const float SCALE = 1.0;
39714
+ const vec2 GRID_MUL = vec2(2.0, 1.0);
39715
+ const float DIGIT_SIZE = 1.5;
39716
+ const float SCANLINE = 0.3;
39717
+ const float FLICKER = 1.0;
39718
+ const float NOISE_AMP = 1.0;
39719
+ const float CURVATURE = 0.2;
39720
+ const float MOUSE_STRENGTH = 0.2;
39721
+ float time;
39722
+ float hash21(vec2 p) {
39723
+ p = fract(p * 234.56);
39724
+ p += dot(p, p + 34.56);
39725
+ return fract(p.x * p.y);
39726
+ }
39727
+ float noise(vec2 p) {
39728
+ return sin(p.x * 10.0) * sin(p.y * (3.0 + sin(time * 0.090909))) + 0.2;
39729
+ }
39730
+ mat2 rotate(float angle) {
39731
+ float c = cos(angle);
39732
+ float s = sin(angle);
39733
+ return mat2(c, -s, s, c);
39734
+ }
39735
+ float fbm(vec2 p) {
39736
+ p *= 1.1;
39737
+ float f = 0.0;
39738
+ float amp = 0.5 * NOISE_AMP;
39739
+ mat2 modify0 = rotate(time * 0.02);
39740
+ f += amp * noise(p);
39741
+ p = modify0 * p * 2.0;
39742
+ amp *= 0.454545;
39743
+ mat2 modify1 = rotate(time * 0.02);
39744
+ f += amp * noise(p);
39745
+ p = modify1 * p * 2.0;
39746
+ amp *= 0.454545;
39747
+ mat2 modify2 = rotate(time * 0.08);
39748
+ f += amp * noise(p);
39749
+ return f;
39750
+ }
39751
+ float pattern(vec2 p, out vec2 q, out vec2 r) {
39752
+ vec2 offset1 = vec2(1.0);
39753
+ vec2 offset0 = vec2(0.0);
39754
+ mat2 rot01 = rotate(0.1 * time);
39755
+ mat2 rot1 = rotate(0.1);
39756
+ q = vec2(fbm(p + offset1), fbm(rot01 * p + offset1));
39757
+ r = vec2(fbm(rot1 * q + offset0), fbm(q + offset0));
39758
+ return fbm(p + r);
39759
+ }
39760
+ float digit(vec2 p) {
39761
+ vec2 grid = GRID_MUL * 15.0;
39762
+ vec2 s = floor(p * grid) / grid;
39763
+ p = p * grid;
39764
+ vec2 q, r;
39765
+ float intensity = pattern(s * 0.1, q, r) * 1.3 - 0.03;
39766
+ vec2 mouseWorld = uMouse * SCALE;
39767
+ float distToMouse = distance(s, mouseWorld);
39768
+ float mouseInfluence = exp(-distToMouse * 8.0) * MOUSE_STRENGTH * 10.0;
39769
+ intensity += mouseInfluence;
39770
+ float ripple = sin(distToMouse * 20.0 - iTime * 5.0) * 0.1 * mouseInfluence;
39771
+ intensity += ripple;
39772
+ float cellRandom = fract(sin(dot(s, vec2(12.9898, 78.233))) * 43758.5453);
39773
+ float cellDelay = cellRandom * 0.8;
39774
+ float cellProgress = clamp((uPageLoadProgress - cellDelay) / 0.2, 0.0, 1.0);
39775
+ intensity *= smoothstep(0.0, 1.0, cellProgress);
39776
+ p = fract(p);
39777
+ p *= DIGIT_SIZE;
39778
+ float px5 = p.x * 5.0;
39779
+ float py5 = (1.0 - p.y) * 5.0;
39780
+ float x = fract(px5);
39781
+ float y = fract(py5);
39782
+ float i = floor(py5) - 2.0;
39783
+ float j = floor(px5) - 2.0;
39784
+ float n = i * i + j * j;
39785
+ float f = n * 0.0625;
39786
+ float isOn = step(0.1, intensity - f);
39787
+ float brightness = isOn * (0.2 + y * 0.8) * (0.75 + x * 0.25);
39788
+ return step(0.0, p.x) * step(p.x, 1.0) * step(0.0, p.y) * step(p.y, 1.0) * brightness;
39789
+ }
39790
+ float onOff(float a, float b, float c) {
39791
+ return step(c, sin(iTime + a * cos(iTime * b))) * FLICKER;
39792
+ }
39793
+ float displace(vec2 look) {
39794
+ float y = look.y - mod(iTime * 0.25, 1.0);
39795
+ float window = 1.0 / (1.0 + 50.0 * y * y);
39796
+ return sin(look.y * 20.0 + iTime) * 0.0125 * onOff(4.0, 2.0, 0.8) * (1.0 + cos(iTime * 60.0)) * window;
39797
+ }
39798
+ vec3 getColor(vec2 p) {
39799
+ float bar = step(mod(p.y + time * 20.0, 1.0), 0.2) * 0.4 + 1.0;
39800
+ bar *= SCANLINE;
39801
+ float displacement = displace(p);
39802
+ p.x += displacement;
39803
+ float middle = digit(p);
39804
+ const float off = 0.002;
39805
+ float sum = digit(p + vec2(-off, -off)) + digit(p + vec2(0.0, -off)) + digit(p + vec2(off, -off)) +
39806
+ digit(p + vec2(-off, 0.0)) + digit(p + vec2(0.0, 0.0)) + digit(p + vec2(off, 0.0)) +
39807
+ digit(p + vec2(-off, off)) + digit(p + vec2(0.0, off)) + digit(p + vec2(off, off));
39808
+ return vec3(0.9) * middle + sum * 0.1 * vec3(1.0) * bar;
39809
+ }
39810
+ vec2 barrel(vec2 uv) {
39811
+ vec2 c = uv * 2.0 - 1.0;
39812
+ c *= 1.0 + CURVATURE * dot(c, c);
39813
+ return c * 0.5 + 0.5;
39814
+ }
39815
+ void main() {
39816
+ time = iTime * TIME_SCALE;
39817
+ vec2 p = barrel(vUv) * SCALE;
39818
+ vec3 col = getColor(p);
39819
+ if (uLightMode > 0.5) {
39820
+ float energy = max(max(col.r, col.g), col.b);
39821
+ float coverage = clamp(smoothstep(0.0, 0.72, energy) * 0.9, 0.0, 0.9);
39822
+ vec3 ink = clamp(col * 0.42, 0.0, 0.76);
39823
+ col = mix(vec3(1.0), ink, coverage);
39824
+ }
39825
+ gl_FragColor = vec4(col, 1.0);
39826
+ }
39827
+ `;
39828
+ const timeOffset = Math.random() * 100;
39829
+ const handle = startShaderCanvas(canvas, viewport, fragment, (state) => {
39830
+ const { gl, uniforms, time, width, height, dpr, pointer } = state;
39831
+ gl.useProgram(state.program);
39832
+ gl.uniform1f(uniforms.iTime, (time + timeOffset) * .3);
39833
+ gl.uniform3f(uniforms.iResolution, width, height, width / Math.max(1, height));
39834
+ gl.uniform2f(uniforms.uMouse, pointer.x / Math.max(1, width / dpr), 1 - pointer.y / Math.max(1, height / dpr));
39835
+ gl.uniform1f(uniforms.uPageLoadProgress, Math.min(1, time / 2));
39836
+ gl.uniform1f(uniforms.uLightMode, state.light ? 1 : 0);
39837
+ state.draw();
39838
+ });
39839
+ if (handle === null) return;
39840
+ return () => {
39841
+ handle.dispose();
39842
+ };
39843
+ }, []);
39844
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
39845
+ ref: canvasRef,
39846
+ className: canvas_workspace_module_css_default.sceneCanvas,
39847
+ "aria-hidden": "true"
39848
+ });
39849
+ }
39850
+ /** reactbits.dev "DotField": a purple dot lattice that bulges away from the
39851
+ * pointer as it moves, springing back home, with a soft glow under the
39852
+ * cursor while the field is engaged (canvas 2D). */
39853
+ function DotFieldBackground() {
39854
+ const canvasRef = (0, react.useRef)(null);
39855
+ (0, react.useEffect)(() => {
39856
+ const canvas = canvasRef.current;
39857
+ const viewport = (canvas?.parentElement)?.parentElement;
39858
+ if (canvas === null || canvas === void 0 || viewport === null || viewport === void 0) return;
39859
+ const ctx = canvas.getContext("2d", { alpha: true });
39860
+ if (ctx === null) return;
39861
+ const FIELD = {
39862
+ radius: 1.5,
39863
+ spacing: 14,
39864
+ cursorRadius: 500,
39865
+ bulgeStrength: 67,
39866
+ glowRadius: 160
39867
+ };
39868
+ const light = detectLightSurface(viewport);
39869
+ const glowInner = light ? "rgba(82, 39, 255, 0.16)" : "rgba(18, 15, 23, 1)";
39870
+ const glowOuter = light ? "rgba(82, 39, 255, 0)" : "rgba(18, 15, 23, 0)";
39871
+ let dots = [];
39872
+ let width = 0;
39873
+ let height = 0;
39874
+ const dpr = Math.max(1, Math.min(2, window.devicePixelRatio ?? 1));
39875
+ const rebuild = () => {
39876
+ const rect = viewport.getBoundingClientRect();
39877
+ width = Math.max(1, Math.round(rect.width));
39878
+ height = Math.max(1, Math.round(rect.height));
39879
+ canvas.width = Math.round(width * dpr);
39880
+ canvas.height = Math.round(height * dpr);
39881
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
39882
+ const step = FIELD.radius + FIELD.spacing;
39883
+ const cols = Math.floor(width / step);
39884
+ const rows = Math.floor(height / step);
39885
+ const padX = width % step / 2;
39886
+ const padY = height % step / 2;
39887
+ dots = [];
39888
+ for (let row = 0; row < rows; row++) for (let col = 0; col < cols; col++) {
39889
+ const ax = padX + col * step + step / 2;
39890
+ const ay = padY + row * step + step / 2;
39891
+ dots.push({
39892
+ ax,
39893
+ ay,
39894
+ sx: ax,
39895
+ sy: ay
39896
+ });
39897
+ }
39898
+ };
39899
+ const mouse = {
39900
+ x: -9999,
39901
+ y: -9999,
39902
+ prevX: -9999,
39903
+ prevY: -9999,
39904
+ speed: 0,
39905
+ seen: false
39906
+ };
39907
+ const onPointerMove = (event) => {
39908
+ const rect = viewport.getBoundingClientRect();
39909
+ mouse.x = event.clientX - rect.left;
39910
+ mouse.y = event.clientY - rect.top;
39911
+ if (!mouse.seen) {
39912
+ mouse.prevX = mouse.x;
39913
+ mouse.prevY = mouse.y;
39914
+ mouse.seen = true;
39915
+ }
39916
+ };
39917
+ let engagement = 0;
39918
+ let glowOpacity = 0;
39919
+ const draw = (frameCount) => {
39920
+ const dx = mouse.prevX - mouse.x;
39921
+ const dy = mouse.prevY - mouse.y;
39922
+ mouse.speed += (Math.hypot(dx, dy) - mouse.speed) * .5;
39923
+ if (mouse.speed < .001) mouse.speed = 0;
39924
+ mouse.prevX = mouse.x;
39925
+ mouse.prevY = mouse.y;
39926
+ const target = Math.min(mouse.speed / 5, 1);
39927
+ engagement += (target - engagement) * .06;
39928
+ if (engagement < .001) engagement = 0;
39929
+ glowOpacity += (engagement - glowOpacity) * .08;
39930
+ ctx.clearRect(0, 0, width, height);
39931
+ if (glowOpacity > .01 && mouse.seen) {
39932
+ const glow = ctx.createRadialGradient(mouse.x, mouse.y, 0, mouse.x, mouse.y, FIELD.glowRadius);
39933
+ glow.addColorStop(0, glowInner);
39934
+ glow.addColorStop(1, glowOuter);
39935
+ ctx.globalAlpha = glowOpacity;
39936
+ ctx.fillStyle = glow;
39937
+ ctx.beginPath();
39938
+ ctx.arc(mouse.x, mouse.y, FIELD.glowRadius, 0, Math.PI * 2);
39939
+ ctx.fill();
39940
+ ctx.globalAlpha = 1;
39941
+ }
39942
+ const gradient = ctx.createLinearGradient(0, 0, width, height);
39943
+ gradient.addColorStop(0, "rgba(168, 85, 247, 0.35)");
39944
+ gradient.addColorStop(1, "rgba(180, 151, 207, 0.25)");
39945
+ ctx.fillStyle = gradient;
39946
+ const crSq = FIELD.cursorRadius * FIELD.cursorRadius;
39947
+ const rad = FIELD.radius / 2;
39948
+ ctx.beginPath();
39949
+ for (const dot of dots) {
39950
+ const dxDot = mouse.x - dot.ax;
39951
+ const dyDot = mouse.y - dot.ay;
39952
+ const distSq = dxDot * dxDot + dyDot * dyDot;
39953
+ if (distSq < crSq && engagement > .01) {
39954
+ const t = 1 - Math.sqrt(distSq) / FIELD.cursorRadius;
39955
+ const push = t * t * FIELD.bulgeStrength * engagement;
39956
+ const angle = Math.atan2(dyDot, dxDot);
39957
+ dot.sx += (dot.ax - Math.cos(angle) * push - dot.sx) * .15;
39958
+ dot.sy += (dot.ay - Math.sin(angle) * push - dot.sy) * .15;
39959
+ } else {
39960
+ dot.sx += (dot.ax - dot.sx) * .1;
39961
+ dot.sy += (dot.ay - dot.sy) * .1;
39962
+ }
39963
+ ctx.moveTo(dot.sx + rad, dot.sy);
39964
+ ctx.arc(dot.sx, dot.sy, rad, 0, Math.PI * 2);
39965
+ }
39966
+ ctx.fill();
39967
+ frame = window.requestAnimationFrame(tick);
39968
+ };
39969
+ const tick = () => {
39970
+ draw(performance.now());
39971
+ };
39972
+ rebuild();
39973
+ let frame = 0;
39974
+ if (globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true) draw(0);
39975
+ else {
39976
+ frame = window.requestAnimationFrame(tick);
39977
+ viewport.addEventListener("pointermove", onPointerMove, true);
39978
+ }
39979
+ const observer = new ResizeObserver(rebuild);
39980
+ observer.observe(viewport);
39981
+ return () => {
39982
+ window.cancelAnimationFrame(frame);
39983
+ observer.disconnect();
39984
+ viewport.removeEventListener("pointermove", onPointerMove);
39985
+ };
39986
+ }, []);
39987
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
39988
+ ref: canvasRef,
39989
+ className: canvas_workspace_module_css_default.sceneCanvas,
39990
+ "aria-hidden": "true"
39991
+ });
39992
+ }
39993
+ /** reactbits.dev "DotGrid": a chunky dot lattice (reactbits default #5227FF)
39994
+ * that reacts to fast pointer strokes and clicks with inertia shockwaves —
39995
+ * dots fly out and elastically spring back (canvas 2D, spring port of the
39996
+ * original's gsap inertia tweens). */
39997
+ function DotGridBackground() {
39998
+ const canvasRef = (0, react.useRef)(null);
39999
+ (0, react.useEffect)(() => {
40000
+ const canvas = canvasRef.current;
40001
+ const viewport = (canvas?.parentElement)?.parentElement;
40002
+ if (canvas === null || canvas === void 0 || viewport === null || viewport === void 0) return;
40003
+ const ctx = canvas.getContext("2d");
40004
+ if (ctx === null) return;
40005
+ const GRID = {
40006
+ dotSize: 16,
40007
+ gap: 32,
40008
+ color: "#5227FF",
40009
+ proximity: 150,
40010
+ speedTrigger: 100,
40011
+ shockRadius: 250,
40012
+ shockStrength: 5
40013
+ };
40014
+ const omega = 7;
40015
+ const damping = 2 * .28 * omega;
40016
+ let dots = [];
40017
+ let width = 0;
40018
+ let height = 0;
40019
+ let lastFrame = 0;
40020
+ const dpr = Math.max(1, Math.min(2, window.devicePixelRatio ?? 1));
40021
+ const rebuild = () => {
40022
+ const rect = viewport.getBoundingClientRect();
40023
+ width = Math.max(1, Math.round(rect.width));
40024
+ height = Math.max(1, Math.round(rect.height));
40025
+ canvas.width = Math.round(width * dpr);
40026
+ canvas.height = Math.round(height * dpr);
40027
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
40028
+ const cell = GRID.dotSize + GRID.gap;
40029
+ const cols = Math.floor((width + GRID.gap) / cell);
40030
+ const rows = Math.floor((height + GRID.gap) / cell);
40031
+ const startX = (width - (cell * cols - GRID.gap)) / 2 + GRID.dotSize / 2;
40032
+ const startY = (height - (cell * rows - GRID.gap)) / 2 + GRID.dotSize / 2;
40033
+ dots = [];
40034
+ for (let y = 0; y < rows; y++) for (let x = 0; x < cols; x++) dots.push({
40035
+ cx: startX + x * cell,
40036
+ cy: startY + y * cell,
40037
+ xo: 0,
40038
+ yo: 0,
40039
+ vxo: 0,
40040
+ vyo: 0
40041
+ });
40042
+ };
40043
+ const pointer = {
40044
+ x: -1e4,
40045
+ y: -1e4,
40046
+ vx: 0,
40047
+ vy: 0,
40048
+ speed: 0,
40049
+ lastTime: 0,
40050
+ lastX: 0,
40051
+ lastY: 0
40052
+ };
40053
+ let lastMoveAt = 0;
40054
+ const onPointerMove = (event) => {
40055
+ const now = performance.now();
40056
+ const dt = pointer.lastTime !== 0 ? now - pointer.lastTime : 16;
40057
+ const dx = event.clientX - pointer.lastX;
40058
+ const dy = event.clientY - pointer.lastY;
40059
+ let vx = dx / Math.max(1, dt) * 1e3;
40060
+ let vy = dy / Math.max(1, dt) * 1e3;
40061
+ const speed = Math.hypot(vx, vy);
40062
+ if (speed > 5e3) {
40063
+ const scale = 5e3 / speed;
40064
+ vx *= scale;
40065
+ vy *= scale;
40066
+ }
40067
+ pointer.lastTime = now;
40068
+ pointer.lastX = event.clientX;
40069
+ pointer.lastY = event.clientY;
40070
+ pointer.vx = vx;
40071
+ pointer.vy = vy;
40072
+ pointer.speed = speed;
40073
+ const rect = viewport.getBoundingClientRect();
40074
+ pointer.x = event.clientX - rect.left;
40075
+ pointer.y = event.clientY - rect.top;
40076
+ if (now - lastMoveAt < 50) return;
40077
+ lastMoveAt = now;
40078
+ if (pointer.speed <= GRID.speedTrigger) return;
40079
+ for (const dot of dots) if (Math.hypot(dot.cx - pointer.x, dot.cy - pointer.y) < GRID.proximity) {
40080
+ dot.vxo += (dot.cx - pointer.x + pointer.vx * .005) * omega;
40081
+ dot.vyo += (dot.cy - pointer.y + pointer.vy * .005) * omega;
40082
+ }
40083
+ };
40084
+ const onClick = (event) => {
40085
+ const rect = viewport.getBoundingClientRect();
40086
+ const cx = event.clientX - rect.left;
40087
+ const cy = event.clientY - rect.top;
40088
+ for (const dot of dots) {
40089
+ const dist = Math.hypot(dot.cx - cx, dot.cy - cy);
40090
+ if (dist < GRID.shockRadius) {
40091
+ const falloff = Math.max(0, 1 - dist / GRID.shockRadius);
40092
+ dot.vxo += (dot.cx - cx) * GRID.shockStrength * falloff * omega;
40093
+ dot.vyo += (dot.cy - cy) * GRID.shockStrength * falloff * omega;
40094
+ }
40095
+ }
40096
+ };
40097
+ const tick = (time) => {
40098
+ const dt = Math.min(.05, lastFrame !== 0 ? (time - lastFrame) / 1e3 : .016);
40099
+ lastFrame = time;
40100
+ ctx.clearRect(0, 0, width, height);
40101
+ ctx.fillStyle = GRID.color;
40102
+ for (const dot of dots) {
40103
+ dot.vxo += (-49 * dot.xo - damping * dot.vxo) * dt;
40104
+ dot.vyo += (-49 * dot.yo - damping * dot.vyo) * dt;
40105
+ dot.xo += dot.vxo * dt;
40106
+ dot.yo += dot.vyo * dt;
40107
+ ctx.beginPath();
40108
+ ctx.arc(dot.cx + dot.xo, dot.cy + dot.yo, GRID.dotSize / 2, 0, Math.PI * 2);
40109
+ ctx.fill();
40110
+ }
40111
+ frame = window.requestAnimationFrame(tick);
40112
+ };
40113
+ let frame = 0;
40114
+ rebuild();
40115
+ if (globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true) {
40116
+ ctx.fillStyle = GRID.color;
40117
+ for (const dot of dots) {
40118
+ ctx.beginPath();
40119
+ ctx.arc(dot.cx, dot.cy, GRID.dotSize / 2, 0, Math.PI * 2);
40120
+ ctx.fill();
40121
+ }
40122
+ } else {
40123
+ frame = window.requestAnimationFrame(tick);
40124
+ viewport.addEventListener("pointermove", onPointerMove, true);
40125
+ viewport.addEventListener("click", onClick, true);
40126
+ }
40127
+ const observer = new ResizeObserver(rebuild);
40128
+ observer.observe(viewport);
40129
+ return () => {
40130
+ window.cancelAnimationFrame(frame);
40131
+ observer.disconnect();
40132
+ viewport.removeEventListener("pointermove", onPointerMove);
40133
+ viewport.removeEventListener("click", onClick);
40134
+ };
40135
+ }, []);
40136
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
40137
+ ref: canvasRef,
40138
+ className: canvas_workspace_module_css_default.sceneCanvas,
40139
+ "aria-hidden": "true"
40140
+ });
40141
+ }
40142
+ /** reactbits.dev "ShapeGrid": a continuously scrolling square grid; the cell
40143
+ * under the pointer fills dark while it passes (canvas 2D). */
40144
+ function ShapeGridBackground() {
40145
+ const canvasRef = (0, react.useRef)(null);
40146
+ (0, react.useEffect)(() => {
40147
+ const canvas = canvasRef.current;
40148
+ const viewport = (canvas?.parentElement)?.parentElement;
40149
+ if (canvas === null || canvas === void 0 || viewport === null || viewport === void 0) return;
40150
+ const ctx = canvas.getContext("2d");
40151
+ if (ctx === null) return;
40152
+ const SHAPE = {
40153
+ size: 40,
40154
+ speed: 1,
40155
+ border: "#999999",
40156
+ hoverFill: "#222222"
40157
+ };
40158
+ let width = 0;
40159
+ let height = 0;
40160
+ const dpr = Math.max(1, Math.min(2, window.devicePixelRatio ?? 1));
40161
+ const offset = {
40162
+ x: 0,
40163
+ y: 0
40164
+ };
40165
+ const opacities = /* @__PURE__ */ new Map();
40166
+ let hovered = null;
40167
+ const rebuild = () => {
40168
+ const rect = viewport.getBoundingClientRect();
40169
+ width = Math.max(1, Math.round(rect.width));
40170
+ height = Math.max(1, Math.round(rect.height));
40171
+ canvas.width = Math.round(width * dpr);
40172
+ canvas.height = Math.round(height * dpr);
40173
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
40174
+ };
40175
+ const wrap = (value, modulo) => (value % modulo + modulo) % modulo;
40176
+ const cellOffsetX = () => wrap(offset.x, SHAPE.size);
40177
+ const cellOffsetY = () => wrap(offset.y, SHAPE.size);
40178
+ const draw = () => {
40179
+ ctx.clearRect(0, 0, width, height);
40180
+ const offsetX = cellOffsetX();
40181
+ const offsetY = cellOffsetY();
40182
+ const cols = Math.ceil(width / SHAPE.size) + 3;
40183
+ const rows = Math.ceil(height / SHAPE.size) + 3;
40184
+ ctx.strokeStyle = SHAPE.border;
40185
+ ctx.lineWidth = 1;
40186
+ for (let col = -2; col < cols; col++) for (let row = -2; row < rows; row++) {
40187
+ const sx = col * SHAPE.size + offsetX;
40188
+ const sy = row * SHAPE.size + offsetY;
40189
+ const key = `${col},${row}`;
40190
+ const alpha = opacities.get(key);
40191
+ if (alpha !== void 0) {
40192
+ ctx.globalAlpha = alpha;
40193
+ ctx.fillStyle = SHAPE.hoverFill;
40194
+ ctx.fillRect(sx, sy, SHAPE.size, SHAPE.size);
40195
+ ctx.globalAlpha = 1;
40196
+ }
40197
+ ctx.strokeRect(sx, sy, SHAPE.size, SHAPE.size);
40198
+ }
40199
+ };
40200
+ const updateOpacities = () => {
40201
+ for (const [key, opacity] of opacities) {
40202
+ const next = opacity + ((hovered !== null && key === `${hovered.x},${hovered.y}` ? 1 : 0) - opacity) * .15;
40203
+ if (next < .005) opacities.delete(key);
40204
+ else opacities.set(key, next);
40205
+ }
40206
+ if (hovered !== null && !opacities.has(`${hovered.x},${hovered.y}`)) opacities.set(`${hovered.x},${hovered.y}`, 0);
40207
+ };
40208
+ const tick = () => {
40209
+ offset.x = wrap(offset.x - SHAPE.speed, SHAPE.size);
40210
+ updateOpacities();
40211
+ draw();
40212
+ frame = window.requestAnimationFrame(tick);
40213
+ };
40214
+ const onPointerMove = (event) => {
40215
+ const rect = viewport.getBoundingClientRect();
40216
+ const col = Math.floor((event.clientX - rect.left - cellOffsetX()) / SHAPE.size);
40217
+ const row = Math.floor((event.clientY - rect.top - cellOffsetY()) / SHAPE.size);
40218
+ if (hovered === null || hovered.x !== col || hovered.y !== row) hovered = {
40219
+ x: col,
40220
+ y: row
40221
+ };
40222
+ };
40223
+ const onPointerLeave = () => {
40224
+ hovered = null;
40225
+ };
40226
+ rebuild();
40227
+ let frame = 0;
40228
+ if (globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true) draw();
40229
+ else {
40230
+ frame = window.requestAnimationFrame(tick);
40231
+ viewport.addEventListener("pointermove", onPointerMove, true);
40232
+ viewport.addEventListener("pointerleave", onPointerLeave);
40233
+ }
40234
+ const observer = new ResizeObserver(rebuild);
40235
+ observer.observe(viewport);
40236
+ return () => {
40237
+ window.cancelAnimationFrame(frame);
40238
+ observer.disconnect();
40239
+ viewport.removeEventListener("pointermove", onPointerMove);
40240
+ viewport.removeEventListener("pointerleave", onPointerLeave);
40241
+ };
40242
+ }, []);
40243
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
40244
+ ref: canvasRef,
40245
+ className: canvas_workspace_module_css_default.sceneCanvas,
40246
+ "aria-hidden": "true"
40247
+ });
40248
+ }
40249
+ //#endregion
40250
+ //#region src/client/CanvasWorkspace.tsx
40251
+ /** Infinite canvas workspace, rebuilt after the node-graph model of
40252
+ * basketikun/infinite-canvas: free nodes (image/text), drag-to-connect edges,
40253
+ * marquee + multi selection, context menus, minimap, undo/redo and a floating
40254
+ * generation composer. Selecting a node pops the composer: the prompt is typed
40255
+ * there (or supplied by connected text nodes), every upstream image node joins
40256
+ * as a reference, and results land as new image nodes on the right. */
40257
+ const MIN_SCALE = .05;
40258
+ const MAX_SCALE = 5;
40259
+ const GRID_SIZE = 48;
40260
+ const IMAGE_NODE_SIZE = {
40261
+ width: 240,
40262
+ height: 240
40263
+ };
40264
+ const TEXT_NODE_SIZE = {
40265
+ width: 280,
40266
+ height: 150
40267
+ };
40268
+ const CONFIG_NODE_SIZE = {
40269
+ width: 320,
40270
+ height: 190
40271
+ };
40272
+ const LEGACY_CONFIG_NODE_SIZE = {
40273
+ width: 240,
40274
+ height: 96
40275
+ };
40276
+ const WORLD_PAD = 12e3;
40277
+ function newId(prefix) {
40278
+ return `${prefix}-${globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`}`;
40279
+ }
40280
+ function imageDataUrl(image) {
40281
+ return `data:${image.mime};base64,${image.b64}`;
40282
+ }
40283
+ function readImageSize(src) {
40284
+ return new Promise((resolve, reject) => {
40285
+ const image = new Image();
40286
+ image.onload = () => resolve({
40287
+ width: image.naturalWidth || 1,
40288
+ height: image.naturalHeight || 1
40289
+ });
40290
+ image.onerror = () => reject(/* @__PURE__ */ new Error("无法读取图片尺寸"));
40291
+ image.src = src;
40292
+ });
40293
+ }
40294
+ async function assetToDataUrl(asset) {
40295
+ if (asset.url.startsWith("data:")) return asset.url;
40296
+ const response = await fetch(asset.url);
40297
+ if (!response.ok) throw new Error("读取画布图片失败");
40298
+ const blob = await response.blob();
40299
+ return await new Promise((resolve, reject) => {
40300
+ const reader = new FileReader();
40301
+ reader.onload = () => resolve(String(reader.result));
40302
+ reader.onerror = () => reject(/* @__PURE__ */ new Error("读取画布图片失败"));
40303
+ reader.readAsDataURL(blob);
40304
+ });
40305
+ }
40306
+ function clampScale(scale) {
40307
+ return Math.min(MAX_SCALE, Math.max(MIN_SCALE, scale));
40308
+ }
40309
+ function sizeForAsset(asset) {
40310
+ const ratio = asset.width > 0 && asset.height > 0 ? asset.width / asset.height : 1;
40311
+ if (ratio >= 1) return {
40312
+ width: IMAGE_NODE_SIZE.width,
40313
+ height: Math.max(160, Math.round(IMAGE_NODE_SIZE.width / ratio))
40314
+ };
40315
+ return {
40316
+ width: Math.max(200, Math.round(IMAGE_NODE_SIZE.height * ratio)),
40317
+ height: IMAGE_NODE_SIZE.height
40318
+ };
40319
+ }
40320
+ /** Node footprint for a generation size ratio such as '1:1' or '16:9'. */
40321
+ function nodeSizeFromRatio(size, spec) {
40322
+ const match = /^(\d+):(\d+)$/.exec(size ?? "");
40323
+ if (match === null) return { ...spec };
40324
+ const width = Number(match[1]);
40325
+ const height = Number(match[2]);
40326
+ if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return { ...spec };
40327
+ const ratio = width / height;
40328
+ return ratio >= 1 ? {
40329
+ width: spec.width,
40330
+ height: Math.max(160, Math.round(spec.width / ratio))
40331
+ } : {
40332
+ width: Math.max(200, Math.round(spec.height * ratio)),
40333
+ height: spec.height
40334
+ };
40335
+ }
40336
+ function nodesBounds(nodes) {
40337
+ return nodes.reduce((acc, node) => ({
40338
+ minX: Math.min(acc.minX, node.x),
40339
+ minY: Math.min(acc.minY, node.y),
40340
+ maxX: Math.max(acc.maxX, node.x + node.width),
38170
40341
  maxY: Math.max(acc.maxY, node.y + node.height)
38171
40342
  }), {
38172
40343
  minX: Infinity,
@@ -39792,7 +41963,7 @@ window.__ModuleLoader__.load({
39792
41963
  return related;
39793
41964
  }, [document, selectedIds]);
39794
41965
  const cursorClass = tool === "pan" || temporaryPanTool ? canvas_workspace_module_css_default.panCursor : canvas_workspace_module_css_default.selectCursor;
39795
- const backgroundMode = document?.background ?? "dots";
41966
+ const backgroundMode = document?.background ?? "liquid";
39796
41967
  const setBackgroundMode = (0, react.useCallback)((mode) => {
39797
41968
  mutate((previous) => ({
39798
41969
  ...previous,
@@ -40640,13 +42811,25 @@ window.__ModuleLoader__.load({
40640
42811
  backgroundImage: `url(${document.backgroundImage})`,
40641
42812
  backgroundSize: "cover",
40642
42813
  backgroundPosition: "center"
40643
- } : backgroundMode === "aurora" ? void 0 : {
42814
+ } : backgroundMode === "liquid" || backgroundMode === "floatingLines" || backgroundMode === "galaxy" || backgroundMode === "silk" || backgroundMode === "waves" || backgroundMode === "faultyTerminal" || backgroundMode === "dotField" || backgroundMode === "dotGrid" || backgroundMode === "shapeGrid" ? void 0 : {
40644
42815
  backgroundSize: `${gridSize}px ${gridSize}px`,
40645
42816
  backgroundPosition: `${gridOffsetX}px ${gridOffsetY}px`
40646
42817
  },
40647
42818
  "data-mode": backgroundMode,
40648
42819
  "aria-hidden": "true",
40649
- children: [backgroundMode === "image" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: canvas_workspace_module_css_default.gridScrim }) : null, backgroundMode === "flow" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FlowBackground, {}) : null]
42820
+ children: [
42821
+ backgroundMode === "image" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: canvas_workspace_module_css_default.gridScrim }) : null,
42822
+ backgroundMode === "flow" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FlowBackground, {}) : null,
42823
+ backgroundMode === "liquid" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LiquidEtherBackground, {}) : null,
42824
+ backgroundMode === "floatingLines" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FloatingLinesBackground, {}) : null,
42825
+ backgroundMode === "galaxy" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GalaxyBackground, {}) : null,
42826
+ backgroundMode === "silk" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SilkBackground, {}) : null,
42827
+ backgroundMode === "waves" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WavesBackground, {}) : null,
42828
+ backgroundMode === "faultyTerminal" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FaultyTerminalBackground, {}) : null,
42829
+ backgroundMode === "dotField" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DotFieldBackground, {}) : null,
42830
+ backgroundMode === "dotGrid" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DotGridBackground, {}) : null,
42831
+ backgroundMode === "shapeGrid" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShapeGridBackground, {}) : null
42832
+ ]
40650
42833
  }),
40651
42834
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
40652
42835
  className: canvas_workspace_module_css_default.world,
@@ -40872,10 +43055,16 @@ window.__ModuleLoader__.load({
40872
43055
  [
40873
43056
  ["dots", tt("canvas.backgroundDots")],
40874
43057
  ["lines", tt("canvas.backgroundLines")],
40875
- ["diagonal", tt("canvas.backgroundDiagonal")],
40876
- ["checker", tt("canvas.backgroundChecker")],
43058
+ ["waves", tt("canvas.backgroundWaves")],
43059
+ ["shapeGrid", tt("canvas.backgroundShapeGrid")],
43060
+ ["dotField", tt("canvas.backgroundDotField")],
43061
+ ["dotGrid", tt("canvas.backgroundDotGrid")],
43062
+ ["floatingLines", tt("canvas.backgroundFloatingLines")],
40877
43063
  ["flow", tt("canvas.backgroundFlow")],
40878
- ["aurora", tt("canvas.backgroundAurora")],
43064
+ ["liquid", tt("canvas.backgroundLiquid")],
43065
+ ["faultyTerminal", tt("canvas.backgroundFaultyTerminal")],
43066
+ ["silk", tt("canvas.backgroundSilk")],
43067
+ ["galaxy", tt("canvas.backgroundGalaxy")],
40879
43068
  ["blank", tt("canvas.backgroundBlank")]
40880
43069
  ].map(([mode, label]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
40881
43070
  type: "button",
@@ -41061,115 +43250,6 @@ window.__ModuleLoader__.load({
41061
43250
  ]
41062
43251
  });
41063
43252
  }
41064
- /** Interactive flowmap-style dot field ("fluid distortion"): the pointer's
41065
- * velocity pushes dots sideways like a fluid; they spring back home when it
41066
- * moves on, with a barely-visible idle drift keeping the field alive. */
41067
- function FlowBackground() {
41068
- const canvasRef = (0, react.useRef)(null);
41069
- (0, react.useEffect)(() => {
41070
- const canvas = canvasRef.current;
41071
- const viewport = (canvas?.parentElement)?.parentElement;
41072
- if (canvas === null || canvas === void 0 || viewport === null || viewport === void 0) return;
41073
- const ctx = canvas.getContext("2d");
41074
- if (ctx === null) return;
41075
- const pointer = {
41076
- x: -1e4,
41077
- y: -1e4,
41078
- vx: 0,
41079
- vy: 0,
41080
- seen: false
41081
- };
41082
- const SPACING = 44;
41083
- const RADIUS = 120;
41084
- let width = 0;
41085
- let height = 0;
41086
- let points = [];
41087
- const rebuild = () => {
41088
- const rect = viewport.getBoundingClientRect();
41089
- const dpr = Math.max(1, Math.min(2, window.devicePixelRatio ?? 1));
41090
- width = Math.max(1, Math.round(rect.width));
41091
- height = Math.max(1, Math.round(rect.height));
41092
- canvas.width = Math.round(width * dpr);
41093
- canvas.height = Math.round(height * dpr);
41094
- ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
41095
- points = [];
41096
- for (let y = SPACING / 2; y < height; y += SPACING) for (let x = SPACING / 2; x < width; x += SPACING) points.push({
41097
- hx: x,
41098
- hy: y,
41099
- x,
41100
- y,
41101
- vx: 0,
41102
- vy: 0
41103
- });
41104
- };
41105
- rebuild();
41106
- const observer = new ResizeObserver(rebuild);
41107
- observer.observe(viewport);
41108
- const onMove = (event) => {
41109
- const rect = viewport.getBoundingClientRect();
41110
- const x = event.clientX - rect.left;
41111
- const y = event.clientY - rect.top;
41112
- if (pointer.seen) {
41113
- pointer.vx = pointer.vx * .6 + (x - pointer.x) * .4;
41114
- pointer.vy = pointer.vy * .6 + (y - pointer.y) * .4;
41115
- }
41116
- pointer.x = x;
41117
- pointer.y = y;
41118
- pointer.seen = true;
41119
- };
41120
- const onLeave = () => {
41121
- pointer.x = -1e4;
41122
- pointer.y = -1e4;
41123
- pointer.vx = 0;
41124
- pointer.vy = 0;
41125
- };
41126
- viewport.addEventListener("pointermove", onMove, true);
41127
- viewport.addEventListener("pointerleave", onLeave);
41128
- let frame = 0;
41129
- let time = 0;
41130
- const tick = () => {
41131
- time += .016;
41132
- for (const p of points) {
41133
- p.vx += (p.hx + Math.sin(time * 1.3 + p.hy * .055) * .5 - p.x) * .03;
41134
- p.vy += (p.hy + Math.cos(time * 1.1 + p.hx * .055) * .5 - p.y) * .03;
41135
- const dx = p.x - pointer.x;
41136
- const dy = p.y - pointer.y;
41137
- const d2 = dx * dx + dy * dy;
41138
- if (d2 < RADIUS * RADIUS && d2 > .01) {
41139
- const d = Math.sqrt(d2);
41140
- const force = (1 - d / RADIUS) * .9;
41141
- p.vx += pointer.vx * force + dx / d * force * 2.2;
41142
- p.vy += pointer.vy * force + dy / d * force * 2.2;
41143
- }
41144
- p.vx *= .86;
41145
- p.vy *= .86;
41146
- p.x += p.vx;
41147
- p.y += p.vy;
41148
- }
41149
- ctx.clearRect(0, 0, width, height);
41150
- for (const p of points) {
41151
- const speed = Math.min(4, Math.hypot(p.vx, p.vy));
41152
- ctx.fillStyle = `rgba(96, 125, 255, ${(.16 + speed * .16).toFixed(3)})`;
41153
- ctx.beginPath();
41154
- ctx.arc(p.x, p.y, 1.4 + Math.min(1.8, speed * .5), 0, Math.PI * 2);
41155
- ctx.fill();
41156
- }
41157
- frame = window.requestAnimationFrame(tick);
41158
- };
41159
- frame = window.requestAnimationFrame(tick);
41160
- return () => {
41161
- window.cancelAnimationFrame(frame);
41162
- observer.disconnect();
41163
- viewport.removeEventListener("pointermove", onMove);
41164
- viewport.removeEventListener("pointerleave", onLeave);
41165
- };
41166
- }, []);
41167
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
41168
- ref: canvasRef,
41169
- className: canvas_workspace_module_css_default.flowCanvas,
41170
- "aria-hidden": "true"
41171
- });
41172
- }
41173
43253
  function ImagePicker(props) {
41174
43254
  const { api, history, gallery, imageModels, defaultChannelId, canvasId, connected, onClose, onAssets } = props;
41175
43255
  const [tab, setTab] = (0, react.useState)(props.initialTab ?? "upload");
@@ -41873,226 +43953,226 @@ window.__ModuleLoader__.load({
41873
43953
  document.head.appendChild(tag);
41874
43954
  }
41875
43955
  var panel_module_css_default = {
41876
- "comparisonFullscreen": "Yvqh9W_comparisonFullscreen",
41877
- "dshImageGenToastIn": "Yvqh9W_dshImageGenToastIn",
41878
- "galleryAvatar": "Yvqh9W_galleryAvatar",
41879
- "taskTrayCount": "Yvqh9W_taskTrayCount",
41880
- "paramLabel": "Yvqh9W_paramLabel",
41881
- "conversationToast": "Yvqh9W_conversationToast",
41882
- "lightboxScaleFrame": "Yvqh9W_lightboxScaleFrame",
43956
+ "galleryFilterDivider": "Yvqh9W_galleryFilterDivider",
43957
+ "galleryTagFilter": "Yvqh9W_galleryTagFilter",
43958
+ "gallerySelectionClear": "Yvqh9W_gallerySelectionClear",
43959
+ "lightboxZoomLevel": "Yvqh9W_lightboxZoomLevel",
43960
+ "lightboxMeta": "Yvqh9W_lightboxMeta",
43961
+ "galleryCardAction": "Yvqh9W_galleryCardAction",
43962
+ "panelHeader": "Yvqh9W_panelHeader",
43963
+ "historyFilters": "Yvqh9W_historyFilters",
41883
43964
  "taskRow": "Yvqh9W_taskRow",
41884
- "chatResizer": "Yvqh9W_chatResizer",
41885
- "ecommerceAdvancedChevron": "Yvqh9W_ecommerceAdvancedChevron",
41886
- "ecommercePlanList": "Yvqh9W_ecommercePlanList",
41887
- "ecommerceSlotCard": "Yvqh9W_ecommerceSlotCard",
41888
- "taskStatus": "Yvqh9W_taskStatus",
41889
- "historyList": "Yvqh9W_historyList",
41890
- "historyInfo": "Yvqh9W_historyInfo",
41891
- "ecommerceField": "Yvqh9W_ecommerceField",
41892
- "configResizer": "Yvqh9W_configResizer",
41893
- "uploadIcon": "Yvqh9W_uploadIcon",
41894
- "card": "Yvqh9W_card",
41895
- "ecommerceGroups": "Yvqh9W_ecommerceGroups",
41896
- "paramGroup": "Yvqh9W_paramGroup",
41897
- "galleryRatioList": "Yvqh9W_galleryRatioList",
41898
- "ecommerceResultsHeader": "Yvqh9W_ecommerceResultsHeader",
41899
- "connectionStatus": "Yvqh9W_connectionStatus",
41900
- "taskTray": "Yvqh9W_taskTray",
41901
- "galleryHeading": "Yvqh9W_galleryHeading",
41902
- "entry": "Yvqh9W_entry",
41903
- "ecommercePlanNote": "Yvqh9W_ecommercePlanNote",
43965
+ "sessionTabLabel": "Yvqh9W_sessionTabLabel",
43966
+ "galleryRatio": "Yvqh9W_galleryRatio",
43967
+ "topNav": "Yvqh9W_topNav",
43968
+ "ecommerceSlotCount": "Yvqh9W_ecommerceSlotCount",
41904
43969
  "optionGrid": "Yvqh9W_optionGrid",
41905
- "comparisonGrid": "Yvqh9W_comparisonGrid",
41906
- "ecommerceAdvancedToggle": "Yvqh9W_ecommerceAdvancedToggle",
41907
- "ecommerceActionChip": "Yvqh9W_ecommerceActionChip",
41908
- "reference": "Yvqh9W_reference",
41909
- "lightboxMeta": "Yvqh9W_lightboxMeta",
41910
- "lightboxCaptionRow": "Yvqh9W_lightboxCaptionRow",
41911
- "galleryFilters": "Yvqh9W_galleryFilters",
41912
- "galleryBulkButton": "Yvqh9W_galleryBulkButton",
41913
- "ecommerceResultsEmpty": "Yvqh9W_ecommerceResultsEmpty",
41914
- "modelSelect": "Yvqh9W_modelSelect",
43970
+ "ecommerceSection": "Yvqh9W_ecommerceSection",
43971
+ "modePill": "Yvqh9W_modePill",
43972
+ "compareControl": "Yvqh9W_compareControl",
43973
+ "galleryImageButton": "Yvqh9W_galleryImageButton",
43974
+ "studio": "Yvqh9W_studio",
43975
+ "configGuideBody": "Yvqh9W_configGuideBody",
41915
43976
  "taskTrayHeader": "Yvqh9W_taskTrayHeader",
41916
- "ecommercePlanBack": "Yvqh9W_ecommercePlanBack",
41917
- "zoomHint": "Yvqh9W_zoomHint",
41918
- "gallerySelectionClear": "Yvqh9W_gallerySelectionClear",
41919
- "generateInner": "Yvqh9W_generateInner",
41920
- "lightboxEdit": "Yvqh9W_lightboxEdit",
41921
- "download": "Yvqh9W_download",
41922
- "ecommerceWorkspace": "Yvqh9W_ecommerceWorkspace",
41923
- "lightboxZoomLevel": "Yvqh9W_lightboxZoomLevel",
41924
- "updateActions": "Yvqh9W_updateActions",
43977
+ "lightboxStage": "Yvqh9W_lightboxStage",
43978
+ "gallerySelectMode": "Yvqh9W_gallerySelectMode",
43979
+ "galleryViewToggle": "Yvqh9W_galleryViewToggle",
43980
+ "comparisonFullscreenGrid": "Yvqh9W_comparisonFullscreenGrid",
41925
43981
  "galleryToast": "Yvqh9W_galleryToast",
41926
- "ecommerceFooterBody": "Yvqh9W_ecommerceFooterBody",
41927
- "galleryRatio": "Yvqh9W_galleryRatio",
43982
+ "enhanceButton": "Yvqh9W_enhanceButton",
43983
+ "lightboxCaptionRow": "Yvqh9W_lightboxCaptionRow",
43984
+ "gallerySort": "Yvqh9W_gallerySort",
41928
43985
  "panelHeaderActions": "Yvqh9W_panelHeaderActions",
41929
- "gallerySelectionBar": "Yvqh9W_gallerySelectionBar",
41930
- "lightboxCaption": "Yvqh9W_lightboxCaption",
41931
- "gallerySelectMode": "Yvqh9W_gallerySelectMode",
43986
+ "galleryFilterHeading": "Yvqh9W_galleryFilterHeading",
43987
+ "conversationAdd": "Yvqh9W_conversationAdd",
43988
+ "canvasMeta": "Yvqh9W_canvasMeta",
43989
+ "comparisonBoard": "Yvqh9W_comparisonBoard",
43990
+ "galleryAvatar": "Yvqh9W_galleryAvatar",
43991
+ "canvas": "Yvqh9W_canvas",
43992
+ "historySearch": "Yvqh9W_historySearch",
43993
+ "historyInfo": "Yvqh9W_historyInfo",
43994
+ "optionPill": "Yvqh9W_optionPill",
43995
+ "galleryTagInput": "Yvqh9W_galleryTagInput",
43996
+ "config": "Yvqh9W_config",
43997
+ "generateInner": "Yvqh9W_generateInner",
43998
+ "galleryCardInfo": "Yvqh9W_galleryCardInfo",
43999
+ "galleryCardActions": "Yvqh9W_galleryCardActions",
41932
44000
  "galleryAdd": "Yvqh9W_galleryAdd",
41933
- "ecommerceFieldLabel": "Yvqh9W_ecommerceFieldLabel",
44001
+ "lightboxCaption": "Yvqh9W_lightboxCaption",
44002
+ "ecommerceGroup": "Yvqh9W_ecommerceGroup",
44003
+ "ecommerceActionChip": "Yvqh9W_ecommerceActionChip",
44004
+ "galleryTagFilterList": "Yvqh9W_galleryTagFilterList",
44005
+ "galleryImage": "Yvqh9W_galleryImage",
44006
+ "galleryFilterNote": "Yvqh9W_galleryFilterNote",
44007
+ "configToggle": "Yvqh9W_configToggle",
44008
+ "lightboxTools": "Yvqh9W_lightboxTools",
44009
+ "paramLabel": "Yvqh9W_paramLabel",
41934
44010
  "referenceImage": "Yvqh9W_referenceImage",
41935
- "templatesButton": "Yvqh9W_templatesButton",
41936
- "studio": "Yvqh9W_studio",
44011
+ "ecommerceAsset": "Yvqh9W_ecommerceAsset",
44012
+ "panel": "Yvqh9W_panel",
41937
44013
  "generation": "Yvqh9W_generation",
41938
- "lightboxTool": "Yvqh9W_lightboxTool",
41939
- "topNavDivider": "Yvqh9W_topNavDivider",
41940
- "ecommerceSlotCount": "Yvqh9W_ecommerceSlotCount",
41941
- "taskTrayToggle": "Yvqh9W_taskTrayToggle",
41942
- "topNavItem": "Yvqh9W_topNavItem",
41943
44014
  "historyMeta": "Yvqh9W_historyMeta",
41944
- "ecommercePrimaryAction": "Yvqh9W_ecommercePrimaryAction",
41945
- "previewBadge": "Yvqh9W_previewBadge",
41946
- "canvasBody": "Yvqh9W_canvasBody",
41947
- "ecommerceFooterHint": "Yvqh9W_ecommerceFooterHint",
41948
- "ecommerceStructureGrid": "Yvqh9W_ecommerceStructureGrid",
41949
- "historyMain": "Yvqh9W_historyMain",
41950
- "configHeader": "Yvqh9W_configHeader",
41951
- "historySearch": "Yvqh9W_historySearch",
44015
+ "ecommerceAdvancedChevron": "Yvqh9W_ecommerceAdvancedChevron",
44016
+ "lightboxClose": "Yvqh9W_lightboxClose",
41952
44017
  "githubLink": "Yvqh9W_githubLink",
41953
- "historyClear": "Yvqh9W_historyClear",
41954
- "canvasStateHint": "Yvqh9W_canvasStateHint",
41955
- "canvas": "Yvqh9W_canvas",
41956
- "ecommerceAsset": "Yvqh9W_ecommerceAsset",
44018
+ "ecommerceFieldLabel": "Yvqh9W_ecommerceFieldLabel",
44019
+ "dshImageGenToastIn": "Yvqh9W_dshImageGenToastIn",
44020
+ "card": "Yvqh9W_card",
44021
+ "ecommercePlanBack": "Yvqh9W_ecommercePlanBack",
44022
+ "ecommercePrimaryAction": "Yvqh9W_ecommercePrimaryAction",
44023
+ "compareModelChoices": "Yvqh9W_compareModelChoices",
44024
+ "generateButton": "Yvqh9W_generateButton",
44025
+ "lightboxIndex": "Yvqh9W_lightboxIndex",
44026
+ "ecommerceFooterBody": "Yvqh9W_ecommerceFooterBody",
44027
+ "panelTitle": "Yvqh9W_panelTitle",
44028
+ "modelMenuList": "Yvqh9W_modelMenuList",
44029
+ "galleryCardFooter": "Yvqh9W_galleryCardFooter",
44030
+ "view": "Yvqh9W_view",
44031
+ "gallerySelect": "Yvqh9W_gallerySelect",
44032
+ "galleryTagEdit": "Yvqh9W_galleryTagEdit",
41957
44033
  "history": "Yvqh9W_history",
41958
- "historyHeaderActions": "Yvqh9W_historyHeaderActions",
41959
- "ecommerceGroupGrid": "Yvqh9W_ecommerceGroupGrid",
44034
+ "historyEmpty": "Yvqh9W_historyEmpty",
44035
+ "comparisonFullscreen": "Yvqh9W_comparisonFullscreen",
44036
+ "updateText": "Yvqh9W_updateText",
44037
+ "canvasEmptyIcon": "Yvqh9W_canvasEmptyIcon",
44038
+ "historyList": "Yvqh9W_historyList",
44039
+ "gallerySearch": "Yvqh9W_gallerySearch",
44040
+ "ecommerceField": "Yvqh9W_ecommerceField",
44041
+ "ecommerceAssets": "Yvqh9W_ecommerceAssets",
44042
+ "taskPrompt": "Yvqh9W_taskPrompt",
44043
+ "zoomHint": "Yvqh9W_zoomHint",
44044
+ "historyTitle": "Yvqh9W_historyTitle",
44045
+ "connectionStatus": "Yvqh9W_connectionStatus",
44046
+ "lightboxScaleFrame": "Yvqh9W_lightboxScaleFrame",
44047
+ "ecommercePlanNote": "Yvqh9W_ecommercePlanNote",
44048
+ "ecommerceRefRow": "Yvqh9W_ecommerceRefRow",
44049
+ "ecommerceSlotCard": "Yvqh9W_ecommerceSlotCard",
44050
+ "historyHeader": "Yvqh9W_historyHeader",
44051
+ "prompt": "Yvqh9W_prompt",
44052
+ "configGuide": "Yvqh9W_configGuide",
44053
+ "taskStatus": "Yvqh9W_taskStatus",
44054
+ "previewBadge": "Yvqh9W_previewBadge",
44055
+ "lightboxImage": "Yvqh9W_lightboxImage",
44056
+ "reference": "Yvqh9W_reference",
44057
+ "templatesButton": "Yvqh9W_templatesButton",
44058
+ "conversationToast": "Yvqh9W_conversationToast",
44059
+ "configResizer": "Yvqh9W_configResizer",
44060
+ "canvasHistoryTag": "Yvqh9W_canvasHistoryTag",
44061
+ "lightboxCopy": "Yvqh9W_lightboxCopy",
44062
+ "ecommerceResults": "Yvqh9W_ecommerceResults",
44063
+ "ecommerceResultsActions": "Yvqh9W_ecommerceResultsActions",
44064
+ "entryIcon": "Yvqh9W_entryIcon",
44065
+ "ecommerceAssetAdd": "Yvqh9W_ecommerceAssetAdd",
44066
+ "uploadIcon": "Yvqh9W_uploadIcon",
41960
44067
  "imageCard": "Yvqh9W_imageCard",
41961
- "paramHint": "Yvqh9W_paramHint",
41962
- "ecommerceParamGrid": "Yvqh9W_ecommerceParamGrid",
44068
+ "ecommerceResultsEmpty": "Yvqh9W_ecommerceResultsEmpty",
44069
+ "sidebarHistoryHost": "Yvqh9W_sidebarHistoryHost",
44070
+ "uploadHint": "Yvqh9W_uploadHint",
44071
+ "galleryFilters": "Yvqh9W_galleryFilters",
44072
+ "lightboxActions": "Yvqh9W_lightboxActions",
44073
+ "image": "Yvqh9W_image",
44074
+ "historyMain": "Yvqh9W_historyMain",
44075
+ "historyThumb": "Yvqh9W_historyThumb",
44076
+ "galleryFilter": "Yvqh9W_galleryFilter",
44077
+ "ecommerceTaskCard": "Yvqh9W_ecommerceTaskCard",
44078
+ "updateActions": "Yvqh9W_updateActions",
44079
+ "galleryBulkButton": "Yvqh9W_galleryBulkButton",
44080
+ "ecommerceTaskState": "Yvqh9W_ecommerceTaskState",
44081
+ "historyThumbPlaceholder": "Yvqh9W_historyThumbPlaceholder",
41963
44082
  "modelLabel": "Yvqh9W_modelLabel",
41964
- "promptFooter": "Yvqh9W_promptFooter",
41965
- "canvasHistoryTag": "Yvqh9W_canvasHistoryTag",
44083
+ "bigSpinner": "Yvqh9W_bigSpinner",
44084
+ "updateBanner": "Yvqh9W_updateBanner",
41966
44085
  "lightbox": "Yvqh9W_lightbox",
41967
- "galleryTagFilter": "Yvqh9W_galleryTagFilter",
44086
+ "galleryWorkspace": "Yvqh9W_galleryWorkspace",
44087
+ "ecommerceSectionHint": "Yvqh9W_ecommerceSectionHint",
44088
+ "historyClear": "Yvqh9W_historyClear",
41968
44089
  "galleryToolbar": "Yvqh9W_galleryToolbar",
41969
- "panelHeading": "Yvqh9W_panelHeading",
41970
- "ecommerceTaskActions": "Yvqh9W_ecommerceTaskActions",
41971
- "panelHeader": "Yvqh9W_panelHeader",
41972
- "connectionDot": "Yvqh9W_connectionDot",
41973
- "taskTrayClose": "Yvqh9W_taskTrayClose",
41974
- "sessionTabs": "Yvqh9W_sessionTabs",
41975
- "taskPrompt": "Yvqh9W_taskPrompt",
41976
- "image": "Yvqh9W_image",
41977
- "enhanceButton": "Yvqh9W_enhanceButton",
41978
- "modelWrap": "Yvqh9W_modelWrap",
41979
- "imageCaption": "Yvqh9W_imageCaption",
41980
- "spinner": "Yvqh9W_spinner",
41981
- "bigSpinner": "Yvqh9W_bigSpinner",
41982
- "galleryClear": "Yvqh9W_galleryClear",
41983
- "uploadBox": "Yvqh9W_uploadBox",
41984
- "ecommerceSection": "Yvqh9W_ecommerceSection",
41985
- "modelMenu": "Yvqh9W_modelMenu",
41986
- "historyActions": "Yvqh9W_historyActions",
41987
- "gallerySelect": "Yvqh9W_gallerySelect",
44090
+ "updateRelease": "Yvqh9W_updateRelease",
44091
+ "galleryCount": "Yvqh9W_galleryCount",
44092
+ "gallerySelectionBar": "Yvqh9W_gallerySelectionBar",
44093
+ "taskTrayChevron": "Yvqh9W_taskTrayChevron",
44094
+ "ecommercePlanList": "Yvqh9W_ecommercePlanList",
44095
+ "taskTrayToggle": "Yvqh9W_taskTrayToggle",
44096
+ "historyHeaderActions": "Yvqh9W_historyHeaderActions",
41988
44097
  "modeRow": "Yvqh9W_modeRow",
41989
- "configGuide": "Yvqh9W_configGuide",
41990
- "galleryCardActions": "Yvqh9W_galleryCardActions",
41991
- "galleryCardAction": "Yvqh9W_galleryCardAction",
41992
- "galleryCardFooter": "Yvqh9W_galleryCardFooter",
41993
- "lightboxStage": "Yvqh9W_lightboxStage",
41994
- "comparisonImageButton": "Yvqh9W_comparisonImageButton",
41995
- "galleryCardInfo": "Yvqh9W_galleryCardInfo",
41996
- "galleryTagEdit": "Yvqh9W_galleryTagEdit",
41997
- "galleryTagEditor": "Yvqh9W_galleryTagEditor",
41998
- "ecommerceSectionHint": "Yvqh9W_ecommerceSectionHint",
41999
- "lightboxFigure": "Yvqh9W_lightboxFigure",
42000
- "galleryViewToggle": "Yvqh9W_galleryViewToggle",
44098
+ "canvasBody": "Yvqh9W_canvasBody",
44099
+ "ecommerceAdvancedToggle": "Yvqh9W_ecommerceAdvancedToggle",
44100
+ "entry": "Yvqh9W_entry",
44101
+ "ecommerceGroups": "Yvqh9W_ecommerceGroups",
44102
+ "referenceActions": "Yvqh9W_referenceActions",
44103
+ "configScroll": "Yvqh9W_configScroll",
42001
44104
  "canvasStateTitle": "Yvqh9W_canvasStateTitle",
42002
- "comparisonBoard": "Yvqh9W_comparisonBoard",
42003
- "galleryFilterNote": "Yvqh9W_galleryFilterNote",
42004
- "optionPill": "Yvqh9W_optionPill",
42005
- "canvasMeta": "Yvqh9W_canvasMeta",
42006
- "lightboxCopy": "Yvqh9W_lightboxCopy",
42007
- "entryLabel": "Yvqh9W_entryLabel",
42008
- "panelTitle": "Yvqh9W_panelTitle",
42009
- "generateButton": "Yvqh9W_generateButton",
42010
- "canvasError": "Yvqh9W_canvasError",
42011
- "gallerySearch": "Yvqh9W_gallerySearch",
42012
- "lightboxClose": "Yvqh9W_lightboxClose",
42013
- "galleryTagFilterList": "Yvqh9W_galleryTagFilterList",
44105
+ "comparisonGrid": "Yvqh9W_comparisonGrid",
44106
+ "panelHeading": "Yvqh9W_panelHeading",
44107
+ "chatResizer": "Yvqh9W_chatResizer",
42014
44108
  "modelMenuItem": "Yvqh9W_modelMenuItem",
42015
- "entryIcon": "Yvqh9W_entryIcon",
42016
- "configScroll": "Yvqh9W_configScroll",
42017
- "historyThumbPlaceholder": "Yvqh9W_historyThumbPlaceholder",
42018
- "ecommerceGroup": "Yvqh9W_ecommerceGroup",
42019
- "ecommerceTaskState": "Yvqh9W_ecommerceTaskState",
42020
- "footer": "Yvqh9W_footer",
44109
+ "galleryClear": "Yvqh9W_galleryClear",
44110
+ "comparisonImageButton": "Yvqh9W_comparisonImageButton",
44111
+ "galleryMasonry": "Yvqh9W_galleryMasonry",
44112
+ "taskTray": "Yvqh9W_taskTray",
44113
+ "sessionTabs": "Yvqh9W_sessionTabs",
44114
+ "promptFooter": "Yvqh9W_promptFooter",
44115
+ "promptCount": "Yvqh9W_promptCount",
44116
+ "ecommerceWorkspace": "Yvqh9W_ecommerceWorkspace",
42021
44117
  "canvasState": "Yvqh9W_canvasState",
42022
- "lightboxDownload": "Yvqh9W_lightboxDownload",
42023
- "canvasEmptyIcon": "Yvqh9W_canvasEmptyIcon",
42024
- "historyPrompt": "Yvqh9W_historyPrompt",
42025
- "lightboxIndex": "Yvqh9W_lightboxIndex",
42026
- "configToggle": "Yvqh9W_configToggle",
42027
- "sidebarHistoryHost": "Yvqh9W_sidebarHistoryHost",
42028
- "uploadHint": "Yvqh9W_uploadHint",
42029
- "lightboxNav": "Yvqh9W_lightboxNav",
42030
- "ecommercePlanWarn": "Yvqh9W_ecommercePlanWarn",
42031
- "hiddenFile": "Yvqh9W_hiddenFile",
42032
44118
  "galleryFilterCount": "Yvqh9W_galleryFilterCount",
42033
- "compareControl": "Yvqh9W_compareControl",
44119
+ "historyIconAction": "Yvqh9W_historyIconAction",
44120
+ "hiddenFile": "Yvqh9W_hiddenFile",
42034
44121
  "galleryCard": "Yvqh9W_galleryCard",
42035
- "galleryImageButton": "Yvqh9W_galleryImageButton",
44122
+ "modelSelect": "Yvqh9W_modelSelect",
44123
+ "canvasStateHint": "Yvqh9W_canvasStateHint",
44124
+ "imageCaption": "Yvqh9W_imageCaption",
44125
+ "galleryBadge": "Yvqh9W_galleryBadge",
42036
44126
  "compareToggle": "Yvqh9W_compareToggle",
42037
- "galleryMasonry": "Yvqh9W_galleryMasonry",
42038
- "promptCount": "Yvqh9W_promptCount",
42039
- "lightboxTools": "Yvqh9W_lightboxTools",
42040
- "historyItem": "Yvqh9W_historyItem",
42041
- "taskRows": "Yvqh9W_taskRows",
42042
- "updateText": "Yvqh9W_updateText",
42043
- "updateRelease": "Yvqh9W_updateRelease",
42044
- "ecommerceAssetAdd": "Yvqh9W_ecommerceAssetAdd",
42045
- "ecommerceResults": "Yvqh9W_ecommerceResults",
42046
- "ecommerceTaskCard": "Yvqh9W_ecommerceTaskCard",
42047
- "historyFilters": "Yvqh9W_historyFilters",
42048
- "topNav": "Yvqh9W_topNav",
42049
- "referenceActions": "Yvqh9W_referenceActions",
42050
- "conversationAdd": "Yvqh9W_conversationAdd",
42051
- "galleryFilter": "Yvqh9W_galleryFilter",
42052
- "dshImageGenSpin": "Yvqh9W_dshImageGenSpin",
44127
+ "taskTrayClose": "Yvqh9W_taskTrayClose",
44128
+ "optionRow": "Yvqh9W_optionRow",
44129
+ "galleryRemove": "Yvqh9W_galleryRemove",
44130
+ "lightboxDownload": "Yvqh9W_lightboxDownload",
44131
+ "footer": "Yvqh9W_footer",
44132
+ "galleryRatioList": "Yvqh9W_galleryRatioList",
44133
+ "uploadBox": "Yvqh9W_uploadBox",
44134
+ "ecommerceStructureGrid": "Yvqh9W_ecommerceStructureGrid",
44135
+ "paramHint": "Yvqh9W_paramHint",
44136
+ "ecommerceParamGrid": "Yvqh9W_ecommerceParamGrid",
44137
+ "lightboxNav": "Yvqh9W_lightboxNav",
44138
+ "configHeader": "Yvqh9W_configHeader",
44139
+ "galleryHeading": "Yvqh9W_galleryHeading",
44140
+ "lightboxEdit": "Yvqh9W_lightboxEdit",
44141
+ "taskTrayCount": "Yvqh9W_taskTrayCount",
44142
+ "entryLabel": "Yvqh9W_entryLabel",
44143
+ "galleryTags": "Yvqh9W_galleryTags",
44144
+ "historyNew": "Yvqh9W_historyNew",
44145
+ "lightboxFigure": "Yvqh9W_lightboxFigure",
44146
+ "lightboxTool": "Yvqh9W_lightboxTool",
44147
+ "topNavItem": "Yvqh9W_topNavItem",
44148
+ "ecommerceResultsHeader": "Yvqh9W_ecommerceResultsHeader",
44149
+ "topNavDivider": "Yvqh9W_topNavDivider",
44150
+ "ecommercePlanWarn": "Yvqh9W_ecommercePlanWarn",
42053
44151
  "grid": "Yvqh9W_grid",
42054
- "galleryFilterHeading": "Yvqh9W_galleryFilterHeading",
42055
44152
  "galleryToolbarActions": "Yvqh9W_galleryToolbarActions",
42056
- "historyTitle": "Yvqh9W_historyTitle",
42057
- "historyThumb": "Yvqh9W_historyThumb",
42058
- "gallerySort": "Yvqh9W_gallerySort",
42059
- "historyNew": "Yvqh9W_historyNew",
42060
- "comparisonFullscreenGrid": "Yvqh9W_comparisonFullscreenGrid",
42061
- "galleryImage": "Yvqh9W_galleryImage",
42062
- "taskTrayChevron": "Yvqh9W_taskTrayChevron",
42063
- "historyIconAction": "Yvqh9W_historyIconAction",
42064
- "ecommerceAssets": "Yvqh9W_ecommerceAssets",
42065
- "updateBanner": "Yvqh9W_updateBanner",
42066
- "lightboxImage": "Yvqh9W_lightboxImage",
42067
- "sessionTabLabel": "Yvqh9W_sessionTabLabel",
42068
- "view": "Yvqh9W_view",
42069
- "ecommerceRefRow": "Yvqh9W_ecommerceRefRow",
42070
- "galleryBadge": "Yvqh9W_galleryBadge",
42071
- "galleryTags": "Yvqh9W_galleryTags",
42072
- "galleryRemove": "Yvqh9W_galleryRemove",
42073
- "modePill": "Yvqh9W_modePill",
42074
- "lightboxActions": "Yvqh9W_lightboxActions",
42075
44153
  "chatToggle": "Yvqh9W_chatToggle",
42076
- "optionRow": "Yvqh9W_optionRow",
42077
- "historyHeader": "Yvqh9W_historyHeader",
42078
- "config": "Yvqh9W_config",
44154
+ "spinner": "Yvqh9W_spinner",
42079
44155
  "ecommerceResultBadge": "Yvqh9W_ecommerceResultBadge",
42080
- "galleryCount": "Yvqh9W_galleryCount",
42081
- "sessionTab": "Yvqh9W_sessionTab",
44156
+ "ecommerceGroupGrid": "Yvqh9W_ecommerceGroupGrid",
44157
+ "canvasError": "Yvqh9W_canvasError",
44158
+ "historyItem": "Yvqh9W_historyItem",
44159
+ "ecommerceFooterHint": "Yvqh9W_ecommerceFooterHint",
44160
+ "paramGroup": "Yvqh9W_paramGroup",
44161
+ "download": "Yvqh9W_download",
44162
+ "galleryTagEditor": "Yvqh9W_galleryTagEditor",
44163
+ "dshImageGenSpin": "Yvqh9W_dshImageGenSpin",
42082
44164
  "sessionTabIcon": "Yvqh9W_sessionTabIcon",
42083
- "ecommerceUploadHero": "Yvqh9W_ecommerceUploadHero",
42084
- "ecommerceResultsActions": "Yvqh9W_ecommerceResultsActions",
42085
- "configGuideBody": "Yvqh9W_configGuideBody",
42086
- "panel": "Yvqh9W_panel",
42087
- "prompt": "Yvqh9W_prompt",
42088
- "galleryFilterDivider": "Yvqh9W_galleryFilterDivider",
42089
- "galleryWorkspace": "Yvqh9W_galleryWorkspace",
42090
- "compareModelChoices": "Yvqh9W_compareModelChoices",
44165
+ "connectionDot": "Yvqh9W_connectionDot",
44166
+ "sessionTab": "Yvqh9W_sessionTab",
44167
+ "taskRows": "Yvqh9W_taskRows",
42091
44168
  "ecommercePlanMini": "Yvqh9W_ecommercePlanMini",
42092
- "historyEmpty": "Yvqh9W_historyEmpty",
44169
+ "historyPrompt": "Yvqh9W_historyPrompt",
44170
+ "historyActions": "Yvqh9W_historyActions",
44171
+ "ecommerceUploadHero": "Yvqh9W_ecommerceUploadHero",
44172
+ "modelMenu": "Yvqh9W_modelMenu",
42093
44173
  "ecommerceAdvancedBody": "Yvqh9W_ecommerceAdvancedBody",
42094
- "galleryTagInput": "Yvqh9W_galleryTagInput",
42095
- "modelMenuList": "Yvqh9W_modelMenuList"
44174
+ "ecommerceTaskActions": "Yvqh9W_ecommerceTaskActions",
44175
+ "modelWrap": "Yvqh9W_modelWrap"
42096
44176
  };
42097
44177
  //#endregion
42098
44178
  //#region src/client/ImageGenPanel.tsx
@@ -46799,97 +48879,97 @@ window.__ModuleLoader__.load({
46799
48879
  document.head.appendChild(tag);
46800
48880
  }
46801
48881
  var settings_card_module_css_default = {
46802
- "spacer": "i1cc5G_spacer",
46803
- "editorClose": "i1cc5G_editorClose",
46804
- "editorField": "i1cc5G_editorField",
46805
- "modelBadge": "i1cc5G_modelBadge",
46806
- "modelRow": "i1cc5G_modelRow",
46807
- "detectOk": "i1cc5G_detectOk",
46808
- "inlineDisclosure": "i1cc5G_inlineDisclosure",
46809
- "discard": "i1cc5G_discard",
46810
- "editorDivider": "i1cc5G_editorDivider",
46811
- "input": "i1cc5G_input",
46812
- "modelCandidate": "i1cc5G_modelCandidate",
48882
+ "channelAddRow": "i1cc5G_channelAddRow",
48883
+ "editorTools": "i1cc5G_editorTools",
48884
+ "channelControls": "i1cc5G_channelControls",
46813
48885
  "presetMeta": "i1cc5G_presetMeta",
46814
- "footer": "i1cc5G_footer",
46815
- "sectionTitle": "i1cc5G_sectionTitle",
46816
- "modelRowBadges": "i1cc5G_modelRowBadges",
46817
- "select": "i1cc5G_select",
46818
- "inputInvalid": "i1cc5G_inputInvalid",
46819
- "modelChip": "i1cc5G_modelChip",
46820
- "editorSectionHeader": "i1cc5G_editorSectionHeader",
46821
- "channelRow": "i1cc5G_channelRow",
46822
- "modelCandidateLabel": "i1cc5G_modelCandidateLabel",
46823
- "save": "i1cc5G_save",
46824
- "modelFetchRow": "i1cc5G_modelFetchRow",
46825
- "failed": "i1cc5G_failed",
46826
- "versionValue": "i1cc5G_versionValue",
46827
- "channelName": "i1cc5G_channelName",
46828
- "modelRowRemove": "i1cc5G_modelRowRemove",
46829
- "hint": "i1cc5G_hint",
46830
- "channelMain": "i1cc5G_channelMain",
48886
+ "channelAction": "i1cc5G_channelAction",
46831
48887
  "versionRow": "i1cc5G_versionRow",
46832
- "channelEmpty": "i1cc5G_channelEmpty",
46833
- "field": "i1cc5G_field",
46834
- "invalid": "i1cc5G_invalid",
46835
- "modelSection": "i1cc5G_modelSection",
46836
- "modelSummary": "i1cc5G_modelSummary",
46837
- "channelMeta": "i1cc5G_channelMeta",
46838
- "badges": "i1cc5G_badges",
46839
- "addModel": "i1cc5G_addModel",
46840
- "presetName": "i1cc5G_presetName",
46841
- "sectionDivider": "i1cc5G_sectionDivider",
46842
48888
  "presetHint": "i1cc5G_presetHint",
46843
- "readOnly": "i1cc5G_readOnly",
46844
- "body": "i1cc5G_body",
46845
- "textarea": "i1cc5G_textarea",
46846
48889
  "chevronOpen": "i1cc5G_chevronOpen",
48890
+ "readOnly": "i1cc5G_readOnly",
48891
+ "inputInvalid": "i1cc5G_inputInvalid",
48892
+ "badge": "i1cc5G_badge",
48893
+ "modelSummary": "i1cc5G_modelSummary",
48894
+ "channelDotReady": "i1cc5G_channelDotReady",
48895
+ "description": "i1cc5G_description",
48896
+ "versionValue": "i1cc5G_versionValue",
48897
+ "failed": "i1cc5G_failed",
46847
48898
  "channelDotWarn": "i1cc5G_channelDotWarn",
46848
- "pending": "i1cc5G_pending",
46849
- "label": "i1cc5G_label",
46850
- "channelSection": "i1cc5G_channelSection",
46851
- "modelChoices": "i1cc5G_modelChoices",
46852
- "sectionHeader": "i1cc5G_sectionHeader",
46853
- "chevron": "i1cc5G_chevron",
46854
- "versionLabel": "i1cc5G_versionLabel",
46855
- "editorTools": "i1cc5G_editorTools",
46856
- "channelAddRow": "i1cc5G_channelAddRow",
48899
+ "channelRow": "i1cc5G_channelRow",
48900
+ "channelHost": "i1cc5G_channelHost",
48901
+ "modelSection": "i1cc5G_modelSection",
48902
+ "editorClose": "i1cc5G_editorClose",
48903
+ "channelList": "i1cc5G_channelList",
48904
+ "spacer": "i1cc5G_spacer",
48905
+ "name": "i1cc5G_name",
48906
+ "presetInline": "i1cc5G_presetInline",
48907
+ "editorHeader": "i1cc5G_editorHeader",
48908
+ "disclosure": "i1cc5G_disclosure",
48909
+ "badges": "i1cc5G_badges",
48910
+ "modelCandidate": "i1cc5G_modelCandidate",
46857
48911
  "editorPanel": "i1cc5G_editorPanel",
46858
- "modelRowInputs": "i1cc5G_modelRowInputs",
46859
- "header": "i1cc5G_header",
48912
+ "modelFetch": "i1cc5G_modelFetch",
48913
+ "editorSectionHeader": "i1cc5G_editorSectionHeader",
46860
48914
  "reset": "i1cc5G_reset",
46861
- "editorHeader": "i1cc5G_editorHeader",
46862
- "channelHost": "i1cc5G_channelHost",
46863
- "optionalContent": "i1cc5G_optionalContent",
48915
+ "footer": "i1cc5G_footer",
48916
+ "pending": "i1cc5G_pending",
48917
+ "label": "i1cc5G_label",
48918
+ "head": "i1cc5G_head",
48919
+ "textareaInvalid": "i1cc5G_textareaInvalid",
48920
+ "modelRow": "i1cc5G_modelRow",
46864
48921
  "presetInlineHeader": "i1cc5G_presetInlineHeader",
46865
- "sectionHint": "i1cc5G_sectionHint",
46866
- "presetList": "i1cc5G_presetList",
46867
48922
  "presetRow": "i1cc5G_presetRow",
46868
- "description": "i1cc5G_description",
46869
- "name": "i1cc5G_name",
46870
- "editorFooter": "i1cc5G_editorFooter",
46871
- "channelAction": "i1cc5G_channelAction",
46872
- "channelBadge": "i1cc5G_channelBadge",
46873
- "textareaInvalid": "i1cc5G_textareaInvalid",
48923
+ "notExposed": "i1cc5G_notExposed",
48924
+ "modelRowBadges": "i1cc5G_modelRowBadges",
46874
48925
  "channelDanger": "i1cc5G_channelDanger",
48926
+ "save": "i1cc5G_save",
48927
+ "textarea": "i1cc5G_textarea",
48928
+ "modelRowRemove": "i1cc5G_modelRowRemove",
48929
+ "header": "i1cc5G_header",
48930
+ "modelCandidateLabel": "i1cc5G_modelCandidateLabel",
48931
+ "discard": "i1cc5G_discard",
48932
+ "modelChip": "i1cc5G_modelChip",
48933
+ "modelChoices": "i1cc5G_modelChoices",
48934
+ "headText": "i1cc5G_headText",
46875
48935
  "modelRows": "i1cc5G_modelRows",
46876
- "channelList": "i1cc5G_channelList",
48936
+ "modelRowInputs": "i1cc5G_modelRowInputs",
48937
+ "editorBackdrop": "i1cc5G_editorBackdrop",
48938
+ "channelBadge": "i1cc5G_channelBadge",
48939
+ "modelBadge": "i1cc5G_modelBadge",
46877
48940
  "manualModelRow": "i1cc5G_manualModelRow",
46878
- "channelAdd": "i1cc5G_channelAdd",
46879
- "channelControls": "i1cc5G_channelControls",
46880
- "notExposed": "i1cc5G_notExposed",
46881
- "disclosure": "i1cc5G_disclosure",
46882
- "badge": "i1cc5G_badge",
46883
- "head": "i1cc5G_head",
46884
- "deleteConfirmText": "i1cc5G_deleteConfirmText",
46885
- "modelFetch": "i1cc5G_modelFetch",
46886
- "channelDotReady": "i1cc5G_channelDotReady",
46887
- "headText": "i1cc5G_headText",
48941
+ "hint": "i1cc5G_hint",
46888
48942
  "modelArrow": "i1cc5G_modelArrow",
46889
- "presetInline": "i1cc5G_presetInline",
48943
+ "sectionDivider": "i1cc5G_sectionDivider",
48944
+ "presetList": "i1cc5G_presetList",
48945
+ "chevron": "i1cc5G_chevron",
48946
+ "invalid": "i1cc5G_invalid",
48947
+ "channelName": "i1cc5G_channelName",
48948
+ "channelSection": "i1cc5G_channelSection",
48949
+ "editorDivider": "i1cc5G_editorDivider",
48950
+ "sectionHint": "i1cc5G_sectionHint",
48951
+ "versionLabel": "i1cc5G_versionLabel",
48952
+ "editorFooter": "i1cc5G_editorFooter",
48953
+ "channelMain": "i1cc5G_channelMain",
48954
+ "channelMeta": "i1cc5G_channelMeta",
48955
+ "select": "i1cc5G_select",
48956
+ "field": "i1cc5G_field",
48957
+ "modelFetchRow": "i1cc5G_modelFetchRow",
48958
+ "sectionTitle": "i1cc5G_sectionTitle",
48959
+ "channelEmpty": "i1cc5G_channelEmpty",
48960
+ "sectionHeader": "i1cc5G_sectionHeader",
48961
+ "addModel": "i1cc5G_addModel",
46890
48962
  "modelCandidateList": "i1cc5G_modelCandidateList",
46891
- "editorBackdrop": "i1cc5G_editorBackdrop",
46892
- "card": "i1cc5G_card"
48963
+ "channelAdd": "i1cc5G_channelAdd",
48964
+ "inlineDisclosure": "i1cc5G_inlineDisclosure",
48965
+ "editorField": "i1cc5G_editorField",
48966
+ "optionalContent": "i1cc5G_optionalContent",
48967
+ "body": "i1cc5G_body",
48968
+ "input": "i1cc5G_input",
48969
+ "deleteConfirmText": "i1cc5G_deleteConfirmText",
48970
+ "detectOk": "i1cc5G_detectOk",
48971
+ "card": "i1cc5G_card",
48972
+ "presetName": "i1cc5G_presetName"
46893
48973
  };
46894
48974
  //#endregion
46895
48975
  //#region src/client/SettingsCard.tsx
@@ -48371,16 +50451,16 @@ window.__ModuleLoader__.load({
48371
50451
  document.head.appendChild(tag);
48372
50452
  }
48373
50453
  var image_toolview_module_css_default = {
48374
- "header": "_3eGrYG_header",
48375
50454
  "images": "_3eGrYG_images",
48376
- "error": "_3eGrYG_error",
48377
- "icon": "_3eGrYG_icon",
50455
+ "status": "_3eGrYG_status",
48378
50456
  "message": "_3eGrYG_message",
50457
+ "error": "_3eGrYG_error",
48379
50458
  "image": "_3eGrYG_image",
50459
+ "icon": "_3eGrYG_icon",
50460
+ "header": "_3eGrYG_header",
48380
50461
  "loading": "_3eGrYG_loading",
48381
- "status": "_3eGrYG_status",
48382
- "root": "_3eGrYG_root",
48383
- "imageLink": "_3eGrYG_imageLink"
50462
+ "imageLink": "_3eGrYG_imageLink",
50463
+ "root": "_3eGrYG_root"
48384
50464
  };
48385
50465
  //#endregion
48386
50466
  //#region src/client/image-toolview.tsx