@zolomedia/bifrost-client 1.7.74
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/L1_Foundation/L1_Foundation.js +13 -0
- package/L1_Foundation/bootstrap/bootstrap.js +11 -0
- package/L1_Foundation/bootstrap/bootstrap_hooks.js +123 -0
- package/L1_Foundation/bootstrap/bootstrap_index.js +15 -0
- package/L1_Foundation/bootstrap/bootstrap_logger.js +135 -0
- package/L1_Foundation/bootstrap/cdn_loader.js +217 -0
- package/L1_Foundation/bootstrap/module_registry.js +102 -0
- package/L1_Foundation/bootstrap/prism_loader.js +164 -0
- package/L1_Foundation/config/client_config.js +110 -0
- package/L1_Foundation/config/config.js +7 -0
- package/L1_Foundation/connection/connection.js +8 -0
- package/L1_Foundation/connection/websocket_connection.js +122 -0
- package/L1_Foundation/constants/bifrost_constants.js +284 -0
- package/L1_Foundation/constants/constants.js +7 -0
- package/L1_Foundation/logger/logger.js +10 -0
- package/L2_Handling/L2_Handling.js +15 -0
- package/L2_Handling/cache/cache.js +22 -0
- package/L2_Handling/cache/cache_constants.js +69 -0
- package/L2_Handling/cache/orchestration/cache_manager.js +299 -0
- package/L2_Handling/cache/orchestration/cache_orchestrator.js +260 -0
- package/L2_Handling/cache/orchestration/orchestration.js +12 -0
- package/L2_Handling/cache/storage/session_manager.js +289 -0
- package/L2_Handling/cache/storage/storage.js +10 -0
- package/L2_Handling/cache/storage/storage_manager.js +590 -0
- package/L2_Handling/display/composite/composite.js +13 -0
- package/L2_Handling/display/composite/dashboard_renderer.js +221 -0
- package/L2_Handling/display/composite/swiper_renderer.js +564 -0
- package/L2_Handling/display/composite/terminal_renderer.js +922 -0
- package/L2_Handling/display/composite/wizard_conditional_renderer.js +274 -0
- package/L2_Handling/display/display.js +30 -0
- package/L2_Handling/display/feedback/feedback.js +11 -0
- package/L2_Handling/display/feedback/progressbar_renderer.js +418 -0
- package/L2_Handling/display/feedback/spinner_renderer.js +246 -0
- package/L2_Handling/display/inputs/button_renderer.js +634 -0
- package/L2_Handling/display/inputs/form_renderer.js +583 -0
- package/L2_Handling/display/inputs/input_renderer.js +658 -0
- package/L2_Handling/display/inputs/inputs.js +12 -0
- package/L2_Handling/display/navigation/menu_renderer.js +206 -0
- package/L2_Handling/display/navigation/navigation.js +11 -0
- package/L2_Handling/display/navigation/navigation_renderer.js +703 -0
- package/L2_Handling/display/orchestration/orchestration.js +11 -0
- package/L2_Handling/display/orchestration/renderer.js +430 -0
- package/L2_Handling/display/orchestration/zdisplay_orchestrator.js +1759 -0
- package/L2_Handling/display/outputs/alert_renderer.js +161 -0
- package/L2_Handling/display/outputs/audio_renderer.js +94 -0
- package/L2_Handling/display/outputs/card_renderer.js +229 -0
- package/L2_Handling/display/outputs/code_renderer.js +66 -0
- package/L2_Handling/display/outputs/dl_renderer.js +131 -0
- package/L2_Handling/display/outputs/header_renderer.js +162 -0
- package/L2_Handling/display/outputs/icon_renderer.js +107 -0
- package/L2_Handling/display/outputs/image_renderer.js +145 -0
- package/L2_Handling/display/outputs/list_renderer.js +190 -0
- package/L2_Handling/display/outputs/outputs.js +19 -0
- package/L2_Handling/display/outputs/table_renderer.js +765 -0
- package/L2_Handling/display/outputs/text_renderer.js +818 -0
- package/L2_Handling/display/outputs/typography_renderer.js +293 -0
- package/L2_Handling/display/outputs/video_renderer.js +116 -0
- package/L2_Handling/display/primitives/document_structure_primitives.js +319 -0
- package/L2_Handling/display/primitives/form_primitives.js +526 -0
- package/L2_Handling/display/primitives/generic_containers.js +109 -0
- package/L2_Handling/display/primitives/interactive_primitives.js +305 -0
- package/L2_Handling/display/primitives/link_primitives.js +552 -0
- package/L2_Handling/display/primitives/lists_primitives.js +262 -0
- package/L2_Handling/display/primitives/media_primitives.js +383 -0
- package/L2_Handling/display/primitives/primitives.js +19 -0
- package/L2_Handling/display/primitives/semantic_element_primitive.js +226 -0
- package/L2_Handling/display/primitives/table_primitives.js +528 -0
- package/L2_Handling/display/primitives/typography_primitives.js +175 -0
- package/L2_Handling/display/specialized/input_request_renderer.js +467 -0
- package/L2_Handling/display/specialized/specialized.js +10 -0
- package/L2_Handling/hooks/hooks.js +9 -0
- package/L2_Handling/hooks/menu_integration.js +57 -0
- package/L2_Handling/hooks/widget_hook_manager.js +292 -0
- package/L2_Handling/message/message.js +8 -0
- package/L2_Handling/message/message_handler.js +701 -0
- package/L2_Handling/navigation/navigation.js +8 -0
- package/L2_Handling/navigation/navigation_manager.js +403 -0
- package/L2_Handling/zhooks/features/cache_live.js +287 -0
- package/L2_Handling/zhooks/features/crumbs_live.js +292 -0
- package/L2_Handling/zhooks/zhooks_manager.js +65 -0
- package/L2_Handling/zvaf/zvaf.js +8 -0
- package/L2_Handling/zvaf/zvaf_manager.js +334 -0
- package/L3_Abstraction/L3_Abstraction.js +12 -0
- package/L3_Abstraction/orchestrator/container_unwrapper.js +101 -0
- package/L3_Abstraction/orchestrator/group_renderer.js +698 -0
- package/L3_Abstraction/orchestrator/input_event_handler.js +797 -0
- package/L3_Abstraction/orchestrator/metadata_processor.js +249 -0
- package/L3_Abstraction/orchestrator/navbar_builder.js +201 -0
- package/L3_Abstraction/orchestrator/orchestrator.js +13 -0
- package/L3_Abstraction/orchestrator/wizard_gate_handler.js +360 -0
- package/L3_Abstraction/renderer/renderer.js +1 -0
- package/L3_Abstraction/session/session.js +1 -0
- package/L4_Orchestration/L4_Orchestration.js +11 -0
- package/L4_Orchestration/client/client.js +1 -0
- package/L4_Orchestration/facade/facade.js +9 -0
- package/L4_Orchestration/facade/manager_registry.js +118 -0
- package/L4_Orchestration/facade/renderer_registry.js +274 -0
- package/L4_Orchestration/lifecycle/asset_loader.js +255 -0
- package/L4_Orchestration/lifecycle/initializer.js +135 -0
- package/L4_Orchestration/lifecycle/lifecycle.js +8 -0
- package/L4_Orchestration/rendering/facade.js +94 -0
- package/L4_Orchestration/rendering/rendering.js +7 -0
- package/LICENSE +21 -0
- package/README.md +82 -0
- package/bifrost_client.js +204 -0
- package/bifrost_core.js +1686 -0
- package/docs/ARCHITECTURE.md +111 -0
- package/docs/PROTOCOL.md +106 -0
- package/docs/RENDERERS.md +101 -0
- package/docs/SECURITY.md +92 -0
- package/package.json +24 -0
- package/syntax/prism-zconfig.js +41 -0
- package/syntax/prism-zenv.js +69 -0
- package/syntax/prism-zolo-theme.css +288 -0
- package/syntax/prism-zolo.js +380 -0
- package/syntax/prism-zschema.js +38 -0
- package/syntax/prism-zspark.js +25 -0
- package/syntax/prism-zui.js +68 -0
- package/zSys/accessibility/accessibility.js +10 -0
- package/zSys/accessibility/emoji_accessibility.js +173 -0
- package/zSys/dom/block_utils.js +122 -0
- package/zSys/dom/container_utils.js +370 -0
- package/zSys/dom/dom.js +13 -0
- package/zSys/dom/dom_utils.js +328 -0
- package/zSys/dom/encoding_utils.js +117 -0
- package/zSys/dom/style_utils.js +71 -0
- package/zSys/errors/error_display.js +299 -0
- package/zSys/errors/errors.js +10 -0
- package/zSys/theme/color_utils.js +274 -0
- package/zSys/theme/dark_mode_utils.js +272 -0
- package/zSys/theme/size_utils.js +256 -0
- package/zSys/theme/spacing_utils.js +405 -0
- package/zSys/theme/theme.js +14 -0
- package/zSys/theme/zbase.css +1735 -0
- package/zSys/theme/zbase_inject.js +161 -0
- package/zSys/theme/ztheme_utils.js +305 -0
- package/zSys/validation/error_boundary.js +201 -0
- package/zSys/validation/validation.js +11 -0
- package/zSys/validation/validation_utils.js +238 -0
- package/zSys/zSys.js +14 -0
|
@@ -0,0 +1,1735 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* zbase.css — zbifrost-client structural baseline
|
|
3
|
+
*
|
|
4
|
+
* Always injected by bifrost_core.js on startup. Provides only what the
|
|
5
|
+
* rendering runtime NEEDS to function: reset, grid, flex, tabs, nav-pills,
|
|
6
|
+
* spacing helpers, and spinners. No colors. No typography scale. No component
|
|
7
|
+
* aesthetics — those are the app's responsibility.
|
|
8
|
+
*
|
|
9
|
+
* Sections:
|
|
10
|
+
* 0. Base color tokens (SSOT — --color-*)
|
|
11
|
+
* 1. Reset
|
|
12
|
+
* 2. Grid (zRow / zCol-* / zCol-auto, responsive xs→xl)
|
|
13
|
+
* 3. Gutters (zG-0 … zG-5)
|
|
14
|
+
* 4. Flex utilities
|
|
15
|
+
* 5. Display helpers (.zD-flex, .zD-block, etc.)
|
|
16
|
+
* 6. Spacing helpers (.zm-*, .zp-*, .zme-*, .zms-*)
|
|
17
|
+
* 7. Tabs (.zTab-content / .zTab-pane / .zActive)
|
|
18
|
+
* 8. Nav (.zNav / .zNav-pills / .zFlex-column)
|
|
19
|
+
* 9. Spinner (.zSpinner-border / .zSpinner-border-sm)
|
|
20
|
+
* 10. Misc runtime helpers (.zVisually-hidden, .zContainer-fluid)
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/* ─── 0. Base color tokens — SSOT ──────────────────────────────────────────── */
|
|
24
|
+
/* The canonical zCLI palette, mirrored from zSys/formatting/colors.py. Every
|
|
25
|
+
* var(--color-*) reference below (zText-*, zBtn-*, fields, blockquote, links)
|
|
26
|
+
* resolves here so Bifrost output matches the terminal. Apps re-skin by
|
|
27
|
+
* redefining any of these in a later stylesheet (zCanvas / zBrush). */
|
|
28
|
+
:root {
|
|
29
|
+
--color-primary: #A2D46E; /* Intention — the heart of zCLI */
|
|
30
|
+
--color-secondary: #9370DB; /* Validation — structure & elegance */
|
|
31
|
+
--color-info: #5CA9FF; /* Perception — clarity & understanding */
|
|
32
|
+
--color-success: #52B788; /* Manifestation — organic & vibrant */
|
|
33
|
+
--color-warning: #FFB347; /* Caution — warm & approachable */
|
|
34
|
+
--color-error: #E63946; /* Decisive — clear & strong */
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* ─── 1. Reset ─────────────────────────────────────────────────────────────── */
|
|
38
|
+
|
|
39
|
+
*,
|
|
40
|
+
*::before,
|
|
41
|
+
*::after { box-sizing: border-box; }
|
|
42
|
+
|
|
43
|
+
html {
|
|
44
|
+
font-family: sans-serif;
|
|
45
|
+
line-height: 1.15;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
body {
|
|
49
|
+
margin: 0;
|
|
50
|
+
padding: 0;
|
|
51
|
+
min-height: 100vh;
|
|
52
|
+
overflow-x: hidden;
|
|
53
|
+
font-size: 1rem;
|
|
54
|
+
line-height: 1.5;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
img, svg { display: block; max-width: 100%; }
|
|
58
|
+
|
|
59
|
+
/* Default link color — zCLI/info palette, overridable via --color-link.
|
|
60
|
+
* Navbar links and buttons opt out below (they manage their own color). */
|
|
61
|
+
a { text-decoration: none; color: var(--color-link, #5CA9FF); }
|
|
62
|
+
|
|
63
|
+
zNavBar a,
|
|
64
|
+
.zBtn { color: inherit; }
|
|
65
|
+
|
|
66
|
+
/* ─── Custom elements — must be block for layout ───────────────────────────── */
|
|
67
|
+
|
|
68
|
+
zvaf,
|
|
69
|
+
zNavBar,
|
|
70
|
+
zBifrostBadge { display: block; }
|
|
71
|
+
|
|
72
|
+
/* ─── zOS heading extensions ──────────────────────────────────────────────── */
|
|
73
|
+
/* h0: zOS system/hero heading — not in HTML5 spec, used for page-level titles */
|
|
74
|
+
|
|
75
|
+
h0 {
|
|
76
|
+
display: block;
|
|
77
|
+
font-size: clamp(2.5rem, 5vw, 4rem);
|
|
78
|
+
font-weight: 800;
|
|
79
|
+
line-height: 1.1;
|
|
80
|
+
letter-spacing: -0.02em;
|
|
81
|
+
margin-top: 0;
|
|
82
|
+
margin-bottom: 0.5rem;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* ─── zTheme semantic text colors — zCLI parity ───────────────────────────── */
|
|
86
|
+
/* The client maps a header/text `color:` token → `.zText-<token>`. These are
|
|
87
|
+
* the zOS defaults so `color: PRIMARY` paints in Bifrost without any _zClass,
|
|
88
|
+
* mirroring zCLI. Apps override by redefining the --color-* variable (the hex
|
|
89
|
+
* is only a fallback) or with a higher-specificity rule. */
|
|
90
|
+
|
|
91
|
+
.zText-primary { color: var(--color-primary, #A2D46E); }
|
|
92
|
+
.zText-secondary { color: var(--color-secondary, #9370DB); }
|
|
93
|
+
.zText-success { color: var(--color-success, #52B788); }
|
|
94
|
+
.zText-info { color: var(--color-info, #5CA9FF); }
|
|
95
|
+
.zText-warning { color: var(--color-warning, #FFB347); }
|
|
96
|
+
.zText-danger { color: var(--color-error, #E63946); }
|
|
97
|
+
.zText-error { color: var(--color-error, #E63946); }
|
|
98
|
+
|
|
99
|
+
/* ─── Inline code chip — zCLI/info palette, overridable via --color-code ───── */
|
|
100
|
+
/* Any inline <code> (not inside a <pre> block) gets a subtle monospace badge.
|
|
101
|
+
* Apps override colour with --color-code; block code is left to zCode/Prism. */
|
|
102
|
+
|
|
103
|
+
code:not(pre code) {
|
|
104
|
+
font-family: 'SF Mono', 'Monaco', 'Courier New', monospace;
|
|
105
|
+
font-size: 0.88em;
|
|
106
|
+
font-weight: 600;
|
|
107
|
+
color: var(--color-code, #5CA9FF);
|
|
108
|
+
background: rgba(92, 169, 255, 0.12);
|
|
109
|
+
border: 1px solid rgba(92, 169, 255, 0.25);
|
|
110
|
+
border-radius: 5px;
|
|
111
|
+
padding: 0.1em 0.4em;
|
|
112
|
+
letter-spacing: -0.01em;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/* ─── Blockquote — zMD `> quote` base, overridable via --color-primary ─────── */
|
|
116
|
+
/* Subtle theme-tinted background (color-mix) so it sits right on light AND dark
|
|
117
|
+
* surfaces — no hardcoded grey. Apps restyle by redefining --color-primary or
|
|
118
|
+
* with a higher-specificity rule. */
|
|
119
|
+
|
|
120
|
+
blockquote {
|
|
121
|
+
margin: 0.75rem 0;
|
|
122
|
+
padding: 0.5rem 1rem;
|
|
123
|
+
border-left: 4px solid var(--color-primary, #A2D46E);
|
|
124
|
+
background: color-mix(in srgb, var(--color-primary, #A2D46E) 8%, transparent);
|
|
125
|
+
border-radius: 0 6px 6px 0;
|
|
126
|
+
color: inherit;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
blockquote > p { margin: 0; }
|
|
130
|
+
|
|
131
|
+
/* ─── Form controls — canonical field base (Bootstrap-like) ────────────────── */
|
|
132
|
+
/* The client emits a real field as `.zForm-control` (default) or `.zInput`
|
|
133
|
+
* (input-groups / explicit). Style BOTH so a field on ANY page — not just
|
|
134
|
+
* dashboards — gets a proper look instead of the raw browser white box.
|
|
135
|
+
* `.zInput` is element-qualified so a wrapper div carrying `_zClass: zInput`
|
|
136
|
+
* is NOT mistaken for the field. Override via --zinput-* or an app rule. */
|
|
137
|
+
|
|
138
|
+
.zForm-control,
|
|
139
|
+
input.zInput, textarea.zInput, select.zInput {
|
|
140
|
+
appearance: none;
|
|
141
|
+
-webkit-appearance: none;
|
|
142
|
+
display: block;
|
|
143
|
+
width: 100%;
|
|
144
|
+
box-sizing: border-box;
|
|
145
|
+
padding: 0.55rem 0.85rem;
|
|
146
|
+
font-family: inherit;
|
|
147
|
+
font-size: 0.95rem;
|
|
148
|
+
line-height: 1.5;
|
|
149
|
+
color: var(--zinput-color, #e2e8f0);
|
|
150
|
+
background: var(--zinput-bg, rgba(255, 255, 255, 0.14));
|
|
151
|
+
border: 1.5px solid var(--zinput-border, rgba(255, 255, 255, 0.18));
|
|
152
|
+
border-radius: var(--zinput-radius, 10px);
|
|
153
|
+
transition: border-color 0.18s, background 0.18s, box-shadow 0.18s;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.zForm-control::placeholder,
|
|
157
|
+
.zInput::placeholder { color: var(--zinput-placeholder, rgba(156, 163, 175, 0.5)); }
|
|
158
|
+
|
|
159
|
+
.zForm-control:focus,
|
|
160
|
+
input.zInput:focus, textarea.zInput:focus, select.zInput:focus {
|
|
161
|
+
outline: none;
|
|
162
|
+
border-color: var(--zinput-focus, var(--color-primary, #6366f1));
|
|
163
|
+
background: var(--zinput-bg-focus, rgba(255, 255, 255, 0.17));
|
|
164
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--zinput-focus, var(--color-primary, #6366f1)) 20%, transparent);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.zForm-control:disabled, .zForm-control[readonly],
|
|
168
|
+
input.zInput:disabled, input.zInput[readonly] { opacity: 0.55; cursor: not-allowed; }
|
|
169
|
+
|
|
170
|
+
textarea.zForm-control, textarea.zInput { min-height: 6rem; resize: vertical; }
|
|
171
|
+
select.zForm-control, select.zInput { cursor: pointer; }
|
|
172
|
+
|
|
173
|
+
/* size + type variants */
|
|
174
|
+
.zForm-control.zInput-sm, .zInput-sm { padding: 0.32rem 0.6rem; font-size: 0.82rem; }
|
|
175
|
+
.zForm-control.zInput-color, .zInput-color { width: 3.25rem; height: 2.6rem; padding: 0.25rem; cursor: pointer; }
|
|
176
|
+
|
|
177
|
+
/* field label rendered above an input */
|
|
178
|
+
.zLabel {
|
|
179
|
+
display: block;
|
|
180
|
+
margin-bottom: 0.2rem;
|
|
181
|
+
font-size: 0.85rem;
|
|
182
|
+
font-weight: 500;
|
|
183
|
+
color: var(--zlabel-color, inherit);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/* The input handler emits a <br> after each label; suppress it so the gap is
|
|
187
|
+
controlled purely by .zLabel margin-bottom and the field hugs its label. */
|
|
188
|
+
.zLabel + br { display: none; }
|
|
189
|
+
|
|
190
|
+
/* Required-field marker — red asterisk suffix on the label (SSOT). */
|
|
191
|
+
.zRequired {
|
|
192
|
+
color: var(--zrequired-color, #ef4444);
|
|
193
|
+
margin-left: 0.15rem;
|
|
194
|
+
font-weight: 600;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/* File selector — native file inputs (emitted as .zForm-control) styled to match
|
|
198
|
+
the theme: muted "no file" text + an indigo pill for the browse button. */
|
|
199
|
+
input[type="file"].zForm-control,
|
|
200
|
+
input[type="file"].zInput {
|
|
201
|
+
display: block;
|
|
202
|
+
width: 100%;
|
|
203
|
+
padding: 0.5rem 0.65rem;
|
|
204
|
+
font-size: 0.9375rem;
|
|
205
|
+
color: var(--zinput-placeholder, rgba(156, 163, 175, 0.85));
|
|
206
|
+
line-height: 1.6;
|
|
207
|
+
cursor: pointer;
|
|
208
|
+
}
|
|
209
|
+
input[type="file"].zForm-control::file-selector-button,
|
|
210
|
+
input[type="file"].zInput::file-selector-button {
|
|
211
|
+
margin-right: 0.85rem;
|
|
212
|
+
padding: 0.45rem 1rem;
|
|
213
|
+
border: 0;
|
|
214
|
+
border-radius: 8px;
|
|
215
|
+
background: var(--zinput-accent, #4f46e5);
|
|
216
|
+
color: #fff;
|
|
217
|
+
font-family: inherit;
|
|
218
|
+
font-size: 0.85rem;
|
|
219
|
+
font-weight: 600;
|
|
220
|
+
cursor: pointer;
|
|
221
|
+
transition: filter 0.15s ease, transform 0.05s ease;
|
|
222
|
+
}
|
|
223
|
+
input[type="file"].zForm-control::file-selector-button:hover,
|
|
224
|
+
input[type="file"].zInput::file-selector-button:hover {
|
|
225
|
+
filter: brightness(1.12);
|
|
226
|
+
}
|
|
227
|
+
input[type="file"].zForm-control::file-selector-button:active,
|
|
228
|
+
input[type="file"].zInput::file-selector-button:active {
|
|
229
|
+
transform: translateY(1px);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/* Color picker — native color inputs stretch full-width; render as a compact
|
|
233
|
+
rounded swatch with a themed frame (SSOT). */
|
|
234
|
+
input[type="color"].zForm-control,
|
|
235
|
+
input[type="color"].zInput {
|
|
236
|
+
-webkit-appearance: none;
|
|
237
|
+
appearance: none;
|
|
238
|
+
width: 3.5rem;
|
|
239
|
+
height: 2.5rem;
|
|
240
|
+
padding: 4px;
|
|
241
|
+
cursor: pointer;
|
|
242
|
+
}
|
|
243
|
+
input[type="color"].zForm-control:hover,
|
|
244
|
+
input[type="color"].zInput:hover {
|
|
245
|
+
border-color: var(--zinput-border-hover, rgba(255, 255, 255, 0.3));
|
|
246
|
+
}
|
|
247
|
+
input[type="color"].zForm-control::-webkit-color-swatch-wrapper,
|
|
248
|
+
input[type="color"].zInput::-webkit-color-swatch-wrapper { padding: 0; }
|
|
249
|
+
input[type="color"].zForm-control::-webkit-color-swatch,
|
|
250
|
+
input[type="color"].zInput::-webkit-color-swatch {
|
|
251
|
+
border: none;
|
|
252
|
+
border-radius: 6px;
|
|
253
|
+
}
|
|
254
|
+
input[type="color"].zForm-control::-moz-color-swatch,
|
|
255
|
+
input[type="color"].zInput::-moz-color-swatch {
|
|
256
|
+
border: none;
|
|
257
|
+
border-radius: 6px;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/* Date / time — fields already inherit .zForm-control styling; this only makes
|
|
261
|
+
the native calendar/clock picker indicator legible on dark themes (SSOT). */
|
|
262
|
+
input[type="date"].zForm-control::-webkit-calendar-picker-indicator,
|
|
263
|
+
input[type="time"].zForm-control::-webkit-calendar-picker-indicator,
|
|
264
|
+
input[type="datetime-local"].zForm-control::-webkit-calendar-picker-indicator,
|
|
265
|
+
input[type="month"].zForm-control::-webkit-calendar-picker-indicator,
|
|
266
|
+
input[type="week"].zForm-control::-webkit-calendar-picker-indicator,
|
|
267
|
+
input[type="date"].zInput::-webkit-calendar-picker-indicator,
|
|
268
|
+
input[type="time"].zInput::-webkit-calendar-picker-indicator,
|
|
269
|
+
input[type="datetime-local"].zInput::-webkit-calendar-picker-indicator {
|
|
270
|
+
filter: var(--zinput-picker-filter, invert(0.85));
|
|
271
|
+
opacity: 0.75;
|
|
272
|
+
cursor: pointer;
|
|
273
|
+
}
|
|
274
|
+
input[type="date"].zForm-control::-webkit-calendar-picker-indicator:hover,
|
|
275
|
+
input[type="time"].zForm-control::-webkit-calendar-picker-indicator:hover,
|
|
276
|
+
input[type="datetime-local"].zForm-control::-webkit-calendar-picker-indicator:hover {
|
|
277
|
+
opacity: 1;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/* input-group affix chips (prefix / suffix) */
|
|
281
|
+
.zInputGroup > .zInputGroup-text {
|
|
282
|
+
display: flex;
|
|
283
|
+
align-items: center;
|
|
284
|
+
padding: 0.55rem 0.85rem;
|
|
285
|
+
font-size: 0.95rem;
|
|
286
|
+
color: var(--zinput-color, #e2e8f0);
|
|
287
|
+
background: var(--zinput-affix-bg, rgba(79, 70, 229, 0.14));
|
|
288
|
+
border: 1.5px solid var(--zinput-border, rgba(255, 255, 255, 0.14));
|
|
289
|
+
white-space: nowrap;
|
|
290
|
+
}
|
|
291
|
+
.zInputGroup > .zInputGroup-text:first-child { border-radius: 10px 0 0 10px; border-right: 0; }
|
|
292
|
+
.zInputGroup > .zInputGroup-text:last-child { border-radius: 0 10px 10px 0; border-left: 0; }
|
|
293
|
+
.zInputGroup > .zForm-control:not(:first-child),
|
|
294
|
+
.zInputGroup > .zInput:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; }
|
|
295
|
+
.zInputGroup > .zForm-control:not(:last-child),
|
|
296
|
+
.zInputGroup > .zInput:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; }
|
|
297
|
+
|
|
298
|
+
/* ─── Checkbox / radio — canonical control base (matches .zForm-control) ───── */
|
|
299
|
+
/* The client emits `zCheckbox` / `zSelect` (radio) as a `.zForm-check` row:
|
|
300
|
+
* <div class="zForm-check"><input class="zForm-check-input"><label class="zForm-check-label">
|
|
301
|
+
* Style the box by element type (so an app's `_zClass` override on the input
|
|
302
|
+
* doesn't strip the look) and theme it via --color-primary, like buttons/fields. */
|
|
303
|
+
|
|
304
|
+
.zForm-check {
|
|
305
|
+
display: flex;
|
|
306
|
+
align-items: center;
|
|
307
|
+
gap: 0.5rem;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.zForm-check input[type="checkbox"],
|
|
311
|
+
.zForm-check input[type="radio"],
|
|
312
|
+
.zForm-check-input {
|
|
313
|
+
appearance: none;
|
|
314
|
+
-webkit-appearance: none;
|
|
315
|
+
flex: 0 0 auto;
|
|
316
|
+
width: 1.15rem;
|
|
317
|
+
height: 1.15rem;
|
|
318
|
+
margin: 0;
|
|
319
|
+
display: inline-grid;
|
|
320
|
+
place-content: center;
|
|
321
|
+
background: var(--zinput-bg, rgba(255, 255, 255, 0.14));
|
|
322
|
+
border: 1.5px solid var(--zinput-border, rgba(255, 255, 255, 0.3));
|
|
323
|
+
cursor: pointer;
|
|
324
|
+
transition: border-color 0.18s, background 0.18s, box-shadow 0.18s;
|
|
325
|
+
}
|
|
326
|
+
.zForm-check input[type="checkbox"],
|
|
327
|
+
.zForm-check-input { border-radius: var(--zcheck-radius, 5px); }
|
|
328
|
+
.zForm-check input[type="radio"] { border-radius: 50%; position: relative; }
|
|
329
|
+
|
|
330
|
+
/* checked fill — theme primary */
|
|
331
|
+
.zForm-check input[type="checkbox"]:checked,
|
|
332
|
+
.zForm-check input[type="radio"]:checked,
|
|
333
|
+
.zForm-check-input:checked {
|
|
334
|
+
background: var(--zinput-focus, var(--color-primary, #6366f1));
|
|
335
|
+
border-color: var(--zinput-focus, var(--color-primary, #6366f1));
|
|
336
|
+
}
|
|
337
|
+
/* checkmark glyph */
|
|
338
|
+
.zForm-check input[type="checkbox"]:checked::after,
|
|
339
|
+
.zForm-check-input:checked::after {
|
|
340
|
+
content: "";
|
|
341
|
+
width: 0.32rem;
|
|
342
|
+
height: 0.6rem;
|
|
343
|
+
border: solid #fff;
|
|
344
|
+
border-width: 0 2px 2px 0;
|
|
345
|
+
transform: rotate(45deg) translate(-1px, -1px);
|
|
346
|
+
}
|
|
347
|
+
/* radio dot — absolutely centered (grid place-content is sub-pixel off on a circle) */
|
|
348
|
+
.zForm-check input[type="radio"]:checked::after {
|
|
349
|
+
content: "";
|
|
350
|
+
position: absolute;
|
|
351
|
+
top: 50%;
|
|
352
|
+
left: 50%;
|
|
353
|
+
transform: translate(-50%, -50%);
|
|
354
|
+
width: 0.45rem;
|
|
355
|
+
height: 0.45rem;
|
|
356
|
+
border-radius: 50%;
|
|
357
|
+
background: #fff;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.zForm-check input[type="checkbox"]:focus-visible,
|
|
361
|
+
.zForm-check input[type="radio"]:focus-visible,
|
|
362
|
+
.zForm-check-input:focus-visible {
|
|
363
|
+
outline: none;
|
|
364
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--zinput-focus, var(--color-primary, #6366f1)) 30%, transparent);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.zForm-check-label {
|
|
368
|
+
cursor: pointer;
|
|
369
|
+
font-size: 0.95rem;
|
|
370
|
+
line-height: 1.4;
|
|
371
|
+
color: inherit;
|
|
372
|
+
user-select: none;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/* disabled — dim box AND label, block interaction (SSOT) */
|
|
376
|
+
.zForm-check input:disabled,
|
|
377
|
+
.zForm-check-input:disabled { opacity: 0.55; cursor: not-allowed; }
|
|
378
|
+
.zForm-check-disabled { opacity: 0.6; }
|
|
379
|
+
.zForm-check-disabled .zForm-check-label { cursor: not-allowed; }
|
|
380
|
+
|
|
381
|
+
/* native radios/checkboxes NOT given the custom .zForm-check treatment
|
|
382
|
+
* still pick up the theme color (belt-and-braces — groups now emit .zForm-check). */
|
|
383
|
+
input[type="radio"], input[type="checkbox"] { accent-color: var(--color-primary, #6366f1); }
|
|
384
|
+
|
|
385
|
+
/* radio / checkbox group (zSelect type:radio|checkbox) — legend + row rhythm */
|
|
386
|
+
.zForm-check-group .zLabel { margin-bottom: 0.45rem; }
|
|
387
|
+
|
|
388
|
+
/* ─── Select / dropdown — canonical control (matches .zForm-control) ───────── */
|
|
389
|
+
/* The client emits `zSelect` as a native <select class="zSelect">. Give it the
|
|
390
|
+
* same field look as text inputs plus a themed caret. Element-qualified so a
|
|
391
|
+
* wrapper carrying `_zClass: zSelect` is NOT mistaken for the control. */
|
|
392
|
+
|
|
393
|
+
select.zSelect,
|
|
394
|
+
select.zForm-control,
|
|
395
|
+
select.zInput {
|
|
396
|
+
appearance: none;
|
|
397
|
+
-webkit-appearance: none;
|
|
398
|
+
display: block;
|
|
399
|
+
width: 100%;
|
|
400
|
+
box-sizing: border-box;
|
|
401
|
+
padding: 0.55rem 2.25rem 0.55rem 0.85rem;
|
|
402
|
+
font-family: inherit;
|
|
403
|
+
font-size: 0.95rem;
|
|
404
|
+
line-height: 1.5;
|
|
405
|
+
color: var(--zinput-color, #e2e8f0);
|
|
406
|
+
background-color: var(--zinput-bg, rgba(255, 255, 255, 0.14));
|
|
407
|
+
border: 1.5px solid var(--zinput-border, rgba(255, 255, 255, 0.18));
|
|
408
|
+
border-radius: var(--zinput-radius, 10px);
|
|
409
|
+
cursor: pointer;
|
|
410
|
+
transition: border-color 0.18s, background 0.18s, box-shadow 0.18s;
|
|
411
|
+
/* themed chevron caret (no external asset) */
|
|
412
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%239ca3af' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
|
|
413
|
+
background-repeat: no-repeat;
|
|
414
|
+
background-position: right 0.75rem center;
|
|
415
|
+
background-size: 1rem;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
select.zSelect:focus,
|
|
419
|
+
select.zForm-control:focus,
|
|
420
|
+
select.zInput:focus {
|
|
421
|
+
outline: none;
|
|
422
|
+
border-color: var(--zinput-focus, var(--color-primary, #6366f1));
|
|
423
|
+
background-color: var(--zinput-bg-focus, rgba(255, 255, 255, 0.17));
|
|
424
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--zinput-focus, var(--color-primary, #6366f1)) 20%, transparent);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
select.zSelect:disabled,
|
|
428
|
+
select.zForm-control:disabled,
|
|
429
|
+
select.zInput:disabled { opacity: 0.55; cursor: not-allowed; }
|
|
430
|
+
|
|
431
|
+
/* native option popup — keep legible regardless of page theme */
|
|
432
|
+
select.zSelect option,
|
|
433
|
+
select.zForm-control option,
|
|
434
|
+
select.zInput option { color: #1f2937; background: #fff; }
|
|
435
|
+
select.zSelect option:disabled,
|
|
436
|
+
select.zForm-control option:disabled { color: #9ca3af; }
|
|
437
|
+
|
|
438
|
+
/* multi-select / sized list box — themed box, no caret, themed inline options */
|
|
439
|
+
select.zSelect[multiple],
|
|
440
|
+
select.zSelect[size],
|
|
441
|
+
select.zForm-control[multiple] {
|
|
442
|
+
padding: 0.4rem;
|
|
443
|
+
height: auto;
|
|
444
|
+
min-height: 0;
|
|
445
|
+
background-image: none;
|
|
446
|
+
}
|
|
447
|
+
select.zSelect[multiple] option,
|
|
448
|
+
select.zSelect[size] option,
|
|
449
|
+
select.zForm-control[multiple] option {
|
|
450
|
+
color: var(--zinput-color, #e2e8f0);
|
|
451
|
+
background: transparent;
|
|
452
|
+
padding: 0.35rem 0.55rem;
|
|
453
|
+
border-radius: 6px;
|
|
454
|
+
margin-bottom: 1px;
|
|
455
|
+
}
|
|
456
|
+
/* selected rows — gradient hack forces the highlight color in Chromium */
|
|
457
|
+
select.zSelect[multiple] option:checked,
|
|
458
|
+
select.zSelect[size] option:checked,
|
|
459
|
+
select.zForm-control[multiple] option:checked {
|
|
460
|
+
color: #fff;
|
|
461
|
+
background: linear-gradient(var(--color-primary, #6366f1), var(--color-primary, #6366f1));
|
|
462
|
+
}
|
|
463
|
+
select.zSelect[multiple] option:disabled,
|
|
464
|
+
select.zForm-control[multiple] option:disabled { color: var(--zinput-placeholder, rgba(156, 163, 175, 0.55)); }
|
|
465
|
+
|
|
466
|
+
/* size variants */
|
|
467
|
+
select.zSelect.zSelect-lg { padding-top: 0.7rem; padding-bottom: 0.7rem; font-size: 1.05rem; }
|
|
468
|
+
select.zSelect.zSelect-sm { padding-top: 0.35rem; padding-bottom: 0.35rem; font-size: 0.82rem; }
|
|
469
|
+
|
|
470
|
+
zBifrostBadge {
|
|
471
|
+
position: fixed;
|
|
472
|
+
bottom: 1rem;
|
|
473
|
+
right: 1rem;
|
|
474
|
+
z-index: 9999;
|
|
475
|
+
pointer-events: none;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/* ─── zBifrostBadge states ─────────────────────────────────────────────────── */
|
|
479
|
+
|
|
480
|
+
.zBadge-pending { color: #fbbf24; }
|
|
481
|
+
.zBadge-success { color: #34d399; }
|
|
482
|
+
.zBadge-error { color: #f87171; }
|
|
483
|
+
.zBadge-dot { border-radius: 50%; background: currentColor; }
|
|
484
|
+
.zIcon { display: inline-block; width: 0.75em; height: 0.75em; fill: currentColor; }
|
|
485
|
+
|
|
486
|
+
/* ─── zVaF content host ─────────────────────────────────────────────────────── */
|
|
487
|
+
/* The re-rendered subtree under the <zVaF> root. Chrome (navbar/badge/errors) are
|
|
488
|
+
* its siblings inside the root, so clearing this node never destroys them. */
|
|
489
|
+
.zVaF-content { display: block; }
|
|
490
|
+
|
|
491
|
+
/* ─── Error toasts — bifrost-owned fixed-corner container (was inline styles) ── */
|
|
492
|
+
.bifrost-error-container {
|
|
493
|
+
position: fixed;
|
|
494
|
+
z-index: 10000;
|
|
495
|
+
max-width: 400px;
|
|
496
|
+
pointer-events: none;
|
|
497
|
+
}
|
|
498
|
+
.bifrost-error-container--top-right { top: 1rem; right: 1rem; }
|
|
499
|
+
.bifrost-error-container--top-left { top: 1rem; left: 1rem; }
|
|
500
|
+
.bifrost-error-container--bottom-right { bottom: 1rem; right: 1rem; }
|
|
501
|
+
.bifrost-error-container--bottom-left { bottom: 1rem; left: 1rem; }
|
|
502
|
+
|
|
503
|
+
/* ─── zNavBar — Bifrost-owned default chrome (token-driven) ─────────────────── */
|
|
504
|
+
/* Structure + a sensible dark visual default. Apps re-skin via --znav-* vars or
|
|
505
|
+
* a higher-specificity rule — no need to re-declare the whole navbar per app. */
|
|
506
|
+
|
|
507
|
+
zNavBar {
|
|
508
|
+
position: sticky;
|
|
509
|
+
top: 0;
|
|
510
|
+
z-index: 1000;
|
|
511
|
+
display: block;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
zNavBar .zNavbar {
|
|
515
|
+
display: flex;
|
|
516
|
+
align-items: center;
|
|
517
|
+
flex-wrap: wrap;
|
|
518
|
+
padding: 0.75rem 1.5rem;
|
|
519
|
+
background: var(--znav-bg, rgba(10, 14, 39, 0.92));
|
|
520
|
+
border-bottom: 1px solid var(--znav-border, rgba(79, 70, 229, 0.15));
|
|
521
|
+
backdrop-filter: blur(12px);
|
|
522
|
+
font-family: var(--znav-font, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
zNavBar .zNavbar-brand {
|
|
526
|
+
font-size: 1.15rem;
|
|
527
|
+
font-weight: 800;
|
|
528
|
+
letter-spacing: -0.02em;
|
|
529
|
+
margin-right: 2rem;
|
|
530
|
+
color: var(--znav-brand-color, #f9fafb);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
zNavBar .zNavbar-toggler {
|
|
534
|
+
display: none;
|
|
535
|
+
margin-left: auto;
|
|
536
|
+
padding: 0.4rem 0.6rem;
|
|
537
|
+
font-size: 1.1rem;
|
|
538
|
+
line-height: 1;
|
|
539
|
+
cursor: pointer;
|
|
540
|
+
color: var(--znav-brand-color, #f9fafb);
|
|
541
|
+
background: var(--znav-link-hover-bg, rgba(79, 70, 229, 0.15));
|
|
542
|
+
border: 1px solid var(--znav-border, rgba(79, 70, 229, 0.3));
|
|
543
|
+
border-radius: 6px;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
zNavBar .zNavbar-collapse {
|
|
547
|
+
display: flex;
|
|
548
|
+
align-items: center;
|
|
549
|
+
flex: 1;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
zNavBar .zNavbar-nav {
|
|
553
|
+
display: flex;
|
|
554
|
+
align-items: center;
|
|
555
|
+
gap: 0.25rem;
|
|
556
|
+
list-style: none;
|
|
557
|
+
margin: 0;
|
|
558
|
+
padding: 0;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
zNavBar .zNav-item { position: relative; }
|
|
562
|
+
|
|
563
|
+
zNavBar .zNav-link {
|
|
564
|
+
display: block;
|
|
565
|
+
padding: 0.45rem 0.85rem;
|
|
566
|
+
font-size: 0.9rem;
|
|
567
|
+
font-weight: 500;
|
|
568
|
+
border-radius: 8px;
|
|
569
|
+
color: var(--znav-link-color, #d1d5db);
|
|
570
|
+
transition: color 0.2s, background 0.2s;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
zNavBar .zNav-link:hover,
|
|
574
|
+
zNavBar .zNav-link.active {
|
|
575
|
+
color: var(--znav-link-hover-color, #f9fafb);
|
|
576
|
+
background: var(--znav-link-hover-bg, rgba(79, 70, 229, 0.15));
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/* ─── zDropdown (navbar menus) — JS toggles .zShow ─────────────────────────── */
|
|
580
|
+
|
|
581
|
+
.zDropdown-menu {
|
|
582
|
+
display: none;
|
|
583
|
+
position: absolute;
|
|
584
|
+
top: calc(100% + 0.5rem);
|
|
585
|
+
left: 0;
|
|
586
|
+
z-index: 100;
|
|
587
|
+
min-width: 11rem;
|
|
588
|
+
padding: 0.4rem 0;
|
|
589
|
+
background: var(--zdropdown-bg, rgba(20, 25, 45, 0.97));
|
|
590
|
+
border: 1px solid var(--znav-border, rgba(79, 70, 229, 0.25));
|
|
591
|
+
border-radius: 10px;
|
|
592
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
593
|
+
backdrop-filter: blur(12px);
|
|
594
|
+
}
|
|
595
|
+
.zDropdown-menu.zShow { display: block; }
|
|
596
|
+
|
|
597
|
+
.zDropdown-item {
|
|
598
|
+
display: block;
|
|
599
|
+
padding: 0.5rem 1rem;
|
|
600
|
+
font-size: 0.875rem;
|
|
601
|
+
color: var(--znav-link-color, #d1d5db);
|
|
602
|
+
transition: color 0.15s, background 0.15s;
|
|
603
|
+
}
|
|
604
|
+
.zDropdown-item:hover {
|
|
605
|
+
color: var(--znav-link-hover-color, #f9fafb);
|
|
606
|
+
background: var(--znav-link-hover-bg, rgba(79, 70, 229, 0.15));
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/* ─── zNavbar-inblock — light, in-content navbar variant ────────────────────────
|
|
610
|
+
The chrome navbar above is scoped to the <zNavBar> element. A BLOCK-LEVEL
|
|
611
|
+
navbar (rendered inline via the navbar_inline event — e.g. an in-page zPsi
|
|
612
|
+
table-of-contents) lives in normal page content, NOT inside <zNavBar>, so it
|
|
613
|
+
inherits none of those rules. This variant re-states the same structure with a
|
|
614
|
+
LIGHT surface (the chrome is dark). Token-driven (--znavl-*) so a future
|
|
615
|
+
`color:` property can flip the palette without touching markup. */
|
|
616
|
+
|
|
617
|
+
.zNavbar-inblock {
|
|
618
|
+
display: flex;
|
|
619
|
+
align-items: center;
|
|
620
|
+
flex-wrap: wrap;
|
|
621
|
+
padding: 0.75rem 1.5rem; /* mirror the global bar's proportions */
|
|
622
|
+
border-radius: 10px; /* embedded in a card → rounded, not full-bleed */
|
|
623
|
+
background: var(--znavl-bg, #ffffff);
|
|
624
|
+
border: 1px solid var(--znavl-border, rgba(15, 20, 48, 0.12));
|
|
625
|
+
box-shadow: 0 1px 2px rgba(15, 20, 48, 0.04);
|
|
626
|
+
font-family: var(--znav-font, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
/* In-content TOC: always expanded, no hamburger. */
|
|
630
|
+
.zNavbar-inblock .zNavbar-toggler { display: none; }
|
|
631
|
+
|
|
632
|
+
.zNavbar-inblock .zNavbar-collapse {
|
|
633
|
+
display: flex;
|
|
634
|
+
align-items: center;
|
|
635
|
+
flex: 1;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
.zNavbar-inblock .zNavbar-nav {
|
|
639
|
+
display: flex;
|
|
640
|
+
align-items: center; /* one row, baseline-aligned — mirror global bar */
|
|
641
|
+
gap: 0.25rem;
|
|
642
|
+
margin: 0;
|
|
643
|
+
padding: 0;
|
|
644
|
+
list-style: none;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/* Immune to host prose list styling: an inblock bar can be embedded inside
|
|
648
|
+
arbitrary content (e.g. a .zCallout whose `li { margin: 0 0 .5rem }` +
|
|
649
|
+
`li:last-child { margin-bottom: 0 }` would drop the last item off-baseline). */
|
|
650
|
+
.zNavbar-inblock .zNav-item { position: relative; margin: 0; line-height: 1; }
|
|
651
|
+
|
|
652
|
+
.zNavbar-inblock .zNav-link {
|
|
653
|
+
display: block;
|
|
654
|
+
padding: 0.45rem 0.85rem; /* mirror global .zNav-link */
|
|
655
|
+
font-size: 0.9rem;
|
|
656
|
+
font-weight: 500;
|
|
657
|
+
border-radius: 8px;
|
|
658
|
+
color: var(--znavl-link, #2a2f45);
|
|
659
|
+
transition: color 0.2s, background 0.2s;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
.zNavbar-inblock .zNav-link:hover,
|
|
663
|
+
.zNavbar-inblock .zNav-link.active {
|
|
664
|
+
color: var(--znavl-link-hover, #0b1020);
|
|
665
|
+
background: var(--znavl-link-hover-bg, rgba(15, 20, 48, 0.07));
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/* Light dropdown (if a block-level bar uses zSub) — overrides the dark default. */
|
|
669
|
+
.zNavbar-inblock .zDropdown-menu {
|
|
670
|
+
background: var(--znavl-dropdown-bg, #ffffff);
|
|
671
|
+
border: 1px solid var(--znavl-border, rgba(15, 20, 48, 0.12));
|
|
672
|
+
box-shadow: 0 8px 24px rgba(15, 20, 48, 0.12);
|
|
673
|
+
}
|
|
674
|
+
.zNavbar-inblock .zDropdown-item { color: var(--znavl-link, #2a2f45); }
|
|
675
|
+
.zNavbar-inblock .zDropdown-item:hover {
|
|
676
|
+
color: var(--znavl-link-hover, #0b1020);
|
|
677
|
+
background: var(--znavl-link-hover-bg, rgba(15, 20, 48, 0.07));
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
/* ─── Mobile hamburger ─────────────────────────────────────────────────────── */
|
|
681
|
+
|
|
682
|
+
@media (max-width: 768px) {
|
|
683
|
+
zNavBar .zNavbar-toggler { display: block; }
|
|
684
|
+
zNavBar .zNavbar-collapse {
|
|
685
|
+
flex-basis: 100%;
|
|
686
|
+
flex-direction: column;
|
|
687
|
+
align-items: flex-start;
|
|
688
|
+
}
|
|
689
|
+
zNavBar .zNavbar-collapse:not(.zShow) { display: none; }
|
|
690
|
+
zNavBar .zNavbar-collapse.zShow { display: flex; padding: 0.5rem 0 0.75rem; }
|
|
691
|
+
zNavBar .zNavbar-nav { flex-direction: column; width: 100%; gap: 0; }
|
|
692
|
+
zNavBar .zNav-link { width: 100%; }
|
|
693
|
+
.zDropdown-menu {
|
|
694
|
+
position: static;
|
|
695
|
+
box-shadow: none;
|
|
696
|
+
border: none;
|
|
697
|
+
border-radius: 0;
|
|
698
|
+
padding-left: 0.75rem;
|
|
699
|
+
background: var(--znav-link-hover-bg, rgba(79, 70, 229, 0.08));
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
/* ─── 2. Grid ──────────────────────────────────────────────────────────────── */
|
|
704
|
+
|
|
705
|
+
.zRow {
|
|
706
|
+
display: flex;
|
|
707
|
+
flex-wrap: wrap;
|
|
708
|
+
margin-right: calc(0.75rem * -1);
|
|
709
|
+
margin-left: calc(0.75rem * -1);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
[class*="zCol"] {
|
|
713
|
+
position: relative;
|
|
714
|
+
width: 100%;
|
|
715
|
+
padding-right: 0.75rem;
|
|
716
|
+
padding-left: 0.75rem;
|
|
717
|
+
flex-shrink: 0;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
.zCol { flex: 1 0 0%; }
|
|
721
|
+
.zCol-auto { flex: 0 0 auto; width: auto; }
|
|
722
|
+
|
|
723
|
+
.zCol-1 { flex: 0 0 auto; width: 8.33333333%; }
|
|
724
|
+
.zCol-2 { flex: 0 0 auto; width: 16.66666667%; }
|
|
725
|
+
.zCol-3 { flex: 0 0 auto; width: 25%; }
|
|
726
|
+
.zCol-4 { flex: 0 0 auto; width: 33.33333333%; }
|
|
727
|
+
.zCol-5 { flex: 0 0 auto; width: 41.66666667%; }
|
|
728
|
+
.zCol-6 { flex: 0 0 auto; width: 50%; }
|
|
729
|
+
.zCol-7 { flex: 0 0 auto; width: 58.33333333%; }
|
|
730
|
+
.zCol-8 { flex: 0 0 auto; width: 66.66666667%; }
|
|
731
|
+
.zCol-9 { flex: 0 0 auto; width: 75%; }
|
|
732
|
+
.zCol-10 { flex: 0 0 auto; width: 83.33333333%; }
|
|
733
|
+
.zCol-11 { flex: 0 0 auto; width: 91.66666667%; }
|
|
734
|
+
.zCol-12 { flex: 0 0 auto; width: 100%; }
|
|
735
|
+
|
|
736
|
+
@media (min-width: 576px) {
|
|
737
|
+
.zCol-sm { flex: 1 0 0%; }
|
|
738
|
+
.zCol-sm-auto { flex: 0 0 auto; width: auto; }
|
|
739
|
+
.zCol-sm-1 { flex: 0 0 auto; width: 8.33333333%; }
|
|
740
|
+
.zCol-sm-2 { flex: 0 0 auto; width: 16.66666667%; }
|
|
741
|
+
.zCol-sm-3 { flex: 0 0 auto; width: 25%; }
|
|
742
|
+
.zCol-sm-4 { flex: 0 0 auto; width: 33.33333333%; }
|
|
743
|
+
.zCol-sm-5 { flex: 0 0 auto; width: 41.66666667%; }
|
|
744
|
+
.zCol-sm-6 { flex: 0 0 auto; width: 50%; }
|
|
745
|
+
.zCol-sm-7 { flex: 0 0 auto; width: 58.33333333%; }
|
|
746
|
+
.zCol-sm-8 { flex: 0 0 auto; width: 66.66666667%; }
|
|
747
|
+
.zCol-sm-9 { flex: 0 0 auto; width: 75%; }
|
|
748
|
+
.zCol-sm-10 { flex: 0 0 auto; width: 83.33333333%; }
|
|
749
|
+
.zCol-sm-11 { flex: 0 0 auto; width: 91.66666667%; }
|
|
750
|
+
.zCol-sm-12 { flex: 0 0 auto; width: 100%; }
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
@media (min-width: 768px) {
|
|
754
|
+
.zCol-md { flex: 1 0 0%; }
|
|
755
|
+
.zCol-md-auto { flex: 0 0 auto; width: auto; }
|
|
756
|
+
.zCol-md-1 { flex: 0 0 auto; width: 8.33333333%; }
|
|
757
|
+
.zCol-md-2 { flex: 0 0 auto; width: 16.66666667%; }
|
|
758
|
+
.zCol-md-3 { flex: 0 0 auto; width: 25%; }
|
|
759
|
+
.zCol-md-4 { flex: 0 0 auto; width: 33.33333333%; }
|
|
760
|
+
.zCol-md-5 { flex: 0 0 auto; width: 41.66666667%; }
|
|
761
|
+
.zCol-md-6 { flex: 0 0 auto; width: 50%; }
|
|
762
|
+
.zCol-md-7 { flex: 0 0 auto; width: 58.33333333%; }
|
|
763
|
+
.zCol-md-8 { flex: 0 0 auto; width: 66.66666667%; }
|
|
764
|
+
.zCol-md-9 { flex: 0 0 auto; width: 75%; }
|
|
765
|
+
.zCol-md-10 { flex: 0 0 auto; width: 83.33333333%; }
|
|
766
|
+
.zCol-md-11 { flex: 0 0 auto; width: 91.66666667%; }
|
|
767
|
+
.zCol-md-12 { flex: 0 0 auto; width: 100%; }
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
@media (min-width: 992px) {
|
|
771
|
+
.zCol-lg { flex: 1 0 0%; }
|
|
772
|
+
.zCol-lg-auto { flex: 0 0 auto; width: auto; }
|
|
773
|
+
.zCol-lg-1 { flex: 0 0 auto; width: 8.33333333%; }
|
|
774
|
+
.zCol-lg-2 { flex: 0 0 auto; width: 16.66666667%; }
|
|
775
|
+
.zCol-lg-3 { flex: 0 0 auto; width: 25%; }
|
|
776
|
+
.zCol-lg-4 { flex: 0 0 auto; width: 33.33333333%; }
|
|
777
|
+
.zCol-lg-5 { flex: 0 0 auto; width: 41.66666667%; }
|
|
778
|
+
.zCol-lg-6 { flex: 0 0 auto; width: 50%; }
|
|
779
|
+
.zCol-lg-7 { flex: 0 0 auto; width: 58.33333333%; }
|
|
780
|
+
.zCol-lg-8 { flex: 0 0 auto; width: 66.66666667%; }
|
|
781
|
+
.zCol-lg-9 { flex: 0 0 auto; width: 75%; }
|
|
782
|
+
.zCol-lg-10 { flex: 0 0 auto; width: 83.33333333%; }
|
|
783
|
+
.zCol-lg-11 { flex: 0 0 auto; width: 91.66666667%; }
|
|
784
|
+
.zCol-lg-12 { flex: 0 0 auto; width: 100%; }
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
@media (min-width: 1200px) {
|
|
788
|
+
.zCol-xl { flex: 1 0 0%; }
|
|
789
|
+
.zCol-xl-auto { flex: 0 0 auto; width: auto; }
|
|
790
|
+
.zCol-xl-1 { flex: 0 0 auto; width: 8.33333333%; }
|
|
791
|
+
.zCol-xl-2 { flex: 0 0 auto; width: 16.66666667%; }
|
|
792
|
+
.zCol-xl-3 { flex: 0 0 auto; width: 25%; }
|
|
793
|
+
.zCol-xl-4 { flex: 0 0 auto; width: 33.33333333%; }
|
|
794
|
+
.zCol-xl-5 { flex: 0 0 auto; width: 41.66666667%; }
|
|
795
|
+
.zCol-xl-6 { flex: 0 0 auto; width: 50%; }
|
|
796
|
+
.zCol-xl-7 { flex: 0 0 auto; width: 58.33333333%; }
|
|
797
|
+
.zCol-xl-8 { flex: 0 0 auto; width: 66.66666667%; }
|
|
798
|
+
.zCol-xl-9 { flex: 0 0 auto; width: 75%; }
|
|
799
|
+
.zCol-xl-10 { flex: 0 0 auto; width: 83.33333333%; }
|
|
800
|
+
.zCol-xl-11 { flex: 0 0 auto; width: 91.66666667%; }
|
|
801
|
+
.zCol-xl-12 { flex: 0 0 auto; width: 100%; }
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/* ─── 3. Gutters ───────────────────────────────────────────────────────────── */
|
|
805
|
+
|
|
806
|
+
.zRow.zG-0 { margin-right: 0; margin-left: 0; }
|
|
807
|
+
.zRow.zG-0 > [class*="zCol"] { padding-right: 0; padding-left: 0; }
|
|
808
|
+
|
|
809
|
+
.zRow.zG-1 { margin-right: -0.25rem; margin-left: -0.25rem; }
|
|
810
|
+
.zRow.zG-1 > [class*="zCol"] { padding-right: 0.25rem; padding-left: 0.25rem; }
|
|
811
|
+
|
|
812
|
+
.zRow.zG-2 { margin-right: -0.5rem; margin-left: -0.5rem; }
|
|
813
|
+
.zRow.zG-2 > [class*="zCol"] { padding-right: 0.5rem; padding-left: 0.5rem; }
|
|
814
|
+
|
|
815
|
+
.zRow.zG-3 { margin-right: -0.75rem; margin-left: -0.75rem; }
|
|
816
|
+
.zRow.zG-3 > [class*="zCol"] { padding-right: 0.75rem; padding-left: 0.75rem; }
|
|
817
|
+
|
|
818
|
+
.zRow.zG-4 { margin-right: -1rem; margin-left: -1rem; }
|
|
819
|
+
.zRow.zG-4 > [class*="zCol"] { padding-right: 1rem; padding-left: 1rem; }
|
|
820
|
+
|
|
821
|
+
.zRow.zG-5 { margin-right: -1.5rem; margin-left: -1.5rem; }
|
|
822
|
+
.zRow.zG-5 > [class*="zCol"] { padding-right: 1.5rem; padding-left: 1.5rem; }
|
|
823
|
+
|
|
824
|
+
/* ─── 4. Flex utilities ────────────────────────────────────────────────────── */
|
|
825
|
+
|
|
826
|
+
.zFlex-row { flex-direction: row !important; }
|
|
827
|
+
.zFlex-column { flex-direction: column !important; }
|
|
828
|
+
.zFlex-row-reverse { flex-direction: row-reverse !important; }
|
|
829
|
+
.zFlex-column-reverse { flex-direction: column-reverse !important; }
|
|
830
|
+
|
|
831
|
+
.zFlex-wrap { flex-wrap: wrap !important; }
|
|
832
|
+
.zFlex-nowrap { flex-wrap: nowrap !important; }
|
|
833
|
+
|
|
834
|
+
.zFlex-start { justify-content: flex-start !important; }
|
|
835
|
+
.zFlex-end { justify-content: flex-end !important; }
|
|
836
|
+
.zFlex-center { justify-content: center !important; }
|
|
837
|
+
.zFlex-between { justify-content: space-between !important; }
|
|
838
|
+
.zFlex-around { justify-content: space-around !important; }
|
|
839
|
+
.zFlex-evenly { justify-content: space-evenly !important; }
|
|
840
|
+
|
|
841
|
+
.zFlex-items-start { align-items: flex-start !important; }
|
|
842
|
+
.zFlex-items-end { align-items: flex-end !important; }
|
|
843
|
+
.zFlex-items-center { align-items: center !important; }
|
|
844
|
+
.zFlex-items-stretch { align-items: stretch !important; }
|
|
845
|
+
.zFlex-items-baseline { align-items: baseline !important; }
|
|
846
|
+
|
|
847
|
+
.zFlex-fill { flex: 1 1 auto !important; }
|
|
848
|
+
.zFlex-1 { flex: 1 !important; }
|
|
849
|
+
.zFlex-grow-0 { flex-grow: 0 !important; }
|
|
850
|
+
.zFlex-grow-1 { flex-grow: 1 !important; }
|
|
851
|
+
.zFlex-shrink-0 { flex-shrink: 0 !important; }
|
|
852
|
+
.zFlex-shrink-1 { flex-shrink: 1 !important; }
|
|
853
|
+
|
|
854
|
+
.zGap-0 { gap: 0 !important; }
|
|
855
|
+
.zGap-1 { gap: 0.25rem !important; }
|
|
856
|
+
.zGap-2 { gap: 0.5rem !important; }
|
|
857
|
+
.zGap-3 { gap: 0.75rem !important; }
|
|
858
|
+
.zGap-4 { gap: 1rem !important; }
|
|
859
|
+
.zGap-5 { gap: 1.5rem !important; }
|
|
860
|
+
|
|
861
|
+
/* ─── 5. Display helpers ───────────────────────────────────────────────────── */
|
|
862
|
+
|
|
863
|
+
.zD-none { display: none !important; }
|
|
864
|
+
.zD-block { display: block !important; }
|
|
865
|
+
.zD-flex { display: flex !important; }
|
|
866
|
+
.zD-inline { display: inline !important; }
|
|
867
|
+
.zD-inline-block { display: inline-block !important; }
|
|
868
|
+
.zD-inline-flex { display: inline-flex !important; }
|
|
869
|
+
|
|
870
|
+
/* ─── 6. Spacing helpers ───────────────────────────────────────────────────── */
|
|
871
|
+
|
|
872
|
+
.zm-0 { margin: 0 !important; }
|
|
873
|
+
.zm-1 { margin: 0.25rem !important; }
|
|
874
|
+
.zm-2 { margin: 0.5rem !important; }
|
|
875
|
+
.zm-3 { margin: 0.75rem !important; }
|
|
876
|
+
.zm-4 { margin: 1rem !important; }
|
|
877
|
+
.zm-5 { margin: 1.5rem !important; }
|
|
878
|
+
|
|
879
|
+
.zmt-0 { margin-top: 0 !important; }
|
|
880
|
+
.zmt-1 { margin-top: 0.25rem !important; }
|
|
881
|
+
.zmt-2 { margin-top: 0.5rem !important; }
|
|
882
|
+
.zmt-3 { margin-top: 0.75rem !important; }
|
|
883
|
+
.zmt-4 { margin-top: 1rem !important; }
|
|
884
|
+
.zmt-5 { margin-top: 1.5rem !important; }
|
|
885
|
+
|
|
886
|
+
.zmb-0 { margin-bottom: 0 !important; }
|
|
887
|
+
.zmb-1 { margin-bottom: 0.25rem !important; }
|
|
888
|
+
.zmb-2 { margin-bottom: 0.5rem !important; }
|
|
889
|
+
.zmb-3 { margin-bottom: 0.75rem !important; }
|
|
890
|
+
.zmb-4 { margin-bottom: 1rem !important; }
|
|
891
|
+
.zmb-5 { margin-bottom: 1.5rem !important; }
|
|
892
|
+
|
|
893
|
+
.zms-0 { margin-left: 0 !important; }
|
|
894
|
+
.zms-1 { margin-left: 0.25rem !important; }
|
|
895
|
+
.zms-2 { margin-left: 0.5rem !important; }
|
|
896
|
+
.zms-3 { margin-left: 0.75rem !important; }
|
|
897
|
+
.zms-4 { margin-left: 1rem !important; }
|
|
898
|
+
.zms-5 { margin-left: 1.5rem !important; }
|
|
899
|
+
|
|
900
|
+
.zme-0 { margin-right: 0 !important; }
|
|
901
|
+
.zme-1 { margin-right: 0.25rem !important; }
|
|
902
|
+
.zme-2 { margin-right: 0.5rem !important; }
|
|
903
|
+
.zme-3 { margin-right: 0.75rem !important; }
|
|
904
|
+
.zme-4 { margin-right: 1rem !important; }
|
|
905
|
+
.zme-5 { margin-right: 1.5rem !important; }
|
|
906
|
+
|
|
907
|
+
.zp-0 { padding: 0 !important; }
|
|
908
|
+
.zp-1 { padding: 0.25rem !important; }
|
|
909
|
+
.zp-2 { padding: 0.5rem !important; }
|
|
910
|
+
.zp-3 { padding: 0.75rem !important; }
|
|
911
|
+
.zp-4 { padding: 1rem !important; }
|
|
912
|
+
.zp-5 { padding: 1.5rem !important; }
|
|
913
|
+
|
|
914
|
+
.zpt-0 { padding-top: 0 !important; }
|
|
915
|
+
.zpt-1 { padding-top: 0.25rem !important; }
|
|
916
|
+
.zpt-2 { padding-top: 0.5rem !important; }
|
|
917
|
+
.zpt-3 { padding-top: 0.75rem !important; }
|
|
918
|
+
.zpt-4 { padding-top: 1rem !important; }
|
|
919
|
+
.zpt-5 { padding-top: 1.5rem !important; }
|
|
920
|
+
|
|
921
|
+
.zpb-0 { padding-bottom: 0 !important; }
|
|
922
|
+
.zpb-1 { padding-bottom: 0.25rem !important; }
|
|
923
|
+
.zpb-2 { padding-bottom: 0.5rem !important; }
|
|
924
|
+
.zpb-3 { padding-bottom: 0.75rem !important; }
|
|
925
|
+
.zpb-4 { padding-bottom: 1rem !important; }
|
|
926
|
+
.zpb-5 { padding-bottom: 1.5rem !important; }
|
|
927
|
+
|
|
928
|
+
.zps-0 { padding-left: 0 !important; }
|
|
929
|
+
.zps-1 { padding-left: 0.25rem !important; }
|
|
930
|
+
.zps-2 { padding-left: 0.5rem !important; }
|
|
931
|
+
.zps-3 { padding-left: 0.75rem !important; }
|
|
932
|
+
.zps-4 { padding-left: 1rem !important; }
|
|
933
|
+
.zps-5 { padding-left: 1.5rem !important; }
|
|
934
|
+
|
|
935
|
+
.zpe-0 { padding-right: 0 !important; }
|
|
936
|
+
.zpe-1 { padding-right: 0.25rem !important; }
|
|
937
|
+
.zpe-2 { padding-right: 0.5rem !important; }
|
|
938
|
+
.zpe-3 { padding-right: 0.75rem !important; }
|
|
939
|
+
.zpe-4 { padding-right: 1rem !important; }
|
|
940
|
+
.zpe-5 { padding-right: 1.5rem !important; }
|
|
941
|
+
|
|
942
|
+
/* ─── 7. Tabs ──────────────────────────────────────────────────────────────── */
|
|
943
|
+
|
|
944
|
+
.zTab-content > .zTab-pane { display: none; }
|
|
945
|
+
.zTab-content > .zActive { display: block; }
|
|
946
|
+
|
|
947
|
+
/* Fade animation (opt-in via .zFade) */
|
|
948
|
+
.zTab-pane.zFade {
|
|
949
|
+
opacity: 0;
|
|
950
|
+
transition: opacity 0.15s linear;
|
|
951
|
+
}
|
|
952
|
+
.zTab-pane.zFade.zShow { opacity: 1; }
|
|
953
|
+
|
|
954
|
+
/* ─── 8. Nav / Nav-pills ───────────────────────────────────────────────────── */
|
|
955
|
+
|
|
956
|
+
.zNav {
|
|
957
|
+
display: flex;
|
|
958
|
+
flex-wrap: wrap;
|
|
959
|
+
padding-left: 0;
|
|
960
|
+
margin-bottom: 0;
|
|
961
|
+
list-style: none;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
.zNav-link {
|
|
965
|
+
display: block;
|
|
966
|
+
padding: 0.5rem 1rem;
|
|
967
|
+
text-decoration: none;
|
|
968
|
+
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
.zNav-link.zDisabled {
|
|
972
|
+
opacity: 0.5;
|
|
973
|
+
pointer-events: none;
|
|
974
|
+
cursor: default;
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
/* Pills */
|
|
978
|
+
.zNav-pills .zNav-link {
|
|
979
|
+
border-radius: 0.375rem;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
/* Active state — color set by app CSS, not here */
|
|
983
|
+
.zNav-pills .zNav-link.zActive {
|
|
984
|
+
font-weight: 500;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
/* ─── 9. Spinner ───────────────────────────────────────────────────────────── */
|
|
988
|
+
|
|
989
|
+
.zSpinner-border {
|
|
990
|
+
display: inline-block;
|
|
991
|
+
width: 2rem;
|
|
992
|
+
height: 2rem;
|
|
993
|
+
border: 0.25em solid currentColor;
|
|
994
|
+
border-right-color: transparent;
|
|
995
|
+
border-radius: 50%;
|
|
996
|
+
animation: zSpinner-border-spin 0.75s linear infinite;
|
|
997
|
+
vertical-align: -0.125em;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
.zSpinner-border-sm {
|
|
1001
|
+
width: 1rem;
|
|
1002
|
+
height: 1rem;
|
|
1003
|
+
border-width: 0.2em;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
.zSpinner-grow {
|
|
1007
|
+
display: inline-block;
|
|
1008
|
+
width: 2rem;
|
|
1009
|
+
height: 2rem;
|
|
1010
|
+
background-color: currentColor;
|
|
1011
|
+
border-radius: 50%;
|
|
1012
|
+
opacity: 0;
|
|
1013
|
+
animation: zSpinner-grow-pulse 0.75s linear infinite;
|
|
1014
|
+
vertical-align: -0.125em;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
.zSpinner-grow-sm { width: 1rem; height: 1rem; }
|
|
1018
|
+
|
|
1019
|
+
@keyframes zSpinner-border-spin { to { transform: rotate(360deg); } }
|
|
1020
|
+
@keyframes zSpinner-grow-pulse {
|
|
1021
|
+
0% { transform: scale(0); opacity: 1; }
|
|
1022
|
+
50% { opacity: 1; transform: scale(1); }
|
|
1023
|
+
100% { transform: scale(0); opacity: 1; }
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1027
|
+
.zSpinner-border, .zSpinner-grow { animation-duration: 1.5s; }
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
/* ─── 10. Misc runtime helpers ─────────────────────────────────────────────── */
|
|
1031
|
+
|
|
1032
|
+
.zContainer-fluid {
|
|
1033
|
+
width: 100%;
|
|
1034
|
+
padding-right: 0.75rem;
|
|
1035
|
+
padding-left: 0.75rem;
|
|
1036
|
+
margin-right: auto;
|
|
1037
|
+
margin-left: auto;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
.zVisually-hidden {
|
|
1041
|
+
position: absolute !important;
|
|
1042
|
+
width: 1px !important;
|
|
1043
|
+
height: 1px !important;
|
|
1044
|
+
padding: 0 !important;
|
|
1045
|
+
margin: -1px !important;
|
|
1046
|
+
overflow: hidden !important;
|
|
1047
|
+
clip: rect(0,0,0,0) !important;
|
|
1048
|
+
white-space: nowrap !important;
|
|
1049
|
+
border: 0 !important;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
.zText-muted { opacity: 0.6; }
|
|
1053
|
+
.zText-center { text-align: center !important; }
|
|
1054
|
+
.zText-start { text-align: left !important; }
|
|
1055
|
+
.zText-end { text-align: right !important; }
|
|
1056
|
+
|
|
1057
|
+
.zW-100 { width: 100% !important; }
|
|
1058
|
+
.zH-100 { height: 100% !important; }
|
|
1059
|
+
.zmx-auto { margin-left: auto !important; margin-right: auto !important; }
|
|
1060
|
+
|
|
1061
|
+
.zRounded { border-radius: 0.375rem !important; }
|
|
1062
|
+
.zRounded-circle { border-radius: 50% !important; }
|
|
1063
|
+
|
|
1064
|
+
/* Base button structural (no colors — app/theme sets those) */
|
|
1065
|
+
.zBtn {
|
|
1066
|
+
display: inline-block;
|
|
1067
|
+
cursor: pointer;
|
|
1068
|
+
text-align: center;
|
|
1069
|
+
white-space: nowrap;
|
|
1070
|
+
vertical-align: middle;
|
|
1071
|
+
user-select: none;
|
|
1072
|
+
border: 1px solid transparent;
|
|
1073
|
+
text-decoration: none;
|
|
1074
|
+
}
|
|
1075
|
+
.zBtn:focus { outline: 2px solid rgba(79, 70, 229, 0.5); outline-offset: 2px; }
|
|
1076
|
+
|
|
1077
|
+
/* ─── Button color variants — canonical fills (theme tokens) ───────────────── */
|
|
1078
|
+
/* The renderer maps a zBtn's `color:` (default primary) to .zBtn-{color}; these
|
|
1079
|
+
* give that class an actual fill everywhere — not just inside .zDash-container.
|
|
1080
|
+
* Keyed to --color-* (mirrors .zText-*); apps restyle by redefining the token.
|
|
1081
|
+
* Dashboard keeps its own look via the higher-specificity .zDash-container rule. */
|
|
1082
|
+
.zBtn-primary, .zBtn-secondary, .zBtn-success,
|
|
1083
|
+
.zBtn-danger, .zBtn-warning, .zBtn-info {
|
|
1084
|
+
display: inline-flex;
|
|
1085
|
+
align-items: center;
|
|
1086
|
+
justify-content: center;
|
|
1087
|
+
gap: 0.4rem;
|
|
1088
|
+
padding: 0.55rem 1.25rem;
|
|
1089
|
+
border: none;
|
|
1090
|
+
border-radius: 9px;
|
|
1091
|
+
font-family: inherit;
|
|
1092
|
+
font-size: 0.9rem;
|
|
1093
|
+
font-weight: 600;
|
|
1094
|
+
line-height: 1.4;
|
|
1095
|
+
cursor: pointer;
|
|
1096
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
|
|
1097
|
+
transition: filter 0.15s ease, transform 0.08s ease, box-shadow 0.15s ease;
|
|
1098
|
+
}
|
|
1099
|
+
.zBtn-primary:hover, .zBtn-secondary:hover, .zBtn-success:hover,
|
|
1100
|
+
.zBtn-danger:hover, .zBtn-warning:hover, .zBtn-info:hover {
|
|
1101
|
+
filter: brightness(1.06);
|
|
1102
|
+
transform: translateY(-1px);
|
|
1103
|
+
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.22);
|
|
1104
|
+
}
|
|
1105
|
+
.zBtn-primary:active, .zBtn-secondary:active, .zBtn-success:active,
|
|
1106
|
+
.zBtn-danger:active, .zBtn-warning:active, .zBtn-info:active {
|
|
1107
|
+
transform: translateY(0);
|
|
1108
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
|
|
1109
|
+
}
|
|
1110
|
+
.zBtn-primary:disabled, .zBtn-secondary:disabled, .zBtn-success:disabled,
|
|
1111
|
+
.zBtn-danger:disabled, .zBtn-warning:disabled, .zBtn-info:disabled {
|
|
1112
|
+
opacity: 0.5; cursor: not-allowed; transform: none; box-shadow: none; filter: none;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
/* SSOT fills — keyed to --color-* (same tokens/hexes as .zText-*), so a button
|
|
1116
|
+
* matches a heading of the same color name. Dark text on the light hues
|
|
1117
|
+
* (primary/success/warning/info), white on the deep ones (secondary/danger). */
|
|
1118
|
+
.zBtn-primary { background: var(--color-primary, #A2D46E); color: #14210a; }
|
|
1119
|
+
.zBtn-secondary { background: var(--color-secondary, #9370DB); color: #ffffff; }
|
|
1120
|
+
.zBtn-success { background: var(--color-success, #52B788); color: #06281c; }
|
|
1121
|
+
.zBtn-danger { background: var(--color-error, #E63946); color: #ffffff; }
|
|
1122
|
+
.zBtn-warning { background: var(--color-warning, #FFB347); color: #3a2400; }
|
|
1123
|
+
.zBtn-info { background: var(--color-info, #5CA9FF); color: #07243d; }
|
|
1124
|
+
|
|
1125
|
+
/* Structural display defaults */
|
|
1126
|
+
.zSignal { display: block; }
|
|
1127
|
+
.zCard { position: relative; }
|
|
1128
|
+
.zInputGroup { display: flex; align-items: stretch; }
|
|
1129
|
+
.zInputGroup > .zInputGroup-text { display: flex; align-items: center; }
|
|
1130
|
+
|
|
1131
|
+
/* Badge (structural — no color) */
|
|
1132
|
+
.zBadge {
|
|
1133
|
+
display: inline-block;
|
|
1134
|
+
padding: 0.25em 0.5em;
|
|
1135
|
+
font-size: 0.75em;
|
|
1136
|
+
font-weight: 700;
|
|
1137
|
+
line-height: 1;
|
|
1138
|
+
text-align: center;
|
|
1139
|
+
white-space: nowrap;
|
|
1140
|
+
vertical-align: baseline;
|
|
1141
|
+
border-radius: 0.375rem;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
/* ─── 10. zDash layout formats ─────────────────────────────────────────────── */
|
|
1145
|
+
|
|
1146
|
+
/* sidebar: fixed left-nav + scrollable content area */
|
|
1147
|
+
.zDash-format-sidebar.zDash-container {
|
|
1148
|
+
display: flex;
|
|
1149
|
+
flex-direction: column;
|
|
1150
|
+
min-height: calc(100vh - 60px);
|
|
1151
|
+
}
|
|
1152
|
+
.zDash-format-sidebar > .zRow {
|
|
1153
|
+
display: flex !important;
|
|
1154
|
+
flex-wrap: nowrap !important;
|
|
1155
|
+
align-items: flex-start !important;
|
|
1156
|
+
flex: 1;
|
|
1157
|
+
margin: 0;
|
|
1158
|
+
}
|
|
1159
|
+
.zDash-format-sidebar > .zRow > .zCol-auto { flex-shrink: 0; }
|
|
1160
|
+
.zDash-format-sidebar > .zRow > .zCol { flex: 1; min-width: 0; width: 0; }
|
|
1161
|
+
|
|
1162
|
+
/* Tablet ≤900px: sidebar collapses to horizontal top bar */
|
|
1163
|
+
@media (max-width: 900px) {
|
|
1164
|
+
.zDash-format-sidebar > .zRow {
|
|
1165
|
+
flex-direction: column !important;
|
|
1166
|
+
flex-wrap: wrap !important;
|
|
1167
|
+
}
|
|
1168
|
+
.zDash-format-sidebar > .zRow > .zCol-auto,
|
|
1169
|
+
.zDash-format-sidebar > .zRow > .zCol {
|
|
1170
|
+
width: 100% !important;
|
|
1171
|
+
flex: none !important;
|
|
1172
|
+
min-width: unset !important;
|
|
1173
|
+
}
|
|
1174
|
+
.zDash-format-sidebar > .zRow > .zCol-auto {
|
|
1175
|
+
border-right: none !important;
|
|
1176
|
+
border-bottom: 1px solid rgba(79, 70, 229, 0.15);
|
|
1177
|
+
}
|
|
1178
|
+
.zDash-format-sidebar .zDash-sidebar {
|
|
1179
|
+
flex-direction: row !important;
|
|
1180
|
+
flex-wrap: wrap;
|
|
1181
|
+
width: 100%;
|
|
1182
|
+
padding: 0.5rem 0.75rem;
|
|
1183
|
+
gap: 0.25rem;
|
|
1184
|
+
}
|
|
1185
|
+
.zDash-format-sidebar .zDash-sidebar .zNav-link.zActive {
|
|
1186
|
+
box-shadow: none !important;
|
|
1187
|
+
border-bottom: 2px solid #4F46E5;
|
|
1188
|
+
}
|
|
1189
|
+
.zDash-panel { padding: 1.25rem 1rem; }
|
|
1190
|
+
.zDash-container .zDialog-form { grid-template-columns: 1fr 1fr; }
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
/* Mobile sidebar toggle button — hidden by default (desktop/tablet) */
|
|
1194
|
+
.zDash-sidebar-toggle {
|
|
1195
|
+
display: none;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
/* Mobile ≤600px: sidebar becomes a toggle-driven drawer */
|
|
1199
|
+
@media (max-width: 600px) {
|
|
1200
|
+
/* Container must be relative so the sidebar overlay positions correctly */
|
|
1201
|
+
.zDash-format-sidebar { position: relative; }
|
|
1202
|
+
|
|
1203
|
+
/* Sidebar column hidden by default on mobile */
|
|
1204
|
+
.zDash-format-sidebar > .zRow > .zCol-auto {
|
|
1205
|
+
display: none !important;
|
|
1206
|
+
position: absolute;
|
|
1207
|
+
top: 0;
|
|
1208
|
+
left: 0;
|
|
1209
|
+
right: 0;
|
|
1210
|
+
z-index: 50;
|
|
1211
|
+
background: rgba(10, 14, 39, 0.98);
|
|
1212
|
+
border-bottom: 1px solid rgba(79, 70, 229, 0.2);
|
|
1213
|
+
backdrop-filter: blur(12px);
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
/* Open state: sidebar slides in as a full-width dropdown */
|
|
1217
|
+
.zDash-format-sidebar.zDash-sidebar-open > .zRow > .zCol-auto {
|
|
1218
|
+
display: block !important;
|
|
1219
|
+
}
|
|
1220
|
+
.zDash-format-sidebar.zDash-sidebar-open .zDash-sidebar {
|
|
1221
|
+
flex-direction: column !important;
|
|
1222
|
+
width: 100% !important;
|
|
1223
|
+
padding: 0.5rem 0.75rem;
|
|
1224
|
+
gap: 0.1rem;
|
|
1225
|
+
}
|
|
1226
|
+
/* Push content down when sidebar is open */
|
|
1227
|
+
.zDash-format-sidebar.zDash-sidebar-open > .zRow > .zCol {
|
|
1228
|
+
margin-top: var(--zdash-sidebar-h, 0px);
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
/* Show the toggle button on mobile */
|
|
1232
|
+
.zDash-sidebar-toggle {
|
|
1233
|
+
display: inline-flex;
|
|
1234
|
+
align-items: center;
|
|
1235
|
+
gap: 0.4rem;
|
|
1236
|
+
margin: 0.75rem 0.75rem 0;
|
|
1237
|
+
padding: 0.45rem 0.85rem;
|
|
1238
|
+
background: rgba(79, 70, 229, 0.15);
|
|
1239
|
+
border: 1px solid rgba(79, 70, 229, 0.3);
|
|
1240
|
+
border-radius: 8px;
|
|
1241
|
+
color: #c7d2fe;
|
|
1242
|
+
font-size: 0.875rem;
|
|
1243
|
+
font-weight: 500;
|
|
1244
|
+
cursor: pointer;
|
|
1245
|
+
font-family: inherit;
|
|
1246
|
+
}
|
|
1247
|
+
.zDash-sidebar-toggle:hover {
|
|
1248
|
+
background: rgba(79, 70, 229, 0.25);
|
|
1249
|
+
color: #e0e7ff;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
.zDash-panel { padding: 1rem 0.75rem; }
|
|
1253
|
+
.zDash-container .zDialog-form { grid-template-columns: 1fr !important; }
|
|
1254
|
+
.zDash-container .zInput { font-size: 1rem; }
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
/* tabs format (future) */
|
|
1258
|
+
.zDash-format-tabs.zDash-container { display: block; }
|
|
1259
|
+
.zDash-format-tabs .zDash-sidebar {
|
|
1260
|
+
display: flex;
|
|
1261
|
+
flex-direction: row;
|
|
1262
|
+
border-bottom: 1px solid rgba(79, 70, 229, 0.2);
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
/* accordion format (future) */
|
|
1266
|
+
.zDash-format-accordion > .zRow { flex-direction: column; }
|
|
1267
|
+
|
|
1268
|
+
/* ─── 11. zDash default visual theme ───────────────────────────────────────── */
|
|
1269
|
+
/*
|
|
1270
|
+
* Default dark theme for all zDash apps.
|
|
1271
|
+
* Override via _zClass or your app's own stylesheet.
|
|
1272
|
+
*/
|
|
1273
|
+
|
|
1274
|
+
/* Sidebar column chrome */
|
|
1275
|
+
.zDash-format-sidebar > .zRow > .zCol-auto {
|
|
1276
|
+
background: rgba(10, 14, 39, 0.6);
|
|
1277
|
+
border-right: 1px solid rgba(79, 70, 229, 0.15);
|
|
1278
|
+
padding: 0;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
/* Sidebar nav */
|
|
1282
|
+
.zDash-sidebar {
|
|
1283
|
+
display: flex;
|
|
1284
|
+
flex-direction: column;
|
|
1285
|
+
gap: 0.15rem;
|
|
1286
|
+
padding: 1rem 0.75rem;
|
|
1287
|
+
width: 200px;
|
|
1288
|
+
}
|
|
1289
|
+
.zDash-sidebar .zNav-link {
|
|
1290
|
+
display: flex;
|
|
1291
|
+
align-items: center;
|
|
1292
|
+
padding: 0.55rem 0.85rem;
|
|
1293
|
+
border-radius: 8px;
|
|
1294
|
+
color: #94a3b8;
|
|
1295
|
+
font-size: 0.875rem;
|
|
1296
|
+
font-weight: 500;
|
|
1297
|
+
cursor: pointer;
|
|
1298
|
+
transition: color 0.15s, background 0.15s;
|
|
1299
|
+
white-space: nowrap;
|
|
1300
|
+
text-decoration: none;
|
|
1301
|
+
}
|
|
1302
|
+
.zDash-sidebar .zNav-link:hover {
|
|
1303
|
+
color: #f1f5f9;
|
|
1304
|
+
background: rgba(79, 70, 229, 0.12);
|
|
1305
|
+
}
|
|
1306
|
+
.zDash-sidebar .zNav-link.zActive {
|
|
1307
|
+
color: #f9fafb;
|
|
1308
|
+
background: rgba(79, 70, 229, 0.22);
|
|
1309
|
+
box-shadow: inset 3px 0 0 #4F46E5;
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
/* Panel area */
|
|
1313
|
+
.zDash-panel { padding: 1.75rem 2rem; }
|
|
1314
|
+
.zDash-panel > .zTab-pane { display: none; }
|
|
1315
|
+
.zDash-panel > .zTab-pane.zActive { display: block; }
|
|
1316
|
+
|
|
1317
|
+
/* Cards */
|
|
1318
|
+
.zDash-container .zCard {
|
|
1319
|
+
width: 100%;
|
|
1320
|
+
box-sizing: border-box;
|
|
1321
|
+
margin-bottom: 1.25rem;
|
|
1322
|
+
background: rgba(15, 20, 48, 0.6);
|
|
1323
|
+
border: 1px solid rgba(79, 70, 229, 0.15);
|
|
1324
|
+
border-radius: 10px;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
/* Dialog / form section header */
|
|
1328
|
+
.zDash-container .zDialog-title {
|
|
1329
|
+
font-size: 1rem;
|
|
1330
|
+
font-weight: 700;
|
|
1331
|
+
color: #c7d2fe;
|
|
1332
|
+
margin-bottom: 1rem;
|
|
1333
|
+
padding-bottom: 0.6rem;
|
|
1334
|
+
border-bottom: 1px solid rgba(79, 70, 229, 0.15);
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
/* Multi-column form grid */
|
|
1338
|
+
.zDash-container .zDialog-form {
|
|
1339
|
+
display: grid;
|
|
1340
|
+
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
1341
|
+
gap: 0.75rem;
|
|
1342
|
+
}
|
|
1343
|
+
.zDash-container .zDialog-form > [class*="zmt-"],
|
|
1344
|
+
.zDash-container .zDialog-errors {
|
|
1345
|
+
grid-column: 1 / -1;
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
/* Labels */
|
|
1349
|
+
.zDash-container .zLabel {
|
|
1350
|
+
font-size: 0.7rem;
|
|
1351
|
+
text-transform: uppercase;
|
|
1352
|
+
letter-spacing: 0.06em;
|
|
1353
|
+
color: #64748b;
|
|
1354
|
+
font-weight: 600;
|
|
1355
|
+
display: block;
|
|
1356
|
+
margin-bottom: 0.3rem;
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
/* Inputs & selects */
|
|
1360
|
+
.zDash-container .zInput {
|
|
1361
|
+
appearance: none;
|
|
1362
|
+
background: rgba(255, 255, 255, 0.04);
|
|
1363
|
+
border: 1px solid rgba(79, 70, 229, 0.2);
|
|
1364
|
+
border-radius: 7px;
|
|
1365
|
+
color: #e2e8f0;
|
|
1366
|
+
padding: 0.5rem 0.75rem;
|
|
1367
|
+
font-size: 0.875rem;
|
|
1368
|
+
width: 100%;
|
|
1369
|
+
box-sizing: border-box;
|
|
1370
|
+
font-family: inherit;
|
|
1371
|
+
transition: border-color 0.15s, background 0.15s;
|
|
1372
|
+
}
|
|
1373
|
+
.zDash-container .zInput:focus {
|
|
1374
|
+
outline: none;
|
|
1375
|
+
border-color: rgba(79, 70, 229, 0.6);
|
|
1376
|
+
background: rgba(255, 255, 255, 0.07);
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
/* Primary action button */
|
|
1380
|
+
.zDash-container .zBtn-primary {
|
|
1381
|
+
background: #4F46E5;
|
|
1382
|
+
border: none;
|
|
1383
|
+
color: #fff;
|
|
1384
|
+
padding: 0.55rem 1.25rem;
|
|
1385
|
+
border-radius: 8px;
|
|
1386
|
+
font-size: 0.875rem;
|
|
1387
|
+
font-weight: 600;
|
|
1388
|
+
cursor: pointer;
|
|
1389
|
+
font-family: inherit;
|
|
1390
|
+
transition: background 0.15s, transform 0.1s;
|
|
1391
|
+
}
|
|
1392
|
+
.zDash-container .zBtn-primary:hover {
|
|
1393
|
+
background: #4338ca;
|
|
1394
|
+
transform: translateY(-1px);
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
/* Panel / menu action buttons */
|
|
1398
|
+
.zDash-container button[data-key] {
|
|
1399
|
+
display: inline-flex;
|
|
1400
|
+
align-items: center;
|
|
1401
|
+
gap: 0.4rem;
|
|
1402
|
+
padding: 0.5rem 1rem;
|
|
1403
|
+
margin: 0 0.4rem 0.4rem 0;
|
|
1404
|
+
background: rgba(79, 70, 229, 0.15);
|
|
1405
|
+
border: 1px solid rgba(79, 70, 229, 0.3);
|
|
1406
|
+
border-radius: 8px;
|
|
1407
|
+
color: #c7d2fe;
|
|
1408
|
+
font-size: 0.875rem;
|
|
1409
|
+
font-weight: 500;
|
|
1410
|
+
font-family: inherit;
|
|
1411
|
+
cursor: pointer;
|
|
1412
|
+
transition: background 0.15s, border-color 0.15s, color 0.15s;
|
|
1413
|
+
}
|
|
1414
|
+
.zDash-container button[data-key]:hover {
|
|
1415
|
+
background: rgba(79, 70, 229, 0.3);
|
|
1416
|
+
border-color: rgba(79, 70, 229, 0.5);
|
|
1417
|
+
color: #e0e7ff;
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
/* Tables */
|
|
1421
|
+
.zDash-container table {
|
|
1422
|
+
width: 100%;
|
|
1423
|
+
border-collapse: collapse;
|
|
1424
|
+
font-size: 0.875rem;
|
|
1425
|
+
color: #e2e8f0;
|
|
1426
|
+
}
|
|
1427
|
+
.zDash-container th {
|
|
1428
|
+
padding: 0.6rem 0.9rem;
|
|
1429
|
+
background: rgba(79, 70, 229, 0.12);
|
|
1430
|
+
color: #a5b4fc;
|
|
1431
|
+
font-weight: 600;
|
|
1432
|
+
text-align: left;
|
|
1433
|
+
border-bottom: 1px solid rgba(79, 70, 229, 0.2);
|
|
1434
|
+
}
|
|
1435
|
+
.zDash-container td {
|
|
1436
|
+
padding: 0.55rem 0.9rem;
|
|
1437
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
|
1438
|
+
}
|
|
1439
|
+
.zDash-container tr:hover td { background: rgba(79, 70, 229, 0.07); }
|
|
1440
|
+
|
|
1441
|
+
/* Section headings */
|
|
1442
|
+
.zDash-container h2 {
|
|
1443
|
+
font-size: 1.2rem;
|
|
1444
|
+
font-weight: 700;
|
|
1445
|
+
color: #f9fafb;
|
|
1446
|
+
margin: 0 0 1rem;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
/* Spinner */
|
|
1450
|
+
.zSpinner-border { color: #6366f1; }
|
|
1451
|
+
|
|
1452
|
+
/* ============================================================================
|
|
1453
|
+
Tables (zTable) — canonical dark-theme data tables
|
|
1454
|
+
----------------------------------------------------------------------------
|
|
1455
|
+
Bifrost-owned SSOT for the zTable look (moved here from zCloud so every app
|
|
1456
|
+
inherits the same table styling). The zTable event opts in via _zClass: zTable.
|
|
1457
|
+
========================================================================== */
|
|
1458
|
+
.zTable-container { margin: 1.5rem 0; }
|
|
1459
|
+
|
|
1460
|
+
.zTable-container h4 {
|
|
1461
|
+
color: #f9fafb;
|
|
1462
|
+
font-size: 1.1rem;
|
|
1463
|
+
font-weight: 700;
|
|
1464
|
+
margin: 0 0 0.75rem;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
.zTable-responsive {
|
|
1468
|
+
overflow-x: auto;
|
|
1469
|
+
border-radius: 12px;
|
|
1470
|
+
border: 1px solid rgba(79, 70, 229, 0.2);
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
.zTable {
|
|
1474
|
+
width: 100%;
|
|
1475
|
+
border-collapse: collapse;
|
|
1476
|
+
background: linear-gradient(145deg, rgba(30, 35, 60, 0.5) 0%, rgba(20, 25, 45, 0.6) 100%);
|
|
1477
|
+
font-size: 0.95rem;
|
|
1478
|
+
text-align: left;
|
|
1479
|
+
/* Default body text colour lives here so cells INHERIT it. Keeping it off the
|
|
1480
|
+
td selector lets a per-cell utility (zText-success/-danger…) win — a bare
|
|
1481
|
+
.zText-* class (0,1,0) would otherwise lose to `.zTable tbody td` (0,1,2). */
|
|
1482
|
+
color: #d1d5db;
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
.zTable thead th {
|
|
1486
|
+
background: rgba(79, 70, 229, 0.18);
|
|
1487
|
+
color: #c7d2fe;
|
|
1488
|
+
font-weight: 700;
|
|
1489
|
+
text-align: left;
|
|
1490
|
+
padding: 0.85rem 1rem;
|
|
1491
|
+
letter-spacing: 0.02em;
|
|
1492
|
+
border-bottom: 1px solid rgba(79, 70, 229, 0.3);
|
|
1493
|
+
white-space: nowrap;
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
.zTable tbody td {
|
|
1497
|
+
padding: 0.8rem 1rem;
|
|
1498
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
|
1499
|
+
vertical-align: top;
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
.zTable tbody tr:last-child td { border-bottom: none; }
|
|
1503
|
+
.zTable tbody tr:nth-child(even) td { background: rgba(255, 255, 255, 0.02); }
|
|
1504
|
+
.zTable tbody tr:hover td { background: rgba(79, 70, 229, 0.08); }
|
|
1505
|
+
.zTable td strong { color: #f9fafb; }
|
|
1506
|
+
|
|
1507
|
+
/* ════════════════════════════════════════════════════════════════════════════
|
|
1508
|
+
Progress bar (zProgress) — canonical animated progress component
|
|
1509
|
+
|
|
1510
|
+
Bifrost-owned SSOT for the progress look (mirrors the zCLI bar). The renderer
|
|
1511
|
+
builds: .zProgress-container > [label row] + .zProgress (track) > .zProgress-bar
|
|
1512
|
+
(the fill). Fill WIDTH is set inline (0–100%); fill COLOR comes from a
|
|
1513
|
+
zBg-{color} class the renderer derives from the event's `color` property.
|
|
1514
|
+
════════════════════════════════════════════════════════════════════════════ */
|
|
1515
|
+
|
|
1516
|
+
.zProgress-container { width: 100%; margin: 0.75rem 0; }
|
|
1517
|
+
|
|
1518
|
+
/* Label / percentage row above the track, pushed to the edges (self-contained
|
|
1519
|
+
so it never depends on zTheme flex utilities being present). */
|
|
1520
|
+
.zProgress-container > .zD-flex {
|
|
1521
|
+
display: flex;
|
|
1522
|
+
justify-content: space-between;
|
|
1523
|
+
align-items: baseline;
|
|
1524
|
+
margin-bottom: 0.4rem;
|
|
1525
|
+
}
|
|
1526
|
+
.zProgress-container .zFw-bold { font-weight: 600; color: var(--zprogress-label, #e5e7eb); }
|
|
1527
|
+
.zProgress-container .zText-muted { color: var(--zprogress-info, rgba(229, 231, 235, 0.6)); }
|
|
1528
|
+
|
|
1529
|
+
/* Track — the rail behind the fill. Inset shadow gives the pill real depth. */
|
|
1530
|
+
.zProgress {
|
|
1531
|
+
width: 100%;
|
|
1532
|
+
height: 1rem; /* default; renderer may override inline via height prop */
|
|
1533
|
+
background: var(--zprogress-track, rgba(255, 255, 255, 0.07));
|
|
1534
|
+
border-radius: 999px;
|
|
1535
|
+
overflow: hidden;
|
|
1536
|
+
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.35);
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
/* Fill — the moving bar. It carries a solid tint (zBg-{color}) PLUS two layered
|
|
1540
|
+
overlays: a fixed top gloss for a glossy 3-D pill, and a diagonal sheen that
|
|
1541
|
+
is ALWAYS running — so the bar reads as alive even when the value is static.
|
|
1542
|
+
Width animates with a soft ease when it does change. */
|
|
1543
|
+
.zProgress-bar {
|
|
1544
|
+
height: 100%;
|
|
1545
|
+
width: 0;
|
|
1546
|
+
background-color: var(--color-primary, #A2D46E); /* default; zBg-{color} overrides */
|
|
1547
|
+
background-image:
|
|
1548
|
+
linear-gradient(to bottom,
|
|
1549
|
+
rgba(255, 255, 255, 0.28), rgba(255, 255, 255, 0.04) 48%, rgba(0, 0, 0, 0.10)),
|
|
1550
|
+
linear-gradient(-45deg,
|
|
1551
|
+
rgba(255, 255, 255, 0.16) 25%, transparent 25%,
|
|
1552
|
+
transparent 50%, rgba(255, 255, 255, 0.16) 50%,
|
|
1553
|
+
rgba(255, 255, 255, 0.16) 75%, transparent 75%, transparent);
|
|
1554
|
+
background-size: 100% 100%, 1.15rem 1.15rem;
|
|
1555
|
+
background-repeat: no-repeat, repeat;
|
|
1556
|
+
border-radius: inherit;
|
|
1557
|
+
transition: width 0.45s cubic-bezier(0.22, 1, 0.36, 1);
|
|
1558
|
+
animation: zProgress-flow 0.9s linear infinite;
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
/* The diagonal sheen scrolls; the gloss layer stays put (position pinned). */
|
|
1562
|
+
@keyframes zProgress-flow {
|
|
1563
|
+
from { background-position: 0 0, 1.15rem 0; }
|
|
1564
|
+
to { background-position: 0 0, 0 0; }
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
/* Respect reduced-motion: keep the look, drop the perpetual scroll. */
|
|
1568
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1569
|
+
.zProgress-bar { animation: none; }
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
/* `color` property → fill color. Bar-scoped (.zProgress-bar.zBg-*) so it always
|
|
1573
|
+
wins over the generic zTheme utility and pulls from the same --color-* SSOT. */
|
|
1574
|
+
.zProgress-bar.zBg-primary { background-color: var(--color-primary, #A2D46E); }
|
|
1575
|
+
.zProgress-bar.zBg-secondary { background-color: var(--color-secondary, #9370DB); }
|
|
1576
|
+
.zProgress-bar.zBg-success { background-color: var(--color-success, #52B788); }
|
|
1577
|
+
.zProgress-bar.zBg-info { background-color: var(--color-info, #5CA9FF); }
|
|
1578
|
+
.zProgress-bar.zBg-warning { background-color: var(--color-warning, #FFB347); }
|
|
1579
|
+
.zProgress-bar.zBg-danger,
|
|
1580
|
+
.zProgress-bar.zBg-error { background-color: var(--color-error, #E63946); }
|
|
1581
|
+
|
|
1582
|
+
/* Indeterminate / "working" state — bolder stripes (renderer adds these when a
|
|
1583
|
+
bar has no total). Reuses the same flow animation. */
|
|
1584
|
+
.zProgress-bar-striped {
|
|
1585
|
+
background-image:
|
|
1586
|
+
linear-gradient(to bottom,
|
|
1587
|
+
rgba(255, 255, 255, 0.28), rgba(255, 255, 255, 0.04) 48%, rgba(0, 0, 0, 0.10)),
|
|
1588
|
+
linear-gradient(-45deg,
|
|
1589
|
+
rgba(255, 255, 255, 0.28) 25%, transparent 25%,
|
|
1590
|
+
transparent 50%, rgba(255, 255, 255, 0.28) 50%,
|
|
1591
|
+
rgba(255, 255, 255, 0.28) 75%, transparent 75%, transparent);
|
|
1592
|
+
}
|
|
1593
|
+
.zProgress-bar-animated { animation: zProgress-flow 0.9s linear infinite; }
|
|
1594
|
+
|
|
1595
|
+
/* Indeterminate "executing" marquee — opaque work of UNKNOWN length (a zFunc /
|
|
1596
|
+
zBtn plugin call). A partial fill chunk marches across the track: the web twin
|
|
1597
|
+
of the zCLI lit-window marquee that parks on the EXECUTE stage. It reads as
|
|
1598
|
+
"zOS is working" and NEVER sits at 100% — so a full bar only ever means done.
|
|
1599
|
+
Completion is signalled by the bar being replaced with the result. */
|
|
1600
|
+
.zProgress--indeterminate { overflow: hidden; }
|
|
1601
|
+
.zProgress--indeterminate > .zProgress-bar {
|
|
1602
|
+
width: 42% !important;
|
|
1603
|
+
transition: none;
|
|
1604
|
+
animation: zProgress-flow 0.9s linear infinite,
|
|
1605
|
+
zProgress-march 1.25s cubic-bezier(0.65, 0, 0.35, 1) infinite;
|
|
1606
|
+
}
|
|
1607
|
+
@keyframes zProgress-march {
|
|
1608
|
+
from { transform: translateX(-115%); }
|
|
1609
|
+
to { transform: translateX(258%); }
|
|
1610
|
+
}
|
|
1611
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1612
|
+
.zProgress--indeterminate > .zProgress-bar {
|
|
1613
|
+
animation: none; transform: none; width: 60% !important;
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
/* ─── zMenu — interactive menu events ──────────────────────────────────────────
|
|
1618
|
+
Canonical Bifrost render of a zMenu: a vertical list of full-width selectable
|
|
1619
|
+
rows, each with a numbered chip (keyboard shortcut) + label. Overrides the
|
|
1620
|
+
generic zBtn-pill fallback so menus read as navigation, not loose buttons.
|
|
1621
|
+
|
|
1622
|
+
Live markup (zdisplay_orchestrator.js _renderZMenuBlock):
|
|
1623
|
+
nav.zMenu-nav > ul.zNavbar-nav > li.zNav-item
|
|
1624
|
+
> button.zNav-link.zBtn[data-key] > span.zBadge + label
|
|
1625
|
+
Legacy markup (menu_renderer.js): .zMenu-container > .zMenu-option > button.
|
|
1626
|
+
Both paths are styled below.
|
|
1627
|
+
|
|
1628
|
+
The block wrapper (.zCallout) supplies the card surface; this only owns the
|
|
1629
|
+
list, rows, and number chip. Accents pull from the zCLI SSOT palette
|
|
1630
|
+
(--color-primary lime, --color-secondary purple); dark-theme friendly. */
|
|
1631
|
+
|
|
1632
|
+
/* Options list — kill inherited bullets / list padding */
|
|
1633
|
+
.zMenu-nav .zNavbar-nav,
|
|
1634
|
+
.zMenu-options {
|
|
1635
|
+
display: flex;
|
|
1636
|
+
flex-direction: column;
|
|
1637
|
+
gap: 0.25rem;
|
|
1638
|
+
margin: 0;
|
|
1639
|
+
padding: 0;
|
|
1640
|
+
list-style: none;
|
|
1641
|
+
}
|
|
1642
|
+
.zMenu-nav .zNav-item,
|
|
1643
|
+
.zMenu-option {
|
|
1644
|
+
margin: 0;
|
|
1645
|
+
padding: 0;
|
|
1646
|
+
list-style: none;
|
|
1647
|
+
}
|
|
1648
|
+
.zMenu-nav .zNav-item::marker,
|
|
1649
|
+
.zMenu-option::marker { content: none; }
|
|
1650
|
+
|
|
1651
|
+
/* Row — overrides the fallback zBtn pill into a full-width nav row */
|
|
1652
|
+
.zMenu-nav .zNav-link,
|
|
1653
|
+
.zMenu-container .zMenu-option button,
|
|
1654
|
+
.zMenu-container .zMenu-option .zBtn {
|
|
1655
|
+
display: flex;
|
|
1656
|
+
align-items: center;
|
|
1657
|
+
gap: 0.75rem;
|
|
1658
|
+
width: 100%;
|
|
1659
|
+
text-align: left;
|
|
1660
|
+
padding: 0.6rem 0.85rem;
|
|
1661
|
+
font-size: 1rem;
|
|
1662
|
+
font-weight: 500;
|
|
1663
|
+
font-family: inherit;
|
|
1664
|
+
color: inherit;
|
|
1665
|
+
background: transparent;
|
|
1666
|
+
border: 1px solid transparent;
|
|
1667
|
+
border-radius: 0.625rem;
|
|
1668
|
+
cursor: pointer;
|
|
1669
|
+
transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
.zMenu-nav .zNav-link:hover,
|
|
1673
|
+
.zMenu-nav .zNav-link:focus-visible,
|
|
1674
|
+
.zMenu-container .zMenu-option button:hover,
|
|
1675
|
+
.zMenu-container .zMenu-option button:focus-visible {
|
|
1676
|
+
background: rgba(162, 212, 110, 0.12);
|
|
1677
|
+
border-color: var(--color-primary, #A2D46E);
|
|
1678
|
+
transform: translateX(2px);
|
|
1679
|
+
outline: none;
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
.zMenu-nav .zNav-link:active,
|
|
1683
|
+
.zMenu-nav .zNav-link.active,
|
|
1684
|
+
.zMenu-container .zMenu-option button:active,
|
|
1685
|
+
.zMenu-container .zMenu-option button.active {
|
|
1686
|
+
background: var(--color-primary, #A2D46E);
|
|
1687
|
+
border-color: var(--color-primary, #A2D46E);
|
|
1688
|
+
color: #1a1a1a;
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
.zMenu-nav .zNav-link.active .zBadge {
|
|
1692
|
+
color: #fff;
|
|
1693
|
+
background: rgba(0, 0, 0, 0.25);
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
.zMenu-nav .zNav-link:disabled,
|
|
1697
|
+
.zMenu-container .zMenu-option button:disabled {
|
|
1698
|
+
opacity: 0.55;
|
|
1699
|
+
cursor: default;
|
|
1700
|
+
transform: none;
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
/* Leading chip — the keyboard index (overrides the faded zBadge-secondary) */
|
|
1704
|
+
.zMenu-nav .zNav-link .zBadge,
|
|
1705
|
+
.zMenu-container .zMenu-option .zBadge,
|
|
1706
|
+
.zMenu-container .zMenu-index {
|
|
1707
|
+
display: inline-flex;
|
|
1708
|
+
align-items: center;
|
|
1709
|
+
justify-content: center;
|
|
1710
|
+
flex: 0 0 auto;
|
|
1711
|
+
width: 1.5rem;
|
|
1712
|
+
height: 1.5rem;
|
|
1713
|
+
padding: 0;
|
|
1714
|
+
font-size: 0.8125rem;
|
|
1715
|
+
font-weight: 600;
|
|
1716
|
+
font-variant-numeric: tabular-nums;
|
|
1717
|
+
color: var(--color-secondary, #9370DB);
|
|
1718
|
+
background: rgba(147, 112, 219, 0.16);
|
|
1719
|
+
border-radius: 50%;
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
.zMenu-nav .zNav-link:hover .zBadge,
|
|
1723
|
+
.zMenu-nav .zNav-link:focus-visible .zBadge,
|
|
1724
|
+
.zMenu-container .zMenu-option button:hover .zBadge,
|
|
1725
|
+
.zMenu-container .zMenu-option button:focus-visible .zBadge {
|
|
1726
|
+
color: #fff;
|
|
1727
|
+
background: var(--color-secondary, #9370DB);
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1731
|
+
.zMenu-nav .zNav-link,
|
|
1732
|
+
.zMenu-container .zMenu-option button { transition: none; }
|
|
1733
|
+
.zMenu-nav .zNav-link:hover,
|
|
1734
|
+
.zMenu-container .zMenu-option button:hover { transform: none; }
|
|
1735
|
+
}
|