@fluid-theme/core 0.4.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +6 -29
- package/CHANGELOG.md +543 -2
- package/CLAUDE.md +193 -14
- package/GEMINI.md +6 -45
- package/README.md +17 -8
- package/assets/js/compare.js +77 -0
- package/assets/js/fit-text.js +103 -0
- package/assets/js/lightbox.js +153 -0
- package/assets/js/scroll-reveal.js +72 -0
- package/assets/js/toc-build.mjs +86 -0
- package/assets/js/toc.js +384 -0
- package/dist/fluid-1x.min.css +4 -0
- package/dist/fluid-fonts.min.css +2 -0
- package/dist/fluid-legacy-1x.css +3 -0
- package/dist/fluid-nav.min.css +3 -0
- package/dist/fluid-toc.min.css +3 -0
- package/dist/fluid-zero.min.css +3 -0
- package/dist/fluid.min.css +3 -2
- package/dist/fonts/OFL-newsreader.txt +93 -0
- package/dist/fonts/OFL-schibsted-grotesk.txt +93 -0
- package/dist/fonts/newsreader-latin-opsz-italic.woff2 +0 -0
- package/dist/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
- package/dist/fonts/schibsted-grotesk-latin-wght-italic.woff2 +0 -0
- package/dist/fonts/schibsted-grotesk-latin-wght-normal.woff2 +0 -0
- package/fluid-agent-kit/README.md +1 -0
- package/fluid-agent-kit/skills/accessibility.md +3 -1
- package/fluid-agent-kit/skills/css-conventions.md +22 -5
- package/fluid-agent-kit/skills/image-optimization.md +2 -0
- package/fluid-agent-kit/skills/preset-composition.md +108 -0
- package/package.json +29 -3
- package/src/animations/scroll-reveal.css +75 -193
- package/src/components/accordion.css +6 -47
- package/src/components/alert.css +47 -88
- package/src/components/avatar.css +4 -20
- package/src/components/badge.css +25 -48
- package/src/components/button.css +69 -175
- package/src/components/card.css +146 -481
- package/src/components/chip.css +46 -12
- package/src/components/compare.css +234 -0
- package/src/components/dropdown.css +10 -67
- package/src/components/empty-state.css +4 -0
- package/src/components/form.css +113 -81
- package/src/components/gallery.css +252 -0
- package/src/components/hero.css +203 -88
- package/src/components/indicator.css +23 -117
- package/src/components/loading.css +7 -29
- package/src/components/modal.css +12 -65
- package/src/components/nav-modes.css +261 -0
- package/src/components/nav.css +324 -392
- package/src/components/search-input.css +4 -2
- package/src/components/step-indicator.css +26 -27
- package/src/components/table.css +64 -171
- package/src/components/toc.css +254 -0
- package/src/components/tooltip.css +5 -46
- package/src/core/base.css +393 -547
- package/src/core/reset.css +17 -5
- package/src/core/tokens.css +426 -2276
- package/src/fluid.css +258 -17
- package/src/fonts/OFL-newsreader.txt +93 -0
- package/src/fonts/OFL-schibsted-grotesk.txt +93 -0
- package/src/fonts/fluid-fonts.css +55 -0
- package/src/fonts/newsreader-latin-opsz-italic.woff2 +0 -0
- package/src/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
- package/src/fonts/schibsted-grotesk-latin-wght-italic.woff2 +0 -0
- package/src/fonts/schibsted-grotesk-latin-wght-normal.woff2 +0 -0
- package/src/layouts/positioning.css +6 -3
- package/src/legacy-1x.css +61 -0
- package/src/sections/cta.css +33 -101
- package/src/sections/features.css +42 -219
- package/src/sections/footer.css +53 -134
- package/src/sections/stats.css +40 -153
- package/src/sections/team.css +24 -113
- package/src/sections/testimonials.css +34 -148
- package/src/zero/base.css +166 -0
- package/src/zero/tokens.css +64 -0
- package/src/zero.css +20 -0
- package/src/components/scroll-progress.css +0 -104
- package/src/components/settings-panel.css +0 -603
- package/src/components/themed-images.css +0 -229
- package/src/components/version-badge.css +0 -70
package/src/core/base.css
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Fluid
|
|
2
|
+
* Fluid Theme - Base Element Styles
|
|
3
3
|
* @layer base
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Native elements, no classes needed. A quality-press page: a serif for
|
|
6
|
+
* display and headings, a grotesk for text and labels, one accent used like
|
|
7
|
+
* spice, square corners, no shadows. Nothing moves on hover except colour
|
|
8
|
+
* and underline.
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
@layer base {
|
|
@@ -13,11 +14,12 @@
|
|
|
13
14
|
======================================== */
|
|
14
15
|
|
|
15
16
|
body {
|
|
16
|
-
font-family: var(--font-body
|
|
17
|
-
font-size: var(--
|
|
18
|
-
line-height: var(--leading-
|
|
17
|
+
font-family: var(--font-body);
|
|
18
|
+
font-size: var(--step-0);
|
|
19
|
+
line-height: var(--leading-body);
|
|
19
20
|
color: var(--color-text);
|
|
20
21
|
background-color: var(--color-background);
|
|
22
|
+
text-wrap: pretty;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
::selection {
|
|
@@ -27,88 +29,141 @@
|
|
|
27
29
|
|
|
28
30
|
|
|
29
31
|
/* ========================================
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
HEADINGS
|
|
33
|
+
A big, obvious ladder: serif h1-h3 at the scale's top, a change of face
|
|
34
|
+
at h4, the label voice at h5 and h6. Every weight adds --_dark-weight
|
|
35
|
+
(30 in dark mode and on dark bands).
|
|
32
36
|
======================================== */
|
|
33
37
|
|
|
34
38
|
h1, h2, h3, h4, h5, h6 {
|
|
35
|
-
font-family: var(--font-heading, var(--font-system));
|
|
36
39
|
color: var(--color-text);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
40
|
+
margin-block: 0 var(--space-4);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* The trim is over the cap height only: trimming the alphabetic baseline
|
|
44
|
+
too let descenders (p, q, g) hang into the next block at display sizes. */
|
|
45
|
+
h1, h2, h3 {
|
|
46
|
+
font-family: var(--font-heading);
|
|
47
|
+
font-weight: calc(var(--weight-display) + var(--_dark-weight));
|
|
48
|
+
line-height: var(--leading-heading);
|
|
49
|
+
text-wrap: balance;
|
|
50
|
+
text-box: trim-start cap alphabetic;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* --h1-size, --h2-size, --h3-size (knobs, no default) set a heading's
|
|
54
|
+
size outright; unset, the steps. legacy-1x sets them to the 1.x clamps,
|
|
55
|
+
so the steps (also the nav brand, lede, card title) keep their values. */
|
|
56
|
+
h1 { font-size: var(--h1-size, var(--step-4)); letter-spacing: var(--tracking-tight); }
|
|
57
|
+
/* --weight-heading (a knob, no default) sets h2 and h3 to one weight;
|
|
58
|
+
unset, h2 follows the display weight and h3 sits 100 above it, but
|
|
59
|
+
never above 700 unless the display is (display 700 gives h3 700, not
|
|
60
|
+
an h3 heavier than its h2). */
|
|
50
61
|
h2 {
|
|
51
|
-
font-size: var(--
|
|
52
|
-
|
|
62
|
+
font-size: var(--h2-size, var(--step-2));
|
|
63
|
+
font-weight: calc(var(--weight-heading, var(--weight-display)) + var(--_dark-weight));
|
|
64
|
+
letter-spacing: var(--tracking-heading);
|
|
53
65
|
}
|
|
54
|
-
|
|
55
66
|
h3 {
|
|
56
|
-
font-size: var(--
|
|
57
|
-
|
|
67
|
+
font-size: var(--h3-size, var(--step-1));
|
|
68
|
+
font-weight: calc(var(--weight-heading, min(var(--weight-display) + 100, max(var(--weight-display), 700))) + var(--_dark-weight));
|
|
69
|
+
letter-spacing: var(--tracking-normal);
|
|
58
70
|
}
|
|
59
71
|
|
|
60
72
|
h4 {
|
|
61
|
-
font-
|
|
62
|
-
letter-spacing: var(--tracking-tight);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
h5 {
|
|
73
|
+
font-family: var(--font-body);
|
|
66
74
|
font-size: var(--font-size-lg);
|
|
67
|
-
font-weight: var(--weight
|
|
68
|
-
|
|
75
|
+
font-weight: calc(650 + var(--_dark-weight));
|
|
76
|
+
line-height: 1.3;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* The label voice: every small uppercase label is this one rule. Longhands,
|
|
80
|
+
so nothing else is reset; lining but proportional figures (tabular ones
|
|
81
|
+
gap the comma: "GOGH , 1889"; a numeric head takes .num); :where(), so
|
|
82
|
+
each element keeps its own low specificity. */
|
|
83
|
+
:where(.eyebrow, h5, h6, thead th, .plate, cite, legend, dt, .toc__label) {
|
|
84
|
+
font-family: var(--font-body);
|
|
85
|
+
font-size: var(--step--2);
|
|
86
|
+
font-weight: calc(var(--weight-semibold) + var(--_dark-weight));
|
|
87
|
+
line-height: var(--leading-tight);
|
|
88
|
+
font-style: normal;
|
|
89
|
+
text-transform: uppercase;
|
|
90
|
+
letter-spacing: var(--tracking-caps);
|
|
91
|
+
font-variant-numeric: lining-nums;
|
|
92
|
+
color: var(--color-text-muted);
|
|
69
93
|
}
|
|
70
94
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
95
|
+
.eyebrow { color: var(--accent-ink); margin-block: 0 var(--space-s); }
|
|
96
|
+
:where(h5, .plate) { color: var(--color-text); }
|
|
97
|
+
h6 { color: var(--color-text-muted); }
|
|
98
|
+
|
|
76
99
|
|
|
77
|
-
/*
|
|
78
|
-
|
|
79
|
-
|
|
100
|
+
/* ========================================
|
|
101
|
+
DISPLAY HEADLINES
|
|
102
|
+
The font size is a fixed share of the column's width, so a hand break
|
|
103
|
+
(<br>) stays put and every line keeps filling the column as the screen
|
|
104
|
+
grows. --fit is the longest line's width in em (characters × 0.5,
|
|
105
|
+
rounded up; fit-text.js measures it once for [data-fit]). Optical size
|
|
106
|
+
is pinned so glyph width scales linearly with size. The cap is also
|
|
107
|
+
15svh, so a three-line headline leaves the lede and actions above the
|
|
108
|
+
fold on a 900px-tall laptop (160px type pushed them under it). Setting
|
|
109
|
+
--hero-headline-size on :root overrides the fit.
|
|
110
|
+
======================================== */
|
|
111
|
+
|
|
112
|
+
.display,
|
|
113
|
+
.hero__headline {
|
|
114
|
+
font-family: var(--font-display);
|
|
115
|
+
font-weight: calc(var(--weight-display) + var(--_dark-weight));
|
|
116
|
+
font-size: var(--hero-headline-size,
|
|
117
|
+
clamp(var(--step-4), 100cqi / var(--fit, 8), min(var(--display-max), 15svh)));
|
|
118
|
+
font-variation-settings: "opsz" 72;
|
|
119
|
+
line-height: 1;
|
|
120
|
+
letter-spacing: var(--tracking-display);
|
|
121
|
+
text-wrap: balance;
|
|
122
|
+
text-box: trim-start cap alphabetic;
|
|
80
123
|
}
|
|
81
124
|
|
|
82
125
|
|
|
83
126
|
/* ========================================
|
|
84
|
-
|
|
85
|
-
Room to breathe
|
|
127
|
+
TEXT
|
|
86
128
|
======================================== */
|
|
87
129
|
|
|
88
130
|
p {
|
|
89
|
-
margin-block
|
|
90
|
-
max-inline-size: var(--
|
|
131
|
+
margin-block: 0 var(--space-5);
|
|
132
|
+
max-inline-size: var(--measure);
|
|
91
133
|
}
|
|
92
134
|
|
|
93
|
-
|
|
94
|
-
p:last-child {
|
|
95
|
-
margin-block-end: 0;
|
|
96
|
-
}
|
|
135
|
+
p:last-child { margin-block-end: 0; }
|
|
97
136
|
|
|
98
|
-
|
|
99
|
-
font-
|
|
137
|
+
.lede {
|
|
138
|
+
font-family: var(--font-heading);
|
|
139
|
+
font-weight: calc(var(--weight-light) + var(--_dark-weight));
|
|
140
|
+
font-size: var(--step-1);
|
|
141
|
+
line-height: 1.4;
|
|
142
|
+
letter-spacing: -0.005em;
|
|
143
|
+
max-inline-size: 30em;
|
|
100
144
|
}
|
|
101
145
|
|
|
102
|
-
|
|
103
|
-
font-
|
|
146
|
+
:is(.meta, figcaption) {
|
|
147
|
+
font-family: var(--font-body);
|
|
148
|
+
font-size: var(--step--1);
|
|
149
|
+
font-weight: 400;
|
|
150
|
+
line-height: 1.45;
|
|
151
|
+
letter-spacing: 0.01em;
|
|
152
|
+
color: var(--color-text-muted);
|
|
153
|
+
/* Lining but proportional: tabular figures in these faces also widen
|
|
154
|
+
the comma and full stop, which gaps running caption text. */
|
|
155
|
+
font-variant-numeric: lining-nums proportional-nums;
|
|
104
156
|
}
|
|
105
157
|
|
|
158
|
+
strong, b { font-weight: calc(var(--weight-semibold) + var(--_dark-weight)); }
|
|
159
|
+
|
|
160
|
+
em, i { font-style: italic; }
|
|
161
|
+
|
|
106
162
|
small {
|
|
107
|
-
font-size: var(--
|
|
163
|
+
font-size: var(--step--1);
|
|
108
164
|
color: var(--color-text-muted);
|
|
109
165
|
}
|
|
110
166
|
|
|
111
|
-
/* Subscript and superscript */
|
|
112
167
|
sub, sup {
|
|
113
168
|
font-size: 75%;
|
|
114
169
|
line-height: 0;
|
|
@@ -116,231 +171,128 @@
|
|
|
116
171
|
vertical-align: baseline;
|
|
117
172
|
}
|
|
118
173
|
|
|
119
|
-
sup {
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
sub {
|
|
124
|
-
inset-block-end: -0.25em;
|
|
125
|
-
}
|
|
174
|
+
sup { inset-block-start: -0.5em; }
|
|
175
|
+
sub { inset-block-end: -0.25em; }
|
|
126
176
|
|
|
127
177
|
|
|
128
178
|
/* ========================================
|
|
129
179
|
LINKS
|
|
130
|
-
|
|
180
|
+
Text colour; the underline marks the link (WCAG 1.4.1). Hover turns
|
|
181
|
+
the underline to the accent and thickens it. Only colour and the
|
|
182
|
+
underline transition.
|
|
131
183
|
======================================== */
|
|
132
184
|
|
|
133
185
|
a {
|
|
134
|
-
color:
|
|
135
|
-
text-decoration: underline;
|
|
136
|
-
text-decoration-
|
|
137
|
-
text-
|
|
186
|
+
color: inherit;
|
|
187
|
+
text-decoration-line: underline;
|
|
188
|
+
text-decoration-color: color-mix(in oklch, var(--accent-ink) 55%, transparent);
|
|
189
|
+
text-decoration-thickness: 0.06em;
|
|
190
|
+
text-underline-offset: 0.22em;
|
|
191
|
+
text-decoration-skip-ink: auto;
|
|
138
192
|
transition:
|
|
139
|
-
color var(--duration-
|
|
140
|
-
text-decoration-color var(--duration-
|
|
193
|
+
color var(--duration-fast) var(--ease-fluid),
|
|
194
|
+
text-decoration-color var(--duration-fast) var(--ease-fluid),
|
|
195
|
+
text-decoration-thickness var(--duration-fast) var(--ease-fluid);
|
|
141
196
|
}
|
|
142
197
|
|
|
143
198
|
a:hover {
|
|
144
|
-
color: var(--accent-
|
|
145
|
-
text-decoration-thickness:
|
|
199
|
+
text-decoration-color: var(--accent-ink);
|
|
200
|
+
text-decoration-thickness: 0.12em;
|
|
146
201
|
}
|
|
147
202
|
|
|
148
|
-
/* Links that look like text
|
|
149
|
-
a[data-subtle] {
|
|
150
|
-
|
|
151
|
-
text-decoration: none;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
a[data-subtle]:hover {
|
|
155
|
-
color: var(--accent);
|
|
156
|
-
text-decoration: underline;
|
|
157
|
-
}
|
|
203
|
+
/* Links that look like text and show their underline on hover */
|
|
204
|
+
a[data-subtle] { text-decoration-line: none; }
|
|
205
|
+
a[data-subtle]:hover { text-decoration-line: underline; }
|
|
158
206
|
|
|
159
207
|
|
|
160
208
|
/* ========================================
|
|
161
209
|
LISTS
|
|
162
|
-
Structured with breathing room
|
|
163
|
-
Theme-specific list markers
|
|
164
210
|
======================================== */
|
|
165
211
|
|
|
166
212
|
ul, ol {
|
|
167
213
|
padding-inline-start: var(--space-6);
|
|
168
|
-
margin-block
|
|
214
|
+
margin-block: 0 var(--space-5);
|
|
169
215
|
}
|
|
170
216
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
li:last-child {
|
|
176
|
-
margin-block-end: 0;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/* Nested lists */
|
|
180
|
-
li > ul,
|
|
181
|
-
li > ol {
|
|
182
|
-
margin-block-start: var(--space-2);
|
|
183
|
-
margin-block-end: 0;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/* === Themed list markers ===
|
|
187
|
-
Each child theme gets a distinctive marker
|
|
188
|
-
Note: Uses :not([class]) to avoid overriding nav dropdowns and other styled lists */
|
|
189
|
-
|
|
190
|
-
/* Still: Clean disc (default - minimal) */
|
|
191
|
-
[data-motion="still"] ul:not([class]) {
|
|
192
|
-
list-style-type: disc;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/* Serene: Open circle - elegant, understated */
|
|
196
|
-
[data-motion="serene"] ul:not([class]) {
|
|
197
|
-
list-style-type: circle;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/* Stream: Dash - modern, horizontal emphasis */
|
|
201
|
-
[data-motion="stream"] ul:not([class]) {
|
|
202
|
-
list-style-type: none;
|
|
203
|
-
padding-inline-start: var(--space-5);
|
|
204
|
-
}
|
|
205
|
-
[data-motion="stream"] ul:not([class]) > li {
|
|
206
|
-
position: relative;
|
|
207
|
-
}
|
|
208
|
-
[data-motion="stream"] ul:not([class]) > li::before {
|
|
209
|
-
content: "—";
|
|
210
|
-
position: absolute;
|
|
211
|
-
inset-inline-start: calc(var(--space-5) * -1);
|
|
212
|
-
color: var(--accent);
|
|
213
|
-
font-weight: var(--weight-bold);
|
|
214
|
-
}
|
|
217
|
+
/* Chrome draws markers with tabular figures, which in these faces widen
|
|
218
|
+
the full stop ("1 ."). */
|
|
219
|
+
::marker { font-variant-numeric: lining-nums proportional-nums; }
|
|
215
220
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
list-style-type: none;
|
|
219
|
-
padding-inline-start: var(--space-6);
|
|
220
|
-
}
|
|
221
|
-
[data-motion="cascade"] ul:not([class]) > li {
|
|
222
|
-
position: relative;
|
|
223
|
-
}
|
|
224
|
-
[data-motion="cascade"] ul:not([class]) > li::before {
|
|
225
|
-
content: "";
|
|
226
|
-
position: absolute;
|
|
227
|
-
inset-inline-start: calc(var(--space-6) * -1);
|
|
228
|
-
inset-block-start: 0.55em;
|
|
229
|
-
inline-size: 0.5em;
|
|
230
|
-
block-size: 0.5em;
|
|
231
|
-
background: var(--accent);
|
|
232
|
-
border-radius: var(--radius-full);
|
|
233
|
-
}
|
|
221
|
+
li { margin-block-end: var(--space-2); }
|
|
222
|
+
li:last-child { margin-block-end: 0; }
|
|
234
223
|
|
|
235
|
-
|
|
236
|
-
[data-motion="rapids"] ul:not([class]) {
|
|
237
|
-
list-style-type: none;
|
|
238
|
-
padding-inline-start: var(--space-6);
|
|
239
|
-
}
|
|
240
|
-
[data-motion="rapids"] ul:not([class]) > li {
|
|
241
|
-
position: relative;
|
|
242
|
-
}
|
|
243
|
-
[data-motion="rapids"] ul:not([class]) > li::before {
|
|
244
|
-
content: "";
|
|
245
|
-
position: absolute;
|
|
246
|
-
inset-inline-start: calc(var(--space-6) * -1);
|
|
247
|
-
inset-block-start: 0.4em;
|
|
248
|
-
inline-size: 0;
|
|
249
|
-
block-size: 0;
|
|
250
|
-
border-block-start: 0.35em solid transparent;
|
|
251
|
-
border-block-end: 0.35em solid transparent;
|
|
252
|
-
border-inline-start: 0.5em solid var(--accent);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/* Tsunami: Square - bold, impactful */
|
|
256
|
-
[data-motion="tsunami"] ul:not([class]) {
|
|
257
|
-
list-style-type: none;
|
|
258
|
-
padding-inline-start: var(--space-6);
|
|
259
|
-
}
|
|
260
|
-
[data-motion="tsunami"] ul:not([class]) > li {
|
|
261
|
-
position: relative;
|
|
262
|
-
}
|
|
263
|
-
[data-motion="tsunami"] ul:not([class]) > li::before {
|
|
264
|
-
content: "";
|
|
265
|
-
position: absolute;
|
|
266
|
-
inset-inline-start: calc(var(--space-6) * -1);
|
|
267
|
-
inset-block-start: 0.5em;
|
|
268
|
-
inline-size: 0.5em;
|
|
269
|
-
block-size: 0.5em;
|
|
270
|
-
background: var(--accent);
|
|
271
|
-
}
|
|
224
|
+
li > :is(ul, ol) { margin-block: var(--space-2) 0; }
|
|
272
225
|
|
|
273
|
-
/*
|
|
274
|
-
dl {
|
|
275
|
-
margin-block-end: var(--space-5);
|
|
276
|
-
}
|
|
226
|
+
/* A term in the label voice (above), its value flush under it. */
|
|
227
|
+
dl { margin-block: 0 var(--space-5); }
|
|
277
228
|
|
|
278
|
-
dt {
|
|
279
|
-
font-weight: var(--weight-semibold);
|
|
280
|
-
margin-block-end: var(--space-1);
|
|
281
|
-
}
|
|
229
|
+
dt { margin-block-end: var(--space-1); }
|
|
282
230
|
|
|
283
231
|
dd {
|
|
284
|
-
margin-inline-start:
|
|
232
|
+
margin-inline-start: 0;
|
|
285
233
|
margin-block-end: var(--space-4);
|
|
286
|
-
color: var(--color-text-muted);
|
|
287
234
|
}
|
|
288
235
|
|
|
289
236
|
|
|
290
237
|
/* ========================================
|
|
291
|
-
|
|
292
|
-
Thoughtful, set apart
|
|
238
|
+
QUOTES
|
|
293
239
|
======================================== */
|
|
294
240
|
|
|
295
241
|
blockquote {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
border-inline-start:
|
|
300
|
-
|
|
242
|
+
margin-inline: 0;
|
|
243
|
+
margin-block: var(--space-l);
|
|
244
|
+
padding-inline-start: 1.25em;
|
|
245
|
+
border-inline-start: var(--border-width-thick) solid var(--accent);
|
|
246
|
+
font-family: var(--font-heading);
|
|
247
|
+
font-size: var(--step-1);
|
|
301
248
|
font-style: italic;
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
blockquote::before {
|
|
305
|
-
content: none; /* No decorative quotes - let content speak */
|
|
249
|
+
line-height: 1.4;
|
|
306
250
|
}
|
|
307
251
|
|
|
308
252
|
blockquote cite {
|
|
309
253
|
display: block;
|
|
310
|
-
margin-block-start: var(--space-
|
|
311
|
-
font-size: var(--font-size-sm);
|
|
312
|
-
font-style: normal;
|
|
313
|
-
color: var(--color-text-subtle);
|
|
254
|
+
margin-block-start: var(--space-s);
|
|
314
255
|
}
|
|
315
256
|
|
|
316
|
-
|
|
317
|
-
|
|
257
|
+
/* A pull quote repeats the text, so it is a <p class="pullquote">, not
|
|
258
|
+
an <aside> (a complementary landmark nested in the article) and not a
|
|
259
|
+
<blockquote> (it quotes no one else). */
|
|
260
|
+
.pullquote {
|
|
261
|
+
margin-inline: 0;
|
|
262
|
+
margin-block: var(--space-l);
|
|
263
|
+
padding-block: var(--space-m);
|
|
264
|
+
border-block: var(--border-width) solid var(--color-border-strong);
|
|
265
|
+
font-family: var(--font-heading);
|
|
266
|
+
font-size: var(--step-3);
|
|
267
|
+
font-weight: calc(var(--weight-light) + var(--_dark-weight));
|
|
268
|
+
line-height: var(--leading-heading);
|
|
269
|
+
letter-spacing: var(--tracking-heading);
|
|
270
|
+
text-wrap: balance;
|
|
318
271
|
}
|
|
319
272
|
|
|
320
273
|
|
|
321
274
|
/* ========================================
|
|
322
275
|
CODE
|
|
323
|
-
Technical but approachable
|
|
324
276
|
======================================== */
|
|
325
277
|
|
|
278
|
+
:is(code, kbd, samp, pre) { font-family: var(--font-mono); }
|
|
279
|
+
|
|
326
280
|
code {
|
|
327
|
-
font-family: var(--font-mono);
|
|
328
281
|
font-size: 0.9em;
|
|
329
282
|
background-color: var(--color-surface);
|
|
330
|
-
padding
|
|
331
|
-
|
|
332
|
-
border-radius: var(--radius-sm);
|
|
283
|
+
padding: 0.1em 0.3em;
|
|
284
|
+
border-radius: var(--radius-control);
|
|
333
285
|
}
|
|
334
286
|
|
|
335
287
|
pre {
|
|
336
|
-
font-
|
|
337
|
-
font-size: var(--font-size-sm);
|
|
288
|
+
font-size: var(--step--1);
|
|
338
289
|
line-height: var(--leading-relaxed);
|
|
339
290
|
background-color: var(--color-surface);
|
|
340
|
-
|
|
341
|
-
border-radius: var(--radius-
|
|
291
|
+
border: var(--border-width) solid var(--color-border);
|
|
292
|
+
border-radius: var(--radius-card);
|
|
293
|
+
padding: var(--space-m);
|
|
342
294
|
overflow-x: auto;
|
|
343
|
-
margin-block
|
|
295
|
+
margin-block: 0 var(--space-5);
|
|
344
296
|
tab-size: 2;
|
|
345
297
|
}
|
|
346
298
|
|
|
@@ -348,22 +300,13 @@
|
|
|
348
300
|
background: none;
|
|
349
301
|
padding: 0;
|
|
350
302
|
font-size: inherit;
|
|
351
|
-
border-radius: 0;
|
|
352
303
|
}
|
|
353
304
|
|
|
354
305
|
kbd {
|
|
355
|
-
font-family: var(--font-mono);
|
|
356
306
|
font-size: 0.875em;
|
|
357
|
-
|
|
358
|
-
border:
|
|
359
|
-
|
|
360
|
-
padding-inline: var(--space-1-5);
|
|
361
|
-
padding-block: var(--space-0-5);
|
|
362
|
-
box-shadow: var(--shadow-xs);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
samp {
|
|
366
|
-
font-family: var(--font-mono);
|
|
307
|
+
border: var(--border-width) solid var(--color-border-strong);
|
|
308
|
+
border-radius: var(--radius-control);
|
|
309
|
+
padding: 0.1em 0.35em;
|
|
367
310
|
}
|
|
368
311
|
|
|
369
312
|
var {
|
|
@@ -373,82 +316,151 @@
|
|
|
373
316
|
|
|
374
317
|
|
|
375
318
|
/* ========================================
|
|
376
|
-
|
|
377
|
-
Quiet separation
|
|
319
|
+
RULES
|
|
378
320
|
======================================== */
|
|
379
321
|
|
|
380
322
|
hr {
|
|
381
323
|
border: none;
|
|
382
|
-
border-block-start:
|
|
383
|
-
|
|
324
|
+
border-block-start: var(--border-width) solid var(--color-border);
|
|
325
|
+
max-inline-size: var(--measure);
|
|
326
|
+
margin-block: var(--space-xl);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
hr[data-variant="ornament"] {
|
|
330
|
+
border: 0;
|
|
331
|
+
text-align: center;
|
|
332
|
+
overflow: visible;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/* Three asterisks in the heading face: the asterism glyph (⁂) is not in
|
|
336
|
+
the latin subset of the fonts file, so it fell back to another face. */
|
|
337
|
+
hr[data-variant="ornament"]::before {
|
|
338
|
+
content: "*\2003*\2003*";
|
|
339
|
+
font: var(--step-1) / 1 var(--font-heading);
|
|
340
|
+
color: var(--color-text-muted);
|
|
384
341
|
}
|
|
385
342
|
|
|
386
343
|
|
|
387
344
|
/* ========================================
|
|
388
345
|
MEDIA
|
|
389
|
-
|
|
346
|
+
Images in true colour at their natural ratio. data-aspect crops any
|
|
347
|
+
img or video; data-focus (on it or a wrapper) sets the crop's focal point.
|
|
390
348
|
======================================== */
|
|
391
349
|
|
|
392
|
-
|
|
393
|
-
|
|
350
|
+
:is(img, video) { object-position: var(--focus, 50% 50%); }
|
|
351
|
+
|
|
352
|
+
[data-aspect="square"] { --_aspect: 1; }
|
|
353
|
+
[data-aspect="video"] { --_aspect: 16 / 9; }
|
|
354
|
+
[data-aspect="portrait"] { --_aspect: 3 / 4; }
|
|
355
|
+
[data-aspect="wide"] { --_aspect: 21 / 9; }
|
|
356
|
+
|
|
357
|
+
:is(img, video)[data-aspect] {
|
|
358
|
+
aspect-ratio: var(--_aspect, auto);
|
|
359
|
+
object-fit: cover;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
[data-focus="top"] { --focus: 50% 0; }
|
|
363
|
+
[data-focus="bottom"] { --focus: 50% 100%; }
|
|
364
|
+
[data-focus="left"] { --focus: 0 50%; }
|
|
365
|
+
[data-focus="right"] { --focus: 100% 50%; }
|
|
366
|
+
[data-focus="center"] { --focus: 50% 50%; }
|
|
367
|
+
|
|
368
|
+
figure { margin: 0; margin-block: var(--space-l); }
|
|
369
|
+
|
|
370
|
+
figure :is(img, picture, video) {
|
|
371
|
+
inline-size: 100%;
|
|
372
|
+
border-radius: var(--radius-card);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/* An uncropped image is never taller than the screen: a portrait at the
|
|
376
|
+
column's full width ran two screens tall. The box keeps the column's
|
|
377
|
+
width and the width/height attributes' ratio, so a lazy image holds
|
|
378
|
+
its space before it loads (inline-size: auto made it 0 × 0); a
|
|
379
|
+
portrait capped at 85svh is fitted inside the box at the start edge,
|
|
380
|
+
never squashed. Full-bleed figures and the hero plate are not capped:
|
|
381
|
+
they are the full width at their natural ratio. */
|
|
382
|
+
figure:not([data-bleed="full"], .alignfull, .hero__plate) > :is(img, video):not([data-aspect]),
|
|
383
|
+
figure:not([data-bleed="full"], .alignfull, .hero__plate) > picture > img:not([data-aspect]) {
|
|
384
|
+
block-size: auto;
|
|
385
|
+
max-block-size: 85svh;
|
|
386
|
+
object-fit: contain;
|
|
387
|
+
object-position: var(--focus, 0% 50%);
|
|
394
388
|
}
|
|
395
389
|
|
|
396
390
|
figcaption {
|
|
397
|
-
margin-block-start: var(--space-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
391
|
+
margin-block-start: var(--space-xs);
|
|
392
|
+
max-inline-size: 48ch;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/* A credit in <small>, a plate number in .plate or b, a work title in <i>. */
|
|
396
|
+
figcaption :is(.plate, b) {
|
|
397
|
+
margin-inline-end: 0.75em;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
figcaption small { font-size: inherit; }
|
|
401
|
+
|
|
402
|
+
@container (inline-size > 60rem) {
|
|
403
|
+
figure[data-caption="side"] {
|
|
404
|
+
display: grid;
|
|
405
|
+
grid-template-columns: 1fr 16rem;
|
|
406
|
+
column-gap: var(--space-m);
|
|
407
|
+
align-items: end;
|
|
408
|
+
}
|
|
401
409
|
}
|
|
402
410
|
|
|
403
411
|
|
|
404
412
|
/* ========================================
|
|
405
413
|
TABLES
|
|
406
|
-
|
|
414
|
+
Label-voice head over a 2px ink rule, hairline rows, tabular figures.
|
|
407
415
|
======================================== */
|
|
408
416
|
|
|
417
|
+
/* Lining but proportional: tabular figures also widen the comma, which
|
|
418
|
+
gapped prose cells ("Boston , MA"). Numeric cells opt in below. */
|
|
409
419
|
table {
|
|
410
420
|
inline-size: 100%;
|
|
411
|
-
margin-block
|
|
421
|
+
margin-block: 0 var(--space-5);
|
|
412
422
|
border-collapse: collapse;
|
|
413
|
-
font-
|
|
423
|
+
font-size: var(--step--1);
|
|
424
|
+
font-variant-numeric: lining-nums proportional-nums;
|
|
414
425
|
}
|
|
415
426
|
|
|
416
|
-
th, td {
|
|
417
|
-
padding:
|
|
427
|
+
:is(th, td) {
|
|
428
|
+
padding-block: 0.85em;
|
|
429
|
+
padding-inline: 0 var(--space-4);
|
|
418
430
|
text-align: start;
|
|
419
|
-
border-block-end:
|
|
431
|
+
border-block-end: var(--border-width) solid var(--color-border);
|
|
420
432
|
}
|
|
421
433
|
|
|
422
|
-
th {
|
|
423
|
-
font-
|
|
424
|
-
|
|
425
|
-
background-color: var(--color-surface);
|
|
434
|
+
:is(td, th):is([data-type="number"], .num) {
|
|
435
|
+
font-variant-numeric: lining-nums tabular-nums;
|
|
436
|
+
text-align: end;
|
|
426
437
|
}
|
|
427
438
|
|
|
428
|
-
|
|
429
|
-
tbody tr:nth-child(even) {
|
|
430
|
-
background-color: oklch(from var(--shadow-color) l c h / 0.02);
|
|
431
|
-
}
|
|
439
|
+
th { font-weight: calc(var(--weight-semibold) + var(--_dark-weight)); }
|
|
432
440
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
441
|
+
thead th {
|
|
442
|
+
vertical-align: bottom;
|
|
443
|
+
border-block-end: var(--border-width-thick) solid var(--color-border-strong);
|
|
436
444
|
}
|
|
437
445
|
|
|
438
|
-
|
|
439
|
-
|
|
446
|
+
caption {
|
|
447
|
+
caption-side: top;
|
|
448
|
+
text-align: start;
|
|
449
|
+
margin-block-end: var(--space-xs);
|
|
440
450
|
}
|
|
441
451
|
|
|
442
452
|
|
|
443
453
|
/* ========================================
|
|
444
|
-
FORMS
|
|
445
|
-
|
|
454
|
+
FORMS
|
|
455
|
+
Square fields on the page colour with an ink edge, 3rem tall, body-size
|
|
456
|
+
text (which also stops iOS zooming on focus). Focus is an outline, so an
|
|
457
|
+
invalid field keeps its error border and still shows focus.
|
|
446
458
|
======================================== */
|
|
447
459
|
|
|
448
460
|
label {
|
|
449
461
|
display: block;
|
|
450
|
-
font-size: var(--
|
|
451
|
-
font-weight: var(--weight-
|
|
462
|
+
font-size: var(--step--1);
|
|
463
|
+
font-weight: calc(var(--weight-semibold) + var(--_dark-weight));
|
|
452
464
|
margin-block-end: var(--space-2);
|
|
453
465
|
color: var(--color-text);
|
|
454
466
|
}
|
|
@@ -457,195 +469,149 @@
|
|
|
457
469
|
textarea,
|
|
458
470
|
select {
|
|
459
471
|
inline-size: 100%;
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
472
|
+
min-block-size: 3rem;
|
|
473
|
+
padding: 0.6em 0.8em;
|
|
474
|
+
font: inherit;
|
|
475
|
+
font-size: var(--step-0);
|
|
476
|
+
line-height: 1.4;
|
|
463
477
|
color: var(--color-text);
|
|
464
478
|
background-color: var(--color-background);
|
|
465
|
-
border:
|
|
466
|
-
border-radius: var(--radius-
|
|
467
|
-
|
|
468
|
-
box-shadow:
|
|
469
|
-
inset 0 1px 2px oklch(from var(--shadow-color) l c h / 0.04),
|
|
470
|
-
0 1px 0 oklch(from var(--theme-light) l c h / 0.6);
|
|
471
|
-
transition:
|
|
472
|
-
border-color var(--duration-normal) var(--ease-fluid),
|
|
473
|
-
box-shadow var(--duration-normal) var(--ease-fluid),
|
|
474
|
-
background-color var(--duration-normal) var(--ease-fluid);
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
input:hover,
|
|
478
|
-
textarea:hover,
|
|
479
|
-
select:hover {
|
|
480
|
-
border-color: var(--color-text-subtle);
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
input:focus,
|
|
484
|
-
textarea:focus,
|
|
485
|
-
select:focus {
|
|
486
|
-
outline: 2px solid transparent;
|
|
487
|
-
border-color: var(--accent);
|
|
488
|
-
/* Focus: glow ring + maintain subtle 3D */
|
|
489
|
-
box-shadow:
|
|
490
|
-
var(--shadow-glow),
|
|
491
|
-
inset 0 1px 2px oklch(from var(--shadow-color) l c h / 0.03);
|
|
492
|
-
/* Soft focus background - subtle tint */
|
|
493
|
-
background-color: color-mix(in oklch, var(--accent) 8%, var(--color-background));
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
/* Dark mode: stronger tint needed for visibility */
|
|
497
|
-
@media (prefers-color-scheme: dark) {
|
|
498
|
-
input:focus,
|
|
499
|
-
textarea:focus,
|
|
500
|
-
select:focus {
|
|
501
|
-
background-color: color-mix(in oklch, var(--accent) 15%, var(--color-background));
|
|
502
|
-
}
|
|
479
|
+
border: var(--border-width) solid var(--color-border-strong);
|
|
480
|
+
border-radius: var(--radius-control);
|
|
481
|
+
transition: border-color var(--duration-fast) var(--ease-fluid);
|
|
503
482
|
}
|
|
504
483
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
background-color: color-mix(in oklch, var(--accent) 15%, var(--color-background));
|
|
484
|
+
:is(input, textarea, select):focus {
|
|
485
|
+
outline: var(--focus-ring-width) solid var(--color-focus);
|
|
486
|
+
outline-offset: 1px;
|
|
509
487
|
}
|
|
510
488
|
|
|
511
|
-
input::placeholder
|
|
512
|
-
textarea::placeholder {
|
|
489
|
+
:is(input, textarea)::placeholder {
|
|
513
490
|
color: var(--color-text-subtle);
|
|
514
491
|
opacity: 1;
|
|
515
492
|
}
|
|
516
493
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
textarea:disabled,
|
|
520
|
-
select:disabled {
|
|
521
|
-
opacity: 0.6;
|
|
494
|
+
:is(input, textarea, select):disabled {
|
|
495
|
+
opacity: 0.5;
|
|
522
496
|
cursor: not-allowed;
|
|
523
|
-
background-color: var(--color-surface);
|
|
524
497
|
}
|
|
525
498
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
499
|
+
/* Bare checkboxes and radios keep a box shape: the text-field rules above
|
|
500
|
+
(full width, padding, border) would turn <label><input type="checkbox">
|
|
501
|
+
Text</label> into a full-width bar. Same weight as `input`, so the custom
|
|
502
|
+
.checkbox / .radio / .switch inputs (one class) still win. */
|
|
503
|
+
input:where([type="checkbox"], [type="radio"]) {
|
|
504
|
+
inline-size: 1.25rem;
|
|
505
|
+
block-size: 1.25rem;
|
|
506
|
+
min-block-size: 0;
|
|
507
|
+
padding: 0;
|
|
508
|
+
margin: 0;
|
|
509
|
+
margin-inline-end: var(--space-2);
|
|
510
|
+
vertical-align: -0.2em;
|
|
511
|
+
border: 0;
|
|
512
|
+
accent-color: var(--accent);
|
|
513
|
+
cursor: pointer;
|
|
529
514
|
}
|
|
530
515
|
|
|
516
|
+
input:where([type="checkbox"], [type="radio"]):focus { outline: 0; }
|
|
531
517
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
518
|
+
input:where([type="checkbox"], [type="radio"]):focus-visible {
|
|
519
|
+
outline: var(--focus-ring-width) solid var(--color-focus);
|
|
520
|
+
outline-offset: 2px;
|
|
521
|
+
}
|
|
536
522
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
background-color: var(--accent);
|
|
548
|
-
border: none;
|
|
549
|
-
border-radius: var(--radius-md);
|
|
550
|
-
cursor: pointer;
|
|
551
|
-
transition:
|
|
552
|
-
background-color var(--duration-normal) var(--ease-fluid),
|
|
553
|
-
transform var(--duration-fast) var(--ease-settle),
|
|
554
|
-
box-shadow var(--duration-normal) var(--ease-fluid);
|
|
523
|
+
/* Date and time boxes take their cell's width. iOS Safari sizes a native
|
|
524
|
+
date/time input to its own content and ignores inline-size, so in a grid
|
|
525
|
+
it ran into the next column (#65). Without the native appearance it
|
|
526
|
+
behaves like a text field. */
|
|
527
|
+
input:where([type="date"], [type="time"], [type="datetime-local"], [type="month"], [type="week"]) {
|
|
528
|
+
display: block;
|
|
529
|
+
min-inline-size: 0;
|
|
530
|
+
max-inline-size: 100%;
|
|
531
|
+
-webkit-appearance: none;
|
|
532
|
+
appearance: none;
|
|
555
533
|
}
|
|
556
534
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
box-shadow: var(--shadow-sm);
|
|
535
|
+
input:where([type="date"], [type="time"], [type="datetime-local"], [type="month"], [type="week"])::-webkit-date-and-time-value {
|
|
536
|
+
text-align: start;
|
|
560
537
|
}
|
|
561
538
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
539
|
+
textarea {
|
|
540
|
+
min-block-size: 8rem;
|
|
541
|
+
resize: vertical;
|
|
565
542
|
}
|
|
566
543
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
544
|
+
/* Fieldset: no box, a top hairline, the legend in the label voice. */
|
|
545
|
+
fieldset {
|
|
546
|
+
margin: 0;
|
|
547
|
+
margin-block-end: var(--space-l);
|
|
548
|
+
padding: 0;
|
|
549
|
+
padding-block-start: var(--space-s);
|
|
550
|
+
border: 0;
|
|
551
|
+
border-block-start: var(--border-width) solid var(--color-border);
|
|
552
|
+
min-inline-size: 0;
|
|
570
553
|
}
|
|
571
554
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
555
|
+
legend {
|
|
556
|
+
float: inline-start;
|
|
557
|
+
inline-size: 100%;
|
|
558
|
+
padding: 0;
|
|
559
|
+
margin-block-end: var(--space-m);
|
|
576
560
|
}
|
|
577
561
|
|
|
562
|
+
legend + * { clear: both; }
|
|
563
|
+
|
|
578
564
|
|
|
579
565
|
/* ========================================
|
|
580
|
-
|
|
581
|
-
Native HTML interactivity
|
|
566
|
+
DETAILS
|
|
582
567
|
======================================== */
|
|
583
568
|
|
|
584
569
|
details {
|
|
585
|
-
margin-block
|
|
586
|
-
border:
|
|
587
|
-
border-radius: var(--radius-md);
|
|
588
|
-
padding: var(--space-4);
|
|
570
|
+
margin-block: 0 var(--space-4);
|
|
571
|
+
border-block: var(--border-width) solid var(--color-border);
|
|
589
572
|
}
|
|
590
573
|
|
|
574
|
+
details + details { border-block-start: 0; margin-block-start: calc(-1 * var(--space-4)); }
|
|
575
|
+
|
|
591
576
|
summary {
|
|
592
|
-
|
|
577
|
+
display: flex;
|
|
578
|
+
flex-wrap: wrap;
|
|
579
|
+
align-items: center;
|
|
580
|
+
gap: 0 var(--space-2);
|
|
581
|
+
min-block-size: 2.75rem;
|
|
582
|
+
padding-block: var(--space-2);
|
|
583
|
+
font-weight: calc(var(--weight-semibold) + var(--_dark-weight));
|
|
593
584
|
cursor: pointer;
|
|
594
|
-
padding: var(--space-2);
|
|
595
|
-
margin: calc(var(--space-4) * -1);
|
|
596
|
-
margin-block-end: 0;
|
|
597
|
-
border-radius: var(--radius-md);
|
|
598
|
-
transition: background-color var(--duration-normal) var(--ease-fluid);
|
|
599
585
|
}
|
|
600
586
|
|
|
601
|
-
summary:
|
|
602
|
-
background-color: var(--color-surface);
|
|
603
|
-
}
|
|
587
|
+
details[open] > summary { margin-block-end: var(--space-s); }
|
|
604
588
|
|
|
605
|
-
details
|
|
606
|
-
|
|
607
|
-
border-block-end: 1px solid var(--color-border-subtle);
|
|
608
|
-
border-end-start-radius: 0;
|
|
609
|
-
border-end-end-radius: 0;
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
/* Hide default marker in webkit */
|
|
613
|
-
summary::-webkit-details-marker {
|
|
614
|
-
display: none;
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
summary::marker {
|
|
618
|
-
content: "";
|
|
619
|
-
}
|
|
589
|
+
summary::-webkit-details-marker { display: none; }
|
|
590
|
+
summary::marker { content: ""; }
|
|
620
591
|
|
|
592
|
+
/* The chevron is decoration: empty alt text keeps it out of the
|
|
593
|
+
summary's accessible name (and so out of a landmark's name). */
|
|
621
594
|
summary::before {
|
|
622
595
|
content: "▸";
|
|
596
|
+
content: "▸" / "";
|
|
623
597
|
display: inline-block;
|
|
624
|
-
|
|
625
|
-
transition: transform var(--duration-normal) var(--ease-settle);
|
|
598
|
+
transition: rotate var(--duration-fast) var(--ease-settle);
|
|
626
599
|
}
|
|
627
600
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
}
|
|
601
|
+
/* Logical: the marker points along the inline direction and turns down. */
|
|
602
|
+
summary:dir(rtl)::before { scale: -1 1; }
|
|
603
|
+
details[open] > summary::before { rotate: 90deg; }
|
|
604
|
+
details[open] > summary:dir(rtl)::before { rotate: -90deg; }
|
|
631
605
|
|
|
632
606
|
|
|
633
607
|
/* ========================================
|
|
634
608
|
SEMANTIC ELEMENTS
|
|
635
|
-
Meaningful markup, meaningful styles
|
|
636
609
|
======================================== */
|
|
637
610
|
|
|
638
611
|
mark {
|
|
639
|
-
background-color: oklch(90% 0.08 90);
|
|
612
|
+
background-color: light-dark(oklch(90% 0.08 90), oklch(40% 0.08 90));
|
|
613
|
+
color: var(--color-text);
|
|
640
614
|
padding-inline: var(--space-1);
|
|
641
|
-
border-radius: var(--radius-sm);
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
@media (prefers-color-scheme: dark) {
|
|
645
|
-
mark {
|
|
646
|
-
background-color: oklch(40% 0.08 90);
|
|
647
|
-
color: oklch(95% 0.02 90);
|
|
648
|
-
}
|
|
649
615
|
}
|
|
650
616
|
|
|
651
617
|
abbr[title] {
|
|
@@ -658,96 +624,49 @@
|
|
|
658
624
|
margin-block-end: var(--space-5);
|
|
659
625
|
}
|
|
660
626
|
|
|
661
|
-
time {
|
|
662
|
-
font-variant-numeric: tabular-nums;
|
|
663
|
-
}
|
|
627
|
+
time { font-variant-numeric: lining-nums; }
|
|
664
628
|
|
|
665
629
|
|
|
666
630
|
/* ========================================
|
|
667
631
|
METER & PROGRESS
|
|
668
|
-
Visual feedback with viewport animation
|
|
669
632
|
======================================== */
|
|
670
633
|
|
|
671
634
|
meter,
|
|
672
635
|
progress {
|
|
673
636
|
inline-size: 100%;
|
|
674
637
|
block-size: var(--space-2);
|
|
675
|
-
border-radius: var(--radius-full);
|
|
676
638
|
overflow: hidden;
|
|
677
639
|
}
|
|
678
640
|
|
|
679
641
|
progress {
|
|
680
642
|
appearance: none;
|
|
643
|
+
border: 0;
|
|
681
644
|
background-color: var(--color-surface);
|
|
682
645
|
}
|
|
683
646
|
|
|
684
|
-
progress::-webkit-progress-bar {
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
progress::-webkit-progress-value {
|
|
690
|
-
background-color: var(--accent);
|
|
691
|
-
border-radius: var(--radius-full);
|
|
692
|
-
/* Animate to draw attention when visible */
|
|
693
|
-
transition: inline-size var(--duration-slow) var(--ease-fluid);
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
progress::-moz-progress-bar {
|
|
697
|
-
background-color: var(--accent);
|
|
698
|
-
border-radius: var(--radius-full);
|
|
699
|
-
transition: inline-size var(--duration-slow) var(--ease-fluid);
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
/* Animated progress - starts at 0 and fills to value when in viewport */
|
|
703
|
-
progress[data-animate] {
|
|
704
|
-
--progress-value: 73; /* Default: NSW easter egg */
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
progress[data-animate]::-webkit-progress-value {
|
|
708
|
-
animation: progress-fill var(--duration-slower) var(--ease-fluid) forwards;
|
|
709
|
-
animation-play-state: paused;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
progress[data-animate][data-visible]::-webkit-progress-value {
|
|
713
|
-
animation-play-state: running;
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
@keyframes progress-fill {
|
|
717
|
-
from { inline-size: 0; }
|
|
718
|
-
to { inline-size: 100%; }
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
@media (prefers-reduced-motion: reduce) {
|
|
722
|
-
progress[data-animate]::-webkit-progress-value {
|
|
723
|
-
animation: none;
|
|
724
|
-
}
|
|
725
|
-
}
|
|
647
|
+
progress::-webkit-progress-bar { background-color: var(--color-surface); }
|
|
648
|
+
progress::-webkit-progress-value { background-color: var(--accent); }
|
|
649
|
+
progress::-moz-progress-bar { background-color: var(--accent); }
|
|
726
650
|
|
|
727
651
|
|
|
728
652
|
/* ========================================
|
|
729
653
|
DIALOG
|
|
730
|
-
Modal overlay styling
|
|
731
654
|
======================================== */
|
|
732
655
|
|
|
733
656
|
dialog {
|
|
734
657
|
max-inline-size: min(90vw, var(--container-sm));
|
|
735
658
|
padding: var(--space-6);
|
|
736
|
-
|
|
737
|
-
border-radius: var(--radius-xl);
|
|
738
|
-
box-shadow: var(--shadow-xl);
|
|
659
|
+
color: var(--color-text);
|
|
739
660
|
background-color: var(--color-background);
|
|
661
|
+
border: var(--border-width) solid var(--color-border-strong);
|
|
662
|
+
border-radius: var(--radius-card);
|
|
740
663
|
}
|
|
741
664
|
|
|
742
|
-
dialog::backdrop {
|
|
743
|
-
background-color: oklch(from var(--shadow-color) l c h / 0.5);
|
|
744
|
-
backdrop-filter: blur(4px);
|
|
745
|
-
}
|
|
665
|
+
dialog::backdrop { background-color: oklch(0 0 0 / 0.5); }
|
|
746
666
|
|
|
747
667
|
|
|
748
668
|
/* ========================================
|
|
749
669
|
SKIP LINK
|
|
750
|
-
Accessibility: Jump to main content
|
|
751
670
|
Hidden until focused for keyboard users
|
|
752
671
|
======================================== */
|
|
753
672
|
|
|
@@ -758,77 +677,24 @@
|
|
|
758
677
|
z-index: var(--z-max);
|
|
759
678
|
padding: var(--space-3) var(--space-5);
|
|
760
679
|
background-color: var(--accent);
|
|
761
|
-
color: var(--
|
|
762
|
-
font-weight: var(--weight-
|
|
680
|
+
color: var(--on-accent);
|
|
681
|
+
font-weight: var(--weight-semibold);
|
|
763
682
|
text-decoration: none;
|
|
764
|
-
|
|
765
|
-
box-shadow: var(--shadow-lg);
|
|
766
|
-
transform: translateY(-200%);
|
|
767
|
-
transition: transform var(--duration-fast) var(--ease-fluid);
|
|
683
|
+
translate: 0 -200%;
|
|
768
684
|
}
|
|
769
685
|
|
|
770
686
|
.skip-link:focus {
|
|
771
|
-
|
|
772
|
-
outline:
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
687
|
+
translate: none;
|
|
688
|
+
outline: var(--focus-ring-width) solid var(--color-focus);
|
|
689
|
+
outline-offset: 2px;
|
|
690
|
+
/* A halo in the page colour: the link lands on the nav bar, which is
|
|
691
|
+
the page's other scheme. */
|
|
692
|
+
box-shadow: 0 0 0 calc(2px + var(--focus-ring-width)) var(--color-background);
|
|
777
693
|
}
|
|
778
694
|
|
|
779
695
|
|
|
780
696
|
/* ========================================
|
|
781
|
-
|
|
782
|
-
Motion styles affect text presentation
|
|
783
|
-
======================================== */
|
|
784
|
-
|
|
785
|
-
/* Still: Clean, precise, Swiss-style typography */
|
|
786
|
-
[data-motion="still"] h1,
|
|
787
|
-
[data-motion="still"] h2,
|
|
788
|
-
[data-motion="still"] h3 {
|
|
789
|
-
font-weight: var(--weight-medium);
|
|
790
|
-
letter-spacing: 0.02em;
|
|
791
|
-
text-transform: uppercase;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
/* Serene: Elegant, classical typography */
|
|
795
|
-
[data-motion="serene"] h1,
|
|
796
|
-
[data-motion="serene"] h2 {
|
|
797
|
-
font-weight: var(--weight-normal);
|
|
798
|
-
letter-spacing: 0;
|
|
799
|
-
font-style: italic;
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
/* Rapids: Bold, italic, aggressive sports feel */
|
|
803
|
-
[data-motion="rapids"] h1,
|
|
804
|
-
[data-motion="rapids"] h2,
|
|
805
|
-
[data-motion="rapids"] h3 {
|
|
806
|
-
font-weight: 900;
|
|
807
|
-
font-style: italic;
|
|
808
|
-
text-transform: uppercase;
|
|
809
|
-
letter-spacing: -0.02em;
|
|
810
|
-
line-height: 0.95;
|
|
811
|
-
}
|
|
812
|
-
[data-motion="rapids"] h1 {
|
|
813
|
-
font-size: clamp(var(--font-size-3xl), 8vw, var(--font-size-5xl));
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
/* Tsunami: Maximum impact, dramatic typography */
|
|
817
|
-
[data-motion="tsunami"] h1,
|
|
818
|
-
[data-motion="tsunami"] h2 {
|
|
819
|
-
font-weight: 900;
|
|
820
|
-
text-transform: uppercase;
|
|
821
|
-
letter-spacing: -0.03em;
|
|
822
|
-
line-height: 0.9;
|
|
823
|
-
}
|
|
824
|
-
[data-motion="tsunami"] h1 {
|
|
825
|
-
font-size: clamp(var(--font-size-4xl), 10vw, 6rem);
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
/* ========================================
|
|
830
|
-
PRINT STYLES
|
|
831
|
-
Clean output for paper
|
|
697
|
+
PRINT
|
|
832
698
|
======================================== */
|
|
833
699
|
|
|
834
700
|
@media print {
|
|
@@ -837,48 +703,28 @@
|
|
|
837
703
|
line-height: 1.5;
|
|
838
704
|
}
|
|
839
705
|
|
|
840
|
-
h1, h2, h3, h4, h5, h6 {
|
|
841
|
-
page-break-after: avoid;
|
|
842
|
-
break-after: avoid;
|
|
843
|
-
}
|
|
706
|
+
h1, h2, h3, h4, h5, h6 { break-after: avoid; }
|
|
844
707
|
|
|
845
|
-
p, blockquote, ul, ol, table {
|
|
846
|
-
page-break-inside: avoid;
|
|
847
|
-
break-inside: avoid;
|
|
848
|
-
}
|
|
708
|
+
p, blockquote, ul, ol, table { break-inside: avoid; }
|
|
849
709
|
|
|
850
|
-
a {
|
|
851
|
-
color: inherit;
|
|
852
|
-
text-decoration: underline;
|
|
853
|
-
}
|
|
710
|
+
a { color: inherit; }
|
|
854
711
|
|
|
855
|
-
/* Show URLs for external links */
|
|
856
712
|
a[href^="http"]::after {
|
|
857
713
|
content: " (" attr(href) ")";
|
|
858
714
|
font-size: 0.8em;
|
|
859
715
|
color: var(--color-text-muted);
|
|
860
716
|
}
|
|
861
717
|
|
|
862
|
-
pre, code {
|
|
863
|
-
background-color: var(--color-surface-raised, #f5f5f5);
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
/* Hide overlays and fixed UI on print */
|
|
867
718
|
.modal,
|
|
868
719
|
.toast-container,
|
|
869
|
-
.settings-fab,
|
|
870
|
-
.settings-drawer,
|
|
871
|
-
.scroll-progress,
|
|
872
720
|
.nav {
|
|
873
721
|
display: none !important;
|
|
874
722
|
}
|
|
875
723
|
|
|
876
|
-
/* Preserve badge/alert colors on print */
|
|
877
724
|
.badge,
|
|
878
725
|
.alert {
|
|
879
|
-
-webkit-print-color-adjust: exact;
|
|
880
726
|
print-color-adjust: exact;
|
|
881
|
-
border:
|
|
727
|
+
border: var(--border-width) solid currentColor;
|
|
882
728
|
}
|
|
883
729
|
}
|
|
884
730
|
}
|