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 +339 -262 0.9.6 → 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,12 +73,17 @@
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 88 /* Non-interactive: clicks in the dimmed area fall through to the overlay
63 89 container, which closes the assistant (click-outside-to-dismiss). */
@@ -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,65 +130,24 @@
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 - * ------------------------------------------------------------------------- */
100 -
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 );
114 -}
115 -
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 - );
124 -}
125 -
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;
132 - color: var( --wp-admin-theme-color, #2271b1 );
133 -}
134 -
135 -/* Mode switch (Commands ↔ AI) — a small segmented pill in the header.
136 - Shown only when AI is available; replaces the `/` shortcut. */
137 -.desktop-mode-ai__modes {
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;
138 142 display: inline-flex;
139 143 gap: 2px;
140 144 padding: 2px;
141 145 border-radius: 999px;
142 - background: rgba( 0, 0, 0, 0.05 );
146 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.05 ) );
143 147 }
144 148
145 -.desktop-mode-ai__modes[hidden] {
146 - display: none;
147 -}
148 -
149 -.desktop-mode-ai__mode {
149 +.os-ai__mode {
150 150 appearance: none;
151 151 border: 0;
152 152 cursor: pointer;
153 153 padding: 3px 12px;
@@ -152,36 +152,38 @@
152 152 cursor: pointer;
153 153 padding: 3px 12px;
154 154 border-radius: 999px;
155 155 background: transparent;
156 - color: #50575e;
156 + color: var( --os-ui-fg-muted, #50575e );
157 157 font-size: 11px;
158 158 font-weight: 600;
159 159 line-height: 1.6;
160 160 }
161 161
162 -.desktop-mode-ai__mode:hover {
163 - color: #1d2327;
162 +.os-ai__mode:hover {
163 + color: var( --os-ui-fg, #1d2327 );
164 164 }
165 165
166 -.desktop-mode-ai__mode.is-active {
167 - background: #fff;
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 ) );
168 172 color: var( --wp-admin-theme-color, #2271b1 );
169 173 box-shadow: 0 1px 2px rgba( 0, 0, 0, 0.12 );
170 174 }
171 175
172 -.desktop-mode-ai__mode:focus-visible {
176 +.os-ai__mode:focus-visible {
173 177 outline: 2px solid var( --wp-admin-theme-color, #2271b1 );
174 178 outline-offset: 1px;
175 179 }
176 180
177 -/* .desktop-mode-ai__close styles moved to the bottom results section */
178 -
179 181 /* ---------------------------------------------------------------------------
180 182 * Input row — the main interaction surface
181 183 * ------------------------------------------------------------------------- */
182 184
183 -.desktop-mode-ai__input-wrap {
185 +.os-ai__input-wrap {
184 186 display: flex;
185 187 align-items: center;
186 188 gap: 10px;
187 189 padding: 14px 16px;
@@ -189,50 +191,92 @@
189 191 border-bottom: 1px solid transparent;
190 192 transition: border-color 0.15s ease;
191 193 }
192 194
193 -.desktop-mode-ai__input-wrap:has( .desktop-mode-ai__input:focus ) {
194 - 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 ) );
195 197 }
196 198
197 -/* Input-row sparkle — visible always, tints toward the accent on focus
198 - so the panel reads as "AI assistant" rather than "search box". */
199 -.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 {
200 203 flex-shrink: 0;
201 204 display: flex;
202 205 align-items: center;
203 - color: var( --wp-admin-theme-color, #2271b1 );
204 - opacity: 0.55;
205 - 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;
206 212 }
207 213
208 -.desktop-mode-ai__input-wrap:has( .desktop-mode-ai__input:focus ) .desktop-mode-ai__input-icon {
209 - 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 + );
210 220 transform: scale( 1.08 );
211 221 }
212 222
213 -.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 {
214 244 flex: 1;
215 245 min-width: 0;
216 246 appearance: none;
217 247 border: none;
248 + border-radius: 0;
218 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;
219 255 background: transparent;
220 256 font: inherit;
221 257 font-size: 17px;
222 258 font-weight: 400;
223 259 line-height: 1.4;
224 - color: #1d2327;
260 + color: var( --os-ui-fg, #1d2327 );
225 261 }
226 262
227 -.desktop-mode-ai__input::placeholder {
228 - 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 );
229 273 font-weight: 400;
230 274 }
231 275
232 276 /* Submit button — hidden until the user types something, then
233 277 springs in via opacity + scale transition. */
234 -.desktop-mode-ai__submit {
278 +.os-ai__submit {
235 279 flex-shrink: 0;
236 280 display: flex;
237 281 align-items: center;
238 282 justify-content: center;
@@ -239,10 +283,25 @@
239 283 width: 30px;
240 284 height: 30px;
241 285 border: none;
242 286 border-radius: 8px;
243 - background: var( --wp-admin-theme-color, #2271b1 );
244 - 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 + );
245 304 cursor: pointer;
246 305 padding: 0;
247 306 opacity: 0;
248 307 transform: scale( 0.7 );
@@ -251,23 +310,23 @@
251 310 opacity 0.2s ease,
252 311 transform 0.2s cubic-bezier( 0.34, 1.56, 0.64, 1 );
253 312 }
254 313
255 -.desktop-mode-ai__submit.has-value {
314 +.os-ai__submit.has-value {
256 315 opacity: 1;
257 316 transform: scale( 1 );
258 317 pointer-events: auto;
259 318 }
260 319
261 -.desktop-mode-ai__submit:hover {
320 +.os-ai__submit:hover {
262 321 filter: brightness( 1.1 );
263 322 }
264 323
265 -.desktop-mode-ai__submit:active {
324 +.os-ai__submit:active {
266 325 transform: scale( 0.92 );
267 326 }
268 327
269 -.desktop-mode-ai__submit:focus-visible {
328 +.os-ai__submit:focus-visible {
270 329 outline: 2px solid var( --wp-admin-theme-color, #2271b1 );
271 330 outline-offset: 2px;
272 331 }
273 332
@@ -274,21 +333,21 @@
274 333 /* ---------------------------------------------------------------------------
275 334 * Footer — hints and keyboard shortcut legend
276 335 * ------------------------------------------------------------------------- */
277 336
278 -.desktop-mode-ai__footer {
337 +.os-ai__footer {
279 338 display: flex;
280 339 align-items: center;
281 340 justify-content: space-between;
282 341 gap: 8px;
283 342 padding: 8px 16px 10px;
284 - background: rgba( 0, 0, 0, 0.018 );
285 - 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 ) );
286 345 }
287 346
288 -.desktop-mode-ai__footer-hint {
347 +.os-ai__footer-hint {
289 348 font-size: 11px;
290 - color: #a7aaad;
349 + color: var( --os-ui-fg-muted, #a7aaad );
291 350 }
292 351
293 352 /* ---------------------------------------------------------------------------
294 353 * Admin bar AI button — ⌘K badge + sparkle icon
@@ -293,47 +352,15 @@
293 352 /* ---------------------------------------------------------------------------
294 353 * Admin bar AI button — ⌘K badge + sparkle icon
295 354 * Styles applied via wp_add_inline_style( 'admin-bar', ... ) in PHP.
296 355 * The styles here are for reference; the actual output lives in
297 - * includes/admin-bar.php :: desktop_mode_enqueue_toggle_assets().
356 + * includes/admin-bar.php :: openstation_enqueue_toggle_assets().
298 357 * ------------------------------------------------------------------------- */
299 358
300 359 /* (The admin-bar button styles are added inline in PHP to keep them
301 - 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.) */
302 361
303 362 /* ---------------------------------------------------------------------------
304 - * Close button — × icon, top-right of header
305 - * ------------------------------------------------------------------------- */
306 -
307 -.desktop-mode-ai__close {
308 - display: inline-flex;
309 - align-items: center;
310 - justify-content: center;
311 - width: 28px;
312 - height: 28px;
313 - appearance: none;
314 - background: rgba( 0, 0, 0, 0.05 );
315 - border: 1px solid rgba( 0, 0, 0, 0.1 );
316 - border-radius: 6px;
317 - cursor: pointer;
318 - color: #646970;
319 - padding: 0;
320 - flex-shrink: 0;
321 - transition: background 0.1s, color 0.1s, border-color 0.1s;
322 -}
323 -
324 -.desktop-mode-ai__close:hover {
325 - background: rgba( 0, 0, 0, 0.09 );
326 - border-color: rgba( 0, 0, 0, 0.2 );
327 - color: #1d2327;
328 -}
329 -
330 -.desktop-mode-ai__close:focus-visible {
331 - outline: 2px solid var( --wp-admin-theme-color, #2271b1 );
332 - outline-offset: 2px;
333 -}
334 -
335 -/* ---------------------------------------------------------------------------
336 363 * Results / conversation area — three render modes:
337 364 * • Suggestions (empty state, example prompts)
338 365 * • Thinking (spinner + "Thinking…")
339 366 * • Response (assistant bubble + entity card | admin links | nothing)
@@ -338,10 +365,10 @@
338 365 * • Thinking (spinner + "Thinking…")
339 366 * • Response (assistant bubble + entity card | admin links | nothing)
340 367 * ------------------------------------------------------------------------- */
341 368
342 -.desktop-mode-ai__results {
343 - 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 ) );
344 371 max-height: 420px;
345 372 overflow-y: auto;
346 373 overflow-x: hidden;
347 374 padding: 14px 16px;
@@ -353,39 +380,39 @@
353 380 /* -----------------------------------------------------------------
354 381 * Suggestion chips (empty state)
355 382 * ---------------------------------------------------------------- */
356 383
357 -.desktop-mode-ai__suggestions-label {
384 +.os-ai__suggestions-label {
358 385 margin: 0 0 4px;
359 386 font-size: 11px;
360 387 font-weight: 600;
361 388 text-transform: uppercase;
362 389 letter-spacing: 0.08em;
363 - color: #8c8f94;
390 + color: var( --os-ui-fg-muted, #8c8f94 );
364 391 }
365 392
366 -.desktop-mode-ai__suggestions-list {
393 +.os-ai__suggestions-list {
367 394 display: flex;
368 395 flex-wrap: wrap;
369 396 gap: 6px;
370 397 }
371 398
372 -.desktop-mode-ai__suggestion {
399 +.os-ai__suggestion {
373 400 appearance: none;
374 - border: 1px solid rgba( 0, 0, 0, 0.1 );
375 - 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 ) );
376 403 border-radius: 999px;
377 404 padding: 5px 12px;
378 405 font: inherit;
379 406 font-size: 12px;
380 - color: #50575e;
407 + color: var( --os-ui-fg-muted, #50575e );
381 408 cursor: pointer;
382 409 transition: background 0.12s, border-color 0.12s, color 0.12s;
383 410 }
384 411
385 -.desktop-mode-ai__suggestion:hover {
386 - background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 8%, #fff );
387 - 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 ) ) );
388 415 color: var( --wp-admin-theme-color, #2271b1 );
389 416 }
390 417
391 418 /* -----------------------------------------------------------------
@@ -391,18 +418,18 @@
391 418 /* -----------------------------------------------------------------
392 419 * Thinking / error state
393 420 * ---------------------------------------------------------------- */
394 421
395 -.desktop-mode-ai__state {
422 +.os-ai__state {
396 423 display: flex;
397 424 align-items: center;
398 425 gap: 10px;
399 426 font-size: 13px;
400 - color: #646970;
427 + color: var( --os-ui-fg-muted, #646970 );
401 428 }
402 429
403 -.desktop-mode-ai__state--error {
404 - color: #d63638;
430 +.os-ai__state--error {
431 + color: var( --os-ui-danger, #d63638 );
405 432 align-items: flex-start;
406 433 }
407 434
408 435 /* Inline "AI Settings" link inside the "AI not enabled" error — opens
@@ -408,9 +435,9 @@
408 435 /* Inline "AI Settings" link inside the "AI not enabled" error — opens
409 436 * OS Settings on the AI tab. Styled as a link within the surrounding
410 437 * error text, not a standalone button: inherits the error color and
411 438 * flows with the sentence. */
412 -.desktop-mode-ai__settings-link {
439 +.os-ai__settings-link {
413 440 appearance: none;
414 441 border: 0;
415 442 margin: 0;
416 443 padding: 0;
@@ -421,10 +448,12 @@
421 448 text-decoration: underline;
422 449 text-underline-offset: 2px;
423 450 }
424 451
425 -.desktop-mode-ai__settings-link:hover {
426 - 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 ) );
427 456 }
428 457
429 458 /* The shell forces `cursor: default !important` on every clickable
430 459 * surface (see the cursor policy at the top of desktop.css). This
@@ -429,20 +458,20 @@
429 458 /* The shell forces `cursor: default !important` on every clickable
430 459 * surface (see the cursor policy at the top of desktop.css). This
431 460 * recovery link is an explicit, user-approved exception: it keeps a
432 461 * pointer so it reads as the actionable link it is. Scoped under
433 - * `body.desktop-mode-active` so it out-specifies the policy's
462 + * `body.os-active` so it out-specifies the policy's
434 463 * `!important` rule, same trick the resize-handle exceptions use. */
435 -body.desktop-mode-active .desktop-mode-ai__settings-link {
464 +body.os-active .os-ai__settings-link {
436 465 cursor: pointer !important;
437 466 }
438 467
439 -@keyframes desktop-mode-spin {
468 +@keyframes os-spin {
440 469 to { transform: rotate( 360deg ); }
441 470 }
442 471
443 -.desktop-mode-ai__spinner-icon {
444 - animation: desktop-mode-spin 0.9s linear infinite;
472 +.os-ai__spinner-icon {
473 + animation: os-spin 0.9s linear infinite;
445 474 flex-shrink: 0;
446 475 color: var( --wp-admin-theme-color, #2271b1 );
447 476 }
448 477
@@ -449,15 +478,15 @@
449 478 /* -----------------------------------------------------------------
450 479 * Assistant message bubble — prefix for every response
451 480 * ---------------------------------------------------------------- */
452 481
453 -.desktop-mode-ai__bubble {
482 +.os-ai__bubble {
454 483 display: flex;
455 484 align-items: flex-start;
456 485 gap: 10px;
457 486 }
458 487
459 -.desktop-mode-ai__bubble-icon {
488 +.os-ai__bubble-icon {
460 489 flex-shrink: 0;
461 490 display: flex;
462 491 align-items: center;
463 492 justify-content: center;
@@ -463,17 +492,17 @@
463 492 justify-content: center;
464 493 width: 24px;
465 494 height: 24px;
466 495 border-radius: 50%;
467 - 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 ) );
468 497 color: var( --wp-admin-theme-color, #2271b1 );
469 498 }
470 499
471 -.desktop-mode-ai__bubble-text {
500 +.os-ai__bubble-text {
472 501 padding-top: 3px;
473 502 font-size: 13px;
474 503 line-height: 1.5;
475 - color: #1d2327;
504 + color: var( --os-ui-fg, #1d2327 );
476 505 flex: 1;
477 506 min-width: 0;
478 507 }
479 508
@@ -481,41 +510,41 @@
481 510 <p>, <ul>/<ol>/<li>, <strong>, <em>, <code>, <a>. Reset margins on
482 511 outer paragraphs so single-paragraph replies (the common case)
483 512 don't get top/bottom spacing; list items get the usual disc/decimal
484 513 markers inside a compact indent. */
485 -.desktop-mode-ai__bubble-text > p,
486 -.desktop-mode-ai__bubble-text > ul,
487 -.desktop-mode-ai__bubble-text > ol {
514 +.os-ai__bubble-text > p,
515 +.os-ai__bubble-text > ul,
516 +.os-ai__bubble-text > ol {
488 517 margin: 0 0 6px;
489 518 }
490 -.desktop-mode-ai__bubble-text > :last-child {
519 +.os-ai__bubble-text > :last-child {
491 520 margin-bottom: 0;
492 521 }
493 -.desktop-mode-ai__bubble-text ul,
494 -.desktop-mode-ai__bubble-text ol {
522 +.os-ai__bubble-text ul,
523 +.os-ai__bubble-text ol {
495 524 padding-inline-start: 20px;
496 525 }
497 -.desktop-mode-ai__bubble-text li {
526 +.os-ai__bubble-text li {
498 527 margin-bottom: 2px;
499 528 }
500 -.desktop-mode-ai__bubble-text code {
501 - 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 ) );
502 531 padding: 1px 5px;
503 532 border-radius: 4px;
504 - font-family: Menlo, Consolas, monospace;
533 + font-family: var( --os-ui-font-mono, Menlo, Consolas, monospace );
505 534 font-size: 11.5px;
506 535 }
507 -.desktop-mode-ai__bubble-text a {
536 +.os-ai__bubble-text a {
508 537 color: var( --wp-admin-theme-color, #2271b1 );
509 538 text-decoration: underline;
510 539 text-underline-offset: 2px;
511 540 }
512 -.desktop-mode-ai__bubble-text a:hover {
541 +.os-ai__bubble-text a:hover {
513 542 text-decoration: none;
514 543 }
515 -.desktop-mode-ai__bubble-text strong {
544 +.os-ai__bubble-text strong {
516 545 font-weight: 600;
517 - color: #1d2327;
546 + color: var( --os-ui-fg, #1d2327 );
518 547 }
519 548
520 549 /* -----------------------------------------------------------------
521 550 * Entity card — shown under the bubble when answer_type=entity
@@ -520,19 +549,19 @@
520 549 /* -----------------------------------------------------------------
521 550 * Entity card — shown under the bubble when answer_type=entity
522 551 * ---------------------------------------------------------------- */
523 552
524 -.desktop-mode-ai__entity {
553 +.os-ai__entity {
525 554 display: flex;
526 555 flex-direction: column;
527 556 gap: 8px;
528 557 padding: 12px 14px;
529 - background: rgba( 0, 0, 0, 0.02 );
530 - 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 ) );
531 560 border-radius: 10px;
532 561 }
533 562
534 -.desktop-mode-ai__entity-header {
563 +.os-ai__entity-header {
535 564 display: flex;
536 565 align-items: center;
537 566 gap: 8px;
538 567 flex-wrap: wrap;
@@ -537,9 +566,9 @@
537 566 gap: 8px;
538 567 flex-wrap: wrap;
539 568 }
540 569
541 -.desktop-mode-ai__entity-topic {
570 +.os-ai__entity-topic {
542 571 display: inline-block;
543 572 font-size: 10px;
544 573 font-weight: 600;
545 574 text-transform: uppercase;
@@ -549,34 +578,34 @@
549 578 padding: 2px 7px;
550 579 border-radius: 999px;
551 580 }
552 581
553 -.desktop-mode-ai__entity-type {
582 +.os-ai__entity-type {
554 583 font-size: 10px;
555 584 font-weight: 600;
556 585 text-transform: uppercase;
557 586 letter-spacing: 0.07em;
558 - color: #8c8f94;
587 + color: var( --os-ui-fg-muted, #8c8f94 );
559 588 }
560 589
561 -.desktop-mode-ai__entity-title {
590 +.os-ai__entity-title {
562 591 margin: 0;
563 592 font-size: 14px;
564 593 font-weight: 600;
565 - color: #1d2327;
594 + color: var( --os-ui-fg, #1d2327 );
566 595 line-height: 1.35;
567 596 }
568 597
569 -.desktop-mode-ai__entity-summary {
598 +.os-ai__entity-summary {
570 599 margin: 0;
571 600 font-size: 12px;
572 601 line-height: 1.5;
573 - color: #50575e;
602 + color: var( --os-ui-fg-muted, #50575e );
574 603 }
575 604
576 605 /* Primary action — opens the entity in a legacy iframe window inside
577 606 the desktop (wp-admin edit URL). */
578 -.desktop-mode-ai__entity-open {
607 +.os-ai__entity-open {
579 608 appearance: none;
580 609 display: inline-flex;
581 610 align-items: center;
582 611 gap: 6px;
@@ -584,9 +613,9 @@
584 613 padding: 6px 14px;
585 614 border: none;
586 615 border-radius: 8px;
587 616 background: var( --wp-admin-theme-color, #2271b1 );
588 - color: #fff;
617 + color: var( --os-ui-accent-ink, var( --os-ui-fg-on-accent, #fff ) );
589 618 font: inherit;
590 619 font-size: 12px;
591 620 font-weight: 500;
592 621 cursor: pointer;
@@ -592,22 +621,22 @@
592 621 cursor: pointer;
593 622 transition: filter 0.1s, transform 0.1s;
594 623 }
595 624
596 -.desktop-mode-ai__entity-open:hover {
625 +.os-ai__entity-open:hover {
597 626 filter: brightness( 1.1 );
598 627 }
599 628
600 -.desktop-mode-ai__entity-open:active {
629 +.os-ai__entity-open:active {
601 630 transform: scale( 0.97 );
602 631 }
603 632
604 -.desktop-mode-ai__entity-open:focus-visible {
633 +.os-ai__entity-open:focus-visible {
605 634 outline: 2px solid var( --wp-admin-theme-color, #2271b1 );
606 635 outline-offset: 2px;
607 636 }
608 637
609 -.desktop-mode-ai__entity-open svg {
638 +.os-ai__entity-open svg {
610 639 margin-inline-start: 2px;
611 640 }
612 641
613 642 /* -----------------------------------------------------------------
@@ -613,22 +642,22 @@
613 642 /* -----------------------------------------------------------------
614 643 * Admin-links list — shown when answer_type=navigation
615 644 * ---------------------------------------------------------------- */
616 645
617 -.desktop-mode-ai__admin-links {
646 +.os-ai__admin-links {
618 647 display: flex;
619 648 flex-direction: column;
620 649 gap: 6px;
621 650 }
622 651
623 -.desktop-mode-ai__admin-link {
652 +.os-ai__admin-link {
624 653 appearance: none;
625 654 display: flex;
626 655 align-items: center;
627 656 gap: 12px;
628 657 padding: 10px 12px;
629 - background: rgba( 0, 0, 0, 0.02 );
630 - 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 ) );
631 660 border-radius: 10px;
632 661 cursor: pointer;
633 662 text-align: start;
634 663 font: inherit;
@@ -635,23 +664,23 @@
635 664 color: inherit;
636 665 transition: background 0.12s, border-color 0.12s, transform 0.08s;
637 666 }
638 667
639 -.desktop-mode-ai__admin-link:hover {
640 - background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 6%, #fff );
641 - 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 ) ) );
642 671 }
643 672
644 -.desktop-mode-ai__admin-link:active {
673 +.os-ai__admin-link:active {
645 674 transform: scale( 0.99 );
646 675 }
647 676
648 -.desktop-mode-ai__admin-link:focus-visible {
677 +.os-ai__admin-link:focus-visible {
649 678 outline: 2px solid var( --wp-admin-theme-color, #2271b1 );
650 679 outline-offset: 2px;
651 680 }
652 681
653 -.desktop-mode-ai__admin-link-icon {
682 +.os-ai__admin-link-icon {
654 683 flex-shrink: 0;
655 684 display: flex;
656 685 align-items: center;
657 686 justify-content: center;
@@ -658,13 +687,13 @@
658 687 width: 32px;
659 688 height: 32px;
660 689 font-size: 18px;
661 690 color: var( --wp-admin-theme-color, #2271b1 );
662 - 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 ) );
663 692 border-radius: 8px;
664 693 }
665 694
666 -.desktop-mode-ai__admin-link-body {
695 +.os-ai__admin-link-body {
667 696 flex: 1;
668 697 display: flex;
669 698 flex-direction: column;
670 699 gap: 2px;
@@ -670,17 +699,17 @@
670 699 gap: 2px;
671 700 min-width: 0;
672 701 }
673 702
674 -.desktop-mode-ai__admin-link-title {
703 +.os-ai__admin-link-title {
675 704 font-size: 13px;
676 705 font-weight: 600;
677 - color: #1d2327;
706 + color: var( --os-ui-fg, #1d2327 );
678 707 }
679 708
680 -.desktop-mode-ai__admin-link-desc {
709 +.os-ai__admin-link-desc {
681 710 font-size: 11px;
682 - color: #646970;
711 + color: var( --os-ui-fg-muted, #646970 );
683 712 line-height: 1.4;
684 713 overflow: hidden;
685 714 text-overflow: ellipsis;
686 715 white-space: nowrap;
@@ -685,15 +714,15 @@
685 714 text-overflow: ellipsis;
686 715 white-space: nowrap;
687 716 }
688 717
689 -.desktop-mode-ai__admin-link-arrow {
718 +.os-ai__admin-link-arrow {
690 719 flex-shrink: 0;
691 - color: #c3c4c7;
720 + color: var( --os-ui-fg-faint, #c3c4c7 );
692 721 transition: color 0.12s, transform 0.12s;
693 722 }
694 723
695 -.desktop-mode-ai__admin-link:hover .desktop-mode-ai__admin-link-arrow {
724 +.os-ai__admin-link:hover .os-ai__admin-link-arrow {
696 725 color: var( --wp-admin-theme-color, #2271b1 );
697 726 transform: translateX( 2px );
698 727 }
699 728
@@ -703,15 +732,15 @@
703 732 * admin-link list's visual shape (icon + title + description) but
704 733 * uses a dedicated set of classes so each can evolve independently.
705 734 * ---------------------------------------------------------------- */
706 735
707 -.desktop-mode-ai__cmd-list {
736 +.os-ai__cmd-list {
708 737 display: flex;
709 738 flex-direction: column;
710 739 gap: 4px;
711 740 }
712 741
713 -.desktop-mode-ai__cmd-item {
742 +.os-ai__cmd-item {
714 743 appearance: none;
715 744 display: flex;
716 745 align-items: flex-start;
717 746 gap: 10px;
@@ -726,24 +755,50 @@
726 755 transition: background 0.1s, border-color 0.1s;
727 756 }
728 757
729 758 /*
730 - * Single-line rows (no `.desktop-mode-ai__cmd-desc` child) need the
759 + * Single-line rows (no `.os-ai__cmd-desc` child) need the
731 760 * icon + label baseline-centered instead of top-aligned, otherwise
732 761 * the label floats to the top of the taller icon tile and reads as
733 762 * misaligned. `:has()` is widely supported in evergreen browsers the
734 763 * desktop shell already targets.
735 764 */
736 -.desktop-mode-ai__cmd-item:not(:has(.desktop-mode-ai__cmd-desc)) {
765 +.os-ai__cmd-item:not(:has(.os-ai__cmd-desc)) {
737 766 align-items: center;
738 767 }
739 768
740 -.desktop-mode-ai__cmd-item:hover,
741 -.desktop-mode-ai__cmd-item.is-selected {
742 - background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 8%, #fff );
743 - 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 + );
744 792 }
745 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 +
746 801 /*
747 802 * When keyboard navigation is driving selection, suppress the :hover
748 803 * style on rows. Without this, arrowing the cursor past the row that
749 804 * happens to sit under the mouse pointer paints BOTH rows as active
@@ -750,23 +805,24 @@
750 805 * — the keyboard target from `.is-selected` and the pointer target
751 806 * from `:hover`. The JS toggles this class on the list container on
752 807 * ArrowUp/Down and clears it on the next real `mousemove`.
753 808 */
754 -.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 {
755 810 background: transparent;
756 811 border-color: transparent;
757 812 }
758 -.desktop-mode-ai__cmd-list--kb-nav .desktop-mode-ai__cmd-item.is-selected:hover {
759 - background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 8%, #fff );
760 - 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 );
761 817 }
762 818
763 -.desktop-mode-ai__cmd-item:focus-visible {
819 +.os-ai__cmd-item:focus-visible {
764 820 outline: 2px solid var( --wp-admin-theme-color, #2271b1 );
765 821 outline-offset: 2px;
766 822 }
767 823
768 -.desktop-mode-ai__cmd-icon {
824 +.os-ai__cmd-icon {
769 825 flex-shrink: 0;
770 826 display: flex;
771 827 align-items: center;
772 828 justify-content: center;
@@ -772,10 +828,20 @@
772 828 justify-content: center;
773 829 width: 36px;
774 830 height: 36px;
775 831 font-size: 20px;
832 + /* The glyph is the accent in every palette; only its tile follows
833 + --os-ai-accent. */
776 834 color: var( --wp-admin-theme-color, #2271b1 );
777 - 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 + );
778 844 border-radius: 7px;
779 845 }
780 846
781 847 /*
@@ -781,9 +847,9 @@
781 847 /*
782 848 * Dashicons ship at a 20px baseline; the tile was scaled up but
783 849 * dashicons glyphs need explicit sizing to follow.
784 850 */
785 -.desktop-mode-ai__cmd-icon.dashicons {
851 +.os-ai__cmd-icon.dashicons {
786 852 font-size: 22px;
787 853 width: 36px;
788 854 height: 36px;
789 855 line-height: 36px;
@@ -794,15 +860,15 @@
794 860 * `@wordpress/icons` markup). Constrain the inline SVG so it sits
795 861 * centered inside the tile regardless of the viewBox the source icon
796 862 * shipped with.
797 863 */
798 -.desktop-mode-ai__cmd-icon--svg svg {
864 +.os-ai__cmd-icon--svg svg {
799 865 width: 24px;
800 866 height: 24px;
801 867 fill: currentColor;
802 868 }
803 869
804 -.desktop-mode-ai__cmd-body {
870 +.os-ai__cmd-body {
805 871 flex: 1;
806 872 display: flex;
807 873 flex-direction: column;
808 874 gap: 2px;
@@ -808,58 +874,68 @@
808 874 gap: 2px;
809 875 min-width: 0;
810 876 }
811 877
812 -.desktop-mode-ai__cmd-title {
878 +.os-ai__cmd-title {
813 879 font-size: 13px;
814 880 font-weight: 600;
815 - color: #1d2327;
816 - font-family: Menlo, Consolas, monospace;
881 + color: var( --os-ui-fg, #1d2327 );
882 + font-family: var( --os-ui-font-mono, Menlo, Consolas, monospace );
817 883 letter-spacing: -0.01em;
818 884 }
819 885
820 -.desktop-mode-ai__cmd-hint {
886 +.os-ai__cmd-hint {
821 887 font-weight: 400;
822 - color: #8c8f94;
888 + color: var( --os-ui-fg-muted, #8c8f94 );
823 889 font-size: 12px;
824 890 margin-inline-start: 6px;
825 891 }
826 892
827 -.desktop-mode-ai__cmd-desc {
893 +.os-ai__cmd-desc {
828 894 font-size: 11.5px;
829 - color: #646970;
895 + color: var( --os-ui-fg-muted, #646970 );
830 896 line-height: 1.4;
831 897 font-family: inherit;
832 898 letter-spacing: 0;
833 899 }
834 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 +
835 910 /* Args mode — a single row showing the locked-in command. Same
836 911 visual language as the list item but with an "Enter to run" hint. */
837 -.desktop-mode-ai__cmd-active {
912 +.os-ai__cmd-active {
838 913 display: flex;
839 914 align-items: flex-start;
840 915 gap: 10px;
841 916 padding: 10px 12px;
842 - background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 10%, #fff );
843 - 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 );
844 920 border-radius: 8px;
845 921 }
846 922
847 -.desktop-mode-ai__cmd-enter-hint {
923 +.os-ai__cmd-enter-hint {
848 924 font-size: 11px;
849 - color: #646970;
925 + color: var( --os-ui-fg-muted, #646970 );
850 926 margin-top: 2px;
851 927 font-family: inherit;
852 928 }
853 929
854 -.desktop-mode-ai__cmd-enter-hint kbd {
930 +.os-ai__cmd-enter-hint kbd {
855 931 font-family: inherit;
856 932 font-size: 10px;
857 933 padding: 1px 4px;
858 - border: 1px solid rgba( 0, 0, 0, 0.12 );
934 + border: 1px solid var( --os-ui-border, rgba( 0, 0, 0, 0.12 ) );
859 935 border-radius: 3px;
860 - background: rgba( 0, 0, 0, 0.03 );
861 - color: #646970;
936 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.03 ) );
937 + color: var( --os-ui-fg-muted, #646970 );
862 938 }
863 939
864 940 /* Suggestion list shown under the locked-in command in args mode.
865 941 Visually identical to the command picker rows but without the
@@ -864,9 +940,9 @@
864 940 /* Suggestion list shown under the locked-in command in args mode.
865 941 Visually identical to the command picker rows but without the
866 942 border-highlight — the "active" glow already lives on the command
867 943 header directly above. */
868 -.desktop-mode-ai__cmd-suggest-list {
944 +.os-ai__cmd-suggest-list {
869 945 display: flex;
870 946 flex-direction: column;
871 947 gap: 2px;
872 948 margin-top: 6px;
@@ -871,9 +947,9 @@
871 947 gap: 2px;
872 948 margin-top: 6px;
873 949 }
874 950
875 -.desktop-mode-ai__cmd-suggest-item {
951 +.os-ai__cmd-suggest-item {
876 952 appearance: none;
877 953 display: flex;
878 954 align-items: flex-start;
879 955 gap: 10px;
@@ -887,23 +963,24 @@
887 963 color: inherit;
888 964 transition: background 0.1s, border-color 0.1s;
889 965 }
890 966
891 -.desktop-mode-ai__cmd-suggest-item:hover,
892 -.desktop-mode-ai__cmd-suggest-item.is-selected {
893 - background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 8%, #fff );
894 - 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 );
895 972 }
896 973
897 -.desktop-mode-ai__cmd-suggest-label {
974 +.os-ai__cmd-suggest-label {
898 975 font-size: 13px;
899 976 font-weight: 500;
900 - color: #1d2327;
977 + color: var( --os-ui-fg, #1d2327 );
901 978 }
902 979
903 980 /* Empty / "no matches" state for the palette */
904 -.desktop-mode-ai__state--empty {
905 - color: #8c8f94;
981 +.os-ai__state--empty {
982 + color: var( --os-ui-fg-muted, #8c8f94 );
906 983 font-size: 13px;
907 984 }
908 985
909 986 /* -----------------------------------------------------------------
@@ -909,9 +986,9 @@
909 986 /* -----------------------------------------------------------------
910 987 * Continue button (budget-exhausted state)
911 988 * ---------------------------------------------------------------- */
912 989
913 -.desktop-mode-ai__continue-btn {
990 +.os-ai__continue-btn {
914 991 appearance: none;
915 992 display: inline-flex;
916 993 align-items: center;
917 994 align-self: flex-start;
@@ -919,17 +996,17 @@
919 996 font: inherit;
920 997 font-size: 12px;
921 998 font-weight: 500;
922 999 padding: 6px 12px;
923 - border: 1px dashed rgba( 0, 0, 0, 0.2 );
1000 + border: 1px dashed var( --os-ui-border-strong, rgba( 0, 0, 0, 0.2 ) );
924 1001 border-radius: 6px;
925 1002 background: transparent;
926 - color: #50575e;
1003 + color: var( --os-ui-fg-muted, #50575e );
927 1004 cursor: pointer;
928 1005 transition: background 0.1s, border-color 0.1s, color 0.1s;
929 1006 }
930 1007
931 -.desktop-mode-ai__continue-btn:hover {
932 - background: rgba( 0, 0, 0, 0.04 );
933 - border-color: rgba( 0, 0, 0, 0.3 );
934 - 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 );
935 1012 }