dsh-remote-plugin 0.6.18 → 0.6.20

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/public/motion.js CHANGED
@@ -7,8 +7,21 @@
7
7
 
8
8
  const reduceQuery = window.matchMedia?.('(prefers-reduced-motion: reduce)')
9
9
  let reduced = !!reduceQuery?.matches
10
- reduceQuery?.addEventListener?.('change', event => { reduced = !!event.matches })
11
- const activePulses = new WeakSet()
10
+ const activePulses = new Set()
11
+ const recentRuns = new WeakMap()
12
+
13
+ reduceQuery?.addEventListener?.('change', event => {
14
+ reduced = !!event.matches
15
+ if (!reduced) return
16
+ const animated = document.querySelectorAll('.view, .ds-view, [data-motion-view], .modal, .ds-modal, .sheet, .ds-drawer, [data-motion-panel]')
17
+ gsap.killTweensOf(animated)
18
+ clear(animated)
19
+ for (const node of activePulses) {
20
+ gsap.killTweensOf(node)
21
+ clear(node)
22
+ }
23
+ activePulses.clear()
24
+ })
12
25
 
13
26
  function clear(targets) {
14
27
  gsap.set(targets, { clearProps: 'opacity,visibility,transform,willChange' })
@@ -22,17 +35,32 @@
22
35
  return items.map(motionKey).join('|')
23
36
  }
24
37
 
38
+ function startedRecently(node, threshold = 48) {
39
+ const now = window.performance?.now?.() || Date.now()
40
+ const previous = recentRuns.get(node) || 0
41
+ recentRuns.set(node, now)
42
+ return previous > 0 && now - previous < threshold
43
+ }
44
+
25
45
  function view(view) {
26
- if (!view) return
27
- const children = [...view.children].filter(child => !child.classList.contains('hidden')).slice(0, 6)
28
- gsap.killTweensOf([view, ...children])
46
+ if (!view || startedRecently(view)) return
47
+ const children = [...view.children].filter(child => !child.classList.contains('hidden')).slice(0, 8)
48
+ const targets = children.length ? children : [view]
49
+ gsap.killTweensOf([view, ...targets])
50
+ gsap.set(view, { autoAlpha: 1, clearProps: 'transform' })
29
51
  if (reduced) {
30
- clear([view, ...children])
52
+ clear([view, ...targets])
31
53
  return
32
54
  }
33
- const tl = gsap.timeline({ defaults: { ease: 'power2.out' } })
34
- tl.fromTo(view, { autoAlpha: 0, y: 8 }, { autoAlpha: 1, y: 0, duration: 0.22, clearProps: 'transform' })
35
- .fromTo(children, { autoAlpha: 0, y: 6 }, { autoAlpha: 1, y: 0, duration: 0.16, stagger: 0.025, clearProps: 'transform' }, '<0.04')
55
+ gsap.fromTo(targets, { opacity: 0.72, y: 8 }, {
56
+ opacity: 1,
57
+ y: 0,
58
+ duration: 0.24,
59
+ ease: 'power2.out',
60
+ stagger: { each: 0.035, from: 'start' },
61
+ overwrite: 'auto',
62
+ clearProps: 'opacity,visibility,transform,willChange'
63
+ })
36
64
  }
37
65
 
38
66
  function list(container, selector) {
@@ -420,8 +448,57 @@
420
448
  registry.set(selector, state)
421
449
  }
422
450
 
