@goodandready/dsh-cron 0.3.17 → 0.3.19

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.
@@ -199,10 +199,6 @@ export function formatDigestMarkdown(digest) {
199
199
  return lines.join('\n');
200
200
  }
201
201
 
202
- export function formatDigestTelegram(digest) {
203
- // Return clean plain Markdown compatible with standard bot message formatting
204
- return formatDigestMarkdown(digest);
205
- }
206
202
 
207
203
  export async function sendAnalyticsDigest({ digest, channels, deliveryConfig }) {
208
204
  if (!channels || !digest) {
package/lib/chat-start.js CHANGED
@@ -5,7 +5,13 @@ export async function chatStartHandler(ctx, req, res, parseJsonBody, sendJson, r
5
5
  return;
6
6
  }
7
7
 
8
- const body = await parseJsonBody(req);
8
+ let body;
9
+ try {
10
+ body = await parseJsonBody(req);
11
+ } catch (err) {
12
+ sendJson(res, err.statusCode || 400, { ok: false, error: err.message });
13
+ return;
14
+ }
9
15
  const userPrompt = (body.prompt || '').trim();
10
16
  if (!userPrompt) {
11
17
  sendJson(res, 400, { ok: false, error: 'Prompt text must not be empty' });
package/lib/client.css ADDED
@@ -0,0 +1,226 @@
1
+ :root {
2
+ --dsh-cron-success: var(--dsw-alias-state-success-primary);
3
+ --dsh-cron-success-bg: color-mix(in srgb, var(--dsh-cron-success) 10%, transparent);
4
+ --dsh-cron-danger: var(--dsw-alias-state-error-primary);
5
+ --dsh-cron-danger-bg: color-mix(in srgb, var(--dsh-cron-danger) 10%, transparent);
6
+ --dsh-cron-info: var(--dsw-alias-state-brand-primary);
7
+ --dsh-cron-info-bg: color-mix(in srgb, var(--dsh-cron-info) 12%, transparent);
8
+ --dsh-cron-accent: var(--dsw-alias-state-info-primary);
9
+ --dsh-cron-accent-bg: color-mix(in srgb, var(--dsh-cron-accent) 12%, transparent);
10
+ --dsh-cron-warning: var(--dsw-alias-state-warning-primary);
11
+ --dsh-cron-warning-bg: color-mix(in srgb, var(--dsh-cron-warning) 12%, transparent);
12
+ }
13
+ [data-pane=conversation], [class*=centerCol] {
14
+ position: relative !important;
15
+ }
16
+ [${VIEW_ATTR}] {
17
+ z-index: 60;
18
+ background: var(--dsw-alias-bg-base);
19
+ display: none;
20
+ position: absolute;
21
+ inset: 0;
22
+ }
23
+ html[${ACTIVE_ATTR}] [${VIEW_ATTR}] {
24
+ display: block !important;
25
+ }
26
+ html[${ACTIVE_ATTR}] [data-pane=conversation] > *:not([${VIEW_ATTR}]),
27
+ html[${ACTIVE_ATTR}] [class*=centerCol] > *:not([${VIEW_ATTR}]) {
28
+ display: none !important;
29
+ }
30
+
31
+ .dsh-cron-entry-clone { display: flex; align-items: center; gap: 8px; }
32
+ .dsh-cron-entry-icon { display: flex; align-items: center; justify-content: center; flex: none; width: 16px; height: 16px; }
33
+ .dsh-cron-entry-label { text-overflow: ellipsis; overflow: hidden; }
34
+ [data-dsh-frame][data-sidebar-collapsed] .dsh-cron-entry-label { display: none; }
35
+
36
+ .dsh-cron-overlay { position: absolute; inset: 0; display: flex; flex-direction: column; background: var(--dsw-alias-bg-base); color: var(--dsw-alias-label-primary); overflow-y: auto; padding: 24px 48px 32px; z-index: 100; box-sizing: border-box; }
37
+ .dsh-cron-container { max-width: 960px; width: 100%; margin: 0 auto; display: flex; flex-direction: column; gap: 20px; padding: 8px 0 32px; box-sizing: border-box; }
38
+
39
+ .dsh-cron-top-bar { display: flex; align-items: center; gap: 12px; }
40
+ .dsh-cron-back-btn { appearance: none; font: inherit; cursor: pointer; color: var(--dsw-alias-label-secondary); background: 0 0; border: 1px solid var(--dsw-alias-border-l2); border-radius: 8px; align-items: center; gap: 6px; padding: 4px 12px; font-size: 13px; display: inline-flex; flex: none; height: 32px; box-sizing: border-box; }
41
+ .dsh-cron-back-btn:hover { color: var(--dsw-alias-label-primary); background: var(--dsw-alias-bg-layer-4, var(--dsw-alias-interactive-bg-hover, color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent))); }
42
+
43
+ .dsh-cron-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; padding-bottom: 16px; border-bottom: 1px solid var(--dsw-alias-border-l2); }
44
+ .dsh-cron-title { font-size: 22px; font-weight: 700; letter-spacing: -0.02em; margin-bottom: 6px; }
45
+ .dsh-cron-subtitle { font-size: 14px; color: var(--dsw-alias-label-secondary); line-height: 1.5; }
46
+ .dsh-cron-create-btn { appearance: none; display: inline-flex; align-items: center; gap: 6px; background: var(--dsw-alias-bg-layer-2); color: var(--dsw-alias-label-primary); border: 1px solid var(--dsw-alias-border-l2); border-radius: 9999px; padding: 8px 16px; font-size: 14px; font-weight: 500; cursor: pointer; position: relative; }
47
+ .dsh-cron-create-btn:hover { background: var(--dsw-alias-bg-layer-hover, var(--dsw-alias-interactive-bg-hover)); }
48
+ .dsh-cron-dropdown { position: absolute; top: calc(100% + 6px); right: 0; width: 200px; background: var(--dsw-alias-bg-layer-3); border: 1px solid var(--dsw-alias-border-l2); border-radius: 12px; padding: 6px; box-shadow: 0 10px 25px color-mix(in srgb, var(--dsw-alias-bg-mask) 50%, transparent); z-index: 200; }
49
+ .dsh-cron-dropdown-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 10px 12px; background: transparent; border: none; border-radius: 8px; color: var(--dsw-alias-label-primary); font-size: 13.5px; text-align: left; cursor: pointer; }
50
+ .dsh-cron-dropdown-item:hover { background: var(--dsw-alias-interactive-bg-hover); }
51
+ .dsh-cron-search-bar { position: relative; margin-bottom: 0; }
52
+ .dsh-cron-search-input { width: 100%; height: 36px; background: var(--dsw-alias-bg-layer-2); border: 1px solid var(--dsw-alias-border-l2); border-radius: 8px; padding: 0 12px 0 38px; color: var(--dsw-alias-label-primary, inherit); font-size: 13px; outline: none; box-sizing: border-box; }
53
+ .dsh-cron-search-input:focus { outline: none; border-color: var(--dsh-cron-info); }
54
+ .dsh-cron-search-icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--dsw-alias-label-tertiary); }
55
+ .dsh-cron-filters { margin-top: 8px; }
56
+ .dsh-cron-filter-toggle { background: none; border: 1px solid var(--dsw-alias-border-l2); color: var(--dsw-alias-label-secondary); border-radius: 8px; padding: 4px 10px; font-size: 12px; cursor: pointer; }
57
+ .dsh-cron-filter-toggle:hover { color: var(--dsw-alias-label-primary); border-color: var(--dsh-cron-info); }
58
+ .dsh-cron-filter-panel { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; margin-top: 10px; padding: 10px 12px; border: 1px solid var(--dsw-alias-border-l2); border-radius: 8px; background: var(--dsw-alias-bg-layer-3, color-mix(in srgb, var(--dsw-alias-label-primary) 2%, transparent)); }
59
+ .dsh-cron-filter-field { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--dsw-alias-label-tertiary); }
60
+ .dsh-cron-filter-field select { background: var(--dsw-alias-bg-layer-2); border: 1px solid var(--dsw-alias-border-l2); color: var(--dsw-alias-label-primary, inherit); border-radius: 6px; padding: 5px 8px; font-size: 12.5px; }
61
+ .dsh-cron-tabs { display: flex; flex-wrap: wrap; gap: 8px; }
62
+ .dsh-cron-tab { appearance: none; background: transparent; border: 1px solid var(--dsw-alias-border-l2); padding: 4px 12px; border-radius: 999px; color: var(--dsw-alias-label-secondary); font-size: 12px; font-weight: 500; cursor: pointer; }
63
+ .dsh-cron-tab[data-active="true"] { background: var(--dsw-alias-bg-layer-4); color: var(--dsw-alias-label-primary); border-color: var(--dsw-alias-label-dimmed, var(--dsw-alias-border-l2)); }
64
+ .dsh-cron-task-list { display: flex; flex-direction: column; gap: 12px; margin-bottom: 0; }
65
+ .dsh-cron-task-item { display: flex; align-items: center; gap: 16px; padding: 14px 18px; background: var(--dsw-alias-bg-layer-3); border: 1px solid var(--dsw-alias-border-l2); border-radius: 12px; cursor: pointer; transition: background 0.15s, border-color 0.15s; }
66
+ .dsh-cron-task-item:hover, .dsh-cron-task-item:focus-visible { background: var(--dsw-alias-bg-layer-4); border-color: var(--dsw-alias-label-dimmed, var(--dsw-alias-border-l1)); outline: none; }
67
+ .dsh-cron-task-prompt-preview { font-size: 12.5px; color: var(--dsw-alias-label-secondary); margin-top: 5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 520px; line-height: 1.3; }
68
+ .dsh-cron-type-tag { display: inline-flex; align-items: center; font-size: 11px; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--dsw-alias-border-l2); text-transform: uppercase; font-weight: 500; margin-left: 8px; vertical-align: middle; }
69
+ .dsh-cron-tag-success { background: var(--dsh-cron-info-bg); color: var(--dsh-cron-info); border-color: var(--dsh-cron-info); }
70
+ .dsh-cron-tag-failure { background: var(--dsh-cron-danger-bg); color: var(--dsh-cron-danger); border-color: var(--dsh-cron-danger); }
71
+ .dsh-cron-tag-heartbeat { background: var(--dsh-cron-accent-bg); color: var(--dsh-cron-accent); border-color: var(--dsh-cron-accent); }
72
+ .dsh-cron-tag-session { background: var(--dsh-cron-info-bg); color: var(--dsh-cron-info); border-color: var(--dsh-cron-info); }
73
+ .dsh-cron-tag-preflight { background: var(--dsh-cron-warning-bg); color: var(--dsh-cron-warning); border-color: var(--dsh-cron-warning); }
74
+
75
+ .dsh-cron-task-model-tag { display: inline-flex; align-items: center; font-size: 11px; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--dsw-alias-border-l2); background: var(--dsw-alias-bg-layer-2, color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent)); color: var(--dsw-alias-label-secondary); margin-left: 8px; vertical-align: middle; }
76
+ .dsh-cron-task-actions { display: flex; gap: 8px; }
77
+ .dsh-cron-icon-btn { appearance: none; font: inherit; background: var(--dsw-alias-bg-layer-2, transparent); border: 1px solid var(--dsw-alias-border-l2); border-radius: 8px; padding: 6px 12px; font-size: 12.5px; font-weight: 500; color: var(--dsw-alias-label-primary); cursor: pointer; display: inline-flex; align-items: center; gap: 6px; transition: all 0.15s ease; }
78
+ .dsh-cron-icon-btn:hover { background: var(--dsw-alias-bg-layer-4); border-color: var(--dsw-alias-label-dimmed, var(--dsw-alias-border-l2)); }
79
+ .dsh-cron-icon-btn.dsh-cron-danger { color: var(--dsh-cron-danger); border-color: var(--dsh-cron-danger-bg); }
80
+ .dsh-cron-icon-btn.dsh-cron-danger:hover { background: var(--dsh-cron-danger-bg); border-color: var(--dsh-cron-danger); }
81
+ .dsh-cron-task-status-btn { background: none; border: 1px solid var(--dsw-alias-border-l2); border-radius: 50%; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; color: var(--dsw-alias-label-tertiary); cursor: pointer; flex-shrink: 0; }
82
+ .dsh-cron-task-status-btn[data-active="true"] { color: var(--dsh-cron-success); border-color: var(--dsh-cron-success); }
83
+ .dsh-cron-recs-title { font-size: 16px; font-weight: 600; margin-bottom: 14px; }
84
+ .dsh-cron-recs-list { display: flex; flex-direction: column; gap: 10px; }
85
+ .dsh-cron-rec-card { display: flex; align-items: center; gap: 16px; padding: 14px 18px; background: var(--dsw-alias-bg-layer-3); border: 1px solid var(--dsw-alias-border-l2); border-radius: 12px; cursor: pointer; transition: background 0.15s; }
86
+ .dsh-cron-rec-card:hover, .dsh-cron-rec-card:focus-visible { background: var(--dsw-alias-bg-layer-4); border-color: var(--dsw-alias-label-dimmed, var(--dsw-alias-border-l2)); outline: none; }
87
+ .dsh-cron-rec-icon { width: 36px; height: 36px; border-radius: 10px; background: var(--dsw-alias-bg-layer-2, color-mix(in srgb, var(--dsw-alias-label-primary) 3%, transparent)); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
88
+ .dsh-cron-rec-content { flex: 1; min-width: 0; }
89
+ .dsh-cron-rec-title { font-size: 14.5px; font-weight: 500; margin-bottom: 4px; }
90
+ .dsh-cron-rec-time { font-size: 13px; color: var(--dsw-alias-label-secondary); font-weight: normal; margin-left: 8px; }
91
+ .dsh-cron-rec-desc { font-size: 13px; color: var(--dsw-alias-label-tertiary); }
92
+
93
+ .dsh-cron-modal-overlay { position: fixed; inset: 0; background: var(--dsw-alias-bg-mask, color-mix(in srgb, #000 75%, transparent)); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; z-index: 1000; padding: 16px; box-sizing: border-box; overflow-y: auto; }
94
+ .dsh-cron-modal { background: var(--dsw-alias-bg-layer-2); border: 1px solid var(--dsw-alias-border-l2); border-radius: 16px; width: 100%; max-width: 540px; max-height: min(90vh, calc(100vh - 36px)); overflow-y: auto; padding: 24px; box-shadow: 0 20px 40px color-mix(in srgb, var(--dsw-alias-bg-mask) 60%, transparent); box-sizing: border-box; }
95
+ .dsh-cron-modal-scroll { max-width: 640px; max-height: min(90vh, calc(100vh - 36px)); overflow-y: auto; }
96
+ .dsh-cron-modal::-webkit-scrollbar { width: 6px; }
97
+ .dsh-cron-modal::-webkit-scrollbar-track { background: transparent; }
98
+ .dsh-cron-modal::-webkit-scrollbar-thumb { background: var(--dsw-alias-border-l2); border-radius: 3px; }
99
+ .dsh-cron-modal::-webkit-scrollbar-thumb:hover { background: var(--dsw-alias-label-tertiary); }
100
+ .dsh-cron-section-head { display: flex; align-items: center; justify-content: space-between; width: 100%; background: none; border: none; padding: 0; margin-bottom: 10px; font: inherit; font-weight: 500; font-size: 12.5px; color: var(--dsw-alias-label-secondary); cursor: pointer; }
101
+ .dsh-cron-section-head:hover { color: var(--dsw-alias-label-primary); }
102
+ .dsh-cron-section-chevron { transition: transform 0.15s ease; display: inline-block; }
103
+ .dsh-cron-section-chevron[data-open="false"] { transform: rotate(-90deg); }
104
+ .dsh-cron-section-body { padding-bottom: 4px; }
105
+ .dsh-cron-modal-title { font-size: 18px; font-weight: 600; margin-bottom: 18px; }
106
+ .dsh-cron-form-group { margin-bottom: 16px; }
107
+ .dsh-cron-form-group label { display: block; font-size: 13px; color: var(--dsw-alias-label-secondary); margin-bottom: 6px; }
108
+ .dsh-cron-form-group input, .dsh-cron-form-group textarea, .dsh-cron-form-group select { width: 100%; background: var(--dsw-alias-bg-layer-2); border: 1px solid var(--dsw-alias-border-l2); border-radius: 8px; padding: 8px 12px; color: var(--dsw-alias-label-primary); font-size: 13px; outline: none; box-sizing: border-box; }
109
+ .dsh-cron-form-group input:focus, .dsh-cron-form-group textarea:focus, .dsh-cron-form-group select:focus { outline: none; border-color: var(--dsh-cron-info); }
110
+ .dsh-cron-form-group select { cursor: pointer; }
111
+ .dsh-cron-form-group textarea { min-height: 80px; resize: vertical; }
112
+ .dsh-cron-form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
113
+ .dsh-cron-modal-foot { display: flex; justify-content: flex-end; align-items: center; gap: 10px; margin-top: 20px; position: sticky; bottom: -24px; background: var(--dsw-alias-bg-layer-2); border-top: 1px solid var(--dsw-alias-border-l2); padding-top: 14px; padding-bottom: 4px; margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; z-index: 10; }
114
+ .dsh-cron-btn-primary { background: var(--dsw-alias-label-primary); color: var(--dsw-alias-bg-layer-3); border: 1px solid transparent; border-radius: 8px; padding: 7px 14px; font-size: 13px; font-weight: 500; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }
115
+ .dsh-cron-btn-primary:hover:not(:disabled) { opacity: 0.88; }
116
+ .dsh-cron-btn-primary:disabled { opacity: 0.5; cursor: not-allowed; }
117
+ .dsh-cron-btn-secondary { appearance: none; font: inherit; background: var(--dsw-alias-bg-layer-2, transparent); color: var(--dsw-alias-label-primary); border: 1px solid var(--dsw-alias-border-l2); border-radius: 8px; padding: 7px 14px; font-size: 13px; font-weight: 500; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; transition: all 0.15s ease; }
118
+ .dsh-cron-btn-secondary:hover:not(:disabled) { background: var(--dsw-alias-bg-layer-4); border-color: var(--dsw-alias-label-dimmed, var(--dsw-alias-border-l2)); }
119
+ .dsh-cron-chat-box { position: relative; background: var(--dsw-alias-bg-base); border: 1px solid var(--dsw-alias-border-l2); border-radius: 12px; padding: 12px; }
120
+ .dsh-cron-chat-input { width: 100%; background: transparent; border: none; color: var(--dsw-alias-label-primary); font-size: 14px; min-height: 100px; resize: vertical; outline: none; box-sizing: border-box; line-height: 1.5; }
121
+ .dsh-cron-chat-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--dsw-alias-border-l1); }
122
+ .dsh-cron-chat-hint { font-size: 12px; color: var(--dsw-alias-label-tertiary); }
123
+ .dsh-cron-send-btn { width: 34px; height: 34px; border-radius: 8px; background: var(--dsw-alias-label-primary); color: var(--dsw-alias-bg-base); border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: transform 0.1s, background 0.15s; }
124
+ .dsh-cron-send-btn:hover:not(:disabled) { transform: translateY(-1px); }
125
+ .dsh-cron-send-btn:disabled { opacity: 0.4; cursor: not-allowed; }
126
+
127
+ .dsh-cron-card { background: var(--dsw-alias-bg-layer-3); border: 1px solid var(--dsw-alias-border-l2); border-radius: 12px; padding: 18px 20px; margin-bottom: 0; display: flex; flex-direction: column; gap: 14px; }
128
+ .dsh-cron-card-head-btn { appearance: none; width: 100%; font: inherit; color: inherit; text-align: left; cursor: pointer; background: 0 0; border: 0; border-radius: 12px; display: flex; align-items: center; gap: 12px; padding: 0; }
129
+ .dsh-cron-card-head-btn .dsh-cron-card-title { flex: 1; }
130
+ .dsh-cron-card-title { font-size: 16px; font-weight: 600; color: var(--dsw-alias-label-primary); }
131
+ .dsh-cron-chev { margin-left: auto; flex: none; color: var(--dsw-alias-label-tertiary); transition: transform 0.16s; display: flex; align-items: center; }
132
+ .dsh-cron-chev-open { transform: rotate(180deg); }
133
+ .dsh-cron-card-body { border-top: 1px solid var(--dsw-alias-border-l2); margin-top: 2px; padding-top: 14px; }
134
+ .dsh-cron-card-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; }
135
+ .dsh-cron-card-desc { font-size: 13px; color: var(--dsw-alias-label-secondary); line-height: 1.4; }
136
+
137
+ .dsh-cron-modal-nav { display: flex; gap: 4px; border-bottom: 1px solid var(--dsw-alias-border-l2); margin-bottom: 18px; padding-bottom: 2px; }
138
+ .dsh-cron-modal-tab { appearance: none; background: transparent; border: none; border-bottom: 2px solid transparent; padding: 8px 14px; font-size: 13.5px; color: var(--dsw-alias-label-tertiary); cursor: pointer; font-weight: 500; transition: color 0.15s, border-color 0.15s; }
139
+ .dsh-cron-modal-tab:hover { color: var(--dsw-alias-label-secondary); }
140
+ .dsh-cron-modal-tab[data-active="true"] { color: var(--dsw-alias-label-primary); border-bottom-color: var(--dsw-alias-label-primary); }
141
+ .dsh-cron-history-list { display: flex; flex-direction: column; gap: 10px; max-height: 420px; overflow-y: auto; padding-right: 4px; }
142
+ .dsh-cron-history-item { background: var(--dsw-alias-bg-base); border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 12px 14px; font-size: 12.5px; }
143
+ .dsh-cron-history-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; }
144
+ .dsh-cron-history-status { font-weight: 500; font-size: 11px; text-transform: uppercase; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--dsw-alias-border-l2); }
145
+ .dsh-cron-history-status[data-status="success"] { background: var(--dsh-cron-success-bg); color: var(--dsh-cron-success); border-color: var(--dsh-cron-success); }
146
+ .dsh-cron-history-status[data-status="validation_failed"] { background: var(--dsh-cron-danger-bg); color: var(--dsh-cron-danger); border-color: var(--dsh-cron-danger); }
147
+ .dsh-cron-stage-pill { font-size: 10.5px; padding: 1px 7px; border-radius: 4px; border: 1px solid var(--dsw-alias-border-l2); color: var(--dsw-alias-label-secondary); }
148
+ .dsh-cron-stage-pill[data-status="success"], .dsh-cron-stage-pill[data-status="delivered"] { background: var(--dsh-cron-success-bg); color: var(--dsh-cron-success); border-color: var(--dsh-cron-success); }
149
+ .dsh-cron-stage-pill[data-status="failed"], .dsh-cron-stage-pill[data-status="error"] { background: var(--dsh-cron-danger-bg); color: var(--dsh-cron-danger); border-color: var(--dsh-cron-danger); }
150
+ .dsh-cron-stage-pill[data-status="partial"] { background: var(--dsh-cron-warning-bg); color: var(--dsh-cron-warning); border-color: var(--dsh-cron-warning); }
151
+ .dsh-cron-stage-pill[data-status="skipped"] { opacity: 0.6; }
152
+ .dsh-cron-history-status[data-status="error"], .dsh-cron-history-status[data-status="timeout"] { background: var(--dsh-cron-danger-bg); color: var(--dsh-cron-danger); border-color: var(--dsh-cron-danger); }
153
+ .dsh-cron-history-status[data-status="skipped"], .dsh-cron-history-status[data-status="missed"] { background: var(--dsh-cron-warning-bg); color: var(--dsh-cron-warning); border-color: var(--dsh-cron-warning); }
154
+ .dsh-cron-history-time { color: var(--dsw-alias-label-tertiary); font-size: 12px; }
155
+ .dsh-cron-history-output { background: var(--dsw-alias-bg-base); border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; padding: 8px 10px; font-family: monospace; font-size: 12px; color: var(--dsw-alias-label-secondary); max-height: 140px; overflow-y: auto; white-space: pre-wrap; word-break: break-all; margin-top: 6px; }
156
+ .dsh-cron-history-empty { text-align: center; padding: 36px 0; color: var(--dsw-alias-label-tertiary); font-size: 13.5px; }
157
+
158
+ .dsh-cron-stats-bar { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-bottom: 0; }
159
+ .dsh-cron-stat-card { background: var(--dsw-alias-bg-layer-2, color-mix(in srgb, var(--dsw-alias-label-primary) 2%, transparent)); border: 1px solid var(--dsw-alias-border-l2); border-radius: 8px; padding: 12px 14px; display: flex; flex-direction: column; gap: 4px; }
160
+ .dsh-cron-stat-val { font-size: 18px; font-weight: 700; color: var(--dsw-alias-label-primary); }
161
+ .dsh-cron-stat-lbl { font-size: 12px; color: var(--dsw-alias-label-secondary); margin-top: 0; }
162
+ .dsh-cron-oneshot-tag { display: inline-flex; align-items: center; font-size: 11px; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--dsh-cron-accent); background: var(--dsh-cron-accent-bg); color: var(--dsh-cron-accent); font-weight: 500; }
163
+ .dsh-cron-config-tag { display: inline-flex; align-items: center; font-size: 11px; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--dsw-alias-border-l2); color: var(--dsw-alias-label-secondary); font-weight: 500; }
164
+ .dsh-cron-cost-tag { display: inline-flex; align-items: center; font-size: 11px; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--dsh-cron-success); background: var(--dsh-cron-success-bg); color: var(--dsh-cron-success); font-weight: 500; }
165
+ .dsh-cron-tokens-tag { display: inline-flex; align-items: center; font-size: 11px; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--dsh-cron-info); background: var(--dsh-cron-info-bg); color: var(--dsh-cron-info); }
166
+ .dsh-cron-checkbox-row { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--dsw-alias-label-secondary); cursor: pointer; user-select: none; }
167
+ .dsh-cron-checkbox-row input { width: 15px; height: 15px; margin: 0; cursor: pointer; accent-color: var(--dsw-alias-label-primary); }
168
+ .dsh-cron-hint { font-size: 12px; color: var(--dsw-alias-label-tertiary); margin-top: 4px; }
169
+ .dsh-cron-channel-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 6px 12px; }
170
+ .dsh-cron-section { border-top: 1px solid var(--dsw-alias-border-l2); margin-top: 16px; padding-top: 12px; }
171
+ .dsh-cron-section-title { font-weight: 500; font-size: 12.5px; color: var(--dsw-alias-label-secondary); margin-bottom: 10px; }
172
+ .dsh-cron-secret-row { display: flex; align-items: center; gap: 8px; }
173
+ .dsh-cron-secret-row input { flex: 1; }
174
+ .dsh-cron-badge-ref { font-size: 11px; padding: 2px 6px; border-radius: 4px; background: var(--dsw-alias-bg-layer-3, color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent)); color: var(--dsw-alias-label-tertiary); white-space: nowrap; }
175
+ .dsh-cron-status-banner { padding: 10px 14px; border-radius: 8px; font-size: 13px; margin-top: 12px; }
176
+ .dsh-cron-status-banner[data-type="success"] { background: var(--dsh-cron-success-bg); border: 1px solid var(--dsh-cron-success); color: var(--dsh-cron-success); }
177
+ .dsh-cron-status-banner[data-type="error"] { background: var(--dsh-cron-danger-bg); border: 1px solid var(--dsh-cron-danger); color: var(--dsh-cron-danger); }
178
+ .dsh-cron-status-banner[data-type="info"] { background: var(--dsh-cron-info-bg); border: 1px solid var(--dsh-cron-info); color: var(--dsh-cron-info); }
179
+ @keyframes dsh-cron-pulse-ring { 0% { box-shadow: 0 0 0 0 var(--dsh-cron-success-bg); } 70% { box-shadow: 0 0 0 9px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }
180
+ .dsh-cron-pulse { animation: dsh-cron-pulse-ring 1.6s infinite; border-color: var(--dsh-cron-success); color: var(--dsh-cron-success); }
181
+
182
+ /* #34: sidebar job list */
183
+ .dsh-cron-sidebar-jobs { display: flex; flex-direction: column; gap: 2px; margin: 2px 0 6px 0; }
184
+ .dsh-cron-sidebar-jobs-head { display: flex; align-items: center; justify-content: space-between; width: 100%; background: none; border: none; padding: 4px 8px; font: inherit; font-size: 12px; color: var(--dsw-alias-label-tertiary); cursor: pointer; border-radius: 6px; text-align: left; }
185
+ .dsh-cron-sidebar-jobs-head:hover { color: var(--dsw-alias-label-primary); background: var(--dsw-alias-interactive-bg-hover, color-mix(in srgb, var(--dsw-alias-label-primary) 4%, transparent)); }
186
+ .dsh-cron-sidebar-jobs-head::after { content: '▾'; font-size: 10px; transition: transform 0.15s ease; }
187
+ .dsh-cron-sidebar-jobs[data-open="false"] .dsh-cron-sidebar-jobs-head::after { transform: rotate(-90deg); }
188
+ .dsh-cron-sidebar-jobs[data-open="false"] .dsh-cron-sidebar-jobs-list { display: none; }
189
+ .dsh-cron-sidebar-jobs-list { display: flex; flex-direction: column; gap: 2px; padding-left: 10px; }
190
+ .dsh-cron-sidebar-job { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; width: 100%; background: none; border: none; border-left: 2px solid transparent; padding: 3px 8px; font: inherit; cursor: pointer; border-radius: 0 6px 6px 0; text-align: left; }
191
+ .dsh-cron-sidebar-job:hover { background: var(--dsw-alias-interactive-bg-hover, color-mix(in srgb, var(--dsw-alias-label-primary) 4%, transparent)); border-left-color: var(--dsh-cron-info); }
192
+ .dsh-cron-sidebar-job-title { font-size: 12px; color: var(--dsw-alias-label-secondary); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
193
+ .dsh-cron-sidebar-job-meta { font-size: 11px; color: var(--dsw-alias-label-tertiary); }
194
+ .dsh-cron-sidebar-empty, .dsh-cron-sidebar-more { font-size: 11px; color: var(--dsw-alias-label-tertiary); padding: 2px 8px; }
195
+ .dsh-cron-task-highlight { border-color: var(--dsh-cron-info) !important; box-shadow: 0 0 0 2px var(--dsh-cron-info-bg); }
196
+
197
+ /* #39: narrow screens. Only layout changes — no information is hidden. */
198
+ @media (max-width: 900px) {
199
+ .dsh-cron-container { padding: 8px 12px 24px; gap: 14px; }
200
+ .dsh-cron-form-row { grid-template-columns: 1fr; }
201
+ .dsh-cron-channel-grid { grid-template-columns: 1fr; }
202
+ .dsh-cron-filter-panel { grid-template-columns: 1fr; }
203
+ .dsh-cron-modal { padding: 16px; border-radius: 12px; }
204
+ .dsh-cron-modal-foot { bottom: -16px; margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; }
205
+ .dsh-cron-modal-scroll { max-height: 92vh; }
206
+ .dsh-cron-task-item { flex-wrap: wrap; gap: 10px; }
207
+ .dsh-cron-task-actions { margin-left: auto; }
208
+ .dsh-cron-history-list { max-height: 320px; }
209
+ }
210
+ @media (max-width: 640px) {
211
+ .dsh-cron-container { padding: 6px 8px 20px; }
212
+ .dsh-cron-top-bar { flex-wrap: wrap; gap: 8px; }
213
+ .dsh-cron-tabs { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 4px; }
214
+ .dsh-cron-tab { white-space: nowrap; }
215
+ .dsh-cron-stats-bar { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }
216
+ .dsh-cron-task-item { align-items: flex-start; padding: 12px; }
217
+ .dsh-cron-task-title { flex-wrap: wrap; row-gap: 4px; }
218
+ .dsh-cron-modal { padding: 14px; }
219
+ .dsh-cron-modal-foot { flex-direction: column-reverse; }
220
+ .dsh-cron-modal-foot > button { width: 100%; }
221
+ .dsh-cron-filter-panel { padding: 8px 10px; }
222
+ .dsh-cron-card { padding: 14px; }
223
+ /* 16px keeps iOS Safari from zooming the page when a field is focused. */
224
+ .dsh-cron-modal input, .dsh-cron-modal select, .dsh-cron-modal textarea,
225
+ .dsh-cron-card input, .dsh-cron-search-input, .dsh-cron-filter-field select { font-size: 16px; }
226
+ }