flock-core 0.4.0b35__py3-none-any.whl → 0.4.0b36__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.

Potentially problematic release.


This version of flock-core might be problematic. Click here for more details.

Files changed (39) hide show
  1. flock/__init__.py +34 -11
  2. flock/cli/loaded_flock_cli.py +38 -18
  3. flock/core/flock.py +48 -3
  4. flock/themes/alabaster.toml +43 -43
  5. flock/themes/guezwhoz.toml +43 -43
  6. flock/themes/wildcherry.toml +43 -43
  7. flock/themes/wombat.toml +43 -43
  8. flock/themes/zenburn.toml +43 -43
  9. flock/webapp/app/config.py +80 -2
  10. flock/webapp/app/main.py +506 -3
  11. flock/webapp/app/templates/theme_mapper.html +326 -0
  12. flock/webapp/app/theme_mapper.py +812 -0
  13. flock/webapp/run.py +116 -14
  14. flock/webapp/static/css/custom.css +168 -83
  15. flock/webapp/templates/base.html +14 -7
  16. flock/webapp/templates/partials/_agent_detail_form.html +4 -3
  17. flock/webapp/templates/partials/_agent_list.html +1 -6
  18. flock/webapp/templates/partials/_agent_manager_view.html +52 -14
  19. flock/webapp/templates/partials/_agent_manager_view_old.html +19 -0
  20. flock/webapp/templates/partials/_create_flock_form.html +1 -1
  21. flock/webapp/templates/partials/_dashboard_flock_properties_preview.html +1 -1
  22. flock/webapp/templates/partials/_env_vars_table.html +25 -0
  23. flock/webapp/templates/partials/_execution_form.html +1 -1
  24. flock/webapp/templates/partials/_execution_view_container.html +13 -12
  25. flock/webapp/templates/partials/_flock_properties_form.html +2 -1
  26. flock/webapp/templates/partials/_header_flock_status.html +5 -0
  27. flock/webapp/templates/partials/_load_manager_view.html +50 -0
  28. flock/webapp/templates/partials/_settings_env_content.html +10 -0
  29. flock/webapp/templates/partials/_settings_theme_content.html +15 -0
  30. flock/webapp/templates/partials/_settings_view.html +36 -0
  31. flock/webapp/templates/partials/_sidebar.html +13 -6
  32. flock/webapp/templates/partials/_structured_data_view.html +4 -4
  33. flock/webapp/templates/partials/_theme_preview.html +23 -0
  34. {flock_core-0.4.0b35.dist-info → flock_core-0.4.0b36.dist-info}/METADATA +1 -1
  35. {flock_core-0.4.0b35.dist-info → flock_core-0.4.0b36.dist-info}/RECORD +38 -29
  36. flock/webapp/templates/partials/_load_manage_view.html +0 -88
  37. {flock_core-0.4.0b35.dist-info → flock_core-0.4.0b36.dist-info}/WHEEL +0 -0
  38. {flock_core-0.4.0b35.dist-info → flock_core-0.4.0b36.dist-info}/entry_points.txt +0 -0
  39. {flock_core-0.4.0b35.dist-info → flock_core-0.4.0b36.dist-info}/licenses/LICENSE +0 -0
flock/webapp/run.py CHANGED
@@ -1,30 +1,132 @@
1
+ import os # For environment variable
1
2
  import sys
2
3
  from pathlib import Path
4
+ from typing import TYPE_CHECKING
3
5
 
4
6
  import uvicorn
5
7
 
