maverick-wave 4.28.0 → 5.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/.claude/settings.local.json +29 -1
- package/.claude/skills/mw-maverick-wave/SKILL.md +39 -24
- package/.claude/skills/mw-maverick-wave/examples/angular-services.md +16 -4
- package/.claude/skills/mw-maverick-wave/examples/static-landing-page.md +13 -4
- package/.claude/skills/mw-maverick-wave/references/components.md +42 -5
- package/.claude/skills/mw-maverick-wave/references/forms.md +14 -2
- package/.claude/skills/mw-maverick-wave/references/javascript.md +17 -4
- package/.claude/skills/mw-maverick-wave/references/layout.md +53 -19
- package/.claude/skills/mw-maverick-wave/references/theming.md +38 -1
- package/.impeccable/config.local.json +5 -0
- package/.impeccable/hook.cache.json +1 -0
- package/CHANGELOG.md +11 -0
- package/CLAUDE.md +5 -5
- package/README.md +48 -4
- package/index.html +19 -38
- package/maverick-wave.min.css +14 -12
- package/maverick-wave.min.js +1 -1
- package/package.json +2 -2
- package/scripts/verify.js +27 -2
- package/src/js/main.js +223 -83
- package/src/partials/accordions-container.html +6 -10
- package/src/partials/alerts-container.html +6 -6
- package/src/partials/announcement-container.html +5 -5
- package/src/partials/avatars-container.html +85 -17
- package/src/partials/badges-container.html +6 -6
- package/src/partials/blog-posts-container.html +11 -12
- package/src/partials/buttons-container.html +3 -3
- package/src/partials/cards-container.html +26 -9
- package/src/partials/code-container.html +5 -5
- package/src/partials/content-slider-container.html +5 -4
- package/src/partials/divider-container.html +7 -7
- package/src/partials/dropdown-container.html +2 -2
- package/src/partials/empty-state-container.html +5 -5
- package/src/partials/footer-container.html +21 -18
- package/src/partials/form-elements-container.html +14 -14
- package/src/partials/gallery-container.html +16 -8
- package/src/partials/get-started-container.html +4 -8
- package/src/partials/header-container.html +18 -7
- package/src/partials/home-container.html +10 -20
- package/src/partials/input-group-container.html +11 -2
- package/src/partials/kbd-container.html +1 -1
- package/src/partials/login-container.html +5 -1
- package/src/partials/media-container.html +2 -2
- package/src/partials/modals-container.html +22 -32
- package/src/partials/pricing-container.html +9 -9
- package/src/partials/skeleton-container.html +6 -6
- package/src/partials/stepper-container.html +2 -2
- package/src/partials/tables-container.html +12 -12
- package/src/partials/tabs-container.html +17 -27
- package/src/partials/tags-container.html +23 -17
- package/src/partials/techstack-bucket-container.html +13 -0
- package/src/partials/tiles-container.html +26 -9
- package/src/partials/typography-container.html +7 -6
- package/src/partials/utilities-container.html +35 -15
- package/src/scss/_layers.scss +10 -0
- package/src/scss/abstracts/_index.scss +6 -0
- package/src/scss/abstracts/_mixins.scss +61 -153
- package/src/scss/abstracts/_variables.scss +123 -319
- package/src/scss/base/_base.scss +170 -190
- package/src/scss/base/_reset.scss +106 -104
- package/src/scss/base/_typography.scss +153 -151
- package/src/scss/components/_accordions.scss +97 -97
- package/src/scss/components/_alerts.scss +71 -70
- package/src/scss/components/_announcement.scss +71 -70
- package/src/scss/components/_avatars.scss +130 -142
- package/src/scss/components/_badge.scss +131 -132
- package/src/scss/components/_blog-post.scss +223 -220
- package/src/scss/components/_breadcrumbs.scss +93 -92
- package/src/scss/components/_button-bar.scss +102 -110
- package/src/scss/components/_buttons.scss +319 -324
- package/src/scss/components/_calendar.scss +251 -252
- package/src/scss/components/_cards.scss +359 -386
- package/src/scss/components/_code.scss +190 -194
- package/src/scss/components/_coming-soon.scss +77 -75
- package/src/scss/components/_content-slider.scss +90 -89
- package/src/scss/components/_divider.scss +55 -53
- package/src/scss/components/_dropdown.scss +179 -185
- package/src/scss/components/_empty-state.scss +57 -57
- package/src/scss/components/_flag.scss +294 -278
- package/src/scss/components/_gallery.scss +131 -133
- package/src/scss/components/_info.scss +151 -167
- package/src/scss/components/_kanban.scss +332 -341
- package/src/scss/components/_kbd.scss +40 -38
- package/src/scss/components/_lang-switch.scss +89 -97
- package/src/scss/components/_links.scss +21 -28
- package/src/scss/components/_lists.scss +510 -514
- package/src/scss/components/_localhost-indicator.scss +26 -24
- package/src/scss/components/_media.scss +22 -20
- package/src/scss/components/_meta-info.scss +35 -33
- package/src/scss/components/_modals.scss +277 -186
- package/src/scss/components/_pagination.scss +81 -87
- package/src/scss/components/_panels.scss +99 -97
- package/src/scss/components/_pricing.scss +183 -241
- package/src/scss/components/_progress.scss +112 -89
- package/src/scss/components/_prose.scss +35 -33
- package/src/scss/components/_ratings.scss +40 -38
- package/src/scss/components/_segmented.scss +82 -84
- package/src/scss/components/_skeleton.scss +66 -72
- package/src/scss/components/_spinners.scss +155 -159
- package/src/scss/components/_stepper.scss +116 -116
- package/src/scss/components/_tables.scss +155 -148
- package/src/scss/components/_tabs.scss +232 -141
- package/src/scss/components/_tags.scss +109 -107
- package/src/scss/components/_techstack-bucket.scss +123 -122
- package/src/scss/components/_testimonial.scss +72 -70
- package/src/scss/components/_theme-toggle.scss +53 -51
- package/src/scss/components/_tiles.scss +174 -174
- package/src/scss/components/_timelines.scss +282 -280
- package/src/scss/components/_toasts.scss +66 -72
- package/src/scss/form-elements/_checkbox.scss +117 -132
- package/src/scss/form-elements/_form.scss +149 -115
- package/src/scss/form-elements/_input-group.scss +99 -103
- package/src/scss/form-elements/_input.scss +74 -74
- package/src/scss/form-elements/_login.scss +48 -48
- package/src/scss/form-elements/_prefilled.scss +53 -51
- package/src/scss/form-elements/_radio.scss +95 -107
- package/src/scss/form-elements/_select.scss +42 -42
- package/src/scss/form-elements/_slider.scss +117 -132
- package/src/scss/form-elements/_textarea.scss +68 -54
- package/src/scss/form-elements/_toggle.scss +127 -140
- package/src/scss/layout/_footer.scss +172 -171
- package/src/scss/layout/_grid.scss +268 -302
- package/src/scss/layout/_header.scss +426 -427
- package/src/scss/layout/_home.scss +28 -27
- package/src/scss/layout/_main.scss +275 -238
- package/src/scss/layout/_page-header.scss +38 -36
- package/src/scss/layout/_section.scss +150 -124
- package/src/scss/main.scss +1 -1
- package/src/scss/utilities/_accessibility.scss +46 -45
- package/src/scss/utilities/_aspect.scss +22 -20
- package/src/scss/utilities/_corner.scss +23 -5
- package/src/scss/utilities/_display.scss +76 -70
- package/src/scss/utilities/_elevation.scss +13 -11
- package/src/scss/utilities/_flex.scss +83 -85
- package/src/scss/utilities/_reveal.scss +40 -63
- package/src/scss/utilities/_spacing.scss +63 -64
- package/src/scss/utilities/_text.scss +139 -141
- package/src/scss/utilities/_touch-targets.scss +130 -147
|
@@ -1,469 +1,442 @@
|
|
|
1
1
|
@use '../abstracts' as *;
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@mixin _card-icon-circle {
|
|
16
|
-
display: flex;
|
|
17
|
-
align-items: center;
|
|
18
|
-
justify-content: center;
|
|
19
|
-
width: 38px;
|
|
20
|
-
height: 38px;
|
|
21
|
-
flex-shrink: 0;
|
|
22
|
-
border-radius: radius('full');
|
|
23
|
-
background: var(--mw-card-addon-color, var(--mw-primary-color));
|
|
24
|
-
color: var(--mw-card-addon-text-color, var(--mw-primary-accent-text-color));
|
|
25
|
-
box-shadow: var(--mw-elevation-2);
|
|
26
|
-
transition: var(--mw-transition);
|
|
27
|
-
overflow: hidden;
|
|
28
|
-
|
|
29
|
-
img {
|
|
30
|
-
width: 100%;
|
|
31
|
-
height: 100%;
|
|
32
|
-
object-fit: cover;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Fading rule used by the title divider and the stack header underline
|
|
37
|
-
@mixin _card-divider-gradient {
|
|
38
|
-
background-image: linear-gradient(
|
|
39
|
-
to right,
|
|
40
|
-
var(--mw-secondary-text-color),
|
|
41
|
-
var(--mw-secondary-text-color),
|
|
42
|
-
var(--mw-gray-background),
|
|
43
|
-
transparent
|
|
44
|
-
);
|
|
45
|
-
opacity: 0.75;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
.mw-card {
|
|
49
|
-
// flex column so the footer can be pushed to the bottom - no height: 100%,
|
|
50
|
-
// grid and flex items already stretch and it would blow up block parents
|
|
51
|
-
display: flex;
|
|
52
|
-
flex-direction: column;
|
|
53
|
-
background: var(--mw-card-background);
|
|
54
|
-
@include surface;
|
|
55
|
-
box-shadow: var(--mw-elevation-2);
|
|
56
|
-
border: 1px solid var(--mw-border);
|
|
57
|
-
transition: var(--mw-transition);
|
|
58
|
-
// deliberately not `overflow: hidden` - that would also cut off anything a
|
|
59
|
-
// child wants to show outside the card, a tooltip above a button being the
|
|
60
|
-
// common case. Images round their own corners below, and only the ribbon
|
|
61
|
-
// really needs the card to clip.
|
|
62
|
-
overflow: visible;
|
|
63
|
-
|
|
64
|
-
// Direct child only - a card nested inside another one must not clip its host
|
|
65
|
-
&:has(> .mw-card-ribbon) {
|
|
66
|
-
overflow: hidden;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Query container for the footer below. Named, so the query cannot resolve to
|
|
70
|
-
// a project's own container further up the tree.
|
|
71
|
-
//
|
|
72
|
-
// Only cards that have a footer, and they claim their slot: inline-size
|
|
73
|
-
// containment computes the card's own width as if it were empty, so a card
|
|
74
|
-
// that takes its width from its content - a flex row, `mw-grid-stack`, a
|
|
75
|
-
// timeline wrapper - would collapse to its border. Filling the slot keeps the
|
|
76
|
-
// width external, which is what makes it queryable in the first place.
|
|
77
|
-
&:has(.mw-card-footer) {
|
|
78
|
-
width: 100%;
|
|
79
|
-
container: mw-card / inline-size;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
&:hover {
|
|
83
|
-
box-shadow: var(--mw-elevation-3);
|
|
84
|
-
border-color: var(--mw-border-accent);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// The lift moves the box, so it is guarded: on touch `:hover` latches after a
|
|
88
|
-
// tap and the card stays raised, visibly out of line with the row it sits in.
|
|
89
|
-
// The colour and shadow below are not - a latched border reads as "the one you
|
|
90
|
-
// last touched", which is no worse than nothing.
|
|
91
|
-
@include hover {
|
|
92
|
-
transform: translateY(-2px);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Padded surface for arbitrary content - stays a block container so inline
|
|
96
|
-
// children keep flowing instead of turning into flex items
|
|
97
|
-
&-simple {
|
|
98
|
-
display: block;
|
|
99
|
-
padding: spacing('5');
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
&-badge {
|
|
103
|
-
position: absolute;
|
|
104
|
-
top: spacing('2');
|
|
105
|
-
right: spacing('4');
|
|
106
|
-
padding: spacing('1') spacing('4');
|
|
107
|
-
font-size: font-size('xs');
|
|
108
|
-
color: var(--mw-card-addon-text-color, var(--mw-primary-accent-text-color));
|
|
3
|
+
@layer mw.components {
|
|
4
|
+
// Round icon badge - shared by the title icon and the stack header icon.
|
|
5
|
+
// Font size stays with the callers: the stack tile is compact and wants a
|
|
6
|
+
// smaller glyph than a full card title.
|
|
7
|
+
@mixin _card-icon-circle {
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
width: 38px;
|
|
12
|
+
height: 38px;
|
|
13
|
+
flex-shrink: 0;
|
|
14
|
+
border-radius: radius('full');
|
|
109
15
|
background: var(--mw-card-addon-color, var(--mw-primary-color));
|
|
110
|
-
border-radius: radius('md');
|
|
111
|
-
white-space: nowrap;
|
|
112
|
-
z-index: 1;
|
|
113
|
-
pointer-events: none;
|
|
114
|
-
text-align: center;
|
|
115
|
-
opacity: 0.9;
|
|
116
|
-
font-weight: font-weight('medium');
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
&-ribbon {
|
|
120
|
-
position: absolute;
|
|
121
|
-
top: 20px;
|
|
122
|
-
right: -35px;
|
|
123
|
-
padding: spacing('1') spacing('4');
|
|
124
|
-
font-size: font-size('xs');
|
|
125
16
|
color: var(--mw-card-addon-text-color, var(--mw-primary-accent-text-color));
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
width: 220px;
|
|
129
|
-
z-index: 1;
|
|
130
|
-
pointer-events: none;
|
|
131
|
-
transform: rotate(25deg);
|
|
132
|
-
text-align: center;
|
|
133
|
-
opacity: 0.8;
|
|
134
|
-
font-weight: font-weight('medium');
|
|
135
|
-
@include media-down('sm') {
|
|
136
|
-
font-size: font-size('2xs');
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
&-img,
|
|
141
|
-
&-img-contain {
|
|
142
|
-
height: var(--mw-card-img-height, 210px);
|
|
17
|
+
box-shadow: var(--mw-elevation-2);
|
|
18
|
+
transition: var(--mw-transition);
|
|
143
19
|
overflow: hidden;
|
|
144
|
-
flex-shrink: 0;
|
|
145
|
-
border-radius: (radius('sm') - 1px) (radius('xl') - 1px) 0 0;
|
|
146
20
|
|
|
147
21
|
img {
|
|
148
22
|
width: 100%;
|
|
149
23
|
height: 100%;
|
|
150
24
|
object-fit: cover;
|
|
151
|
-
transition: transform var(--mw-duration-zoom) var(--mw-ease-out);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
&:hover img {
|
|
155
|
-
transform: scale(1.05);
|
|
156
25
|
}
|
|
157
26
|
}
|
|
158
27
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
&-xl {
|
|
173
|
-
--mw-card-img-height: 480px;
|
|
174
|
-
|
|
175
|
-
@include media-down('sm') {
|
|
176
|
-
--mw-card-img-height: 340px;
|
|
177
|
-
}
|
|
28
|
+
// Fading rule used by the title divider and the stack header underline
|
|
29
|
+
@mixin _card-divider-gradient {
|
|
30
|
+
background-image: linear-gradient(
|
|
31
|
+
to right,
|
|
32
|
+
var(--mw-secondary-text-color),
|
|
33
|
+
var(--mw-secondary-text-color),
|
|
34
|
+
var(--mw-gray-background),
|
|
35
|
+
transparent
|
|
36
|
+
);
|
|
37
|
+
opacity: 0.75;
|
|
178
38
|
}
|
|
179
39
|
|
|
180
|
-
|
|
40
|
+
.mw-card {
|
|
41
|
+
// flex column so the footer can be pushed to the bottom - no height: 100%,
|
|
42
|
+
// grid and flex items already stretch and it would blow up block parents
|
|
181
43
|
display: flex;
|
|
182
44
|
flex-direction: column;
|
|
183
|
-
|
|
184
|
-
|
|
45
|
+
background: var(--mw-card-background);
|
|
46
|
+
@include surface;
|
|
47
|
+
box-shadow: var(--mw-elevation-2);
|
|
48
|
+
border: 1px solid var(--mw-border);
|
|
49
|
+
transition: var(--mw-transition);
|
|
50
|
+
// deliberately not `overflow: hidden` - that would also cut off anything a
|
|
51
|
+
// child wants to show outside the card, a tooltip above a button being the
|
|
52
|
+
// common case. Images round their own corners below, and only the ribbon
|
|
53
|
+
// really needs the card to clip.
|
|
54
|
+
overflow: visible;
|
|
55
|
+
|
|
56
|
+
// Direct child only - a card nested inside another one must not clip its host
|
|
57
|
+
&:has(> .mw-card-ribbon) {
|
|
58
|
+
overflow: hidden;
|
|
59
|
+
}
|
|
185
60
|
|
|
186
|
-
|
|
187
|
-
|
|
61
|
+
// Named, so the query cannot resolve to a container further up the tree. Only
|
|
62
|
+
// cards with a footer, and they claim their slot: inline-size containment
|
|
63
|
+
// computes the width as if the card were empty, so one that sizes to its
|
|
64
|
+
// content would collapse to its border.
|
|
65
|
+
&:has(.mw-card-footer) {
|
|
66
|
+
width: 100%;
|
|
67
|
+
container: mw-card / inline-size;
|
|
188
68
|
}
|
|
189
69
|
|
|
190
|
-
|
|
191
|
-
|
|
70
|
+
// The arc on the two round corners is the one mark that makes a card look
|
|
71
|
+
// like this framework and not like a rounded box, so it is what the hover
|
|
72
|
+
// pulls on. Recoloured through the token the mixin already reads, which is
|
|
73
|
+
// why the rule sits on the card and not on its ::after.
|
|
74
|
+
&::after {
|
|
75
|
+
transition: var(--mw-transition);
|
|
192
76
|
}
|
|
193
77
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
78
|
+
&:hover {
|
|
79
|
+
box-shadow: var(--mw-elevation-3);
|
|
80
|
+
border-color: var(--mw-border-accent);
|
|
81
|
+
--mw-corner-accent: var(--mw-corner-accent-hover);
|
|
197
82
|
}
|
|
198
|
-
}
|
|
199
83
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
84
|
+
// The lift moves the box, so it is guarded: on touch `:hover` latches after a
|
|
85
|
+
// tap and the card stays raised, visibly out of line with the row it sits in.
|
|
86
|
+
// The colour and shadow below are not - a latched border reads as "the one you
|
|
87
|
+
// last touched", which is no worse than nothing.
|
|
88
|
+
@include hover {
|
|
89
|
+
transform: translateY(-2px);
|
|
205
90
|
}
|
|
206
91
|
|
|
207
|
-
//
|
|
208
|
-
//
|
|
209
|
-
|
|
210
|
-
display:
|
|
211
|
-
|
|
212
|
-
gap: spacing('4');
|
|
92
|
+
// Padded surface for arbitrary content - stays a block container so inline
|
|
93
|
+
// children keep flowing instead of turning into flex items
|
|
94
|
+
&-simple {
|
|
95
|
+
display: block;
|
|
96
|
+
padding: spacing('5');
|
|
213
97
|
}
|
|
214
|
-
}
|
|
215
98
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
99
|
+
&-badge {
|
|
100
|
+
position: absolute;
|
|
101
|
+
top: spacing('2');
|
|
102
|
+
right: spacing('4');
|
|
103
|
+
padding: spacing('1') spacing('4');
|
|
104
|
+
font-size: font-size('xs');
|
|
105
|
+
color: var(
|
|
106
|
+
--mw-card-addon-text-color,
|
|
107
|
+
var(--mw-primary-accent-text-color)
|
|
108
|
+
);
|
|
109
|
+
background: var(--mw-card-addon-color, var(--mw-primary-color));
|
|
110
|
+
border-radius: radius('md');
|
|
111
|
+
white-space: nowrap;
|
|
112
|
+
z-index: 1;
|
|
113
|
+
pointer-events: none;
|
|
114
|
+
text-align: center;
|
|
115
|
+
opacity: 0.9;
|
|
116
|
+
font-weight: font-weight('medium');
|
|
117
|
+
}
|
|
229
118
|
|
|
230
|
-
&-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
119
|
+
&-ribbon {
|
|
120
|
+
position: absolute;
|
|
121
|
+
top: 20px;
|
|
122
|
+
right: -35px;
|
|
123
|
+
padding: spacing('1') spacing('4');
|
|
124
|
+
font-size: font-size('2xs');
|
|
125
|
+
color: var(
|
|
126
|
+
--mw-card-addon-text-color,
|
|
127
|
+
var(--mw-primary-accent-text-color)
|
|
128
|
+
);
|
|
129
|
+
background: var(--mw-card-addon-color, var(--mw-primary-color));
|
|
130
|
+
white-space: nowrap;
|
|
131
|
+
width: 220px;
|
|
132
|
+
z-index: 1;
|
|
133
|
+
pointer-events: none;
|
|
134
|
+
transform: rotate(25deg);
|
|
135
|
+
text-align: center;
|
|
136
|
+
opacity: 0.8;
|
|
137
|
+
font-weight: font-weight('medium');
|
|
138
|
+
@include media-up('sm') {
|
|
139
|
+
font-size: font-size('xs');
|
|
140
|
+
}
|
|
234
141
|
}
|
|
235
|
-
}
|
|
236
142
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
143
|
+
&-img,
|
|
144
|
+
&-img-contain {
|
|
145
|
+
height: var(--mw-card-img-height, 210px);
|
|
146
|
+
overflow: hidden;
|
|
147
|
+
flex-shrink: 0;
|
|
148
|
+
border-radius: (radius('sm') - 1px) (radius('xl') - 1px) 0 0;
|
|
244
149
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
150
|
+
img {
|
|
151
|
+
width: 100%;
|
|
152
|
+
height: 100%;
|
|
153
|
+
object-fit: cover;
|
|
154
|
+
transition: transform var(--mw-duration-zoom) var(--mw-ease-out);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
&:hover img {
|
|
158
|
+
transform: scale(1.05);
|
|
159
|
+
}
|
|
253
160
|
}
|
|
254
|
-
}
|
|
255
161
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
@include media-down('sm') {
|
|
260
|
-
margin-bottom: spacing('2');
|
|
162
|
+
&-img-contain img {
|
|
163
|
+
object-fit: contain;
|
|
164
|
+
object-position: center;
|
|
261
165
|
}
|
|
262
|
-
}
|
|
263
166
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
justify-content: flex-start;
|
|
267
|
-
// centered, so plain text next to a button sits on the button's centre
|
|
268
|
-
// line instead of being stretched to its height and starting at the top
|
|
269
|
-
align-items: center;
|
|
270
|
-
// Buttons do not shrink, so two that no longer fit have to wrap - without
|
|
271
|
-
// this they leave the card sideways
|
|
272
|
-
flex-wrap: wrap;
|
|
273
|
-
gap: spacing('3');
|
|
274
|
-
flex-shrink: 0;
|
|
275
|
-
text-wrap: balance;
|
|
167
|
+
&-lg {
|
|
168
|
+
--mw-card-img-height: 260px;
|
|
276
169
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
text-align: right;
|
|
170
|
+
@include media-up('sm') {
|
|
171
|
+
--mw-card-img-height: 340px;
|
|
172
|
+
}
|
|
281
173
|
}
|
|
282
174
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
175
|
+
&-xl {
|
|
176
|
+
--mw-card-img-height: 340px;
|
|
177
|
+
|
|
178
|
+
@include media-up('sm') {
|
|
179
|
+
--mw-card-img-height: 480px;
|
|
180
|
+
}
|
|
286
181
|
}
|
|
287
182
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
// phone and used to keep its actions in a cramped row anyway.
|
|
291
|
-
@container mw-card (max-width: #{$mw-card-narrow}) {
|
|
183
|
+
&-body {
|
|
184
|
+
display: flex;
|
|
292
185
|
flex-direction: column;
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
&:has(.mw-actions-note),
|
|
299
|
-
&:has(.mw-form-actions-hint) {
|
|
300
|
-
flex-wrap: nowrap;
|
|
186
|
+
flex-grow: 1;
|
|
187
|
+
padding: spacing('6') spacing('4') spacing('5');
|
|
188
|
+
|
|
189
|
+
@include media-up('sm') {
|
|
190
|
+
padding: spacing('7') spacing('5') spacing('6');
|
|
301
191
|
}
|
|
302
192
|
|
|
303
|
-
.mw-
|
|
304
|
-
|
|
305
|
-
flex: 0 0 auto;
|
|
306
|
-
text-align: left;
|
|
193
|
+
> *:last-child:not(.mw-card-footer) {
|
|
194
|
+
margin-bottom: spacing('0');
|
|
307
195
|
}
|
|
308
196
|
|
|
309
|
-
|
|
310
|
-
|
|
197
|
+
.mw-card-footer {
|
|
198
|
+
margin-top: auto;
|
|
199
|
+
padding-top: spacing('5');
|
|
311
200
|
}
|
|
201
|
+
}
|
|
312
202
|
|
|
313
|
-
|
|
203
|
+
&-title {
|
|
204
|
+
margin-bottom: spacing('3');
|
|
205
|
+
font-size: font-size('lg');
|
|
206
|
+
@include media-up('md') {
|
|
207
|
+
font-size: font-size('xl');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Only with an icon - a plain title stays a block, so a long one keeps
|
|
211
|
+
// wrapping the way a heading is expected to
|
|
212
|
+
&:has(> .mw-card-title-icon) {
|
|
314
213
|
display: flex;
|
|
315
214
|
align-items: center;
|
|
316
|
-
|
|
215
|
+
gap: spacing('4');
|
|
317
216
|
}
|
|
318
217
|
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
&-stack {
|
|
322
|
-
padding: spacing('4') spacing('5');
|
|
323
218
|
|
|
324
|
-
|
|
219
|
+
// Colour comes from mw-card-addon-* on the card, like the badge and the ribbon.
|
|
220
|
+
// An <img> works in the same slot - reach for -lg there, a wordmark inside
|
|
221
|
+
// 38px is a smudge.
|
|
222
|
+
&-title-icon {
|
|
325
223
|
@include _card-icon-circle;
|
|
326
|
-
|
|
327
|
-
|
|
224
|
+
font-size: font-size('lg');
|
|
225
|
+
|
|
226
|
+
&-lg {
|
|
227
|
+
width: 62px;
|
|
228
|
+
height: 62px;
|
|
229
|
+
font-size: font-size('2xl');
|
|
230
|
+
}
|
|
328
231
|
}
|
|
329
232
|
|
|
330
|
-
|
|
331
|
-
|
|
233
|
+
&-title-divider {
|
|
234
|
+
height: 4px;
|
|
235
|
+
margin: spacing('1') spacing('0') spacing('4') spacing('0');
|
|
236
|
+
border: 0;
|
|
237
|
+
width: 70%;
|
|
238
|
+
@include _card-divider-gradient;
|
|
332
239
|
}
|
|
333
240
|
|
|
334
|
-
&-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
bottom: spacing('-3');
|
|
343
|
-
left: 50%;
|
|
344
|
-
transform: translateX(-50%);
|
|
345
|
-
width: 90%;
|
|
346
|
-
height: 2px;
|
|
347
|
-
@include _card-divider-gradient;
|
|
241
|
+
&-subtitle {
|
|
242
|
+
margin-bottom: spacing('2');
|
|
243
|
+
font-size: font-size('md');
|
|
244
|
+
line-height: 1.2;
|
|
245
|
+
font-style: italic;
|
|
246
|
+
color: var(--mw-text-muted-color);
|
|
247
|
+
@include media-up('md') {
|
|
248
|
+
margin-bottom: spacing('3');
|
|
348
249
|
}
|
|
349
250
|
}
|
|
350
251
|
|
|
351
|
-
&-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
justify-content: center;
|
|
355
|
-
margin: spacing('0');
|
|
356
|
-
|
|
252
|
+
&-text {
|
|
253
|
+
margin: spacing('2') spacing('0') spacing('4') spacing('0');
|
|
254
|
+
color: var(--mw-text-color);
|
|
357
255
|
@include media-down('sm') {
|
|
358
|
-
|
|
256
|
+
margin-bottom: spacing('2');
|
|
359
257
|
}
|
|
360
258
|
}
|
|
361
259
|
|
|
362
|
-
&-
|
|
260
|
+
&-footer {
|
|
363
261
|
display: flex;
|
|
364
|
-
|
|
365
|
-
|
|
262
|
+
justify-content: flex-start;
|
|
263
|
+
// centered, so plain text next to a button sits on the button's centre
|
|
264
|
+
// line instead of being stretched to its height and starting at the top
|
|
265
|
+
align-items: center;
|
|
266
|
+
// Buttons do not shrink, so two that no longer fit have to wrap - without
|
|
267
|
+
// this they leave the card sideways
|
|
268
|
+
flex-wrap: wrap;
|
|
269
|
+
gap: spacing('3');
|
|
270
|
+
flex-shrink: 0;
|
|
271
|
+
text-wrap: balance;
|
|
272
|
+
|
|
273
|
+
/* push the last element all the way right - a single one included */
|
|
274
|
+
> *:last-child {
|
|
275
|
+
margin-left: auto;
|
|
276
|
+
text-align: right;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Ensure buttons maintain their size
|
|
280
|
+
.mw-btn {
|
|
281
|
+
flex-shrink: 0;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Stacked once the card is narrow, not once the window is - a card in a
|
|
285
|
+
// three-column grid on a wide desktop is as narrow as the same card on a
|
|
286
|
+
// phone and used to keep its actions in a cramped row anyway.
|
|
287
|
+
@container mw-card (max-width: #{$mw-card-narrow}) {
|
|
288
|
+
flex-direction: column;
|
|
289
|
+
align-items: stretch;
|
|
290
|
+
gap: spacing('2');
|
|
291
|
+
|
|
292
|
+
// `flex: 1 0 100%` on the note is 100% of the *height* in a column: it
|
|
293
|
+
// fills the column and the buttons wrap out of the card sideways
|
|
294
|
+
&:has(.mw-actions-note),
|
|
295
|
+
&:has(.mw-form-actions-hint) {
|
|
296
|
+
flex-wrap: nowrap;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.mw-actions-note,
|
|
300
|
+
.mw-form-actions-hint {
|
|
301
|
+
flex: 0 0 auto;
|
|
302
|
+
text-align: left;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
> * {
|
|
306
|
+
width: 100%;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.mw-btn {
|
|
310
|
+
display: flex;
|
|
311
|
+
align-items: center;
|
|
312
|
+
justify-content: center;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
366
315
|
}
|
|
367
316
|
|
|
368
|
-
&-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
317
|
+
&-stack {
|
|
318
|
+
padding: spacing('4') spacing('5');
|
|
319
|
+
|
|
320
|
+
&-icon {
|
|
321
|
+
@include _card-icon-circle;
|
|
322
|
+
margin-right: spacing('2');
|
|
323
|
+
font-size: font-size('md');
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
&:hover &-icon {
|
|
327
|
+
transform: rotate(25deg);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
&-header {
|
|
331
|
+
display: flex;
|
|
332
|
+
align-items: center;
|
|
333
|
+
position: relative;
|
|
334
|
+
|
|
335
|
+
&:after {
|
|
336
|
+
content: '';
|
|
337
|
+
position: absolute;
|
|
338
|
+
bottom: spacing('-3');
|
|
339
|
+
left: 50%;
|
|
340
|
+
transform: translateX(-50%);
|
|
341
|
+
width: 90%;
|
|
342
|
+
height: 2px;
|
|
343
|
+
@include _card-divider-gradient;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
&-title {
|
|
348
|
+
display: flex;
|
|
349
|
+
align-items: center;
|
|
350
|
+
justify-content: center;
|
|
351
|
+
margin: spacing('0');
|
|
352
|
+
|
|
353
|
+
@include media-down('sm') {
|
|
354
|
+
font-size: font-size('sm');
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
&-body {
|
|
359
|
+
display: flex;
|
|
360
|
+
flex-direction: column;
|
|
361
|
+
padding-top: spacing('5');
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
&-text {
|
|
365
|
+
margin-top: spacing('2');
|
|
366
|
+
color: var(--mw-text-color);
|
|
367
|
+
font-size: font-size('sm');
|
|
368
|
+
}
|
|
372
369
|
}
|
|
373
370
|
}
|
|
374
|
-
}
|
|
375
371
|
|
|
376
|
-
// Frame
|
|
377
|
-
//
|
|
378
|
-
//
|
|
379
|
-
//
|
|
380
|
-
//
|
|
381
|
-
//
|
|
382
|
-
// the grid gap.
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
// <p class="mw-card-feature-label">Most booked</p>
|
|
386
|
-
// <div class="mw-card">…</div>
|
|
387
|
-
// </div>
|
|
388
|
-
//
|
|
389
|
-
// Primary out of the box, `mw-card-feature-secondary` and
|
|
390
|
-
// `mw-card-feature-info` swap the colour.
|
|
391
|
-
//
|
|
392
|
-
// Geometry: 22px bar, 6px gap between frame and card, 1px border. The bar
|
|
393
|
-
// height is fixed and the margins count on it - a two-line label needs the
|
|
394
|
-
// margin and the padding raised with it. It is kept low on purpose: every
|
|
395
|
-
// pixel of bar is a pixel the grid below has to add to its row gap.
|
|
396
|
-
.mw-card-feature {
|
|
397
|
-
position: relative;
|
|
398
|
-
display: flex;
|
|
399
|
-
flex-direction: column;
|
|
400
|
-
margin: -29px -7px -7px;
|
|
401
|
-
padding: 28px 6px 6px;
|
|
402
|
-
border: 1px solid var(--mw-primary-color);
|
|
403
|
-
border-radius: 12px 27px 12px 27px;
|
|
404
|
-
|
|
405
|
-
&-label {
|
|
406
|
-
position: absolute;
|
|
407
|
-
inset: 0 0 auto;
|
|
372
|
+
// Frame and bar wrapped *around* a card, growing outwards into the grid gap, so
|
|
373
|
+
// the card keeps the size and look of its neighbours. mw-card-badge sits inside
|
|
374
|
+
// the body instead and overlaps the title on a narrow card.
|
|
375
|
+
//
|
|
376
|
+
// Geometry: 22px bar, 6px gap, 1px border. The bar height is fixed and the
|
|
377
|
+
// margins count on it, so a two-line label needs both raised - and every pixel
|
|
378
|
+
// of bar is one the grid has to add to its row gap.
|
|
379
|
+
.mw-card-feature {
|
|
380
|
+
position: relative;
|
|
408
381
|
display: flex;
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
382
|
+
flex-direction: column;
|
|
383
|
+
margin: -29px -7px -7px;
|
|
384
|
+
padding: 28px 6px 6px;
|
|
385
|
+
border: 1px solid var(--mw-primary-color);
|
|
386
|
+
border-radius: 12px 27px 12px 27px;
|
|
387
|
+
|
|
388
|
+
&-label {
|
|
389
|
+
position: absolute;
|
|
390
|
+
inset: 0 0 auto;
|
|
391
|
+
display: flex;
|
|
392
|
+
align-items: center;
|
|
393
|
+
justify-content: center;
|
|
394
|
+
height: 22px;
|
|
395
|
+
margin: 0;
|
|
396
|
+
padding-inline: spacing('4');
|
|
397
|
+
border-radius: 11px 26px 0 0;
|
|
398
|
+
background: var(--mw-primary-color);
|
|
399
|
+
color: var(--mw-primary-accent-text-color);
|
|
400
|
+
font-size: font-size('2xs');
|
|
401
|
+
font-weight: font-weight('bold');
|
|
402
|
+
letter-spacing: 0.06em;
|
|
403
|
+
text-transform: uppercase;
|
|
404
|
+
@include truncate;
|
|
405
|
+
}
|
|
425
406
|
|
|
426
|
-
|
|
427
|
-
|
|
407
|
+
> .mw-card {
|
|
408
|
+
flex: 1;
|
|
409
|
+
}
|
|
428
410
|
}
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
[class*='mw-grid-']:has(> .mw-card-feature) {
|
|
432
|
-
row-gap: 48px;
|
|
433
|
-
}
|
|
434
411
|
|
|
435
|
-
// Colour variants - primary is the default above, these two override it
|
|
436
|
-
@each $name in ('secondary', 'info') {
|
|
437
|
-
|
|
438
|
-
|
|
412
|
+
// Colour variants - primary is the default above, these two override it
|
|
413
|
+
@each $name in ('secondary', 'info') {
|
|
414
|
+
.mw-card-feature-#{$name} {
|
|
415
|
+
border-color: var(--mw-#{$name}-color);
|
|
439
416
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
417
|
+
> .mw-card-feature-label {
|
|
418
|
+
background: var(--mw-#{$name}-color);
|
|
419
|
+
color: var(--mw-#{$name}-accent-text-color);
|
|
420
|
+
}
|
|
443
421
|
}
|
|
444
422
|
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
@each $name, $col in $_mw-card-addon-colors {
|
|
448
|
-
.mw-card-addon-#{$name} {
|
|
449
|
-
--mw-card-addon-color: #{$col};
|
|
450
|
-
--mw-card-addon-text-color: var(--mw-#{$name}-accent-text-color);
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
423
|
|
|
454
|
-
@
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
.mw-card-stack-icon {
|
|
460
|
-
transition: none;
|
|
424
|
+
@each $name, $col in $semantic-colors {
|
|
425
|
+
.mw-card-addon-#{$name} {
|
|
426
|
+
--mw-card-addon-color: #{$col};
|
|
427
|
+
--mw-card-addon-text-color: var(--mw-#{$name}-accent-text-color);
|
|
428
|
+
}
|
|
461
429
|
}
|
|
462
430
|
|
|
463
|
-
.
|
|
464
|
-
.
|
|
465
|
-
.
|
|
466
|
-
|
|
467
|
-
|
|
431
|
+
// Only the movement. The durations are already pinned to 1ms globally in
|
|
432
|
+
// base/_base.scss; a hover that *travels* has to be taken away outright, or it
|
|
433
|
+
// still jumps to its lifted position in one frame.
|
|
434
|
+
@media (prefers-reduced-motion: reduce) {
|
|
435
|
+
.mw-card:hover,
|
|
436
|
+
.mw-card-img:hover img,
|
|
437
|
+
.mw-card-img-contain:hover img,
|
|
438
|
+
.mw-card-stack:hover .mw-card-stack-icon {
|
|
439
|
+
transform: none;
|
|
440
|
+
}
|
|
468
441
|
}
|
|
469
442
|
}
|