@sethlivingston/cathode 0.1.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.
@@ -0,0 +1,1388 @@
1
+ /*! cathode v0.1.0 — dark-only design system · github.com/sethlivingston/cathode · MIT (fonts: IBM Plex, OFL-1.1) */
2
+
3
+ /* cathode/reset.css — minimal modern reset (subset of modern-normalize, MIT) */
4
+
5
+ *,
6
+ *::before,
7
+ *::after {
8
+ box-sizing: border-box;
9
+ }
10
+
11
+ html {
12
+ -webkit-text-size-adjust: 100%;
13
+ tab-size: 2;
14
+ }
15
+
16
+ body {
17
+ margin: 0;
18
+ }
19
+
20
+ b,
21
+ strong {
22
+ font-weight: 600;
23
+ }
24
+
25
+ code,
26
+ kbd,
27
+ samp,
28
+ pre {
29
+ font-size: 1em;
30
+ }
31
+
32
+ small {
33
+ font-size: 80%;
34
+ }
35
+
36
+ sub,
37
+ sup {
38
+ font-size: 75%;
39
+ line-height: 0;
40
+ position: relative;
41
+ vertical-align: baseline;
42
+ }
43
+
44
+ sub {
45
+ bottom: -0.25em;
46
+ }
47
+
48
+ sup {
49
+ top: -0.5em;
50
+ }
51
+
52
+ table {
53
+ border-color: currentcolor;
54
+ border-collapse: collapse;
55
+ }
56
+
57
+ button,
58
+ input,
59
+ optgroup,
60
+ select,
61
+ textarea {
62
+ font: inherit;
63
+ color: inherit;
64
+ margin: 0;
65
+ }
66
+
67
+ button,
68
+ select {
69
+ text-transform: none;
70
+ }
71
+
72
+ legend {
73
+ padding: 0;
74
+ }
75
+
76
+ progress {
77
+ vertical-align: baseline;
78
+ }
79
+
80
+ summary {
81
+ display: list-item;
82
+ }
83
+
84
+ img,
85
+ svg,
86
+ video,
87
+ canvas {
88
+ display: block;
89
+ max-width: 100%;
90
+ }
91
+
92
+ /* cathode/fonts.css — self-hosted IBM Plex (OFL-1.1), latin subset */
93
+
94
+ @font-face {
95
+ font-family: "IBM Plex Sans";
96
+ font-style: normal;
97
+ font-weight: 400;
98
+ font-display: swap;
99
+ src: url("../fonts/ibm-plex-sans-latin-400-normal.woff2") format("woff2");
100
+ }
101
+
102
+ @font-face {
103
+ font-family: "IBM Plex Sans";
104
+ font-style: italic;
105
+ font-weight: 400;
106
+ font-display: swap;
107
+ src: url("../fonts/ibm-plex-sans-latin-400-italic.woff2") format("woff2");
108
+ }
109
+
110
+ @font-face {
111
+ font-family: "IBM Plex Sans";
112
+ font-style: normal;
113
+ font-weight: 500;
114
+ font-display: swap;
115
+ src: url("../fonts/ibm-plex-sans-latin-500-normal.woff2") format("woff2");
116
+ }
117
+
118
+ @font-face {
119
+ font-family: "IBM Plex Sans";
120
+ font-style: normal;
121
+ font-weight: 600;
122
+ font-display: swap;
123
+ src: url("../fonts/ibm-plex-sans-latin-600-normal.woff2") format("woff2");
124
+ }
125
+
126
+ @font-face {
127
+ font-family: "IBM Plex Sans";
128
+ font-style: normal;
129
+ font-weight: 700;
130
+ font-display: swap;
131
+ src: url("../fonts/ibm-plex-sans-latin-700-normal.woff2") format("woff2");
132
+ }
133
+
134
+ @font-face {
135
+ font-family: "IBM Plex Mono";
136
+ font-style: normal;
137
+ font-weight: 400;
138
+ font-display: swap;
139
+ src: url("../fonts/ibm-plex-mono-latin-400-normal.woff2") format("woff2");
140
+ }
141
+
142
+ @font-face {
143
+ font-family: "IBM Plex Mono";
144
+ font-style: normal;
145
+ font-weight: 500;
146
+ font-display: swap;
147
+ src: url("../fonts/ibm-plex-mono-latin-500-normal.woff2") format("woff2");
148
+ }
149
+
150
+ @font-face {
151
+ font-family: "IBM Plex Mono";
152
+ font-style: normal;
153
+ font-weight: 600;
154
+ font-display: swap;
155
+ src: url("../fonts/ibm-plex-mono-latin-600-normal.woff2") format("woff2");
156
+ }
157
+
158
+ /* cathode/tokens.css — design tokens. The single source of truth.
159
+ Rule for humans and agents alike: style with these variables, never raw values. */
160
+
161
+ :root {
162
+ color-scheme: dark;
163
+
164
+ /* ── Surfaces ─────────────────────────────────────────────
165
+ Elevation is expressed by border brightness, not shadows.
166
+ bg-0 page · bg-1 card · bg-2 control resting · bg-3 hover fill */
167
+ --ct-bg-0: #0b0b10;
168
+ --ct-bg-1: #121219;
169
+ --ct-bg-2: #1a1a23;
170
+ --ct-bg-3: #23232e;
171
+
172
+ --ct-border: #28282f;
173
+ --ct-border-bright: #41414c;
174
+
175
+ /* ── Text ───────────────────────────────────────────────── */
176
+ --ct-text: #e9e9f1;
177
+ --ct-text-dim: #a2a2b3;
178
+ --ct-text-faint: #6a6a78;
179
+
180
+ /* ── Interactive accent — arcade magenta ────────────────── */
181
+ --ct-accent: #c95cf2;
182
+ --ct-accent-bright: #de8bff;
183
+ --ct-accent-glow: rgba(201, 92, 242, 0.4);
184
+ --ct-on-accent: #150420;
185
+
186
+ /* ── Arcade semantic palette ──────────────────────────────
187
+ Status hues — fixed meanings, do not repurpose: */
188
+ --ct-green: #4ae07a; /* success / pass / online */
189
+ --ct-red: #ff5d5d; /* danger / fail / destructive */
190
+ --ct-amber: #ffb454; /* warning / pending */
191
+ --ct-cyan: #4dd8ff; /* info / neutral-active */
192
+
193
+ /* Categorical hues — free for tagging/series, no fixed meaning: */
194
+ --ct-orange: #ff8d4d;
195
+ --ct-lime: #b5e853;
196
+ --ct-pink: #ff6fb0;
197
+ --ct-indigo: #8a93ff;
198
+
199
+ /* ── Typography ───────────────────────────────────────────
200
+ Sans for prose. Mono for data: IDs, counts, timestamps,
201
+ code, badges, table numerics. */
202
+ --ct-font-sans: "IBM Plex Sans", system-ui, -apple-system, sans-serif;
203
+ --ct-font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", monospace;
204
+
205
+ --ct-text-xs: 0.75rem; /* 12px — fine print, table headers */
206
+ --ct-text-sm: 0.8125rem; /* 13px — mono data, badges, captions */
207
+ --ct-text-md: 0.9375rem; /* 15px — body default */
208
+ --ct-text-lg: 1.0625rem; /* 17px — emphasized body, h4 */
209
+ --ct-text-xl: 1.3125rem; /* 21px — h3 */
210
+ --ct-text-2xl: 1.625rem; /* 26px — h2 */
211
+ --ct-text-3xl: 2rem; /* 32px — h1 */
212
+
213
+ --ct-leading: 1.55;
214
+ --ct-leading-tight: 1.25;
215
+ --ct-tracking-mono: 0.04em; /* uppercase mono labels */
216
+
217
+ /* ── Space — 4px grid. Compose only from these. ─────────── */
218
+ --ct-space-1: 4px;
219
+ --ct-space-2: 8px;
220
+ --ct-space-3: 12px;
221
+ --ct-space-4: 16px;
222
+ --ct-space-5: 24px;
223
+ --ct-space-6: 32px;
224
+ --ct-space-7: 48px;
225
+ --ct-space-8: 64px;
226
+
227
+ /* ── Shape ──────────────────────────────────────────────── */
228
+ --ct-radius: 2px;
229
+
230
+ /* ── Motion ─────────────────────────────────────────────── */
231
+ --ct-ease: cubic-bezier(0.2, 0, 0.2, 1);
232
+ --ct-quick: 120ms;
233
+ --ct-slow: 240ms;
234
+
235
+ /* ── Layers ─────────────────────────────────────────────── */
236
+ --ct-z-nav: 100;
237
+ --ct-z-modal: 200;
238
+ --ct-z-toast: 300;
239
+ --ct-z-tooltip: 400;
240
+ }
241
+
242
+ @media (prefers-reduced-motion: reduce) {
243
+ :root {
244
+ --ct-quick: 0ms;
245
+ --ct-slow: 0ms;
246
+ }
247
+ }
248
+
249
+ /* cathode/base.css — element defaults on the dark base */
250
+
251
+ html {
252
+ background: var(--ct-bg-0);
253
+ }
254
+
255
+ body {
256
+ font-family: var(--ct-font-sans);
257
+ font-size: var(--ct-text-md);
258
+ line-height: var(--ct-leading);
259
+ color: var(--ct-text);
260
+ background: var(--ct-bg-0);
261
+ -webkit-font-smoothing: antialiased;
262
+ }
263
+
264
+ ::selection {
265
+ background: var(--ct-accent);
266
+ color: var(--ct-on-accent);
267
+ }
268
+
269
+ /* Headings — tight, confident, no decoration */
270
+ h1,
271
+ h2,
272
+ h3,
273
+ h4,
274
+ h5,
275
+ h6 {
276
+ margin: 0 0 var(--ct-space-3);
277
+ line-height: var(--ct-leading-tight);
278
+ font-weight: 600;
279
+ letter-spacing: -0.01em;
280
+ }
281
+
282
+ h1 { font-size: var(--ct-text-3xl); }
283
+ h2 { font-size: var(--ct-text-2xl); }
284
+ h3 { font-size: var(--ct-text-xl); }
285
+ h4 { font-size: var(--ct-text-lg); }
286
+ h5,
287
+ h6 { font-size: var(--ct-text-md); }
288
+
289
+ p {
290
+ margin: 0 0 var(--ct-space-3);
291
+ }
292
+
293
+ p:last-child {
294
+ margin-bottom: 0;
295
+ }
296
+
297
+ a {
298
+ color: var(--ct-accent);
299
+ text-decoration: none;
300
+ transition: color var(--ct-quick) var(--ct-ease);
301
+ }
302
+
303
+ a:hover {
304
+ color: var(--ct-accent-bright);
305
+ text-decoration: underline;
306
+ text-underline-offset: 3px;
307
+ }
308
+
309
+ hr {
310
+ border: 0;
311
+ border-top: 1px solid var(--ct-border);
312
+ margin: var(--ct-space-5) 0;
313
+ }
314
+
315
+ ul,
316
+ ol {
317
+ margin: 0 0 var(--ct-space-3);
318
+ padding-left: var(--ct-space-5);
319
+ }
320
+
321
+ blockquote {
322
+ margin: 0 0 var(--ct-space-3);
323
+ padding: var(--ct-space-2) var(--ct-space-4);
324
+ border-left: 2px solid var(--ct-accent);
325
+ color: var(--ct-text-dim);
326
+ }
327
+
328
+ /* Code & data — the mono wink */
329
+ code,
330
+ kbd,
331
+ samp,
332
+ pre {
333
+ font-family: var(--ct-font-mono);
334
+ font-size: var(--ct-text-sm);
335
+ }
336
+
337
+ code,
338
+ samp {
339
+ background: var(--ct-bg-2);
340
+ border: 1px solid var(--ct-border);
341
+ border-radius: var(--ct-radius);
342
+ padding: 1px 5px;
343
+ }
344
+
345
+ pre {
346
+ background: var(--ct-bg-1);
347
+ border: 1px solid var(--ct-border);
348
+ border-radius: var(--ct-radius);
349
+ padding: var(--ct-space-4);
350
+ overflow-x: auto;
351
+ margin: 0 0 var(--ct-space-3);
352
+ }
353
+
354
+ pre code {
355
+ background: none;
356
+ border: 0;
357
+ padding: 0;
358
+ }
359
+
360
+ kbd {
361
+ background: var(--ct-bg-3);
362
+ border: 1px solid var(--ct-border-bright);
363
+ border-bottom-width: 2px;
364
+ border-radius: var(--ct-radius);
365
+ padding: 1px 6px;
366
+ font-size: var(--ct-text-xs);
367
+ }
368
+
369
+ /* .ct-data — apply to any inline run of IDs, counts, timestamps */
370
+ .ct-data {
371
+ font-family: var(--ct-font-mono);
372
+ font-size: var(--ct-text-sm);
373
+ font-variant-numeric: tabular-nums;
374
+ }
375
+
376
+ /* .ct-label-mono — uppercase mono micro-label (section headers, table heads) */
377
+ .ct-label-mono {
378
+ font-family: var(--ct-font-mono);
379
+ font-size: var(--ct-text-xs);
380
+ font-weight: 600;
381
+ letter-spacing: var(--ct-tracking-mono);
382
+ text-transform: uppercase;
383
+ color: var(--ct-text-faint);
384
+ }
385
+
386
+ /* Muted text helpers */
387
+ .ct-dim { color: var(--ct-text-dim); }
388
+ .ct-faint { color: var(--ct-text-faint); }
389
+
390
+ /* Focus — one ring to rule them all */
391
+ :focus-visible {
392
+ outline: 2px solid var(--ct-accent-glow);
393
+ outline-offset: 1px;
394
+ }
395
+
396
+ /* Scrollbars — quiet, square */
397
+ * {
398
+ scrollbar-width: thin;
399
+ scrollbar-color: var(--ct-border-bright) transparent;
400
+ }
401
+
402
+ *::-webkit-scrollbar {
403
+ width: 10px;
404
+ height: 10px;
405
+ }
406
+
407
+ *::-webkit-scrollbar-thumb {
408
+ background: var(--ct-border-bright);
409
+ border: 2px solid var(--ct-bg-0);
410
+ }
411
+
412
+ *::-webkit-scrollbar-track {
413
+ background: transparent;
414
+ }
415
+
416
+ /* cathode/layout.css — app shell and composition helpers */
417
+
418
+ /* App shell: navbar on top, sidebar + main below
419
+ <body class="ct-shell">
420
+ <nav class="ct-navbar">…</nav>
421
+ <aside class="ct-sidebar">…</aside>
422
+ <main class="ct-main">…</main>
423
+ </body> */
424
+ .ct-shell {
425
+ display: grid;
426
+ grid-template-columns: auto 1fr;
427
+ grid-template-rows: auto 1fr;
428
+ grid-template-areas:
429
+ "nav nav"
430
+ "side main";
431
+ min-height: 100vh;
432
+ }
433
+
434
+ .ct-shell > .ct-navbar { grid-area: nav; }
435
+ .ct-shell > .ct-sidebar { grid-area: side; }
436
+ .ct-shell > .ct-main { grid-area: main; }
437
+
438
+ .ct-main {
439
+ padding: var(--ct-space-5);
440
+ overflow-y: auto;
441
+ min-width: 0;
442
+ }
443
+
444
+ /* Centered content page (docs, marketing, settings) */
445
+ .ct-container {
446
+ width: min(720px, 100% - var(--ct-space-6));
447
+ margin-inline: auto;
448
+ }
449
+
450
+ .ct-container--wide {
451
+ width: min(1100px, 100% - var(--ct-space-6));
452
+ }
453
+
454
+ /* Vertical rhythm */
455
+ .ct-stack {
456
+ display: flex;
457
+ flex-direction: column;
458
+ gap: var(--ct-space-4);
459
+ }
460
+
461
+ .ct-stack--tight { gap: var(--ct-space-2); }
462
+ .ct-stack--loose { gap: var(--ct-space-6); }
463
+
464
+ /* Horizontal cluster, wraps */
465
+ .ct-cluster {
466
+ display: flex;
467
+ flex-wrap: wrap;
468
+ align-items: center;
469
+ gap: var(--ct-space-2);
470
+ }
471
+
472
+ /* Responsive card grid */
473
+ .ct-grid {
474
+ display: grid;
475
+ grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
476
+ gap: var(--ct-space-4);
477
+ }
478
+
479
+ /* Mobile: sidebar collapses under navbar */
480
+ @media (max-width: 720px) {
481
+ .ct-shell {
482
+ grid-template-columns: 1fr;
483
+ grid-template-areas:
484
+ "nav"
485
+ "main";
486
+ }
487
+
488
+ .ct-shell > .ct-sidebar {
489
+ display: none;
490
+ }
491
+ }
492
+
493
+ /* cathode/button.css */
494
+
495
+ .ct-button {
496
+ display: inline-flex;
497
+ align-items: center;
498
+ justify-content: center;
499
+ gap: var(--ct-space-2);
500
+ font-family: var(--ct-font-sans);
501
+ font-size: var(--ct-text-md);
502
+ font-weight: 500;
503
+ line-height: 1;
504
+ color: var(--ct-text);
505
+ background: var(--ct-bg-2);
506
+ border: 1px solid var(--ct-border);
507
+ border-radius: var(--ct-radius);
508
+ padding: var(--ct-space-2) var(--ct-space-4);
509
+ min-height: 36px;
510
+ cursor: pointer;
511
+ user-select: none;
512
+ white-space: nowrap;
513
+ transition:
514
+ border-color var(--ct-quick) var(--ct-ease),
515
+ background var(--ct-quick) var(--ct-ease),
516
+ color var(--ct-quick) var(--ct-ease);
517
+ }
518
+
519
+ .ct-button:hover {
520
+ border-color: var(--ct-border-bright);
521
+ background: var(--ct-bg-3);
522
+ }
523
+
524
+ .ct-button:active {
525
+ transform: translateY(1px);
526
+ }
527
+
528
+ .ct-button:disabled {
529
+ opacity: 0.45;
530
+ cursor: not-allowed;
531
+ transform: none;
532
+ }
533
+
534
+ /* Primary — the one magenta action per view */
535
+ .ct-button--primary {
536
+ background: var(--ct-accent);
537
+ border-color: var(--ct-accent);
538
+ color: var(--ct-on-accent);
539
+ font-weight: 600;
540
+ }
541
+
542
+ .ct-button--primary:hover {
543
+ background: var(--ct-accent-bright);
544
+ border-color: var(--ct-accent-bright);
545
+ }
546
+
547
+ /* Danger — destructive actions only */
548
+ .ct-button--danger {
549
+ color: var(--ct-red);
550
+ border-color: color-mix(in srgb, var(--ct-red) 40%, transparent);
551
+ }
552
+
553
+ .ct-button--danger:hover {
554
+ background: color-mix(in srgb, var(--ct-red) 12%, transparent);
555
+ border-color: var(--ct-red);
556
+ }
557
+
558
+ /* Ghost — toolbar/inline actions, no box until hover */
559
+ .ct-button--ghost {
560
+ background: transparent;
561
+ border-color: transparent;
562
+ color: var(--ct-text-dim);
563
+ }
564
+
565
+ .ct-button--ghost:hover {
566
+ background: var(--ct-bg-2);
567
+ border-color: var(--ct-border);
568
+ color: var(--ct-text);
569
+ }
570
+
571
+ /* Sizes */
572
+ .ct-button--sm {
573
+ font-size: var(--ct-text-sm);
574
+ padding: var(--ct-space-1) var(--ct-space-3);
575
+ min-height: 28px;
576
+ }
577
+
578
+ .ct-button--lg {
579
+ font-size: var(--ct-text-lg);
580
+ padding: var(--ct-space-3) var(--ct-space-5);
581
+ min-height: 44px;
582
+ }
583
+
584
+ /* Icon-only — square */
585
+ .ct-button--icon {
586
+ padding: var(--ct-space-2);
587
+ width: 36px;
588
+ }
589
+
590
+ .ct-button--icon.ct-button--sm {
591
+ width: 28px;
592
+ padding: var(--ct-space-1);
593
+ }
594
+
595
+ /* Button row */
596
+ .ct-button-group {
597
+ display: inline-flex;
598
+ gap: var(--ct-space-2);
599
+ }
600
+
601
+ /* cathode/forms.css — fields, inputs, selects, checks, switch */
602
+
603
+ .ct-field {
604
+ display: flex;
605
+ flex-direction: column;
606
+ gap: var(--ct-space-2);
607
+ margin-bottom: var(--ct-space-4);
608
+ }
609
+
610
+ .ct-label {
611
+ font-size: var(--ct-text-sm);
612
+ font-weight: 500;
613
+ color: var(--ct-text-dim);
614
+ }
615
+
616
+ .ct-label--required::after {
617
+ content: " *";
618
+ color: var(--ct-red);
619
+ }
620
+
621
+ .ct-input,
622
+ .ct-select,
623
+ .ct-textarea {
624
+ font-family: var(--ct-font-sans);
625
+ font-size: var(--ct-text-md);
626
+ color: var(--ct-text);
627
+ background: var(--ct-bg-1);
628
+ border: 1px solid var(--ct-border);
629
+ border-radius: var(--ct-radius);
630
+ padding: var(--ct-space-2) var(--ct-space-3);
631
+ min-height: 36px;
632
+ width: 100%;
633
+ transition: border-color var(--ct-quick) var(--ct-ease);
634
+ }
635
+
636
+ .ct-input:hover,
637
+ .ct-select:hover,
638
+ .ct-textarea:hover {
639
+ border-color: var(--ct-border-bright);
640
+ }
641
+
642
+ .ct-input:focus,
643
+ .ct-select:focus,
644
+ .ct-textarea:focus {
645
+ outline: none;
646
+ border-color: var(--ct-accent);
647
+ box-shadow: 0 0 0 2px var(--ct-accent-glow);
648
+ }
649
+
650
+ .ct-input::placeholder,
651
+ .ct-textarea::placeholder {
652
+ color: var(--ct-text-faint);
653
+ }
654
+
655
+ /* Mono input — for IDs, tokens, code-like values */
656
+ .ct-input--mono {
657
+ font-family: var(--ct-font-mono);
658
+ font-size: var(--ct-text-sm);
659
+ }
660
+
661
+ .ct-textarea {
662
+ min-height: 96px;
663
+ resize: vertical;
664
+ line-height: var(--ct-leading);
665
+ }
666
+
667
+ .ct-select {
668
+ appearance: none;
669
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5L6 8l3.5-3.5' fill='none' stroke='%23a2a2b3' stroke-width='1.5'/%3E%3C/svg%3E");
670
+ background-repeat: no-repeat;
671
+ background-position: right var(--ct-space-3) center;
672
+ padding-right: var(--ct-space-6);
673
+ cursor: pointer;
674
+ }
675
+
676
+ /* Validation */
677
+ .ct-input[aria-invalid="true"],
678
+ .ct-select[aria-invalid="true"],
679
+ .ct-textarea[aria-invalid="true"] {
680
+ border-color: var(--ct-red);
681
+ }
682
+
683
+ .ct-input[aria-invalid="true"]:focus,
684
+ .ct-textarea[aria-invalid="true"]:focus {
685
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--ct-red) 40%, transparent);
686
+ }
687
+
688
+ .ct-help {
689
+ font-size: var(--ct-text-sm);
690
+ color: var(--ct-text-faint);
691
+ }
692
+
693
+ .ct-error {
694
+ font-size: var(--ct-text-sm);
695
+ color: var(--ct-red);
696
+ }
697
+
698
+ /* Checkbox & radio — square pixels, round dots */
699
+ .ct-check,
700
+ .ct-radio {
701
+ display: inline-flex;
702
+ align-items: center;
703
+ gap: var(--ct-space-2);
704
+ font-size: var(--ct-text-md);
705
+ cursor: pointer;
706
+ user-select: none;
707
+ }
708
+
709
+ .ct-check input,
710
+ .ct-radio input {
711
+ appearance: none;
712
+ width: 16px;
713
+ height: 16px;
714
+ margin: 0;
715
+ background: var(--ct-bg-1);
716
+ border: 1px solid var(--ct-border-bright);
717
+ cursor: pointer;
718
+ flex-shrink: 0;
719
+ transition:
720
+ background var(--ct-quick) var(--ct-ease),
721
+ border-color var(--ct-quick) var(--ct-ease);
722
+ }
723
+
724
+ .ct-check input {
725
+ border-radius: var(--ct-radius);
726
+ }
727
+
728
+ .ct-radio input {
729
+ border-radius: 50%;
730
+ }
731
+
732
+ .ct-check input:checked,
733
+ .ct-radio input:checked {
734
+ background: var(--ct-accent);
735
+ border-color: var(--ct-accent);
736
+ }
737
+
738
+ .ct-check input:checked {
739
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'%3E%3Cpath d='M1.5 5.5l2.5 2.5 4.5-5.5' fill='none' stroke='%23150420' stroke-width='2'/%3E%3C/svg%3E");
740
+ background-repeat: no-repeat;
741
+ background-position: center;
742
+ }
743
+
744
+ .ct-radio input:checked {
745
+ box-shadow: inset 0 0 0 3px var(--ct-bg-1);
746
+ }
747
+
748
+ /* Switch */
749
+ .ct-switch {
750
+ display: inline-flex;
751
+ align-items: center;
752
+ gap: var(--ct-space-2);
753
+ font-size: var(--ct-text-md);
754
+ cursor: pointer;
755
+ user-select: none;
756
+ }
757
+
758
+ .ct-switch input {
759
+ appearance: none;
760
+ width: 32px;
761
+ height: 18px;
762
+ margin: 0;
763
+ background: var(--ct-bg-3);
764
+ border: 1px solid var(--ct-border-bright);
765
+ border-radius: var(--ct-radius);
766
+ position: relative;
767
+ cursor: pointer;
768
+ flex-shrink: 0;
769
+ transition: background var(--ct-quick) var(--ct-ease);
770
+ }
771
+
772
+ .ct-switch input::before {
773
+ content: "";
774
+ position: absolute;
775
+ top: 2px;
776
+ left: 2px;
777
+ width: 12px;
778
+ height: 12px;
779
+ background: var(--ct-text-dim);
780
+ border-radius: var(--ct-radius);
781
+ transition:
782
+ translate var(--ct-quick) var(--ct-ease),
783
+ background var(--ct-quick) var(--ct-ease);
784
+ }
785
+
786
+ .ct-switch input:checked {
787
+ background: var(--ct-accent);
788
+ border-color: var(--ct-accent);
789
+ }
790
+
791
+ .ct-switch input:checked::before {
792
+ translate: 14px 0;
793
+ background: var(--ct-on-accent);
794
+ }
795
+
796
+ /* Inline form row */
797
+ .ct-form-row {
798
+ display: flex;
799
+ gap: var(--ct-space-3);
800
+ align-items: flex-end;
801
+ }
802
+
803
+ .ct-form-row .ct-field {
804
+ flex: 1;
805
+ margin-bottom: 0;
806
+ }
807
+
808
+ /* cathode/badge.css — the arcade tag. Always mono, always meaningful.
809
+ Status variants have fixed meanings; categorical variants are free.
810
+ Custom hue: <span class="ct-badge" style="--badge-hue: var(--ct-pink)"> */
811
+
812
+ .ct-badge {
813
+ display: inline-flex;
814
+ align-items: center;
815
+ gap: var(--ct-space-1);
816
+ font-family: var(--ct-font-mono);
817
+ font-size: var(--ct-text-xs);
818
+ font-weight: 600;
819
+ letter-spacing: var(--ct-tracking-mono);
820
+ text-transform: uppercase;
821
+ line-height: 1;
822
+ border-radius: var(--ct-radius);
823
+ padding: 3px var(--ct-space-2);
824
+ --badge-hue: var(--ct-text-dim);
825
+ color: var(--badge-hue);
826
+ background: color-mix(in srgb, var(--badge-hue) 13%, transparent);
827
+ border: 1px solid color-mix(in srgb, var(--badge-hue) 35%, transparent);
828
+ white-space: nowrap;
829
+ }
830
+
831
+ /* Status — fixed meanings */
832
+ .ct-badge--success { --badge-hue: var(--ct-green); }
833
+ .ct-badge--danger { --badge-hue: var(--ct-red); }
834
+ .ct-badge--warning { --badge-hue: var(--ct-amber); }
835
+ .ct-badge--info { --badge-hue: var(--ct-cyan); }
836
+ .ct-badge--accent { --badge-hue: var(--ct-accent); }
837
+
838
+ /* Categorical — free for tags/series */
839
+ .ct-badge--orange { --badge-hue: var(--ct-orange); }
840
+ .ct-badge--lime { --badge-hue: var(--ct-lime); }
841
+ .ct-badge--pink { --badge-hue: var(--ct-pink); }
842
+ .ct-badge--indigo { --badge-hue: var(--ct-indigo); }
843
+
844
+ /* Solid variant — louder, for counts and hero stats */
845
+ .ct-badge--solid {
846
+ color: var(--ct-bg-0);
847
+ background: var(--badge-hue);
848
+ border-color: var(--badge-hue);
849
+ }
850
+
851
+ /* Status dot — minimal presence indicator */
852
+ .ct-dot {
853
+ display: inline-block;
854
+ width: 7px;
855
+ height: 7px;
856
+ border-radius: 50%;
857
+ --dot-hue: var(--ct-text-faint);
858
+ background: var(--dot-hue);
859
+ box-shadow: 0 0 6px color-mix(in srgb, var(--dot-hue) 60%, transparent);
860
+ }
861
+
862
+ .ct-dot--success { --dot-hue: var(--ct-green); }
863
+ .ct-dot--danger { --dot-hue: var(--ct-red); }
864
+ .ct-dot--warning { --dot-hue: var(--ct-amber); }
865
+ .ct-dot--info { --dot-hue: var(--ct-cyan); }
866
+ .ct-dot--accent { --dot-hue: var(--ct-accent); }
867
+
868
+ /* cathode/card.css — the 1px-ruled box. Elevation = border brightness. */
869
+
870
+ .ct-card {
871
+ background: var(--ct-bg-1);
872
+ border: 1px solid var(--ct-border);
873
+ border-radius: var(--ct-radius);
874
+ }
875
+
876
+ .ct-card--interactive {
877
+ cursor: pointer;
878
+ transition: border-color var(--ct-quick) var(--ct-ease);
879
+ }
880
+
881
+ .ct-card--interactive:hover {
882
+ border-color: var(--ct-border-bright);
883
+ }
884
+
885
+ .ct-card__header {
886
+ display: flex;
887
+ align-items: center;
888
+ justify-content: space-between;
889
+ gap: var(--ct-space-3);
890
+ padding: var(--ct-space-3) var(--ct-space-4);
891
+ border-bottom: 1px solid var(--ct-border);
892
+ }
893
+
894
+ .ct-card__title {
895
+ font-size: var(--ct-text-md);
896
+ font-weight: 600;
897
+ margin: 0;
898
+ }
899
+
900
+ .ct-card__body {
901
+ padding: var(--ct-space-4);
902
+ }
903
+
904
+ .ct-card__footer {
905
+ display: flex;
906
+ align-items: center;
907
+ justify-content: flex-end;
908
+ gap: var(--ct-space-2);
909
+ padding: var(--ct-space-3) var(--ct-space-4);
910
+ border-top: 1px solid var(--ct-border);
911
+ }
912
+
913
+ /* Stat card — hero number in mono */
914
+ .ct-stat {
915
+ display: flex;
916
+ flex-direction: column;
917
+ gap: var(--ct-space-1);
918
+ padding: var(--ct-space-4);
919
+ }
920
+
921
+ .ct-stat__value {
922
+ font-family: var(--ct-font-mono);
923
+ font-size: var(--ct-text-2xl);
924
+ font-weight: 600;
925
+ font-variant-numeric: tabular-nums;
926
+ line-height: var(--ct-leading-tight);
927
+ }
928
+
929
+ .ct-stat__delta {
930
+ font-family: var(--ct-font-mono);
931
+ font-size: var(--ct-text-sm);
932
+ }
933
+
934
+ .ct-stat__delta--up { color: var(--ct-green); }
935
+ .ct-stat__delta--down { color: var(--ct-red); }
936
+
937
+ /* cathode/table.css — data tables. Numerics get .ct-num (mono, right-aligned). */
938
+
939
+ .ct-table {
940
+ width: 100%;
941
+ font-size: var(--ct-text-md);
942
+ border: 1px solid var(--ct-border);
943
+ border-radius: var(--ct-radius);
944
+ }
945
+
946
+ .ct-table th {
947
+ font-family: var(--ct-font-mono);
948
+ font-size: var(--ct-text-xs);
949
+ font-weight: 600;
950
+ letter-spacing: var(--ct-tracking-mono);
951
+ text-transform: uppercase;
952
+ color: var(--ct-text-faint);
953
+ text-align: left;
954
+ padding: var(--ct-space-2) var(--ct-space-3);
955
+ border-bottom: 1px solid var(--ct-border);
956
+ background: var(--ct-bg-1);
957
+ }
958
+
959
+ .ct-table td {
960
+ padding: var(--ct-space-2) var(--ct-space-3);
961
+ border-bottom: 1px solid var(--ct-border);
962
+ }
963
+
964
+ .ct-table tbody tr:last-child td {
965
+ border-bottom: 0;
966
+ }
967
+
968
+ .ct-table tbody tr {
969
+ transition: background var(--ct-quick) var(--ct-ease);
970
+ }
971
+
972
+ .ct-table tbody tr:hover {
973
+ background: var(--ct-bg-1);
974
+ }
975
+
976
+ .ct-table tbody tr[aria-selected="true"] {
977
+ background: color-mix(in srgb, var(--ct-accent) 8%, transparent);
978
+ }
979
+
980
+ /* Numeric/data cells */
981
+ .ct-table .ct-num,
982
+ .ct-table th.ct-num {
983
+ font-family: var(--ct-font-mono);
984
+ font-size: var(--ct-text-sm);
985
+ font-variant-numeric: tabular-nums;
986
+ text-align: right;
987
+ }
988
+
989
+ /* Compact variant for dense dashboards */
990
+ .ct-table--compact th,
991
+ .ct-table--compact td {
992
+ padding: var(--ct-space-1) var(--ct-space-2);
993
+ }
994
+
995
+ /* cathode/nav.css — navbar, sidebar, tabs, breadcrumb */
996
+
997
+ /* Top navbar */
998
+ .ct-navbar {
999
+ display: flex;
1000
+ align-items: center;
1001
+ gap: var(--ct-space-4);
1002
+ padding: 0 var(--ct-space-4);
1003
+ height: 52px;
1004
+ background: var(--ct-bg-1);
1005
+ border-bottom: 1px solid var(--ct-border);
1006
+ position: sticky;
1007
+ top: 0;
1008
+ z-index: var(--ct-z-nav);
1009
+ }
1010
+
1011
+ .ct-navbar__brand {
1012
+ font-family: var(--ct-font-mono);
1013
+ font-size: var(--ct-text-md);
1014
+ font-weight: 600;
1015
+ letter-spacing: var(--ct-tracking-mono);
1016
+ text-transform: uppercase;
1017
+ color: var(--ct-text);
1018
+ }
1019
+
1020
+ .ct-navbar__spacer {
1021
+ flex: 1;
1022
+ }
1023
+
1024
+ /* Sidebar */
1025
+ .ct-sidebar {
1026
+ display: flex;
1027
+ flex-direction: column;
1028
+ gap: var(--ct-space-1);
1029
+ width: 220px;
1030
+ padding: var(--ct-space-3);
1031
+ background: var(--ct-bg-1);
1032
+ border-right: 1px solid var(--ct-border);
1033
+ overflow-y: auto;
1034
+ }
1035
+
1036
+ .ct-sidebar__section {
1037
+ font-family: var(--ct-font-mono);
1038
+ font-size: var(--ct-text-xs);
1039
+ font-weight: 600;
1040
+ letter-spacing: var(--ct-tracking-mono);
1041
+ text-transform: uppercase;
1042
+ color: var(--ct-text-faint);
1043
+ padding: var(--ct-space-3) var(--ct-space-2) var(--ct-space-1);
1044
+ }
1045
+
1046
+ .ct-nav-item {
1047
+ display: flex;
1048
+ align-items: center;
1049
+ gap: var(--ct-space-2);
1050
+ font-size: var(--ct-text-md);
1051
+ color: var(--ct-text-dim);
1052
+ padding: var(--ct-space-2) var(--ct-space-3);
1053
+ border: 1px solid transparent;
1054
+ border-radius: var(--ct-radius);
1055
+ text-decoration: none;
1056
+ cursor: pointer;
1057
+ transition:
1058
+ color var(--ct-quick) var(--ct-ease),
1059
+ background var(--ct-quick) var(--ct-ease);
1060
+ }
1061
+
1062
+ .ct-nav-item:hover {
1063
+ color: var(--ct-text);
1064
+ background: var(--ct-bg-2);
1065
+ text-decoration: none;
1066
+ }
1067
+
1068
+ .ct-nav-item[aria-current="page"],
1069
+ .ct-nav-item--active {
1070
+ color: var(--ct-text);
1071
+ background: var(--ct-bg-2);
1072
+ border-color: var(--ct-border);
1073
+ }
1074
+
1075
+ .ct-nav-item[aria-current="page"]::before,
1076
+ .ct-nav-item--active::before {
1077
+ content: "";
1078
+ width: 2px;
1079
+ align-self: stretch;
1080
+ margin: 2px 0;
1081
+ background: var(--ct-accent);
1082
+ }
1083
+
1084
+ /* Tabs */
1085
+ .ct-tabs {
1086
+ display: flex;
1087
+ gap: var(--ct-space-1);
1088
+ border-bottom: 1px solid var(--ct-border);
1089
+ }
1090
+
1091
+ .ct-tab {
1092
+ font-family: var(--ct-font-sans);
1093
+ font-size: var(--ct-text-md);
1094
+ font-weight: 500;
1095
+ color: var(--ct-text-dim);
1096
+ background: none;
1097
+ border: 0;
1098
+ border-bottom: 2px solid transparent;
1099
+ padding: var(--ct-space-2) var(--ct-space-3);
1100
+ margin-bottom: -1px;
1101
+ cursor: pointer;
1102
+ transition: color var(--ct-quick) var(--ct-ease);
1103
+ }
1104
+
1105
+ .ct-tab:hover {
1106
+ color: var(--ct-text);
1107
+ }
1108
+
1109
+ .ct-tab[aria-selected="true"],
1110
+ .ct-tab--active {
1111
+ color: var(--ct-text);
1112
+ border-bottom-color: var(--ct-accent);
1113
+ }
1114
+
1115
+ /* Breadcrumb — mono path, like a filesystem */
1116
+ .ct-breadcrumb {
1117
+ display: flex;
1118
+ align-items: center;
1119
+ gap: var(--ct-space-2);
1120
+ font-family: var(--ct-font-mono);
1121
+ font-size: var(--ct-text-sm);
1122
+ color: var(--ct-text-faint);
1123
+ list-style: none;
1124
+ padding: 0;
1125
+ margin: 0;
1126
+ }
1127
+
1128
+ .ct-breadcrumb li {
1129
+ display: flex;
1130
+ align-items: center;
1131
+ gap: var(--ct-space-2);
1132
+ }
1133
+
1134
+ .ct-breadcrumb li + li::before {
1135
+ content: "/";
1136
+ color: var(--ct-text-faint);
1137
+ }
1138
+
1139
+ .ct-breadcrumb a {
1140
+ color: var(--ct-text-dim);
1141
+ }
1142
+
1143
+ .ct-breadcrumb li:last-child {
1144
+ color: var(--ct-text);
1145
+ }
1146
+
1147
+ /* cathode/overlay.css — modal (native <dialog>), toast, tooltip */
1148
+
1149
+ /* Modal — use <dialog class="ct-modal"> with .showModal() */
1150
+ .ct-modal {
1151
+ background: var(--ct-bg-1);
1152
+ color: var(--ct-text);
1153
+ border: 1px solid var(--ct-border-bright);
1154
+ border-radius: var(--ct-radius);
1155
+ padding: 0;
1156
+ width: min(480px, calc(100vw - var(--ct-space-6)));
1157
+ max-height: calc(100vh - var(--ct-space-8));
1158
+ }
1159
+
1160
+ .ct-modal::backdrop {
1161
+ background: rgba(5, 5, 8, 0.7);
1162
+ }
1163
+
1164
+ .ct-modal[open] {
1165
+ animation: ct-modal-in var(--ct-slow) var(--ct-ease);
1166
+ }
1167
+
1168
+ @keyframes ct-modal-in {
1169
+ from {
1170
+ opacity: 0;
1171
+ transform: translateY(8px);
1172
+ }
1173
+ }
1174
+
1175
+ .ct-modal__header {
1176
+ display: flex;
1177
+ align-items: center;
1178
+ justify-content: space-between;
1179
+ padding: var(--ct-space-4);
1180
+ border-bottom: 1px solid var(--ct-border);
1181
+ }
1182
+
1183
+ .ct-modal__title {
1184
+ font-size: var(--ct-text-lg);
1185
+ font-weight: 600;
1186
+ margin: 0;
1187
+ }
1188
+
1189
+ .ct-modal__body {
1190
+ padding: var(--ct-space-4);
1191
+ overflow-y: auto;
1192
+ }
1193
+
1194
+ .ct-modal__footer {
1195
+ display: flex;
1196
+ justify-content: flex-end;
1197
+ gap: var(--ct-space-2);
1198
+ padding: var(--ct-space-4);
1199
+ border-top: 1px solid var(--ct-border);
1200
+ }
1201
+
1202
+ /* Toasts — fixed stack, bottom right */
1203
+ .ct-toasts {
1204
+ position: fixed;
1205
+ bottom: var(--ct-space-4);
1206
+ right: var(--ct-space-4);
1207
+ display: flex;
1208
+ flex-direction: column;
1209
+ gap: var(--ct-space-2);
1210
+ z-index: var(--ct-z-toast);
1211
+ }
1212
+
1213
+ .ct-toast {
1214
+ display: flex;
1215
+ align-items: center;
1216
+ gap: var(--ct-space-3);
1217
+ background: var(--ct-bg-2);
1218
+ border: 1px solid var(--ct-border-bright);
1219
+ border-left: 2px solid var(--toast-hue, var(--ct-border-bright));
1220
+ border-radius: var(--ct-radius);
1221
+ padding: var(--ct-space-3) var(--ct-space-4);
1222
+ min-width: 280px;
1223
+ max-width: 400px;
1224
+ font-size: var(--ct-text-md);
1225
+ animation: ct-toast-in var(--ct-slow) var(--ct-ease);
1226
+ }
1227
+
1228
+ @keyframes ct-toast-in {
1229
+ from {
1230
+ opacity: 0;
1231
+ transform: translateX(16px);
1232
+ }
1233
+ }
1234
+
1235
+ .ct-toast--success { --toast-hue: var(--ct-green); }
1236
+ .ct-toast--danger { --toast-hue: var(--ct-red); }
1237
+ .ct-toast--warning { --toast-hue: var(--ct-amber); }
1238
+ .ct-toast--info { --toast-hue: var(--ct-cyan); }
1239
+
1240
+ .ct-toast__title {
1241
+ font-weight: 600;
1242
+ }
1243
+
1244
+ /* Tooltip — CSS-only: <button data-ct-tip="Copied!"> */
1245
+ [data-ct-tip] {
1246
+ position: relative;
1247
+ }
1248
+
1249
+ [data-ct-tip]::after {
1250
+ content: attr(data-ct-tip);
1251
+ position: absolute;
1252
+ bottom: calc(100% + 6px);
1253
+ left: 50%;
1254
+ transform: translateX(-50%);
1255
+ background: var(--ct-bg-3);
1256
+ color: var(--ct-text);
1257
+ border: 1px solid var(--ct-border-bright);
1258
+ border-radius: var(--ct-radius);
1259
+ padding: var(--ct-space-1) var(--ct-space-2);
1260
+ font-family: var(--ct-font-mono);
1261
+ font-size: var(--ct-text-xs);
1262
+ white-space: nowrap;
1263
+ opacity: 0;
1264
+ pointer-events: none;
1265
+ transition: opacity var(--ct-quick) var(--ct-ease);
1266
+ z-index: var(--ct-z-tooltip);
1267
+ }
1268
+
1269
+ [data-ct-tip]:hover::after,
1270
+ [data-ct-tip]:focus-visible::after {
1271
+ opacity: 1;
1272
+ }
1273
+
1274
+ /* cathode/feedback.css — progress, meter, spinner, empty state, alert */
1275
+
1276
+ /* Progress bar — smooth fill. Set width on the fill span. */
1277
+ .ct-progress {
1278
+ height: 6px;
1279
+ background: var(--ct-bg-3);
1280
+ border: 1px solid var(--ct-border);
1281
+ border-radius: var(--ct-radius);
1282
+ overflow: hidden;
1283
+ }
1284
+
1285
+ .ct-progress__fill {
1286
+ display: block;
1287
+ height: 100%;
1288
+ background: var(--progress-hue, var(--ct-accent));
1289
+ transition: width var(--ct-slow) var(--ct-ease);
1290
+ }
1291
+
1292
+ .ct-progress--success { --progress-hue: var(--ct-green); }
1293
+ .ct-progress--danger { --progress-hue: var(--ct-red); }
1294
+ .ct-progress--warning { --progress-hue: var(--ct-amber); }
1295
+
1296
+ /* Meter — the cell variant. Visible segments, the one louder wink. */
1297
+ .ct-meter {
1298
+ height: 10px;
1299
+ background: var(--ct-bg-3);
1300
+ border: 1px solid var(--ct-border);
1301
+ border-radius: var(--ct-radius);
1302
+ overflow: hidden;
1303
+ }
1304
+
1305
+ .ct-meter__fill {
1306
+ display: block;
1307
+ height: 100%;
1308
+ background: var(--progress-hue, var(--ct-accent));
1309
+ -webkit-mask: repeating-linear-gradient(
1310
+ to right,
1311
+ #000 0 6px,
1312
+ transparent 6px 8px
1313
+ );
1314
+ mask: repeating-linear-gradient(to right, #000 0 6px, transparent 6px 8px);
1315
+ transition: width var(--ct-slow) var(--ct-ease);
1316
+ }
1317
+
1318
+ /* Spinner — a rotating square, naturally */
1319
+ .ct-spinner {
1320
+ display: inline-block;
1321
+ width: 14px;
1322
+ height: 14px;
1323
+ border: 2px solid var(--ct-border-bright);
1324
+ border-top-color: var(--ct-accent);
1325
+ border-radius: var(--ct-radius);
1326
+ animation: ct-spin 0.7s linear infinite;
1327
+ }
1328
+
1329
+ @keyframes ct-spin {
1330
+ to {
1331
+ transform: rotate(360deg);
1332
+ }
1333
+ }
1334
+
1335
+ /* Empty state */
1336
+ .ct-empty {
1337
+ display: flex;
1338
+ flex-direction: column;
1339
+ align-items: center;
1340
+ justify-content: center;
1341
+ gap: var(--ct-space-2);
1342
+ padding: var(--ct-space-7) var(--ct-space-4);
1343
+ text-align: center;
1344
+ border: 1px dashed var(--ct-border-bright);
1345
+ border-radius: var(--ct-radius);
1346
+ color: var(--ct-text-dim);
1347
+ }
1348
+
1349
+ .ct-empty__glyph {
1350
+ font-family: var(--ct-font-mono);
1351
+ font-size: var(--ct-text-2xl);
1352
+ color: var(--ct-text-faint);
1353
+ line-height: 1;
1354
+ }
1355
+
1356
+ .ct-empty__title {
1357
+ font-weight: 600;
1358
+ color: var(--ct-text);
1359
+ }
1360
+
1361
+ .ct-empty__hint {
1362
+ font-size: var(--ct-text-sm);
1363
+ color: var(--ct-text-faint);
1364
+ max-width: 360px;
1365
+ }
1366
+
1367
+ /* Alert — inline callout */
1368
+ .ct-alert {
1369
+ display: flex;
1370
+ gap: var(--ct-space-3);
1371
+ padding: var(--ct-space-3) var(--ct-space-4);
1372
+ font-size: var(--ct-text-md);
1373
+ border: 1px solid color-mix(in srgb, var(--alert-hue, var(--ct-cyan)) 35%, transparent);
1374
+ border-left-width: 2px;
1375
+ border-left-color: var(--alert-hue, var(--ct-cyan));
1376
+ border-radius: var(--ct-radius);
1377
+ background: color-mix(in srgb, var(--alert-hue, var(--ct-cyan)) 7%, transparent);
1378
+ }
1379
+
1380
+ .ct-alert--success { --alert-hue: var(--ct-green); }
1381
+ .ct-alert--danger { --alert-hue: var(--ct-red); }
1382
+ .ct-alert--warning { --alert-hue: var(--ct-amber); }
1383
+ .ct-alert--info { --alert-hue: var(--ct-cyan); }
1384
+
1385
+ .ct-alert__title {
1386
+ font-weight: 600;
1387
+ margin: 0 0 var(--ct-space-1);
1388
+ }