8
+ if TYPE_CHECKING:
9
+ from flock.core import Flock
10
+
11
+ # --- Integrated Server Function ---
12
+
13
+
14
+ def start_integrated_server(
15
+ flock_instance: "Flock",
16
+ host: str,
17
+ port: int,
18
+ server_name: str, # Currently unused as UI sets its own title
19
+ theme_name: str | None = None,
20
+ ):
21
+ """Starts the webapp, preloads flock & theme, includes API routes (TODO)."""
22
+ print(
23
+ f"Starting integrated server for Flock '{flock_instance.name}' on {host}:{port}"
24
+ )
25
+ try:
26
+ # Ensure src is in path (important if called from core)
27
+ src_dir = Path(__file__).resolve().parent.parent
28
+ if str(src_dir) not in sys.path:
29
+ sys.path.insert(0, str(src_dir))
30
+
31
+ # Import necessary webapp components *after* path setup
32
+ from flock.core.api.run_store import (
33
+ RunStore, # Needed for API routes later
34
+ )
35
+ from flock.webapp.app.config import (
36
+ get_current_theme_name,
37
+ set_current_theme_name,
38
+ )
39
+ from flock.webapp.app.main import app as webapp_fastapi_app
40
+ from flock.webapp.app.services.flock_service import (
41
+ set_current_flock_instance_programmatically,
42
+ )
43
+ # from flock.core.api.endpoints import create_api_router # Need to adapt this later
44
+
45
+ # 1. Set Theme (use provided or default)
46
+ set_current_theme_name(
47
+ theme_name
48
+ ) # Uses default from config if theme_name is None
49
+ print(f"Integrated server using theme: {get_current_theme_name()}")
50
+
51
+ # 2. Set Flock Instance
52
+ set_current_flock_instance_programmatically(
53
+ flock_instance,
54
+ f"{flock_instance.name.replace(' ', '_').lower()}_integrated.flock",
55
+ )
56
+ print(f"Flock '{flock_instance.name}' preloaded.")
57
+
58
+ # 3. TODO: Adapt and Include API Routes
59
+ # run_store = RunStore()
60
+ # api_router = create_api_router(flock_instance, run_store) # Assuming refactored signature
61
+ # webapp_fastapi_app.include_router(api_router, prefix="/api")
62
+ # print("API routes included.")
63
+
64
+ # 4. Run Uvicorn - STILL PASSING INSTANCE here because we need to modify it (add routes)
65
+ # and set state BEFORE running. Reload won't work well here.
66
+ uvicorn.run(
67
+ webapp_fastapi_app, host=host, port=port, reload=False
68
+ ) # Ensure reload=False
69
+
70
+ except ImportError as e:
71
+ print(
72
+ f"Error importing components for integrated server: {e}",
73
+ file=sys.stderr,
74
+ )
75
+ print(
76
+ "Ensure all dependencies are installed and paths are correct.",
77
+ file=sys.stderr,
78
+ )
79
+ sys.exit(1)
80
+ except Exception as e:
81
+ print(f"Error starting integrated server: {e}", file=sys.stderr)
82
+ sys.exit(1)
83
+
84
+
85
+ # --- Standalone Webapp Runner (for `flock --web`) ---
86
+
6
87
 
7
88
  def main():
8
- """Run the Flock web application."""
9
- # Ensure the webapp directory is in the Python path
10
- webapp_dir = Path(__file__).resolve().parent
11
- if str(webapp_dir) not in sys.path:
12
- sys.path.insert(0, str(webapp_dir.parent.parent)) # Add 'src' to path
89
+ """Run the Flock web application standalone."""
90
+ # Theme is now set via environment variable read by config.py on import
91
+ # No need to explicitly set it here anymore.
92
+ print(f"Starting standalone webapp...")
93
+ # Ensure src is in path
94
+ src_dir = Path(__file__).resolve().parent.parent
95
+ if str(src_dir) not in sys.path:
96
+ sys.path.insert(0, str(src_dir))
13
97
 
14
98
  try:
99
+ # Determine host, port, and reload settings
100
+ host = os.environ.get("FLOCK_WEB_HOST", "127.0.0.1")
101
+ port = int(os.environ.get("FLOCK_WEB_PORT", "8344"))
102
+ reload = os.environ.get("FLOCK_WEB_RELOAD", "true").lower() == "true"
103
+ # Use import string for app path
104
+ app_import_string = "flock.webapp.app.main:app"
105
+
106
+ # No need to import app instance here anymore for standalone mode
107
+ # from flock.webapp.app.main import app as webapp_fastapi_app
108
+ # from flock.webapp.app.config import get_current_theme_name
109
+ # print(f"Standalone webapp using theme: {get_current_theme_name()}") # Config now logs this on load
110
+
15
111
  uvicorn.run(
16
- "flock.webapp.app.main:app",
17
- host="127.0.0.1",
18
- port=8344,
19
- reload=True,
112
+ app_import_string, # Use import string for reload capability
113
+ host=host,
114
+ port=port,
115
+ reload=reload,
20
116
  )
