@dumiflex/wp-kit 0.0.0-stage → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +77 -0
- package/LICENSE +674 -0
- package/README.md +72 -2
- package/package.json +76 -4
- package/src/Avatar.vue +83 -0
- package/src/Badge.vue +97 -0
- package/src/Banner.vue +118 -0
- package/src/BookmarkButton.vue +27 -0
- package/src/BundleMeta.vue +51 -0
- package/src/Button.vue +103 -0
- package/src/Card.vue +68 -0
- package/src/Checkbox.vue +109 -0
- package/src/Chip.vue +163 -0
- package/src/ChoiceCards.vue +133 -0
- package/src/CloseButton.vue +69 -0
- package/src/CodeBlock.vue +119 -0
- package/src/ColorField.vue +188 -0
- package/src/ColorPicker.vue +201 -0
- package/src/Combobox.vue +331 -0
- package/src/ConfirmDialog.vue +165 -0
- package/src/ConfirmModal.vue +147 -0
- package/src/ConstraintMatrixPreview.vue +708 -0
- package/src/ContextMenu.vue +386 -0
- package/src/CopyButton.vue +156 -0
- package/src/DataTable.vue +292 -0
- package/src/DatePicker.vue +234 -0
- package/src/DescriptionList.vue +73 -0
- package/src/DiffView.vue +68 -0
- package/src/Disclosure.vue +166 -0
- package/src/DragHandle.vue +49 -0
- package/src/Drawer.vue +131 -0
- package/src/DropZone.vue +196 -0
- package/src/DropdownMenu.vue +72 -0
- package/src/EmptyState.vue +111 -0
- package/src/Field.vue +28 -0
- package/src/HsvPicker.vue +208 -0
- package/src/Icon.vue +39 -0
- package/src/IconPicker.vue +209 -0
- package/src/ImageGrid.vue +125 -0
- package/src/InlineEdit.vue +183 -0
- package/src/Input.vue +99 -0
- package/src/Kbd.vue +56 -0
- package/src/Lightbox.vue +173 -0
- package/src/ListFilter.vue +85 -0
- package/src/ListRow.vue +204 -0
- package/src/LoadingMark.vue +175 -0
- package/src/Logo.vue +60 -0
- package/src/Modal.vue +78 -0
- package/src/ModalShell.vue +109 -0
- package/src/Pagination.vue +106 -0
- package/src/Popover.vue +180 -0
- package/src/PostCard.vue +210 -0
- package/src/ProgressBar.vue +90 -0
- package/src/RadioGroup.vue +177 -0
- package/src/RangeSlider.vue +183 -0
- package/src/RelativeDate.vue +35 -0
- package/src/ResizeHandle.vue +143 -0
- package/src/SearchInput.vue +192 -0
- package/src/Select.vue +644 -0
- package/src/Separator.vue +54 -0
- package/src/Skeleton.vue +82 -0
- package/src/Slider.vue +198 -0
- package/src/SortableList.vue +260 -0
- package/src/SplitPane.vue +68 -0
- package/src/StarButton.vue +40 -0
- package/src/Stepper.vue +141 -0
- package/src/SupportLinks.vue +93 -0
- package/src/TagInput.vue +297 -0
- package/src/Textarea.vue +57 -0
- package/src/Timeline.vue +92 -0
- package/src/ToastCard.vue +119 -0
- package/src/ToastHost.vue +40 -0
- package/src/Toggle.vue +36 -0
- package/src/TokenizedValue.vue +310 -0
- package/src/Toolbar.vue +110 -0
- package/src/VirtualList.vue +87 -0
- package/src/VisuallyHidden.vue +29 -0
- package/src/WpButton.vue +75 -0
- package/src/WpCheck.vue +104 -0
- package/src/WpIconButton.vue +107 -0
- package/src/WpImageZoom.vue +544 -0
- package/src/WpNumber.vue +178 -0
- package/src/WpSegmented.vue +175 -0
- package/src/WpSelect.vue +93 -0
- package/src/WpSwitch.vue +163 -0
- package/src/WpTabs.vue +188 -0
- package/src/_modal-motion.css +33 -0
- package/src/_skeleton.css +50 -0
- package/src/axis-color.ts +42 -0
- package/src/button.css +169 -0
- package/src/calendar.ts +59 -0
- package/src/clipboard.ts +50 -0
- package/src/colour-presets.ts +12 -0
- package/src/diff.ts +51 -0
- package/src/drop-zone.ts +41 -0
- package/src/field.css +50 -0
- package/src/flip.ts +237 -0
- package/src/floating-layer.ts +48 -0
- package/src/floating.ts +99 -0
- package/src/hsv.ts +100 -0
- package/src/icon-catalog.ts +52 -0
- package/src/image-zoom.ts +93 -0
- package/src/kind-colour.ts +28 -0
- package/src/logo-paths.ts +21 -0
- package/src/matrix-axis.ts +91 -0
- package/src/pagination.ts +27 -0
- package/src/platform-keys.ts +29 -0
- package/src/rich-tokenize.ts +357 -0
- package/src/select-types.ts +32 -0
- package/src/slider-math.ts +45 -0
- package/src/sortable.ts +22 -0
- package/src/theme/fonts/OFL-Fraunces.txt +93 -0
- package/src/theme/fonts/OFL-JetBrainsMono.txt +93 -0
- package/src/theme/fonts/OFL-Manrope.txt +93 -0
- package/src/theme/fonts/fraunces-latin-wght-normal.woff2 +0 -0
- package/src/theme/fonts/jetbrains-mono-latin.woff2 +0 -0
- package/src/theme/fonts/manrope-latin-wght-normal.woff2 +0 -0
- package/src/theme/looks.css +428 -0
- package/src/theme/palettes.css +254 -0
- package/src/theme/tokens.css +2896 -0
- package/src/tokens.ts +56 -0
- package/src/tooltip.css +43 -0
- package/src/tooltip.ts +146 -0
- package/src/useDialogFocus.ts +73 -0
- package/src/useGrowableField.ts +357 -0
- package/src/useModalKeyShield.ts +116 -0
- package/src/useToast.ts +48 -0
- package/src/wp-logo.svg +14 -0
|
@@ -0,0 +1,2896 @@
|
|
|
1
|
+
/* =========================================================
|
|
2
|
+
Wildcard Pipeline — Design Tokens & Base
|
|
3
|
+
PrimeVue 4 Aura-inspired, dark, brand-customized.
|
|
4
|
+
|
|
5
|
+
1:1 port of docs/design-handoff/wildcard-pipeline/project/styles.css.
|
|
6
|
+
Keep selectors and rule order in sync with the prototype so future
|
|
7
|
+
ports can diff cleanly.
|
|
8
|
+
========================================================= */
|
|
9
|
+
|
|
10
|
+
:root {
|
|
11
|
+
/* Variable color palette — kept in sync with
|
|
12
|
+
* src/components/shared/theme.css (extension surface). The bundle
|
|
13
|
+
* editor mounts Context-side section components (CombineTemplateSection
|
|
14
|
+
* detected pills + preview tokens etc.) which call `varColorClass()`
|
|
15
|
+
* to emit `.var-1`..`.var-8`; without these rules in the manager
|
|
16
|
+
* surface the highlight collapses to default text color. */
|
|
17
|
+
--wp-var-1: #93c5fd;
|
|
18
|
+
--wp-var-2: #fcd34d;
|
|
19
|
+
--wp-var-3: #86efac;
|
|
20
|
+
--wp-var-4: #f9a8d4;
|
|
21
|
+
--wp-var-5: #fdba74;
|
|
22
|
+
--wp-var-6: #c4b5fd;
|
|
23
|
+
--wp-var-7: #67e8f9;
|
|
24
|
+
--wp-var-8: #fda4af;
|
|
25
|
+
|
|
26
|
+
/* Brand gradient (from logo) */
|
|
27
|
+
--wp-brand-1: #6c4cff;
|
|
28
|
+
--wp-brand-2: #a371ff;
|
|
29
|
+
--wp-brand-3: #2dd4bf;
|
|
30
|
+
|
|
31
|
+
/* Accent scale: Orbit indigo, the logo's #6366f1 (Tailwind indigo).
|
|
32
|
+
* One accent across canvas and manager; filled controls use -600. */
|
|
33
|
+
--wp-accent-50: #eef2ff;
|
|
34
|
+
--wp-accent-100: #e0e7ff;
|
|
35
|
+
--wp-accent-200: #c7d2fe;
|
|
36
|
+
--wp-accent-300: #a5b4fc;
|
|
37
|
+
--wp-accent-400: #818cf8;
|
|
38
|
+
--wp-accent-500: #6366f1;
|
|
39
|
+
--wp-accent-600: #4f46e5;
|
|
40
|
+
--wp-accent-700: #4338ca;
|
|
41
|
+
--wp-accent-800: #3730a3;
|
|
42
|
+
--wp-accent-900: #312e81;
|
|
43
|
+
|
|
44
|
+
/* Semantic accent text (theme-aware — overridden in light theme) */
|
|
45
|
+
--wp-accent-text: var(--wp-accent-300);
|
|
46
|
+
--wp-accent-text-strong: var(--wp-accent-200);
|
|
47
|
+
|
|
48
|
+
/* Surfaces (dark) */
|
|
49
|
+
--wp-bg: #0b0b12;
|
|
50
|
+
--wp-bg-1: #11111b;
|
|
51
|
+
--wp-bg-2: #15151f;
|
|
52
|
+
--wp-bg-3: #1c1c28;
|
|
53
|
+
--wp-bg-4: #232333;
|
|
54
|
+
|
|
55
|
+
--wp-border: rgba(255,255,255,0.08);
|
|
56
|
+
--wp-border-strong: rgba(255,255,255,0.14);
|
|
57
|
+
--wp-border-focus: var(--wp-accent-400);
|
|
58
|
+
|
|
59
|
+
/* Text */
|
|
60
|
+
--wp-text: #e7e7ee;
|
|
61
|
+
--wp-text-muted: #a1a1ad;
|
|
62
|
+
/* Dim was previously #6e6e7c (~3.8:1 vs --wp-bg). Bumped to #8a8a9a
|
|
63
|
+
* so all dim text — row ids, version chip, toolbar counters,
|
|
64
|
+
* sidebar section headings — passes WCAG AA 4.5:1 contrast on the
|
|
65
|
+
* darkest surface. Still visually subordinate to text-muted. */
|
|
66
|
+
--wp-text-dim: #8a8a9a;
|
|
67
|
+
|
|
68
|
+
/* Status */
|
|
69
|
+
/* Tag-axis accessor (`$outfit.SHOES`). One fixed colour rather than the
|
|
70
|
+
group's own hue: an accessor is the same KIND of thing wherever it
|
|
71
|
+
appears, and per-group hues made the meaning look different per
|
|
72
|
+
variable. Deliberately amber-400, not --wp-warn (amber-500), so a valid
|
|
73
|
+
axis never reads as the undeclared-axis warning. */
|
|
74
|
+
--wp-axis: #fbbf24;
|
|
75
|
+
--wp-success: #22c55e;
|
|
76
|
+
--wp-warn: #f59e0b;
|
|
77
|
+
--wp-danger: #ef4444;
|
|
78
|
+
--wp-info: #3b82f6;
|
|
79
|
+
|
|
80
|
+
/* Status text — for direct `color:` usage on dark tinted surfaces.
|
|
81
|
+
* Dark: lighter tint than the base status color (red-300 vs red-500) for dark-bg legibility.
|
|
82
|
+
* Light overrides below cascade through --wp-danger etc. which flip to -700 shades. */
|
|
83
|
+
--wp-danger-text: #fca5a5; /* red-300; light override → var(--wp-danger) = red-700 */
|
|
84
|
+
|
|
85
|
+
/* Syntax @ref pill color — pink/magenta, distinct from wildcard KIND violet */
|
|
86
|
+
--wp-kind-ref: #f0abfc; /* fuchsia-300; light override → fuchsia-800 */
|
|
87
|
+
--wp-kind-ref-bg: rgba(192, 38, 211, 0.18);
|
|
88
|
+
|
|
89
|
+
/* Type */
|
|
90
|
+
--wp-font: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
91
|
+
--wp-font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
|
|
92
|
+
|
|
93
|
+
/* Spacing — 4/8 grid. All padding/margin/gap in src/manager/** routes through these. */
|
|
94
|
+
|
|
95
|
+
/* Base spacing (pre-density). The scale a designer reasons about. */
|
|
96
|
+
--wp-space-1-base: 2px;
|
|
97
|
+
--wp-space-2-base: 4px;
|
|
98
|
+
--wp-space-3-base: 6px;
|
|
99
|
+
--wp-space-4-base: 8px;
|
|
100
|
+
--wp-space-5-base: 12px;
|
|
101
|
+
--wp-space-6-base: 16px;
|
|
102
|
+
--wp-space-7-base: 24px;
|
|
103
|
+
--wp-space-8-base: 32px;
|
|
104
|
+
|
|
105
|
+
/* Shared names (2026-10-27): the canvas's motion and soft-border names,
|
|
106
|
+
* so a shared component (components/shared/) reads the same names here.
|
|
107
|
+
* SHARED_TOKENS in components/shared/shared-tokens.test.ts lists them. */
|
|
108
|
+
--wp-motion-quick: 120ms;
|
|
109
|
+
--wp-motion-hover: 150ms;
|
|
110
|
+
--wp-motion-fade: 180ms;
|
|
111
|
+
--wp-motion-swap: 200ms;
|
|
112
|
+
--wp-motion-flip: 280ms;
|
|
113
|
+
--wp-motion-pulse: 420ms;
|
|
114
|
+
--wp-motion-collapse: 450ms;
|
|
115
|
+
--wp-motion-stagger: 60ms;
|
|
116
|
+
--wp-motion-shimmer: 1400ms;
|
|
117
|
+
--wp-motion-curve-collapse: cubic-bezier(0.4, 0, 0.2, 1);
|
|
118
|
+
--wp-motion-curve-flip: cubic-bezier(0.22, 1, 0.36, 1);
|
|
119
|
+
--wp-motion-curve-linear: linear;
|
|
120
|
+
--wp-border-soft: var(--wp-border);
|
|
121
|
+
|
|
122
|
+
/* Density multiplier — comfortable=1, compact=0.85. Set on <html>
|
|
123
|
+
* via uiStore.setDensity. Defaults to 1 here so a fresh boot before
|
|
124
|
+
* the store applies its class reads as comfortable. */
|
|
125
|
+
--wp-density: 1;
|
|
126
|
+
|
|
127
|
+
/* Applied spacing — what consumers reference. Multiplied by density. */
|
|
128
|
+
--wp-space-0: 0;
|
|
129
|
+
--wp-space-1: calc(var(--wp-space-1-base) * var(--wp-density));
|
|
130
|
+
--wp-space-2: calc(var(--wp-space-2-base) * var(--wp-density));
|
|
131
|
+
--wp-space-3: calc(var(--wp-space-3-base) * var(--wp-density));
|
|
132
|
+
--wp-space-4: calc(var(--wp-space-4-base) * var(--wp-density));
|
|
133
|
+
--wp-space-5: calc(var(--wp-space-5-base) * var(--wp-density));
|
|
134
|
+
--wp-space-6: calc(var(--wp-space-6-base) * var(--wp-density));
|
|
135
|
+
--wp-space-7: calc(var(--wp-space-7-base) * var(--wp-density));
|
|
136
|
+
--wp-space-8: calc(var(--wp-space-8-base) * var(--wp-density));
|
|
137
|
+
|
|
138
|
+
/* Mapping rule: prefer the closest token. The audit allows raw 0
|
|
139
|
+
* (= --wp-space-0) and 2px (= --wp-space-1) as direct token values,
|
|
140
|
+
* plus 1px as an off-grid hairline exemption (e.g. 1px borders).
|
|
141
|
+
* Other off-grid values (3px, 5px, 7px, etc.) stay raw only when
|
|
142
|
+
* tagged `audit-exempt` with a justifying comment. */
|
|
143
|
+
|
|
144
|
+
/* Typography scale. line-height paired per step. */
|
|
145
|
+
--wp-text-xs: 11px; --wp-line-xs: 16px;
|
|
146
|
+
--wp-text-sm: 12px; --wp-line-sm: 16px;
|
|
147
|
+
--wp-text-base: 13px; --wp-line-base: 20px;
|
|
148
|
+
--wp-text-md: 14px; --wp-line-md: 20px;
|
|
149
|
+
--wp-text-lg: 16px; --wp-line-lg: 22px;
|
|
150
|
+
--wp-text-xl: 20px; --wp-line-xl: 28px;
|
|
151
|
+
--wp-text-2xl: 24px; --wp-line-2xl: 32px;
|
|
152
|
+
--wp-text-3xl: 30px; --wp-line-3xl: 38px;
|
|
153
|
+
|
|
154
|
+
/* Weights */
|
|
155
|
+
--wp-weight-normal: 400;
|
|
156
|
+
--wp-weight-medium: 500;
|
|
157
|
+
--wp-weight-semibold: 600;
|
|
158
|
+
--wp-weight-bold: 700;
|
|
159
|
+
|
|
160
|
+
/* Sizing — 4/8 grid */
|
|
161
|
+
--wp-radius-sm: 6px;
|
|
162
|
+
--wp-radius: 8px;
|
|
163
|
+
--wp-radius-lg: 12px;
|
|
164
|
+
--wp-radius-xl: 16px;
|
|
165
|
+
/* The roundest a corner may get: fixed corners are written
|
|
166
|
+
* min(Npx, var(--wp-radius-cap, 999px)), so a look (styles/looks.css)
|
|
167
|
+
* squares them by lowering this one name. */
|
|
168
|
+
--wp-radius-cap: 999px;
|
|
169
|
+
/* Alias used by some prototype rules */
|
|
170
|
+
--wp-radius-md: var(--wp-radius);
|
|
171
|
+
|
|
172
|
+
/* Form-control sizing — single canonical scale. */
|
|
173
|
+
|
|
174
|
+
/* Base control heights (pre-density). */
|
|
175
|
+
--wp-control-h-sm-base: 24px;
|
|
176
|
+
--wp-control-h-md-base: 32px;
|
|
177
|
+
--wp-control-h-lg-base: 40px;
|
|
178
|
+
|
|
179
|
+
/* Applied — multiplied by density, rounded to whole pixels. sm never
|
|
180
|
+
drops under the 24px manager hit target, so Compact keeps it at 24. */
|
|
181
|
+
--wp-control-h-sm: max(24px, round(calc(var(--wp-control-h-sm-base) * var(--wp-density)), 1px));
|
|
182
|
+
--wp-control-h-md: round(calc(var(--wp-control-h-md-base) * var(--wp-density)), 1px);
|
|
183
|
+
--wp-control-h-lg: round(calc(var(--wp-control-h-lg-base) * var(--wp-density)), 1px);
|
|
184
|
+
|
|
185
|
+
--wp-input-h: var(--wp-control-h-md); /* unified input height */
|
|
186
|
+
--wp-input-h-sm: var(--wp-control-h-sm);
|
|
187
|
+
--wp-btn-h: var(--wp-control-h-md);
|
|
188
|
+
--wp-btn-h-sm: var(--wp-control-h-sm);
|
|
189
|
+
|
|
190
|
+
/* Focus ring — single declaration reused across all controls. */
|
|
191
|
+
--wp-focus-ring: 0 0 0 3px rgba(99, 102, 241, 0.45);
|
|
192
|
+
/* Text and marks on a solid accent fill, and over a picture: the same in
|
|
193
|
+
both themes. --wp-scrim darkens a picture enough to read on it. */
|
|
194
|
+
--wp-on-accent: #fff;
|
|
195
|
+
--wp-on-media: #fff;
|
|
196
|
+
--wp-scrim: rgba(0, 0, 0, 0.55);
|
|
197
|
+
/* Brand colours of services we link to: the same in both themes. */
|
|
198
|
+
--wp-brand-discord: #5865f2;
|
|
199
|
+
|
|
200
|
+
/* Error treatment */
|
|
201
|
+
--wp-error-border: var(--wp-danger);
|
|
202
|
+
--wp-error-text: var(--wp-danger);
|
|
203
|
+
|
|
204
|
+
--wp-sidebar-w: 232px;
|
|
205
|
+
--wp-topbar-h: 48px;
|
|
206
|
+
|
|
207
|
+
--wp-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
|
|
208
|
+
--wp-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
209
|
+
--wp-shadow-md: 0 1px 2px rgba(0, 0, 0, 0.24), 0 4px 12px rgba(0, 0, 0, 0.28);
|
|
210
|
+
--wp-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.4);
|
|
211
|
+
--wp-shadow-xl: 0 16px 40px rgba(0, 0, 0, 0.45);
|
|
212
|
+
|
|
213
|
+
/* Elevation — semantic aliases over the shadow scale. Pick by
|
|
214
|
+
* purpose (resting, popover, modal) rather than visual weight.
|
|
215
|
+
* elev-0 flat (no shadow)
|
|
216
|
+
* elev-1 resting cards, list items
|
|
217
|
+
* elev-2 popovers, dropdowns, hover-lift
|
|
218
|
+
* elev-3 modals
|
|
219
|
+
* elev-4 full-page overlays (rare)
|
|
220
|
+
*/
|
|
221
|
+
--wp-elev-0: none;
|
|
222
|
+
--wp-elev-1: var(--wp-shadow-sm);
|
|
223
|
+
--wp-elev-2: var(--wp-shadow-md);
|
|
224
|
+
--wp-elev-3: var(--wp-shadow-lg);
|
|
225
|
+
--wp-elev-4: var(--wp-shadow-xl);
|
|
226
|
+
|
|
227
|
+
/* Overlays / drawers */
|
|
228
|
+
--wp-overlay-bg: rgba(0, 0, 0, 0.45);
|
|
229
|
+
|
|
230
|
+
/* Phase 4 — row hover + scrollbar thumb + input-shade tokens.
|
|
231
|
+
* Pre-fix these were inline `rgba(255,255,255,0.02)` / `rgba(0,0,0,0.32)`
|
|
232
|
+
* literals across components; tokenize so the light theme override
|
|
233
|
+
* below can flip the tint instead of leaving white-on-white or
|
|
234
|
+
* black-on-white surfaces. */
|
|
235
|
+
--wp-row-hover: rgba(255,255,255,0.02);
|
|
236
|
+
--wp-row-active: rgba(79,70,229,0.04);
|
|
237
|
+
--wp-scrollbar-thumb: rgba(255,255,255,0.08);
|
|
238
|
+
--wp-scrollbar-thumb-hover: rgba(255,255,255,0.16);
|
|
239
|
+
--wp-input-shade: rgba(0,0,0,0.32);
|
|
240
|
+
|
|
241
|
+
/* Pipeline / kind stripe accents */
|
|
242
|
+
--wp-kind-stripe-w: 3px;
|
|
243
|
+
|
|
244
|
+
/* Rich-text token colors (used by RichTextInput / RichTextPreview) */
|
|
245
|
+
--wp-rt-token-good: #34d399;
|
|
246
|
+
--wp-rt-token-good-bg: color-mix(in oklab, #10b981 12%, transparent);
|
|
247
|
+
--wp-rt-token-mut: #fb923c;
|
|
248
|
+
--wp-rt-token-mut-bg: color-mix(in oklab, #f97316 12%, transparent);
|
|
249
|
+
|
|
250
|
+
/* Status colors — `modified` retained for the SPA ImportExport "mod"
|
|
251
|
+
* badge + the in-graph ContextWidget modified-dot, both of which
|
|
252
|
+
* mean "user diff from upstream". Drift state in ContextWidget reuses
|
|
253
|
+
* `--wp-warn` for SPA-IO `--exists` parity (see ContextWidget.vue
|
|
254
|
+
* `.wp-mod-dot--drift`). */
|
|
255
|
+
--wp-status-modified: #fb923c;
|
|
256
|
+
|
|
257
|
+
/* WP node identity accent — brand teal, deliberately distinct from the
|
|
258
|
+
* 5 module kind colors so a node icon never reads as a module kind. */
|
|
259
|
+
--wp-node: var(--wp-brand-3); /* #2dd4bf */
|
|
260
|
+
|
|
261
|
+
/* Kept as a name for older call sites; Orbit has no gradients, so it is flat. */
|
|
262
|
+
--wp-accent-gradient: var(--wp-accent-500);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/* `.var-N` color classes — emitted by `varColorClass(name)` in
|
|
266
|
+
* src/components/shared/var-color.ts. Same definitions live in
|
|
267
|
+
* extension theme.css; mirrored here so the manager surface paints
|
|
268
|
+
* them when mounting Context-side section components. */
|
|
269
|
+
.var-1 { color: var(--wp-var-1); }
|
|
270
|
+
.var-2 { color: var(--wp-var-2); }
|
|
271
|
+
.var-3 { color: var(--wp-var-3); }
|
|
272
|
+
.var-4 { color: var(--wp-var-4); }
|
|
273
|
+
.var-5 { color: var(--wp-var-5); }
|
|
274
|
+
.var-6 { color: var(--wp-var-6); }
|
|
275
|
+
.var-7 { color: var(--wp-var-7); }
|
|
276
|
+
.var-8 { color: var(--wp-var-8); }
|
|
277
|
+
|
|
278
|
+
* { box-sizing: border-box; }
|
|
279
|
+
|
|
280
|
+
:root, .wp-theme-dark {
|
|
281
|
+
color-scheme: dark;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.wp-theme-light {
|
|
285
|
+
color-scheme: light;
|
|
286
|
+
--wp-bg: #f7f7fb;
|
|
287
|
+
--wp-bg-1: #ffffff;
|
|
288
|
+
--wp-bg-2: #ffffff;
|
|
289
|
+
--wp-bg-3: #f1f1f6;
|
|
290
|
+
--wp-bg-4: #e6e6ee;
|
|
291
|
+
|
|
292
|
+
--wp-border: rgba(15,15,30,0.10);
|
|
293
|
+
--wp-border-strong: rgba(15,15,30,0.18);
|
|
294
|
+
|
|
295
|
+
--wp-text: #1a1a25;
|
|
296
|
+
--wp-text-muted: #5a5a6a;
|
|
297
|
+
/* Light theme: dim was #8b8b98 (~3.2:1 vs #f7f7fb). Bumped to #6e6e7e
|
|
298
|
+
* for WCAG AA on the darkest light-mode surface. */
|
|
299
|
+
--wp-text-dim: #6e6e7e;
|
|
300
|
+
|
|
301
|
+
--wp-shadow-sm: 0 1px 2px rgba(15, 15, 30, 0.06);
|
|
302
|
+
--wp-shadow: 0 2px 8px rgba(15, 15, 30, 0.08);
|
|
303
|
+
--wp-shadow-md: 0 1px 2px rgba(15, 15, 30, 0.06), 0 4px 12px rgba(15, 15, 30, 0.10);
|
|
304
|
+
--wp-shadow-lg: 0 8px 24px rgba(15, 15, 30, 0.12);
|
|
305
|
+
--wp-shadow-xl: 0 16px 40px rgba(15, 15, 30, 0.16);
|
|
306
|
+
|
|
307
|
+
/* Phase 4 — flip the dark-theme white tints to dark tints so subtle
|
|
308
|
+
* surfaces remain visible on light bg. */
|
|
309
|
+
--wp-row-hover: rgba(15,15,30,0.04);
|
|
310
|
+
--wp-row-active: rgba(79,70,229,0.08);
|
|
311
|
+
--wp-scrollbar-thumb: rgba(15,15,30,0.14);
|
|
312
|
+
--wp-scrollbar-thumb-hover: rgba(15,15,30,0.22);
|
|
313
|
+
--wp-input-shade: rgba(15,15,30,0.06);
|
|
314
|
+
|
|
315
|
+
/* Light theme needs darker accent text for contrast on near-white surfaces */
|
|
316
|
+
--wp-accent-text: var(--wp-accent-700);
|
|
317
|
+
--wp-accent-text-strong: var(--wp-accent-800);
|
|
318
|
+
|
|
319
|
+
/* Status colors — dark amber/green/red/blue are ~2.5–4:1 on white (fail AA for text).
|
|
320
|
+
* Swap to -700 / -800 level shades that clear 4.5:1. Values from Tailwind palette. */
|
|
321
|
+
--wp-success: #15803d; /* green-700 4.55:1 on white */
|
|
322
|
+
--wp-warn: #b45309; /* amber-700 4.75:1 on white */
|
|
323
|
+
--wp-danger: #b91c1c; /* red-700 5.25:1 on white */
|
|
324
|
+
--wp-info: #1d4ed8; /* blue-700 5.53:1 on white */
|
|
325
|
+
|
|
326
|
+
/* Status-text: in light mode, override to the same -700 shade as the base token
|
|
327
|
+
* (dark has lighter pastels; light has deeper shades — both are correct for their surface) */
|
|
328
|
+
--wp-danger-text: var(--wp-danger); /* red-700 via cascade */
|
|
329
|
+
|
|
330
|
+
/* Overlay — lighter scrim so light bg beneath still registers as dimmed */
|
|
331
|
+
--wp-overlay-bg: rgba(15, 15, 30, 0.35);
|
|
332
|
+
|
|
333
|
+
/* Bundle default — slate-700 for AA contrast on near-white.
|
|
334
|
+
* Slate signals "container/structural" vs the kind palette which
|
|
335
|
+
* signals "module type". Passes ~9.2:1 on white. */
|
|
336
|
+
--wp-bundle-default: #334155;
|
|
337
|
+
|
|
338
|
+
/* Ref pill — deeper magenta for light surfaces */
|
|
339
|
+
--wp-kind-ref: #86198f; /* fuchsia-800 5.03:1 on white */
|
|
340
|
+
--wp-kind-ref-bg: rgba(192, 38, 211, 0.13);
|
|
341
|
+
|
|
342
|
+
/* Rich-text inline tokens — flip bright pastels to readable dark shades */
|
|
343
|
+
--wp-rt-token-good: #166534; /* green-800 4.80:1 on white */
|
|
344
|
+
--wp-rt-token-good-bg: color-mix(in oklab, #166534 12%, transparent);
|
|
345
|
+
--wp-rt-token-mut: #9a3412; /* orange-800 5.19:1 on white */
|
|
346
|
+
--wp-rt-token-mut-bg: color-mix(in oklab, #9a3412 12%, transparent);
|
|
347
|
+
|
|
348
|
+
/* Status-modified badge (ImportExport mod indicator) — orange-800 for light */
|
|
349
|
+
--wp-status-modified: #c2410c; /* orange-700 4.63:1 on white */
|
|
350
|
+
|
|
351
|
+
/* teal-700 — AA on near-white (4.54:1) */
|
|
352
|
+
--wp-node: #0f766e;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/* ---------- Light-theme kind-color overrides ----------
|
|
356
|
+
Dark-theme kind values are high-chroma pastels that fail WCAG AA on white/near-white.
|
|
357
|
+
These darker shades pass AA for both page-surface usage (icons, borders, dots ≥3.0)
|
|
358
|
+
and chip-text usage (color on 22% tint background ≥4.5). Verified 2026-05-18.
|
|
359
|
+
See docs/superpowers/specs/2026-05-18-kind-color-audit.md.
|
|
360
|
+
|
|
361
|
+
Selector is `html.wp-theme-light` (specificity 0,1,1) — beats the
|
|
362
|
+
later `:root` kind-color block (specificity 0,1,0) further down the
|
|
363
|
+
file. Without the `html` qualifier the second `:root` definition
|
|
364
|
+
would clobber these overrides through plain source-order cascade. */
|
|
365
|
+
html.wp-theme-light {
|
|
366
|
+
--wp-kind-wildcard: #6d28d9; /* violet-700 — chip 4.91:1 on white */
|
|
367
|
+
--wp-kind-wildcard-bg: rgba(109, 40, 217, 0.12);
|
|
368
|
+
/* Fixed moved off cyan-800 — too close to combine emerald-800 in light. */
|
|
369
|
+
--wp-kind-fixed: #1d4ed8; /* blue-700 — chip 6.61:1 on white */
|
|
370
|
+
--wp-kind-fixed-bg: rgba(29, 78, 216, 0.12);
|
|
371
|
+
--wp-kind-combine: #065f46; /* emerald-800 — chip 5.37:1 on white */
|
|
372
|
+
--wp-kind-combine-bg: rgba(6, 95, 70, 0.12);
|
|
373
|
+
--wp-kind-derivation: #92400e; /* amber-800 — chip 4.99:1 on white */
|
|
374
|
+
--wp-kind-derivation-bg: rgba(146, 64, 14, 0.12);
|
|
375
|
+
--wp-kind-constraint: #9d174d; /* pink-800 — chip 5.29:1 on white */
|
|
376
|
+
--wp-kind-constraint-bg: rgba(157, 23, 77, 0.12);
|
|
377
|
+
|
|
378
|
+
/* Constraint matrix source/target — darker shades for light bg. */
|
|
379
|
+
--wp-constraint-source: #7c3aed; /* violet-600 — 6.16:1 on white */
|
|
380
|
+
--wp-constraint-source-text: #6d28d9;
|
|
381
|
+
--wp-constraint-target: #0891b2; /* cyan-600 — 4.97:1 on white */
|
|
382
|
+
--wp-constraint-target-text: #155e75;
|
|
383
|
+
|
|
384
|
+
/* Variable hash colors — dark pastel defaults fail on near-white;
|
|
385
|
+
* shift to *-700 family for AA contrast on the light page surface. */
|
|
386
|
+
--wp-var-1: #0369a1; /* sky-700 4.84:1 on white */
|
|
387
|
+
--wp-var-2: #b45309; /* amber-700 4.85:1 on white */
|
|
388
|
+
--wp-var-3: #047857; /* emerald-700 4.91:1 on white */
|
|
389
|
+
--wp-var-4: #be185d; /* rose-700 5.78:1 on white */
|
|
390
|
+
--wp-var-5: #c2410c; /* orange-700 4.93:1 on white */
|
|
391
|
+
--wp-var-6: #6d28d9; /* violet-700 4.91:1 on white */
|
|
392
|
+
--wp-var-7: #0e7490; /* cyan-700 5.24:1 on white */
|
|
393
|
+
--wp-var-8: #b91c1c; /* red-700 6.74:1 on white */
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/* Constraint source/target — dark-theme defaults at :root above. */
|
|
397
|
+
:root {
|
|
398
|
+
--wp-constraint-source: #c084fc; /* purple-400 */
|
|
399
|
+
--wp-constraint-source-text: #d8b4fe; /* purple-300 */
|
|
400
|
+
--wp-constraint-target: #22d3ee; /* cyan-400 */
|
|
401
|
+
--wp-constraint-target-text: #67e8f9; /* cyan-300 */
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.wp-theme-light {
|
|
405
|
+
/* Slightly tighter alpha on light surfaces keeps the ring at the same
|
|
406
|
+
* perceived intensity as dark-mode's 0.35 on dark bg. */
|
|
407
|
+
--wp-focus-ring: 0 0 0 3px rgba(79, 70, 229, 0.35);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.wp-theme-light ::-webkit-scrollbar-thumb { background: rgba(15,15,30,0.14); }
|
|
411
|
+
.wp-theme-light ::-webkit-scrollbar-thumb:hover { background: rgba(15,15,30,0.22); }
|
|
412
|
+
|
|
413
|
+
/* Theme-switching: kill ALL transitions/animations briefly so dark↔light flips in one paint */
|
|
414
|
+
.wp-theme-switching,
|
|
415
|
+
.wp-theme-switching *,
|
|
416
|
+
.wp-theme-switching *::before,
|
|
417
|
+
.wp-theme-switching *::after {
|
|
418
|
+
transition: none !important;
|
|
419
|
+
animation-duration: 0s !important;
|
|
420
|
+
animation-delay: 0s !important;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
html, body, #app, #root {
|
|
424
|
+
margin: 0;
|
|
425
|
+
padding: 0;
|
|
426
|
+
background: var(--wp-bg);
|
|
427
|
+
color: var(--wp-text);
|
|
428
|
+
font-family: var(--wp-font);
|
|
429
|
+
font-size: 13.5px;
|
|
430
|
+
line-height: 1.45;
|
|
431
|
+
-webkit-font-smoothing: antialiased;
|
|
432
|
+
height: 100%;
|
|
433
|
+
overflow: hidden;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
button { font: inherit; color: inherit; }
|
|
437
|
+
input, textarea, select { font: inherit; }
|
|
438
|
+
|
|
439
|
+
::-webkit-scrollbar { width: 10px; height: 10px; }
|
|
440
|
+
::-webkit-scrollbar-track { background: transparent; }
|
|
441
|
+
::-webkit-scrollbar-thumb { background: var(--wp-scrollbar-thumb, rgba(255,255,255,0.08)); border-radius: var(--wp-radius-cap, 999px); }
|
|
442
|
+
::-webkit-scrollbar-thumb:hover { background: var(--wp-scrollbar-thumb-hover, rgba(255,255,255,0.16)); }
|
|
443
|
+
|
|
444
|
+
/* ---------- App shell ---------- */
|
|
445
|
+
.wp-app {
|
|
446
|
+
display: grid;
|
|
447
|
+
grid-template-rows: var(--wp-topbar-h) 1fr;
|
|
448
|
+
height: 100vh;
|
|
449
|
+
width: 100vw;
|
|
450
|
+
background: var(--wp-bg);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
.wp-topbar {
|
|
454
|
+
display: flex;
|
|
455
|
+
align-items: center;
|
|
456
|
+
gap: 12px;
|
|
457
|
+
padding: 0 14px;
|
|
458
|
+
border-bottom: 1px solid var(--wp-border);
|
|
459
|
+
background: var(--wp-bg-1);
|
|
460
|
+
height: var(--wp-topbar-h);
|
|
461
|
+
position: relative;
|
|
462
|
+
z-index: 30;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
.wp-topbar__brand {
|
|
466
|
+
display: flex;
|
|
467
|
+
align-items: center;
|
|
468
|
+
gap: 10px;
|
|
469
|
+
font-weight: 600;
|
|
470
|
+
font-size: 14px;
|
|
471
|
+
letter-spacing: -0.01em;
|
|
472
|
+
}
|
|
473
|
+
.wp-topbar__version {
|
|
474
|
+
font-family: var(--wp-font-mono);
|
|
475
|
+
font-size: 10.5px;
|
|
476
|
+
color: var(--wp-text-dim);
|
|
477
|
+
padding: 2px 6px;
|
|
478
|
+
border: 1px solid var(--wp-border);
|
|
479
|
+
border-radius: var(--wp-radius-cap, 999px);
|
|
480
|
+
letter-spacing: 0.02em;
|
|
481
|
+
}
|
|
482
|
+
.wp-topbar__spacer { flex: 1; }
|
|
483
|
+
|
|
484
|
+
.wp-topbar__icon-btn {
|
|
485
|
+
width: 30px; height: 30px;
|
|
486
|
+
border-radius: min(8px, var(--wp-radius-cap, 999px));
|
|
487
|
+
display: inline-grid; place-items: center;
|
|
488
|
+
background: transparent; border: 1px solid transparent;
|
|
489
|
+
color: var(--wp-text-muted);
|
|
490
|
+
cursor: pointer;
|
|
491
|
+
transition: background .15s, color .15s, border-color .15s;
|
|
492
|
+
}
|
|
493
|
+
.wp-topbar__icon-btn:hover {
|
|
494
|
+
background: var(--wp-bg-3);
|
|
495
|
+
color: var(--wp-text);
|
|
496
|
+
border-color: var(--wp-border);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/* ---------- Body grid ---------- */
|
|
500
|
+
.wp-body {
|
|
501
|
+
display: grid;
|
|
502
|
+
grid-template-columns: var(--wp-sidebar-w) 1fr;
|
|
503
|
+
min-height: 0;
|
|
504
|
+
}
|
|
505
|
+
.wp-body[data-collapsed="true"] { grid-template-columns: 56px 1fr; }
|
|
506
|
+
|
|
507
|
+
/* ---------- Sidebar ---------- */
|
|
508
|
+
.wp-sidebar {
|
|
509
|
+
border-right: 1px solid var(--wp-border);
|
|
510
|
+
background: var(--wp-bg-1);
|
|
511
|
+
padding: 10px 8px;
|
|
512
|
+
overflow-y: auto;
|
|
513
|
+
display: flex; flex-direction: column;
|
|
514
|
+
gap: 2px;
|
|
515
|
+
min-height: 0;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
.wp-sidebar__section {
|
|
519
|
+
font-size: 10px;
|
|
520
|
+
font-weight: 600;
|
|
521
|
+
letter-spacing: 0.08em;
|
|
522
|
+
text-transform: uppercase;
|
|
523
|
+
color: var(--wp-text-dim);
|
|
524
|
+
padding: 14px 10px 6px;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
.wp-nav {
|
|
528
|
+
display: flex; align-items: center; gap: 10px;
|
|
529
|
+
padding: 7px 10px;
|
|
530
|
+
border-radius: min(7px, var(--wp-radius-cap, 999px));
|
|
531
|
+
color: var(--wp-text-muted);
|
|
532
|
+
cursor: pointer;
|
|
533
|
+
font-size: 13px;
|
|
534
|
+
user-select: none;
|
|
535
|
+
background: transparent;
|
|
536
|
+
border: 1px solid transparent;
|
|
537
|
+
text-align: left;
|
|
538
|
+
font-family: inherit;
|
|
539
|
+
transition: background .12s, color .12s, border-color .12s;
|
|
540
|
+
position: relative;
|
|
541
|
+
}
|
|
542
|
+
.wp-nav:hover { background: var(--wp-bg-3); color: var(--wp-text); }
|
|
543
|
+
.wp-nav[data-active] {
|
|
544
|
+
background: color-mix(in oklab, var(--wp-accent-500) 14%, transparent);
|
|
545
|
+
color: var(--wp-text);
|
|
546
|
+
border-color: color-mix(in oklab, var(--wp-accent-500) 30%, transparent);
|
|
547
|
+
}
|
|
548
|
+
/* Active-row gradient strip lives in AppSidebar.vue scoped CSS (presence selector). */
|
|
549
|
+
.wp-nav__icon { width: 16px; flex: 0 0 16px; display: grid; place-items: center; color: inherit; }
|
|
550
|
+
.wp-nav__label { flex: 1; white-space: nowrap; }
|
|
551
|
+
.wp-nav__badge {
|
|
552
|
+
font-size: 9.5px;
|
|
553
|
+
letter-spacing: 0.04em;
|
|
554
|
+
text-transform: uppercase;
|
|
555
|
+
padding: 1.5px 6px;
|
|
556
|
+
border-radius: var(--wp-radius-cap, 999px);
|
|
557
|
+
background: var(--wp-bg-3);
|
|
558
|
+
color: var(--wp-text-dim);
|
|
559
|
+
border: 1px solid var(--wp-border);
|
|
560
|
+
font-weight: 600;
|
|
561
|
+
}
|
|
562
|
+
.wp-nav__ext { color: var(--wp-text-dim); width: 12px; }
|
|
563
|
+
|
|
564
|
+
/* ---------- Content area ---------- */
|
|
565
|
+
.wp-content {
|
|
566
|
+
overflow: auto;
|
|
567
|
+
padding: 18px 22px 40px;
|
|
568
|
+
min-width: 0;
|
|
569
|
+
--wp-content-px: 22px;
|
|
570
|
+
--wp-content-pb: 40px;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
.wp-page {
|
|
574
|
+
max-width: 1200px;
|
|
575
|
+
margin: 0 auto;
|
|
576
|
+
display: flex; flex-direction: column;
|
|
577
|
+
gap: 16px;
|
|
578
|
+
min-height: 100%;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/* Fill-mode page: instead of growing the parent's scroll, become a fixed-height
|
|
582
|
+
flex column whose children opt-in to scrolling (typically a table-wrap). */
|
|
583
|
+
.wp-page--fill {
|
|
584
|
+
height: 100%;
|
|
585
|
+
min-height: 0;
|
|
586
|
+
}
|
|
587
|
+
.wp-page--fill > .wp-table-wrap--scroll {
|
|
588
|
+
flex: 1 1 auto;
|
|
589
|
+
min-height: 0;
|
|
590
|
+
overflow: auto;
|
|
591
|
+
}
|
|
592
|
+
.wp-table--sticky-head thead th {
|
|
593
|
+
position: sticky;
|
|
594
|
+
top: 0;
|
|
595
|
+
z-index: 1;
|
|
596
|
+
background: var(--wp-bg-2);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
.wp-page__header {
|
|
600
|
+
display: flex; align-items: flex-end; justify-content: space-between;
|
|
601
|
+
gap: 16px;
|
|
602
|
+
padding-bottom: 4px;
|
|
603
|
+
}
|
|
604
|
+
.wp-page__title-wrap { display: flex; flex-direction: column; gap: 4px; }
|
|
605
|
+
.wp-page__title { font-size: 20px; font-weight: 600; letter-spacing: -0.01em; margin: 0; }
|
|
606
|
+
.wp-page__subtitle { color: var(--wp-text-muted); font-size: 12.5px; margin: 0; max-width: 720px; }
|
|
607
|
+
|
|
608
|
+
.wp-breadcrumb {
|
|
609
|
+
display: inline-flex; align-items: center; gap: 6px;
|
|
610
|
+
color: var(--wp-text-muted); font-size: 12px;
|
|
611
|
+
background: none; border: none; padding: 0; cursor: pointer;
|
|
612
|
+
margin-bottom: 4px;
|
|
613
|
+
}
|
|
614
|
+
.wp-breadcrumb:hover { color: var(--wp-text); }
|
|
615
|
+
|
|
616
|
+
/* ---------- Cards / panels ---------- */
|
|
617
|
+
.wp-card {
|
|
618
|
+
background: var(--wp-bg-1);
|
|
619
|
+
border: 1px solid var(--wp-border);
|
|
620
|
+
border-radius: var(--wp-radius-lg);
|
|
621
|
+
}
|
|
622
|
+
.wp-card__header {
|
|
623
|
+
padding: 12px 14px;
|
|
624
|
+
border-bottom: 1px solid var(--wp-border);
|
|
625
|
+
display: flex; align-items: center; gap: 10px;
|
|
626
|
+
/* Wrap only engages once the row genuinely cannot fit, which previously
|
|
627
|
+
meant the widest flexible child collapsed instead — the derivation card
|
|
628
|
+
has four buttons and squeezed its filter input to 18px in a narrow
|
|
629
|
+
window. A header that fits is unaffected. */
|
|
630
|
+
flex-wrap: wrap;
|
|
631
|
+
}
|
|
632
|
+
.wp-card__title-wrap { display: flex; flex-direction: column; gap: 1px; }
|
|
633
|
+
/* A card's name reads as its title: normal case, 14px semibold, full text
|
|
634
|
+
* colour. Uppercase stays for small group labels (Field, table heads). */
|
|
635
|
+
.wp-card__title { font-size: 14px; line-height: 1.35; color: var(--wp-text); margin: 0; font-weight: 600; letter-spacing: -0.005em; }
|
|
636
|
+
.wp-card__subtitle {
|
|
637
|
+
font-size: 11.5px;
|
|
638
|
+
color: var(--wp-text-dim);
|
|
639
|
+
margin: 0;
|
|
640
|
+
font-weight: 400;
|
|
641
|
+
}
|
|
642
|
+
.wp-card__body { padding: 14px; }
|
|
643
|
+
/* Sticky-header cards pin their header + `subheader` slot (e.g. a bulk-edit
|
|
644
|
+
* toolbar) to the top of the scroll region so a long list's actions (Add
|
|
645
|
+
* option, Bulk edit, the selection toolbar, …) stay reachable at the bottom.
|
|
646
|
+
* The whole `.wp-card__sticky` region sticks as one so its sub-toolbar can't
|
|
647
|
+
* be left behind. Card.vue publishes `--wp-card-header-h` (the region's
|
|
648
|
+
* measured height) so a sticky <thead> below offsets right under it. Needs an
|
|
649
|
+
* opaque bg (header/subheader are transparent). */
|
|
650
|
+
.wp-card--sticky-header > .wp-card__sticky {
|
|
651
|
+
position: sticky;
|
|
652
|
+
/* -1px, not 0: the scroll container's top can land on a fractional device
|
|
653
|
+
* pixel (measured e.g. 152.39 at dpr 1), so pinning exactly at top:0 leaves
|
|
654
|
+
* a sub-pixel sliver above the opaque header through which the scrolled
|
|
655
|
+
* content behind bleeds as a faint ghost line. Overlapping the scroll edge
|
|
656
|
+
* by 1px (the extra px is clipped by the container's overflow and absorbed
|
|
657
|
+
* by the header's 12px top padding) guarantees the bg covers that seam at
|
|
658
|
+
* any DPR. The sticky <thead> below tracks the same -1px. */
|
|
659
|
+
top: -1px;
|
|
660
|
+
z-index: 5;
|
|
661
|
+
background: var(--wp-bg-1);
|
|
662
|
+
}
|
|
663
|
+
/* Sticky column header inside a sticky-header card — pins right under the
|
|
664
|
+
* toolbar. Chromium won't scroll-anchor a table CELL here, but sticking the
|
|
665
|
+
* <thead> element does; th gets an opaque bg so rows don't bleed through.
|
|
666
|
+
* Shared by the wildcard + fixed-values option tables. The -1px mirrors the
|
|
667
|
+
* header's overlap above so the two stay flush (no gap for rows to bleed). */
|
|
668
|
+
.wp-card--sticky-header .wp-options-table thead {
|
|
669
|
+
position: sticky;
|
|
670
|
+
top: calc(var(--wp-card-header-h, 53px) - 1px);
|
|
671
|
+
z-index: 4;
|
|
672
|
+
}
|
|
673
|
+
.wp-card--sticky-header .wp-options-table thead th {
|
|
674
|
+
background: var(--wp-bg-1);
|
|
675
|
+
box-shadow: inset 0 -1px 0 var(--wp-border);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/* Quick-select preset chip — shared by the import/export presets bars
|
|
679
|
+
* (ExportTab + ImportPicker). Layout of the bar itself stays per-component;
|
|
680
|
+
* this is just the button atom. */
|
|
681
|
+
.wp-preset-btn {
|
|
682
|
+
background: var(--wp-bg-3);
|
|
683
|
+
border: 1px solid var(--wp-border);
|
|
684
|
+
color: var(--wp-text);
|
|
685
|
+
font-family: var(--wp-font);
|
|
686
|
+
font-size: var(--wp-text-sm);
|
|
687
|
+
padding: 4px 11px;
|
|
688
|
+
border-radius: var(--wp-radius-sm);
|
|
689
|
+
cursor: pointer;
|
|
690
|
+
display: inline-flex;
|
|
691
|
+
align-items: center;
|
|
692
|
+
gap: 6px;
|
|
693
|
+
font-weight: 500;
|
|
694
|
+
}
|
|
695
|
+
.wp-preset-btn:hover:not(:disabled) {
|
|
696
|
+
background: var(--wp-bg-4);
|
|
697
|
+
border-color: var(--wp-border-strong);
|
|
698
|
+
}
|
|
699
|
+
.wp-preset-btn:disabled {
|
|
700
|
+
opacity: 0.4;
|
|
701
|
+
cursor: not-allowed;
|
|
702
|
+
}
|
|
703
|
+
.wp-preset-btn .pi {
|
|
704
|
+
font-size: 10px;
|
|
705
|
+
color: var(--wp-text-muted);
|
|
706
|
+
}
|
|
707
|
+
.wp-preset-btn:focus-visible {
|
|
708
|
+
outline: 2px solid var(--wp-accent-500);
|
|
709
|
+
outline-offset: 2px;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
/* ---------- Buttons ----------
|
|
713
|
+
* The .wp-btn rules live in kit/button.css, shared with the
|
|
714
|
+
* canvas Button (component standard, rule 8). main.ts loads it right after
|
|
715
|
+
* this file. */
|
|
716
|
+
|
|
717
|
+
/* ---------- Inputs ---------- */
|
|
718
|
+
.wp-input,
|
|
719
|
+
.wp-select,
|
|
720
|
+
.wp-textarea {
|
|
721
|
+
height: var(--wp-input-h);
|
|
722
|
+
width: 100%;
|
|
723
|
+
background: var(--wp-bg-2);
|
|
724
|
+
color: var(--wp-text);
|
|
725
|
+
border: 1px solid var(--wp-border);
|
|
726
|
+
border-radius: var(--wp-radius-sm);
|
|
727
|
+
padding: 0 10px;
|
|
728
|
+
font-size: 12.5px;
|
|
729
|
+
outline: none;
|
|
730
|
+
transition: border-color .12s, background .12s, box-shadow .12s;
|
|
731
|
+
}
|
|
732
|
+
.wp-textarea {
|
|
733
|
+
height: auto;
|
|
734
|
+
padding: 8px 10px;
|
|
735
|
+
resize: vertical;
|
|
736
|
+
min-height: var(--wp-input-h);
|
|
737
|
+
line-height: 1.5;
|
|
738
|
+
}
|
|
739
|
+
.wp-input:focus-visible,
|
|
740
|
+
.wp-select:focus-visible,
|
|
741
|
+
.wp-textarea:focus-visible {
|
|
742
|
+
border-color: var(--wp-accent-500);
|
|
743
|
+
box-shadow: var(--wp-focus-ring);
|
|
744
|
+
background: var(--wp-bg-1);
|
|
745
|
+
}
|
|
746
|
+
/* Retain :focus fallback for browsers/contexts that don't support :focus-visible */
|
|
747
|
+
.wp-input:focus,
|
|
748
|
+
.wp-select:focus,
|
|
749
|
+
.wp-textarea:focus {
|
|
750
|
+
border-color: var(--wp-accent-500);
|
|
751
|
+
box-shadow: var(--wp-focus-ring);
|
|
752
|
+
background: var(--wp-bg-1);
|
|
753
|
+
}
|
|
754
|
+
/* Error state on standalone controls (when not wrapped in .wp-field) */
|
|
755
|
+
.wp-input[aria-invalid="true"],
|
|
756
|
+
.wp-select[aria-invalid="true"],
|
|
757
|
+
.wp-textarea[aria-invalid="true"] {
|
|
758
|
+
border-color: var(--wp-error-border);
|
|
759
|
+
}
|
|
760
|
+
.wp-input::placeholder, .wp-textarea::placeholder { color: var(--wp-text-dim); }
|
|
761
|
+
.wp-input--sm, .wp-select--sm { height: var(--wp-input-h-sm); font-size: 12px; padding: 0 8px; }
|
|
762
|
+
.wp-input--lg { height: var(--wp-control-h-lg); font-size: 13.5px; padding: 0 12px; }
|
|
763
|
+
/* Readonly: shown, not editable. Dimmer fill, no focus ring (Input adds a lock). */
|
|
764
|
+
.wp-input[readonly],
|
|
765
|
+
.wp-textarea[readonly] {
|
|
766
|
+
background: var(--wp-bg-1);
|
|
767
|
+
color: var(--wp-text-muted);
|
|
768
|
+
border-style: dashed;
|
|
769
|
+
cursor: default;
|
|
770
|
+
}
|
|
771
|
+
.wp-input[readonly]:focus,
|
|
772
|
+
.wp-input[readonly]:focus-visible,
|
|
773
|
+
.wp-textarea[readonly]:focus,
|
|
774
|
+
.wp-textarea[readonly]:focus-visible { box-shadow: none; border-color: var(--wp-border-strong); background: var(--wp-bg-1); }
|
|
775
|
+
.wp-input:disabled,
|
|
776
|
+
.wp-textarea:disabled { opacity: 0.45; cursor: not-allowed; }
|
|
777
|
+
/* Custom select trigger button — flex layout so label + spacer + chevron align. */
|
|
778
|
+
.wp-select {
|
|
779
|
+
display: flex;
|
|
780
|
+
align-items: center;
|
|
781
|
+
gap: 4px;
|
|
782
|
+
text-align: left;
|
|
783
|
+
cursor: pointer;
|
|
784
|
+
appearance: none;
|
|
785
|
+
-webkit-appearance: none;
|
|
786
|
+
box-sizing: border-box;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
.wp-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
|
|
790
|
+
.wp-field__label {
|
|
791
|
+
font-size: 11px;
|
|
792
|
+
letter-spacing: 0.04em;
|
|
793
|
+
text-transform: uppercase;
|
|
794
|
+
color: var(--wp-text-muted);
|
|
795
|
+
font-weight: 600;
|
|
796
|
+
}
|
|
797
|
+
.wp-field__hint { font-size: 11.5px; color: var(--wp-text-dim); }
|
|
798
|
+
.wp-field__error { font-size: 11.5px; color: var(--wp-error-text); }
|
|
799
|
+
.wp-field--error .wp-input,
|
|
800
|
+
.wp-field--error .wp-textarea,
|
|
801
|
+
.wp-field--error .wp-select,
|
|
802
|
+
.wp-field--error .wp-input-group {
|
|
803
|
+
border-color: var(--wp-error-border);
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
.wp-input-group {
|
|
807
|
+
display: inline-flex; align-items: stretch; width: 100%;
|
|
808
|
+
border: 1px solid var(--wp-border); border-radius: var(--wp-radius-sm);
|
|
809
|
+
background: var(--wp-bg-2);
|
|
810
|
+
overflow: hidden;
|
|
811
|
+
height: var(--wp-input-h);
|
|
812
|
+
min-height: var(--wp-input-h);
|
|
813
|
+
flex-shrink: 0;
|
|
814
|
+
transition: border-color .12s, box-shadow .12s;
|
|
815
|
+
}
|
|
816
|
+
.wp-input-group:focus-within {
|
|
817
|
+
border-color: var(--wp-accent-500);
|
|
818
|
+
box-shadow: var(--wp-focus-ring);
|
|
819
|
+
}
|
|
820
|
+
/* Inline icon and prefix/suffix text: no box, no divider, sitting in the
|
|
821
|
+
* field's own padding so "$" reads as part of "$hair". */
|
|
822
|
+
.wp-input-group__icon,
|
|
823
|
+
.wp-input-group__affix,
|
|
824
|
+
.wp-input-group__lock {
|
|
825
|
+
display: inline-flex; align-items: center; flex-shrink: 0;
|
|
826
|
+
color: var(--wp-text-dim);
|
|
827
|
+
user-select: none;
|
|
828
|
+
}
|
|
829
|
+
.wp-input-group__icon { padding-left: 10px; }
|
|
830
|
+
.wp-input-group__icon .pi { font-size: 13px; line-height: 1; }
|
|
831
|
+
.wp-input-group__affix { font-family: var(--wp-font-mono); font-size: 12.5px; }
|
|
832
|
+
.wp-input-group__affix--prefix { padding-left: 10px; }
|
|
833
|
+
.wp-input-group__affix--suffix { padding-right: 10px; }
|
|
834
|
+
.wp-input-group__lock { padding-right: 10px; }
|
|
835
|
+
.wp-input-group__icon + .wp-input,
|
|
836
|
+
.wp-input-group__icon + .wp-input-group__affix--prefix { padding-left: 7px; }
|
|
837
|
+
.wp-input-group__affix--prefix + .wp-input { padding-left: 2px; }
|
|
838
|
+
.wp-input-group .wp-input:has(+ .wp-input-group__affix--suffix),
|
|
839
|
+
.wp-input-group .wp-input:has(+ .wp-input-group__lock) { padding-right: 4px; }
|
|
840
|
+
.wp-input-group--sm { height: var(--wp-control-h-sm); min-height: var(--wp-control-h-sm); }
|
|
841
|
+
.wp-input-group--lg { height: var(--wp-control-h-lg); min-height: var(--wp-control-h-lg); }
|
|
842
|
+
.wp-input-group--readonly { background: var(--wp-bg-1); border-style: dashed; }
|
|
843
|
+
.wp-input-group--readonly:focus-within { box-shadow: none; border-color: var(--wp-border-strong); }
|
|
844
|
+
.wp-input-group--readonly .wp-input[readonly] { border: none; }
|
|
845
|
+
.wp-input-group--disabled { opacity: 0.45; cursor: not-allowed; }
|
|
846
|
+
.wp-input-group--disabled .wp-input:disabled { opacity: 1; }
|
|
847
|
+
.wp-input-group[aria-invalid="true"] { border-color: var(--wp-error-border); }
|
|
848
|
+
.wp-input-group .wp-input {
|
|
849
|
+
border: none !important;
|
|
850
|
+
background: transparent !important;
|
|
851
|
+
border-radius: 0;
|
|
852
|
+
height: 100%;
|
|
853
|
+
flex: 1;
|
|
854
|
+
}
|
|
855
|
+
.wp-input-group .wp-input:focus { box-shadow: none; }
|
|
856
|
+
|
|
857
|
+
/* ---------- Chips / tags ---------- */
|
|
858
|
+
.wp-chip {
|
|
859
|
+
/* Reduced overall density: padding 2→1, font 11→10.5, gap 5→4 →
|
|
860
|
+
* chips feel like compact tags instead of buttons. The close-target
|
|
861
|
+
* min-height drops in lockstep so an X-bearing chip doesn't end up
|
|
862
|
+
* forced taller than its bare counterpart. */
|
|
863
|
+
display: inline-flex; align-items: center; gap: 4px;
|
|
864
|
+
padding: 1px 7px;
|
|
865
|
+
border-radius: var(--wp-radius-cap, 999px);
|
|
866
|
+
font-size: 10.5px;
|
|
867
|
+
background: var(--wp-bg-3);
|
|
868
|
+
color: var(--wp-text-muted);
|
|
869
|
+
border: 1px solid var(--wp-border);
|
|
870
|
+
white-space: nowrap;
|
|
871
|
+
font-weight: 500;
|
|
872
|
+
}
|
|
873
|
+
.wp-chip--accent {
|
|
874
|
+
color: var(--wp-accent-text-strong);
|
|
875
|
+
background: rgba(99, 102, 241, 0.16);
|
|
876
|
+
background: color-mix(in oklab, var(--wp-accent-500) 16%, transparent);
|
|
877
|
+
border-color: rgba(99, 102, 241, 0.38);
|
|
878
|
+
border-color: color-mix(in oklab, var(--wp-accent-500) 38%, transparent);
|
|
879
|
+
}
|
|
880
|
+
/* Status chips — text is a lighter tint of the status color in dark, deeper shade in light.
|
|
881
|
+
* Dark theme: --wp-success etc. are bright saturated (green-500/amber-500/red-500/blue-500),
|
|
882
|
+
* readable on dark surface tints. Light-mode overrides below flip to -700 shades via the
|
|
883
|
+
* status token cascade set in .wp-theme-light. */
|
|
884
|
+
.wp-chip--success { color: var(--wp-success); background: color-mix(in oklab, var(--wp-success) 14%, transparent); border-color: color-mix(in oklab, var(--wp-success) 36%, transparent); }
|
|
885
|
+
.wp-chip--warn { color: var(--wp-warn); background: color-mix(in oklab, var(--wp-warn) 14%, transparent); border-color: color-mix(in oklab, var(--wp-warn) 36%, transparent); }
|
|
886
|
+
.wp-chip--danger { color: var(--wp-danger); background: color-mix(in oklab, var(--wp-danger) 14%, transparent); border-color: color-mix(in oklab, var(--wp-danger) 36%, transparent); }
|
|
887
|
+
.wp-chip--info { color: var(--wp-info); background: color-mix(in oklab, var(--wp-info) 14%, transparent); border-color: color-mix(in oklab, var(--wp-info) 36%, transparent); }
|
|
888
|
+
.wp-chip__dot { width: 7px; height: 7px; border-radius: var(--wp-radius-cap, 999px); background: currentColor; }
|
|
889
|
+
.wp-chip__close {
|
|
890
|
+
/* A plain ✕: no background zone and no box that makes a removable chip
|
|
891
|
+
* taller than a bare one. The glyph box is 12px, inside the chip's own
|
|
892
|
+
* line; the ::after reaches 4px past it on every side for a 20px click
|
|
893
|
+
* target without changing the layout. Hover only darkens the glyph. */
|
|
894
|
+
position: relative;
|
|
895
|
+
background: none; border: none; padding: 0; margin: 0 -2px 0 1px;
|
|
896
|
+
width: 12px; height: 12px;
|
|
897
|
+
color: inherit; opacity: 0.65; cursor: pointer; line-height: 0;
|
|
898
|
+
display: inline-grid; place-items: center;
|
|
899
|
+
border-radius: 0;
|
|
900
|
+
transition: opacity .12s, color .12s;
|
|
901
|
+
}
|
|
902
|
+
.wp-chip__close::after { content: ""; position: absolute; inset: -4px; }
|
|
903
|
+
.wp-chip__close:hover { opacity: 1; background: none; }
|
|
904
|
+
.wp-chip__close:focus-visible { outline: 2px solid var(--wp-accent-500); outline-offset: 1px; border-radius: min(2px, var(--wp-radius-cap, 999px)); opacity: 1; }
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
/* ---------- DataTable ---------- */
|
|
908
|
+
.wp-table-wrap {
|
|
909
|
+
background: var(--wp-bg-1);
|
|
910
|
+
border: 1px solid var(--wp-border);
|
|
911
|
+
border-radius: var(--wp-radius-lg);
|
|
912
|
+
overflow: hidden;
|
|
913
|
+
}
|
|
914
|
+
.wp-table { width: 100%; border-collapse: collapse; }
|
|
915
|
+
.wp-table thead th {
|
|
916
|
+
text-align: left;
|
|
917
|
+
font-size: 11px;
|
|
918
|
+
text-transform: uppercase;
|
|
919
|
+
letter-spacing: 0.05em;
|
|
920
|
+
font-weight: 600;
|
|
921
|
+
color: var(--wp-text-muted);
|
|
922
|
+
padding: 10px 12px;
|
|
923
|
+
background: var(--wp-bg-2);
|
|
924
|
+
border-bottom: 1px solid var(--wp-border);
|
|
925
|
+
white-space: nowrap;
|
|
926
|
+
user-select: none;
|
|
927
|
+
}
|
|
928
|
+
.wp-table thead th.wp-sortable { cursor: pointer; }
|
|
929
|
+
.wp-table thead th.wp-sortable:hover { color: var(--wp-text); }
|
|
930
|
+
.wp-table tbody td {
|
|
931
|
+
padding: 10px 12px;
|
|
932
|
+
font-size: 12.5px;
|
|
933
|
+
border-bottom: 1px solid var(--wp-border);
|
|
934
|
+
vertical-align: middle;
|
|
935
|
+
}
|
|
936
|
+
.wp-table tbody tr:last-child td { border-bottom: none; }
|
|
937
|
+
.wp-table tbody tr:hover td { background: var(--wp-row-hover, rgba(255,255,255,0.02)); }
|
|
938
|
+
.wp-table tbody tr[data-expanded="true"] > td { background: var(--wp-row-active, rgba(79,70,229,0.04)); }
|
|
939
|
+
|
|
940
|
+
/* Skeleton rows shown during first paint of list views. The shimmer
|
|
941
|
+
* animation is short + low-contrast so it reads as "content settling"
|
|
942
|
+
* rather than competing for attention. `prefers-reduced-motion` users
|
|
943
|
+
* still get the bar — sans pulse — so absence of motion does not
|
|
944
|
+
* collapse the loading affordance to nothing. */
|
|
945
|
+
/* Skip-to-content link — hidden off-screen until keyboard focus, then
|
|
946
|
+
* pops into the top-left so users can jump past the topbar + sidebar.
|
|
947
|
+
* Standard a11y pattern; matches WCAG 2.4.1 bypass-blocks. */
|
|
948
|
+
.wp-skip-link {
|
|
949
|
+
position: fixed;
|
|
950
|
+
top: -40px;
|
|
951
|
+
left: 8px;
|
|
952
|
+
z-index: 10000;
|
|
953
|
+
padding: 8px 14px;
|
|
954
|
+
background: var(--wp-accent-500);
|
|
955
|
+
color: #fff;
|
|
956
|
+
font-size: 13px;
|
|
957
|
+
font-weight: 600;
|
|
958
|
+
border-radius: min(6px, var(--wp-radius-cap, 999px));
|
|
959
|
+
text-decoration: none;
|
|
960
|
+
transition: top 120ms ease;
|
|
961
|
+
}
|
|
962
|
+
.wp-skip-link:focus,
|
|
963
|
+
.wp-skip-link:focus-visible {
|
|
964
|
+
top: 8px;
|
|
965
|
+
outline: 2px solid var(--wp-accent-300, var(--wp-accent-500));
|
|
966
|
+
outline-offset: 2px;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
/* Visually-hidden text for screen readers — pattern lifted from
|
|
970
|
+
* Tailwind's `sr-only`. Used to give empty `<th>` cells (select,
|
|
971
|
+
* expand, favorite) an accessible name without showing one. */
|
|
972
|
+
.wp-sr-only {
|
|
973
|
+
position: absolute;
|
|
974
|
+
width: 1px; height: 1px;
|
|
975
|
+
padding: 0; margin: -1px;
|
|
976
|
+
overflow: hidden;
|
|
977
|
+
clip: rect(0, 0, 0, 0);
|
|
978
|
+
white-space: nowrap;
|
|
979
|
+
border: 0;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
/* Subtle banner transition used by load-error, draft-restore, and
|
|
983
|
+
* editor field-error rollups. Slide-down + fade on enter, fade only on
|
|
984
|
+
* leave so the banner doesn't visually retreat to the wrong direction.
|
|
985
|
+
* Honored by Vue's <Transition name="wp-banner">. */
|
|
986
|
+
.wp-banner-enter-active { transition: opacity 180ms ease, transform 180ms ease; }
|
|
987
|
+
.wp-banner-leave-active { transition: opacity 140ms ease; }
|
|
988
|
+
.wp-banner-enter-from { opacity: 0; transform: translateY(-6px); }
|
|
989
|
+
.wp-banner-leave-to { opacity: 0; }
|
|
990
|
+
@media (prefers-reduced-motion: reduce) {
|
|
991
|
+
.wp-banner-enter-active,
|
|
992
|
+
.wp-banner-leave-active { transition: none; }
|
|
993
|
+
.wp-banner-enter-from { transform: none; }
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
.wp-row-skel:hover td { background: transparent; }
|
|
997
|
+
.wp-row-skel td { vertical-align: middle; }
|
|
998
|
+
.wp-skel-bar {
|
|
999
|
+
display: block;
|
|
1000
|
+
height: 10px;
|
|
1001
|
+
border-radius: min(5px, var(--wp-radius-cap, 999px));
|
|
1002
|
+
background: linear-gradient(
|
|
1003
|
+
90deg,
|
|
1004
|
+
var(--wp-bg-3) 0%,
|
|
1005
|
+
var(--wp-bg-4) 50%,
|
|
1006
|
+
var(--wp-bg-3) 100%
|
|
1007
|
+
);
|
|
1008
|
+
background-size: 200% 100%;
|
|
1009
|
+
animation: wp-skel-pulse 1.4s ease-in-out infinite;
|
|
1010
|
+
opacity: 0.55;
|
|
1011
|
+
}
|
|
1012
|
+
@keyframes wp-skel-pulse {
|
|
1013
|
+
0% { background-position: 100% 50%; }
|
|
1014
|
+
100% { background-position: -100% 50%; }
|
|
1015
|
+
}
|
|
1016
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1017
|
+
.wp-skel-bar { animation: none; }
|
|
1018
|
+
}
|
|
1019
|
+
.wp-table .wp-row-expand {
|
|
1020
|
+
background: var(--wp-bg-2);
|
|
1021
|
+
padding: 12px 16px 14px 56px;
|
|
1022
|
+
font-size: 12px;
|
|
1023
|
+
}
|
|
1024
|
+
.wp-table .wp-row-expand .wp-row-expand__title {
|
|
1025
|
+
font-size: 10.5px;
|
|
1026
|
+
text-transform: uppercase;
|
|
1027
|
+
letter-spacing: 0.06em;
|
|
1028
|
+
color: var(--wp-text-dim);
|
|
1029
|
+
margin-bottom: 8px;
|
|
1030
|
+
font-weight: 600;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
/* ---------- List-row chrome (used by all 6 list screens) ---------- */
|
|
1034
|
+
.wp-tag-chip {
|
|
1035
|
+
font-size: 10px;
|
|
1036
|
+
padding: 2px 8px;
|
|
1037
|
+
background: var(--wp-bg-3);
|
|
1038
|
+
color: var(--wp-text-muted);
|
|
1039
|
+
border-radius: var(--wp-radius-cap, 999px);
|
|
1040
|
+
letter-spacing: 0.02em;
|
|
1041
|
+
transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
|
|
1042
|
+
}
|
|
1043
|
+
.wp-tag-chip:hover { background: var(--wp-bg-4); color: var(--wp-text); }
|
|
1044
|
+
/* Active state defined globally so scoped view files can use color-mix and this
|
|
1045
|
+
serves as the rgba fallback when color-mix is unsupported (old Chromium). */
|
|
1046
|
+
.wp-tag-chip[data-active="true"] {
|
|
1047
|
+
background: rgba(99, 102, 241, 0.22);
|
|
1048
|
+
background: color-mix(in oklab, var(--wp-accent-500) 22%, transparent);
|
|
1049
|
+
border-color: rgba(99, 102, 241, 0.45);
|
|
1050
|
+
border-color: color-mix(in oklab, var(--wp-accent-500) 45%, transparent);
|
|
1051
|
+
color: var(--wp-accent-text);
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
.wp-id {
|
|
1055
|
+
font-family: var(--wp-font-mono);
|
|
1056
|
+
font-size: 10.5px;
|
|
1057
|
+
color: var(--wp-text-dim);
|
|
1058
|
+
cursor: pointer;
|
|
1059
|
+
user-select: all;
|
|
1060
|
+
}
|
|
1061
|
+
.wp-id:hover { color: var(--wp-text-muted); }
|
|
1062
|
+
|
|
1063
|
+
.wp-fav-toggle {
|
|
1064
|
+
display: flex; align-items: center; gap: 8px;
|
|
1065
|
+
font-size: 13px; color: var(--wp-text); cursor: pointer;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
.wp-row-name {
|
|
1069
|
+
display: flex; flex-direction: column; gap: 1px;
|
|
1070
|
+
}
|
|
1071
|
+
.wp-row-name__text {
|
|
1072
|
+
font-weight: 500; cursor: pointer;
|
|
1073
|
+
}
|
|
1074
|
+
.wp-row-name__text:hover { color: var(--wp-text); filter: brightness(1.1); }
|
|
1075
|
+
|
|
1076
|
+
.wp-row-expand__title {
|
|
1077
|
+
font-size: 10.5px;
|
|
1078
|
+
text-transform: uppercase;
|
|
1079
|
+
letter-spacing: 0.06em;
|
|
1080
|
+
color: var(--wp-text-muted);
|
|
1081
|
+
margin: 0 0 8px 0;
|
|
1082
|
+
font-weight: 600;
|
|
1083
|
+
}
|
|
1084
|
+
.wp-row-expand__name {
|
|
1085
|
+
color: var(--wp-accent-text);
|
|
1086
|
+
font-weight: 600;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
.wp-filters-grid {
|
|
1090
|
+
display: grid;
|
|
1091
|
+
grid-template-columns: repeat(2, 1fr);
|
|
1092
|
+
gap: 14px;
|
|
1093
|
+
}
|
|
1094
|
+
.wp-field--full { grid-column: 1 / -1; }
|
|
1095
|
+
.wp-field__label {
|
|
1096
|
+
display: block;
|
|
1097
|
+
font-size: 11px;
|
|
1098
|
+
color: var(--wp-text-muted);
|
|
1099
|
+
margin-bottom: 4px;
|
|
1100
|
+
font-weight: 500;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
/* A colour-tinted chip (a category, a kind): the colour triple is inline,
|
|
1104
|
+
set by Chip's `color` prop; the label reads a touch heavier. */
|
|
1105
|
+
.wp-chip--color { font-weight: 500; }
|
|
1106
|
+
|
|
1107
|
+
/* ---------- Wildcard syntax indicators ---------- */
|
|
1108
|
+
.wp-syntax-cell {
|
|
1109
|
+
display: inline-flex;
|
|
1110
|
+
gap: 4px;
|
|
1111
|
+
align-items: center;
|
|
1112
|
+
flex-wrap: nowrap;
|
|
1113
|
+
}
|
|
1114
|
+
.wp-syntax-pill {
|
|
1115
|
+
display: inline-flex;
|
|
1116
|
+
align-items: center;
|
|
1117
|
+
gap: 3px;
|
|
1118
|
+
height: 20px;
|
|
1119
|
+
padding: 0 6px;
|
|
1120
|
+
border-radius: var(--wp-radius-cap, 999px);
|
|
1121
|
+
font-size: 10.5px;
|
|
1122
|
+
font-weight: 600;
|
|
1123
|
+
font-family: var(--wp-font-mono);
|
|
1124
|
+
border: 1px solid transparent;
|
|
1125
|
+
white-space: nowrap;
|
|
1126
|
+
line-height: 1;
|
|
1127
|
+
}
|
|
1128
|
+
.wp-syntax-pill .pi { font-size: 9.5px; }
|
|
1129
|
+
.wp-syntax-pill--ref {
|
|
1130
|
+
/* outgoing nested @refs — pink/magenta; uses --wp-kind-ref which flips to fuchsia-800 in light */
|
|
1131
|
+
color: var(--wp-kind-ref);
|
|
1132
|
+
background: var(--wp-kind-ref-bg);
|
|
1133
|
+
border-color: color-mix(in oklab, var(--wp-kind-ref) 32%, transparent);
|
|
1134
|
+
}
|
|
1135
|
+
.wp-syntax-pill--in {
|
|
1136
|
+
/* incoming references — accent (purple) */
|
|
1137
|
+
color: var(--wp-accent-text);
|
|
1138
|
+
background: rgba(99, 102, 241, 0.18);
|
|
1139
|
+
background: color-mix(in oklab, var(--wp-accent-500) 18%, transparent);
|
|
1140
|
+
border-color: rgba(99, 102, 241, 0.35);
|
|
1141
|
+
border-color: color-mix(in oklab, var(--wp-accent-500) 35%, transparent);
|
|
1142
|
+
}
|
|
1143
|
+
.wp-syntax-pill--dp {
|
|
1144
|
+
/* inline {a|b|c} — derivation yellow; --wp-kind-derivation flips to amber-800 in light */
|
|
1145
|
+
color: var(--wp-kind-derivation);
|
|
1146
|
+
background: var(--wp-kind-derivation-bg);
|
|
1147
|
+
border-color: color-mix(in oklab, var(--wp-kind-derivation) 32%, transparent);
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
/* Syntax-color tint for filter-panel toggle chips. Lets the
|
|
1151
|
+
* Wildcards filter pills (Uses nested refs / Has inline / Referenced
|
|
1152
|
+
* by others) match the colored pills in the body's Syntax column —
|
|
1153
|
+
* users learn one color set for both surfaces. Same hue tokens as
|
|
1154
|
+
* `.wp-syntax-pill--*` above; tint depth tuned for the chip shape
|
|
1155
|
+
* (border-only at rest, full fill when active). */
|
|
1156
|
+
.wp-chip--toggle.wp-chip--syntax-ref {
|
|
1157
|
+
border-color: color-mix(in oklab, var(--wp-kind-ref) 35%, transparent);
|
|
1158
|
+
color: var(--wp-kind-ref);
|
|
1159
|
+
}
|
|
1160
|
+
.wp-chip--toggle.wp-chip--syntax-ref[data-active] {
|
|
1161
|
+
background: color-mix(in oklab, var(--wp-kind-ref) 22%, transparent);
|
|
1162
|
+
border-color: color-mix(in oklab, var(--wp-kind-ref) 45%, transparent);
|
|
1163
|
+
color: var(--wp-kind-ref);
|
|
1164
|
+
}
|
|
1165
|
+
.wp-chip--toggle.wp-chip--syntax-in {
|
|
1166
|
+
border-color: color-mix(in oklab, var(--wp-accent-500) 35%, transparent);
|
|
1167
|
+
color: var(--wp-accent-text);
|
|
1168
|
+
}
|
|
1169
|
+
.wp-chip--toggle.wp-chip--syntax-in[data-active] {
|
|
1170
|
+
background: color-mix(in oklab, var(--wp-accent-500) 22%, transparent);
|
|
1171
|
+
border-color: color-mix(in oklab, var(--wp-accent-500) 45%, transparent);
|
|
1172
|
+
color: var(--wp-accent-text);
|
|
1173
|
+
}
|
|
1174
|
+
.wp-chip--toggle.wp-chip--syntax-dp {
|
|
1175
|
+
border-color: color-mix(in oklab, var(--wp-kind-derivation) 35%, transparent);
|
|
1176
|
+
color: var(--wp-kind-derivation);
|
|
1177
|
+
}
|
|
1178
|
+
.wp-chip--toggle.wp-chip--syntax-dp[data-active] {
|
|
1179
|
+
background: color-mix(in oklab, var(--wp-kind-derivation) 22%, transparent);
|
|
1180
|
+
border-color: color-mix(in oklab, var(--wp-kind-derivation) 45%, transparent);
|
|
1181
|
+
color: var(--wp-kind-derivation);
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
/* Light-mode pill overrides — token cascade handles color; adjust tint depth for near-white surface */
|
|
1185
|
+
.wp-theme-light .wp-syntax-pill--ref {
|
|
1186
|
+
/* --wp-kind-ref → fuchsia-800 (#86198f) in light; --wp-kind-ref-bg → 13% tint */
|
|
1187
|
+
color: var(--wp-kind-ref);
|
|
1188
|
+
background: var(--wp-kind-ref-bg);
|
|
1189
|
+
border-color: color-mix(in oklab, var(--wp-kind-ref) 38%, transparent);
|
|
1190
|
+
}
|
|
1191
|
+
.wp-theme-light .wp-syntax-pill--in {
|
|
1192
|
+
/* color inherits --wp-accent-text which light mode sets to accent-700 */
|
|
1193
|
+
background: rgba(99, 102, 241, 0.13);
|
|
1194
|
+
border-color: rgba(99, 102, 241, 0.40);
|
|
1195
|
+
}
|
|
1196
|
+
.wp-theme-light .wp-syntax-pill--dp {
|
|
1197
|
+
/* --wp-kind-derivation → amber-800 (#92400e) in light; --wp-kind-derivation-bg → 12% tint */
|
|
1198
|
+
color: var(--wp-kind-derivation);
|
|
1199
|
+
background: var(--wp-kind-derivation-bg);
|
|
1200
|
+
border-color: color-mix(in oklab, var(--wp-kind-derivation) 45%, transparent);
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
/* ── Light-mode overrides: buttons, chips, tags, links ── */
|
|
1204
|
+
/* Danger button hover: white text fails on light tint; swap to dark-red label */
|
|
1205
|
+
|
|
1206
|
+
/* Tone chips: swap light text for dark text, slightly stronger tint.
|
|
1207
|
+
* Colors route through status tokens which flip to -700/-800 shades in light mode. */
|
|
1208
|
+
.wp-theme-light .wp-chip--accent {
|
|
1209
|
+
/* color inherits --wp-accent-text-strong → accent-800 in light mode */
|
|
1210
|
+
background: rgba(99, 102, 241, 0.13);
|
|
1211
|
+
border-color: rgba(99, 102, 241, 0.40);
|
|
1212
|
+
}
|
|
1213
|
+
.wp-theme-light .wp-chip--success { color: var(--wp-success); background: color-mix(in oklab, var(--wp-success) 14%, transparent); border-color: color-mix(in oklab, var(--wp-success) 42%, transparent); }
|
|
1214
|
+
.wp-theme-light .wp-chip--warn { color: var(--wp-warn); background: color-mix(in oklab, var(--wp-warn) 14%, transparent); border-color: color-mix(in oklab, var(--wp-warn) 42%, transparent); }
|
|
1215
|
+
.wp-theme-light .wp-chip--danger { color: var(--wp-danger); background: color-mix(in oklab, var(--wp-danger) 14%, transparent); border-color: color-mix(in oklab, var(--wp-danger) 42%, transparent); }
|
|
1216
|
+
.wp-theme-light .wp-chip--info { color: var(--wp-info); background: color-mix(in oklab, var(--wp-info) 14%, transparent); border-color: color-mix(in oklab, var(--wp-info) 42%, transparent); }
|
|
1217
|
+
/* Tag chip active: color auto-adapts (--wp-accent-text → dark purple in light mode) */
|
|
1218
|
+
.wp-theme-light .wp-tag-chip[data-active="true"] {
|
|
1219
|
+
background: rgba(99, 102, 241, 0.16);
|
|
1220
|
+
border-color: rgba(99, 102, 241, 0.42);
|
|
1221
|
+
}
|
|
1222
|
+
/* Missing wildcard ref link: --wp-danger flips to red-700 in light */
|
|
1223
|
+
.wp-theme-light .wp-syntax-link--missing,
|
|
1224
|
+
.wp-theme-light .wp-syntax-link--missing:hover {
|
|
1225
|
+
color: var(--wp-danger);
|
|
1226
|
+
border-color: color-mix(in oklab, var(--wp-danger) 42%, transparent);
|
|
1227
|
+
background: color-mix(in oklab, var(--wp-danger) 12%, transparent);
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
/* Reference graph block inside row-expand */
|
|
1231
|
+
.wp-syntax-graph {
|
|
1232
|
+
margin-top: 12px;
|
|
1233
|
+
padding-top: 10px;
|
|
1234
|
+
border-top: 1px dashed var(--wp-border);
|
|
1235
|
+
display: flex;
|
|
1236
|
+
flex-direction: column;
|
|
1237
|
+
gap: 6px;
|
|
1238
|
+
font-size: 12px;
|
|
1239
|
+
}
|
|
1240
|
+
.wp-syntax-graph__row {
|
|
1241
|
+
display: flex;
|
|
1242
|
+
flex-wrap: wrap;
|
|
1243
|
+
align-items: center;
|
|
1244
|
+
gap: 6px;
|
|
1245
|
+
}
|
|
1246
|
+
.wp-syntax-graph__row .pi { font-size: 11px; opacity: 0.7; }
|
|
1247
|
+
.wp-syntax-link {
|
|
1248
|
+
appearance: none;
|
|
1249
|
+
background: var(--wp-bg-3);
|
|
1250
|
+
border: 1px solid var(--wp-border);
|
|
1251
|
+
color: var(--wp-text-dim);
|
|
1252
|
+
font: inherit;
|
|
1253
|
+
padding: 1px 8px;
|
|
1254
|
+
border-radius: var(--wp-radius-cap, 999px);
|
|
1255
|
+
cursor: pointer;
|
|
1256
|
+
transition: color 120ms, background 120ms, border-color 120ms;
|
|
1257
|
+
}
|
|
1258
|
+
.wp-syntax-link:hover {
|
|
1259
|
+
color: var(--wp-accent-text);
|
|
1260
|
+
border-color: rgba(99, 102, 241, 0.45);
|
|
1261
|
+
border-color: color-mix(in oklab, var(--wp-accent-500) 45%, transparent);
|
|
1262
|
+
background: rgba(99, 102, 241, 0.12);
|
|
1263
|
+
background: color-mix(in oklab, var(--wp-accent-500) 12%, var(--wp-bg-3));
|
|
1264
|
+
}
|
|
1265
|
+
.wp-syntax-link--missing {
|
|
1266
|
+
/* audit-exempt: red-400 (#f87171) is lighter than --wp-danger for dark-bg legibility;
|
|
1267
|
+
* light-mode override above uses var(--wp-danger) which flips to red-700. */
|
|
1268
|
+
color: #f87171;
|
|
1269
|
+
border-color: color-mix(in oklab, #f87171 38%, transparent);
|
|
1270
|
+
background: color-mix(in oklab, #f87171 14%, transparent);
|
|
1271
|
+
font-family: var(--wp-font-mono);
|
|
1272
|
+
cursor: default;
|
|
1273
|
+
}
|
|
1274
|
+
.wp-syntax-link--missing:hover {
|
|
1275
|
+
color: #f87171; /* audit-exempt: see above */
|
|
1276
|
+
border-color: color-mix(in oklab, #f87171 38%, transparent);
|
|
1277
|
+
background: color-mix(in oklab, #f87171 14%, transparent);
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
.wp-id {
|
|
1281
|
+
font-family: var(--wp-font-mono);
|
|
1282
|
+
font-size: 10.5px;
|
|
1283
|
+
color: var(--wp-text-dim);
|
|
1284
|
+
letter-spacing: 0;
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
/* ---------- Toolbar ---------- */
|
|
1288
|
+
.wp-toolbar {
|
|
1289
|
+
display: flex; align-items: center; gap: 8px;
|
|
1290
|
+
flex-wrap: wrap;
|
|
1291
|
+
}
|
|
1292
|
+
.wp-toolbar__search { flex: 1; min-width: 220px; max-width: 320px; }
|
|
1293
|
+
.wp-toolbar__count { font-size: 11.5px; color: var(--wp-text-dim); margin-left: auto; }
|
|
1294
|
+
|
|
1295
|
+
/* ---------- Pagination ---------- */
|
|
1296
|
+
.wp-pagination {
|
|
1297
|
+
display: flex; align-items: center; gap: 10px;
|
|
1298
|
+
padding: 8px 12px;
|
|
1299
|
+
background: var(--wp-bg-1);
|
|
1300
|
+
border: 1px solid var(--wp-border);
|
|
1301
|
+
border-radius: var(--wp-radius-md);
|
|
1302
|
+
}
|
|
1303
|
+
.wp-pager {
|
|
1304
|
+
display: inline-flex; align-items: center; gap: 2px;
|
|
1305
|
+
background: var(--wp-bg-2);
|
|
1306
|
+
border: 1px solid var(--wp-border);
|
|
1307
|
+
border-radius: min(7px, var(--wp-radius-cap, 999px));
|
|
1308
|
+
padding: 2px;
|
|
1309
|
+
}
|
|
1310
|
+
.wp-pager__label {
|
|
1311
|
+
padding: 0 10px;
|
|
1312
|
+
font-size: 11.5px;
|
|
1313
|
+
color: var(--wp-text-muted);
|
|
1314
|
+
font-variant-numeric: tabular-nums;
|
|
1315
|
+
min-width: 80px;
|
|
1316
|
+
text-align: center;
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
/* ---------- Rule card (Derivation editor) ---------- */
|
|
1320
|
+
.wp-rule {
|
|
1321
|
+
background: var(--wp-bg-2);
|
|
1322
|
+
border: 1px solid var(--wp-border);
|
|
1323
|
+
border-radius: var(--wp-radius-md);
|
|
1324
|
+
padding: 10px 12px;
|
|
1325
|
+
display: flex; flex-direction: column; gap: 8px;
|
|
1326
|
+
}
|
|
1327
|
+
.wp-rule__head {
|
|
1328
|
+
display: flex; align-items: center; gap: 8px;
|
|
1329
|
+
}
|
|
1330
|
+
.wp-rule__num {
|
|
1331
|
+
font-family: var(--wp-font-mono);
|
|
1332
|
+
font-size: 10.5px;
|
|
1333
|
+
font-weight: 600;
|
|
1334
|
+
letter-spacing: 0.05em;
|
|
1335
|
+
padding: 2px 8px;
|
|
1336
|
+
border-radius: min(4px, var(--wp-radius-cap, 999px));
|
|
1337
|
+
background: color-mix(in oklab, var(--wp-accent-500) 18%, transparent);
|
|
1338
|
+
color: var(--wp-accent-text);
|
|
1339
|
+
}
|
|
1340
|
+
.wp-rule__index { font-size: 11px; color: var(--wp-text-dim); font-variant-numeric: tabular-nums; }
|
|
1341
|
+
.wp-rule__row {
|
|
1342
|
+
display: grid;
|
|
1343
|
+
grid-template-columns: 64px 1fr;
|
|
1344
|
+
gap: 10px;
|
|
1345
|
+
align-items: center;
|
|
1346
|
+
}
|
|
1347
|
+
.wp-rule__label {
|
|
1348
|
+
font-size: 11.5px;
|
|
1349
|
+
color: var(--wp-text-muted);
|
|
1350
|
+
text-transform: uppercase;
|
|
1351
|
+
letter-spacing: 0.04em;
|
|
1352
|
+
font-weight: 500;
|
|
1353
|
+
}
|
|
1354
|
+
.wp-rule__cond {
|
|
1355
|
+
display: flex;
|
|
1356
|
+
flex-wrap: wrap;
|
|
1357
|
+
gap: 8px;
|
|
1358
|
+
align-items: center;
|
|
1359
|
+
}
|
|
1360
|
+
.wp-rule--else {
|
|
1361
|
+
margin-top: 12px;
|
|
1362
|
+
border-style: dashed;
|
|
1363
|
+
background: transparent;
|
|
1364
|
+
}
|
|
1365
|
+
.wp-rule--else[data-active="true"] {
|
|
1366
|
+
background: var(--wp-bg-2);
|
|
1367
|
+
border-style: solid;
|
|
1368
|
+
}
|
|
1369
|
+
.wp-rule--else .wp-rule__num {
|
|
1370
|
+
background: color-mix(in oklab, var(--wp-warn) 18%, transparent);
|
|
1371
|
+
color: var(--wp-warn);
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
/* Group rule (independent rule with its own IF/ELIF/ELSE branches) */
|
|
1375
|
+
.wp-rule--group {
|
|
1376
|
+
border: 1px solid var(--wp-border-strong);
|
|
1377
|
+
background: var(--wp-bg-1);
|
|
1378
|
+
padding: 12px;
|
|
1379
|
+
}
|
|
1380
|
+
.wp-rule--group .wp-rule__num {
|
|
1381
|
+
background: color-mix(in oklab, var(--wp-accent-500) 24%, transparent);
|
|
1382
|
+
}
|
|
1383
|
+
.wp-rule__branches {
|
|
1384
|
+
display: flex;
|
|
1385
|
+
flex-direction: column;
|
|
1386
|
+
gap: 8px;
|
|
1387
|
+
margin-top: 4px;
|
|
1388
|
+
padding-left: 10px;
|
|
1389
|
+
border-left: 2px solid color-mix(in oklab, var(--wp-accent-500) 30%, transparent);
|
|
1390
|
+
}
|
|
1391
|
+
.wp-branch {
|
|
1392
|
+
background: var(--wp-bg-2);
|
|
1393
|
+
border: 1px solid var(--wp-border);
|
|
1394
|
+
border-radius: min(8px, var(--wp-radius-cap, 999px));
|
|
1395
|
+
padding: 10px 12px;
|
|
1396
|
+
display: flex; flex-direction: column; gap: 8px;
|
|
1397
|
+
}
|
|
1398
|
+
.wp-branch__head {
|
|
1399
|
+
display: flex; align-items: center; gap: 8px;
|
|
1400
|
+
}
|
|
1401
|
+
.wp-branch__tag {
|
|
1402
|
+
font-family: var(--wp-font-mono);
|
|
1403
|
+
font-size: 10px;
|
|
1404
|
+
font-weight: 700;
|
|
1405
|
+
letter-spacing: 0.06em;
|
|
1406
|
+
padding: 2px 7px;
|
|
1407
|
+
border-radius: min(4px, var(--wp-radius-cap, 999px));
|
|
1408
|
+
text-transform: uppercase;
|
|
1409
|
+
}
|
|
1410
|
+
.wp-branch__tag[data-kind="if"] {
|
|
1411
|
+
background: color-mix(in oklab, var(--wp-accent-500) 22%, transparent);
|
|
1412
|
+
color: var(--wp-accent-text);
|
|
1413
|
+
}
|
|
1414
|
+
.wp-branch__tag[data-kind="elif"] {
|
|
1415
|
+
background: color-mix(in oklab, var(--wp-info, #60a5fa) 22%, transparent);
|
|
1416
|
+
color: var(--wp-info, #60a5fa);
|
|
1417
|
+
}
|
|
1418
|
+
.wp-branch__tag[data-kind="else"] {
|
|
1419
|
+
background: color-mix(in oklab, var(--wp-warn) 22%, transparent);
|
|
1420
|
+
color: var(--wp-warn);
|
|
1421
|
+
}
|
|
1422
|
+
.wp-branch--else {
|
|
1423
|
+
border-style: dashed;
|
|
1424
|
+
}
|
|
1425
|
+
.wp-rule__addbar {
|
|
1426
|
+
display: flex;
|
|
1427
|
+
gap: 6px;
|
|
1428
|
+
margin-top: 8px;
|
|
1429
|
+
padding-left: 12px;
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
/* ---------- Hero ----------
|
|
1433
|
+
* A page header with the logo or an icon. Plain surface: Orbit has no
|
|
1434
|
+
* decorative gradients. */
|
|
1435
|
+
.wp-hero {
|
|
1436
|
+
border-radius: var(--wp-radius-xl);
|
|
1437
|
+
padding: 16px 20px;
|
|
1438
|
+
display: flex; align-items: center; gap: 16px;
|
|
1439
|
+
background: var(--wp-bg-1);
|
|
1440
|
+
border: 1px solid var(--wp-border);
|
|
1441
|
+
}
|
|
1442
|
+
.wp-hero__icon {
|
|
1443
|
+
width: 48px; height: 48px;
|
|
1444
|
+
border-radius: min(12px, var(--wp-radius-cap, 999px));
|
|
1445
|
+
background: var(--wp-bg-3);
|
|
1446
|
+
display: grid; place-items: center;
|
|
1447
|
+
flex-shrink: 0;
|
|
1448
|
+
color: var(--wp-accent-text);
|
|
1449
|
+
}
|
|
1450
|
+
.wp-hero__title { font-size: 17px; font-weight: 600; margin: 0 0 2px; letter-spacing: -0.01em; color: var(--wp-text); }
|
|
1451
|
+
.wp-hero__sub { font-size: 13px; color: var(--wp-text-muted); margin: 0; max-width: 640px; }
|
|
1452
|
+
|
|
1453
|
+
/* ---------- Stat cards ---------- */
|
|
1454
|
+
.wp-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
|
|
1455
|
+
/* Page area narrower than 680px (usePageWidth; the chat can take the rest). */
|
|
1456
|
+
.wp-content[data-lt~="680"] .wp-stats { grid-template-columns: repeat(2, 1fr); }
|
|
1457
|
+
.wp-stat {
|
|
1458
|
+
background: var(--wp-bg-1);
|
|
1459
|
+
border: 1px solid var(--wp-border);
|
|
1460
|
+
border-radius: var(--wp-radius-lg);
|
|
1461
|
+
padding: 12px 14px;
|
|
1462
|
+
display: flex; flex-direction: column; gap: 4px;
|
|
1463
|
+
position: relative;
|
|
1464
|
+
overflow: hidden;
|
|
1465
|
+
transition: transform 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
|
|
1466
|
+
}
|
|
1467
|
+
.wp-stat:is(button, a):hover,
|
|
1468
|
+
.wp-stat[role="button"]:hover {
|
|
1469
|
+
transform: translateY(-2px);
|
|
1470
|
+
border-color: var(--wp-border-strong);
|
|
1471
|
+
box-shadow: var(--wp-shadow);
|
|
1472
|
+
}
|
|
1473
|
+
.wp-stat__label {
|
|
1474
|
+
font-size: 10.5px;
|
|
1475
|
+
text-transform: uppercase;
|
|
1476
|
+
letter-spacing: 0.07em;
|
|
1477
|
+
color: var(--wp-text-dim);
|
|
1478
|
+
font-weight: 600;
|
|
1479
|
+
display: flex; align-items: center; gap: 6px;
|
|
1480
|
+
}
|
|
1481
|
+
.wp-stat__value { font-size: 24px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.1; }
|
|
1482
|
+
.wp-stat__delta { font-size: 11px; color: var(--wp-text-dim); display: flex; align-items: center; gap: 4px; }
|
|
1483
|
+
.wp-stat__icon {
|
|
1484
|
+
position: absolute; top: 10px; right: 10px;
|
|
1485
|
+
width: 26px; height: 26px;
|
|
1486
|
+
border-radius: min(7px, var(--wp-radius-cap, 999px));
|
|
1487
|
+
display: grid; place-items: center;
|
|
1488
|
+
background: color-mix(in oklab, var(--wp-accent-500) 14%, transparent);
|
|
1489
|
+
color: var(--wp-accent-text);
|
|
1490
|
+
font-size: 13px;
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
/* ---------- List rows ---------- */
|
|
1494
|
+
.wp-list { display: flex; flex-direction: column; }
|
|
1495
|
+
.wp-list__row {
|
|
1496
|
+
display: flex; align-items: center; gap: 10px;
|
|
1497
|
+
padding: 9px 12px;
|
|
1498
|
+
border-radius: min(8px, var(--wp-radius-cap, 999px));
|
|
1499
|
+
cursor: pointer;
|
|
1500
|
+
transition: background .12s;
|
|
1501
|
+
}
|
|
1502
|
+
.wp-list__row:hover { background: var(--wp-bg-3); }
|
|
1503
|
+
.wp-list__row + .wp-list__row { border-top: 1px solid var(--wp-border); border-radius: 0; }
|
|
1504
|
+
|
|
1505
|
+
/* ---------- Empty state ---------- */
|
|
1506
|
+
.wp-empty {
|
|
1507
|
+
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
1508
|
+
text-align: center;
|
|
1509
|
+
padding: 48px 24px;
|
|
1510
|
+
color: var(--wp-text-muted);
|
|
1511
|
+
gap: 10px;
|
|
1512
|
+
}
|
|
1513
|
+
.wp-empty__icon {
|
|
1514
|
+
width: 56px; height: 56px;
|
|
1515
|
+
border-radius: min(14px, var(--wp-radius-cap, 999px));
|
|
1516
|
+
background: var(--wp-bg-2);
|
|
1517
|
+
border: 1px solid var(--wp-border);
|
|
1518
|
+
display: grid; place-items: center;
|
|
1519
|
+
color: var(--wp-text-dim);
|
|
1520
|
+
font-size: 22px;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
/* `.wp-empty--card` (full-width dashed empty state) lived alongside the
|
|
1524
|
+
community sub-screens. It moved to the feat/community-tab branch with
|
|
1525
|
+
them; main has no remaining consumer. Re-introduce here when another
|
|
1526
|
+
surface needs it. */
|
|
1527
|
+
|
|
1528
|
+
/* Compact dashed-card empty placeholder used inside editor cards
|
|
1529
|
+
(DerivationEditor rules list, ConstraintEditor matrix/exceptions,
|
|
1530
|
+
PipelineSteps step list). Single-line muted text in a softly-bordered box. */
|
|
1531
|
+
.wp-empty-card {
|
|
1532
|
+
border: 1px dashed var(--wp-border);
|
|
1533
|
+
border-radius: var(--wp-radius);
|
|
1534
|
+
padding: 18px;
|
|
1535
|
+
text-align: center;
|
|
1536
|
+
color: var(--wp-text-dim);
|
|
1537
|
+
font-size: 12.5px;
|
|
1538
|
+
}
|
|
1539
|
+
/* A leading info/status icon (e.g. the matrix "needs a sub-category" hint or
|
|
1540
|
+
the exceptions hint) sat flush against the message text. Give it breathing
|
|
1541
|
+
room without restructuring the centered single-line layout. */
|
|
1542
|
+
.wp-empty-card .pi { margin-right: 6px; }
|
|
1543
|
+
|
|
1544
|
+
/* Small muted hint text used above editor card content
|
|
1545
|
+
(replaces dv-hint / cn-hint / pl-hint / wp-text-xs duplicates). */
|
|
1546
|
+
.wp-card__hint {
|
|
1547
|
+
font-size: 11.5px;
|
|
1548
|
+
color: var(--wp-text-dim);
|
|
1549
|
+
margin: 0 0 8px 0;
|
|
1550
|
+
line-height: 1.45;
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
/* Status icon colour modifiers — for Wildcards list validity icons and
|
|
1554
|
+
similar inline status glyphs. Keeps inline color attributes pointing at
|
|
1555
|
+
semantic tokens out of templates. */
|
|
1556
|
+
.wp-icon--success { color: var(--wp-success); }
|
|
1557
|
+
.wp-icon--warn { color: var(--wp-warn); }
|
|
1558
|
+
.wp-icon--danger { color: var(--wp-danger); }
|
|
1559
|
+
.wp-icon--info { color: var(--wp-info); }
|
|
1560
|
+
|
|
1561
|
+
/* Refresh-button affordance — spins the `pi-refresh` icon on the
|
|
1562
|
+
* button it's attached to while a fetch is in flight. Defined in
|
|
1563
|
+
* tokens.css (global) rather than per-component scoped styles so
|
|
1564
|
+
* every list page that imports Button.vue can wear the modifier
|
|
1565
|
+
* class without crossing :deep() boundaries. */
|
|
1566
|
+
.wp-refresh-btn--spin .pi-refresh {
|
|
1567
|
+
animation: wp-refresh-spin 0.9s linear infinite;
|
|
1568
|
+
}
|
|
1569
|
+
@keyframes wp-refresh-spin {
|
|
1570
|
+
to { transform: rotate(360deg); }
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
/* ---------- Sticky footer for editors ---------- */
|
|
1574
|
+
.wp-footer-bar {
|
|
1575
|
+
position: sticky; bottom: 0;
|
|
1576
|
+
margin-top: auto;
|
|
1577
|
+
background: var(--wp-bg);
|
|
1578
|
+
border-top: 1px solid var(--wp-border);
|
|
1579
|
+
padding: 12px 0;
|
|
1580
|
+
display: flex; justify-content: flex-end; gap: 8px;
|
|
1581
|
+
z-index: 5;
|
|
1582
|
+
}
|
|
1583
|
+
.wp-footer-bar::before {
|
|
1584
|
+
content: "";
|
|
1585
|
+
position: absolute;
|
|
1586
|
+
left: 0; right: 0; bottom: 100%;
|
|
1587
|
+
height: 20px;
|
|
1588
|
+
background: linear-gradient(180deg, transparent, var(--wp-bg));
|
|
1589
|
+
pointer-events: none;
|
|
1590
|
+
}
|
|
1591
|
+
.wp-footer-bar__inner {
|
|
1592
|
+
display: contents;
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
/* ---------- Toggle ----------
|
|
1596
|
+
Toggle.vue wraps the shared WpSwitch; its look lives in
|
|
1597
|
+
kit/WpSwitch.vue (one sheet for canvas + manager). */
|
|
1598
|
+
|
|
1599
|
+
/* ---------- Checkbox ----------
|
|
1600
|
+
Canonical geometry matches the wildcard pool's per-option box
|
|
1601
|
+
(`.opt__check` in OptionRow.vue: 14px, 1.5px soft border, 3px radius, sunk
|
|
1602
|
+
into `--wp-bg`). This is THE checkbox look for the whole app; the only
|
|
1603
|
+
opt-outs are the custom toggle BUTTONS (internal flag, seed-lock).
|
|
1604
|
+
|
|
1605
|
+
Markup-agnostic on purpose: works for both the shared ui/Checkbox.vue
|
|
1606
|
+
`<button data-checked>` and bare `<span role="checkbox" aria-checked>`
|
|
1607
|
+
used inline in the size-sensitive embed tree (which avoids importing the
|
|
1608
|
+
component to stay within the bundle budget). On-state fill stays at
|
|
1609
|
+
accent-600 for the white-tick contrast audit. */
|
|
1610
|
+
.wp-check {
|
|
1611
|
+
width: 14px; height: 14px;
|
|
1612
|
+
/* A visible edge on the empty box: the hairline border tokens vanished on
|
|
1613
|
+
* a dark row, so nobody saw that list rows can be selected. */
|
|
1614
|
+
border: 1.5px solid color-mix(in srgb, var(--wp-text-dim) 70%, transparent);
|
|
1615
|
+
border-radius: min(3px, var(--wp-radius-cap, 999px));
|
|
1616
|
+
background: var(--wp-bg);
|
|
1617
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
1618
|
+
padding: 0; margin: 0;
|
|
1619
|
+
cursor: pointer;
|
|
1620
|
+
flex-shrink: 0;
|
|
1621
|
+
color: transparent;
|
|
1622
|
+
transition: background .12s, border-color .12s, color .12s;
|
|
1623
|
+
line-height: 0;
|
|
1624
|
+
}
|
|
1625
|
+
.wp-check[data-checked="true"],
|
|
1626
|
+
.wp-check[aria-checked="true"] {
|
|
1627
|
+
background: var(--wp-accent-600);
|
|
1628
|
+
border-color: var(--wp-accent-500);
|
|
1629
|
+
color: #fff; /* audit-exempt: white checkmark on accent-600 background ≥4.5:1 both themes */
|
|
1630
|
+
}
|
|
1631
|
+
/* Indeterminate (tri-state) — must look visually distinct from an empty box.
|
|
1632
|
+
The base .wp-check sets color: transparent, so the dash SVG (stroke="currentColor")
|
|
1633
|
+
would be invisible without flipping color here. Mirrors the checked-state fill so
|
|
1634
|
+
a section-checkbox with a partial selection is unmistakably "some, not none, not all".
|
|
1635
|
+
Visibility contract: see src/manager/components/ui/Checkbox.vue (indeterminate prop)
|
|
1636
|
+
and src/manager/__tests__/ui/Checkbox.test.ts (data-indeterminate assertions). */
|
|
1637
|
+
.wp-check[data-indeterminate="true"] {
|
|
1638
|
+
background: var(--wp-accent-600);
|
|
1639
|
+
border-color: var(--wp-accent-500);
|
|
1640
|
+
color: #fff; /* audit-exempt: white dash on accent-600 background ≥4.5:1 both themes */
|
|
1641
|
+
}
|
|
1642
|
+
.wp-check svg { width: 9px; height: 9px; display: block; pointer-events: none; }
|
|
1643
|
+
.wp-check:not(:disabled, [aria-disabled="true"], [data-checked="true"], [aria-checked="true"], [data-indeterminate="true"]):hover {
|
|
1644
|
+
border-color: var(--wp-accent-500);
|
|
1645
|
+
}
|
|
1646
|
+
/* Disabled: grey, not dim purple, so a ticked disabled box no longer reads
|
|
1647
|
+
* as a live one in dark mode. */
|
|
1648
|
+
.wp-check:disabled,
|
|
1649
|
+
.wp-check[aria-disabled="true"] {
|
|
1650
|
+
cursor: not-allowed;
|
|
1651
|
+
background: var(--wp-bg-3);
|
|
1652
|
+
border-color: var(--wp-border);
|
|
1653
|
+
opacity: 0.6;
|
|
1654
|
+
}
|
|
1655
|
+
.wp-check:disabled[data-checked="true"],
|
|
1656
|
+
.wp-check:disabled[data-indeterminate="true"],
|
|
1657
|
+
.wp-check[aria-disabled="true"][aria-checked="true"] {
|
|
1658
|
+
background: var(--wp-text-dim);
|
|
1659
|
+
border-color: var(--wp-text-dim);
|
|
1660
|
+
color: var(--wp-bg-1);
|
|
1661
|
+
}
|
|
1662
|
+
.wp-checkbox.is-disabled { cursor: not-allowed; }
|
|
1663
|
+
.wp-checkbox.is-disabled .wp-checkbox__label { opacity: 0.5; }
|
|
1664
|
+
.wp-check:focus-visible { outline: none; box-shadow: var(--wp-focus-ring); }
|
|
1665
|
+
|
|
1666
|
+
/* Inline checkbox wrapper (label + box) — min-height fills canonical hit-target. */
|
|
1667
|
+
.wp-checkbox {
|
|
1668
|
+
display: inline-flex; align-items: center; gap: 8px;
|
|
1669
|
+
min-height: var(--wp-input-h);
|
|
1670
|
+
cursor: pointer;
|
|
1671
|
+
user-select: none;
|
|
1672
|
+
font-size: 12.5px;
|
|
1673
|
+
color: var(--wp-text);
|
|
1674
|
+
}
|
|
1675
|
+
/* Box-only checkbox inside a row or a <label> that already gives the hit
|
|
1676
|
+
target (AI result lists, file lists): no 32px min-height, so it sits on
|
|
1677
|
+
the row's text line. */
|
|
1678
|
+
.wp-checkbox--inline { min-height: 0; flex: none; }
|
|
1679
|
+
/* Field checkbox (`<Checkbox field>`): an input-height box in a form grid.
|
|
1680
|
+
The label fills the box so a click anywhere toggles once (the label
|
|
1681
|
+
toggles, the box toggles, nothing else does). */
|
|
1682
|
+
.wp-checkbox--field {
|
|
1683
|
+
display: flex;
|
|
1684
|
+
width: 100%;
|
|
1685
|
+
height: var(--wp-input-h);
|
|
1686
|
+
gap: 0;
|
|
1687
|
+
background: var(--wp-bg-2);
|
|
1688
|
+
border: 1px solid var(--wp-border);
|
|
1689
|
+
border-radius: var(--wp-radius-sm);
|
|
1690
|
+
transition: border-color .12s;
|
|
1691
|
+
}
|
|
1692
|
+
.wp-checkbox--field:hover { border-color: var(--wp-border-strong); }
|
|
1693
|
+
.wp-checkbox--field:focus-within { border-color: var(--wp-accent-500); }
|
|
1694
|
+
.wp-checkbox--field .wp-check { margin-left: 10px; }
|
|
1695
|
+
.wp-checkbox--field .wp-checkbox__label {
|
|
1696
|
+
flex: 1;
|
|
1697
|
+
align-self: stretch;
|
|
1698
|
+
display: flex;
|
|
1699
|
+
align-items: center;
|
|
1700
|
+
padding: 0 10px 0 8px;
|
|
1701
|
+
white-space: nowrap;
|
|
1702
|
+
overflow: hidden;
|
|
1703
|
+
text-overflow: ellipsis;
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1706
|
+
/* ---------- Radio ----------
|
|
1707
|
+
Native <input type="radio" class="wp-radio"> drawn to match .wp-check:
|
|
1708
|
+
same 14px box, soft border and accent-600 fill, round. Stays a real
|
|
1709
|
+
radio so name-grouping, arrow keys and v-model keep working. */
|
|
1710
|
+
.wp-radio {
|
|
1711
|
+
appearance: none; -webkit-appearance: none;
|
|
1712
|
+
width: 14px; height: 14px; margin: 0; flex-shrink: 0;
|
|
1713
|
+
border: 1.5px solid var(--wp-border-strong);
|
|
1714
|
+
border-radius: 50%; /* round: a radio is round in every look */
|
|
1715
|
+
background: var(--wp-bg);
|
|
1716
|
+
display: inline-grid; place-items: center;
|
|
1717
|
+
cursor: pointer;
|
|
1718
|
+
transition: background .12s, border-color .12s;
|
|
1719
|
+
}
|
|
1720
|
+
.wp-radio::before {
|
|
1721
|
+
content: ""; width: 6px; height: 6px; border-radius: 50%; /* round: radio dot */
|
|
1722
|
+
background: #fff; /* audit-exempt: white dot on accent-600 fill ≥4.5:1 both themes */
|
|
1723
|
+
transform: scale(0); transition: transform .12s;
|
|
1724
|
+
}
|
|
1725
|
+
.wp-radio:checked { background: var(--wp-accent-600); border-color: var(--wp-accent-500); }
|
|
1726
|
+
.wp-radio:checked::before { transform: scale(1); }
|
|
1727
|
+
.wp-radio:disabled { opacity: 0.6; cursor: not-allowed; background: var(--wp-bg-3); border-color: var(--wp-border); }
|
|
1728
|
+
.wp-radio:disabled:checked { background: var(--wp-text-dim); border-color: var(--wp-text-dim); }
|
|
1729
|
+
.wp-radio:disabled:checked::before { background: var(--wp-bg-1); }
|
|
1730
|
+
label:has(> .wp-radio:disabled) { cursor: not-allowed; color: var(--wp-text-dim); }
|
|
1731
|
+
.wp-radio:focus-visible { outline: none; box-shadow: var(--wp-focus-ring); }
|
|
1732
|
+
.wp-checkbox__label { color: var(--wp-text); }
|
|
1733
|
+
|
|
1734
|
+
/* ---------- Star (favorite) ---------- */
|
|
1735
|
+
.wp-star { color: var(--wp-text-dim); cursor: pointer; transition: color .12s, transform .1s; background: none; border: none; padding: 4px; line-height: 0; }
|
|
1736
|
+
.wp-star:hover { color: var(--wp-warn); }
|
|
1737
|
+
.wp-star[data-on="true"] { color: var(--wp-warn); }
|
|
1738
|
+
|
|
1739
|
+
/* ---------- Tabs ---------- */
|
|
1740
|
+
.wp-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--wp-border); }
|
|
1741
|
+
.wp-tab {
|
|
1742
|
+
padding: 8px 12px;
|
|
1743
|
+
background: none; border: none;
|
|
1744
|
+
color: var(--wp-text-muted);
|
|
1745
|
+
font-size: 12.5px;
|
|
1746
|
+
cursor: pointer;
|
|
1747
|
+
border-bottom: 2px solid transparent;
|
|
1748
|
+
margin-bottom: -1px;
|
|
1749
|
+
display: inline-flex; align-items: center; gap: 6px;
|
|
1750
|
+
font-weight: 500;
|
|
1751
|
+
}
|
|
1752
|
+
.wp-tab:hover { color: var(--wp-text); }
|
|
1753
|
+
.wp-tab[data-active="true"] { color: var(--wp-text); border-bottom-color: var(--wp-accent-400); }
|
|
1754
|
+
|
|
1755
|
+
/* ---------- Code-ish snippet display ---------- */
|
|
1756
|
+
.wp-snippet {
|
|
1757
|
+
font-family: var(--wp-font-mono);
|
|
1758
|
+
font-size: 12px;
|
|
1759
|
+
background: var(--wp-bg-2);
|
|
1760
|
+
border: 1px solid var(--wp-border);
|
|
1761
|
+
border-radius: min(7px, var(--wp-radius-cap, 999px));
|
|
1762
|
+
padding: 8px 10px;
|
|
1763
|
+
color: var(--wp-text);
|
|
1764
|
+
line-height: 1.6;
|
|
1765
|
+
}
|
|
1766
|
+
.wp-token-var { color: var(--wp-accent-text); }
|
|
1767
|
+
.wp-token-str { color: var(--wp-rt-token-good); } /* green; --wp-rt-token-good flips in light */
|
|
1768
|
+
.wp-token-key { color: var(--wp-kind-derivation); } /* amber; --wp-kind-derivation flips in light */
|
|
1769
|
+
.wp-token-com { color: var(--wp-text-dim); }
|
|
1770
|
+
|
|
1771
|
+
/* ---------- Toast ---------- */
|
|
1772
|
+
.wp-toast-stack {
|
|
1773
|
+
position: fixed; right: 16px; bottom: 16px;
|
|
1774
|
+
display: flex; flex-direction: column; gap: 8px;
|
|
1775
|
+
z-index: 100;
|
|
1776
|
+
pointer-events: none;
|
|
1777
|
+
}
|
|
1778
|
+
/* The toast itself is kit/ToastCard.vue (shared with the canvas). */
|
|
1779
|
+
.wp-toast-stack > * { animation: wp-slide-in .18s ease-out; }
|
|
1780
|
+
@keyframes wp-slide-in { from { transform: translateY(8px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
|
|
1781
|
+
|
|
1782
|
+
/* ---------- Misc utility ---------- */
|
|
1783
|
+
.wp-hsplit { display: flex; align-items: center; gap: 8px; }
|
|
1784
|
+
.wp-spacer { flex: 1; }
|
|
1785
|
+
.wp-mono { font-family: var(--wp-font-mono); }
|
|
1786
|
+
.wp-muted { color: var(--wp-text-muted); }
|
|
1787
|
+
.wp-dim { color: var(--wp-text-dim); }
|
|
1788
|
+
.wp-divider { height: 1px; background: var(--wp-border); margin: 4px 0; }
|
|
1789
|
+
|
|
1790
|
+
/* ---------- Token autocomplete popup ---------- */
|
|
1791
|
+
.wp-autocomplete {
|
|
1792
|
+
position: absolute;
|
|
1793
|
+
top: calc(100% + 4px);
|
|
1794
|
+
left: 0; right: 0;
|
|
1795
|
+
z-index: 50;
|
|
1796
|
+
background: var(--wp-bg-2);
|
|
1797
|
+
border: 1px solid var(--wp-border-strong);
|
|
1798
|
+
border-radius: min(8px, var(--wp-radius-cap, 999px));
|
|
1799
|
+
box-shadow: var(--wp-shadow-md);
|
|
1800
|
+
overflow: hidden;
|
|
1801
|
+
max-height: 280px;
|
|
1802
|
+
display: flex; flex-direction: column;
|
|
1803
|
+
animation: wp-fade-in .1s ease-out;
|
|
1804
|
+
}
|
|
1805
|
+
.wp-autocomplete[data-flip] {
|
|
1806
|
+
top: auto;
|
|
1807
|
+
bottom: calc(100% + 4px);
|
|
1808
|
+
}
|
|
1809
|
+
.wp-autocomplete__head {
|
|
1810
|
+
display: flex; align-items: center;
|
|
1811
|
+
padding: 6px 10px;
|
|
1812
|
+
font-size: 11px;
|
|
1813
|
+
border-bottom: 1px solid var(--wp-border);
|
|
1814
|
+
background: var(--wp-bg-3);
|
|
1815
|
+
color: var(--wp-text-dim);
|
|
1816
|
+
}
|
|
1817
|
+
.wp-autocomplete__item {
|
|
1818
|
+
display: flex; align-items: center; gap: 12px;
|
|
1819
|
+
padding: 7px 10px;
|
|
1820
|
+
background: transparent;
|
|
1821
|
+
border: none;
|
|
1822
|
+
text-align: left;
|
|
1823
|
+
cursor: pointer;
|
|
1824
|
+
color: var(--wp-text);
|
|
1825
|
+
font-size: 12.5px;
|
|
1826
|
+
font-family: var(--wp-font-mono);
|
|
1827
|
+
}
|
|
1828
|
+
.wp-autocomplete__item[data-active="true"] {
|
|
1829
|
+
background: color-mix(in oklab, var(--wp-accent-600) 22%, transparent);
|
|
1830
|
+
}
|
|
1831
|
+
.wp-autocomplete__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1832
|
+
.wp-autocomplete__hint { font-size: 11px; color: var(--wp-text-dim); font-family: var(--wp-font); }
|
|
1833
|
+
|
|
1834
|
+
/* ---------- Custom select popup ---------- */
|
|
1835
|
+
.wp-select-wrap { position: relative; display: inline-block; width: 100%; }
|
|
1836
|
+
|
|
1837
|
+
/* Menu teleported to <body>; position/top/left provided via inline style from JS. */
|
|
1838
|
+
.wp-select__menu {
|
|
1839
|
+
background: var(--wp-bg-3);
|
|
1840
|
+
border: 1px solid var(--wp-border-strong);
|
|
1841
|
+
border-radius: min(7px, var(--wp-radius-cap, 999px));
|
|
1842
|
+
box-shadow: var(--wp-shadow-md);
|
|
1843
|
+
z-index: 9999;
|
|
1844
|
+
padding: 4px;
|
|
1845
|
+
max-height: 240px;
|
|
1846
|
+
overflow: auto;
|
|
1847
|
+
list-style: none;
|
|
1848
|
+
margin: 0;
|
|
1849
|
+
}
|
|
1850
|
+
.wp-select__option {
|
|
1851
|
+
display: flex; align-items: center; gap: 6px;
|
|
1852
|
+
padding: 6px 8px;
|
|
1853
|
+
border-radius: min(6px, var(--wp-radius-cap, 999px));
|
|
1854
|
+
color: var(--wp-text-muted);
|
|
1855
|
+
cursor: pointer;
|
|
1856
|
+
font-size: 12.5px;
|
|
1857
|
+
user-select: none;
|
|
1858
|
+
}
|
|
1859
|
+
.wp-select__option:hover {
|
|
1860
|
+
background: var(--wp-bg-4);
|
|
1861
|
+
color: var(--wp-text);
|
|
1862
|
+
}
|
|
1863
|
+
.wp-select__option[data-active="true"] {
|
|
1864
|
+
background: rgba(99, 102, 241, 0.20);
|
|
1865
|
+
background: color-mix(in oklab, var(--wp-accent-500) 20%, transparent);
|
|
1866
|
+
color: var(--wp-text);
|
|
1867
|
+
}
|
|
1868
|
+
.wp-select__option[data-selected="true"] {
|
|
1869
|
+
background: rgba(99, 102, 241, 0.18);
|
|
1870
|
+
background: color-mix(in oklab, var(--wp-accent-500) 18%, transparent);
|
|
1871
|
+
color: var(--wp-text);
|
|
1872
|
+
}
|
|
1873
|
+
/* Dot + label wrapper inside trigger button */
|
|
1874
|
+
.wp-select__label-wrap {
|
|
1875
|
+
display: flex; align-items: center; gap: 6px;
|
|
1876
|
+
flex: 1; min-width: 0; overflow: hidden;
|
|
1877
|
+
}
|
|
1878
|
+
/* Color dot — rendered in both trigger and option list */
|
|
1879
|
+
.wp-select__dot {
|
|
1880
|
+
width: 8px; height: 8px;
|
|
1881
|
+
border-radius: 50%; /* round: colour dot */
|
|
1882
|
+
flex-shrink: 0;
|
|
1883
|
+
display: inline-block;
|
|
1884
|
+
}
|
|
1885
|
+
/* Label text inside trigger — must be a flex item (not inline) for ellipsis to work */
|
|
1886
|
+
.wp-select__label-text,
|
|
1887
|
+
.wp-select__placeholder {
|
|
1888
|
+
flex: 1; min-width: 0;
|
|
1889
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
1890
|
+
}
|
|
1891
|
+
/* Option label text — no truncation; menu grows to fit widest option */
|
|
1892
|
+
.wp-select__option-label {
|
|
1893
|
+
flex: 1;
|
|
1894
|
+
white-space: nowrap;
|
|
1895
|
+
}
|
|
1896
|
+
.wp-select__placeholder { color: var(--wp-text-dim); }
|
|
1897
|
+
.wp-select__chevron { color: var(--wp-text-dim); font-size: 11px; margin-left: 6px; flex-shrink: 0; }
|
|
1898
|
+
|
|
1899
|
+
/* ---------- Color picker (categories) ---------- */
|
|
1900
|
+
.wp-color-picker {
|
|
1901
|
+
display: inline-flex; align-items: center; gap: 8px;
|
|
1902
|
+
}
|
|
1903
|
+
.wp-color-picker__swatch {
|
|
1904
|
+
position: relative;
|
|
1905
|
+
width: var(--wp-input-h); height: var(--wp-input-h);
|
|
1906
|
+
border-radius: min(7px, var(--wp-radius-cap, 999px));
|
|
1907
|
+
border: 1px solid var(--wp-border);
|
|
1908
|
+
cursor: pointer;
|
|
1909
|
+
flex-shrink: 0;
|
|
1910
|
+
overflow: hidden;
|
|
1911
|
+
display: inline-grid; place-items: center;
|
|
1912
|
+
}
|
|
1913
|
+
.wp-color-picker__swatch input[type="color"] {
|
|
1914
|
+
position: absolute; inset: -2px;
|
|
1915
|
+
width: calc(100% + 4px); height: calc(100% + 4px);
|
|
1916
|
+
border: none; padding: 0; background: transparent;
|
|
1917
|
+
cursor: pointer; opacity: 0;
|
|
1918
|
+
}
|
|
1919
|
+
.wp-color-picker__palette {
|
|
1920
|
+
display: inline-flex; gap: 4px;
|
|
1921
|
+
}
|
|
1922
|
+
.wp-color-picker__chip {
|
|
1923
|
+
width: 22px; height: 22px;
|
|
1924
|
+
border-radius: min(5px, var(--wp-radius-cap, 999px));
|
|
1925
|
+
border: 1px solid var(--wp-border);
|
|
1926
|
+
cursor: pointer; padding: 0;
|
|
1927
|
+
transition: transform .08s, box-shadow .12s;
|
|
1928
|
+
}
|
|
1929
|
+
.wp-color-picker__chip:hover { transform: scale(1.08); }
|
|
1930
|
+
.wp-color-picker__chip[data-active="true"] {
|
|
1931
|
+
box-shadow: 0 0 0 2px var(--wp-bg-1), 0 0 0 4px var(--wp-accent-500);
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
/* ---------- Constraint rule matrix ---------- */
|
|
1935
|
+
.wp-matrix {
|
|
1936
|
+
border-collapse: separate; border-spacing: 4px;
|
|
1937
|
+
font-size: 12px;
|
|
1938
|
+
}
|
|
1939
|
+
.wp-matrix__corner {
|
|
1940
|
+
padding: 0 8px; text-align: left;
|
|
1941
|
+
color: var(--wp-text-dim);
|
|
1942
|
+
font-weight: 500; font-size: 10.5px;
|
|
1943
|
+
text-transform: uppercase; letter-spacing: .05em;
|
|
1944
|
+
display: flex; flex-direction: column; gap: 2px;
|
|
1945
|
+
}
|
|
1946
|
+
.wp-matrix__col-h {
|
|
1947
|
+
padding: 0 8px; color: var(--wp-text-muted);
|
|
1948
|
+
font-weight: 500; white-space: nowrap;
|
|
1949
|
+
}
|
|
1950
|
+
.wp-matrix__row-h {
|
|
1951
|
+
padding: 0 8px; color: var(--wp-text-muted);
|
|
1952
|
+
white-space: nowrap; text-align: left;
|
|
1953
|
+
}
|
|
1954
|
+
.wp-matrix-cell {
|
|
1955
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 3px;
|
|
1956
|
+
min-width: 56px; height: 30px; padding: 0 8px;
|
|
1957
|
+
border-radius: min(6px, var(--wp-radius-cap, 999px)); cursor: pointer;
|
|
1958
|
+
border: 1px solid var(--wp-border);
|
|
1959
|
+
font-family: var(--wp-font);
|
|
1960
|
+
transition: background .12s, border-color .12s, transform .04s;
|
|
1961
|
+
}
|
|
1962
|
+
.wp-matrix-cell:hover { transform: translateY(-1px); }
|
|
1963
|
+
.wp-matrix-cell[data-mode="allow"] { min-width: 36px; padding: 0 6px; }
|
|
1964
|
+
.wp-matrix-cell[data-mode="exclude"] { min-width: 36px; padding: 0 6px; }
|
|
1965
|
+
.wp-matrix-cell__icon { font-size: 14px; font-weight: 600; line-height: 1; }
|
|
1966
|
+
.wp-matrix-cell__factor {
|
|
1967
|
+
font-family: var(--wp-font-mono);
|
|
1968
|
+
font-size: 10.5px; font-weight: 500;
|
|
1969
|
+
opacity: 0.85;
|
|
1970
|
+
}
|
|
1971
|
+
.wp-matrix-cell__tune {
|
|
1972
|
+
position: absolute; top: -6px; right: -6px;
|
|
1973
|
+
width: 18px; height: 18px;
|
|
1974
|
+
border-radius: min(50%, var(--wp-radius-cap, 999px));
|
|
1975
|
+
display: grid; place-items: center;
|
|
1976
|
+
background: var(--wp-bg-1);
|
|
1977
|
+
border: 1px solid var(--wp-border-strong);
|
|
1978
|
+
color: var(--wp-text-muted);
|
|
1979
|
+
cursor: pointer; padding: 0;
|
|
1980
|
+
font-size: 9px;
|
|
1981
|
+
box-shadow: var(--wp-shadow-sm);
|
|
1982
|
+
transition: color .12s, border-color .12s, background .12s;
|
|
1983
|
+
}
|
|
1984
|
+
.wp-matrix-cell__tune:hover {
|
|
1985
|
+
color: var(--wp-accent-text);
|
|
1986
|
+
border-color: var(--wp-accent-500);
|
|
1987
|
+
background: var(--wp-bg-2);
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
/* ---------- Tune popover (matrix factor fine-tune) ---------- */
|
|
1991
|
+
.wp-tune-pop {
|
|
1992
|
+
z-index: 200;
|
|
1993
|
+
background: var(--wp-bg-1);
|
|
1994
|
+
border: 1px solid var(--wp-border-strong);
|
|
1995
|
+
border-radius: min(10px, var(--wp-radius-cap, 999px));
|
|
1996
|
+
padding: 10px 12px;
|
|
1997
|
+
box-shadow: var(--wp-shadow-md, 0 12px 28px rgba(0,0,0,.35));
|
|
1998
|
+
display: flex; flex-direction: column; gap: 8px;
|
|
1999
|
+
}
|
|
2000
|
+
.wp-matrix-cell-wrap {
|
|
2001
|
+
position: relative;
|
|
2002
|
+
display: inline-block;
|
|
2003
|
+
}
|
|
2004
|
+
.wp-tune-pop__head {
|
|
2005
|
+
display: flex; justify-content: space-between; align-items: center;
|
|
2006
|
+
}
|
|
2007
|
+
.wp-tune-pop__row {
|
|
2008
|
+
display: grid; grid-template-columns: 80px 1fr; gap: 8px; align-items: center;
|
|
2009
|
+
}
|
|
2010
|
+
.wp-tune-pop__presets {
|
|
2011
|
+
display: flex; gap: 4px; flex-wrap: wrap; justify-content: flex-end;
|
|
2012
|
+
}
|
|
2013
|
+
.wp-chip-btn {
|
|
2014
|
+
padding: 3px 7px;
|
|
2015
|
+
border-radius: var(--wp-radius-cap, 999px);
|
|
2016
|
+
border: 1px solid var(--wp-border);
|
|
2017
|
+
background: var(--wp-bg-2);
|
|
2018
|
+
color: var(--wp-text-muted);
|
|
2019
|
+
font-size: 10.5px;
|
|
2020
|
+
font-family: var(--wp-font-mono);
|
|
2021
|
+
cursor: pointer;
|
|
2022
|
+
transition: background .12s, color .12s, border-color .12s;
|
|
2023
|
+
}
|
|
2024
|
+
.wp-chip-btn:hover { background: var(--wp-bg-3); color: var(--wp-text); }
|
|
2025
|
+
.wp-chip-btn[data-active="true"] {
|
|
2026
|
+
background: color-mix(in oklab, var(--wp-accent-500) 18%, transparent);
|
|
2027
|
+
color: var(--wp-accent-text-strong);
|
|
2028
|
+
border-color: color-mix(in oklab, var(--wp-accent-500) 40%, transparent);
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
/* native range styled to match */
|
|
2032
|
+
.wp-range {
|
|
2033
|
+
width: 100%;
|
|
2034
|
+
-webkit-appearance: none; appearance: none;
|
|
2035
|
+
height: 4px;
|
|
2036
|
+
background: var(--wp-bg-3);
|
|
2037
|
+
border-radius: var(--wp-radius-cap, 999px);
|
|
2038
|
+
outline: none;
|
|
2039
|
+
cursor: pointer;
|
|
2040
|
+
margin: 6px 0;
|
|
2041
|
+
}
|
|
2042
|
+
.wp-range::-webkit-slider-thumb {
|
|
2043
|
+
-webkit-appearance: none; appearance: none;
|
|
2044
|
+
width: 14px; height: 14px;
|
|
2045
|
+
border-radius: min(50%, var(--wp-radius-cap, 999px));
|
|
2046
|
+
background: var(--wp-accent-500);
|
|
2047
|
+
border: 2px solid var(--wp-bg-1);
|
|
2048
|
+
cursor: pointer;
|
|
2049
|
+
box-shadow: 0 0 0 1px var(--wp-accent-600);
|
|
2050
|
+
}
|
|
2051
|
+
.wp-range::-moz-range-thumb {
|
|
2052
|
+
width: 14px; height: 14px;
|
|
2053
|
+
border-radius: min(50%, var(--wp-radius-cap, 999px));
|
|
2054
|
+
background: var(--wp-accent-500);
|
|
2055
|
+
border: 2px solid var(--wp-bg-1);
|
|
2056
|
+
cursor: pointer;
|
|
2057
|
+
box-shadow: 0 0 0 1px var(--wp-accent-600);
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
/* ---------- Rich text input (syntax-highlighted overlay) ---------- */
|
|
2061
|
+
.wp-rt {
|
|
2062
|
+
position: relative;
|
|
2063
|
+
width: 100%;
|
|
2064
|
+
background: var(--wp-bg-2);
|
|
2065
|
+
border: 1px solid var(--wp-border);
|
|
2066
|
+
border-radius: min(7px, var(--wp-radius-cap, 999px));
|
|
2067
|
+
transition: border-color .12s, background .12s, box-shadow .12s;
|
|
2068
|
+
overflow: hidden;
|
|
2069
|
+
}
|
|
2070
|
+
.wp-rt[data-focused] {
|
|
2071
|
+
border-color: var(--wp-accent-500);
|
|
2072
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--wp-accent-500) 25%, transparent);
|
|
2073
|
+
background: var(--wp-bg-1);
|
|
2074
|
+
}
|
|
2075
|
+
|
|
2076
|
+
/* Mirror layer — renders styled tokens behind the textarea. Two visual modes
|
|
2077
|
+
driven by parent class:
|
|
2078
|
+
--editing : while textarea is focused. Chips are zero-width visual
|
|
2079
|
+
decorations (no padding/margin/border) so mirror text width
|
|
2080
|
+
matches the textarea text width exactly and the caret tracks.
|
|
2081
|
+
--rest : when textarea is blurred. Chips get a hair of horizontal
|
|
2082
|
+
padding so they read as proper pills at a glance. */
|
|
2083
|
+
.wp-rt__mirror {
|
|
2084
|
+
position: absolute;
|
|
2085
|
+
inset: 0;
|
|
2086
|
+
margin: 0;
|
|
2087
|
+
padding: 0 10px;
|
|
2088
|
+
font-size: 12.5px;
|
|
2089
|
+
line-height: var(--wp-input-h);
|
|
2090
|
+
color: var(--wp-text);
|
|
2091
|
+
white-space: pre;
|
|
2092
|
+
overflow: hidden;
|
|
2093
|
+
pointer-events: none;
|
|
2094
|
+
user-select: none;
|
|
2095
|
+
letter-spacing: 0;
|
|
2096
|
+
}
|
|
2097
|
+
.wp-rt__mirror--multi {
|
|
2098
|
+
padding: 8px 10px;
|
|
2099
|
+
line-height: 1.5;
|
|
2100
|
+
white-space: pre-wrap;
|
|
2101
|
+
word-wrap: break-word;
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
/* Textarea/input layer — transparent text so the mirror shows through.
|
|
2105
|
+
Caret stays visible (native blink, native colour). */
|
|
2106
|
+
.wp-rt__input {
|
|
2107
|
+
position: relative;
|
|
2108
|
+
display: block;
|
|
2109
|
+
width: 100%;
|
|
2110
|
+
margin: 0;
|
|
2111
|
+
border: none;
|
|
2112
|
+
outline: none;
|
|
2113
|
+
background: transparent;
|
|
2114
|
+
color: transparent;
|
|
2115
|
+
caret-color: var(--wp-text);
|
|
2116
|
+
font-size: 12.5px;
|
|
2117
|
+
font-family: inherit;
|
|
2118
|
+
letter-spacing: 0;
|
|
2119
|
+
resize: none;
|
|
2120
|
+
}
|
|
2121
|
+
.wp-rt__input--single {
|
|
2122
|
+
height: var(--wp-input-h);
|
|
2123
|
+
padding: 0 10px;
|
|
2124
|
+
line-height: var(--wp-input-h);
|
|
2125
|
+
}
|
|
2126
|
+
.wp-rt__input--multi {
|
|
2127
|
+
padding: 8px 10px;
|
|
2128
|
+
line-height: 1.5;
|
|
2129
|
+
resize: vertical;
|
|
2130
|
+
min-height: 72px;
|
|
2131
|
+
white-space: pre-wrap;
|
|
2132
|
+
word-wrap: break-word;
|
|
2133
|
+
}
|
|
2134
|
+
.wp-rt__input::selection { background: color-mix(in oklab, var(--wp-accent-500) 38%, transparent); color: transparent; }
|
|
2135
|
+
.wp-rt__input::placeholder { color: var(--wp-text-dim); }
|
|
2136
|
+
.wp-rt__tail { color: transparent; }
|
|
2137
|
+
|
|
2138
|
+
/* Token spans — base appearance (width-neutral, suitable while editing) */
|
|
2139
|
+
.wp-rt-text { color: var(--wp-text); }
|
|
2140
|
+
.wp-rt-comment { color: var(--wp-text-dim); font-style: italic; }
|
|
2141
|
+
.wp-rt-escape { color: var(--wp-text-muted); opacity: 0.7; }
|
|
2142
|
+
|
|
2143
|
+
/* `$var`: syntax-coloured text, no pill (the hover card carries the detail). */
|
|
2144
|
+
.wp-rt-var {
|
|
2145
|
+
color: var(--wp-accent-text);
|
|
2146
|
+
font-weight: 600;
|
|
2147
|
+
pointer-events: auto;
|
|
2148
|
+
}
|
|
2149
|
+
.wp-rt-ref {
|
|
2150
|
+
/* --wp-kind-ref = fuchsia-300 dark / fuchsia-800 light */
|
|
2151
|
+
color: var(--wp-kind-ref);
|
|
2152
|
+
background: var(--wp-kind-ref-bg);
|
|
2153
|
+
box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--wp-kind-ref) 28%, transparent);
|
|
2154
|
+
border-radius: min(4px, var(--wp-radius-cap, 999px));
|
|
2155
|
+
font-weight: 500;
|
|
2156
|
+
}
|
|
2157
|
+
/* dp = inline {a|b|c} derivation — matches --wp-kind-derivation (amber) */
|
|
2158
|
+
.wp-rt-dp-brace { color: var(--wp-kind-derivation); font-weight: 600; }
|
|
2159
|
+
.wp-rt-dp-pipe { color: var(--wp-kind-derivation); opacity: 0.65; }
|
|
2160
|
+
.wp-rt-dp-multi {
|
|
2161
|
+
/* multi-candidate group — uses --wp-rt-token-good (green); light override below.
|
|
2162
|
+
SP2b V2: colour only, NO background/box — kept in sync with the scoped rule
|
|
2163
|
+
in manager/styles/rich-text.css (a stray background here was the source of a
|
|
2164
|
+
leftover green box behind multi-pick blocks). */
|
|
2165
|
+
color: var(--wp-rt-token-good);
|
|
2166
|
+
font-weight: 500;
|
|
2167
|
+
}
|
|
2168
|
+
.wp-rt-dp-weight {
|
|
2169
|
+
/* weight factor — uses --wp-rt-token-mut (orange); light override below */
|
|
2170
|
+
color: var(--wp-rt-token-mut);
|
|
2171
|
+
background: var(--wp-rt-token-mut-bg);
|
|
2172
|
+
border-radius: min(3px, var(--wp-radius-cap, 999px));
|
|
2173
|
+
font-weight: 500;
|
|
2174
|
+
}
|
|
2175
|
+
.wp-rt-quantifier {
|
|
2176
|
+
/* quantifier — matches --wp-info (blue) */
|
|
2177
|
+
color: var(--wp-info);
|
|
2178
|
+
background: color-mix(in oklab, var(--wp-info) 14%, transparent);
|
|
2179
|
+
box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--wp-info) 28%, transparent);
|
|
2180
|
+
border-radius: min(3px, var(--wp-radius-cap, 999px));
|
|
2181
|
+
font-weight: 500;
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2184
|
+
/* AT-REST: hair of horizontal padding so chips don't kiss their text. The
|
|
2185
|
+
mirror's width can drift from the (hidden) textarea here — fine, the
|
|
2186
|
+
textarea is invisible at rest. */
|
|
2187
|
+
.wp-rt__mirror--rest .wp-rt-var,
|
|
2188
|
+
.wp-rt__mirror--rest .wp-rt-ref,
|
|
2189
|
+
.wp-rt__mirror--rest .wp-rt-dp-multi,
|
|
2190
|
+
.wp-rt__mirror--rest .wp-rt-dp-weight,
|
|
2191
|
+
.wp-rt__mirror--rest .wp-rt-quantifier {
|
|
2192
|
+
padding: 0 3px;
|
|
2193
|
+
margin: 0 0.5px;
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2196
|
+
/* Inline preview span (used in Combine preview etc.) */
|
|
2197
|
+
.wp-rt__preview {
|
|
2198
|
+
font-family: var(--wp-font-mono);
|
|
2199
|
+
font-size: 12px;
|
|
2200
|
+
}
|
|
2201
|
+
|
|
2202
|
+
/* Token properties popover (for $var chips) */
|
|
2203
|
+
.wp-tokenprops {
|
|
2204
|
+
position: fixed;
|
|
2205
|
+
z-index: 200;
|
|
2206
|
+
width: 320px;
|
|
2207
|
+
background: var(--wp-bg-1);
|
|
2208
|
+
border: 1px solid var(--wp-border-strong);
|
|
2209
|
+
border-radius: min(10px, var(--wp-radius-cap, 999px));
|
|
2210
|
+
box-shadow: var(--wp-shadow-md, 0 12px 28px rgba(0,0,0,.4));
|
|
2211
|
+
padding: 12px;
|
|
2212
|
+
display: flex;
|
|
2213
|
+
flex-direction: column;
|
|
2214
|
+
gap: 10px;
|
|
2215
|
+
}
|
|
2216
|
+
.wp-tokenprops__head {
|
|
2217
|
+
display: flex; align-items: center; gap: 6px;
|
|
2218
|
+
padding-bottom: 8px;
|
|
2219
|
+
border-bottom: 1px solid var(--wp-border);
|
|
2220
|
+
}
|
|
2221
|
+
.wp-tokenprops__name {
|
|
2222
|
+
font-family: var(--wp-font-mono);
|
|
2223
|
+
font-size: 13px;
|
|
2224
|
+
color: var(--wp-accent-text);
|
|
2225
|
+
font-weight: 500;
|
|
2226
|
+
}
|
|
2227
|
+
.wp-tokenprops__type {
|
|
2228
|
+
margin-left: auto;
|
|
2229
|
+
font-size: 10.5px;
|
|
2230
|
+
color: var(--wp-text-dim);
|
|
2231
|
+
text-transform: uppercase;
|
|
2232
|
+
letter-spacing: 0.5px;
|
|
2233
|
+
}
|
|
2234
|
+
.wp-tokenprops__row {
|
|
2235
|
+
display: grid;
|
|
2236
|
+
grid-template-columns: 86px 1fr;
|
|
2237
|
+
gap: 8px;
|
|
2238
|
+
align-items: center;
|
|
2239
|
+
}
|
|
2240
|
+
.wp-tokenprops__label {
|
|
2241
|
+
font-size: 11.5px;
|
|
2242
|
+
color: var(--wp-text-muted);
|
|
2243
|
+
}
|
|
2244
|
+
.wp-tokenprops__output {
|
|
2245
|
+
font-family: var(--wp-font-mono);
|
|
2246
|
+
font-size: 11.5px;
|
|
2247
|
+
background: var(--wp-bg-2);
|
|
2248
|
+
border: 1px solid var(--wp-border);
|
|
2249
|
+
border-radius: min(6px, var(--wp-radius-cap, 999px));
|
|
2250
|
+
padding: 6px 8px;
|
|
2251
|
+
color: var(--wp-text);
|
|
2252
|
+
word-break: break-all;
|
|
2253
|
+
line-height: 1.5;
|
|
2254
|
+
}
|
|
2255
|
+
.wp-tokenprops__legend {
|
|
2256
|
+
font-size: 10.5px;
|
|
2257
|
+
color: var(--wp-text-dim);
|
|
2258
|
+
display: flex;
|
|
2259
|
+
align-items: center;
|
|
2260
|
+
gap: 4px;
|
|
2261
|
+
}
|
|
2262
|
+
|
|
2263
|
+
|
|
2264
|
+
/* ===================== PIPELINES ===================== */
|
|
2265
|
+
|
|
2266
|
+
/* Stack of step rows in the pipeline editor */
|
|
2267
|
+
.wp-pl-stack {
|
|
2268
|
+
display: flex;
|
|
2269
|
+
flex-direction: column;
|
|
2270
|
+
gap: 6px;
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
/* `.wp-pl-empty` removed: PipelineSteps now uses the canonical
|
|
2274
|
+
`.wp-empty-card` class for its empty placeholder. */
|
|
2275
|
+
|
|
2276
|
+
/* ---------- Step row ---------- */
|
|
2277
|
+
.wp-pl-row {
|
|
2278
|
+
display: grid;
|
|
2279
|
+
grid-template-columns: 22px 22px 32px 1fr auto;
|
|
2280
|
+
align-items: center;
|
|
2281
|
+
gap: 10px;
|
|
2282
|
+
padding: 8px 10px;
|
|
2283
|
+
background: var(--wp-bg2);
|
|
2284
|
+
border: 1px solid var(--wp-border);
|
|
2285
|
+
border-left: 3px solid var(--step-color, var(--wp-accent-500));
|
|
2286
|
+
border-radius: var(--wp-radius-md);
|
|
2287
|
+
transition: border-color 120ms ease, background 120ms ease, transform 120ms ease, opacity 120ms ease;
|
|
2288
|
+
}
|
|
2289
|
+
.wp-pl-row:hover {
|
|
2290
|
+
border-color: var(--wp-border-strong);
|
|
2291
|
+
background: var(--wp-bg3);
|
|
2292
|
+
}
|
|
2293
|
+
.wp-pl-row[data-drag-over] {
|
|
2294
|
+
border-top-color: var(--wp-accent-500);
|
|
2295
|
+
box-shadow: 0 -2px 0 var(--wp-accent-500);
|
|
2296
|
+
}
|
|
2297
|
+
.wp-pl-row[data-disabled] { opacity: 0.5; }
|
|
2298
|
+
.wp-pl-row[data-disabled] .wp-pl-row__name select { text-decoration: line-through; }
|
|
2299
|
+
|
|
2300
|
+
/* drag handle */
|
|
2301
|
+
.wp-pl-row__handle {
|
|
2302
|
+
display: flex; align-items: center; justify-content: center;
|
|
2303
|
+
width: 22px; height: 22px;
|
|
2304
|
+
color: var(--wp-text-dim);
|
|
2305
|
+
cursor: grab;
|
|
2306
|
+
border-radius: min(4px, var(--wp-radius-cap, 999px));
|
|
2307
|
+
user-select: none;
|
|
2308
|
+
}
|
|
2309
|
+
.wp-pl-row__handle:hover { color: var(--wp-text); background: var(--wp-bg-hover); }
|
|
2310
|
+
.wp-pl-row__handle:active { cursor: grabbing; }
|
|
2311
|
+
|
|
2312
|
+
/* enable/disable toggle */
|
|
2313
|
+
.wp-pl-row__toggle {
|
|
2314
|
+
width: 22px; height: 22px;
|
|
2315
|
+
display: flex; align-items: center; justify-content: center;
|
|
2316
|
+
border: 1px solid var(--wp-border);
|
|
2317
|
+
background: var(--wp-bg);
|
|
2318
|
+
border-radius: min(4px, var(--wp-radius-cap, 999px));
|
|
2319
|
+
color: var(--wp-text-muted);
|
|
2320
|
+
cursor: pointer;
|
|
2321
|
+
padding: 0;
|
|
2322
|
+
transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
|
|
2323
|
+
}
|
|
2324
|
+
.wp-pl-row__toggle:hover { background: var(--wp-bg-hover); color: var(--wp-text); border-color: var(--wp-border-strong); }
|
|
2325
|
+
|
|
2326
|
+
/* kind icon (color tinted by --step-color) */
|
|
2327
|
+
.wp-pl-row__icon {
|
|
2328
|
+
width: 32px; height: 32px;
|
|
2329
|
+
border-radius: var(--wp-radius-sm);
|
|
2330
|
+
display: flex; align-items: center; justify-content: center;
|
|
2331
|
+
background: color-mix(in oklab, var(--step-color, var(--wp-accent-500)) 16%, var(--wp-bg3));
|
|
2332
|
+
color: var(--step-color, var(--wp-accent-300));
|
|
2333
|
+
flex-shrink: 0;
|
|
2334
|
+
}
|
|
2335
|
+
|
|
2336
|
+
/* main column */
|
|
2337
|
+
.wp-pl-row__main {
|
|
2338
|
+
min-width: 0;
|
|
2339
|
+
display: flex;
|
|
2340
|
+
flex-direction: column;
|
|
2341
|
+
gap: 2px;
|
|
2342
|
+
}
|
|
2343
|
+
.wp-pl-row__top {
|
|
2344
|
+
display: flex; align-items: center; gap: 8px;
|
|
2345
|
+
font-size: 11px;
|
|
2346
|
+
text-transform: uppercase;
|
|
2347
|
+
letter-spacing: 0.04em;
|
|
2348
|
+
color: var(--wp-text-muted);
|
|
2349
|
+
font-weight: 500;
|
|
2350
|
+
}
|
|
2351
|
+
.wp-pl-row__kind { color: var(--step-color, var(--wp-text-muted)); }
|
|
2352
|
+
.wp-pl-row__index {
|
|
2353
|
+
margin-left: auto;
|
|
2354
|
+
font-family: var(--wp-font-mono);
|
|
2355
|
+
font-size: 10.5px;
|
|
2356
|
+
letter-spacing: 0;
|
|
2357
|
+
padding: 1px 5px;
|
|
2358
|
+
border-radius: min(3px, var(--wp-radius-cap, 999px));
|
|
2359
|
+
background: var(--wp-bg);
|
|
2360
|
+
border: 1px solid var(--wp-border);
|
|
2361
|
+
color: var(--wp-text-dim);
|
|
2362
|
+
}
|
|
2363
|
+
.wp-pl-row__name {
|
|
2364
|
+
display: flex;
|
|
2365
|
+
align-items: center;
|
|
2366
|
+
min-width: 0;
|
|
2367
|
+
}
|
|
2368
|
+
.wp-pl-row__sub {
|
|
2369
|
+
font-size: 11.5px;
|
|
2370
|
+
color: var(--wp-text-muted);
|
|
2371
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
/* `.wp-pl-row__refselect` styles intentionally removed.
|
|
2375
|
+
Earlier the pipeline ref-select was a native <select> styled here
|
|
2376
|
+
to look like inline text. We now route through the shared `Select`
|
|
2377
|
+
component (see `components/ui/Select.vue`), which already brings
|
|
2378
|
+
its own height (`--wp-input-h-sm`, 24px at Comfortable) + chevron + focus ring.
|
|
2379
|
+
The leftover `height: 26px; overflow: hidden` rule was clipping the
|
|
2380
|
+
new trigger by ~2px at the bottom, which read as a "cut" border on
|
|
2381
|
+
the pipeline row. The scoped block in PipelineSteps.vue keeps the
|
|
2382
|
+
only two rules still needed (`flex: 1; min-width: 0`). */
|
|
2383
|
+
|
|
2384
|
+
/* row actions */
|
|
2385
|
+
.wp-pl-row__actions {
|
|
2386
|
+
display: flex;
|
|
2387
|
+
align-items: center;
|
|
2388
|
+
gap: 2px;
|
|
2389
|
+
}
|
|
2390
|
+
.wp-pl-row__act {
|
|
2391
|
+
width: 26px; height: 26px;
|
|
2392
|
+
display: flex; align-items: center; justify-content: center;
|
|
2393
|
+
background: transparent;
|
|
2394
|
+
border: 1px solid transparent;
|
|
2395
|
+
border-radius: min(4px, var(--wp-radius-cap, 999px));
|
|
2396
|
+
color: var(--wp-text-muted);
|
|
2397
|
+
cursor: pointer;
|
|
2398
|
+
font-size: 12px;
|
|
2399
|
+
padding: 0;
|
|
2400
|
+
transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
|
|
2401
|
+
}
|
|
2402
|
+
.wp-pl-row__act:hover {
|
|
2403
|
+
background: var(--wp-bg-hover);
|
|
2404
|
+
color: var(--wp-text);
|
|
2405
|
+
border-color: var(--wp-border);
|
|
2406
|
+
}
|
|
2407
|
+
.wp-pl-row__act--danger:hover {
|
|
2408
|
+
background: color-mix(in oklab, var(--wp-danger) 16%, transparent);
|
|
2409
|
+
color: var(--wp-danger-text);
|
|
2410
|
+
border-color: color-mix(in oklab, var(--wp-danger) 30%, transparent);
|
|
2411
|
+
}
|
|
2412
|
+
|
|
2413
|
+
/* add-step button */
|
|
2414
|
+
.wp-pl-add {
|
|
2415
|
+
display: flex;
|
|
2416
|
+
align-items: center;
|
|
2417
|
+
justify-content: center;
|
|
2418
|
+
gap: 8px;
|
|
2419
|
+
padding: 12px;
|
|
2420
|
+
width: 100%;
|
|
2421
|
+
border: 1px dashed var(--wp-border-strong);
|
|
2422
|
+
border-radius: var(--wp-radius-md);
|
|
2423
|
+
background: transparent;
|
|
2424
|
+
color: var(--wp-text-muted);
|
|
2425
|
+
font-size: 12.5px;
|
|
2426
|
+
font-weight: 500;
|
|
2427
|
+
text-transform: uppercase;
|
|
2428
|
+
letter-spacing: 0.06em;
|
|
2429
|
+
cursor: pointer;
|
|
2430
|
+
margin-top: 4px;
|
|
2431
|
+
transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
|
|
2432
|
+
}
|
|
2433
|
+
.wp-pl-add:hover {
|
|
2434
|
+
border-style: solid;
|
|
2435
|
+
border-color: var(--wp-accent-500);
|
|
2436
|
+
color: var(--wp-accent-text);
|
|
2437
|
+
background: color-mix(in oklab, var(--wp-accent-500) 7%, transparent);
|
|
2438
|
+
}
|
|
2439
|
+
.wp-pl-add .pi { font-size: 11px; }
|
|
2440
|
+
|
|
2441
|
+
/* ---------- Module picker tabs ---------- */
|
|
2442
|
+
.wp-pl-tab {
|
|
2443
|
+
display: inline-flex;
|
|
2444
|
+
align-items: center;
|
|
2445
|
+
gap: 6px;
|
|
2446
|
+
padding: 6px 10px;
|
|
2447
|
+
background: var(--wp-bg2);
|
|
2448
|
+
border: 1px solid var(--wp-border);
|
|
2449
|
+
border-radius: var(--wp-radius-sm);
|
|
2450
|
+
color: var(--wp-text-muted);
|
|
2451
|
+
font-size: 12px;
|
|
2452
|
+
font-weight: 500;
|
|
2453
|
+
cursor: pointer;
|
|
2454
|
+
transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
|
|
2455
|
+
}
|
|
2456
|
+
.wp-pl-tab:hover {
|
|
2457
|
+
background: var(--wp-bg3);
|
|
2458
|
+
color: var(--wp-text);
|
|
2459
|
+
border-color: var(--wp-border-strong);
|
|
2460
|
+
}
|
|
2461
|
+
.wp-pl-tab[data-active] {
|
|
2462
|
+
background: color-mix(in oklab, var(--tab-color, var(--wp-accent-500)) 14%, var(--wp-bg2));
|
|
2463
|
+
border-color: color-mix(in oklab, var(--tab-color, var(--wp-accent-500)) 50%, transparent);
|
|
2464
|
+
color: var(--tab-color, var(--wp-accent-text));
|
|
2465
|
+
}
|
|
2466
|
+
.wp-pl-tab__count {
|
|
2467
|
+
font-family: var(--wp-font-mono);
|
|
2468
|
+
font-size: 10.5px;
|
|
2469
|
+
padding: 0 5px;
|
|
2470
|
+
border-radius: var(--wp-radius-cap, 999px);
|
|
2471
|
+
background: var(--wp-bg);
|
|
2472
|
+
border: 1px solid var(--wp-border);
|
|
2473
|
+
color: var(--wp-text-dim);
|
|
2474
|
+
min-width: 18px;
|
|
2475
|
+
text-align: center;
|
|
2476
|
+
}
|
|
2477
|
+
|
|
2478
|
+
/* picker rows */
|
|
2479
|
+
.wp-pl-pickrow {
|
|
2480
|
+
display: flex;
|
|
2481
|
+
align-items: center;
|
|
2482
|
+
gap: 10px;
|
|
2483
|
+
padding: 9px 12px;
|
|
2484
|
+
background: var(--wp-bg2);
|
|
2485
|
+
border: none;
|
|
2486
|
+
cursor: pointer;
|
|
2487
|
+
text-align: left;
|
|
2488
|
+
width: 100%;
|
|
2489
|
+
font-size: 13px;
|
|
2490
|
+
color: var(--wp-text);
|
|
2491
|
+
transition: background 120ms ease;
|
|
2492
|
+
}
|
|
2493
|
+
.wp-pl-pickrow:hover {
|
|
2494
|
+
background: var(--wp-bg3);
|
|
2495
|
+
}
|
|
2496
|
+
.wp-pl-pickrow__icon {
|
|
2497
|
+
width: 28px; height: 28px;
|
|
2498
|
+
border-radius: var(--wp-radius-sm);
|
|
2499
|
+
display: flex; align-items: center; justify-content: center;
|
|
2500
|
+
flex-shrink: 0;
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2503
|
+
/* ---------- Resolution preview flow ---------- */
|
|
2504
|
+
.wp-pl-flow {
|
|
2505
|
+
display: flex;
|
|
2506
|
+
flex-direction: column;
|
|
2507
|
+
gap: 4px;
|
|
2508
|
+
}
|
|
2509
|
+
.wp-pl-flow__step {
|
|
2510
|
+
display: flex;
|
|
2511
|
+
flex-direction: column;
|
|
2512
|
+
gap: 4px;
|
|
2513
|
+
padding: 10px 12px;
|
|
2514
|
+
background: var(--wp-bg);
|
|
2515
|
+
border: 1px solid var(--wp-border);
|
|
2516
|
+
border-left: 3px solid var(--step-color, var(--wp-accent-500));
|
|
2517
|
+
border-radius: var(--wp-radius-md);
|
|
2518
|
+
position: relative;
|
|
2519
|
+
}
|
|
2520
|
+
.wp-pl-flow__step + .wp-pl-flow__step::before {
|
|
2521
|
+
content: "";
|
|
2522
|
+
position: absolute;
|
|
2523
|
+
top: -5px;
|
|
2524
|
+
left: 18px;
|
|
2525
|
+
width: 1px;
|
|
2526
|
+
height: 6px;
|
|
2527
|
+
background: var(--wp-border-strong);
|
|
2528
|
+
}
|
|
2529
|
+
.wp-pl-flow__head {
|
|
2530
|
+
display: flex; align-items: center; gap: 8px;
|
|
2531
|
+
color: var(--wp-text);
|
|
2532
|
+
}
|
|
2533
|
+
.wp-pl-flow__idx {
|
|
2534
|
+
font-family: var(--wp-font-mono);
|
|
2535
|
+
font-size: 10.5px;
|
|
2536
|
+
padding: 1px 5px;
|
|
2537
|
+
border-radius: min(3px, var(--wp-radius-cap, 999px));
|
|
2538
|
+
background: var(--wp-bg2);
|
|
2539
|
+
border: 1px solid var(--wp-border);
|
|
2540
|
+
color: var(--wp-text-dim);
|
|
2541
|
+
}
|
|
2542
|
+
.wp-pl-flow__adds {
|
|
2543
|
+
display: flex;
|
|
2544
|
+
flex-direction: column;
|
|
2545
|
+
gap: 2px;
|
|
2546
|
+
padding-left: 30px;
|
|
2547
|
+
}
|
|
2548
|
+
.wp-pl-flow__binding {
|
|
2549
|
+
display: flex;
|
|
2550
|
+
align-items: baseline;
|
|
2551
|
+
gap: 6px;
|
|
2552
|
+
font-size: 12px;
|
|
2553
|
+
line-height: 1.4;
|
|
2554
|
+
}
|
|
2555
|
+
.wp-pl-flow__binding > span:last-child {
|
|
2556
|
+
color: var(--wp-text);
|
|
2557
|
+
word-break: break-word;
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2560
|
+
/* ---------- Modal (simple, used by picker) ---------- */
|
|
2561
|
+
.wp-modal__backdrop,
|
|
2562
|
+
.wp-modal-backdrop {
|
|
2563
|
+
position: fixed; inset: 0;
|
|
2564
|
+
background: var(--wp-overlay-bg, rgba(0,0,0,0.55));
|
|
2565
|
+
backdrop-filter: blur(4px);
|
|
2566
|
+
display: flex; align-items: center; justify-content: center;
|
|
2567
|
+
z-index: 1000;
|
|
2568
|
+
padding: 24px;
|
|
2569
|
+
animation: wp-modal-fade 120ms ease;
|
|
2570
|
+
}
|
|
2571
|
+
@keyframes wp-modal-fade {
|
|
2572
|
+
from { opacity: 0; }
|
|
2573
|
+
to { opacity: 1; }
|
|
2574
|
+
}
|
|
2575
|
+
.wp-theme-light .wp-modal-backdrop,
|
|
2576
|
+
.wp-theme-light .wp-modal__backdrop {
|
|
2577
|
+
background: rgba(15, 15, 30, 0.45);
|
|
2578
|
+
}
|
|
2579
|
+
.wp-modal {
|
|
2580
|
+
background: var(--wp-bg-2);
|
|
2581
|
+
border: 1px solid var(--wp-border);
|
|
2582
|
+
border-radius: var(--wp-radius-lg);
|
|
2583
|
+
box-shadow: var(--wp-shadow-xl, 0 20px 60px rgba(0,0,0,0.5));
|
|
2584
|
+
width: 100%;
|
|
2585
|
+
max-width: 560px;
|
|
2586
|
+
max-height: calc(100vh - 48px);
|
|
2587
|
+
display: flex;
|
|
2588
|
+
flex-direction: column;
|
|
2589
|
+
overflow: hidden;
|
|
2590
|
+
animation: wp-modal-pop 160ms cubic-bezier(.2,.7,.3,1.2);
|
|
2591
|
+
}
|
|
2592
|
+
/* The dialog takes focus only when nothing in it can (see Modal.vue). */
|
|
2593
|
+
.wp-modal:focus { outline: none; }
|
|
2594
|
+
.wp-modal--sm { max-width: 360px; }
|
|
2595
|
+
.wp-modal--md { max-width: 560px; }
|
|
2596
|
+
.wp-modal--lg { max-width: 880px; }
|
|
2597
|
+
@keyframes wp-modal-pop {
|
|
2598
|
+
from { opacity: 0; transform: translateY(8px) scale(.98); }
|
|
2599
|
+
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
2600
|
+
}
|
|
2601
|
+
.wp-modal__head {
|
|
2602
|
+
display: flex; align-items: center; gap: 10px;
|
|
2603
|
+
padding: 12px 14px;
|
|
2604
|
+
border-bottom: 1px solid var(--wp-border);
|
|
2605
|
+
background: var(--wp-bg);
|
|
2606
|
+
}
|
|
2607
|
+
.wp-modal__title { font-size: 14px; font-weight: 600; margin: 0; flex: 1; }
|
|
2608
|
+
.wp-modal__body {
|
|
2609
|
+
padding: 12px 14px;
|
|
2610
|
+
overflow: auto;
|
|
2611
|
+
flex: 1;
|
|
2612
|
+
min-height: 0;
|
|
2613
|
+
}
|
|
2614
|
+
.wp-modal__foot {
|
|
2615
|
+
display: flex; justify-content: flex-end; gap: 8px;
|
|
2616
|
+
padding: 10px 14px;
|
|
2617
|
+
border-top: 1px solid var(--wp-border);
|
|
2618
|
+
background: var(--wp-bg);
|
|
2619
|
+
}
|
|
2620
|
+
|
|
2621
|
+
|
|
2622
|
+
/* ---------- Picker modal sizing & layout ---------- */
|
|
2623
|
+
.wp-modal--picker {
|
|
2624
|
+
width: 560px;
|
|
2625
|
+
max-width: 100%;
|
|
2626
|
+
max-height: 80vh;
|
|
2627
|
+
display: flex;
|
|
2628
|
+
flex-direction: column;
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2631
|
+
.wp-pl-picker__body {
|
|
2632
|
+
display: flex;
|
|
2633
|
+
flex-direction: column;
|
|
2634
|
+
gap: 10px;
|
|
2635
|
+
min-height: 0;
|
|
2636
|
+
}
|
|
2637
|
+
|
|
2638
|
+
/* tabs row — wraps on narrow widths instead of forcing horizontal scroll */
|
|
2639
|
+
.wp-pl-picker__tabs {
|
|
2640
|
+
display: flex;
|
|
2641
|
+
flex-wrap: wrap;
|
|
2642
|
+
gap: 4px;
|
|
2643
|
+
}
|
|
2644
|
+
.wp-pl-tab {
|
|
2645
|
+
flex: 0 1 auto;
|
|
2646
|
+
min-width: 0;
|
|
2647
|
+
}
|
|
2648
|
+
.wp-pl-tab__label {
|
|
2649
|
+
white-space: nowrap;
|
|
2650
|
+
overflow: hidden;
|
|
2651
|
+
text-overflow: ellipsis;
|
|
2652
|
+
min-width: 0;
|
|
2653
|
+
}
|
|
2654
|
+
|
|
2655
|
+
/* picker list */
|
|
2656
|
+
.wp-pl-picker__list {
|
|
2657
|
+
overflow-y: auto;
|
|
2658
|
+
overflow-x: hidden;
|
|
2659
|
+
border: 1px solid var(--wp-border);
|
|
2660
|
+
border-radius: min(8px, var(--wp-radius-cap, 999px));
|
|
2661
|
+
background: var(--wp-bg);
|
|
2662
|
+
flex: 1;
|
|
2663
|
+
min-height: 200px;
|
|
2664
|
+
display: flex;
|
|
2665
|
+
flex-direction: column;
|
|
2666
|
+
}
|
|
2667
|
+
.wp-pl-pickrow {
|
|
2668
|
+
display: flex;
|
|
2669
|
+
align-items: center;
|
|
2670
|
+
gap: 10px;
|
|
2671
|
+
padding: 9px 12px;
|
|
2672
|
+
background: var(--wp-bg2);
|
|
2673
|
+
border: none;
|
|
2674
|
+
border-bottom: 1px solid var(--wp-border);
|
|
2675
|
+
cursor: pointer;
|
|
2676
|
+
text-align: left;
|
|
2677
|
+
width: 100%;
|
|
2678
|
+
font-size: 13px;
|
|
2679
|
+
color: var(--wp-text);
|
|
2680
|
+
transition: background 120ms ease;
|
|
2681
|
+
min-width: 0;
|
|
2682
|
+
}
|
|
2683
|
+
.wp-pl-pickrow:last-child { border-bottom: none; }
|
|
2684
|
+
.wp-pl-pickrow:hover { background: var(--wp-bg3); }
|
|
2685
|
+
.wp-pl-pickrow__icon {
|
|
2686
|
+
width: 28px; height: 28px;
|
|
2687
|
+
border-radius: var(--wp-radius-sm);
|
|
2688
|
+
display: flex; align-items: center; justify-content: center;
|
|
2689
|
+
flex-shrink: 0;
|
|
2690
|
+
}
|
|
2691
|
+
.wp-pl-pickrow__main {
|
|
2692
|
+
flex: 1;
|
|
2693
|
+
min-width: 0;
|
|
2694
|
+
display: flex;
|
|
2695
|
+
flex-direction: column;
|
|
2696
|
+
gap: 1px;
|
|
2697
|
+
overflow: hidden;
|
|
2698
|
+
}
|
|
2699
|
+
.wp-pl-pickrow__name {
|
|
2700
|
+
font-weight: 500;
|
|
2701
|
+
font-size: 13px;
|
|
2702
|
+
color: var(--wp-text);
|
|
2703
|
+
white-space: nowrap;
|
|
2704
|
+
overflow: hidden;
|
|
2705
|
+
text-overflow: ellipsis;
|
|
2706
|
+
}
|
|
2707
|
+
.wp-pl-pickrow__id {
|
|
2708
|
+
font-size: 11px;
|
|
2709
|
+
font-family: var(--wp-font-mono);
|
|
2710
|
+
color: var(--wp-text-muted);
|
|
2711
|
+
white-space: nowrap;
|
|
2712
|
+
overflow: hidden;
|
|
2713
|
+
text-overflow: ellipsis;
|
|
2714
|
+
}
|
|
2715
|
+
|
|
2716
|
+
/* shrink modal padding on narrow viewports */
|
|
2717
|
+
@media (max-width: 640px) {
|
|
2718
|
+
.wp-modal-backdrop { padding: 12px; }
|
|
2719
|
+
.wp-modal__head, .wp-modal__body, .wp-modal__foot {
|
|
2720
|
+
padding-left: 12px;
|
|
2721
|
+
padding-right: 12px;
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
|
|
2725
|
+
|
|
2726
|
+
/* In picker modal, give the search bar a bit more breathing room. */
|
|
2727
|
+
.wp-pl-picker__body .wp-input-group {
|
|
2728
|
+
flex-shrink: 0;
|
|
2729
|
+
height: 38px;
|
|
2730
|
+
min-height: 38px;
|
|
2731
|
+
}
|
|
2732
|
+
.wp-pl-picker__body .wp-pl-picker__tabs { flex-shrink: 0; }
|
|
2733
|
+
|
|
2734
|
+
/* ---------- Module-kind palette (icon + bg pairs) ----------
|
|
2735
|
+
Source: docs/design-handoff/wildcard-pipeline/project/data.jsx KIND_META.
|
|
2736
|
+
Dark-theme values (bright, high-chroma) — all pass WCAG AA on dark surfaces.
|
|
2737
|
+
Light-theme overrides in .wp-theme-light below use darker shades so the
|
|
2738
|
+
same tokens pass AA on white/near-white surfaces and as chip text on 22% tint. */
|
|
2739
|
+
:root {
|
|
2740
|
+
--wp-kind-wildcard: #a78bfa; /* violet */
|
|
2741
|
+
--wp-kind-wildcard-bg: rgba(167, 139, 250, 0.12);
|
|
2742
|
+
--wp-kind-fixed: #22d3ee; /* cyan */
|
|
2743
|
+
--wp-kind-fixed-bg: rgba(34, 211, 238, 0.12);
|
|
2744
|
+
--wp-kind-combine: #34d399; /* green */
|
|
2745
|
+
--wp-kind-combine-bg: rgba(52, 211, 153, 0.12);
|
|
2746
|
+
--wp-kind-derivation: #fbbf24; /* amber */
|
|
2747
|
+
--wp-kind-derivation-bg: rgba(251, 191, 36, 0.12);
|
|
2748
|
+
--wp-kind-constraint: #f472b6; /* pink */
|
|
2749
|
+
--wp-kind-constraint-bg: rgba(244, 114, 182, 0.12);
|
|
2750
|
+
}
|
|
2751
|
+
|
|
2752
|
+
/* ---------- Accent presets (data-accent on :root) ---------- */
|
|
2753
|
+
:root[data-accent="indigo"] {
|
|
2754
|
+
--wp-accent-50: #eef2ff;
|
|
2755
|
+
--wp-accent-100: #e0e7ff;
|
|
2756
|
+
--wp-accent-200: #c7d2fe;
|
|
2757
|
+
--wp-accent-300: #a5b4fc;
|
|
2758
|
+
--wp-accent-400: #818cf8;
|
|
2759
|
+
--wp-accent-500: #6366f1;
|
|
2760
|
+
--wp-accent-600: #4f46e5;
|
|
2761
|
+
--wp-accent-700: #4338ca;
|
|
2762
|
+
--wp-accent-800: #3730a3;
|
|
2763
|
+
--wp-accent-900: #312e81;
|
|
2764
|
+
}
|
|
2765
|
+
:root[data-accent="teal"] {
|
|
2766
|
+
--wp-accent-50: #f0fdfa;
|
|
2767
|
+
--wp-accent-100: #ccfbf1;
|
|
2768
|
+
--wp-accent-200: #99f6e4;
|
|
2769
|
+
--wp-accent-300: #5eead4;
|
|
2770
|
+
--wp-accent-400: #2dd4bf;
|
|
2771
|
+
--wp-accent-500: #14b8a6;
|
|
2772
|
+
--wp-accent-600: #0d9488;
|
|
2773
|
+
--wp-accent-700: #0f766e;
|
|
2774
|
+
--wp-accent-800: #115e59;
|
|
2775
|
+
--wp-accent-900: #134e4a;
|
|
2776
|
+
}
|
|
2777
|
+
:root[data-accent="rose"] {
|
|
2778
|
+
--wp-accent-50: #fff1f2;
|
|
2779
|
+
--wp-accent-100: #ffe4e6;
|
|
2780
|
+
--wp-accent-200: #fecdd3;
|
|
2781
|
+
--wp-accent-300: #fda4af;
|
|
2782
|
+
--wp-accent-400: #fb7185;
|
|
2783
|
+
--wp-accent-500: #f43f5e;
|
|
2784
|
+
--wp-accent-600: #e11d48;
|
|
2785
|
+
--wp-accent-700: #be123c;
|
|
2786
|
+
--wp-accent-800: #9f1239;
|
|
2787
|
+
--wp-accent-900: #881337;
|
|
2788
|
+
}
|
|
2789
|
+
:root[data-accent="amber"] {
|
|
2790
|
+
--wp-accent-50: #fffbeb;
|
|
2791
|
+
--wp-accent-100: #fef3c7;
|
|
2792
|
+
--wp-accent-200: #fde68a;
|
|
2793
|
+
--wp-accent-300: #fcd34d;
|
|
2794
|
+
--wp-accent-400: #fbbf24;
|
|
2795
|
+
--wp-accent-500: #f59e0b;
|
|
2796
|
+
--wp-accent-600: #d97706;
|
|
2797
|
+
--wp-accent-700: #b45309;
|
|
2798
|
+
--wp-accent-800: #92400e;
|
|
2799
|
+
--wp-accent-900: #78350f;
|
|
2800
|
+
}
|
|
2801
|
+
|
|
2802
|
+
/* Density — applied to <html> by uiStore.setDensity(). Comfortable is the
|
|
2803
|
+
* default (--wp-density: 1 in :root). Control heights and spacing scale
|
|
2804
|
+
* through it; the store writes no heights inline. */
|
|
2805
|
+
html.wp-density-compact {
|
|
2806
|
+
--wp-density: 0.85;
|
|
2807
|
+
}
|
|
2808
|
+
html.wp-density-cozy {
|
|
2809
|
+
--wp-density: 1.12;
|
|
2810
|
+
}
|
|
2811
|
+
|
|
2812
|
+
/* Motion — Settings › Appearance. "Reduce" stops animations and transitions
|
|
2813
|
+
* whatever the OS says; "Auto" leaves the prefers-reduced-motion rules above
|
|
2814
|
+
* in charge. */
|
|
2815
|
+
html.wp-reduce-motion *,
|
|
2816
|
+
html.wp-reduce-motion *::before,
|
|
2817
|
+
html.wp-reduce-motion *::after {
|
|
2818
|
+
animation-duration: 0.001ms !important;
|
|
2819
|
+
animation-iteration-count: 1 !important;
|
|
2820
|
+
transition-duration: 0.001ms !important;
|
|
2821
|
+
scroll-behavior: auto !important;
|
|
2822
|
+
}
|
|
2823
|
+
|
|
2824
|
+
/* ---------- Brand gradient utility ---------- */
|
|
2825
|
+
:root {
|
|
2826
|
+
--wp-brand-gradient: linear-gradient(135deg, var(--wp-brand-1), var(--wp-brand-2), var(--wp-brand-3));
|
|
2827
|
+
}
|
|
2828
|
+
|
|
2829
|
+
/* ---------- Color-scheme hint ----------
|
|
2830
|
+
* The app applies `wp-dark` / `wp-theme-light` classes on <html> from
|
|
2831
|
+
* stores/uiStore.ts. Mark the dark scope explicitly so form controls (date
|
|
2832
|
+
* pickers, scrollbars) respect the theme. */
|
|
2833
|
+
html.wp-dark {
|
|
2834
|
+
color-scheme: dark;
|
|
2835
|
+
}
|
|
2836
|
+
|
|
2837
|
+
/* ---------- Legacy compatibility aliases ----------
|
|
2838
|
+
* Existing .vue components reference an older flat set of token names
|
|
2839
|
+
* (--wp-bg2, --wp-text2, --wp-accent, etc.). Map them to the new tokens
|
|
2840
|
+
* so the screen-by-screen port can roll out without a flag-day rewrite. */
|
|
2841
|
+
:root {
|
|
2842
|
+
/* Surfaces */
|
|
2843
|
+
--wp-bg2: var(--wp-bg-2);
|
|
2844
|
+
--wp-bg3: var(--wp-bg-3);
|
|
2845
|
+
--wp-bg4: var(--wp-bg-4);
|
|
2846
|
+
|
|
2847
|
+
/* Text tiers */
|
|
2848
|
+
--wp-text2: var(--wp-text-muted);
|
|
2849
|
+
--wp-text3: var(--wp-text-dim);
|
|
2850
|
+
--wp-text4: var(--wp-text-dim);
|
|
2851
|
+
|
|
2852
|
+
/* Borders */
|
|
2853
|
+
--wp-border2: var(--wp-border-strong);
|
|
2854
|
+
|
|
2855
|
+
/* Accent — old flat aliases */
|
|
2856
|
+
--wp-accent: var(--wp-accent-500);
|
|
2857
|
+
--wp-accent2: var(--wp-accent-400);
|
|
2858
|
+
--wp-accent-glow: rgba(99, 102, 241, 0.15);
|
|
2859
|
+
|
|
2860
|
+
/* Bundle default color — used by bundle kind icon/badge when no user
|
|
2861
|
+
* color is set. Slate signals "container/structural" vs the kind
|
|
2862
|
+
* palette which signals "module type". Distinct from accent purple
|
|
2863
|
+
* + every kind color; works on dark + light surfaces. */
|
|
2864
|
+
--wp-bundle-default: #64748b; /* slate-500 — light override → #334155 (slate-700) */
|
|
2865
|
+
|
|
2866
|
+
/* Module-kind aliases (legacy single-color tokens) */
|
|
2867
|
+
--wp-violet: var(--wp-kind-wildcard);
|
|
2868
|
+
--wp-violet-bg: var(--wp-kind-wildcard-bg);
|
|
2869
|
+
--wp-teal: var(--wp-kind-fixed);
|
|
2870
|
+
--wp-teal-bg: var(--wp-kind-fixed-bg);
|
|
2871
|
+
--wp-green: var(--wp-kind-combine);
|
|
2872
|
+
--wp-green-bg: var(--wp-kind-combine-bg);
|
|
2873
|
+
--wp-amber: var(--wp-kind-derivation);
|
|
2874
|
+
--wp-amber-bg: var(--wp-kind-derivation-bg);
|
|
2875
|
+
--wp-rose: var(--wp-kind-constraint);
|
|
2876
|
+
--wp-rose-bg: var(--wp-kind-constraint-bg);
|
|
2877
|
+
--wp-red: var(--wp-danger);
|
|
2878
|
+
--wp-red-bg: rgba(239, 68, 68, 0.12);
|
|
2879
|
+
|
|
2880
|
+
/* Type alias */
|
|
2881
|
+
--wp-font-sans: var(--wp-font);
|
|
2882
|
+
}
|
|
2883
|
+
|
|
2884
|
+
/* ---------- Route transition (RouterView fade) ---------- */
|
|
2885
|
+
.route-fade-enter-active,
|
|
2886
|
+
.route-fade-leave-active {
|
|
2887
|
+
transition: opacity 0.16s ease, transform 0.16s ease;
|
|
2888
|
+
}
|
|
2889
|
+
.route-fade-enter-from { opacity: 0; transform: translateY(4px); }
|
|
2890
|
+
.route-fade-leave-to { opacity: 0; transform: translateY(-4px); }
|
|
2891
|
+
|
|
2892
|
+
/* ---------- Toast slide-in (already used by ToastHost) ---------- */
|
|
2893
|
+
@keyframes wp-toast-in {
|
|
2894
|
+
from { opacity: 0; transform: translateX(12px); }
|
|
2895
|
+
to { opacity: 1; transform: translateX(0); }
|
|
2896
|
+
}
|