# desktop-mode/1.1.10/apps/my-wordpress/my-wordpress.css

OpenStation: Desktop Windows, Dock &amp; Virtual Desktops for WP Admin, version 1.1.10. 2,001 lines.

- Page: https://pluginprobe.com/plugins/desktop-mode/1.1.10/code/apps/my-wordpress/my-wordpress.css
- Raw: https://pluginprobe.com/plugins/desktop-mode/1.1.10/raw/apps/my-wordpress/my-wordpress.css
- Modified: 2026-09-18T20:10:18+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/desktop-mode/1.1.10/code/apps/my-wordpress/my-wordpress.css#L10-L20`.

```css
/**
 * My WordPress — the content explorer app.
 *
 * Injected on the window's first open, after the runtime's own sheet.
 * Every colour resolves through the palette tokens with the pre-brand
 * literal as the floor, per the variables.css contract.
 */

.os-mywp {
	display: flex;
	flex-direction: column;
	block-size: 100%;
	font-family: var(
		--os-font,
		-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif
	);
	/* The SAME window-token family WP Explorer wears
	 * (`--os-my-wordpress-*`), so a desktop theme that repaints one
	 * explorer repaints both — with the palette chain underneath and
	 * the pre-brand literal as the floor. */
	color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
	background: var(
		--os-my-wordpress-bg,
		var( --os-window-bg, #fff )
	);
	/*
	 * Tile token re-scope — the same recipe as WP Explorer. The
	 * shared `.os-file-tile` is born on the WALLPAPER, where its
	 * label is white over a dark gradient; inside a window those
	 * defaults are invisible on a light surface. Re-pointing the
	 * `--os-tile-*` tokens here retones the one shared element for
	 * in-window reading, and keeps it on the theme chain.
	 */
	--os-tile-fg: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
	--os-tile-fg-muted: var(
		--os-my-wordpress-fg-muted,
		var( --os-ui-fg-muted, rgba( 0, 0, 0, 0.55 ) )
	);
	--os-tile-hover-bg: var( --os-hover, rgba( 0, 0, 0, 0.06 ) );
	--os-tile-label-shadow: none;
	--os-tile-label-weight: 500;
	--os-tile-label-smoothing: antialiased;
	--os-tile-label-color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
}

/* ------------------------------------------------------------ header */

.os-mywp__header {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 8px 12px;
	border-block-end: 1px solid var( --os-ui-border, #dcdcde );
	flex: 0 0 auto;
}

.os-mywp__back {
	flex: 0 0 auto;
	inline-size: 28px;
	block-size: 28px;
	display: grid;
	place-items: center;
	border: 0;
	border-radius: 6px;
	background: transparent;
	color: var( --os-ui-fg-muted, #646970 );
	font: inherit;
	font-size: 18px;
	line-height: 1;
	cursor: pointer;
}

.os-mywp__back:hover,
.os-mywp__back:focus-visible {
	/* The shared breadcrumb back-button hover chain
	 * (`.os-breadcrumbs__back` in desktop-files.css). */
	background: var( --os-hover, var( --os-ui-hover, rgba( 0, 0, 0, 0.06 ) ) );
	color: inherit;
}

.os-mywp__crumbs {
	display: flex;
	align-items: center;
	gap: 8px;
	min-inline-size: 0;
	flex: 1 1 auto;
	font-size: 13px;
}

.os-mywp__crumb-link {
	border: 0;
	padding: 0;
	background: transparent;
	font: inherit;
	/* WP Explorer's link chain: the palette's link colour first, the
	 * accent next, the pre-brand admin blue as the floor. */
	color: var( --os-link, var( --os-ui-accent, #2271b1 ) );
	cursor: pointer;
}

.os-mywp__crumb-link:hover,
.os-mywp__crumb-link:focus-visible {
	text-decoration: underline;
}

.os-mywp__crumb-current {
	font-weight: 600;
}

.os-mywp__sep {
	color: var( --os-ui-fg-muted, #646970 );
}

/* Search row — its own band under the header, WP Explorer style.
 * The view switch sits at its far end. */
.os-mywp__add-user {
	flex: 0 0 auto;
}

.os-mywp__search {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 10px 14px;
	flex: 0 0 auto;
	border-block-end: 1px solid var( --os-ui-border, #dcdcde );
}

.os-mywp__search os-text-field {
	inline-size: min( 360px, 100% );
	display: block;
	flex: 1 1 auto;
}

.os-mywp__view-switch {
	flex: 0 0 auto;
}

.os-mywp__view-switch .dashicons {
	font-size: 16px;
	inline-size: 16px;
	block-size: 16px;
	vertical-align: -3px;
}

/* Under ~560px the switch keeps its glyphs and drops the words. */
@container ( max-width: 560px ) {
	.os-mywp__view-label {
		display: none;
	}
}

/* -------------------------------------------------------------- body */

.os-mywp__body {
	flex: 1 1 auto;
	overflow: hidden;
	display: flex;
	flex-direction: column;
}

/* -------------------------------------------------------------- root */

/*
 * The group-extras seam's container — a plugin panel above a folder's
 * tiles (Woo's Store totals). The panel inside brings its own chrome;
 * this only gives it the folder grid's gutter, and only when a
 * subscriber actually painted something.
 */
.os-mywp__body > .os-my-wordpress__group-extras:not( :empty ) {
	padding: 16px 16px 0;
}

.os-mywp__root {
	display: grid;
	grid-template-columns: repeat( auto-fill, 116px );
	justify-content: start;
	gap: 8px;
	padding: 16px;
	overflow-y: auto;
	align-content: start;
}

.os-mywp__tile {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	padding: 14px 8px;
	border: 0;
	border-radius: 8px;
	background: transparent;
	color: inherit;
	font: inherit;
	cursor: pointer;
}

.os-mywp__tile:hover,
.os-mywp__tile:focus-visible {
	background: var( --os-tile-hover-bg, rgba( 0, 0, 0, 0.06 ) );
}

/* The CANONICAL selection pair every tile in the shell wears
 * (`.os-file-tile--selected` in desktop-files.css): the
 * `--os-tile-selected-bg` fill under an inset `--os-tile-focus-ring`
 * ring whose width the palette decides (0 on OpenStation's, 1px on
 * Legacy). The root folder tiles are plain buttons rather than
 * `<os-tile>`s, so they restate the same chains — reading
 * `--os-ui-accent` here painted the raw brand Pulse instead of the
 * theme's selection, which is exactly the divergence the shared
 * tokens exist to prevent. */
.os-mywp__tile.is-selected {
	background: var( --os-tile-selected-bg, rgba( 34, 113, 177, 0.14 ) );
	box-shadow: inset 0 0 0 var( --os-tile-selected-ring-width, 1px )
		var( --os-tile-focus-ring, var( --wp-admin-theme-color, #2271b1 ) );
}

/* The icon well matches WP Explorer's `.os-file-tile__icon` /
 * `__preview` pair (48px box, 32px glyph), so the two windows' root
 * grids — the Agents portrait included — read at the same size. */
.os-mywp__tile-icon.dashicons {
	inline-size: 48px;
	block-size: 48px;
	font-size: 32px;
	display: grid;
	place-items: center;
}

.os-mywp__icon-img {
	inline-size: 48px;
	block-size: 48px;
	object-fit: contain;
}

.os-mywp__tile-label {
	font-size: 12px;
	text-align: center;
	overflow-wrap: anywhere;
}

/* ------------------------------------------------------------- split */

.os-mywp__split {
	display: grid;
	/*
	 * WP Explorer's two-pane ratio: the list leads, the preview takes
	 * roughly the remaining 40% and grows with the window — but never
	 * below 430px while the window can afford it, because under that
	 * the pane's fact tables and the Woo merchant panels wrap every
	 * row. When the window truly can't (both floors exceed it), the
	 * list keeps its 240px and the pane takes what is left.
	 */
	grid-template-columns: minmax( 240px, 1fr ) minmax( min( 430px, calc( 100% - 240px ) ), 40% );
	flex: 1 1 auto;
	min-block-size: 0;
}

/* Nothing open, no pane: the list has the whole window until a
 * click needs the preview beside it (`splitView()` in
 * `parts/dossier-views.ts` leaves the aside out entirely). */
.os-mywp__split--solo {
	grid-template-columns: minmax( 0, 1fr );
}

.os-mywp__list-pane {
	min-inline-size: 0;
	/* Grid items default to min-size auto; without the 0 the row
	   grows with a tall list instead of letting the canvas scroll. */
	min-block-size: 0;
	display: flex;
	flex-direction: column;
}

.os-mywp__detail-pane {
	min-inline-size: 0;
	min-block-size: 0;
	border-inline-start: 1px solid var( --os-ui-border, #dcdcde );
	overflow-y: auto;
}

/*
 * A narrow window — a phone, or a desktop window pulled in under
 * the two floors above (240px list + 430px pane). The panes stack:
 * the list takes the window and the preview becomes a sheet along
 * the bottom, at most 45% tall and scrolling on its own. It is only
 * rendered while something is selected, so the list alone fills the
 * single row the rest of the time. The container is the app root
 * (`.os-app`, `app-runtime.css`).
 */
@container ( max-width: 640px ) {
	.os-mywp__split {
		grid-template-columns: minmax( 0, 1fr );
		grid-template-rows: minmax( 0, 1fr ) auto;
	}

	.os-mywp__detail-pane {
		border-inline-start: 0;
		border-block-start: 1px solid var( --os-ui-border, #dcdcde );
		max-block-size: 45%;
	}
}

/*
 * The phone's item page (`renderBody` in `my-wordpress.os.ts`): the
 * opened item takes the whole body, pushed over the list, with Back
 * in the header and the trail one step longer. The pane's own ✕ is
 * redundant beside Back and goes; the action row stacks so every
 * button is a full-width finger's target.
 */
.os-mywp__detail-page {
	flex: 1 1 auto;
	min-block-size: 0;
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
}

.os-mywp__detail-page .os-mywp__pane-close {
	display: none;
}

.os-mywp__detail-page .os-mywp__detail {
	padding: 16px 16px 24px;
}

.os-mywp__detail-page .os-mywp__actions {
	flex-direction: column;
	align-items: stretch;
	align-self: stretch;
}

.os-mywp__detail-page .os-mywp__actions os-button {
	inline-size: 100%;
}

/* -------------------------------------------------- quick-edit modal */

.os-mywp__qe {
	display: flex;
	flex-direction: column;
	gap: 12px;
	min-inline-size: 240px;
}

.os-mywp__qe-row {
	display: flex;
	flex-direction: column;
	gap: 4px;
	font-size: 12px;
}

/* The hint above the fields — the same info notice the original's
 * bulk modal leads with. Ink contrast on the dark dialog is owned by
 * os-modal itself (it re-points --os-ui-notice-color through
 * --os-ui-modal-text); this rule is spacing only. */
.os-mywp__qe-notice {
	margin-block-end: 12px;
}

.os-mywp__cell.is-disabled {
	opacity: 0.5;
}

/* --------------------------------------------------------- tile grid */

/*
 * The same tile element the wallpaper and WP Explorer paint
 * (`os-tile` → `.os-file-tile`), flowed as a grid: in-window lists
 * are not a free canvas here, so the wallpaper's absolute
 * positioning is switched off and the grid owns the layout.
 */
/* Fixed pitch, like the original canvas: resizing the window changes
 * how many tiles fit per row, never how wide a tile is. */
.os-mywp__tiles {
	display: grid;
	grid-template-columns: repeat( auto-fill, 104px );
	justify-content: start;
	gap: 10px 4px;
	align-content: start;
	padding: 12px;
	overflow-y: auto;
	flex: 1 1 auto;
}

.os-mywp__cell {
	display: flex;
	justify-content: center;
}

/*
 * `relative`, not `static`: the tile must join normal flow (the grid
 * owns layout here, not the wallpaper's absolute canvas) but it must
 * REMAIN the containing block of its own `<os-ribbon>` — flattened to
 * static, the DRAFT ribbon anchors to the grid cell and floats off
 * the tile's corner.
 */
.os-mywp__cell os-tile,
.os-mywp__cell .os-file-tile {
	position: relative;
	inset: auto;
}

.os-mywp__tilebox {
	position: relative;
	display: inline-flex;
}

.os-mywp__cell.is-open .os-file-tile {
	outline: 1px solid
		var( --os-tile-focus-ring, var( --wp-admin-theme-color, #2271b1 ) );
	outline-offset: -1px;
	border-radius: 8px;
}

.os-mywp__lock {
	position: absolute;
	inset-block-start: 2px;
	inset-inline-start: 2px;
	font-size: 12px;
	pointer-events: none;
}

/* Skeletons for the page being fetched — WP Explorer's loading
 * placeholders: same cell footprint, shimmering blocks. */
.os-mywp__cell--ghost {
	pointer-events: none;
}

.os-mywp__ghost {
	inline-size: var( --os-tile-w, 88px );
	padding: 8px 4px;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 6px;
}

/* The shell's skeleton fill chain (`--os-skeleton-*`, see WP
 * Explorer's loading placeholders), so the ghosts follow the theme
 * instead of guessing at a raised surface. */
.os-mywp__ghost-visual {
	inline-size: 48px;
	block-size: 48px;
	border-radius: 8px;
	background: var( --os-skeleton-high, var( --os-ui-hover, rgba( 0, 0, 0, 0.08 ) ) );
	animation: os-mywp-shimmer 1.2s ease-in-out infinite;
}

.os-mywp__ghost-label {
	inline-size: 64px;
	block-size: 10px;
	border-radius: 5px;
	background: var( --os-skeleton-high, var( --os-ui-hover, rgba( 0, 0, 0, 0.08 ) ) );
	animation: os-mywp-shimmer 1.2s ease-in-out infinite;
	animation-delay: 0.15s;
}

@keyframes os-mywp-shimmer {
	0%, 100% { opacity: 0.45; }
	50% { opacity: 1; }
}

@media ( prefers-reduced-motion: reduce ) {
	.os-mywp__ghost-visual,
	.os-mywp__ghost-label {
		animation: none;
	}
}

/* --------------------------------------------------------- list view */

/*
 * The table: the same rows as the tile canvas, in columns. The
 * wrapper is the scrolling canvas (both axes — a narrow window scrolls
 * the columns sideways rather than crushing them), the header sticks,
 * and every colour resolves through the same chains the tiles read so
 * a desktop theme repaints both views at once.
 */
.os-mywp__table-wrap {
	flex: 1 1 auto;
	min-block-size: 0;
	overflow: auto;
	position: relative;
}

/*
 * Auto layout with ONE stretching column: every other column is
 * declared 1px wide, which in an auto table means "as wide as your
 * (nowrap) content"; the title column takes what is left. Its
 * `max-inline-size: 0` is what lets the ellipsis work — an auto
 * layout would otherwise size the column to its longest title. No
 * percentage widths and no `max-content` minimum on the table: a
 * 100% column against a max-content floor resolves to an unbounded
 * width and the wrapper scrolls forever.
 */
.os-mywp__table {
	inline-size: 100%;
	border-collapse: separate;
	border-spacing: 0;
	font-size: 13px;
	table-layout: auto;
}

.os-mywp__th:not( .os-mywp__th--title ),
.os-mywp__td:not( .os-mywp__td--title ) {
	inline-size: 1px;
}

.os-mywp__th--title,
.os-mywp__td--title {
	inline-size: 100%;
	max-inline-size: 0;
	min-inline-size: 160px;
}

.os-mywp__th {
	position: sticky;
	inset-block-start: 0;
	z-index: 2;
	padding: 0 10px;
	block-size: 32px;
	text-align: start;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	white-space: nowrap;
	color: var( --os-ui-fg-muted, #646970 );
	/* The band-head recipe: near-opaque frost, so rows scrolling under
	 * the header stay behind it. */
	background: color-mix( in srgb, var( --os-ui-bg, #fff ) 94%, transparent );
	backdrop-filter: blur( 14px ) saturate( 180% );
	border-block-end: 1px solid var( --os-ui-border, #dcdcde );
}

@supports not ( background: color-mix( in srgb, red 50%, transparent ) ) {
	.os-mywp__th {
		background: var( --os-ui-bg, #fff );
	}
}

.os-mywp__th--end,
.os-mywp__td--end {
	text-align: end;
}

.os-mywp__th,
.os-mywp__td {
	vertical-align: middle;
}

/* The column-chooser button sits on the header's centre line, not on
 * its baseline. */
.os-mywp__th--actions {
	inline-size: 1px;
	line-height: 0;
}

.os-mywp__columns-btn {
	vertical-align: middle;
}

/* A sortable heading is a button wearing the heading's costume. */
.os-mywp__sort {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	margin: 0;
	padding: 0;
	border: 0;
	background: transparent;
	color: inherit;
	font: inherit;
	letter-spacing: inherit;
	text-transform: inherit;
	cursor: pointer;
}

.os-mywp__sort:hover,
.os-mywp__sort:focus-visible,
.os-mywp__sort.is-active {
	color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
}

.os-mywp__sort-arrow {
	font-size: 8px;
	min-inline-size: 8px;
}

.os-mywp__row {
	cursor: default;
}

.os-mywp__td {
	padding: 0 10px;
	block-size: 36px;
	vertical-align: middle;
	white-space: nowrap;
	max-inline-size: 320px;
	overflow: hidden;
	text-overflow: ellipsis;
	border-block-end: 1px solid
		var( --os-ui-border-subtle, var( --os-ui-border, rgba( 0, 0, 0, 0.06 ) ) );
}

.os-mywp__td--mono,
.os-mywp__cell-id {
	font-family: var( --os-ui-font-mono, ui-monospace, monospace );
	font-variant-numeric: tabular-nums;
	font-size: 12px;
}

/* Hover, selection and the open row read the tile canvas's tokens —
 * one selection colour in the whole window, whichever view. */
.os-mywp__row:hover .os-mywp__td {
	background: var( --os-tile-hover-bg, rgba( 0, 0, 0, 0.06 ) );
}

.os-mywp__row.is-selected .os-mywp__td {
	background: var( --os-tile-selected-bg, rgba( 34, 113, 177, 0.14 ) );
}

.os-mywp__row.is-open .os-mywp__td {
	box-shadow: inset 0 -1px 0 var( --os-tile-focus-ring, var( --wp-admin-theme-color, #2271b1 ) ),
		inset 0 1px 0 var( --os-tile-focus-ring, var( --wp-admin-theme-color, #2271b1 ) );
}

.os-mywp__row:focus-visible {
	outline: none;
}

.os-mywp__row:focus-visible .os-mywp__td {
	box-shadow: inset 0 0 0 1px var( --os-tile-focus-ring, var( --wp-admin-theme-color, #2271b1 ) );
}

/* The id copies itself; it looks like a chip so the affordance reads. */
.os-mywp__cell-id--copy {
	margin: 0;
	padding: 2px 6px;
	border: 0;
	border-radius: 4px;
	background: var( --os-ui-surface-raised, rgba( 0, 0, 0, 0.04 ) );
	color: var( --os-my-wordpress-fg-muted, var( --os-ui-fg-muted, #646970 ) );
	cursor: copy;
}

.os-mywp__cell-id--copy:hover,
.os-mywp__cell-id--copy:focus-visible {
	background: var( --os-hover, var( --os-ui-hover, rgba( 0, 0, 0, 0.08 ) ) );
	color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
}

.os-mywp__cell-title {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-inline-size: 0;
	max-inline-size: 100%;
}

.os-mywp__cell-text {
	overflow: hidden;
	text-overflow: ellipsis;
	font-weight: 500;
}

.os-mywp__cell-thumb {
	inline-size: 24px;
	block-size: 24px;
	border-radius: 4px;
	object-fit: cover;
	flex: 0 0 auto;
	background: var( --os-ui-surface-raised, rgba( 0, 0, 0, 0.04 ) );
}

.os-mywp__cell-glyph.dashicons {
	inline-size: 24px;
	block-size: 24px;
	font-size: 18px;
	display: grid;
	place-items: center;
	color: var( --os-ui-fg-muted, #646970 );
	flex: 0 0 auto;
}

.os-mywp__cell-glyph.os-mywp__icon-mask {
	inline-size: 20px;
	block-size: 20px;
}

.os-mywp__cell-badge {
	flex: 0 0 auto;
}

.os-mywp__cell-lock {
	font-size: 14px;
	inline-size: 14px;
	block-size: 14px;
	color: var( --os-ui-fg-muted, #646970 );
}

.os-mywp__cell-muted {
	color: var( --os-ui-fg-muted, #646970 );
}

.os-mywp__cell-parent .os-mywp__cell-id {
	color: var( --os-ui-fg-muted, #646970 );
}

/* The action cluster: icon-only ghost buttons, visible on hover, on
 * the selected row, and whenever one of them holds focus. */
.os-mywp__row-actions {
	display: inline-flex;
	gap: 2px;
	opacity: 0;
	transition: opacity 120ms ease;
}

.os-mywp__row:hover .os-mywp__row-actions,
.os-mywp__row.is-selected .os-mywp__row-actions,
.os-mywp__row.is-open .os-mywp__row-actions,
.os-mywp__row-actions:focus-within {
	opacity: 1;
}

@media ( prefers-reduced-motion: reduce ) {
	.os-mywp__row-actions {
		transition: none;
	}
}

.os-mywp__row-action {
	--os-ui-button-padding: 3px;
	--os-ui-button-border-radius: 4px;
	line-height: 0;
}

.os-mywp__row-action .dashicons {
	font-size: 16px;
	inline-size: 16px;
	block-size: 16px;
}

.os-mywp__columns-btn {
	opacity: 1;
}

/* Skeleton rows for the page being fetched — the tile ghosts' fill. */
.os-mywp__row--ghost td {
	padding: 10px;
	border-block-end: 1px solid
		var( --os-ui-border-subtle, var( --os-ui-border, rgba( 0, 0, 0, 0.06 ) ) );
}

.os-mywp__ghost-line {
	display: block;
	block-size: 12px;
	inline-size: min( 60%, 420px );
	border-radius: 6px;
	background: var( --os-skeleton-high, var( --os-ui-hover, rgba( 0, 0, 0, 0.08 ) ) );
	animation: os-mywp-shimmer 1.2s ease-in-out infinite;
}

@media ( prefers-reduced-motion: reduce ) {
	.os-mywp__ghost-line {
		animation: none;
	}
}

.os-mywp__table-empty {
	margin: 0;
	padding: 32px 16px;
	text-align: center;
	color: var( --os-ui-fg-muted, #646970 );
}

/* ------------------------------------------------------- list bands */

/* Banded layout — the `os.my-wordpress.list-bands` filter's canvas.
 * The scroller becomes a column of band sections, each with its own
 * grid at the same pitch as the flat canvas; headings mirror WP
 * Explorer's band bars (sticky, frosted, tone-tintable). */

.os-mywp__tiles--banded {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.os-mywp__band + .os-mywp__band {
	margin-block-start: 8px;
}

.os-mywp__band-head {
	display: flex;
	align-items: center;
	gap: 8px;
	position: sticky;
	/* Keeps the band label visible while scrolling a long band —
	 * the whole point of banding is knowing what you're looking at. */
	inset-block-start: 0;
	z-index: 3;
	margin: 0;
	padding: 6px 12px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var( --os-ui-fg-muted, #787c82 );
	/* Near-opaque frosted bar, WP Explorer's recipe: at 94% the tiles
	 * scrolling beneath stay behind the bar instead of resolving into
	 * ghostly shapes through it. */
	background: color-mix(
		in srgb,
		var( --os-ui-bg, #fff ) 94%,
		transparent
	);
	backdrop-filter: blur( 14px ) saturate( 180% );
	border-block-end: 1px solid var( --os-ui-border, rgba( 0, 0, 0, 0.08 ) );
}

@supports not ( background: color-mix( in srgb, red 50%, transparent ) ) {
	.os-mywp__band-head {
		background: var( --os-ui-bg, #fff );
	}
}

/* Attention-carrying bands tint their bar so the eye lands there
 * first instead of having to read every heading. */
.os-mywp__band-head--warn {
	color: var( --os-ui-warning, #8a6116 );
	background: color-mix(
		in srgb,
		var( --os-ui-warning, #8a6116 ) 12%,
		var( --os-ui-bg, #fff )
	);
	border-block-end-color: color-mix(
		in srgb,
		var( --os-ui-warning, #8a6116 ) 35%,
		transparent
	);
}

.os-mywp__band-head--danger {
	color: var( --os-ui-danger, #b32d2e );
	background: color-mix(
		in srgb,
		var( --os-ui-danger, #b32d2e ) 12%,
		var( --os-ui-bg, #fff )
	);
	border-block-end-color: color-mix(
		in srgb,
		var( --os-ui-danger, #b32d2e ) 35%,
		transparent
	);
}

.os-mywp__band-count {
	padding: 0 6px;
	border-radius: 999px;
	font-size: 11px;
	line-height: 1.7;
	background: color-mix( in srgb, currentColor 16%, transparent );
	color: inherit;
}

.os-mywp__band-grid {
	display: grid;
	grid-template-columns: repeat( auto-fill, 104px );
	justify-content: start;
	gap: 10px 4px;
	align-content: start;
	padding: 12px;
}

/* ------------------------------------------------------------ detail */

.os-mywp__detail {
	position: relative;
	padding: 16px;
	display: flex;
	flex-direction: column;
	gap: 12px;
	align-items: flex-start;
}

.os-mywp__pane-close {
	position: absolute;
	inset-block-start: 8px;
	inset-inline-end: 8px;
}

/* Plugin slots on the article (`os.my-wordpress.preview-extras`).
 * The article is a gap-spaced column, so a slot nobody painted into
 * must not spend a gap step. Scoped to OUR pane — WP Explorer's own
 * slots keep their stylesheet's rules. */
.os-mywp__detail .os-my-wordpress__article-slot {
	align-self: stretch;
}

.os-mywp__detail .os-my-wordpress__article-slot:empty {
	display: none;
}

.os-mywp__hero {
	max-inline-size: 100%;
	max-block-size: 200px;
	border-radius: 8px;
	object-fit: contain;
}

.os-mywp__detail-title {
	margin: 0;
	font-size: 17px;
	padding-inline-end: 32px;
}

/* The identity line under a person's name: role badge + archive link. */
.os-mywp__user-meta {
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 0;
}

.os-mywp__facts {
	display: grid;
	grid-template-columns: max-content 1fr;
	gap: 6px 14px;
	margin: 0;
	font-size: 13px;
}

.os-mywp__fact {
	display: contents;
}

.os-mywp__fact dt {
	color: var( --os-ui-fg-muted, #646970 );
}

.os-mywp__fact dd {
	margin: 0;
}

.os-mywp__pane-h {
	margin: 4px 0 0;
	font-size: 12px;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var( --os-ui-fg-muted, #646970 );
}

.os-mywp__used-in {
	margin: 0;
	padding-inline-start: 18px;
	font-size: 13px;
}

.os-mywp__actions {
	display: flex;
	gap: 8px;
	flex-wrap: wrap;
}

.os-mywp__content {
	max-inline-size: 100%;
	overflow-wrap: anywhere;
	font-size: 13px;
}

.os-mywp__content img {
	max-inline-size: 100%;
	block-size: auto;
}

.os-mywp__hero.is-zoomable {
	cursor: zoom-in;
}

.os-mywp__sentinel {
	block-size: 1px;
}

/* The hover card (.os-my-wordpress__tooltip and friends) is painted
 * by the SHARED explorer stylesheet, which rides this window as a
 * companion style (includes/my-wordpress/assets.php) — one set of
 * rules for both explorers' cards, not a copy here. */

/* ---------------------------------------------------- marquee + menu */

/* The SAME token pair the shell's rubber band wears
 * (desktop-files.css): a ring on the admin scheme colour over the
 * shared marquee wash — a WASH, so you can see what it is about to
 * catch. */
.os-mywp__marquee {
	position: fixed;
	z-index: 100000;
	border: 1px solid
		var( --os-tile-focus-ring, var( --wp-admin-theme-color, #2271b1 ) );
	border-radius: 2px;
	background: var(
		--os-selection-marquee-bg,
		var( --os-ui-accent-soft, rgba( 34, 113, 177, 0.14 ) )
	);
	pointer-events: none;
}

.os-mywp__menu-backdrop {
	position: fixed;
	inset: 0;
	z-index: 99998;
}

.os-mywp__menu {
	z-index: 99999;
}

/* -------------------------------------------------------------- zoom */

.os-mywp__zoom {
	position: fixed;
	inset: 0;
	z-index: 100000;
	display: grid;
	place-items: center;
	background: rgba( 0, 0, 0, 0.8 );
	cursor: zoom-out;
}

.os-mywp__zoom img {
	max-inline-size: 92vw;
	max-block-size: 92vh;
	object-fit: contain;
}

/* -------------------------------------------- sub-list stats panes */

.os-mywp__icon-mask {
	inline-size: 48px;
	block-size: 48px;
	display: inline-block;
	background: currentColor;
	-webkit-mask: var( --mywp-icon ) center / contain no-repeat;
	mask: var( --mywp-icon ) center / contain no-repeat;
}

.os-mywp__term-head {
	display: flex;
	align-items: flex-start;
	gap: 12px;
}

.os-mywp__term-head div {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 4px;
}

/* WP Explorer's taxonomy medallion, tokens and shadow included
 * (`.os-my-wordpress__term-icon--category`). */
.os-mywp__term-swatch {
	inline-size: 48px;
	block-size: 48px;
	border-radius: 12px;
	background: linear-gradient(
		135deg,
		var( --os-ui-accent, #2271b1 ) 0%,
		var( --os-ui-accent-strong, #135e96 ) 100%
	);
	box-shadow: 0 4px 12px rgba( 34, 113, 177, 0.32 );
	flex: 0 0 auto;
}

.os-mywp__stats {
	display: grid;
	grid-template-columns: repeat( auto-fill, minmax( 110px, 1fr ) );
	gap: 8px;
	inline-size: 100%;
}

/* The stat tiles are the kit's <os-stat>, on its defaults — the
   accent-coloured value is the same --wp-admin-theme-color chain WP
   Explorer's stat values read, declared in the component. */

.os-mywp__activity {
	display: flex;
	align-items: flex-end;
	gap: 4px;
	block-size: 72px;
	inline-size: 100%;
}

.os-mywp__activity-col {
	flex: 1 1 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: flex-end;
	block-size: 100%;
	gap: 2px;
	min-inline-size: 0;
}

.os-mywp__activity-bar {
	inline-size: 100%;
	min-block-size: 1px;
	border-radius: 3px 3px 0 0;
	/* WP Explorer's sparkline gradient, verbatim. */
	background: linear-gradient(
		180deg,
		var( --wp-admin-theme-color, #2271b1 ) 0%,
		rgba( 34, 113, 177, 0.55 ) 100%
	);
}

.os-mywp__activity-label {
	font-size: 9px;
	color: var( --os-ui-fg-muted, #646970 );
}

.os-mywp__recent {
	display: flex;
	flex-direction: column;
	gap: 4px;
	inline-size: 100%;
}

.os-mywp__recent-row {
	display: flex;
	flex-direction: column;
	gap: 2px;
	padding: 8px 10px;
	border: 0;
	border-radius: 6px;
	background: var( --os-ui-surface-raised, rgba( 0, 0, 0, 0.04 ) );
	color: inherit;
	font: inherit;
	text-align: start;
	cursor: pointer;
}

.os-mywp__recent-row:hover,
.os-mywp__recent-row:focus-visible {
	background: var( --os-hover, var( --os-ui-hover, rgba( 0, 0, 0, 0.06 ) ) );
}

.os-mywp__recent-title {
	font-weight: 600;
	color: var( --os-link, var( --os-ui-accent, #2271b1 ) );
}

.os-mywp__people {
	display: flex;
	flex-direction: column;
	gap: 6px;
	inline-size: 100%;
}

.os-mywp__person {
	display: flex;
	align-items: center;
	gap: 8px;
}

.os-mywp__person-name {
	font-weight: 600;
	flex: 1 1 auto;
	min-inline-size: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.os-mywp__chips {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}

.os-mywp__chip {
	border: 1px solid var( --os-ui-border, #dcdcde );
	border-radius: 999px;
	padding: 3px 10px;
	background: transparent;
	color: inherit;
	font: inherit;
	font-size: 12px;
	cursor: pointer;
}

.os-mywp__chip:hover,
.os-mywp__chip:focus-visible {
	background: var( --os-hover, var( --os-ui-hover, rgba( 0, 0, 0, 0.06 ) ) );
}

/* The user dossier's top-terms chips are facts, not doors — no hover. */
.os-mywp__chip--static:hover {
	background: transparent;
	cursor: default;
}

/* ------------------------------------------------------------ status */

.os-mywp__status {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 4px 12px;
	font-size: 11px;
	color: var( --os-ui-fg-muted, #646970 );
	border-block-start: 1px solid var( --os-ui-border, #dcdcde );
	flex: 0 0 auto;
}

/* ------------------------------------------------------------------ */
/* Agents section — WP Explorer's `dm-agents` design, ported 1:1      */
/* (assets/css/my-wordpress.css is the original; same class names,    */
/* same tokens, so a desktop theme that repaints one repaints both).  */
/* ------------------------------------------------------------------ */

.dm-agents {
	display: flex;
	flex-direction: column;
	height: 100%;
	min-height: 0;
	padding: 12px;
	gap: 10px;
	overflow: hidden;
	box-sizing: border-box;
}

.dm-agents__detail {
	flex: 1;
	min-width: 0;
	overflow-y: auto;
	display: flex;
	flex-direction: column;
	gap: 10px;
}

/* `<os-empty-state>` owns the icon + copy and centres them within
   itself; the host is still a flex item that shrinks to its content,
   so without this it sits at the top of a pane that is mostly empty
   space. Auto margins on both axes absorb the slack — placement only,
   same as the comments window. Covers the framework-off state and
   "No agents yet" alike. */
.dm-agents__detail > os-empty-state {
	margin: auto;
}

.dm-agents__detail-head {
	display: flex;
	align-items: center;
	gap: 10px;
}

.dm-agents__detail-avatar {
	width: 48px;
	height: 48px;
	border-radius: 50%;
	/* Placeholder behind the avatar image while it loads — follows the
	   palette so it isn't a white disc on a dark station. */
	background: var( --os-ui-surface-elevated, #fff );
	flex: none;
}

.dm-agents__detail-title {
	flex: 1;
	min-width: 0;
}

.dm-agents__detail-title h3 {
	margin: 0;
	font-size: 16px;
}

.dm-agents__detail-slug {
	font-size: 12px;
	opacity: 0.6;
}

/* Verbs get their own row under the identity block: the set grows
   (profile, contributions, desktop, chat, delete) and squeezing them
   beside the name truncated it first. */
.dm-agents__detail-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

/* The pane strip is the kit's own <os-tabs>; nothing to restyle. */

.dm-agents__pane {
	display: flex;
	flex-direction: column;
	gap: 10px;
	padding-bottom: 12px;
}

.dm-agents__hint {
	margin: 0;
	font-size: 12px;
	opacity: 0.7;
}

/* Role first: least privilege is the decision, so the control holds
   the mockup's width instead of stretching into a landing strip. */
.dm-agents__role-select {
	max-width: 280px;
}

/* The ability filter. Sized like the role select rather than the
   full pane: it sits above a list of rules, and a search box as wide
   as the rules reads as another one of them. */
.dm-agents__ability-search {
	display: block;
	max-width: 320px;
	margin: 12px 0 4px;
}

/* Each category is a native disclosure. `<details>` because the
   behaviour is exactly what it is for: keyboard, screen-reader
   semantics and the open/closed state all arrive for free, and the
   only thing left to write is the costume. */
.dm-agents__ability-group {
	border-bottom: 1px solid var( --os-border, rgba( 0, 0, 0, 0.08 ) );
}

.dm-agents__ability-group:last-of-type {
	border-bottom: 0;
}

.dm-agents__category {
	margin: 18px 0 2px;
	font-family: var( --os-ui-font-mono, ui-monospace, monospace );
	font-size: 11px;
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var( --os-ui-fg-muted, #646970 );
}

/* A `<summary>` is a button, so it gets a button's affordances: a
   pointer, a hover, and a focus ring that is visible on the dark
   surface the section is drawn on. */
summary.dm-agents__category {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0;
	padding: 10px 0;
	cursor: pointer;
	list-style: none;
	user-select: none;
}

summary.dm-agents__category::-webkit-details-marker {
	display: none;
}

/* The marker is drawn here rather than left to the UA so it can be
   the same triangle in every browser and turn with the disclosure.
   Rotation only: a transform, so opening a group of forty rows
   costs no layout. */
summary.dm-agents__category::before {
	content: '';
	flex: none;
	width: 0;
	height: 0;
	border-inline-start: 5px solid currentcolor;
	border-block: 4px solid transparent;
	transition: transform 120ms ease;
}

.dm-agents__ability-group[ open ] > summary.dm-agents__category::before {
	transform: rotate( 90deg );
}

@media ( prefers-reduced-motion: reduce ) {
	summary.dm-agents__category::before {
		transition: none;
	}
}

summary.dm-agents__category:hover {
	color: var( --os-ui-fg, #1e1e1e );
}

summary.dm-agents__category:focus-visible {
	outline: 2px solid var( --os-ui-accent, #3858e9 );
	outline-offset: 2px;
	border-radius: 4px;
}

.dm-agents__category-name {
	flex: 1 1 auto;
}

/* "3 of 12" when some are ticked, otherwise just the size of the
   group. The count is why a closed group is still informative:
   collapsing must not hide the fact that something in there is
   switched on. */
.dm-agents__category-count {
	flex: none;
	font-variant-numeric: tabular-nums;
	opacity: 0.75;
}

/* One ability per row, ruled like the mockup: tick and name on the
   left, badge on the right, the description indented under the name
   (the checkbox column is the control's own 26px). */
.dm-agents__ability {
	display: grid;
	grid-template-columns: 1fr auto;
	gap: 2px 10px;
	align-items: start;
	padding: 11px 0;
	border-bottom: 1px solid var( --os-border, rgba( 0, 0, 0, 0.08 ) );
}

.dm-agents__ability:last-of-type {
	border-bottom: 0;
}

.dm-agents__ability-desc {
	grid-column: 1 / -1;
	margin: 0;
	padding-inline-start: 26px;
	font-size: 12.5px;
	color: var( --os-ui-fg-muted, #646970 );
}

/* Access badges in the instrument voice. The palette's own warning
   tokens carry the pale-yellow "can modify"; all this changes is the
   costume: mono, uppercase, an outline instead of a wash. */
.dm-agents__ability os-badge {
	--os-ui-badge-font: 500 10px/1.6 var( --os-ui-font-mono, ui-monospace, monospace );
	--os-ui-badge-dot-size: 0;
	--os-ui-badge-gap: 0;
	--os-ui-badge-padding: 3px 8px;
	--os-ui-badge-bg: transparent;
	--os-ui-badge-border: 1px solid var( --os-border, rgba( 0, 0, 0, 0.12 ) );
	text-transform: uppercase;
	letter-spacing: 0.06em;
	white-space: nowrap;
	margin-top: 2px;
}

.dm-agents__ability os-badge[ tone='warning' ] {
	--os-ui-badge-border: 1px solid
		var( --os-ui-warning-border, rgba( 154, 103, 0, 0.4 ) );
}

.dm-agents__trigger {
	border: 1px solid var( --os-border, rgba( 0, 0, 0, 0.08 ) );
	border-radius: 8px;
	padding: 8px 10px;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.dm-agents__trigger-head {
	display: flex;
	align-items: center;
	gap: 8px;
}

.dm-agents__trigger-desc {
	margin: 0;
	font-size: 12px;
	opacity: 0.75;
}

.dm-agents__trigger-config {
	display: flex;
	flex-wrap: wrap;
	gap: 4px 14px;
}

.dm-agents__actions {
	display: flex;
	gap: 8px;
	align-items: center;
	flex-wrap: wrap;
	margin-block-start: 12px;
}

/* ---------------------------------------------------------------------
   The cast
   ------------------------------------------------------------------ */

/* One view at a time: the grid, an agent, or the wizard. A sidebar of
   faces next to a detail form would leave neither enough room, and the
   whole point of the grid is that the faces are big enough to tell
   apart. */
.dm-agents__view {
	display: flex;
	flex-direction: column;
	flex: 1;
	min-height: 0;
	overflow-y: auto;
	gap: 12px;
}

.dm-agents__cast-head {
	display: flex;
	align-items: baseline;
	gap: 8px;
}

.dm-agents__cast-head h3 {
	margin: 0;
}

.dm-agents__cast-count {
	font-family: var( --os-ui-font-mono, ui-monospace, monospace );
	font-size: 12px;
	color: var( --os-ui-fg-muted, #646970 );
}

.dm-agents__cast {
	display: grid;
	gap: 16px;
	grid-template-columns: repeat( auto-fill, minmax( 288px, 1fr ) );
	align-content: start;
}

/* The card reacts like the mockup's: a lift and a brighter edge.
   Transform and border-color only — both cheap, and the same pair the
   mockup transitions. Document styles win over the component's own
   :host rules, which is the sanctioned way to restyle a host. */
.dm-agents__cast-card,
.dm-agents__cast-new {
	--os-ui-card-padding: 20px 18px 16px;
	transition: border-color 0.18s ease, transform 0.18s ease;
}

.dm-agents__cast-card:hover,
.dm-agents__cast-card:focus-within {
	border-color: var( --os-ui-border-strong, #8c8f94 );
	transform: translateY( -2px );
}

/* The dashed door, same as the mockup's crew-new card. */
.dm-agents__cast-new {
	border-style: dashed;
	--os-ui-card-bg: var( --os-ui-surface-subtle, transparent );
}

/* The crew breathes. Transform only, staggered so five faces do not
   bob in lockstep, and gone entirely under reduced motion. */
@media ( prefers-reduced-motion: no-preference ) {
	.dm-agents__cast-card .dm-agents__cast-face {
		animation: dm-agents-bob 6s ease-in-out infinite;
	}
	.dm-agents__cast-card:nth-child( 2n ) .dm-agents__cast-face {
		animation-duration: 7.2s;
		animation-delay: -1.4s;
	}
	.dm-agents__cast-card:nth-child( 3n ) .dm-agents__cast-face {
		animation-duration: 6.6s;
		animation-delay: -2.8s;
	}
}

@keyframes dm-agents-bob {
	0%,
	100% {
		transform: translateY( 0 );
	}
	50% {
		transform: translateY( -4px );
	}
}

/* The column lives on a wrapper we own, not on the host: the slotted
   children sit inside the card's own container, so a flex rule on the
   host never reaches them and the role badges land wherever the
   description's line count leaves them. */
.dm-agents__cast-inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 2px;
	height: 100%;
}

/* The faces are the loud part of this surface, and deliberately so:
   agent identity is the one place the station spends the mesh budget
   on something other than a hero CTA. A cast has to be legible at a
   glance, which is exactly what a flat accent cannot do. */
.dm-agents__cast-face {
	width: 118px;
	height: 118px;
	margin: -10px 0 6px;
	flex: none;
}

.dm-agents__cast-name {
	font-size: 17px;
	font-weight: 600;
	color: var( --os-ui-fg, #1d2327 );
}

/* The voice line, in the instrument register: this is metadata about
   the agent, not prose from it. */
.dm-agents__cast-vibes {
	font-family: var( --os-ui-font-mono, ui-monospace, monospace );
	font-size: 11.5px;
	color: var( --os-ui-accent-strong, #2271b1 );
}

.dm-agents__cast-good {
	font-size: 13px;
	color: var( --os-ui-fg-muted, #646970 );
	margin-block: 4px 14px;
	flex: 1;
}

/* The role pill in the instrument voice: mono, uppercase, no status
   dot — this is a fact about the agent, not a state to monitor. The
   custom properties are the component's own theming hooks; the
   inherited text properties flow into its shadow label. */
.dm-agents__cast-card os-badge {
	--os-ui-badge-font: 500 11px/1.6 var( --os-ui-font-mono, ui-monospace, monospace );
	--os-ui-badge-dot-size: 0;
	--os-ui-badge-gap: 0;
	--os-ui-badge-padding: 3px 10px;
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

/* The framework-off bar: the section's status and its one action, on
   one line above the crew it would hire. It is deliberately not an
   `os-empty-state` — that block is centred, icon-led and paragraph-
   shaped, which is exactly the wall of text the cast replaced, and at
   five cards tall it would push the button that undoes the situation
   off the bottom of the window. `flex: none` because `.dm-agents__view`
   is a scrolling flex column and the bar must not absorb the slack. */
.dm-agents__off-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	flex: none;
	gap: 8px 16px;
	padding: 12px 14px;
	border-radius: 10px;
	background: var( --os-ui-surface-elevated, #fff );
	border: 1px solid var( --os-border, rgba( 0, 0, 0, 0.08 ) );
}

.dm-agents__off-copy {
	min-width: 0;
}

.dm-agents__off-copy h3 {
	margin: 0;
}

.dm-agents__off-copy p {
	margin: 2px 0 0;
	font-size: 13px;
	color: var( --os-ui-fg-muted, #646970 );
}

/* The cast the site would get, drawn while the framework is off.
   Dimmed as a whole rather than desaturated: the five hues ARE the
   argument this state is making, and a greyscale filter would flatten
   the crew into five identical blobs on the way to saying "not yet".
   Opacity says inactive and leaves the faces telling each other apart.

   `pointer-events` is belt and braces — the cards are rendered without
   `interactive` and without a click handler, so there is nothing to
   press. It exists so a hover state cannot promise otherwise. */
.dm-agents__cast--preview {
	opacity: 0.6;
	pointer-events: none;
}

.dm-agents__cast-new .dm-agents__cast-plus {
	display: grid;
	place-items: center;
	width: 118px;
	height: 118px;
	margin: -10px 0 6px;
	border-radius: 50%;
	border: 1.5px dashed var( --os-ui-border-strong, #8c8f94 );
	font-size: 30px;
	font-weight: 300;
	line-height: 1;
	color: var( --os-ui-fg-muted, #646970 );
}

/* ---------------------------------------------------------------------
   The wizard
   ------------------------------------------------------------------ */

.dm-agents__wizard {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.dm-agents__wiz-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px 12px;
	flex-wrap: wrap;
}

.dm-agents__wiz-head h3 {
	margin: 0;
}

/* The trail wears the instrument voice: mono uppercase labels, 22px
   dots, a thin rule between stations. All of it goes through the
   component's own theming hooks; the host elements live in this light
   DOM, so the per-state overrides below can select them directly. */
.dm-agents__trail {
	margin-block: 6px 14px;
	--os-ui-steps-gap: 10px;
	--os-ui-step-gap: 7px;
	--os-ui-step-chip-size: 22px;
	--os-ui-step-chip-font-size: 11px;
	--os-ui-step-chip-family: var( --os-ui-font-mono, ui-monospace, monospace );
	--os-ui-step-title-size: 11px;
	--os-ui-step-title-family: var( --os-ui-font-mono, ui-monospace, monospace );
	--os-ui-step-title-transform: uppercase;
	--os-ui-step-title-spacing: 0.08em;
}

/* A station you have not reached is an outline, not a filled dot: the
   mesh chip is where you ARE, and it only reads that way if it is the
   only one lit. */
.dm-agents__trail os-step:not( [ done ] ):not( [ current ] ) {
	--os-ui-step-chip-bg: transparent;
	--os-ui-step-chip-border: 1px solid var( --os-ui-border-strong, #8c8f94 );
	--os-ui-step-chip-fg: var( --os-ui-fg-muted, #646970 );
}

/* Done is quiet: a filled tick on the elevated surface, muted like its
   label. It reads as history, not as a second highlight. */
.dm-agents__trail os-step[ done ] {
	--os-ui-step-chip-done-bg: var( --os-ui-surface-elevated, #f0f0f1 );
	--os-ui-step-chip-fg: var( --os-ui-fg-muted, #646970 );
}

.dm-agents__wiz-heading {
	margin: 12px 0 2px;
	font-size: 16px;
	font-weight: 600;
	color: var( --os-ui-fg, #1d2327 );
}

/* The door. Five complete agents already ship with the plugin, and
   until now the create flow showed them to nobody. */
.dm-agents__starters {
	display: grid;
	gap: 12px;
	grid-template-columns: repeat( auto-fill, minmax( 148px, 1fr ) );
	margin-block: 8px 16px;
}

.dm-agents__starter {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 3px;
	--os-ui-card-padding: 16px 14px;
	--os-ui-card-radius: 10px;
	--os-ui-card-bg: var( --os-ui-surface-subtle, transparent );
	transition: border-color 0.18s ease;
}

.dm-agents__starter:hover,
.dm-agents__starter:focus-within {
	border-color: var( --os-ui-border-strong, #8c8f94 );
}

.dm-agents__starter-face {
	width: 76px;
	height: 76px;
	margin: -8px 0 4px;
	flex: none;
}

.dm-agents__starter-name {
	font-size: 14px;
	font-weight: 500;
	color: var( --os-ui-fg, #1d2327 );
}

.dm-agents__starter-vibes {
	font-family: var( --os-ui-font-mono, ui-monospace, monospace );
	font-size: 11.5px;
	color: var( --os-ui-fg-muted, #646970 );
}

/* Meet: the portrait beside the fields, so the thing being named is
   visible while it is being named. */
.dm-agents__meet {
	display: grid;
	gap: 20px;
	grid-template-columns: 220px 1fr;
	align-items: start;
}

/* The character card. Sunken rather than subtle: the portrait is the
   hero of this step, and the mockup floats it on the darkest surface
   so the face's own glow does the framing. */
.dm-agents__portrait {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 10px;
	padding: 20px 14px 14px;
	border: 1px solid var( --os-border, rgba( 0, 0, 0, 0.08 ) );
	border-radius: var( --os-ui-card-radius, 10px );
	background: var( --os-ui-surface-sunken, #f6f7f7 );
}

.dm-agents__portrait-face {
	width: 176px;
	height: 176px;
	max-width: 100%;
	margin-top: -12px;
}

/* What this face is, in two words. */
.dm-agents__portrait-chips {
	display: flex;
	gap: 6px;
	flex-wrap: wrap;
	justify-content: center;
}

.dm-agents__faces {
	display: grid;
	grid-template-columns: repeat( 6, 1fr );
	gap: 2px;
	width: 100%;
}

.dm-agents__face-pick {
	display: grid;
	place-items: center;
	padding: 2px;
	border: 1px solid transparent;
	border-radius: 8px;
	background: none;
	cursor: pointer;
}

.dm-agents__face-pick img {
	width: 100%;
	height: auto;
	display: block;
}

.dm-agents__face-pick:hover {
	border-color: var( --os-ui-border-strong, #8c8f94 );
}

.dm-agents__face-pick.is-picked {
	border-color: var( --os-ui-accent, #2271b1 );
}

.dm-agents__face-pick:focus-visible {
	outline: var( --os-ui-focus-ring, 2px solid #2271b1 );
	outline-offset: 1px;
}

.dm-agents__meet-fields {
	display: flex;
	flex-direction: column;
	gap: 10px;
	min-width: 0;
}

/* Launch: one card, the brand's card radius, floating on the darkest
   surface like the portrait it echoes. */
.dm-agents__summary {
	display: grid;
	grid-template-columns: 106px 1fr;
	gap: 18px;
	align-items: start;
	--os-ui-card-padding: 18px;
	--os-ui-card-radius: 10px;
	--os-ui-card-bg: var( --os-ui-surface-sunken, #f6f7f7 );
}

.dm-agents__summary-face {
	width: 106px;
	height: 106px;
	flex: none;
}

.dm-agents__summary-text h4 {
	margin: 0 0 2px;
	font-size: 17px;
}

.dm-agents__summary-vibes {
	font-family: var( --os-ui-font-mono, ui-monospace, monospace );
	font-size: 11.5px;
	color: var( --os-ui-accent-strong, #2271b1 );
	margin: 0 0 6px;
}

.dm-agents__summary-desc {
	margin: 0;
	font-size: 13px;
	color: var( --os-ui-fg-muted, #646970 );
}

.dm-agents__chips {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-block-start: 10px;
}

/* What the agent will actually be told, under the chips. Clamped: a
   summary card quotes the instructions, it does not host them. */
.dm-agents__summary-instr {
	margin: 10px 0 0;
	font-size: 13px;
	color: var( --os-ui-fg-muted, #646970 );
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* Identity chips — role, abilities, silhouette, hue — all wear the
   instrument voice: these are facts about the character, stamped
   rather than said. */
.dm-agents__chips os-chip,
.dm-agents__portrait-chips os-chip {
	--os-ui-chip-font-size: 10.5px;
	--os-ui-chip-font-weight: 500;
	--os-ui-chip-bg: transparent;
	--os-ui-chip-fg: var( --os-ui-fg-muted, #646970 );
	--os-ui-chip-border: 1px solid var( --os-border, rgba( 0, 0, 0, 0.12 ) );
	font-family: var( --os-ui-font-mono, ui-monospace, monospace );
	text-transform: uppercase;
	letter-spacing: 0.06em;
}

@media ( max-width: 640px ) {
	.dm-agents__meet,
	.dm-agents__summary {
		grid-template-columns: 1fr;
	}
	.dm-agents__portrait-face {
		width: 128px;
		height: 128px;
	}
}

/* The way back to the grid. The window's own breadcrumb goes UP to the
   folder, which is a different journey: this one returns to the cast. */
.dm-agents__back {
	align-self: flex-start;
	margin-block-end: 4px;
}

/*
 * Long press is the touch right-click (`parts/long-press.ts`). What
 * the browser would do with a held finger — iOS's callout, a text
 * selection creeping across a label — is turned off on the pressable
 * surfaces, and only where a finger is the pointer: on a desk the
 * labels stay selectable.
 */
@media ( pointer: coarse ) {
	.os-mywp__tile,
	.os-mywp__cell,
	.os-mywp__row,
	.os-mywp__canvas {
		-webkit-touch-callout: none;
		-webkit-user-select: none;
		user-select: none;
	}
}
html[data-os-mode="mobile"] .os-mywp__tile,
html[data-os-mode="mobile"] .os-mywp__cell,
html[data-os-mode="mobile"] .os-mywp__row,
html[data-os-mode="mobile"] .os-mywp__canvas {
	-webkit-touch-callout: none;
	-webkit-user-select: none;
	user-select: none;
}

```