21
- except ModuleNotFoundError as e:
22
- print(f"Error loading webapp modules: {e}")
117
+ except ImportError as e:
118
+ # Catch potential import error during uvicorn startup if path is wrong
119
+ print(f"Error loading webapp modules via Uvicorn: {e}", file=sys.stderr)
23
120
  print(
24
- "Make sure all required packages are installed and module structure is correct."
121
+ "Make sure all required packages are installed and src path is correct.",
122
+ file=sys.stderr,
25
123
  )
26
124
  sys.exit(1)
125
+ except Exception as e:
126
+ print(f"Error starting standalone webapp: {e}", file=sys.stderr)
127
+ sys.exit(1)
27
128
 
28
129
 
29
- if __name__ == "__main__":
30
- main()
130
+ # Note: The `if __name__ == "__main__":` block is removed as this module
131
+ # is now primarily meant to be called via `main()` or `start_integrated_server()`
132
+ # The CLI entry point will call `main()` after potentially calling `set_initial_theme()`.
@@ -3,9 +3,7 @@ body {
3
3
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
4
4
  display: grid;
5
5
  grid-template-columns: 300px 1fr;
6
- /* Increased sidebar width from 280px to 300px */
7
6
  grid-template-rows: auto 1fr auto;
8
- /* Header, content, footer */
9
7
  grid-template-areas:
10
8
  "header header"
11
9
  "sidebar main"
@@ -13,7 +11,8 @@ body {
13
11
  min-height: 100vh;
14
12
  margin: 0;
15
13
  background-color: var(--pico-background-color);
16
- /* Ensure body background is dark too */
14
+ /* Add body padding here if needed, instead of in base.html <style> */
15
+ /* padding-bottom: 50px; */
17
16
  }
18
17
 
19
18
  /* --- Improved Header Styles --- */
@@ -21,7 +20,7 @@ header.top-header {
21
20
  grid-area: header;
22
21
  border-bottom: 1px solid var(--pico-muted-border-color);
23
22
  padding: 0.7rem 1.5rem;
24
- background-color: var(--pico-card-background-color);
23
+ background-color: var(--pico-card-sectioning-background-color); /* Use custom or fallback */
25
24
  display: flex;
26
25
  justify-content: space-between;
27
26
  align-items: center;
@@ -30,24 +29,24 @@ header.top-header {
30
29
  left: 0;
31
30
  right: 0;
32
31
  z-index: 1001;
33
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
32
+ box-shadow: var(--pico-card-box-shadow, 0 2px 10px rgba(0, 0, 0, 0.2)); /* Use Pico shadow or fallback */
34
33
  }
35
34
 
36
35
  header.top-header strong {
37
- color: white;
36
+ color: var(--pico-color); /* Use theme text color */
38
37
  font-weight: 600;
39
38
  font-size: 1.2rem;
40
39
  letter-spacing: 0.02em;
41
40
  }
42
41
 
43
42
  header.top-header small {
44
- color: rgba(255, 255, 255, 0.7);
43
+ color: var(--pico-muted-color); /* Use muted color */
45
44
  font-size: 0.85rem;
46
45
  }
47
46
 
48
47
  header.top-header code {
49
- background: rgba(255, 255, 255, 0.1);
50
- color: rgba(255, 255, 255, 0.9);
48
+ background: var(--pico-code-background-color); /* Use code background */
49
+ color: var(--pico-code-color); /* Use code text color */
51
50
  padding: 0.2em 0.5em;
52
51
  border-radius: 4px;
53
52
  font-size: 0.85rem;
@@ -59,43 +58,42 @@ main.main-content {
59
58
  grid-area: main;
60
59
  padding: 1.5rem;
61
60
  overflow-y: auto;
62
- margin-top: 3.5rem;
61
+ margin-top: 3.5rem; /* Needs to match header height */
63
62
  background-color: var(--pico-background-color);
64
- /* Main content area background */
63
+ padding-bottom: 50px; /* Add padding here to avoid overlap with fixed footer */
65
64
  }
66
65
 
67
66
  footer.main-footer {
68
- grid-area: footer;
67
+ position: fixed;
68
+ left: 0;
69
+ bottom: 0;
70
+ width: 100%;
71
+ background-color: var(--pico-card-background-color);
72
+ border-top: 1px solid var(--pico-muted-border-color);
69
73
  padding: 0.5rem 1rem;
70
- border-top: 1px solid rgba(255, 255, 255, 0.07);
71
- font-size: 0.8em;
72
74
  text-align: center;
73
- z-index: 1;
74
- background: var(--pico-card-background-color);
75
- color: rgba(255, 255, 255, 0.6);
75
+ z-index: 1000;
76
76
  }
77
77
 
78
78
  /* --- Improved Sidebar Styles --- */
79
79
  aside.sidebar {
80
80
  grid-area: sidebar;
81
- background: var(--pico-card-background-color);
81
+ background: var(--flock-sidebar-background, var(--pico-card-background-color)); /* Use custom or fallback */
82
82
  padding: 1.5rem 0;
83
- border-right: 1px solid rgba(255, 255, 255, 0.07);
84
- margin-top: 3.3rem;
85
- height: calc(100vh - 3.5rem - 2.1rem);
83
+ border-right: 1px solid var(--pico-muted-border-color);
84
+ margin-top: 3.2rem; /* Adjust if header height changed */
85
+ height: calc(100vh - 3.5rem - 2.1rem); /* Adjust based on header/footer heights */
86
86
  position: fixed;
87
87
  left: 0;
88
- bottom: 2.1rem;
89
- width: 320px;
90
- /* Increased from 280px to 300px */
88
+ bottom: 2.1rem; /* Adjust based on footer height */
89
+ width: 300px; /* Match grid-template-columns */
91
90
  z-index: 1000;
92
91
  }
93
92
 
94
93
  .sidebar nav h5 {
95
-
96
94
  margin-bottom: 0.9rem;
97
95
  padding-left: 1.5rem;
98
- color: rgba(255, 255, 255, 0.6);
96
+ color: var(--pico-color); /* Use muted color */
99
97
  font-size: 0.85em;
100
98
  text-transform: uppercase;
101
99
  letter-spacing: 0.08em;
@@ -104,7 +102,6 @@ aside.sidebar {
104
102
 
105
103
  .sidebar nav h5:first-of-type {
106
104
  margin-top: 0;
107
- /* First heading should not have top margin */
108
105
  margin-bottom: 0.9rem;
109
106
  }
110
107
 
@@ -121,8 +118,8 @@ aside.sidebar {
121
118
 
122
119
  .sidebar hr {
123
120
  margin: 1.25rem 1.5rem;
124
- border-color: rgba(255, 255, 255, 0.1);
125
- opacity: 0.5;
121
+ border-color: var(--pico-muted-border-color); /* Use muted border */
122
+ opacity: 0.5; /* Keep opacity or adjust as needed */
126
123
  }
127
124
 
128
125
  /* Links and buttons in sidebar */
@@ -135,7 +132,7 @@ aside.sidebar {
135
132
  padding: 0.7rem 1rem;
136
133
  border: none;
137
134
  background-color: transparent;
138
- color: rgba(255, 255, 255, 0.85);
135
+ color: var(--pico-button-base-color); /* Use theme text color */
139
136
  text-decoration: none;
140
137
  border-radius: 8px;
141
138
  font-size: 0.9em;
@@ -143,7 +140,6 @@ aside.sidebar {
143
140
  transition: all 0.2s ease-in-out;
144
141
  font-weight: 500;
145
142
  white-space: nowrap;
146
- /* Prevent text wrapping in menu items */
147
143
  overflow: hidden;
148
144
  text-overflow: ellipsis;
149
145
  }
@@ -154,17 +150,16 @@ aside.sidebar {
154
150
  width: 24px;
155
151
  margin-right: 8px;
156
152
  text-align: center;
157
- color: rgba(255, 255, 255, 0.7);
153
+ color: var(--pico-h2-color); /* Use muted color */
158
154
  transition: all 0.2s ease-in-out;
159
155
  flex-shrink: 0;
160
- /* Prevent icon from shrinking */
161
156
  }
162
157
 
163
158
  .sidebar nav a:hover i,
164
159
  .sidebar nav button:hover i,
165
160
  .sidebar nav a.active-nav i,
166
161
  .sidebar nav button.active-nav i {
167
- color: white;
162
+ color: var(--pico-primary-inverse); /* Color for icon on active/hover background */
168
163
  transform: scale(1.1);
169
164
  }
170
165
 
@@ -173,18 +168,19 @@ aside.sidebar {
173
168
  .sidebar nav button.contrast {
174
169
  border: none;
175
170
  background-color: transparent;
176
- color: rgba(255, 255, 255, 0.85);
171
+ color: var(--pico-muted-color); /* Use theme text color */
177
172
  box-shadow: none;
178
173
  }
179
174
 
180
175
  .sidebar nav button:focus {
181
- box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.4);
176
+ /* Use Pico's focus style or define a custom one using theme vars */
177
+ box-shadow: 0 0 0 3px var(--pico-primary-focus);
182
178
  }
183
179
 
184
180
  .sidebar nav a:hover,
185
181
  .sidebar nav button:hover {
186
- background-color: rgba(79, 70, 229, 0.15);
187
- color: #fff;
182
+ background-color: var(--pico-primary-hover-background, var(--pico-primary-focus)); /* Use hover background or focus as fallback */
183
+ color: var(--pico-primary-inverse); /* Text color on hover background */
188
184
  transform: translateX(3px);
189
185
  }
190
186
 
@@ -193,10 +189,10 @@ aside.sidebar {
193
189
  .sidebar nav button[aria-current="page"],
194
190
  .sidebar nav a.active-nav,
195
191
  .sidebar nav button.active-nav {
196
- background-color: #4f46e5;
197
- color: white;
192
+ background-color: var(--pico-primary);
193
+ color: var(--pico-primary-inverse);
198
194
  font-weight: 600;
199
- box-shadow: 0 4px 12px rgba(79, 70, 229, 0.4);
195
+ box-shadow: var(--pico-card-box-shadow); /* Use a standard shadow or define custom */
200
196
  }
201
197
 
202
198
  /* --- End Sidebar Styles --- */
@@ -208,12 +204,11 @@ aside.sidebar {
208
204
  bottom: 3rem;
209
205
  right: 1rem;
210
206
  z-index: 1002;
211
- /* Higher than sidebar */
212
207
  width: auto;
213
208
  max-width: 400px;
214
209
  }
215
210
 
216
- .message-container>div {
211
+ .message-container > div {
217
212
  margin-top: 0.5rem;
218
213
  box-shadow: var(--pico-card-box-shadow);
219
214
  display: flex;
@@ -225,15 +220,15 @@ aside.sidebar {
225
220
  }
226
221
 
227
222
  .message-container .success {
228
- background-color: var(--pico-ins-color);
229
- color: var(--pico-primary-inverse);
230
- border: 1px solid var(--pico-ins-color);
223
+ background-color: var(--flock-success-color, var(--pico-ins-color)); /* Use custom or Pico fallback */
224
+ color: var(--pico-primary-inverse); /* Assuming success background provides contrast */
225
+ border: 1px solid var(--flock-success-color, var(--pico-ins-color));
231
226
  }
232
227
 
233
228
  .message-container .error {
234
- background-color: var(--pico-del-color);
235
- color: var(--pico-primary-inverse);
236
- border: 1px solid var(--pico-del-color);
229
+ background-color: var(--flock-error-color, var(--pico-del-color)); /* Use custom or Pico fallback */
230
+ color: var(--pico-primary-inverse); /* Assuming error background provides contrast */
231
+ border: 1px solid var(--flock-error-color, var(--pico-del-color));
237
232
  }
238
233
 
239
234
  .message-container .close {
@@ -253,11 +248,15 @@ progress {
253
248
  }
254
249
 
255
250
  progress:indeterminate {
256
- background: rgba(79, 70, 229, 0.2);
251
+ background: rgba(var(--pico-primary-rgb), 0.2); /* Need RGB version or approximation */
252
+ /* Fallback if RGB not available */
253
+ /* background: var(--pico-loading-bar-background-color); */
257
254
  }
258
255
 
259
256
  progress:indeterminate::after {
260
- background-image: linear-gradient(90deg, rgba(79, 70, 229, 0.2) 0%, #4f46e5 50%, rgba(79, 70, 229, 0.2) 100%);
257
+ /* Fallback if RGB not available */
258
+ /* background-image: var(--pico-loading-bar-indeterminate-background-image); */
259
+ background-image: linear-gradient(90deg, rgba(var(--pico-primary-rgb), 0.2) 0%, var(--pico-primary) 50%, rgba(var(--pico-primary-rgb), 0.2) 100%);
261
260
  }
262
261
 
263
262
  .sidebar progress {
@@ -277,7 +276,7 @@ progress:indeterminate::after {
277
276
  #agent-list-panel,
278
277
  #agent-detail-panel {
279
278
  height: calc(80vh - var(--pico-block-spacing-vertical) * 2);
280
- overflow-y: auto;
279
+
281
280
  }
282
281
 
283
282
  #agent-list-panel article,
@@ -291,6 +290,7 @@ progress:indeterminate::after {
291
290
 
292
291
  #agent-list-panel header,
293
292
  #agent-detail-panel header {
293
+ /* background-color: var(--pico-card-sectioning-background-color); */
294
294
  flex-shrink: 0;
295
295
  }
296
296
 
@@ -299,7 +299,6 @@ progress:indeterminate::after {
299
299
  overflow-y: auto;
300
300
  list-style-type: none;
301
301
  padding: 0;
302
- margin-top: 1rem;
303
302
  }
304
303
 
305
304
  #agent-list-panel li {
@@ -312,12 +311,12 @@ progress:indeterminate::after {
312
311
  }
313
312
 
314
313
  #agent-list-panel li:hover,
315
- #agent-list-panel li.htmx-settling {
314
+ #agent-list-panel li.htmx-setting {
316
315
  background-color: var(--pico-muted-hover-background-color);
317
316
  }
318
317
 
319
318
  #agent-list-panel li.selected-agent {
320
- background-color: var(--pico-primary-focus);
319
+ background-color: var(--pico-primary-focus); /* Use focus color for selection */
321
320
  border-color: var(--pico-primary);
322
321
  color: var(--pico-primary-inverse);
323
322
  }
@@ -357,16 +356,17 @@ progress:indeterminate::after {
357
356
  /* Buttons and Forms Styling */
358
357
  button[type="submit"],
359
358
  button.primary {
360
- background-color: #4f46e5;
361
- border-color: #4f46e5;
362
- box-shadow: 0 4px 12px rgba(79, 70, 229, 0.3);
359
+ color: var(--pico-color);
360
+ background-color: var(--pico-primary);
361
+ border-color: var(--pico-primary);
362
+ box-shadow: var(--pico-card-box-shadow); /* Use standard shadow or focus? */
363
363
  }
364
364
 
365
365
  button[type="submit"]:hover,
366
366
  button.primary:hover {
367
- background-color: #4338ca;
368
- border-color: #4338ca;
369
- box-shadow: 0 6px 14px rgba(79, 70, 229, 0.4);
367
+ background-color: var(--pico-primary-hover);
368
+ border-color: var(--pico-primary-hover);
369
+ box-shadow: var(--pico-card-box-shadow); /* Enhance shadow on hover? */
370
370
  }
371
371
 
372
372
  /* Tool Checklist */
@@ -378,7 +378,6 @@ button.primary:hover {
378
378
  margin-bottom: 0.75rem;
379
379
  border-radius: var(--pico-border-radius);
380
380
  background-color: var(--pico-form-element-background-color);
381
- /* Match form input background */
382
381
  }
383
382
 
384
383
  .tool-checklist label {
@@ -441,7 +440,7 @@ button.primary:hover {
441
440
  }
442
441
 
443
442
  #results-display .structured-table td[style*="font-weight: bold"] {
444
- color: var(--pico-secondary);
443
+ color: var(--pico-secondary); /* Use secondary color for keys? */
445
444
  min-width: 120px;
446
445
  max-width: 250px;
447
446
  word-break: break-word;
@@ -486,42 +485,128 @@ button.primary:hover {
486
485
 
487
486
  /* Utility for form field errors */
488
487
  .field-error {
489
- color: var(--pico-del-color);
488
+ color: var(--flock-error-color, var(--pico-del-color)); /* Use custom or fallback */
490
489
  font-size: var(--pico-font-size-small);
491
490
  margin-top: -0.5rem;
492
491
  margin-bottom: 0.5rem;
493
492
  }
494
493
 
495
494
  /* Main content headings - ensure consistent vertical alignment */
496
- main.main-content h1 {
497
- font-size: 2rem;
498
- margin-top: 0;
499
- margin-bottom: 1.5rem;
500
- color: white;
495
+ main.main-content h1,
496
+ main.main-content h2,
497
+ main.main-content h3 {
498
+ color: var(--pico-color); /* Use theme text color */
501
499
  font-weight: 600;
502
500
  line-height: 1.2;
501
+ margin-top: 0; /* Reset top margin */
503
502
  }
504
503
 
505
- main.main-content h2 {
506
- font-size: 1.75rem;
507
- margin-top: 0;
504
+ main.main-content h1 {
505
+ font-size: 2rem;
506
+ margin-bottom: 1.5rem;
507
+ }
508
+ main.main-content h2 {
509
+ font-size: 1.75rem;
508
510
  margin-bottom: 1.25rem;
509
- color: white;
510
- font-weight: 600;
511
- line-height: 1.2;
512
511
  }
513
-
514
- main.main-content h3 {
515
- font-size: 1.5rem;
516
- margin-top: 0;
512
+ main.main-content h3 {
513
+ font-size: 1.5rem;
517
514
  margin-bottom: 1rem;
518
- color: white;
519
- font-weight: 600;
520
- line-height: 1.2;
521
515
  }
522
516
 
523
517
  /* Panel titles styling for consistency */
524
518
  .panel-title {
525
519
  margin-top: 0;
526
520
  margin-bottom: 1.25rem;
527
- }
521
+ /* Inherits color from h1/h2/h3 now */
522
+ }
523
+
524
+ /* ==========================================================================
525
+ Two-Pane Flex Layout (Unified)
526
+ ========================================================================== */
527
+
528
+ .two-pane-flex-container {
529
+ display: flex;
530
+ gap: 1.5rem; /* Consistent gap like in execution view */
531
+ border: 1px solid var(--pico-muted-border-color); /* Optional: If the container itself needs a border
532
+ /* border-radius: var(--pico-border-radius); */
533
+ background-color: var(--pico-card-background-color); /* Optional: If the container needs a distinct background */
534
+ }
535
+
536
+ .left-pane {
537
+ flex: 1;
538
+ min-width: 300px; /* Minimum width for the left selection/control pane */
539
+ /* background-color: var(--pico-card-background-color); /* Optional: if left pane needs card-like bg */
540
+ /* border: 1px solid var(--pico-muted-border-color); /* Optional: if left pane needs border */
541
+ /* border-radius: var(--pico-border-radius); */
542
+ display: flex; /* To allow header and scrollable content within */
543
+ flex-direction: column;
544
+
545
+ }
546
+
547
+ /* If the left pane has a content div that should be scrollable (e.g., a list) */
548
+ .left-pane > .scrollable-content {
549
+ flex-grow: 1;
550
+
551
+ }
552
+
553
+ .right-pane-framed {
554
+ flex: 2; /* Right pane takes more space */
555
+ /* background-color: var(--pico-background-color); /* Match execution view's right pane style if it's plain */
556
+ border-left: 1px solid var(--pico-muted-border-color); /* Separator line */
557
+ padding-left: 1.5rem; /* Padding to the left of the separator */
558
+
559
+ }
560
+
561
+ .right-pane-framed > header {
562
+ padding-bottom: 0.75rem; /* Space below the title in the right pane */
563
+ border-bottom: 1px solid var(--pico-muted-border-color); /* Line below title */
564
+ margin-bottom: 1rem; /* Space between header and content */
565
+ }
566
+
567
+ .right-pane-framed > header > h5 {
568
+ margin-bottom: 0; /* Reset Pico's default h5 margin if needed */
569
+ font-size: 1.1rem; /* Consistent header size */
570
+ }
571
+
572
+ /* Styles for item lists within the left-pane if needed globally */
573
+ .item-list-container {
574
+ flex-grow: 1;
575
+
576
+ /* border-top: 1px solid var(--pico-muted-border-color); */
577
+ }
578
+
579
+ ul.item-list {
580
+ list-style-type: none;
581
+ padding: 0;
582
+ margin: 0;
583
+ }
584
+
585
+ ul.item-list li {
586
+ padding: 0.75rem 1rem;
587
+ border-bottom: 1px solid var(--pico-muted-border-color);
588
+ cursor: pointer;
589
+ transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out;
590
+ }
591
+
592
+ ul.item-list li:last-child {
593
+ border-bottom: none;
594
+ }
595
+
596
+ ul.item-list li:hover,
597
+ ul.item-list li.selected-item {
598
+ background-color: var(--pico-primary-focus); /* Or var(--pico-active-background-color) */
599
+ color: var(--pico-primary-inverse); /* Or var(--pico-active-color) */
600
+ }
601
+
602
+ /* Attempt to override/reset .editor-grid if it's defined elsewhere and conflicts.
603
+ If .editor-grid and .flock-manager-grid are only in <style> tags, they will be removed with the HTML. */
604
+ .editor-grid {
605
+ display: unset;
606
+ grid-template-columns: unset;
607
+ gap: unset;
608
+ height: unset;
609
+ border: unset;
610
+ border-radius: unset;
611
+ background-color: unset;
612
+ }
@@ -9,6 +9,15 @@
9
9
  <link rel="stylesheet" href="/static/css/custom.css">
10
10
  <!-- Font Awesome for icons -->
11
11
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
12
+ {# Inject Theme CSS Variables #}
13
+ {% if theme_css %}
14
+ <style>
15
+ /* Start Theme CSS */
16
+ {{ theme_css | safe }}
17
+ /* End Theme CSS */
18
+ </style>
19
+ {% endif %}
20
+ {# End Theme CSS Injection #}
12
21
  <script src="https://unpkg.com/htmx.org@1.9.10"
13
22
  integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC"
14
23
  crossorigin="anonymous"></script>
@@ -19,12 +28,10 @@
19
28
  <body>
20
29
  <header class="top-header">
21
30
  <span><strong>🐧 Flock UI 🐤</strong></span>
22
- {# Use the variables passed from the route handler #}
23
- {% if current_flock %}
24
- <small>Current: <code>{{ current_filename or current_flock.name }}</code></small>
25
- {% else %}
26
- <small>No Flock Loaded</small>
27
- {% endif %}
31
+ <span id="header-flock-status-container" hx-get="/ui/htmx/header-flock-status?ui_mode={{ ui_mode }}"
32
+ hx-trigger="load, flockLoaded from:body, flockCleared from:body" hx-swap="innerHTML">
33
+ <small>Loading status...</small> {# Placeholder while loading #}
34
+ </span>
28
35
  </header>
29
36
 
30
37
  <aside class="sidebar" hx-get="/ui/htmx/sidebar?ui_mode={{ ui_mode }}"
@@ -60,7 +67,7 @@
60
67
  </div>
61
68
 
62
69
  <footer class="main-footer">
63
- <small>Built with FastAPI, HTMX, Pico.CSS by 🤍 white duck 🦆</small>
70
+ <small>Built with FastAPI, HTMX, Pico.CSS by 🤍 white duck 🦆 - Theme: {{ active_theme_name | default('default') }}</small>
64
71
  </footer>
65
72
 
66
73
  <script>