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.
Files changed (138) hide show
  1. package/.claude/settings.local.json +29 -1
  2. package/.claude/skills/mw-maverick-wave/SKILL.md +39 -24
  3. package/.claude/skills/mw-maverick-wave/examples/angular-services.md +16 -4
  4. package/.claude/skills/mw-maverick-wave/examples/static-landing-page.md +13 -4
  5. package/.claude/skills/mw-maverick-wave/references/components.md +42 -5
  6. package/.claude/skills/mw-maverick-wave/references/forms.md +14 -2
  7. package/.claude/skills/mw-maverick-wave/references/javascript.md +17 -4
  8. package/.claude/skills/mw-maverick-wave/references/layout.md +53 -19
  9. package/.claude/skills/mw-maverick-wave/references/theming.md +38 -1
  10. package/.impeccable/config.local.json +5 -0
  11. package/.impeccable/hook.cache.json +1 -0
  12. package/CHANGELOG.md +11 -0
  13. package/CLAUDE.md +5 -5
  14. package/README.md +48 -4
  15. package/index.html +19 -38
  16. package/maverick-wave.min.css +14 -12
  17. package/maverick-wave.min.js +1 -1
  18. package/package.json +2 -2
  19. package/scripts/verify.js +27 -2
  20. package/src/js/main.js +223 -83
  21. package/src/partials/accordions-container.html +6 -10
  22. package/src/partials/alerts-container.html +6 -6
  23. package/src/partials/announcement-container.html +5 -5
  24. package/src/partials/avatars-container.html +85 -17
  25. package/src/partials/badges-container.html +6 -6
  26. package/src/partials/blog-posts-container.html +11 -12
  27. package/src/partials/buttons-container.html +3 -3
  28. package/src/partials/cards-container.html +26 -9
  29. package/src/partials/code-container.html +5 -5
  30. package/src/partials/content-slider-container.html +5 -4
  31. package/src/partials/divider-container.html +7 -7
  32. package/src/partials/dropdown-container.html +2 -2
  33. package/src/partials/empty-state-container.html +5 -5
  34. package/src/partials/footer-container.html +21 -18
  35. package/src/partials/form-elements-container.html +14 -14
  36. package/src/partials/gallery-container.html +16 -8
  37. package/src/partials/get-started-container.html +4 -8
  38. package/src/partials/header-container.html +18 -7
  39. package/src/partials/home-container.html +10 -20
  40. package/src/partials/input-group-container.html +11 -2
  41. package/src/partials/kbd-container.html +1 -1
  42. package/src/partials/login-container.html +5 -1
  43. package/src/partials/media-container.html +2 -2
  44. package/src/partials/modals-container.html +22 -32
  45. package/src/partials/pricing-container.html +9 -9
  46. package/src/partials/skeleton-container.html +6 -6
  47. package/src/partials/stepper-container.html +2 -2
  48. package/src/partials/tables-container.html +12 -12
  49. package/src/partials/tabs-container.html +17 -27
  50. package/src/partials/tags-container.html +23 -17
  51. package/src/partials/techstack-bucket-container.html +13 -0
  52. package/src/partials/tiles-container.html +26 -9
  53. package/src/partials/typography-container.html +7 -6
  54. package/src/partials/utilities-container.html +35 -15
  55. package/src/scss/_layers.scss +10 -0
  56. package/src/scss/abstracts/_index.scss +6 -0
  57. package/src/scss/abstracts/_mixins.scss +61 -153
  58. package/src/scss/abstracts/_variables.scss +123 -319
  59. package/src/scss/base/_base.scss +170 -190
  60. package/src/scss/base/_reset.scss +106 -104
  61. package/src/scss/base/_typography.scss +153 -151
  62. package/src/scss/components/_accordions.scss +97 -97
  63. package/src/scss/components/_alerts.scss +71 -70
  64. package/src/scss/components/_announcement.scss +71 -70
  65. package/src/scss/components/_avatars.scss +130 -142
  66. package/src/scss/components/_badge.scss +131 -132
  67. package/src/scss/components/_blog-post.scss +223 -220
  68. package/src/scss/components/_breadcrumbs.scss +93 -92
  69. package/src/scss/components/_button-bar.scss +102 -110
  70. package/src/scss/components/_buttons.scss +319 -324
  71. package/src/scss/components/_calendar.scss +251 -252
  72. package/src/scss/components/_cards.scss +359 -386
  73. package/src/scss/components/_code.scss +190 -194
  74. package/src/scss/components/_coming-soon.scss +77 -75
  75. package/src/scss/components/_content-slider.scss +90 -89
  76. package/src/scss/components/_divider.scss +55 -53
  77. package/src/scss/components/_dropdown.scss +179 -185
  78. package/src/scss/components/_empty-state.scss +57 -57
  79. package/src/scss/components/_flag.scss +294 -278
  80. package/src/scss/components/_gallery.scss +131 -133
  81. package/src/scss/components/_info.scss +151 -167
  82. package/src/scss/components/_kanban.scss +332 -341
  83. package/src/scss/components/_kbd.scss +40 -38
  84. package/src/scss/components/_lang-switch.scss +89 -97
  85. package/src/scss/components/_links.scss +21 -28
  86. package/src/scss/components/_lists.scss +510 -514
  87. package/src/scss/components/_localhost-indicator.scss +26 -24
  88. package/src/scss/components/_media.scss +22 -20
  89. package/src/scss/components/_meta-info.scss +35 -33
  90. package/src/scss/components/_modals.scss +277 -186
  91. package/src/scss/components/_pagination.scss +81 -87
  92. package/src/scss/components/_panels.scss +99 -97
  93. package/src/scss/components/_pricing.scss +183 -241
  94. package/src/scss/components/_progress.scss +112 -89
  95. package/src/scss/components/_prose.scss +35 -33
  96. package/src/scss/components/_ratings.scss +40 -38
  97. package/src/scss/components/_segmented.scss +82 -84
  98. package/src/scss/components/_skeleton.scss +66 -72
  99. package/src/scss/components/_spinners.scss +155 -159
  100. package/src/scss/components/_stepper.scss +116 -116
  101. package/src/scss/components/_tables.scss +155 -148
  102. package/src/scss/components/_tabs.scss +232 -141
  103. package/src/scss/components/_tags.scss +109 -107
  104. package/src/scss/components/_techstack-bucket.scss +123 -122
  105. package/src/scss/components/_testimonial.scss +72 -70
  106. package/src/scss/components/_theme-toggle.scss +53 -51
  107. package/src/scss/components/_tiles.scss +174 -174
  108. package/src/scss/components/_timelines.scss +282 -280
  109. package/src/scss/components/_toasts.scss +66 -72
  110. package/src/scss/form-elements/_checkbox.scss +117 -132
  111. package/src/scss/form-elements/_form.scss +149 -115
  112. package/src/scss/form-elements/_input-group.scss +99 -103
  113. package/src/scss/form-elements/_input.scss +74 -74
  114. package/src/scss/form-elements/_login.scss +48 -48
  115. package/src/scss/form-elements/_prefilled.scss +53 -51
  116. package/src/scss/form-elements/_radio.scss +95 -107
  117. package/src/scss/form-elements/_select.scss +42 -42
  118. package/src/scss/form-elements/_slider.scss +117 -132
  119. package/src/scss/form-elements/_textarea.scss +68 -54
  120. package/src/scss/form-elements/_toggle.scss +127 -140
  121. package/src/scss/layout/_footer.scss +172 -171
  122. package/src/scss/layout/_grid.scss +268 -302
  123. package/src/scss/layout/_header.scss +426 -427
  124. package/src/scss/layout/_home.scss +28 -27
  125. package/src/scss/layout/_main.scss +275 -238
  126. package/src/scss/layout/_page-header.scss +38 -36
  127. package/src/scss/layout/_section.scss +150 -124
  128. package/src/scss/main.scss +1 -1
  129. package/src/scss/utilities/_accessibility.scss +46 -45
  130. package/src/scss/utilities/_aspect.scss +22 -20
  131. package/src/scss/utilities/_corner.scss +23 -5
  132. package/src/scss/utilities/_display.scss +76 -70
  133. package/src/scss/utilities/_elevation.scss +13 -11
  134. package/src/scss/utilities/_flex.scss +83 -85
  135. package/src/scss/utilities/_reveal.scss +40 -63
  136. package/src/scss/utilities/_spacing.scss +63 -64
  137. package/src/scss/utilities/_text.scss +139 -141
  138. package/src/scss/utilities/_touch-targets.scss +130 -147
