PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.12
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.12
1.1.12 1.1.11 1.1.10 1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.1 1.0.0 0.9.8 0.9.7 0.9.6 0.9.4 0.9.5 0.9.3 0.9.2 0.9.1 0.9.0 0.8.9 All 36 releases
← All changes | assets/css/ai-assistant.css +359 -260 0.9.1 → 1.1.12 View file →
@@ -1,17 +1,38 @@
1 1 /**
2 - * Desktop Mode — AI Assistant spotlight overlay.
2 + * OpenStation — AI Assistant spotlight overlay.
3 3 *
4 4 * A system-level command palette that floats above the entire shell,
5 5 * including the WP admin bar. Visually modeled on macOS Spotlight and
6 6 * Linear's command menu — frosted-glass backdrop, spring-physics panel
7 - * entrance, large search input, accent-tinted header.
7 + * entrance, large search input.
8 8 *
9 - * z-index 10000 puts this above --desktop-mode-z-adminbar (9991) so the
10 - * overlay truly covers the full viewport. The panel itself is white/light
11 - * regardless of wallpaper, providing consistent contrast.
9 + * ## How much accent the chrome shows
12 10 *
13 - * @since 0.14.0
11 + * Every accent-derived surface below (the header tint and its mark, the
12 + * search icon, a selected or hovered row, the icon tiles) mixes the
13 + * accent by --os-ai-accent towards a neutral. Unset that is 100%, the
14 + * accent-tinted panel this has always been; the OpenStation palette
15 + * answers 0% and lifts rows and tiles with --os-ai-row-fill and
16 + * --os-ai-tile-fill instead. The command icons themselves are not part
17 + * of it: they read the accent directly, in every palette.
18 + *
19 + * z-index 10000 puts this above --os-z-adminbar (9991) so the
20 + * overlay truly covers the full viewport.
21 + *
22 + * ## Desktop-theme awareness
23 + *
24 + * The overlay mounts on `document.body`, so it sits inside the
25 + * `body.os-desktop-theme-<slug>` half of a compiled theme's
26 + * doubled selector and every `--os-ui-*` token below resolves against the
27 + * active theme. Each site reads `var( --os-ui-x, <the literal that was
28 + * always there> )`, so an unthemed shell paints exactly as before.
29 + *
30 + * Getting this half-right is worse than not doing it at all: when the
31 + * text tones followed the theme but the panel stayed hardcoded white,
32 + * a dark theme's light `--os-ui-fg` landed on white and the results were
33 + * unreadable. Any new surface added here MUST take its background,
34 + * border and text from the palette — not from a literal.
14 35 */
15 36
16 37 /* ---------------------------------------------------------------------------
17 38 * Root overlay — full viewport, fades in/out
@@ -16,9 +37,9 @@
16 37 /* ---------------------------------------------------------------------------
17 38 * Root overlay — full viewport, fades in/out
18 39 * ------------------------------------------------------------------------- */
19 40
20 -.desktop-mode-ai {
41 +.os-ai {
21 42 position: fixed;
22 43 inset: 0;
23 44 z-index: 10000;
24 45
@@ -39,13 +60,13 @@
39 60 }
40 61
41 62 /* [hidden] keeps the element out of the a11y tree between sessions.
42 63 Only removed while the overlay is visually visible (open or animating). */
43 -.desktop-mode-ai[hidden] {
64 +.os-ai[hidden] {
44 65 display: none;
45 66 }
46 67
47 -.desktop-mode-ai.is-open {
68 +.os-ai.is-open {
48 69 opacity: 1;
49 70 pointer-events: auto;
50 71 }
51 72
@@ -52,16 +73,21 @@
52 73 /* ---------------------------------------------------------------------------
53 74 * Backdrop — frosted glass
54 75 * ------------------------------------------------------------------------- */
55 76
56 -.desktop-mode-ai__backdrop {
77 +.os-ai__backdrop {
57 78 position: absolute;
58 79 inset: 0;
59 - background: rgba( 0, 0, 0, 0.36 );
80 + background-color: var( --os-ui-scrim, rgba( 0, 0, 0, 0.36 ) );
81 + /* Desktop-theme SCRIM texture slot: unset resolves to none. */
82 + background-image: var( --os-ui-scrim-image, none );
83 + background-repeat: var( --os-ui-scrim-image-repeat, repeat );
84 + background-size: var( --os-ui-scrim-image-size, auto );
85 + background-position: var( --os-ui-scrim-image-position, center );
60 86 backdrop-filter: blur( 8px ) saturate( 0.75 );
61 87 -webkit-backdrop-filter: blur( 8px ) saturate( 0.75 );
62 - /* Backdrop is intentionally non-interactive — the overlay stays open
63 - until the user explicitly clicks the × close button. */
88 + /* Non-interactive: clicks in the dimmed area fall through to the overlay
89 + container, which closes the assistant (click-outside-to-dismiss). */
64 90 pointer-events: none;
65 91 }
66 92
67 93 /* ---------------------------------------------------------------------------
@@ -67,20 +93,35 @@
67 93 /* ---------------------------------------------------------------------------
68 94 * Panel — the visible card
69 95 * ------------------------------------------------------------------------- */
70 96
71 -.desktop-mode-ai__panel {
97 +.os-ai__panel {
72 98 position: relative; /* sits above the backdrop */
73 99 width: 100%;
74 100 max-width: 600px;
75 101
76 - background: rgba( 255, 255, 255, 0.97 );
102 + /* Longhand on purpose: the DIALOG texture slot below owns
103 + background-image, and the shorthand would reset it. */
104 + background-color: var(
105 + --os-ai-panel-bg,
106 + var( --os-ui-surface, rgba( 255, 255, 255, 0.97 ) )
107 + );
108 + /* Desktop-theme DIALOG texture slot: unset resolves to none. */
109 + background-image: var( --os-ui-dialog-bg-image, none );
110 + background-repeat: var( --os-ui-dialog-bg-image-repeat, repeat );
111 + background-size: var( --os-ui-dialog-bg-image-size, auto );
112 + background-position: var( --os-ui-dialog-bg-image-position, center );
113 + color: var( --os-ui-fg, #1d2327 );
114 + font-family: var( --os-ui-font, inherit );
77 115 border-radius: 16px;
78 116 overflow: hidden;
79 117
80 - /* Tight under-shadow + wide atmospheric shadow */
118 + /* Tight under-shadow + wide atmospheric shadow. The hairline ring
119 + is the panel's only edge, so it follows the palette; the two
120 + atmospheric shadows stay black because they read as depth
121 + against the wallpaper, not as part of the surface. */
81 122 box-shadow:
82 - 0 0 0 1px rgba( 0, 0, 0, 0.07 ),
123 + 0 0 0 1px var( --os-ui-border, rgba( 0, 0, 0, 0.07 ) ),
83 124 0 4px 16px rgba( 0, 0, 0, 0.12 ),
84 125 0 24px 64px rgba( 0, 0, 0, 0.22 );
85 126
86 127 /* Spring-physics entrance: starts slightly small + shifted up,
@@ -89,57 +130,60 @@
89 130 transition: transform 0.28s cubic-bezier( 0.34, 1.56, 0.64, 1 );
90 131 will-change: transform;
91 132 }
92 133
93 -.desktop-mode-ai.is-open .desktop-mode-ai__panel {
134 +.os-ai.is-open .os-ai__panel {
94 135 transform: scale( 1 ) translateY( 0 );
95 136 }
96 137
97 -/* ---------------------------------------------------------------------------
98 - * Header — accent-tinted identity strip
99 - * ------------------------------------------------------------------------- */
138 +/* Mode switch (Commands ↔ AI) — a small segmented pill at the end of
139 + the input row. Always shown; replaces the `/` shortcut. */
140 +.os-ai__modes {
141 + flex-shrink: 0;
142 + display: inline-flex;
143 + gap: 2px;
144 + padding: 2px;
145 + border-radius: 999px;
146 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.05 ) );
147 +}
100 148
101 -.desktop-mode-ai__header {
102 - display: flex;
103 - align-items: center;
104 - gap: 8px;
105 - padding: 10px 14px;
106 - /* Gradient fades from a very faint accent tint to white — visible
107 - on fresh/blue schemes, subtle on light schemes. */
108 - background: linear-gradient(
109 - to bottom,
110 - color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 8%, #fff ),
111 - #fff
112 - );
113 - border-bottom: 1px solid rgba( 0, 0, 0, 0.06 );
149 +.os-ai__mode {
150 + appearance: none;
151 + border: 0;
152 + cursor: pointer;
153 + padding: 3px 12px;
154 + border-radius: 999px;
155 + background: transparent;
156 + color: var( --os-ui-fg-muted, #50575e );
157 + font-size: 11px;
158 + font-weight: 600;
159 + line-height: 1.6;
114 160 }
115 161
116 -.desktop-mode-ai__header-icon {
117 - display: flex;
118 - align-items: center;
119 - color: var( --wp-admin-theme-color, #2271b1 );
120 - /* Glow so the sparkle feels alive on dark or saturated themes */
121 - filter: drop-shadow(
122 - 0 0 5px color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 55%, transparent )
123 - );
162 +.os-ai__mode:hover {
163 + color: var( --os-ui-fg, #1d2327 );
124 164 }
125 165
126 -.desktop-mode-ai__header-label {
127 - flex: 1;
128 - font-size: 11px;
129 - font-weight: 700;
130 - letter-spacing: 0.09em;
131 - text-transform: uppercase;
166 +.os-ai__mode.is-active {
167 + /* Elevated first: the pill sits ON the panel, which is already
168 + `--os-ui-surface`, so a theme that distinguishes the two keeps the
169 + active segment readable. Falls through to plain surface, which is
170 + the default look. */
171 + background: var( --os-ui-surface-elevated, var( --os-ui-surface, #fff ) );
132 172 color: var( --wp-admin-theme-color, #2271b1 );
173 + box-shadow: 0 1px 2px rgba( 0, 0, 0, 0.12 );
133 174 }
134 175
135 -/* .desktop-mode-ai__close styles moved to the bottom results section */
176 +.os-ai__mode:focus-visible {
177 + outline: 2px solid var( --wp-admin-theme-color, #2271b1 );
178 + outline-offset: 1px;
179 +}
136 180
137 181 /* ---------------------------------------------------------------------------
138 182 * Input row — the main interaction surface
139 183 * ------------------------------------------------------------------------- */
140 184
141 -.desktop-mode-ai__input-wrap {
185 +.os-ai__input-wrap {
142 186 display: flex;
143 187 align-items: center;
144 188 gap: 10px;
145 189 padding: 14px 16px;
@@ -147,50 +191,92 @@
147 191 border-bottom: 1px solid transparent;
148 192 transition: border-color 0.15s ease;
149 193 }
150 194
151 -.desktop-mode-ai__input-wrap:has( .desktop-mode-ai__input:focus ) {
152 - border-bottom-color: rgba( 0, 0, 0, 0.06 );
195 +.os-ai__input-wrap:has( .os-ai__input:focus ) {
196 + border-bottom-color: var( --os-ui-border, rgba( 0, 0, 0, 0.06 ) );
153 197 }
154 198
155 -/* Input-row sparkle — visible always, tints toward the accent on focus
156 - so the panel reads as "AI assistant" rather than "search box". */
157 -.desktop-mode-ai__input-icon {
199 +/* Input-row icon: dim at rest, full strength on focus. At rest it is
200 + the accent at 55% alpha, mixed by --os-ai-accent towards the faint
201 + text colour; focused, the accent mixed towards the text colour. */
202 +.os-ai__input-icon {
158 203 flex-shrink: 0;
159 204 display: flex;
160 205 align-items: center;
161 - color: var( --wp-admin-theme-color, #2271b1 );
162 - opacity: 0.55;
163 - transition: opacity 0.18s ease, transform 0.18s ease;
206 + color: color-mix(
207 + in srgb,
208 + color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 55%, transparent ) var( --os-ai-accent, 100% ),
209 + var( --os-ui-fg-faint, #c3c4c7 )
210 + );
211 + transition: color 0.18s ease, transform 0.18s ease;
164 212 }
165 213
166 -.desktop-mode-ai__input-wrap:has( .desktop-mode-ai__input:focus ) .desktop-mode-ai__input-icon {
167 - opacity: 1;
214 +.os-ai__input-wrap:has( .os-ai__input:focus ) .os-ai__input-icon {
215 + color: color-mix(
216 + in srgb,
217 + var( --wp-admin-theme-color, #2271b1 ) var( --os-ai-accent, 100% ),
218 + var( --os-ui-fg, #1d2327 )
219 + );
168 220 transform: scale( 1.08 );
169 221 }
170 222
171 -.desktop-mode-ai__input {
223 +/*
224 + * The search field is a raw `<input type="text">` in the parent shell,
225 + * so core's `forms.css` reaches it:
226 + *
227 + * input[type="text"], … { background-color: #fff; color: #2c3338;
228 + * border: 1px solid #8c8f94;
229 + * border-radius: 4px;
230 + * box-shadow: 0 0 0 transparent }
231 + * input[type="text"]:focus { border-color: #2271b1;
232 + * box-shadow: 0 0 0 1px #2271b1 }
233 + *
234 + * That weighs (0,1,1) — one type selector plus one attribute selector —
235 + * which beats a bare `.os-ai__input` at (0,1,0). The result
236 + * was a bordered white box floating inside the panel: core's chrome,
237 + * core's text colour, ignoring both the design intent (a chromeless
238 + * Spotlight-style field) and any active desktop theme.
239 + *
240 + * Scoping to the overlay root takes the selector to (0,2,0) and wins.
241 + * Same fix as the native-window form-control rule in window-chrome.css.
242 + */
243 +.os-ai .os-ai__input {
172 244 flex: 1;
173 245 min-width: 0;
174 246 appearance: none;
175 247 border: none;
248 + border-radius: 0;
176 249 outline: none;
250 + box-shadow: none;
251 + padding: 0;
252 + /* Matches the height core gave the control, so the row keeps its
253 + comfortable hit target now that core's box is gone. */
254 + min-height: 30px;
177 255 background: transparent;
178 256 font: inherit;
179 257 font-size: 17px;
180 258 font-weight: 400;
181 259 line-height: 1.4;
182 - color: #1d2327;
260 + color: var( --os-ui-fg, #1d2327 );
183 261 }
184 262
185 -.desktop-mode-ai__input::placeholder {
186 - color: #c3c4c7;
263 +/* Core paints a focus border + ring on the element itself; the focus
264 + affordance here is the input row's bottom hairline instead. */
265 +.os-ai .os-ai__input:focus {
266 + border-color: transparent;
267 + box-shadow: none;
268 + outline: none;
269 +}
270 +
271 +.os-ai .os-ai__input::placeholder {
272 + color: var( --os-ui-fg-faint, #c3c4c7 );
187 273 font-weight: 400;
188 274 }
189 275
190 276 /* Submit button — hidden until the user types something, then
191 277 springs in via opacity + scale transition. */
192 -.desktop-mode-ai__submit {
278 +.os-ai__submit {
193 279 flex-shrink: 0;
194 280 display: flex;
195 281 align-items: center;
196 282 justify-content: center;
@@ -197,10 +283,25 @@
197 283 width: 30px;
198 284 height: 30px;
199 285 border: none;
200 286 border-radius: 8px;
201 - background: var( --wp-admin-theme-color, #2271b1 );
202 - color: #fff;
287 + /* An accent key at --os-ai-accent's strength. At 0 it is an icon tile
288 + like the command rows' (the neutral fill, the glyph in the accent);
289 + at 100% the filled accent button with its ink. */
290 + background-color: color-mix(
291 + in srgb,
292 + var( --wp-admin-theme-color, #2271b1 ) var( --os-ai-accent, 100% ),
293 + transparent
294 + );
295 + background-image: linear-gradient(
296 + var( --os-ai-tile-fill, transparent ),
297 + var( --os-ai-tile-fill, transparent )
298 + );
299 + color: color-mix(
300 + in srgb,
301 + var( --os-ui-accent-ink, var( --os-ui-fg-on-accent, #fff ) ) var( --os-ai-accent, 100% ),
302 + var( --wp-admin-theme-color, #2271b1 )
303 + );
203 304 cursor: pointer;
204 305 padding: 0;
205 306 opacity: 0;
206 307 transform: scale( 0.7 );
@@ -209,23 +310,23 @@
209 310 opacity 0.2s ease,
210 311 transform 0.2s cubic-bezier( 0.34, 1.56, 0.64, 1 );
211 312 }
212 313
213 -.desktop-mode-ai__submit.has-value {
314 +.os-ai__submit.has-value {
214 315 opacity: 1;
215 316 transform: scale( 1 );
216 317 pointer-events: auto;
217 318 }
218 319
219 -.desktop-mode-ai__submit:hover {
320 +.os-ai__submit:hover {
220 321 filter: brightness( 1.1 );
221 322 }
222 323
223 -.desktop-mode-ai__submit:active {
324 +.os-ai__submit:active {
224 325 transform: scale( 0.92 );
225 326 }
226 327
227 -.desktop-mode-ai__submit:focus-visible {
328 +.os-ai__submit:focus-visible {
228 329 outline: 2px solid var( --wp-admin-theme-color, #2271b1 );
229 330 outline-offset: 2px;
230 331 }
231 332
@@ -232,86 +333,34 @@
232 333 /* ---------------------------------------------------------------------------
233 334 * Footer — hints and keyboard shortcut legend
234 335 * ------------------------------------------------------------------------- */
235 336
236 -.desktop-mode-ai__footer {
337 +.os-ai__footer {
237 338 display: flex;
238 339 align-items: center;
239 340 justify-content: space-between;
240 341 gap: 8px;
241 342 padding: 8px 16px 10px;
242 - background: rgba( 0, 0, 0, 0.018 );
243 - border-top: 1px solid rgba( 0, 0, 0, 0.05 );
343 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.018 ) );
344 + border-top: 1px solid var( --os-ui-border, rgba( 0, 0, 0, 0.05 ) );
244 345 }
245 346
246 -.desktop-mode-ai__footer-hint {
347 +.os-ai__footer-hint {
247 348 font-size: 11px;
248 - color: #a7aaad;
349 + color: var( --os-ui-fg-muted, #a7aaad );
249 350 }
250 351
251 -.desktop-mode-ai__footer-keys {
252 - display: flex;
253 - align-items: center;
254 - gap: 2px;
255 - font-size: 11px;
256 - color: #b4b9be;
257 - white-space: nowrap;
258 - flex-shrink: 0;
259 -}
260 -
261 -.desktop-mode-ai__footer-keys kbd {
262 - font-family: inherit;
263 - font-size: 10px;
264 - padding: 1px 5px;
265 - border: 1px solid rgba( 0, 0, 0, 0.1 );
266 - border-radius: 4px;
267 - background: rgba( 0, 0, 0, 0.03 );
268 - color: #646970;
269 -}
270 -
271 352 /* ---------------------------------------------------------------------------
272 353 * Admin bar AI button — ⌘K badge + sparkle icon
273 354 * Styles applied via wp_add_inline_style( 'admin-bar', ... ) in PHP.
274 355 * The styles here are for reference; the actual output lives in
275 - * includes/admin-bar.php :: desktop_mode_enqueue_toggle_assets().
356 + * includes/admin-bar.php :: openstation_enqueue_toggle_assets().
276 357 * ------------------------------------------------------------------------- */
277 358
278 359 /* (The admin-bar button styles are added inline in PHP to keep them
279 - on the admin-bar handle so they load even before desktop-mode.js.) */
360 + on the admin-bar handle so they load even before os.js.) */
280 361
281 362 /* ---------------------------------------------------------------------------
282 - * Close button — × icon, top-right of header
283 - * ------------------------------------------------------------------------- */
284 -
285 -.desktop-mode-ai__close {
286 - display: inline-flex;
287 - align-items: center;
288 - justify-content: center;
289 - width: 28px;
290 - height: 28px;
291 - appearance: none;
292 - background: rgba( 0, 0, 0, 0.05 );
293 - border: 1px solid rgba( 0, 0, 0, 0.1 );
294 - border-radius: 6px;
295 - cursor: pointer;
296 - color: #646970;
297 - padding: 0;
298 - flex-shrink: 0;
299 - transition: background 0.1s, color 0.1s, border-color 0.1s;
300 -}
301 -
302 -.desktop-mode-ai__close:hover {
303 - background: rgba( 0, 0, 0, 0.09 );
304 - border-color: rgba( 0, 0, 0, 0.2 );
305 - color: #1d2327;
306 -}
307 -
308 -.desktop-mode-ai__close:focus-visible {
309 - outline: 2px solid var( --wp-admin-theme-color, #2271b1 );
310 - outline-offset: 2px;
311 -}
312 -
313 -/* ---------------------------------------------------------------------------
314 363 * Results / conversation area — three render modes:
315 364 * • Suggestions (empty state, example prompts)
316 365 * • Thinking (spinner + "Thinking…")
317 366 * • Response (assistant bubble + entity card | admin links | nothing)
@@ -316,10 +365,10 @@
316 365 * • Thinking (spinner + "Thinking…")
317 366 * • Response (assistant bubble + entity card | admin links | nothing)
318 367 * ------------------------------------------------------------------------- */
319 368
320 -.desktop-mode-ai__results {
321 - border-top: 1px solid rgba( 0, 0, 0, 0.06 );
369 +.os-ai__results {
370 + border-top: 1px solid var( --os-ui-border, rgba( 0, 0, 0, 0.06 ) );
322 371 max-height: 420px;
323 372 overflow-y: auto;
324 373 overflow-x: hidden;
325 374 padding: 14px 16px;
@@ -331,39 +380,39 @@
331 380 /* -----------------------------------------------------------------
332 381 * Suggestion chips (empty state)
333 382 * ---------------------------------------------------------------- */
334 383
335 -.desktop-mode-ai__suggestions-label {
384 +.os-ai__suggestions-label {
336 385 margin: 0 0 4px;
337 386 font-size: 11px;
338 387 font-weight: 600;
339 388 text-transform: uppercase;
340 389 letter-spacing: 0.08em;
341 - color: #8c8f94;
390 + color: var( --os-ui-fg-muted, #8c8f94 );
342 391 }
343 392
344 -.desktop-mode-ai__suggestions-list {
393 +.os-ai__suggestions-list {
345 394 display: flex;
346 395 flex-wrap: wrap;
347 396 gap: 6px;
348 397 }
349 398
350 -.desktop-mode-ai__suggestion {
399 +.os-ai__suggestion {
351 400 appearance: none;
352 - border: 1px solid rgba( 0, 0, 0, 0.1 );
353 - background: rgba( 0, 0, 0, 0.02 );
401 + border: 1px solid var( --os-ui-border, rgba( 0, 0, 0, 0.1 ) );
402 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.02 ) );
354 403 border-radius: 999px;
355 404 padding: 5px 12px;
356 405 font: inherit;
357 406 font-size: 12px;
358 - color: #50575e;
407 + color: var( --os-ui-fg-muted, #50575e );
359 408 cursor: pointer;
360 409 transition: background 0.12s, border-color 0.12s, color 0.12s;
361 410 }
362 411
363 -.desktop-mode-ai__suggestion:hover {
364 - background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 8%, #fff );
365 - border-color: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 30%, rgba( 0, 0, 0, 0.1 ) );
412 +.os-ai__suggestion:hover {
413 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 8%, var( --os-ui-surface, #fff ) );
414 + border-color: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 30%, var( --os-ui-border, rgba( 0, 0, 0, 0.1 ) ) );
366 415 color: var( --wp-admin-theme-color, #2271b1 );
367 416 }
368 417
369 418 /* -----------------------------------------------------------------
@@ -369,18 +418,18 @@
369 418 /* -----------------------------------------------------------------
370 419 * Thinking / error state
371 420 * ---------------------------------------------------------------- */
372 421
373 -.desktop-mode-ai__state {
422 +.os-ai__state {
374 423 display: flex;
375 424 align-items: center;
376 425 gap: 10px;
377 426 font-size: 13px;
378 - color: #646970;
427 + color: var( --os-ui-fg-muted, #646970 );
379 428 }
380 429
381 -.desktop-mode-ai__state--error {
382 - color: #d63638;
430 +.os-ai__state--error {
431 + color: var( --os-ui-danger, #d63638 );
383 432 align-items: flex-start;
384 433 }
385 434
386 435 /* Inline "AI Settings" link inside the "AI not enabled" error — opens
@@ -386,9 +435,9 @@
386 435 /* Inline "AI Settings" link inside the "AI not enabled" error — opens
387 436 * OS Settings on the AI tab. Styled as a link within the surrounding
388 437 * error text, not a standalone button: inherits the error color and
389 438 * flows with the sentence. */
390 -.desktop-mode-ai__settings-link {
439 +.os-ai__settings-link {
391 440 appearance: none;
392 441 border: 0;
393 442 margin: 0;
394 443 padding: 0;
@@ -399,10 +448,12 @@
399 448 text-decoration: underline;
400 449 text-underline-offset: 2px;
401 450 }
402 451
403 -.desktop-mode-ai__settings-link:hover {
404 - text-decoration: none;
452 +/* Keeps the underline and nudges the colour toward the foreground, so
453 + hovering reads as a response rather than the link going away. */
454 +.os-ai__settings-link:hover {
455 + color: color-mix( in srgb, currentColor 65%, var( --os-ui-fg, #1d2327 ) );
405 456 }
406 457
407 458 /* The shell forces `cursor: default !important` on every clickable
408 459 * surface (see the cursor policy at the top of desktop.css). This
@@ -407,20 +458,20 @@
407 458 /* The shell forces `cursor: default !important` on every clickable
408 459 * surface (see the cursor policy at the top of desktop.css). This
409 460 * recovery link is an explicit, user-approved exception: it keeps a
410 461 * pointer so it reads as the actionable link it is. Scoped under
411 - * `body.desktop-mode-active` so it out-specifies the policy's
462 + * `body.os-active` so it out-specifies the policy's
412 463 * `!important` rule, same trick the resize-handle exceptions use. */
413 -body.desktop-mode-active .desktop-mode-ai__settings-link {
464 +body.os-active .os-ai__settings-link {
414 465 cursor: pointer !important;
415 466 }
416 467
417 -@keyframes desktop-mode-spin {
468 +@keyframes os-spin {
418 469 to { transform: rotate( 360deg ); }
419 470 }
420 471
421 -.desktop-mode-ai__spinner-icon {
422 - animation: desktop-mode-spin 0.9s linear infinite;
472 +.os-ai__spinner-icon {
473 + animation: os-spin 0.9s linear infinite;
423 474 flex-shrink: 0;
424 475 color: var( --wp-admin-theme-color, #2271b1 );
425 476 }
426 477
@@ -427,15 +478,15 @@
427 478 /* -----------------------------------------------------------------
428 479 * Assistant message bubble — prefix for every response
429 480 * ---------------------------------------------------------------- */
430 481
431 -.desktop-mode-ai__bubble {
482 +.os-ai__bubble {
432 483 display: flex;
433 484 align-items: flex-start;
434 485 gap: 10px;
435 486 }
436 487
437 -.desktop-mode-ai__bubble-icon {
488 +.os-ai__bubble-icon {
438 489 flex-shrink: 0;
439 490 display: flex;
440 491 align-items: center;
441 492 justify-content: center;
@@ -441,17 +492,17 @@
441 492 justify-content: center;
442 493 width: 24px;
443 494 height: 24px;
444 495 border-radius: 50%;
445 - background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 12%, #fff );
496 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 12%, var( --os-ui-surface, #fff ) );
446 497 color: var( --wp-admin-theme-color, #2271b1 );
447 498 }
448 499
449 -.desktop-mode-ai__bubble-text {
500 +.os-ai__bubble-text {
450 501 padding-top: 3px;
451 502 font-size: 13px;
452 503 line-height: 1.5;
453 - color: #1d2327;
504 + color: var( --os-ui-fg, #1d2327 );
454 505 flex: 1;
455 506 min-width: 0;
456 507 }
457 508
@@ -459,41 +510,41 @@
459 510 <p>, <ul>/<ol>/<li>, <strong>, <em>, <code>, <a>. Reset margins on
460 511 outer paragraphs so single-paragraph replies (the common case)
461 512 don't get top/bottom spacing; list items get the usual disc/decimal
462 513 markers inside a compact indent. */
463 -.desktop-mode-ai__bubble-text > p,
464 -.desktop-mode-ai__bubble-text > ul,
465 -.desktop-mode-ai__bubble-text > ol {
514 +.os-ai__bubble-text > p,
515 +.os-ai__bubble-text > ul,
516 +.os-ai__bubble-text > ol {
466 517 margin: 0 0 6px;
467 518 }
468 -.desktop-mode-ai__bubble-text > :last-child {
519 +.os-ai__bubble-text > :last-child {
469 520 margin-bottom: 0;
470 521 }
471 -.desktop-mode-ai__bubble-text ul,
472 -.desktop-mode-ai__bubble-text ol {
522 +.os-ai__bubble-text ul,
523 +.os-ai__bubble-text ol {
473 524 padding-inline-start: 20px;
474 525 }
475 -.desktop-mode-ai__bubble-text li {
526 +.os-ai__bubble-text li {
476 527 margin-bottom: 2px;
477 528 }
478 -.desktop-mode-ai__bubble-text code {
479 - background: rgba( 0, 0, 0, 0.05 );
529 +.os-ai__bubble-text code {
530 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.05 ) );
480 531 padding: 1px 5px;
481 532 border-radius: 4px;
482 - font-family: Menlo, Consolas, monospace;
533 + font-family: var( --os-ui-font-mono, Menlo, Consolas, monospace );
483 534 font-size: 11.5px;
484 535 }
485 -.desktop-mode-ai__bubble-text a {
536 +.os-ai__bubble-text a {
486 537 color: var( --wp-admin-theme-color, #2271b1 );
487 538 text-decoration: underline;
488 539 text-underline-offset: 2px;
489 540 }
490 -.desktop-mode-ai__bubble-text a:hover {
541 +.os-ai__bubble-text a:hover {
491 542 text-decoration: none;
492 543 }
493 -.desktop-mode-ai__bubble-text strong {
544 +.os-ai__bubble-text strong {
494 545 font-weight: 600;
495 - color: #1d2327;
546 + color: var( --os-ui-fg, #1d2327 );
496 547 }
497 548
498 549 /* -----------------------------------------------------------------
499 550 * Entity card — shown under the bubble when answer_type=entity
@@ -498,19 +549,19 @@
498 549 /* -----------------------------------------------------------------
499 550 * Entity card — shown under the bubble when answer_type=entity
500 551 * ---------------------------------------------------------------- */
501 552
502 -.desktop-mode-ai__entity {
553 +.os-ai__entity {
503 554 display: flex;
504 555 flex-direction: column;
505 556 gap: 8px;
506 557 padding: 12px 14px;
507 - background: rgba( 0, 0, 0, 0.02 );
508 - border: 1px solid rgba( 0, 0, 0, 0.08 );
558 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.02 ) );
559 + border: 1px solid var( --os-ui-border, rgba( 0, 0, 0, 0.08 ) );
509 560 border-radius: 10px;
510 561 }
511 562
512 -.desktop-mode-ai__entity-header {
563 +.os-ai__entity-header {
513 564 display: flex;
514 565 align-items: center;
515 566 gap: 8px;
516 567 flex-wrap: wrap;
@@ -515,9 +566,9 @@
515 566 gap: 8px;
516 567 flex-wrap: wrap;
517 568 }
518 569
519 -.desktop-mode-ai__entity-topic {
570 +.os-ai__entity-topic {
520 571 display: inline-block;
521 572 font-size: 10px;
522 573 font-weight: 600;
523 574 text-transform: uppercase;
@@ -527,34 +578,34 @@
527 578 padding: 2px 7px;
528 579 border-radius: 999px;
529 580 }
530 581
531 -.desktop-mode-ai__entity-type {
582 +.os-ai__entity-type {
532 583 font-size: 10px;
533 584 font-weight: 600;
534 585 text-transform: uppercase;
535 586 letter-spacing: 0.07em;
536 - color: #8c8f94;
587 + color: var( --os-ui-fg-muted, #8c8f94 );
537 588 }
538 589
539 -.desktop-mode-ai__entity-title {
590 +.os-ai__entity-title {
540 591 margin: 0;
541 592 font-size: 14px;
542 593 font-weight: 600;
543 - color: #1d2327;
594 + color: var( --os-ui-fg, #1d2327 );
544 595 line-height: 1.35;
545 596 }
546 597
547 -.desktop-mode-ai__entity-summary {
598 +.os-ai__entity-summary {
548 599 margin: 0;
549 600 font-size: 12px;
550 601 line-height: 1.5;
551 - color: #50575e;
602 + color: var( --os-ui-fg-muted, #50575e );
552 603 }
553 604
554 605 /* Primary action — opens the entity in a legacy iframe window inside
555 606 the desktop (wp-admin edit URL). */
556 -.desktop-mode-ai__entity-open {
607 +.os-ai__entity-open {
557 608 appearance: none;
558 609 display: inline-flex;
559 610 align-items: center;
560 611 gap: 6px;
@@ -562,9 +613,9 @@
562 613 padding: 6px 14px;
563 614 border: none;
564 615 border-radius: 8px;
565 616 background: var( --wp-admin-theme-color, #2271b1 );
566 - color: #fff;
617 + color: var( --os-ui-accent-ink, var( --os-ui-fg-on-accent, #fff ) );
567 618 font: inherit;
568 619 font-size: 12px;
569 620 font-weight: 500;
570 621 cursor: pointer;
@@ -570,22 +621,22 @@
570 621 cursor: pointer;
571 622 transition: filter 0.1s, transform 0.1s;
572 623 }
573 624
574 -.desktop-mode-ai__entity-open:hover {
625 +.os-ai__entity-open:hover {
575 626 filter: brightness( 1.1 );
576 627 }
577 628
578 -.desktop-mode-ai__entity-open:active {
629 +.os-ai__entity-open:active {
579 630 transform: scale( 0.97 );
580 631 }
581 632
582 -.desktop-mode-ai__entity-open:focus-visible {
633 +.os-ai__entity-open:focus-visible {
583 634 outline: 2px solid var( --wp-admin-theme-color, #2271b1 );
584 635 outline-offset: 2px;
585 636 }
586 637
587 -.desktop-mode-ai__entity-open svg {
638 +.os-ai__entity-open svg {
588 639 margin-inline-start: 2px;
589 640 }
590 641
591 642 /* -----------------------------------------------------------------
@@ -591,22 +642,22 @@
591 642 /* -----------------------------------------------------------------
592 643 * Admin-links list — shown when answer_type=navigation
593 644 * ---------------------------------------------------------------- */
594 645
595 -.desktop-mode-ai__admin-links {
646 +.os-ai__admin-links {
596 647 display: flex;
597 648 flex-direction: column;
598 649 gap: 6px;
599 650 }
600 651
601 -.desktop-mode-ai__admin-link {
652 +.os-ai__admin-link {
602 653 appearance: none;
603 654 display: flex;
604 655 align-items: center;
605 656 gap: 12px;
606 657 padding: 10px 12px;
607 - background: rgba( 0, 0, 0, 0.02 );
608 - border: 1px solid rgba( 0, 0, 0, 0.08 );
658 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.02 ) );
659 + border: 1px solid var( --os-ui-border, rgba( 0, 0, 0, 0.08 ) );
609 660 border-radius: 10px;
610 661 cursor: pointer;
611 662 text-align: start;
612 663 font: inherit;
@@ -613,23 +664,23 @@
613 664 color: inherit;
614 665 transition: background 0.12s, border-color 0.12s, transform 0.08s;
615 666 }
616 667
617 -.desktop-mode-ai__admin-link:hover {
618 - background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 6%, #fff );
619 - border-color: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 25%, rgba( 0, 0, 0, 0.08 ) );
668 +.os-ai__admin-link:hover {
669 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 6%, var( --os-ui-surface, #fff ) );
670 + border-color: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 25%, var( --os-ui-border, rgba( 0, 0, 0, 0.08 ) ) );
620 671 }
621 672
622 -.desktop-mode-ai__admin-link:active {
673 +.os-ai__admin-link:active {
623 674 transform: scale( 0.99 );
624 675 }
625 676
626 -.desktop-mode-ai__admin-link:focus-visible {
677 +.os-ai__admin-link:focus-visible {
627 678 outline: 2px solid var( --wp-admin-theme-color, #2271b1 );
628 679 outline-offset: 2px;
629 680 }
630 681
631 -.desktop-mode-ai__admin-link-icon {
682 +.os-ai__admin-link-icon {
632 683 flex-shrink: 0;
633 684 display: flex;
634 685 align-items: center;
635 686 justify-content: center;
@@ -636,13 +687,13 @@
636 687 width: 32px;
637 688 height: 32px;
638 689 font-size: 18px;
639 690 color: var( --wp-admin-theme-color, #2271b1 );
640 - background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 10%, #fff );
691 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 10%, var( --os-ui-surface, #fff ) );
641 692 border-radius: 8px;
642 693 }
643 694
644 -.desktop-mode-ai__admin-link-body {
695 +.os-ai__admin-link-body {
645 696 flex: 1;
646 697 display: flex;
647 698 flex-direction: column;
648 699 gap: 2px;
@@ -648,17 +699,17 @@
648 699 gap: 2px;
649 700 min-width: 0;
650 701 }
651 702
652 -.desktop-mode-ai__admin-link-title {
703 +.os-ai__admin-link-title {
653 704 font-size: 13px;
654 705 font-weight: 600;
655 - color: #1d2327;
706 + color: var( --os-ui-fg, #1d2327 );
656 707 }
657 708
658 -.desktop-mode-ai__admin-link-desc {
709 +.os-ai__admin-link-desc {
659 710 font-size: 11px;
660 - color: #646970;
711 + color: var( --os-ui-fg-muted, #646970 );
661 712 line-height: 1.4;
662 713 overflow: hidden;
663 714 text-overflow: ellipsis;
664 715 white-space: nowrap;
@@ -663,15 +714,15 @@
663 714 text-overflow: ellipsis;
664 715 white-space: nowrap;
665 716 }
666 717
667 -.desktop-mode-ai__admin-link-arrow {
718 +.os-ai__admin-link-arrow {
668 719 flex-shrink: 0;
669 - color: #c3c4c7;
720 + color: var( --os-ui-fg-faint, #c3c4c7 );
670 721 transition: color 0.12s, transform 0.12s;
671 722 }
672 723
673 -.desktop-mode-ai__admin-link:hover .desktop-mode-ai__admin-link-arrow {
724 +.os-ai__admin-link:hover .os-ai__admin-link-arrow {
674 725 color: var( --wp-admin-theme-color, #2271b1 );
675 726 transform: translateX( 2px );
676 727 }
677 728
@@ -681,15 +732,15 @@
681 732 * admin-link list's visual shape (icon + title + description) but
682 733 * uses a dedicated set of classes so each can evolve independently.
683 734 * ---------------------------------------------------------------- */
684 735
685 -.desktop-mode-ai__cmd-list {
736 +.os-ai__cmd-list {
686 737 display: flex;
687 738 flex-direction: column;
688 739 gap: 4px;
689 740 }
690 741
691 -.desktop-mode-ai__cmd-item {
742 +.os-ai__cmd-item {
692 743 appearance: none;
693 744 display: flex;
694 745 align-items: flex-start;
695 746 gap: 10px;
@@ -704,24 +755,50 @@
704 755 transition: background 0.1s, border-color 0.1s;
705 756 }
706 757
707 758 /*
708 - * Single-line rows (no `.desktop-mode-ai__cmd-desc` child) need the
759 + * Single-line rows (no `.os-ai__cmd-desc` child) need the
709 760 * icon + label baseline-centered instead of top-aligned, otherwise
710 761 * the label floats to the top of the taller icon tile and reads as
711 762 * misaligned. `:has()` is widely supported in evergreen browsers the
712 763 * desktop shell already targets.
713 764 */
714 -.desktop-mode-ai__cmd-item:not(:has(.desktop-mode-ai__cmd-desc)) {
765 +.os-ai__cmd-item:not(:has(.os-ai__cmd-desc)) {
715 766 align-items: center;
716 767 }
717 768
718 -.desktop-mode-ai__cmd-item:hover,
719 -.desktop-mode-ai__cmd-item.is-selected {
720 - background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 8%, #fff );
721 - border-color: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 25%, rgba( 0, 0, 0, 0.08 ) );
769 +/* The lit row: an accent wash and edge at --os-ai-accent's strength,
770 + over the row fill the palette names. Shared with the args-mode rows
771 + below through the same two custom properties. */
772 +.os-ai {
773 + --_row-wash: color-mix(
774 + in srgb,
775 + var( --wp-admin-theme-color, #2271b1 ) calc( var( --os-ai-accent, 100% ) * 0.08 ),
776 + var( --os-ui-surface, #fff )
777 + );
778 + --_row-edge: color-mix(
779 + in srgb,
780 + color-mix(
781 + in srgb,
782 + var( --wp-admin-theme-color, #2271b1 ) 25%,
783 + var( --os-ui-border, rgba( 0, 0, 0, 0.08 ) )
784 + )
785 + var( --os-ai-accent, 100% ),
786 + transparent
787 + );
788 + --_row-fill: linear-gradient(
789 + var( --os-ai-row-fill, transparent ),
790 + var( --os-ai-row-fill, transparent )
791 + );
722 792 }
723 793
794 +.os-ai__cmd-item:hover,
795 +.os-ai__cmd-item.is-selected {
796 + background-color: var( --_row-wash );
797 + background-image: var( --_row-fill );
798 + border-color: var( --_row-edge );
799 +}
800 +
724 801 /*
725 802 * When keyboard navigation is driving selection, suppress the :hover
726 803 * style on rows. Without this, arrowing the cursor past the row that
727 804 * happens to sit under the mouse pointer paints BOTH rows as active
@@ -728,23 +805,24 @@
728 805 * — the keyboard target from `.is-selected` and the pointer target
729 806 * from `:hover`. The JS toggles this class on the list container on
730 807 * ArrowUp/Down and clears it on the next real `mousemove`.
731 808 */
732 -.desktop-mode-ai__cmd-list--kb-nav .desktop-mode-ai__cmd-item:hover {
809 +.os-ai__cmd-list--kb-nav .os-ai__cmd-item:hover {
733 810 background: transparent;
734 811 border-color: transparent;
735 812 }
736 -.desktop-mode-ai__cmd-list--kb-nav .desktop-mode-ai__cmd-item.is-selected:hover {
737 - background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 8%, #fff );
738 - border-color: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 25%, rgba( 0, 0, 0, 0.08 ) );
813 +.os-ai__cmd-list--kb-nav .os-ai__cmd-item.is-selected:hover {
814 + background-color: var( --_row-wash );
815 + background-image: var( --_row-fill );
816 + border-color: var( --_row-edge );
739 817 }
740 818
741 -.desktop-mode-ai__cmd-item:focus-visible {
819 +.os-ai__cmd-item:focus-visible {
742 820 outline: 2px solid var( --wp-admin-theme-color, #2271b1 );
743 821 outline-offset: 2px;
744 822 }
745 823
746 -.desktop-mode-ai__cmd-icon {
824 +.os-ai__cmd-icon {
747 825 flex-shrink: 0;
748 826 display: flex;
749 827 align-items: center;
750 828 justify-content: center;
@@ -750,10 +828,20 @@
750 828 justify-content: center;
751 829 width: 36px;
752 830 height: 36px;
753 831 font-size: 20px;
832 + /* The glyph is the accent in every palette; only its tile follows
833 + --os-ai-accent. */
754 834 color: var( --wp-admin-theme-color, #2271b1 );
755 - background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 10%, #fff );
835 + background-color: color-mix(
836 + in srgb,
837 + var( --wp-admin-theme-color, #2271b1 ) calc( var( --os-ai-accent, 100% ) * 0.1 ),
838 + var( --os-ui-surface, #fff )
839 + );
840 + background-image: linear-gradient(
841 + var( --os-ai-tile-fill, transparent ),
842 + var( --os-ai-tile-fill, transparent )
843 + );
756 844 border-radius: 7px;
757 845 }
758 846
759 847 /*
@@ -759,9 +847,9 @@
759 847 /*
760 848 * Dashicons ship at a 20px baseline; the tile was scaled up but
761 849 * dashicons glyphs need explicit sizing to follow.
762 850 */
763 -.desktop-mode-ai__cmd-icon.dashicons {
851 +.os-ai__cmd-icon.dashicons {
764 852 font-size: 22px;
765 853 width: 36px;
766 854 height: 36px;
767 855 line-height: 36px;
@@ -772,15 +860,15 @@
772 860 * `@wordpress/icons` markup). Constrain the inline SVG so it sits
773 861 * centered inside the tile regardless of the viewBox the source icon
774 862 * shipped with.
775 863 */
776 -.desktop-mode-ai__cmd-icon--svg svg {
864 +.os-ai__cmd-icon--svg svg {
777 865 width: 24px;
778 866 height: 24px;
779 867 fill: currentColor;
780 868 }
781 869
782 -.desktop-mode-ai__cmd-body {
870 +.os-ai__cmd-body {
783 871 flex: 1;
784 872 display: flex;
785 873 flex-direction: column;
786 874 gap: 2px;
@@ -786,58 +874,68 @@
786 874 gap: 2px;
787 875 min-width: 0;
788 876 }
789 877
790 -.desktop-mode-ai__cmd-title {
878 +.os-ai__cmd-title {
791 879 font-size: 13px;
792 880 font-weight: 600;
793 - color: #1d2327;
794 - font-family: Menlo, Consolas, monospace;
881 + color: var( --os-ui-fg, #1d2327 );
882 + font-family: var( --os-ui-font-mono, Menlo, Consolas, monospace );
795 883 letter-spacing: -0.01em;
796 884 }
797 885
798 -.desktop-mode-ai__cmd-hint {
886 +.os-ai__cmd-hint {
799 887 font-weight: 400;
800 - color: #8c8f94;
888 + color: var( --os-ui-fg-muted, #8c8f94 );
801 889 font-size: 12px;
802 890 margin-inline-start: 6px;
803 891 }
804 892
805 -.desktop-mode-ai__cmd-desc {
893 +.os-ai__cmd-desc {
806 894 font-size: 11.5px;
807 - color: #646970;
895 + color: var( --os-ui-fg-muted, #646970 );
808 896 line-height: 1.4;
809 897 font-family: inherit;
810 898 letter-spacing: 0;
811 899 }
812 900
901 +/* Entity search results (posts, pages) — rendered in the same list as
902 + commands but are navigable destinations, not actions. Use regular font
903 + (not the monospace used for slash-commands) so they read as content
904 + search results, matching the classic command palette UX. */
905 +.os-ai__cmd-item.is-entity-result .os-ai__cmd-title {
906 + font-family: inherit;
907 + letter-spacing: 0;
908 +}
909 +
813 910 /* Args mode — a single row showing the locked-in command. Same
814 911 visual language as the list item but with an "Enter to run" hint. */
815 -.desktop-mode-ai__cmd-active {
912 +.os-ai__cmd-active {
816 913 display: flex;
817 914 align-items: flex-start;
818 915 gap: 10px;
819 916 padding: 10px 12px;
820 - background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 10%, #fff );
821 - border: 1px solid color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 30%, rgba( 0, 0, 0, 0.08 ) );
917 + background-color: var( --_row-wash );
918 + background-image: var( --_row-fill );
919 + border: 1px solid var( --_row-edge );
822 920 border-radius: 8px;
823 921 }
824 922
825 -.desktop-mode-ai__cmd-enter-hint {
923 +.os-ai__cmd-enter-hint {
826 924 font-size: 11px;
827 - color: #646970;
925 + color: var( --os-ui-fg-muted, #646970 );
828 926 margin-top: 2px;
829 927 font-family: inherit;
830 928 }
831 929
832 -.desktop-mode-ai__cmd-enter-hint kbd {
930 +.os-ai__cmd-enter-hint kbd {
833 931 font-family: inherit;
834 932 font-size: 10px;
835 933 padding: 1px 4px;
836 - border: 1px solid rgba( 0, 0, 0, 0.12 );
934 + border: 1px solid var( --os-ui-border, rgba( 0, 0, 0, 0.12 ) );
837 935 border-radius: 3px;
838 - background: rgba( 0, 0, 0, 0.03 );
839 - color: #646970;
936 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.03 ) );
937 + color: var( --os-ui-fg-muted, #646970 );
840 938 }
841 939
842 940 /* Suggestion list shown under the locked-in command in args mode.
843 941 Visually identical to the command picker rows but without the
@@ -842,9 +940,9 @@
842 940 /* Suggestion list shown under the locked-in command in args mode.
843 941 Visually identical to the command picker rows but without the
844 942 border-highlight — the "active" glow already lives on the command
845 943 header directly above. */
846 -.desktop-mode-ai__cmd-suggest-list {
944 +.os-ai__cmd-suggest-list {
847 945 display: flex;
848 946 flex-direction: column;
849 947 gap: 2px;
850 948 margin-top: 6px;
@@ -849,9 +947,9 @@
849 947 gap: 2px;
850 948 margin-top: 6px;
851 949 }
852 950
853 -.desktop-mode-ai__cmd-suggest-item {
951 +.os-ai__cmd-suggest-item {
854 952 appearance: none;
855 953 display: flex;
856 954 align-items: flex-start;
857 955 gap: 10px;
@@ -865,23 +963,24 @@
865 963 color: inherit;
866 964 transition: background 0.1s, border-color 0.1s;
867 965 }
868 966
869 -.desktop-mode-ai__cmd-suggest-item:hover,
870 -.desktop-mode-ai__cmd-suggest-item.is-selected {
871 - background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 8%, #fff );
872 - border-color: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 25%, rgba( 0, 0, 0, 0.08 ) );
967 +.os-ai__cmd-suggest-item:hover,
968 +.os-ai__cmd-suggest-item.is-selected {
969 + background-color: var( --_row-wash );
970 + background-image: var( --_row-fill );
971 + border-color: var( --_row-edge );
873 972 }
874 973
875 -.desktop-mode-ai__cmd-suggest-label {
974 +.os-ai__cmd-suggest-label {
876 975 font-size: 13px;
877 976 font-weight: 500;
878 - color: #1d2327;
977 + color: var( --os-ui-fg, #1d2327 );
879 978 }
880 979
881 980 /* Empty / "no matches" state for the palette */
882 -.desktop-mode-ai__state--empty {
883 - color: #8c8f94;
981 +.os-ai__state--empty {
982 + color: var( --os-ui-fg-muted, #8c8f94 );
884 983 font-size: 13px;
885 984 }
886 985
887 986 /* -----------------------------------------------------------------
@@ -887,9 +986,9 @@
887 986 /* -----------------------------------------------------------------
888 987 * Continue button (budget-exhausted state)
889 988 * ---------------------------------------------------------------- */
890 989
891 -.desktop-mode-ai__continue-btn {
990 +.os-ai__continue-btn {
892 991 appearance: none;
893 992 display: inline-flex;
894 993 align-items: center;
895 994 align-self: flex-start;
@@ -897,17 +996,17 @@
897 996 font: inherit;
898 997 font-size: 12px;
899 998 font-weight: 500;
900 999 padding: 6px 12px;
901 - border: 1px dashed rgba( 0, 0, 0, 0.2 );
1000 + border: 1px dashed var( --os-ui-border-strong, rgba( 0, 0, 0, 0.2 ) );
902 1001 border-radius: 6px;
903 1002 background: transparent;
904 - color: #50575e;
1003 + color: var( --os-ui-fg-muted, #50575e );
905 1004 cursor: pointer;
906 1005 transition: background 0.1s, border-color 0.1s, color 0.1s;
907 1006 }
908 1007
909 -.desktop-mode-ai__continue-btn:hover {
910 - background: rgba( 0, 0, 0, 0.04 );
911 - border-color: rgba( 0, 0, 0, 0.3 );
912 - color: #1d2327;
1008 +.os-ai__continue-btn:hover {
1009 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.04 ) );
1010 + border-color: var( --os-ui-border-strong, rgba( 0, 0, 0, 0.3 ) );
1011 + color: var( --os-ui-fg, #1d2327 );
913 1012 }