@ash-qw/dsh-theme-prts 0.1.93 → 0.1.95

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.
@@ -1,5 +1,4 @@
1
- import { CONVERSATION_SCALE_FOCUS_CONTRAST_DEFAULT, CONVERSATION_SCALE_FOCUS_CONTRAST_MAX, CONVERSATION_SCALE_FOCUS_CONTRAST_MIN, CONVERSATION_SCALE_FOCUS_CONTRAST_STEP, PARTICLE_TRAVERSAL_SPEED_DEFAULT, PARTICLE_TRAVERSAL_SPEED_MAX, PARTICLE_TRAVERSAL_SPEED_MIN, PARTICLE_TRAVERSAL_SPEED_STEP, resolveParticleDetail } from './preferences.js'
2
- import { resolveConversationScaleLengths } from './conversation-scale-adapter.js'
1
+ import { PARTICLE_TRAVERSAL_SPEED_DEFAULT, PARTICLE_TRAVERSAL_SPEED_MAX, PARTICLE_TRAVERSAL_SPEED_MIN, PARTICLE_TRAVERSAL_SPEED_STEP, resolveParticleDetail } from './preferences.js'
3
2
 
4
3
  const SETTINGS_FOCUSABLE = [
5
4
  'button:not([disabled])',
@@ -57,24 +56,6 @@ function particleMarkup() {
57
56
  </button>`).join('')
58
57
  }
59
58
 
60
- function calibrationMarkup() {
61
- return `<div data-prts-scale-calibration data-prts-calibration-mode="hidden" data-prts-calibration-reason="unmeasured">
62
- <div data-prts-scale-calibration-viewport>
63
- <div data-prts-scale-calibration-canvas aria-hidden="true">
64
- <i data-prts-scale-calibration-sidebar></i>
65
- <span data-prts-scale-calibration-measure><i></i><output data-prts-scale-calibration-value>96 px</output></span>
66
- <span data-prts-scale-calibration-rail>${Array.from({ length: 9 }, (_, index) => `<i style="--prts-calibration-tick:${index}"></i>`).join('')}</span>
67
- <i data-prts-scale-calibration-gap></i>
68
- <span data-prts-scale-calibration-content><i></i><small>会话内容区</small></span>
69
- </div>
70
- </div>
71
- <div data-prts-scale-calibration-meta>
72
- <span data-prts-scale-calibration-scale hidden>缩放预览</span>
73
- <output data-prts-scale-calibration-status aria-live="polite">当前视图:几何测量中</output>
74
- </div>
75
- </div>`
76
- }
77
-
78
59
  export function themeSettingsMarkup() {
79
60
  return `<div data-prts-settings-backdrop hidden aria-hidden="true"></div>
80
61
  <dialog id="prts-theme-settings" data-prts-theme-settings aria-label="P.R.T.S. 主题设置" aria-hidden="true">
@@ -100,7 +81,7 @@ export function themeSettingsMarkup() {
100
81
  </section>
101
82
 
102
83
  <details data-prts-settings-advanced>
103
- <summary><span><small>精细调整</small><strong>粒子与会话刻度</strong></span><output data-prts-advanced-summary>标准 / 96 px</output></summary>
84
+ <summary><span><small>精细调整</small><strong>粒子效果</strong></span><output data-prts-advanced-summary>标准 / 1×</output></summary>
104
85
  <div data-prts-settings-advanced-content>
105
86
  <section data-prts-particle-detail>
106
87
  <header><strong>粒子精度</strong><span>同时调整会话与新会话徽记</span></header>
@@ -111,22 +92,6 @@ export function themeSettingsMarkup() {
111
92
  </label>
112
93
  <span data-prts-particle-error role="alert" hidden>粒子资源加载异常,主题已使用静态后备效果</span>
113
94
  </section>
114
- <section data-prts-scale-adjustment>
115
- <header><strong>会话刻度</strong><span>调整位置距离与悬停焦点的视觉区分</span></header>
116
- ${calibrationMarkup()}
117
- <label data-prts-setting-row="conversationScaleMaxDistance" data-prts-setting-range-row>
118
- <span>最大距离</span>
119
- <div><input type="range" min="16" max="240" step="8" value="96" data-prts-setting-range data-prts-setting-key="conversationScaleMaxDistance" aria-label="会话刻度最大距离"><output data-prts-scale-distance-output>96 px</output></div>
120
- </label>
121
- <label data-prts-setting-row="conversationScaleFocusContrast" data-prts-setting-range-row>
122
- <span>聚焦区分度</span>
123
- <div data-prts-scale-focus-control>
124
- <span data-prts-scale-focus-preview aria-hidden="true">${Array.from({ length: 5 }, (_, index) => `<i data-prts-scale-focus-preview-tick="${index}"></i>`).join('')}</span>
125
- <input type="range" min="0" max="100" step="10" value="70" data-prts-setting-range data-prts-setting-key="conversationScaleFocusContrast" aria-label="会话刻度聚焦区分度">
126
- <output data-prts-scale-focus-output>70</output>
127
- </div>
128
- </label>
129
- </section>
130
95
  </div>
131
96
  </details>
132
97
 
@@ -160,7 +125,6 @@ export function createThemeSettingsOverlay({
160
125
  onPreferencePreview = () => {},
161
126
  onResetVisual = () => {},
162
127
  onRetrySave = () => {},
163
- getConversationScalePreview = () => ({ visible: false, reason: 'unmeasured', mode: 'hidden' }),
164
128
  }) {
165
129
  const window = document?.defaultView
166
130
  const transparencyMedia = window?.matchMedia?.('(prefers-reduced-transparency: reduce)')
@@ -171,17 +135,8 @@ export function createThemeSettingsOverlay({
171
135
  let currentPreferences
172
136
  let currentStatus
173
137
  let currentPersistence = { phase: 'idle', revision: 0 }
174
- let scaleDistanceDraft
175
- let scaleDistanceDirty = false
176
- let scaleFocusContrastDraft
177
- let scaleFocusContrastDirty = false
178
138
  let particleTraversalSpeedDraft
179
139
  let particleTraversalSpeedDirty = false
180
- let calibrationResizeObserver
181
- let calibrationSettleTimer
182
- let calibrationFrame
183
- let calibrationViewportWidth
184
- let calibrationFactor
185
140
  let savedTimer
186
141
  let feedbackTimer
187
142
  let feedbackTarget
@@ -230,8 +185,6 @@ export function createThemeSettingsOverlay({
230
185
  const value = Boolean(next)
231
186
  if (value === isOpen) return isOpen
232
187
  if (!value) {
233
- commitScaleDistance()
234
- commitScaleFocusContrast()
235
188
  commitParticleTraversalSpeed()
236
189
  }
237
190
  isOpen = value
@@ -243,7 +196,6 @@ export function createThemeSettingsOverlay({
243
196
  onOpen()
244
197
  showPanel()
245
198
  panel.setAttribute('data-prts-settings-visible', '')
246
- renderScaleCalibration()
247
199
  ;(panel.querySelector('[data-prts-theme-settings-close]') ?? focusable()[0] ?? panel).focus?.()
248
200
  } else {
249
201
  panel.removeAttribute('data-prts-settings-visible')
@@ -254,27 +206,6 @@ export function createThemeSettingsOverlay({
254
206
  return isOpen
255
207
  }
256
208
 
257
- function normalizeScaleDistance(value) {
258
- const numeric = Number(value)
259
- if (!Number.isFinite(numeric)) return 96
260
- return Math.min(240, Math.max(16, Math.round(numeric / 8) * 8))
261
- }
262
-
263
- function currentScaleDistance() {
264
- return normalizeScaleDistance(scaleDistanceDirty ? scaleDistanceDraft : currentPreferences?.conversationScaleMaxDistance)
265
- }
266
-
267
- function normalizeScaleFocusContrast(value) {
268
- const numeric = Number(value)
269
- if (!Number.isFinite(numeric)) return CONVERSATION_SCALE_FOCUS_CONTRAST_DEFAULT
270
- const clamped = Math.min(CONVERSATION_SCALE_FOCUS_CONTRAST_MAX, Math.max(CONVERSATION_SCALE_FOCUS_CONTRAST_MIN, numeric))
271
- return Math.round(clamped / CONVERSATION_SCALE_FOCUS_CONTRAST_STEP) * CONVERSATION_SCALE_FOCUS_CONTRAST_STEP
272
- }
273
-
274
- function currentScaleFocusContrast() {
275
- return normalizeScaleFocusContrast(scaleFocusContrastDirty ? scaleFocusContrastDraft : currentPreferences?.conversationScaleFocusContrast)
276
- }
277
-
278
209
  function normalizeParticleTraversalSpeed(value) {
279
210
  const numeric = Number(value)
280
211
  if (!Number.isFinite(numeric)) return PARTICLE_TRAVERSAL_SPEED_DEFAULT
@@ -306,142 +237,10 @@ export function createThemeSettingsOverlay({
306
237
  setText(panel.querySelector('[data-prts-particle-traversal-output]'), particleTraversalLabel(value))
307
238
  }
308
239
 
309
- function calibrationStatus(state, value) {
310
- if (state?.mode === 'configured') return `当前视图:使用配置上限 / ${Math.round(Number(state.left) || value)} px`
311
- if (state?.simulated) return `模拟布局:使用配置上限 / ${value} px`
312
- if (state?.mode === 'centered') return `当前视图:自动居中 / 距侧栏 ${Math.round(Number(state.left) || 0)} px`
313
- const reasons = {
314
- drawer: '抽屉布局', phone: '手机布局', turns: '消息不足', corridor: '会话走廊不足',
315
- preview: '会话预览空间不足', unmeasured: '模拟布局',
316
- }
317
- return `当前视图:隐藏 / ${reasons[state?.reason] || '空间不足'}`
318
- }
319
-
320
240
  function setText(node, value) {
321
241
  if (node && node.textContent !== value) node.textContent = value
322
242
  }
323
243
 
324
- function setCalibrationResizeState(active) {
325
- for (const node of [panel, backdrop]) {
326
- if (!node || node.hasAttribute('data-prts-resizing') === active) continue
327
- node.toggleAttribute('data-prts-resizing', active)
328
- }
329
- }
330
-
331
- function cancelCalibrationFrame() {
332
- if (calibrationFrame === undefined) return
333
- window?.cancelAnimationFrame?.(calibrationFrame)
334
- window?.clearTimeout?.(calibrationFrame)
335
- calibrationFrame = undefined
336
- }
337
-
338
- function measureScaleCalibration() {
339
- calibrationFrame = undefined
340
- if (!isOpen) return
341
- const viewport = panel?.querySelector?.('[data-prts-scale-calibration-viewport]')
342
- const canvas = panel?.querySelector?.('[data-prts-scale-calibration-canvas]')
343
- const calibration = panel?.querySelector?.('[data-prts-scale-calibration]')
344
- const scaleNote = panel?.querySelector?.('[data-prts-scale-calibration-scale]')
345
- if (!viewport || !canvas || !calibration) return
346
- const available = calibrationViewportWidth || viewport.clientWidth
347
- const factor = available > 0 ? Math.min(1, available / 360) : 1
348
- const roundedFactor = Number(factor.toFixed(4))
349
- const value = currentScaleDistance()
350
- let state
351
- try { state = getConversationScalePreview(value) } catch { state = { visible: false, reason: 'unmeasured', mode: 'hidden' } }
352
-
353
- if (roundedFactor !== calibrationFactor) {
354
- calibrationFactor = roundedFactor
355
- canvas.style.transform = `scale(${roundedFactor})`
356
- viewport.style.height = `${Math.ceil(94 * roundedFactor)}px`
357
- }
358
- const scaled = factor < .999
359
- if (calibration.hasAttribute('data-prts-calibration-scaled') !== scaled) calibration.toggleAttribute('data-prts-calibration-scaled', scaled)
360
- if (scaleNote && scaleNote.hidden !== !scaled) scaleNote.hidden = !scaled
361
- const mode = state?.simulated ? 'simulated' : state?.mode || 'hidden'
362
- const reason = state?.reason || 'unmeasured'
363
- if (calibration.dataset.prtsCalibrationMode !== mode) calibration.dataset.prtsCalibrationMode = mode
364
- if (calibration.dataset.prtsCalibrationReason !== reason) calibration.dataset.prtsCalibrationReason = reason
365
- setText(panel.querySelector('[data-prts-scale-calibration-status]'), calibrationStatus(state, value))
366
- }
367
-
368
- function scheduleCalibrationMeasurement() {
369
- if (!isOpen) return
370
- cancelCalibrationFrame()
371
- calibrationFrame = window?.requestAnimationFrame?.(measureScaleCalibration)
372
- ?? window?.setTimeout?.(measureScaleCalibration, 16)
373
- }
374
-
375
- function scheduleScalePreviewRefresh(entries = []) {
376
- const viewportEntry = entries.find?.(entry => entry.target?.matches?.('[data-prts-scale-calibration-viewport]'))
377
- const observedWidth = Number(viewportEntry?.contentRect?.width)
378
- if (Number.isFinite(observedWidth) && observedWidth > 0) {
379
- calibrationViewportWidth = observedWidth
380
- }
381
- if (!isOpen) return
382
- setCalibrationResizeState(true)
383
- if (calibrationSettleTimer !== undefined) window?.clearTimeout?.(calibrationSettleTimer)
384
- calibrationSettleTimer = window?.setTimeout?.(() => {
385
- calibrationSettleTimer = undefined
386
- setCalibrationResizeState(false)
387
- renderScaleCalibration()
388
- }, 160)
389
- }
390
-
391
- function renderScaleCalibration() {
392
- if (!isOpen) return
393
- if (!panel || !currentPreferences) return
394
- const value = currentScaleDistance()
395
- const contrast = currentScaleFocusContrast()
396
- const lengths = resolveConversationScaleLengths(contrast)
397
- const calibration = panel.querySelector('[data-prts-scale-calibration]')
398
- const distanceRange = panel.querySelector('input[data-prts-setting-range][data-prts-setting-key="conversationScaleMaxDistance"]')
399
- const contrastRange = panel.querySelector('input[data-prts-setting-range][data-prts-setting-key="conversationScaleFocusContrast"]')
400
- const distanceOutput = panel.querySelector('[data-prts-scale-distance-output]')
401
- const contrastOutput = panel.querySelector('[data-prts-scale-focus-output]')
402
- const calibrationValue = panel.querySelector('[data-prts-scale-calibration-value]')
403
- if (distanceRange && distanceRange.value !== String(value)) distanceRange.value = String(value)
404
- if (contrastRange && contrastRange.value !== String(contrast)) contrastRange.value = String(contrast)
405
- setText(distanceOutput, `${value} px`)
406
- setText(contrastOutput, String(contrast))
407
- setText(calibrationValue, `${value} px`)
408
- for (const tick of panel.querySelectorAll('[data-prts-scale-focus-preview-tick]')) {
409
- const length = lengths[Number(tick.dataset.prtsScaleFocusPreviewTick)] ?? lengths.at(-1)
410
- const width = `${length}px`
411
- if (tick.style.width !== width) tick.style.width = width
412
- }
413
- const detail = resolveParticleDetail(currentPreferences)
414
- const detailLabels = { compact: '精简', standard: '标准', precise: '精细' }
415
- const advanced = panel.querySelector('[data-prts-advanced-summary]')
416
- setText(advanced, `${detailLabels[detail]} / ${conciseNumber(currentParticleTraversalSpeed())}× / 区分度 ${contrast} / ${value} px`)
417
- if (!calibration) return
418
- const distance = `${value}px`
419
- if (calibration.style.getPropertyValue('--prts-calibration-distance') !== distance) {
420
- calibration.style.setProperty('--prts-calibration-distance', distance)
421
- }
422
- scheduleCalibrationMeasurement()
423
- }
424
-
425
- function commitScaleDistance() {
426
- if (!scaleDistanceDirty || !currentPreferences) return false
427
- const value = currentScaleDistance()
428
- scaleDistanceDirty = false
429
- scaleDistanceDraft = value
430
- if (value !== normalizeScaleDistance(currentPreferences.conversationScaleMaxDistance)) onPreferenceChange('conversationScaleMaxDistance', value)
431
- else renderScaleCalibration()
432
- return true
433
- }
434
-
435
- function commitScaleFocusContrast() {
436
- if (!scaleFocusContrastDirty || !currentPreferences) return false
437
- const value = currentScaleFocusContrast()
438
- scaleFocusContrastDirty = false
439
- scaleFocusContrastDraft = value
440
- if (value !== normalizeScaleFocusContrast(currentPreferences.conversationScaleFocusContrast)) onPreferenceChange('conversationScaleFocusContrast', value)
441
- else renderScaleCalibration()
442
- return true
443
- }
444
-
445
244
  function commitParticleTraversalSpeed() {
446
245
  if (!particleTraversalSpeedDirty || !currentPreferences) return false
447
246
  const value = currentParticleTraversalSpeed()
@@ -495,11 +294,8 @@ export function createThemeSettingsOverlay({
495
294
  if (transparency) transparency.hidden = !(currentPreferences.glass !== 'off' && transparencyMedia?.matches)
496
295
  const particleError = panel.querySelector('[data-prts-particle-error]')
497
296
  if (particleError) particleError.hidden = currentStatus?.particle?.phase !== 'error'
498
- if (!scaleDistanceDirty) scaleDistanceDraft = normalizeScaleDistance(currentPreferences.conversationScaleMaxDistance)
499
- if (!scaleFocusContrastDirty) scaleFocusContrastDraft = normalizeScaleFocusContrast(currentPreferences.conversationScaleFocusContrast)
500
297
  if (!particleTraversalSpeedDirty) particleTraversalSpeedDraft = normalizeParticleTraversalSpeed(currentPreferences.particleTraversalSpeed)
501
298
  renderParticleTraversal()
502
- renderScaleCalibration()
503
299
  renderPersistence()
504
300
  }
505
301
 
@@ -531,10 +327,6 @@ export function createThemeSettingsOverlay({
531
327
  if (target.hasAttribute('data-prts-reset-visual')) { setResetConfirmation(true); return }
532
328
  if (target.hasAttribute('data-prts-reset-cancel')) { setResetConfirmation(false); return }
533
329
  if (target.hasAttribute('data-prts-reset-confirm-action')) {
534
- scaleDistanceDirty = false
535
- scaleDistanceDraft = undefined
536
- scaleFocusContrastDirty = false
537
- scaleFocusContrastDraft = undefined
538
330
  particleTraversalSpeedDirty = false
539
331
  particleTraversalSpeedDraft = undefined
540
332
  setResetConfirmation(false)
@@ -547,13 +339,7 @@ export function createThemeSettingsOverlay({
547
339
  if (!target?.matches?.('input[data-prts-setting-range]')) return
548
340
  const value = Number(target.value)
549
341
  if (!Number.isFinite(value)) return
550
- if (target.dataset.prtsSettingKey === 'conversationScaleMaxDistance') {
551
- scaleDistanceDraft = value
552
- scaleDistanceDirty = true
553
- } else if (target.dataset.prtsSettingKey === 'conversationScaleFocusContrast') {
554
- scaleFocusContrastDraft = value
555
- scaleFocusContrastDirty = true
556
- } else if (target.dataset.prtsSettingKey === 'particleTraversalSpeed') {
342
+ if (target.dataset.prtsSettingKey === 'particleTraversalSpeed') {
557
343
  particleTraversalSpeedDraft = normalizeParticleTraversalSpeed(value)
558
344
  particleTraversalSpeedDirty = true
559
345
  renderParticleTraversal()
@@ -562,7 +348,6 @@ export function createThemeSettingsOverlay({
562
348
  } else {
563
349
  return
564
350
  }
565
- renderScaleCalibration()
566
351
  }
567
352
 
568
353
  function onKeydown(event) {
@@ -584,8 +369,6 @@ export function createThemeSettingsOverlay({
584
369
  const commitFromControl = event => {
585
370
  const target = event.target
586
371
  if (!target?.matches?.('input[data-prts-setting-range]')) return
587
- if (target.dataset.prtsSettingKey === 'conversationScaleMaxDistance') commitScaleDistance()
588
- if (target.dataset.prtsSettingKey === 'conversationScaleFocusContrast') commitScaleFocusContrast()
589
372
  if (target.dataset.prtsSettingKey === 'particleTraversalSpeed') commitParticleTraversalSpeed()
590
373
  }
591
374
 
@@ -600,24 +383,15 @@ export function createThemeSettingsOverlay({
600
383
  document.addEventListener('keydown', onKeydown)
601
384
  transparencyMedia?.addEventListener?.('change', renderMediaState)
602
385
  motionMedia?.addEventListener?.('change', renderMediaState)
603
- if (typeof window?.ResizeObserver === 'function') {
604
- calibrationResizeObserver = new window.ResizeObserver(scheduleScalePreviewRefresh)
605
- const viewport = panel?.querySelector?.('[data-prts-scale-calibration-viewport]')
606
- if (viewport) calibrationResizeObserver.observe(viewport)
607
- }
608
386
 
609
387
  return {
610
388
  update(preferences, status, persistenceState = currentPersistence) {
611
389
  currentPreferences = preferences
612
390
  currentStatus = status
613
391
  currentPersistence = persistenceState ?? { phase: 'idle', revision: 0 }
614
- if (!scaleDistanceDirty) scaleDistanceDraft = normalizeScaleDistance(preferences?.conversationScaleMaxDistance)
615
- if (!scaleFocusContrastDirty) scaleFocusContrastDraft = normalizeScaleFocusContrast(preferences?.conversationScaleFocusContrast)
616
392
  if (!particleTraversalSpeedDirty) particleTraversalSpeedDraft = normalizeParticleTraversalSpeed(preferences?.particleTraversalSpeed)
617
393
  renderState()
618
394
  },
619
- refreshScalePreview: renderScaleCalibration,
620
- scheduleScalePreviewRefresh,
621
395
  open: () => setOpen(true),
622
396
  close: () => setOpen(false),
623
397
  toggle,
@@ -626,10 +400,6 @@ export function createThemeSettingsOverlay({
626
400
  hidePanel()
627
401
  if (savedTimer !== undefined) window?.clearTimeout?.(savedTimer)
628
402
  if (feedbackTimer !== undefined) window?.clearTimeout?.(feedbackTimer)
629
- if (calibrationSettleTimer !== undefined) window?.clearTimeout?.(calibrationSettleTimer)
630
- calibrationSettleTimer = undefined
631
- cancelCalibrationFrame()
632
- setCalibrationResizeState(false)
633
403
  feedbackTarget?.removeAttribute?.('data-prts-setting-feedback')
634
404
  trigger?.setAttribute('aria-expanded', 'false')
635
405
  trigger?.removeEventListener('click', toggle)
@@ -643,7 +413,6 @@ export function createThemeSettingsOverlay({
643
413
  document.removeEventListener('keydown', onKeydown)
644
414
  transparencyMedia?.removeEventListener?.('change', renderMediaState)
645
415
  motionMedia?.removeEventListener?.('change', renderMediaState)
646
- calibrationResizeObserver?.disconnect()
647
416
  document.documentElement.removeAttribute('data-prts-settings-open')
648
417
  },
649
418
  }
@@ -16,6 +16,7 @@ html[data-dsh-prts] {
16
16
  --prts-cyan: #5ccddb;
17
17
  --prts-red: #ee625a;
18
18
  --prts-green: #8fcf79;
19
+ --dsw-alias-label-primary-inverted: #15191c;
19
20
  --prts-host-top-inset: 0px;
20
21
  --prts-rail-width: 52px;
21
22
  --prts-nav-width: 52px;
@@ -65,6 +66,7 @@ html[data-dsh-prts][data-prts-scheme="light"] {
65
66
  --prts-dim: #738087;
66
67
  --prts-line: #9eabb1;
67
68
  --prts-line-strong: #65727a;
69
+ --dsw-alias-label-primary-inverted: #edf1f2;
68
70
  --prts-glass-border: rgba(62, 82, 92, .48);
69
71
  --prts-glass-soft-surface: rgba(247, 250, 251, .9);
70
72
  --prts-glass-standard-surface: rgba(244, 249, 251, .94);
@@ -99,10 +101,6 @@ html[data-dsh-prts] :is(
99
101
  [data-prts-shell] *,
100
102
  [data-prts-particle-layer],
101
103
  [data-prts-ambient-layer],
102
- [data-prts-conversation-scale],
103
- [data-prts-conversation-scale] *,
104
- [data-prts-conversation-preview],
105
- [data-prts-conversation-preview] *,
106
104
  [data-prts-facility-face],
107
105
  [data-composer-card],
108
106
  [data-prts-composer-fallback],
@@ -114,10 +112,6 @@ html[data-dsh-prts] :is(
114
112
  [data-prts-shell] *,
115
113
  [data-prts-particle-layer],
116
114
  [data-prts-ambient-layer],
117
- [data-prts-conversation-scale],
118
- [data-prts-conversation-scale] *,
119
- [data-prts-conversation-preview],
120
- [data-prts-conversation-preview] *,
121
115
  [data-prts-facility-face],
122
116
  [data-composer-card],
123
117
  [data-prts-composer-fallback],
@@ -129,10 +123,6 @@ html[data-dsh-prts] :is(
129
123
  [data-prts-shell] *,
130
124
  [data-prts-particle-layer],
131
125
  [data-prts-ambient-layer],
132
- [data-prts-conversation-scale],
133
- [data-prts-conversation-scale] *,
134
- [data-prts-conversation-preview],
135
- [data-prts-conversation-preview] *,
136
126
  [data-prts-facility-face],
137
127
  [data-composer-card],
138
128
  [data-prts-composer-fallback],
@@ -294,18 +284,23 @@ html[data-dsh-prts][data-prts-rail-mode="overlay"] [data-prts-rail-launcher]:is(
294
284
 
295
285
  @media (hover: none), (pointer: coarse) {
296
286
  html[data-dsh-prts][data-prts-rail-mode="overlay"] [data-prts-rail-launcher] {
297
- top: calc(var(--prts-host-top-inset) + 12px);
298
- width: 40px;
299
- height: 40px;
300
- opacity: .92;
301
- transform: none;
287
+ top: 50%; width: 24px; height: 88px; opacity: .58;
288
+ transform: translateY(-50%); touch-action: none;
302
289
  }
303
-
304
- html[data-dsh-prts][data-prts-rail-mode="overlay"] [data-prts-rail-launcher] > span {
305
- opacity: 1;
290
+ html[data-dsh-prts] [data-prts-rail-launcher] > span { opacity: 0; }
291
+ html[data-dsh-prts] [data-prts-rail-launcher][data-prts-rail-gesture-active] { width: 40px; opacity: 1; }
292
+ html[data-dsh-prts] [data-prts-rail-gesture-cue] {
293
+ position: absolute; inset: calc(27px + var(--prts-rail-gesture-progress, 0px)) 10px auto auto;
294
+ display: block; opacity: 0; font: 700 14px/8px sans-serif;
295
+ }
296
+ html[data-dsh-prts] [data-prts-rail-gesture-active] [data-prts-rail-gesture-cue] {
297
+ opacity: 1; animation: prts-rail-swipe-cue 720ms ease-in-out infinite;
306
298
  }
299
+ html[data-dsh-prts] [data-prts-rail-gesture-ready] [data-prts-rail-gesture-cue] { filter: drop-shadow(0 0 3px currentColor); }
307
300
  }
308
301
 
302
+ @keyframes prts-rail-swipe-cue { 50% { opacity: .45; } }
303
+
309
304
  html[data-dsh-prts] [data-prts-rail-brand] {
310
305
  height: 64px;
311
306
  display: grid;
@@ -811,12 +806,18 @@ html[data-dsh-prts] [data-prts-region="operation"] {
811
806
  color: var(--prts-ink);
812
807
  }
813
808
 
814
- html[data-dsh-prts][data-prts-sessions-collapsed] [data-prts-region="sessions"] [data-slot="sidebar.workspaces"],
815
- html[data-dsh-prts][data-prts-sessions-collapsed] [data-prts-region="sessions"] [data-slot="sidebar.settings"] {
809
+ html[data-dsh-prts] [data-prts-region="frame"][data-sidebar-collapsed] [data-prts-region="sessions"] :is(
810
+ [data-slot="sidebar.workspaces"],
811
+ [data-slot="sidebar.settings"]
812
+ ) {
816
813
  opacity: 0;
817
814
  pointer-events: none;
818
815
  }
819
816
 
817
+ html[data-dsh-prts] [data-sidebar-collapsed] :is([data-prts-owned-facility], [data-prts-owned-facility-spine], [data-prts-owned-facility-vector]) {
818
+ visibility: hidden; content-visibility: hidden;
819
+ }
820
+
820
821
  html[data-dsh-prts] [data-prts-region="sessions"] > *,
821
822
  html[data-dsh-prts] [data-prts-region="sessions"] [data-slot="sidebar"] {
822
823
  height: 100%;
@@ -827,11 +828,15 @@ html[data-dsh-prts] [data-prts-region="sessions"] [data-rc7-sidebar-root] {
827
828
  width: 100% !important;
828
829
  min-width: var(--prts-sessions-width);
829
830
  padding: 14px 10px;
830
- overflow-y: auto;
831
+ overflow: hidden auto;
831
832
  background: transparent !important;
832
833
  color: var(--prts-ink);
833
834
  }
834
835
 
836
+ html[data-dsh-prts] [data-prts-region="sessions"] [data-slot="sidebar.workspaces"] [role="tree"] {
837
+ overflow-x: hidden;
838
+ }
839
+
835
840
  html[data-dsh-prts] [data-prts-region="sessions"] > * > [data-slot="sidebar"] > :first-child > button[aria-label*="new session" i] {
836
841
  display: none !important;
837
842
  }
@@ -1062,37 +1067,12 @@ html[data-dsh-prts] [data-conversation-scroll] {
1062
1067
  z-index: 2;
1063
1068
  }
1064
1069
 
1065
- html[data-dsh-prts] [data-conversation-scroll]::before {
1066
- content: "";
1067
- position: absolute;
1068
- z-index: -1;
1069
- top: 28px;
1070
- bottom: 140px;
1071
- left: clamp(30px, 3.6vw, 52px);
1072
- width: 1px;
1073
- background: linear-gradient(var(--prts-line-strong), var(--prts-line), transparent);
1074
- }
1075
-
1076
1070
  html[data-dsh-prts] [data-message-role="user"],
1077
1071
  html[data-dsh-prts] [data-chat-flow-kind="user"] {
1078
1072
  position: relative;
1079
1073
  color: var(--prts-ink);
1080
1074
  }
1081
1075
 
1082
- html[data-dsh-prts] [data-message-role="user"]::before,
1083
- html[data-dsh-prts] [data-chat-flow-kind="user"]::before {
1084
- content: "";
1085
- position: absolute;
1086
- top: 8px;
1087
- left: calc(clamp(-66px, -4vw, -42px));
1088
- width: 11px;
1089
- height: 11px;
1090
- border: 2px solid var(--prts-canvas);
1091
- background: var(--prts-yellow);
1092
- box-shadow: 0 0 0 1px var(--prts-yellow);
1093
- transform: rotate(45deg);
1094
- }
1095
-
1096
1076
 
1097
1077
  html[data-dsh-prts] [data-message-role="user"],
1098
1078
  html[data-dsh-prts] [data-chat-flow-kind="user"] [class$="_bubble"] {
@@ -1209,9 +1189,6 @@ html[data-dsh-prts] [data-prts-ambient-layer][data-prts-resizing] :is(
1209
1189
  }
1210
1190
 
1211
1191
  html[data-dsh-prts] :is(
1212
- [data-prts-conversation-preview][data-prts-resizing],
1213
- [data-prts-conversation-history-hint][data-prts-resizing],
1214
- [data-prts-conversation-history-status][data-prts-resizing],
1215
1192
  [data-prts-theme-settings][data-prts-resizing],
1216
1193
  [data-prts-settings-backdrop][data-prts-resizing]
1217
1194
  ),
@@ -1362,6 +1339,7 @@ html[data-dsh-prts-settings] .prts-plugin-settings {
1362
1339
  width: 100%;
1363
1340
  display: grid;
1364
1341
  gap: 16px;
1342
+ container: prts-plugin-settings / inline-size;
1365
1343
  color: inherit;
1366
1344
  font: inherit;
1367
1345
  }
@@ -1474,19 +1452,23 @@ html[data-dsh-prts-settings] .prts-plugin-settings button[role='switch']:disable
1474
1452
  }
1475
1453
  }
1476
1454
 
1477
-
1478
- @media (max-width: 640px) {
1479
- html[data-dsh-prts] {
1480
- --prts-nav-width: 52px;
1455
+ @container prts-plugin-settings (max-width: 22rem) {
1456
+ html[data-dsh-prts-settings] .prts-plugin-settings__row {
1457
+ flex-direction: column;
1458
+ align-items: stretch;
1459
+ gap: 10px;
1481
1460
  }
1482
1461
 
1483
- html[data-dsh-prts] [data-conversation-scroll]::before {
1484
- left: 18px;
1462
+ html[data-dsh-prts-settings] .prts-plugin-settings button[role='switch'] {
1463
+ align-self: flex-end;
1485
1464
  }
1465
+ }
1466
+
1467
+
1486
1468
 
1487
- html[data-dsh-prts] [data-message-role]::before,
1488
- html[data-dsh-prts] [data-chat-flow-kind]::before {
1489
- left: -25px;
1469
+ @media (max-width: 640px) {
1470
+ html[data-dsh-prts] {
1471
+ --prts-nav-width: 52px;
1490
1472
  }
1491
1473
 
1492
1474
  html[data-dsh-prts] [data-slot="conversation.session.header"] {
@@ -1532,10 +1514,6 @@ html[data-dsh-prts-settings] .prts-plugin-settings button[role='switch']:disable
1532
1514
  [data-prts-shell] *,
1533
1515
  [data-prts-particle-layer],
1534
1516
  [data-prts-ambient-layer],
1535
- [data-prts-conversation-scale],
1536
- [data-prts-conversation-scale] *,
1537
- [data-prts-conversation-preview],
1538
- [data-prts-conversation-preview] *,
1539
1517
  [data-prts-facility-face],
1540
1518
  [data-composer-card],
1541
1519
  [data-prts-composer-fallback],
@@ -1547,10 +1525,6 @@ html[data-dsh-prts-settings] .prts-plugin-settings button[role='switch']:disable
1547
1525
  [data-prts-shell] *,
1548
1526
  [data-prts-particle-layer],
1549
1527
  [data-prts-ambient-layer],
1550
- [data-prts-conversation-scale],
1551
- [data-prts-conversation-scale] *,
1552
- [data-prts-conversation-preview],
1553
- [data-prts-conversation-preview] *,
1554
1528
  [data-prts-facility-face],
1555
1529
  [data-composer-card],
1556
1530
  [data-prts-composer-fallback],
@@ -1562,10 +1536,6 @@ html[data-dsh-prts-settings] .prts-plugin-settings button[role='switch']:disable
1562
1536
  [data-prts-shell] *,
1563
1537
  [data-prts-particle-layer],
1564
1538
  [data-prts-ambient-layer],
1565
- [data-prts-conversation-scale],
1566
- [data-prts-conversation-scale] *,
1567
- [data-prts-conversation-preview],
1568
- [data-prts-conversation-preview] *,
1569
1539
  [data-prts-facility-face],
1570
1540
  [data-composer-card],
1571
1541
  [data-prts-composer-fallback],