@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.
- package/AGENTS.md +137 -0
- package/LICENSE +21 -0
- package/README.md +91 -0
- package/dist/cathode.css +1388 -0
- package/fonts/LICENSE.txt +4 -0
- package/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-600-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-400-italic.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-400-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-500-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-600-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-700-normal.woff2 +0 -0
- package/package.json +38 -0
- package/src/base.css +166 -0
- package/src/components/badge.css +59 -0
- package/src/components/button.css +107 -0
- package/src/components/card.css +68 -0
- package/src/components/feedback.css +115 -0
- package/src/components/forms.css +206 -0
- package/src/components/layout.css +76 -0
- package/src/components/nav.css +151 -0
- package/src/components/overlay.css +126 -0
- package/src/components/table.css +57 -0
- package/src/fonts.css +65 -0
- package/src/reset.css +88 -0
- package/src/tokens.css +90 -0
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
The IBM Plex font files in this directory (IBM Plex Sans, IBM Plex Mono)
|
|
2
|
+
are copyright IBM Corp. and licensed under the SIL Open Font License 1.1.
|
|
3
|
+
Full license text: https://github.com/IBM/plex/blob/master/LICENSE.txt
|
|
4
|
+
Files sourced via Fontsource (https://fontsource.org), latin subset, woff2.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sethlivingston/cathode",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Dark-only CSS design system: inky surfaces, hairline borders, mono for data, arcade semantic color. Built to be driven by AI agents.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Seth Livingston",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/sethlivingston/cathode.git"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"css",
|
|
13
|
+
"design-system",
|
|
14
|
+
"design-tokens",
|
|
15
|
+
"dark-theme",
|
|
16
|
+
"ai-agents"
|
|
17
|
+
],
|
|
18
|
+
"style": "dist/cathode.css",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": "./dist/cathode.css",
|
|
21
|
+
"./tokens": "./src/tokens.css",
|
|
22
|
+
"./agents": "./AGENTS.md",
|
|
23
|
+
"./fonts/*": "./fonts/*",
|
|
24
|
+
"./src/*": "./src/*"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"src",
|
|
29
|
+
"fonts",
|
|
30
|
+
"AGENTS.md"
|
|
31
|
+
],
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "node build.mjs"
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/base.css
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/* cathode/base.css — element defaults on the dark base */
|
|
2
|
+
|
|
3
|
+
html {
|
|
4
|
+
background: var(--ct-bg-0);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
body {
|
|
8
|
+
font-family: var(--ct-font-sans);
|
|
9
|
+
font-size: var(--ct-text-md);
|
|
10
|
+
line-height: var(--ct-leading);
|
|
11
|
+
color: var(--ct-text);
|
|
12
|
+
background: var(--ct-bg-0);
|
|
13
|
+
-webkit-font-smoothing: antialiased;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
::selection {
|
|
17
|
+
background: var(--ct-accent);
|
|
18
|
+
color: var(--ct-on-accent);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* Headings — tight, confident, no decoration */
|
|
22
|
+
h1,
|
|
23
|
+
h2,
|
|
24
|
+
h3,
|
|
25
|
+
h4,
|
|
26
|
+
h5,
|
|
27
|
+
h6 {
|
|
28
|
+
margin: 0 0 var(--ct-space-3);
|
|
29
|
+
line-height: var(--ct-leading-tight);
|
|
30
|
+
font-weight: 600;
|
|
31
|
+
letter-spacing: -0.01em;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
h1 { font-size: var(--ct-text-3xl); }
|
|
35
|
+
h2 { font-size: var(--ct-text-2xl); }
|
|
36
|
+
h3 { font-size: var(--ct-text-xl); }
|
|
37
|
+
h4 { font-size: var(--ct-text-lg); }
|
|
38
|
+
h5,
|
|
39
|
+
h6 { font-size: var(--ct-text-md); }
|
|
40
|
+
|
|
41
|
+
p {
|
|
42
|
+
margin: 0 0 var(--ct-space-3);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
p:last-child {
|
|
46
|
+
margin-bottom: 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
a {
|
|
50
|
+
color: var(--ct-accent);
|
|
51
|
+
text-decoration: none;
|
|
52
|
+
transition: color var(--ct-quick) var(--ct-ease);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
a:hover {
|
|
56
|
+
color: var(--ct-accent-bright);
|
|
57
|
+
text-decoration: underline;
|
|
58
|
+
text-underline-offset: 3px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
hr {
|
|
62
|
+
border: 0;
|
|
63
|
+
border-top: 1px solid var(--ct-border);
|
|
64
|
+
margin: var(--ct-space-5) 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
ul,
|
|
68
|
+
ol {
|
|
69
|
+
margin: 0 0 var(--ct-space-3);
|
|
70
|
+
padding-left: var(--ct-space-5);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
blockquote {
|
|
74
|
+
margin: 0 0 var(--ct-space-3);
|
|
75
|
+
padding: var(--ct-space-2) var(--ct-space-4);
|
|
76
|
+
border-left: 2px solid var(--ct-accent);
|
|
77
|
+
color: var(--ct-text-dim);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* Code & data — the mono wink */
|
|
81
|
+
code,
|
|
82
|
+
kbd,
|
|
83
|
+
samp,
|
|
84
|
+
pre {
|
|
85
|
+
font-family: var(--ct-font-mono);
|
|
86
|
+
font-size: var(--ct-text-sm);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
code,
|
|
90
|
+
samp {
|
|
91
|
+
background: var(--ct-bg-2);
|
|
92
|
+
border: 1px solid var(--ct-border);
|
|
93
|
+
border-radius: var(--ct-radius);
|
|
94
|
+
padding: 1px 5px;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
pre {
|
|
98
|
+
background: var(--ct-bg-1);
|
|
99
|
+
border: 1px solid var(--ct-border);
|
|
100
|
+
border-radius: var(--ct-radius);
|
|
101
|
+
padding: var(--ct-space-4);
|
|
102
|
+
overflow-x: auto;
|
|
103
|
+
margin: 0 0 var(--ct-space-3);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
pre code {
|
|
107
|
+
background: none;
|
|
108
|
+
border: 0;
|
|
109
|
+
padding: 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
kbd {
|
|
113
|
+
background: var(--ct-bg-3);
|
|
114
|
+
border: 1px solid var(--ct-border-bright);
|
|
115
|
+
border-bottom-width: 2px;
|
|
116
|
+
border-radius: var(--ct-radius);
|
|
117
|
+
padding: 1px 6px;
|
|
118
|
+
font-size: var(--ct-text-xs);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* .ct-data — apply to any inline run of IDs, counts, timestamps */
|
|
122
|
+
.ct-data {
|
|
123
|
+
font-family: var(--ct-font-mono);
|
|
124
|
+
font-size: var(--ct-text-sm);
|
|
125
|
+
font-variant-numeric: tabular-nums;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* .ct-label-mono — uppercase mono micro-label (section headers, table heads) */
|
|
129
|
+
.ct-label-mono {
|
|
130
|
+
font-family: var(--ct-font-mono);
|
|
131
|
+
font-size: var(--ct-text-xs);
|
|
132
|
+
font-weight: 600;
|
|
133
|
+
letter-spacing: var(--ct-tracking-mono);
|
|
134
|
+
text-transform: uppercase;
|
|
135
|
+
color: var(--ct-text-faint);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* Muted text helpers */
|
|
139
|
+
.ct-dim { color: var(--ct-text-dim); }
|
|
140
|
+
.ct-faint { color: var(--ct-text-faint); }
|
|
141
|
+
|
|
142
|
+
/* Focus — one ring to rule them all */
|
|
143
|
+
:focus-visible {
|
|
144
|
+
outline: 2px solid var(--ct-accent-glow);
|
|
145
|
+
outline-offset: 1px;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* Scrollbars — quiet, square */
|
|
149
|
+
* {
|
|
150
|
+
scrollbar-width: thin;
|
|
151
|
+
scrollbar-color: var(--ct-border-bright) transparent;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
*::-webkit-scrollbar {
|
|
155
|
+
width: 10px;
|
|
156
|
+
height: 10px;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
*::-webkit-scrollbar-thumb {
|
|
160
|
+
background: var(--ct-border-bright);
|
|
161
|
+
border: 2px solid var(--ct-bg-0);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
*::-webkit-scrollbar-track {
|
|
165
|
+
background: transparent;
|
|
166
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/* cathode/badge.css — the arcade tag. Always mono, always meaningful.
|
|
2
|
+
Status variants have fixed meanings; categorical variants are free.
|
|
3
|
+
Custom hue: <span class="ct-badge" style="--badge-hue: var(--ct-pink)"> */
|
|
4
|
+
|
|
5
|
+
.ct-badge {
|
|
6
|
+
display: inline-flex;
|
|
7
|
+
align-items: center;
|
|
8
|
+
gap: var(--ct-space-1);
|
|
9
|
+
font-family: var(--ct-font-mono);
|
|
10
|
+
font-size: var(--ct-text-xs);
|
|
11
|
+
font-weight: 600;
|
|
12
|
+
letter-spacing: var(--ct-tracking-mono);
|
|
13
|
+
text-transform: uppercase;
|
|
14
|
+
line-height: 1;
|
|
15
|
+
border-radius: var(--ct-radius);
|
|
16
|
+
padding: 3px var(--ct-space-2);
|
|
17
|
+
--badge-hue: var(--ct-text-dim);
|
|
18
|
+
color: var(--badge-hue);
|
|
19
|
+
background: color-mix(in srgb, var(--badge-hue) 13%, transparent);
|
|
20
|
+
border: 1px solid color-mix(in srgb, var(--badge-hue) 35%, transparent);
|
|
21
|
+
white-space: nowrap;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Status — fixed meanings */
|
|
25
|
+
.ct-badge--success { --badge-hue: var(--ct-green); }
|
|
26
|
+
.ct-badge--danger { --badge-hue: var(--ct-red); }
|
|
27
|
+
.ct-badge--warning { --badge-hue: var(--ct-amber); }
|
|
28
|
+
.ct-badge--info { --badge-hue: var(--ct-cyan); }
|
|
29
|
+
.ct-badge--accent { --badge-hue: var(--ct-accent); }
|
|
30
|
+
|
|
31
|
+
/* Categorical — free for tags/series */
|
|
32
|
+
.ct-badge--orange { --badge-hue: var(--ct-orange); }
|
|
33
|
+
.ct-badge--lime { --badge-hue: var(--ct-lime); }
|
|
34
|
+
.ct-badge--pink { --badge-hue: var(--ct-pink); }
|
|
35
|
+
.ct-badge--indigo { --badge-hue: var(--ct-indigo); }
|
|
36
|
+
|
|
37
|
+
/* Solid variant — louder, for counts and hero stats */
|
|
38
|
+
.ct-badge--solid {
|
|
39
|
+
color: var(--ct-bg-0);
|
|
40
|
+
background: var(--badge-hue);
|
|
41
|
+
border-color: var(--badge-hue);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* Status dot — minimal presence indicator */
|
|
45
|
+
.ct-dot {
|
|
46
|
+
display: inline-block;
|
|
47
|
+
width: 7px;
|
|
48
|
+
height: 7px;
|
|
49
|
+
border-radius: 50%;
|
|
50
|
+
--dot-hue: var(--ct-text-faint);
|
|
51
|
+
background: var(--dot-hue);
|
|
52
|
+
box-shadow: 0 0 6px color-mix(in srgb, var(--dot-hue) 60%, transparent);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.ct-dot--success { --dot-hue: var(--ct-green); }
|
|
56
|
+
.ct-dot--danger { --dot-hue: var(--ct-red); }
|
|
57
|
+
.ct-dot--warning { --dot-hue: var(--ct-amber); }
|
|
58
|
+
.ct-dot--info { --dot-hue: var(--ct-cyan); }
|
|
59
|
+
.ct-dot--accent { --dot-hue: var(--ct-accent); }
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/* cathode/button.css */
|
|
2
|
+
|
|
3
|
+
.ct-button {
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
justify-content: center;
|
|
7
|
+
gap: var(--ct-space-2);
|
|
8
|
+
font-family: var(--ct-font-sans);
|
|
9
|
+
font-size: var(--ct-text-md);
|
|
10
|
+
font-weight: 500;
|
|
11
|
+
line-height: 1;
|
|
12
|
+
color: var(--ct-text);
|
|
13
|
+
background: var(--ct-bg-2);
|
|
14
|
+
border: 1px solid var(--ct-border);
|
|
15
|
+
border-radius: var(--ct-radius);
|
|
16
|
+
padding: var(--ct-space-2) var(--ct-space-4);
|
|
17
|
+
min-height: 36px;
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
user-select: none;
|
|
20
|
+
white-space: nowrap;
|
|
21
|
+
transition:
|
|
22
|
+
border-color var(--ct-quick) var(--ct-ease),
|
|
23
|
+
background var(--ct-quick) var(--ct-ease),
|
|
24
|
+
color var(--ct-quick) var(--ct-ease);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.ct-button:hover {
|
|
28
|
+
border-color: var(--ct-border-bright);
|
|
29
|
+
background: var(--ct-bg-3);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.ct-button:active {
|
|
33
|
+
transform: translateY(1px);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.ct-button:disabled {
|
|
37
|
+
opacity: 0.45;
|
|
38
|
+
cursor: not-allowed;
|
|
39
|
+
transform: none;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* Primary — the one magenta action per view */
|
|
43
|
+
.ct-button--primary {
|
|
44
|
+
background: var(--ct-accent);
|
|
45
|
+
border-color: var(--ct-accent);
|
|
46
|
+
color: var(--ct-on-accent);
|
|
47
|
+
font-weight: 600;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.ct-button--primary:hover {
|
|
51
|
+
background: var(--ct-accent-bright);
|
|
52
|
+
border-color: var(--ct-accent-bright);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* Danger — destructive actions only */
|
|
56
|
+
.ct-button--danger {
|
|
57
|
+
color: var(--ct-red);
|
|
58
|
+
border-color: color-mix(in srgb, var(--ct-red) 40%, transparent);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.ct-button--danger:hover {
|
|
62
|
+
background: color-mix(in srgb, var(--ct-red) 12%, transparent);
|
|
63
|
+
border-color: var(--ct-red);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* Ghost — toolbar/inline actions, no box until hover */
|
|
67
|
+
.ct-button--ghost {
|
|
68
|
+
background: transparent;
|
|
69
|
+
border-color: transparent;
|
|
70
|
+
color: var(--ct-text-dim);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.ct-button--ghost:hover {
|
|
74
|
+
background: var(--ct-bg-2);
|
|
75
|
+
border-color: var(--ct-border);
|
|
76
|
+
color: var(--ct-text);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Sizes */
|
|
80
|
+
.ct-button--sm {
|
|
81
|
+
font-size: var(--ct-text-sm);
|
|
82
|
+
padding: var(--ct-space-1) var(--ct-space-3);
|
|
83
|
+
min-height: 28px;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.ct-button--lg {
|
|
87
|
+
font-size: var(--ct-text-lg);
|
|
88
|
+
padding: var(--ct-space-3) var(--ct-space-5);
|
|
89
|
+
min-height: 44px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* Icon-only — square */
|
|
93
|
+
.ct-button--icon {
|
|
94
|
+
padding: var(--ct-space-2);
|
|
95
|
+
width: 36px;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.ct-button--icon.ct-button--sm {
|
|
99
|
+
width: 28px;
|
|
100
|
+
padding: var(--ct-space-1);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* Button row */
|
|
104
|
+
.ct-button-group {
|
|
105
|
+
display: inline-flex;
|
|
106
|
+
gap: var(--ct-space-2);
|
|
107
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/* cathode/card.css — the 1px-ruled box. Elevation = border brightness. */
|
|
2
|
+
|
|
3
|
+
.ct-card {
|
|
4
|
+
background: var(--ct-bg-1);
|
|
5
|
+
border: 1px solid var(--ct-border);
|
|
6
|
+
border-radius: var(--ct-radius);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.ct-card--interactive {
|
|
10
|
+
cursor: pointer;
|
|
11
|
+
transition: border-color var(--ct-quick) var(--ct-ease);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.ct-card--interactive:hover {
|
|
15
|
+
border-color: var(--ct-border-bright);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.ct-card__header {
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
justify-content: space-between;
|
|
22
|
+
gap: var(--ct-space-3);
|
|
23
|
+
padding: var(--ct-space-3) var(--ct-space-4);
|
|
24
|
+
border-bottom: 1px solid var(--ct-border);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.ct-card__title {
|
|
28
|
+
font-size: var(--ct-text-md);
|
|
29
|
+
font-weight: 600;
|
|
30
|
+
margin: 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.ct-card__body {
|
|
34
|
+
padding: var(--ct-space-4);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.ct-card__footer {
|
|
38
|
+
display: flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
justify-content: flex-end;
|
|
41
|
+
gap: var(--ct-space-2);
|
|
42
|
+
padding: var(--ct-space-3) var(--ct-space-4);
|
|
43
|
+
border-top: 1px solid var(--ct-border);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Stat card — hero number in mono */
|
|
47
|
+
.ct-stat {
|
|
48
|
+
display: flex;
|
|
49
|
+
flex-direction: column;
|
|
50
|
+
gap: var(--ct-space-1);
|
|
51
|
+
padding: var(--ct-space-4);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.ct-stat__value {
|
|
55
|
+
font-family: var(--ct-font-mono);
|
|
56
|
+
font-size: var(--ct-text-2xl);
|
|
57
|
+
font-weight: 600;
|
|
58
|
+
font-variant-numeric: tabular-nums;
|
|
59
|
+
line-height: var(--ct-leading-tight);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.ct-stat__delta {
|
|
63
|
+
font-family: var(--ct-font-mono);
|
|
64
|
+
font-size: var(--ct-text-sm);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.ct-stat__delta--up { color: var(--ct-green); }
|
|
68
|
+
.ct-stat__delta--down { color: var(--ct-red); }
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/* cathode/feedback.css — progress, meter, spinner, empty state, alert */
|
|
2
|
+
|
|
3
|
+
/* Progress bar — smooth fill. Set width on the fill span. */
|
|
4
|
+
.ct-progress {
|
|
5
|
+
height: 6px;
|
|
6
|
+
background: var(--ct-bg-3);
|
|
7
|
+
border: 1px solid var(--ct-border);
|
|
8
|
+
border-radius: var(--ct-radius);
|
|
9
|
+
overflow: hidden;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.ct-progress__fill {
|
|
13
|
+
display: block;
|
|
14
|
+
height: 100%;
|
|
15
|
+
background: var(--progress-hue, var(--ct-accent));
|
|
16
|
+
transition: width var(--ct-slow) var(--ct-ease);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.ct-progress--success { --progress-hue: var(--ct-green); }
|
|
20
|
+
.ct-progress--danger { --progress-hue: var(--ct-red); }
|
|
21
|
+
.ct-progress--warning { --progress-hue: var(--ct-amber); }
|
|
22
|
+
|
|
23
|
+
/* Meter — the cell variant. Visible segments, the one louder wink. */
|
|
24
|
+
.ct-meter {
|
|
25
|
+
height: 10px;
|
|
26
|
+
background: var(--ct-bg-3);
|
|
27
|
+
border: 1px solid var(--ct-border);
|
|
28
|
+
border-radius: var(--ct-radius);
|
|
29
|
+
overflow: hidden;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.ct-meter__fill {
|
|
33
|
+
display: block;
|
|
34
|
+
height: 100%;
|
|
35
|
+
background: var(--progress-hue, var(--ct-accent));
|
|
36
|
+
-webkit-mask: repeating-linear-gradient(
|
|
37
|
+
to right,
|
|
38
|
+
#000 0 6px,
|
|
39
|
+
transparent 6px 8px
|
|
40
|
+
);
|
|
41
|
+
mask: repeating-linear-gradient(to right, #000 0 6px, transparent 6px 8px);
|
|
42
|
+
transition: width var(--ct-slow) var(--ct-ease);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* Spinner — a rotating square, naturally */
|
|
46
|
+
.ct-spinner {
|
|
47
|
+
display: inline-block;
|
|
48
|
+
width: 14px;
|
|
49
|
+
height: 14px;
|
|
50
|
+
border: 2px solid var(--ct-border-bright);
|
|
51
|
+
border-top-color: var(--ct-accent);
|
|
52
|
+
border-radius: var(--ct-radius);
|
|
53
|
+
animation: ct-spin 0.7s linear infinite;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@keyframes ct-spin {
|
|
57
|
+
to {
|
|
58
|
+
transform: rotate(360deg);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* Empty state */
|
|
63
|
+
.ct-empty {
|
|
64
|
+
display: flex;
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
align-items: center;
|
|
67
|
+
justify-content: center;
|
|
68
|
+
gap: var(--ct-space-2);
|
|
69
|
+
padding: var(--ct-space-7) var(--ct-space-4);
|
|
70
|
+
text-align: center;
|
|
71
|
+
border: 1px dashed var(--ct-border-bright);
|
|
72
|
+
border-radius: var(--ct-radius);
|
|
73
|
+
color: var(--ct-text-dim);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.ct-empty__glyph {
|
|
77
|
+
font-family: var(--ct-font-mono);
|
|
78
|
+
font-size: var(--ct-text-2xl);
|
|
79
|
+
color: var(--ct-text-faint);
|
|
80
|
+
line-height: 1;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.ct-empty__title {
|
|
84
|
+
font-weight: 600;
|
|
85
|
+
color: var(--ct-text);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.ct-empty__hint {
|
|
89
|
+
font-size: var(--ct-text-sm);
|
|
90
|
+
color: var(--ct-text-faint);
|
|
91
|
+
max-width: 360px;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* Alert — inline callout */
|
|
95
|
+
.ct-alert {
|
|
96
|
+
display: flex;
|
|
97
|
+
gap: var(--ct-space-3);
|
|
98
|
+
padding: var(--ct-space-3) var(--ct-space-4);
|
|
99
|
+
font-size: var(--ct-text-md);
|
|
100
|
+
border: 1px solid color-mix(in srgb, var(--alert-hue, var(--ct-cyan)) 35%, transparent);
|
|
101
|
+
border-left-width: 2px;
|
|
102
|
+
border-left-color: var(--alert-hue, var(--ct-cyan));
|
|
103
|
+
border-radius: var(--ct-radius);
|
|
104
|
+
background: color-mix(in srgb, var(--alert-hue, var(--ct-cyan)) 7%, transparent);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.ct-alert--success { --alert-hue: var(--ct-green); }
|
|
108
|
+
.ct-alert--danger { --alert-hue: var(--ct-red); }
|
|
109
|
+
.ct-alert--warning { --alert-hue: var(--ct-amber); }
|
|
110
|
+
.ct-alert--info { --alert-hue: var(--ct-cyan); }
|
|
111
|
+
|
|
112
|
+
.ct-alert__title {
|
|
113
|
+
font-weight: 600;
|
|
114
|
+
margin: 0 0 var(--ct-space-1);
|
|
115
|
+
}
|