ovellum 0.2.0 → 0.2.2
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/dist/dev/run-build.d.ts.map +1 -1
- package/dist/index.cjs +4088 -284
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4151 -347
- package/dist/index.js.map +1 -1
- package/dist/templates/default/script.js +115 -4
- package/dist/templates/default/style.css +817 -179
- package/package.json +5 -1
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Ovellum default site theme
|
|
3
|
-
*
|
|
2
|
+
* Ovellum default site theme.
|
|
3
|
+
*
|
|
4
|
+
* The Tier-1 palette, font stacks, type scale, space scale, and a few
|
|
5
|
+
* radii live between the `@tokens:from-styles-md` markers below and are
|
|
6
|
+
* auto-synced from `docs/internal/STYLES.md` by
|
|
7
|
+
* `scripts/extract-style-tokens.mjs`. Edit STYLES.md, then run
|
|
8
|
+
* `pnpm extract-tokens` to refresh; `pnpm check-tokens` reports drift.
|
|
9
|
+
*
|
|
10
|
+
* Tokens *outside* the markers are site-specific or deliberate
|
|
11
|
+
* deviations from STYLES.md — leave them alone unless you know the
|
|
12
|
+
* reason for the deviation.
|
|
4
13
|
*/
|
|
5
14
|
|
|
6
15
|
:root {
|
|
16
|
+
/* @tokens:from-styles-md:start */
|
|
17
|
+
|
|
7
18
|
/* Tier 1 — neutrals (zinc) */
|
|
8
19
|
--color-zinc-50: oklch(98.5% 0.001 286.38);
|
|
9
20
|
--color-zinc-100: oklch(96.7% 0.001 286.38);
|
|
@@ -15,7 +26,7 @@
|
|
|
15
26
|
--color-zinc-900: oklch(21% 0.006 285.89);
|
|
16
27
|
--color-zinc-950: oklch(14.1% 0.005 285.82);
|
|
17
28
|
|
|
18
|
-
/* Tier 1 — accents */
|
|
29
|
+
/* Tier 1 — accents (blue) */
|
|
19
30
|
--color-blue-50: oklch(97% 0.014 254.6);
|
|
20
31
|
--color-blue-200: oklch(88.2% 0.059 254.16);
|
|
21
32
|
--color-blue-300: oklch(80.9% 0.105 251.81);
|
|
@@ -25,21 +36,23 @@
|
|
|
25
36
|
--color-blue-700: oklch(48.8% 0.243 264.38);
|
|
26
37
|
--color-blue-900: oklch(37.9% 0.146 265.52);
|
|
27
38
|
|
|
28
|
-
/* Tier
|
|
29
|
-
--color-
|
|
30
|
-
--color-
|
|
31
|
-
--color-
|
|
32
|
-
--color-
|
|
33
|
-
--color-
|
|
34
|
-
--color-
|
|
35
|
-
--color-
|
|
36
|
-
--color-
|
|
37
|
-
--color-
|
|
38
|
-
--color-
|
|
39
|
-
--color-
|
|
40
|
-
--color-
|
|
41
|
-
--color-
|
|
42
|
-
--color-
|
|
39
|
+
/* Tier 1 — status accents (callouts) */
|
|
40
|
+
--color-green-50: oklch(98.2% 0.018 155.83);
|
|
41
|
+
--color-green-300: oklch(87.1% 0.15 154.45);
|
|
42
|
+
--color-green-700: oklch(52.7% 0.154 150.07);
|
|
43
|
+
--color-green-950: oklch(26.6% 0.065 152.93);
|
|
44
|
+
--color-amber-50: oklch(98.7% 0.022 95.28);
|
|
45
|
+
--color-amber-300: oklch(87.9% 0.169 91.61);
|
|
46
|
+
--color-amber-800: oklch(47.3% 0.137 46.2);
|
|
47
|
+
--color-amber-950: oklch(27.9% 0.077 45.64);
|
|
48
|
+
--color-red-50: oklch(97.1% 0.013 17.38);
|
|
49
|
+
--color-red-300: oklch(80.8% 0.114 19.57);
|
|
50
|
+
--color-red-700: oklch(50.5% 0.213 27.52);
|
|
51
|
+
--color-red-950: oklch(25.8% 0.092 26.05);
|
|
52
|
+
--color-violet-50: oklch(96.9% 0.016 293.76);
|
|
53
|
+
--color-violet-300: oklch(81.1% 0.111 293.57);
|
|
54
|
+
--color-violet-700: oklch(49.1% 0.27 292.58);
|
|
55
|
+
--color-violet-950: oklch(28.3% 0.141 291.09);
|
|
43
56
|
|
|
44
57
|
/* Fonts */
|
|
45
58
|
--font-sans:
|
|
@@ -49,10 +62,7 @@
|
|
|
49
62
|
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
|
|
50
63
|
monospace;
|
|
51
64
|
|
|
52
|
-
/* Type scale (Major Third → Perfect Fourth)
|
|
53
|
-
Body deliberately runs 15→16px (tightened from the Utopia default
|
|
54
|
-
of 16→19px) — closer to Stripe/Mintlify density. Other steps in
|
|
55
|
-
the scale are unchanged. */
|
|
65
|
+
/* Type scale (Major Third → Perfect Fourth) — full Utopia values */
|
|
56
66
|
--font-size-0: clamp(0.9375rem, 0.9158rem + 0.1087vw, 1rem);
|
|
57
67
|
--font-size-1: clamp(1.25rem, 1.1341rem + 0.5793vw, 1.5831rem);
|
|
58
68
|
--font-size-2: clamp(1.5625rem, 1.3721rem + 0.9522vw, 2.11rem);
|
|
@@ -67,29 +77,95 @@
|
|
|
67
77
|
--space-m: clamp(1.5rem, 1.4022rem + 0.4892vw, 1.7813rem);
|
|
68
78
|
--space-l: clamp(2rem, 1.8696rem + 0.6522vw, 2.375rem);
|
|
69
79
|
--space-xl: clamp(3rem, 2.8043rem + 0.9783vw, 3.5625rem);
|
|
80
|
+
--space-2xl: clamp(4rem, 3.7391rem + 1.3043vw, 4.75rem);
|
|
81
|
+
--space-3xl: clamp(6rem, 5.6087rem + 1.9565vw, 7.125rem);
|
|
70
82
|
|
|
71
|
-
/*
|
|
83
|
+
/* Radii (subset shipped) */
|
|
72
84
|
--radius-md: 0.375rem;
|
|
73
85
|
--radius-lg: 0.5rem;
|
|
86
|
+
|
|
87
|
+
/* @tokens:from-styles-md:end */
|
|
88
|
+
|
|
89
|
+
/* Tier 2 — semantic (default light) — site-specific remappings */
|
|
90
|
+
/* Body + footer-chrome are pure-neutral grays (chroma 0 — no hue) for
|
|
91
|
+
now; a blended background image is planned to replace this surface
|
|
92
|
+
later. Chrome (footer) sits ~4% L below body in light mode — the
|
|
93
|
+
smallest gap that reads as real tonal separation rather than
|
|
94
|
+
rendering noise. */
|
|
95
|
+
--color-bg: oklch(97% 0 0);
|
|
96
|
+
--color-bg-chrome: oklch(93% 0 0);
|
|
97
|
+
--color-bg-subtle: var(--color-zinc-100);
|
|
98
|
+
--color-bg-muted: var(--color-zinc-200);
|
|
99
|
+
/* Card surface — a hair lighter than body so a card lifts off the page
|
|
100
|
+
on a hairline border alone, no heavy shadow. */
|
|
101
|
+
--color-surface: oklch(100% 0 0);
|
|
102
|
+
--color-fg: var(--color-zinc-900);
|
|
103
|
+
--color-fg-muted: var(--color-zinc-700);
|
|
104
|
+
--color-fg-subtle: var(--color-zinc-500);
|
|
105
|
+
--color-border: var(--color-zinc-200);
|
|
106
|
+
--color-border-strong: var(--color-zinc-300);
|
|
107
|
+
--color-border-focus: var(--color-blue-500);
|
|
108
|
+
--color-accent: var(--color-blue-600);
|
|
109
|
+
--color-accent-hover: var(--color-blue-700);
|
|
110
|
+
--color-link: var(--color-blue-600);
|
|
111
|
+
--color-link-hover: var(--color-blue-700);
|
|
112
|
+
--color-code-bg: var(--color-zinc-100);
|
|
113
|
+
|
|
114
|
+
/* Callout types — GitHub alert vocabulary, editorial-calm palette */
|
|
115
|
+
--callout-note-fg: var(--color-blue-700);
|
|
116
|
+
--callout-note-bg: var(--color-blue-50);
|
|
117
|
+
--callout-tip-fg: var(--color-green-700);
|
|
118
|
+
--callout-tip-bg: var(--color-green-50);
|
|
119
|
+
--callout-important-fg: var(--color-violet-700);
|
|
120
|
+
--callout-important-bg: var(--color-violet-50);
|
|
121
|
+
--callout-warning-fg: var(--color-amber-800);
|
|
122
|
+
--callout-warning-bg: var(--color-amber-50);
|
|
123
|
+
--callout-caution-fg: var(--color-red-700);
|
|
124
|
+
--callout-caution-bg: var(--color-red-50);
|
|
125
|
+
|
|
126
|
+
/* Deliberate deviations from STYLES.md:
|
|
127
|
+
- shadows inlined (no shared --shadow-color token in this build)
|
|
128
|
+
- body line-height 1.55 (vs spec 1.5) — closer to Stripe density at our
|
|
129
|
+
tightened 15→16px body size
|
|
130
|
+
- tight 1.2 (vs spec 1.15) — large headings need a hair more air */
|
|
74
131
|
--shadow-sm: 0 1px 2px oklch(0% 0 0 / 0.08);
|
|
75
132
|
--shadow-md: 0 4px 6px oklch(0% 0 0 / 0.08), 0 2px 4px oklch(0% 0 0 / 0.08);
|
|
76
|
-
|
|
77
133
|
--leading-normal: 1.55;
|
|
78
134
|
--leading-tight: 1.2;
|
|
79
135
|
--leading-mono: 1.55;
|
|
80
136
|
|
|
81
|
-
/* Layout widths */
|
|
82
|
-
--sidebar-w:
|
|
83
|
-
--toc-w:
|
|
84
|
-
--content-max:
|
|
137
|
+
/* Layout widths (site-specific, not in STYLES.md) */
|
|
138
|
+
--sidebar-w: 260px;
|
|
139
|
+
--toc-w: 220px;
|
|
140
|
+
--content-max: 76ch;
|
|
141
|
+
/* Width tokens.
|
|
142
|
+
--chrome-max stays constant across every page — topbar and footer
|
|
143
|
+
read this so the chrome never shifts width between landing and docs
|
|
144
|
+
(avoiding the jarring "small header → wide header" jump on click).
|
|
145
|
+
--page-max governs the main content boundary: docs run wide
|
|
146
|
+
(Mintlify-style) so long code blocks and reference tables have room;
|
|
147
|
+
landing tightens via the body class for editorial centrepiece feel. */
|
|
148
|
+
--chrome-max: 1600px;
|
|
149
|
+
--page-max: 1600px;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
body.ov-body-landing {
|
|
153
|
+
--page-max: 1100px;
|
|
85
154
|
}
|
|
86
155
|
|
|
87
156
|
/* Dark theme — auto + explicit */
|
|
88
157
|
@media (prefers-color-scheme: dark) {
|
|
89
158
|
:root[data-theme='auto'] {
|
|
90
|
-
--color-bg:
|
|
159
|
+
--color-bg: oklch(14.1% 0 0);
|
|
160
|
+
/* Chrome lifts ~6% L above body in dark mode (elevation inversion:
|
|
161
|
+
you can't go darker than near-black without reading as a void).
|
|
162
|
+
The gap is bigger than light mode's 4% because the human eye
|
|
163
|
+
discriminates lightness deltas worse in dark regions. */
|
|
164
|
+
--color-bg-chrome: oklch(20% 0 0);
|
|
91
165
|
--color-bg-subtle: var(--color-zinc-900);
|
|
92
166
|
--color-bg-muted: var(--color-zinc-800);
|
|
167
|
+
/* Card sits between body (14.1%) and chrome (20%) — a gentle lift. */
|
|
168
|
+
--color-surface: oklch(17.5% 0 0);
|
|
93
169
|
--color-fg: var(--color-zinc-100);
|
|
94
170
|
--color-fg-muted: var(--color-zinc-300);
|
|
95
171
|
--color-fg-subtle: var(--color-zinc-500);
|
|
@@ -101,13 +177,25 @@
|
|
|
101
177
|
--color-link: var(--color-blue-400);
|
|
102
178
|
--color-link-hover: var(--color-blue-300);
|
|
103
179
|
--color-code-bg: var(--color-zinc-900);
|
|
180
|
+
--callout-note-fg: var(--color-blue-300);
|
|
181
|
+
--callout-note-bg: var(--color-blue-950);
|
|
182
|
+
--callout-tip-fg: var(--color-green-300);
|
|
183
|
+
--callout-tip-bg: var(--color-green-950);
|
|
184
|
+
--callout-important-fg: var(--color-violet-300);
|
|
185
|
+
--callout-important-bg: var(--color-violet-950);
|
|
186
|
+
--callout-warning-fg: var(--color-amber-300);
|
|
187
|
+
--callout-warning-bg: var(--color-amber-950);
|
|
188
|
+
--callout-caution-fg: var(--color-red-300);
|
|
189
|
+
--callout-caution-bg: var(--color-red-950);
|
|
104
190
|
}
|
|
105
191
|
}
|
|
106
192
|
|
|
107
193
|
:root[data-theme='dark'] {
|
|
108
|
-
--color-bg:
|
|
194
|
+
--color-bg: oklch(14.1% 0 0);
|
|
195
|
+
--color-bg-chrome: oklch(20% 0 0);
|
|
109
196
|
--color-bg-subtle: var(--color-zinc-900);
|
|
110
197
|
--color-bg-muted: var(--color-zinc-800);
|
|
198
|
+
--color-surface: oklch(17.5% 0 0);
|
|
111
199
|
--color-fg: var(--color-zinc-100);
|
|
112
200
|
--color-fg-muted: var(--color-zinc-300);
|
|
113
201
|
--color-fg-subtle: var(--color-zinc-500);
|
|
@@ -119,6 +207,16 @@
|
|
|
119
207
|
--color-link: var(--color-blue-400);
|
|
120
208
|
--color-link-hover: var(--color-blue-300);
|
|
121
209
|
--color-code-bg: var(--color-zinc-900);
|
|
210
|
+
--callout-note-fg: var(--color-blue-300);
|
|
211
|
+
--callout-note-bg: var(--color-blue-950);
|
|
212
|
+
--callout-tip-fg: var(--color-green-300);
|
|
213
|
+
--callout-tip-bg: var(--color-green-950);
|
|
214
|
+
--callout-important-fg: var(--color-violet-300);
|
|
215
|
+
--callout-important-bg: var(--color-violet-950);
|
|
216
|
+
--callout-warning-fg: var(--color-amber-300);
|
|
217
|
+
--callout-warning-bg: var(--color-amber-950);
|
|
218
|
+
--callout-caution-fg: var(--color-red-300);
|
|
219
|
+
--callout-caution-bg: var(--color-red-950);
|
|
122
220
|
}
|
|
123
221
|
|
|
124
222
|
/* Reset + base */
|
|
@@ -134,6 +232,15 @@ body {
|
|
|
134
232
|
padding: 0;
|
|
135
233
|
}
|
|
136
234
|
|
|
235
|
+
/* html bg matches the body (not the chrome) so Safari's rubber-band
|
|
236
|
+
overscroll at the top continues the topbar's body color cleanly.
|
|
237
|
+
The footer keeps its chrome tint, so bottom overscroll will reveal
|
|
238
|
+
body instead of footer — accepted tradeoff: top overscroll is the
|
|
239
|
+
one users actually notice. */
|
|
240
|
+
html {
|
|
241
|
+
background: var(--color-bg);
|
|
242
|
+
}
|
|
243
|
+
|
|
137
244
|
body {
|
|
138
245
|
font-family: var(--font-sans);
|
|
139
246
|
font-size: var(--font-size-0);
|
|
@@ -159,30 +266,77 @@ a:hover {
|
|
|
159
266
|
border-radius: 2px;
|
|
160
267
|
}
|
|
161
268
|
|
|
162
|
-
/* Top bar
|
|
269
|
+
/* Top bar
|
|
270
|
+
===
|
|
271
|
+
Outer element is full-bleed so the chrome tint and bottom border span
|
|
272
|
+
the viewport — keeps the header visually identical between landing
|
|
273
|
+
(narrow body) and docs (wide body). Inner element holds the grid and
|
|
274
|
+
constrains content to --chrome-max. */
|
|
163
275
|
.ov-topbar {
|
|
164
276
|
position: sticky;
|
|
165
277
|
top: 0;
|
|
166
278
|
z-index: 10;
|
|
279
|
+
inline-size: 100%;
|
|
280
|
+
/* Topbar reads as a continuation of the body, separated only by a
|
|
281
|
+
thin hairline border-block-end. Footer keeps the chrome tint —
|
|
282
|
+
the asymmetry is intentional: a tinted footer reads as a closing
|
|
283
|
+
baseline, a tinted topbar fought every other surface on the page. */
|
|
284
|
+
background: var(--color-bg);
|
|
285
|
+
border-block-end: 1px solid var(--color-border);
|
|
286
|
+
}
|
|
287
|
+
.ov-topbar-inner {
|
|
167
288
|
display: grid;
|
|
289
|
+
/* brand | search (fills the middle) | icon cluster */
|
|
168
290
|
grid-template-columns: auto 1fr auto;
|
|
169
291
|
align-items: center;
|
|
170
292
|
gap: var(--space-m);
|
|
171
293
|
padding: var(--space-2xs) var(--space-m);
|
|
172
|
-
max-inline-size:
|
|
294
|
+
max-inline-size: var(--chrome-max);
|
|
173
295
|
margin-inline: auto;
|
|
174
296
|
inline-size: 100%;
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
297
|
+
}
|
|
298
|
+
.ov-brand-row {
|
|
299
|
+
display: inline-flex;
|
|
300
|
+
align-items: center;
|
|
301
|
+
gap: var(--space-2xs);
|
|
302
|
+
min-inline-size: 0;
|
|
178
303
|
}
|
|
179
304
|
.ov-brand {
|
|
180
|
-
|
|
305
|
+
display: inline-flex;
|
|
306
|
+
align-items: center;
|
|
307
|
+
gap: var(--space-2xs);
|
|
308
|
+
font-weight: 700;
|
|
181
309
|
text-decoration: none;
|
|
182
310
|
color: var(--color-fg);
|
|
183
|
-
font-size:
|
|
311
|
+
font-size: 1.125rem;
|
|
184
312
|
letter-spacing: -0.01em;
|
|
185
313
|
}
|
|
314
|
+
.ov-brand-mark {
|
|
315
|
+
flex: none;
|
|
316
|
+
inline-size: 1.5rem;
|
|
317
|
+
block-size: 1.5rem;
|
|
318
|
+
line-height: 0;
|
|
319
|
+
}
|
|
320
|
+
/* Center zone — the search box stretches to fill it. */
|
|
321
|
+
.ov-topbar-search {
|
|
322
|
+
display: flex;
|
|
323
|
+
min-inline-size: 0;
|
|
324
|
+
}
|
|
325
|
+
.ov-brand-version {
|
|
326
|
+
display: inline-flex;
|
|
327
|
+
align-items: center;
|
|
328
|
+
padding: 1px 0.45em;
|
|
329
|
+
font-family: var(--font-mono);
|
|
330
|
+
font-size: 0.7em;
|
|
331
|
+
font-weight: 500;
|
|
332
|
+
line-height: 1.4;
|
|
333
|
+
color: var(--color-fg-muted);
|
|
334
|
+
background: var(--color-bg-subtle);
|
|
335
|
+
border: 1px solid var(--color-border);
|
|
336
|
+
border-radius: var(--radius-sm);
|
|
337
|
+
letter-spacing: 0;
|
|
338
|
+
user-select: all;
|
|
339
|
+
}
|
|
186
340
|
.ov-topbar-nav {
|
|
187
341
|
display: flex;
|
|
188
342
|
gap: var(--space-xs);
|
|
@@ -206,13 +360,39 @@ a:hover {
|
|
|
206
360
|
color: var(--color-fg);
|
|
207
361
|
background: var(--color-bg-subtle);
|
|
208
362
|
}
|
|
363
|
+
/* Icon-only links (e.g. GitHub, npm) and the theme toggle share one look:
|
|
364
|
+
rounded-corner square buttons with a hairline border, spaced apart. */
|
|
365
|
+
.ov-topbar-link--icon,
|
|
366
|
+
.ov-theme-toggle {
|
|
367
|
+
display: inline-flex;
|
|
368
|
+
align-items: center;
|
|
369
|
+
justify-content: center;
|
|
370
|
+
inline-size: 2.25rem;
|
|
371
|
+
block-size: 2.25rem;
|
|
372
|
+
padding: 0;
|
|
373
|
+
border: 1px solid var(--color-border);
|
|
374
|
+
background: var(--color-bg-subtle);
|
|
375
|
+
color: var(--color-fg-muted);
|
|
376
|
+
border-radius: var(--radius-md);
|
|
377
|
+
transition: color 120ms ease, background-color 120ms ease, border-color 120ms ease;
|
|
378
|
+
}
|
|
379
|
+
.ov-topbar-link--icon:hover,
|
|
380
|
+
.ov-theme-toggle:hover {
|
|
381
|
+
color: var(--color-fg);
|
|
382
|
+
background: var(--color-bg-muted);
|
|
383
|
+
border-color: var(--color-border-strong);
|
|
384
|
+
}
|
|
385
|
+
.ov-topbar-glyph {
|
|
386
|
+
line-height: 0;
|
|
387
|
+
}
|
|
209
388
|
.ov-topbar-icon {
|
|
210
389
|
opacity: 0.7;
|
|
211
390
|
}
|
|
212
391
|
.ov-topbar-right {
|
|
213
392
|
display: flex;
|
|
214
393
|
align-items: center;
|
|
215
|
-
gap: var(--space-
|
|
394
|
+
gap: var(--space-xs);
|
|
395
|
+
min-inline-size: 0;
|
|
216
396
|
}
|
|
217
397
|
|
|
218
398
|
/* Search box (Pagefind UI as a floating dropdown)
|
|
@@ -228,8 +408,11 @@ a:hover {
|
|
|
228
408
|
.ov-search {
|
|
229
409
|
position: relative;
|
|
230
410
|
inline-size: 100%;
|
|
231
|
-
min-inline-size:
|
|
232
|
-
|
|
411
|
+
min-inline-size: 0;
|
|
412
|
+
/* Fills the center grid column; capped so it stays comfortable on very
|
|
413
|
+
wide viewports without hugging the icon cluster. */
|
|
414
|
+
max-inline-size: 720px;
|
|
415
|
+
margin-inline: auto;
|
|
233
416
|
}
|
|
234
417
|
.ov-search .pagefind-ui {
|
|
235
418
|
--pagefind-ui-scale: 0.6;
|
|
@@ -242,6 +425,13 @@ a:hover {
|
|
|
242
425
|
--pagefind-ui-border-radius: var(--radius-md);
|
|
243
426
|
--pagefind-ui-font: var(--font-sans);
|
|
244
427
|
}
|
|
428
|
+
/* Let the search collapse with its grid column — an <input>'s intrinsic
|
|
429
|
+
min-width would otherwise refuse to shrink and overflow the topbar
|
|
430
|
+
(pushing the hamburger off-screen) on narrow viewports. */
|
|
431
|
+
.ov-search .pagefind-ui__form,
|
|
432
|
+
.ov-search .pagefind-ui__search-input {
|
|
433
|
+
min-inline-size: 0;
|
|
434
|
+
}
|
|
245
435
|
.ov-search .pagefind-ui__search-input {
|
|
246
436
|
font-weight: 500;
|
|
247
437
|
color: var(--color-fg);
|
|
@@ -317,30 +507,10 @@ a:hover {
|
|
|
317
507
|
display: none;
|
|
318
508
|
}
|
|
319
509
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
display: none;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
510
|
+
/* Shared icon-button appearance (square, bordered) lives with
|
|
511
|
+
`.ov-topbar-link--icon` above; here we only add the toggle's cursor. */
|
|
326
512
|
.ov-theme-toggle {
|
|
327
|
-
display: inline-flex;
|
|
328
|
-
align-items: center;
|
|
329
|
-
justify-content: center;
|
|
330
|
-
inline-size: 2.25rem;
|
|
331
|
-
block-size: 2.25rem;
|
|
332
|
-
padding: 0;
|
|
333
|
-
border: 1px solid transparent;
|
|
334
|
-
background: transparent;
|
|
335
|
-
color: var(--color-fg-muted);
|
|
336
|
-
border-radius: var(--radius-md);
|
|
337
513
|
cursor: pointer;
|
|
338
|
-
transition: color 120ms ease, background-color 120ms ease, border-color 120ms ease;
|
|
339
|
-
}
|
|
340
|
-
.ov-theme-toggle:hover {
|
|
341
|
-
color: var(--color-fg);
|
|
342
|
-
background: var(--color-bg-subtle);
|
|
343
|
-
border-color: var(--color-border);
|
|
344
514
|
}
|
|
345
515
|
.ov-theme-icon {
|
|
346
516
|
display: none;
|
|
@@ -406,15 +576,39 @@ a:hover {
|
|
|
406
576
|
.ov-mobile-nav .ov-topbar-link {
|
|
407
577
|
padding: var(--space-xs) var(--space-s);
|
|
408
578
|
font-size: 1.05em;
|
|
579
|
+
gap: 0.6em;
|
|
580
|
+
}
|
|
581
|
+
/* Theme toggle lives in the sheet on mobile (kept out of the top row). */
|
|
582
|
+
.ov-mobile-theme {
|
|
583
|
+
display: flex;
|
|
584
|
+
align-items: center;
|
|
585
|
+
justify-content: space-between;
|
|
586
|
+
padding: var(--space-2xs) var(--space-s);
|
|
587
|
+
margin-block-start: var(--space-2xs);
|
|
588
|
+
border-block-start: 1px solid var(--color-border);
|
|
589
|
+
}
|
|
590
|
+
.ov-mobile-theme-label {
|
|
591
|
+
font-size: 1.05em;
|
|
592
|
+
font-weight: 500;
|
|
593
|
+
color: var(--color-fg-muted);
|
|
409
594
|
}
|
|
410
595
|
body.ov-menu-open {
|
|
411
596
|
overflow: hidden;
|
|
412
597
|
}
|
|
413
598
|
|
|
414
599
|
@media (max-width: 720px) {
|
|
600
|
+
/* Tighter inner gap so the centered search keeps room next to the
|
|
601
|
+
larger brand and the hamburger. */
|
|
602
|
+
.ov-topbar-inner {
|
|
603
|
+
gap: var(--space-xs);
|
|
604
|
+
}
|
|
415
605
|
.ov-topbar-nav {
|
|
416
606
|
display: none;
|
|
417
607
|
}
|
|
608
|
+
/* The desktop theme toggle hides on mobile; the sheet carries its own. */
|
|
609
|
+
.ov-topbar-right > .ov-theme-toggle {
|
|
610
|
+
display: none;
|
|
611
|
+
}
|
|
418
612
|
.ov-topbar-menu {
|
|
419
613
|
display: inline-flex;
|
|
420
614
|
}
|
|
@@ -425,7 +619,7 @@ body.ov-menu-open {
|
|
|
425
619
|
display: grid;
|
|
426
620
|
grid-template-columns: var(--sidebar-w) minmax(0, 1fr) var(--toc-w);
|
|
427
621
|
gap: var(--space-l);
|
|
428
|
-
max-inline-size:
|
|
622
|
+
max-inline-size: var(--page-max);
|
|
429
623
|
margin-inline: auto;
|
|
430
624
|
padding: var(--space-m);
|
|
431
625
|
}
|
|
@@ -446,23 +640,35 @@ body.ov-menu-open {
|
|
|
446
640
|
padding: 0;
|
|
447
641
|
}
|
|
448
642
|
.ov-sidebar-nav > ul > li {
|
|
449
|
-
margin-block-end: var(--space-
|
|
643
|
+
margin-block-end: var(--space-s);
|
|
644
|
+
padding-block-end: var(--space-s);
|
|
645
|
+
border-block-end: 1px solid var(--color-border);
|
|
646
|
+
}
|
|
647
|
+
.ov-sidebar-nav > ul > li:last-child {
|
|
648
|
+
border-block-end: 0;
|
|
649
|
+
padding-block-end: 0;
|
|
650
|
+
}
|
|
651
|
+
.ov-sidebar-nav li {
|
|
652
|
+
margin-block-end: var(--space-3xs);
|
|
450
653
|
}
|
|
451
654
|
.ov-nav-link {
|
|
452
655
|
display: block;
|
|
453
656
|
padding: var(--space-3xs) var(--space-2xs);
|
|
454
|
-
border-radius: var(--radius-
|
|
657
|
+
border-radius: var(--radius-sm);
|
|
455
658
|
text-decoration: none;
|
|
456
659
|
color: var(--color-fg-muted);
|
|
457
660
|
font-size: 0.95em;
|
|
661
|
+
border-inline-start: 2px solid transparent;
|
|
662
|
+
margin-inline-start: -2px;
|
|
663
|
+
transition: color 120ms ease, border-color 120ms ease, background-color 120ms ease;
|
|
458
664
|
}
|
|
459
665
|
.ov-nav-link:hover {
|
|
460
|
-
background: var(--color-bg-subtle);
|
|
461
666
|
color: var(--color-fg);
|
|
462
667
|
}
|
|
463
668
|
.ov-nav-link.is-active {
|
|
464
|
-
|
|
465
|
-
|
|
669
|
+
color: var(--color-accent-fg, var(--color-accent));
|
|
670
|
+
font-weight: 600;
|
|
671
|
+
border-inline-start-color: var(--color-accent);
|
|
466
672
|
}
|
|
467
673
|
.ov-nav-group {
|
|
468
674
|
display: block;
|
|
@@ -489,25 +695,31 @@ body.ov-menu-open {
|
|
|
489
695
|
.ov-prose h1 {
|
|
490
696
|
font-size: var(--font-size-4);
|
|
491
697
|
line-height: var(--leading-tight);
|
|
492
|
-
letter-spacing: -0.
|
|
698
|
+
letter-spacing: -0.03em;
|
|
493
699
|
margin-block: 0 var(--space-m);
|
|
700
|
+
font-weight: 700;
|
|
494
701
|
}
|
|
495
702
|
.ov-prose h2 {
|
|
496
703
|
font-size: var(--font-size-3);
|
|
497
704
|
line-height: var(--leading-tight);
|
|
498
|
-
letter-spacing: -0.
|
|
499
|
-
margin-block: var(--space-
|
|
500
|
-
|
|
501
|
-
border-block-start: 1px solid var(--color-border);
|
|
705
|
+
letter-spacing: -0.02em;
|
|
706
|
+
margin-block: var(--space-xl) var(--space-s);
|
|
707
|
+
font-weight: 700;
|
|
502
708
|
}
|
|
503
709
|
.ov-prose h3 {
|
|
504
710
|
font-size: var(--font-size-2);
|
|
505
711
|
line-height: 1.25;
|
|
506
|
-
|
|
712
|
+
letter-spacing: -0.015em;
|
|
713
|
+
margin-block: var(--space-l) var(--space-2xs);
|
|
714
|
+
font-weight: 600;
|
|
507
715
|
}
|
|
508
716
|
.ov-prose h4 {
|
|
509
717
|
font-size: var(--font-size-1);
|
|
510
|
-
margin-block: var(--space-m) var(--space-
|
|
718
|
+
margin-block: var(--space-m) var(--space-2xs);
|
|
719
|
+
font-weight: 600;
|
|
720
|
+
}
|
|
721
|
+
.ov-prose :is(h1, h2, h3, h4) + p {
|
|
722
|
+
margin-block-start: 0;
|
|
511
723
|
}
|
|
512
724
|
.ov-prose p,
|
|
513
725
|
.ov-prose ul,
|
|
@@ -522,37 +734,163 @@ body.ov-menu-open {
|
|
|
522
734
|
border-inline-start: 3px solid var(--color-border-strong);
|
|
523
735
|
color: var(--color-fg-muted);
|
|
524
736
|
}
|
|
737
|
+
|
|
738
|
+
/* Callouts (GitHub alert syntax: > [!NOTE] / [!TIP] / [!IMPORTANT] /
|
|
739
|
+
[!WARNING] / [!CAUTION]). Rendered as a labelled panel with a 3px
|
|
740
|
+
left rule in the type color, a faint type-color background, and an
|
|
741
|
+
uppercase eyebrow label. Editorial-calm: thin rule, restrained tint,
|
|
742
|
+
no icon — the label carries the meaning. */
|
|
743
|
+
.ov-prose .ov-callout {
|
|
744
|
+
--_fg: var(--color-fg);
|
|
745
|
+
--_bg: var(--color-bg-subtle);
|
|
746
|
+
margin-block: 0 var(--space-s);
|
|
747
|
+
padding: var(--space-s) var(--space-m);
|
|
748
|
+
border-inline-start: 3px solid var(--_fg);
|
|
749
|
+
background: var(--_bg);
|
|
750
|
+
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
|
|
751
|
+
color: var(--color-fg);
|
|
752
|
+
}
|
|
753
|
+
.ov-prose .ov-callout--note {
|
|
754
|
+
--_fg: var(--callout-note-fg);
|
|
755
|
+
--_bg: var(--callout-note-bg);
|
|
756
|
+
}
|
|
757
|
+
.ov-prose .ov-callout--tip {
|
|
758
|
+
--_fg: var(--callout-tip-fg);
|
|
759
|
+
--_bg: var(--callout-tip-bg);
|
|
760
|
+
}
|
|
761
|
+
.ov-prose .ov-callout--important {
|
|
762
|
+
--_fg: var(--callout-important-fg);
|
|
763
|
+
--_bg: var(--callout-important-bg);
|
|
764
|
+
}
|
|
765
|
+
.ov-prose .ov-callout--warning {
|
|
766
|
+
--_fg: var(--callout-warning-fg);
|
|
767
|
+
--_bg: var(--callout-warning-bg);
|
|
768
|
+
}
|
|
769
|
+
.ov-prose .ov-callout--caution {
|
|
770
|
+
--_fg: var(--callout-caution-fg);
|
|
771
|
+
--_bg: var(--callout-caution-bg);
|
|
772
|
+
}
|
|
773
|
+
.ov-prose .ov-callout-label {
|
|
774
|
+
font-size: 0.74em;
|
|
775
|
+
font-weight: 700;
|
|
776
|
+
letter-spacing: 0.08em;
|
|
777
|
+
text-transform: uppercase;
|
|
778
|
+
color: var(--_fg);
|
|
779
|
+
margin-block-end: var(--space-2xs);
|
|
780
|
+
}
|
|
781
|
+
.ov-prose .ov-callout > p {
|
|
782
|
+
margin-block: 0;
|
|
783
|
+
}
|
|
784
|
+
.ov-prose .ov-callout > p + p,
|
|
785
|
+
.ov-prose .ov-callout > * + * {
|
|
786
|
+
margin-block-start: var(--space-2xs);
|
|
787
|
+
}
|
|
525
788
|
.ov-prose ul,
|
|
526
789
|
.ov-prose ol {
|
|
527
790
|
padding-inline-start: var(--space-m);
|
|
528
791
|
}
|
|
792
|
+
.ov-prose li {
|
|
793
|
+
margin-block-end: 0.25em;
|
|
794
|
+
}
|
|
795
|
+
.ov-prose li:last-child {
|
|
796
|
+
margin-block-end: 0;
|
|
797
|
+
}
|
|
798
|
+
.ov-prose li > p {
|
|
799
|
+
margin-block: 0;
|
|
800
|
+
}
|
|
801
|
+
.ov-prose li > p + p {
|
|
802
|
+
margin-block-start: var(--space-2xs);
|
|
803
|
+
}
|
|
804
|
+
.ov-prose ul ul,
|
|
805
|
+
.ov-prose ul ol,
|
|
806
|
+
.ov-prose ol ol,
|
|
807
|
+
.ov-prose ol ul {
|
|
808
|
+
margin-block: 0.25em 0;
|
|
809
|
+
}
|
|
810
|
+
.ov-prose ul li::marker {
|
|
811
|
+
color: var(--color-fg-subtle);
|
|
812
|
+
}
|
|
813
|
+
.ov-prose ol li::marker {
|
|
814
|
+
color: var(--color-fg-subtle);
|
|
815
|
+
font-variant-numeric: tabular-nums;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/* GFM task lists: kill the bullet, keep the checkbox tight to the text. */
|
|
819
|
+
.ov-prose ul.contains-task-list {
|
|
820
|
+
list-style: none;
|
|
821
|
+
padding-inline-start: 0;
|
|
822
|
+
}
|
|
823
|
+
.ov-prose li.task-list-item {
|
|
824
|
+
display: flex;
|
|
825
|
+
align-items: baseline;
|
|
826
|
+
gap: 0.5em;
|
|
827
|
+
}
|
|
828
|
+
.ov-prose li.task-list-item input[type='checkbox'] {
|
|
829
|
+
margin: 0;
|
|
830
|
+
accent-color: var(--color-accent);
|
|
831
|
+
transform: translateY(2px);
|
|
832
|
+
}
|
|
529
833
|
.ov-prose code:not(pre code) {
|
|
530
834
|
font-family: var(--font-mono);
|
|
531
835
|
background: var(--color-code-bg);
|
|
532
|
-
padding: 0.1em 0.
|
|
533
|
-
border-radius:
|
|
534
|
-
font-size: 0.
|
|
836
|
+
padding: 0.1em 0.38em;
|
|
837
|
+
border-radius: var(--radius-sm);
|
|
838
|
+
font-size: 0.88em;
|
|
839
|
+
color: var(--color-fg);
|
|
840
|
+
white-space: nowrap;
|
|
841
|
+
}
|
|
842
|
+
.ov-prose a > code:not(pre code) {
|
|
843
|
+
color: var(--color-link);
|
|
535
844
|
}
|
|
536
845
|
.ov-prose img {
|
|
537
846
|
max-inline-size: 100%;
|
|
538
847
|
height: auto;
|
|
539
848
|
border-radius: var(--radius-md);
|
|
540
849
|
}
|
|
850
|
+
/* Tables — editorial-calm: horizontal rules only, no grid, no header
|
|
851
|
+
fill. Header reads via weight + a thicker bottom rule.
|
|
852
|
+
Each table is wrapped by `.ov-table-wrap` (rehypeTableWrap) so a
|
|
853
|
+
table wider than the prose column scrolls horizontally inside the
|
|
854
|
+
wrap instead of forcing the column to grow. */
|
|
855
|
+
.ov-prose .ov-table-wrap {
|
|
856
|
+
margin-block: 0 var(--space-s);
|
|
857
|
+
inline-size: 100%;
|
|
858
|
+
max-inline-size: 100%;
|
|
859
|
+
overflow-x: auto;
|
|
860
|
+
}
|
|
861
|
+
.ov-prose .ov-table-wrap > table {
|
|
862
|
+
margin-block: 0;
|
|
863
|
+
}
|
|
541
864
|
.ov-prose table {
|
|
542
865
|
border-collapse: collapse;
|
|
543
866
|
inline-size: 100%;
|
|
544
|
-
|
|
545
|
-
font-
|
|
867
|
+
font-size: 0.92em;
|
|
868
|
+
font-variant-numeric: tabular-nums;
|
|
546
869
|
}
|
|
547
870
|
.ov-prose th,
|
|
548
871
|
.ov-prose td {
|
|
549
|
-
padding: var(--space-2xs) var(--space-s);
|
|
550
|
-
border: 1px solid var(--color-border);
|
|
872
|
+
padding: var(--space-2xs) var(--space-s) var(--space-2xs) 0;
|
|
551
873
|
text-align: start;
|
|
874
|
+
vertical-align: top;
|
|
875
|
+
border-block-end: 1px solid var(--color-border);
|
|
552
876
|
}
|
|
553
877
|
.ov-prose th {
|
|
554
|
-
background: var(--color-bg-subtle);
|
|
555
878
|
font-weight: 600;
|
|
879
|
+
font-size: 0.92em;
|
|
880
|
+
text-transform: uppercase;
|
|
881
|
+
letter-spacing: 0.04em;
|
|
882
|
+
color: var(--color-fg-muted);
|
|
883
|
+
border-block-end: 1px solid var(--color-border-strong);
|
|
884
|
+
padding-block: var(--space-xs);
|
|
885
|
+
}
|
|
886
|
+
.ov-prose tbody tr:last-child td {
|
|
887
|
+
border-block-end: 0;
|
|
888
|
+
}
|
|
889
|
+
.ov-prose tbody tr:hover td {
|
|
890
|
+
background: var(--color-bg-subtle);
|
|
891
|
+
}
|
|
892
|
+
.ov-prose table code:not(pre code) {
|
|
893
|
+
font-size: 0.9em;
|
|
556
894
|
}
|
|
557
895
|
|
|
558
896
|
/* Heading anchors
|
|
@@ -578,14 +916,19 @@ body.ov-menu-open {
|
|
|
578
916
|
color: var(--color-accent);
|
|
579
917
|
}
|
|
580
918
|
|
|
581
|
-
/* Code blocks (shiki dual-theme)
|
|
919
|
+
/* Code blocks (shiki dual-theme)
|
|
920
|
+
===
|
|
921
|
+
Padding bumped on top to clear the language eyebrow injected via
|
|
922
|
+
`pre[data-language]::before`. On hover the eyebrow fades and the
|
|
923
|
+
copy button (added by script.js) fades in at the same corner —
|
|
924
|
+
they trade places rather than compete for space. */
|
|
582
925
|
.ov-prose pre {
|
|
583
926
|
position: relative;
|
|
584
|
-
padding: var(--space-s);
|
|
927
|
+
padding: var(--space-m) var(--space-s) var(--space-s);
|
|
585
928
|
border-radius: var(--radius-md);
|
|
586
929
|
overflow-x: auto;
|
|
587
930
|
font-family: var(--font-mono);
|
|
588
|
-
font-size: 0.
|
|
931
|
+
font-size: 0.9em;
|
|
589
932
|
line-height: var(--leading-mono);
|
|
590
933
|
}
|
|
591
934
|
.ov-prose pre.shiki {
|
|
@@ -612,38 +955,106 @@ body.ov-menu-open {
|
|
|
612
955
|
color: var(--shiki-dark);
|
|
613
956
|
}
|
|
614
957
|
|
|
615
|
-
/*
|
|
616
|
-
.ov-
|
|
958
|
+
/* Language eyebrow (top-right of every highlighted fenced block) */
|
|
959
|
+
.ov-prose pre[data-language]::before {
|
|
960
|
+
content: attr(data-language);
|
|
617
961
|
position: absolute;
|
|
618
962
|
top: var(--space-2xs);
|
|
963
|
+
right: var(--space-s);
|
|
964
|
+
font-family: var(--font-mono);
|
|
965
|
+
font-size: 0.66em;
|
|
966
|
+
font-weight: 600;
|
|
967
|
+
text-transform: uppercase;
|
|
968
|
+
letter-spacing: 0.08em;
|
|
969
|
+
color: var(--color-fg-subtle);
|
|
970
|
+
opacity: 0.85;
|
|
971
|
+
pointer-events: none;
|
|
972
|
+
transition: opacity 120ms ease;
|
|
973
|
+
}
|
|
974
|
+
.ov-prose pre:hover[data-language]::before {
|
|
975
|
+
opacity: 0;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
/* Copy button (injected by script.js) — shares the top-right corner
|
|
979
|
+
with the language eyebrow, swaps in on hover. */
|
|
980
|
+
.ov-copy-btn {
|
|
981
|
+
position: absolute;
|
|
982
|
+
top: var(--space-3xs);
|
|
619
983
|
right: var(--space-2xs);
|
|
620
|
-
padding:
|
|
621
|
-
font-size: 0.
|
|
984
|
+
padding: 2px var(--space-2xs);
|
|
985
|
+
font-size: 0.72em;
|
|
622
986
|
font-family: var(--font-sans);
|
|
623
|
-
|
|
987
|
+
font-weight: 600;
|
|
988
|
+
letter-spacing: 0.02em;
|
|
989
|
+
background: transparent;
|
|
624
990
|
color: var(--color-fg-muted);
|
|
625
|
-
border: 1px solid
|
|
626
|
-
border-radius:
|
|
991
|
+
border: 1px solid transparent;
|
|
992
|
+
border-radius: var(--radius-sm);
|
|
627
993
|
cursor: pointer;
|
|
628
994
|
opacity: 0;
|
|
629
|
-
transition: opacity 120ms ease;
|
|
995
|
+
transition: opacity 120ms ease, color 120ms ease, background-color 120ms ease, border-color 120ms ease;
|
|
630
996
|
}
|
|
631
997
|
.ov-prose pre:hover .ov-copy-btn,
|
|
632
998
|
.ov-copy-btn:focus-visible {
|
|
633
999
|
opacity: 1;
|
|
634
1000
|
}
|
|
1001
|
+
.ov-copy-btn:hover {
|
|
1002
|
+
color: var(--color-fg);
|
|
1003
|
+
background: var(--color-bg-subtle);
|
|
1004
|
+
border-color: var(--color-border);
|
|
1005
|
+
}
|
|
1006
|
+
/* Breadcrumbs — sits above the page-meta when the page is nested 2+
|
|
1007
|
+
levels deep. Slash separator inserted via ::after on each crumb so
|
|
1008
|
+
it scales with text and doesn't render as an extra DOM element. */
|
|
1009
|
+
.ov-breadcrumbs {
|
|
1010
|
+
margin: 0 0 var(--space-2xs);
|
|
1011
|
+
}
|
|
1012
|
+
.ov-breadcrumbs ol {
|
|
1013
|
+
list-style: none;
|
|
1014
|
+
margin: 0;
|
|
1015
|
+
padding: 0;
|
|
1016
|
+
display: flex;
|
|
1017
|
+
flex-wrap: wrap;
|
|
1018
|
+
gap: 0;
|
|
1019
|
+
font-size: 0.82em;
|
|
1020
|
+
color: var(--color-fg-muted);
|
|
1021
|
+
}
|
|
1022
|
+
.ov-crumb {
|
|
1023
|
+
display: inline-flex;
|
|
1024
|
+
align-items: baseline;
|
|
1025
|
+
}
|
|
1026
|
+
.ov-crumb a {
|
|
1027
|
+
color: var(--color-fg-muted);
|
|
1028
|
+
text-decoration: none;
|
|
1029
|
+
transition: color 120ms ease;
|
|
1030
|
+
}
|
|
1031
|
+
.ov-crumb a:hover {
|
|
1032
|
+
color: var(--color-fg);
|
|
1033
|
+
}
|
|
1034
|
+
.ov-crumb:not(:last-child)::after {
|
|
1035
|
+
content: '/';
|
|
1036
|
+
color: var(--color-fg-subtle);
|
|
1037
|
+
opacity: 0.45;
|
|
1038
|
+
padding-inline: 0.5em;
|
|
1039
|
+
}
|
|
1040
|
+
.ov-crumb.is-current {
|
|
1041
|
+
color: var(--color-fg);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
635
1044
|
/* Page meta line (reading time + last-modified) above the article */
|
|
636
1045
|
.ov-page-meta {
|
|
637
1046
|
margin: 0 0 var(--space-s);
|
|
638
|
-
font-size: 0.
|
|
639
|
-
color: var(--color-fg-
|
|
1047
|
+
font-size: 0.82em;
|
|
1048
|
+
color: var(--color-fg-subtle);
|
|
640
1049
|
display: flex;
|
|
641
1050
|
flex-wrap: wrap;
|
|
642
|
-
gap: 0
|
|
1051
|
+
gap: 0;
|
|
643
1052
|
align-items: baseline;
|
|
1053
|
+
font-variant-numeric: tabular-nums;
|
|
644
1054
|
}
|
|
645
1055
|
.ov-page-meta-sep {
|
|
646
|
-
opacity: 0.
|
|
1056
|
+
opacity: 0.4;
|
|
1057
|
+
padding-inline: 0.5em;
|
|
647
1058
|
}
|
|
648
1059
|
|
|
649
1060
|
/* Edit-this-page link */
|
|
@@ -664,12 +1075,15 @@ body.ov-menu-open {
|
|
|
664
1075
|
}
|
|
665
1076
|
|
|
666
1077
|
/* Prev / next page navigation */
|
|
1078
|
+
/* Prev / next — Retype-style bordered button pair. The whole card is
|
|
1079
|
+
the click target; an arrow inline with the eyebrow label shows
|
|
1080
|
+
direction. Hover lifts the border + bg-subtle to confirm clickability. */
|
|
667
1081
|
.ov-prevnext {
|
|
668
1082
|
display: grid;
|
|
669
1083
|
grid-template-columns: 1fr 1fr;
|
|
670
1084
|
gap: var(--space-m);
|
|
671
|
-
margin-block: var(--space-
|
|
672
|
-
padding-block-start: var(--space-
|
|
1085
|
+
margin-block: var(--space-2xl) var(--space-m);
|
|
1086
|
+
padding-block-start: var(--space-l);
|
|
673
1087
|
border-block-start: 1px solid var(--color-border);
|
|
674
1088
|
}
|
|
675
1089
|
.ov-prevnext-link {
|
|
@@ -681,25 +1095,62 @@ body.ov-menu-open {
|
|
|
681
1095
|
border-radius: var(--radius-md);
|
|
682
1096
|
text-decoration: none;
|
|
683
1097
|
color: var(--color-fg);
|
|
684
|
-
|
|
1098
|
+
background: var(--color-bg);
|
|
1099
|
+
transition: border-color 120ms ease, background-color 120ms ease, color 120ms ease;
|
|
1100
|
+
min-inline-size: 0;
|
|
685
1101
|
}
|
|
686
1102
|
.ov-prevnext-link:hover {
|
|
687
|
-
border-color: var(--color-
|
|
688
|
-
|
|
1103
|
+
border-color: var(--color-border-strong);
|
|
1104
|
+
background: var(--color-bg-subtle);
|
|
1105
|
+
color: var(--color-accent);
|
|
689
1106
|
}
|
|
690
1107
|
.ov-prevnext-next {
|
|
691
1108
|
text-align: end;
|
|
692
1109
|
align-items: flex-end;
|
|
693
1110
|
}
|
|
694
1111
|
.ov-prevnext-label {
|
|
695
|
-
|
|
1112
|
+
display: inline-flex;
|
|
1113
|
+
align-items: center;
|
|
1114
|
+
gap: 0.4em;
|
|
1115
|
+
font-size: 0.74em;
|
|
696
1116
|
text-transform: uppercase;
|
|
697
|
-
letter-spacing: 0.
|
|
1117
|
+
letter-spacing: 0.08em;
|
|
698
1118
|
color: var(--color-fg-subtle);
|
|
699
1119
|
font-weight: 600;
|
|
700
1120
|
}
|
|
1121
|
+
.ov-prevnext-prev .ov-prevnext-label::before {
|
|
1122
|
+
content: '←';
|
|
1123
|
+
font-size: 1.1em;
|
|
1124
|
+
line-height: 1;
|
|
1125
|
+
letter-spacing: 0;
|
|
1126
|
+
transition: transform 120ms ease;
|
|
1127
|
+
}
|
|
1128
|
+
.ov-prevnext-next .ov-prevnext-label::after {
|
|
1129
|
+
content: '→';
|
|
1130
|
+
font-size: 1.1em;
|
|
1131
|
+
line-height: 1;
|
|
1132
|
+
letter-spacing: 0;
|
|
1133
|
+
transition: transform 120ms ease;
|
|
1134
|
+
}
|
|
1135
|
+
.ov-prevnext-link:hover .ov-prevnext-label {
|
|
1136
|
+
color: var(--color-accent);
|
|
1137
|
+
}
|
|
1138
|
+
.ov-prevnext-prev:hover .ov-prevnext-label::before {
|
|
1139
|
+
transform: translateX(-2px);
|
|
1140
|
+
}
|
|
1141
|
+
.ov-prevnext-next:hover .ov-prevnext-label::after {
|
|
1142
|
+
transform: translateX(2px);
|
|
1143
|
+
}
|
|
701
1144
|
.ov-prevnext-title {
|
|
702
|
-
font-weight:
|
|
1145
|
+
font-weight: 600;
|
|
1146
|
+
font-size: var(--font-size-1);
|
|
1147
|
+
letter-spacing: -0.01em;
|
|
1148
|
+
line-height: 1.3;
|
|
1149
|
+
/* Truncate insanely long titles rather than wrapping the button shape. */
|
|
1150
|
+
overflow: hidden;
|
|
1151
|
+
text-overflow: ellipsis;
|
|
1152
|
+
white-space: nowrap;
|
|
1153
|
+
inline-size: 100%;
|
|
703
1154
|
}
|
|
704
1155
|
.ov-prevnext-spacer {
|
|
705
1156
|
display: block;
|
|
@@ -715,7 +1166,8 @@ body.ov-menu-open {
|
|
|
715
1166
|
}
|
|
716
1167
|
|
|
717
1168
|
.ov-copy-btn.is-copied {
|
|
718
|
-
color: var(--
|
|
1169
|
+
color: var(--callout-tip-fg);
|
|
1170
|
+
opacity: 1;
|
|
719
1171
|
}
|
|
720
1172
|
|
|
721
1173
|
/* Right ToC */
|
|
@@ -728,44 +1180,146 @@ body.ov-menu-open {
|
|
|
728
1180
|
font-size: 0.9em;
|
|
729
1181
|
}
|
|
730
1182
|
.ov-toc-title {
|
|
731
|
-
font-size: 0.
|
|
1183
|
+
font-size: 0.72em;
|
|
732
1184
|
text-transform: uppercase;
|
|
733
|
-
letter-spacing: 0.
|
|
1185
|
+
letter-spacing: 0.08em;
|
|
734
1186
|
color: var(--color-fg-subtle);
|
|
735
|
-
margin-block: 0 var(--space-
|
|
1187
|
+
margin-block: 0 var(--space-xs);
|
|
736
1188
|
font-weight: 600;
|
|
737
1189
|
}
|
|
738
1190
|
.ov-toc ul {
|
|
739
1191
|
list-style: none;
|
|
740
1192
|
margin: 0;
|
|
741
1193
|
padding: 0;
|
|
1194
|
+
position: relative;
|
|
1195
|
+
border-inline-start: 1px solid var(--color-border);
|
|
742
1196
|
}
|
|
743
1197
|
.ov-toc li {
|
|
744
|
-
margin
|
|
1198
|
+
margin: 0;
|
|
745
1199
|
}
|
|
746
1200
|
.ov-toc li a {
|
|
1201
|
+
position: relative;
|
|
1202
|
+
display: block;
|
|
1203
|
+
padding: 0.3em 0;
|
|
1204
|
+
padding-inline-start: var(--space-s);
|
|
747
1205
|
color: var(--color-fg-muted);
|
|
748
1206
|
text-decoration: none;
|
|
1207
|
+
transition: color 120ms ease;
|
|
1208
|
+
line-height: 1.4;
|
|
749
1209
|
}
|
|
750
1210
|
.ov-toc li a:hover {
|
|
751
1211
|
color: var(--color-fg);
|
|
752
1212
|
}
|
|
753
|
-
.ov-toc-
|
|
754
|
-
|
|
1213
|
+
.ov-toc li a.is-current {
|
|
1214
|
+
color: var(--color-accent);
|
|
1215
|
+
font-weight: 500;
|
|
1216
|
+
}
|
|
1217
|
+
/* The active indicator: 2px accent strip overlaying the 1px ul border.
|
|
1218
|
+
Pulled 1px outside so it covers the track cleanly. */
|
|
1219
|
+
.ov-toc li a.is-current::before {
|
|
1220
|
+
content: '';
|
|
1221
|
+
position: absolute;
|
|
1222
|
+
inset-block: 0;
|
|
1223
|
+
inset-inline-start: -1px;
|
|
1224
|
+
inline-size: 2px;
|
|
1225
|
+
background: var(--color-accent);
|
|
1226
|
+
}
|
|
1227
|
+
.ov-toc-h3 a {
|
|
1228
|
+
padding-inline-start: calc(var(--space-s) + var(--space-s));
|
|
1229
|
+
font-size: 0.95em;
|
|
755
1230
|
}
|
|
756
1231
|
|
|
757
|
-
/* Footer
|
|
1232
|
+
/* Footer
|
|
1233
|
+
===
|
|
1234
|
+
Outer is full-bleed (matches .ov-topbar) so the chrome tint and top
|
|
1235
|
+
border span the viewport; inner holds the grid and constrains to
|
|
1236
|
+
--chrome-max. Result: the topbar, content area, and footer rails
|
|
1237
|
+
share identical vertical gutters at every viewport, and the chrome
|
|
1238
|
+
width never jumps between landing and docs. */
|
|
758
1239
|
.ov-footer {
|
|
759
|
-
|
|
760
|
-
margin: var(--space-
|
|
761
|
-
padding: var(--space-s) var(--space-m);
|
|
1240
|
+
inline-size: 100%;
|
|
1241
|
+
margin-block-start: var(--space-2xl);
|
|
762
1242
|
border-block-start: 1px solid var(--color-border);
|
|
1243
|
+
background: var(--color-bg-chrome);
|
|
763
1244
|
color: var(--color-fg-subtle);
|
|
764
|
-
font-size: 0.
|
|
765
|
-
|
|
1245
|
+
font-size: 0.84em;
|
|
1246
|
+
}
|
|
1247
|
+
.ov-footer-inner {
|
|
1248
|
+
display: grid;
|
|
1249
|
+
grid-template-columns: auto 1fr auto;
|
|
1250
|
+
align-items: center;
|
|
1251
|
+
gap: var(--space-m);
|
|
1252
|
+
padding: var(--space-m);
|
|
1253
|
+
max-inline-size: var(--chrome-max);
|
|
1254
|
+
margin-inline: auto;
|
|
1255
|
+
inline-size: 100%;
|
|
1256
|
+
}
|
|
1257
|
+
.ov-footer-left {
|
|
1258
|
+
grid-column: 1;
|
|
1259
|
+
display: inline-flex;
|
|
1260
|
+
align-items: baseline;
|
|
1261
|
+
flex-wrap: wrap;
|
|
1262
|
+
gap: 0.45em;
|
|
1263
|
+
min-inline-size: 0;
|
|
1264
|
+
}
|
|
1265
|
+
.ov-footer-right {
|
|
1266
|
+
grid-column: 3;
|
|
1267
|
+
display: inline-flex;
|
|
1268
|
+
align-items: center;
|
|
1269
|
+
flex-wrap: wrap;
|
|
1270
|
+
gap: var(--space-xs);
|
|
1271
|
+
}
|
|
1272
|
+
.ov-footer-link {
|
|
1273
|
+
color: var(--color-fg-muted);
|
|
1274
|
+
text-decoration: none;
|
|
1275
|
+
transition: color 120ms ease;
|
|
1276
|
+
}
|
|
1277
|
+
.ov-footer-link:hover {
|
|
1278
|
+
color: var(--color-fg);
|
|
1279
|
+
}
|
|
1280
|
+
.ov-footer-link--icon {
|
|
1281
|
+
display: inline-flex;
|
|
1282
|
+
align-items: center;
|
|
1283
|
+
justify-content: center;
|
|
1284
|
+
inline-size: 1.85rem;
|
|
1285
|
+
block-size: 1.85rem;
|
|
1286
|
+
border-radius: var(--radius-md);
|
|
1287
|
+
color: var(--color-fg-muted);
|
|
1288
|
+
}
|
|
1289
|
+
.ov-footer-link--icon:hover {
|
|
1290
|
+
color: var(--color-fg);
|
|
1291
|
+
background: var(--color-bg-subtle);
|
|
1292
|
+
}
|
|
1293
|
+
.ov-footer-icon {
|
|
1294
|
+
display: block;
|
|
766
1295
|
}
|
|
767
1296
|
.ov-footer-sep {
|
|
768
|
-
margin-inline:
|
|
1297
|
+
margin-inline: 0.05em;
|
|
1298
|
+
opacity: 0.5;
|
|
1299
|
+
}
|
|
1300
|
+
.ov-sr-only {
|
|
1301
|
+
position: absolute;
|
|
1302
|
+
inline-size: 1px;
|
|
1303
|
+
block-size: 1px;
|
|
1304
|
+
padding: 0;
|
|
1305
|
+
margin: -1px;
|
|
1306
|
+
overflow: hidden;
|
|
1307
|
+
clip: rect(0, 0, 0, 0);
|
|
1308
|
+
white-space: nowrap;
|
|
1309
|
+
border: 0;
|
|
1310
|
+
}
|
|
1311
|
+
@media (max-width: 720px) {
|
|
1312
|
+
.ov-footer {
|
|
1313
|
+
grid-template-columns: 1fr;
|
|
1314
|
+
gap: var(--space-2xs);
|
|
1315
|
+
}
|
|
1316
|
+
.ov-footer-left {
|
|
1317
|
+
grid-column: 1;
|
|
1318
|
+
}
|
|
1319
|
+
.ov-footer-right {
|
|
1320
|
+
grid-column: 1;
|
|
1321
|
+
justify-content: flex-start;
|
|
1322
|
+
}
|
|
769
1323
|
}
|
|
770
1324
|
|
|
771
1325
|
/* Narrow viewports: drop the right ToC, then collapse the sidebar */
|
|
@@ -888,61 +1442,74 @@ body.ov-body-landing {
|
|
|
888
1442
|
}
|
|
889
1443
|
|
|
890
1444
|
.ov-landing {
|
|
891
|
-
max-inline-size:
|
|
1445
|
+
max-inline-size: var(--page-max);
|
|
892
1446
|
margin-inline: auto;
|
|
893
1447
|
padding: 0 var(--space-m) var(--space-l);
|
|
894
1448
|
}
|
|
895
1449
|
|
|
896
1450
|
/* Hero
|
|
897
1451
|
===
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
1452
|
+
Centred prose (title / subtitle / CTAs) on a flat background. The earlier
|
|
1453
|
+
dotted-noise + accent-spotlight pseudo-layers were removed — a blended
|
|
1454
|
+
background image is planned to take this surface later. The vertical
|
|
1455
|
+
padding alone gives the hero its presence and the breathing room between
|
|
1456
|
+
the topbar above and the body content below. The `[data-media]` variant
|
|
1457
|
+
(site.landing.hero.media) still renders its own full-bleed <img> layer
|
|
1458
|
+
(see .ov-hero-art below). */
|
|
904
1459
|
.ov-hero {
|
|
1460
|
+
/* position + isolation are dormant here (flat background) but kept so the
|
|
1461
|
+
[data-media] variant's absolutely-positioned .ov-hero-art layer still
|
|
1462
|
+
anchors to the hero and stays in its own stacking context. */
|
|
905
1463
|
position: relative;
|
|
906
1464
|
isolation: isolate;
|
|
907
1465
|
text-align: center;
|
|
908
|
-
padding-block: clamp(var(--space-2xl),
|
|
909
|
-
clamp(var(--space-
|
|
910
|
-
margin-inline: calc(-1 * var(--space-m));
|
|
911
|
-
overflow: hidden;
|
|
1466
|
+
padding-block: clamp(var(--space-2xl), 11vw, var(--space-3xl))
|
|
1467
|
+
clamp(var(--space-l), 7vw, var(--space-2xl));
|
|
912
1468
|
}
|
|
913
|
-
|
|
914
|
-
.
|
|
915
|
-
|
|
1469
|
+
|
|
1470
|
+
/* Imagery hero variant — when `site.landing.hero.media` is configured the
|
|
1471
|
+
template adds `data-media`, switching the hero to a taller full-bleed
|
|
1472
|
+
layout sized to hold the supplied <img> (.ov-hero-art). */
|
|
1473
|
+
.ov-hero[data-media] {
|
|
1474
|
+
padding-block: clamp(var(--space-3xl), 14vw, calc(var(--space-3xl) * 1.4))
|
|
1475
|
+
clamp(var(--space-xl), 9vw, var(--space-3xl));
|
|
1476
|
+
min-block-size: clamp(420px, 56vw, 640px);
|
|
1477
|
+
display: flex;
|
|
1478
|
+
flex-direction: column;
|
|
1479
|
+
justify-content: center;
|
|
1480
|
+
}
|
|
1481
|
+
.ov-hero-art {
|
|
916
1482
|
position: absolute;
|
|
917
1483
|
inset: 0;
|
|
918
1484
|
pointer-events: none;
|
|
919
1485
|
z-index: -1;
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
:
|
|
932
|
-
|
|
933
|
-
|
|
1486
|
+
overflow: hidden;
|
|
1487
|
+
/* Soft fade-out so the art recedes into the page before the feature grid
|
|
1488
|
+
begins — keeps the seam editorial-calm rather than hard-edged. */
|
|
1489
|
+
-webkit-mask-image: linear-gradient(to bottom,
|
|
1490
|
+
black 0%, black 78%, transparent 100%);
|
|
1491
|
+
mask-image: linear-gradient(to bottom,
|
|
1492
|
+
black 0%, black 78%, transparent 100%);
|
|
1493
|
+
}
|
|
1494
|
+
.ov-hero-art-img {
|
|
1495
|
+
position: absolute;
|
|
1496
|
+
inset: 0;
|
|
1497
|
+
inline-size: 100%;
|
|
1498
|
+
block-size: 100%;
|
|
1499
|
+
object-fit: cover;
|
|
1500
|
+
object-position: center;
|
|
1501
|
+
}
|
|
1502
|
+
/* Default: light shown, dark hidden. Theme + auto-with-OS-preference flip. */
|
|
1503
|
+
.ov-hero-art-img--dark { opacity: 0; }
|
|
1504
|
+
:root[data-theme='dark'] .ov-hero-art-img--light { opacity: 0; }
|
|
1505
|
+
:root[data-theme='dark'] .ov-hero-art-img--dark { opacity: 1; }
|
|
934
1506
|
@media (prefers-color-scheme: dark) {
|
|
935
|
-
:root[data-theme='auto'] .ov-hero
|
|
936
|
-
|
|
937
|
-
}
|
|
1507
|
+
:root[data-theme='auto'] .ov-hero-art-img--light { opacity: 0; }
|
|
1508
|
+
:root[data-theme='auto'] .ov-hero-art-img--dark { opacity: 1; }
|
|
938
1509
|
}
|
|
939
|
-
.ov-hero
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
ellipse 50% 38% at 50% 35%,
|
|
943
|
-
color-mix(in oklch, var(--color-accent) 22%, transparent) 0%,
|
|
944
|
-
transparent 70%
|
|
945
|
-
);
|
|
1510
|
+
.ov-hero-inner {
|
|
1511
|
+
position: relative;
|
|
1512
|
+
z-index: 1;
|
|
946
1513
|
}
|
|
947
1514
|
.ov-hero-title {
|
|
948
1515
|
position: relative;
|
|
@@ -996,17 +1563,28 @@ body.ov-body-landing {
|
|
|
996
1563
|
.ov-cta--secondary {
|
|
997
1564
|
background: transparent;
|
|
998
1565
|
color: var(--color-fg);
|
|
999
|
-
border: 1px solid var(--color-border
|
|
1566
|
+
border: 1px solid var(--color-border);
|
|
1000
1567
|
}
|
|
1001
1568
|
.ov-cta--secondary:hover {
|
|
1002
|
-
background:
|
|
1003
|
-
border-color: var(--color-fg
|
|
1569
|
+
background: transparent;
|
|
1570
|
+
border-color: var(--color-fg);
|
|
1004
1571
|
color: var(--color-fg);
|
|
1005
1572
|
}
|
|
1006
1573
|
|
|
1007
|
-
/*
|
|
1574
|
+
/* Card — a clean, subtle surface primitive. A surface a hair lighter than
|
|
1575
|
+
the page, a hairline border, a modest radius, and a whisper of shadow.
|
|
1576
|
+
Reused across the site; the landing feature grid is the first adopter. */
|
|
1577
|
+
.ov-card {
|
|
1578
|
+
background: var(--color-surface);
|
|
1579
|
+
border: 1px solid var(--color-border);
|
|
1580
|
+
border-radius: var(--radius-lg);
|
|
1581
|
+
padding: var(--space-m);
|
|
1582
|
+
box-shadow: 0 1px 2px oklch(0% 0 0 / 0.04);
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
/* Feature grid — three subtle cards beneath the hero. */
|
|
1008
1586
|
.ov-feature-grid-wrap {
|
|
1009
|
-
margin-block: var(--space-
|
|
1587
|
+
margin-block: var(--space-2xl) var(--space-xl);
|
|
1010
1588
|
}
|
|
1011
1589
|
.ov-feature-grid {
|
|
1012
1590
|
display: grid;
|
|
@@ -1014,33 +1592,27 @@ body.ov-body-landing {
|
|
|
1014
1592
|
gap: var(--space-m);
|
|
1015
1593
|
}
|
|
1016
1594
|
.ov-feature-card {
|
|
1017
|
-
background: var(--color-bg-subtle);
|
|
1018
|
-
border: 1px solid var(--color-border);
|
|
1019
|
-
border-radius: var(--radius-lg);
|
|
1020
|
-
padding: var(--space-m);
|
|
1021
1595
|
display: flex;
|
|
1022
1596
|
flex-direction: column;
|
|
1023
1597
|
gap: var(--space-2xs);
|
|
1024
|
-
transition: border-color 120ms ease;
|
|
1025
|
-
}
|
|
1026
|
-
.ov-feature-card:hover {
|
|
1027
|
-
border-color: var(--color-border-strong);
|
|
1028
1598
|
}
|
|
1029
1599
|
.ov-feature-icon {
|
|
1030
1600
|
font-size: var(--font-size-2);
|
|
1031
1601
|
line-height: 1;
|
|
1602
|
+
color: var(--color-fg-subtle);
|
|
1032
1603
|
}
|
|
1033
1604
|
.ov-feature-title {
|
|
1034
1605
|
margin: 0;
|
|
1035
1606
|
font-size: var(--font-size-1);
|
|
1036
|
-
line-height: 1.
|
|
1607
|
+
line-height: 1.25;
|
|
1037
1608
|
font-weight: 600;
|
|
1609
|
+
letter-spacing: -0.01em;
|
|
1038
1610
|
}
|
|
1039
1611
|
.ov-feature-description {
|
|
1040
1612
|
margin: 0;
|
|
1041
1613
|
color: var(--color-fg-muted);
|
|
1042
1614
|
font-size: var(--font-size-0);
|
|
1043
|
-
line-height: 1.
|
|
1615
|
+
line-height: 1.6;
|
|
1044
1616
|
}
|
|
1045
1617
|
|
|
1046
1618
|
/* Pitch section (from _landing.md prose body) */
|
|
@@ -1052,7 +1624,7 @@ body.ov-body-landing {
|
|
|
1052
1624
|
.ov-pitch-inner {
|
|
1053
1625
|
max-inline-size: 60ch;
|
|
1054
1626
|
margin-inline: auto;
|
|
1055
|
-
font-size: var(--font-size-
|
|
1627
|
+
font-size: var(--font-size-1);
|
|
1056
1628
|
line-height: 1.65;
|
|
1057
1629
|
color: var(--color-fg-muted);
|
|
1058
1630
|
}
|
|
@@ -1084,11 +1656,11 @@ body.ov-body-landing {
|
|
|
1084
1656
|
text-align: center;
|
|
1085
1657
|
}
|
|
1086
1658
|
.ov-trust-label {
|
|
1087
|
-
font-size: 0.
|
|
1659
|
+
font-size: 0.72em;
|
|
1088
1660
|
text-transform: uppercase;
|
|
1089
|
-
letter-spacing: 0.
|
|
1661
|
+
letter-spacing: 0.1em;
|
|
1090
1662
|
color: var(--color-fg-subtle);
|
|
1091
|
-
margin-block: 0 var(--space-
|
|
1663
|
+
margin-block: 0 var(--space-m);
|
|
1092
1664
|
font-weight: 600;
|
|
1093
1665
|
}
|
|
1094
1666
|
.ov-trust-items {
|
|
@@ -1096,12 +1668,14 @@ body.ov-body-landing {
|
|
|
1096
1668
|
flex-wrap: wrap;
|
|
1097
1669
|
justify-content: center;
|
|
1098
1670
|
align-items: center;
|
|
1099
|
-
gap: var(--space-
|
|
1671
|
+
gap: var(--space-xl);
|
|
1100
1672
|
}
|
|
1101
1673
|
.ov-trust-item {
|
|
1102
|
-
color: var(--color-fg-
|
|
1674
|
+
color: var(--color-fg-subtle);
|
|
1103
1675
|
text-decoration: none;
|
|
1104
1676
|
font-weight: 500;
|
|
1677
|
+
font-size: 0.95em;
|
|
1678
|
+
transition: color 120ms ease;
|
|
1105
1679
|
}
|
|
1106
1680
|
.ov-trust-item:hover {
|
|
1107
1681
|
color: var(--color-fg);
|
|
@@ -1116,6 +1690,60 @@ body.ov-body-landing {
|
|
|
1116
1690
|
opacity: 1;
|
|
1117
1691
|
}
|
|
1118
1692
|
|
|
1693
|
+
/* Ambient "scenes" — centered visual figures between landing sections.
|
|
1694
|
+
* Editorial-calm: no chrome, top/bottom mask fades so the visual recedes
|
|
1695
|
+
* into the surrounding content. SVG-driven animation lives inside each
|
|
1696
|
+
* asset; this wrapper is intentionally still. */
|
|
1697
|
+
.ov-scene {
|
|
1698
|
+
margin-block: var(--space-xl);
|
|
1699
|
+
inline-size: 100%;
|
|
1700
|
+
/* No full-bleed: scenes sit centered inside the landing column. The
|
|
1701
|
+
* landing's --page-max (1100px on body.ov-body-landing) is the
|
|
1702
|
+
* authoritative width; .ov-landing already centers itself. */
|
|
1703
|
+
margin-inline: auto;
|
|
1704
|
+
}
|
|
1705
|
+
.ov-scene-art {
|
|
1706
|
+
margin: 0;
|
|
1707
|
+
position: relative;
|
|
1708
|
+
aspect-ratio: 16 / 9;
|
|
1709
|
+
display: flex;
|
|
1710
|
+
justify-content: center;
|
|
1711
|
+
align-items: center;
|
|
1712
|
+
-webkit-mask-image: linear-gradient(
|
|
1713
|
+
to bottom,
|
|
1714
|
+
transparent 0%,
|
|
1715
|
+
black 14%,
|
|
1716
|
+
black 86%,
|
|
1717
|
+
transparent 100%
|
|
1718
|
+
);
|
|
1719
|
+
mask-image: linear-gradient(
|
|
1720
|
+
to bottom,
|
|
1721
|
+
transparent 0%,
|
|
1722
|
+
black 14%,
|
|
1723
|
+
black 86%,
|
|
1724
|
+
transparent 100%
|
|
1725
|
+
);
|
|
1726
|
+
}
|
|
1727
|
+
.ov-scene-img {
|
|
1728
|
+
position: absolute;
|
|
1729
|
+
inset: 0;
|
|
1730
|
+
inline-size: 100%;
|
|
1731
|
+
block-size: 100%;
|
|
1732
|
+
/* `contain` keeps the SVG's intrinsic aspect ratio visible; the figure
|
|
1733
|
+
* sits centered (justify/align on the parent) inside the 16:9 frame. */
|
|
1734
|
+
object-fit: contain;
|
|
1735
|
+
object-position: center;
|
|
1736
|
+
opacity: 0.95;
|
|
1737
|
+
transition: opacity 200ms ease;
|
|
1738
|
+
}
|
|
1739
|
+
.ov-scene-img--dark { opacity: 0; }
|
|
1740
|
+
:root[data-theme='dark'] .ov-scene-img--light { opacity: 0; }
|
|
1741
|
+
:root[data-theme='dark'] .ov-scene-img--dark { opacity: 0.95; }
|
|
1742
|
+
@media (prefers-color-scheme: dark) {
|
|
1743
|
+
:root[data-theme='auto'] .ov-scene-img--light { opacity: 0; }
|
|
1744
|
+
:root[data-theme='auto'] .ov-scene-img--dark { opacity: 0.95; }
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1119
1747
|
/* Landing-page responsive */
|
|
1120
1748
|
@media (max-width: 720px) {
|
|
1121
1749
|
.ov-landing {
|
|
@@ -1125,6 +1753,10 @@ body.ov-body-landing {
|
|
|
1125
1753
|
margin-inline: calc(-1 * var(--space-s));
|
|
1126
1754
|
padding-block: var(--space-xl) var(--space-l);
|
|
1127
1755
|
}
|
|
1756
|
+
.ov-hero[data-media] {
|
|
1757
|
+
padding-block: var(--space-2xl) var(--space-xl);
|
|
1758
|
+
min-block-size: clamp(320px, 70vw, 460px);
|
|
1759
|
+
}
|
|
1128
1760
|
.ov-hero-title {
|
|
1129
1761
|
letter-spacing: -0.03em;
|
|
1130
1762
|
}
|
|
@@ -1134,4 +1766,10 @@ body.ov-body-landing {
|
|
|
1134
1766
|
.ov-trust-items {
|
|
1135
1767
|
gap: var(--space-m);
|
|
1136
1768
|
}
|
|
1769
|
+
.ov-scene {
|
|
1770
|
+
margin-block: var(--space-l);
|
|
1771
|
+
}
|
|
1772
|
+
.ov-scene-art {
|
|
1773
|
+
aspect-ratio: 16 / 10;
|
|
1774
|
+
}
|
|
1137
1775
|
}
|