@@ -1,277 +1,219 @@
1
1
  @use '../abstracts' as *;
2
2
 
3
- // The word variant is set down from the price size and then has to climb back
4
- // to its line box - the two numbers only work as a pair, so they are named.
5
- $_mw-price-line-height: 1.1;
6
- $_mw-price-word-scale: 0.68;
3
+ @layer mw.components {
4
+ // Set down from the price size and climbing back to its line box - a pair
5
+ $_mw-price-line-height: 1.1;
6
+ $_mw-price-word-scale: 0.68;
7
7
 
8
- // ---------------------------------------------------------------------------
9
- // Price
10
- //
11
- // The figure, not the card around it: one baseline row holding the price that
12
- // was, the price that is, the unit and a discount tag.
13
- //
14
- // Every part is sized in `em` off a single token, so the size variants only
15
- // have to retune `--mw-price-size` and the whole row moves together - cents,
16
- // currency and struck-through original included.
17
- // ---------------------------------------------------------------------------
8
+ // The figure, not the card around it. Every part is sized in `em` off
9
+ // --mw-price-size, so a size variant only retunes that one token.
18
10
 
19
- .mw-price {
20
- --mw-price-size: #{font-size('3xl')};
11
+ .mw-price {
12
+ --mw-price-size: #{font-size('3xl')};
21
13
 
22
- display: flex;
23
- flex-wrap: wrap;
24
- // Baseline, not centre: figure and words are read as one line of text, and
25
- // centring a 0.45em word against a 2.2rem number floats it in the middle of
26
- // the digits instead of sitting it on them.
27
- align-items: baseline;
28
- gap: spacing('2') spacing('3');
29
- margin: spacing('0');
30
- font-size: var(--mw-price-size);
31
- line-height: $_mw-price-line-height;
32
- color: var(--mw-primary-text-color);
14
+ display: flex;
15
+ flex-wrap: wrap;
16
+ // Baseline, or a 0.45em word floats in the middle of a 2.2rem number
17
+ align-items: baseline;
18
+ gap: spacing('2') spacing('3');
19
+ margin: spacing('0');
20
+ font-size: var(--mw-price-size);
21
+ line-height: $_mw-price-line-height;
22
+ color: var(--mw-primary-text-color);
23
+
24
+ // A pill is a box, not a word - on the baseline it hangs off the digits
25
+ > .mw-tag,
26
+ > .mw-badge {
27
+ align-self: center;
28
+ flex-shrink: 0;
29
+ }
33
30
 
34
- // A pill is a box, not a word - on the baseline it hangs off the bottom of
35
- // the digits. Centre is where the eye looks for it.
36
- > .mw-tag,
37
- > .mw-badge {
38
- align-self: center;
39
- flex-shrink: 0;
40
- }
31
+ &-amount {
32
+ font-weight: font-weight('bold');
33
+ // So a figure swapped by a billing toggle does not jump sideways
34
+ font-variant-numeric: tabular-nums lining-nums;
35
+ font-feature-settings: 'tnum', 'lnum';
36
+ white-space: nowrap;
37
+ }
41
38
 
42
- &-amount {
43
- font-weight: font-weight('bold');
44
- // Two prices under each other line up, and a figure swapped by a billing
45
- // toggle does not jump sideways on the way
46
- font-variant-numeric: tabular-nums lining-nums;
47
- font-feature-settings: 'tnum', 'lnum';
48
- white-space: nowrap;
49
- }
39
+ // Down and left on the baseline: cents raised to cap height are a
40
+ // discounter's idiom and make a service price read cheaper than it is
41
+ &-fraction {
42
+ font-size: 0.62em;
43
+ font-weight: font-weight('medium');
44
+ }
50
45
 
51
- // Cents, written inside the amount. One step down and left on the baseline -
52
- // cents raised to the cap height are a discounter's idiom, and a service
53
- // price that borrows it reads cheaper than it is.
54
- &-fraction {
55
- font-size: 0.62em;
56
- font-weight: font-weight('medium');
57
- }
46
+ // The unit, not the number, so it does not carry the weight either. The floor
47
+ // is where the `em` chain stops helping: 0.45 of an mw-price-sm is 11px.
48
+ &-currency {
49
+ font-size: max(0.45em, #{font-size('xs')});
50
+ font-weight: font-weight('normal');
51
+ }
58
52
 
59
- // "Euro", "CHF", "€" - the unit, not the number, so it does not carry the
60
- // weight either.
61
- //
62
- // The floor is where the `em` chain stops being useful: 0.45 of an
63
- // `mw-price-sm` is 11px, and that is the size most offer cards run at.
64
- &-currency {
65
- font-size: max(0.45em, #{font-size('xs')});
66
- font-weight: font-weight('normal');
67
- }
53
+ // Muted *and* struck - muted alone reads as a footnote. The rule is drawn
54
+ // explicitly because the default hairline vanishes at this size.
55
+ &-original {
56
+ // Its own line, because inline the first part to wrap away is the discount
57
+ // tag - the one that was there to catch the eye. `flex-basis` is the break;
58
+ // a wrapper element would cost an element in every price on the page.
59
+ flex-basis: 100%;
60
+ margin-bottom: spacing('-1');
61
+ // Floored higher than the unit: a reader has to compare it with the new price
62
+ font-size: max(0.5em, #{font-size('sm')});
63
+ font-weight: font-weight('normal');
64
+ color: var(--mw-text-muted-color);
65
+ text-decoration: line-through;
66
+ text-decoration-thickness: 0.09em;
67
+ white-space: nowrap;
68
+ }
68
69
 
69
- // What it cost before the discount. Muted *and* struck: muted alone reads as
70
- // a footnote, the line is what says "this is no longer the price".
71
- //
72
- // The rule is drawn explicitly, because the browser default is a hairline
73
- // that vanishes at this size against a muted tone.
74
- &-original {
75
- // On its own line, above the new price. Inline it reads fine on a wide card
76
- // and badly everywhere else: "199 Euro 159 Euro -20 %" is a long row, and
77
- // the first thing to drop to the next line when the width runs out is the
78
- // discount tag - the one part that was there to catch the eye. Broken here
79
- // it breaks where it is meant to.
80
- //
81
- // `flex-basis` is the line break. A wrapper element around the rest would
82
- // do the same job and cost an element in every price on the page.
83
- flex-basis: 100%;
84
- margin-bottom: spacing('-1');
85
- // Floored higher than the unit - this one is a figure, and a reader has to
86
- // be able to compare it with the one next to it
87
- font-size: max(0.5em, #{font-size('sm')});
88
- font-weight: font-weight('normal');
89
- color: var(--mw-text-muted-color);
90
- text-decoration: line-through;
91
- text-decoration-thickness: 0.09em;
92
- white-space: nowrap;
93
- }
70
+ // "/ month", "per session" - what the price is per
71
+ &-period {
72
+ font-size: max(0.42em, #{font-size('xs')});
73
+ font-weight: font-weight('normal');
74
+ color: var(--mw-text-muted-color);
75
+ }
94
76
 
95
- // "/ month", "per session" - what the price is per
96
- &-period {
97
- font-size: max(0.42em, #{font-size('xs')});
98
- font-weight: font-weight('normal');
99
- color: var(--mw-text-muted-color);
100
- }
77
+ // Not a figure, so not set like one, but bold enough to hold the same slot.
78
+ // The line height matches a full-size amount, or the card sits out of line.
79
+ &-word {
80
+ font-size: $_mw-price-word-scale * 1em;
81
+ line-height: calc(#{$_mw-price-line-height}em / #{$_mw-price-word-scale});
82
+ font-weight: font-weight('bold');
83
+ }
101
84
 
102
- // "On request", "free" - not a figure, so not set like one. Still bold, so it
103
- // holds the same slot in a row of cards as a real price would.
104
- //
105
- // The line height is scaled back up to the one a full-size amount has: a row
106
- // of offers puts "On request" next to "129", and a shorter line box would sit
107
- // that card's price a few pixels out of line with its neighbours.
108
- &-word {
109
- font-size: $_mw-price-word-scale * 1em;
110
- line-height: calc(#{$_mw-price-line-height}em / #{$_mw-price-word-scale});
111
- font-weight: font-weight('bold');
85
+ // A *sibling* of the row: inside it, it would inherit the price size
86
+ &-note {
87
+ margin: spacing('2') spacing('0') spacing('0');
88
+ font-size: font-size('sm');
89
+ color: var(--mw-text-muted-color);
90
+ }
112
91
  }
113
92
 
114
- // The line under a price - what it includes, what it saves. A *sibling* of
115
- // the row, not a child: inside it, it would inherit the price size and be a
116
- // flex item on the same baseline.
117
- &-note {
118
- margin: spacing('2') spacing('0') spacing('0');
119
- font-size: font-size('sm');
120
- color: var(--mw-text-muted-color);
93
+ // Size. Only the token moves - see the `em` above.
94
+ .mw-price-sm {
95
+ --mw-price-size: #{font-size('xl')};
121
96
  }
122
- }
123
-
124
- // Size. Only the token moves - see the `em` above.
125
- .mw-price-sm {
126
- --mw-price-size: #{font-size('xl')};
127
- }
128
-
129
- .mw-price-lg {
130
- --mw-price-size: #{font-size('5xl')};
131
- }
132
97
 
133
- // Old price in front of the new one instead of above it - one line, for a wide
134
- // card or a table row that has the width to spare. Check it at the narrow end
135
- // before reaching for it: the discount tag is the first thing to wrap away.
136
- .mw-price-inline .mw-price-original {
137
- flex-basis: auto;
138
- margin-bottom: spacing('0');
139
- }
140
-
141
- .mw-price-center {
142
- justify-content: center;
143
- }
144
-
145
- // Body colour instead of the brand - for a table row or a list where a coloured
146
- // price would be the loudest thing on screen for no reason.
147
- .mw-price-plain {
148
- color: var(--mw-text-color);
149
- }
150
-
151
- // ---------------------------------------------------------------------------
152
- // Offer card
153
- //
154
- // The card a price is sold from: what you get, what it costs, the button that
155
- // asks for it. Deliberately thin - shell, body and footer are `mw-card`'s, this
156
- // adds only what selling something needs.
157
- // ---------------------------------------------------------------------------
98
+ .mw-price-lg {
99
+ --mw-price-size: #{font-size('5xl')};
100
+ }
158
101
 
159
- .mw-offer {
160
- // Prices in a row of offers have to sit on one line, and the feature lists
161
- // are never the same length. Pushed down rather than positioned: the grid
162
- // already stretches the cards to equal height, so "as far down as it goes"
163
- // resolves to the same line in every card of the row.
164
- > .mw-card-body > .mw-price {
165
- margin-top: auto;
166
- padding-top: spacing('5');
102
+ // One line, for a card with width to spare - check the narrow end before using
103
+ // it, the discount tag is the first thing to wrap away
104
+ .mw-price-inline .mw-price-original {
105
+ flex-basis: auto;
106
+ margin-bottom: spacing('0');
167
107
  }
168
108
 
169
- // The card body already pushes its footer down the same way. Two `auto`
170
- // margins in one column *share* the free space instead of collecting it above
171
- // the first, which leaves the price floating somewhere in the middle and at a
172
- // different height in every card - so the footer gives its own up as soon as
173
- // a price stands in front of it.
174
- //
175
- // Bottom-aligned, note included: a card that carries a `mw-price-note` and
176
- // one that does not will not have their prices on the same line. Give every
177
- // card in a row a note, or none of them.
178
- > .mw-card-body > .mw-price ~ .mw-card-footer {
179
- margin-top: spacing('0');
109
+ .mw-price-center {
110
+ justify-content: center;
180
111
  }
181
112
 
182
- // The one action on an offer card fills its row. A card footer otherwise
183
- // keeps every button at its label's width - a "Details" link has no business
184
- // being a band - but this is the button the whole card was built to get
185
- // pressed, and an 80px target parked in a corner is not that.
186
- //
187
- // Only when it stands alone: with a price beside it the row is shared, and
188
- // that case is at the bottom of this file.
189
- //
190
- // The auto margin has to go with it. An auto margin in a flex row eats the
191
- // free space *before* flex-grow is ever offered any, so growing on its own
192
- // leaves the button sitting exactly where it was.
193
- > .mw-card-body > .mw-card-footer > .mw-btn:only-child {
194
- flex: 1 1 auto;
195
- margin-left: spacing('0');
113
+ // For a row or list where a coloured price would be the loudest thing on screen
114
+ .mw-price-plain {
115
+ color: var(--mw-text-color);
196
116
  }
197
117
 
198
- // A solid band across the top carrying the name and the price - the layout
199
- // for when the price is the thing being compared and the feature list is
200
- // only its justification. Colour comes from `mw-card-addon-*` on the card,
201
- // the same set the card badge and the ribbon read.
202
- &-head {
203
- display: flex;
204
- flex-direction: column;
205
- align-items: center;
206
- gap: spacing('2');
207
- padding: spacing('6') spacing('5');
208
- // The card's own radius minus its border - the band sits inside it
209
- border-radius: (radius('sm') - 1px) (radius('xl') - 1px) 0 0;
210
- background: var(--mw-card-addon-color, var(--mw-primary-color));
211
- color: var(--mw-card-addon-text-color, var(--mw-primary-accent-text-color));
212
- text-align: center;
118
+ // The card a price is sold from. Thin on purpose: shell, body and footer are
119
+ // mw-card's, this adds only what selling something needs.
213
120
 
214
- // On a solid fill the price cannot keep the brand colour, and the muted
215
- // parts cannot keep a grey that was mixed against the page background
216
- .mw-price,
217
- .mw-price-original,
218
- .mw-price-period {
219
- color: inherit;
121
+ .mw-offer {
122
+ // Pushed down, not positioned: the grid already stretches the cards to equal
123
+ // height, so "as far as it goes" is the same line in every card of the row
124
+ > .mw-card-body > .mw-price {
125
+ margin-top: auto;
126
+ padding-top: spacing('5');
220
127
  }
221
128
 
222
- .mw-price-original,
223
- .mw-price-period {
224
- opacity: 0.7;
129
+ // The card body already pushes its footer down the same way. Two `auto`
130
+ // margins in one column *share* the free space instead of collecting it above
131
+ // the first, which leaves the price floating somewhere in the middle and at a
132
+ // different height in every card - so the footer gives its own up as soon as
133
+ // a price stands in front of it.
134
+ //
135
+ // Note included, so give every card in a row a note or none - otherwise their
136
+ // prices do not sit on the same line
137
+ > .mw-card-body > .mw-price ~ .mw-card-footer {
138
+ margin-top: spacing('0');
225
139
  }
226
- }
227
-
228
- &-name {
229
- margin: spacing('0');
230
- font-size: font-size('md');
231
- font-weight: font-weight('bold');
232
- letter-spacing: 0.06em;
233
- text-transform: uppercase;
234
- }
235
140
 
236
- // With a band above it the body no longer opens the card, so it does not need
237
- // the air a card top usually gets
238
- &-head + .mw-card-body {
239
- padding-top: spacing('6');
240
- }
241
- }
141
+ // The button the whole card was built to get pressed, so it fills the row -
142
+ // but only when it stands alone; shared with a price, see the end of the file.
143
+ // The auto margin goes with it: it eats the free space before flex-grow is
144
+ // offered any, so growing alone would leave the button where it was.
145
+ > .mw-card-body > .mw-card-footer > .mw-btn:only-child {
146
+ flex: 1 1 auto;
147
+ margin-left: spacing('0');
148
+ }
242
149
 
243
- // The band owns the top-right corner. An arc drawn over it either disappears
244
- // into the fill or fights it - the same call the coloured panel header makes.
245
- .mw-offer:has(> .mw-offer-head)::after {
246
- @include corner-accent(1px, 'bottom');
247
- }
150
+ // For when the price is what gets compared and the feature list only justifies
151
+ // it. Colour comes from mw-card-addon-*, like the badge and the ribbon.
152
+ &-head {
153
+ display: flex;
154
+ flex-direction: column;
155
+ align-items: center;
156
+ gap: spacing('2');
157
+ padding: spacing('6') spacing('5');
158
+ // The card's own radius minus its border - the band sits inside it
159
+ border-radius: (radius('sm') - 1px) (radius('xl') - 1px) 0 0;
160
+ background: var(--mw-card-addon-color, var(--mw-primary-color));
161
+ color: var(
162
+ --mw-card-addon-text-color,
163
+ var(--mw-primary-accent-text-color)
164
+ );
165
+ text-align: center;
166
+
167
+ // On a solid fill neither the brand colour nor a page-mixed grey survives
168
+ .mw-price,
169
+ .mw-price-original,
170
+ .mw-price-period {
171
+ color: inherit;
172
+ }
173
+
174
+ .mw-price-original,
175
+ .mw-price-period {
176
+ opacity: 0.7;
177
+ }
178
+ }
248
179
 
249
- // A price in a card footer is a label next to an action, not a second action.
250
- //
251
- // The footer stacks its children to full width once the *card* is narrow, which
252
- // is right for two buttons that would otherwise squeeze into nothing on a phone
253
- // - and wrong here: "33 Euro" needs no width, and the one button beside it does
254
- // not need the whole card either. A full-bleed action under a left-aligned
255
- // price reads as a banner, not as the end of a card.
256
- //
257
- // So the row survives, and the action takes half of it. Lives here rather than
258
- // in _cards.scss because the price is the guest: the footer's own rule is
259
- // correct for everything that is not one.
260
- @container mw-card (max-width: #{$mw-card-narrow}) {
261
- .mw-card-footer:has(> .mw-price) {
262
- flex-direction: row;
263
- align-items: center;
180
+ &-name {
181
+ margin: spacing('0');
182
+ font-size: font-size('md');
183
+ font-weight: font-weight('bold');
184
+ letter-spacing: 0.06em;
185
+ text-transform: uppercase;
186
+ }
264
187
 
265
- // The footer's own rule hands every child `width: 100%` for the stack. Taken
266
- // back for all of them, not just the price - the second slot is a button on
267
- // one card and an "Ausgebucht" tag on the next, and a full-width tag is no
268
- // better than a full-width button.
269
- > * {
270
- width: auto;
188
+ // With a band above it the body no longer opens the card
189
+ &-head + .mw-card-body {
190
+ padding-top: spacing('6');
271
191
  }
192
+ }
193
+
194
+ // The band owns the corner - an arc over it disappears into the fill or fights it
195
+ .mw-offer:has(> .mw-offer-head)::after {
196
+ @include corner-accent(1px, 'bottom');
197
+ }
272
198
 
273
- > .mw-btn {
274
- width: 50%;
199
+ // A price in a footer is a label next to an action, not a second action, so the
200
+ // row survives the narrow-card stack and the action takes half of it. Here and
201
+ // not in _cards.scss because the price is the guest - the footer's own rule is
202
+ // right for everything that is not one.
203
+ @container mw-card (max-width: #{$mw-card-narrow}) {
204
+ .mw-card-footer:has(> .mw-price) {
205
+ flex-direction: row;
206
+ align-items: center;
207
+
208
+ // Taken back for every child, not just the price: the second slot is a button
209
+ // on one card and a tag on the next
210
+ > * {
211
+ width: auto;
212
+ }
213
+
214
+ > .mw-btn {
215
+ width: 50%;
216
+ }
275
217
  }
276
218
  }
277
219
  }