@jjlmoya/utils-chrono 1.5.0 → 1.6.0

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 (36) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +2 -0
  3. package/src/entries.ts +4 -1
  4. package/src/index.ts +1 -0
  5. package/src/tests/locale_completeness.test.ts +1 -1
  6. package/src/tests/tool_validation.test.ts +1 -1
  7. package/src/tool/service-interval-tracker/bibliography.astro +16 -0
  8. package/src/tool/service-interval-tracker/bibliography.ts +12 -0
  9. package/src/tool/service-interval-tracker/client.ts +233 -0
  10. package/src/tool/service-interval-tracker/component.astro +50 -0
  11. package/src/tool/service-interval-tracker/components/AddEditModal.astro +75 -0
  12. package/src/tool/service-interval-tracker/components/DashboardHeader.astro +14 -0
  13. package/src/tool/service-interval-tracker/components/EmptyState.astro +26 -0
  14. package/src/tool/service-interval-tracker/entry.ts +56 -0
  15. package/src/tool/service-interval-tracker/helpers.ts +82 -0
  16. package/src/tool/service-interval-tracker/i18n/de.ts +117 -0
  17. package/src/tool/service-interval-tracker/i18n/en.ts +170 -0
  18. package/src/tool/service-interval-tracker/i18n/es.ts +117 -0
  19. package/src/tool/service-interval-tracker/i18n/fr.ts +98 -0
  20. package/src/tool/service-interval-tracker/i18n/id.ts +89 -0
  21. package/src/tool/service-interval-tracker/i18n/it.ts +88 -0
  22. package/src/tool/service-interval-tracker/i18n/ja.ts +88 -0
  23. package/src/tool/service-interval-tracker/i18n/ko.ts +88 -0
  24. package/src/tool/service-interval-tracker/i18n/nl.ts +88 -0
  25. package/src/tool/service-interval-tracker/i18n/pl.ts +88 -0
  26. package/src/tool/service-interval-tracker/i18n/pt.ts +88 -0
  27. package/src/tool/service-interval-tracker/i18n/ru.ts +88 -0
  28. package/src/tool/service-interval-tracker/i18n/sv.ts +88 -0
  29. package/src/tool/service-interval-tracker/i18n/tr.ts +88 -0
  30. package/src/tool/service-interval-tracker/i18n/zh.ts +88 -0
  31. package/src/tool/service-interval-tracker/index.ts +11 -0
  32. package/src/tool/service-interval-tracker/renderer.ts +91 -0
  33. package/src/tool/service-interval-tracker/seo.astro +16 -0
  34. package/src/tool/service-interval-tracker/service-interval-tracker.css +767 -0
  35. package/src/tool/service-interval-tracker/utils.ts +58 -0
  36. package/src/tools.ts +2 -0
