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 +740 -147 1.0.0 → 1.1.13 View file →
@@ -27,12 +27,24 @@
27 27 background: var(
28 28 --os-my-wordpress-bg,
29 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. */
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. */
33 42 --os-tile-fg: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
34 - --os-tile-fg-muted: rgba( 0, 0, 0, 0.55 );
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 + );
35 47 --os-tile-hover-bg: var(
36 48 --os-hover,
37 49 rgba( 0, 0, 0, 0.06 )
38 50 );
@@ -263,9 +275,13 @@
263 275 background: var(
264 276 --os-media-tile-bg,
265 277 rgba( 0, 0, 0, 0.05 )
266 278 );
267 - box-shadow: inset 0 0 0 1px rgba( 0, 0, 0, 0.12 );
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 ) );
268 284 }
269 285
270 286 /* Banded list views. A section can split its tiles into labelled
271 287 * bands (WooCommerce Orders groups by status, needs-attention first)
@@ -394,9 +410,12 @@
394 410 0 1px 3px rgba( 0, 0, 0, 0.35 );
395 411 pointer-events: none;
396 412 }
397 413
398 -/* Tooltip lock banner — shown above the excerpt when present. */
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. */
399 418 .os-my-wordpress__tooltip-lock {
400 419 display: flex;
401 420 align-items: center;
402 421 gap: 6px;
@@ -402,9 +421,12 @@
402 421 gap: 6px;
403 422 margin: 0 0 8px;
404 423 padding: 6px 8px;
405 424 border-radius: 4px;
406 - background: rgba( 179, 45, 46, 0.08 );
425 + background: var(
426 + --os-my-wordpress-card-lock-bg,
427 + rgba( 179, 45, 46, 0.08 )
428 + );
407 429 color: var( --os-danger, var( --os-ui-danger, #b32d2e ) );
408 430 font-size: 12px;
409 431 font-weight: 600;
410 432 }
@@ -689,9 +711,23 @@
689 711 .os-my-wordpress__error {
690 712 color: var( --os-danger, var( --os-ui-danger, #b32d2e ) );
691 713 }
692 714
693 -/* ----- 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. */
694 730
695 731 .os-my-wordpress__tooltip {
696 732 position: fixed;
697 733 z-index: 100000;
@@ -696,19 +732,28 @@
696 732 position: fixed;
697 733 z-index: 100000;
698 734 max-width: 320px;
699 735 background: var(
700 - --os-tooltip-bg,
701 - var( --os-surface, var( --os-ui-surface, #fff ) )
736 + --os-my-wordpress-card-bg,
737 + var(
738 + --os-tooltip-bg,
739 + var( --os-surface, var( --os-ui-surface, #fff ) )
740 + )
702 741 );
703 742 color: var(
704 - --os-tooltip-fg,
705 - var( --os-fg, #1d2327 )
743 + --os-my-wordpress-card-fg,
744 + var( --os-tooltip-fg, var( --os-fg, #1d2327 ) )
706 745 );
707 - border: 1px solid var( --os-ui-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 );
708 750 border-radius: 6px;
709 751 padding: 12px;
710 - 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 + );
711 756 font-size: 12px;
712 757 pointer-events: none;
713 758 }
714 759
@@ -717,8 +762,12 @@
717 762 margin-bottom: 6px;
718 763 font-size: 13px;
719 764 }
720 765
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. */
721 770 .os-my-wordpress__tooltip-thumb {
722 771 display: block;
723 772 max-width: 100%;
724 773 height: auto;
@@ -723,13 +772,18 @@
723 772 max-width: 100%;
724 773 height: auto;
725 774 border-radius: 4px;
726 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 + );
727 781 }
728 782
729 783 .os-my-wordpress__tooltip-excerpt {
730 784 margin: 0;
731 - color: var( --os-ui-fg-muted, #50575e );
785 + color: var( --os-my-wordpress-card-fg-muted, #50575e );
732 786 line-height: 1.4;
733 787 }
734 788
735 789 /* ----- Context menu host ----- */
@@ -792,9 +846,9 @@
792 846 font-size: 11px;
793 847 font-weight: 600;
794 848 text-transform: uppercase;
795 849 letter-spacing: 0.04em;
796 - background: rgba( 34, 113, 177, 0.12 );
850 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 12%, transparent );
797 851 color: var( --wp-admin-theme-color, #2271b1 );
798 852 }
799 853
800 854 .os-my-wordpress__user-links {
@@ -814,9 +868,9 @@
814 868
815 869 .os-my-wordpress__user-bio {
816 870 font-size: 14px;
817 871 line-height: 1.5;
818 - color: var( --os-fg, #1d2327 );
872 + color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
819 873 margin: 0 0 16px;
820 874 padding-left: 12px;
821 875 border-left: 3px solid var( --os-ui-border, #dcdcde );
822 876 }
@@ -897,9 +951,9 @@
897 951 .os-my-wordpress__user-spark-bar {
898 952 background: linear-gradient(
899 953 180deg,
900 954 var( --wp-admin-theme-color, #2271b1 ) 0%,
901 - rgba( 34, 113, 177, 0.55 ) 100%
955 + color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 55%, transparent ) 100%
902 956 );
903 957 border-radius: 3px 3px 0 0;
904 958 min-height: 2px;
905 959 transition: height 0.3s ease;
@@ -1033,9 +1087,9 @@
1033 1087 }
1034 1088
1035 1089 .os-my-wordpress__term-icon--category {
1036 1090 background: linear-gradient( 135deg, var( --os-ui-accent, #2271b1 ) 0%, var( --os-ui-accent-strong, #135e96 ) 100% );
1037 - box-shadow: 0 4px 12px rgba( 34, 113, 177, 0.32 );
1091 + box-shadow: 0 4px 12px color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 32%, transparent );
1038 1092 }
1039 1093
1040 1094 .os-my-wordpress__term-icon--tag {
1041 1095 background: linear-gradient( 135deg, #7c3aed 0%, #5b21b6 100% );
@@ -1042,9 +1096,9 @@
1042 1096 box-shadow: 0 4px 12px rgba( 124, 58, 237, 0.32 );
1043 1097 }
1044 1098
1045 1099 .os-my-wordpress__user-role--category {
1046 - background: rgba( 34, 113, 177, 0.12 );
1100 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 12%, transparent );
1047 1101 color: var( --os-ui-accent-strong, #135e96 );
1048 1102 }
1049 1103
1050 1104 .os-my-wordpress__user-role--tag {
@@ -1104,9 +1158,9 @@
1104 1158 * for users with moderate_comments.
1105 1159 * --------------------------------------------------------------- */
1106 1160
1107 1161 .os-my-wordpress__comment-status--approved {
1108 - background: rgba( 34, 113, 177, 0.12 );
1162 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 12%, transparent );
1109 1163 color: var( --os-ui-accent-strong, #135e96 );
1110 1164 }
1111 1165
1112 1166 .os-my-wordpress__comment-status--pending {
@@ -1137,9 +1191,9 @@
1137 1191 .os-my-wordpress__comment-quote {
1138 1192 margin: 0 0 16px;
1139 1193 padding: 10px 14px;
1140 1194 border-left: 3px solid var( --wp-admin-theme-color, #2271b1 );
1141 - background: rgba( 34, 113, 177, 0.06 );
1195 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 6%, transparent );
1142 1196 border-radius: 0 6px 6px 0;
1143 1197 font-size: 13px;
1144 1198 }
1145 1199
@@ -1153,9 +1207,9 @@
1153 1207 }
1154 1208
1155 1209 .os-my-wordpress__comment-quote p {
1156 1210 margin: 0;
1157 - color: var( --os-fg, #1d2327 );
1211 + color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
1158 1212 }
1159 1213
1160 1214 /* Comment body — same style as article-content but with a soft
1161 1215 * card background so it reads as the focal element. */
@@ -1245,9 +1299,9 @@
1245 1299
1246 1300 .os-my-wordpress__comment-reply-excerpt {
1247 1301 margin: 0;
1248 1302 font-size: 13px;
1249 - color: var( --os-fg, #1d2327 );
1303 + color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
1250 1304 line-height: 1.45;
1251 1305 }
1252 1306
1253 1307 /* =================================================================== *
@@ -1282,10 +1336,10 @@
1282 1336 border-radius: 50%;
1283 1337 overflow: hidden;
1284 1338 background: linear-gradient(
1285 1339 135deg,
1286 - rgba( 34, 113, 177, 0.18 ),
1287 - 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 )
1288 1342 );
1289 1343 box-shadow:
1290 1344 inset 0 0 0 1px rgba( 0, 0, 0, 0.08 ),
1291 1345 0 2px 6px rgba( 0, 0, 0, 0.08 );
@@ -1406,10 +1460,10 @@
1406 1460 padding: 24px;
1407 1461 border-radius: 16px;
1408 1462 background: linear-gradient(
1409 1463 135deg,
1410 - rgba( 34, 113, 177, 0.10 ) 0%,
1411 - 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%,
1412 1466 transparent 100%
1413 1467 );
1414 1468 border: 1px solid var( --os-ui-border, #dcdcde );
1415 1469 }
@@ -1424,10 +1478,10 @@
1424 1478 inset 0 0 0 2px rgba( 255, 255, 255, 0.8 ),
1425 1479 0 6px 24px rgba( 0, 0, 0, 0.14 );
1426 1480 background: linear-gradient(
1427 1481 135deg,
1428 - rgba( 34, 113, 177, 0.18 ),
1429 - 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 )
1430 1484 );
1431 1485 display: inline-flex;
1432 1486 align-items: center;
1433 1487 justify-content: center;
@@ -1452,14 +1506,17 @@
1452 1506 flex-direction: column;
1453 1507 gap: 8px;
1454 1508 }
1455 1509
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. */
1456 1513 .os-my-wordpress__footprint-title {
1457 1514 margin: 0;
1458 1515 font-size: 28px;
1459 1516 line-height: 1.15;
1460 1517 font-weight: 700;
1461 - color: var( --os-fg, #1d2327 );
1518 + color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
1462 1519 }
1463 1520
1464 1521 .os-my-wordpress__footprint-meta {
1465 1522 display: flex;
@@ -1559,17 +1616,17 @@
1559 1616 background: var( --os-ui-hover, rgba( 0, 0, 0, 0.06 ) );
1560 1617 }
1561 1618
1562 1619 .os-my-wordpress__footprint-cell--l1 {
1563 - background: rgba( 34, 113, 177, 0.25 );
1620 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 25%, transparent );
1564 1621 }
1565 1622
1566 1623 .os-my-wordpress__footprint-cell--l2 {
1567 - background: rgba( 34, 113, 177, 0.5 );
1624 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 50%, transparent );
1568 1625 }
1569 1626
1570 1627 .os-my-wordpress__footprint-cell--l3 {
1571 - background: rgba( 34, 113, 177, 0.75 );
1628 + background: color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 75%, transparent );
1572 1629 }
1573 1630
1574 1631 .os-my-wordpress__footprint-cell--l4 {
1575 1632 background: var( --wp-admin-theme-color, #2271b1 );
@@ -1639,9 +1696,9 @@
1639 1696 .os-my-wordpress__footprint-bar {
1640 1697 background: linear-gradient(
1641 1698 180deg,
1642 1699 var( --wp-admin-theme-color, #2271b1 ) 0%,
1643 - rgba( 34, 113, 177, 0.55 ) 100%
1700 + color-mix( in srgb, var( --wp-admin-theme-color, #2271b1 ) 55%, transparent ) 100%
1644 1701 );
1645 1702 border-radius: 3px 3px 0 0;
1646 1703 min-height: 2px;
1647 1704 transition: opacity 0.2s ease;
@@ -1673,10 +1730,10 @@
1673 1730 text-align: center;
1674 1731 padding: 20px 24px;
1675 1732 background: linear-gradient(
1676 1733 135deg,
1677 - rgba( 34, 113, 177, 0.10 ),
1678 - 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 )
1679 1736 );
1680 1737 }
1681 1738
1682 1739 .os-my-wordpress__footprint-callout-label {
@@ -1690,9 +1747,9 @@
1690 1747 .os-my-wordpress__footprint-callout-value {
1691 1748 margin: 2px 0;
1692 1749 font-size: 24px;
1693 1750 font-weight: 700;
1694 - color: var( --os-fg, #1d2327 );
1751 + color: var( --os-my-wordpress-fg, var( --os-ui-fg, #1d2327 ) );
1695 1752 }
1696 1753
1697 1754 .os-my-wordpress__footprint-callout-detail {
1698 1755 margin: 0;
@@ -2101,8 +2158,9 @@
2101 2158 overflow: hidden;
2102 2159 box-sizing: border-box;
2103 2160 }
2104 2161
2162 +
2105 2163 /* Section-level loading — same scale curve as the My WordPress
2106 2164 preview loader and the window-loading overlay, instead of the bare
2107 2165 48px component default. */
2108 2166 .dm-agents__loading {
@@ -2116,112 +2174,27 @@
2116 2174 .dm-agents__loading os-spinner {
2117 2175 --os-ui-spinner-size: clamp( 96px, 14vw, 192px );
2118 2176 }
2119 2177
2120 -.dm-agents__layout {
2121 - display: flex;
2178 +.dm-agents__detail {
2122 2179 flex: 1;
2123 - min-height: 0;
2124 - gap: 12px;
2125 -}
2126 -
2127 -/* Sidebar column: a fixed "Create agent" header over the scrolling
2128 - list. The button used to be the list's last child, which put it out
2129 - of reach on any site with enough agents to need it. */
2130 -.dm-agents__sidebar {
2131 - display: flex;
2132 - flex-direction: column;
2133 - flex: 0 0 260px;
2134 - /* `min-width: auto` on a flex item resolves to its min-content
2135 - width, and the rows carry long `white-space: nowrap` descriptions
2136 - — without this the column ignores its 260px basis and eats the
2137 - detail pane. The scroll container used to be this item, whose
2138 - non-visible overflow zeroed the minimum for free. */
2139 2180 min-width: 0;
2140 - min-height: 0;
2141 - border-inline-end: 1px solid var( --os-border, rgba( 0, 0, 0, 0.08 ) );
2142 -}
2143 -
2144 -.dm-agents__list-toolbar {
2145 - flex: none;
2146 - display: flex;
2147 - padding-block-end: 8px;
2148 - padding-inline-end: 8px;
2149 -}
2150 -
2151 -.dm-agents__list-toolbar .dm-agents__create {
2152 - flex: 1;
2153 -}
2154 -
2155 -.dm-agents__list {
2156 - display: flex;
2157 - flex-direction: column;
2158 - gap: 4px;
2159 - flex: 1;
2160 - min-height: 0;
2161 2181 overflow-y: auto;
2162 - padding-inline-end: 4px;
2163 -}
2164 -
2165 -.dm-agents__row {
2166 2182 display: flex;
2167 - align-items: center;
2168 - gap: 8px;
2169 - padding: 8px;
2170 - border-radius: 8px;
2171 - cursor: pointer;
2172 -}
2173 -
2174 -.dm-agents__row:hover {
2175 - background: var( --os-hover, rgba( 0, 0, 0, 0.06 ) );
2176 -}
2177 -
2178 -.dm-agents__row.is-selected {
2179 - background: var( --os-selected, rgba( 0, 0, 0, 0.1 ) );
2180 -}
2181 -
2182 -.dm-agents__row-avatar {
2183 - width: 32px;
2184 - height: 32px;
2185 - border-radius: 50%;
2186 - /* Placeholder behind the avatar image while it loads — follows the
2187 - palette so it isn't a white disc on a dark station. */
2188 - background: var( --os-ui-surface-elevated, #fff );
2189 - flex: none;
2190 -}
2191 -
2192 -.dm-agents__row-text {
2193 - display: flex;
2194 2183 flex-direction: column;
2195 - min-width: 0;
2196 - flex: 1;
2184 + gap: 10px;
2197 2185 }
2198 2186
2199 -.dm-agents__row-name {
2200 - font-weight: 600;
2201 - white-space: nowrap;
2202 - overflow: hidden;
2203 - 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;
2204 2195 }
2205 2196
2206 -.dm-agents__row-desc {
2207 - font-size: 12px;
2208 - opacity: 0.65;
2209 - white-space: nowrap;
2210 - overflow: hidden;
2211 - text-overflow: ellipsis;
2212 -}
2213 -
2214 -
2215 -.dm-agents__detail {
2216 - flex: 1;
2217 - min-width: 0;
2218 - overflow-y: auto;
2219 - display: flex;
2220 - flex-direction: column;
2221 - gap: 10px;
2222 -}
2223 -
2224 2197 .dm-agents__detail-head {
2225 2198 display: flex;
2226 2199 align-items: center;
2227 2200 gap: 10px;
@@ -2311,31 +2284,156 @@
2311 2284 font-size: 12px;
2312 2285 opacity: 0.7;
2313 2286 }
2314 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 +
2315 2315 .dm-agents__category {
2316 - margin: 8px 0 0;
2317 - 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;
2318 2320 text-transform: uppercase;
2319 - letter-spacing: 0.04em;
2320 - opacity: 0.6;
2321 + letter-spacing: 0.08em;
2322 + color: var( --os-ui-fg-muted, #646970 );
2321 2323 }
2322 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). */
2323 2394 .dm-agents__ability {
2324 2395 display: grid;
2325 2396 grid-template-columns: 1fr auto;
2326 - gap: 2px 8px;
2327 - align-items: center;
2328 - 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 ) );
2329 2401 }
2330 2402
2403 +.dm-agents__ability:last-of-type {
2404 + border-bottom: 0;
2405 +}
2406 +
2331 2407 .dm-agents__ability-desc {
2332 2408 grid-column: 1 / -1;
2333 2409 margin: 0;
2334 - font-size: 12px;
2335 - opacity: 0.6;
2410 + padding-inline-start: 26px;
2411 + font-size: 12.5px;
2412 + color: var( --os-ui-fg-muted, #646970 );
2336 2413 }
2337 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 +
2338 2436 .dm-agents__trigger {
2339 2437 border: 1px solid var( --os-border, rgba( 0, 0, 0, 0.08 ) );
2340 2438 border-radius: 8px;
2341 2439 padding: 8px 10px;
@@ -2349,15 +2447,12 @@
2349 2447 align-items: center;
2350 2448 gap: 8px;
2351 2449 }
2352 2450
2353 -.dm-agents__trigger-summary {
2354 - flex: 1;
2451 +.dm-agents__trigger-desc {
2452 + margin: 0;
2355 2453 font-size: 12px;
2356 - opacity: 0.65;
2357 - white-space: nowrap;
2358 - overflow: hidden;
2359 - text-overflow: ellipsis;
2454 + opacity: 0.75;
2360 2455 }
2361 2456
2362 2457 .dm-agents__trigger-config {
2363 2458 display: flex;
@@ -2367,5 +2462,503 @@
2367 2462
2368 2463 .dm-agents__actions {
2369 2464 display: flex;
2370 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;
2371 2964 }