@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 +168 -2
- package/build/tokens-auto.css +68 -0
- package/build/tokens.css +283 -0
- package/build/tokens.json +1514 -0
- package/build/type.css +141 -0
- package/package.json +50 -4
- package/src/components.css +1391 -0
- package/src/fonts/LICENSE.charter.txt +10 -0
- package/src/fonts/charter_bold.woff2 +0 -0
- package/src/fonts/charter_bold_italic.woff2 +0 -0
- package/src/fonts/charter_italic.woff2 +0 -0
- package/src/fonts/charter_regular.woff2 +0 -0
- package/src/fonts.css +45 -0
- package/tokens/core.tokens.json +364 -0
- package/tokens/themes/dark.tokens.json +82 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
This is a copy of the Charter fonts which Bitstream contributed to the X
|
|
2
|
+
consortium. This is the original notice included with the fonts:
|
|
3
|
+
|
|
4
|
+
(c) Copyright 1989-1992, Bitstream Inc., Cambridge, MA. You are hereby granted
|
|
5
|
+
permission under all Bitstream propriety rights to use, copy, modify, sublicense,
|
|
6
|
+
sell, and redistribute the 4 Bitstream Charter (r) Type 1 outline fonts and the
|
|
7
|
+
4 Courier Type 1 outline fonts for any purpose and without restriction; provided,
|
|
8
|
+
that this notice is left intact on all copies of such fonts and that Bitstream's
|
|
9
|
+
trademark is acknowledged as shown below on all unmodified copies of the 4 Charter
|
|
10
|
+
Type 1 fonts. BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/fonts.css
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/* Charter, self-hosted. 64KB for four faces, no CDN request, no Google Fonts.
|
|
2
|
+
*
|
|
3
|
+
* Bitstream contributed Charter to the X Consortium in 1992 with permission to
|
|
4
|
+
* use, copy, modify, sublicense, sell and redistribute, provided the notice
|
|
5
|
+
* stays intact. src/fonts/LICENSE.charter.txt is that notice and ships with the
|
|
6
|
+
* files. BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
|
|
7
|
+
*
|
|
8
|
+
* This is the typeface macOS and iOS already carry, which is why the design
|
|
9
|
+
* looked right before anything was loaded. Shipping it is what makes the other
|
|
10
|
+
* 64 per cent of readers, who are on Android, see the same page.
|
|
11
|
+
*
|
|
12
|
+
* font-display: swap, because a reader arriving from search should see the
|
|
13
|
+
* headline in a fallback immediately rather than stare at nothing. */
|
|
14
|
+
|
|
15
|
+
@font-face {
|
|
16
|
+
font-family: "Charter";
|
|
17
|
+
src: url("./fonts/charter_regular.woff2") format("woff2");
|
|
18
|
+
font-weight: 400;
|
|
19
|
+
font-style: normal;
|
|
20
|
+
font-display: swap;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@font-face {
|
|
24
|
+
font-family: "Charter";
|
|
25
|
+
src: url("./fonts/charter_italic.woff2") format("woff2");
|
|
26
|
+
font-weight: 400;
|
|
27
|
+
font-style: italic;
|
|
28
|
+
font-display: swap;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@font-face {
|
|
32
|
+
font-family: "Charter";
|
|
33
|
+
src: url("./fonts/charter_bold.woff2") format("woff2");
|
|
34
|
+
font-weight: 700;
|
|
35
|
+
font-style: normal;
|
|
36
|
+
font-display: swap;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@font-face {
|
|
40
|
+
font-family: "Charter";
|
|
41
|
+
src: url("./fonts/charter_bold_italic.woff2") format("woff2");
|
|
42
|
+
font-weight: 700;
|
|
43
|
+
font-style: italic;
|
|
44
|
+
font-display: swap;
|
|
45
|
+
}
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$description": "Plus234Feed design system core tokens. Light theme values live here; tokens/themes/dark.tokens.json overrides the colour group. Format follows the W3C Design Tokens Community Group draft. Values become CSS custom properties prefixed --p234-.",
|
|
3
|
+
|
|
4
|
+
"color": {
|
|
5
|
+
"$type": "color",
|
|
6
|
+
|
|
7
|
+
"ink": { "$value": "#1a1a18", "$description": "Body and headline text. Warm near-black, not pure black, so long serif copy does not vibrate." },
|
|
8
|
+
"ink-muted": { "$value": "#5b584f", "$description": "Bylines, timestamps, source names, captions. Must stay 4.5:1 on paper and paper-alt." },
|
|
9
|
+
"ink-subtle": { "$value": "#6e6b62", "$description": "The lightest text allowed anywhere. Still passes 4.5:1. Below this, use ink-muted." },
|
|
10
|
+
"ink-inverse": { "$value": "#ffffff", "$description": "Text on paper-dark and on brand." },
|
|
11
|
+
|
|
12
|
+
"paper": { "$value": "#ffffff", "$description": "Page background." },
|
|
13
|
+
"paper-alt": { "$value": "#faf8f4", "$description": "Warm newsprint tint for section bands and pull panels. Subtle on purpose: this is not a cream site." },
|
|
14
|
+
"paper-sunk": { "$value": "#f1eee7", "$description": "Recessed blocks: data tables, quote blocks, the ad slot frame." },
|
|
15
|
+
"paper-dark": { "$value": "#1a1a18", "$description": "Footer, masthead inverse, section dividers on dark." },
|
|
16
|
+
|
|
17
|
+
"rule": { "$value": "#e3dfd6", "$description": "The hairline that does the layout work. Editorial pages separate with rules, not shadows or cards." },
|
|
18
|
+
"rule-strong": { "$value": "#8c887e", "$description": "Section rules and form control borders. Non-text, needs 3:1." },
|
|
19
|
+
|
|
20
|
+
"brand": { "$value": "#417742", "$description": "Plus234Feed green. Kickers, links, the masthead plus. Carried over from the existing identity." },
|
|
21
|
+
"brand-hover": { "$value": "#356136" },
|
|
22
|
+
"on-brand": { "$value": "#ffffff", "$description": "Text on a brand background. Build verifies 4.5:1." },
|
|
23
|
+
"brand-tint": { "$value": "#eaf1e8", "$description": "Selected rows, followed-topic chips, the live band." },
|
|
24
|
+
|
|
25
|
+
"link": { "$value": "{color.brand}" },
|
|
26
|
+
"link-hover": { "$value": "{color.brand-hover}" },
|
|
27
|
+
"link-visited": { "$value": "#5b2a86", "$description": "Real news readers revisit. Visited state is not optional on an archive this size." },
|
|
28
|
+
|
|
29
|
+
"focus": { "$value": "#ffbf47", "$description": "Focus ring. Always drawn with focus-outer behind it so it survives any background." },
|
|
30
|
+
"focus-outer": { "$value": "#1a1a18", "$description": "The ring drawn outside the focus colour. Dark on light pages, so the amber reads; in dark it recedes and the amber does the work alone." },
|
|
31
|
+
|
|
32
|
+
"section-politics": { "$value": "#9b2c2c", "$description": "Kicker text and section rule only. Never a background." },
|
|
33
|
+
"section-business": { "$value": "#1f4e79" },
|
|
34
|
+
"section-markets": { "$value": "#8a5700" },
|
|
35
|
+
"section-world": { "$value": "#5b2a86" },
|
|
36
|
+
"section-sport": { "$value": "#0f6e5c" },
|
|
37
|
+
|
|
38
|
+
"data-up": { "$value": "#15683b", "$description": "Gainers. Paired with an arrow glyph, never colour alone. Dark enough to clear 4.5:1 inside a sunk data table, which the first draft missed." },
|
|
39
|
+
"data-down": { "$value": "#b4232a", "$description": "Decliners. Paired with an arrow glyph, never colour alone." },
|
|
40
|
+
"data-flat": { "$value": "{color.ink-muted}" },
|
|
41
|
+
|
|
42
|
+
"chart-series-1": { "$value": "#1565C0", "$description": "Blue. Series are assigned in this fixed order and never cycled: colour follows the entity, so a filter that drops a series must not repaint the survivors." },
|
|
43
|
+
"chart-series-2": { "$value": "#B08500", "$description": "Ochre." },
|
|
44
|
+
"chart-series-3": { "$value": "#B5537F", "$description": "Magenta. The first three are the mutually distinct set, safe when series are compared through a legend rather than side by side." },
|
|
45
|
+
"chart-series-4": { "$value": "#2E7D32", "$description": "Green. From here on only ADJACENT separation is guaranteed, so four or more series need direct labels or faceting." },
|
|
46
|
+
"chart-series-5": { "$value": "#6A4FA3", "$description": "Purple. The last slot. A sixth series folds into Other, or the chart becomes small multiples." },
|
|
47
|
+
|
|
48
|
+
"chart-axis": { "$value": "#8c887e", "$description": "Axis line and ticks. Non-text, needs 3:1." },
|
|
49
|
+
"chart-grid": { "$value": "#ebe8e1", "$description": "Grid lines, deliberately recessive. Not gated at 3:1 because a grid that competes with the data is a worse chart." },
|
|
50
|
+
"chart-reference": { "$value": "#6e6b62", "$description": "Dashed reference lines: a target, an official figure, a prior period." },
|
|
51
|
+
"chart-tooltip-bg": { "$value": "#1a1a18" },
|
|
52
|
+
"chart-tooltip-ink": { "$value": "#ffffff" },
|
|
53
|
+
"chart-tooltip-border": { "$value": "#3f3d38" },
|
|
54
|
+
|
|
55
|
+
"chart-seq-1": { "$value": "#8CB2DD", "$description": "Sequential ramp for magnitude, one hue light to dark. This is what the Nigeria choropleth reads. Never a rainbow." },
|
|
56
|
+
"chart-seq-2": { "$value": "#5F8FC4" },
|
|
57
|
+
"chart-seq-3": { "$value": "#3F6EA8" },
|
|
58
|
+
"chart-seq-4": { "$value": "#27507F" },
|
|
59
|
+
"chart-seq-5": { "$value": "#123455" },
|
|
60
|
+
|
|
61
|
+
"chart-div-1": { "$value": "#8A6D00", "$description": "Diverging ramp for polarity: warm pole, neutral midpoint, cool pole. For swings and margins, where the sign matters as much as the size." },
|
|
62
|
+
"chart-div-2": { "$value": "#C9AE6E" },
|
|
63
|
+
"chart-div-3": { "$value": "#EDEBE6", "$description": "The neutral midpoint. Never a hue: a coloured midpoint invents a category that is not in the data." },
|
|
64
|
+
"chart-div-4": { "$value": "#6E9FD4" },
|
|
65
|
+
"chart-div-5": { "$value": "#1D4F85" },
|
|
66
|
+
|
|
67
|
+
"field-bg": { "$value": "#ffffff", "$description": "Input, select and textarea background." },
|
|
68
|
+
"field-border": { "$value": "#8c887e", "$description": "Resting border. Non-text, needs 3:1, which is what makes the control visible at all." },
|
|
69
|
+
"field-border-hover": { "$value": "#5b584f" },
|
|
70
|
+
"field-ink-placeholder": { "$value": "#6e6b62", "$description": "Placeholder text. Still 4.5:1, because a placeholder nobody can read is not a hint." },
|
|
71
|
+
"field-bg-disabled": { "$value": "#f1eee7" },
|
|
72
|
+
|
|
73
|
+
"success": { "$value": "#00703c" },
|
|
74
|
+
"success-tint": { "$value": "#e6f2ec" },
|
|
75
|
+
"warning": { "$value": "#8a5700" },
|
|
76
|
+
"warning-tint": { "$value": "#fdf3e1" },
|
|
77
|
+
"error": { "$value": "#b00020" },
|
|
78
|
+
"error-tint": { "$value": "#fbe9ec" },
|
|
79
|
+
"info": { "$value": "#1d70b8" },
|
|
80
|
+
"info-tint": { "$value": "#e8f1f8" }
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
"font": {
|
|
84
|
+
"family-display": {
|
|
85
|
+
"$type": "fontFamily",
|
|
86
|
+
"$value": ["Charter", "Charis SIL", "Iowan Old Style", "Georgia", "serif"],
|
|
87
|
+
"$description": "Headlines, standfirsts and article body. Charter, shipped by src/fonts.css at 64KB for four faces. It is the face macOS and iOS already carry, so the design looked right before anything was loaded; self-hosting it is what gives Android readers, who are 64 per cent of search traffic, the same page."
|
|
88
|
+
},
|
|
89
|
+
"family-text": {
|
|
90
|
+
"$type": "fontFamily",
|
|
91
|
+
"$value": ["Inter", "ui-sans-serif", "system-ui", "Segoe UI", "Helvetica Neue", "Arial", "sans-serif"],
|
|
92
|
+
"$description": "Interface, navigation, kickers, metadata and all figures. Already loaded site-wide and used by the wordmark."
|
|
93
|
+
},
|
|
94
|
+
"family-mono": {
|
|
95
|
+
"$type": "fontFamily",
|
|
96
|
+
"$value": ["IBM Plex Mono", "ui-monospace", "SFMono-Regular", "Menlo", "Consolas", "monospace"],
|
|
97
|
+
"$description": "API documentation and code samples only. Figures use family-text with tabular numerals."
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
"type": {
|
|
102
|
+
"$description": "Named editorial roles, not t-shirt sizes. Each role is one decision. Picking a raw font-size in a component is the thing this system exists to stop.",
|
|
103
|
+
|
|
104
|
+
"display-1": {
|
|
105
|
+
"size": { "$type": "dimension", "$value": "clamp(2.25rem, 1.30rem + 4.2vw, 3.25rem)" },
|
|
106
|
+
"leading": { "$type": "number", "$value": 1.04 },
|
|
107
|
+
"weight": { "$type": "fontWeight", "$value": 700 },
|
|
108
|
+
"tracking": { "$type": "dimension", "$value": "-0.022em" },
|
|
109
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-display}" },
|
|
110
|
+
"$description": "The one dominant story. One per page, never two."
|
|
111
|
+
},
|
|
112
|
+
"display-2": {
|
|
113
|
+
"size": { "$type": "dimension", "$value": "clamp(1.75rem, 1.18rem + 2.5vw, 2.5rem)" },
|
|
114
|
+
"leading": { "$type": "number", "$value": 1.07 },
|
|
115
|
+
"weight": { "$type": "fontWeight", "$value": 700 },
|
|
116
|
+
"tracking": { "$type": "dimension", "$value": "-0.02em" },
|
|
117
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-display}" },
|
|
118
|
+
"$description": "Article H1, secondary lead."
|
|
119
|
+
},
|
|
120
|
+
"headline": {
|
|
121
|
+
"size": { "$type": "dimension", "$value": "1.625rem" },
|
|
122
|
+
"leading": { "$type": "number", "$value": 1.18 },
|
|
123
|
+
"weight": { "$type": "fontWeight", "$value": 700 },
|
|
124
|
+
"tracking": { "$type": "dimension", "$value": "-0.015em" },
|
|
125
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-display}" },
|
|
126
|
+
"$description": "Strong secondary story in a grid."
|
|
127
|
+
},
|
|
128
|
+
"headline-sm": {
|
|
129
|
+
"size": { "$type": "dimension", "$value": "1.3125rem" },
|
|
130
|
+
"leading": { "$type": "number", "$value": 1.24 },
|
|
131
|
+
"weight": { "$type": "fontWeight", "$value": 700 },
|
|
132
|
+
"tracking": { "$type": "dimension", "$value": "-0.01em" },
|
|
133
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-display}" },
|
|
134
|
+
"$description": "Card headline, sidebar lead."
|
|
135
|
+
},
|
|
136
|
+
"headline-xs": {
|
|
137
|
+
"size": { "$type": "dimension", "$value": "1.125rem" },
|
|
138
|
+
"leading": { "$type": "number", "$value": 1.3 },
|
|
139
|
+
"weight": { "$type": "fontWeight", "$value": 700 },
|
|
140
|
+
"tracking": { "$type": "dimension", "$value": "-0.005em" },
|
|
141
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-display}" },
|
|
142
|
+
"$description": "Compact supporting headline, the stacked list items."
|
|
143
|
+
},
|
|
144
|
+
"standfirst": {
|
|
145
|
+
"size": { "$type": "dimension", "$value": "1.1875rem" },
|
|
146
|
+
"leading": { "$type": "number", "$value": 1.5 },
|
|
147
|
+
"weight": { "$type": "fontWeight", "$value": 400 },
|
|
148
|
+
"tracking": { "$type": "dimension", "$value": "0" },
|
|
149
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-display}" },
|
|
150
|
+
"$description": "The deck under a headline. One sentence that says why the story matters."
|
|
151
|
+
},
|
|
152
|
+
"body": {
|
|
153
|
+
"size": { "$type": "dimension", "$value": "1.125rem" },
|
|
154
|
+
"leading": { "$type": "number", "$value": 1.68 },
|
|
155
|
+
"weight": { "$type": "fontWeight", "$value": 400 },
|
|
156
|
+
"tracking": { "$type": "dimension", "$value": "0" },
|
|
157
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-display}" },
|
|
158
|
+
"$description": "Article copy. 18px serif. The floor for running text is 16px anywhere on the site."
|
|
159
|
+
},
|
|
160
|
+
"body-sm": {
|
|
161
|
+
"size": { "$type": "dimension", "$value": "1rem" },
|
|
162
|
+
"leading": { "$type": "number", "$value": 1.6 },
|
|
163
|
+
"weight": { "$type": "fontWeight", "$value": 400 },
|
|
164
|
+
"tracking": { "$type": "dimension", "$value": "0" },
|
|
165
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-display}" },
|
|
166
|
+
"$description": "Summary text in cards and rails. 16px, the minimum for running text."
|
|
167
|
+
},
|
|
168
|
+
"ui": {
|
|
169
|
+
"size": { "$type": "dimension", "$value": "0.9375rem" },
|
|
170
|
+
"leading": { "$type": "number", "$value": 1.45 },
|
|
171
|
+
"weight": { "$type": "fontWeight", "$value": 500 },
|
|
172
|
+
"tracking": { "$type": "dimension", "$value": "0" },
|
|
173
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-text}" },
|
|
174
|
+
"$description": "Navigation, buttons, tabs, form labels."
|
|
175
|
+
},
|
|
176
|
+
"ui-sm": {
|
|
177
|
+
"size": { "$type": "dimension", "$value": "0.8125rem" },
|
|
178
|
+
"leading": { "$type": "number", "$value": 1.4 },
|
|
179
|
+
"weight": { "$type": "fontWeight", "$value": 500 },
|
|
180
|
+
"tracking": { "$type": "dimension", "$value": "0" },
|
|
181
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-text}" },
|
|
182
|
+
"$description": "Dense controls, filter chips, table headers."
|
|
183
|
+
},
|
|
184
|
+
"kicker": {
|
|
185
|
+
"size": { "$type": "dimension", "$value": "0.75rem" },
|
|
186
|
+
"leading": { "$type": "number", "$value": 1.2 },
|
|
187
|
+
"weight": { "$type": "fontWeight", "$value": 700 },
|
|
188
|
+
"tracking": { "$type": "dimension", "$value": "0.08em" },
|
|
189
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-text}" },
|
|
190
|
+
"case": { "$type": "string", "$value": "uppercase" },
|
|
191
|
+
"$description": "The section label above a headline. Carries the section colour."
|
|
192
|
+
},
|
|
193
|
+
"meta": {
|
|
194
|
+
"size": { "$type": "dimension", "$value": "0.8125rem" },
|
|
195
|
+
"leading": { "$type": "number", "$value": 1.4 },
|
|
196
|
+
"weight": { "$type": "fontWeight", "$value": 400 },
|
|
197
|
+
"tracking": { "$type": "dimension", "$value": "0" },
|
|
198
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-text}" },
|
|
199
|
+
"$description": "Source, timestamp, coverage count. Always ink-muted."
|
|
200
|
+
},
|
|
201
|
+
"caption": {
|
|
202
|
+
"size": { "$type": "dimension", "$value": "0.75rem" },
|
|
203
|
+
"leading": { "$type": "number", "$value": 1.45 },
|
|
204
|
+
"weight": { "$type": "fontWeight", "$value": 400 },
|
|
205
|
+
"tracking": { "$type": "dimension", "$value": "0" },
|
|
206
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-text}" },
|
|
207
|
+
"$description": "Photo credits and footnotes. The only role allowed below 13px."
|
|
208
|
+
},
|
|
209
|
+
"data-lg": {
|
|
210
|
+
"size": { "$type": "dimension", "$value": "2rem" },
|
|
211
|
+
"leading": { "$type": "number", "$value": 1.1 },
|
|
212
|
+
"weight": { "$type": "fontWeight", "$value": 600 },
|
|
213
|
+
"tracking": { "$type": "dimension", "$value": "-0.01em" },
|
|
214
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-text}" },
|
|
215
|
+
"numeric": { "$type": "string", "$value": "tabular-nums" },
|
|
216
|
+
"$description": "The headline figure on a price or market page."
|
|
217
|
+
},
|
|
218
|
+
"data": {
|
|
219
|
+
"size": { "$type": "dimension", "$value": "1.125rem" },
|
|
220
|
+
"leading": { "$type": "number", "$value": 1.2 },
|
|
221
|
+
"weight": { "$type": "fontWeight", "$value": 600 },
|
|
222
|
+
"tracking": { "$type": "dimension", "$value": "0" },
|
|
223
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-text}" },
|
|
224
|
+
"numeric": { "$type": "string", "$value": "tabular-nums" },
|
|
225
|
+
"$description": "Figures in tables and tiles. Tabular so columns align."
|
|
226
|
+
},
|
|
227
|
+
"data-sm": {
|
|
228
|
+
"size": { "$type": "dimension", "$value": "0.875rem" },
|
|
229
|
+
"leading": { "$type": "number", "$value": 1.2 },
|
|
230
|
+
"weight": { "$type": "fontWeight", "$value": 500 },
|
|
231
|
+
"tracking": { "$type": "dimension", "$value": "0" },
|
|
232
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-text}" },
|
|
233
|
+
"numeric": { "$type": "string", "$value": "tabular-nums" },
|
|
234
|
+
"$description": "Deltas and units beside a figure."
|
|
235
|
+
},
|
|
236
|
+
"quote": {
|
|
237
|
+
"size": { "$type": "dimension", "$value": "1.375rem" },
|
|
238
|
+
"leading": { "$type": "number", "$value": 1.45 },
|
|
239
|
+
"weight": { "$type": "fontWeight", "$value": 400 },
|
|
240
|
+
"tracking": { "$type": "dimension", "$value": "-0.01em" },
|
|
241
|
+
"family": { "$type": "fontFamily", "$value": "{font.family-display}" },
|
|
242
|
+
"$description": "Pull quotes and the lead sentence of a brief."
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
"space": {
|
|
247
|
+
"$type": "dimension",
|
|
248
|
+
"$description": "4px base. Editorial spacing is mostly vertical rhythm between rules.",
|
|
249
|
+
"0": { "$value": "0" },
|
|
250
|
+
"1": { "$value": "0.125rem" },
|
|
251
|
+
"2": { "$value": "0.25rem" },
|
|
252
|
+
"3": { "$value": "0.5rem" },
|
|
253
|
+
"4": { "$value": "0.75rem" },
|
|
254
|
+
"5": { "$value": "1rem" },
|
|
255
|
+
"6": { "$value": "1.5rem" },
|
|
256
|
+
"7": { "$value": "2rem" },
|
|
257
|
+
"8": { "$value": "3rem" },
|
|
258
|
+
"9": { "$value": "4rem" },
|
|
259
|
+
"10": { "$value": "6rem" }
|
|
260
|
+
},
|
|
261
|
+
|
|
262
|
+
"measure": {
|
|
263
|
+
"$type": "dimension",
|
|
264
|
+
"narrow": { "$value": "46ch", "$description": "Sidebar and rail copy." },
|
|
265
|
+
"text": { "$value": "66ch", "$description": "Article body. The reason the article column is capped, not full width." },
|
|
266
|
+
"wide": { "$value": "78ch", "$description": "Data tables and wide standfirsts." }
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
"radius": {
|
|
270
|
+
"$type": "dimension",
|
|
271
|
+
"$description": "Editorial restraint. The current site uses rounded-xl 354 times; nothing here goes past 4px except pill, which is for tags and chips only.",
|
|
272
|
+
"none": { "$value": "0" },
|
|
273
|
+
"sm": { "$value": "2px" },
|
|
274
|
+
"md": { "$value": "4px" },
|
|
275
|
+
"pill": { "$value": "999px" }
|
|
276
|
+
},
|
|
277
|
+
|
|
278
|
+
"border": {
|
|
279
|
+
"$type": "dimension",
|
|
280
|
+
"hairline": { "$value": "1px", "$description": "Default rule between stories." },
|
|
281
|
+
"thick": { "$value": "2px", "$description": "Section heading underline." },
|
|
282
|
+
"heavy": { "$value": "4px", "$description": "Masthead rule and the live band." }
|
|
283
|
+
},
|
|
284
|
+
|
|
285
|
+
"shadow": {
|
|
286
|
+
"$type": "shadow",
|
|
287
|
+
"$description": "Three only. An editorial page separates with rules; shadows are for things that genuinely float.",
|
|
288
|
+
"none": { "$value": "none" },
|
|
289
|
+
"raise": { "$value": "0 1px 2px rgba(26, 26, 24, 0.06)", "$description": "Sticky masthead once the page scrolls." },
|
|
290
|
+
"overlay": { "$value": "0 8px 24px rgba(26, 26, 24, 0.16)", "$description": "Menus, dialogs, the search panel." }
|
|
291
|
+
},
|
|
292
|
+
|
|
293
|
+
"layout": {
|
|
294
|
+
"$type": "dimension",
|
|
295
|
+
"gutter": { "$value": "1rem", "$description": "Page side gutter on phones." },
|
|
296
|
+
"gutter-lg": { "$value": "2rem" },
|
|
297
|
+
"column-gap": { "$value": "2rem", "$description": "Gap between editorial columns, wide enough for the rule to read." },
|
|
298
|
+
"container": { "$value": "1280px" },
|
|
299
|
+
"container-text": { "$value": "720px", "$description": "Article shell." }
|
|
300
|
+
},
|
|
301
|
+
|
|
302
|
+
"chart": {
|
|
303
|
+
"$description": "Mark specs. Thin marks, recessive grid, and a gap between adjacent fills so stacked segments read as separate.",
|
|
304
|
+
"line-width": { "$type": "dimension", "$value": "2px" },
|
|
305
|
+
"grid-width": { "$type": "dimension", "$value": "1px" },
|
|
306
|
+
"marker-size": { "$type": "dimension", "$value": "8px", "$description": "Minimum hit and read size for a point marker." },
|
|
307
|
+
"area-opacity": { "$type": "number", "$value": 0.14, "$description": "Fill under a line. Low enough that an overlapping pair stays legible." },
|
|
308
|
+
"mark-gap": { "$type": "dimension", "$value": "2px", "$description": "Surface-coloured gap between adjacent bars and stacked segments." },
|
|
309
|
+
"radius-end": { "$type": "dimension", "$value": "4px", "$description": "Rounded data end on a bar, anchored to the baseline. The baseline end stays square." }
|
|
310
|
+
},
|
|
311
|
+
|
|
312
|
+
"field": {
|
|
313
|
+
"$type": "dimension",
|
|
314
|
+
"height": { "$value": "2.75rem", "$description": "44px, the touch target floor. Most readers are on a phone." },
|
|
315
|
+
"padding-x": { "$value": "0.75rem" },
|
|
316
|
+
"radius": { "$value": "4px", "$description": "radius.md. Form controls are the one place a visible radius helps, because it separates the control from the rule grid." },
|
|
317
|
+
"border-width": { "$value": "1px" },
|
|
318
|
+
"border-width-invalid": { "$value": "2px", "$description": "An invalid field thickens its border as well as changing colour, so the state is not carried by colour alone." }
|
|
319
|
+
},
|
|
320
|
+
|
|
321
|
+
"figure": {
|
|
322
|
+
"$description": "Image shapes. The image service resizes to 16:9 at a requested width, so 16:9 is the shape the system is built around and anything else is a deliberate exception.",
|
|
323
|
+
"ratio": { "$type": "string", "$value": "16 / 9", "$description": "The default, and what img.plus234feed.com returns." },
|
|
324
|
+
"ratio-portrait": { "$type": "string", "$value": "3 / 4", "$description": "People. A politician's photograph cropped to 16:9 loses the face." },
|
|
325
|
+
"ratio-square": { "$type": "string", "$value": "1 / 1", "$description": "Logos and avatars." },
|
|
326
|
+
"hero-max-height": { "$type": "dimension", "$value": "31.25rem", "$description": "500px. A hero taller than this pushes the first paragraph off a laptop screen." },
|
|
327
|
+
"inset-width": { "$type": "dimension", "$value": "45%", "$description": "An image set beside the text on wide screens." }
|
|
328
|
+
},
|
|
329
|
+
|
|
330
|
+
"z": {
|
|
331
|
+
"$type": "number",
|
|
332
|
+
"$description": "One scale for everything that stacks. Before this, the masthead, dropdowns, the search overlay and toasts each picked their own number.",
|
|
333
|
+
"base": { "$value": 0 },
|
|
334
|
+
"raised": { "$value": 10, "$description": "A mark lifted above its siblings." },
|
|
335
|
+
"sticky": { "$value": 20, "$description": "The masthead and any sticky section rule." },
|
|
336
|
+
"dropdown": { "$value": 30, "$description": "Nav menus, the account menu, select popovers." },
|
|
337
|
+
"overlay": { "$value": 40, "$description": "Search overlay, dialogs, the mobile menu." },
|
|
338
|
+
"toast": { "$value": 50, "$description": "Always on top. Nothing goes above a message about what just happened." }
|
|
339
|
+
},
|
|
340
|
+
|
|
341
|
+
"breakpoint": {
|
|
342
|
+
"$type": "dimension",
|
|
343
|
+
"$description": "Custom properties cannot be used in a media query, so these are the agreed values rather than something a stylesheet reads. They are exported in build/tokens.json for JavaScript, and every media query in the system uses one of them literally.",
|
|
344
|
+
"sm": { "$value": "30rem", "$description": "480px. Large phone." },
|
|
345
|
+
"md": { "$value": "48rem", "$description": "768px. Tablet, and where the article column stops being full bleed." },
|
|
346
|
+
"lg": { "$value": "62rem", "$description": "992px. Where a sidebar becomes worth having." },
|
|
347
|
+
"xl": { "$value": "80rem", "$description": "1280px. Full container." }
|
|
348
|
+
},
|
|
349
|
+
|
|
350
|
+
"icon": {
|
|
351
|
+
"$type": "dimension",
|
|
352
|
+
"$description": "lucide-react, sized from this scale. An icon never appears without a label or an aria-label.",
|
|
353
|
+
"size-sm": { "$value": "16px", "$description": "Inline with ui-sm and meta text." },
|
|
354
|
+
"size-md": { "$value": "20px", "$description": "Default: buttons, nav, controls." },
|
|
355
|
+
"size-lg": { "$value": "24px", "$description": "Section headers and empty states." },
|
|
356
|
+
"stroke": { "$type": "number", "$value": 1.75, "$description": "Slightly lighter than lucide's default 2, to sit with the serif rather than shout over it." }
|
|
357
|
+
},
|
|
358
|
+
|
|
359
|
+
"motion": {
|
|
360
|
+
"duration-fast": { "$type": "duration", "$value": "120ms" },
|
|
361
|
+
"duration-base": { "$type": "duration", "$value": "180ms" },
|
|
362
|
+
"easing-standard": { "$type": "cubicBezier", "$value": "cubic-bezier(0.2, 0, 0, 1)" }
|
|
363
|
+
}
|
|
364
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$description": "Dark theme. Overrides the colour group only; type, space and layout are shared with core. Every pair in CONTRAST_PAIRS is checked against these values too, so a dark-only regression fails the build.",
|
|
3
|
+
|
|
4
|
+
"color": {
|
|
5
|
+
"$type": "color",
|
|
6
|
+
|
|
7
|
+
"ink": { "$value": "#f2f0ea", "$description": "Warm off-white. Pure white on a dark ground glares under serif copy." },
|
|
8
|
+
"ink-muted": { "$value": "#b0aca2" },
|
|
9
|
+
"ink-subtle": { "$value": "#9b978d" },
|
|
10
|
+
"ink-inverse": { "$value": "#f2f0ea", "$description": "In dark the footer is still a dark surface, so text on it stays light. Text on the brand colour is on-brand, which is the dark value." },
|
|
11
|
+
|
|
12
|
+
"paper": { "$value": "#141413" },
|
|
13
|
+
"paper-alt": { "$value": "#1c1c1a" },
|
|
14
|
+
"paper-sunk": { "$value": "#242421" },
|
|
15
|
+
"paper-dark": { "$value": "#0d0d0c" },
|
|
16
|
+
|
|
17
|
+
"rule": { "$value": "#32312d" },
|
|
18
|
+
"rule-strong": { "$value": "#6b685f" },
|
|
19
|
+
|
|
20
|
+
"brand": { "$value": "#8cc48c", "$description": "The light-theme green fails on a dark ground, so dark gets a lifted tint of the same hue." },
|
|
21
|
+
"brand-hover": { "$value": "#a4d2a4" },
|
|
22
|
+
"on-brand": { "$value": "#141413" },
|
|
23
|
+
"brand-tint": { "$value": "#1e2a1e" },
|
|
24
|
+
|
|
25
|
+
"link": { "$value": "{color.brand}" },
|
|
26
|
+
"link-hover": { "$value": "{color.brand-hover}" },
|
|
27
|
+
"link-visited": { "$value": "#cbb0ea" },
|
|
28
|
+
|
|
29
|
+
"focus": { "$value": "#ffbf47" },
|
|
30
|
+
"focus-outer": { "$value": "#0d0d0c", "$description": "On a dark page the outer ring recedes and the amber carries the focus state on its own." },
|
|
31
|
+
|
|
32
|
+
"section-politics": { "$value": "#eb9494" },
|
|
33
|
+
"section-business": { "$value": "#8fbce8" },
|
|
34
|
+
"section-markets": { "$value": "#e5bc6a" },
|
|
35
|
+
"section-world": { "$value": "#c9a9ee" },
|
|
36
|
+
"section-sport": { "$value": "#63c9b0" },
|
|
37
|
+
|
|
38
|
+
"data-up": { "$value": "#5cc184" },
|
|
39
|
+
"data-down": { "$value": "#ef8288" },
|
|
40
|
+
"data-flat": { "$value": "{color.ink-muted}" },
|
|
41
|
+
|
|
42
|
+
"chart-series-1": { "$value": "#4A90D9", "$description": "Dark is a selected palette, not an automatic flip: each step was re-chosen against the dark surface and re-validated." },
|
|
43
|
+
"chart-series-2": { "$value": "#AD8B2A" },
|
|
44
|
+
"chart-series-3": { "$value": "#D16A9A" },
|
|
45
|
+
"chart-series-4": { "$value": "#2F9463" },
|
|
46
|
+
"chart-series-5": { "$value": "#9B7ED9" },
|
|
47
|
+
|
|
48
|
+
"chart-axis": { "$value": "#6b685f" },
|
|
49
|
+
"chart-grid": { "$value": "#282722" },
|
|
50
|
+
"chart-reference": { "$value": "#9b978d" },
|
|
51
|
+
"chart-tooltip-bg": { "$value": "#2a2a26" },
|
|
52
|
+
"chart-tooltip-ink": { "$value": "#f2f0ea" },
|
|
53
|
+
"chart-tooltip-border": { "$value": "#4a4840" },
|
|
54
|
+
|
|
55
|
+
"chart-seq-1": { "$value": "#36618C" },
|
|
56
|
+
"chart-seq-2": { "$value": "#4A7FB0" },
|
|
57
|
+
"chart-seq-3": { "$value": "#5E9CD1" },
|
|
58
|
+
"chart-seq-4": { "$value": "#86B9E3" },
|
|
59
|
+
"chart-seq-5": { "$value": "#B3D6F2" },
|
|
60
|
+
|
|
61
|
+
"chart-div-1": { "$value": "#AD8B2A" },
|
|
62
|
+
"chart-div-2": { "$value": "#7E6A32" },
|
|
63
|
+
"chart-div-3": { "$value": "#34322E" },
|
|
64
|
+
"chart-div-4": { "$value": "#3E6B96" },
|
|
65
|
+
"chart-div-5": { "$value": "#86B9E3" },
|
|
66
|
+
|
|
67
|
+
"field-bg": { "$value": "#1c1c1a" },
|
|
68
|
+
"field-border": { "$value": "#6b685f" },
|
|
69
|
+
"field-border-hover": { "$value": "#9b978d" },
|
|
70
|
+
"field-ink-placeholder": { "$value": "#9b978d" },
|
|
71
|
+
"field-bg-disabled": { "$value": "#242421" },
|
|
72
|
+
|
|
73
|
+
"success": { "$value": "#5cc184" },
|
|
74
|
+
"success-tint": { "$value": "#15251b" },
|
|
75
|
+
"warning": { "$value": "#e5bc6a" },
|
|
76
|
+
"warning-tint": { "$value": "#272015" },
|
|
77
|
+
"error": { "$value": "#ef8288" },
|
|
78
|
+
"error-tint": { "$value": "#2a1719" },
|
|
79
|
+
"info": { "$value": "#8fbce8" },
|
|
80
|
+
"info-tint": { "$value": "#151f28" }
|
|
81
|
+
}
|
|
82
|
+
}
|