@fluid-theme/core 0.4.3 → 2.1.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 +564 -2
- package/CLAUDE.md +201 -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-archivo.min.css +2 -0
- package/dist/fluid-fonts-bodoni.min.css +2 -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-archivo.txt +93 -0
- package/dist/fonts/OFL-bodoni-moda.txt +93 -0
- package/dist/fonts/OFL-hanken-grotesk.txt +93 -0
- package/dist/fonts/OFL-newsreader.txt +93 -0
- package/dist/fonts/OFL-schibsted-grotesk.txt +93 -0
- package/dist/fonts/archivo-latin-wdth-italic.woff2 +0 -0
- package/dist/fonts/archivo-latin-wdth-normal.woff2 +0 -0
- package/dist/fonts/bodoni-moda-latin-opsz-italic.woff2 +0 -0
- package/dist/fonts/bodoni-moda-latin-opsz-normal.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-latin-wght-italic.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-latin-wght-normal.woff2 +0 -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 +36 -11
- 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/starters/workflows/README.md +40 -0
- package/starters/workflows/dependabot.yml +21 -0
- package/starters/workflows/update-fluid-theme.yml +296 -0
- package/themes/fonts/OFL-archivo.txt +93 -0
- package/themes/fonts/OFL-bodoni-moda.txt +93 -0
- package/themes/fonts/OFL-hanken-grotesk.txt +93 -0
- package/themes/fonts/archivo-latin-wdth-italic.woff2 +0 -0
- package/themes/fonts/archivo-latin-wdth-normal.woff2 +0 -0
- package/themes/fonts/archivo.css +20 -0
- package/themes/fonts/bodoni-moda-latin-opsz-italic.woff2 +0 -0
- package/themes/fonts/bodoni-moda-latin-opsz-normal.woff2 +0 -0
- package/themes/fonts/bodoni.css +35 -0
- package/themes/fonts/hanken-grotesk-latin-wght-italic.woff2 +0 -0
- package/themes/fonts/hanken-grotesk-latin-wght-normal.woff2 +0 -0
- package/themes/gallery.css +105 -0
- package/themes/swiss.css +53 -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
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TOC: a table of contents with scroll spy (spec _docs/plans/base-v2.md §13)
|
|
3
|
+
* @layer components
|
|
4
|
+
*
|
|
5
|
+
* The server writes the list from the article's own headings (H2 top level,
|
|
6
|
+
* H3 nested; assets/js/toc-build.mjs), so crawlers, AI fetchers and no-JS
|
|
7
|
+
* readers get plain links. assets/js/toc.js adds the spy and the dock.
|
|
8
|
+
* Built to its own file, dist/fluid-toc.min.css (package export "./toc"):
|
|
9
|
+
* link it after core on article pages. Gate: scripts/toc-check.mjs.
|
|
10
|
+
*
|
|
11
|
+
* <div class="article__body">
|
|
12
|
+
* <nav class="toc" data-toc="rail dock" aria-labelledby="toc-label">
|
|
13
|
+
* <details class="toc__fold" open>
|
|
14
|
+
* <summary class="toc__label" id="toc-label">On this page</summary>
|
|
15
|
+
* <ol><li><a href="#cost">What it costs</a>
|
|
16
|
+
* <ol><li><a href="#labour">Labour</a></li></ol></li></ol>
|
|
17
|
+
* </details>
|
|
18
|
+
* </nav>
|
|
19
|
+
* <div class="prose content-grid">…</div>
|
|
20
|
+
* </div>
|
|
21
|
+
*
|
|
22
|
+
* data-toc words, one per layer:
|
|
23
|
+
* placement inline (in the flow) · rail (sticky side column at 70rem and
|
|
24
|
+
* up, inline below) · dock (pinned two-row bar; needs toc.js) ·
|
|
25
|
+
* "rail dock" (rail when wide, dock when narrow)
|
|
26
|
+
* side end puts the rail after the article (default: inline start)
|
|
27
|
+
* data-toc-depth="2" lists H2s only. toc.js sets data-toc-mode
|
|
28
|
+
* (inline | rail | dock) and aria-current="location" on the active link.
|
|
29
|
+
*
|
|
30
|
+
* Look hooks, read with fallbacks and never declared (set them on :root in
|
|
31
|
+
* a child theme): --toc-font, --toc-dock-font, --toc-dock-bg, --toc-size,
|
|
32
|
+
* --toc-sub-size (H3 entries, default 0.93em), --toc-color (resting entries; the active
|
|
33
|
+
* entry and its section's H2 rise to the text colour), --toc-active,
|
|
34
|
+
* --toc-rule, --toc-marker (a counter style for H2 entries, e.g.
|
|
35
|
+
* decimal-leading-zero).
|
|
36
|
+
*
|
|
37
|
+
* TOC PRESETS: each is markup words + a :root snippet. Layer 1 placement
|
|
38
|
+
* (vertical rail / inline list / horizontal dock), layer 2 behaviour
|
|
39
|
+
* (static: no toc.js; dynamic: toc.js spy, centring, the dock), layer 3
|
|
40
|
+
* motion (glide; a jump under reduced motion or data-motion="reduced"),
|
|
41
|
+
* layer 4 the look (the hooks).
|
|
42
|
+
* editorial (the default) data-toc="rail dock" no snippet
|
|
43
|
+
* numbered data-toc="rail dock" :root { --toc-marker: decimal-leading-zero; }
|
|
44
|
+
* serif data-toc="rail dock" :root { --toc-font: var(--font-heading); --toc-size: var(--step-0); }
|
|
45
|
+
* swiss data-toc="rail dock" :root { --toc-marker: decimal-leading-zero; --toc-dock-font: var(--font-body); --toc-rule: 3px; }
|
|
46
|
+
* gallery data-toc="dock" :root { --toc-font: var(--font-body); --toc-dock-font: var(--font-display); }
|
|
47
|
+
* quiet (static list) data-toc="inline" no toc.js; :root { --toc-sub-size: 0.875em; }
|
|
48
|
+
* end rail data-toc="rail end" the rail after the article
|
|
49
|
+
*
|
|
50
|
+
* The dock shows one section's subsections at a time (row two): the current
|
|
51
|
+
* section's, or those of the section that holds keyboard focus. The others
|
|
52
|
+
* stay in the accessibility tree and the tab order, clipped until reached.
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
@layer components {
|
|
56
|
+
.toc { font-variant-numeric: lining-nums proportional-nums; }
|
|
57
|
+
|
|
58
|
+
/* The type sits on the fold, not the nav: the nav's own ch (its --measure
|
|
59
|
+
width below) then resolves at body size and lines up with the prose. */
|
|
60
|
+
.toc__fold {
|
|
61
|
+
margin: 0;
|
|
62
|
+
font: var(--toc-size, var(--step--1)) / 1.3 var(--toc-font, var(--font-body));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.toc ol { list-style: none; margin: 0; padding: 0; counter-reset: toc; }
|
|
66
|
+
.toc ol ol { margin-inline-start: 1em; }
|
|
67
|
+
.toc li { margin: 0; counter-increment: toc; }
|
|
68
|
+
|
|
69
|
+
/* Rows 44px under a coarse pointer, 32px with a mouse. The rule sits on
|
|
70
|
+
the link, so the active mark moves with its (indented) text. */
|
|
71
|
+
.toc { --_toc-row: 2.75rem; }
|
|
72
|
+
@media (pointer: fine) { .toc { --_toc-row: 2rem; } }
|
|
73
|
+
|
|
74
|
+
.toc a {
|
|
75
|
+
display: block;
|
|
76
|
+
padding-block: calc((var(--_toc-row) - 1lh) / 2);
|
|
77
|
+
padding-inline: var(--space-s) 0;
|
|
78
|
+
border-inline-start: var(--toc-rule, var(--border-width-thick)) solid transparent;
|
|
79
|
+
color: var(--toc-color, var(--color-text-muted));
|
|
80
|
+
text-decoration-line: none;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* The outline reads at a glance: sections in a heavier weight,
|
|
84
|
+
subsections smaller. At rest both are muted, so the current place
|
|
85
|
+
(the active entry and its section) stands out in the text colour. */
|
|
86
|
+
.toc__fold > ol > li > a { font-weight: calc(var(--weight-medium) + var(--_dark-weight)); }
|
|
87
|
+
.toc__fold > ol > li + li { margin-block-start: var(--space-1); }
|
|
88
|
+
.toc li li a { font-size: var(--toc-sub-size, 0.93em); }
|
|
89
|
+
|
|
90
|
+
.toc a:hover { color: var(--color-text); text-decoration-line: underline; }
|
|
91
|
+
.toc a:focus-visible { outline-offset: -2px; }
|
|
92
|
+
|
|
93
|
+
/* The H2 that holds the active H3 is lit without the rule. */
|
|
94
|
+
.toc li:has(a[aria-current]) > a,
|
|
95
|
+
.toc a[aria-current] { color: var(--color-text); }
|
|
96
|
+
.toc a[aria-current] { border-inline-start-color: var(--toc-active, var(--accent-ink)); }
|
|
97
|
+
|
|
98
|
+
/* Forced colours turn the transparent resting rule into a LinkText bar
|
|
99
|
+
on every entry; only the active one keeps a mark. */
|
|
100
|
+
@media (forced-colors: active) {
|
|
101
|
+
.toc a { border-inline-start-color: Canvas; }
|
|
102
|
+
.toc a[aria-current] { border-inline-start-color: Highlight; text-decoration-line: underline; }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* Numbering: a leading space collapses when the counter style is none. */
|
|
106
|
+
.toc__fold > ol > li > a::before {
|
|
107
|
+
content: counter(toc, var(--toc-marker, none)) " ";
|
|
108
|
+
word-spacing: 0.5em;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.article__body > .toc {
|
|
112
|
+
inline-size: min(100% - 2 * var(--page-edge), var(--measure));
|
|
113
|
+
margin: 0 auto var(--space-l);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* RAIL: two columns, the nav sticky in the first (or the second, "end").
|
|
117
|
+
Full bleed stops at the article column on these pages. toc.js keeps the
|
|
118
|
+
active entry in view when the list is taller than the rail. */
|
|
119
|
+
@media (width >= 70rem) {
|
|
120
|
+
.article__body:has(> .toc[data-toc~="rail"]) {
|
|
121
|
+
display: grid;
|
|
122
|
+
grid-template-columns: minmax(12rem, 16rem) minmax(0, 1fr);
|
|
123
|
+
column-gap: var(--space-l);
|
|
124
|
+
padding-inline: max(var(--page-edge), (100% - var(--container-content)) / 2);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.article__body:has(> .toc[data-toc~="rail"][data-toc~="end"]) { grid-template-columns: minmax(0, 1fr) minmax(12rem, 16rem); }
|
|
128
|
+
.article__body:has(> .toc[data-toc~="rail"]) > .content-grid { --_edge: 0rem; }
|
|
129
|
+
|
|
130
|
+
.article__body > .toc[data-toc~="rail"] {
|
|
131
|
+
position: sticky;
|
|
132
|
+
inset-block-start: var(--space-xl);
|
|
133
|
+
align-self: start;
|
|
134
|
+
inline-size: auto;
|
|
135
|
+
max-block-size: calc(100dvh - 2 * var(--space-xl));
|
|
136
|
+
margin: 0;
|
|
137
|
+
overflow-y: auto;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.article__body > .toc[data-toc~="end"] { grid-area: 1 / 2; }
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/* DOCK: a bar pinned to the bottom. Row one is the sections, the current
|
|
144
|
+
one centred with its neighbours either side; row two is the current
|
|
145
|
+
section's subsections. toc.js centres both. Off screen it is only
|
|
146
|
+
translated away: it stays in the accessibility tree and the tab order,
|
|
147
|
+
and slides in when a link inside it takes focus. */
|
|
148
|
+
.toc[data-toc-mode="dock"] {
|
|
149
|
+
position: fixed;
|
|
150
|
+
inset: auto 0 0;
|
|
151
|
+
z-index: var(--z-sticky);
|
|
152
|
+
inline-size: auto;
|
|
153
|
+
margin: 0;
|
|
154
|
+
padding-block-end: env(safe-area-inset-bottom, 0px);
|
|
155
|
+
/* A hint off the page, so it reads as part of the content: the surface
|
|
156
|
+
tint, one step stronger in dark (the plain surface is 1.07:1 there). */
|
|
157
|
+
--_dock-bg: var(--toc-dock-bg, light-dark(var(--color-surface), var(--color-surface-raised)));
|
|
158
|
+
background-color: var(--_dock-bg);
|
|
159
|
+
border-block-start: var(--border-width) solid var(--color-border);
|
|
160
|
+
translate: 0 100%;
|
|
161
|
+
transition: translate var(--duration-normal) var(--ease-settle);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.toc[data-toc-mode="dock"]:is([data-toc-visible], :has(:focus-visible)) { translate: none; }
|
|
165
|
+
.toc[data-toc-instant] { transition: none; }
|
|
166
|
+
.toc[data-toc-mode="dock"] .toc__fold { border: 0; }
|
|
167
|
+
.toc[data-toc-mode="dock"] .toc__label { display: none; }
|
|
168
|
+
|
|
169
|
+
.toc[data-toc-mode="dock"] ol {
|
|
170
|
+
display: flex;
|
|
171
|
+
margin: 0;
|
|
172
|
+
overflow-x: auto;
|
|
173
|
+
scrollbar-width: none;
|
|
174
|
+
overscroll-behavior-inline: contain;
|
|
175
|
+
padding-inline: 50%;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* The neighbours fade only at the very edge (1.5rem), so a neighbour's
|
|
179
|
+
label keeps its contrast; an overlay, not a mask, because a mask on row
|
|
180
|
+
one would also hide row two, which sits inside it. */
|
|
181
|
+
.toc[data-toc-mode="dock"]::after {
|
|
182
|
+
content: "";
|
|
183
|
+
position: absolute;
|
|
184
|
+
inset: 0;
|
|
185
|
+
pointer-events: none;
|
|
186
|
+
background: linear-gradient(90deg, var(--_dock-bg), transparent 1.5rem calc(100% - 1.5rem), var(--_dock-bg));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* No scroll snap: toc.js centres the rows, and snapping rows cancelled
|
|
190
|
+
the page's own scroll to a #fragment while it loaded (Chromium). */
|
|
191
|
+
.toc[data-toc-mode="dock"] li { flex: none; }
|
|
192
|
+
.toc[data-toc-mode="dock"] li + li { margin: 0; }
|
|
193
|
+
.toc[data-toc-mode="dock"] a {
|
|
194
|
+
--_toc-row: 2.75rem;
|
|
195
|
+
white-space: nowrap;
|
|
196
|
+
padding-inline: var(--space-s);
|
|
197
|
+
border: 0;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.toc[data-toc-mode="dock"] .toc__fold > ol > li > a {
|
|
201
|
+
font: calc(var(--weight-display) + var(--_dark-weight)) var(--step-0) / 1.2 var(--toc-dock-font, var(--font-heading));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/* On a phone a neighbour is cut short with an ellipsis, so both read as
|
|
205
|
+
words either side of the current section (which is never cut).
|
|
206
|
+
toc.js writes --_toc-side, the room left beside the centred entry,
|
|
207
|
+
so a neighbour ends with its ellipsis on screen, never cut at the edge. */
|
|
208
|
+
@media (width < 48rem) {
|
|
209
|
+
.toc[data-toc-mode="dock"] .toc__fold > ol > li:not(:has(a[aria-current])) > a {
|
|
210
|
+
max-inline-size: var(--_toc-side, 34vw);
|
|
211
|
+
overflow: hidden;
|
|
212
|
+
text-overflow: ellipsis;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.toc[data-toc-mode="dock"] li > ol {
|
|
217
|
+
position: absolute;
|
|
218
|
+
inset: auto 0 env(safe-area-inset-bottom, 0px);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/* Row two: the current section's subsections, or those of the section
|
|
222
|
+
that holds keyboard focus (a link a pointer pressed keeps its focus
|
|
223
|
+
but does not count). The others are clipped, not removed. */
|
|
224
|
+
.toc[data-toc-mode="dock"] li:not(:has(a[aria-current])) > ol,
|
|
225
|
+
.toc[data-toc-mode="dock"] .toc__fold:has(a:focus-visible) > ol > li:not(:has(a:focus-visible)) > ol {
|
|
226
|
+
clip-path: inset(50%);
|
|
227
|
+
opacity: 0;
|
|
228
|
+
pointer-events: none;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.toc[data-toc-mode="dock"] .toc__fold > ol > li:has(a:focus-visible) > ol {
|
|
232
|
+
clip-path: none;
|
|
233
|
+
opacity: 1;
|
|
234
|
+
pointer-events: auto;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/* Row two's space is kept whenever any section has subsections, so the
|
|
238
|
+
bar never grows and shrinks between sections. */
|
|
239
|
+
.toc[data-toc-mode="dock"]:has(li > ol) { padding-block-end: calc(2.75rem + env(safe-area-inset-bottom, 0px)); }
|
|
240
|
+
|
|
241
|
+
.toc[data-toc-mode="dock"] :is(li:has(a[aria-current]) > a, a[aria-current]) {
|
|
242
|
+
text-decoration: underline var(--toc-rule, var(--border-width-thick)) var(--toc-active, var(--accent-ink));
|
|
243
|
+
text-underline-offset: 0.35em;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/* The article ends with the section rhythm in every mode (the rail left
|
|
247
|
+
its last line 18px above the next band). */
|
|
248
|
+
.article__body { padding-block-end: var(--space-section); }
|
|
249
|
+
.article__body:has(> .toc[data-toc-mode="dock"]) { padding-block-end: max(var(--space-section), var(--_toc-dock-size, 6rem) + var(--space-m)); }
|
|
250
|
+
/* toc.js writes the dock's measured height; 6rem until it does. */
|
|
251
|
+
:root:has(.toc[data-toc-mode="dock"]) { scroll-padding-block-end: calc(var(--_toc-dock-size, 6rem) + var(--space-s)); }
|
|
252
|
+
|
|
253
|
+
@media print { .toc[data-toc-mode="dock"] { display: none; } }
|
|
254
|
+
}
|
|
@@ -50,14 +50,11 @@
|
|
|
50
50
|
max-inline-size: min(20rem, 90vw);
|
|
51
51
|
padding: var(--space-1-5) var(--space-3);
|
|
52
52
|
border-radius: var(--radius-md);
|
|
53
|
-
box-shadow: var(--shadow-md);
|
|
54
53
|
|
|
55
54
|
/* Hidden state */
|
|
56
55
|
opacity: 0;
|
|
57
|
-
transform: scale(0.95);
|
|
58
56
|
transition:
|
|
59
|
-
opacity var(--duration-fast) var(--ease-fluid)
|
|
60
|
-
transform var(--duration-fast) var(--ease-settle);
|
|
57
|
+
opacity var(--duration-fast) var(--ease-fluid);
|
|
61
58
|
}
|
|
62
59
|
|
|
63
60
|
/* Dark mode tooltip — automatically inverts via semantic tokens above */
|
|
@@ -66,7 +63,6 @@
|
|
|
66
63
|
[data-tooltip]:hover::after,
|
|
67
64
|
[data-tooltip]:focus-visible::after {
|
|
68
65
|
opacity: 1;
|
|
69
|
-
transform: scale(1);
|
|
70
66
|
}
|
|
71
67
|
|
|
72
68
|
|
|
@@ -153,10 +149,8 @@
|
|
|
153
149
|
|
|
154
150
|
/* Hidden by default */
|
|
155
151
|
opacity: 0;
|
|
156
|
-
transform: scale(0.95) translateY(-4px);
|
|
157
152
|
transition:
|
|
158
153
|
opacity var(--duration-fast) var(--ease-fluid),
|
|
159
|
-
transform var(--duration-fast) var(--ease-settle),
|
|
160
154
|
display var(--duration-fast) allow-discrete,
|
|
161
155
|
overlay var(--duration-fast) allow-discrete;
|
|
162
156
|
}
|
|
@@ -165,22 +159,19 @@
|
|
|
165
159
|
.popover:popover-open,
|
|
166
160
|
.popover[data-open] {
|
|
167
161
|
opacity: 1;
|
|
168
|
-
transform: scale(1) translateY(0);
|
|
169
162
|
}
|
|
170
163
|
|
|
171
164
|
/* Starting style for entry animation */
|
|
172
165
|
@starting-style {
|
|
173
166
|
.popover:popover-open {
|
|
174
167
|
opacity: 0;
|
|
175
|
-
transform: scale(0.95) translateY(-4px);
|
|
176
168
|
}
|
|
177
169
|
}
|
|
178
170
|
|
|
179
171
|
.popover__content {
|
|
180
|
-
background: var(--color-
|
|
181
|
-
border: var(--border-width) solid var(--color-border-
|
|
182
|
-
border-radius: var(--radius-
|
|
183
|
-
box-shadow: var(--shadow-lg);
|
|
172
|
+
background: var(--color-background);
|
|
173
|
+
border: var(--border-width) solid var(--color-border-strong);
|
|
174
|
+
border-radius: var(--radius-card);
|
|
184
175
|
padding: var(--space-4);
|
|
185
176
|
min-inline-size: 12rem;
|
|
186
177
|
max-inline-size: 24rem;
|
|
@@ -199,29 +190,6 @@
|
|
|
199
190
|
}
|
|
200
191
|
|
|
201
192
|
|
|
202
|
-
/* ========================================
|
|
203
|
-
THEME-SPECIFIC STYLES
|
|
204
|
-
======================================== */
|
|
205
|
-
|
|
206
|
-
/* Still: no animation */
|
|
207
|
-
[data-motion="still"] [data-tooltip]::after {
|
|
208
|
-
transition: none;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
[data-motion="still"] .popover {
|
|
212
|
-
transition: none;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/* Rapids: hard shadow */
|
|
216
|
-
[data-motion="rapids"] .popover__content {
|
|
217
|
-
box-shadow: var(--shadow-offset);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/* Tsunami: asymmetric */
|
|
221
|
-
[data-motion="tsunami"] .popover__content {
|
|
222
|
-
border-radius: var(--radius-asymmetric, 0 24px 0 0);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
193
|
|
|
226
194
|
/* ========================================
|
|
227
195
|
ACCESSIBILITY
|
|
@@ -234,14 +202,5 @@
|
|
|
234
202
|
}
|
|
235
203
|
}
|
|
236
204
|
|
|
237
|
-
/* Reduced motion: instant show/hide */
|
|
238
|
-
@media (prefers-reduced-motion: reduce) {
|
|
239
|
-
[data-tooltip]::after {
|
|
240
|
-
transition: none;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
.popover {
|
|
244
|
-
transition: none;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
205
|
+
/* Reduced motion: the reset shortens every transition (instant show/hide). */
|
|
247
206
|
}
|