@ash-qw/dsh-theme-prts 0.1.99 → 0.1.100

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,4 +1,4 @@
1
- import { PARTICLE_TRAVERSAL_SPEED_DEFAULT, PARTICLE_TRAVERSAL_SPEED_MAX, PARTICLE_TRAVERSAL_SPEED_MIN, PARTICLE_TRAVERSAL_SPEED_STEP, resolveParticleDetail } from './preferences.js'
1
+ import { PARTICLE_TRAVERSAL_SPEED_DEFAULT, PARTICLE_TRAVERSAL_SPEED_MAX, PARTICLE_TRAVERSAL_SPEED_MIN, PARTICLE_TRAVERSAL_SPEED_STEP, SESSION_FLOW_SPEED_DEFAULT, SESSION_FLOW_SPEED_MAX, SESSION_FLOW_SPEED_MIN, SESSION_FLOW_SPEED_STEP, resolveParticleDetail } from './preferences.js'
2
2
 
3
3
  const SETTINGS_FOCUSABLE = [
4
4
  'button:not([disabled])',
@@ -20,7 +20,14 @@ const COMMON_CONTROLS = [
20
20
  ['glass', '玻璃材质', [['off', '关闭'], ['soft', '柔和'], ['standard', '标准'], ['clear', '清晰']]],
21
21
  ['motion', '动态效果', [['system', '跟随系统'], ['reduced', '减少']]],
22
22
  ['sessionFlow', '当前会话流线', [['false', '关闭'], ['true', '开启']]],
23
- ['conversationStyle', '会话主题', [['native', '原有'], ['deck-chat', '通讯链路']]],
23
+ ['sessionGlow', '流线光效', [['false', '关闭'], ['true', '开启']]],
24
+ ['sessionFlowPalette', '流线色调', [['triad', '三色'], ['rhodes', '青蓝'], ['amber', '金黄'], ['alert', '赤红'], ['custom', '自定义']]],
25
+ ]
26
+
27
+ const SESSION_FLOW_COLOR_CONTROLS = [
28
+ ['sessionFlowColorBack', '后层'],
29
+ ['sessionFlowColorCore', '中层'],
30
+ ['sessionFlowColorFront', '前层'],
24
31
  ]
25
32
 
26
33
  const PARTICLE_OPTIONS = [
@@ -40,8 +47,12 @@ function settingButtons(key, label, options) {
40
47
  ? '<small data-prts-setting-note>立即切换会话背景、头像与消息气泡</small>'
41
48
  : key === 'sessionFlow'
42
49
  ? '<small data-prts-setting-note>仅控制当前会话卡片的三色流线</small>'
50
+ : key === 'sessionGlow'
51
+ ? '<small data-prts-setting-note>为流线添加柔和的同色辉光</small>'
52
+ : key === 'sessionFlowPalette'
53
+ ? '<small data-prts-setting-note>同时适配日间与夜间模式</small>'
43
54
  : ''
44
- const sample = value => key === 'texture' || key === 'glass'
55
+ const sample = value => key === 'texture' || key === 'glass' || key === 'sessionFlowPalette'
45
56
  ? `<i data-prts-option-sample="${key}" data-prts-option-sample-value="${value}" aria-hidden="true"></i>`
46
57
  : ''
47
58
  return `<div data-prts-setting-row="${key}">
@@ -62,6 +73,33 @@ function particleMarkup() {
62
73
  </button>`).join('')
63
74
  }
64
75
 
76
+ function sessionFlowPreviewMarkup() {
77
+ const filaments = [
78
+ ['back', 'M 3 29 C 34 8 66 36 101 17 C 126 5 151 27 177 13'],
79
+ ['core', 'M 3 24 C 30 35 61 7 94 23 C 124 37 148 7 177 20'],
80
+ ['front', 'M 3 18 C 34 4 66 30 96 12 C 125 -1 148 30 177 24'],
81
+ ]
82
+ return `<svg data-prts-session-flow-preview viewBox="0 0 180 42" aria-label="三色流线预览" role="img">
83
+ ${filaments.map(([strand, path]) => `<g data-prts-session-flow-preview-filament="${strand}">
84
+ <path data-prts-session-flow-preview-layer="halo" d="${path}"></path>
85
+ <path data-prts-session-flow-preview-layer="body" d="${path}"></path>
86
+ <path data-prts-session-flow-preview-layer="core" d="${path}"></path>
87
+ </g>`).join('')}
88
+ </svg>`
89
+ }
90
+
91
+ function sessionFlowColorMarkup() {
92
+ return `<div data-prts-setting-row="sessionFlowColors" data-prts-session-flow-colors>
93
+ <span><strong>三色调色盘</strong><small data-prts-setting-note>任意修改后切换为自定义,日夜模式均保持原色</small></span>
94
+ <div data-prts-session-flow-color-workbench>
95
+ ${sessionFlowPreviewMarkup()}
96
+ <div data-prts-session-flow-color-inputs role="group" aria-label="三色流线调色盘">
97
+ ${SESSION_FLOW_COLOR_CONTROLS.map(([key, label]) => `<label><span>${label}</span><input type="color" value="#ffffff" data-prts-setting-color data-prts-setting-key="${key}" aria-label="${label}流线颜色"><output data-prts-setting-color-output="${key}">#ffffff</output></label>`).join('')}
98
+ </div>
99
+ </div>
100
+ </div>`
101
+ }
102
+
65
103
  export function themeSettingsMarkup() {
66
104
  return `<div data-prts-settings-backdrop hidden aria-hidden="true"></div>
67
105
  <dialog id="prts-theme-settings" data-prts-theme-settings aria-label="P.R.T.S. 主题设置" aria-hidden="true">
@@ -83,7 +121,14 @@ export function themeSettingsMarkup() {
83
121
 
84
122
  <section data-prts-settings-common>
85
123
  <header><span><small>常用设置</small><strong>主题表现</strong></span></header>
86
- <div data-prts-settings-common-grid>${COMMON_CONTROLS.map(([key, label, options]) => settingButtons(key, label, options)).join('')}</div>
124
+ <div data-prts-settings-common-grid>${COMMON_CONTROLS.map(([key, label, options]) => settingButtons(key, label, options)).join('')}
125
+ ${sessionFlowColorMarkup()}
126
+ <label data-prts-setting-row="sessionFlowSpeed" data-prts-setting-range-row data-prts-session-flow-speed>
127
+ <span><strong>流线速度</strong><small data-prts-setting-note>控制当前会话流线的形变速度</small></span>
128
+ <div><input type="range" min="0.25" max="2" step="0.25" value="1" data-prts-setting-range data-prts-setting-key="sessionFlowSpeed" aria-label="当前会话流线速度"><output data-prts-session-flow-speed-output>1× · 标准</output></div>
129
+ </label>
130
+ ${settingButtons('conversationStyle', '会话主题', [['native', '原有'], ['deck-chat', '通讯链路']])}
131
+ </div>
87
132
  </section>
88
133
 
89
134
  <details data-prts-settings-advanced>
@@ -143,6 +188,10 @@ export function createThemeSettingsOverlay({
143
188
  let currentPersistence = { phase: 'idle', revision: 0 }
144
189
  let particleTraversalSpeedDraft
145
190
  let particleTraversalSpeedDirty = false
191
+ let sessionFlowSpeedDraft
192
+ let sessionFlowSpeedDirty = false
193
+ let sessionFlowColorDrafts = {}
194
+ const sessionFlowColorDirty = new Set()
146
195
  let savedTimer
147
196
  let feedbackTimer
148
197
  let feedbackTarget
@@ -192,6 +241,8 @@ export function createThemeSettingsOverlay({
192
241
  if (value === isOpen) return isOpen
193
242
  if (!value) {
194
243
  commitParticleTraversalSpeed()
244
+ commitSessionFlowSpeed()
245
+ commitSessionFlowColors()
195
246
  }
196
247
  isOpen = value
197
248
  trigger.setAttribute('aria-expanded', String(isOpen))
@@ -225,6 +276,34 @@ export function createThemeSettingsOverlay({
225
276
  )
226
277
  }
227
278
 
279
+ function normalizeSessionFlowSpeed(value) {
280
+ const numeric = Number(value)
281
+ if (!Number.isFinite(numeric)) return SESSION_FLOW_SPEED_DEFAULT
282
+ const clamped = Math.min(SESSION_FLOW_SPEED_MAX, Math.max(SESSION_FLOW_SPEED_MIN, numeric))
283
+ return Math.round(clamped / SESSION_FLOW_SPEED_STEP) * SESSION_FLOW_SPEED_STEP
284
+ }
285
+
286
+ function currentSessionFlowSpeed() {
287
+ return normalizeSessionFlowSpeed(
288
+ sessionFlowSpeedDirty ? sessionFlowSpeedDraft : currentPreferences?.sessionFlowSpeed,
289
+ )
290
+ }
291
+
292
+ function normalizeSessionFlowColor(value, fallback = '#ffffff') {
293
+ return typeof value === 'string' && /^#[\da-f]{6}$/i.test(value) ? value.toLowerCase() : fallback
294
+ }
295
+
296
+ function currentSessionFlowColor(key) {
297
+ return normalizeSessionFlowColor(
298
+ sessionFlowColorDirty.has(key) ? sessionFlowColorDrafts[key] : currentPreferences?.[key],
299
+ '#ffffff',
300
+ )
301
+ }
302
+
303
+ function activeSessionFlowPalette() {
304
+ return sessionFlowColorDirty.size > 0 ? 'custom' : currentPreferences?.sessionFlowPalette
305
+ }
306
+
228
307
  function conciseNumber(value) {
229
308
  return String(Number(Number(value).toFixed(2)))
230
309
  }
@@ -243,6 +322,42 @@ export function createThemeSettingsOverlay({
243
322
  setText(panel.querySelector('[data-prts-particle-traversal-output]'), particleTraversalLabel(value))
244
323
  }
245
324
 
325
+ function sessionFlowSpeedLabel(value) {
326
+ const speed = normalizeSessionFlowSpeed(value)
327
+ const description = speed < 1 ? '缓慢' : speed === 1 ? '标准' : speed <= 1.5 ? '快速' : '高速'
328
+ return `${conciseNumber(speed)}× · ${description}`
329
+ }
330
+
331
+ function renderSessionFlowSpeed() {
332
+ if (!panel || !currentPreferences) return
333
+ const value = currentSessionFlowSpeed()
334
+ const range = panel.querySelector('input[data-prts-setting-range][data-prts-setting-key="sessionFlowSpeed"]')
335
+ if (range && range.value !== String(value)) range.value = String(value)
336
+ setText(panel.querySelector('[data-prts-session-flow-speed-output]'), sessionFlowSpeedLabel(value))
337
+ }
338
+
339
+ function renderSessionFlowColors() {
340
+ if (!panel || !currentPreferences) return
341
+ for (const [key] of SESSION_FLOW_COLOR_CONTROLS) {
342
+ const value = currentSessionFlowColor(key)
343
+ const input = panel.querySelector(`input[data-prts-setting-color][data-prts-setting-key="${key}"]`)
344
+ if (input && input.value !== value) input.value = value
345
+ setText(panel.querySelector(`[data-prts-setting-color-output="${key}"]`), value)
346
+ }
347
+ const preview = panel.querySelector('[data-prts-session-flow-preview]')
348
+ if (preview) {
349
+ preview.dataset.prtsSessionFlowPreviewPalette = activeSessionFlowPalette() || 'triad'
350
+ preview.style.setProperty('--prts-session-flow-back', currentSessionFlowColor('sessionFlowColorBack'))
351
+ preview.style.setProperty('--prts-session-flow-core', currentSessionFlowColor('sessionFlowColorCore'))
352
+ preview.style.setProperty('--prts-session-flow-front', currentSessionFlowColor('sessionFlowColorFront'))
353
+ }
354
+ for (const button of panel.querySelectorAll('button[data-prts-setting-key="sessionFlowPalette"]')) {
355
+ const selected = button.dataset.prtsSettingValue === activeSessionFlowPalette()
356
+ button.classList.toggle('is-selected', selected)
357
+ button.setAttribute('aria-pressed', String(selected))
358
+ }
359
+ }
360
+
246
361
  function setText(node, value) {
247
362
  if (node && node.textContent !== value) node.textContent = value
248
363
  }
@@ -260,6 +375,38 @@ export function createThemeSettingsOverlay({
260
375
  return true
261
376
  }
262
377
 
378
+ function commitSessionFlowSpeed() {
379
+ if (!sessionFlowSpeedDirty || !currentPreferences) return false
380
+ const value = currentSessionFlowSpeed()
381
+ sessionFlowSpeedDirty = false
382
+ sessionFlowSpeedDraft = value
383
+ if (value !== normalizeSessionFlowSpeed(currentPreferences.sessionFlowSpeed)) {
384
+ onPreferenceChange('sessionFlowSpeed', value)
385
+ } else {
386
+ renderSessionFlowSpeed()
387
+ }
388
+ return true
389
+ }
390
+
391
+ function commitSessionFlowColor(key) {
392
+ if (!sessionFlowColorDirty.has(key) || !currentPreferences) return false
393
+ const value = currentSessionFlowColor(key)
394
+ sessionFlowColorDirty.delete(key)
395
+ sessionFlowColorDrafts[key] = value
396
+ if (value !== normalizeSessionFlowColor(currentPreferences[key]) || currentPreferences.sessionFlowPalette !== 'custom') {
397
+ onPreferenceChange(key, value)
398
+ } else {
399
+ renderSessionFlowColors()
400
+ }
401
+ return true
402
+ }
403
+
404
+ function commitSessionFlowColors() {
405
+ let committed = false
406
+ for (const key of [...sessionFlowColorDirty]) committed = commitSessionFlowColor(key) || committed
407
+ return committed
408
+ }
409
+
263
410
  function renderPersistence() {
264
411
  const status = panel?.querySelector?.('[data-prts-persistence-status]')
265
412
  const error = panel?.querySelector?.('[data-prts-persistence-error]')
@@ -286,8 +433,10 @@ export function createThemeSettingsOverlay({
286
433
  const key = button.dataset.prtsSettingKey
287
434
  const actual = key === 'particleDetail'
288
435
  ? particleDetail
289
- : key === 'sessionFlow'
290
- ? currentPreferences.sessionFlow !== false
436
+ : key === 'sessionFlowPalette'
437
+ ? activeSessionFlowPalette()
438
+ : key === 'sessionFlow' || key === 'sessionGlow'
439
+ ? currentPreferences[key] !== false
291
440
  : currentPreferences[key]
292
441
  const selected = String(actual) === button.dataset.prtsSettingValue
293
442
  button.classList.toggle('is-selected', selected)
@@ -305,7 +454,13 @@ export function createThemeSettingsOverlay({
305
454
  const particleError = panel.querySelector('[data-prts-particle-error]')
306
455
  if (particleError) particleError.hidden = currentStatus?.particle?.phase !== 'error'
307
456
  if (!particleTraversalSpeedDirty) particleTraversalSpeedDraft = normalizeParticleTraversalSpeed(currentPreferences.particleTraversalSpeed)
457
+ if (!sessionFlowSpeedDirty) sessionFlowSpeedDraft = normalizeSessionFlowSpeed(currentPreferences.sessionFlowSpeed)
458
+ for (const [key] of SESSION_FLOW_COLOR_CONTROLS) {
459
+ if (!sessionFlowColorDirty.has(key)) sessionFlowColorDrafts[key] = normalizeSessionFlowColor(currentPreferences[key])
460
+ }
308
461
  renderParticleTraversal()
462
+ renderSessionFlowSpeed()
463
+ renderSessionFlowColors()
309
464
  renderPersistence()
310
465
  }
311
466
 
@@ -329,6 +484,10 @@ export function createThemeSettingsOverlay({
329
484
  if (target.hasAttribute('data-prts-theme-settings-close')) { setOpen(false); return }
330
485
  if (target.hasAttribute('data-prts-setting-key')) {
331
486
  const raw = target.dataset.prtsSettingValue
487
+ if (target.dataset.prtsSettingKey === 'sessionFlowPalette') {
488
+ sessionFlowColorDirty.clear()
489
+ sessionFlowColorDrafts = {}
490
+ }
332
491
  markFeedback(target)
333
492
  onPreferenceChange(target.dataset.prtsSettingKey, raw === 'true' ? true : raw === 'false' ? false : raw)
334
493
  return
@@ -339,6 +498,10 @@ export function createThemeSettingsOverlay({
339
498
  if (target.hasAttribute('data-prts-reset-confirm-action')) {
340
499
  particleTraversalSpeedDirty = false
341
500
  particleTraversalSpeedDraft = undefined
501
+ sessionFlowSpeedDirty = false
502
+ sessionFlowSpeedDraft = undefined
503
+ sessionFlowColorDirty.clear()
504
+ sessionFlowColorDrafts = {}
342
505
  setResetConfirmation(false)
343
506
  onResetVisual()
344
507
  }
@@ -346,6 +509,15 @@ export function createThemeSettingsOverlay({
346
509
 
347
510
  function onPanelInput(event) {
348
511
  const target = event.target
512
+ if (target?.matches?.('input[data-prts-setting-color]')) {
513
+ const key = target.dataset.prtsSettingKey
514
+ const value = normalizeSessionFlowColor(target.value, currentSessionFlowColor(key))
515
+ sessionFlowColorDrafts[key] = value
516
+ sessionFlowColorDirty.add(key)
517
+ renderSessionFlowColors()
518
+ onPreferencePreview(key, value)
519
+ return
520
+ }
349
521
  if (!target?.matches?.('input[data-prts-setting-range]')) return
350
522
  const value = Number(target.value)
351
523
  if (!Number.isFinite(value)) return
@@ -355,6 +527,12 @@ export function createThemeSettingsOverlay({
355
527
  renderParticleTraversal()
356
528
  onPreferencePreview('particleTraversalSpeed', particleTraversalSpeedDraft)
357
529
  return
530
+ } else if (target.dataset.prtsSettingKey === 'sessionFlowSpeed') {
531
+ sessionFlowSpeedDraft = normalizeSessionFlowSpeed(value)
532
+ sessionFlowSpeedDirty = true
533
+ renderSessionFlowSpeed()
534
+ onPreferencePreview('sessionFlowSpeed', sessionFlowSpeedDraft)
535
+ return
358
536
  } else {
359
537
  return
360
538
  }
@@ -378,8 +556,13 @@ export function createThemeSettingsOverlay({
378
556
  const renderMediaState = () => renderState()
379
557
  const commitFromControl = event => {
380
558
  const target = event.target
559
+ if (target?.matches?.('input[data-prts-setting-color]')) {
560
+ if (event.type === 'change' || event.type === 'focusout') commitSessionFlowColor(target.dataset.prtsSettingKey)
561
+ return
562
+ }
381
563
  if (!target?.matches?.('input[data-prts-setting-range]')) return
382
564
  if (target.dataset.prtsSettingKey === 'particleTraversalSpeed') commitParticleTraversalSpeed()
565
+ if (target.dataset.prtsSettingKey === 'sessionFlowSpeed') commitSessionFlowSpeed()
383
566
  }
384
567
 
385
568
  trigger?.addEventListener('click', toggle)
@@ -400,6 +583,10 @@ export function createThemeSettingsOverlay({
400
583
  currentStatus = status
401
584
  currentPersistence = persistenceState ?? { phase: 'idle', revision: 0 }
402
585
  if (!particleTraversalSpeedDirty) particleTraversalSpeedDraft = normalizeParticleTraversalSpeed(preferences?.particleTraversalSpeed)
586
+ if (!sessionFlowSpeedDirty) sessionFlowSpeedDraft = normalizeSessionFlowSpeed(preferences?.sessionFlowSpeed)
587
+ for (const [key] of SESSION_FLOW_COLOR_CONTROLS) {
588
+ if (!sessionFlowColorDirty.has(key)) sessionFlowColorDrafts[key] = normalizeSessionFlowColor(preferences?.[key])
589
+ }
403
590
  renderState()
404
591
  },
405
592
  open: () => setOpen(true),
@@ -150,42 +150,107 @@ html[data-dsh-prts] [data-prts-session-lifeline] {
150
150
  pointer-events: none;
151
151
  }
152
152
 
153
- html[data-dsh-prts][data-prts-scheme="light"] [data-prts-session-lifeline] {
154
- --prts-lifeline-pink: #c36f99;
155
- --prts-lifeline-green: #218d6b;
156
- --prts-lifeline-blue: #357ebc;
153
+ html[data-dsh-prts][data-prts-session-flow-palette="rhodes"] [data-prts-session-lifeline] {
154
+ --prts-lifeline-pink: #b9edf4;
155
+ --prts-lifeline-green: #5ccddb;
156
+ --prts-lifeline-blue: #5a9ee6;
157
+ }
158
+
159
+ html[data-dsh-prts][data-prts-session-flow-palette="amber"] [data-prts-session-lifeline] {
160
+ --prts-lifeline-pink: #ffe6a3;
161
+ --prts-lifeline-green: #f0c800;
162
+ --prts-lifeline-blue: #ee8f42;
163
+ }
164
+
165
+ html[data-dsh-prts][data-prts-session-flow-palette="alert"] [data-prts-session-lifeline] {
166
+ --prts-lifeline-pink: #ffc0b8;
167
+ --prts-lifeline-green: #ee625a;
168
+ --prts-lifeline-blue: #db5b8c;
169
+ }
170
+
171
+ html[data-dsh-prts][data-prts-session-flow-palette="custom"] [data-prts-session-lifeline] {
172
+ --prts-lifeline-pink: var(--prts-session-flow-back);
173
+ --prts-lifeline-green: var(--prts-session-flow-core);
174
+ --prts-lifeline-blue: var(--prts-session-flow-front);
157
175
  }
158
176
 
159
177
  html[data-dsh-prts] [data-prts-session-lifeline-filament] {
178
+ --prts-lifeline-color: currentColor;
179
+ }
180
+
181
+ html[data-dsh-prts] [data-prts-session-lifeline-layer] {
160
182
  fill: none;
161
- stroke: currentColor;
162
- stroke-width: .8;
183
+ stroke: var(--prts-lifeline-color);
163
184
  stroke-linecap: round;
164
185
  stroke-linejoin: round;
165
186
  vector-effect: non-scaling-stroke;
166
187
  shape-rendering: geometricPrecision;
188
+ transition: opacity 160ms ease, stroke-width 160ms ease;
167
189
  }
168
190
 
169
191
  html[data-dsh-prts] [data-prts-session-lifeline-filament="back"] {
170
- stroke: var(--prts-lifeline-pink);
171
- opacity: .74;
172
- stroke-width: .85;
192
+ --prts-lifeline-color: var(--prts-lifeline-pink);
193
+ opacity: .92;
173
194
  }
174
195
 
175
196
  html[data-dsh-prts] [data-prts-session-lifeline-filament="core"] {
176
- stroke: var(--prts-lifeline-green);
177
- opacity: .68;
178
- stroke-width: .9;
197
+ --prts-lifeline-color: var(--prts-lifeline-green);
198
+ opacity: .9;
179
199
  }
180
200
 
181
201
  html[data-dsh-prts] [data-prts-session-lifeline-filament="front"] {
182
- stroke: var(--prts-lifeline-blue);
183
- opacity: .74;
184
- stroke-width: .85;
202
+ --prts-lifeline-color: var(--prts-lifeline-blue);
203
+ opacity: .98;
204
+ }
205
+
206
+ html[data-dsh-prts] [data-prts-session-lifeline-layer="body"] {
207
+ stroke-width: .9;
208
+ }
209
+
210
+ html[data-dsh-prts] [data-prts-session-lifeline-layer="halo"],
211
+ html[data-dsh-prts] [data-prts-session-lifeline-layer="core"] {
212
+ opacity: 0;
213
+ }
214
+
215
+ html[data-dsh-prts][data-prts-session-glow="off"] :is([data-prts-session-lifeline-layer="halo"], [data-prts-session-lifeline-layer="core"]) {
216
+ opacity: 0;
217
+ }
218
+
219
+ html[data-dsh-prts][data-prts-session-glow="on"] [data-prts-session-lifeline-layer="halo"] {
220
+ stroke-width: 4.25;
221
+ opacity: .28;
222
+ filter: blur(1.15px);
223
+ }
224
+
225
+ html[data-dsh-prts][data-prts-session-glow="on"] [data-prts-session-lifeline-layer="body"] {
226
+ stroke-width: 1.65;
227
+ opacity: .98;
228
+ }
229
+
230
+ html[data-dsh-prts][data-prts-session-glow="on"] [data-prts-session-lifeline-layer="core"] {
231
+ stroke: color-mix(in srgb, var(--prts-lifeline-color) 18%, #fff);
232
+ stroke-width: .58;
233
+ opacity: .96;
234
+ }
235
+
236
+ html[data-dsh-prts][data-prts-scheme="light"][data-prts-session-glow="on"] [data-prts-session-lifeline-layer="halo"] {
237
+ stroke: color-mix(in srgb, var(--prts-lifeline-color) 42%, #fff);
238
+ stroke-width: 4.4;
239
+ opacity: .45;
240
+ filter: blur(1.05px);
241
+ }
242
+
243
+ html[data-dsh-prts][data-prts-scheme="light"][data-prts-session-glow="on"] [data-prts-session-lifeline-layer="body"] {
244
+ stroke-width: 1.5;
245
+ }
246
+
247
+ html[data-dsh-prts][data-prts-scheme="light"][data-prts-session-glow="on"] [data-prts-session-lifeline-layer="core"] {
248
+ stroke: color-mix(in srgb, var(--prts-lifeline-color) 58%, #fff);
249
+ stroke-width: .52;
185
250
  }
186
251
 
187
252
  html[data-dsh-prts] [data-prts-session-row][aria-selected="true"] [data-prts-session-lifeline] {
188
- opacity: .62;
253
+ opacity: .98;
189
254
  }
190
255
 
191
256
  html[data-dsh-prts] [data-prts-session-row][aria-selected="true"]:hover [data-prts-session-lifeline] {
@@ -197,12 +262,14 @@ html[data-dsh-prts][data-prts-session-flow="off"] [data-prts-session-row] [data-
197
262
  }
198
263
 
199
264
  @media (prefers-reduced-motion: reduce) {
200
- html[data-dsh-prts] [data-prts-session-lifeline] {
265
+ html[data-dsh-prts] [data-prts-session-lifeline],
266
+ html[data-dsh-prts] [data-prts-session-lifeline-layer] {
201
267
  transition-duration: 0s;
202
268
  }
203
269
  }
204
270
 
205
- html[data-dsh-prts][data-prts-motion="reduced"] [data-prts-session-lifeline] {
271
+ html[data-dsh-prts][data-prts-motion="reduced"] [data-prts-session-lifeline],
272
+ html[data-dsh-prts][data-prts-motion="reduced"] [data-prts-session-lifeline-layer] {
206
273
  transition-duration: 0s;
207
274
  }
208
275
 
@@ -260,12 +260,18 @@ html[data-dsh-prts] [data-prts-settings-common] [data-prts-setting-row] {
260
260
  }
261
261
 
262
262
  html[data-dsh-prts] [data-prts-settings-common] [data-prts-setting-row]:nth-child(2n) { border-right: 0; }
263
- html[data-dsh-prts] [data-prts-settings-common] [data-prts-setting-row]:nth-last-child(-n + 2) { border-bottom: 0; }
264
263
 
265
- html[data-dsh-prts] [data-prts-settings-common] [data-prts-setting-row="conversationStyle"] {
264
+ html[data-dsh-prts] [data-prts-settings-common] :is(
265
+ [data-prts-setting-row="sessionFlowPalette"],
266
+ [data-prts-setting-row="sessionFlowColors"],
267
+ [data-prts-setting-row="sessionFlowSpeed"],
268
+ [data-prts-setting-row="conversationStyle"]
269
+ ) {
266
270
  grid-column: 1 / -1;
267
- border-top: 1px solid var(--prts-line);
268
271
  border-right: 0;
272
+ }
273
+
274
+ html[data-dsh-prts] [data-prts-settings-common] [data-prts-setting-row="conversationStyle"] {
269
275
  border-bottom: 0;
270
276
  }
271
277
 
@@ -300,6 +306,9 @@ html[data-dsh-prts] [data-prts-settings-common] button[data-prts-setting-key] {
300
306
  gap: 5px;
301
307
  }
302
308
 
309
+ html[data-dsh-prts] [data-prts-setting-row="sessionFlowPalette"] > div { flex-wrap: wrap; }
310
+ html[data-dsh-prts] [data-prts-setting-row="sessionFlowPalette"] button[data-prts-setting-key] { flex-basis: 98px; }
311
+
303
312
  html[data-dsh-prts] [data-prts-option-sample] {
304
313
  position: relative;
305
314
  width: 22px;
@@ -341,6 +350,67 @@ html[data-dsh-prts] [data-prts-option-sample="glass"][data-prts-option-sample-va
341
350
  html[data-dsh-prts] [data-prts-option-sample="glass"][data-prts-option-sample-value="standard"]::after { background: color-mix(in srgb, var(--prts-panel-raised) 62%, transparent); }
342
351
  html[data-dsh-prts] [data-prts-option-sample="glass"][data-prts-option-sample-value="clear"]::after { background: color-mix(in srgb, var(--prts-panel-raised) 34%, transparent); backdrop-filter: blur(4px) saturate(1.35); -webkit-backdrop-filter: blur(4px) saturate(1.35); }
343
352
 
353
+ html[data-dsh-prts] [data-prts-option-sample="sessionFlowPalette"] {
354
+ border: 0;
355
+ background: linear-gradient(90deg, #f7ddeb 0 33%, #65ddb0 33% 66%, #6eb7f3 66%);
356
+ clip-path: polygon(0 40%, 24% 18%, 48% 54%, 72% 24%, 100% 46%, 100% 68%, 72% 46%, 48% 76%, 24% 40%, 0 62%);
357
+ }
358
+ html[data-dsh-prts] [data-prts-option-sample="sessionFlowPalette"][data-prts-option-sample-value="rhodes"] { background: linear-gradient(90deg, #b9edf4 0 33%, #5ccddb 33% 66%, #5a9ee6 66%); }
359
+ html[data-dsh-prts] [data-prts-option-sample="sessionFlowPalette"][data-prts-option-sample-value="amber"] { background: linear-gradient(90deg, #ffe6a3 0 33%, #f0c800 33% 66%, #ee8f42 66%); }
360
+ html[data-dsh-prts] [data-prts-option-sample="sessionFlowPalette"][data-prts-option-sample-value="alert"] { background: linear-gradient(90deg, #ffc0b8 0 33%, #ee625a 33% 66%, #db5b8c 66%); }
361
+ html[data-dsh-prts] [data-prts-option-sample="sessionFlowPalette"][data-prts-option-sample-value="custom"] { background: linear-gradient(90deg, #d95785 0 33%, #d0a900 33% 66%, #268fbd 66%); }
362
+
363
+ html[data-dsh-prts] [data-prts-settings-common] [data-prts-setting-row="sessionFlowColors"] {
364
+ align-items: stretch;
365
+ padding-block: 9px;
366
+ }
367
+
368
+ html[data-dsh-prts] [data-prts-settings-common] [data-prts-session-flow-color-workbench] {
369
+ display: grid;
370
+ grid-template-columns: minmax(160px, .8fr) minmax(0, 1.2fr);
371
+ align-items: center;
372
+ gap: 10px;
373
+ }
374
+
375
+ html[data-dsh-prts] [data-prts-session-flow-preview] {
376
+ --prts-lifeline-pink: #f7ddeb;
377
+ --prts-lifeline-green: #65ddb0;
378
+ --prts-lifeline-blue: #6eb7f3;
379
+ width: 100%;
380
+ height: 54px;
381
+ display: block;
382
+ overflow: visible;
383
+ border: 1px solid var(--prts-line);
384
+ background: color-mix(in srgb, var(--prts-canvas) 72%, transparent);
385
+ }
386
+
387
+ html[data-dsh-prts] [data-prts-session-flow-preview][data-prts-session-flow-preview-palette="rhodes"] { --prts-lifeline-pink: #b9edf4; --prts-lifeline-green: #5ccddb; --prts-lifeline-blue: #5a9ee6; }
388
+ html[data-dsh-prts] [data-prts-session-flow-preview][data-prts-session-flow-preview-palette="amber"] { --prts-lifeline-pink: #ffe6a3; --prts-lifeline-green: #f0c800; --prts-lifeline-blue: #ee8f42; }
389
+ html[data-dsh-prts] [data-prts-session-flow-preview][data-prts-session-flow-preview-palette="alert"] { --prts-lifeline-pink: #ffc0b8; --prts-lifeline-green: #ee625a; --prts-lifeline-blue: #db5b8c; }
390
+ html[data-dsh-prts] [data-prts-session-flow-preview][data-prts-session-flow-preview-palette="custom"] { --prts-lifeline-pink: var(--prts-session-flow-back); --prts-lifeline-green: var(--prts-session-flow-core); --prts-lifeline-blue: var(--prts-session-flow-front); }
391
+
392
+ html[data-dsh-prts] [data-prts-session-flow-preview-filament="back"] { --prts-preview-color: var(--prts-lifeline-pink); }
393
+ html[data-dsh-prts] [data-prts-session-flow-preview-filament="core"] { --prts-preview-color: var(--prts-lifeline-green); }
394
+ html[data-dsh-prts] [data-prts-session-flow-preview-filament="front"] { --prts-preview-color: var(--prts-lifeline-blue); }
395
+ html[data-dsh-prts] [data-prts-session-flow-preview-layer] { fill: none; stroke: var(--prts-preview-color); stroke-linecap: round; stroke-linejoin: round; }
396
+ html[data-dsh-prts] [data-prts-session-flow-preview-layer="body"] { stroke-width: 1.3; opacity: .92; }
397
+ html[data-dsh-prts] [data-prts-session-flow-preview-layer="halo"],
398
+ html[data-dsh-prts] [data-prts-session-flow-preview-layer="core"] { opacity: 0; }
399
+ html[data-dsh-prts][data-prts-session-glow="on"] [data-prts-session-flow-preview-layer="halo"] { stroke-width: 5; opacity: .25; filter: blur(1.2px); }
400
+ html[data-dsh-prts][data-prts-session-glow="on"] [data-prts-session-flow-preview-layer="body"] { stroke-width: 2.2; }
401
+ html[data-dsh-prts][data-prts-session-glow="on"] [data-prts-session-flow-preview-layer="core"] { stroke: color-mix(in srgb, var(--prts-preview-color) 18%, #fff); stroke-width: .72; opacity: .98; }
402
+ html[data-dsh-prts][data-prts-scheme="light"][data-prts-session-glow="on"] [data-prts-session-flow-preview-layer="halo"] { stroke: color-mix(in srgb, var(--prts-preview-color) 42%, #fff); stroke-width: 5.5; opacity: .45; filter: blur(1.3px); }
403
+ html[data-dsh-prts][data-prts-scheme="light"][data-prts-session-glow="on"] [data-prts-session-flow-preview-layer="core"] { stroke: color-mix(in srgb, var(--prts-preview-color) 58%, #fff); }
404
+
405
+ html[data-dsh-prts] [data-prts-session-flow-color-inputs] {
406
+ display: grid;
407
+ grid-template-columns: repeat(3, minmax(0, 1fr));
408
+ gap: 5px;
409
+ }
410
+ html[data-dsh-prts] [data-prts-session-flow-color-inputs] label { min-width: 0; display: grid; grid-template-columns: 34px minmax(34px, 1fr); gap: 4px; align-items: center; color: var(--prts-muted); font: 700 8px/1 var(--prts-mono); }
411
+ html[data-dsh-prts] [data-prts-session-flow-color-inputs] input[type="color"] { width: 100%; height: 28px; padding: 2px; border: 1px solid var(--prts-line); border-radius: 0; background: var(--prts-panel-raised); cursor: pointer; }
412
+ html[data-dsh-prts] [data-prts-session-flow-color-inputs] output { grid-column: 1 / -1; color: var(--prts-ink); font: 700 8px/1 var(--prts-mono); text-align: center; text-transform: uppercase; }
413
+
344
414
  html[data-dsh-prts] [data-prts-theme-settings] button[data-prts-setting-key],
345
415
  html[data-dsh-prts] [data-prts-retry-save],
346
416
  html[data-dsh-prts] [data-prts-reset-visual],
@@ -463,6 +533,13 @@ html[data-dsh-prts] [data-prts-particle-traversal-output] {
463
533
  font: 800 8px/1.2 var(--prts-mono);
464
534
  text-align: right;
465
535
  }
536
+ html[data-dsh-prts] [data-prts-session-flow-speed-output] {
537
+ min-width: 64px;
538
+ color: var(--prts-cyan);
539
+ font: 800 8px/1.2 var(--prts-mono);
540
+ text-align: right;
541
+ }
542
+ html[data-dsh-prts] [data-prts-session-flow-speed] input[type="range"] { min-width: 120px; }
466
543
  html[data-dsh-prts] [data-prts-particle-error] { margin: 8px 0 0; color: var(--prts-yellow); font: 700 8px/1.4 var(--prts-mono); }
467
544
 
468
545
  html[data-dsh-prts] [data-prts-setting-range-row] {
@@ -625,7 +702,9 @@ html[data-dsh-prts] :is(
625
702
  html[data-dsh-prts] [data-prts-settings-common] [data-prts-setting-row] { min-height: 62px; }
626
703
  html[data-dsh-prts] [data-prts-settings-common] button[data-prts-setting-key] { min-height: 40px; }
627
704
  html[data-dsh-prts] [data-prts-settings-common] [data-prts-setting-row] { border-right: 0; border-bottom: 1px solid var(--prts-line); }
628
- html[data-dsh-prts] [data-prts-settings-common] [data-prts-setting-row]:nth-last-child(2) { border-bottom: 1px solid var(--prts-line); }
705
+ html[data-dsh-prts] [data-prts-settings-common] [data-prts-session-flow-color-workbench] { grid-template-columns: minmax(0, 1fr); }
706
+ html[data-dsh-prts] [data-prts-settings-common] [data-prts-setting-row]:nth-last-child(2),
707
+ html[data-dsh-prts] [data-prts-settings-common] [data-prts-setting-row]:nth-last-child(3) { border-bottom: 1px solid var(--prts-line); }
629
708
  html[data-dsh-prts] [data-prts-settings-common] [data-prts-setting-row]:last-child { border-bottom: 0; }
630
709
  html[data-dsh-prts] [data-prts-settings-advanced-content] { grid-template-columns: minmax(0, 1fr); }
631
710
  html[data-dsh-prts] [data-prts-settings-advanced-content] > section + section { border-left: 0; border-top: 1px solid var(--prts-line); }