@aiwuk/team 0.0.0-stage → 5.0.8

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.
Files changed (117) hide show
  1. package/CHANGELOG.md +175 -0
  2. package/LICENSE +21 -0
  3. package/README.md +149 -2
  4. package/README.zh-CN.md +150 -0
  5. package/access.js +93 -0
  6. package/activity-summary.js +36 -0
  7. package/allocation.js +34 -0
  8. package/board-dispatch.js +141 -0
  9. package/brand.js +41 -0
  10. package/client/00-core-zh.js +284 -0
  11. package/client/01-i18n-en.js +265 -0
  12. package/client/02-styles.js +336 -0
  13. package/client/02b-stage-styles.js +65 -0
  14. package/client/03-shared.js +82 -0
  15. package/client/03b-collapsible-list.js +34 -0
  16. package/client/03c-config-panel.js +605 -0
  17. package/client/04-tool-cards.js +110 -0
  18. package/client/04a-dispatch-confirm.js +162 -0
  19. package/client/04b-more-cards.js +78 -0
  20. package/client/04c-model-picker.js +68 -0
  21. package/client/04d-confirm-dock.js +40 -0
  22. package/client/05-policy.js +217 -0
  23. package/client/06-usage.js +195 -0
  24. package/client/06b-model-source.js +67 -0
  25. package/client/07-board-parts.js +312 -0
  26. package/client/07a-role-theme.js +25 -0
  27. package/client/08-artifacts-report.js +375 -0
  28. package/client/08a-task-control.js +126 -0
  29. package/client/08b-stage-sprites.js +97 -0
  30. package/client/08c-stage-colors.js +55 -0
  31. package/client/08c-stage-scene.js +238 -0
  32. package/client/08d-stage-adapter.js +65 -0
  33. package/client/08e-stage-activity.js +83 -0
  34. package/client/09-team-board.js +181 -0
  35. package/client/09b-role-view.js +95 -0
  36. package/client/09c-model-tabs.js +20 -0
  37. package/client/10-overview.js +364 -0
  38. package/client/10b-onboarding.js +121 -0
  39. package/client/11-register.js +249 -0
  40. package/client.js +5053 -0
  41. package/config-projection.js +40 -0
  42. package/config.js +411 -0
  43. package/cordis.patch.yml +110 -0
  44. package/defaults.js +222 -0
  45. package/dispatch-confirm.js +293 -0
  46. package/dispatch-routes-store.js +31 -0
  47. package/failover.js +85 -0
  48. package/file-limits.js +119 -0
  49. package/free-worker.mjs +125 -0
  50. package/http-guard.js +14 -0
  51. package/i18n/roles.en.json +23 -0
  52. package/i18n/roles.zh.json +23 -0
  53. package/i18n/server.en.json +659 -0
  54. package/i18n/server.zh.json +659 -0
  55. package/i18n.js +34 -0
  56. package/icon.svg +7 -0
  57. package/index.js +113 -0
  58. package/integrations-config.js +301 -0
  59. package/integrations-messages.js +62 -0
  60. package/integrations.js +17 -0
  61. package/lead-route.js +30 -0
  62. package/locale/en.json +6 -0
  63. package/locale/zh.json +6 -0
  64. package/long-context.js +30 -0
  65. package/managed-config-route.js +49 -0
  66. package/managed-ref.js +38 -0
  67. package/managed-resolve.js +47 -0
  68. package/member-models.js +84 -0
  69. package/member-task-control.js +242 -0
  70. package/memory-backends.js +89 -0
  71. package/memory-embed.js +70 -0
  72. package/memory-hub.js +140 -0
  73. package/memory-openviking.js +101 -0
  74. package/memory-redact.js +34 -0
  75. package/memory-store.js +270 -0
  76. package/memory-sync-queue.js +28 -0
  77. package/model-policy.js +85 -0
  78. package/model-prefs.js +104 -0
  79. package/observability-api.js +76 -0
  80. package/observability-projection.js +116 -0
  81. package/onboarding.js +47 -0
  82. package/opencode.js +74 -0
  83. package/package.json +155 -4
  84. package/plan-gate.js +92 -0
  85. package/preset-guard.js +47 -0
  86. package/request-evidence.js +41 -0
  87. package/roles.js +105 -0
  88. package/roster-defaults.js +70 -0
  89. package/route-health.js +39 -0
  90. package/runtime-observability.js +78 -0
  91. package/runtime-view.js +21 -0
  92. package/scripts/memory-cli.mjs +138 -0
  93. package/search-engines.js +119 -0
  94. package/search.js +164 -0
  95. package/session-policy.js +59 -0
  96. package/session-rotation.js +206 -0
  97. package/settings-schema.js +40 -0
  98. package/shared/managed-config.js +84 -0
  99. package/single-model.js +44 -0
  100. package/skills/project-role-theme/SKILL.md +46 -0
  101. package/task-bridge.js +32 -0
  102. package/task-control-api.js +36 -0
  103. package/task-control-audit.js +60 -0
  104. package/team.js +101 -0
  105. package/teammate-context.js +120 -0
  106. package/teammate-wait.js +18 -0
  107. package/template.js +46 -0
  108. package/theme-plugin.js +172 -0
  109. package/theme.js +115 -0
  110. package/token-discipline.js +116 -0
  111. package/token-metrics.js +37 -0
  112. package/tool-names.js +10 -0
  113. package/tool-schema.js +23 -0
  114. package/transcribe.js +104 -0
  115. package/ui.js +113 -0
  116. package/usage.js +96 -0
  117. package/workflow.js +246 -0
