PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.13
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.13
1.1.13 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 All 37 releases
← All changes | assets/css/my-wordpress.css +1312 -513 0.9.8 → 1.1.13 View file →
@@ -1,11 +1,11 @@
1 1 /**
2 2 * My WordPress — window-local layout.
3 3 *
4 4 * Two-pane file-explorer for browsing WordPress entities. Mirrors the
5 - * Recycle Bin and Posts window CSS conventions (`desktop-mode-*`
5 + * Recycle Bin and Posts window CSS conventions (`os-*`
6 6 * BEM-ish prefix, container-relative geometry, theming via the
7 - * desktop-mode-variables CSS custom properties).
7 + * os-variables CSS custom properties).
8 8 *
9 9 */
10 10
11 11 .desktop-mode-my-wordpress {
@@ -14,55 +14,67 @@
14 14 width: 100%;
15 15 height: 100%;
16 16 min-height: 0;
17 17 font-family: var(
18 - --desktop-mode-font,
18 + --os-font,
19 19 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif
20 20 );
21 - color: var( --desktop-mode-my-wordpress-fg, var( --wpd-fg, #1d2327 ) );
21 + color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
22 22 /* Window background — separate from the wallpaper bg so the
23 23 * folder window reads as a real OS window even when the desktop
24 24 * gradient is dark. Themes / plugins can override
25 - * `--desktop-mode-my-wordpress-bg` to repaint just this surface
25 + * `--os-my-wordpress-bg` to repaint just this surface
26 26 * without touching every other window. */
27 27 background: var(
28 - --desktop-mode-my-wordpress-bg,
29 - var( --desktop-mode-window-bg, #fff )
28 + --os-my-wordpress-bg,
29 + var( --os-window-bg, #fff )
30 30 );
31 - /* Light-context tile color tokens — same recipe as the folder
32 - * window. Tiles inside My WordPress paint dark-on-light. */
33 - --desktop-mode-tile-fg: var( --desktop-mode-my-wordpress-fg, var( --wpd-fg, #1d2327 ) );
34 - --desktop-mode-tile-fg-muted: rgba( 0, 0, 0, 0.55 );
35 - --desktop-mode-tile-hover-bg: var(
36 - --desktop-mode-hover,
31 + /* Tile color tokens — same recipe as the folder window. Both
32 + * chain through the palette so the surface follows the active
33 + * desktop theme, with the pre-brand WordPress-admin literal as
34 + * the floor if no stylesheet declares one.
35 + *
36 + * `--os-tile-fg-muted` used to be the bare literal below, which
37 + * outranked the palette's own value and painted every tile's
38 + * secondary line near-black — invisible on a dark station, while
39 + * the label right beside it followed the theme correctly. A
40 + * colour declared next to the thing it paints is out of reach of
41 + * the palette AND of every desktop theme. */
42 + --os-tile-fg: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
43 + --os-tile-fg-muted: var(
44 + --os-my-wordpress-fg-muted,
45 + var( --os-ui-fg-muted, rgba( 0, 0, 0, 0.55 ) )
46 + );
47 + --os-tile-hover-bg: var(
48 + --os-hover,
37 49 rgba( 0, 0, 0, 0.06 )
38 50 );
39 51 /* Light-context label rendering — same recipe as the folder
40 52 * window. Defined as tokens in `variables.css`; the single
41 - * `.desktop-mode-file-tile__label` rule reads them for every
53 + * `.os-file-tile__label` rule reads them for every
42 54 * surface. */
43 - --desktop-mode-tile-label-shadow: none;
44 - --desktop-mode-tile-label-weight: 500;
45 - --desktop-mode-tile-label-smoothing: antialiased;
46 - --desktop-mode-tile-label-color: var( --desktop-mode-my-wordpress-fg, var( --wpd-fg, #1d2327 ) );
55 + --os-tile-label-shadow: none;
56 + --os-tile-label-weight: 500;
57 + --os-tile-label-smoothing: antialiased;
58 + --os-tile-label-color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
47 59 }
48 60
49 -/* Pinned-icon visual cue — used by `desktop-mode-icon--pinned` (the
61 +/* Pinned-icon visual cue — used by `os-icon--pinned` (the
50 62 * generic flag added in 0.8.0). The icon-rail itself owns the
51 63 * non-draggable invariant; this rule just removes the grab affordance
52 64 * if the framework ever attaches one in a later phase.
53 65 */
54 -.desktop-mode-icon--pinned {
66 +.os-icon--pinned {
55 67 cursor: pointer;
56 68 }
57 69
58 70 /* Breadcrumb header chrome — owned by the shared
59 - * `.desktop-mode-breadcrumbs` rules in `desktop-files.css`. No
71 + * `.os-breadcrumbs` rules in `desktop-files.css`. No
60 72 * per-surface duplication. */
61 73
62 74 /* ----- Body host ----- */
63 75
64 -.desktop-mode-my-wordpress__body {
76 +.os-my-wordpress__body {
65 77 flex: 1 1 auto;
66 78 min-height: 0;
67 79 overflow: hidden;
68 80 position: relative;
@@ -75,19 +87,23 @@
75 87 * Holds the server-side search input today; reserved for future
76 88 * filter / sort controls. Visual treatment mirrors the Content
77 89 * Graph toolbar's search row so the two surfaces read as the same
78 90 * control. */
79 -.desktop-mode-my-wordpress__list-toolbar {
91 +.os-my-wordpress__list-toolbar {
80 92 flex: 0 0 auto;
81 93 display: flex;
82 94 align-items: center;
83 95 gap: 8px;
84 96 padding: 8px 12px;
85 - border-bottom: 1px solid var( --wpd-border, #dcdcde );
86 - background: transparent;
97 + border-bottom: 1px solid var( --os-ui-border, #dcdcde );
98 + /* Opaque and above the canvas: the tile canvas scrolls beneath
99 + * this row, and a transparent toolbar let tiles read through it. */
100 + position: relative;
101 + z-index: 4;
102 + background: var( --os-ui-bg, #fff );
87 103 }
88 104
89 -.desktop-mode-my-wordpress__list-toolbar-search {
105 +.os-my-wordpress__list-toolbar-search {
90 106 position: relative;
91 107 flex: 1 1 auto;
92 108 min-width: 0;
93 109 max-width: 360px;
@@ -92,23 +108,23 @@
92 108 min-width: 0;
93 109 max-width: 360px;
94 110 }
95 111
96 -.desktop-mode-my-wordpress__list-toolbar-search-input {
112 +.os-my-wordpress__list-toolbar-search-input {
97 113 width: 100%;
98 114 padding: 6px 10px;
99 - border: 1px solid var( --wpd-border, #d8dde4 );
115 + border: 1px solid var( --os-ui-border, #d8dde4 );
100 116 border-radius: 6px;
101 - background: var( --wpd-surface, #fff );
117 + background: var( --os-ui-surface, #fff );
102 118 color: inherit;
103 119 font-size: 13px;
104 120 box-sizing: border-box;
105 121 }
106 122
107 -.desktop-mode-my-wordpress__list-toolbar-search-input:focus {
123 +.os-my-wordpress__list-toolbar-search-input:focus {
108 124 outline: none;
109 - border-color: var( --wpd-accent, #2c6be5 );
110 - box-shadow: 0 0 0 3px var( --wpd-accent-soft, rgba( 44, 107, 229, 0.18 ) );
125 + border-color: var( --os-ui-accent, #2c6be5 );
126 + box-shadow: 0 0 0 3px var( --os-ui-accent-soft, rgba( 44, 107, 229, 0.18 ) );
111 127 }
112 128
113 129 /* When the list-toolbar mounts, the split pane needs to claim the
114 130 * remaining vertical space inside the flex column body — without
@@ -113,9 +129,9 @@
113 129 /* When the list-toolbar mounts, the split pane needs to claim the
114 130 * remaining vertical space inside the flex column body — without
115 131 * this rule it would size to its content (which, for an empty list,
116 132 * is zero) and the tile canvas would collapse. */
117 -.desktop-mode-my-wordpress__body > .desktop-mode-my-wordpress__split {
133 +.os-my-wordpress__body > .os-my-wordpress__split {
118 134 flex: 1 1 auto;
119 135 min-height: 0;
120 136 }
121 137
@@ -123,10 +139,10 @@
123 139 * (no skeleton flash, no empty intermediate page) but reads as
124 140 * "stale" until the new page lands and the renderer atomically swaps
125 141 * the tiles. `pointer-events: none` blocks the user from clicking
126 142 * a tile that's about to disappear. */
127 -.desktop-mode-my-wordpress__tiles--searching,
128 -.desktop-mode-my-wordpress__media-grid--searching {
143 +.os-my-wordpress__tiles--searching,
144 +.os-my-wordpress__media-grid--searching {
129 145 opacity: 0.45;
130 146 pointer-events: none;
131 147 transition: opacity 0.12s ease-out;
132 148 }
@@ -131,27 +147,27 @@
131 147 transition: opacity 0.12s ease-out;
132 148 }
133 149
134 150 /* Reuse the file-system folder window's status-bar element
135 - * (`.desktop-mode-folder-status-bar`) so segments render with the
151 + * (`.os-folder-status-bar`) so segments render with the
136 152 * exact same DOM the file-system uses — but retone it for the
137 153 * white window background. The dark default (white-on-dark) reads
138 - * as invisible against `--desktop-mode-window-bg`. */
139 -.desktop-mode-my-wordpress > .desktop-mode-folder-status-bar {
140 - border-top: 1px solid var( --wpd-border, #dcdcde );
154 + * as invisible against `--os-window-bg`. */
155 +.desktop-mode-my-wordpress > .os-folder-status-bar {
156 + border-top: 1px solid var( --os-ui-border, #dcdcde );
141 157 background: transparent;
142 - color: var( --wpd-fg-muted, #50575e );
158 + color: var( --os-ui-fg-muted, #50575e );
143 159 }
144 160
145 161 .desktop-mode-my-wordpress
146 - > .desktop-mode-folder-status-bar
147 - button.desktop-mode-folder-status-bar__segment:hover {
148 - background: var( --desktop-mode-hover, var( --wpd-hover, rgba( 0, 0, 0, 0.06 ) ) );
162 + > .os-folder-status-bar
163 + button.os-folder-status-bar__segment:hover {
164 + background: var( --os-hover, var( --os-ui-hover, rgba( 0, 0, 0, 0.06 ) ) );
149 165 }
150 166
151 167 /* ----- Tile canvas (root + entity list) -----
152 168 *
153 - * Both views use the SAME tile element (`.desktop-mode-file-tile`)
169 + * Both views use the SAME tile element (`.os-file-tile`)
154 170 * the wallpaper uses, so visuals stay 1:1 with the desktop. The
155 171 * canvas is `position: relative`; tiles are absolute-positioned and
156 172 * draggable — same interaction pattern as the wallpaper, just
157 173 * scoped to the window. Positions persist per-window in
@@ -157,9 +173,9 @@
157 173 * scoped to the window. Positions persist per-window in
158 174 * `localStorage` (see `createTileLayout` in src/my-wordpress).
159 175 */
160 176
161 -.desktop-mode-my-wordpress__canvas {
177 +.os-my-wordpress__canvas {
162 178 position: relative;
163 179 min-height: 100%;
164 180 box-sizing: border-box;
165 181 /* Note — DO NOT add `overflow: auto` here. Scroll is owned by
@@ -168,9 +184,9 @@
168 184 * would steal the wheel from the outer pane and break the
169 185 * IntersectionObserver-based infinite scroll. */
170 186 }
171 187
172 -.desktop-mode-my-wordpress__grid {
188 +.os-my-wordpress__grid {
173 189 height: 100%;
174 190 overflow-y: scroll;
175 191 }
176 192
@@ -178,12 +194,12 @@
178 194 * On the wallpaper the file tile sits on a dark gradient and uses
179 195 * white text + a 12% white hover — both of which would be invisible
180 196 * on a white window background. Inside My WordPress we re-tone the
181 197 * same element to read on light surfaces. The dimensions / tile
182 - * structure are inherited from `.desktop-mode-file-tile`.
198 + * structure are inherited from `.os-file-tile`.
183 199 */
184 -.desktop-mode-my-wordpress .desktop-mode-file-tile {
185 - /* Color + hover come from `--desktop-mode-tile-*` — see the
200 +.desktop-mode-my-wordpress .os-file-tile {
201 + /* Color + hover come from `--os-tile-*` — see the
186 202 * scope-level variable overrides on `.desktop-mode-my-wordpress`
187 203 * above. We only override structural / animation bits here.
188 204 *
189 205 * Drop the wallpaper's `transition: transform` — it hints at
@@ -195,24 +211,190 @@
195 211 transform: none;
196 212 }
197 213
198 214 /* Selected state for every tile in My WordPress is rendered by
199 - * the canonical `.desktop-mode-file-tile--selected` rule in
215 + * the canonical `.os-file-tile--selected` rule in
200 216 * `desktop-files.css` — same accent border + tinted background
201 217 * the folder windows + wallpaper tiles use. No section-specific
202 218 * override here — visual parity across the whole shell.
203 219 */
204 220
221 +/* Large tiles — sections that opt in with `tileSize: 'large'`.
222 + *
223 + * A section whose rows carry a photograph (a shop's products) reads
224 + * as a catalogue, not a file list: the picture is what's being
225 + * scanned, and at 48px it's a thumbnail of a thumbnail. Roughly
226 + * doubling the icon well also gives a corner ribbon room to be a
227 + * corner flash instead of covering the subject.
228 + *
229 + * The cell pitch lives in `TILE_METRICS_LARGE` (src/my-wordpress/
230 + * index.ts) and the two MUST move together — a wider tile in a cell
231 + * that didn't grow overlaps its neighbour. */
232 +/*
233 + * Image-led sections re-point the tile tokens for their whole
234 + * subtree rather than overriding the tile's width directly. The base
235 + * `.os-file-tile` rule then sizes itself from them, and so does
236 + * everything derived from them (the label's max-width, the loading
237 + * skeletons) — one declaration instead of a chain of overrides that
238 + * have to be kept in step.
239 + */
240 +.os-my-wordpress__tiles--large {
241 + --os-tile-w: var( --os-tile-w-large, 132px );
242 + --os-tile-h: var( --os-tile-h-large, 160px );
243 +}
244 +
245 +.os-my-wordpress__tiles--large .os-file-tile__visual,
246 +.os-my-wordpress__tiles--large .os-file-tile__icon {
247 + width: 104px;
248 + height: 104px;
249 + font-size: 64px;
250 +}
251 +
252 +.os-my-wordpress__tiles--large .os-file-tile__preview {
253 + width: 104px;
254 + height: 104px;
255 + border-radius: 8px;
256 +}
257 +
258 +/* Three lines of title at this width instead of two — a product name
259 + * is long and the extra width earns the room. Matches the taller
260 + * cell in `TILE_METRICS_LARGE`. */
261 +.os-my-wordpress__tiles--large .os-file-tile__label {
262 + -webkit-line-clamp: 3;
263 +}
264 +
265 +/* Featured-image tiles. Entries that have a featured image render it
266 + * in the icon well instead of the section dashicon — decisive for
267 + * image-led types like WooCommerce products. The base
268 + * `.os-file-tile__preview` rule in `desktop-files.css`
269 + * already sizes and crops it; all that's added here is a hairline
270 + * border so a light-on-light photo still reads as a distinct object
271 + * against the wallpaper, plus a neutral well behind it so a
272 + * transparent PNG or a slow-loading image doesn't flash the
273 + * wallpaper through. */
274 +.os-my-wordpress__tile--entry .os-file-tile__preview {
275 + background: var(
276 + --os-media-tile-bg,
277 + rgba( 0, 0, 0, 0.05 )
278 + );
279 + /* The hairline was a flat 12%-alpha black — right on the pre-brand
280 + * white canvas, and nothing at all on a dark one, where a black
281 + * line over a near-black surface leaves the photo edgeless. It
282 + * follows the border token now, so it inverts with the theme. */
283 + box-shadow: inset 0 0 0 1px var( --os-ui-border, rgba( 0, 0, 0, 0.12 ) );
284 +}
285 +
286 +/* Banded list views. A section can split its tiles into labelled
287 + * bands (WooCommerce Orders groups by status, needs-attention first)
288 + * instead of one flat canvas. The root container stops being a
289 + * positioned canvas and becomes a plain stack; each band owns its
290 + * own canvas below its heading. */
291 +.os-my-wordpress__tiles--banded {
292 + position: static;
293 + min-height: 0;
294 +}
295 +
296 +.os-my-wordpress__band + .os-my-wordpress__band {
297 + margin-block-start: 8px;
298 +}
299 +
300 +/* Bands are laid out in order before the first page arrives so none
301 + * appears mid-scroll, but one that hasn't received a row yet stays
302 + * out of the way rather than showing a heading over nothing. */
303 +.os-my-wordpress__band--empty {
304 + display: none;
305 +}
306 +
307 +.os-my-wordpress__band-title {
308 + display: flex;
309 + align-items: center;
310 + gap: 8px;
311 + position: sticky;
312 + /* Keeps the band label visible while scrolling a long band —
313 + * the whole point of banding is knowing what you're looking at. */
314 + top: 0;
315 + /* Above the absolutely-positioned tiles of every band, including
316 + * the ones that come later in the DOM. */
317 + z-index: 3;
318 + margin: 0;
319 + padding: 6px 12px;
320 + font-size: 11px;
321 + font-weight: 600;
322 + letter-spacing: 0.06em;
323 + text-transform: uppercase;
324 + color: var( --os-ui-fg-muted, #787c82 );
325 + /* Near-opaque on purpose. Tiles scrolling underneath are behind
326 + * the bar, but at 85% they still read as ghostly blurred shapes
327 + * through it, which looks like a rendering fault rather than
328 + * frosted glass. The blur + saturate keeps the frosted feel while
329 + * the alpha stops the content beneath resolving into shapes. */
330 + background: color-mix(
331 + in srgb,
332 + var( --os-ui-bg, #fff ) 94%,
333 + transparent
334 + );
335 + backdrop-filter: blur( 14px ) saturate( 180% );
336 + border-block-end: 1px solid var( --os-ui-border, rgba( 0, 0, 0, 0.08 ) );
337 +}
338 +
339 +/* Browsers without `color-mix()` fall back to the flat surface —
340 + * still opaque, just without the translucency. */
341 +@supports not ( background: color-mix( in srgb, red 50%, transparent ) ) {
342 + .os-my-wordpress__band-title {
343 + background: var( --os-ui-bg, #fff );
344 + }
345 +}
346 +
347 +/* Attention-carrying bands (WooCommerce's "Needs attention",
348 + * "Problems") tint their bar so the eye lands there first instead of
349 + * having to read every heading. */
350 +.os-my-wordpress__band-title--warn {
351 + color: var( --os-ui-warning, #8a6116 );
352 + background: color-mix(
353 + in srgb,
354 + var( --os-ui-warning, #8a6116 ) 12%,
355 + var( --os-ui-bg, #fff )
356 + );
357 + border-block-end-color: color-mix(
358 + in srgb,
359 + var( --os-ui-warning, #8a6116 ) 35%,
360 + transparent
361 + );
362 +}
363 +
364 +.os-my-wordpress__band-title--danger {
365 + color: var( --os-ui-danger, #b32d2e );
366 + background: color-mix(
367 + in srgb,
368 + var( --os-ui-danger, #b32d2e ) 12%,
369 + var( --os-ui-bg, #fff )
370 + );
371 + border-block-end-color: color-mix(
372 + in srgb,
373 + var( --os-ui-danger, #b32d2e ) 35%,
374 + transparent
375 + );
376 +}
377 +
378 +.os-my-wordpress__band-count {
379 + padding: 0 6px;
380 + border-radius: 999px;
381 + font-size: 11px;
382 + line-height: 1.7;
383 + background: color-mix( in srgb, currentColor 16%, transparent );
384 + color: inherit;
385 +}
386 +
205 387 /* Lock state — another user is currently editing this post. We dim
206 388 * the tile a touch and overlay a small dashicon-lock badge on the
207 389 * top-right of the icon. The whole tile stays clickable; the lock
208 390 * is just a visual heads-up so the user knows the takeover dialog
209 391 * is coming if they double-click. */
210 -.desktop-mode-my-wordpress__tile--locked {
392 +.os-my-wordpress__tile--locked {
211 393 opacity: 0.85;
212 394 }
213 395
214 -.desktop-mode-my-wordpress__tile-lock {
396 +.os-my-wordpress__tile-lock {
215 397 position: absolute;
216 398 top: 4px;
217 399 inset-inline-end: 14px;
218 400 width: 18px;
@@ -220,10 +402,10 @@
220 402 font-size: 12px;
221 403 line-height: 18px;
222 404 text-align: center;
223 405 border-radius: 50%;
224 - background: var( --desktop-mode-danger, var( --wpd-danger, #b32d2e ) );
225 - color: var( --wpd-fg-on-accent, #fff );
406 + background: var( --os-danger, var( --os-ui-danger, #b32d2e ) );
407 + color: var( --os-ui-fg-on-accent, #fff );
226 408 box-shadow:
227 409 0 0 0 1.5px rgba( 0, 0, 0, 0.4 ),
228 410 0 1px 3px rgba( 0, 0, 0, 0.35 );
229 411 pointer-events: none;
@@ -228,10 +410,13 @@
228 410 0 1px 3px rgba( 0, 0, 0, 0.35 );
229 411 pointer-events: none;
230 412 }
231 413
232 -/* Tooltip lock banner — shown above the excerpt when present. */
233 -.desktop-mode-my-wordpress__tooltip-lock {
414 +/* Hover-card lock banner — shown above the excerpt when present. The
415 + * wash was a fixed 8%-alpha red, which on a dark card was a smear too
416 + * faint to read as a banner at all; it follows the badge-danger token
417 + * now, so it lands at the alpha the active theme picked. */
418 +.os-my-wordpress__tooltip-lock {
234 419 display: flex;
235 420 align-items: center;
236 421 gap: 6px;
237 422 margin: 0 0 8px;
@@ -236,15 +421,18 @@
236 421 gap: 6px;
237 422 margin: 0 0 8px;
238 423 padding: 6px 8px;
239 424 border-radius: 4px;
240 - background: rgba( 179, 45, 46, 0.08 );
241 - color: var( --desktop-mode-danger, var( --wpd-danger, #b32d2e ) );
425 + background: var(
426 + --os-my-wordpress-card-lock-bg,
427 + rgba( 179, 45, 46, 0.08 )
428 + );
429 + color: var( --os-danger, var( --os-ui-danger, #b32d2e ) );
242 430 font-size: 12px;
243 431 font-weight: 600;
244 432 }
245 433
246 -.desktop-mode-my-wordpress__tooltip-lock .dashicons {
434 +.os-my-wordpress__tooltip-lock .dashicons {
247 435 font-size: 14px;
248 436 width: 14px;
249 437 height: 14px;
250 438 }
@@ -254,9 +442,9 @@
254 442 * HiDPI screens snaps text to fractional device pixels and renders
255 443 * blurry. `max-height: 2 × line-height` + `overflow: hidden` looks
256 444 * the same and stays sharp.
257 445 */
258 -.desktop-mode-my-wordpress__tile .desktop-mode-file-tile__label {
446 +.os-my-wordpress__tile .os-file-tile__label {
259 447 font-size: 12px;
260 448 line-height: 1.3;
261 449 max-height: calc( 1.3em * 2 );
262 450 text-align: center;
@@ -266,9 +454,9 @@
266 454 }
267 455
268 456 /* ----- Entity list: two-pane split ----- */
269 457
270 -.desktop-mode-my-wordpress__split {
458 +.os-my-wordpress__split {
271 459 display: grid;
272 460 grid-template-columns: minmax( 240px, 60% ) minmax( 0, 1fr );
273 461 height: 100%;
274 462 min-height: 0;
@@ -273,11 +461,11 @@
273 461 height: 100%;
274 462 min-height: 0;
275 463 }
276 464
277 -.desktop-mode-my-wordpress__list {
465 +.os-my-wordpress__list {
278 466 overflow-y: scroll;
279 - border-inline-end: 1px solid var( --wpd-border, #dcdcde );
467 + border-inline-end: 1px solid var( --os-ui-border, #dcdcde );
280 468 min-width: 0;
281 469 }
282 470
283 471 /* Always-visible scrollbar styling for the icon canvases. macOS
@@ -286,40 +474,40 @@
286 474 * canvas where the user can't tell whether more icons live below
287 475 * or to the right. We force the scrollbar to render at all times
288 476 * via `::-webkit-scrollbar` (works in WebKit / Blink / Edge), and
289 477 * the explicit `scrollbar-width: thin` covers Firefox. */
290 -.desktop-mode-my-wordpress__list,
291 -.desktop-mode-my-wordpress__grid {
478 +.os-my-wordpress__list,
479 +.os-my-wordpress__grid {
292 480 scrollbar-width: thin;
293 481 scrollbar-color: rgba( 0, 0, 0, 0.25 ) transparent;
294 482 }
295 483
296 -.desktop-mode-my-wordpress__list::-webkit-scrollbar,
297 -.desktop-mode-my-wordpress__grid::-webkit-scrollbar {
484 +.os-my-wordpress__list::-webkit-scrollbar,
485 +.os-my-wordpress__grid::-webkit-scrollbar {
298 486 width: 12px;
299 487 height: 12px;
300 488 }
301 489
302 -.desktop-mode-my-wordpress__list::-webkit-scrollbar-thumb,
303 -.desktop-mode-my-wordpress__grid::-webkit-scrollbar-thumb {
304 - background: var( --wpd-scrim, rgba( 0, 0, 0, 0.25 ) );
490 +.os-my-wordpress__list::-webkit-scrollbar-thumb,
491 +.os-my-wordpress__grid::-webkit-scrollbar-thumb {
492 + background: var( --os-ui-scrim, rgba( 0, 0, 0, 0.25 ) );
305 493 border-radius: 6px;
306 494 border: 3px solid transparent;
307 495 background-clip: padding-box;
308 496 }
309 497
310 -.desktop-mode-my-wordpress__list::-webkit-scrollbar-thumb:hover,
311 -.desktop-mode-my-wordpress__grid::-webkit-scrollbar-thumb:hover {
312 - background: var( --wpd-scrim, rgba( 0, 0, 0, 0.4 ) );
498 +.os-my-wordpress__list::-webkit-scrollbar-thumb:hover,
499 +.os-my-wordpress__grid::-webkit-scrollbar-thumb:hover {
500 + background: var( --os-ui-scrim, rgba( 0, 0, 0, 0.4 ) );
313 501 background-clip: padding-box;
314 502 }
315 503
316 -.desktop-mode-my-wordpress__list::-webkit-scrollbar-track,
317 -.desktop-mode-my-wordpress__grid::-webkit-scrollbar-track {
504 +.os-my-wordpress__list::-webkit-scrollbar-track,
505 +.os-my-wordpress__grid::-webkit-scrollbar-track {
318 506 background: transparent;
319 507 }
320 508
321 -.desktop-mode-my-wordpress__sentinel {
509 +.os-my-wordpress__sentinel {
322 510 height: 1px;
323 511 }
324 512
325 513 /* Tile-grid loading skeleton — placeholder tiles that mimic the
@@ -336,50 +524,53 @@
336 524 * `src/my-wordpress/index.ts`. Per-tile shimmer delay and label
337 525 * width are inlined so a row of placeholders reads as a cascade,
338 526 * not a uniform pulse.
339 527 *
340 - * Tile dimensions mirror the real `.desktop-mode-file-tile` width
528 + * Tile dimensions mirror the real `.os-file-tile` width
341 529 * so a placeholder sits cleanly in the cell its successor will
342 530 * inherit.
343 531 */
344 -.desktop-mode-my-wordpress__skeleton-tile {
532 +.os-my-wordpress__skeleton-tile {
345 533 position: absolute;
346 534 display: flex;
347 535 flex-direction: column;
348 536 align-items: center;
349 537 gap: 6px;
350 - width: 88px;
538 + /* Same box as the real tile it stands in for — a skeleton that
539 + * doesn't match the grid makes the list jump when rows land. */
540 + width: var( --os-tile-w, 88px );
541 + height: var( --os-tile-h, 104px );
351 542 padding: 8px 4px;
352 543 box-sizing: border-box;
353 544 pointer-events: none;
354 545 }
355 546
356 -.desktop-mode-my-wordpress__skeleton-icon,
357 -.desktop-mode-my-wordpress__skeleton-label {
547 +.os-my-wordpress__skeleton-icon,
548 +.os-my-wordpress__skeleton-label {
358 549 background: linear-gradient(
359 550 90deg,
360 - var( --desktop-mode-skeleton-low, var( --wpd-hover, rgba( 0, 0, 0, 0.05 ) ) ) 0%,
361 - var( --desktop-mode-skeleton-high, var( --wpd-hover, rgba( 0, 0, 0, 0.13 ) ) ) 50%,
362 - var( --desktop-mode-skeleton-low, var( --wpd-hover, rgba( 0, 0, 0, 0.05 ) ) ) 100%
551 + var( --os-skeleton-low, var( --os-ui-hover, rgba( 0, 0, 0, 0.05 ) ) ) 0%,
552 + var( --os-skeleton-high, var( --os-ui-hover, rgba( 0, 0, 0, 0.13 ) ) ) 50%,
553 + var( --os-skeleton-low, var( --os-ui-hover, rgba( 0, 0, 0, 0.05 ) ) ) 100%
363 554 );
364 555 background-size: 200% 100%;
365 - animation: desktop-mode-my-wordpress-skeleton-shimmer 1.4s ease-in-out
366 - var( --desktop-mode-skeleton-delay, 0s ) infinite;
556 + animation: os-my-wordpress-skeleton-shimmer 1.4s ease-in-out
557 + var( --os-skeleton-delay, 0s ) infinite;
367 558 }
368 559
369 -.desktop-mode-my-wordpress__skeleton-icon {
560 +.os-my-wordpress__skeleton-icon {
370 561 width: 44px;
371 562 height: 44px;
372 563 border-radius: 10px;
373 564 }
374 565
375 -.desktop-mode-my-wordpress__skeleton-label {
566 +.os-my-wordpress__skeleton-label {
376 567 width: 72%;
377 568 height: 10px;
378 569 border-radius: 4px;
379 570 }
380 571
381 -@keyframes desktop-mode-my-wordpress-skeleton-shimmer {
572 +@keyframes os-my-wordpress-skeleton-shimmer {
382 573 from {
383 574 background-position: 200% 0;
384 575 }
385 576 to {
@@ -387,10 +578,10 @@
387 578 }
388 579 }
389 580
390 581 @media ( prefers-reduced-motion: reduce ) {
391 - .desktop-mode-my-wordpress__skeleton-icon,
392 - .desktop-mode-my-wordpress__skeleton-label {
582 + .os-my-wordpress__skeleton-icon,
583 + .os-my-wordpress__skeleton-label {
393 584 animation: none;
394 585 }
395 586 }
396 587
@@ -395,27 +586,52 @@
395 586 }
396 587
397 588 /* ----- Right pane: preview ----- */
398 589
399 -.desktop-mode-my-wordpress__preview {
590 +.os-my-wordpress__preview {
400 591 overflow: auto;
401 592 min-width: 0;
402 593 background: transparent;
403 594 }
404 595
405 -.desktop-mode-my-wordpress__preview-empty {
596 +.os-my-wordpress__preview-empty {
406 597 display: flex;
598 + flex-direction: column;
599 + gap: 6px;
407 600 align-items: center;
408 601 justify-content: center;
409 602 height: 100%;
410 - color: var( --wpd-fg-muted, #787c82 );
603 + color: var( --os-ui-fg-muted, #787c82 );
411 604 font-size: 13px;
412 605 padding: 24px;
413 606 text-align: center;
414 607 }
415 608
416 -.desktop-mode-my-wordpress__preview-loading {
609 +/* Type / status breakdown under a multi-selection's count. */
610 +.os-my-wordpress__preview-selection-breakdown {
611 + font-size: 12px;
612 + opacity: 0.75;
613 +}
614 +
615 +/* One labelled control in the bulk-edit modal. Label above field,
616 + * because the fields are wide (a category tree, a tag row) and a
617 + * two-column grid would put a one-word label beside a control four
618 + * times its height. */
619 +.os-my-wordpress__bulk-row {
417 620 display: flex;
621 + flex-direction: column;
622 + gap: 6px;
623 + margin-block-end: 16px;
624 +}
625 +
626 +.os-my-wordpress__bulk-label {
627 + font-size: 12px;
628 + font-weight: 600;
629 + color: var( --os-ui-fg-muted, #787c82 );
630 +}
631 +
632 +.os-my-wordpress__preview-loading {
633 + display: flex;
418 634 align-items: center;
419 635 justify-content: center;
420 636 height: 100%;
421 637 min-height: 320px;
@@ -424,37 +640,37 @@
424 640 }
425 641
426 642 /* Preview-pane loader — same scale curve as the tile-grid first
427 643 * spinner and the window-loading overlay. The JS used to hard-code
428 - * `size="128"`, which set an inline `--wpd-spinner-size` that
644 + * `size="128"`, which set an inline `--os-ui-spinner-size` that
429 645 * overrode any CSS knob; the size attribute is now omitted so this
430 646 * rule is the single source of truth for both the My WordPress
431 647 * preview and the wallpaper file-preview pane (which reuses this
432 648 * class deliberately).
433 649 */
434 -.desktop-mode-my-wordpress__preview-loading wpd-spinner {
435 - --wpd-spinner-size: clamp( 96px, 14vw, 192px );
650 +.os-my-wordpress__preview-loading os-spinner {
651 + --os-ui-spinner-size: clamp( 96px, 14vw, 192px );
436 652 }
437 653
438 -.desktop-mode-my-wordpress__article {
654 +.os-my-wordpress__article {
439 655 padding: 24px 32px;
440 656 max-width: 720px;
441 657 margin: 0 auto;
442 658 }
443 659
444 -.desktop-mode-my-wordpress__article-title {
660 +.os-my-wordpress__article-title {
445 661 font-size: 22px;
446 662 margin: 0 0 8px;
447 663 line-height: 1.3;
448 664 }
449 665
450 -.desktop-mode-my-wordpress__article-meta {
666 +.os-my-wordpress__article-meta {
451 667 margin: 0 0 16px;
452 - color: var( --wpd-fg-muted, #50575e );
668 + color: var( --os-ui-fg-muted, #50575e );
453 669 font-size: 12px;
454 670 }
455 671
456 -.desktop-mode-my-wordpress__article-hero {
672 +.os-my-wordpress__article-hero {
457 673 width: 100%;
458 674 height: auto;
459 675 border-radius: 6px;
460 676 margin-bottom: 16px;
@@ -460,22 +676,22 @@
460 676 margin-bottom: 16px;
461 677 display: block;
462 678 }
463 679
464 -.desktop-mode-my-wordpress__article-content {
680 +.os-my-wordpress__article-content {
465 681 font-size: 14px;
466 682 line-height: 1.6;
467 683 }
468 684
469 -.desktop-mode-my-wordpress__article-content img {
685 +.os-my-wordpress__article-content img {
470 686 max-width: 100%;
471 687 height: auto;
472 688 }
473 689
474 -.desktop-mode-my-wordpress__article-footer {
690 +.os-my-wordpress__article-footer {
475 691 margin-top: 24px;
476 692 padding-top: 16px;
477 - border-top: 1px solid var( --wpd-border, #dcdcde );
693 + border-top: 1px solid var( --os-ui-border, #dcdcde );
478 694 display: flex;
479 695 justify-content: flex-end;
480 696 align-items: center;
481 697 gap: 8px;
@@ -483,65 +699,97 @@
483 699 }
484 700
485 701 /* ----- Empty / error states ----- */
486 702
487 -.desktop-mode-my-wordpress__empty,
488 -.desktop-mode-my-wordpress__error {
703 +.os-my-wordpress__empty,
704 +.os-my-wordpress__error {
489 705 padding: 32px 24px;
490 706 text-align: center;
491 - color: var( --wpd-fg-muted, #787c82 );
707 + color: var( --os-ui-fg-muted, #787c82 );
492 708 font-size: 13px;
493 709 }
494 710
495 -.desktop-mode-my-wordpress__error {
496 - color: var( --desktop-mode-danger, var( --wpd-danger, #b32d2e ) );
711 +.os-my-wordpress__error {
712 + color: var( --os-danger, var( --os-ui-danger, #b32d2e ) );
497 713 }
498 714
499 -/* ----- Hover tooltip (floats over body) ----- */
715 +/* ----- Hover card (floats over body) -----
716 + *
717 + * The card is summoned from a tile and belongs to the window that
718 + * tile is in, so it follows the active desktop theme rather than the
719 + * shell's tooltip chip. Every colour chains
720 + * `--os-my-wordpress-card-*` first — derived in `variables.css` from
721 + * the window family, so a theme that repaints the window repaints the
722 + * card with it — then the chip tokens, then the pre-brand literal.
723 + *
724 + * It is appended to `document.body`, not to the window, because it is
725 + * `position: fixed` and a window with `overflow: hidden` would clip
726 + * it. Theme tokens still reach it: a desktop theme declares on
727 + * `body.os-desktop-theme-<slug>`, an ancestor of both. What does NOT
728 + * reach it is anything scoped to `.desktop-mode-my-wordpress`, which
729 + * is why the card family is declared at palette level. */
500 730
501 -.desktop-mode-my-wordpress__tooltip {
731 +.os-my-wordpress__tooltip {
502 732 position: fixed;
503 733 z-index: 100000;
504 734 max-width: 320px;
505 735 background: var(
506 - --desktop-mode-tooltip-bg,
507 - var( --desktop-mode-surface, var( --wpd-surface, #fff ) )
736 + --os-my-wordpress-card-bg,
737 + var(
738 + --os-tooltip-bg,
739 + var( --os-surface, var( --os-ui-surface, #fff ) )
740 + )
508 741 );
509 742 color: var(
510 - --desktop-mode-tooltip-fg,
511 - var( --desktop-mode-fg, #1d2327 )
743 + --os-my-wordpress-card-fg,
744 + var( --os-tooltip-fg, var( --os-fg, #1d2327 ) )
512 745 );
513 - border: 1px solid var( --wpd-border, #dcdcde );
746 + /* The card lands on the same colour as the window under it — the
747 + * border and the shadow are the only reason it reads as a separate
748 + * object, so neither is decoration. */
749 + border: 1px solid var( --os-my-wordpress-card-border, #dcdcde );
514 750 border-radius: 6px;
515 751 padding: 12px;
516 - box-shadow: 0 6px 24px rgba( 0, 0, 0, 0.18 );
752 + box-shadow: var(
753 + --os-my-wordpress-card-shadow,
754 + 0 6px 24px rgba( 0, 0, 0, 0.18 )
755 + );
517 756 font-size: 12px;
518 757 pointer-events: none;
519 758 }
520 759
521 -.desktop-mode-my-wordpress__tooltip-title {
760 +.os-my-wordpress__tooltip-title {
522 761 font-weight: 600;
523 762 margin-bottom: 6px;
524 763 font-size: 13px;
525 764 }
526 765
527 -.desktop-mode-my-wordpress__tooltip-thumb {
766 +/* Same neutral well the entry and media tiles give their thumbnails:
767 + * a transparent PNG or a still-loading image would otherwise show the
768 + * card straight through, and a photo whose edge matches the card
769 + * would have no boundary. */
770 +.os-my-wordpress__tooltip-thumb {
528 771 display: block;
529 772 max-width: 100%;
530 773 height: auto;
531 774 border-radius: 4px;
532 775 margin: 6px 0;
776 + background: var( --os-my-wordpress-card-thumb-bg, rgba( 0, 0, 0, 0.05 ) );
777 + box-shadow: inset 0 0 0 1px var(
778 + --os-my-wordpress-card-border,
779 + #dcdcde
780 + );
533 781 }
534 782
535 -.desktop-mode-my-wordpress__tooltip-excerpt {
783 +.os-my-wordpress__tooltip-excerpt {
536 784 margin: 0;
537 - color: var( --wpd-fg-muted, #50575e );
785 + color: var( --os-my-wordpress-card-fg-muted, #50575e );
538 786 line-height: 1.4;
539 787 }
540 788
541 789 /* ----- Context menu host ----- */
542 790
543 -.desktop-mode-my-wordpress__menu {
791 +.os-my-wordpress__menu {
544 792 position: fixed;
545 793 z-index: 100001;
546 794 }
547 795
@@ -553,13 +801,13 @@
553 801 * but to stretch nicely up to ~720px before the line-length stops
554 802 * helping readability.
555 803 * --------------------------------------------------------------- */
556 804
557 -.desktop-mode-my-wordpress__user {
805 +.os-my-wordpress__user {
558 806 max-width: 720px;
559 807 }
560 808
561 -.desktop-mode-my-wordpress__user-header {
809 +.os-my-wordpress__user-header {
562 810 display: flex;
563 811 gap: 16px;
564 812 align-items: center;
565 813 margin-bottom: 16px;
@@ -564,9 +812,9 @@
564 812 align-items: center;
565 813 margin-bottom: 16px;
566 814 }
567 815
568 -.desktop-mode-my-wordpress__user-avatar {
816 +.os-my-wordpress__user-avatar {
569 817 width: 96px;
570 818 height: 96px;
571 819 border-radius: 50%;
572 820 flex-shrink: 0;
@@ -572,19 +820,19 @@
572 820 flex-shrink: 0;
573 821 box-shadow: 0 2px 8px rgba( 0, 0, 0, 0.12 );
574 822 }
575 823
576 -.desktop-mode-my-wordpress__user-headline {
824 +.os-my-wordpress__user-headline {
577 825 flex: 1 1 auto;
578 826 min-width: 0;
579 827 }
580 828
581 -.desktop-mode-my-wordpress__user
582 - .desktop-mode-my-wordpress__article-title {
829 +.os-my-wordpress__user
830 + .os-my-wordpress__article-title {
583 831 margin: 0 0 4px;
584 832 }
585 833
586 -.desktop-mode-my-wordpress__user-roles {
834 +.os-my-wordpress__user-roles {
587 835 display: flex;
588 836 flex-wrap: wrap;
589 837 gap: 6px;
590 838 margin-bottom: 6px;
@@ -589,9 +837,9 @@
589 837 gap: 6px;
590 838 margin-bottom: 6px;
591 839 }
592 840
593 -.desktop-mode-my-wordpress__user-role {
841 +.os-my-wordpress__user-role {
594 842 display: inline-flex;
595 843 align-items: center;
596 844 padding: 2px 8px;
597 845 border-radius: 10px;
@@ -598,39 +846,39 @@
598 846 font-size: 11px;
599 847 font-weight: 600;
600 848 text-transform: uppercase;
601 849 letter-spacing: 0.04em;
602 - background: rgba( 34, 113, 177, 0.12 );
850 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 12%, transparent );
603 851 color: var( --wp-admin-theme-color, #2271b1 );
604 852 }
605 853
606 -.desktop-mode-my-wordpress__user-links {
854 +.os-my-wordpress__user-links {
607 855 display: flex;
608 856 gap: 12px;
609 857 font-size: 12px;
610 858 }
611 859
612 -.desktop-mode-my-wordpress__user-links a {
613 - color: var( --desktop-mode-link, var( --wpd-accent, #2271b1 ) );
860 +.os-my-wordpress__user-links a {
861 + color: var( --os-link, var( --os-ui-accent, #2271b1 ) );
614 862 text-decoration: none;
615 863 }
616 864
617 -.desktop-mode-my-wordpress__user-links a:hover {
865 +.os-my-wordpress__user-links a:hover {
618 866 text-decoration: underline;
619 867 }
620 868
621 -.desktop-mode-my-wordpress__user-bio {
869 +.os-my-wordpress__user-bio {
622 870 font-size: 14px;
623 871 line-height: 1.5;
624 - color: var( --desktop-mode-fg, #1d2327 );
872 + color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
625 873 margin: 0 0 16px;
626 874 padding-left: 12px;
627 - border-left: 3px solid var( --wpd-border, #dcdcde );
875 + border-left: 3px solid var( --os-ui-border, #dcdcde );
628 876 }
629 877
630 878 /* ----- Stat cards row ----- */
631 879
632 -.desktop-mode-my-wordpress__user-stats {
880 +.os-my-wordpress__user-stats {
633 881 display: grid;
634 882 grid-template-columns: repeat( auto-fit, minmax( 120px, 1fr ) );
635 883 gap: 8px;
636 884 margin-bottom: 20px;
@@ -635,19 +883,19 @@
635 883 gap: 8px;
636 884 margin-bottom: 20px;
637 885 }
638 886
639 -.desktop-mode-my-wordpress__user-stat {
887 +.os-my-wordpress__user-stat {
640 888 display: flex;
641 889 flex-direction: column;
642 890 gap: 2px;
643 891 padding: 12px 14px;
644 892 border-radius: 8px;
645 - background: var( --desktop-mode-hover, var( --wpd-hover, rgba( 0, 0, 0, 0.04 ) ) );
646 - border: 1px solid var( --wpd-border, #dcdcde );
893 + background: var( --os-hover, var( --os-ui-hover, rgba( 0, 0, 0, 0.04 ) ) );
894 + border: 1px solid var( --os-ui-border, #dcdcde );
647 895 }
648 896
649 -.desktop-mode-my-wordpress__user-stat-value {
897 +.os-my-wordpress__user-stat-value {
650 898 font-size: 26px;
651 899 font-weight: 700;
652 900 line-height: 1.1;
653 901 color: var( --wp-admin-theme-color, #2271b1 );
@@ -653,36 +901,36 @@
653 901 color: var( --wp-admin-theme-color, #2271b1 );
654 902 font-variant-numeric: tabular-nums;
655 903 }
656 904
657 -.desktop-mode-my-wordpress__user-stat-label {
905 +.os-my-wordpress__user-stat-label {
658 906 font-size: 12px;
659 - color: var( --wpd-fg-muted, #50575e );
907 + color: var( --os-ui-fg-muted, #50575e );
660 908 text-transform: uppercase;
661 909 letter-spacing: 0.04em;
662 910 }
663 911
664 -.desktop-mode-my-wordpress__user-stat-caption {
912 +.os-my-wordpress__user-stat-caption {
665 913 font-size: 11px;
666 - color: var( --wpd-fg-muted, #787c82 );
914 + color: var( --os-ui-fg-muted, #787c82 );
667 915 }
668 916
669 917 /* ----- 12-month activity sparkline ----- */
670 918
671 -.desktop-mode-my-wordpress__user-section {
919 +.os-my-wordpress__user-section {
672 920 margin-bottom: 20px;
673 921 }
674 922
675 -.desktop-mode-my-wordpress__user-section h3 {
923 +.os-my-wordpress__user-section h3 {
676 924 font-size: 13px;
677 925 font-weight: 600;
678 - color: var( --wpd-fg-muted, #50575e );
926 + color: var( --os-ui-fg-muted, #50575e );
679 927 text-transform: uppercase;
680 928 letter-spacing: 0.04em;
681 929 margin: 0 0 8px;
682 930 }
683 931
684 -.desktop-mode-my-wordpress__user-spark-chart {
932 +.os-my-wordpress__user-spark-chart {
685 933 display: grid;
686 934 grid-template-columns: repeat( 12, 1fr );
687 935 gap: 4px;
688 936 height: 80px;
@@ -689,9 +937,9 @@
689 937 align-items: end;
690 938 padding: 6px 0;
691 939 }
692 940
693 -.desktop-mode-my-wordpress__user-spark-col {
941 +.os-my-wordpress__user-spark-col {
694 942 display: flex;
695 943 flex-direction: column;
696 944 align-items: stretch;
697 945 justify-content: flex-end;
@@ -699,13 +947,13 @@
699 947 height: 100%;
700 948 min-height: 0;
701 949 }
702 950
703 -.desktop-mode-my-wordpress__user-spark-bar {
951 +.os-my-wordpress__user-spark-bar {
704 952 background: linear-gradient(
705 953 180deg,
706 954 var( --wp-admin-theme-color, #2271b1 ) 0%,
707 - rgba( 34, 113, 177, 0.55 ) 100%
955 + color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 55%, transparent ) 100%
708 956 );
709 957 border-radius: 3px 3px 0 0;
710 958 min-height: 2px;
711 959 transition: height 0.3s ease;
@@ -710,23 +958,23 @@
710 958 min-height: 2px;
711 959 transition: height 0.3s ease;
712 960 }
713 961
714 -.desktop-mode-my-wordpress__user-spark-bar--empty {
715 - background: var( --wpd-border, #dcdcde );
962 +.os-my-wordpress__user-spark-bar--empty {
963 + background: var( --os-ui-border, #dcdcde );
716 964 min-height: 2px;
717 965 height: 2px !important;
718 966 }
719 967
720 -.desktop-mode-my-wordpress__user-spark-label {
968 +.os-my-wordpress__user-spark-label {
721 969 font-size: 10px;
722 970 text-align: center;
723 - color: var( --wpd-fg-muted, #787c82 );
971 + color: var( --os-ui-fg-muted, #787c82 );
724 972 }
725 973
726 974 /* ----- Milestones ----- */
727 975
728 -.desktop-mode-my-wordpress__user-milestones {
976 +.os-my-wordpress__user-milestones {
729 977 display: grid;
730 978 grid-template-columns: repeat( auto-fit, minmax( 140px, 1fr ) );
731 979 gap: 12px;
732 980 margin: 0 0 20px;
@@ -731,17 +979,17 @@
731 979 gap: 12px;
732 980 margin: 0 0 20px;
733 981 }
734 982
735 -.desktop-mode-my-wordpress__user-milestones dt {
983 +.os-my-wordpress__user-milestones dt {
736 984 font-size: 11px;
737 - color: var( --wpd-fg-muted, #50575e );
985 + color: var( --os-ui-fg-muted, #50575e );
738 986 text-transform: uppercase;
739 987 letter-spacing: 0.04em;
740 988 margin-bottom: 2px;
741 989 }
742 990
743 -.desktop-mode-my-wordpress__user-milestones dd {
991 +.os-my-wordpress__user-milestones dd {
744 992 font-size: 14px;
745 993 font-weight: 600;
746 994 margin: 0;
747 995 }
@@ -747,9 +995,9 @@
747 995 }
748 996
749 997 /* ----- Recent posts list ----- */
750 998
751 -.desktop-mode-my-wordpress__user-recent {
999 +.os-my-wordpress__user-recent {
752 1000 list-style: none;
753 1001 margin: 0;
754 1002 padding: 0;
755 1003 display: flex;
@@ -756,41 +1004,41 @@
756 1004 flex-direction: column;
757 1005 gap: 6px;
758 1006 }
759 1007
760 -.desktop-mode-my-wordpress__user-recent li {
1008 +.os-my-wordpress__user-recent li {
761 1009 display: flex;
762 1010 flex-direction: column;
763 1011 gap: 2px;
764 1012 padding: 8px 10px;
765 1013 border-radius: 6px;
766 - background: var( --wpd-hover, rgba( 0, 0, 0, 0.02 ) );
1014 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.02 ) );
767 1015 }
768 1016
769 -.desktop-mode-my-wordpress__user-recent a {
1017 +.os-my-wordpress__user-recent a {
770 1018 font-weight: 600;
771 - color: var( --desktop-mode-link, var( --wpd-accent, #2271b1 ) );
1019 + color: var( --os-link, var( --os-ui-accent, #2271b1 ) );
772 1020 text-decoration: none;
773 1021 }
774 1022
775 -.desktop-mode-my-wordpress__user-recent a:hover {
1023 +.os-my-wordpress__user-recent a:hover {
776 1024 text-decoration: underline;
777 1025 }
778 1026
779 -.desktop-mode-my-wordpress__user-recent-meta {
1027 +.os-my-wordpress__user-recent-meta {
780 1028 font-size: 11px;
781 - color: var( --wpd-fg-muted, #787c82 );
1029 + color: var( --os-ui-fg-muted, #787c82 );
782 1030 }
783 1031
784 1032 /* ----- Top categories chips ----- */
785 1033
786 -.desktop-mode-my-wordpress__user-chips {
1034 +.os-my-wordpress__user-chips {
787 1035 display: flex;
788 1036 flex-wrap: wrap;
789 1037 gap: 6px;
790 1038 }
791 1039
792 -.desktop-mode-my-wordpress__user-chip {
1040 +.os-my-wordpress__user-chip {
793 1041 display: inline-flex;
794 1042 align-items: center;
795 1043 gap: 6px;
796 1044 padding: 4px 10px;
@@ -795,18 +1043,18 @@
795 1043 gap: 6px;
796 1044 padding: 4px 10px;
797 1045 border-radius: 999px;
798 1046 font-size: 12px;
799 - background: var( --wpd-hover, rgba( 0, 0, 0, 0.05 ) );
800 - border: 1px solid var( --wpd-border, #dcdcde );
1047 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.05 ) );
1048 + border: 1px solid var( --os-ui-border, #dcdcde );
801 1049 }
802 1050
803 -.desktop-mode-my-wordpress__user-chip--tag {
1051 +.os-my-wordpress__user-chip--tag {
804 1052 background: rgba( 124, 58, 237, 0.08 );
805 1053 border-color: rgba( 124, 58, 237, 0.25 );
806 1054 }
807 1055
808 -.desktop-mode-my-wordpress__user-chip-count {
1056 +.os-my-wordpress__user-chip-count {
809 1057 font-weight: 700;
810 1058 color: var( --wp-admin-theme-color, #2271b1 );
811 1059 font-variant-numeric: tabular-nums;
812 1060 }
@@ -819,9 +1067,9 @@
819 1067 * "Top contributors" grid that pairs an author avatar with a
820 1068 * post count.
821 1069 * --------------------------------------------------------------- */
822 1070
823 -.desktop-mode-my-wordpress__term-header {
1071 +.os-my-wordpress__term-header {
824 1072 display: flex;
825 1073 align-items: center;
826 1074 gap: 16px;
827 1075 margin-bottom: 16px;
@@ -826,9 +1074,9 @@
826 1074 gap: 16px;
827 1075 margin-bottom: 16px;
828 1076 }
829 1077
830 -.desktop-mode-my-wordpress__term-icon {
1078 +.os-my-wordpress__term-icon {
831 1079 width: 64px;
832 1080 height: 64px;
833 1081 border-radius: 12px;
834 1082 display: inline-flex;
@@ -834,49 +1082,49 @@
834 1082 display: inline-flex;
835 1083 align-items: center;
836 1084 justify-content: center;
837 1085 flex-shrink: 0;
838 - color: var( --wpd-fg-on-accent, #fff );
1086 + color: var( --os-ui-fg-on-accent, #fff );
839 1087 }
840 1088
841 -.desktop-mode-my-wordpress__term-icon--category {
842 - background: linear-gradient( 135deg, var( --wpd-accent, #2271b1 ) 0%, var( --wpd-accent-strong, #135e96 ) 100% );
843 - box-shadow: 0 4px 12px rgba( 34, 113, 177, 0.32 );
1089 +.os-my-wordpress__term-icon--category {
1090 + background: linear-gradient( 135deg, var( --os-ui-accent, #2271b1 ) 0%, var( --os-ui-accent-strong, #135e96 ) 100% );
1091 + box-shadow: 0 4px 12px color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 32%, transparent );
844 1092 }
845 1093
846 -.desktop-mode-my-wordpress__term-icon--tag {
1094 +.os-my-wordpress__term-icon--tag {
847 1095 background: linear-gradient( 135deg, #7c3aed 0%, #5b21b6 100% );
848 1096 box-shadow: 0 4px 12px rgba( 124, 58, 237, 0.32 );
849 1097 }
850 1098
851 -.desktop-mode-my-wordpress__user-role--category {
852 - background: rgba( 34, 113, 177, 0.12 );
853 - color: var( --wpd-accent-strong, #135e96 );
1099 +.os-my-wordpress__user-role--category {
1100 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 12%, transparent );
1101 + color: var( --os-ui-accent-strong, #135e96 );
854 1102 }
855 1103
856 -.desktop-mode-my-wordpress__user-role--tag {
1104 +.os-my-wordpress__user-role--tag {
857 1105 background: rgba( 124, 58, 237, 0.12 );
858 1106 color: #6d28d9;
859 1107 }
860 1108
861 1109 /* Top contributors row — paired avatar + name + post count. */
862 -.desktop-mode-my-wordpress__term-authors {
1110 +.os-my-wordpress__term-authors {
863 1111 display: grid;
864 1112 grid-template-columns: repeat( auto-fit, minmax( 180px, 1fr ) );
865 1113 gap: 8px;
866 1114 }
867 1115
868 -.desktop-mode-my-wordpress__term-author {
1116 +.os-my-wordpress__term-author {
869 1117 display: flex;
870 1118 align-items: center;
871 1119 gap: 10px;
872 1120 padding: 8px 12px;
873 1121 border-radius: 8px;
874 - background: var( --wpd-hover, rgba( 0, 0, 0, 0.03 ) );
875 - border: 1px solid var( --wpd-border, #dcdcde );
1122 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.03 ) );
1123 + border: 1px solid var( --os-ui-border, #dcdcde );
876 1124 }
877 1125
878 -.desktop-mode-my-wordpress__term-author-avatar {
1126 +.os-my-wordpress__term-author-avatar {
879 1127 width: 36px;
880 1128 height: 36px;
881 1129 border-radius: 50%;
882 1130 flex-shrink: 0;
@@ -881,9 +1129,9 @@
881 1129 border-radius: 50%;
882 1130 flex-shrink: 0;
883 1131 }
884 1132
885 -.desktop-mode-my-wordpress__term-author-text {
1133 +.os-my-wordpress__term-author-text {
886 1134 display: flex;
887 1135 flex-direction: column;
888 1136 gap: 2px;
889 1137 min-width: 0;
@@ -888,9 +1136,9 @@
888 1136 gap: 2px;
889 1137 min-width: 0;
890 1138 }
891 1139
892 -.desktop-mode-my-wordpress__term-author-name {
1140 +.os-my-wordpress__term-author-name {
893 1141 font-weight: 600;
894 1142 font-size: 13px;
895 1143 overflow: hidden;
896 1144 text-overflow: ellipsis;
@@ -896,11 +1144,11 @@
896 1144 text-overflow: ellipsis;
897 1145 white-space: nowrap;
898 1146 }
899 1147
900 -.desktop-mode-my-wordpress__term-author-count {
1148 +.os-my-wordpress__term-author-count {
901 1149 font-size: 11px;
902 - color: var( --wpd-fg-muted, #50575e );
1150 + color: var( --os-ui-fg-muted, #50575e );
903 1151 }
904 1152
905 1153 /* ---------------------------------------------------------------
906 1154 * Comment dossier — header (avatar + name + status / date / count
@@ -909,32 +1157,32 @@
909 1157 * direct-reply thread, and a moderation strip (IP + user agent)
910 1158 * for users with moderate_comments.
911 1159 * --------------------------------------------------------------- */
912 1160
913 -.desktop-mode-my-wordpress__comment-status--approved {
914 - background: rgba( 34, 113, 177, 0.12 );
915 - color: var( --wpd-accent-strong, #135e96 );
1161 +.os-my-wordpress__comment-status--approved {
1162 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 12%, transparent );
1163 + color: var( --os-ui-accent-strong, #135e96 );
916 1164 }
917 1165
918 -.desktop-mode-my-wordpress__comment-status--pending {
1166 +.os-my-wordpress__comment-status--pending {
919 1167 background: rgba( 217, 119, 6, 0.16 );
920 1168 color: #b45309;
921 1169 }
922 1170
923 -.desktop-mode-my-wordpress__comment-status--spam {
1171 +.os-my-wordpress__comment-status--spam {
924 1172 background: rgba( 179, 45, 46, 0.14 );
925 - color: var( --wpd-danger-hover, #b32d2e );
1173 + color: var( --os-ui-danger-hover, #b32d2e );
926 1174 }
927 1175
928 -.desktop-mode-my-wordpress__comment-status--trash {
929 - background: var( --wpd-hover, rgba( 0, 0, 0, 0.08 ) );
930 - color: var( --wpd-fg-muted, #50575e );
1176 +.os-my-wordpress__comment-status--trash {
1177 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.08 ) );
1178 + color: var( --os-ui-fg-muted, #50575e );
931 1179 }
932 1180
933 -.desktop-mode-my-wordpress__comment-date-badge {
1181 +.os-my-wordpress__comment-date-badge {
934 1182 background: transparent;
935 - color: var( --wpd-fg-muted, #50575e );
936 - border: 1px solid var( --wpd-border, #dcdcde );
1183 + color: var( --os-ui-fg-muted, #50575e );
1184 + border: 1px solid var( --os-ui-border, #dcdcde );
937 1185 text-transform: none;
938 1186 letter-spacing: normal;
939 1187 }
940 1188
@@ -939,68 +1187,68 @@
939 1187 }
940 1188
941 1189 /* "In reply to ..." quote shown above the comment body when this
942 1190 * is a thread reply. */
943 -.desktop-mode-my-wordpress__comment-quote {
1191 +.os-my-wordpress__comment-quote {
944 1192 margin: 0 0 16px;
945 1193 padding: 10px 14px;
946 1194 border-left: 3px solid var( --wp-admin-theme-color, #2271b1 );
947 - background: rgba( 34, 113, 177, 0.06 );
1195 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 6%, transparent );
948 1196 border-radius: 0 6px 6px 0;
949 1197 font-size: 13px;
950 1198 }
951 1199
952 -.desktop-mode-my-wordpress__comment-quote-lead {
1200 +.os-my-wordpress__comment-quote-lead {
953 1201 font-size: 11px;
954 1202 font-weight: 600;
955 - color: var( --wpd-fg-muted, #50575e );
1203 + color: var( --os-ui-fg-muted, #50575e );
956 1204 text-transform: uppercase;
957 1205 letter-spacing: 0.04em;
958 1206 margin-bottom: 4px;
959 1207 }
960 1208
961 -.desktop-mode-my-wordpress__comment-quote p {
1209 +.os-my-wordpress__comment-quote p {
962 1210 margin: 0;
963 - color: var( --desktop-mode-fg, #1d2327 );
1211 + color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
964 1212 }
965 1213
966 1214 /* Comment body — same style as article-content but with a soft
967 1215 * card background so it reads as the focal element. */
968 -.desktop-mode-my-wordpress__comment-body {
1216 +.os-my-wordpress__comment-body {
969 1217 padding: 14px 16px;
970 - background: var( --wpd-hover, rgba( 0, 0, 0, 0.03 ) );
1218 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.03 ) );
971 1219 border-radius: 8px;
972 - border: 1px solid var( --wpd-border, #dcdcde );
1220 + border: 1px solid var( --os-ui-border, #dcdcde );
973 1221 }
974 1222
975 1223 /* Parent-post card under the comment body. */
976 -.desktop-mode-my-wordpress__comment-post {
1224 +.os-my-wordpress__comment-post {
977 1225 display: flex;
978 1226 flex-direction: column;
979 1227 gap: 4px;
980 1228 padding: 10px 14px;
981 1229 border-radius: 8px;
982 - background: var( --wpd-hover, rgba( 0, 0, 0, 0.04 ) );
983 - border: 1px solid var( --wpd-border, #dcdcde );
1230 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.04 ) );
1231 + border: 1px solid var( --os-ui-border, #dcdcde );
984 1232 }
985 1233
986 -.desktop-mode-my-wordpress__comment-post-title {
1234 +.os-my-wordpress__comment-post-title {
987 1235 font-weight: 600;
988 - color: var( --desktop-mode-link, var( --wpd-accent, #2271b1 ) );
1236 + color: var( --os-link, var( --os-ui-accent, #2271b1 ) );
989 1237 text-decoration: none;
990 1238 }
991 1239
992 -.desktop-mode-my-wordpress__comment-post-title:hover {
1240 +.os-my-wordpress__comment-post-title:hover {
993 1241 text-decoration: underline;
994 1242 }
995 1243
996 -.desktop-mode-my-wordpress__comment-post-meta {
1244 +.os-my-wordpress__comment-post-meta {
997 1245 font-size: 11px;
998 - color: var( --wpd-fg-muted, #787c82 );
1246 + color: var( --os-ui-fg-muted, #787c82 );
999 1247 }
1000 1248
1001 1249 /* Replies list. */
1002 -.desktop-mode-my-wordpress__comment-replies {
1250 +.os-my-wordpress__comment-replies {
1003 1251 list-style: none;
1004 1252 margin: 0;
1005 1253 padding: 0;
1006 1254 display: flex;
@@ -1007,19 +1255,19 @@
1007 1255 flex-direction: column;
1008 1256 gap: 10px;
1009 1257 }
1010 1258
1011 -.desktop-mode-my-wordpress__comment-reply {
1259 +.os-my-wordpress__comment-reply {
1012 1260 display: flex;
1013 1261 gap: 10px;
1014 1262 align-items: flex-start;
1015 1263 padding: 10px 12px;
1016 1264 border-radius: 8px;
1017 - background: var( --wpd-hover, rgba( 0, 0, 0, 0.02 ) );
1018 - border: 1px solid var( --wpd-border, #dcdcde );
1265 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.02 ) );
1266 + border: 1px solid var( --os-ui-border, #dcdcde );
1019 1267 }
1020 1268
1021 -.desktop-mode-my-wordpress__comment-reply-avatar {
1269 +.os-my-wordpress__comment-reply-avatar {
1022 1270 width: 32px;
1023 1271 height: 32px;
1024 1272 border-radius: 50%;
1025 1273 flex-shrink: 0;
@@ -1024,9 +1272,9 @@
1024 1272 border-radius: 50%;
1025 1273 flex-shrink: 0;
1026 1274 }
1027 1275
1028 -.desktop-mode-my-wordpress__comment-reply-text {
1276 +.os-my-wordpress__comment-reply-text {
1029 1277 display: flex;
1030 1278 flex-direction: column;
1031 1279 gap: 2px;
1032 1280 min-width: 0;
@@ -1031,9 +1279,9 @@
1031 1279 gap: 2px;
1032 1280 min-width: 0;
1033 1281 }
1034 1282
1035 -.desktop-mode-my-wordpress__comment-reply-head {
1283 +.os-my-wordpress__comment-reply-head {
1036 1284 display: flex;
1037 1285 align-items: baseline;
1038 1286 gap: 8px;
1039 1287 flex-wrap: wrap;
@@ -1038,22 +1286,22 @@
1038 1286 gap: 8px;
1039 1287 flex-wrap: wrap;
1040 1288 }
1041 1289
1042 -.desktop-mode-my-wordpress__comment-reply-name {
1290 +.os-my-wordpress__comment-reply-name {
1043 1291 font-weight: 600;
1044 1292 font-size: 13px;
1045 1293 }
1046 1294
1047 -.desktop-mode-my-wordpress__comment-reply-when {
1295 +.os-my-wordpress__comment-reply-when {
1048 1296 font-size: 11px;
1049 - color: var( --wpd-fg-muted, #787c82 );
1297 + color: var( --os-ui-fg-muted, #787c82 );
1050 1298 }
1051 1299
1052 -.desktop-mode-my-wordpress__comment-reply-excerpt {
1300 +.os-my-wordpress__comment-reply-excerpt {
1053 1301 margin: 0;
1054 1302 font-size: 13px;
1055 - color: var( --desktop-mode-fg, #1d2327 );
1303 + color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
1056 1304 line-height: 1.45;
1057 1305 }
1058 1306
1059 1307 /* =================================================================== *
@@ -1068,9 +1316,9 @@
1068 1316 * Since 0.20.0.
1069 1317 * =================================================================== */
1070 1318
1071 1319 /* User tile — replaces the dashicon glyph with a real avatar */
1072 -.desktop-mode-my-wordpress__tile--user {
1320 +.os-my-wordpress__tile--user {
1073 1321 display: flex;
1074 1322 flex-direction: column;
1075 1323 align-items: center;
1076 1324 justify-content: flex-start;
@@ -1078,9 +1326,9 @@
1078 1326 padding: 8px 4px 6px;
1079 1327 box-sizing: border-box;
1080 1328 }
1081 1329
1082 -.desktop-mode-my-wordpress__user-tile-avatar {
1330 +.os-my-wordpress__user-tile-avatar {
1083 1331 display: inline-flex;
1084 1332 align-items: center;
1085 1333 justify-content: center;
1086 1334 width: 44px;
@@ -1088,10 +1336,10 @@
1088 1336 border-radius: 50%;
1089 1337 overflow: hidden;
1090 1338 background: linear-gradient(
1091 1339 135deg,
1092 - rgba( 34, 113, 177, 0.18 ),
1093 - rgba( 34, 113, 177, 0.04 )
1340 + color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 18%, transparent ),
1341 + color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 4%, transparent )
1094 1342 );
1095 1343 box-shadow:
1096 1344 inset 0 0 0 1px rgba( 0, 0, 0, 0.08 ),
1097 1345 0 2px 6px rgba( 0, 0, 0, 0.08 );
@@ -1097,9 +1345,9 @@
1097 1345 0 2px 6px rgba( 0, 0, 0, 0.08 );
1098 1346 flex: 0 0 auto;
1099 1347 }
1100 1348
1101 -.desktop-mode-my-wordpress__user-tile-avatar img {
1349 +.os-my-wordpress__user-tile-avatar img {
1102 1350 width: 100%;
1103 1351 height: 100%;
1104 1352 object-fit: cover;
1105 1353 display: block;
@@ -1104,9 +1352,9 @@
1104 1352 object-fit: cover;
1105 1353 display: block;
1106 1354 }
1107 1355
1108 -.desktop-mode-my-wordpress__user-tile-initials {
1356 +.os-my-wordpress__user-tile-initials {
1109 1357 font-weight: 600;
1110 1358 font-size: 14px;
1111 1359 letter-spacing: 0.02em;
1112 1360 color: var( --wp-admin-theme-color, #2271b1 );
@@ -1115,9 +1363,9 @@
1115 1363
1116 1364 /* Single-line label for user tiles — we already have a generic
1117 1365 * label clamp, but the user variant gets only ONE line so the
1118 1366 * sub-line ("Editor · 12 posts") can fit beneath it. */
1119 -.desktop-mode-my-wordpress__tile--user .desktop-mode-file-tile__label {
1367 +.os-my-wordpress__tile--user .os-file-tile__label {
1120 1368 font-size: 11px;
1121 1369 font-weight: 500;
1122 1370 line-height: 1.25;
1123 1371 max-height: 1.25em;
@@ -1128,12 +1376,12 @@
1128 1376 padding: 0 4px;
1129 1377 box-sizing: border-box;
1130 1378 }
1131 1379
1132 -.desktop-mode-my-wordpress__user-tile-sub {
1380 +.os-my-wordpress__user-tile-sub {
1133 1381 font-size: 10px;
1134 1382 line-height: 1.2;
1135 - color: var( --desktop-mode-tile-fg-muted, rgba( 0, 0, 0, 0.55 ) );
1383 + color: var( --os-tile-fg-muted, rgba( 0, 0, 0, 0.55 ) );
1136 1384 max-height: 1.2em;
1137 1385 white-space: nowrap;
1138 1386 overflow: hidden;
1139 1387 text-overflow: ellipsis;
@@ -1143,9 +1391,9 @@
1143 1391 box-sizing: border-box;
1144 1392 }
1145 1393
1146 1394 /* Selected/hover user tiles inherit the same chrome the post tiles
1147 - * use — see `.desktop-mode-my-wordpress__tile--selected` above. */
1395 + * use — see `.os-my-wordpress__tile--selected` above. */
1148 1396
1149 1397 /* ----- Activity footprint — full-width body surface -----
1150 1398 *
1151 1399 * Opens via the right-click context menu on a user tile (or the
@@ -1153,9 +1401,9 @@
1153 1401 * list/preview with a wide canvas so each section gets enough room
1154 1402 * to read.
1155 1403 */
1156 1404
1157 -.desktop-mode-my-wordpress__footprint {
1405 +.os-my-wordpress__footprint {
1158 1406 display: flex;
1159 1407 flex-direction: column;
1160 1408 gap: 20px;
1161 1409 padding: 24px 28px 32px;
@@ -1168,20 +1416,20 @@
1168 1416 * cap is applied to each immediate child instead (below). */
1169 1417 align-items: center;
1170 1418 }
1171 1419
1172 -.desktop-mode-my-wordpress__footprint > * {
1420 +.os-my-wordpress__footprint > * {
1173 1421 width: 100%;
1174 1422 max-width: 1080px;
1175 1423 }
1176 1424
1177 -.desktop-mode-my-wordpress__footprint-section {
1178 - border: 1px solid var( --wpd-border, #dcdcde );
1425 +.os-my-wordpress__footprint-section {
1426 + border: 1px solid var( --os-ui-border, #dcdcde );
1179 1427 border-radius: 12px;
1180 1428 padding: 18px 20px;
1181 1429 background: var(
1182 - --desktop-mode-my-wordpress-surface,
1183 - var( --desktop-mode-surface, var( --wpd-surface, rgba( 255, 255, 255, 0.6 ) ) )
1430 + --os-my-wordpress-surface,
1431 + var( --os-surface, var( --os-ui-surface, rgba( 255, 255, 255, 0.6 ) ) )
1184 1432 );
1185 1433 box-shadow: 0 1px 2px rgba( 0, 0, 0, 0.04 );
1186 1434 /* The parent `.__footprint` is a flex column with `overflow-y:
1187 1435 * auto`. Flex items default to `flex-shrink: 1`, so each section
@@ -1193,20 +1441,20 @@
1193 1441 * overflow. */
1194 1442 flex: 0 0 auto;
1195 1443 }
1196 1444
1197 -.desktop-mode-my-wordpress__footprint-section h3 {
1445 +.os-my-wordpress__footprint-section h3 {
1198 1446 margin: 0 0 12px;
1199 1447 font-size: 13px;
1200 1448 font-weight: 600;
1201 1449 letter-spacing: 0.04em;
1202 1450 text-transform: uppercase;
1203 - color: var( --wpd-fg-muted, #50575e );
1451 + color: var( --os-ui-fg-muted, #50575e );
1204 1452 }
1205 1453
1206 1454 /* ----- Hero ----- */
1207 1455
1208 -.desktop-mode-my-wordpress__footprint-hero {
1456 +.os-my-wordpress__footprint-hero {
1209 1457 display: flex;
1210 1458 gap: 20px;
1211 1459 align-items: center;
1212 1460 padding: 24px;
@@ -1212,16 +1460,16 @@
1212 1460 padding: 24px;
1213 1461 border-radius: 16px;
1214 1462 background: linear-gradient(
1215 1463 135deg,
1216 - rgba( 34, 113, 177, 0.10 ) 0%,
1217 - rgba( 34, 113, 177, 0.02 ) 60%,
1464 + color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 10%, transparent ) 0%,
1465 + color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 2%, transparent ) 60%,
1218 1466 transparent 100%
1219 1467 );
1220 - border: 1px solid var( --wpd-border, #dcdcde );
1468 + border: 1px solid var( --os-ui-border, #dcdcde );
1221 1469 }
1222 1470
1223 -.desktop-mode-my-wordpress__footprint-avatar {
1471 +.os-my-wordpress__footprint-avatar {
1224 1472 width: 112px;
1225 1473 height: 112px;
1226 1474 border-radius: 50%;
1227 1475 overflow: hidden;
@@ -1230,10 +1478,10 @@
1230 1478 inset 0 0 0 2px rgba( 255, 255, 255, 0.8 ),
1231 1479 0 6px 24px rgba( 0, 0, 0, 0.14 );
1232 1480 background: linear-gradient(
1233 1481 135deg,
1234 - rgba( 34, 113, 177, 0.18 ),
1235 - rgba( 34, 113, 177, 0.04 )
1482 + color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 18%, transparent ),
1483 + color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 4%, transparent )
1236 1484 );
1237 1485 display: inline-flex;
1238 1486 align-items: center;
1239 1487 justify-content: center;
@@ -1238,9 +1486,9 @@
1238 1486 align-items: center;
1239 1487 justify-content: center;
1240 1488 }
1241 1489
1242 -.desktop-mode-my-wordpress__footprint-avatar img {
1490 +.os-my-wordpress__footprint-avatar img {
1243 1491 width: 100%;
1244 1492 height: 100%;
1245 1493 object-fit: cover;
1246 1494 display: block;
@@ -1245,14 +1493,14 @@
1245 1493 object-fit: cover;
1246 1494 display: block;
1247 1495 }
1248 1496
1249 -.desktop-mode-my-wordpress__footprint-avatar
1250 - .desktop-mode-my-wordpress__user-tile-initials {
1497 +.os-my-wordpress__footprint-avatar
1498 + .os-my-wordpress__user-tile-initials {
1251 1499 font-size: 36px;
1252 1500 }
1253 1501
1254 -.desktop-mode-my-wordpress__footprint-headline {
1502 +.os-my-wordpress__footprint-headline {
1255 1503 min-width: 0;
1256 1504 flex: 1 1 auto;
1257 1505 display: flex;
1258 1506 flex-direction: column;
@@ -1258,17 +1506,20 @@
1258 1506 flex-direction: column;
1259 1507 gap: 8px;
1260 1508 }
1261 1509
1262 -.desktop-mode-my-wordpress__footprint-title {
1510 +/* Window text reads the app's own foreground, never `--os-fg`: that token
1511 + * is the shell's text ON THE DESK, so a light theme (Legacy) leaves it
1512 + * white and the name vanished into the white hero. */
1513 +.os-my-wordpress__footprint-title {
1263 1514 margin: 0;
1264 1515 font-size: 28px;
1265 1516 line-height: 1.15;
1266 1517 font-weight: 700;
1267 - color: var( --desktop-mode-fg, #1d2327 );
1518 + color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
1268 1519 }
1269 1520
1270 -.desktop-mode-my-wordpress__footprint-meta {
1521 +.os-my-wordpress__footprint-meta {
1271 1522 display: flex;
1272 1523 flex-wrap: wrap;
1273 1524 gap: 6px;
1274 1525 align-items: center;
@@ -1273,16 +1524,16 @@
1273 1524 gap: 6px;
1274 1525 align-items: center;
1275 1526 }
1276 1527
1277 -.desktop-mode-my-wordpress__footprint-since {
1278 - background: var( --wpd-hover, rgba( 0, 0, 0, 0.06 ) );
1279 - color: var( --wpd-fg-muted, #50575e );
1528 +.os-my-wordpress__footprint-since {
1529 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.06 ) );
1530 + color: var( --os-ui-fg-muted, #50575e );
1280 1531 }
1281 1532
1282 1533 /* ----- Headline stats row (4 cards) ----- */
1283 1534
1284 -.desktop-mode-my-wordpress__footprint-stats-row {
1535 +.os-my-wordpress__footprint-stats-row {
1285 1536 display: grid;
1286 1537 grid-template-columns: repeat( auto-fit, minmax( 160px, 1fr ) );
1287 1538 gap: 12px;
1288 1539 padding: 16px 18px;
@@ -1287,21 +1538,21 @@
1287 1538 gap: 12px;
1288 1539 padding: 16px 18px;
1289 1540 }
1290 1541
1291 -.desktop-mode-my-wordpress__footprint-stats-row
1292 - .desktop-mode-my-wordpress__user-stat {
1293 - background: var( --desktop-mode-surface, var( --wpd-surface, rgba( 255, 255, 255, 0.9 ) ) );
1542 +.os-my-wordpress__footprint-stats-row
1543 + .os-my-wordpress__user-stat {
1544 + background: var( --os-surface, var( --os-ui-surface, rgba( 255, 255, 255, 0.9 ) ) );
1294 1545 box-shadow: 0 1px 4px rgba( 0, 0, 0, 0.04 );
1295 1546 }
1296 1547
1297 1548 /* ----- Calendar heatmap (GitHub-style) ----- */
1298 1549
1299 -.desktop-mode-my-wordpress__footprint-calendar-section {
1550 +.os-my-wordpress__footprint-calendar-section {
1300 1551 overflow-x: auto;
1301 1552 }
1302 1553
1303 -.desktop-mode-my-wordpress__footprint-calendar {
1554 +.os-my-wordpress__footprint-calendar {
1304 1555 display: flex;
1305 1556 flex-direction: column;
1306 1557 gap: 8px;
1307 1558 /* Size to the grid itself so the legend (justify-content: flex-end
@@ -1312,9 +1563,9 @@
1312 1563 max-width: 100%;
1313 1564 margin-inline: auto;
1314 1565 }
1315 1566
1316 -.desktop-mode-my-wordpress__footprint-grid {
1567 +.os-my-wordpress__footprint-grid {
1317 1568 display: grid;
1318 1569 /* Row 1 holds month labels (auto height); rows 2–8 are the 7
1319 1570 * weekdays at fixed 11px. Col 1 holds weekday labels (auto width);
1320 1571 * subsequent cols are 11px-wide week tracks, set per-cell via
@@ -1326,17 +1577,17 @@
1326 1577 row-gap: 3px;
1327 1578 width: max-content;
1328 1579 }
1329 1580
1330 -.desktop-mode-my-wordpress__footprint-month,
1331 -.desktop-mode-my-wordpress__footprint-weekday {
1581 +.os-my-wordpress__footprint-month,
1582 +.os-my-wordpress__footprint-weekday {
1332 1583 font-size: 10px;
1333 1584 line-height: 11px;
1334 - color: var( --wpd-fg-muted, #50575e );
1585 + color: var( --os-ui-fg-muted, #50575e );
1335 1586 white-space: nowrap;
1336 1587 }
1337 1588
1338 -.desktop-mode-my-wordpress__footprint-weekday {
1589 +.os-my-wordpress__footprint-weekday {
1339 1590 /* Sit flush to the right of the label gutter so each label reads
1340 1591 * adjacent to its row. The 6px breathing room is in addition to
1341 1592 * the grid's column-gap. */
1342 1593 padding-inline-end: 6px;
@@ -1343,68 +1594,68 @@
1343 1594 align-self: center;
1344 1595 justify-self: end;
1345 1596 }
1346 1597
1347 -.desktop-mode-my-wordpress__footprint-month {
1598 +.os-my-wordpress__footprint-month {
1348 1599 padding-bottom: 2px;
1349 1600 }
1350 1601
1351 -.desktop-mode-my-wordpress__footprint-cell {
1602 +.os-my-wordpress__footprint-cell {
1352 1603 width: 11px;
1353 1604 height: 11px;
1354 1605 border-radius: 2px;
1355 - background: var( --wpd-border, #ebedf0 );
1606 + background: var( --os-ui-border, #ebedf0 );
1356 1607 display: inline-block;
1357 1608 transition: transform 0.12s ease;
1358 1609 }
1359 1610
1360 -.desktop-mode-my-wordpress__footprint-cell--pad {
1611 +.os-my-wordpress__footprint-cell--pad {
1361 1612 background: transparent;
1362 1613 }
1363 1614
1364 -.desktop-mode-my-wordpress__footprint-cell--l0 {
1365 - background: var( --wpd-hover, rgba( 0, 0, 0, 0.06 ) );
1615 +.os-my-wordpress__footprint-cell--l0 {
1616 + background: var( --os-ui-hover, rgba( 0, 0, 0, 0.06 ) );
1366 1617 }
1367 1618
1368 -.desktop-mode-my-wordpress__footprint-cell--l1 {
1369 - background: rgba( 34, 113, 177, 0.25 );
1619 +.os-my-wordpress__footprint-cell--l1 {
1620 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 25%, transparent );
1370 1621 }
1371 1622
1372 -.desktop-mode-my-wordpress__footprint-cell--l2 {
1373 - background: rgba( 34, 113, 177, 0.5 );
1623 +.os-my-wordpress__footprint-cell--l2 {
1624 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 50%, transparent );
1374 1625 }
1375 1626
1376 -.desktop-mode-my-wordpress__footprint-cell--l3 {
1377 - background: rgba( 34, 113, 177, 0.75 );
1627 +.os-my-wordpress__footprint-cell--l3 {
1628 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 75%, transparent );
1378 1629 }
1379 1630
1380 -.desktop-mode-my-wordpress__footprint-cell--l4 {
1631 +.os-my-wordpress__footprint-cell--l4 {
1381 1632 background: var( --wp-admin-theme-color, #2271b1 );
1382 1633 }
1383 1634
1384 -.desktop-mode-my-wordpress__footprint-cell:hover {
1635 +.os-my-wordpress__footprint-cell:hover {
1385 1636 transform: scale( 1.4 );
1386 1637 z-index: 1;
1387 1638 }
1388 1639
1389 -.desktop-mode-my-wordpress__footprint-legend {
1640 +.os-my-wordpress__footprint-legend {
1390 1641 display: flex;
1391 1642 gap: 4px;
1392 1643 align-items: center;
1393 1644 justify-content: flex-end;
1394 1645 font-size: 11px;
1395 - color: var( --wpd-fg-muted, #50575e );
1646 + color: var( --os-ui-fg-muted, #50575e );
1396 1647 }
1397 1648
1398 -.desktop-mode-my-wordpress__footprint-legend-label {
1649 +.os-my-wordpress__footprint-legend-label {
1399 1650 font-size: 11px;
1400 - color: var( --wpd-fg-muted, #50575e );
1651 + color: var( --os-ui-fg-muted, #50575e );
1401 1652 padding: 0 4px;
1402 1653 }
1403 1654
1404 1655 /* ----- Rhythm (weekday + hour bar charts) ----- */
1405 1656
1406 -.desktop-mode-my-wordpress__footprint-rhythm-grid {
1657 +.os-my-wordpress__footprint-rhythm-grid {
1407 1658 display: grid;
1408 1659 grid-template-columns: minmax( 0, 1fr ) minmax( 0, 1.7fr );
1409 1660 gap: 24px;
1410 1661 }
@@ -1409,20 +1660,20 @@
1409 1660 gap: 24px;
1410 1661 }
1411 1662
1412 1663 @container ( max-width: 720px ) {
1413 - .desktop-mode-my-wordpress__footprint-rhythm-grid {
1664 + .os-my-wordpress__footprint-rhythm-grid {
1414 1665 grid-template-columns: 1fr;
1415 1666 }
1416 1667 }
1417 1668
1418 -.desktop-mode-my-wordpress__footprint-chart-caption {
1669 +.os-my-wordpress__footprint-chart-caption {
1419 1670 font-size: 12px;
1420 - color: var( --wpd-fg-muted, #50575e );
1671 + color: var( --os-ui-fg-muted, #50575e );
1421 1672 margin-bottom: 6px;
1422 1673 }
1423 1674
1424 -.desktop-mode-my-wordpress__footprint-bars {
1675 +.os-my-wordpress__footprint-bars {
1425 1676 display: flex;
1426 1677 align-items: end;
1427 1678 gap: 4px;
1428 1679 height: 100px;
@@ -1429,9 +1680,9 @@
1429 1680 padding-bottom: 18px;
1430 1681 position: relative;
1431 1682 }
1432 1683
1433 -.desktop-mode-my-wordpress__footprint-bar-col {
1684 +.os-my-wordpress__footprint-bar-col {
1434 1685 flex: 1 1 0;
1435 1686 min-width: 0;
1436 1687 display: flex;
1437 1688 flex-direction: column;
@@ -1441,13 +1692,13 @@
1441 1692 height: 100%;
1442 1693 position: relative;
1443 1694 }
1444 1695
1445 -.desktop-mode-my-wordpress__footprint-bar {
1696 +.os-my-wordpress__footprint-bar {
1446 1697 background: linear-gradient(
1447 1698 180deg,
1448 1699 var( --wp-admin-theme-color, #2271b1 ) 0%,
1449 - rgba( 34, 113, 177, 0.55 ) 100%
1700 + color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 55%, transparent ) 100%
1450 1701 );
1451 1702 border-radius: 3px 3px 0 0;
1452 1703 min-height: 2px;
1453 1704 transition: opacity 0.2s ease;
@@ -1452,15 +1703,15 @@
1452 1703 min-height: 2px;
1453 1704 transition: opacity 0.2s ease;
1454 1705 }
1455 1706
1456 -.desktop-mode-my-wordpress__footprint-bar--empty {
1457 - background: var( --wpd-border, #dcdcde );
1707 +.os-my-wordpress__footprint-bar--empty {
1708 + background: var( --os-ui-border, #dcdcde );
1458 1709 height: 2px !important;
1459 1710 min-height: 2px;
1460 1711 }
1461 1712
1462 -.desktop-mode-my-wordpress__footprint-bar-label {
1713 +.os-my-wordpress__footprint-bar-label {
1463 1714 position: absolute;
1464 1715 bottom: -16px;
1465 1716 left: 0;
1466 1717 right: 0;
@@ -1465,14 +1716,14 @@
1465 1716 left: 0;
1466 1717 right: 0;
1467 1718 text-align: center;
1468 1719 font-size: 10px;
1469 - color: var( --wpd-fg-muted, #787c82 );
1720 + color: var( --os-ui-fg-muted, #787c82 );
1470 1721 }
1471 1722
1472 1723 /* ----- Most-prolific-month callout ----- */
1473 1724
1474 -.desktop-mode-my-wordpress__footprint-callout {
1725 +.os-my-wordpress__footprint-callout {
1475 1726 display: flex;
1476 1727 flex-direction: column;
1477 1728 gap: 4px;
1478 1729 align-items: center;
@@ -1479,38 +1730,38 @@
1479 1730 text-align: center;
1480 1731 padding: 20px 24px;
1481 1732 background: linear-gradient(
1482 1733 135deg,
1483 - rgba( 34, 113, 177, 0.10 ),
1484 - rgba( 34, 113, 177, 0.02 )
1734 + color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 10%, transparent ),
1735 + color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 2%, transparent )
1485 1736 );
1486 1737 }
1487 1738
1488 -.desktop-mode-my-wordpress__footprint-callout-label {
1739 +.os-my-wordpress__footprint-callout-label {
1489 1740 font-size: 11px;
1490 1741 text-transform: uppercase;
1491 1742 letter-spacing: 0.08em;
1492 - color: var( --wpd-fg-muted, #50575e );
1743 + color: var( --os-ui-fg-muted, #50575e );
1493 1744 font-weight: 600;
1494 1745 }
1495 1746
1496 -.desktop-mode-my-wordpress__footprint-callout-value {
1747 +.os-my-wordpress__footprint-callout-value {
1497 1748 margin: 2px 0;
1498 1749 font-size: 24px;
1499 1750 font-weight: 700;
1500 - color: var( --desktop-mode-fg, #1d2327 );
1751 + color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
1501 1752 }
1502 1753
1503 -.desktop-mode-my-wordpress__footprint-callout-detail {
1754 +.os-my-wordpress__footprint-callout-detail {
1504 1755 margin: 0;
1505 1756 font-size: 13px;
1506 - color: var( --wpd-fg-muted, #50575e );
1757 + color: var( --os-ui-fg-muted, #50575e );
1507 1758 max-width: 480px;
1508 1759 }
1509 1760
1510 1761 /* ----- Recent-activity timeline ----- */
1511 1762
1512 -.desktop-mode-my-wordpress__footprint-timeline {
1763 +.os-my-wordpress__footprint-timeline {
1513 1764 list-style: none;
1514 1765 margin: 0;
1515 1766 padding: 0;
1516 1767 position: relative;
@@ -1518,9 +1769,9 @@
1518 1769 flex-direction: column;
1519 1770 gap: 12px;
1520 1771 }
1521 1772
1522 -.desktop-mode-my-wordpress__footprint-timeline::before {
1773 +.os-my-wordpress__footprint-timeline::before {
1523 1774 content: '';
1524 1775 position: absolute;
1525 1776 inset-inline-start: 13px;
1526 1777 top: 4px;
@@ -1525,13 +1776,13 @@
1525 1776 inset-inline-start: 13px;
1526 1777 top: 4px;
1527 1778 bottom: 4px;
1528 1779 width: 2px;
1529 - background: var( --wpd-border, #dcdcde );
1780 + background: var( --os-ui-border, #dcdcde );
1530 1781 border-radius: 1px;
1531 1782 }
1532 1783
1533 -.desktop-mode-my-wordpress__footprint-event {
1784 +.os-my-wordpress__footprint-event {
1534 1785 display: flex;
1535 1786 gap: 12px;
1536 1787 align-items: flex-start;
1537 1788 position: relative;
@@ -1538,9 +1789,9 @@
1538 1789 padding-inline-start: 36px;
1539 1790 min-height: 28px;
1540 1791 }
1541 1792
1542 -.desktop-mode-my-wordpress__footprint-dot {
1793 +.os-my-wordpress__footprint-dot {
1543 1794 position: absolute;
1544 1795 inset-inline-start: 0;
1545 1796 top: 0;
1546 1797 width: 28px;
@@ -1548,20 +1799,20 @@
1548 1799 border-radius: 50%;
1549 1800 display: inline-flex;
1550 1801 align-items: center;
1551 1802 justify-content: center;
1552 - background: var( --desktop-mode-surface, var( --wpd-surface, #fff ) );
1803 + background: var( --os-surface, var( --os-ui-surface, #fff ) );
1553 1804 border: 2px solid var( --wp-admin-theme-color, #2271b1 );
1554 1805 color: var( --wp-admin-theme-color, #2271b1 );
1555 1806 }
1556 1807
1557 -.desktop-mode-my-wordpress__footprint-event--comment
1558 - .desktop-mode-my-wordpress__footprint-dot {
1559 - border-color: var( --wpd-fg-muted, #787c82 );
1560 - color: var( --wpd-fg-muted, #787c82 );
1808 +.os-my-wordpress__footprint-event--comment
1809 + .os-my-wordpress__footprint-dot {
1810 + border-color: var( --os-ui-fg-muted, #787c82 );
1811 + color: var( --os-ui-fg-muted, #787c82 );
1561 1812 }
1562 1813
1563 -.desktop-mode-my-wordpress__footprint-dot .dashicons {
1814 +.os-my-wordpress__footprint-dot .dashicons {
1564 1815 font-size: 14px;
1565 1816 width: 14px;
1566 1817 height: 14px;
1567 1818 line-height: 1;
@@ -1566,9 +1817,9 @@
1566 1817 height: 14px;
1567 1818 line-height: 1;
1568 1819 }
1569 1820
1570 -.desktop-mode-my-wordpress__footprint-event-body {
1821 +.os-my-wordpress__footprint-event-body {
1571 1822 display: flex;
1572 1823 flex-direction: column;
1573 1824 gap: 2px;
1574 1825 min-width: 0;
@@ -1574,12 +1825,12 @@
1574 1825 min-width: 0;
1575 1826 flex: 1 1 auto;
1576 1827 }
1577 1828
1578 -.desktop-mode-my-wordpress__footprint-event-title {
1829 +.os-my-wordpress__footprint-event-title {
1579 1830 font-weight: 600;
1580 1831 font-size: 13px;
1581 - color: var( --desktop-mode-link, var( --wpd-accent, #2271b1 ) );
1832 + color: var( --os-link, var( --os-ui-accent, #2271b1 ) );
1582 1833 text-decoration: none;
1583 1834 overflow: hidden;
1584 1835 text-overflow: ellipsis;
1585 1836 white-space: nowrap;
@@ -1584,20 +1835,20 @@
1584 1835 text-overflow: ellipsis;
1585 1836 white-space: nowrap;
1586 1837 }
1587 1838
1588 -a.desktop-mode-my-wordpress__footprint-event-title:hover {
1839 +a.os-my-wordpress__footprint-event-title:hover {
1589 1840 text-decoration: underline;
1590 1841 }
1591 1842
1592 -.desktop-mode-my-wordpress__footprint-event-meta {
1843 +.os-my-wordpress__footprint-event-meta {
1593 1844 font-size: 11px;
1594 - color: var( --wpd-fg-muted, #787c82 );
1845 + color: var( --os-ui-fg-muted, #787c82 );
1595 1846 }
1596 1847
1597 1848 /* ----- Footer actions ----- */
1598 1849
1599 -.desktop-mode-my-wordpress__footprint-footer {
1850 +.os-my-wordpress__footprint-footer {
1600 1851 display: flex;
1601 1852 justify-content: flex-end;
1602 1853 align-items: center;
1603 1854 gap: 8px;
@@ -1625,9 +1876,9 @@
1625 1876 * banner across that corner. The strip extends past the
1626 1877 * tile edges; `overflow: hidden` on the parent crops it
1627 1878 * into a clean triangle.
1628 1879 *
1629 - * The status tiles need a positioning context. `.desktop-mode-
1880 + * The status tiles need a positioning context. `.os-
1630 1881 * file-tile` is `position: absolute` (canvas layout) on the
1631 1882 * Posts/Pages browse views — that satisfies the positioning-
1632 1883 * context requirement. For the Media drill-in usage tiles we
1633 1884 * swap from `static` to `relative` via the per-status rule
@@ -1634,9 +1885,9 @@
1634 1885 * below so the ribbon stays anchored to its own tile.
1635 1886 * ============================================================ */
1636 1887
1637 1888 /* Status ribbon — the diagonal corner banner — is now drawn by
1638 - * the `<wpd-ribbon>` web component slotted inside `<wpd-tile>`.
1889 + * the `<os-ribbon>` web component slotted inside `<os-tile>`.
1639 1890 * The component's own shadow-DOM styles own placement, rotation,
1640 1891 * background, lettering, and the WP admin-theme tint. The only
1641 1892 * surface-specific rule left here is dimming the icon on non-
1642 1893 * published tiles so the unpublished signal carries even when
@@ -1641,19 +1892,19 @@
1641 1892 * surface-specific rule left here is dimming the icon on non-
1642 1893 * published tiles so the unpublished signal carries even when
1643 1894 * the ribbon is hidden via the OS-settings toggle. */
1644 1895
1645 -.desktop-mode-my-wordpress__tile--draft,
1646 -.desktop-mode-my-wordpress__tile--pending,
1647 -.desktop-mode-my-wordpress__tile--private,
1648 -.desktop-mode-my-wordpress__tile--future {
1896 +.os-my-wordpress__tile--draft,
1897 +.os-my-wordpress__tile--pending,
1898 +.os-my-wordpress__tile--private,
1899 +.os-my-wordpress__tile--future {
1649 1900 overflow: hidden;
1650 1901 }
1651 1902
1652 -wpd-tile[ status='draft' ] .desktop-mode-file-tile__icon,
1653 -wpd-tile[ status='pending' ] .desktop-mode-file-tile__icon,
1654 -wpd-tile[ status='private' ] .desktop-mode-file-tile__icon,
1655 -wpd-tile[ status='future' ] .desktop-mode-file-tile__icon {
1903 +os-tile[ status='draft' ] .os-file-tile__icon,
1904 +os-tile[ status='pending' ] .os-file-tile__icon,
1905 +os-tile[ status='private' ] .os-file-tile__icon,
1906 +os-tile[ status='future' ] .os-file-tile__icon {
1656 1907 opacity: 0.7;
1657 1908 }
1658 1909
1659 1910 /* ============================================================ *
@@ -1659,19 +1910,23 @@
1659 1910 /* ============================================================ *
1660 1911 * Media section (since 0.21.0)
1661 1912 * ============================================================ */
1662 1913
1663 -.desktop-mode-my-wordpress__media-grid {
1914 +.os-my-wordpress__media-grid {
1664 1915 display: grid;
1665 1916 grid-template-columns: repeat( auto-fill, minmax( 120px, 1fr ) );
1666 - gap: 12px;
1667 - padding: 16px;
1917 + /* A flow grid rather than the absolute canvas, but the air
1918 + * between two icons should not depend on which window you are
1919 + * looking at — so the gaps and the gutter come from the same
1920 + * tokens the canvas pitch is built from. */
1921 + gap: var( --os-grid-gap-y, 16px ) var( --os-grid-gap-x, 20px );
1922 + padding: var( --os-grid-padding, 16px );
1668 1923 overflow-y: auto;
1669 1924 align-content: start;
1670 1925 }
1671 1926
1672 -.desktop-mode-my-wordpress__media-tile {
1673 - /* Override the base `.desktop-mode-file-tile` (position: absolute,
1927 +.os-my-wordpress__media-tile {
1928 + /* Override the base `.os-file-tile` (position: absolute,
1674 1929 * width: 88px) so media tiles flow inside the CSS Grid instead of
1675 1930 * stacking at (0,0) like the absolute-positioned post/user tiles.
1676 1931 *
1677 1932 * `relative` (not `static`) so the tile remains a containing
@@ -1676,14 +1931,18 @@
1676 1931 *
1677 1932 * `relative` (not `static`) so the tile remains a containing
1678 1933 * block for absolutely-positioned descendants — the `::after`
1679 1934 * shortcut-arrow badge on attachment tiles, and the
1680 - * `<wpd-ribbon>` post-status corner ribbon — both of which
1935 + * `<os-ribbon>` post-status corner ribbon — both of which
1681 1936 * would otherwise escape to the nearest positioned ancestor
1682 1937 * (the window, the desktop, the viewport) and render way off
1683 1938 * the tile. */
1684 1939 position: relative;
1685 1940 width: auto;
1941 + /* …and out of the fixed tile height for the same reason: a media
1942 + * tile is a square thumbnail plus a caption, sized by the grid
1943 + * column it lands in, not by the icon-canvas cell. */
1944 + height: auto;
1686 1945 display: flex;
1687 1946 flex-direction: column;
1688 1947 align-items: stretch;
1689 1948 gap: 6px;
@@ -1695,13 +1954,13 @@
1695 1954 text-align: center;
1696 1955 min-width: 0;
1697 1956 }
1698 1957
1699 -.desktop-mode-my-wordpress__media-tile:hover {
1700 - background: var( --desktop-mode-hover, var( --wpd-hover, rgba( 0, 0, 0, 0.04 ) ) );
1958 +.os-my-wordpress__media-tile:hover {
1959 + background: var( --os-hover, var( --os-ui-hover, rgba( 0, 0, 0, 0.04 ) ) );
1701 1960 }
1702 1961
1703 -/* Media tiles inherit the canonical `.desktop-mode-file-tile--selected`
1962 +/* Media tiles inherit the canonical `.os-file-tile--selected`
1704 1963 * rule from `desktop-files.css` — accent inset border + tinted
1705 1964 * background — same as every other tile in the shell. */
1706 1965
1707 1966 /* Override the canonical 48×48 visual/preview sizing — media tiles
@@ -1709,9 +1968,9 @@
1709 1968 * thumbnail (or icon-fallback square). Photos browser look, not
1710 1969 * folder-icon look. Applies to BOTH the `<img>` (real thumbnail)
1711 1970 * and the dashicon fallback (non-image MIME), so the two tile
1712 1971 * shapes are visually consistent in the grid. */
1713 -.desktop-mode-my-wordpress__media-tile .desktop-mode-file-tile__visual {
1972 +.os-my-wordpress__media-tile .os-file-tile__visual {
1714 1973 display: flex;
1715 1974 align-items: center;
1716 1975 justify-content: center;
1717 1976 width: 100%;
@@ -1719,9 +1978,9 @@
1719 1978 aspect-ratio: 1 / 1;
1720 1979 overflow: hidden;
1721 1980 border-radius: 6px;
1722 1981 background: var(
1723 - --desktop-mode-media-tile-bg,
1982 + --os-media-tile-bg,
1724 1983 rgba( 0, 0, 0, 0.05 )
1725 1984 );
1726 1985 /* Reset the base 32px font + 48px size since we're sizing the
1727 1986 * inner img/icon explicitly below. */
@@ -1728,9 +1987,9 @@
1728 1987 font-size: 0;
1729 1988 line-height: 1;
1730 1989 }
1731 1990
1732 -.desktop-mode-my-wordpress__media-tile .desktop-mode-file-tile__preview {
1991 +.os-my-wordpress__media-tile .os-file-tile__preview {
1733 1992 width: 100%;
1734 1993 height: 100%;
1735 1994 object-fit: cover;
1736 1995 border-radius: 0;
@@ -1735,18 +1994,18 @@
1735 1994 object-fit: cover;
1736 1995 border-radius: 0;
1737 1996 }
1738 1997
1739 -.desktop-mode-my-wordpress__media-tile .desktop-mode-file-tile__icon {
1998 +.os-my-wordpress__media-tile .os-file-tile__icon {
1740 1999 /* Centered dashicon fallback — proportional to the larger
1741 2000 * thumbnail well so it doesn't look like a postage stamp. */
1742 2001 width: auto;
1743 2002 height: auto;
1744 2003 font-size: 36px;
1745 - color: var( --wpd-fg-muted, #787c82 );
2004 + color: var( --os-ui-fg-muted, #787c82 );
1746 2005 }
1747 2006
1748 -.desktop-mode-my-wordpress__media-tile .desktop-mode-file-tile__label {
2007 +.os-my-wordpress__media-tile .os-file-tile__label {
1749 2008 font-size: 12px;
1750 2009 line-height: 1.3;
1751 2010 overflow: hidden;
1752 2011 text-overflow: ellipsis;
@@ -1756,9 +2015,9 @@
1756 2015 }
1757 2016
1758 2017 /* ----- Media preview pane ----- */
1759 2018
1760 -.desktop-mode-my-wordpress__media-pane {
2019 +.os-my-wordpress__media-pane {
1761 2020 display: flex;
1762 2021 flex-direction: column;
1763 2022 gap: 16px;
1764 2023 padding: 16px;
@@ -1763,19 +2022,19 @@
1763 2022 gap: 16px;
1764 2023 padding: 16px;
1765 2024 }
1766 2025
1767 -.desktop-mode-my-wordpress__media-title {
2026 +.os-my-wordpress__media-title {
1768 2027 font-size: 16px;
1769 2028 font-weight: 600;
1770 2029 margin: 0;
1771 2030 }
1772 2031
1773 -.desktop-mode-my-wordpress__media-visual {
2032 +.os-my-wordpress__media-visual {
1774 2033 display: flex;
1775 2034 align-items: center;
1776 2035 justify-content: center;
1777 - background: var( --desktop-mode-media-visual-bg, var( --wpd-hover, rgba( 0, 0, 0, 0.04 ) ) );
2036 + background: var( --os-media-visual-bg, var( --os-ui-hover, rgba( 0, 0, 0, 0.04 ) ) );
1778 2037 border-radius: 8px;
1779 2038 min-height: 200px;
1780 2039 max-height: 480px;
1781 2040 overflow: hidden;
@@ -1780,28 +2039,28 @@
1780 2039 max-height: 480px;
1781 2040 overflow: hidden;
1782 2041 }
1783 2042
1784 -.desktop-mode-my-wordpress__media-image,
1785 -.desktop-mode-my-wordpress__media-video {
2043 +.os-my-wordpress__media-image,
2044 +.os-my-wordpress__media-video {
1786 2045 max-width: 100%;
1787 2046 max-height: 480px;
1788 2047 object-fit: contain;
1789 2048 }
1790 2049
1791 -.desktop-mode-my-wordpress__media-fallback-icon {
2050 +.os-my-wordpress__media-fallback-icon {
1792 2051 font-size: 96px;
1793 2052 width: 96px;
1794 2053 height: 96px;
1795 - color: var( --wpd-fg-muted, #787c82 );
2054 + color: var( --os-ui-fg-muted, #787c82 );
1796 2055 }
1797 2056
1798 -.desktop-mode-my-wordpress__media-doc-link {
2057 +.os-my-wordpress__media-doc-link {
1799 2058 margin-inline-start: 16px;
1800 2059 align-self: center;
1801 2060 }
1802 2061
1803 -.desktop-mode-my-wordpress__media-audio-stack {
2062 +.os-my-wordpress__media-audio-stack {
1804 2063 display: flex;
1805 2064 flex-direction: column;
1806 2065 align-items: center;
1807 2066 gap: 12px;
@@ -1807,9 +2066,9 @@
1807 2066 gap: 12px;
1808 2067 padding: 24px;
1809 2068 }
1810 2069
1811 -.desktop-mode-my-wordpress__media-meta {
2070 +.os-my-wordpress__media-meta {
1812 2071 display: grid;
1813 2072 grid-template-columns: max-content 1fr;
1814 2073 gap: 4px 16px;
1815 2074 font-size: 13px;
@@ -1815,31 +2074,31 @@
1815 2074 font-size: 13px;
1816 2075 margin: 0;
1817 2076 }
1818 2077
1819 -.desktop-mode-my-wordpress__media-meta-term {
1820 - color: var( --wpd-fg-muted, #787c82 );
2078 +.os-my-wordpress__media-meta-term {
2079 + color: var( --os-ui-fg-muted, #787c82 );
1821 2080 margin: 0;
1822 2081 }
1823 2082
1824 -.desktop-mode-my-wordpress__media-meta-value {
1825 - color: var( --wpd-fg, #1d2327 );
2083 +.os-my-wordpress__media-meta-value {
2084 + color: var( --os-ui-fg, #1d2327 );
1826 2085 word-break: break-word;
1827 2086 margin: 0;
1828 2087 }
1829 2088
1830 -.desktop-mode-my-wordpress__media-actions {
2089 +.os-my-wordpress__media-actions {
1831 2090 display: flex;
1832 2091 flex-wrap: wrap;
1833 2092 gap: 8px;
1834 2093 padding-top: 8px;
1835 - border-top: 1px solid var( --wpd-border, #dcdcde );
2094 + border-top: 1px solid var( --os-ui-border, #dcdcde );
1836 2095 }
1837 2096
1838 2097 /* ----- Media drill-in ----- */
1839 2098
1840 2099 /* Drill-in: referencing-posts list. Visually identical to the
1841 - * Posts / Pages tiles — same `desktop-mode-file-tile` chrome (48px
2100 + * Posts / Pages tiles — same `os-file-tile` chrome (48px
1842 2101 * dashicon + 88px-wide two-line label). We can't reuse the
1843 2102 * absolute-positioning canvas layout from `renderEntityList` here
1844 2103 * (those internals don't export), so this surface uses a flex-wrap
1845 2104 * of fixed-width tiles to reproduce the look.
@@ -1847,22 +2106,22 @@
1847 2106 * NOTE: this rule INTENTIONALLY overrides the `__media-grid`
1848 2107 * defaults (which target square thumbnails on 130px columns) so
1849 2108 * usage tiles match the canvas-flowed post tiles instead.
1850 2109 */
1851 -.desktop-mode-my-wordpress__usage-grid {
2110 +.os-my-wordpress__usage-grid {
1852 2111 display: flex;
1853 2112 flex-wrap: wrap;
1854 - gap: 12px 8px;
1855 - padding: 16px;
2113 + gap: var( --os-grid-gap-y, 16px ) var( --os-grid-gap-x, 20px );
2114 + padding: var( --os-grid-padding, 16px );
1856 2115 align-content: flex-start;
1857 2116 }
1858 2117
1859 2118 /* Reset the `__media-tile` overrides for usage tiles so they
1860 - * inherit the unmodified `.desktop-mode-file-tile` chrome the
2119 + * inherit the unmodified `.os-file-tile` chrome the
1861 2120 * canvas-positioned post tiles use — except for `position: static`
1862 2121 * so they participate in the flex layout. */
1863 -.desktop-mode-my-wordpress__tile--usage {
1864 - width: 88px;
2122 +.os-my-wordpress__tile--usage {
2123 + width: var( --os-tile-w, 88px );
1865 2124 align-items: center;
1866 2125 padding: 8px 4px;
1867 2126 gap: 6px;
1868 2127 }
@@ -1867,20 +2126,20 @@
1867 2126 gap: 6px;
1868 2127 }
1869 2128
1870 2129 /* Right-pane summary bar sits ABOVE the inline media preview. */
1871 -.desktop-mode-my-wordpress__media-detail-summary-bar {
2130 +.os-my-wordpress__media-detail-summary-bar {
1872 2131 padding: 12px 16px;
1873 - border-bottom: 1px solid var( --wpd-border, #dcdcde );
2132 + border-bottom: 1px solid var( --os-ui-border, #dcdcde );
1874 2133 }
1875 2134
1876 -.desktop-mode-my-wordpress__media-detail-summary {
2135 +.os-my-wordpress__media-detail-summary {
1877 2136 margin: 0;
1878 - color: var( --wpd-fg-muted, #787c82 );
2137 + color: var( --os-ui-fg-muted, #787c82 );
1879 2138 font-size: 13px;
1880 2139 }
1881 2140
1882 -.desktop-mode-my-wordpress__media-detail-preview {
2141 +.os-my-wordpress__media-detail-preview {
1883 2142 /* Lets the embedded `__media-pane` keep its own padding without
1884 2143 * fighting the summary bar's spacing. */
1885 2144 display: block;
1886 2145 }
@@ -1899,8 +2158,9 @@
1899 2158 overflow: hidden;
1900 2159 box-sizing: border-box;
1901 2160 }
1902 2161
2162 +
1903 2163 /* Section-level loading — same scale curve as the My WordPress
1904 2164 preview loader and the window-loading overlay, instead of the bare
1905 2165 48px component default. */
1906 2166 .dm-agents__loading {
@@ -1910,114 +2170,31 @@
1910 2170 height: 100%;
1911 2171 min-height: 320px;
1912 2172 }
1913 2173
1914 -.dm-agents__loading wpd-spinner {
1915 - --wpd-spinner-size: clamp( 96px, 14vw, 192px );
2174 +.dm-agents__loading os-spinner {
2175 + --os-ui-spinner-size: clamp( 96px, 14vw, 192px );
1916 2176 }
1917 2177
1918 -.dm-agents__layout {
1919 - display: flex;
2178 +.dm-agents__detail {
1920 2179 flex: 1;
1921 - min-height: 0;
1922 - gap: 12px;
1923 -}
1924 -
1925 -/* Sidebar column: a fixed "Create agent" header over the scrolling
1926 - list. The button used to be the list's last child, which put it out
1927 - of reach on any site with enough agents to need it. */
1928 -.dm-agents__sidebar {
1929 - display: flex;
1930 - flex-direction: column;
1931 - flex: 0 0 260px;
1932 - /* `min-width: auto` on a flex item resolves to its min-content
1933 - width, and the rows carry long `white-space: nowrap` descriptions
1934 - — without this the column ignores its 260px basis and eats the
1935 - detail pane. The scroll container used to be this item, whose
1936 - non-visible overflow zeroed the minimum for free. */
1937 2180 min-width: 0;
1938 - min-height: 0;
1939 - border-inline-end: 1px solid var( --desktop-mode-border, rgba( 0, 0, 0, 0.08 ) );
1940 -}
1941 -
1942 -.dm-agents__list-toolbar {
1943 - flex: none;
1944 - display: flex;
1945 - padding-block-end: 8px;
1946 - padding-inline-end: 8px;
1947 -}
1948 -
1949 -.dm-agents__list-toolbar .dm-agents__create {
1950 - flex: 1;
1951 -}
1952 -
1953 -.dm-agents__list {
1954 - display: flex;
1955 - flex-direction: column;
1956 - gap: 4px;
1957 - flex: 1;
1958 - min-height: 0;
1959 2181 overflow-y: auto;
1960 - padding-inline-end: 4px;
1961 -}
1962 -
1963 -.dm-agents__row {
1964 2182 display: flex;
1965 - align-items: center;
1966 - gap: 8px;
1967 - padding: 8px;
1968 - border-radius: 8px;
1969 - cursor: pointer;
1970 -}
1971 -
1972 -.dm-agents__row:hover {
1973 - background: var( --desktop-mode-hover, rgba( 0, 0, 0, 0.06 ) );
1974 -}
1975 -
1976 -.dm-agents__row.is-selected {
1977 - background: var( --desktop-mode-selected, rgba( 0, 0, 0, 0.1 ) );
1978 -}
1979 -
1980 -.dm-agents__row-avatar {
1981 - width: 32px;
1982 - height: 32px;
1983 - border-radius: 50%;
1984 - background: #fff;
1985 - flex: none;
1986 -}
1987 -
1988 -.dm-agents__row-text {
1989 - display: flex;
1990 2183 flex-direction: column;
1991 - min-width: 0;
1992 - flex: 1;
2184 + gap: 10px;
1993 2185 }
1994 2186
1995 -.dm-agents__row-name {
1996 - font-weight: 600;
1997 - white-space: nowrap;
1998 - overflow: hidden;
1999 - text-overflow: ellipsis;
2187 +/* `<os-empty-state>` owns the icon + copy and centres them within
2188 + itself; the host is still a flex item that shrinks to its content,
2189 + so without this it sits at the top of a pane that is mostly empty
2190 + space. Auto margins on both axes absorb the slack — placement only,
2191 + same as the comments window. Covers the framework-off state and
2192 + "No agents yet" alike. */
2193 +.dm-agents__detail > os-empty-state {
2194 + margin: auto;
2000 2195 }
2001 2196
2002 -.dm-agents__row-desc {
2003 - font-size: 12px;
2004 - opacity: 0.65;
2005 - white-space: nowrap;
2006 - overflow: hidden;
2007 - text-overflow: ellipsis;
2008 -}
2009 -
2010 -
2011 -.dm-agents__detail {
2012 - flex: 1;
2013 - min-width: 0;
2014 - overflow-y: auto;
2015 - display: flex;
2016 - flex-direction: column;
2017 - gap: 10px;
2018 -}
2019 -
2020 2197 .dm-agents__detail-head {
2021 2198 display: flex;
2022 2199 align-items: center;
2023 2200 gap: 10px;
@@ -2026,9 +2203,11 @@
2026 2203 .dm-agents__detail-avatar {
2027 2204 width: 48px;
2028 2205 height: 48px;
2029 2206 border-radius: 50%;
2030 - background: #fff;
2207 + /* Placeholder behind the avatar image while it loads — follows the
2208 + palette so it isn't a white disc on a dark station. */
2209 + background: var( --os-ui-surface-elevated, #fff );
2031 2210 flex: none;
2032 2211 }
2033 2212
2034 2213 .dm-agents__detail-title {
@@ -2057,9 +2236,9 @@
2057 2236
2058 2237 .dm-agents__tabs {
2059 2238 display: flex;
2060 2239 gap: 4px;
2061 - border-bottom: 1px solid var( --desktop-mode-border, rgba( 0, 0, 0, 0.08 ) );
2240 + border-bottom: 1px solid var( --os-border, rgba( 0, 0, 0, 0.08 ) );
2062 2241 }
2063 2242
2064 2243 .dm-agents__tab {
2065 2244 appearance: none;
@@ -2073,9 +2252,9 @@
2073 2252 opacity: 0.7;
2074 2253 }
2075 2254
2076 2255 .dm-agents__tab.is-active {
2077 - border-bottom-color: var( --desktop-mode-accent, #2271b1 );
2256 + border-bottom-color: var( --os-accent, #2271b1 );
2078 2257 opacity: 1;
2079 2258 font-weight: 600;
2080 2259 }
2081 2260
@@ -2095,10 +2274,10 @@
2095 2274 flex: 1;
2096 2275 min-height: 260px;
2097 2276 }
2098 2277
2099 -.dm-agents__pane--loading wpd-spinner {
2100 - --wpd-spinner-size: clamp( 96px, 12vw, 160px );
2278 +.dm-agents__pane--loading os-spinner {
2279 + --os-ui-spinner-size: clamp( 96px, 12vw, 160px );
2101 2280 }
2102 2281
2103 2282 .dm-agents__hint {
2104 2283 margin: 0;
@@ -2105,33 +2284,158 @@
2105 2284 font-size: 12px;
2106 2285 opacity: 0.7;
2107 2286 }
2108 2287
2288 +/* Role first: least privilege is the decision, so the control holds
2289 + the mockup's width instead of stretching into a landing strip. */
2290 +.dm-agents__role-select {
2291 + max-width: 280px;
2292 +}
2293 +
2294 +/* The ability filter. Sized like the role select rather than the
2295 + full pane: it sits above a list of rules, and a search box as wide
2296 + as the rules reads as another one of them. */
2297 +.dm-agents__ability-search {
2298 + display: block;
2299 + max-width: 320px;
2300 + margin: 12px 0 4px;
2301 +}
2302 +
2303 +/* Each category is a native disclosure. `<details>` because the
2304 + behaviour is exactly what it is for: keyboard, screen-reader
2305 + semantics and the open/closed state all arrive for free, and the
2306 + only thing left to write is the costume. */
2307 +.dm-agents__ability-group {
2308 + border-bottom: 1px solid var( --os-border, rgba( 0, 0, 0, 0.08 ) );
2309 +}
2310 +
2311 +.dm-agents__ability-group:last-of-type {
2312 + border-bottom: 0;
2313 +}
2314 +
2109 2315 .dm-agents__category {
2110 - margin: 8px 0 0;
2111 - font-size: 12px;
2316 + margin: 18px 0 2px;
2317 + font-family: var( --os-ui-font-mono, ui-monospace, monospace );
2318 + font-size: 11px;
2319 + font-weight: 500;
2112 2320 text-transform: uppercase;
2113 - letter-spacing: 0.04em;
2114 - opacity: 0.6;
2321 + letter-spacing: 0.08em;
2322 + color: var( --os-ui-fg-muted, #646970 );
2115 2323 }
2116 2324
2325 +/* A `<summary>` is a button, so it gets a button's affordances: a
2326 + pointer, a hover, and a focus ring that is visible on the dark
2327 + surface the section is drawn on. */
2328 +summary.dm-agents__category {
2329 + display: flex;
2330 + align-items: center;
2331 + gap: 8px;
2332 + margin: 0;
2333 + padding: 10px 0;
2334 + cursor: pointer;
2335 + list-style: none;
2336 + user-select: none;
2337 +}
2338 +
2339 +summary.dm-agents__category::-webkit-details-marker {
2340 + display: none;
2341 +}
2342 +
2343 +/* The marker is drawn here rather than left to the UA so it can be
2344 + the same triangle in every browser and turn with the disclosure.
2345 + Rotation only: a transform, so opening a group of forty rows
2346 + costs no layout. */
2347 +summary.dm-agents__category::before {
2348 + content: '';
2349 + flex: none;
2350 + width: 0;
2351 + height: 0;
2352 + border-inline-start: 5px solid currentcolor;
2353 + border-block: 4px solid transparent;
2354 + transition: transform 120ms ease;
2355 +}
2356 +
2357 +.dm-agents__ability-group[ open ] > summary.dm-agents__category::before {
2358 + transform: rotate( 90deg );
2359 +}
2360 +
2361 +@media ( prefers-reduced-motion: reduce ) {
2362 + summary.dm-agents__category::before {
2363 + transition: none;
2364 + }
2365 +}
2366 +
2367 +summary.dm-agents__category:hover {
2368 + color: var( --os-ui-fg, #1e1e1e );
2369 +}
2370 +
2371 +summary.dm-agents__category:focus-visible {
2372 + outline: 2px solid var( --os-ui-accent, #3858e9 );
2373 + outline-offset: 2px;
2374 + border-radius: 4px;
2375 +}
2376 +
2377 +.dm-agents__category-name {
2378 + flex: 1 1 auto;
2379 +}
2380 +
2381 +/* "3 of 12" when some are ticked, otherwise just the size of the
2382 + group. The count is why a closed group is still informative:
2383 + collapsing must not hide the fact that something in there is
2384 + switched on. */
2385 +.dm-agents__category-count {
2386 + flex: none;
2387 + font-variant-numeric: tabular-nums;
2388 + opacity: 0.75;
2389 +}
2390 +
2391 +/* One ability per row, ruled like the mockup: tick and name on the
2392 + left, badge on the right, the description indented under the name
2393 + (the checkbox column is the control's own 26px). */
2117 2394 .dm-agents__ability {
2118 2395 display: grid;
2119 2396 grid-template-columns: 1fr auto;
2120 - gap: 2px 8px;
2121 - align-items: center;
2122 - padding: 4px 0;
2397 + gap: 2px 10px;
2398 + align-items: start;
2399 + padding: 11px 0;
2400 + border-bottom: 1px solid var( --os-border, rgba( 0, 0, 0, 0.08 ) );
2123 2401 }
2124 2402
2403 +.dm-agents__ability:last-of-type {
2404 + border-bottom: 0;
2405 +}
2406 +
2125 2407 .dm-agents__ability-desc {
2126 2408 grid-column: 1 / -1;
2127 2409 margin: 0;
2128 - font-size: 12px;
2129 - opacity: 0.6;
2410 + padding-inline-start: 26px;
2411 + font-size: 12.5px;
2412 + color: var( --os-ui-fg-muted, #646970 );
2130 2413 }
2131 2414
2415 +/* Access badges in the instrument voice. The palette's own warning
2416 + tokens carry the pale-yellow "can modify"; all this changes is the
2417 + costume: mono, uppercase, an outline instead of a wash. */
2418 +.dm-agents__ability os-badge {
2419 + --os-ui-badge-font: 500 10px/1.6 var( --os-ui-font-mono, ui-monospace, monospace );
2420 + --os-ui-badge-dot-size: 0;
2421 + --os-ui-badge-gap: 0;
2422 + --os-ui-badge-padding: 3px 8px;
2423 + --os-ui-badge-bg: transparent;
2424 + --os-ui-badge-border: 1px solid var( --os-border, rgba( 0, 0, 0, 0.12 ) );
2425 + text-transform: uppercase;
2426 + letter-spacing: 0.06em;
2427 + white-space: nowrap;
2428 + margin-top: 2px;
2429 +}
2430 +
2431 +.dm-agents__ability os-badge[ tone='warning' ] {
2432 + --os-ui-badge-border: 1px solid
2433 + var( --os-ui-warning-border, rgba( 154, 103, 0, 0.4 ) );
2434 +}
2435 +
2132 2436 .dm-agents__trigger {
2133 - border: 1px solid var( --desktop-mode-border, rgba( 0, 0, 0, 0.08 ) );
2437 + border: 1px solid var( --os-border, rgba( 0, 0, 0, 0.08 ) );
2134 2438 border-radius: 8px;
2135 2439 padding: 8px 10px;
2136 2440 display: flex;
2137 2441 flex-direction: column;
@@ -2143,15 +2447,12 @@
2143 2447 align-items: center;
2144 2448 gap: 8px;
2145 2449 }
2146 2450
2147 -.dm-agents__trigger-summary {
2148 - flex: 1;
2451 +.dm-agents__trigger-desc {
2452 + margin: 0;
2149 2453 font-size: 12px;
2150 - opacity: 0.65;
2151 - white-space: nowrap;
2152 - overflow: hidden;
2153 - text-overflow: ellipsis;
2454 + opacity: 0.75;
2154 2455 }
2155 2456
2156 2457 .dm-agents__trigger-config {
2157 2458 display: flex;
@@ -2161,5 +2462,503 @@
2161 2462
2162 2463 .dm-agents__actions {
2163 2464 display: flex;
2164 2465 gap: 8px;
2466 + align-items: center;
2467 + flex-wrap: wrap;
2468 + margin-block-start: 12px;
2469 +}
2470 +
2471 +/* ---------------------------------------------------------------------
2472 + The cast
2473 + ------------------------------------------------------------------ */
2474 +
2475 +/* One view at a time: the grid, an agent, or the wizard. A sidebar of
2476 + faces next to a detail form would leave neither enough room, and the
2477 + whole point of the grid is that the faces are big enough to tell
2478 + apart. */
2479 +/* The pane scrolls, and a scroll container clips ink overflow: a field
2480 + flush with its edge loses the focus halo the kit paints outside the
2481 + border (1px ring + 4px bloom), so the brief's ring read as a top and
2482 + bottom line with nothing at the sides. Trade 5px of the section's
2483 + 12px padding for a gutter inside the pane; the content does not move. */
2484 +.dm-agents__view {
2485 + display: flex;
2486 + flex-direction: column;
2487 + flex: 1;
2488 + min-height: 0;
2489 + overflow-y: auto;
2490 + gap: 12px;
2491 + margin-inline: -5px;
2492 + padding-inline: 5px;
2493 +}
2494 +
2495 +.dm-agents__cast-head {
2496 + display: flex;
2497 + align-items: baseline;
2498 + gap: 8px;
2499 +}
2500 +
2501 +.dm-agents__cast-head h3 {
2502 + margin: 0;
2503 +}
2504 +
2505 +.dm-agents__cast-count {
2506 + font-family: var( --os-ui-font-mono, ui-monospace, monospace );
2507 + font-size: 12px;
2508 + color: var( --os-ui-fg-muted, #646970 );
2509 +}
2510 +
2511 +.dm-agents__cast {
2512 + display: grid;
2513 + gap: 16px;
2514 + grid-template-columns: repeat( auto-fill, minmax( 288px, 1fr ) );
2515 + align-content: start;
2516 +}
2517 +
2518 +/* The card reacts like the mockup's: a lift and a brighter edge.
2519 + Transform and border-color only — both cheap, and the same pair the
2520 + mockup transitions. Document styles win over the component's own
2521 + :host rules, which is the sanctioned way to restyle a host. */
2522 +.dm-agents__cast-card,
2523 +.dm-agents__cast-new {
2524 + --os-ui-card-padding: 20px 18px 16px;
2525 + transition: border-color 0.18s ease, transform 0.18s ease;
2526 +}
2527 +
2528 +.dm-agents__cast-card:hover,
2529 +.dm-agents__cast-card:focus-within {
2530 + border-color: var( --os-ui-border-strong, #8c8f94 );
2531 + transform: translateY( -2px );
2532 +}
2533 +
2534 +/* The dashed door, same as the mockup's crew-new card. */
2535 +.dm-agents__cast-new {
2536 + border-style: dashed;
2537 + --os-ui-card-bg: var( --os-ui-surface-subtle, transparent );
2538 +}
2539 +
2540 +/* The crew breathes. Transform only, staggered so five faces do not
2541 + bob in lockstep, and gone entirely under reduced motion. */
2542 +@media ( prefers-reduced-motion: no-preference ) {
2543 + .dm-agents__cast-card .dm-agents__cast-face {
2544 + animation: dm-agents-bob 6s ease-in-out infinite;
2545 + }
2546 + .dm-agents__cast-card:nth-child( 2n ) .dm-agents__cast-face {
2547 + animation-duration: 7.2s;
2548 + animation-delay: -1.4s;
2549 + }
2550 + .dm-agents__cast-card:nth-child( 3n ) .dm-agents__cast-face {
2551 + animation-duration: 6.6s;
2552 + animation-delay: -2.8s;
2553 + }
2554 +}
2555 +
2556 +@keyframes dm-agents-bob {
2557 + 0%,
2558 + 100% {
2559 + transform: translateY( 0 );
2560 + }
2561 + 50% {
2562 + transform: translateY( -4px );
2563 + }
2564 +}
2565 +
2566 +/* The column lives on a wrapper we own, not on the host: the slotted
2567 + children sit inside the card's own container, so a flex rule on the
2568 + host never reaches them and the role badges land wherever the
2569 + description's line count leaves them. */
2570 +.dm-agents__cast-inner {
2571 + display: flex;
2572 + flex-direction: column;
2573 + align-items: center;
2574 + text-align: center;
2575 + gap: 2px;
2576 + height: 100%;
2577 +}
2578 +
2579 +/* The faces are the loud part of this surface, and deliberately so:
2580 + agent identity is the one place the station spends the mesh budget
2581 + on something other than a hero CTA. A cast has to be legible at a
2582 + glance, which is exactly what a flat accent cannot do. */
2583 +.dm-agents__cast-face {
2584 + width: 118px;
2585 + height: 118px;
2586 + margin: -10px 0 6px;
2587 + flex: none;
2588 +}
2589 +
2590 +.dm-agents__cast-name {
2591 + font-size: 17px;
2592 + font-weight: 600;
2593 + color: var( --os-ui-fg, #1d2327 );
2594 +}
2595 +
2596 +/* The voice line, in the instrument register: this is metadata about
2597 + the agent, not prose from it. */
2598 +.dm-agents__cast-vibes {
2599 + font-family: var( --os-ui-font-mono, ui-monospace, monospace );
2600 + font-size: 11.5px;
2601 + color: var( --os-ui-accent-strong, #2271b1 );
2602 +}
2603 +
2604 +.dm-agents__cast-good {
2605 + font-size: 13px;
2606 + color: var( --os-ui-fg-muted, #646970 );
2607 + margin-block: 4px 14px;
2608 + flex: 1;
2609 +}
2610 +
2611 +/* The role pill in the instrument voice: mono, uppercase, no status
2612 + dot — this is a fact about the agent, not a state to monitor. The
2613 + custom properties are the component's own theming hooks; the
2614 + inherited text properties flow into its shadow label. */
2615 +.dm-agents__cast-card os-badge {
2616 + --os-ui-badge-font: 500 11px/1.6 var( --os-ui-font-mono, ui-monospace, monospace );
2617 + --os-ui-badge-dot-size: 0;
2618 + --os-ui-badge-gap: 0;
2619 + --os-ui-badge-padding: 3px 10px;
2620 + text-transform: uppercase;
2621 + letter-spacing: 0.08em;
2622 +}
2623 +
2624 +/* The framework-off bar: the section's status and its one action, on
2625 + one line above the crew it would hire. It is deliberately not an
2626 + `os-empty-state` — that block is centred, icon-led and paragraph-
2627 + shaped, which is exactly the wall of text the cast replaced, and at
2628 + five cards tall it would push the button that undoes the situation
2629 + off the bottom of the window. `flex: none` because `.dm-agents__view`
2630 + is a scrolling flex column and the bar must not absorb the slack. */
2631 +.dm-agents__off-head {
2632 + display: flex;
2633 + align-items: center;
2634 + justify-content: space-between;
2635 + flex-wrap: wrap;
2636 + flex: none;
2637 + gap: 8px 16px;
2638 + padding: 12px 14px;
2639 + border-radius: 10px;
2640 + background: var( --os-ui-surface-elevated, #fff );
2641 + border: 1px solid var( --os-border, rgba( 0, 0, 0, 0.08 ) );
2642 +}
2643 +
2644 +.dm-agents__off-copy {
2645 + min-width: 0;
2646 +}
2647 +
2648 +.dm-agents__off-copy h3 {
2649 + margin: 0;
2650 +}
2651 +
2652 +.dm-agents__off-copy p {
2653 + margin: 2px 0 0;
2654 + font-size: 13px;
2655 + color: var( --os-ui-fg-muted, #646970 );
2656 +}
2657 +
2658 +/* The cast the site would get, drawn while the framework is off.
2659 + Dimmed as a whole rather than desaturated: the five hues ARE the
2660 + argument this state is making, and a greyscale filter would flatten
2661 + the crew into five identical blobs on the way to saying "not yet".
2662 + Opacity says inactive and leaves the faces telling each other apart.
2663 +
2664 + `pointer-events` is belt and braces — the cards are rendered without
2665 + `interactive` and without a click handler, so there is nothing to
2666 + press. It exists so a hover state cannot promise otherwise. */
2667 +.dm-agents__cast--preview {
2668 + opacity: 0.6;
2669 + pointer-events: none;
2670 +}
2671 +
2672 +.dm-agents__cast-new .dm-agents__cast-plus {
2673 + display: grid;
2674 + place-items: center;
2675 + width: 118px;
2676 + height: 118px;
2677 + margin: -10px 0 6px;
2678 + border-radius: 50%;
2679 + border: 1.5px dashed var( --os-ui-border-strong, #8c8f94 );
2680 + font-size: 30px;
2681 + font-weight: 300;
2682 + line-height: 1;
2683 + color: var( --os-ui-fg-muted, #646970 );
2684 +}
2685 +
2686 +/* ---------------------------------------------------------------------
2687 + The wizard
2688 + ------------------------------------------------------------------ */
2689 +
2690 +.dm-agents__wizard {
2691 + display: flex;
2692 + flex-direction: column;
2693 + gap: 10px;
2694 +}
2695 +
2696 +.dm-agents__wiz-head {
2697 + display: flex;
2698 + align-items: center;
2699 + justify-content: space-between;
2700 + gap: 8px 12px;
2701 + flex-wrap: wrap;
2702 +}
2703 +
2704 +.dm-agents__wiz-head h3 {
2705 + margin: 0;
2706 +}
2707 +
2708 +/* The trail wears the instrument voice: mono uppercase labels, 22px
2709 + dots, a thin rule between stations. All of it goes through the
2710 + component's own theming hooks; the host elements live in this light
2711 + DOM, so the per-state overrides below can select them directly. */
2712 +.dm-agents__trail {
2713 + margin-block: 6px 14px;
2714 + --os-ui-steps-gap: 10px;
2715 + --os-ui-step-gap: 7px;
2716 + --os-ui-step-chip-size: 22px;
2717 + --os-ui-step-chip-font-size: 11px;
2718 + --os-ui-step-chip-family: var( --os-ui-font-mono, ui-monospace, monospace );
2719 + --os-ui-step-title-size: 11px;
2720 + --os-ui-step-title-family: var( --os-ui-font-mono, ui-monospace, monospace );
2721 + --os-ui-step-title-transform: uppercase;
2722 + --os-ui-step-title-spacing: 0.08em;
2723 +}
2724 +
2725 +/* A station you have not reached is an outline, not a filled dot: the
2726 + mesh chip is where you ARE, and it only reads that way if it is the
2727 + only one lit. */
2728 +.dm-agents__trail os-step:not( [ done ] ):not( [ current ] ) {
2729 + --os-ui-step-chip-bg: transparent;
2730 + --os-ui-step-chip-border: 1px solid var( --os-ui-border-strong, #8c8f94 );
2731 + --os-ui-step-chip-fg: var( --os-ui-fg-muted, #646970 );
2732 +}
2733 +
2734 +/* Done is quiet: a filled tick on the elevated surface, muted like its
2735 + label. It reads as history, not as a second highlight. */
2736 +.dm-agents__trail os-step[ done ] {
2737 + --os-ui-step-chip-done-bg: var( --os-ui-surface-elevated, #f0f0f1 );
2738 + --os-ui-step-chip-fg: var( --os-ui-fg-muted, #646970 );
2739 +}
2740 +
2741 +.dm-agents__wiz-heading {
2742 + margin: 12px 0 2px;
2743 + font-size: 16px;
2744 + font-weight: 600;
2745 + color: var( --os-ui-fg, #1d2327 );
2746 +}
2747 +
2748 +/* The door. Five complete agents already ship with the plugin, and
2749 + until now the create flow showed them to nobody. */
2750 +.dm-agents__starters {
2751 + display: grid;
2752 + gap: 12px;
2753 + grid-template-columns: repeat( auto-fill, minmax( 148px, 1fr ) );
2754 + margin-block: 8px 16px;
2755 +}
2756 +
2757 +.dm-agents__starter {
2758 + display: flex;
2759 + flex-direction: column;
2760 + align-items: center;
2761 + text-align: center;
2762 + gap: 3px;
2763 + --os-ui-card-padding: 16px 14px;
2764 + --os-ui-card-radius: 10px;
2765 + --os-ui-card-bg: var( --os-ui-surface-subtle, transparent );
2766 + transition: border-color 0.18s ease;
2767 +}
2768 +
2769 +.dm-agents__starter:hover,
2770 +.dm-agents__starter:focus-within {
2771 + border-color: var( --os-ui-border-strong, #8c8f94 );
2772 +}
2773 +
2774 +.dm-agents__starter-face {
2775 + width: 76px;
2776 + height: 76px;
2777 + margin: -8px 0 4px;
2778 + flex: none;
2779 +}
2780 +
2781 +.dm-agents__starter-name {
2782 + font-size: 14px;
2783 + font-weight: 500;
2784 + color: var( --os-ui-fg, #1d2327 );
2785 +}
2786 +
2787 +.dm-agents__starter-vibes {
2788 + font-family: var( --os-ui-font-mono, ui-monospace, monospace );
2789 + font-size: 11.5px;
2790 + color: var( --os-ui-fg-muted, #646970 );
2791 +}
2792 +
2793 +/* Meet: the portrait beside the fields, so the thing being named is
2794 + visible while it is being named. */
2795 +.dm-agents__meet {
2796 + display: grid;
2797 + gap: 20px;
2798 + grid-template-columns: 220px 1fr;
2799 + align-items: start;
2800 +}
2801 +
2802 +/* The character card. Sunken rather than subtle: the portrait is the
2803 + hero of this step, and the mockup floats it on the darkest surface
2804 + so the face's own glow does the framing. */
2805 +.dm-agents__portrait {
2806 + display: flex;
2807 + flex-direction: column;
2808 + align-items: center;
2809 + gap: 10px;
2810 + padding: 20px 14px 14px;
2811 + border: 1px solid var( --os-border, rgba( 0, 0, 0, 0.08 ) );
2812 + border-radius: var( --os-ui-card-radius, 10px );
2813 + background: var( --os-ui-surface-sunken, #f6f7f7 );
2814 +}
2815 +
2816 +.dm-agents__portrait-face {
2817 + width: 176px;
2818 + height: 176px;
2819 + max-width: 100%;
2820 + margin-top: -12px;
2821 +}
2822 +
2823 +/* What this face is, in two words. */
2824 +.dm-agents__portrait-chips {
2825 + display: flex;
2826 + gap: 6px;
2827 + flex-wrap: wrap;
2828 + justify-content: center;
2829 +}
2830 +
2831 +.dm-agents__faces {
2832 + display: grid;
2833 + grid-template-columns: repeat( 6, 1fr );
2834 + gap: 2px;
2835 + width: 100%;
2836 +}
2837 +
2838 +.dm-agents__face-pick {
2839 + display: grid;
2840 + place-items: center;
2841 + padding: 2px;
2842 + border: 1px solid transparent;
2843 + border-radius: 8px;
2844 + background: none;
2845 + cursor: pointer;
2846 +}
2847 +
2848 +.dm-agents__face-pick img {
2849 + width: 100%;
2850 + height: auto;
2851 + display: block;
2852 +}
2853 +
2854 +.dm-agents__face-pick:hover {
2855 + border-color: var( --os-ui-border-strong, #8c8f94 );
2856 +}
2857 +
2858 +.dm-agents__face-pick.is-picked {
2859 + border-color: var( --os-ui-accent, #2271b1 );
2860 +}
2861 +
2862 +.dm-agents__face-pick:focus-visible {
2863 + outline: var( --os-ui-focus-ring, 2px solid #2271b1 );
2864 + outline-offset: 1px;
2865 +}
2866 +
2867 +.dm-agents__meet-fields {
2868 + display: flex;
2869 + flex-direction: column;
2870 + gap: 10px;
2871 + min-width: 0;
2872 +}
2873 +
2874 +/* Launch: one card, the brand's card radius, floating on the darkest
2875 + surface like the portrait it echoes. */
2876 +.dm-agents__summary {
2877 + display: grid;
2878 + grid-template-columns: 106px 1fr;
2879 + gap: 18px;
2880 + align-items: start;
2881 + --os-ui-card-padding: 18px;
2882 + --os-ui-card-radius: 10px;
2883 + --os-ui-card-bg: var( --os-ui-surface-sunken, #f6f7f7 );
2884 +}
2885 +
2886 +.dm-agents__summary-face {
2887 + width: 106px;
2888 + height: 106px;
2889 + flex: none;
2890 +}
2891 +
2892 +.dm-agents__summary-text h4 {
2893 + margin: 0 0 2px;
2894 + font-size: 17px;
2895 +}
2896 +
2897 +.dm-agents__summary-vibes {
2898 + font-family: var( --os-ui-font-mono, ui-monospace, monospace );
2899 + font-size: 11.5px;
2900 + color: var( --os-ui-accent-strong, #2271b1 );
2901 + margin: 0 0 6px;
2902 +}
2903 +
2904 +.dm-agents__summary-desc {
2905 + margin: 0;
2906 + font-size: 13px;
2907 + color: var( --os-ui-fg-muted, #646970 );
2908 +}
2909 +
2910 +.dm-agents__chips {
2911 + display: flex;
2912 + flex-wrap: wrap;
2913 + gap: 6px;
2914 + margin-block-start: 10px;
2915 +}
2916 +
2917 +/* What the agent will actually be told, under the chips. Clamped: a
2918 + summary card quotes the instructions, it does not host them. */
2919 +.dm-agents__summary-instr {
2920 + margin: 10px 0 0;
2921 + font-size: 13px;
2922 + color: var( --os-ui-fg-muted, #646970 );
2923 + display: -webkit-box;
2924 + -webkit-line-clamp: 3;
2925 + -webkit-box-orient: vertical;
2926 + overflow: hidden;
2927 +}
2928 +
2929 +/* Identity chips — role, abilities, silhouette, hue — all wear the
2930 + instrument voice: these are facts about the character, stamped
2931 + rather than said. */
2932 +.dm-agents__chips os-chip,
2933 +.dm-agents__portrait-chips os-chip {
2934 + --os-ui-chip-font-size: 10.5px;
2935 + --os-ui-chip-font-weight: 500;
2936 + --os-ui-chip-bg: transparent;
2937 + --os-ui-chip-fg: var( --os-ui-fg-muted, #646970 );
2938 + --os-ui-chip-border: 1px solid var( --os-border, rgba( 0, 0, 0, 0.12 ) );
2939 + font-family: var( --os-ui-font-mono, ui-monospace, monospace );
2940 + text-transform: uppercase;
2941 + letter-spacing: 0.06em;
2942 +}
2943 +
2944 +.dm-agents__spacer {
2945 + flex: 1;
2946 +}
2947 +
2948 +@media ( max-width: 640px ) {
2949 + .dm-agents__meet,
2950 + .dm-agents__summary {
2951 + grid-template-columns: 1fr;
2952 + }
2953 + .dm-agents__portrait-face {
2954 + width: 128px;
2955 + height: 128px;
2956 + }
2957 +}
2958 +
2959 +/* The way back to the grid. The window's own breadcrumb goes UP to the
2960 + folder, which is a different journey: this one returns to the cast. */
2961 +.dm-agents__back {
2962 + align-self: flex-start;
2963 + margin-block-end: 4px;
2165 2964 }