451
+ function panel(node) {
452
+ if (!node || startedRecently(node)) return
453
+ gsap.killTweensOf(node)
454
+ if (reduced) return clear(node)
455
+ gsap.fromTo(node, { autoAlpha: 0, y: 8 }, {
456
+ autoAlpha: 1,
457
+ y: 0,
458
+ duration: 0.2,
459
+ ease: 'power2.out',
460
+ overwrite: 'auto',
461
+ clearProps: 'opacity,visibility,transform,willChange'
462
+ })
463
+ }
464
+
465
+ function popover(node) {
466
+ if (!node || startedRecently(node)) return
467
+ const opensUpward = !!(node.closest('.composer-wrap, .ds-composer') || node.style.bottom)
468
+ gsap.killTweensOf(node)
469
+ if (reduced) return clear(node)
470
+ gsap.fromTo(node, {
471
+ autoAlpha: 0,
472
+ y: opensUpward ? 7 : -7,
473
+ scale: 0.985,
474
+ transformOrigin: opensUpward ? 'bottom left' : 'top right'
475
+ }, {
476
+ autoAlpha: 1,
477
+ y: 0,
478
+ scale: 1,
479
+ duration: 0.18,
480
+ ease: 'power2.out',
481
+ overwrite: 'auto',
482
+ clearProps: 'opacity,visibility,transform,transformOrigin,willChange'
483
+ })
484
+ }
485
+
486
+ function activate(node) {
487
+ if (!node || reduced || startedRecently(node, 90)) return
488
+ const target = node.querySelector('.nav-home-orb, .nav-ico, .ds-nav-ico') || node
489
+ gsap.killTweensOf(target)
490
+ gsap.fromTo(target, { scale: 0.9, y: 2 }, {
491
+ scale: 1,
492
+ y: 0,
493
+ duration: 0.22,
494
+ ease: 'power2.out',
495
+ overwrite: 'auto',
496
+ clearProps: 'transform,willChange'
497
+ })
498
+ }
499
+
423
500
  function overlay(node) {
424
- if (!node) return
501
+ if (!node || startedRecently(node)) return
425
502
  const card = node.querySelector('.modal-card, .ds-modal-card, .sheet, .ds-drawer') || node
426
503
  gsap.killTweensOf([node, card])
427
504
  if (reduced) {
@@ -430,11 +507,18 @@
430
507
  }
431
508
  const isSideDrawer = card.classList.contains('ds-drawer')
432
509
  const isSheet = card.classList.contains('sheet')
510
+ if (card === node) {
511
+ gsap.fromTo(card,
512
+ { autoAlpha: 0, x: isSideDrawer ? 28 : 0, y: isSheet ? 24 : 8, scale: isSideDrawer || isSheet ? 1 : 0.985 },
513
+ { autoAlpha: 1, x: 0, y: 0, scale: 1, duration: isSheet ? 0.24 : 0.2, ease: 'power3.out', overwrite: 'auto', clearProps: 'opacity,visibility,transform,willChange' }
514
+ )
515
+ return
516
+ }
433
517
  const tl = gsap.timeline({ defaults: { ease: 'power3.out' } })
434
- tl.fromTo(node, { autoAlpha: 0 }, { autoAlpha: 1, duration: 0.16 })
518
+ tl.fromTo(node, { autoAlpha: 0 }, { autoAlpha: 1, duration: 0.14, overwrite: 'auto', clearProps: 'opacity,visibility' })
435
519
  .fromTo(card,
436
- { autoAlpha: 0, x: isSideDrawer ? 28 : 0, y: isSheet ? 24 : 8, scale: isSideDrawer || isSheet ? 1 : 0.985 },
437
- { autoAlpha: 1, x: 0, y: 0, scale: 1, duration: isSheet ? 0.24 : 0.2, clearProps: 'transform' },
520
+ { x: isSideDrawer ? 28 : 0, y: isSheet ? 24 : 8, scale: isSideDrawer || isSheet ? 1 : 0.985 },
521
+ { x: 0, y: 0, scale: 1, duration: isSheet ? 0.24 : 0.2, overwrite: 'auto', clearProps: 'transform,willChange' },
438
522
  '<'
439
523
  )
440
524
  }
@@ -449,10 +533,10 @@
449
533
  }
450
534
  }
451
535
 
452
- window.DshMotion = { gsap, reduced: () => reduced, view, list, relayout, bindLongPressReorder, overlay, pulse }
536
+ window.DshMotion = { gsap, reduced: () => reduced, view, list, relayout, bindLongPressReorder, overlay, panel, popover, activate, pulse }
453
537
 
