@atelic-action/ui 0.9.0 → 0.11.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 +45 -2
- package/package.json +1 -1
- package/src/components/Disclosure.tsx +73 -0
- package/src/components/StackedBar.tsx +25 -12
- package/src/components/StatRow.tsx +16 -2
- package/src/components/index.ts +1 -0
- package/src/styles/components.css +236 -116
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ The package sheets sit inside `@layer atelic-ui`, so any rule a site writes outs
|
|
|
41
41
|
| Import | Exports |
|
|
42
42
|
|---|---|
|
|
43
43
|
| `@atelic-action/ui/chrome` | `SiteHeader`, `SiteMenu`, `Footer`, `CreditBar`, `StickyCTABar`, `BrandLockup`, `SkipLink`, and their prop types |
|
|
44
|
-
| `@atelic-action/ui/components` | `NotFound` and the page components (`Checklist`, `DataTable`, `StatRow`, `Callout`, `Collapsible`, `StackedBar`, `ColumnChart`, `ThresholdScale`, `StarRating`), with their prop types (see [The Not Found Page](#the-not-found-page) and [Page Components](#page-components)) |
|
|
44
|
+
| `@atelic-action/ui/components` | `NotFound` and the page components (`Checklist`, `DataTable`, `StatRow`, `Callout`, `Collapsible`, `StackedBar`, `ColumnChart`, `ThresholdScale`, `StarRating`, `Disclosure`), with their prop types (see [The Not Found Page](#the-not-found-page) and [Page Components](#page-components)) |
|
|
45
45
|
| `@atelic-action/ui/email` | The email components, the theme provider, the plain text helpers, and their prop types (see [Email](#email)) |
|
|
46
46
|
| `@atelic-action/ui/email/render` | `renderEmail` and `renderFailureEmail`, the only entry that imports `react-dom/server` |
|
|
47
47
|
| `@atelic-action/ui/tokens` | `Palette`, `atelicPalette`, `Fonts`, `atelicFonts`, `toThemeCSS`, `themeTokenMap` |
|
|
@@ -256,8 +256,9 @@ The blocks a page composes, each styled in `styles/components.css` inside the `a
|
|
|
256
256
|
|---|---|---|
|
|
257
257
|
| `Checklist` | A short list of checks, each passed or failed | Two columns when there is room, one on a phone. `passLabel` and `failLabel` name the icons for a screen reader |
|
|
258
258
|
| `DataTable` | A table whose first column names each row, sortable by any column marked `sortable` | A click on a heading sorts on a wide screen. On a phone each row stacks, every fact wearing its column's label, and a dropdown sorts. A cell is a node, or `{ display, sort }` when what it shows is not what it sorts by; a formatted number in a string (`"$12,047"`, `"0.24%"`) sorts as a number. It renders in `defaultSort` on the server |
|
|
259
|
-
| `StatRow` | A row of large figures, each over what it counts and its `period` | `trend` draws an arrow before a figure that is itself a change. `deltas` list comparisons beneath: an arrow, how far, against what (`basis`), and the earlier figure (`was`), each in its own tone, since a spend falling and a cost falling read differently |
|
|
259
|
+
| `StatRow` | A row of large figures, each over what it counts and its `period`. `variant="quiet"` is the glance row for a working page: a light figure in the text color over a small capitalized label, hairlines between; `unit` sets a figure's unit small beside it | `trend` draws an arrow before a figure that is itself a change. `deltas` list comparisons beneath: an arrow, how far, against what (`basis`), and the earlier figure (`was`), each in its own tone, since a spend falling and a cost falling read differently |
|
|
260
260
|
| `Callout` | One finding: an icon in its tone beside the title, the explainer under it | `variant="box"` sets it apart on a tinted ground, for something missing or owed |
|
|
261
|
+
| `Disclosure` | A section the page opens and closes: a header row that folds a body the caller controls | For an app. The caller holds `open`, so it can remember what was folded, and a closed body is not rendered. The label is the toggle; `meta` (a count, a flag) sits beside it, outside its name, and a tap on it still folds. `headingLevel` makes the label a real heading |
|
|
261
262
|
| `Collapsible` | A labeled line the reader opens for the detail behind it | A native `details`, so it works before any script loads and find in page opens it. `summary` carries the point, so the detail needs no explaining once open. It prints open |
|
|
262
263
|
| `StackedBar` | One bar split into the parts of a whole, with a key | A part of zero is keyed and not drawn |
|
|
263
264
|
| `ColumnChart` | A bar a period, the periods in groups that carry a label and a total | Months in quarters is the case it was cut for: a quarter reads against the one before it and the same one a year earlier |
|
|
@@ -266,8 +267,50 @@ The blocks a page composes, each styled in `styles/components.css` inside the `a
|
|
|
266
267
|
|
|
267
268
|
**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
269
|
|
|
270
|
+
**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.
|
|
271
|
+
|
|
269
272
|
**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
273
|
|
|
274
|
+
## In an App
|
|
275
|
+
|
|
276
|
+
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):
|
|
277
|
+
|
|
278
|
+
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.
|
|
279
|
+
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 the app **must declare the layer order before any stylesheet loads**, in a `<style>` in the `<head>` of its `index.html`: `@layer properties, theme, base, atelic-ui, components, utilities;`. A layer ranks by where it is first named, and a bundler is free to name the package's first, which ranks it below Tailwind's reset; the reset then strips the padding, margins, and borders off every component, while colors and type still look right, so it is easy to miss. Named there, the package ranks above the reset and below the app's utilities.
|
|
280
|
+
3. **The app maps its tokens** onto the ones the components read, in its own stylesheet on the same scope:
|
|
281
|
+
|
|
282
|
+
| Token | What it colors |
|
|
283
|
+
|---|---|
|
|
284
|
+
| `--ink`, `--ink-soft` | Text and quieter text |
|
|
285
|
+
| `--neutral-100`, `--neutral-200`, `--neutral-500` | Hairlines, tracks, and captions |
|
|
286
|
+
| `--surface-alt` | The quiet ground behind a muted tone |
|
|
287
|
+
| `--ui-primary` (falls back to `--primary`), `--primary-bright`, `--primary-tint` | The accent, its brighter fill, and its tint |
|
|
288
|
+
| `--ui-card` (falls back to `--card`) | A raised surface |
|
|
289
|
+
| `--font-sans`, `--font-mono`, `--radius-sm` | Type and the small radius |
|
|
290
|
+
| `--tone-good`, `--tone-warn`, `--tone-bad`, each with `-fill` and `-bg` | Optional: the package defines these, and a dark theme restates them |
|
|
291
|
+
|
|
292
|
+
`--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.
|
|
293
|
+
|
|
294
|
+
```css
|
|
295
|
+
/* app.css */
|
|
296
|
+
.atelic-ui {
|
|
297
|
+
--ink: hsl(var(--foreground));
|
|
298
|
+
--ink-soft: hsl(var(--muted-foreground));
|
|
299
|
+
--neutral-500: hsl(var(--muted-foreground));
|
|
300
|
+
--neutral-200: hsl(var(--border));
|
|
301
|
+
--neutral-100: hsl(var(--muted));
|
|
302
|
+
--surface-alt: hsl(var(--muted));
|
|
303
|
+
--ui-primary: hsl(var(--brand));
|
|
304
|
+
--primary-bright: hsl(var(--brand));
|
|
305
|
+
--primary-tint: color-mix(in srgb, hsl(var(--brand)) 12%, transparent);
|
|
306
|
+
--ui-card: hsl(var(--card));
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**Unit tests.** The package ships TSX source, and Vitest compiles it like any other module. A file under `node_modules` has no tsconfig of its own to name a JSX runtime, so a test that renders a package component fails with `React is not defined` until the test config says which to use: `esbuild: { jsx: "automatic" }` at the top level of `vitest.config.ts`. The app build needs nothing, since the React plugin sets it for Vite.
|
|
311
|
+
|
|
312
|
+
`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.
|
|
313
|
+
|
|
271
314
|
## The Gallery
|
|
272
315
|
|
|
273
316
|
`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
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { ChevronDown } from "lucide-react";
|
|
2
|
+
import { type ReactNode, useId } from "react";
|
|
3
|
+
|
|
4
|
+
export interface DisclosureProps {
|
|
5
|
+
/** What the section is, and the toggle's accessible name. */
|
|
6
|
+
label: ReactNode;
|
|
7
|
+
open: boolean;
|
|
8
|
+
onToggle: () => void;
|
|
9
|
+
/**
|
|
10
|
+
* Sits beside the label and outside the toggle's name: a count, a flag, a
|
|
11
|
+
* small chart. A tap on it still folds the section.
|
|
12
|
+
*/
|
|
13
|
+
meta?: ReactNode;
|
|
14
|
+
/** Makes the label a real heading at this level; leave it out for none. */
|
|
15
|
+
headingLevel?: 2 | 3 | 4 | 5 | 6;
|
|
16
|
+
/** The panel's id; minted when left out. */
|
|
17
|
+
panelId?: string;
|
|
18
|
+
className?: string;
|
|
19
|
+
children: ReactNode;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A section the page opens and closes: a header row that folds a body the
|
|
24
|
+
* caller controls. Where `Collapsible` is a native details element that keeps
|
|
25
|
+
* its own state and its detail in the page, this one is for an app. The
|
|
26
|
+
* caller holds `open`, so it can remember which sections were folded, and a
|
|
27
|
+
* closed body is not rendered, so a long list costs nothing until asked for.
|
|
28
|
+
*
|
|
29
|
+
* The label is the toggle, so its name reads "Produce, collapsed" and not
|
|
30
|
+
* "Produce 10 items"; `meta` is a sibling for that reason. The toggle's
|
|
31
|
+
* `::after` stretches over the whole header row, so a tap anywhere on it,
|
|
32
|
+
* meta and chevron included, folds the section.
|
|
33
|
+
*/
|
|
34
|
+
export function Disclosure({
|
|
35
|
+
label,
|
|
36
|
+
open,
|
|
37
|
+
onToggle,
|
|
38
|
+
meta,
|
|
39
|
+
headingLevel,
|
|
40
|
+
panelId,
|
|
41
|
+
className,
|
|
42
|
+
children,
|
|
43
|
+
}: DisclosureProps) {
|
|
44
|
+
const minted = useId();
|
|
45
|
+
const id = panelId ?? minted;
|
|
46
|
+
const Root = headingLevel ? "section" : "div";
|
|
47
|
+
const Title = headingLevel ? (`h${headingLevel}` as const) : "div";
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Root className={["disclosure", open && "is-open", className].filter(Boolean).join(" ")}>
|
|
51
|
+
<div className="disclosure-head">
|
|
52
|
+
<Title className="disclosure-title">
|
|
53
|
+
<button
|
|
54
|
+
type="button"
|
|
55
|
+
className="disclosure-toggle"
|
|
56
|
+
onClick={onToggle}
|
|
57
|
+
aria-expanded={open}
|
|
58
|
+
aria-controls={id}
|
|
59
|
+
>
|
|
60
|
+
{label}
|
|
61
|
+
</button>
|
|
62
|
+
</Title>
|
|
63
|
+
{meta != null && meta !== false && <span className="disclosure-meta">{meta}</span>}
|
|
64
|
+
<ChevronDown className="disclosure-chevron" size={16} aria-hidden="true" />
|
|
65
|
+
</div>
|
|
66
|
+
{open && (
|
|
67
|
+
<div className="disclosure-body" id={id}>
|
|
68
|
+
{children}
|
|
69
|
+
</div>
|
|
70
|
+
)}
|
|
71
|
+
</Root>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
@@ -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
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
}
|
|
@@ -22,6 +22,8 @@ export interface StatDelta {
|
|
|
22
22
|
export interface StatItem {
|
|
23
23
|
/** The big figure, e.g. "$199", "3,948", "23%"; may embed an inline glyph. */
|
|
24
24
|
value: ReactNode;
|
|
25
|
+
/** The figure's unit, set small after it on the same baseline, e.g. "mi". */
|
|
26
|
+
unit?: ReactNode;
|
|
25
27
|
/** An arrow before the figure, when the figure is itself a change. */
|
|
26
28
|
trend?: StatDirection;
|
|
27
29
|
/** What the figure counts. */
|
|
@@ -38,6 +40,13 @@ export interface StatItem {
|
|
|
38
40
|
|
|
39
41
|
export interface StatRowProps {
|
|
40
42
|
stats: StatItem[];
|
|
43
|
+
/**
|
|
44
|
+
* How loud the row is. `loud`, the default, is a report's headline figures:
|
|
45
|
+
* heavy, large, in the accent. `quiet` is a glance row for a working page:
|
|
46
|
+
* a light figure in the text color over a small capitalized label, the
|
|
47
|
+
* stats divided by a hairline. A tone still colors a quiet figure.
|
|
48
|
+
*/
|
|
49
|
+
variant?: "loud" | "quiet";
|
|
41
50
|
className?: string;
|
|
42
51
|
}
|
|
43
52
|
|
|
@@ -50,9 +59,13 @@ const spoken = { up: "Up", down: "Down", flat: "Unchanged" } as const;
|
|
|
50
59
|
* closes the stat, with the period it covers. The row wraps to as many
|
|
51
60
|
* columns as fit, and arrows are read aloud as up or down.
|
|
52
61
|
*/
|
|
53
|
-
export function StatRow({ stats, className }: StatRowProps) {
|
|
62
|
+
export function StatRow({ stats, variant = "loud", className }: StatRowProps) {
|
|
54
63
|
return (
|
|
55
|
-
<div
|
|
64
|
+
<div
|
|
65
|
+
className={["stat-row", variant === "quiet" && "is-quiet", className]
|
|
66
|
+
.filter(Boolean)
|
|
67
|
+
.join(" ")}
|
|
68
|
+
>
|
|
56
69
|
{stats.map((stat, i) => {
|
|
57
70
|
const Trend = stat.trend ? arrow[stat.trend] : null;
|
|
58
71
|
return (
|
|
@@ -63,6 +76,7 @@ export function StatRow({ stats, className }: StatRowProps) {
|
|
|
63
76
|
<Trend className="stat-trend" role="img" aria-label={spoken[stat.trend]} />
|
|
64
77
|
)}
|
|
65
78
|
{stat.value}
|
|
79
|
+
{stat.unit != null && <span className="stat-unit">{stat.unit}</span>}
|
|
66
80
|
</div>
|
|
67
81
|
{stat.deltas?.map((delta) => {
|
|
68
82
|
const Icon = arrow[delta.direction];
|
package/src/components/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ export {
|
|
|
16
16
|
type DataTableValueCell,
|
|
17
17
|
type SortDirection,
|
|
18
18
|
} from "./DataTable";
|
|
19
|
+
export { Disclosure, type DisclosureProps } from "./Disclosure";
|
|
19
20
|
export { NotFound, type NotFoundProps } from "./NotFound";
|
|
20
21
|
export { StackedBar, type StackedBarProps, type StackedBarSegment } from "./StackedBar";
|
|
21
22
|
export { describeStarRating, StarRating, type StarRatingProps } from "./StarRating";
|
|
@@ -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,135 @@
|
|
|
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
|
|
|
151
|
+
:is(.mkt, .atelic-ui) .stat-unit {
|
|
152
|
+
margin-left: 0.2em;
|
|
153
|
+
font-size: 0.4em;
|
|
154
|
+
font-weight: 500;
|
|
155
|
+
letter-spacing: 0;
|
|
156
|
+
color: var(--neutral-500);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* ---- StatRow, quiet: a glance row for a working page. A light figure in
|
|
160
|
+
the text color over a small capitalized label, the stats divided by a
|
|
161
|
+
hairline. `--stat-size` sets the figure. ---- */
|
|
162
|
+
:is(.mkt, .atelic-ui) .stat-row.is-quiet {
|
|
163
|
+
display: flex;
|
|
164
|
+
gap: 0;
|
|
165
|
+
}
|
|
166
|
+
:is(.mkt, .atelic-ui) .stat-row.is-quiet .stat {
|
|
167
|
+
flex: 1;
|
|
168
|
+
min-width: 64px;
|
|
169
|
+
padding-right: 16px;
|
|
170
|
+
}
|
|
171
|
+
:is(.mkt, .atelic-ui) .stat-row.is-quiet .stat + .stat {
|
|
172
|
+
padding-left: 16px;
|
|
173
|
+
border-left: 1px solid var(--neutral-200);
|
|
174
|
+
}
|
|
175
|
+
:is(.mkt, .atelic-ui) .stat-row.is-quiet .stat .num {
|
|
176
|
+
align-items: baseline;
|
|
177
|
+
gap: 4px;
|
|
178
|
+
font: 300 var(--stat-size, 28px) / 1 var(--font-sans);
|
|
179
|
+
/* After the shorthand, which would otherwise reset it. */
|
|
180
|
+
font-variant-numeric: tabular-nums;
|
|
181
|
+
letter-spacing: -0.02em;
|
|
182
|
+
color: var(--tone, var(--ink));
|
|
183
|
+
}
|
|
184
|
+
:is(.mkt, .atelic-ui) .stat-row.is-quiet .stat-unit {
|
|
185
|
+
margin-left: 0;
|
|
186
|
+
font: 500 12px / 1 var(--font-mono);
|
|
187
|
+
}
|
|
188
|
+
:is(.mkt, .atelic-ui) .stat-row.is-quiet .stat .lbl {
|
|
189
|
+
margin-top: 7px;
|
|
190
|
+
font: 500 10px / 1.2 var(--font-sans);
|
|
191
|
+
letter-spacing: 0.1em;
|
|
192
|
+
text-transform: uppercase;
|
|
193
|
+
color: var(--neutral-500);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* ---- Disclosure: a section the page opens and closes. The toggle's
|
|
197
|
+
::after covers the whole header row, so the meta and the chevron fold
|
|
198
|
+
it too while staying out of its name. ---- */
|
|
199
|
+
:is(.mkt, .atelic-ui) .disclosure {
|
|
200
|
+
border: 1px solid var(--neutral-200);
|
|
201
|
+
border-radius: 16px;
|
|
202
|
+
background: var(--ui-card, var(--card));
|
|
203
|
+
overflow: hidden;
|
|
204
|
+
}
|
|
205
|
+
:is(.mkt, .atelic-ui) .disclosure-head {
|
|
206
|
+
position: relative;
|
|
207
|
+
display: flex;
|
|
208
|
+
align-items: center;
|
|
209
|
+
gap: 10px;
|
|
210
|
+
padding: 14px 18px;
|
|
211
|
+
}
|
|
212
|
+
:is(.mkt, .atelic-ui) .disclosure-title {
|
|
213
|
+
display: flex;
|
|
214
|
+
min-width: 0;
|
|
215
|
+
margin: 0;
|
|
216
|
+
font: inherit;
|
|
217
|
+
}
|
|
218
|
+
:is(.mkt, .atelic-ui) .disclosure-toggle {
|
|
219
|
+
border: none;
|
|
220
|
+
background: transparent;
|
|
221
|
+
padding: 0;
|
|
222
|
+
text-align: left;
|
|
223
|
+
font: 500 17px / 1 var(--font-sans);
|
|
224
|
+
letter-spacing: -0.01em;
|
|
225
|
+
color: var(--ink);
|
|
226
|
+
cursor: pointer;
|
|
227
|
+
}
|
|
228
|
+
:is(.mkt, .atelic-ui) .disclosure-toggle::after {
|
|
229
|
+
content: "";
|
|
230
|
+
position: absolute;
|
|
231
|
+
inset: 0;
|
|
232
|
+
}
|
|
233
|
+
:is(.mkt, .atelic-ui) .disclosure-toggle:focus-visible {
|
|
234
|
+
outline: none;
|
|
235
|
+
}
|
|
236
|
+
:is(.mkt, .atelic-ui) .disclosure-toggle:focus-visible::after {
|
|
237
|
+
outline: 2px solid var(--disclosure-focus, var(--ink));
|
|
238
|
+
outline-offset: -2px;
|
|
239
|
+
border-radius: 15px;
|
|
240
|
+
}
|
|
241
|
+
:is(.mkt, .atelic-ui) .disclosure-meta {
|
|
242
|
+
display: inline-flex;
|
|
243
|
+
align-items: center;
|
|
244
|
+
color: var(--neutral-500);
|
|
245
|
+
}
|
|
246
|
+
:is(.mkt, .atelic-ui) .disclosure-chevron {
|
|
247
|
+
margin-left: auto;
|
|
248
|
+
flex-shrink: 0;
|
|
249
|
+
color: var(--neutral-500);
|
|
250
|
+
transition: transform 200ms ease;
|
|
251
|
+
}
|
|
252
|
+
:is(.mkt, .atelic-ui) .disclosure.is-open .disclosure-chevron {
|
|
253
|
+
transform: rotate(180deg);
|
|
254
|
+
}
|
|
255
|
+
:is(.mkt, .atelic-ui) .disclosure-body {
|
|
256
|
+
border-top: 1px solid var(--neutral-200);
|
|
257
|
+
}
|
|
258
|
+
|
|
139
259
|
/* ---- Collapsible: a labeled line that opens to the detail behind it ---- */
|
|
140
|
-
.mkt .collapsible > summary {
|
|
260
|
+
:is(.mkt, .atelic-ui) .collapsible > summary {
|
|
141
261
|
display: flex;
|
|
142
262
|
align-items: center;
|
|
143
263
|
justify-content: space-between;
|
|
@@ -145,77 +265,77 @@
|
|
|
145
265
|
cursor: pointer;
|
|
146
266
|
list-style: none;
|
|
147
267
|
}
|
|
148
|
-
.mkt .collapsible > summary::-webkit-details-marker {
|
|
268
|
+
:is(.mkt, .atelic-ui) .collapsible > summary::-webkit-details-marker {
|
|
149
269
|
display: none;
|
|
150
270
|
}
|
|
151
|
-
.mkt .collapsible-text {
|
|
271
|
+
:is(.mkt, .atelic-ui) .collapsible-text {
|
|
152
272
|
display: flex;
|
|
153
273
|
flex-direction: column;
|
|
154
274
|
gap: 2px;
|
|
155
275
|
min-width: 0;
|
|
156
276
|
}
|
|
157
|
-
.mkt .collapsible-label {
|
|
277
|
+
:is(.mkt, .atelic-ui) .collapsible-label {
|
|
158
278
|
font-weight: 650;
|
|
159
279
|
color: var(--ink);
|
|
160
280
|
}
|
|
161
|
-
.mkt .collapsible-summary {
|
|
281
|
+
:is(.mkt, .atelic-ui) .collapsible-summary {
|
|
162
282
|
color: var(--ink-soft);
|
|
163
283
|
text-wrap: pretty;
|
|
164
284
|
}
|
|
165
|
-
.mkt .collapsible > summary:hover .collapsible-label {
|
|
166
|
-
color: var(--primary);
|
|
285
|
+
:is(.mkt, .atelic-ui) .collapsible > summary:hover .collapsible-label {
|
|
286
|
+
color: var(--ui-primary, var(--primary));
|
|
167
287
|
}
|
|
168
|
-
.mkt .collapsible-chevron {
|
|
288
|
+
:is(.mkt, .atelic-ui) .collapsible-chevron {
|
|
169
289
|
flex: none;
|
|
170
290
|
color: var(--neutral-500);
|
|
171
291
|
transition: transform 0.15s;
|
|
172
292
|
}
|
|
173
|
-
.mkt .collapsible[open] > summary .collapsible-chevron {
|
|
293
|
+
:is(.mkt, .atelic-ui) .collapsible[open] > summary .collapsible-chevron {
|
|
174
294
|
transform: rotate(180deg);
|
|
175
295
|
}
|
|
176
|
-
.mkt .collapsible-body {
|
|
296
|
+
:is(.mkt, .atelic-ui) .collapsible-body {
|
|
177
297
|
margin-top: 12px;
|
|
178
298
|
}
|
|
179
299
|
@media (prefers-reduced-motion: reduce) {
|
|
180
|
-
.mkt .collapsible-chevron {
|
|
300
|
+
:is(.mkt, .atelic-ui) .collapsible-chevron {
|
|
181
301
|
transition: none;
|
|
182
302
|
}
|
|
183
303
|
}
|
|
184
304
|
/* Paper cannot be clicked, so a printed collapsible is open. */
|
|
185
305
|
@media print {
|
|
186
|
-
.mkt .collapsible::details-content {
|
|
306
|
+
:is(.mkt, .atelic-ui) .collapsible::details-content {
|
|
187
307
|
content-visibility: visible;
|
|
188
308
|
display: block;
|
|
189
309
|
}
|
|
190
|
-
.mkt .collapsible-chevron {
|
|
310
|
+
:is(.mkt, .atelic-ui) .collapsible-chevron {
|
|
191
311
|
display: none;
|
|
192
312
|
}
|
|
193
313
|
}
|
|
194
314
|
|
|
195
315
|
/* ---- Callout: an icon in its tone beside the title, the explainer
|
|
196
316
|
under it; boxed, it sits apart on a tinted ground ---- */
|
|
197
|
-
.mkt .callout {
|
|
317
|
+
:is(.mkt, .atelic-ui) .callout {
|
|
198
318
|
display: grid;
|
|
199
319
|
grid-template-columns: auto minmax(0, 1fr);
|
|
200
320
|
gap: 10px;
|
|
201
321
|
align-items: start;
|
|
202
322
|
}
|
|
203
|
-
.mkt .callout-icon {
|
|
323
|
+
:is(.mkt, .atelic-ui) .callout-icon {
|
|
204
324
|
margin-top: 0.15em;
|
|
205
325
|
color: var(--tone);
|
|
206
326
|
flex: none;
|
|
207
327
|
}
|
|
208
|
-
.mkt .callout-title {
|
|
328
|
+
:is(.mkt, .atelic-ui) .callout-title {
|
|
209
329
|
font-weight: 650;
|
|
210
330
|
color: var(--ink);
|
|
211
331
|
text-wrap: pretty;
|
|
212
332
|
}
|
|
213
|
-
.mkt .callout-body {
|
|
333
|
+
:is(.mkt, .atelic-ui) .callout-body {
|
|
214
334
|
margin-top: 2px;
|
|
215
335
|
color: var(--ink-soft);
|
|
216
336
|
text-wrap: pretty;
|
|
217
337
|
}
|
|
218
|
-
.mkt .callout.is-box {
|
|
338
|
+
:is(.mkt, .atelic-ui) .callout.is-box {
|
|
219
339
|
padding: 14px 16px;
|
|
220
340
|
border-radius: var(--radius-sm);
|
|
221
341
|
background: var(--tone-bg);
|
|
@@ -223,7 +343,7 @@
|
|
|
223
343
|
}
|
|
224
344
|
|
|
225
345
|
/* ---- Checklist: checks passed or failed, two columns when there is room ---- */
|
|
226
|
-
.mkt .checklist {
|
|
346
|
+
:is(.mkt, .atelic-ui) .checklist {
|
|
227
347
|
list-style: none;
|
|
228
348
|
margin: 0;
|
|
229
349
|
padding: 0;
|
|
@@ -232,36 +352,36 @@
|
|
|
232
352
|
gap: 12px 28px;
|
|
233
353
|
}
|
|
234
354
|
@media print, (min-width: 721px) {
|
|
235
|
-
.mkt .checklist {
|
|
355
|
+
:is(.mkt, .atelic-ui) .checklist {
|
|
236
356
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
237
357
|
}
|
|
238
358
|
}
|
|
239
|
-
.mkt .checklist li {
|
|
359
|
+
:is(.mkt, .atelic-ui) .checklist li {
|
|
240
360
|
display: grid;
|
|
241
361
|
grid-template-columns: auto minmax(0, 1fr);
|
|
242
362
|
gap: 10px;
|
|
243
363
|
align-items: start;
|
|
244
364
|
line-height: 1.4;
|
|
245
365
|
}
|
|
246
|
-
.mkt .checklist li > svg {
|
|
366
|
+
:is(.mkt, .atelic-ui) .checklist li > svg {
|
|
247
367
|
margin-top: 0.1em;
|
|
248
368
|
color: var(--tone);
|
|
249
369
|
}
|
|
250
|
-
.mkt .checklist-label {
|
|
370
|
+
:is(.mkt, .atelic-ui) .checklist-label {
|
|
251
371
|
display: block;
|
|
252
372
|
font-weight: 600;
|
|
253
373
|
color: var(--ink);
|
|
254
374
|
}
|
|
255
|
-
.mkt .checklist li[data-tone="bad"] .checklist-label {
|
|
375
|
+
:is(.mkt, .atelic-ui) .checklist li[data-tone="bad"] .checklist-label {
|
|
256
376
|
color: var(--tone);
|
|
257
377
|
}
|
|
258
|
-
.mkt .checklist-detail {
|
|
378
|
+
:is(.mkt, .atelic-ui) .checklist-detail {
|
|
259
379
|
display: block;
|
|
260
380
|
color: var(--ink-soft);
|
|
261
381
|
}
|
|
262
382
|
|
|
263
383
|
/* ---- The charts' shared key: a swatch, a figure, a label ---- */
|
|
264
|
-
.mkt .chart-key {
|
|
384
|
+
:is(.mkt, .atelic-ui) .chart-key {
|
|
265
385
|
list-style: none;
|
|
266
386
|
margin: 10px 0 0;
|
|
267
387
|
padding: 0;
|
|
@@ -271,17 +391,17 @@
|
|
|
271
391
|
font-size: 0.82rem;
|
|
272
392
|
color: var(--ink-soft);
|
|
273
393
|
}
|
|
274
|
-
.mkt .chart-key li {
|
|
394
|
+
:is(.mkt, .atelic-ui) .chart-key li {
|
|
275
395
|
display: inline-flex;
|
|
276
396
|
align-items: baseline;
|
|
277
397
|
gap: 7px;
|
|
278
398
|
}
|
|
279
|
-
.mkt .chart-key b {
|
|
399
|
+
:is(.mkt, .atelic-ui) .chart-key b {
|
|
280
400
|
font-weight: 650;
|
|
281
401
|
color: var(--ink);
|
|
282
402
|
font-variant-numeric: tabular-nums;
|
|
283
403
|
}
|
|
284
|
-
.mkt .chart-swatch {
|
|
404
|
+
:is(.mkt, .atelic-ui) .chart-swatch {
|
|
285
405
|
width: 10px;
|
|
286
406
|
height: 10px;
|
|
287
407
|
border-radius: 3px;
|
|
@@ -291,35 +411,35 @@
|
|
|
291
411
|
}
|
|
292
412
|
|
|
293
413
|
/* ---- StackedBar: one bar, the parts of a whole ---- */
|
|
294
|
-
.mkt .stacked-bar-track {
|
|
414
|
+
:is(.mkt, .atelic-ui) .stacked-bar-track {
|
|
295
415
|
display: flex;
|
|
296
416
|
gap: 2px;
|
|
297
417
|
height: 16px;
|
|
298
418
|
border-radius: 999px;
|
|
299
419
|
overflow: hidden;
|
|
300
420
|
}
|
|
301
|
-
.mkt .stacked-bar-track span {
|
|
421
|
+
:is(.mkt, .atelic-ui) .stacked-bar-track span {
|
|
302
422
|
background: var(--tone-fill);
|
|
303
423
|
min-width: 4px;
|
|
304
424
|
}
|
|
305
425
|
|
|
306
426
|
/* ---- ColumnChart: a bar a period, the periods in labeled groups ---- */
|
|
307
|
-
.mkt .column-chart-plot {
|
|
427
|
+
:is(.mkt, .atelic-ui) .column-chart-plot {
|
|
308
428
|
display: flex;
|
|
309
429
|
align-items: flex-end;
|
|
310
430
|
gap: 12px;
|
|
311
431
|
min-width: 0;
|
|
312
432
|
}
|
|
313
|
-
.mkt .column-chart-group {
|
|
433
|
+
:is(.mkt, .atelic-ui) .column-chart-group {
|
|
314
434
|
flex: 1 1 0;
|
|
315
435
|
min-width: 0;
|
|
316
436
|
}
|
|
317
|
-
.mkt .column-chart-bars {
|
|
437
|
+
:is(.mkt, .atelic-ui) .column-chart-bars {
|
|
318
438
|
display: flex;
|
|
319
439
|
align-items: flex-end;
|
|
320
440
|
gap: 3px;
|
|
321
441
|
}
|
|
322
|
-
.mkt .column-chart-col {
|
|
442
|
+
:is(.mkt, .atelic-ui) .column-chart-col {
|
|
323
443
|
flex: 1 1 0;
|
|
324
444
|
min-width: 0;
|
|
325
445
|
display: flex;
|
|
@@ -327,24 +447,24 @@
|
|
|
327
447
|
align-items: center;
|
|
328
448
|
gap: 3px;
|
|
329
449
|
}
|
|
330
|
-
.mkt .column-chart-value {
|
|
450
|
+
:is(.mkt, .atelic-ui) .column-chart-value {
|
|
331
451
|
font-size: 0.64rem;
|
|
332
452
|
font-variant-numeric: tabular-nums;
|
|
333
453
|
color: var(--ink-soft);
|
|
334
454
|
white-space: nowrap;
|
|
335
455
|
}
|
|
336
|
-
.mkt .column-chart-bar {
|
|
456
|
+
:is(.mkt, .atelic-ui) .column-chart-bar {
|
|
337
457
|
width: 100%;
|
|
338
458
|
max-width: 48px;
|
|
339
459
|
border-radius: 4px 4px 0 0;
|
|
340
460
|
background: var(--tone-fill);
|
|
341
461
|
}
|
|
342
|
-
.mkt .column-chart-label {
|
|
462
|
+
:is(.mkt, .atelic-ui) .column-chart-label {
|
|
343
463
|
font-size: 0.66rem;
|
|
344
464
|
color: var(--ink-soft);
|
|
345
465
|
white-space: nowrap;
|
|
346
466
|
}
|
|
347
|
-
.mkt .column-chart-group-label {
|
|
467
|
+
:is(.mkt, .atelic-ui) .column-chart-group-label {
|
|
348
468
|
display: flex;
|
|
349
469
|
flex-wrap: wrap;
|
|
350
470
|
justify-content: center;
|
|
@@ -358,7 +478,7 @@
|
|
|
358
478
|
color: var(--neutral-500);
|
|
359
479
|
white-space: nowrap;
|
|
360
480
|
}
|
|
361
|
-
.mkt .column-chart-group-label b {
|
|
481
|
+
:is(.mkt, .atelic-ui) .column-chart-group-label b {
|
|
362
482
|
font-family: var(--font-sans);
|
|
363
483
|
font-size: 0.8rem;
|
|
364
484
|
letter-spacing: 0;
|
|
@@ -368,37 +488,37 @@
|
|
|
368
488
|
}
|
|
369
489
|
|
|
370
490
|
/* ---- ThresholdScale: zones, and a pin a reading ---- */
|
|
371
|
-
.mkt .threshold-scale {
|
|
491
|
+
:is(.mkt, .atelic-ui) .threshold-scale {
|
|
372
492
|
display: flex;
|
|
373
493
|
flex-direction: column;
|
|
374
494
|
gap: 10px;
|
|
375
495
|
}
|
|
376
|
-
.mkt .threshold-scale-row {
|
|
496
|
+
:is(.mkt, .atelic-ui) .threshold-scale-row {
|
|
377
497
|
display: grid;
|
|
378
498
|
grid-template-columns: 4.4em minmax(0, 1fr) 3.4em;
|
|
379
499
|
gap: 10px;
|
|
380
500
|
align-items: center;
|
|
381
501
|
}
|
|
382
|
-
.mkt .threshold-scale-label {
|
|
502
|
+
:is(.mkt, .atelic-ui) .threshold-scale-label {
|
|
383
503
|
color: var(--ink-soft);
|
|
384
504
|
}
|
|
385
|
-
.mkt .threshold-scale-track {
|
|
505
|
+
:is(.mkt, .atelic-ui) .threshold-scale-track {
|
|
386
506
|
position: relative;
|
|
387
507
|
display: flex;
|
|
388
508
|
gap: 2px;
|
|
389
509
|
height: 12px;
|
|
390
510
|
}
|
|
391
|
-
.mkt .threshold-scale-zone {
|
|
511
|
+
:is(.mkt, .atelic-ui) .threshold-scale-zone {
|
|
392
512
|
background: var(--tone-fill);
|
|
393
513
|
opacity: 0.32;
|
|
394
514
|
}
|
|
395
|
-
.mkt .threshold-scale-zone:first-child {
|
|
515
|
+
:is(.mkt, .atelic-ui) .threshold-scale-zone:first-child {
|
|
396
516
|
border-radius: 999px 0 0 999px;
|
|
397
517
|
}
|
|
398
|
-
.mkt .threshold-scale-zone:nth-last-child(2) {
|
|
518
|
+
:is(.mkt, .atelic-ui) .threshold-scale-zone:nth-last-child(2) {
|
|
399
519
|
border-radius: 0 999px 999px 0;
|
|
400
520
|
}
|
|
401
|
-
.mkt .threshold-scale-pin {
|
|
521
|
+
:is(.mkt, .atelic-ui) .threshold-scale-pin {
|
|
402
522
|
position: absolute;
|
|
403
523
|
top: 50%;
|
|
404
524
|
width: 18px;
|
|
@@ -406,30 +526,30 @@
|
|
|
406
526
|
margin: -9px 0 0 -9px;
|
|
407
527
|
border-radius: 50%;
|
|
408
528
|
background: var(--tone-fill);
|
|
409
|
-
border: 3px solid var(--card);
|
|
529
|
+
border: 3px solid var(--ui-card, var(--card));
|
|
410
530
|
box-shadow: 0 0 0 1.5px var(--tone-fill);
|
|
411
531
|
}
|
|
412
|
-
.mkt .threshold-scale-value {
|
|
532
|
+
:is(.mkt, .atelic-ui) .threshold-scale-value {
|
|
413
533
|
font-weight: 700;
|
|
414
534
|
font-variant-numeric: tabular-nums;
|
|
415
535
|
color: var(--tone);
|
|
416
536
|
text-align: right;
|
|
417
537
|
}
|
|
418
|
-
.mkt .threshold-scale-axis {
|
|
538
|
+
:is(.mkt, .atelic-ui) .threshold-scale-axis {
|
|
419
539
|
position: relative;
|
|
420
540
|
display: flex;
|
|
421
541
|
gap: 2px;
|
|
422
542
|
height: 2.3em;
|
|
423
543
|
font-size: 0.8rem;
|
|
424
544
|
}
|
|
425
|
-
.mkt .threshold-scale-axis > span {
|
|
545
|
+
:is(.mkt, .atelic-ui) .threshold-scale-axis > span {
|
|
426
546
|
color: var(--tone);
|
|
427
547
|
font-weight: 600;
|
|
428
548
|
white-space: nowrap;
|
|
429
549
|
overflow: hidden;
|
|
430
550
|
text-overflow: ellipsis;
|
|
431
551
|
}
|
|
432
|
-
.mkt .threshold-scale-axis > i {
|
|
552
|
+
:is(.mkt, .atelic-ui) .threshold-scale-axis > i {
|
|
433
553
|
position: absolute;
|
|
434
554
|
top: 1.25em;
|
|
435
555
|
transform: translateX(-50%);
|
|
@@ -443,12 +563,12 @@
|
|
|
443
563
|
/* ---- DataTable: on a phone each row stacks, its facts wearing their
|
|
444
564
|
column's label, and a dropdown sorts; wide, it is a table whose
|
|
445
565
|
headings sort ---- */
|
|
446
|
-
.mkt .data-table table,
|
|
447
|
-
.mkt .data-table tbody {
|
|
566
|
+
:is(.mkt, .atelic-ui) .data-table table,
|
|
567
|
+
:is(.mkt, .atelic-ui) .data-table tbody {
|
|
448
568
|
display: block;
|
|
449
569
|
width: 100%;
|
|
450
570
|
}
|
|
451
|
-
.mkt .data-table thead {
|
|
571
|
+
:is(.mkt, .atelic-ui) .data-table thead {
|
|
452
572
|
position: absolute;
|
|
453
573
|
width: 1px;
|
|
454
574
|
height: 1px;
|
|
@@ -456,7 +576,7 @@
|
|
|
456
576
|
clip: rect(0, 0, 0, 0);
|
|
457
577
|
white-space: nowrap;
|
|
458
578
|
}
|
|
459
|
-
.mkt .data-table-sort {
|
|
579
|
+
:is(.mkt, .atelic-ui) .data-table-sort {
|
|
460
580
|
display: flex;
|
|
461
581
|
align-items: center;
|
|
462
582
|
gap: 8px;
|
|
@@ -464,16 +584,16 @@
|
|
|
464
584
|
font-size: 0.85rem;
|
|
465
585
|
color: var(--ink-soft);
|
|
466
586
|
}
|
|
467
|
-
.mkt .data-table-sort select {
|
|
587
|
+
:is(.mkt, .atelic-ui) .data-table-sort select {
|
|
468
588
|
font: inherit;
|
|
469
589
|
color: var(--ink);
|
|
470
|
-
background: var(--card);
|
|
590
|
+
background: var(--ui-card, var(--card));
|
|
471
591
|
border: 1px solid var(--neutral-200);
|
|
472
592
|
border-radius: var(--radius-sm);
|
|
473
593
|
padding: 5px 8px;
|
|
474
594
|
max-width: 100%;
|
|
475
595
|
}
|
|
476
|
-
.mkt .data-table tbody tr {
|
|
596
|
+
:is(.mkt, .atelic-ui) .data-table tbody tr {
|
|
477
597
|
display: flex;
|
|
478
598
|
flex-wrap: wrap;
|
|
479
599
|
align-items: center;
|
|
@@ -482,25 +602,25 @@
|
|
|
482
602
|
border-bottom: 1px solid var(--neutral-100);
|
|
483
603
|
line-height: 1.35;
|
|
484
604
|
}
|
|
485
|
-
.mkt .data-table tbody tr:first-child {
|
|
605
|
+
:is(.mkt, .atelic-ui) .data-table tbody tr:first-child {
|
|
486
606
|
border-top: 1.5px solid var(--ink);
|
|
487
607
|
}
|
|
488
|
-
.mkt .data-table tbody tr:last-child {
|
|
608
|
+
:is(.mkt, .atelic-ui) .data-table tbody tr:last-child {
|
|
489
609
|
border-bottom: 0;
|
|
490
610
|
padding-bottom: 0;
|
|
491
611
|
}
|
|
492
|
-
.mkt .data-table tbody th {
|
|
612
|
+
:is(.mkt, .atelic-ui) .data-table tbody th {
|
|
493
613
|
width: 100%;
|
|
494
614
|
text-align: left;
|
|
495
615
|
font-weight: 400;
|
|
496
616
|
}
|
|
497
|
-
.mkt .data-table td {
|
|
617
|
+
:is(.mkt, .atelic-ui) .data-table td {
|
|
498
618
|
display: inline-flex;
|
|
499
619
|
align-items: center;
|
|
500
620
|
gap: 6px;
|
|
501
621
|
font-variant-numeric: tabular-nums;
|
|
502
622
|
}
|
|
503
|
-
.mkt .data-table td::before {
|
|
623
|
+
:is(.mkt, .atelic-ui) .data-table td::before {
|
|
504
624
|
content: attr(data-label);
|
|
505
625
|
font-family: var(--font-mono);
|
|
506
626
|
font-size: 0.7rem;
|
|
@@ -509,33 +629,33 @@
|
|
|
509
629
|
color: var(--neutral-500);
|
|
510
630
|
}
|
|
511
631
|
@media print, (min-width: 721px) {
|
|
512
|
-
.mkt .data-table-sort {
|
|
632
|
+
:is(.mkt, .atelic-ui) .data-table-sort {
|
|
513
633
|
display: none;
|
|
514
634
|
}
|
|
515
|
-
.mkt .data-table table {
|
|
635
|
+
:is(.mkt, .atelic-ui) .data-table table {
|
|
516
636
|
display: table;
|
|
517
637
|
border-collapse: collapse;
|
|
518
638
|
}
|
|
519
|
-
.mkt .data-table tbody {
|
|
639
|
+
:is(.mkt, .atelic-ui) .data-table tbody {
|
|
520
640
|
display: table-row-group;
|
|
521
641
|
}
|
|
522
|
-
.mkt .data-table thead {
|
|
642
|
+
:is(.mkt, .atelic-ui) .data-table thead {
|
|
523
643
|
position: static;
|
|
524
644
|
width: auto;
|
|
525
645
|
height: auto;
|
|
526
646
|
overflow: visible;
|
|
527
647
|
clip: auto;
|
|
528
648
|
}
|
|
529
|
-
.mkt .data-table tbody tr {
|
|
649
|
+
:is(.mkt, .atelic-ui) .data-table tbody tr {
|
|
530
650
|
display: table-row;
|
|
531
651
|
padding: 0;
|
|
532
652
|
border: 0;
|
|
533
653
|
}
|
|
534
|
-
.mkt .data-table tbody tr:first-child {
|
|
654
|
+
:is(.mkt, .atelic-ui) .data-table tbody tr:first-child {
|
|
535
655
|
border-top: 0;
|
|
536
656
|
}
|
|
537
|
-
.mkt .data-table th,
|
|
538
|
-
.mkt .data-table td {
|
|
657
|
+
:is(.mkt, .atelic-ui) .data-table th,
|
|
658
|
+
:is(.mkt, .atelic-ui) .data-table td {
|
|
539
659
|
display: table-cell;
|
|
540
660
|
padding: 7px 14px 7px 0;
|
|
541
661
|
border-bottom: 1px solid var(--neutral-100);
|
|
@@ -543,23 +663,23 @@
|
|
|
543
663
|
vertical-align: middle;
|
|
544
664
|
font-weight: 400;
|
|
545
665
|
}
|
|
546
|
-
.mkt .data-table tbody th {
|
|
666
|
+
:is(.mkt, .atelic-ui) .data-table tbody th {
|
|
547
667
|
width: auto;
|
|
548
668
|
}
|
|
549
|
-
.mkt .data-table td::before {
|
|
669
|
+
:is(.mkt, .atelic-ui) .data-table td::before {
|
|
550
670
|
content: none;
|
|
551
671
|
}
|
|
552
|
-
.mkt .data-table th:last-child,
|
|
553
|
-
.mkt .data-table td:last-child {
|
|
672
|
+
:is(.mkt, .atelic-ui) .data-table th:last-child,
|
|
673
|
+
:is(.mkt, .atelic-ui) .data-table td:last-child {
|
|
554
674
|
padding-right: 0;
|
|
555
675
|
}
|
|
556
|
-
.mkt .data-table [data-align="center"] {
|
|
676
|
+
:is(.mkt, .atelic-ui) .data-table [data-align="center"] {
|
|
557
677
|
text-align: center;
|
|
558
678
|
}
|
|
559
|
-
.mkt .data-table [data-align="right"] {
|
|
679
|
+
:is(.mkt, .atelic-ui) .data-table [data-align="right"] {
|
|
560
680
|
text-align: right;
|
|
561
681
|
}
|
|
562
|
-
.mkt .data-table thead th {
|
|
682
|
+
:is(.mkt, .atelic-ui) .data-table thead th {
|
|
563
683
|
padding-top: 0;
|
|
564
684
|
padding-bottom: 8px;
|
|
565
685
|
border-bottom: 1.5px solid var(--ink);
|
|
@@ -571,7 +691,7 @@
|
|
|
571
691
|
white-space: nowrap;
|
|
572
692
|
vertical-align: bottom;
|
|
573
693
|
}
|
|
574
|
-
.mkt .data-table thead th button {
|
|
694
|
+
:is(.mkt, .atelic-ui) .data-table thead th button {
|
|
575
695
|
display: inline-flex;
|
|
576
696
|
align-items: center;
|
|
577
697
|
gap: 4px;
|
|
@@ -584,23 +704,23 @@
|
|
|
584
704
|
color: inherit;
|
|
585
705
|
cursor: pointer;
|
|
586
706
|
}
|
|
587
|
-
.mkt .data-table thead th button:hover,
|
|
588
|
-
.mkt .data-table thead th button[data-active] {
|
|
589
|
-
color: var(--primary);
|
|
707
|
+
:is(.mkt, .atelic-ui) .data-table thead th button:hover,
|
|
708
|
+
:is(.mkt, .atelic-ui) .data-table thead th button[data-active] {
|
|
709
|
+
color: var(--ui-primary, var(--primary));
|
|
590
710
|
}
|
|
591
|
-
.mkt .data-table thead th button svg {
|
|
711
|
+
:is(.mkt, .atelic-ui) .data-table thead th button svg {
|
|
592
712
|
opacity: 0.55;
|
|
593
713
|
}
|
|
594
|
-
.mkt .data-table thead th button[data-active] svg {
|
|
714
|
+
:is(.mkt, .atelic-ui) .data-table thead th button[data-active] svg {
|
|
595
715
|
opacity: 1;
|
|
596
716
|
}
|
|
597
|
-
.mkt .data-table tbody tr:last-child th,
|
|
598
|
-
.mkt .data-table tbody tr:last-child td {
|
|
717
|
+
:is(.mkt, .atelic-ui) .data-table tbody tr:last-child th,
|
|
718
|
+
:is(.mkt, .atelic-ui) .data-table tbody tr:last-child td {
|
|
599
719
|
border-bottom: 0;
|
|
600
720
|
}
|
|
601
721
|
}
|
|
602
722
|
@media print {
|
|
603
|
-
.mkt .data-table thead th button svg {
|
|
723
|
+
:is(.mkt, .atelic-ui) .data-table thead th button svg {
|
|
604
724
|
display: none;
|
|
605
725
|
}
|
|
606
726
|
}
|