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