454
538
  document.addEventListener('DOMContentLoaded', () => {
455
- document.querySelectorAll('.view:not(.hidden), .ds-view:not(.hidden)').forEach(node => view(node))
539
+ document.querySelectorAll('.view:not(.hidden), .ds-view:not(.hidden), [data-motion-view]:not(.hidden)').forEach(node => view(node))
456
540
  }, { once: true })
457
541
 
458
542
  const observer = new MutationObserver(records => {
@@ -460,9 +544,13 @@
460
544
  const node = record.target
461
545
  if (!(node instanceof HTMLElement)) continue
462
546
  const becameVisible = record.oldValue?.split(/\s+/).includes('hidden') && !node.classList.contains('hidden')
547
+ const becameActive = !record.oldValue?.split(/\s+/).includes('active') && node.classList.contains('active')
548
+ if (becameActive && node.matches('.nav-btn, .ds-nav-item')) activate(node)
463
549
  if (!becameVisible) continue
464
- if (node.matches('.view, .ds-view')) view(node)
465
- else if (node.matches('.modal, .ds-modal, .sheet, .ds-drawer')) overlay(node)
550
+ if (node.matches('.view, .ds-view, [data-motion-view]')) view(node)
551
+ else if (node.matches('.modal, .ds-modal, .sheet-backdrop, .sheet, .ds-drawer')) overlay(node)
552
+ else if (node.matches('.composer-menu, .ds-group-menu, .ds-feedback-menu, .fb-menu')) popover(node)
553
+ else if (node.matches('[data-motion-panel], .wb-panel, .ds-wb-panel, .doctor-body, .settings-subpage')) panel(node)
466
554
  }
467
555
  })
468
556
  observer.observe(document.documentElement, { subtree: true, attributes: true, attributeFilter: ['class'], attributeOldValue: true })
@@ -4,19 +4,19 @@
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
6
6
  <title>DSH Remote</title>
7
- <script>/* 插件抽屉首帧沿用当前主题 */ (function(){try{var t=localStorage.getItem('dshTheme');if(t!=='default'&&t!=='dark'&&t!=='light'&&t!=='neutral'){t=window.matchMedia('(prefers-color-scheme: light)').matches?'light':'default'}document.documentElement.setAttribute('data-theme',t)}catch(e){}})()</script>
7
+ <script>/* 插件抽屉首帧沿用当前主题 */ (function(){try{var t=localStorage.getItem('dshTheme');if(t!=='default'&&t!=='dark'&&t!=='light'&&t!=='neutral'&&t!=='mono'){t=window.matchMedia('(prefers-color-scheme: light)').matches?'light':'default'}document.documentElement.setAttribute('data-theme',t)}catch(e){}})()</script>
8
8
  <link rel="stylesheet" href="theme-vars.css">
9
9
  <style>
10
10
  :root { color-scheme: dark; }
11
11
  html[data-theme="light"], html[data-theme="neutral"] { color-scheme: light; }
