@ash-qw/dsh-theme-prts 2.6.1 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ash-qw/dsh-theme-prts",
3
- "version": "2.6.1",
3
+ "version": "2.7.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Unofficial Arknights P.R.T.S.-inspired UI theme for DeepSeek Harness Web and the official desktop client",
@@ -69,7 +69,7 @@
69
69
  },
70
70
  "engines": {
71
71
  "node": ">=20.9.0",
72
- "dsh": "0.2.1-rc.2 || 0.2.1-rc.3 || 0.2.1-rc.5"
72
+ "dsh": "0.2.1-rc.2 || 0.2.1-rc.3 || 0.2.1-rc.5 || 0.2.2-rc.1"
73
73
  },
74
74
  "devDependencies": {
75
75
  "@playwright/test": "1.55.1",
@@ -13,6 +13,7 @@ export function createComposerGlassSurface({document, window, mount}) {
13
13
  surfaces.delete(card)
14
14
  }
15
15
  function sync() {
16
+ if (frame !== undefined) window.cancelAnimationFrame?.(frame)
16
17
  frame = undefined
17
18
  const cards = new Set(document.querySelectorAll('[data-composer-card], [data-prts-composer-fallback]'))
18
19
  for (const [card, entry] of surfaces) if (!cards.has(card)) remove(card, entry)
@@ -68,12 +69,21 @@ export function createComposerGlassSurface({document, window, mount}) {
68
69
  if (!mount) return
69
70
  document.documentElement.setAttribute('data-prts-composer-enhanced', '')
70
71
  if (!observer) {
71
- resize = new window.ResizeObserver(queue)
72
+ resize = new window.ResizeObserver(entries => {
73
+ if (entries.some(({target}) => !surfaces.has(target)
74
+ && target.offsetWidth && target.offsetHeight)) sync()
75
+ else queue()
76
+ })
72
77
  observer = new window.MutationObserver(records => {
73
78
  const selector = '[data-composer-card], [data-prts-composer-fallback]'
74
- if (records.some(record => record.type === 'attributes'
75
- || [...record.addedNodes, ...record.removedNodes].some(node =>
76
- node.nodeType === 1 && (node.matches(selector) || node.querySelector(selector))))) queue()
79
+ const containsComposer = node => node.nodeType === 1
80
+ && (node.matches(selector) || node.querySelector(selector))
81
+ const mounting = records.some(record =>
82
+ (record.type === 'attributes' && record.target.matches(selector) && !surfaces.has(record.target))
83
+ || [...record.addedNodes].some(containsComposer))
84
+ if (mounting) sync()
85
+ else if (records.some(record => record.type === 'attributes'
86
+ || [...record.removedNodes].some(containsComposer))) queue()
77
87
  })
78
88
  observer.observe(document.body, {childList:true, subtree:true, attributes:true, attributeFilter:['data-composer-card','data-prts-composer-fallback']})
79
89
  }
@@ -15,7 +15,7 @@ export function createCursorAdapter({document, window, assets}) {
15
15
  const root = document.documentElement
16
16
  let follower, img, point, moveFrame, timer, family, resting, pressed = false, phase
17
17
  let semantics, captureTarget, layerContext, stateObserver, watchedTarget, nativePicker
18
- let textContext, renderedX, renderedY
18
+ let textContext, renderedX, renderedY, nativeScrollbar=false
19
19
  let eventTarget, semanticTarget, semanticValue, pose, poseKind, dirty = true, hitDirty = true
20
20
  let suspended = false, visible = false, currentUrl, ready = false
21
21
  const staticPose=(rest,hotspot)=>({rest,hotspot})
@@ -78,7 +78,7 @@ export function createCursorAdapter({document, window, assets}) {
78
78
  play(family.release,()=>{stop();sync()})
79
79
  }
80
80
  function sync() {
81
- if (!follower || !ready || !point || nativePicker || suspended || document.hidden || document.pointerLockElement) return hide()
81
+ if (!follower || !ready || !point || nativePicker || nativeScrollbar || suspended || document.hidden || document.pointerLockElement) return hide()
82
82
  const hit=hitDirty || !eventTarget?.isConnected ? document.elementFromPoint(point.x,point.y) : eventTarget
83
83
  eventTarget=hit;hitDirty=false
84
84
  if(!hit || hit.closest('iframe'))return hide()
@@ -138,6 +138,7 @@ export function createCursorAdapter({document, window, assets}) {
138
138
  function flush() { moveFrame=undefined;sync() }
139
139
  function move(event) {
140
140
  if(event.pointerType!=='mouse')return
141
+ if(nativeScrollbar){if(event.buttons)return;nativeScrollbar=false}
141
142
  resumePicker(event)
142
143
  if(suspended && !event.buttons)suspended=false
143
144
  const unchanged=point?.x===event.clientX && point?.y===event.clientY && eventTarget===event.target
@@ -146,9 +147,34 @@ export function createCursorAdapter({document, window, assets}) {
146
147
  if(pressed && !(event.buttons&1)){stop();draw(resting)}
147
148
  if(!unchanged || dirty)if(moveFrame===undefined)moveFrame=window.requestAnimationFrame(flush)
148
149
  }
150
+ // Native scrollbar drags stop delivering mouse coordinates to the page.
151
+ // Measure only on press; never add geometry reads to ordinary movement.
152
+ function onScrollbar(event){
153
+ const el=event.target
154
+ if(!(el instanceof window.HTMLElement))return false
155
+ if(el===root || el===document.body){
156
+ if(event.clientX>=root.clientWidth && window.innerWidth>root.clientWidth)return true
157
+ if(event.clientY>=root.clientHeight && window.innerHeight>root.clientHeight)return true
158
+ }
159
+ if(el.offsetWidth<=el.clientWidth && el.offsetHeight<=el.clientHeight)return false
160
+ const style=window.getComputedStyle(el),rect=el.getBoundingClientRect()
161
+ if(!el.offsetWidth || !el.offsetHeight)return false
162
+ const x=(event.clientX-rect.left)*el.offsetWidth/rect.width
163
+ const y=(event.clientY-rect.top)*el.offsetHeight/rect.height
164
+ const left=parseFloat(style.borderLeftWidth)||0,right=parseFloat(style.borderRightWidth)||0
165
+ const top=parseFloat(style.borderTopWidth)||0,bottom=parseFloat(style.borderBottomWidth)||0
166
+ const inside=x>=left && x<el.offsetWidth-right && y>=top && y<el.offsetHeight-bottom
167
+ if(!inside)return false
168
+ const vertical=el.scrollHeight>el.clientHeight && /^(auto|scroll)$/.test(style.overflowY)
169
+ && el.offsetWidth-el.clientWidth-left-right>0 && (x<el.clientLeft || x>=el.clientLeft+el.clientWidth)
170
+ const horizontal=el.scrollWidth>el.clientWidth && /^(auto|scroll)$/.test(style.overflowX)
171
+ && el.offsetHeight-el.clientHeight-top-bottom>0 && y>=el.clientTop+el.clientHeight
172
+ return vertical || horizontal
173
+ }
149
174
  function down(event) {
150
175
  if(event.pointerType!=='mouse'){reset();return}
151
176
  if(event.button!==0||event.isPrimary===false)return
177
+ if(onScrollbar(event)){reset();nativeScrollbar=true;return}
152
178
  const picker=event.target.closest?.('select,input[type="file"],input[type="color"]')
153
179
  if(picker){nativePicker=picker;reset();return}
154
180
  nativePicker=undefined
@@ -177,6 +203,7 @@ export function createCursorAdapter({document, window, assets}) {
177
203
  }
178
204
  function over(event) {
179
205
  if(event.pointerType!=='mouse')return
206
+ if(nativeScrollbar){if(event.buttons)return;nativeScrollbar=false}
180
207
  resumePicker(event)
181
208
  if(moveFrame!==undefined)window.cancelAnimationFrame(moveFrame)
182
209
  moveFrame=undefined
@@ -185,6 +212,7 @@ export function createCursorAdapter({document, window, assets}) {
185
212
  sync()
186
213
  }
187
214
  function up(event) {
215
+ if(nativeScrollbar && event.pointerType==='mouse' && event.button===0){nativeScrollbar=false;move(event);return}
188
216
  if(event.pointerType!=='mouse'||event.button!==0||!pressed)return
189
217
  pressed=false;dirty=true
190
218
  if(reduced()){stop();draw(resting);return}
@@ -192,7 +220,7 @@ export function createCursorAdapter({document, window, assets}) {
192
220
  }
193
221
  function reset() {
194
222
  if(moveFrame!==undefined)window.cancelAnimationFrame(moveFrame)
195
- moveFrame=undefined;point=undefined;eventTarget=undefined;hitDirty=true;captureTarget=undefined;hide()
223
+ moveFrame=undefined;point=undefined;eventTarget=undefined;hitDirty=true;captureTarget=undefined;nativeScrollbar=false;hide()
196
224
  }
197
225
  function blur(event){if(event.target===window)reset()}
198
226
  function leave(event){if(!event.relatedTarget || event.relatedTarget.closest?.('iframe'))reset()}
@@ -440,12 +440,17 @@ export function apply(ctx) {
440
440
  defineStore,
441
441
  mountComposerGlassSurface(container, props) {
442
442
  const { createRoot } = require('react-dom/client')
443
+ const materialStyle = { backdropFilter: 'blur(5px) saturate(1)', WebkitBackdropFilter: 'blur(5px) saturate(1)' }
444
+ const placeholder = document.createElement('div')
445
+ placeholder.className = 'glass-surface glass-surface--fallback'
446
+ Object.assign(placeholder.style, { width: '100%', height: '100%', ...materialStyle })
447
+ container.append(placeholder)
443
448
  const root = createRoot(container)
444
449
  const update = props => root.render(React.createElement(PrtsGlassSurface.default, {
445
450
  width: '100%', height: '100%',
446
- // Gentle edge refraction; a fully calm center avoids shifting input content.
447
- distortionScale: -18, redOffset: 0, greenOffset: 1, blueOffset: 2,
448
- opacity: 1, backgroundOpacity: 0.5, displace: 5,
451
+ refraction: false,
452
+ style: materialStyle,
453
+ opacity: 1, backgroundOpacity: 0.5,
449
454
  ...props,
450
455
  }))
451
456
  update(props)
@@ -241,7 +241,8 @@ export function normalizePreferences(value) {
241
241
  cornerColor: colorOr(input.cornerColor, DEFAULT_PREFERENCES.cornerColor),
242
242
  cornerColorLight: colorOr(input.cornerColorLight, colorOr(input.cornerColor, DEFAULT_PREFERENCES.cornerColor)),
243
243
  cornerCustomColorLight: colorOr(input.cornerCustomColorLight, colorOr(input.cornerCustomColor, DEFAULT_PREFERENCES.cornerCustomColor)),
244
- cursor: ['system', 'prts-follower'].includes(input.cursor) ? input.cursor : DEFAULT_PREFERENCES.cursor,
244
+ // The follower experiment is paused; stored/imported values fall back to native PRTS.
245
+ cursor: input.cursor === 'system' ? 'system' : DEFAULT_PREFERENCES.cursor,
245
246
  conversationParticleDensity: enumOr(legacyDensities.conversation, PARTICLE_DENSITIES, particlePreset.conversationParticleDensity),
246
247
  heroParticleDensity: enumOr(legacyDensities.hero, PARTICLE_DENSITIES, particlePreset.heroParticleDensity),
247
248
  particleTraversalSpeed: particleTraversalSpeedOr(
@@ -52,7 +52,10 @@ export function resolveRc7Regions(document, report = () => {}) {
52
52
  return null
53
53
  }
54
54
 
55
- const frame = closestCommonContainer(root, [sidebar, center, auxiliary])
55
+ const centerColumn = center.parentElement?.parentElement === auxiliary.parentElement
56
+ ? center.parentElement
57
+ : center
58
+ const frame = closestCommonContainer(root, [sidebar, centerColumn, auxiliary])
56
59
  if (!frame) {
57
60
  report('common layout container is unavailable')
58
61
  return null
@@ -62,7 +65,7 @@ export function resolveRc7Regions(document, report = () => {}) {
62
65
  root,
63
66
  frame,
64
67
  sidebar,
65
- center,
68
+ center: centerColumn,
66
69
  auxiliary,
67
70
  sidebarSlot,
68
71
  centerSlot,
@@ -19,6 +19,8 @@ const OWNED_ATTRIBUTES = [
19
19
  'data-prts-session-menu-anchor',
20
20
  'data-prts-session-menu',
21
21
  'data-prts-session-time',
22
+ 'data-prts-session-resting',
23
+ 'data-prts-session-pin',
22
24
  'data-prts-session-index',
23
25
  'data-prts-session-state',
24
26
  'data-prts-selection-target',
@@ -106,15 +108,16 @@ function markSidebarNode(node, attribute, next) {
106
108
  }
107
109
 
108
110
  function resolveRowControls(row, kind) {
109
- const menu = row.querySelector(':scope > span > span > button[type="button"]')
110
- const anchor = menu?.parentElement
111
+ const menu = row.querySelector(':scope > span > button[type="button"]:is([data-context-menu-trigger], [aria-haspopup="menu"])')
112
+ ?? row.querySelector(':scope > span > span > button[type="button"]')
113
+ const anchor = menu?.parentElement?.parentElement === row ? menu : menu?.parentElement
111
114
  // Ungrouped workspaces have a create button but no management menu.
112
115
  const actions = anchor?.parentElement ?? (kind === 'workspace'
113
116
  ? Array.from(row.children).find(node => node.matches('span') && node.querySelector(':scope > button[type="button"]'))
114
117
  : undefined)
115
118
  if (actions?.parentElement !== row) return {}
116
119
  const create = kind === 'workspace'
117
- ? actions.querySelector(':scope > button[type="button"]')
120
+ ? Array.from(actions.children).find(child => child !== anchor && child.matches('button[type="button"]'))
118
121
  : undefined
119
122
  const quickActions = kind === 'session'
120
123
  ? Array.from(actions.children).filter(child => child !== anchor && child.querySelector('button'))
@@ -122,6 +125,11 @@ function resolveRowControls(row, kind) {
122
125
  return { actions, anchor, create, menu, quickActions }
123
126
  }
124
127
 
128
+ function isRowMenuOpen(row, menu) {
129
+ return menu?.getAttribute('aria-expanded') === 'true'
130
+ || Array.from(row.classList).some(token => token === 'menuOpen' || token.endsWith('_menuOpen'))
131
+ }
132
+
125
133
  function resolveRowTitle(row, kind, actions) {
126
134
  const candidates = Array.from(row.querySelectorAll(':scope > span')).filter(node => (
127
135
  node !== actions
@@ -158,10 +166,11 @@ function resolveWorkspaceDisclosure(row, title, actions, icon) {
158
166
  ))
159
167
  }
160
168
 
161
- function resolveSessionTime(row, title, actions) {
169
+ function resolveSessionTime(row, title, actions, pin) {
162
170
  const candidates = Array.from(row.querySelectorAll(':scope > span')).filter(node => (
163
171
  node !== title
164
172
  && node !== actions
173
+ && node !== pin
165
174
  && !node.hasAttribute('data-prts-facility-face')
166
175
  && !node.hasAttribute('data-prts-row-projection')
167
176
  && !node.querySelector('button')
@@ -171,6 +180,18 @@ function resolveSessionTime(row, title, actions) {
171
180
  ?? candidates.filter(node => node.getAttribute('aria-hidden') !== 'true' && !node.querySelector('[data-state]')).at(-1)
172
181
  }
173
182
 
183
+ function resolveSessionTrailing(row, title, actions) {
184
+ const pin = row.querySelector('[class*="_pinIndicator"], [aria-label="Pinned"]')
185
+ const resting = Array.from(row.children).find(node => node !== title && node !== actions && node !== pin && (
186
+ (pin && node.contains(pin))
187
+ || Array.from(node.classList).some(token => token === 'rowResting' || token.endsWith('_rowResting'))
188
+ ))
189
+ const time = resting
190
+ ? resting.querySelector('time, [data-session-time], [class*="_timestamp"], [class*="_time"]')
191
+ : resolveSessionTime(row, title, actions, pin)
192
+ return { pin, resting, time }
193
+ }
194
+
174
195
  function ensureFacilityFace(document, row, kind, next) {
175
196
  let face = row.querySelector(':scope > [data-prts-facility-face]')
176
197
  if (!face) {
@@ -916,8 +937,7 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
916
937
  const icon = resolveWorkspaceIcon(row, title, controls.actions)
917
938
  markSidebarNode(icon, 'data-prts-workspace-icon', next)
918
939
  markSidebarNode(resolveWorkspaceDisclosure(row, title, controls.actions, icon), 'data-prts-workspace-disclosure', next)
919
- row.toggleAttribute('data-prts-row-menu-open', controls.menu?.getAttribute('aria-expanded') === 'true'
920
- || row.classList.contains('menuOpen'))
940
+ row.toggleAttribute('data-prts-row-menu-open', isRowMenuOpen(row, controls.menu))
921
941
  markSidebarNode(controls.actions, 'data-prts-workspace-actions', next)
922
942
  markSidebarNode(controls.anchor, 'data-prts-workspace-menu-anchor', next)
923
943
  markSidebarNode(controls.menu, 'data-prts-workspace-menu', next)
@@ -963,10 +983,12 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
963
983
  setSidebarAttribute(row, 'data-prts-session-index', sessionIndex)
964
984
  const title = resolveRowTitle(row, 'session', controls.actions)
965
985
  markSidebarNode(title, 'data-prts-row-title', next)
966
- markSidebarNode(resolveSessionTime(row, title, controls.actions), 'data-prts-session-time', next)
986
+ const trailing = resolveSessionTrailing(row, title, controls.actions)
987
+ markSidebarNode(trailing.time, 'data-prts-session-time', next)
988
+ markSidebarNode(trailing.resting, 'data-prts-session-resting', next)
989
+ markSidebarNode(trailing.pin, 'data-prts-session-pin', next)
967
990
  if (title) setSidebarAttribute(title, 'data-prts-session-index', sessionIndex)
968
- row.toggleAttribute('data-prts-row-menu-open', controls.menu?.getAttribute('aria-expanded') === 'true'
969
- || row.classList.contains('menuOpen'))
991
+ row.toggleAttribute('data-prts-row-menu-open', isRowMenuOpen(row, controls.menu))
970
992
  markSidebarNode(controls.actions, 'data-prts-session-actions', next)
971
993
  for (const action of controls.quickActions ?? []) markSidebarNode(action, 'data-prts-session-quick-actions', next)
972
994
  markSidebarNode(controls.anchor, 'data-prts-session-menu-anchor', next)
@@ -21,7 +21,7 @@ const CURSOR_DESCRIPTIONS = {
21
21
  }
22
22
 
23
23
  const COMMON_CONTROLS = [
24
- ['cursor', '光标模式', [['system', '系统光标'], ['prts', 'PRTS 原生光标'], ['prts-follower', 'PRTS 跟随光标(实验)']]],
24
+ ['cursor', '光标模式', [['system', '系统光标'], ['prts', 'PRTS 原生光标']]],
25
25
  ['railDefaultHidden', '默认隐藏导航栏', [['false', '关闭'], ['true', '开启']]],
26
26
  ['motion', '动态效果', []],
27
27
  ['sessionFlow', '当前会话流线', [['false', '关闭'], ['true', '开启']]],
@@ -3,8 +3,8 @@ html[data-dsh-prts] { --prts-background-wash: color-mix(in srgb, var(--prts-canv
3
3
  html[data-dsh-prts][data-prts-background-mode="full"][data-prts-background-full] :is([data-prts-region="frame"], [data-prts-nav-rail]) {
4
4
  background: linear-gradient(var(--prts-background-wash), var(--prts-background-wash)), var(--prts-background-full) var(--prts-protected-full-x, 50%) var(--prts-protected-full-y, 50%) / cover fixed;
5
5
  }
6
- html[data-dsh-prts][data-prts-background-mode="full"][data-prts-background-full] :is([data-prts-region="sessions"], [data-prts-region="operation"]) { background: transparent; }
7
- html[data-dsh-prts][data-prts-background-mode="split"][data-prts-background-sidebar] {
6
+ html[data-dsh-prts][data-dsh-prts][data-prts-background-mode="full"][data-prts-background-full] :is([data-prts-region="sessions"], [data-prts-region="operation"]) { background: transparent; }
7
+ html[data-dsh-prts][data-dsh-prts][data-prts-background-mode="split"][data-prts-background-sidebar] {
8
8
  & :is([data-prts-region="sessions"],[data-prts-nav-rail]) {
9
9
  --prts-wall-width:var(--prts-protected-sidebar-width,max(calc(var(--prts-sidebar-width,280px) + var(--prts-nav-width)),calc((100dvh - var(--prts-host-top-inset)) * var(--prts-sidebar-image-ratio,1))));
10
10
  --prts-wall-x:var(--prts-protected-sidebar-x,calc((var(--prts-sidebar-width,280px) + var(--prts-nav-width) - var(--prts-wall-width)) / 2));
@@ -996,6 +996,10 @@ html[data-dsh-prts] [data-prts-session-actions] {
996
996
  transform: translate3d(var(--prts-row-shift), 0, 0);
997
997
  }
998
998
 
999
+ html[data-dsh-prts] :is([data-prts-workspace-row], [data-prts-session-row]):is(:hover, :focus-within, [data-prts-row-menu-open]) :is([data-prts-workspace-actions], [data-prts-session-actions]) {
1000
+ display: inline-flex;
1001
+ }
1002
+
999
1003
  html[data-dsh-prts] [data-prts-workspace-actions] {
1000
1004
  width: 57px;
1001
1005
  }
@@ -1023,6 +1027,7 @@ html[data-dsh-prts] [data-prts-session-actions] button {
1023
1027
  min-width: 28px !important;
1024
1028
  height: var(--prts-facility-height) !important;
1025
1029
  min-height: var(--prts-facility-height) !important;
1030
+ margin: 0 !important;
1026
1031
  display: grid !important;
1027
1032
  place-items: center;
1028
1033
  padding: 0 !important;
@@ -1046,11 +1051,11 @@ html[data-dsh-prts] [data-prts-session-actions] button:is(:hover, :focus-visible
1046
1051
  animation: prts-facility-button-dock 520ms both;
1047
1052
  }
1048
1053
 
1049
- html[data-dsh-prts] [data-prts-workspace-row]:is(:hover, :focus-within, [data-prts-row-menu-open]) [data-prts-workspace-actions] > :nth-child(1) button {
1054
+ html[data-dsh-prts] [data-prts-workspace-row]:is(:hover, :focus-within, [data-prts-row-menu-open]) [data-prts-workspace-menu] {
1050
1055
  animation-delay: 55ms;
1051
1056
  }
1052
1057
 
1053
- html[data-dsh-prts] [data-prts-workspace-row]:is(:hover, :focus-within, [data-prts-row-menu-open]) [data-prts-workspace-actions] > :nth-child(2) {
1058
+ html[data-dsh-prts] [data-prts-workspace-row]:is(:hover, :focus-within, [data-prts-row-menu-open]) [data-prts-workspace-create] {
1054
1059
  animation-delay: 125ms;
1055
1060
  }
1056
1061
  }
@@ -136,7 +136,12 @@ html[data-dsh-prts] [data-prts-session-actions] button:is(:hover, :focus-visible
136
136
  background: var(--prts-yellow) !important;
137
137
  }
138
138
 
139
- html[data-dsh-prts] [data-prts-session-time] {
139
+ html[data-dsh-prts] [data-prts-session-row] > [data-prts-row-title]:last-child {
140
+ margin-right: var(--prts-row-end-reserve);
141
+ }
142
+
143
+ html[data-dsh-prts] [data-prts-session-time],
144
+ html[data-dsh-prts] [data-prts-session-resting] {
140
145
  position: relative;
141
146
  z-index: 3;
142
147
  flex: 0 0 auto;
@@ -146,15 +151,77 @@ html[data-dsh-prts] [data-prts-session-time] {
146
151
  transition: opacity 120ms ease, transform 220ms var(--prts-ease-spring);
147
152
  }
148
153
 
149
- /* DSH keeps its pin in the row's trailing slot; move that slot inside our face. */
150
- html[data-dsh-prts] [data-prts-session-row] > :is([aria-label="Pinned"], [class*="_pinIndicator"]) {
154
+ html[data-dsh-prts] [data-prts-session-resting] {
155
+ align-items: center;
156
+ gap: 8px;
157
+ }
158
+
159
+ html[data-dsh-prts] [data-prts-session-resting]:has([data-prts-session-pin]) {
160
+ display: inline-flex !important;
161
+ flex-shrink: 1;
162
+ min-width: 0;
163
+ margin-right: calc(var(--prts-row-end-reserve) + 6px);
164
+ padding-left: 0;
165
+ }
166
+
167
+ html[data-dsh-prts] [data-prts-session-row]:has([data-prts-session-pin]) [data-prts-row-title] {
168
+ padding-left: clamp(0px, calc(50% - 60px), 13px);
169
+ padding-right: clamp(0px, calc(50% - 60px), 10px);
170
+ }
171
+
172
+ html[data-dsh-prts] [data-prts-session-row]:has([data-prts-session-pin]) [data-prts-session-time] {
173
+ flex-shrink: 1;
174
+ min-width: 0;
175
+ overflow: hidden;
176
+ }
177
+
178
+ html[data-dsh-prts] [data-prts-session-resting] [data-prts-session-time] {
179
+ margin: 0;
180
+ padding: 0;
181
+ transform: none;
182
+ }
183
+
184
+ html[data-dsh-prts] [data-prts-session-pin] {
185
+ display: inline-flex !important;
186
+ flex: 0 0 16px;
187
+ width: 16px;
188
+ margin-left: 0;
189
+ align-items: center;
190
+ justify-content: center;
191
+ }
192
+
193
+ html[data-dsh-prts] [data-prts-session-row] > [data-prts-session-pin] {
151
194
  margin-right: calc(var(--prts-row-end-reserve) + 6px);
152
195
  }
153
196
 
154
- html[data-dsh-prts] [data-prts-session-row]:has(> :is([aria-label="Pinned"], [class*="_pinIndicator"])) [data-prts-session-time] {
197
+ html[data-dsh-prts] [data-prts-session-row]:has(> [data-prts-session-pin]) [data-prts-session-time] {
155
198
  margin-right: 8px;
156
199
  }
157
200
 
201
+ html[data-dsh-prts] [data-prts-session-row]:is(:hover, :focus-within, [data-prts-row-menu-open]) [data-prts-session-resting] {
202
+ margin-right: 8px;
203
+ }
204
+
205
+ html[data-dsh-prts] [data-prts-session-row]:is(:hover, :focus-within, [data-prts-row-menu-open]) > [data-prts-session-pin] {
206
+ margin-right: 6px;
207
+ }
208
+
209
+ html[data-dsh-prts] [data-prts-session-row]:is(:hover, :focus-within, [data-prts-row-menu-open], [data-prts-selection-target="true"], [aria-selected="true"]:not([data-prts-selection-target="false"])):has([data-prts-session-pin]) [data-prts-session-time],
210
+ html[data-dsh-prts] [data-prts-session-row]:is(:hover, :focus-within, [data-prts-row-menu-open]) [data-prts-session-resting]:not(:has([data-prts-session-pin])) {
211
+ display: none !important;
212
+ }
213
+
214
+ @media (hover: none) {
215
+ html[data-dsh-prts] [data-prts-session-resting],
216
+ html[data-dsh-prts] [data-prts-session-resting]:has([data-prts-session-pin]) {
217
+ margin-right: 8px;
218
+ }
219
+
220
+ html[data-dsh-prts] [data-prts-session-row] > [data-prts-session-pin] {
221
+ margin-right: 6px;
222
+ }
223
+ }
224
+
158
225
  html[data-dsh-prts] [data-prts-session-row]:hover [data-prts-session-time] {
159
226
  opacity: 0;
160
227
  }