| @@ -50,9 +50,9 @@ | ||
| 50 | 50 | position: relative; |
| 51 | 51 | display: flex; |
| 52 | 52 | flex-direction: column; |
| 53 | 53 | align-items: center; |
| 54 | - width: 40px; | |
| 54 | + width: var( --os-dock-item-size, 40px ); | |
| 55 | 55 | flex-shrink: 0; |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | 58 | /* Primary icon button — opens or focuses the page. */ |
| @@ -60,12 +60,12 @@ | ||
| 60 | 60 | position: relative; |
| 61 | 61 | display: flex; |
| 62 | 62 | align-items: center; |
| 63 | 63 | justify-content: center; |
| 64 | - width: 40px; | |
| 65 | - height: 40px; | |
| 64 | + width: var( --os-dock-item-size, 40px ); | |
| 65 | + height: var( --os-dock-item-size, 40px ); | |
| 66 | 66 | border: none; |
| 67 | - border-radius: 10px; | |
| 67 | + border-radius: var( --os-dock-item-radius, 10px ); | |
| 68 | 68 | cursor: pointer; |
| 69 | 69 | padding: 0; |
| 70 | 70 | background-color: transparent; |
| 71 | 71 | /* |
| @@ -87,8 +87,32 @@ | ||
| 87 | 87 | color: var( --os-dock-icon-color, rgba( 255, 255, 255, 0.7 ) ); |
| 88 | 88 | transition: background-color 0.15s ease, transform 0.15s ease, color 0.15s ease; |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | +/* | |
| 92 | + * The tile whose window is in front sits on a lit plate. Declared | |
| 93 | + * before the hover rule at the same specificity so the pointer still | |
| 94 | + * wins while it is over the tile. Falls back to nothing, which is | |
| 95 | + * what every placement drew before the token existed. | |
| 96 | + */ | |
| 97 | +.os-dock__item--focused .os-dock__item-primary { | |
| 98 | + background-color: var( --os-dock-item-bg-focused, transparent ); | |
| 99 | + color: var( --os-dock-icon-color-hover, var( --os-ui-fg-on-accent, #fff ) ); | |
| 100 | +} | |
| 101 | + | |
| 102 | +/* | |
| 103 | + * DOCK_ITEM_FOCUSED texture slot — the face of the tile whose window is | |
| 104 | + * in front, and of any tile held down: a key that stays pressed while | |
| 105 | + * its window is up. Falls back to the resting face. | |
| 106 | + */ | |
| 107 | +.os-dock__item--focused .os-dock__item-primary, | |
| 108 | +.os-dock__item-primary:active { | |
| 109 | + background-image: var( | |
| 110 | + --os-dock-item-image-focused, | |
| 111 | + var( --os-dock-item-image, none ) | |
| 112 | + ); | |
| 113 | +} | |
| 114 | + | |
| 91 | 115 | .os-dock__item-primary:hover { |
| 92 | 116 | background-color: var( |
| 93 | 117 | --os-dock-item-bg-hover, |
| 94 | 118 | rgba( 255, 255, 255, 0.15 ) |
| @@ -96,13 +120,13 @@ | ||
| 96 | 120 | color: var( |
| 97 | 121 | --os-dock-icon-color-hover, |
| 98 | 122 | var( --os-ui-fg-on-accent, #fff ) |
| 99 | 123 | ); |
| 100 | - transform: scale( 1.1 ); | |
| 124 | + transform: var( --os-dock-item-hover-transform, scale( 1.1 ) ); | |
| 101 | 125 | } |
| 102 | 126 | |
| 103 | 127 | .os-dock__item-primary:active { |
| 104 | - transform: scale( 0.95 ); | |
| 128 | + transform: var( --os-dock-item-press-transform, scale( 0.95 ) ); | |
| 105 | 129 | } |
| 106 | 130 | |
| 107 | 131 | .os-dock__item-primary:focus-visible { |
| 108 | 132 | outline: 2px solid var( |
| @@ -113,21 +137,29 @@ | ||
| 113 | 137 | } |
| 114 | 138 | |
| 115 | 139 | /* Stacked card hint on hover — a second card peeks from behind the |
| 116 | 140 | icon when the tile has multiple open windows. Only visible on hover so |
| 117 | - it never conflicts with focused tiles. */ | |
| 118 | -.os-dock__item--stacked:hover .os-dock__item-primary::before, | |
| 119 | -.os-dock__item--stacked[data-peek-active] .os-dock__item-primary::before { | |
| 141 | + it never conflicts with focused tiles. | |
| 142 | + * | |
| 143 | + * Painted on the TILE, not on the button it hints at. The hover that | |
| 144 | + * arms this also scales the button, a transform makes a stacking | |
| 145 | + * context, and a `z-index: -1` child of one cannot escape it: the card | |
| 146 | + * landed above the button's own hover plate instead of behind the | |
| 147 | + * tile, reading as a second plate laid over the first. The tile is | |
| 148 | + * transformed by nothing, and a positioned child (the button) paints | |
| 149 | + * over a parent's `::before` at the same level, so the card sits where | |
| 150 | + * its name says without asking for a z-index at all. */ | |
| 151 | +.os-dock__item--stacked:hover::before, | |
| 152 | +.os-dock__item--stacked[ data-peek-active ]::before { | |
| 120 | 153 | content: ""; |
| 121 | 154 | position: absolute; |
| 122 | 155 | top: -4px; |
| 123 | 156 | inset-inline-start: -4px; |
| 124 | - width: 100%; | |
| 125 | - height: 100%; | |
| 126 | - border-radius: inherit; | |
| 157 | + width: 40px; | |
| 158 | + height: 40px; | |
| 159 | + border-radius: 10px; | |
| 127 | 160 | background: rgba( 255, 255, 255, 0.06 ); |
| 128 | 161 | border: 1px solid rgba( 255, 255, 255, 0.10 ); |
| 129 | - z-index: -1; | |
| 130 | 162 | pointer-events: none; |
| 131 | 163 | } |
| 132 | 164 | |
| 133 | 165 | /* Dashicon inside dock item. */ |
| @@ -249,9 +281,9 @@ | ||
| 249 | 281 | padding: 0; |
| 250 | 282 | border: 2px solid var( --os-dock-bg, rgba( 0, 0, 0, 0.4 ) ); |
| 251 | 283 | border-radius: 50%; |
| 252 | 284 | background: var( --wp-admin-theme-color, #2271b1 ); |
| 253 | - color: var( --os-ui-fg-on-accent, #fff ); | |
| 285 | + color: var( --os-ui-accent-ink, var( --os-ui-fg-on-accent, #fff ) ); | |
| 254 | 286 | cursor: pointer; |
| 255 | 287 | transition: background-color 0.15s ease, transform 0.15s ease; |
| 256 | 288 | z-index: 1; |
| 257 | 289 | } |
| @@ -510,9 +542,9 @@ | ||
| 510 | 542 | |
| 511 | 543 | /* Shared tooltip — placement-specific anchor modifiers applied by JS. */ |
| 512 | 544 | .os-dock__tooltip { |
| 513 | 545 | position: fixed; |
| 514 | - padding: 6px 12px; | |
| 546 | + padding: var( --os-tooltip-padding, 6px 12px ); | |
| 515 | 547 | background: var( |
| 516 | 548 | --os-tooltip-bg, |
| 517 | 549 | var( --os-ui-scrim, rgba( 0, 0, 0, 0.85 ) ) |
| 518 | 550 | ); |
| @@ -519,13 +551,15 @@ | ||
| 519 | 551 | color: var( |
| 520 | 552 | --os-tooltip-fg, |
| 521 | 553 | var( --os-ui-fg-on-accent, #fff ) |
| 522 | 554 | ); |
| 523 | - font-size: 12px; | |
| 555 | + font-size: var( --os-tooltip-font-size, 12px ); | |
| 524 | 556 | font-weight: 400; |
| 525 | 557 | line-height: 1.4; |
| 526 | 558 | white-space: nowrap; |
| 527 | - border-radius: 6px; | |
| 559 | + border: var( --os-tooltip-border, 0 ); | |
| 560 | + border-radius: var( --os-tooltip-radius, 6px ); | |
| 561 | + box-shadow: var( --os-tooltip-shadow, none ); | |
| 528 | 562 | pointer-events: none; |
| 529 | 563 | z-index: calc( var( --os-z-dock ) + 1 ); |
| 530 | 564 | opacity: 0; |
| 531 | 565 | transition: opacity 0.15s ease, transform 0.15s ease; |
| @@ -632,9 +666,9 @@ | ||
| 632 | 666 | transform: translateY( -50% ); |
| 633 | 667 | width: 4px; |
| 634 | 668 | height: 4px; |
| 635 | 669 | border-radius: 50%; |
| 636 | - background: var( --os-dock-item-outline, #fff ); | |
| 670 | + background: var( --os-dock-active-indicator, var( --os-dock-item-outline, #fff ) ); | |
| 637 | 671 | } |
| 638 | 672 | |
| 639 | 673 | .os-dock[ data-os-dock-placement="left" ] |
| 640 | 674 | .os-dock__item--focused::before { |
| @@ -658,9 +692,9 @@ | ||
| 658 | 692 | width: 6px; |
| 659 | 693 | height: 6px; |
| 660 | 694 | border-radius: 50%; |
| 661 | 695 | background: transparent; |
| 662 | - border: 1px solid var( --os-dock-item-outline, rgba( 255, 255, 255, 0.85 ) ); | |
| 696 | + border: 1px solid var( --os-dock-active-indicator, var( --os-dock-item-outline, rgba( 255, 255, 255, 0.85 ) ) ); | |
| 663 | 697 | } |
| 664 | 698 | |
| 665 | 699 | /* Right dock: indicator on the opposite edge (inside-facing). */ |
| 666 | 700 | .os-dock[ data-os-dock-placement="right" ] |
| @@ -672,9 +706,9 @@ | ||
| 672 | 706 | transform: translateY( -50% ); |
| 673 | 707 | width: 4px; |
| 674 | 708 | height: 4px; |
| 675 | 709 | border-radius: 50%; |
| 676 | - background: var( --os-dock-item-outline, #fff ); | |
| 710 | + background: var( --os-dock-active-indicator, var( --os-dock-item-outline, #fff ) ); | |
| 677 | 711 | } |
| 678 | 712 | |
| 679 | 713 | .os-dock[ data-os-dock-placement="right" ] |
| 680 | 714 | .os-dock__item--focused::before { |
| @@ -688,9 +722,9 @@ | ||
| 688 | 722 | width: 6px; |
| 689 | 723 | height: 6px; |
| 690 | 724 | border-radius: 50%; |
| 691 | 725 | background: transparent; |
| 692 | - border: 1px solid var( --os-dock-item-outline, rgba( 255, 255, 255, 0.85 ) ); | |
| 726 | + border: 1px solid var( --os-dock-active-indicator, var( --os-dock-item-outline, rgba( 255, 255, 255, 0.85 ) ) ); | |
| 693 | 727 | } |
| 694 | 728 | |
| 695 | 729 | /* "Open another" chip — left: right of tile; right: left of tile. */ |
| 696 | 730 | .os-dock[ data-os-dock-placement="left" ] |
| @@ -841,16 +875,22 @@ | ||
| 841 | 875 | * viewport floor. Absolutely positioned so it floats as pure chrome |
| 842 | 876 | * rather than stealing vertical space from the shell body. |
| 843 | 877 | * ------------------------------------------------------------------ */ |
| 844 | 878 | |
| 879 | +/* | |
| 880 | + * The pill's geometry is tokenized so a theme can draw a different | |
| 881 | + * object along the same edge: a full-width bar flush with the floor | |
| 882 | + * is `width: 100%`, `bottom: 0`, radius 0. The work area measures the | |
| 883 | + * rail's real box, so windows keep clear of whatever shape it takes. | |
| 884 | + */ | |
| 845 | 885 | .os-dock[ data-os-dock-placement="bottom" ] { |
| 846 | 886 | position: absolute; |
| 847 | 887 | inset-inline-start: 0; |
| 848 | 888 | inset-inline-end: 0; |
| 849 | - bottom: 12px; | |
| 889 | + bottom: var( --os-dock-floating-offset, 12px ); | |
| 850 | 890 | margin: 0 auto; |
| 851 | - width: fit-content; | |
| 852 | - max-width: calc( 100% - 32px ); | |
| 891 | + width: var( --os-dock-floating-width, fit-content ); | |
| 892 | + max-width: var( --os-dock-floating-max-width, calc( 100% - 32px ) ); | |
| 853 | 893 | flex-direction: row; |
| 854 | 894 | justify-content: center; |
| 855 | 895 | /* Top padding is 4px instead of 8px so that the inner `__scroll` |
| 856 | 896 | * wrapper can claim its own 4px padding-top for badge clearance |
| @@ -856,11 +896,11 @@ | ||
| 856 | 896 | * wrapper can claim its own 4px padding-top for badge clearance |
| 857 | 897 | * (the tile's badge sits at top: -3px). Net vertical chrome stays |
| 858 | 898 | * symmetric: 4px pill padding + 4px wrapper padding above the |
| 859 | 899 | * tile, 8px pill padding below — tile is 8px from both edges. */ |
| 860 | - padding: 4px 12px 8px; | |
| 861 | - gap: 6px; | |
| 862 | - border-radius: 18px; | |
| 900 | + padding: var( --os-dock-floating-padding, 4px 12px 8px ); | |
| 901 | + gap: var( --os-dock-floating-gap, 6px ); | |
| 902 | + border-radius: var( --os-dock-floating-radius, 18px ); | |
| 863 | 903 | |
| 864 | 904 | /* Warmer, more saturated glass tint than vertical placements so |
| 865 | 905 | * the floating pill reads as a distinct piece of chrome rather |
| 866 | 906 | * than a section of the sidebar. |
| @@ -876,10 +916,10 @@ | ||
| 876 | 916 | background-color: var( |
| 877 | 917 | --os-dock-floating-bg, |
| 878 | 918 | rgba( 22, 22, 26, 0.42 ) |
| 879 | 919 | ); |
| 880 | - backdrop-filter: blur( 28px ) saturate( 170% ); | |
| 881 | - -webkit-backdrop-filter: blur( 28px ) saturate( 170% ); | |
| 920 | + backdrop-filter: var( --os-dock-floating-backdrop, blur( 28px ) saturate( 170% ) ); | |
| 921 | + -webkit-backdrop-filter: var( --os-dock-floating-backdrop, blur( 28px ) saturate( 170% ) ); | |
| 882 | 922 | |
| 883 | 923 | /* |
| 884 | 924 | * Hairline + inset highlight. These used to be hardcoded, which |
| 885 | 925 | * meant a theme could restyle every dock placement EXCEPT this |
| @@ -925,9 +965,9 @@ | ||
| 925 | 965 | transform: translateX( -50% ); |
| 926 | 966 | width: 4px; |
| 927 | 967 | height: 4px; |
| 928 | 968 | border-radius: 50%; |
| 929 | - background: var( --os-dock-item-outline, #fff ); | |
| 969 | + background: var( --os-dock-active-indicator, var( --os-dock-item-outline, #fff ) ); | |
| 930 | 970 | } |
| 931 | 971 | |
| 932 | 972 | .os-dock[ data-os-dock-placement="bottom" ] |
| 933 | 973 | .os-dock__item--focused::before { |
| @@ -946,9 +986,9 @@ | ||
| 946 | 986 | width: 6px; |
| 947 | 987 | height: 6px; |
| 948 | 988 | border-radius: 50%; |
| 949 | 989 | background: transparent; |
| 950 | - border: 1px solid var( --os-dock-item-outline, rgba( 255, 255, 255, 0.85 ) ); | |
| 990 | + border: 1px solid var( --os-dock-active-indicator, var( --os-dock-item-outline, rgba( 255, 255, 255, 0.85 ) ) ); | |
| 951 | 991 | } |
| 952 | 992 | |
| 953 | 993 | /* |
| 954 | 994 | * "Show Desktop" — every live window on the active desktop minimized. |
| @@ -1003,23 +1043,30 @@ | ||
| 1003 | 1043 | * general problem. The inline padding is symmetric so the tile cluster |
| 1004 | 1044 | * stays centred in the pill. `min-width: 0` lets the wrapper shrink below its |
| 1005 | 1045 | * content's natural width, so the dock pill's `max-width` is what |
| 1006 | 1046 | * decides when scroll kicks in instead of the content forcing the |
| 1007 | - * pill wider. `justify-content: center` keeps tiles balanced inside | |
| 1008 | - * the pill when content fits; when it overflows, scroll engages and | |
| 1009 | - * items extend past the visible area. | |
| 1047 | + * pill wider. `justify-content: safe center` keeps tiles balanced inside | |
| 1048 | + * the pill when content fits; when it overflows, the `safe` keyword | |
| 1049 | + * ensures alignment falls back to `start` so `scrollLeft = 0` reveals the | |
| 1050 | + * first item and all items remain scrollable without clipping. Bare | |
| 1051 | + * `center` put the leading tiles at a negative offset, and a scroll | |
| 1052 | + * container clamps `scrollLeft` at 0, so Dashboard and its neighbours | |
| 1053 | + * were clipped with no way to scroll back to them. **The plain `start` | |
| 1054 | + * above it is the fallback, not a leftover** — a browser that cannot | |
| 1055 | + * parse the overflow-alignment keyword drops the `safe center` | |
| 1056 | + * declaration and keeps that one, which left-aligns the tiles rather | |
| 1057 | + * than hiding them. Deleting it restores the bug on those browsers. | |
| 1010 | 1058 | */ |
| 1011 | 1059 | .os-dock[ data-os-dock-placement="bottom" ] .os-dock__scroll { |
| 1012 | 1060 | display: flex; |
| 1013 | 1061 | flex-direction: row; |
| 1014 | 1062 | align-items: center; |
| 1015 | - justify-content: center; | |
| 1016 | - gap: 6px; | |
| 1063 | + justify-content: start; | |
| 1064 | + justify-content: var( --os-dock-floating-justify, safe center ); | |
| 1065 | + gap: var( --os-dock-floating-gap, 6px ); | |
| 1017 | 1066 | flex: 1 1 auto; |
| 1018 | 1067 | min-width: 0; |
| 1019 | - padding-top: 4px; | |
| 1020 | - padding-bottom: 6px; | |
| 1021 | - padding-inline: 4px; | |
| 1068 | + padding: var( --os-dock-floating-track-padding, 4px 4px 6px ); | |
| 1022 | 1069 | overflow-x: auto; |
| 1023 | 1070 | /* |
| 1024 | 1071 | * Authored `visible`, computed `auto` — see the note above. Kept as |
| 1025 | 1072 | * the honest statement of intent: nothing here wants a vertical |
| @@ -1037,14 +1084,16 @@ | ||
| 1037 | 1084 | .os-dock[ data-os-dock-placement="bottom" ] .os-dock__pinned { |
| 1038 | 1085 | display: flex; |
| 1039 | 1086 | flex-direction: row; |
| 1040 | 1087 | align-items: center; |
| 1041 | - gap: 6px; | |
| 1088 | + gap: var( --os-dock-floating-gap, 6px ); | |
| 1042 | 1089 | flex-shrink: 0; |
| 1043 | 1090 | /* Match the scroll wrapper's badge clearance so system tiles sit |
| 1044 | 1091 | * on the same vertical baseline as the menu tiles. */ |
| 1045 | - padding-top: 4px; | |
| 1046 | - padding-bottom: 6px; | |
| 1092 | + padding: var( --os-dock-floating-pinned-padding, 4px 0 6px ); | |
| 1093 | + /* A well the system tiles sit in, when a theme draws one. */ | |
| 1094 | + background: var( --os-dock-pinned-bg, transparent ); | |
| 1095 | + box-shadow: var( --os-dock-pinned-shadow, none ); | |
| 1047 | 1096 | } |
| 1048 | 1097 | |
| 1049 | 1098 | /* Separator — the line between two groups of tiles. The system one |
| 1050 | 1099 | * lives at the leading edge of `__pinned` (flex flow handles the |
| @@ -1054,12 +1103,12 @@ | ||
| 1054 | 1103 | * note on the vertical placements above for why there is only one. */ |
| 1055 | 1104 | .os-dock[ data-os-dock-placement="bottom" ] |
| 1056 | 1105 | .os-dock__separator { |
| 1057 | 1106 | position: relative; |
| 1058 | - width: 2px; | |
| 1107 | + width: var( --os-dock-separator-width, 2px ); | |
| 1059 | 1108 | /* Fixed height — `60%` collapses against the floating pill's |
| 1060 | 1109 | intrinsic height, leaving the line effectively invisible. */ |
| 1061 | - height: 34px; | |
| 1110 | + height: var( --os-dock-separator-height, 34px ); | |
| 1062 | 1111 | /* Symmetric horizontal margin so the divider sits centered in the |
| 1063 | 1112 | * inter-tile gap: the 6px flex gap on each side (`__scroll`→`__pinned` |
| 1064 | 1113 | * on the left, `__pinned`'s own gap on the right) plus an equal |
| 1065 | 1114 | * margin per side balances out. An asymmetric margin here nudges the |
| @@ -1065,23 +1114,34 @@ | ||
| 1065 | 1114 | * margin per side balances out. An asymmetric margin here nudges the |
| 1066 | 1115 | * divider — and the whole menu cluster with it — off the pill's |
| 1067 | 1116 | * center. Wider than the tile gap on purpose: the clusters need to |
| 1068 | 1117 | * read as groups before the line between them means anything. */ |
| 1069 | - margin: auto 14px; | |
| 1118 | + margin: auto var( --os-dock-separator-margin, 14px ); | |
| 1070 | 1119 | border-radius: 2px; |
| 1071 | - background: linear-gradient( | |
| 1072 | - to bottom, | |
| 1073 | - transparent 0%, | |
| 1074 | - var( --os-dock-divider, rgba( 217, 46, 227, 0.7 ) ) 28%, | |
| 1075 | - var( --os-dock-divider, rgba( 217, 46, 227, 0.7 ) ) 72%, | |
| 1076 | - transparent 100% | |
| 1120 | + /* | |
| 1121 | + * The glowing seam by default. A theme drawing an etched groove | |
| 1122 | + * instead answers `--os-dock-separator-bg` with a flat colour and | |
| 1123 | + * `--os-dock-separator-shadow` with the highlight beside it. | |
| 1124 | + */ | |
| 1125 | + background: var( | |
| 1126 | + --os-dock-separator-bg, | |
| 1127 | + linear-gradient( | |
| 1128 | + to bottom, | |
| 1129 | + transparent 0%, | |
| 1130 | + var( --os-dock-divider, rgba( 217, 46, 227, 0.7 ) ) 28%, | |
| 1131 | + var( --os-dock-divider, rgba( 217, 46, 227, 0.7 ) ) 72%, | |
| 1132 | + transparent 100% | |
| 1133 | + ) | |
| 1077 | 1134 | ); |
| 1078 | - box-shadow: 0 0 10px | |
| 1079 | - color-mix( | |
| 1080 | - in srgb, | |
| 1081 | - var( --os-dock-divider, rgba( 217, 46, 227, 0.7 ) ) 45%, | |
| 1082 | - transparent | |
| 1083 | - ); | |
| 1135 | + box-shadow: var( | |
| 1136 | + --os-dock-separator-shadow, | |
| 1137 | + 0 0 10px | |
| 1138 | + color-mix( | |
| 1139 | + in srgb, | |
| 1140 | + var( --os-dock-divider, rgba( 217, 46, 227, 0.7 ) ) 45%, | |
| 1141 | + transparent | |
| 1142 | + ) | |
| 1143 | + ); | |
| 1084 | 1144 | flex-shrink: 0; |
| 1085 | 1145 | } |
| 1086 | 1146 | |
| 1087 | 1147 | /* Tooltip — above the hovered tile. JS writes the horizontal center |
| @@ -1167,9 +1227,9 @@ | ||
| 1167 | 1227 | order: 1; |
| 1168 | 1228 | } |
| 1169 | 1229 | |
| 1170 | 1230 | .os-dock__item[ data-system-id="os-exit" ] .os-dock__item-primary { |
| 1171 | - border-radius: 50%; | |
| 1231 | + border-radius: var( --os-dock-exit-radius, 50% ); | |
| 1172 | 1232 | background-color: transparent; |
| 1173 | 1233 | box-shadow: inset 0 0 0 1px var( |
| 1174 | 1234 | --os-dock-exit-ring, |
| 1175 | 1235 | var( --os-dock-border, rgba( 255, 255, 255, 0.18 ) ) |
| @@ -1182,9 +1242,9 @@ | ||
| 1182 | 1242 | * inline for the horizontal pill, block for the vertical pillars. |
| 1183 | 1243 | */ |
| 1184 | 1244 | .os-dock[ data-os-dock-placement="bottom" ] |
| 1185 | 1245 | .os-dock__item[ data-system-id="os-exit" ] { |
| 1186 | - margin-inline-start: 10px; | |
| 1246 | + margin-inline-start: var( --os-dock-exit-gap, 10px ); | |
| 1187 | 1247 | } |
| 1188 | 1248 | |
| 1189 | 1249 | .os-dock[ data-os-dock-placement="left" ] |
| 1190 | 1250 | .os-dock__item[ data-system-id="os-exit" ], |
| @@ -1211,9 +1271,9 @@ | ||
| 1211 | 1271 | |
| 1212 | 1272 | .os-dock[ data-os-dock-placement="bottom" ] |
| 1213 | 1273 | .os-dock__item[ data-system-id="os-exit" ] |
| 1214 | 1274 | .os-dock__item-primary:hover { |
| 1215 | - transform: translateY( 2px ); | |
| 1275 | + transform: var( --os-dock-exit-hover-transform, translateY( 2px ) ); | |
| 1216 | 1276 | } |
| 1217 | 1277 | |
| 1218 | 1278 | .os-dock[ data-os-dock-placement="left" ] |
| 1219 | 1279 | .os-dock__item[ data-system-id="os-exit" ] |
| @@ -1362,8 +1422,23 @@ | ||
| 1362 | 1422 | |
| 1363 | 1423 | html.os-dock-vt::view-transition-old( root ), |
| 1364 | 1424 | html.os-dock-vt::view-transition-new( root ) { |
| 1365 | 1425 | animation: none; |
| 1426 | + } | |
| 1427 | + | |
| 1428 | + /* | |
| 1429 | + * The transition layer must not catch the pointer. By default it | |
| 1430 | + * does — the whole page reads as inert until the morph settles — | |
| 1431 | + * and with the root opted out of the snapshot that is worse than | |
| 1432 | + * pointless: the live desktop is right there under a layer that | |
| 1433 | + * swallows every mouseup and every pointerenter for 260ms. The | |
| 1434 | + * behavior module already holds a park back while a button is | |
| 1435 | + * down; this is the other half, so a hover that lands on a tile | |
| 1436 | + * while the rail is still morphing out starts its hover-intent | |
| 1437 | + * timer instead of waiting for the next pointer movement. | |
| 1438 | + */ | |
| 1439 | + html.os-dock-vt::view-transition { | |
| 1440 | + pointer-events: none; | |
| 1366 | 1441 | } |
| 1367 | 1442 | |
| 1368 | 1443 | ::view-transition-group( os-dock-os-dock ), |
| 1369 | 1444 | ::view-transition-group( os-dock-os-side-dock ) { |