scitex 2.7.3__py3-none-any.whl → 2.8.1__py3-none-any.whl

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.
Files changed (160) hide show
  1. scitex/__version__.py +1 -1
  2. scitex/dev/plt/__init__.py +0 -0
  3. scitex/dev/plt/plot_mpl_axhline.py +0 -0
  4. scitex/dev/plt/plot_mpl_axhspan.py +0 -0
  5. scitex/dev/plt/plot_mpl_axvline.py +0 -0
  6. scitex/dev/plt/plot_mpl_axvspan.py +0 -0
  7. scitex/dev/plt/plot_mpl_bar.py +0 -0
  8. scitex/dev/plt/plot_mpl_barh.py +0 -0
  9. scitex/dev/plt/plot_mpl_boxplot.py +0 -0
  10. scitex/dev/plt/plot_mpl_contour.py +0 -0
  11. scitex/dev/plt/plot_mpl_contourf.py +0 -0
  12. scitex/dev/plt/plot_mpl_errorbar.py +0 -0
  13. scitex/dev/plt/plot_mpl_eventplot.py +0 -0
  14. scitex/dev/plt/plot_mpl_fill.py +0 -0
  15. scitex/dev/plt/plot_mpl_fill_between.py +0 -0
  16. scitex/dev/plt/plot_mpl_hexbin.py +0 -0
  17. scitex/dev/plt/plot_mpl_hist.py +0 -0
  18. scitex/dev/plt/plot_mpl_hist2d.py +0 -0
  19. scitex/dev/plt/plot_mpl_imshow.py +0 -0
  20. scitex/dev/plt/plot_mpl_pcolormesh.py +0 -0
  21. scitex/dev/plt/plot_mpl_pie.py +0 -0
  22. scitex/dev/plt/plot_mpl_plot.py +0 -0
  23. scitex/dev/plt/plot_mpl_quiver.py +0 -0
  24. scitex/dev/plt/plot_mpl_scatter.py +0 -0
  25. scitex/dev/plt/plot_mpl_stackplot.py +0 -0
  26. scitex/dev/plt/plot_mpl_stem.py +0 -0
  27. scitex/dev/plt/plot_mpl_step.py +0 -0
  28. scitex/dev/plt/plot_mpl_violinplot.py +0 -0
  29. scitex/dev/plt/plot_sns_barplot.py +0 -0
  30. scitex/dev/plt/plot_sns_boxplot.py +0 -0
  31. scitex/dev/plt/plot_sns_heatmap.py +0 -0
  32. scitex/dev/plt/plot_sns_histplot.py +0 -0
  33. scitex/dev/plt/plot_sns_kdeplot.py +0 -0
  34. scitex/dev/plt/plot_sns_lineplot.py +0 -0
  35. scitex/dev/plt/plot_sns_scatterplot.py +0 -0
  36. scitex/dev/plt/plot_sns_stripplot.py +0 -0
  37. scitex/dev/plt/plot_sns_swarmplot.py +0 -0
  38. scitex/dev/plt/plot_sns_violinplot.py +0 -0
  39. scitex/dev/plt/plot_stx_bar.py +0 -0
  40. scitex/dev/plt/plot_stx_barh.py +0 -0
  41. scitex/dev/plt/plot_stx_box.py +0 -0
  42. scitex/dev/plt/plot_stx_boxplot.py +0 -0
  43. scitex/dev/plt/plot_stx_conf_mat.py +0 -0
  44. scitex/dev/plt/plot_stx_contour.py +0 -0
  45. scitex/dev/plt/plot_stx_ecdf.py +0 -0
  46. scitex/dev/plt/plot_stx_errorbar.py +0 -0
  47. scitex/dev/plt/plot_stx_fill_between.py +0 -0
  48. scitex/dev/plt/plot_stx_fillv.py +0 -0
  49. scitex/dev/plt/plot_stx_heatmap.py +0 -0
  50. scitex/dev/plt/plot_stx_image.py +0 -0
  51. scitex/dev/plt/plot_stx_imshow.py +0 -0
  52. scitex/dev/plt/plot_stx_joyplot.py +0 -0
  53. scitex/dev/plt/plot_stx_kde.py +0 -0
  54. scitex/dev/plt/plot_stx_line.py +0 -0
  55. scitex/dev/plt/plot_stx_mean_ci.py +0 -0
  56. scitex/dev/plt/plot_stx_mean_std.py +0 -0
  57. scitex/dev/plt/plot_stx_median_iqr.py +0 -0
  58. scitex/dev/plt/plot_stx_raster.py +0 -0
  59. scitex/dev/plt/plot_stx_rectangle.py +0 -0
  60. scitex/dev/plt/plot_stx_scatter.py +0 -0
  61. scitex/dev/plt/plot_stx_shaded_line.py +0 -0
  62. scitex/dev/plt/plot_stx_violin.py +0 -0
  63. scitex/dev/plt/plot_stx_violinplot.py +0 -0
  64. scitex/diagram/README.md +197 -0
  65. scitex/diagram/__init__.py +48 -0
  66. scitex/diagram/_compile.py +312 -0
  67. scitex/diagram/_diagram.py +355 -0
  68. scitex/diagram/_presets.py +173 -0
  69. scitex/diagram/_schema.py +182 -0
  70. scitex/diagram/_split.py +278 -0
  71. scitex/fig/editor/__init__.py +5 -2
  72. scitex/fig/editor/_dearpygui_editor.py +1 -1
  73. scitex/fig/editor/_mpl_editor.py +1 -1
  74. scitex/fig/editor/_qt_editor.py +1 -1
  75. scitex/fig/editor/_tkinter_editor.py +1 -1
  76. scitex/fig/editor/edit/__init__.py +50 -0
  77. scitex/fig/editor/edit/backend_detector.py +109 -0
  78. scitex/fig/editor/edit/bundle_resolver.py +240 -0
  79. scitex/fig/editor/edit/editor_launcher.py +239 -0
  80. scitex/fig/editor/edit/manual_handler.py +53 -0
  81. scitex/fig/editor/edit/panel_loader.py +232 -0
  82. scitex/fig/editor/edit/path_resolver.py +67 -0
  83. scitex/fig/editor/flask_editor/_bbox.py +23 -0
  84. scitex/fig/editor/flask_editor/_core.py +908 -103
  85. scitex/fig/editor/flask_editor/_renderer.py +74 -0
  86. scitex/fig/editor/flask_editor/static/css/base/reset.css +41 -0
  87. scitex/fig/editor/flask_editor/static/css/base/typography.css +16 -0
  88. scitex/fig/editor/flask_editor/static/css/base/variables.css +85 -0
  89. scitex/fig/editor/flask_editor/static/css/components/buttons.css +217 -0
  90. scitex/fig/editor/flask_editor/static/css/components/context-menu.css +93 -0
  91. scitex/fig/editor/flask_editor/static/css/components/dropdown.css +57 -0
  92. scitex/fig/editor/flask_editor/static/css/components/forms.css +112 -0
  93. scitex/fig/editor/flask_editor/static/css/components/modal.css +59 -0
  94. scitex/fig/editor/flask_editor/static/css/components/sections.css +212 -0
  95. scitex/fig/editor/flask_editor/static/css/features/canvas.css +176 -0
  96. scitex/fig/editor/flask_editor/static/css/features/element-inspector.css +190 -0
  97. scitex/fig/editor/flask_editor/static/css/features/loading.css +59 -0
  98. scitex/fig/editor/flask_editor/static/css/features/overlay.css +45 -0
  99. scitex/fig/editor/flask_editor/static/css/features/panel-grid.css +95 -0
  100. scitex/fig/editor/flask_editor/static/css/features/selection.css +101 -0
  101. scitex/fig/editor/flask_editor/static/css/features/statistics.css +138 -0
  102. scitex/fig/editor/flask_editor/static/css/index.css +31 -0
  103. scitex/fig/editor/flask_editor/static/css/layout/container.css +7 -0
  104. scitex/fig/editor/flask_editor/static/css/layout/controls.css +56 -0
  105. scitex/fig/editor/flask_editor/static/css/layout/preview.css +78 -0
  106. scitex/fig/editor/flask_editor/static/js/alignment/axis.js +314 -0
  107. scitex/fig/editor/flask_editor/static/js/alignment/basic.js +107 -0
  108. scitex/fig/editor/flask_editor/static/js/alignment/distribute.js +54 -0
  109. scitex/fig/editor/flask_editor/static/js/canvas/canvas.js +172 -0
  110. scitex/fig/editor/flask_editor/static/js/canvas/dragging.js +258 -0
  111. scitex/fig/editor/flask_editor/static/js/canvas/resize.js +48 -0
  112. scitex/fig/editor/flask_editor/static/js/canvas/selection.js +71 -0
  113. scitex/fig/editor/flask_editor/static/js/core/api.js +288 -0
  114. scitex/fig/editor/flask_editor/static/js/core/state.js +143 -0
  115. scitex/fig/editor/flask_editor/static/js/core/utils.js +245 -0
  116. scitex/fig/editor/flask_editor/static/js/dev/element-inspector.js +992 -0
  117. scitex/fig/editor/flask_editor/static/js/editor/bbox.js +339 -0
  118. scitex/fig/editor/flask_editor/static/js/editor/element-drag.js +286 -0
  119. scitex/fig/editor/flask_editor/static/js/editor/overlay.js +371 -0
  120. scitex/fig/editor/flask_editor/static/js/editor/preview.js +293 -0
  121. scitex/fig/editor/flask_editor/static/js/main.js +426 -0
  122. scitex/fig/editor/flask_editor/static/js/shortcuts/context-menu.js +152 -0
  123. scitex/fig/editor/flask_editor/static/js/shortcuts/keyboard.js +265 -0
  124. scitex/fig/editor/flask_editor/static/js/ui/controls.js +184 -0
  125. scitex/fig/editor/flask_editor/static/js/ui/download.js +57 -0
  126. scitex/fig/editor/flask_editor/static/js/ui/help.js +100 -0
  127. scitex/fig/editor/flask_editor/static/js/ui/theme.js +34 -0
  128. scitex/fig/editor/flask_editor/templates/__init__.py +95 -5
  129. scitex/fig/editor/flask_editor/templates/_html.py +27 -9
  130. scitex/fig/editor/flask_editor/templates/_scripts.py +1928 -131
  131. scitex/fig/editor/flask_editor/templates/_styles.py +363 -51
  132. scitex/fig/io/_bundle.py +97 -12
  133. scitex/io/__init__.py +12 -0
  134. scitex/io/_bundle.py +69 -10
  135. scitex/io/_zip_bundle.py +439 -0
  136. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/__init__.py +0 -0
  137. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_labels.py +0 -0
  138. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_metadata.py +0 -0
  139. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_visual.py +0 -0
  140. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/__init__.py +0 -0
  141. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_base.py +0 -0
  142. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_scientific.py +0 -0
  143. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_statistical.py +0 -0
  144. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_stx_aliases.py +0 -0
  145. scitex/plt/_subplots/_AxisWrapperMixins/_RawMatplotlibMixin.py +0 -0
  146. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/__init__.py +0 -0
  147. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_base.py +0 -0
  148. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +0 -0
  149. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_bar.py +0 -0
  150. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_barh.py +0 -0
  151. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_errorbar.py +0 -0
  152. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_scatter.py +0 -0
  153. scitex/plt/io/_layered_bundle.py +0 -0
  154. scitex/schema/_plot.py +0 -0
  155. {scitex-2.7.3.dist-info → scitex-2.8.1.dist-info}/METADATA +1 -1
  156. {scitex-2.7.3.dist-info → scitex-2.8.1.dist-info}/RECORD +78 -22
  157. scitex/fig/editor/_edit.py +0 -751
  158. {scitex-2.7.3.dist-info → scitex-2.8.1.dist-info}/WHEEL +0 -0
  159. {scitex-2.7.3.dist-info → scitex-2.8.1.dist-info}/entry_points.txt +0 -0
  160. {scitex-2.7.3.dist-info → scitex-2.8.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,7 +1,22 @@
1
1
  #!/usr/bin/env python3
2
2
  # -*- coding: utf-8 -*-
3
3
  # File: ./src/scitex/vis/editor/flask_editor/templates/styles.py
4
- """CSS styles for the Flask editor UI."""
4
+ """CSS styles for the Flask editor UI.
5
+
6
+ DEPRECATED: This inline CSS module is kept for fallback compatibility only.
7
+ The CSS has been modularized into static/css/ directory:
8
+ - static/css/index.css (main entry point with @imports)
9
+ - static/css/base/ (variables, reset, typography)
10
+ - static/css/layout/ (container, preview, controls)
11
+ - static/css/components/ (buttons, forms, sections, dropdown, modal, context-menu)
12
+ - static/css/features/ (canvas, panel-grid, selection, overlay, loading, statistics)
13
+
14
+ To use static files (recommended):
15
+ Set USE_STATIC_FILES = True in templates/__init__.py
16
+
17
+ To use this inline version (fallback):
18
+ Set USE_STATIC_FILES = False in templates/__init__.py
19
+ """
5
20
 
6
21
  CSS_STYLES = """
7
22
  /* =============================================================================
@@ -144,48 +159,57 @@ body {
144
159
  pointer-events: none;
145
160
  }
146
161
 
162
+ /* Color-neutral hover/selection: white outline with glow works with any element color */
147
163
  .hover-rect {
148
164
  fill: none;
149
- stroke: rgba(100, 180, 255, 0.6);
150
- stroke-width: 1;
165
+ stroke: rgba(255, 255, 255, 0.9);
166
+ stroke-width: 2;
151
167
  pointer-events: none;
168
+ filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.5)) drop-shadow(0 0 1px rgba(255, 255, 255, 0.8));
152
169
  }
153
170
 
154
171
  .selected-rect {
155
172
  fill: none;
156
- stroke: rgba(255, 200, 80, 0.8);
173
+ stroke: rgba(255, 255, 255, 1);
157
174
  stroke-width: 2;
175
+ stroke-dasharray: 4 2;
158
176
  pointer-events: none;
177
+ filter: drop-shadow(0 0 4px rgba(0, 0, 0, 0.7)) drop-shadow(0 0 2px rgba(255, 255, 255, 1));
159
178
  }
160
179
 
161
180
  .hover-label {
162
181
  font-size: 10px;
163
- fill: rgba(100, 180, 255, 0.9);
182
+ fill: rgba(255, 255, 255, 0.9);
164
183
  pointer-events: none;
184
+ filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.8));
165
185
  }
166
186
 
167
187
  .selected-label {
168
188
  font-size: 10px;
169
- fill: rgba(255, 200, 80, 0.9);
189
+ fill: rgba(255, 255, 255, 1);
170
190
  pointer-events: none;
191
+ filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.9));
171
192
  }
172
193
 
173
194
  .hover-path {
174
195
  fill: none;
175
- stroke: rgba(100, 180, 255, 0.9);
176
- stroke-width: 4;
196
+ stroke: rgba(255, 255, 255, 0.9);
197
+ stroke-width: 6;
177
198
  stroke-linecap: round;
178
199
  stroke-linejoin: round;
179
200
  pointer-events: none;
201
+ filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.6));
180
202
  }
181
203
 
182
204
  .selected-path {
183
205
  fill: none;
184
- stroke: rgba(255, 200, 80, 0.9);
185
- stroke-width: 5;
206
+ stroke: rgba(255, 255, 255, 1);
207
+ stroke-width: 6;
186
208
  stroke-linecap: round;
187
209
  stroke-linejoin: round;
210
+ stroke-dasharray: 8 4;
188
211
  pointer-events: none;
212
+ filter: drop-shadow(0 0 4px rgba(0, 0, 0, 0.7));
189
213
  }
190
214
 
191
215
  /* Debug mode - show all hit areas */
@@ -252,18 +276,23 @@ body {
252
276
  background: #c00;
253
277
  }
254
278
 
279
+ /* Hover scatter: White ring around points */
255
280
  .hover-scatter {
256
- fill: rgba(100, 180, 255, 0.7);
257
- stroke: rgba(100, 180, 255, 0.9);
258
- stroke-width: 1;
281
+ fill: none;
282
+ stroke: rgba(255, 255, 255, 0.9);
283
+ stroke-width: 3;
259
284
  pointer-events: none;
285
+ filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.6));
260
286
  }
261
287
 
288
+ /* Selected scatter: Dashed white ring */
262
289
  .selected-scatter {
263
- fill: rgba(255, 200, 80, 0.7);
264
- stroke: rgba(255, 200, 80, 0.9);
265
- stroke-width: 2;
290
+ fill: none;
291
+ stroke: rgba(255, 255, 255, 1);
292
+ stroke-width: 3;
293
+ stroke-dasharray: 3 2;
266
294
  pointer-events: none;
295
+ filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.7));
267
296
  }
268
297
 
269
298
  /* =============================================================================
@@ -1096,13 +1125,42 @@ input[type="range"]::-moz-range-thumb {
1096
1125
  border-radius: 8px;
1097
1126
  }
1098
1127
 
1128
+ /* Global loading overlay - non-intrusive top bar style */
1129
+ .global-loading-overlay {
1130
+ position: fixed;
1131
+ top: 0;
1132
+ left: 0;
1133
+ width: 100%;
1134
+ height: 36px;
1135
+ background: var(--workspace-bg-elevated);
1136
+ border-bottom: 1px solid var(--workspace-border-default);
1137
+ display: flex;
1138
+ align-items: center;
1139
+ justify-content: center;
1140
+ z-index: 9999;
1141
+ gap: 8px;
1142
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1);
1143
+ }
1144
+
1145
+ .global-loading-overlay .loading-text {
1146
+ color: var(--text-secondary);
1147
+ font-size: 12px;
1148
+ font-weight: 500;
1149
+ }
1150
+
1099
1151
  .spinner {
1100
- width: 40px;
1101
- height: 40px;
1102
- border: 3px solid var(--scitex-06);
1103
- border-top: 3px solid var(--status-success);
1152
+ width: 16px;
1153
+ height: 16px;
1154
+ border: 2px solid var(--scitex-06);
1155
+ border-top: 2px solid var(--status-success);
1104
1156
  border-radius: 50%;
1105
- animation: spin 0.8s linear infinite;
1157
+ animation: spin 0.6s linear infinite;
1158
+ }
1159
+
1160
+ .spinner-small {
1161
+ width: 14px;
1162
+ height: 14px;
1163
+ border-width: 2px;
1106
1164
  }
1107
1165
 
1108
1166
  @keyframes spin {
@@ -1171,6 +1229,13 @@ input[type="range"]::-moz-range-thumb {
1171
1229
  display: block;
1172
1230
  }
1173
1231
 
1232
+ /* Dark mode: invert plot colors for visibility */
1233
+ [data-theme="dark"] .panel-card img,
1234
+ [data-theme="dark"] .panel-canvas-item img,
1235
+ [data-theme="dark"] .preview-wrapper img {
1236
+ filter: invert(0.88) hue-rotate(180deg);
1237
+ }
1238
+
1174
1239
  .panel-card-container {
1175
1240
  position: relative;
1176
1241
  display: inline-block;
@@ -1260,86 +1325,333 @@ input[type="range"]::-moz-range-thumb {
1260
1325
  }
1261
1326
 
1262
1327
  /* =============================================================================
1263
- * Draggable Panel Canvas
1328
+ * Unified Panel Canvas (matches figz export layout)
1329
+ * Exactly matches SciTeX Cloud's .plot-preview-area styling
1264
1330
  * ============================================================================= */
1265
1331
  .panel-canvas {
1266
1332
  position: relative;
1267
1333
  min-height: 400px;
1268
- background: var(--workspace-bg-secondary);
1269
- border: 2px dashed var(--workspace-border-default);
1334
+ /* White background with grid pattern - exact match to SciTeX Cloud */
1335
+ background: #ffffff;
1336
+ background-image:
1337
+ linear-gradient(0deg, transparent 23px, #e5e5e5 23px),
1338
+ linear-gradient(90deg, transparent 23px, #e5e5e5 23px);
1339
+ background-size: 24px 24px;
1270
1340
  border-radius: 8px;
1271
- overflow: hidden;
1341
+ overflow: visible; /* Allow panels to extend slightly if needed */
1342
+ }
1343
+
1344
+ /* Dark mode: dark canvas background for eye comfort */
1345
+ [data-theme="dark"] .panel-canvas,
1346
+ .dark-mode .panel-canvas {
1347
+ background: #1a1a1a;
1348
+ background-image:
1349
+ linear-gradient(0deg, transparent 23px, #2a2a2a 23px),
1350
+ linear-gradient(90deg, transparent 23px, #2a2a2a 23px);
1351
+ background-size: 24px 24px;
1352
+ }
1353
+
1354
+ /* Hide grid when toggled off (G key) */
1355
+ .panel-canvas.hide-grid {
1356
+ background-image: none !important;
1272
1357
  }
1273
1358
 
1359
+ /* Unified canvas - panels appear as single figure matching figz export */
1274
1360
  .panel-canvas-item {
1275
1361
  position: absolute;
1276
- cursor: move;
1277
1362
  user-select: none;
1278
- transition: box-shadow 0.2s;
1279
- background: var(--preview-bg);
1280
- background-size: 16px 16px;
1281
- background-position: 0 0, 0 8px, 8px -8px, -8px 0px;
1282
- border-radius: 6px;
1283
- overflow: hidden;
1284
- border: 2px solid transparent;
1363
+ background: transparent;
1364
+ overflow: visible;
1365
+ border: none;
1366
+ cursor: grab; /* Indicate draggability */
1285
1367
  }
1286
1368
 
1287
1369
  .panel-canvas-item:hover {
1288
- box-shadow: 0 4px 12px rgba(0,0,0,0.2);
1289
1370
  z-index: 10;
1290
1371
  }
1291
1372
 
1292
- .panel-canvas-item.dragging {
1293
- box-shadow: 0 8px 24px rgba(0,0,0,0.3);
1294
- z-index: 100;
1295
- opacity: 0.9;
1373
+ .panel-canvas-item:active {
1374
+ cursor: grabbing;
1296
1375
  }
1297
1376
 
1298
1377
  .panel-canvas-item.active {
1299
- border-color: var(--status-success);
1378
+ outline: 2px solid var(--status-success);
1379
+ outline-offset: 2px;
1380
+ }
1381
+
1382
+ .panel-canvas-item .panel-card-container {
1383
+ width: 100%;
1384
+ height: 100%;
1385
+ position: relative;
1300
1386
  }
1301
1387
 
1302
1388
  .panel-canvas-item img {
1303
1389
  width: 100%;
1304
1390
  height: 100%;
1305
- object-fit: contain;
1391
+ object-fit: contain; /* Preserve aspect ratio - never distort figures */
1306
1392
  pointer-events: none;
1393
+ display: block;
1307
1394
  }
1308
1395
 
1309
1396
  .panel-canvas-label {
1310
1397
  position: absolute;
1311
1398
  top: 4px;
1312
1399
  left: 4px;
1313
- background: rgba(0,0,0,0.7);
1400
+ background: rgba(0,0,0,0.6);
1314
1401
  color: white;
1315
1402
  padding: 2px 6px;
1316
1403
  border-radius: 3px;
1317
- font-size: 0.7em;
1404
+ font-size: 0.65em;
1318
1405
  font-weight: 600;
1319
- pointer-events: none;
1406
+ cursor: move;
1407
+ opacity: 1; /* Show by default */
1408
+ transition: opacity 0.2s, background 0.2s;
1409
+ z-index: 5;
1410
+ }
1411
+
1412
+ .panel-canvas-item:hover .panel-canvas-label {
1413
+ opacity: 1;
1414
+ background: rgba(0,0,0,0.8); /* Slightly darker on hover */
1320
1415
  }
1321
1416
 
1322
- .panel-canvas-resize {
1417
+ /* Drag handle for panel repositioning */
1418
+ .panel-drag-handle {
1323
1419
  position: absolute;
1324
- bottom: 0;
1325
- right: 0;
1326
- width: 16px;
1327
- height: 16px;
1328
- cursor: se-resize;
1329
- background: linear-gradient(135deg, transparent 50%, var(--color-cta) 50%);
1330
- border-radius: 0 0 4px 0;
1420
+ top: 4px;
1421
+ right: 4px;
1422
+ background: rgba(0,0,0,0.5);
1423
+ color: white;
1424
+ padding: 2px 4px;
1425
+ border-radius: 3px;
1426
+ font-size: 0.7em;
1427
+ cursor: move;
1428
+ opacity: 0;
1429
+ transition: opacity 0.2s, background 0.2s;
1430
+ z-index: 5;
1431
+ user-select: none;
1432
+ }
1433
+
1434
+ .panel-canvas-item:hover .panel-drag-handle {
1435
+ opacity: 1;
1436
+ }
1437
+
1438
+ .panel-drag-handle:hover {
1439
+ background: rgba(0,0,0,0.8);
1440
+ }
1441
+
1442
+ .panel-drag-handle:active {
1443
+ background: var(--accent-primary);
1444
+ }
1445
+
1446
+ /* Position indicator while dragging */
1447
+ .panel-position-indicator {
1448
+ position: absolute;
1449
+ bottom: 4px;
1450
+ left: 4px;
1451
+ background: rgba(0,0,0,0.7);
1452
+ color: #4fc3f7;
1453
+ padding: 2px 6px;
1454
+ border-radius: 3px;
1455
+ font-size: 0.6em;
1456
+ font-family: monospace;
1457
+ pointer-events: none;
1458
+ opacity: 0;
1459
+ transition: opacity 0.3s;
1460
+ z-index: 5;
1461
+ }
1462
+
1463
+ /* Dragging state */
1464
+ .panel-canvas-item.dragging {
1465
+ opacity: 0.85;
1466
+ z-index: 100;
1467
+ box-shadow: 0 8px 24px rgba(0,0,0,0.3);
1468
+ outline: 2px dashed var(--accent-primary);
1469
+ outline-offset: 2px;
1470
+ cursor: grabbing;
1471
+ }
1472
+
1473
+ .panel-canvas-item.dragging .panel-position-indicator {
1474
+ opacity: 1;
1331
1475
  }
1332
1476
 
1333
1477
  .canvas-controls {
1334
1478
  display: flex;
1335
1479
  gap: 8px;
1336
1480
  margin-bottom: 8px;
1481
+ align-items: center;
1337
1482
  }
1338
1483
 
1339
1484
  .canvas-controls button {
1340
1485
  padding: 4px 12px;
1341
1486
  font-size: 0.8em;
1342
1487
  }
1488
+
1489
+ /* Toolbar separator */
1490
+ .toolbar-separator {
1491
+ width: 1px;
1492
+ height: 24px;
1493
+ background: #555;
1494
+ margin: 0 4px;
1495
+ }
1496
+
1497
+ /* Download dropdown in toolbar */
1498
+ .download-dropdown {
1499
+ position: relative;
1500
+ display: inline-block;
1501
+ }
1502
+
1503
+ .download-dropdown #download-btn {
1504
+ background: #4a90d9;
1505
+ border: none;
1506
+ color: white;
1507
+ padding: 4px 12px;
1508
+ font-size: 0.8em;
1509
+ border-radius: 3px;
1510
+ cursor: pointer;
1511
+ }
1512
+
1513
+ .download-dropdown #download-btn:hover {
1514
+ background: #5a9fe9;
1515
+ }
1516
+
1517
+ #download-menu {
1518
+ display: none;
1519
+ position: absolute;
1520
+ top: 100%;
1521
+ left: 0;
1522
+ background: #2a2a2a;
1523
+ border: 1px solid #444;
1524
+ border-radius: 4px;
1525
+ min-width: 160px;
1526
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
1527
+ z-index: 1000;
1528
+ margin-top: 4px;
1529
+ padding: 4px 0;
1530
+ }
1531
+
1532
+ .download-item {
1533
+ display: block;
1534
+ padding: 8px 12px;
1535
+ color: #ddd;
1536
+ text-decoration: none;
1537
+ font-size: 0.85em;
1538
+ transition: background 0.15s;
1539
+ white-space: nowrap;
1540
+ }
1541
+
1542
+ .download-item:hover {
1543
+ background: #3a3a3a;
1544
+ color: #fff;
1545
+ }
1546
+
1547
+ .download-divider {
1548
+ height: 1px;
1549
+ background: #444;
1550
+ margin: 4px 0;
1551
+ }
1552
+
1553
+ /* =============================================================================
1554
+ Context Menu (Right-Click)
1555
+ ============================================================================= */
1556
+ .context-menu {
1557
+ position: fixed;
1558
+ background: var(--bg-secondary, #2a2a2a);
1559
+ border: 1px solid var(--border-color, #444);
1560
+ border-radius: 6px;
1561
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
1562
+ min-width: 200px;
1563
+ z-index: 10000;
1564
+ padding: 4px 0;
1565
+ font-size: 13px;
1566
+ }
1567
+
1568
+ .context-menu-item {
1569
+ display: flex;
1570
+ align-items: center;
1571
+ padding: 8px 12px;
1572
+ cursor: pointer;
1573
+ color: var(--text-primary, #ddd);
1574
+ transition: background 0.1s;
1575
+ position: relative;
1576
+ }
1577
+
1578
+ .context-menu-item:hover:not(.disabled) {
1579
+ background: var(--accent-primary, #4a90d9);
1580
+ color: #fff;
1581
+ }
1582
+
1583
+ .context-menu-item.disabled {
1584
+ color: var(--text-muted, #666);
1585
+ cursor: not-allowed;
1586
+ }
1587
+
1588
+ .context-menu-icon {
1589
+ width: 20px;
1590
+ margin-right: 8px;
1591
+ text-align: center;
1592
+ font-size: 14px;
1593
+ }
1594
+
1595
+ .context-menu-shortcut {
1596
+ margin-left: auto;
1597
+ font-size: 11px;
1598
+ color: var(--text-muted, #888);
1599
+ padding-left: 16px;
1600
+ }
1601
+
1602
+ .context-menu-item:hover:not(.disabled) .context-menu-shortcut {
1603
+ color: rgba(255, 255, 255, 0.7);
1604
+ }
1605
+
1606
+ .context-menu-arrow {
1607
+ margin-left: auto;
1608
+ font-size: 10px;
1609
+ color: var(--text-muted, #888);
1610
+ }
1611
+
1612
+ .context-menu-divider {
1613
+ height: 1px;
1614
+ background: var(--border-color, #444);
1615
+ margin: 4px 0;
1616
+ }
1617
+
1618
+ /* Submenu */
1619
+ .context-menu-submenu {
1620
+ position: relative;
1621
+ }
1622
+
1623
+ .context-submenu {
1624
+ display: none;
1625
+ position: absolute;
1626
+ left: 100%;
1627
+ top: 0;
1628
+ background: var(--bg-secondary, #2a2a2a);
1629
+ border: 1px solid var(--border-color, #444);
1630
+ border-radius: 6px;
1631
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
1632
+ min-width: 150px;
1633
+ padding: 4px 0;
1634
+ }
1635
+
1636
+ .context-menu-submenu:hover > .context-submenu {
1637
+ display: block;
1638
+ }
1639
+
1640
+ .context-submenu .context-menu-item {
1641
+ padding: 6px 12px;
1642
+ }
1643
+
1644
+ /* Panel selection styling */
1645
+ .panel-canvas-item.active {
1646
+ outline: 3px solid var(--accent-primary, #4a90d9);
1647
+ outline-offset: 2px;
1648
+ z-index: 100;
1649
+ }
1650
+
1651
+ .panel-canvas-item:hover:not(.active) {
1652
+ outline: 2px dashed var(--accent-secondary, #6ab04c);
1653
+ outline-offset: 2px;
1654
+ }
1343
1655
  """
1344
1656
 
1345
1657