12
- * { box-sizing: border-box; }
12
+ * { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
13
13
  body {
14
14
  margin: 0; min-width: 280px; color: var(--dsr-text); background:
15
15
  radial-gradient(420px 240px at 100% 0, var(--dsr-accent-soft), transparent 72%),
16
16
  var(--dsr-bg); font: 13px/1.45 system-ui, -apple-system, "PingFang SC", "Noto Sans CJK SC", sans-serif;
17
17
  }
18
18
  button, a { font: inherit; }
19
- button { cursor: pointer; }
19
+ button { cursor: pointer; touch-action: manipulation; }
20
20
  .plugin-shell { min-height: 100vh; padding: 18px 16px 16px; display: flex; flex-direction: column; gap: 14px; }
21
21
  .plugin-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
22
22
  .plugin-brand { display: flex; align-items: center; gap: 9px; min-width: 0; }
@@ -41,8 +41,9 @@
41
41
  .plugin-primary:hover, .plugin-primary:focus-visible { filter: brightness(1.08); transform: translateY(-1px); }
42
42
  .plugin-primary:disabled { cursor: wait; opacity: .65; transform: none; }
43
43
  .plugin-actions { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
44
- .plugin-action { min-height: 42px; padding: 7px 5px; border: 1px solid var(--dsr-line); border-radius: 12px; background: var(--dsr-panel); color: var(--dsr-text); font-size: 11px; }
44
+ .plugin-action { min-height: 42px; padding: 7px 5px; border: 1px solid var(--dsr-line); border-radius: 12px; background: var(--dsr-panel); color: var(--dsr-text); font-size: 11px; transition: transform .18s ease, background-color .18s ease, border-color .18s ease; }
45
45
  .plugin-action:hover, .plugin-action:focus-visible { border-color: var(--dsr-accent-line); background: var(--dsr-accent-soft); }
46
+ .plugin-action:active { transform: scale(.98); }
46
47
  .plugin-action svg { display: block; width: 17px; height: 17px; margin: 0 auto 3px; color: var(--dsr-accent-strong); }
47
48
  .plugin-usage { padding: 14px; border: 1px solid var(--dsr-line); border-radius: 16px; background: linear-gradient(145deg, var(--dsr-panel), var(--dsr-bg-2)); }
48
49
  .plugin-section-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; color: var(--dsr-text); font-size: 12px; font-weight: 750; }
@@ -87,7 +88,7 @@
87
88
  </style>
88
89
  </head>
89
90
  <body>
90
- <main class="plugin-shell">
91
+ <main class="plugin-shell" data-motion-view>
91
92
  <header class="plugin-head">
92
93
  <div class="plugin-brand">
93
94
  <span class="plugin-brand-mark" aria-hidden="true"></span>
package/public/styles.css CHANGED
@@ -1,4 +1,4 @@
1
- /* DSH Remote · 移动优先 · 四皮肤(默认深空/深色落日/亮色易北爱乐厅/中性草原孤塔)
1
+ /* DSH Remote · 移动优先 · 五皮肤(默认深空/深色落日/亮色易北爱乐厅/中性草原孤塔/黑曜白)
2
2
  * 规则样式表; 变量定义已抽取到 theme-vars.css(桌面端共享), 保持单一来源。 */
3
3
 
4
4
  @import 'theme-vars.css';
@@ -424,12 +424,42 @@ body.in-session .view {
424
424
  .queue-dock-item:last-child { border-bottom: 0; }
425
425
  .queue-dock-preview { flex: 1; min-width: 0; color: var(--dsr-text); font-size: 13px; line-height: 1.4; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
426
426
  .queue-dock-action { flex: 0 0 auto; }
427
+ .session-pending { flex:0 0 auto; margin:0 0 10px; padding:10px; border:1px solid var(--dsr-warning-line); border-radius:13px; background:var(--dsr-warning-soft); }
428
+ .session-pending-head { display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:8px; color:var(--dsr-text); font-size:12px; font-weight:750; }
429
+ .session-pending-list { display:flex; flex-direction:column; gap:8px; }
430
+ .session-pending .pending-card { min-width:0; background:var(--dsr-panel); }
431
+ .session-pending .pc-title { line-height:1.45; overflow-wrap:anywhere; word-break:break-word; }
432
+ .session-pending .pc-desc { line-height:1.5; white-space:pre-wrap; overflow-wrap:anywhere; }
433
+ .session-pending .goal-actions { justify-content:flex-end; }
427
434
  .md-table-wrap { max-width: 100%; overflow-x: auto; margin: 8px 0; }
428
435
  .md-table-wrap table { width: max-content; min-width: 100%; border-collapse: collapse; font-size: .94em; }
429
436
  .md-table-wrap th, .md-table-wrap td { padding: 6px 9px; border: 1px solid var(--dsr-line); text-align: left; white-space: nowrap; }
430
437
  .md-table-wrap th { background: var(--dsr-bg-2); font-weight: 700; }
431
438
  .md-table-wrap tbody tr:nth-child(even) { background: color-mix(in srgb, var(--dsr-bg-2) 45%, transparent); }
432
- .goal-obj { font-size: 13px; line-height: 1.55; color: var(--dsr-text); }
439
+ .goal-disclosure { width: 100%; min-width: 0; display: flex; justify-content: flex-end; }
440
+ .goal-disclosure .goal-card { width: 100%; min-width: 0; }
441
+ .goal-card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
442
+ .goal-card-head .card-title { min-width: 0; margin-bottom: 0; }
443
+ .goal-collapse-btn,
444
+ .goal-side-tab {
445
+ touch-action: manipulation; border: 1px solid var(--dsr-line); background: var(--dsr-bg-2); color: var(--dsr-muted);
446
+ font: inherit; cursor: pointer;
447
+ }
448
+ .goal-collapse-btn { min-height: 34px; display: inline-flex; align-items: center; gap: 4px; padding: 4px 9px; border-radius: 9px; font-size: 12px; }
449
+ .goal-collapse-btn > span { color: var(--dsr-accent-strong); font-size: 18px; line-height: 1; }
450
+ .goal-side-tab {
451
+ min-height: 46px; max-width: min(100%, 210px); display: inline-flex; align-items: center; gap: 7px; padding: 7px 12px 7px 10px;
452
+ border-right: 0; border-radius: 12px 0 0 12px; box-shadow: -5px 6px 18px var(--dsr-shadow); color: var(--dsr-text); font-size: 13px; font-weight: 700;
453
+ }
454
+ .goal-side-tab > span:first-child { color: var(--dsr-accent-strong); font-size: 20px; line-height: 1; }
455
+ .goal-side-tab small { min-width: 0; color: var(--dsr-muted); font-size: 11px; font-weight: 500; white-space: nowrap; }
456
+ .goal-collapse-btn:hover,
457
+ .goal-side-tab:hover { background: var(--dsr-panel-2); color: var(--dsr-text); }
458
+ .goal-collapse-btn:active,
459
+ .goal-side-tab:active { transform: translateY(1px); }
460
+ .goal-collapse-btn:focus-visible,
461
+ .goal-side-tab:focus-visible { outline: 2px solid var(--dsr-accent-strong); outline-offset: 2px; }
462
+ .goal-obj { font-size: 13px; line-height: 1.55; color: var(--dsr-text); overflow-wrap: anywhere; }
433
463
  .goal-phase { font-size: 12px; color: var(--dsr-info); margin-top: 3px; }
434
464
  .goal-actions { display: flex; gap: 8px; margin-top: 9px; flex-wrap: wrap; }
435
465
  .goal-actions .mini-btn { flex: 1; text-align: center; min-width: 64px; }
@@ -688,16 +718,17 @@ body.in-session .main { padding-bottom: 0; }
688
718
  .overview-section-meta { color:var(--dsr-muted); font-size:11px; font-weight:500; }
689
719
  .overview-attention-list, .overview-session-list { display:flex; flex-direction:column; gap:7px; }
690
720
  .overview-attention-item, .overview-session-item { width:100%; display:flex; align-items:center; gap:10px; min-width:0; padding:11px 12px; border:1px solid var(--dsr-line); border-radius:13px; background:var(--dsr-panel); color:var(--dsr-text); text-align:left; }
721
+ .overview-attention-item { align-items:flex-start; }
691
722
  button.overview-attention-item, button.overview-session-item { cursor:pointer; }
692
723
  .overview-attention-item { border-left:3px solid var(--dsr-warning); }
693
724
  .overview-attention-item.question { border-left-color:var(--dsr-accent-2); }
694
725
  .overview-item-mark { flex:0 0 auto; width:25px; height:25px; display:grid; place-items:center; border-radius:8px; background:var(--dsr-warning-soft); color:var(--dsr-warning); font-size:12px; }
695
726
  .overview-attention-item.question .overview-item-mark { background:var(--dsr-accent-2-soft); color:var(--dsr-accent-2); }
696
727
  .overview-item-copy { min-width:0; flex:1; }
697
- .overview-item-title { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:12.5px; font-weight:650; }
698
- .overview-item-desc { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; margin-top:2px; color:var(--dsr-muted); font-size:11px; }
728
+ .overview-item-title { font-size:12.5px; font-weight:650; line-height:1.45; overflow-wrap:anywhere; word-break:break-word; }
729
+ .overview-item-desc { margin-top:3px; color:var(--dsr-muted); font-size:11px; line-height:1.45; white-space:normal; overflow-wrap:anywhere; }
699
730
  .overview-item-arrow { color:var(--dsr-muted); font-size:18px; }
700
- .overview-item-actions { flex:0 0 auto; display:flex; gap:4px; }
731
+ .overview-item-actions { flex:0 0 auto; display:flex; flex-wrap:wrap; justify-content:flex-end; gap:4px; }
701
732
  .overview-item-actions .mini-btn { padding:4px 7px; font-size:10px; }
702
733
  .overview-metric-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:7px; }
703
734
  .overview-metric { min-width:0; padding:11px 12px; border:1px solid var(--dsr-line); border-radius:13px; background:var(--dsr-panel); }
@@ -868,6 +899,16 @@ button.overview-attention-item, button.overview-session-item { cursor:pointer; }
868
899
  }
869
900
  .setting-row > div:first-child { flex: 1; min-width: 0; }
870
901
  .setting-row + .setting-row { border-top: 1px solid var(--dsr-line); }
902
+ .setting-link {
903
+ width: 100%; color: var(--dsr-text); text-align: left;
904
+ transition: background-color .18s ease, color .18s ease;
905
+ }
906
+ .setting-link::after {
907
+ content: '›'; flex: 0 0 auto; color: var(--dsr-muted); font-size: 20px; font-weight: 400;
908
+ transform: translateX(0); transition: transform .18s ease, color .18s ease;
909
+ }
910
+ .setting-link:hover, .setting-link:focus-visible { background: var(--dsr-bg-2); }
911
+ .setting-link:hover::after, .setting-link:focus-visible::after { color: var(--dsr-accent-strong); transform: translateX(2px); }
871
912
  .setting-name { font-size: 14.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
872
913
  .dsh-experimental-badge { display: inline-block; margin-left: 6px; padding: 2px 6px; border: 1px solid var(--dsr-warning-line); border-radius: 999px; color: var(--dsr-warning); background: var(--dsr-warning-soft); font-size: 10px; font-weight: 700; vertical-align: 2px; }
873
914
  .setting-desc { font-size: 12px; color: var(--dsr-muted); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@@ -942,11 +983,11 @@ button.overview-attention-item, button.overview-session-item { cursor:pointer; }
942
983
  .switch input { opacity: 0; width: 0; height: 0; }
943
984
  .slider {
944
985
  position: absolute; inset: 0; border-radius: 999px; background: var(--dsr-panel-2);
945
- border: 1px solid var(--dsr-line); transition: .2s;
986
+ border: 1px solid var(--dsr-line); transition: background-color .2s ease, border-color .2s ease;
946
987
  }
947
988
  .slider::before {
948
989
  content: ''; position: absolute; width: 19px; height: 19px; border-radius: 50%;
949
- left: 3px; top: 3px; background: var(--dsr-muted); transition: .2s;
990
+ left: 3px; top: 3px; background: var(--dsr-muted); transition: transform .2s ease, background-color .2s ease;
950
991
  }
951
992
  .switch input:checked + .slider { background: var(--dsr-accent-soft); border-color: var(--dsr-accent); }
952
993
  .switch input:checked + .slider::before { transform: translateX(19px); background: var(--dsr-accent); }
@@ -970,21 +1011,17 @@ button.overview-attention-item, button.overview-session-item { cursor:pointer; }
970
1011
  }
971
1012
  .nav-btn .nav-ico { width: 22px; height: 22px; display: grid; place-items: center; line-height: 1; transition: transform .18s ease, color .18s ease; }
972
1013
  .nav-btn .nav-ico svg { width: 21px; height: 21px; display: block; }
973
- .nav-btn:nth-of-type(1) { --nav-tint: var(--dsr-info); }
974
- .nav-btn:nth-of-type(2) { --nav-tint: var(--dsr-success); }
975
- .nav-btn:nth-of-type(4) { --nav-tint: var(--dsr-warning); }
976
- .nav-btn:nth-of-type(5) { --nav-tint: var(--dsr-accent-2); }
977
- .nav-btn:not(.nav-home) .nav-ico { color: var(--nav-tint, var(--dsr-nav-muted)); opacity: .82; }
1014
+ .nav-btn:not(.nav-home) .nav-ico { color: var(--dsr-nav-muted); opacity: .84; }
978
1015
  .nav-btn:not(.nav-home) > span:last-of-type { color: var(--dsr-nav-muted); }
979
1016
  .nav-btn.active:not(.nav-home) { color: var(--dsr-nav-active); }
980
- .nav-btn.active:not(.nav-home) .nav-ico { transform: translateY(-1px); opacity: 1; }
1017
+ .nav-btn.active:not(.nav-home) .nav-ico { color: var(--dsr-nav-active); transform: translateY(-1px); opacity: 1; }
981
1018
  .nav-btn.active:not(.nav-home)::after { content: ''; position: absolute; bottom: 3px; width: 4px; height: 4px; border-radius: 50%; background: var(--dsr-nav-active); box-shadow: 0 0 10px var(--dsr-glow); }
982
1019
  .nav-home { z-index: 2; transform: translateY(-13px); color: var(--dsr-nav-muted); }
983
1020
  .nav-home-orb { width: 56px; height: 56px; display: grid; place-items: center; border-radius: 50%; background: var(--dsr-bg-2); border: 1px solid var(--dsr-accent-line); box-shadow: 0 5px 18px var(--dsr-shadow); transition: transform .18s ease, background .18s ease, box-shadow .18s ease; }
984
1021
  .nav-home .nav-ico { width: 30px; height: 30px; color: var(--dsr-accent-strong); }
985
1022
  .nav-home .nav-ico svg { width: 29px; height: 29px; }
986
1023
  .nav-home.active { color: var(--dsr-nav-active); }
987
- .nav-home.active .nav-home-orb { background: radial-gradient(circle at 34% 27%, var(--dsr-info), var(--dsr-accent) 42%, var(--dsr-accent-2)); border-color: var(--dsr-accent); color: var(--dsr-on-accent); box-shadow: 0 7px 24px var(--dsr-glow), inset 0 0 0 1px rgba(255,255,255,.32); }
1024
+ .nav-home.active .nav-home-orb { background: linear-gradient(145deg, var(--dsr-accent-2), var(--dsr-accent) 64%); border-color: var(--dsr-accent); color: var(--dsr-on-accent); box-shadow: 0 7px 24px var(--dsr-glow), inset 0 0 0 1px rgba(255,255,255,.28); }
988
1025
  .nav-home.active .nav-ico { color: var(--dsr-on-accent); transform: none; }
989
1026
  .nav-home:active .nav-home-orb { transform: scale(.96); }
990
1027
  .nav-badge {
@@ -997,7 +1034,6 @@ button.overview-attention-item, button.overview-session-item { cursor:pointer; }
997
1034
  .sheet-backdrop {
998
1035
  position: fixed; inset: 0; z-index: 45;
999
1036
  background: var(--dsr-overlay);
1000
- animation: sheet-fade .18s ease;
1001
1037
  }
1002
1038
  .sheet {
1003
1039
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 46;
@@ -1025,7 +1061,6 @@ button.overview-attention-item, button.overview-session-item { cursor:pointer; }
1025
1061
  .sheet-item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
1026
1062
  .sheet-item-name { font-size: 14px; font-weight: 600; }
1027
1063
  .sheet-item-desc { font-size: 12px; color: var(--dsr-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
1028
- @keyframes sheet-fade { from { opacity: 0 } to { opacity: 1 } }
1029
1064
 
1030
1065
  /* ---------- 应用内选择抽屉 ---------- */
1031
1066
  .custom-select-native {
@@ -1116,7 +1151,7 @@ button.overview-attention-item, button.overview-session-item { cursor:pointer; }
1116
1151
  .modal-card {
1117
1152
  width: 100%; max-width: 460px; max-height: 82vh; overflow-y: auto;
1118
1153
  background: var(--dsr-bg-2); border: 1px solid var(--dsr-line); border-radius: 18px;
1119
- padding: 16px;
1154
+ padding: 16px; box-shadow: 0 22px 60px var(--dsr-shadow); overscroll-behavior: contain;
1120
1155
  }
1121
1156
  .modal-title { font-size: 16px; font-weight: 700; margin-bottom: 10px; }
1122
1157
  .modal-body { font-size: 14px; }
@@ -1191,25 +1226,30 @@ button.overview-attention-item, button.overview-session-item { cursor:pointer; }
1191
1226
  .fs-workspace-nav { grid-template-columns: 1fr; }
1192
1227
  .file-preview-card { height: 88vh; padding: 13px; }
1193
1228
  }
1194
- .theme-panel-list { display: flex; flex-direction: column; gap: 8px; }
1229
+ .theme-panel-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px; }
1195
1230
  .theme-option {
1196
- display: flex; align-items: center; gap: 10px; min-width: 0; width: 100%;
1197
- padding: 11px 12px; border-radius: 12px; text-align: left;
1231
+ position: relative; display: flex; flex-direction: column; align-items: stretch; gap: 9px; min-width: 0; width: 100%;
1232
+ min-height: 86px; padding: 10px; border-radius: 13px; text-align: left;
1198
1233
  background: var(--dsr-panel); border: 1px solid var(--dsr-line);
1199
- white-space: nowrap;
1234
+ white-space: nowrap; overflow: hidden;
1235
+ transition: transform .18s ease, background-color .18s ease, border-color .18s ease, box-shadow .18s ease;
1200
1236
  }
1201
- .theme-option:active { background: var(--dsr-panel-2); }
1237
+ .theme-option:hover, .theme-option:focus-visible { background: var(--dsr-panel-2); border-color: var(--dsr-accent-line); transform: translateY(-1px); }
1238
+ .theme-option:active { background: var(--dsr-panel-2); transform: scale(.985); }
1202
1239
  .theme-option.current { border-color: var(--dsr-accent-line); box-shadow: 0 0 0 1px var(--dsr-accent-soft); }
1203
- .theme-swatches { display: inline-flex; gap: 4px; flex-shrink: 0; }
1240
+ .theme-swatches {
1241
+ display: grid; grid-template-columns: 1.35fr 1fr .72fr; height: 30px; flex-shrink: 0;
1242
+ overflow: hidden; border: 1px solid rgba(127, 127, 127, .28); border-radius: 8px;
1243
+ }
1204
1244
  .theme-swatches i {
1205
- width: 14px; height: 14px; border-radius: 50%; display: block;
1206
- border: 1px solid rgba(127, 127, 127, .35);
1245
+ width: auto; height: 100%; display: block;
1207
1246
  }
1208
1247
  .theme-option .theme-name {
1209
- flex: 1; min-width: 0; font-size: 14px; font-weight: 600;
1248
+ min-width: 0; padding-right: 22px; font-size: 13px; font-weight: 650;
1210
1249
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
1211
1250
  }
1212
- .theme-option .theme-check { flex-shrink: 0; color: var(--dsr-accent-strong); font-size: 14px; font-weight: 700; }
1251
+ .theme-option .theme-check { position: absolute; right: 11px; bottom: 9px; color: var(--dsr-accent-strong); font-size: 14px; font-weight: 700; }
1252
+ @media (max-width: 350px) { .theme-panel-list { grid-template-columns: 1fr; } }
1213
1253
 
1214
1254
  /* ---------- toast ---------- */
1215
1255
  .toast {