@@ -0,0 +1,336 @@
1
+ const CSS = `
2
+ :root{--aw-z-popover:1100;--aw-z-modal:1000}
3
+ .ctm-card{display:flex;flex-direction:column}
4
+ .ctm-row{position:relative;display:flex;align-items:center;min-width:0;height:calc(24px + var(--dsh-content-font-delta,0px));overflow:hidden;color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));transition:color .1s}
5
+ .ctm-row:hover,.ctm-row[data-open]{color:var(--dsw-alias-label-secondary)}
6
+ .ctm-row[data-expandable]{cursor:pointer}
7
+ .ctm-row:focus-visible{outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:-1px;border-radius:var(--dsw-radius-xs)}
8
+ .ctm-lead{position:relative;flex:none;display:inline-flex;align-items:center;justify-content:center;width:calc(16px + var(--dsh-content-font-delta,0px));height:calc(16px + var(--dsh-content-font-delta,0px));margin-right:6px}
9
+ .ctm-lead svg{width:calc(14px + var(--dsh-content-font-delta,0px));height:calc(14px + var(--dsh-content-font-delta,0px))}
10
+ .ctm-ico{display:inline-flex;transition:opacity .1s}
11
+ .ctm-chev{position:absolute;inset:0;display:inline-flex;align-items:center;justify-content:center;opacity:0;transition:opacity .1s}
12
+ .ctm-row[data-expandable]:hover .ctm-ico,.ctm-row[data-open] .ctm-ico{opacity:0}
13
+ .ctm-row[data-expandable]:hover .ctm-chev,.ctm-row[data-open] .ctm-chev{opacity:1}
14
+ .ctm-title{flex:none;font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px))}
15
+ .ctm-sep{flex:none;width:2px;height:2px;margin:0 8px;border-radius:var(--dsw-radius-xs);background:var(--dsw-alias-label-caption,currentColor)}
16
+ .ctm-summary{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px))}
17
+ .ctm-badge{flex:none;margin-left:8px;padding:0 6px;border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-xl);font-size:var(--dsw-font-xxxs-11-font-size);line-height:17px;color:var(--dsw-alias-label-secondary);white-space:nowrap}
18
+ .ctm-badge[data-tone=brand]{color:var(--dsw-alias-brand-primary);border-color:currentColor}
19
+ .ctm-badge[data-tone=success]{color:var(--dsw-alias-state-success-primary);border-color:currentColor}
20
+ .ctm-badge[data-tone=warn]{color:var(--dsw-alias-state-warn-primary);border-color:currentColor}
21
+ .ctm-error{color:var(--dsw-alias-state-error-primary)}
22
+ .ctm-warn{color:var(--dsw-alias-state-warn-primary)}
23
+ .ctm-card[data-state=running] .ctm-summary,.ctm-card[data-state=preparing] .ctm-title{animation:ctm-pulse 1.4s ease-in-out infinite}
24
+ @keyframes ctm-pulse{50%{opacity:.45}}
25
+ .ctm-tc{margin-top:6px;border-top:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.2));padding-top:6px;font-size:var(--dsw-font-xxs-12-font-size)}
26
+ .ctm-tc>summary{cursor:pointer;display:flex;gap:8px;align-items:baseline;list-style:none}
27
+ .ctm-tc>summary::-webkit-details-marker{display:none}
28
+ .ctm-tc-body,.ctm-tc-actions,.ctm-tc-confirm,.ctm-tc-audit{display:flex;flex-direction:column;gap:6px;margin-top:6px}
29
+ .ctm-tc-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
30
+ .ctm-tc-override{display:flex;flex-direction:column;gap:2px}
31
+ .ctm-tc-reason,.ctm-tc select{font:inherit;padding:3px 6px;border-radius:var(--dsw-radius-sm);border:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.35));background:transparent;color:inherit;max-width:100%}
32
+ .ctm-tc-confirm{padding:8px;border-radius:var(--dsw-radius-md);border:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.35))}
33
+ .ctm-tc-audit ul{margin:0;padding-left:16px;display:flex;flex-direction:column;gap:2px}
34
+ .ctm-mc-list{display:flex;flex-direction:column;gap:6px}
35
+ .ctm-mc-item{padding-left:8px;border-left:2px solid var(--dsw-alias-border-l1,rgba(127,127,127,.25))}
36
+ .ctm-mc-results{margin:0;padding-left:18px;display:flex;flex-direction:column;gap:6px}
37
+ .ctm-mc-results li{display:flex;flex-direction:column;gap:1px;min-width:0;overflow-wrap:anywhere}
38
+ .ctm-dc{display:flex;flex-direction:column;gap:12px;padding:12px 14px;border-radius:var(--dsw-radius-lg);border:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.3));font-size:var(--dsw-font-xxs-12-font-size);line-height:1.5}
39
+ .ctm-dc-head{display:flex;flex-direction:column;gap:2px}
40
+ .ctm-dc-title{font-size:var(--dsw-font-xs-13-font-size)}
41
+ .ctm-dc-roles{display:flex;flex-direction:column;gap:10px}
42
+ .ctm-dc-role{display:flex;flex-direction:column;gap:8px;padding:10px 12px;border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1,rgba(127,127,127,.06))}
43
+ .ctm-dc-role-head{display:flex;align-items:center;gap:10px;min-width:0}
44
+ .ctm-dc-avatar{flex:none;width:26px;height:26px;border-radius:50%;display:grid;place-items:center;font-weight:600;background:var(--dsw-alias-interactive-bg-hover,rgba(127,127,127,.18))}
45
+ .ctm-dc-who{display:flex;flex-direction:column;gap:1px;min-width:0}
46
+ .ctm-dc-meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px;color:var(--dsw-alias-label-secondary,inherit);font-size:var(--dsw-font-xxxs-11-font-size)}
47
+ .ctm-dc-meta code{font-size:var(--dsw-font-xxxs-11-font-size)}
48
+ .ctm-dc-task{display:flex;flex-direction:column;align-items:flex-start;gap:2px}
49
+ .ctm-dc-task p{margin:0;white-space:pre-wrap;overflow-wrap:anywhere}
50
+ .ctm-dc-task p[data-clamped]{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
51
+ .ctm-dc-link{font:inherit;font-size:var(--dsw-font-xxxs-11-font-size);padding:0;border:0;background:none;color:var(--dsw-alias-link);cursor:pointer}
52
+ .ctm-dc-grid{display:grid;grid-template-columns:76px minmax(0,360px);gap:8px 10px;align-items:start}
53
+ .ctm-dc-key{padding-top:6px;display:flex;gap:4px;align-items:baseline}
54
+ .ctm-dc-count{font-weight:400;font-variant-numeric:tabular-nums;opacity:.7}
55
+ .ctm-dc-fallbacks{display:flex;flex-direction:column;gap:6px;min-width:0}
56
+ .ctm-dc-list{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:4px}
57
+ .ctm-dc-item{display:grid;grid-template-columns:18px minmax(0,1fr) auto;align-items:center;gap:6px;padding:3px 4px 3px 6px;border-radius:var(--dsw-radius-sm);border:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.25))}
58
+ .ctm-dc-index{font-variant-numeric:tabular-nums;opacity:.6;text-align:center}
59
+ .ctm-dc-route{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
60
+ .ctm-dc-actions{display:flex;gap:2px}
61
+ .ctm-dc-icon{font:inherit;line-height:1;width:22px;height:22px;border-radius:var(--dsw-radius-sm);border:0;background:transparent;color:inherit;cursor:pointer}
62
+ .ctm-dc-icon:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,rgba(127,127,127,.15))}
63
+ .ctm-dc-icon:disabled{opacity:.3;cursor:default}
64
+ .ctm-dc-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px;padding-top:10px;border-top:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.2))}
65
+ .ctm-dc-scope{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}
66
+ .ctm-dc-seg{display:inline-flex;padding:2px;border-radius:var(--dsw-radius-md);background:var(--dsw-alias-interactive-bg-hover,rgba(127,127,127,.12))}
67
+ .ctm-dc-segbtn{font:inherit;font-size:var(--dsw-font-xxs-12-font-size);padding:3px 10px;border:0;border-radius:var(--dsw-radius-sm);background:transparent;color:inherit;cursor:pointer}
68
+ .ctm-dc-segbtn[aria-checked=true]{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);box-shadow:var(--dsw-elevation-prominent);font-weight:600}
69
+ .ctm-dc-buttons{display:flex;gap:8px;margin-left:auto}
70
+ .ctm-dc-wrap{display:flex;flex-direction:column;gap:6px}
71
+ .ctm-dock{box-sizing:border-box;width:calc(100% - 2 * (var(--dsh-composer-side-clearance,16px) + 16px));max-width:var(--dsh-chat-content-width,760px);align-self:center;margin:0 auto 8px;max-height:min(60vh,560px);overflow:auto;border-radius:var(--dsw-radius-lg);background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-bg-base));box-shadow:var(--dsw-elevation-prominent)}
72
+ .ctm-dock>.ctm-dc{border-color:var(--dsw-alias-brand-primary,var(--dsw-alias-border-l1,rgba(127,127,127,.3)))}
73
+ .ctm-dc-pointer{margin:0;padding-left:2px}
74
+ .ctm-mp{position:relative;min-width:0}
75
+ .ctm-mp-input{box-sizing:border-box;width:100%;font:inherit;font-size:var(--dsw-font-xxs-12-font-size);padding:5px 26px 5px 8px;border-radius:var(--dsw-radius-sm);border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)}
76
+ .ctm-mp-input:focus{outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:-1px}
77
+ .ctm-mp-caret{position:absolute;right:8px;top:50%;transform:translateY(-50%);pointer-events:none;opacity:.6}
78
+ .ctm-mp-pop{position:absolute;z-index:var(--aw-z-popover);left:0;right:0;top:calc(100% + 4px);border-radius:var(--dsw-radius-lg,10px);background-color:var(--dsw-alias-bg-base);background-image:linear-gradient(var(--dsw-specific-menu),var(--dsw-specific-menu));box-shadow:var(--dsw-elevation-prominent);color:var(--dsw-alias-label-primary);overflow:hidden}
79
+ .ctm-mp-count{padding:5px 8px;border-bottom:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.2))}
80
+ .ctm-mp-list{list-style:none;margin:0;padding:4px 0;max-height:240px;overflow:auto}
81
+ .ctm-mp-group{padding:6px 10px 2px;font-size:var(--dsw-font-xxxs-11-font-size);font-weight:600;opacity:.65;text-transform:none}
82
+ .ctm-mp-option{display:flex;justify-content:space-between;gap:8px;padding:5px 10px 5px 16px;cursor:pointer}
83
+ .ctm-mp-option[data-active]{background:var(--dsw-alias-interactive-bg-hover,rgba(127,127,127,.15))}
84
+ .ctm-mp-option[aria-selected=true]{font-weight:600}
85
+ .ctm-mp-model{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
86
+ .ctm-mp-empty{padding:10px}
87
+ @media (max-width:560px){.ctm-dc-grid{grid-template-columns:minmax(0,1fr);gap:4px}.ctm-dc-key{padding-top:0}.ctm-dock{max-height:55vh}.ctm-dock>.ctm-dc{padding:10px 12px}.ctm-dc-buttons{width:100%}.ctm-dc-buttons>.ctm-btn{flex:1 1 0;min-height:36px}.ctm-mp-input{min-height:34px;font-size:var(--dsw-font-base-16-font-size)}}
88
+ .ctm-plan-board{margin:6px 0 0;padding-left:16px;display:flex;flex-direction:column;gap:2px;font-size:var(--dsw-font-xxs-12-font-size)}
89
+ @media (prefers-reduced-motion:reduce){.ctm-card .ctm-summary,.ctm-card .ctm-title{animation:none!important}}
90
+ .ctm-wrap{display:flex;flex-direction:column}
91
+ .ctm-body{display:flex;flex-direction:column;margin:4px 0 4px 4px;overflow:hidden;border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-lg,8px);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font-size:var(--dsh-content-font-size-secondary,13px)}
92
+ .ctm-section{display:flex;flex-direction:column;gap:6px;padding:8px 12px;min-width:0}
93
+ .ctm-section+.ctm-section{border-top:.5px solid var(--dsw-alias-border-l2)}
94
+ .ctm-label{font-size:var(--dsw-font-xxs-12-font-size);color:var(--dsw-alias-label-secondary)}
95
+ .ctm-text{white-space:pre-wrap;word-break:break-word;line-height:1.6}
96
+ .ctm-pre{margin:0;max-height:320px;overflow:auto;white-space:pre-wrap;word-break:break-word;font:inherit;line-height:1.6}
97
+ .ctm-pre[data-short]{max-height:120px}
98
+ .ctm-grid{display:grid;grid-template-columns:max-content minmax(0,1fr);column-gap:16px;row-gap:8px;align-items:baseline}
99
+ .ctm-grid3{display:grid;grid-template-columns:max-content max-content minmax(0,1fr);column-gap:16px;row-gap:6px;align-items:baseline}
100
+ .ctm-who{display:flex;flex-direction:column;min-width:0}
101
+ .ctm-name{font-weight:500}
102
+ .ctm-sub{font-size:var(--dsw-font-xxs-12-font-size);color:var(--dsw-alias-label-secondary);word-break:break-all}
103
+ .ctm-chips{display:flex;flex-wrap:wrap;gap:6px}
104
+ .ctm-chip{display:inline-flex;gap:4px;padding:1px 8px;border-radius:var(--dsw-radius-xl);background:var(--dsw-alias-bg-layer-2);font-size:var(--dsw-font-xxs-12-font-size);line-height:20px}
105
+ .ctm-chip>span:first-child{color:var(--dsw-alias-label-secondary)}
106
+ .ctm-list{display:flex;flex-direction:column;gap:2px;margin:0;padding:0;list-style:none}
107
+ .ctm-link{padding:0;border:none;background:none;color:var(--dsw-alias-brand-primary);font:inherit;text-align:left;word-break:break-all;cursor:pointer}
108
+ .ctm-link:hover{text-decoration:underline}
109
+ .ctm-inspect{align-self:flex-start;margin:0 0 4px 4px;padding:2px 4px;border:none;border-radius:var(--dsw-radius-xs);background:none;color:var(--dsw-alias-label-secondary);font-size:var(--dsw-font-xxs-12-font-size);cursor:pointer}
110
+ .ctm-inspect:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2)}
111
+ .ctm-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
112
+ .ctm-badge[data-tone=error]{color:var(--dsw-alias-state-error-primary);border-color:currentColor}
113
+ .ctm-success{color:var(--dsw-alias-state-success-primary)}
114
+ .ctm-btn{flex:none;padding:3px 10px;border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-sm);background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:var(--dsw-font-xxs-12-font-size);line-height:18px;cursor:pointer;transition:background .12s,color .12s,border-color .12s}
115
+ .ctm-btn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}
116
+ .ctm-btn:active:not(:disabled){background:var(--dsw-alias-interactive-bg-active)}
117
+ .ctm-btn:disabled{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);cursor:default}
118
+ .ctm-btn[data-primary]{border-color:var(--dsw-alias-button-primary-fill);background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-inverted);font-weight:500}
119
+ .ctm-btn[data-primary]:hover:not(:disabled){border-color:var(--dsw-alias-button-primary-hover);background:var(--dsw-alias-button-primary-hover)}
120
+ .ctm-btn[data-primary]:active:not(:disabled){opacity:.85}
121
+ .ctm-btn[data-primary]:disabled{border-color:transparent;background:var(--dsw-alias-button-primary-dimmed);color:var(--dsw-alias-label-tertiary)}
122
+ .ctm-btn:focus-visible,.ctm-ov-tab:focus-visible,.ctm-switch:focus-visible,.ctm-ov-group>summary:focus-visible{outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px}
123
+ .ctm-card,.ctm-ov{--ctm-accent:var(--dsw-alias-state-business-primary,var(--dsw-alias-link,#4d6bfe))}
124
+ .ctm-ov .ctm-badge[data-tone=brand]{color:var(--ctm-accent)}
125
+ .ctm-ov{container:ctm-ov/inline-size;background:var(--dsw-alias-bg-base);display:flex;flex-direction:column;height:100%;min-height:0;box-sizing:border-box;color:var(--dsw-alias-label-primary);font-size:var(--dsh-content-font-size-secondary,13px)}
126
+ .ctm-ov-head{flex:none;display:flex;flex-direction:column;gap:1px;padding:8px 16px 6px;border-bottom:.5px solid var(--dsw-alias-border-l2)}
127
+ .ctm-ov-titlerow{display:flex;align-items:center;gap:6px;min-width:0}
128
+ .ctm-ov-title{margin:0;font-size:var(--dsw-font-s-14-font-size);font-weight:600;line-height:20px}
129
+ .ctm-ov-subrow{margin:0;font-size:var(--dsw-font-xxxs-11-font-size);line-height:16px;color:var(--dsw-alias-label-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
130
+ .ctm-ov-titlerow .ctm-badge{margin-left:0}
131
+ .ctm-ov-refresh{margin-left:auto}
132
+ .ctm-ov-scroll{flex:1 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:12px;padding:12px 16px 24px}
133
+ .ctm-ov-scroll>*,.ctm-ov-panel>*,.ctm-ov-editor>*{flex-shrink:0}
134
+ .ctm-ov-empty{padding:24px 0;text-align:center}
135
+ .ctm-ov-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(54px,1fr));gap:6px}
136
+ .ctm-ov-stat{display:flex;flex-direction:column;gap:2px;min-width:0;padding:7px 8px;border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1)}
137
+ .ctm-ov-stat strong{font-size:var(--dsw-font-m-18-font-size);font-weight:600;line-height:22px}
138
+ .ctm-ov-stat span{font-size:var(--dsw-font-xxs-12-font-size);color:var(--dsw-alias-label-secondary)}
139
+ .ctm-ov-stat[data-tone=warn] strong{color:var(--dsw-alias-state-warn-primary)}
140
+ .ctm-ov-stat[data-tone=error] strong{color:var(--dsw-alias-state-error-primary)}
141
+ .ctm-ov-callout{display:flex;flex-direction:column;gap:8px;margin:0;padding:10px 12px;border-radius:var(--dsw-radius-md);border:.5px solid currentColor;line-height:1.6;word-break:break-word}
142
+ .ctm-ov-callout[data-tone=warn]{color:var(--dsw-alias-state-warn-primary)}
143
+ .ctm-ov-callout[data-tone=error]{color:var(--dsw-alias-state-error-primary)}
144
+ .ctm-ov-callout .ctm-text{color:var(--dsw-alias-label-primary)}
145
+ .ctm-ov-tabs{position:sticky;top:-12px;z-index:2;display:flex;flex-wrap:wrap;gap:2px;padding:3px;margin:0 -2px;border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-2)}
146
+ .ctm-ov-tab{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:4px 8px;border:none;border-radius:var(--dsw-radius-sm);background:none;color:var(--dsw-alias-label-secondary);font:inherit;font-size:var(--dsw-font-xxs-12-font-size);line-height:18px;white-space:nowrap;cursor:pointer}
147
+ .ctm-ov-tab:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}
148
+ .ctm-ov-tab[aria-pressed=true]{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font-weight:500;box-shadow:0 0 0 .5px var(--dsw-alias-border-l1)}
149
+ .ctm-ov-count{padding:0 5px;border-radius:var(--dsw-radius-xl);background:var(--dsw-alias-bg-layer-2);font-size:var(--dsw-font-xxxs-11-font-size);line-height:16px;color:var(--dsw-alias-label-secondary);flex:none}
150
+ @container ctm-ov (min-width:480px){.ctm-ov-tab{flex:1 1 0;min-width:0}}
151
+ .ctm-ov-subtabs{display:flex;flex-wrap:wrap;gap:2px;padding:3px;margin:0 0 8px;border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-2)}
152
+ .ctm-ov-subtab{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:4px 8px;border:none;border-radius:var(--dsw-radius-sm);background:none;color:var(--dsw-alias-label-secondary);font:inherit;font-size:var(--dsw-font-xxs-12-font-size);line-height:18px;white-space:nowrap;cursor:pointer}
153
+ .ctm-ov-subtab:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}
154
+ .ctm-ov-subtab[aria-pressed=true]{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font-weight:500;box-shadow:0 0 0 .5px var(--dsw-alias-border-l1)}
155
+ @container ctm-ov (min-width:420px){.ctm-ov-subtab{flex:1 1 0;min-width:0}}
156
+ .ctm-ov-panel{display:flex;flex-direction:column;gap:12px;min-width:0}
157
+ .ctm-ov-panel[hidden]{display:none}
158
+ .ctm-ov-block{display:flex;flex-direction:column;gap:6px;min-width:0}
159
+ .ctm-ov-help{margin:0;line-height:1.5}
160
+ .ctm-ov-note{font-size:var(--dsw-font-xxs-12-font-size)}
161
+ .ctm-ov-editor{display:flex;flex-direction:column;gap:12px;min-width:0}
162
+ .ctm-ov-toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding:6px 0;background:var(--dsw-alias-bg-base)}
163
+ .ctm-ov-search{box-sizing:border-box;width:100%;padding:5px 10px;border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:inherit;font-size:var(--dsw-font-xxs-12-font-size)}
164
+ .ctm-ov-search:focus{outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:-1px}
165
+ .ctm-ov-allocs{display:flex;flex-direction:column;border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1)}
166
+ .ctm-ov-alloc{display:grid;grid-template-columns:minmax(56px,max-content) minmax(0,1fr);column-gap:10px;padding:6px 10px;align-items:baseline}
167
+ .ctm-ov-alloc+.ctm-ov-alloc{border-top:.5px solid var(--dsw-alias-border-l2)}
168
+ .ctm-ov-chain{display:flex;align-items:center;flex-wrap:wrap;gap:4px;min-width:0}
169
+ .ctm-ov-hop{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:1px 7px;border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-xl);background:var(--dsw-alias-bg-layer-2);font-family:var(--dsw-font-markdown-code-font-family,ui-monospace,monospace);font-size:var(--dsw-font-xxxs-11-font-size);line-height:17px;color:var(--dsw-alias-label-secondary)}
170
+ .ctm-ov-hop[data-primary]{border-color:var(--ctm-accent);background:none;color:var(--ctm-accent)}
171
+ .ctm-ov-arrow{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));font-size:var(--dsw-font-xs-13-font-size);line-height:1}
172
+ .ctm-ov-tiers{display:flex;flex-wrap:wrap;gap:6px}
173
+ .ctm-ov-tier{position:relative;flex:none;display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-xl);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);font:inherit;font-size:var(--dsw-font-xxs-12-font-size);line-height:18px;white-space:nowrap;cursor:pointer}
174
+ .ctm-ov-tier:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}
175
+ .ctm-ov-more{align-self:center}
176
+ .ctm-ov-tier[aria-selected=true]{border-color:var(--ctm-accent);color:var(--ctm-accent);font-weight:500}
177
+ .ctm-ov-tier[aria-selected=true] .ctm-ov-count{background:var(--ctm-accent);color:var(--dsw-alias-label-primary-inverted)}
178
+ .ctm-ov-tier:focus-visible{outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px}
179
+ .ctm-ov-offdot{position:absolute;top:1px;right:1px;width:6px;height:6px;border-radius:50%;background:var(--dsw-alias-state-warn-primary)}
180
+ .ctm-ov-list-flat{border-top:none}
181
+ .ctm-ov-rule-input{display:flex;gap:6px}
182
+ .ctm-ov-rule-input .ctm-ov-search{flex:1 1 auto;min-width:0;font-family:var(--dsw-font-markdown-code-font-family,ui-monospace,monospace)}
183
+ .ctm-ov-rule{align-items:center;font-family:var(--dsw-font-markdown-code-font-family,ui-monospace,monospace);border:.5px solid var(--dsw-alias-state-warn-primary)}
184
+ .ctm-ov-rule-x{margin-left:2px;padding:0 4px;border:none;border-radius:var(--dsw-radius-xs);background:none;color:var(--dsw-alias-label-secondary);font:inherit;line-height:18px;cursor:pointer}
185
+ .ctm-ov-rule-x:hover:not(:disabled){color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-interactive-bg-hover)}
186
+ .ctm-ov-panel{container-type:inline-size}
187
+ .ctm-ov-split{display:flex;flex-direction:column;gap:16px;min-width:0}
188
+ .ctm-ov-split>*{flex-shrink:0;min-width:0}
189
+ @container (min-width:720px){.ctm-ov-split{display:grid;grid-template-columns:minmax(300px,2fr) minmax(0,3fr);align-items:start}}
190
+ .ctm-bd{display:flex;flex-direction:column;gap:8px;min-width:0}
191
+ .ctm-bd-head{display:flex;align-items:center;gap:8px}
192
+ .ctm-bd-head .ctm-badge{margin-left:0}
193
+ .ctm-bd-at{margin-left:auto;display:inline-flex;align-items:center;gap:5px}
194
+ .ctm-bd-pulse{width:6px;height:6px;border-radius:50%;background:var(--dsw-alias-state-success-primary);animation:ctm-beat 2.5s ease-out infinite}
195
+ @keyframes ctm-beat{0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--dsw-alias-state-success-primary) 55%,transparent)}70%,100%{box-shadow:0 0 0 6px transparent}}
196
+ .ctm-bd-card{position:relative;display:flex;flex-direction:column;gap:6px;min-width:0;padding:9px 10px 11px;border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);box-shadow:var(--dsw-shadow-lv1);transition:border-color .2s,box-shadow .2s,opacity .2s}
197
+ .ctm-bd-card[data-status=inactive]{opacity:.62;border-style:dashed}
198
+ .ctm-bd-card[data-open]{cursor:pointer}
199
+ .ctm-bd-card[data-open]:hover{border-color:var(--ctm-accent)}
200
+ .ctm-bd-card[data-open]:focus-visible{outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:2px}
201
+ .ctm-bd-card[data-status=failed]{border-color:var(--dsw-alias-state-error-primary)}
202
+ .ctm-bd-card[data-status=running]{border-color:var(--ctm-accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--ctm-accent) 14%,transparent),0 4px 14px color-mix(in srgb,var(--ctm-accent) 18%,transparent);animation:ctm-glow 2.4s ease-in-out infinite}
203
+ @keyframes ctm-glow{50%{box-shadow:0 0 0 5px color-mix(in srgb,var(--ctm-accent) 8%,transparent),0 4px 18px color-mix(in srgb,var(--ctm-accent) 26%,transparent)}}
204
+ .ctm-bd-top{display:flex;align-items:center;gap:8px;min-width:0}
205
+ .ctm-bd-top .ctm-who{flex:1 1 0;min-width:0}
206
+ .ctm-bd-top .ctm-name,.ctm-bd-top .ctm-sub{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
207
+ .ctm-bd-avatar{position:relative;flex:none;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:50%;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font-weight:600;font-size:var(--dsw-font-xs-13-font-size)}
208
+ .ctm-bd-card[data-status=running] .ctm-bd-avatar{background:var(--ctm-accent);color:var(--dsw-alias-label-primary-inverted)}
209
+ .ctm-bd-card[data-status=running] .ctm-bd-avatar::after{content:'';position:absolute;inset:-4px;border-radius:50%;border:1.5px solid transparent;border-top-color:var(--ctm-accent);border-right-color:var(--ctm-accent);animation:ctm-spin 1.1s linear infinite}
210
+ @keyframes ctm-spin{to{transform:rotate(360deg)}}
211
+ .ctm-bd-state{flex:none;display:inline-flex;align-items:center;gap:4px;font-size:var(--dsw-font-xxxs-11-font-size);line-height:16px;color:var(--dsw-alias-label-secondary);white-space:nowrap}
212
+ .ctm-bd-state[data-tone=brand]{color:var(--ctm-accent)}
213
+ .ctm-bd-state[data-tone=success]{color:var(--dsw-alias-state-success-primary)}
214
+ .ctm-bd-state[data-tone=error]{color:var(--dsw-alias-state-error-primary)}
215
+ .ctm-bd-dot{width:6px;height:6px;border-radius:50%;background:currentColor}
216
+ .ctm-bd-card[data-status=running] .ctm-bd-dot,.ctm-bd-card[data-status=provisioning] .ctm-bd-dot{animation:ctm-pulse 1s ease-in-out infinite}
217
+ .ctm-bd-time{font-variant-numeric:tabular-nums;opacity:.8}
218
+ .ctm-bd-task{display:flex;align-items:baseline;gap:5px;min-width:0;font-size:var(--dsw-font-xxs-12-font-size);line-height:1.45}
219
+ .ctm-bd-subject{min-width:0;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
220
+ .ctm-bd-model{display:flex;min-width:0}
221
+ .ctm-bd-task>.ctm-sub{flex:none}
222
+ .ctm-bd-bar{position:absolute;left:10px;right:10px;bottom:4px;height:2px;border-radius:var(--dsw-radius-xs);overflow:hidden;opacity:0}
223
+ .ctm-bd-card[data-status=running] .ctm-bd-bar,.ctm-bd-card[data-status=provisioning] .ctm-bd-bar{opacity:1;background:linear-gradient(90deg,transparent,var(--ctm-accent),transparent) 0 0/40% 100% no-repeat,color-mix(in srgb,var(--ctm-accent) 12%,transparent);animation:ctm-scan 1.4s ease-in-out infinite}
224
+ @keyframes ctm-scan{0%{background-position:-40% 0,0 0}100%{background-position:140% 0,0 0}}
225
+ @media (prefers-reduced-motion:reduce){.ctm-bd *,.ctm-bd *::before,.ctm-bd *::after,.ctm-bd-card{animation:none!important}}
226
+ .ctm-ov-route{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--dsw-font-markdown-code-font-family,ui-monospace,monospace);font-size:var(--dsw-font-xxs-12-font-size)}
227
+ .ctm-ov-group{border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);overflow:hidden}
228
+ .ctm-ov-group>summary{display:flex;align-items:center;gap:8px;padding:7px 10px;cursor:pointer;list-style:none;user-select:none}
229
+ .ctm-ov-group>summary::-webkit-details-marker{display:none}
230
+ .ctm-ov-group>summary::before{content:'';flex:none;width:5px;height:5px;margin-right:2px;border-right:1.3px solid currentColor;border-bottom:1.3px solid currentColor;transform:rotate(-45deg);transition:transform .1s;color:var(--dsw-alias-label-secondary)}
231
+ .ctm-ov-group[open]>summary::before{transform:rotate(45deg)}
232
+ .ctm-ov-group>summary>.ctm-sub:last-child{margin-left:auto}
233
+ .ctm-ov-group>summary .ctm-badge{margin-left:0}
234
+ .ctm-ov-group>.ctm-ov-block,.ctm-ov-group>p{margin:0;padding:0 10px 10px}
235
+ .ctm-ov-list{display:flex;flex-direction:column;border-top:.5px solid var(--dsw-alias-border-l2)}
236
+ .ctm-ov-model{display:flex;align-items:flex-start;gap:10px;padding:8px 10px;cursor:pointer}
237
+ .ctm-ov-model+.ctm-ov-model{border-top:.5px solid var(--dsw-alias-border-l2)}
238
+ .ctm-ov-model:hover{background:var(--dsw-alias-interactive-bg-hover)}
239
+ .ctm-ov-model{content-visibility:auto;contain-intrinsic-size:auto 56px}
240
+ .ctm-ov-model[data-off] .ctm-ov-model-name .ctm-name{color:var(--dsw-alias-label-secondary);text-decoration:line-through}
241
+ .ctm-ov-model-main{display:flex;flex-direction:column;gap:4px;min-width:0}
242
+ .ctm-ov-model-name{display:flex;align-items:baseline;flex-wrap:wrap;gap:6px;min-width:0;overflow-wrap:anywhere}
243
+ .ctm-ov-model-name .ctm-badge{margin-left:0}
244
+ .ctm-switch{appearance:none;flex:none;position:relative;width:28px;height:16px;margin:2px 0 0;border-radius:var(--dsw-radius-xl);background:var(--dsw-alias-border-l1);cursor:pointer;transition:background .15s}
245
+ .ctm-switch::after{content:'';position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:var(--dsw-alias-switch-thumb);box-shadow:var(--dsw-shadow-lv1);transition:transform .15s}
246
+ .ctm-switch:checked{background:var(--dsw-alias-state-success-primary)}
247
+ .ctm-switch:checked::after{transform:translateX(12px)}
248
+ .ctm-switch:disabled{opacity:.5;cursor:default}
249
+ .ctm-ov-roles{display:flex;flex-direction:column;gap:8px}
250
+ .ctm-ov-role{display:flex;flex-direction:column;gap:3px;padding:8px 10px;border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);min-width:0}
251
+ .ctm-ov-role-head{display:flex;align-items:center;gap:6px}
252
+ .ctm-ov-role-head .ctm-badge{margin-left:auto}
253
+ .ctm-ov-desc{font-size:var(--dsw-font-xxs-12-font-size);line-height:1.5;color:var(--dsw-alias-label-secondary);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
254
+ .ctm-ov-kv{padding:8px 10px;border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1)}
255
+ .ctm-ov-logs{display:flex;flex-direction:column;border-top:.5px solid var(--dsw-alias-border-l2)}
256
+ .ctm-us-meter{height:4px;border-radius:var(--dsw-radius-xs);background:var(--dsw-alias-bg-layer-2);overflow:hidden}
257
+ .ctm-us-meter>i{display:block;height:100%;background:var(--ctm-accent)}
258
+ .ctm-us-meter[data-tone=warn]>i{background:var(--dsw-alias-state-warn-primary,#d97706)}
259
+ .ctm-us-meter[data-tone=error]>i{background:var(--dsw-alias-state-error-primary)}
260
+ .ctm-us-num{font-variant-numeric:tabular-nums}
261
+ .ctm-ov-log{display:flex;align-items:center;gap:6px;min-width:0;padding:5px 10px}
262
+ .ctm-ov-log+.ctm-ov-log{border-top:.5px solid var(--dsw-alias-border-l2)}
263
+ .ctm-ov-log .ctm-badge{margin-left:0}
264
+ .ctm-ov-log .ctm-ov-route{flex:1 1 auto}
265
+ .ctm-ov-seq{flex:none;min-width:32px;font-variant-numeric:tabular-nums}
266
+ .ctm-ov-time{flex:none;font-variant-numeric:tabular-nums;white-space:nowrap}
267
+ .ctm-bd-open-btn{position:absolute;top:7px;right:8px;z-index:2;padding:2px 7px;border:.5px solid var(--ctm-accent);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-1);color:var(--ctm-accent);font:inherit;font-size:var(--dsw-font-xxxs-11-font-size);line-height:16px;cursor:pointer;opacity:0;pointer-events:none;transition:opacity .15s,background .12s,color .12s}
268
+ .ctm-bd-open-btn:hover{background:var(--ctm-accent);color:var(--dsw-alias-label-primary-inverted)}
269
+ .ctm-bd-card:hover .ctm-bd-open-btn,.ctm-bd-card:focus-within .ctm-bd-open-btn,.ctm-bd-open-btn:focus{opacity:1;pointer-events:auto}
270
+ @media (hover: none){.ctm-bd-open-btn{opacity:1;pointer-events:auto}}
271
+ .ctm-model-badge{display:inline-flex;align-items:center;gap:4px;font-family:var(--dsw-font-markdown-code-font-family,ui-monospace,monospace);font-size:var(--dsw-font-xxxs-11-font-size);line-height:16px;padding:1px 6px;border-radius:var(--dsw-radius-xl);border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
272
+ .ctm-model-badge[data-grade=legendary]{color:var(--dsw-alias-state-warn-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 50%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 12%,transparent)}
273
+ .ctm-model-badge[data-grade=epic]{color:var(--dsw-alias-state-done-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-done-primary) 50%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-done-primary) 12%,transparent)}
274
+ .ctm-model-badge[data-grade=rare]{color:var(--dsw-alias-state-business-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-business-primary) 50%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,transparent)}
275
+ .ctm-model-badge[data-grade=cloth]{color:var(--dsw-alias-label-tertiary);border-color:var(--dsw-alias-border-l2);background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 60%,transparent)}
276
+ .ctm-badge-rank{font-weight:600;font-size:10px;padding:0 3px;border-radius:var(--dsw-radius-xs);background:color-mix(in srgb,currentColor 15%,transparent);flex:none}
277
+ .ctm-badge-alias{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
278
+ .ctm-bd-bubble{position:relative;display:flex;flex-direction:column;gap:3px;padding:6px 8px;border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-2);border:.5px solid var(--dsw-alias-border-l2);font-size:var(--dsw-font-xxs-12-font-size);line-height:1.45;color:var(--dsw-alias-label-primary)}
279
+ .ctm-bd-bubble-head{display:flex;align-items:center;gap:6px;font-size:var(--dsw-font-xxxs-11-font-size);color:var(--dsw-alias-label-secondary)}
280
+ .ctm-bd-bubble-head .ctm-badge{margin-left:0}
281
+ .ctm-bd-bubble-body{word-break:break-word;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
282
+ .ctm-bd-quote{font-style:italic;color:var(--dsw-alias-label-secondary);font-size:var(--dsw-font-xxxs-11-font-size)}
283
+ .ctm-bd-meters{display:flex;flex-direction:column;gap:5px;margin-top:2px}
284
+ .ctm-bd-meter-row{display:flex;flex-direction:column;gap:2px}
285
+ .ctm-bd-meter-labels{display:flex;justify-content:space-between;align-items:baseline;font-size:var(--dsw-font-xxxs-11-font-size);color:var(--dsw-alias-label-secondary)}
286
+ .ctm-bd-meter-labels .ctm-us-num{font-variant-numeric:tabular-nums}
287
+ .ctm-bd-deps{display:flex;flex-direction:column;gap:8px;padding-top:10px;border-top:.5px solid var(--dsw-alias-border-l2)}
288
+ .ctm-bd-deps-head{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap}
289
+ .ctm-bd-deps-chain{display:flex;align-items:center;flex-wrap:wrap;gap:4px;font-size:var(--dsw-font-xxxs-11-font-size);color:var(--ctm-accent);background:color-mix(in srgb,var(--ctm-accent) 10%,transparent);padding:2px 8px;border-radius:var(--dsw-radius-sm);border:.5px solid color-mix(in srgb,var(--ctm-accent) 30%,transparent)}
290
+ .ctm-bd-deps-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:6px}
291
+ .ctm-bd-dep-node{display:flex;flex-direction:column;gap:3px;padding:6px 8px;border-radius:var(--dsw-radius-sm);border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);font-size:var(--dsw-font-xxxs-11-font-size)}
292
+ .ctm-bd-dep-node[data-longest]{border-color:var(--ctm-accent);box-shadow:0 0 0 1px var(--ctm-accent)}
293
+ .ctm-bd-dep-top{display:flex;align-items:center;justify-content:space-between;gap:4px}
294
+ .ctm-bd-dep-subj{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary)}
295
+ .ctm-bd-dep-blocked{font-size:10px;color:var(--dsw-alias-state-warn-primary)}
296
+ .ctm-bd-switch{font-size:10px;color:var(--ctm-accent);background:color-mix(in srgb,var(--ctm-accent) 8%,transparent);border-radius:var(--dsw-radius-xs);padding:2px 4px;margin-top:2px}
297
+ .ctm-badge[data-tone=cooling]{color:var(--dsw-alias-state-warn-primary);border-color:currentColor;background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 10%,transparent)}
298
+ .ctm-act-recent{margin-top:4px}
299
+ .ctm-act-recent>summary{font-size:var(--dsw-font-xxxs-11-font-size);color:var(--dsw-alias-label-secondary);cursor:pointer;list-style:none}
300
+ .ctm-act-recent>summary::-webkit-details-marker{display:none}
301
+ .ctm-act-list{display:flex;flex-direction:column;gap:3px;margin-top:4px;padding:4px;background:var(--dsw-alias-bg-layer-1);border-radius:var(--dsw-radius-sm);font-size:10px}
302
+ .ctm-act-row{display:flex;justify-content:space-between;align-items:center;gap:4px;color:var(--dsw-alias-label-secondary)}
303
+ .ctm-act-row span:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
304
+ .ctm-art-shelf{display:flex;flex-direction:column;gap:12px}
305
+ .ctm-art-filter{display:flex;align-items:center;gap:8px}
306
+ .ctm-art-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:8px}
307
+ .ctm-art-card{display:flex;flex-direction:column;gap:4px;padding:8px 10px;border-radius:var(--dsw-radius-md);border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1)}
308
+ .ctm-art-head{display:flex;justify-content:space-between;align-items:center;gap:6px}
309
+ .ctm-art-path{font-family:var(--dsw-font-markdown-code-font-family,monospace);font-size:var(--dsw-font-xxxs-11-font-size);word-break:break-all;color:var(--dsw-alias-label-primary)}
310
+ .ctm-art-changes{display:flex;flex-direction:column;gap:6px;margin-top:10px;padding-top:10px;border-top:.5px solid var(--dsw-alias-border-l2)}
311
+ .ctm-chg-item{border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-1);padding:6px 8px}
312
+ .ctm-chg-item>summary{cursor:pointer;font-size:var(--dsw-font-xxs-12-font-size);font-weight:500;color:var(--dsw-alias-label-primary)}
313
+ .ctm-chg-diff{margin-top:6px;padding:6px;background:var(--dsw-alias-bg-layer-2);border-radius:var(--dsw-radius-xs);overflow-x:auto;font-family:var(--dsw-font-markdown-code-font-family,monospace);font-size:var(--dsw-font-xxxs-11-font-size)}
314
+ .ctm-rpt-shelf{display:flex;flex-direction:column;gap:12px}
315
+ .ctm-rpt-section{display:flex;flex-direction:column;gap:8px}
316
+ .ctm-rpt-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:8px}
317
+ .ctm-rpt-box{display:flex;flex-direction:column;gap:4px;padding:10px;border-radius:var(--dsw-radius-md);border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1)}
318
+ .ctm-rpt-box strong{font-size:var(--dsw-font-base-16-font-size);color:var(--dsw-alias-label-primary)}
319
+ .ctm-rpt-defs{margin-top:8px}
320
+ .ctm-rpt-defs>summary{cursor:pointer;font-size:var(--dsw-font-xxs-12-font-size);color:var(--dsw-alias-label-secondary)}
321
+ .ctm-rpt-defs-list{display:flex;flex-direction:column;gap:6px;margin-top:6px;padding:8px;background:var(--dsw-alias-bg-layer-1);border-radius:var(--dsw-radius-sm);font-size:var(--dsw-font-xxxs-11-font-size);color:var(--dsw-alias-label-secondary);line-height:1.5}
322
+ .ctm-collapse-wrap{display:contents}
323
+ .ctm-list-toggle{align-self:flex-start;margin-top:4px;font-size:var(--dsw-font-xxxs-11-font-size);padding:2px 8px;border-radius:var(--dsw-radius-xs)}
324
+ .ctm-teammate-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 12px;margin-bottom:12px;background:var(--dsw-alias-bg-layer-1);border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-md)}
325
+ .ctm-tm-info{display:flex;align-items:center;gap:10px;min-width:0;flex:1}
326
+ .ctm-tm-avatar{width:32px;height:32px;border-radius:50%;background:var(--ctm-accent);color:var(--dsw-alias-label-primary-inverted);display:inline-flex;align-items:center;justify-content:center;font-weight:600;font-size:var(--dsw-font-s-14-font-size);flex:none}
327
+ .ctm-tm-meta{display:flex;flex-direction:column;gap:2px;min-width:0}
328
+ .ctm-tm-names{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
329
+ .ctm-tm-sub{display:flex;align-items:center;gap:8px;font-size:var(--dsw-font-xxxs-11-font-size);color:var(--dsw-alias-label-secondary);flex-wrap:wrap}
330
+ .ctm-tm-actions{display:flex;align-items:center;gap:8px;flex:none}
331
+ .ctm-rv-empty{margin:4px 0 8px;font-size:var(--dsw-font-xxxs-11-font-size);color:var(--dsw-alias-label-tertiary)}
332
+ .ctm-rv-tasks{display:flex;flex-direction:column;gap:6px}
333
+ .ctm-rv-task{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 10px;background:var(--dsw-alias-bg-layer-1);border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-sm);font-size:var(--dsw-font-xxs-12-font-size)}
334
+ .ctm-rv-task-title{display:flex;align-items:center;gap:6px;min-width:0;color:var(--dsw-alias-label-primary)}
335
+ @media (prefers-reduced-motion:reduce){.ctm-switch,.ctm-switch::after,.ctm-ov-group>summary::before,.ctm-bd-open-btn{transition:none!important}}
336
+ `;
@@ -0,0 +1,65 @@
1
+ // Pixel office stage. Stage surfaces, text, borders, and state colors derive from host --dsw-* tokens via local aliases.
2
+ const STAGE_CSS = `
3
+ .ctm-stage{--aw-bg:var(--dsw-alias-bg-layer-1);--aw-fg:var(--dsw-alias-label-primary);--aw-muted:var(--dsw-alias-label-secondary);--aw-line:var(--dsw-alias-border-l2);--ctm-stage-floor-a:var(--dsw-alias-bg-layer-1);--ctm-stage-floor-b:var(--dsw-alias-bg-module-platform);--ctm-stage-grout:var(--dsw-alias-border-l1);--ctm-stage-wall:var(--dsw-alias-bg-overlay);--ctm-stage-desk:var(--dsw-alias-illustration-backing);--ctm-stage-desk-top:var(--dsw-alias-illustration-surface);--ctm-stage-plate:var(--dsw-alias-bg-layer-2);--ctm-stage-select:var(--dsw-alias-state-warn-primary);display:flex;flex-direction:column;gap:6px;min-width:0;container:ctm-stage/inline-size}
4
+ .ctm-stage-head{display:flex;align-items:center;gap:8px;min-width:0}
5
+ .ctm-stage-head .ctm-sub{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
6
+ .ctm-stage-toggle{margin-left:auto;flex:none}
7
+ .ctm-stage-office{position:relative;width:100%;height:clamp(220px,34vh,340px);border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-md);overflow:hidden;background:var(--ctm-stage-floor-a);user-select:none}
8
+ .ctm-stage-canvas{position:absolute;inset:0;width:100%;height:100%;display:block;image-rendering:pixelated}
9
+ .ctm-stage-overlay{position:absolute;inset:0;pointer-events:none}
10
+ .ctm-stage-overlay>*{pointer-events:auto}
11
+ .ctm-stage-empty{position:absolute;left:50%;top:55%;transform:translate(-50%,-50%);margin:0;padding:6px 12px;border-radius:var(--dsw-radius-md);background:var(--ctm-stage-plate);color:var(--aw-muted);text-align:center;max-width:80%}
12
+ .ctm-stage-plate{position:absolute;z-index:1;transform:translate(-50%,0);display:flex;flex-direction:column;gap:3px;min-width:72px;max-width:var(--pw,150px);padding:3px 7px;border:.5px solid var(--aw-line);border-radius:var(--dsw-radius-sm);background:var(--ctm-stage-plate);color:var(--aw-fg);backdrop-filter:blur(6px);box-shadow:var(--dsw-shadow-lv2);font-size:var(--dsw-font-xxxs-11-font-size);line-height:15px;text-align:left;cursor:pointer;transition:border-color .15s,box-shadow .15s}
13
+ .ctm-stage-plate:hover{border-color:var(--dsw-alias-border-l4);z-index:3}
14
+ .ctm-stage-plate:focus-visible{outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px}
15
+ .ctm-stage-plate[aria-selected=true]{border-color:var(--ctm-accent);box-shadow:0 0 0 1px var(--ctm-accent),var(--dsw-shadow-lv2);z-index:3}
16
+ .ctm-stage-plate[data-status=inactive]{opacity:.62;border-style:dashed}
17
+ .ctm-stage-plate-name{display:flex;align-items:center;gap:5px;font-size:var(--dsw-font-xxs-12-font-size);font-weight:600;line-height:16px;white-space:nowrap;min-width:0}
18
+ .ctm-stage-plate-name>span{flex:none;max-width:100%;overflow:hidden;text-overflow:ellipsis}
19
+ .ctm-stage-plate-more{display:none;flex-direction:column;gap:3px;min-width:0}
20
+ .ctm-stage-plate-more .ctm-sub{color:var(--aw-muted)}
21
+ .ctm-stage-plate:hover .ctm-stage-plate-more,.ctm-stage-plate[aria-selected=true] .ctm-stage-plate-more{display:flex}
22
+ .ctm-stage-plate .ctm-model-badge{align-self:flex-start;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
23
+ .ctm-stage-plate .ctm-model-badge[data-flash]{animation:ctm-stage-flash .35s 4}
24
+ .ctm-stage-plate-task{color:var(--aw-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
25
+ .ctm-stage-open{align-self:flex-start;padding:1px 8px;font-size:var(--dsw-font-xxxs-11-font-size);border-color:var(--dsw-alias-border-l3);color:var(--aw-fg)}
26
+ .ctm-stage-dot{flex:none;width:7px;height:7px;border-radius:50%;background:var(--dsw-alias-state-idle-primary)}
27
+ .ctm-stage-dot[data-s=running]{background:var(--dsw-alias-state-success-primary,#3ddc84);box-shadow:0 0 6px var(--dsw-alias-state-success-primary,#3ddc84);animation:ctm-stage-blink 1.4s infinite}
28
+ .ctm-stage-dot[data-s=provisioning]{background:var(--ctm-accent)}
29
+ .ctm-stage-dot[data-s=failed]{background:var(--dsw-alias-state-error-primary,#ff5c5c)}
30
+ .ctm-stage-meter{flex:1 1 24px;min-width:18px;max-width:48px;height:5px;border-radius:var(--dsw-radius-xs);background:var(--dsw-alias-border-l2);overflow:hidden}
31
+ .ctm-stage-meter>i{display:block;height:100%;width:var(--p);background:var(--ctm-accent);transition:width .5s ease}
32
+ .ctm-stage-meter[data-tone=warn]>i{background:var(--dsw-alias-state-warn-primary,#f5a524)}
33
+ .ctm-stage-meter[data-tone=error]>i{background:var(--dsw-alias-state-error-primary,#ff5c5c)}
34
+ .ctm-stage-icon{position:absolute;transform:translate(-50%,-100%);font-size:var(--dsw-font-s-14-font-size);line-height:1;filter:drop-shadow(0 1px 1px var(--dsw-alias-bg-mask-1));animation:ctm-stage-float 1.6s ease-in-out infinite}
35
+ .ctm-stage-bubble{position:absolute;z-index:2;transform:translate(-50%,-100%);max-width:180px;padding:3px 8px;border-radius:var(--dsw-radius-md);background:var(--ctm-stage-plate);border:.5px solid var(--dsw-alias-border-l3);color:var(--aw-fg);font-size:var(--dsw-font-xxxs-11-font-size);line-height:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
36
+ .ctm-stage-plate-act{font-size:10.5px;line-height:14px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
37
+ .ctm-stage-plate-act:empty{display:none}
38
+ .ctm-stage-plate[data-act=thinking] .ctm-stage-plate-act,.ctm-stage-plate[data-act=writing] .ctm-stage-plate-act,.ctm-stage-plate[data-act=reading] .ctm-stage-plate-act,.ctm-stage-plate[data-act=searching] .ctm-stage-plate-act,.ctm-stage-plate[data-act=browsing] .ctm-stage-plate-act{color:var(--dsw-alias-link)}
39
+ .ctm-stage-plate[data-act=terminal] .ctm-stage-plate-act{color:var(--dsw-alias-state-success-primary)}
40
+ .ctm-stage-plate[data-act=messaging] .ctm-stage-plate-act,.ctm-stage-plate[data-act=board] .ctm-stage-plate-act{color:var(--dsw-alias-state-warn-primary)}
41
+ .ctm-stage-plate[data-act=waiting] .ctm-stage-plate-act{color:var(--dsw-alias-label-secondary)}
42
+ .ctm-stage-plate[data-act=failed]{border-color:var(--dsw-alias-state-error-primary,#ff5c5c)}
43
+ .ctm-stage-plate[data-act=failed] .ctm-stage-plate-act{color:var(--dsw-alias-state-error-secondary)}
44
+ .ctm-stage-icon[data-act=thinking]{animation:ctm-stage-pulse 1.2s ease-in-out infinite}
45
+ .ctm-stage-icon[data-act=waiting]{animation:ctm-stage-sway 2s ease-in-out infinite}
46
+ .ctm-stage-icon[data-act=failed]{animation:ctm-stage-shake .5s 3}
47
+ .ctm-stage-icon[data-act=done]{animation:ctm-stage-pop .5s ease-out}
48
+ .ctm-stage-bubble[data-act=failed]{border-color:var(--dsw-alias-state-error-primary,#ff5c5c);color:var(--dsw-alias-state-error-primary)}
49
+ .ctm-stage-bubble[data-act=done]{border-color:var(--dsw-alias-state-success-primary,#3ddc84)}
50
+ .ctm-stage-bubble[data-act=thinking]{font-style:italic}
51
+ .ctm-stage-detail{display:flex;flex-direction:column;gap:6px;min-width:0}
52
+ .ctm-stage-detail-head{display:flex;align-items:center;gap:8px;min-width:0}
53
+ .ctm-stage-detail-head .ctm-btn{margin-left:auto;flex:none}
54
+ .ctm-stage-detail-hint{margin:0;padding:6px 10px;border:.5px dashed var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-md);text-align:center}
55
+ .ctm-stage-detail>.ctm-bd-card{width:100%;box-sizing:border-box}
56
+ @container ctm-stage (max-width:599px){.ctm-stage-plate{min-width:64px;padding:2px 6px}.ctm-stage-bubble{max-width:140px}}
57
+ @keyframes ctm-stage-blink{0%,100%{opacity:1}50%{opacity:.35}}
58
+ @keyframes ctm-stage-float{0%,100%{transform:translate(-50%,-100%)}50%{transform:translate(-50%,calc(-100% - 3px))}}
59
+ @keyframes ctm-stage-flash{0%,100%{filter:none}50%{filter:brightness(1.8)}}
60
+ @keyframes ctm-stage-pulse{0%,100%{opacity:1;transform:translate(-50%,-100%) scale(1)}50%{opacity:.6;transform:translate(-50%,-100%) scale(.88)}}
61
+ @keyframes ctm-stage-sway{0%,100%{transform:translate(-50%,-100%) rotate(-12deg)}50%{transform:translate(-50%,-100%) rotate(12deg)}}
62
+ @keyframes ctm-stage-shake{0%,100%{transform:translate(-50%,-100%)}25%{transform:translate(calc(-50% - 2px),-100%)}75%{transform:translate(calc(-50% + 2px),-100%)}}
63
+ @keyframes ctm-stage-pop{0%{transform:translate(-50%,-100%) scale(.3)}70%{transform:translate(-50%,-100%) scale(1.3)}100%{transform:translate(-50%,-100%) scale(1)}}
64
+ @media (prefers-reduced-motion:reduce){.ctm-stage-icon,.ctm-stage-icon[data-act],.ctm-stage-dot[data-s=running],.ctm-stage-plate .ctm-model-badge[data-flash]{animation:none}.ctm-stage-meter>i,.ctm-stage-plate{transition:none}}
65
+ `;
@@ -0,0 +1,82 @@
1
+ // ---------- pure helpers ----------
2
+ const apiUrl = (path, params) => {
3
+ const cleanPath = String(path ?? '').replace(/^\/+/, '');
4
+ if (!params || typeof params !== 'object') return cleanPath;
5
+ const USP = typeof URLSearchParams === 'function' ? URLSearchParams : null;
6
+ if (USP) {
7
+ const sp = new USP();
8
+ for (const [k, v] of Object.entries(params)) {
9
+ if (v !== undefined && v !== null) sp.set(k, String(v));
10
+ }
11
+ const qs = sp.toString();
12
+ return qs ? `${cleanPath}?${qs}` : cleanPath;
13
+ }
14
+ const parts = [];
15
+ for (const [k, v] of Object.entries(params)) {
16
+ if (v !== undefined && v !== null) {
17
+ parts.push(`${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`);
18
+ }
19
+ }
20
+ return parts.length ? `${cleanPath}?${parts.join('&')}` : cleanPath;
21
+ };
22
+ const fmt = (text, values) => String(text).replace(/\{(\w+)\}/g, (_, k) => (values[k] ?? ''));
23
+ const baseName = name => String(name ?? '').replace(/-r\d+$/, '');
24
+ const firstLine = text => { const s = String(text ?? '').trim(); const i = s.indexOf('\n'); return i === -1 ? s : s.slice(0, i); };
25
+ const parse = raw => { if (typeof raw !== 'string' || !raw) return undefined; try { const v = JSON.parse(raw); return v && typeof v === 'object' ? v : undefined; } catch { return undefined; } };
26
+ const cleanError = text => String(text ?? '').replace(/^(?:Error|\u9519\u8bef)[::]\s*/, '');
27
+ /** Durable result blocks flatten like the host's generic row: text parts joined, others as JSON. */
28
+ function resultText(block) {
29
+ const parts = (block.content ?? []).map(item => item.type === 'text' ? item.text : JSON.stringify(item, null, 2));
30
+ if (!parts.length && block.error) parts.push(`${block.error.name}: ${block.error.code}`);
31
+ return parts.join('\n') || null;
32
+ }
33
+ /** Stage facts shared by every card; settled blocks carry `kind`. */
34
+ function stage(props) {
35
+ if (props.phase === 'preparing') return { state: 'preparing', args: {}, output: null, data: undefined };
36
+ const block = props.block;
37
+ const settled = 'kind' in block;
38
+ const args = parse(settled ? block.call?.argsRaw : block.argsRaw) ?? {};
39
+ const output = settled ? resultText(block) : null;
40
+ const state = !settled ? 'running' : block.error?.code === 'interrupted' ? 'stopped' : block.isError ? 'error' : 'ok';
41
+ return { state, args, output, data: state === 'ok' ? parse(output) : undefined };
42
+ }
43
+
44
+ // ---------- icons (original, stroke = currentColor) ----------
45
+ const svg = (...children) => h('svg', { viewBox: '0 0 16 16', fill: 'none', stroke: 'currentColor', strokeWidth: 1.3, strokeLinecap: 'round', strokeLinejoin: 'round', 'aria-hidden': true }, ...children);
46
+ const ICONS = {
47
+ plan: () => svg(h('path', { d: 'M3 3.5h10M3 8h6M3 12.5h4' }), h('path', { d: 'M10.5 10.5l1.5 1.5 2.5-3' })),
48
+ free: () => svg(h('path', { d: 'M8.5 1.8L3.5 9h4l-.5 5.2L12.5 7h-4z' })),
49
+ team: () => svg(h('circle', { cx: 6, cy: 5.5, r: 2.2 }), h('path', { d: 'M2 13c.5-2.3 2-3.5 4-3.5s3.5 1.2 4 3.5' }), h('circle', { cx: 11.5, cy: 6, r: 1.7 }), h('path', { d: 'M11 9.6c1.6 0 2.7.9 3 2.6' })),
50
+ };
51
+ const chevron = open => svg(h('path', { d: open ? 'M4 6l4 4 4-4' : 'M6 4l4 4-4 4' }));
52
+
53
+ // ---------- shared row ----------
54
+ function Card({ tool, icon, title, summary, summaryTone, badges, state, body, inspect, t }) {
55
+ const [open, setOpen] = React.useState(false);
56
+ const expandable = body != null && body !== false;
57
+ const isOpen = open && expandable;
58
+ const toggle = () => setOpen(v => !v);
59
+ const rowProps = expandable ? {
60
+ role: 'button', tabIndex: 0, 'aria-expanded': isOpen, 'data-expandable': '', onClick: toggle,
61
+ onKeyDown: event => { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); toggle(); } },
62
+ } : {};
63
+ const status = state === 'running' ? t('state.running') : state === 'error' ? t('state.failed') : state === 'stopped' ? t('state.stopped') : null;
64
+ const tone = state === 'error' ? 'ctm-error' : state === 'stopped' ? 'ctm-warn' : summaryTone ?? '';
65
+ return h('div', { className: 'ctm-card', 'data-tool': tool, 'data-state': state },
66
+ h('div', { className: 'ctm-row', ...(isOpen ? { 'data-open': '' } : {}), ...rowProps },
67
+ h('span', { className: 'ctm-lead' }, h('span', { className: 'ctm-ico' }, icon()), expandable ? h('span', { className: 'ctm-chev' }, chevron(isOpen)) : null),
68
+ status ? h('span', { className: 'ctm-hidden' }, status) : null,
69
+ h('span', { className: 'ctm-title' }, title),
70
+ summary ? h('span', { className: 'ctm-sep', 'aria-hidden': true }) : null,
71
+ summary ? h('span', { className: `ctm-summary ${tone}`, title: summary }, summary) : null,
72
+ ...(badges ?? []).filter(Boolean)),
73
+ isOpen ? h('div', { className: 'ctm-wrap' },
74
+ h('div', { className: 'ctm-body' }, ...(Array.isArray(body) ? body : [body])),
75
+ inspect ? h('button', { type: 'button', className: 'ctm-inspect', onClick: inspect }, t('action.inspect')) : null) : null);
76
+ }
77
+ const section = (label, ...children) => h('div', { className: 'ctm-section' }, label ? h('div', { className: 'ctm-label' }, label) : null, ...children);
78
+ const badge = (text, tone, key) => h('span', { className: 'ctm-badge', 'data-tone': tone, key }, text);
79
+ const chip = (label, value, key) => h('span', { className: 'ctm-chip', key }, label ? h('span', null, label) : null, h('span', null, value));
80
+ const errorBody = (s, t) => s.state === 'error' && s.output ? section(null, h('pre', { className: 'ctm-pre ctm-error' }, cleanError(s.output))) : null;
81
+ /** Results that are not the expected JSON (older sessions, other versions) stay readable as text. */
82
+ const rawBody = (s, t) => s.state === 'ok' && s.output && !s.data ? section(t('output'), h('pre', { className: 'ctm-pre' }, s.output)) : null;
@@ -0,0 +1,34 @@
1
+ // ---------- 03b-collapsible-list.js: Shared collapsible list component ----------
2
+ /**
3
+ * CollapsibleList:
4
+ * Show the first limit items (default 5), then offer localized expand/collapse controls.
5
+ * Hide the toggle when items <= limit.
6
+ */
7
+ function CollapsibleList({ items = [], limit = 5, renderItem, as = 'div', className, t, expandText, collapseText }) {
8
+ const [expanded, setExpanded] = React.useState(false);
9
+ const total = items.length;
10
+ if (!total) return null;
11
+
12
+ const visibleItems = (expanded || total <= limit) ? items : items.slice(0, limit);
13
+ const remaining = total - limit;
14
+
15
+ const moreLabel = expandText
16
+ ? (typeof expandText === 'function' ? expandText(remaining) : expandText)
17
+ : (typeof t === 'function' && t('list.more') ? fmt(t('list.more'), { n: remaining }) : fmt(en['list.more'], { n: remaining }));
18
+
19
+ const collapseLabel = collapseText
20
+ ? collapseText
21
+ : (typeof t === 'function' && t('list.collapse') ? t('list.collapse') : en['list.collapse']);
22
+
23
+ const renderedChildren = visibleItems.map((item, index) => renderItem(item, index));
24
+ if (total > limit) {
25
+ renderedChildren.push(h('button', {
26
+ key: 'ctm-toggle-btn',
27
+ type: 'button',
28
+ className: 'ctm-btn ctm-list-toggle',
29
+ onClick: () => setExpanded(prev => !prev),
30
+ 'aria-expanded': expanded,
31
+ }, expanded ? collapseLabel : moreLabel));
32
+ }
33
+ return h(as, { className }, ...renderedChildren);
34
+ }