@@ -0,0 +1,767 @@
1
+ .svc {
2
+ width: 100%;
3
+ max-width: 1200px;
4
+ margin: 0 auto;
5
+ background: var(--bg-surface);
6
+ border: 1px solid var(--border-color);
7
+ border-radius: 1.5rem;
8
+ padding: 1.5rem;
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: 1.5rem;
12
+ box-shadow: var(--shadow-base);
13
+ box-sizing: border-box;
14
+ }
15
+
16
+ .svc-header-row {
17
+ display: flex;
18
+ align-items: flex-start;
19
+ justify-content: space-between;
20
+ gap: 1.5rem;
21
+ flex-wrap: wrap;
22
+ }
23
+
24
+ .svc-dashboard-header {
25
+ display: flex;
26
+ flex-direction: column;
27
+ gap: 0.5rem;
28
+ }
29
+
30
+ .svc-h {
31
+ font-size: 1.5rem;
32
+ font-weight: 800;
33
+ color: var(--text-base);
34
+ margin: 0;
35
+ letter-spacing: -0.03em;
36
+ background: linear-gradient(135deg, var(--text-base) 0%, color-mix(in srgb, var(--text-base) 70%, var(--accent)) 100%);
37
+ -webkit-background-clip: text;
38
+ -webkit-text-fill-color: transparent;
39
+ }
40
+
41
+ .svc-subtitle {
42
+ font-size: 0.75rem;
43
+ font-weight: 600;
44
+ text-transform: uppercase;
45
+ letter-spacing: 0.05em;
46
+ color: var(--text-base);
47
+ opacity: 0.4;
48
+ margin: 0;
49
+ }
50
+
51
+ .svc-add-btn-top {
52
+ display: inline-flex;
53
+ align-items: center;
54
+ gap: 0.5rem;
55
+ padding: 0.65rem 1.25rem;
56
+ border-radius: 0.75rem;
57
+ border: 1px solid var(--accent);
58
+ background: var(--accent);
59
+ color: var(--text-on-primary, #fff);
60
+ font-size: 0.8125rem;
61
+ font-weight: 700;
62
+ cursor: pointer;
63
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
64
+ box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 25%, transparent);
65
+ }
66
+
67
+ .svc-add-btn-top:hover {
68
+ transform: translateY(-2px);
69
+ box-shadow: 0 6px 16px color-mix(in srgb, var(--accent) 40%, transparent);
70
+ background: color-mix(in srgb, var(--accent) 90%, #fff);
71
+ }
72
+
73
+ .svc-add-btn-top:active {
74
+ transform: translateY(0);
75
+ }
76
+
77
+ .svc-stats-summary {
78
+ display: flex;
79
+ gap: 0.75rem;
80
+ flex-wrap: wrap;
81
+ margin-top: 0.5rem;
82
+ }
83
+
84
+ .svc-stat-card {
85
+ display: flex;
86
+ flex-direction: column;
87
+ padding: 0.5rem 1rem;
88
+ border-radius: 0.75rem;
89
+ border: 1px solid var(--border-color);
90
+ background: color-mix(in srgb, var(--bg-page) 60%, transparent);
91
+ min-width: 80px;
92
+ }
93
+
94
+ .svc-stat-val {
95
+ font-size: 1.25rem;
96
+ font-weight: 800;
97
+ color: var(--text-base);
98
+ line-height: 1.2;
99
+ }
100
+
101
+ .svc-stat-lbl {
102
+ font-size: 0.625rem;
103
+ font-weight: 700;
104
+ text-transform: uppercase;
105
+ letter-spacing: 0.05em;
106
+ color: var(--text-base);
107
+ opacity: 0.4;
108
+ }
109
+
110
+ .svc-stat-healthy {
111
+ border-color: color-mix(in srgb, var(--color-green, #10b981) 30%, var(--border-color));
112
+ background: color-mix(in srgb, var(--color-green, #10b981) 5%, var(--bg-surface));
113
+ }
114
+ .svc-stat-healthy .svc-stat-val {
115
+ color: var(--color-green, #10b981);
116
+ }
117
+
118
+ .svc-stat-due {
119
+ border-color: color-mix(in srgb, var(--color-amber, #f59e0b) 30%, var(--border-color));
120
+ background: color-mix(in srgb, var(--color-amber, #f59e0b) 5%, var(--bg-surface));
121
+ }
122
+ .svc-stat-due .svc-stat-val {
123
+ color: var(--color-amber, #f59e0b);
124
+ }
125
+
126
+ .svc-stat-overdue {
127
+ border-color: color-mix(in srgb, var(--color-red, #f43f5e) 30%, var(--border-color));
128
+ background: color-mix(in srgb, var(--color-red, #f43f5e) 5%, var(--bg-surface));
129
+ }
130
+ .svc-stat-overdue .svc-stat-val {
131
+ color: var(--color-red, #f43f5e);
132
+ }
133
+
134
+ .svc-body {
135
+ min-height: 200px;
136
+ }
137
+
138
+ .svc-empty {
139
+ display: flex;
140
+ flex-direction: column;
141
+ align-items: center;
142
+ justify-content: center;
143
+ gap: 1rem;
144
+ padding: 4rem 2rem;
145
+ text-align: center;
146
+ border: 1px dashed var(--border-color);
147
+ border-radius: 1.25rem;
148
+ background: color-mix(in srgb, var(--bg-page) 30%, var(--bg-surface));
149
+ }
150
+
151
+ .svc-empty-vis {
152
+ position: relative;
153
+ width: 90px;
154
+ height: 90px;
155
+ margin-bottom: 0.5rem;
156
+ display: flex;
157
+ align-items: center;
158
+ justify-content: center;
159
+ }
160
+
161
+ .svc-empty-glow {
162
+ position: absolute;
163
+ width: 60px;
164
+ height: 60px;
165
+ border-radius: 50%;
166
+ background: var(--accent);
167
+ filter: blur(24px);
168
+ opacity: 0.15;
169
+ }
170
+
171
+ .svc-empty-svg {
172
+ width: 100%;
173
+ height: 100%;
174
+ color: var(--text-base);
175
+ opacity: 0.65;
176
+ animation: svc-empty-pulse 4s infinite ease-in-out;
177
+ }
178
+
179
+ @keyframes svc-empty-pulse {
180
+ 0%, 100% {
181
+ transform: scale(1);
182
+ opacity: 0.65;
183
+ }
184
+ 50% {
185
+ transform: scale(1.05);
186
+ opacity: 0.85;
187
+ }
188
+ }
189
+
190
+ .svc-empty-title {
191
+ font-size: 1.25rem;
192
+ font-weight: 800;
193
+ color: var(--text-base);
194
+ letter-spacing: -0.02em;
195
+ margin: 0;
196
+ }
197
+
198
+ .svc-empty-desc {
199
+ font-size: 0.875rem;
200
+ color: var(--text-base);
201
+ opacity: 0.5;
202
+ max-width: 320px;
203
+ line-height: 1.5;
204
+ margin: 0;
205
+ }
206
+
207
+ .svc-empty-btn {
208
+ display: inline-flex;
209
+ align-items: center;
210
+ gap: 0.5rem;
211
+ padding: 0.65rem 1.25rem;
212
+ border: 1px solid var(--border-color);
213
+ border-radius: 0.75rem;
214
+ background: var(--bg-surface);
215
+ color: var(--text-base);
216
+ font-size: 0.8125rem;
217
+ font-weight: 700;
218
+ cursor: pointer;
219
+ transition: all 0.2s;
220
+ box-shadow: var(--shadow-base);
221
+ }
222
+
223
+ .svc-empty-btn:hover {
224
+ border-color: var(--accent);
225
+ color: var(--accent);
226
+ background: color-mix(in srgb, var(--accent) 4%, var(--bg-surface));
227
+ transform: translateY(-1px);
228
+ }
229
+
230
+ .svc-roster {
231
+ display: grid;
232
+ grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
233
+ gap: 1.25rem;
234
+ width: 100%;
235
+ }
236
+
237
+ .svc-card {
238
+ display: flex;
239
+ flex-direction: column;
240
+ gap: 1rem;
241
+ background: var(--bg-surface);
242
+ border: 1px solid var(--border-color);
243
+ border-radius: 1.25rem;
244
+ padding: 1.25rem;
245
+ cursor: pointer;
246
+ transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
247
+ position: relative;
248
+ overflow: hidden;
249
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
250
+ }
251
+
252
+ .svc-card:hover {
253
+ transform: translateY(-4px);
254
+ box-shadow: 0 12px 24px rgba(0, 0, 0, 0.08);
255
+ border-color: color-mix(in srgb, var(--text-base) 15%, var(--border-color));
256
+ }
257
+
258
+ .svc-card:focus-visible {
259
+ outline: none;
260
+ border-color: var(--accent);
261
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent);
262
+ }
263
+
264
+ .svc-card::before {
265
+ content: '';
266
+ position: absolute;
267
+ top: 0;
268
+ left: 0;
269
+ width: 100%;
270
+ height: 4px;
271
+ }
272
+
273
+ .svc-card-healthy::before { background: var(--color-green, #10b981); }
274
+ .svc-card-due::before { background: var(--color-amber, #f59e0b); }
275
+ .svc-card-overdue::before { background: var(--color-red, #f43f5e); }
276
+ .svc-card-unknown::before { background: var(--border-color); }
277
+
278
+ .svc-card-header {
279
+ display: flex;
280
+ align-items: center;
281
+ gap: 0.75rem;
282
+ position: relative;
283
+ }
284
+
285
+ .svc-card-icon-container {
286
+ width: 36px;
287
+ height: 36px;
288
+ border-radius: 0.5rem;
289
+ display: flex;
290
+ align-items: center;
291
+ justify-content: center;
292
+ color: var(--text-base);
293
+ background: color-mix(in srgb, var(--text-base) 8%, var(--bg-page));
294
+ flex-shrink: 0;
295
+ }
296
+
297
+ .svc-card-healthy .svc-card-icon-container {
298
+ color: var(--color-green, #10b981);
299
+ background: color-mix(in srgb, var(--color-green, #10b981) 8%, var(--bg-surface));
300
+ }
301
+
302
+ .svc-card-due .svc-card-icon-container {
303
+ color: var(--color-amber, #f59e0b);
304
+ background: color-mix(in srgb, var(--color-amber, #f59e0b) 8%, var(--bg-surface));
305
+ }
306
+
307
+ .svc-card-overdue .svc-card-icon-container {
308
+ color: var(--color-red, #f43f5e);
309
+ background: color-mix(in srgb, var(--color-red, #f43f5e) 8%, var(--bg-surface));
310
+ }
311
+
312
+ .svc-card-icon-container svg {
313
+ width: 20px;
314
+ height: 20px;
315
+ }
316
+
317
+ .svc-card-title-group {
318
+ display: flex;
319
+ flex-direction: column;
320
+ min-width: 0;
321
+ flex: 1;
322
+ }
323
+
324
+ .svc-card-name {
325
+ font-size: 0.9375rem;
326
+ font-weight: 700;
327
+ color: var(--text-base);
328
+ overflow: hidden;
329
+ text-overflow: ellipsis;
330
+ white-space: nowrap;
331
+ }
332
+
333
+ .svc-card-movement {
334
+ font-size: 0.6875rem;
335
+ font-weight: 700;
336
+ text-transform: uppercase;
337
+ letter-spacing: 0.05em;
338
+ color: var(--text-base);
339
+ opacity: 0.45;
340
+ margin-top: 0.1rem;
341
+ }
342
+
343
+ .svc-card-del {
344
+ background: none;
345
+ border: none;
346
+ color: var(--text-base);
347
+ opacity: 0.15;
348
+ cursor: pointer;
349
+ padding: 0.25rem;
350
+ line-height: 1;
351
+ display: flex;
352
+ align-items: center;
353
+ justify-content: center;
354
+ transition: all 0.2s ease;
355
+ border-radius: 0.35rem;
356
+ }
357
+
358
+ .svc-card:hover .svc-card-del:hover {
359
+ opacity: 1;
360
+ }
361
+
362
+ .svc-card-del:hover {
363
+ color: var(--color-red, #f43f5e);
364
+ background: color-mix(in srgb, var(--color-red, #f43f5e) 8%, transparent);
365
+ }
366
+
367
+ .svc-card-del svg {
368
+ width: 16px;
369
+ height: 16px;
370
+ }
371
+
372
+ .svc-card-progress-section {
373
+ display: flex;
374
+ flex-direction: column;
375
+ gap: 0.35rem;
376
+ }
377
+
378
+ .svc-card-progress-info {
379
+ display: flex;
380
+ align-items: center;
381
+ justify-content: space-between;
382
+ }
383
+
384
+ .svc-card-progress-pct {
385
+ font-size: 0.8125rem;
386
+ font-weight: 700;
387
+ font-variant-numeric: tabular-nums;
388
+ color: var(--text-base);
389
+ }
390
+
391
+ .svc-card-status-badge {
392
+ font-size: 0.6875rem;
393
+ font-weight: 700;
394
+ padding: 0.15rem 0.5rem;
395
+ border-radius: 0.5rem;
396
+ text-transform: uppercase;
397
+ letter-spacing: 0.02em;
398
+ }
399
+
400
+ .svc-badge-healthy {
401
+ background: color-mix(in srgb, var(--color-green, #10b981) 12%, transparent);
402
+ color: var(--color-green, #10b981);
403
+ }
404
+
405
+ .svc-badge-due {
406
+ background: color-mix(in srgb, var(--color-amber, #f59e0b) 12%, transparent);
407
+ color: var(--color-amber, #f59e0b);
408
+ }
409
+
410
+ .svc-badge-overdue {
411
+ background: color-mix(in srgb, var(--color-red, #f43f5e) 12%, transparent);
412
+ color: var(--color-red, #f43f5e);
413
+ }
414
+
415
+ .svc-badge-unknown {
416
+ background: color-mix(in srgb, var(--text-base) 8%, transparent);
417
+ color: var(--text-base);
418
+ opacity: 0.6;
419
+ }
420
+
421
+ .svc-card-progress-track {
422
+ height: 6px;
423
+ background: color-mix(in srgb, var(--text-base) 6%, var(--bg-page));
424
+ border-radius: 999px;
425
+ overflow: hidden;
426
+ }
427
+
428
+ .svc-card-progress-bar {
429
+ height: 100%;
430
+ border-radius: 999px;
431
+ transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
432
+ }
433
+
434
+ .svc-card-healthy .svc-card-progress-bar {
435
+ background: linear-gradient(90deg, color-mix(in srgb, var(--color-green, #10b981) 70%, transparent) 0%, var(--color-green, #10b981) 100%);
436
+ }
437
+
438
+ .svc-card-due .svc-card-progress-bar {
439
+ background: linear-gradient(90deg, color-mix(in srgb, var(--color-amber, #f59e0b) 70%, transparent) 0%, var(--color-amber, #f59e0b) 100%);
440
+ }
441
+
442
+ .svc-card-overdue .svc-card-progress-bar {
443
+ background: linear-gradient(90deg, color-mix(in srgb, var(--color-red, #f43f5e) 70%, transparent) 0%, var(--color-red, #f43f5e) 100%);
444
+ }
445
+
446
+ .svc-card-info-grid {
447
+ display: grid;
448
+ grid-template-columns: 1fr 1fr;
449
+ gap: 0.5rem;
450
+ border-top: 1px solid color-mix(in srgb, var(--border-color) 50%, transparent);
451
+ padding-top: 0.75rem;
452
+ }
453
+
454
+ .svc-card-info-item {
455
+ display: flex;
456
+ flex-direction: column;
457
+ }
458
+
459
+ .svc-card-info-lbl {
460
+ font-size: 0.625rem;
461
+ font-weight: 700;
462
+ text-transform: uppercase;
463
+ letter-spacing: 0.05em;
464
+ color: var(--text-base);
465
+ opacity: 0.4;
466
+ }
467
+
468
+ .svc-card-info-val {
469
+ font-size: 0.75rem;
470
+ font-weight: 600;
471
+ color: var(--text-base);
472
+ opacity: 0.85;
473
+ margin-top: 0.15rem;
474
+ }
475
+
476
+ .svc-card-add-placeholder {
477
+ display: flex;
478
+ align-items: center;
479
+ justify-content: center;
480
+ border: 2px dashed var(--border-color);
481
+ border-radius: 1.25rem;
482
+ background: transparent;
483
+ min-height: 180px;
484
+ cursor: pointer;
485
+ transition: all 0.25s ease;
486
+ box-shadow: none;
487
+ }
488
+
489
+ .svc-card-add-placeholder::before {
490
+ display: none;
491
+ }
492
+
493
+ .svc-card-add-placeholder:hover {
494
+ border-color: var(--accent);
495
+ background: color-mix(in srgb, var(--accent) 3%, transparent);
496
+ transform: translateY(-4px);
497
+ }
498
+
499
+ .svc-card-add-inner {
500
+ display: flex;
501
+ flex-direction: column;
502
+ align-items: center;
503
+ gap: 0.5rem;
504
+ color: var(--text-base);
505
+ opacity: 0.5;
506
+ transition: opacity 0.2s;
507
+ }
508
+
509
+ .svc-card-add-placeholder:hover .svc-card-add-inner {
510
+ opacity: 0.85;
511
+ color: var(--accent);
512
+ }
513
+
514
+ .svc-card-add-icon {
515
+ width: 40px;
516
+ height: 40px;
517
+ border-radius: 50%;
518
+ border: 1px solid currentcolor;
519
+ display: flex;
520
+ align-items: center;
521
+ justify-content: center;
522
+ transition: transform 0.25s ease;
523
+ }
524
+
525
+ .svc-card-add-placeholder:hover .svc-card-add-icon {
526
+ transform: scale(1.1) rotate(90deg);
527
+ }
528
+
529
+ .svc-card-add-icon svg {
530
+ width: 20px;
531
+ height: 20px;
532
+ }
533
+
534
+ .svc-card-add-text {
535
+ font-size: 0.8125rem;
536
+ font-weight: 700;
537
+ }
538
+
539
+ .svc-overlay {
540
+ position: fixed;
541
+ inset: 0;
542
+ z-index: 999;
543
+ display: flex;
544
+ align-items: center;
545
+ justify-content: center;
546
+ background: rgba(0, 0, 0, 0.45);
547
+ backdrop-filter: blur(16px);
548
+ opacity: 0;
549
+ pointer-events: none;
550
+ transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
551
+ padding: 1rem;
552
+ }
553
+
554
+ .svc-overlay.open {
555
+ opacity: 1;
556
+ pointer-events: auto;
557
+ }
558
+
559
+ .svc-modal {
560
+ width: 100%;
561
+ max-width: 380px;
562
+ background: var(--bg-surface);
563
+ border: 1px solid var(--border-color);
564
+ border-radius: 1.5rem;
565
+ padding: 1.5rem;
566
+ display: flex;
567
+ flex-direction: column;
568
+ gap: 1.25rem;
569
+ box-shadow: 0 20px 50px rgba(0, 0, 0, 0.3);
570
+ transform: scale(0.95) translateY(10px);
571
+ transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
572
+ }
573
+
574
+ .svc-overlay.open .svc-modal {
575
+ transform: scale(1) translateY(0);
576
+ }
577
+
578
+ .svc-modal-top {
579
+ display: flex;
580
+ align-items: center;
581
+ justify-content: space-between;
582
+ }
583
+
584
+ .svc-modal-title {
585
+ font-size: 1.125rem;
586
+ font-weight: 800;
587
+ color: var(--text-base);
588
+ letter-spacing: -0.02em;
589
+ }
590
+
591
+ .svc-modal-x {
592
+ background: none;
593
+ border: none;
594
+ color: var(--text-base);
595
+ opacity: 0.3;
596
+ cursor: pointer;
597
+ padding: 0.25rem;
598
+ display: flex;
599
+ align-items: center;
600
+ justify-content: center;
601
+ transition: all 0.2s;
602
+ border-radius: 50%;
603
+ }
604
+
605
+ .svc-modal-x:hover {
606
+ opacity: 0.8;
607
+ background: color-mix(in srgb, var(--text-base) 8%, transparent);
608
+ }
609
+
610
+ .svc-modal-x svg {
611
+ width: 18px;
612
+ height: 18px;
613
+ }
614
+
615
+ .svc-modal-body {
616
+ display: flex;
617
+ flex-direction: column;
618
+ gap: 1rem;
619
+ }
620
+
621
+ .svc-field {
622
+ display: flex;
623
+ flex-direction: column;
624
+ gap: 0.35rem;
625
+ }
626
+
627
+ .svc-label {
628
+ font-size: 0.6875rem;
629
+ font-weight: 700;
630
+ text-transform: uppercase;
631
+ letter-spacing: 0.05em;
632
+ color: var(--text-base);
633
+ opacity: 0.5;
634
+ }
635
+
636
+ .svc-input {
637
+ padding: 0.65rem 0.85rem;
638
+ border: 1px solid var(--border-color);
639
+ border-radius: 0.75rem;
640
+ background: var(--bg-page);
641
+ color: var(--text-base);
642
+ font-size: 0.875rem;
643
+ font-weight: 500;
644
+ box-sizing: border-box;
645
+ width: 100%;
646
+ transition: all 0.2s;
647
+ }
648
+
649
+ .svc-input:focus {
650
+ outline: none;
651
+ border-color: var(--accent);
652
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent);
653
+ background: var(--bg-surface);
654
+ }
655
+
656
+ .svc-select-wrapper {
657
+ position: relative;
658
+ width: 100%;
659
+ }
660
+
661
+ select.svc-input {
662
+ appearance: none;
663
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' fill='none' stroke='%23888888' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1l4 4 4-4'/%3E%3C/svg%3E");
664
+ background-repeat: no-repeat;
665
+ background-position: right 0.85rem center;
666
+ padding-right: 2.2rem;
667
+ }
668
+
669
+ .svc-check {
670
+ display: inline-flex;
671
+ align-items: center;
672
+ gap: 0.45rem;
673
+ font-size: 0.75rem;
674
+ font-weight: 600;
675
+ color: var(--text-base);
676
+ opacity: 0.6;
677
+ cursor: pointer;
678
+ margin-top: 0.25rem;
679
+ user-select: none;
680
+ }
681
+
682
+ .svc-checkbox {
683
+ appearance: none;
684
+ width: 14px;
685
+ height: 14px;
686
+ border: 1px solid var(--border-color);
687
+ border-radius: 0.25rem;
688
+ background: var(--bg-page);
689
+ cursor: pointer;
690
+ position: relative;
691
+ transition: all 0.15s;
692
+ }
693
+
694
+ .svc-checkbox:checked {
695
+ background: var(--accent);
696
+ border-color: var(--accent);
697
+ }
698
+
699
+ .svc-checkbox:checked::after {
700
+ content: '';
701
+ position: absolute;
702
+ width: 4px;
703
+ height: 7px;
704
+ border: solid #fff;
705
+ border-width: 0 1.5px 1.5px 0;
706
+ top: 1.5px;
707
+ left: 4.5px;
708
+ transform: rotate(45deg);
709
+ }
710
+
711
+ .svc-modal-err {
712
+ font-size: 0.75rem;
713
+ font-weight: 600;
714
+ color: var(--color-red, #f43f5e);
715
+ min-height: 1.2em;
716
+ }
717
+
718
+ .svc-modal-acts {
719
+ display: flex;
720
+ gap: 0.75rem;
721
+ justify-content: flex-end;
722
+ margin-top: 0.5rem;
723
+ }
724
+
725
+ .svc-btn {
726
+ padding: 0.65rem 1.25rem;
727
+ border-radius: 0.75rem;
728
+ font-size: 0.8125rem;
729
+ font-weight: 700;
730
+ cursor: pointer;
731
+ transition: all 0.2s;
732
+ border: 1px solid var(--border-color);
733
+ background: var(--bg-page);
734
+ color: var(--text-base);
735
+ }
736
+
737
+ .svc-btn-sec:hover {
738
+ background: var(--bg-surface);
739
+ border-color: color-mix(in srgb, var(--text-base) 15%, var(--border-color));
740
+ }
741
+
742
+ .svc-btn-pri {
743
+ background: var(--accent);
744
+ color: var(--text-on-primary, #fff);
745
+ border-color: var(--accent);
746
+ box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 15%, transparent);
747
+ }
748
+
749
+ .svc-btn-pri:hover {
750
+ background: color-mix(in srgb, var(--accent) 90%, #fff);
751
+ box-shadow: 0 4px 16px color-mix(in srgb, var(--accent) 25%, transparent);
752
+ transform: translateY(-1px);
753
+ }
754
+
755
+ .svc-btn-pri:active {
756
+ transform: translateY(0);
757
+ }
758
+
759
+ @media (max-width: 640px) {
760
+ .svc-header-row {
761
+ flex-direction: column;
762
+ align-items: stretch;
763
+ }
764
+ .svc-add-btn-top {
765
+ justify-content: center;
766
+ }
767
+ }