@plus234feed/ds 0.0.0-stage → 0.3.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
@@ -1,3 +1,169 @@
1
- # Temporary Holding Version
1
+ # Plus234Feed Design System
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Editorial tokens, a named type scale and the components a news intelligence
4
+ platform needs. Plain CSS on top of design tokens, no framework, no build step
5
+ for consumers.
6
+
7
+ Documentation site: `docs/index.html`, generated from `site/pages/`. Deploy the
8
+ `docs/` folder; `vercel.json` already points at it.
9
+
10
+ 27 pages: get started, foundations, one page per component, patterns and the
11
+ rules. Each component page says what it is, when to use it, when not to, live
12
+ examples with copyable HTML, and the tokens it reads.
13
+
14
+ ## Why this exists
15
+
16
+ The frontend had 252 component files and 40,638 lines of TSX, but only 25
17
+ shared components. Measured on 2026-11-04:
18
+
19
+ | Symptom | Count |
20
+ | --- | --- |
21
+ | `page.tsx` files not using `PageLayout` | 92 (16 do) |
22
+ | Files re-implementing an article card | 47 |
23
+ | `rounded-*` variants in use | 11 |
24
+ | Ad-hoc text sizes in use | 9, dominated by `text-sm` (1,019) and `text-xs` (720) |
25
+ | Hardcoded uses of a single green | 27 |
26
+ | Variables used but defined nowhere | 5 |
27
+
28
+ That last row was a live bug, not a matter of taste. `--text-muted` (42 uses),
29
+ `--border` (36), `--bg-elevated` (13), `--bg-secondary` and `--bg-hover` were
30
+ referenced with no fallback and declared in no stylesheet, concentrated in
31
+ `components/prices/` and the cost of living pages.
32
+
33
+ Reader behaviour pointed the same way. Almost every visitor is new, and
34
+ almost nobody opens a second page. Readers arriving from search spend real
35
+ time on the article, finish it, and leave: the problem is not that they are
36
+ bored, it is that the page offers them nothing to do next.
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ npm install
42
+ npm run build # tokens + gallery
43
+ npm test # 13 checks
44
+ ```
45
+
46
+ ```
47
+ npm run build:tokens tokens/*.json -> build/*.css, build/tokens.json
48
+ npm run build:docs site/pages/** -> docs/**
49
+ npm run check build + test, what CI runs
50
+ ```
51
+
52
+ ### Authoring a docs page
53
+
54
+ A page is an HTML fragment with a JSON comment at the top, wrapped by
55
+ `site/layout.html`. Four authoring elements expand at build time:
56
+
57
+ ```html
58
+ <!-- { "title": "Story", "section": "components", "order": 10, "description": "..." } -->
59
+
60
+ <docs-example label="...">markup</docs-example> preview plus copyable HTML
61
+ <docs-tokens names="ink,ink-muted"> generated swatches, both themes
62
+ <docs-type roles="display-1,headline"> generated specimens
63
+ <docs-scale group="space"> generated scale table
64
+ <docs-uses>--p234-color-ink, ...</docs-uses> the tokens a component reads
65
+ ```
66
+
67
+ Navigation and the section sidebar are derived from the front matter, so a new
68
+ page appears in both by existing.
69
+
70
+ ## Use it
71
+
72
+ ```css
73
+ @import "@plus234feed/ds/fonts.css"; /* Charter, self-hosted, 64KB */
74
+ @import "@plus234feed/ds/tokens.css"; /* theme driven by a .dark class */
75
+ @import "@plus234feed/ds/type.css"; /* .p234-headline and friends */
76
+ @import "@plus234feed/ds/components.css";
77
+ ```
78
+
79
+ Use `tokens-auto.css` instead of `tokens.css` only on standalone pages that
80
+ have no theme toggle. It adds an OS-preference block. The app must not use it:
81
+ a reader who picked light has to get light on a dark laptop.
82
+
83
+ ```html
84
+ <a class="p234-story p234-story--lead" href="...">
85
+ <span class="p234-kicker" data-section="markets">Market intelligence</span>
86
+ <h3 class="p234-story__headline">Pump prices are running 25 per cent above the last official figure</h3>
87
+ <p class="p234-story__standfirst">NBS puts Lagos petrol at 1,077 naira in May.</p>
88
+ <div class="p234-meta">
89
+ <span class="p234-meta__source">Plus234Feed</span>
90
+ <span class="p234-meta__dot">&middot;</span>
91
+ <span>2 hours ago</span>
92
+ <span class="p234-coverage">6 sources</span>
93
+ </div>
94
+ </a>
95
+ ```
96
+
97
+ ## How it is built
98
+
99
+ ```
100
+ tokens/core.tokens.json light theme, type, space, radius, layout
101
+ tokens/themes/dark.tokens.json colour overrides only, enforced
102
+ scripts/color.mjs WCAG luminance and contrast maths
103
+ scripts/tokens.mjs loading, flattening, alias resolution, the contrast table
104
+ scripts/build-tokens.mjs writes build/, fails on any unreadable pair
105
+ scripts/build-site.mjs writes the gallery from the built tokens
106
+ src/components.css editorial components, every rule reads a token
107
+ ```
108
+
109
+ Token format follows the W3C Design Tokens Community Group draft. Values become
110
+ CSS custom properties prefixed `--p234-`.
111
+
112
+ ### The contrast gate
113
+
114
+ 44 colour pairs are checked in every theme, 88 checks in all, and the build
115
+ exits non-zero on any failure. This is the point of the pipeline: a combination
116
+ nobody can read cannot reach the site. The first run caught three real
117
+ problems, two of which were dark-theme only.
118
+
119
+ The focus ring is checked differently. It is two colours, `focus` with
120
+ `focus-outer` drawn around it, and neither half clears 3:1 alone. The amber is
121
+ 1.64:1 on white and relies on the dark outer ring there; on a dark page the
122
+ outer ring recedes and the amber carries it. So the rule is that at least one
123
+ half must clear 3:1 on every surface. See `checkFocus`.
124
+
125
+ ## Rules the tokens cannot enforce
126
+
127
+ 1. **Two ad slots on an article, maximum, and no mobile sticky.** The current
128
+ template carries six plus a sticky around a 147-word summary. Mobile is 64
129
+ per cent of search traffic.
130
+ 2. **Every article ends with a next step that matches why the reader came.** A
131
+ visa reader gets visa stories, not the general feed. This is the module the
132
+ near-total absence of second pages is asking for.
133
+ 3. **No raw hex.** If a colour is missing, add a token.
134
+ 4. **No undefined tokens.** A prebuild check fails on any `--p234-` variable
135
+ this package does not declare.
136
+ 5. **Pick a type role, never a font size.** Seventeen roles cover the site.
137
+ Reaching past them means a role is missing, which is a conversation.
138
+ 6. **Direction is never colour alone.** Gainers and decliners carry an arrow.
139
+ 7. **One lead per page.** If two stories both look like the lead, neither is.
140
+
141
+ ## Type
142
+
143
+ Roles, not t-shirt sizes. Serif for what a reader reads, sans for what a reader
144
+ operates, tabular sans for every figure.
145
+
146
+ The serif is **Charter**, self-hosted from `src/fonts/`, 64KB for four faces,
147
+ `font-display: swap`. Charter is the face macOS and iOS already carry, which is
148
+ why the gallery looked right before a single font was loaded. Shipping it is
149
+ what gives Android readers, who are most of the audience, the same page
150
+ instead of a Noto Serif fallback.
151
+
152
+ Bitstream contributed Charter to the X Consortium in 1992 with permission to
153
+ use, copy, modify, sublicense, sell and redistribute, provided the notice stays
154
+ intact. That notice is `src/fonts/LICENSE.charter.txt` and ships with the
155
+ files. BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
156
+
157
+ The sans is still the system stack headed by Inter, which the Next app already
158
+ loads. On a machine without Inter it resolves to San Francisco or Roboto. If
159
+ that drift matters it should be self-hosted the same way.
160
+
161
+ Running text never drops below 16px. `caption` and `kicker` are the only roles
162
+ allowed at 12px, and the tests enforce both floors.
163
+
164
+ ## Scope
165
+
166
+ Phase 1 is this package plus the site chrome and the article template:
167
+ almost every session starts on an article, and the masthead and footer appear
168
+ on every page, so those are what make the site stop looking like two sites.
169
+ Fronts, data pages, account and forms follow.
@@ -0,0 +1,68 @@
1
+ /* Generated from tokens/. Do not edit by hand: run `npm run build:tokens`. */
2
+ @import "./tokens.css";
3
+
4
+ @media (prefers-color-scheme: dark) {
5
+ :root:not(.light):not([data-theme="light"]) {
6
+ --p234-color-ink: #f2f0ea;
7
+ --p234-color-ink-muted: #b0aca2;
8
+ --p234-color-ink-subtle: #9b978d;
9
+ --p234-color-ink-inverse: #f2f0ea;
10
+ --p234-color-paper: #141413;
11
+ --p234-color-paper-alt: #1c1c1a;
12
+ --p234-color-paper-sunk: #242421;
13
+ --p234-color-paper-dark: #0d0d0c;
14
+ --p234-color-rule: #32312d;
15
+ --p234-color-rule-strong: #6b685f;
16
+ --p234-color-brand: #8cc48c;
17
+ --p234-color-brand-hover: #a4d2a4;
18
+ --p234-color-on-brand: #141413;
19
+ --p234-color-brand-tint: #1e2a1e;
20
+ --p234-color-link: #8cc48c;
21
+ --p234-color-link-hover: #a4d2a4;
22
+ --p234-color-link-visited: #cbb0ea;
23
+ --p234-color-focus: #ffbf47;
24
+ --p234-color-focus-outer: #0d0d0c;
25
+ --p234-color-section-politics: #eb9494;
26
+ --p234-color-section-business: #8fbce8;
27
+ --p234-color-section-markets: #e5bc6a;
28
+ --p234-color-section-world: #c9a9ee;
29
+ --p234-color-section-sport: #63c9b0;
30
+ --p234-color-data-up: #5cc184;
31
+ --p234-color-data-down: #ef8288;
32
+ --p234-color-data-flat: #b0aca2;
33
+ --p234-color-chart-series-1: #4A90D9;
34
+ --p234-color-chart-series-2: #AD8B2A;
35
+ --p234-color-chart-series-3: #D16A9A;
36
+ --p234-color-chart-series-4: #2F9463;
37
+ --p234-color-chart-series-5: #9B7ED9;
38
+ --p234-color-chart-axis: #6b685f;
39
+ --p234-color-chart-grid: #282722;
40
+ --p234-color-chart-reference: #9b978d;
41
+ --p234-color-chart-tooltip-bg: #2a2a26;
42
+ --p234-color-chart-tooltip-ink: #f2f0ea;
43
+ --p234-color-chart-tooltip-border: #4a4840;
44
+ --p234-color-chart-seq-1: #36618C;
45
+ --p234-color-chart-seq-2: #4A7FB0;
46
+ --p234-color-chart-seq-3: #5E9CD1;
47
+ --p234-color-chart-seq-4: #86B9E3;
48
+ --p234-color-chart-seq-5: #B3D6F2;
49
+ --p234-color-chart-div-1: #AD8B2A;
50
+ --p234-color-chart-div-2: #7E6A32;
51
+ --p234-color-chart-div-3: #34322E;
52
+ --p234-color-chart-div-4: #3E6B96;
53
+ --p234-color-chart-div-5: #86B9E3;
54
+ --p234-color-field-bg: #1c1c1a;
55
+ --p234-color-field-border: #6b685f;
56
+ --p234-color-field-border-hover: #9b978d;
57
+ --p234-color-field-ink-placeholder: #9b978d;
58
+ --p234-color-field-bg-disabled: #242421;
59
+ --p234-color-success: #5cc184;
60
+ --p234-color-success-tint: #15251b;
61
+ --p234-color-warning: #e5bc6a;
62
+ --p234-color-warning-tint: #272015;
63
+ --p234-color-error: #ef8288;
64
+ --p234-color-error-tint: #2a1719;
65
+ --p234-color-info: #8fbce8;
66
+ --p234-color-info-tint: #151f28;
67
+ }
68
+ }
@@ -0,0 +1,283 @@
1
+ /* Generated from tokens/. Do not edit by hand: run `npm run build:tokens`. */
2
+
3
+ :root {
4
+ --p234-color-ink: #1a1a18;
5
+ --p234-color-ink-muted: #5b584f;
6
+ --p234-color-ink-subtle: #6e6b62;
7
+ --p234-color-ink-inverse: #ffffff;
8
+ --p234-color-paper: #ffffff;
9
+ --p234-color-paper-alt: #faf8f4;
10
+ --p234-color-paper-sunk: #f1eee7;
11
+ --p234-color-paper-dark: #1a1a18;
12
+ --p234-color-rule: #e3dfd6;
13
+ --p234-color-rule-strong: #8c887e;
14
+ --p234-color-brand: #417742;
15
+ --p234-color-brand-hover: #356136;
16
+ --p234-color-on-brand: #ffffff;
17
+ --p234-color-brand-tint: #eaf1e8;
18
+ --p234-color-link: #417742;
19
+ --p234-color-link-hover: #356136;
20
+ --p234-color-link-visited: #5b2a86;
21
+ --p234-color-focus: #ffbf47;
22
+ --p234-color-focus-outer: #1a1a18;
23
+ --p234-color-section-politics: #9b2c2c;
24
+ --p234-color-section-business: #1f4e79;
25
+ --p234-color-section-markets: #8a5700;
26
+ --p234-color-section-world: #5b2a86;
27
+ --p234-color-section-sport: #0f6e5c;
28
+ --p234-color-data-up: #15683b;
29
+ --p234-color-data-down: #b4232a;
30
+ --p234-color-data-flat: #5b584f;
31
+ --p234-color-chart-series-1: #1565C0;
32
+ --p234-color-chart-series-2: #B08500;
33
+ --p234-color-chart-series-3: #B5537F;
34
+ --p234-color-chart-series-4: #2E7D32;
35
+ --p234-color-chart-series-5: #6A4FA3;
36
+ --p234-color-chart-axis: #8c887e;
37
+ --p234-color-chart-grid: #ebe8e1;
38
+ --p234-color-chart-reference: #6e6b62;
39
+ --p234-color-chart-tooltip-bg: #1a1a18;
40
+ --p234-color-chart-tooltip-ink: #ffffff;
41
+ --p234-color-chart-tooltip-border: #3f3d38;
42
+ --p234-color-chart-seq-1: #8CB2DD;
43
+ --p234-color-chart-seq-2: #5F8FC4;
44
+ --p234-color-chart-seq-3: #3F6EA8;
45
+ --p234-color-chart-seq-4: #27507F;
46
+ --p234-color-chart-seq-5: #123455;
47
+ --p234-color-chart-div-1: #8A6D00;
48
+ --p234-color-chart-div-2: #C9AE6E;
49
+ --p234-color-chart-div-3: #EDEBE6;
50
+ --p234-color-chart-div-4: #6E9FD4;
51
+ --p234-color-chart-div-5: #1D4F85;
52
+ --p234-color-field-bg: #ffffff;
53
+ --p234-color-field-border: #8c887e;
54
+ --p234-color-field-border-hover: #5b584f;
55
+ --p234-color-field-ink-placeholder: #6e6b62;
56
+ --p234-color-field-bg-disabled: #f1eee7;
57
+ --p234-color-success: #00703c;
58
+ --p234-color-success-tint: #e6f2ec;
59
+ --p234-color-warning: #8a5700;
60
+ --p234-color-warning-tint: #fdf3e1;
61
+ --p234-color-error: #b00020;
62
+ --p234-color-error-tint: #fbe9ec;
63
+ --p234-color-info: #1d70b8;
64
+ --p234-color-info-tint: #e8f1f8;
65
+ --p234-font-family-display: Charter, "Charis SIL", "Iowan Old Style", Georgia, serif;
66
+ --p234-font-family-text: Inter, ui-sans-serif, system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
67
+ --p234-font-family-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
68
+ --p234-type-display-1-size: clamp(2.25rem, 1.30rem + 4.2vw, 3.25rem);
69
+ --p234-type-display-1-leading: 1.04;
70
+ --p234-type-display-1-weight: 700;
71
+ --p234-type-display-1-tracking: -0.022em;
72
+ --p234-type-display-1-family: Charter, "Charis SIL", "Iowan Old Style", Georgia, serif;
73
+ --p234-type-display-2-size: clamp(1.75rem, 1.18rem + 2.5vw, 2.5rem);
74
+ --p234-type-display-2-leading: 1.07;
75
+ --p234-type-display-2-weight: 700;
76
+ --p234-type-display-2-tracking: -0.02em;
77
+ --p234-type-display-2-family: Charter, "Charis SIL", "Iowan Old Style", Georgia, serif;
78
+ --p234-type-headline-size: 1.625rem;
79
+ --p234-type-headline-leading: 1.18;
80
+ --p234-type-headline-weight: 700;
81
+ --p234-type-headline-tracking: -0.015em;
82
+ --p234-type-headline-family: Charter, "Charis SIL", "Iowan Old Style", Georgia, serif;
83
+ --p234-type-headline-sm-size: 1.3125rem;
84
+ --p234-type-headline-sm-leading: 1.24;
85
+ --p234-type-headline-sm-weight: 700;
86
+ --p234-type-headline-sm-tracking: -0.01em;
87
+ --p234-type-headline-sm-family: Charter, "Charis SIL", "Iowan Old Style", Georgia, serif;
88
+ --p234-type-headline-xs-size: 1.125rem;
89
+ --p234-type-headline-xs-leading: 1.3;
90
+ --p234-type-headline-xs-weight: 700;
91
+ --p234-type-headline-xs-tracking: -0.005em;
92
+ --p234-type-headline-xs-family: Charter, "Charis SIL", "Iowan Old Style", Georgia, serif;
93
+ --p234-type-standfirst-size: 1.1875rem;
94
+ --p234-type-standfirst-leading: 1.5;
95
+ --p234-type-standfirst-weight: 400;
96
+ --p234-type-standfirst-tracking: 0;
97
+ --p234-type-standfirst-family: Charter, "Charis SIL", "Iowan Old Style", Georgia, serif;
98
+ --p234-type-body-size: 1.125rem;
99
+ --p234-type-body-leading: 1.68;
100
+ --p234-type-body-weight: 400;
101
+ --p234-type-body-tracking: 0;
102
+ --p234-type-body-family: Charter, "Charis SIL", "Iowan Old Style", Georgia, serif;
103
+ --p234-type-body-sm-size: 1rem;
104
+ --p234-type-body-sm-leading: 1.6;
105
+ --p234-type-body-sm-weight: 400;
106
+ --p234-type-body-sm-tracking: 0;
107
+ --p234-type-body-sm-family: Charter, "Charis SIL", "Iowan Old Style", Georgia, serif;
108
+ --p234-type-ui-size: 0.9375rem;
109
+ --p234-type-ui-leading: 1.45;
110
+ --p234-type-ui-weight: 500;
111
+ --p234-type-ui-tracking: 0;
112
+ --p234-type-ui-family: Inter, ui-sans-serif, system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
113
+ --p234-type-ui-sm-size: 0.8125rem;
114
+ --p234-type-ui-sm-leading: 1.4;
115
+ --p234-type-ui-sm-weight: 500;
116
+ --p234-type-ui-sm-tracking: 0;
117
+ --p234-type-ui-sm-family: Inter, ui-sans-serif, system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
118
+ --p234-type-kicker-size: 0.75rem;
119
+ --p234-type-kicker-leading: 1.2;
120
+ --p234-type-kicker-weight: 700;
121
+ --p234-type-kicker-tracking: 0.08em;
122
+ --p234-type-kicker-family: Inter, ui-sans-serif, system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
123
+ --p234-type-kicker-case: uppercase;
124
+ --p234-type-meta-size: 0.8125rem;
125
+ --p234-type-meta-leading: 1.4;
126
+ --p234-type-meta-weight: 400;
127
+ --p234-type-meta-tracking: 0;
128
+ --p234-type-meta-family: Inter, ui-sans-serif, system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
129
+ --p234-type-caption-size: 0.75rem;
130
+ --p234-type-caption-leading: 1.45;
131
+ --p234-type-caption-weight: 400;
132
+ --p234-type-caption-tracking: 0;
133
+ --p234-type-caption-family: Inter, ui-sans-serif, system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
134
+ --p234-type-data-lg-size: 2rem;
135
+ --p234-type-data-lg-leading: 1.1;
136
+ --p234-type-data-lg-weight: 600;
137
+ --p234-type-data-lg-tracking: -0.01em;
138
+ --p234-type-data-lg-family: Inter, ui-sans-serif, system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
139
+ --p234-type-data-lg-numeric: tabular-nums;
140
+ --p234-type-data-size: 1.125rem;
141
+ --p234-type-data-leading: 1.2;
142
+ --p234-type-data-weight: 600;
143
+ --p234-type-data-tracking: 0;
144
+ --p234-type-data-family: Inter, ui-sans-serif, system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
145
+ --p234-type-data-numeric: tabular-nums;
146
+ --p234-type-data-sm-size: 0.875rem;
147
+ --p234-type-data-sm-leading: 1.2;
148
+ --p234-type-data-sm-weight: 500;
149
+ --p234-type-data-sm-tracking: 0;
150
+ --p234-type-data-sm-family: Inter, ui-sans-serif, system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
151
+ --p234-type-data-sm-numeric: tabular-nums;
152
+ --p234-type-quote-size: 1.375rem;
153
+ --p234-type-quote-leading: 1.45;
154
+ --p234-type-quote-weight: 400;
155
+ --p234-type-quote-tracking: -0.01em;
156
+ --p234-type-quote-family: Charter, "Charis SIL", "Iowan Old Style", Georgia, serif;
157
+ --p234-space-0: 0;
158
+ --p234-space-1: 0.125rem;
159
+ --p234-space-2: 0.25rem;
160
+ --p234-space-3: 0.5rem;
161
+ --p234-space-4: 0.75rem;
162
+ --p234-space-5: 1rem;
163
+ --p234-space-6: 1.5rem;
164
+ --p234-space-7: 2rem;
165
+ --p234-space-8: 3rem;
166
+ --p234-space-9: 4rem;
167
+ --p234-space-10: 6rem;
168
+ --p234-measure-narrow: 46ch;
169
+ --p234-measure-text: 66ch;
170
+ --p234-measure-wide: 78ch;
171
+ --p234-radius-none: 0;
172
+ --p234-radius-sm: 2px;
173
+ --p234-radius-md: 4px;
174
+ --p234-radius-pill: 999px;
175
+ --p234-border-hairline: 1px;
176
+ --p234-border-thick: 2px;
177
+ --p234-border-heavy: 4px;
178
+ --p234-shadow-none: none;
179
+ --p234-shadow-raise: 0 1px 2px rgba(26, 26, 24, 0.06);
180
+ --p234-shadow-overlay: 0 8px 24px rgba(26, 26, 24, 0.16);
181
+ --p234-layout-gutter: 1rem;
182
+ --p234-layout-gutter-lg: 2rem;
183
+ --p234-layout-column-gap: 2rem;
184
+ --p234-layout-container: 1280px;
185
+ --p234-layout-container-text: 720px;
186
+ --p234-chart-line-width: 2px;
187
+ --p234-chart-grid-width: 1px;
188
+ --p234-chart-marker-size: 8px;
189
+ --p234-chart-area-opacity: 0.14;
190
+ --p234-chart-mark-gap: 2px;
191
+ --p234-chart-radius-end: 4px;
192
+ --p234-field-height: 2.75rem;
193
+ --p234-field-padding-x: 0.75rem;
194
+ --p234-field-radius: 4px;
195
+ --p234-field-border-width: 1px;
196
+ --p234-field-border-width-invalid: 2px;
197
+ --p234-figure-ratio: 16 / 9;
198
+ --p234-figure-ratio-portrait: 3 / 4;
199
+ --p234-figure-ratio-square: 1 / 1;
200
+ --p234-figure-hero-max-height: 31.25rem;
201
+ --p234-figure-inset-width: 45%;
202
+ --p234-z-base: 0;
203
+ --p234-z-raised: 10;
204
+ --p234-z-sticky: 20;
205
+ --p234-z-dropdown: 30;
206
+ --p234-z-overlay: 40;
207
+ --p234-z-toast: 50;
208
+ --p234-breakpoint-sm: 30rem;
209
+ --p234-breakpoint-md: 48rem;
210
+ --p234-breakpoint-lg: 62rem;
211
+ --p234-breakpoint-xl: 80rem;
212
+ --p234-icon-size-sm: 16px;
213
+ --p234-icon-size-md: 20px;
214
+ --p234-icon-size-lg: 24px;
215
+ --p234-icon-stroke: 1.75;
216
+ --p234-motion-duration-fast: 120ms;
217
+ --p234-motion-duration-base: 180ms;
218
+ --p234-motion-easing-standard: cubic-bezier(0.2, 0, 0, 1);
219
+ }
220
+
221
+ .dark, [data-theme="dark"] {
222
+ --p234-color-ink: #f2f0ea;
223
+ --p234-color-ink-muted: #b0aca2;
224
+ --p234-color-ink-subtle: #9b978d;
225
+ --p234-color-ink-inverse: #f2f0ea;
226
+ --p234-color-paper: #141413;
227
+ --p234-color-paper-alt: #1c1c1a;
228
+ --p234-color-paper-sunk: #242421;
229
+ --p234-color-paper-dark: #0d0d0c;
230
+ --p234-color-rule: #32312d;
231
+ --p234-color-rule-strong: #6b685f;
232
+ --p234-color-brand: #8cc48c;
233
+ --p234-color-brand-hover: #a4d2a4;
234
+ --p234-color-on-brand: #141413;
235
+ --p234-color-brand-tint: #1e2a1e;
236
+ --p234-color-link: #8cc48c;
237
+ --p234-color-link-hover: #a4d2a4;
238
+ --p234-color-link-visited: #cbb0ea;
239
+ --p234-color-focus: #ffbf47;
240
+ --p234-color-focus-outer: #0d0d0c;
241
+ --p234-color-section-politics: #eb9494;
242
+ --p234-color-section-business: #8fbce8;
243
+ --p234-color-section-markets: #e5bc6a;
244
+ --p234-color-section-world: #c9a9ee;
245
+ --p234-color-section-sport: #63c9b0;
246
+ --p234-color-data-up: #5cc184;
247
+ --p234-color-data-down: #ef8288;
248
+ --p234-color-data-flat: #b0aca2;
249
+ --p234-color-chart-series-1: #4A90D9;
250
+ --p234-color-chart-series-2: #AD8B2A;
251
+ --p234-color-chart-series-3: #D16A9A;
252
+ --p234-color-chart-series-4: #2F9463;
253
+ --p234-color-chart-series-5: #9B7ED9;
254
+ --p234-color-chart-axis: #6b685f;
255
+ --p234-color-chart-grid: #282722;
256
+ --p234-color-chart-reference: #9b978d;
257
+ --p234-color-chart-tooltip-bg: #2a2a26;
258
+ --p234-color-chart-tooltip-ink: #f2f0ea;
259
+ --p234-color-chart-tooltip-border: #4a4840;
260
+ --p234-color-chart-seq-1: #36618C;
261
+ --p234-color-chart-seq-2: #4A7FB0;
262
+ --p234-color-chart-seq-3: #5E9CD1;
263
+ --p234-color-chart-seq-4: #86B9E3;
264
+ --p234-color-chart-seq-5: #B3D6F2;
265
+ --p234-color-chart-div-1: #AD8B2A;
266
+ --p234-color-chart-div-2: #7E6A32;
267
+ --p234-color-chart-div-3: #34322E;
268
+ --p234-color-chart-div-4: #3E6B96;
269
+ --p234-color-chart-div-5: #86B9E3;
270
+ --p234-color-field-bg: #1c1c1a;
271
+ --p234-color-field-border: #6b685f;
272
+ --p234-color-field-border-hover: #9b978d;
273
+ --p234-color-field-ink-placeholder: #9b978d;
274
+ --p234-color-field-bg-disabled: #242421;
275
+ --p234-color-success: #5cc184;
276
+ --p234-color-success-tint: #15251b;
277
+ --p234-color-warning: #e5bc6a;
278
+ --p234-color-warning-tint: #272015;
279
+ --p234-color-error: #ef8288;
280
+ --p234-color-error-tint: #2a1719;
281
+ --p234-color-info: #8fbce8;
282
+ --p234-color-info-tint: #151f28;
283
+ }