@atelic-action/ui 0.9.0 → 0.10.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/README.md CHANGED
@@ -266,8 +266,46 @@ The blocks a page composes, each styled in `styles/components.css` inside the `a
266
266
 
267
267
  **StarRating outside a site.** It is the one component that does not sit under `.mkt` or read a theme token: its styles are in `styles/star-rating.css`, and its two colors are the `--star-fill` and `--star-outline` custom properties, falling back to the text color and a faint tint of it. An app that installs the package for this component alone imports that one sheet, not `components.css`.
268
268
 
269
+ **A part's own color.** `StackedBar` takes a `color` on a segment, any CSS color, for parts that are not good or bad (the protein, carbs, and fat of a meal), and it wins over `tone`. `showKey={false}` draws the bar alone for a page that keys the parts its own way; the bar keeps its spoken summary.
270
+
269
271
  **Tones.** `good`, `warn`, `bad`, `info`, and `muted` are the one palette the package carries, because good, a warning, and broken read green, amber, and red whatever the brand is. A component sets `data-tone`, and `--tone`, `--tone-fill`, and `--tone-bg` follow for whatever sits inside. A site's theme may restate `--tone-good` and the rest on `.mkt`; `info` and `muted` come from the theme's own primary and neutral tokens.
270
272
 
273
+ ## In an App
274
+
275
+ The page components also work in an app that has its own base styles (Tailwind, shadcn) and wears none of the site chrome. Three things make that so (0.10.0):
276
+
277
+ 1. **A second scope.** Every rule in `styles/components.css` answers to `.atelic-ui` as well as `.mkt`. `.atelic-ui` has no resets behind it, so an app puts the class on the region that holds a package component and nothing else in it restyles. Prefer a region to `body`: the components use plain class names (`.stat .num`, `.callout`, `.note`), and an app with markup of its own under those names would have a page wide scope reach it. `body` is right only for an app that has checked it has none, and it is the one way to cover a component rendered in a portal.
278
+ 2. **The app imports one sheet**, `@atelic-action/ui/styles/components.css`, and neither `base.css` nor `chrome.css`. An app's own unlayered CSS always wins over the package. With Tailwind, where the app can declare the layer order before Tailwind loads, `@layer theme, base, atelic-ui, components, utilities;` keeps utilities winning over the package too; where it cannot, the package's layer lands last and wins over utilities set on a package element, which only matters to a caller styling one with a utility class.
279
+ 3. **The app maps its tokens** onto the ones the components read, in its own stylesheet on the same scope:
280
+
281
+ | Token | What it colors |
282
+ |---|---|
283
+ | `--ink`, `--ink-soft` | Text and quieter text |
284
+ | `--neutral-100`, `--neutral-200`, `--neutral-500` | Hairlines, tracks, and captions |
285
+ | `--surface-alt` | The quiet ground behind a muted tone |
286
+ | `--ui-primary` (falls back to `--primary`), `--primary-bright`, `--primary-tint` | The accent, its brighter fill, and its tint |
287
+ | `--ui-card` (falls back to `--card`) | A raised surface |
288
+ | `--font-sans`, `--font-mono`, `--radius-sm` | Type and the small radius |
289
+ | `--tone-good`, `--tone-warn`, `--tone-bad`, each with `-fill` and `-bg` | Optional: the package defines these, and a dark theme restates them |
290
+
291
+ `--ui-primary` and `--ui-card` exist because an app's own `--primary` and `--card` may hold something else: shadcn keeps bare HSL channels there, which are not a color on their own. A site sets neither and nothing changes.
292
+
293
+ ```css
294
+ /* app.css */
295
+ .atelic-ui {
296
+ --ink: hsl(var(--foreground));
297
+ --ink-soft: hsl(var(--muted-foreground));
298
+ --neutral-500: hsl(var(--muted-foreground));
299
+ --neutral-200: hsl(var(--border));
300
+ --neutral-100: hsl(var(--muted));
301
+ --surface-alt: hsl(var(--muted));
302
+ --ui-primary: hsl(var(--brand));
303
+ --ui-card: hsl(var(--card));
304
+ }
305
+ ```
306
+
307
+ `StarRating` needs none of this: its sheet is unscoped and reads no token. The chrome (`SiteHeader`, `Footer`, and the rest) and `NotFound` remain site shaped and are not meant for a signed in app.
308
+
271
309
  ## The Gallery
272
310
 
273
311
  `gallery/` is one static page, The Components, that shows every page component on its own with made up data for a fictional bakery, wearing the practice's own palette and type. It lives at [ui.atelic.me](https://ui.atelic.me), noindexed and disallowed in its `robots.txt`, since it is for the people building with the package and never search inventory. It imports the components and stylesheets from `src/` by relative path rather than from npm, so it always shows the code in the repo, and it reads the package name and version from `package.json` at build time. It sits outside `src/`, so it is never published.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atelic-action/ui",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Shared UI for the Atelic templates: site chrome, base styles, and the component library they install",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -1,3 +1,4 @@
1
+ import type { CSSProperties } from "react";
1
2
  import type { Tone } from "./tone";
2
3
 
3
4
  export interface StackedBarSegment {
@@ -5,16 +6,26 @@ export interface StackedBarSegment {
5
6
  value: number;
6
7
  /** The figure as printed, e.g. "1,158"; defaults to the value with separators. */
7
8
  display?: string;
8
- tone: Tone;
9
+ /** How the part reads. Leave it out when `color` says it instead. */
10
+ tone?: Tone;
11
+ /** A color of the part's own, any CSS color, for parts that are not good or bad. It wins over `tone`. */
12
+ color?: string;
9
13
  }
10
14
 
11
15
  export interface StackedBarProps {
12
16
  segments: StackedBarSegment[];
17
+ /** False draws the bar alone, for a page that keys the parts its own way. The bar keeps its spoken summary. */
18
+ showKey?: boolean;
13
19
  className?: string;
14
20
  }
15
21
 
22
+ /** A part's own color, set as the fill its bar and its swatch both read. */
23
+ function fill(segment: StackedBarSegment): CSSProperties | undefined {
24
+ return segment.color ? ({ "--tone-fill": segment.color } as CSSProperties) : undefined;
25
+ }
26
+
16
27
  /** One bar split into the parts of a whole, with a key naming each part and its figure. */
17
- export function StackedBar({ segments, className }: StackedBarProps) {
28
+ export function StackedBar({ segments, showKey = true, className }: StackedBarProps) {
18
29
  const total = segments.reduce((sum, segment) => sum + segment.value, 0) || 1;
19
30
  const figure = (segment: StackedBarSegment) =>
20
31
  segment.display ?? segment.value.toLocaleString("en-US");
@@ -28,19 +39,21 @@ export function StackedBar({ segments, className }: StackedBarProps) {
28
39
  <span
29
40
  key={segment.label}
30
41
  data-tone={segment.tone}
31
- style={{ flexGrow: segment.value / total }}
42
+ style={{ flexGrow: segment.value / total, ...fill(segment) }}
32
43
  />
33
44
  ))}
34
45
  </div>
35
- <ul className="chart-key">
36
- {segments.map((segment) => (
37
- <li key={segment.label} data-tone={segment.tone}>
38
- <span className="chart-swatch" aria-hidden="true" />
39
- <b>{figure(segment)}</b>
40
- <span>{segment.label}</span>
41
- </li>
42
- ))}
43
- </ul>
46
+ {showKey && (
47
+ <ul className="chart-key">
48
+ {segments.map((segment) => (
49
+ <li key={segment.label} data-tone={segment.tone} style={fill(segment)}>
50
+ <span className="chart-swatch" aria-hidden="true" />
51
+ <b>{figure(segment)}</b>
52
+ <span>{segment.label}</span>
53
+ </li>
54
+ ))}
55
+ </ul>
56
+ )}
44
57
  </div>
45
58
  );
46
59
  }
@@ -2,21 +2,33 @@
2
2
 
3
3
  /* Layout defaults for the components under src/components. A site's own
4
4
  classes (.page-hero, .eyebrow, .lead, .btn) arrive unlayered and win, so
5
- these only fill in where a site does not style them. */
5
+ these only fill in where a site does not style them.
6
+
7
+ Every rule answers to either of two scopes. `.mkt` is a site's canvas,
8
+ which base.css also resets headings, links, and buttons under.
9
+ `.atelic-ui` is the same scope with no resets behind it, for an app that
10
+ has its own base (Tailwind, shadcn) and wants only the components. The
11
+ two weigh the same, so nothing a site already overrides changes.
12
+
13
+ Two tokens are read through names of the package's own first:
14
+ `--ui-primary` and `--ui-card`, each falling back to `--primary` and
15
+ `--card`. A site sets neither and nothing changes. An app whose own
16
+ `--primary` and `--card` hold something else (shadcn keeps bare HSL
17
+ channels there) sets the `--ui-` names and leaves its own alone. */
6
18
  @layer atelic-ui {
7
- .mkt .not-found-hero {
19
+ :is(.mkt, .atelic-ui) .not-found-hero {
8
20
  padding-top: calc(var(--nav-height, 72px) + clamp(40px, 7vw, 86px));
9
21
  padding-bottom: clamp(28px, 5vw, 60px);
10
22
  }
11
- .mkt .not-found-hero h1 {
23
+ :is(.mkt, .atelic-ui) .not-found-hero h1 {
12
24
  margin: 16px 0 0;
13
25
  }
14
- .mkt .not-found-hero .lead {
26
+ :is(.mkt, .atelic-ui) .not-found-hero .lead {
15
27
  margin-top: 22px;
16
28
  max-width: 56ch;
17
29
  }
18
- .mkt .not-found-links .cta-row,
19
- .mkt .not-found-closing .cta-row {
30
+ :is(.mkt, .atelic-ui) .not-found-links .cta-row,
31
+ :is(.mkt, .atelic-ui) .not-found-closing .cta-row {
20
32
  margin-top: 22px;
21
33
  }
22
34
 
@@ -24,7 +36,7 @@
24
36
  warning, and broken read green, amber, and red whatever the brand is.
25
37
  A site's theme may restate any of these on .mkt. A component sets
26
38
  data-tone, and --tone, --tone-fill, and --tone-bg follow. ---- */
27
- .mkt {
39
+ :is(.mkt, .atelic-ui) {
28
40
  --tone-good: #1b7f3b;
29
41
  --tone-good-fill: #37a35c;
30
42
  --tone-good-bg: #eaf6ee;
@@ -35,27 +47,27 @@
35
47
  --tone-bad-fill: #d9483f;
36
48
  --tone-bad-bg: #fdecea;
37
49
  }
38
- .mkt [data-tone="good"] {
50
+ :is(.mkt, .atelic-ui) [data-tone="good"] {
39
51
  --tone: var(--tone-good);
40
52
  --tone-fill: var(--tone-good-fill);
41
53
  --tone-bg: var(--tone-good-bg);
42
54
  }
43
- .mkt [data-tone="warn"] {
55
+ :is(.mkt, .atelic-ui) [data-tone="warn"] {
44
56
  --tone: var(--tone-warn);
45
57
  --tone-fill: var(--tone-warn-fill);
46
58
  --tone-bg: var(--tone-warn-bg);
47
59
  }
48
- .mkt [data-tone="bad"] {
60
+ :is(.mkt, .atelic-ui) [data-tone="bad"] {
49
61
  --tone: var(--tone-bad);
50
62
  --tone-fill: var(--tone-bad-fill);
51
63
  --tone-bg: var(--tone-bad-bg);
52
64
  }
53
- .mkt [data-tone="info"] {
54
- --tone: var(--primary);
65
+ :is(.mkt, .atelic-ui) [data-tone="info"] {
66
+ --tone: var(--ui-primary, var(--primary));
55
67
  --tone-fill: var(--primary-bright);
56
68
  --tone-bg: var(--primary-tint);
57
69
  }
58
- .mkt [data-tone="muted"] {
70
+ :is(.mkt, .atelic-ui) [data-tone="muted"] {
59
71
  --tone: var(--neutral-500);
60
72
  --tone-fill: var(--neutral-200);
61
73
  --tone-bg: var(--surface-alt);
@@ -63,50 +75,50 @@
63
75
 
64
76
  /* ---- StatRow: large figures, each over what it counts, its period,
65
77
  and its comparisons ---- */
66
- .mkt .stat-row {
78
+ :is(.mkt, .atelic-ui) .stat-row {
67
79
  display: grid;
68
80
  gap: 24px;
69
81
  grid-template-columns: repeat(2, minmax(0, 1fr));
70
82
  }
71
83
  @media (min-width: 760px) {
72
- .mkt .stat-row {
84
+ :is(.mkt, .atelic-ui) .stat-row {
73
85
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
74
86
  }
75
87
  }
76
- .mkt .stat-row.is-center .stat {
88
+ :is(.mkt, .atelic-ui) .stat-row.is-center .stat {
77
89
  text-align: center;
78
90
  }
79
- .mkt .stat .num {
91
+ :is(.mkt, .atelic-ui) .stat .num {
80
92
  display: flex;
81
93
  align-items: center;
82
94
  gap: 0.12em;
83
95
  font-size: clamp(2.2rem, 5vw, 3rem);
84
96
  font-weight: 800;
85
97
  letter-spacing: -0.03em;
86
- color: var(--tone, var(--primary));
98
+ color: var(--tone, var(--ui-primary, var(--primary)));
87
99
  line-height: 1;
88
100
  font-variant-numeric: tabular-nums;
89
101
  }
90
- .mkt .stat-row.is-center .stat .num {
102
+ :is(.mkt, .atelic-ui) .stat-row.is-center .stat .num {
91
103
  justify-content: center;
92
104
  }
93
- .mkt .stat-trend {
105
+ :is(.mkt, .atelic-ui) .stat-trend {
94
106
  width: 0.8em;
95
107
  height: 0.8em;
96
108
  flex: none;
97
109
  }
98
- .mkt .stat .lbl {
110
+ :is(.mkt, .atelic-ui) .stat .lbl {
99
111
  font-size: 0.95rem;
100
112
  font-weight: 650;
101
113
  color: var(--ink);
102
114
  margin-top: 8px;
103
115
  }
104
- .mkt .stat-period {
116
+ :is(.mkt, .atelic-ui) .stat-period {
105
117
  margin-left: 0.5em;
106
118
  font-weight: 400;
107
119
  color: var(--neutral-500);
108
120
  }
109
- .mkt .stat-delta {
121
+ :is(.mkt, .atelic-ui) .stat-delta {
110
122
  display: flex;
111
123
  flex-wrap: wrap;
112
124
  align-items: baseline;
@@ -117,27 +129,27 @@
117
129
  color: var(--neutral-500);
118
130
  font-variant-numeric: tabular-nums;
119
131
  }
120
- .mkt .stat-delta-change {
132
+ :is(.mkt, .atelic-ui) .stat-delta-change {
121
133
  display: inline-flex;
122
134
  align-items: center;
123
135
  gap: 2px;
124
136
  font-weight: 700;
125
137
  color: var(--tone);
126
138
  }
127
- .mkt .stat-delta-change svg {
139
+ :is(.mkt, .atelic-ui) .stat-delta-change svg {
128
140
  align-self: center;
129
141
  }
130
- .mkt .stat-delta-basis {
142
+ :is(.mkt, .atelic-ui) .stat-delta-basis {
131
143
  text-decoration: none;
132
144
  }
133
- .mkt .stat .note {
145
+ :is(.mkt, .atelic-ui) .stat .note {
134
146
  font-size: 0.8rem;
135
147
  color: var(--neutral-500);
136
148
  margin-top: 4px;
137
149
  }
138
150
 
139
151
  /* ---- Collapsible: a labeled line that opens to the detail behind it ---- */
140
- .mkt .collapsible > summary {
152
+ :is(.mkt, .atelic-ui) .collapsible > summary {
141
153
  display: flex;
142
154
  align-items: center;
143
155
  justify-content: space-between;
@@ -145,77 +157,77 @@
145
157
  cursor: pointer;
146
158
  list-style: none;
147
159
  }
148
- .mkt .collapsible > summary::-webkit-details-marker {
160
+ :is(.mkt, .atelic-ui) .collapsible > summary::-webkit-details-marker {
149
161
  display: none;
150
162
  }
151
- .mkt .collapsible-text {
163
+ :is(.mkt, .atelic-ui) .collapsible-text {
152
164
  display: flex;
153
165
  flex-direction: column;
154
166
  gap: 2px;
155
167
  min-width: 0;
156
168
  }
157
- .mkt .collapsible-label {
169
+ :is(.mkt, .atelic-ui) .collapsible-label {
158
170
  font-weight: 650;
159
171
  color: var(--ink);
160
172
  }
161
- .mkt .collapsible-summary {
173
+ :is(.mkt, .atelic-ui) .collapsible-summary {
162
174
  color: var(--ink-soft);
163
175
  text-wrap: pretty;
164
176
  }
165
- .mkt .collapsible > summary:hover .collapsible-label {
166
- color: var(--primary);
177
+ :is(.mkt, .atelic-ui) .collapsible > summary:hover .collapsible-label {
178
+ color: var(--ui-primary, var(--primary));
167
179
  }
168
- .mkt .collapsible-chevron {
180
+ :is(.mkt, .atelic-ui) .collapsible-chevron {
169
181
  flex: none;
170
182
  color: var(--neutral-500);
171
183
  transition: transform 0.15s;
172
184
  }
173
- .mkt .collapsible[open] > summary .collapsible-chevron {
185
+ :is(.mkt, .atelic-ui) .collapsible[open] > summary .collapsible-chevron {
174
186
  transform: rotate(180deg);
175
187
  }
176
- .mkt .collapsible-body {
188
+ :is(.mkt, .atelic-ui) .collapsible-body {
177
189
  margin-top: 12px;
178
190
  }
179
191
  @media (prefers-reduced-motion: reduce) {
180
- .mkt .collapsible-chevron {
192
+ :is(.mkt, .atelic-ui) .collapsible-chevron {
181
193
  transition: none;
182
194
  }
183
195
  }
184
196
  /* Paper cannot be clicked, so a printed collapsible is open. */
185
197
  @media print {
186
- .mkt .collapsible::details-content {
198
+ :is(.mkt, .atelic-ui) .collapsible::details-content {
187
199
  content-visibility: visible;
188
200
  display: block;
189
201
  }
190
- .mkt .collapsible-chevron {
202
+ :is(.mkt, .atelic-ui) .collapsible-chevron {
191
203
  display: none;
192
204
  }
193
205
  }
194
206
 
195
207
  /* ---- Callout: an icon in its tone beside the title, the explainer
196
208
  under it; boxed, it sits apart on a tinted ground ---- */
197
- .mkt .callout {
209
+ :is(.mkt, .atelic-ui) .callout {
198
210
  display: grid;
199
211
  grid-template-columns: auto minmax(0, 1fr);
200
212
  gap: 10px;
201
213
  align-items: start;
202
214
  }
203
- .mkt .callout-icon {
215
+ :is(.mkt, .atelic-ui) .callout-icon {
204
216
  margin-top: 0.15em;
205
217
  color: var(--tone);
206
218
  flex: none;
207
219
  }
208
- .mkt .callout-title {
220
+ :is(.mkt, .atelic-ui) .callout-title {
209
221
  font-weight: 650;
210
222
  color: var(--ink);
211
223
  text-wrap: pretty;
212
224
  }
213
- .mkt .callout-body {
225
+ :is(.mkt, .atelic-ui) .callout-body {
214
226
  margin-top: 2px;
215
227
  color: var(--ink-soft);
216
228
  text-wrap: pretty;
217
229
  }
218
- .mkt .callout.is-box {
230
+ :is(.mkt, .atelic-ui) .callout.is-box {
219
231
  padding: 14px 16px;
220
232
  border-radius: var(--radius-sm);
221
233
  background: var(--tone-bg);
@@ -223,7 +235,7 @@
223
235
  }
224
236
 
225
237
  /* ---- Checklist: checks passed or failed, two columns when there is room ---- */
226
- .mkt .checklist {
238
+ :is(.mkt, .atelic-ui) .checklist {
227
239
  list-style: none;
228
240
  margin: 0;
229
241
  padding: 0;
@@ -232,36 +244,36 @@
232
244
  gap: 12px 28px;
233
245
  }
234
246
  @media print, (min-width: 721px) {
235
- .mkt .checklist {
247
+ :is(.mkt, .atelic-ui) .checklist {
236
248
  grid-template-columns: repeat(2, minmax(0, 1fr));
237
249
  }
238
250
  }
239
- .mkt .checklist li {
251
+ :is(.mkt, .atelic-ui) .checklist li {
240
252
  display: grid;
241
253
  grid-template-columns: auto minmax(0, 1fr);
242
254
  gap: 10px;
243
255
  align-items: start;
244
256
  line-height: 1.4;
245
257
  }
246
- .mkt .checklist li > svg {
258
+ :is(.mkt, .atelic-ui) .checklist li > svg {
247
259
  margin-top: 0.1em;
248
260
  color: var(--tone);
249
261
  }
250
- .mkt .checklist-label {
262
+ :is(.mkt, .atelic-ui) .checklist-label {
251
263
  display: block;
252
264
  font-weight: 600;
253
265
  color: var(--ink);
254
266
  }
255
- .mkt .checklist li[data-tone="bad"] .checklist-label {
267
+ :is(.mkt, .atelic-ui) .checklist li[data-tone="bad"] .checklist-label {
256
268
  color: var(--tone);
257
269
  }
258
- .mkt .checklist-detail {
270
+ :is(.mkt, .atelic-ui) .checklist-detail {
259
271
  display: block;
260
272
  color: var(--ink-soft);
261
273
  }
262
274
 
263
275
  /* ---- The charts' shared key: a swatch, a figure, a label ---- */
264
- .mkt .chart-key {
276
+ :is(.mkt, .atelic-ui) .chart-key {
265
277
  list-style: none;
266
278
  margin: 10px 0 0;
267
279
  padding: 0;
@@ -271,17 +283,17 @@
271
283
  font-size: 0.82rem;
272
284
  color: var(--ink-soft);
273
285
  }
274
- .mkt .chart-key li {
286
+ :is(.mkt, .atelic-ui) .chart-key li {
275
287
  display: inline-flex;
276
288
  align-items: baseline;
277
289
  gap: 7px;
278
290
  }
279
- .mkt .chart-key b {
291
+ :is(.mkt, .atelic-ui) .chart-key b {
280
292
  font-weight: 650;
281
293
  color: var(--ink);
282
294
  font-variant-numeric: tabular-nums;
283
295
  }
284
- .mkt .chart-swatch {
296
+ :is(.mkt, .atelic-ui) .chart-swatch {
285
297
  width: 10px;
286
298
  height: 10px;
287
299
  border-radius: 3px;
@@ -291,35 +303,35 @@
291
303
  }
292
304
 
293
305
  /* ---- StackedBar: one bar, the parts of a whole ---- */
294
- .mkt .stacked-bar-track {
306
+ :is(.mkt, .atelic-ui) .stacked-bar-track {
295
307
  display: flex;
296
308
  gap: 2px;
297
309
  height: 16px;
298
310
  border-radius: 999px;
299
311
  overflow: hidden;
300
312
  }
301
- .mkt .stacked-bar-track span {
313
+ :is(.mkt, .atelic-ui) .stacked-bar-track span {
302
314
  background: var(--tone-fill);
303
315
  min-width: 4px;
304
316
  }
305
317
 
306
318
  /* ---- ColumnChart: a bar a period, the periods in labeled groups ---- */
307
- .mkt .column-chart-plot {
319
+ :is(.mkt, .atelic-ui) .column-chart-plot {
308
320
  display: flex;
309
321
  align-items: flex-end;
310
322
  gap: 12px;
311
323
  min-width: 0;
312
324
  }
313
- .mkt .column-chart-group {
325
+ :is(.mkt, .atelic-ui) .column-chart-group {
314
326
  flex: 1 1 0;
315
327
  min-width: 0;
316
328
  }
317
- .mkt .column-chart-bars {
329
+ :is(.mkt, .atelic-ui) .column-chart-bars {
318
330
  display: flex;
319
331
  align-items: flex-end;
320
332
  gap: 3px;
321
333
  }
322
- .mkt .column-chart-col {
334
+ :is(.mkt, .atelic-ui) .column-chart-col {
323
335
  flex: 1 1 0;
324
336
  min-width: 0;
325
337
  display: flex;
@@ -327,24 +339,24 @@
327
339
  align-items: center;
328
340
  gap: 3px;
329
341
  }
330
- .mkt .column-chart-value {
342
+ :is(.mkt, .atelic-ui) .column-chart-value {
331
343
  font-size: 0.64rem;
332
344
  font-variant-numeric: tabular-nums;
333
345
  color: var(--ink-soft);
334
346
  white-space: nowrap;
335
347
  }
336
- .mkt .column-chart-bar {
348
+ :is(.mkt, .atelic-ui) .column-chart-bar {
337
349
  width: 100%;
338
350
  max-width: 48px;
339
351
  border-radius: 4px 4px 0 0;
340
352
  background: var(--tone-fill);
341
353
  }
342
- .mkt .column-chart-label {
354
+ :is(.mkt, .atelic-ui) .column-chart-label {
343
355
  font-size: 0.66rem;
344
356
  color: var(--ink-soft);
345
357
  white-space: nowrap;
346
358
  }
347
- .mkt .column-chart-group-label {
359
+ :is(.mkt, .atelic-ui) .column-chart-group-label {
348
360
  display: flex;
349
361
  flex-wrap: wrap;
350
362
  justify-content: center;
@@ -358,7 +370,7 @@
358
370
  color: var(--neutral-500);
359
371
  white-space: nowrap;
360
372
  }
361
- .mkt .column-chart-group-label b {
373
+ :is(.mkt, .atelic-ui) .column-chart-group-label b {
362
374
  font-family: var(--font-sans);
363
375
  font-size: 0.8rem;
364
376
  letter-spacing: 0;
@@ -368,37 +380,37 @@
368
380
  }
369
381
 
370
382
  /* ---- ThresholdScale: zones, and a pin a reading ---- */
371
- .mkt .threshold-scale {
383
+ :is(.mkt, .atelic-ui) .threshold-scale {
372
384
  display: flex;
373
385
  flex-direction: column;
374
386
  gap: 10px;
375
387
  }
376
- .mkt .threshold-scale-row {
388
+ :is(.mkt, .atelic-ui) .threshold-scale-row {
377
389
  display: grid;
378
390
  grid-template-columns: 4.4em minmax(0, 1fr) 3.4em;
379
391
  gap: 10px;
380
392
  align-items: center;
381
393
  }
382
- .mkt .threshold-scale-label {
394
+ :is(.mkt, .atelic-ui) .threshold-scale-label {
383
395
  color: var(--ink-soft);
384
396
  }
385
- .mkt .threshold-scale-track {
397
+ :is(.mkt, .atelic-ui) .threshold-scale-track {
386
398
  position: relative;
387
399
  display: flex;
388
400
  gap: 2px;
389
401
  height: 12px;
390
402
  }
391
- .mkt .threshold-scale-zone {
403
+ :is(.mkt, .atelic-ui) .threshold-scale-zone {
392
404
  background: var(--tone-fill);
393
405
  opacity: 0.32;
394
406
  }
395
- .mkt .threshold-scale-zone:first-child {
407
+ :is(.mkt, .atelic-ui) .threshold-scale-zone:first-child {
396
408
  border-radius: 999px 0 0 999px;
397
409
  }
398
- .mkt .threshold-scale-zone:nth-last-child(2) {
410
+ :is(.mkt, .atelic-ui) .threshold-scale-zone:nth-last-child(2) {
399
411
  border-radius: 0 999px 999px 0;
400
412
  }
401
- .mkt .threshold-scale-pin {
413
+ :is(.mkt, .atelic-ui) .threshold-scale-pin {
402
414
  position: absolute;
403
415
  top: 50%;
404
416
  width: 18px;
@@ -406,30 +418,30 @@
406
418
  margin: -9px 0 0 -9px;
407
419
  border-radius: 50%;
408
420
  background: var(--tone-fill);
409
- border: 3px solid var(--card);
421
+ border: 3px solid var(--ui-card, var(--card));
410
422
  box-shadow: 0 0 0 1.5px var(--tone-fill);
411
423
  }
412
- .mkt .threshold-scale-value {
424
+ :is(.mkt, .atelic-ui) .threshold-scale-value {
413
425
  font-weight: 700;
414
426
  font-variant-numeric: tabular-nums;
415
427
  color: var(--tone);
416
428
  text-align: right;
417
429
  }
418
- .mkt .threshold-scale-axis {
430
+ :is(.mkt, .atelic-ui) .threshold-scale-axis {
419
431
  position: relative;
420
432
  display: flex;
421
433
  gap: 2px;
422
434
  height: 2.3em;
423
435
  font-size: 0.8rem;
424
436
  }
425
- .mkt .threshold-scale-axis > span {
437
+ :is(.mkt, .atelic-ui) .threshold-scale-axis > span {
426
438
  color: var(--tone);
427
439
  font-weight: 600;
428
440
  white-space: nowrap;
429
441
  overflow: hidden;
430
442
  text-overflow: ellipsis;
431
443
  }
432
- .mkt .threshold-scale-axis > i {
444
+ :is(.mkt, .atelic-ui) .threshold-scale-axis > i {
433
445
  position: absolute;
434
446
  top: 1.25em;
435
447
  transform: translateX(-50%);
@@ -443,12 +455,12 @@
443
455
  /* ---- DataTable: on a phone each row stacks, its facts wearing their
444
456
  column's label, and a dropdown sorts; wide, it is a table whose
445
457
  headings sort ---- */
446
- .mkt .data-table table,
447
- .mkt .data-table tbody {
458
+ :is(.mkt, .atelic-ui) .data-table table,
459
+ :is(.mkt, .atelic-ui) .data-table tbody {
448
460
  display: block;
449
461
  width: 100%;
450
462
  }
451
- .mkt .data-table thead {
463
+ :is(.mkt, .atelic-ui) .data-table thead {
452
464
  position: absolute;
453
465
  width: 1px;
454
466
  height: 1px;
@@ -456,7 +468,7 @@
456
468
  clip: rect(0, 0, 0, 0);
457
469
  white-space: nowrap;
458
470
  }
459
- .mkt .data-table-sort {
471
+ :is(.mkt, .atelic-ui) .data-table-sort {
460
472
  display: flex;
461
473
  align-items: center;
462
474
  gap: 8px;
@@ -464,16 +476,16 @@
464
476
  font-size: 0.85rem;
465
477
  color: var(--ink-soft);
466
478
  }
467
- .mkt .data-table-sort select {
479
+ :is(.mkt, .atelic-ui) .data-table-sort select {
468
480
  font: inherit;
469
481
  color: var(--ink);
470
- background: var(--card);
482
+ background: var(--ui-card, var(--card));
471
483
  border: 1px solid var(--neutral-200);
472
484
  border-radius: var(--radius-sm);
473
485
  padding: 5px 8px;
474
486
  max-width: 100%;
475
487
  }
476
- .mkt .data-table tbody tr {
488
+ :is(.mkt, .atelic-ui) .data-table tbody tr {
477
489
  display: flex;
478
490
  flex-wrap: wrap;
479
491
  align-items: center;
@@ -482,25 +494,25 @@
482
494
  border-bottom: 1px solid var(--neutral-100);
483
495
  line-height: 1.35;
484
496
  }
485
- .mkt .data-table tbody tr:first-child {
497
+ :is(.mkt, .atelic-ui) .data-table tbody tr:first-child {
486
498
  border-top: 1.5px solid var(--ink);
487
499
  }
488
- .mkt .data-table tbody tr:last-child {
500
+ :is(.mkt, .atelic-ui) .data-table tbody tr:last-child {
489
501
  border-bottom: 0;
490
502
  padding-bottom: 0;
491
503
  }
492
- .mkt .data-table tbody th {
504
+ :is(.mkt, .atelic-ui) .data-table tbody th {
493
505
  width: 100%;
494
506
  text-align: left;
495
507
  font-weight: 400;
496
508
  }
497
- .mkt .data-table td {
509
+ :is(.mkt, .atelic-ui) .data-table td {
498
510
  display: inline-flex;
499
511
  align-items: center;
500
512
  gap: 6px;
501
513
  font-variant-numeric: tabular-nums;
502
514
  }
503
- .mkt .data-table td::before {
515
+ :is(.mkt, .atelic-ui) .data-table td::before {
504
516
  content: attr(data-label);
505
517
  font-family: var(--font-mono);
506
518
  font-size: 0.7rem;
@@ -509,33 +521,33 @@
509
521
  color: var(--neutral-500);
510
522
  }
511
523
  @media print, (min-width: 721px) {
512
- .mkt .data-table-sort {
524
+ :is(.mkt, .atelic-ui) .data-table-sort {
513
525
  display: none;
514
526
  }
515
- .mkt .data-table table {
527
+ :is(.mkt, .atelic-ui) .data-table table {
516
528
  display: table;
517
529
  border-collapse: collapse;
518
530
  }
519
- .mkt .data-table tbody {
531
+ :is(.mkt, .atelic-ui) .data-table tbody {
520
532
  display: table-row-group;
521
533
  }
522
- .mkt .data-table thead {
534
+ :is(.mkt, .atelic-ui) .data-table thead {
523
535
  position: static;
524
536
  width: auto;
525
537
  height: auto;
526
538
  overflow: visible;
527
539
  clip: auto;
528
540
  }
529
- .mkt .data-table tbody tr {
541
+ :is(.mkt, .atelic-ui) .data-table tbody tr {
530
542
  display: table-row;
531
543
  padding: 0;
532
544
  border: 0;
533
545
  }
534
- .mkt .data-table tbody tr:first-child {
546
+ :is(.mkt, .atelic-ui) .data-table tbody tr:first-child {
535
547
  border-top: 0;
536
548
  }
537
- .mkt .data-table th,
538
- .mkt .data-table td {
549
+ :is(.mkt, .atelic-ui) .data-table th,
550
+ :is(.mkt, .atelic-ui) .data-table td {
539
551
  display: table-cell;
540
552
  padding: 7px 14px 7px 0;
541
553
  border-bottom: 1px solid var(--neutral-100);
@@ -543,23 +555,23 @@
543
555
  vertical-align: middle;
544
556
  font-weight: 400;
545
557
  }
546
- .mkt .data-table tbody th {
558
+ :is(.mkt, .atelic-ui) .data-table tbody th {
547
559
  width: auto;
548
560
  }
549
- .mkt .data-table td::before {
561
+ :is(.mkt, .atelic-ui) .data-table td::before {
550
562
  content: none;
551
563
  }
552
- .mkt .data-table th:last-child,
553
- .mkt .data-table td:last-child {
564
+ :is(.mkt, .atelic-ui) .data-table th:last-child,
565
+ :is(.mkt, .atelic-ui) .data-table td:last-child {
554
566
  padding-right: 0;
555
567
  }
556
- .mkt .data-table [data-align="center"] {
568
+ :is(.mkt, .atelic-ui) .data-table [data-align="center"] {
557
569
  text-align: center;
558
570
  }
559
- .mkt .data-table [data-align="right"] {
571
+ :is(.mkt, .atelic-ui) .data-table [data-align="right"] {
560
572
  text-align: right;
561
573
  }
562
- .mkt .data-table thead th {
574
+ :is(.mkt, .atelic-ui) .data-table thead th {
563
575
  padding-top: 0;
564
576
  padding-bottom: 8px;
565
577
  border-bottom: 1.5px solid var(--ink);
@@ -571,7 +583,7 @@
571
583
  white-space: nowrap;
572
584
  vertical-align: bottom;
573
585
  }
574
- .mkt .data-table thead th button {
586
+ :is(.mkt, .atelic-ui) .data-table thead th button {
575
587
  display: inline-flex;
576
588
  align-items: center;
577
589
  gap: 4px;
@@ -584,23 +596,23 @@
584
596
  color: inherit;
585
597
  cursor: pointer;
586
598
  }
587
- .mkt .data-table thead th button:hover,
588
- .mkt .data-table thead th button[data-active] {
589
- color: var(--primary);
599
+ :is(.mkt, .atelic-ui) .data-table thead th button:hover,
600
+ :is(.mkt, .atelic-ui) .data-table thead th button[data-active] {
601
+ color: var(--ui-primary, var(--primary));
590
602
  }
591
- .mkt .data-table thead th button svg {
603
+ :is(.mkt, .atelic-ui) .data-table thead th button svg {
592
604
  opacity: 0.55;
593
605
  }
594
- .mkt .data-table thead th button[data-active] svg {
606
+ :is(.mkt, .atelic-ui) .data-table thead th button[data-active] svg {
595
607
  opacity: 1;
596
608
  }
597
- .mkt .data-table tbody tr:last-child th,
598
- .mkt .data-table tbody tr:last-child td {
609
+ :is(.mkt, .atelic-ui) .data-table tbody tr:last-child th,
610
+ :is(.mkt, .atelic-ui) .data-table tbody tr:last-child td {
599
611
  border-bottom: 0;
600
612
  }
601
613
  }
602
614
  @media print {
603
- .mkt .data-table thead th button svg {
615
+ :is(.mkt, .atelic-ui) .data-table thead th button svg {
604
616
  display: none;
605
617
  }
606
618
  }