maverick-wave 5.32.0 → 5.34.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/README.md +2 -2
- package/maverick-wave.min.css +16 -2
- package/maverick-wave.min.js +1 -1
- package/package.json +2 -2
- package/src/js/main.js +769 -3
- package/src/js/occasions.js +107 -0
- package/src/scss/abstracts/_variables.scss +2 -0
- package/src/scss/components/_deck-blocks.scss +963 -0
- package/src/scss/components/_deck-frame.scss +102 -0
- package/src/scss/components/_deck.scss +700 -0
- package/src/scss/components/_index.scss +3 -0
- package/src/scss/components/_occasions.scss +1574 -0
- package/src/scss/layout/_main.scss +18 -0
- package/src/scss/layout/_section.scss +4 -4
|
@@ -0,0 +1,1574 @@
|
|
|
1
|
+
@use 'sass:list';
|
|
2
|
+
@use 'sass:math';
|
|
3
|
+
@use 'sass:string';
|
|
4
|
+
@use '../abstracts' as *;
|
|
5
|
+
|
|
6
|
+
// Seasonal decoration - snow on the cards in winter, a garland at Christmas,
|
|
7
|
+
// leaves in autumn. Switched on with one class on <html>:
|
|
8
|
+
//
|
|
9
|
+
// <html class="mw-occasion-snow"> static, CSS only
|
|
10
|
+
// <html class="mw-occasion-snow mw-occasion-scroll"> arrives with the scroll
|
|
11
|
+
//
|
|
12
|
+
// The intro overlay and the particles that drift with the scroll are the two
|
|
13
|
+
// parts that need the script; everything they show is drawn here.
|
|
14
|
+
|
|
15
|
+
// --- Art helpers --------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
@function _replace($text, $search, $with) {
|
|
18
|
+
$result: '';
|
|
19
|
+
$index: string.index($text, $search);
|
|
20
|
+
|
|
21
|
+
@while $index {
|
|
22
|
+
$result: $result + string.slice($text, 1, $index - 1) + $with;
|
|
23
|
+
$text: string.slice($text, $index + string.length($search));
|
|
24
|
+
$index: string.index($text, $search);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@return $result + $text;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// The art is written with double quotes and plain colours; the data URI wants
|
|
31
|
+
// single quotes and the four characters that would end or break it encoded.
|
|
32
|
+
@function _svg($view-box, $body, $attributes: '') {
|
|
33
|
+
$markup: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="#{$view-box}" #{$attributes}>#{$body}</svg>';
|
|
34
|
+
|
|
35
|
+
@each $char,
|
|
36
|
+
$code in ('%': '%25', '<': '%3C', '>': '%3E', '#': '%23', '"': "'")
|
|
37
|
+
{
|
|
38
|
+
$markup: _replace($markup, $char, $code);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@return url('data:image/svg+xml,#{$markup}');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@function _n($value) {
|
|
45
|
+
@return math.div(math.round($value * 100), 100);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@function _polygon($cx, $cy, $r, $rotation, $sides: 5) {
|
|
49
|
+
$points: '';
|
|
50
|
+
|
|
51
|
+
@for $k from 0 to $sides {
|
|
52
|
+
$angle: $rotation + $k * math.div(360deg, $sides);
|
|
53
|
+
$points: $points +
|
|
54
|
+
_n($cx + $r * math.cos($angle)) +
|
|
55
|
+
',' +
|
|
56
|
+
_n($cy + $r * math.sin($angle)) +
|
|
57
|
+
' ';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@return $points;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@function _star($cx, $cy, $outer, $inner) {
|
|
64
|
+
$points: '';
|
|
65
|
+
|
|
66
|
+
@for $k from 0 to 10 {
|
|
67
|
+
$angle: -90deg + $k * 36deg;
|
|
68
|
+
$r: $inner;
|
|
69
|
+
|
|
70
|
+
@if $k % 2 == 0 {
|
|
71
|
+
$r: $outer;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
$points: $points +
|
|
75
|
+
_n($cx + $r * math.cos($angle)) +
|
|
76
|
+
',' +
|
|
77
|
+
_n($cy + $r * math.sin($angle)) +
|
|
78
|
+
' ';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@return '<polygon points="#{$points}"/>';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Four points with concave sides - the glint on anything gold
|
|
85
|
+
@function _sparkle($x, $y, $s) {
|
|
86
|
+
$a: $s * 0.14;
|
|
87
|
+
$b: $s * 0.22;
|
|
88
|
+
|
|
89
|
+
@return '<path d="M#{$x} #{$y - $s}C#{$x + $a} #{$y - $b} #{$x + $b} #{$y - $a} #{$x + $s} #{$y}C#{$x + $b} #{$y + $a} #{$x + $a} #{$y + $b} #{$x} #{$y + $s}C#{$x - $a} #{$y + $b} #{$x - $b} #{$y + $a} #{$x - $s} #{$y}C#{$x - $b} #{$y - $a} #{$x - $a} #{$y - $b} #{$x} #{$y - $s}Z"/>';
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@function _blossom() {
|
|
93
|
+
$petals: '';
|
|
94
|
+
|
|
95
|
+
@for $k from 0 to 5 {
|
|
96
|
+
$petals: $petals +
|
|
97
|
+
'<ellipse cy="-4.6" rx="3.4" ry="4.6" transform="rotate(#{$k * 72})"/>';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@return '<g id="f"><g fill="#fbd3de" stroke="#e59bb2" stroke-width=".5">#{$petals}</g>' +
|
|
101
|
+
'<circle r="2.1" fill="#e2708f"/>' +
|
|
102
|
+
'<g fill="#fff1a8"><circle cx="-1" cy="-.8" r=".55"/><circle cx="1.1" cy="-.4" r=".55"/><circle cx=".1" cy="1.1" r=".55"/></g></g>';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@function _egg($x, $y, $rotation, $scale, $color, $pattern) {
|
|
106
|
+
@return '<g transform="translate(#{$x} #{$y}) rotate(#{$rotation}) scale(#{$scale})">' +
|
|
107
|
+
'<path fill="#{$color}" stroke="#000" stroke-opacity=".12" stroke-width=".6" d="M0 -9.5C5 -9.5 7 -1 7 3C7 7.5 4 10 0 10C-4 10 -7 7.5 -7 3C-7 -1 -5 -9.5 0 -9.5Z"/>' +
|
|
108
|
+
$pattern +
|
|
109
|
+
'<ellipse cx="-2.6" cy="-3.6" rx="1.4" ry="2.4" fill="#fff" fill-opacity=".45" transform="rotate(20 -2.6 -3.6)"/></g>';
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@function _bauble($light, $mid, $dark) {
|
|
113
|
+
@return _svg(
|
|
114
|
+
'0 0 16 22',
|
|
115
|
+
'<defs><radialGradient id="b" cx=".36" cy=".34" r=".72"><stop offset="0" stop-color="#{$light}"/><stop offset=".5" stop-color="#{$mid}"/><stop offset="1" stop-color="#{$dark}"/></radialGradient></defs>' +
|
|
116
|
+
'<path d="M8 0V4" stroke="#b8923a" stroke-width="1"/>' +
|
|
117
|
+
'<rect x="5.6" y="3.4" width="4.8" height="3" rx=".8" fill="#d8b24c"/>' +
|
|
118
|
+
'<circle cx="8" cy="14" r="7.4" fill="url(#b)"/>' +
|
|
119
|
+
'<ellipse cx="5.5" cy="11.2" rx="1.9" ry="1.2" fill="#fff" fill-opacity=".55" transform="rotate(-35 5.5 11.2)"/>'
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@function _garland-needles() {
|
|
124
|
+
$dark: '';
|
|
125
|
+
$mid: '';
|
|
126
|
+
$light: '';
|
|
127
|
+
|
|
128
|
+
// From -3 so the needles that start left of the tile and reach into it are
|
|
129
|
+
// drawn too - otherwise every repeat shows a seam.
|
|
130
|
+
@for $i from -3 through 11 {
|
|
131
|
+
$x: $i * 4;
|
|
132
|
+
$j: $i + 12;
|
|
133
|
+
$dark: $dark + 'M#{$x} 12l6 #{-9 + $j % 3}M#{$x + 1} 12l6 #{9 - $j % 2}';
|
|
134
|
+
$mid: $mid + 'M#{$x + 2} 12l5 #{-6 + $j % 2}M#{$x + 3} 12l5 #{6 - $j % 3}';
|
|
135
|
+
|
|
136
|
+
@if $j % 2 == 0 {
|
|
137
|
+
$light: $light + 'M#{$x + 1.5} 11l3.5 -4M#{$x + 2.5} 13l3.5 4';
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@return '<g fill="none" stroke-linecap="round">' +
|
|
142
|
+
'<path d="M0 12H48" stroke="#3a2a1a" stroke-width="1.4"/>' +
|
|
143
|
+
'<path d="#{$dark}" stroke="#153d24" stroke-width="1.8"/>' +
|
|
144
|
+
'<path d="#{$mid}" stroke="#23663c" stroke-width="1.6"/>' +
|
|
145
|
+
'<path d="#{$light}" stroke="#4d9a63" stroke-width="1"/></g>';
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@function _football() {
|
|
149
|
+
$body: '<defs><radialGradient id="g" cx=".38" cy=".32" r=".78"><stop offset="0" stop-color="#fff"/><stop offset=".65" stop-color="#eceef2"/><stop offset="1" stop-color="#aab2bd"/></radialGradient><clipPath id="c"><circle cx="12" cy="12" r="11"/></clipPath></defs>' +
|
|
150
|
+
'<circle cx="12" cy="12" r="11" fill="url(#g)"/>' +
|
|
151
|
+
'<g clip-path="url(#c)" fill="#1f2228"><polygon points="#{_polygon(12, 12, 4.2, -90deg)}"/>';
|
|
152
|
+
$seams: '';
|
|
153
|
+
|
|
154
|
+
@each $angle in (-90deg, -18deg, 54deg, 126deg, 198deg) {
|
|
155
|
+
$cx: 12 + 10.6 * math.cos($angle);
|
|
156
|
+
$cy: 12 + 10.6 * math.sin($angle);
|
|
157
|
+
$body: $body +
|
|
158
|
+
'<polygon points="#{_polygon($cx, $cy, 3.4, $angle + 180deg)}"/>';
|
|
159
|
+
$seams: $seams +
|
|
160
|
+
'M#{_n(12 + 4.2 * math.cos($angle))} #{_n(12 + 4.2 * math.sin($angle))}L#{_n(12 + 7.2 * math.cos($angle))} #{_n(12 + 7.2 * math.sin($angle))}';
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@return _svg(
|
|
164
|
+
'0 0 24 24',
|
|
165
|
+
$body + '</g><path d="#{$seams}" stroke="#1f2228" stroke-width=".8"/>' +
|
|
166
|
+
'<circle cx="12" cy="12" r="11" fill="none" stroke="#1f2228" stroke-opacity=".45" stroke-width=".6"/>'
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
$_maple: 'M12 1L13.6 5.6L16.8 4.2L15.9 8.8L21 7.4L19.1 11.2L23 12.6L18.3 14.7L19.5 17.6L14.3 16.6L12.7 20V23.5H11.3V20L9.7 16.6L4.5 17.6L5.7 14.7L1 12.6L4.9 11.2L3 7.4L8.1 8.8L7.2 4.2L10.4 5.6Z';
|
|
171
|
+
$_maple-veins: 'M12 21V5.5M12 14L4.5 9.5M12 14L19.5 9.5M12 16.5L6 17M12 16.5L18 17';
|
|
172
|
+
$_oak: 'M12 2C15 4 14 6 16.5 7C19 8 16.5 10 18.5 11.5C20.5 13 17 14.5 18 16.5C19 18.5 14.5 18.5 13 21L12.6 23.5H11.4L11 21C9.5 18.5 5 18.5 6 16.5C7 14.5 3.5 13 5.5 11.5C7.5 10 5 8 7.5 7C10 6 9 4 12 2Z';
|
|
173
|
+
$_oak-veins: 'M12 22V5M12 9L8 7.5M12 9L16 7.5M12 13L7 11.5M12 13L17 11.5M12 17L8 16M12 17L16 16';
|
|
174
|
+
$_birch: 'M12 1.5C17.5 6 18 14 12 21.5C6 14 6.5 6 12 1.5ZM11.4 21H12.6V23.5H11.4Z';
|
|
175
|
+
$_birch-veins: 'M12 21V4M12 10L8.5 7.5M12 10L15.5 7.5M12 14L8 11.5M12 14L16 11.5';
|
|
176
|
+
|
|
177
|
+
@function _leaf($shape, $veins, $fill) {
|
|
178
|
+
@return _svg(
|
|
179
|
+
'0 0 24 24',
|
|
180
|
+
'<path d="#{$shape}" fill="#{$fill}" stroke="#4a1a08" stroke-opacity=".25" stroke-width=".5"/>' +
|
|
181
|
+
'<path d="#{$veins}" fill="none" stroke="#000" stroke-opacity=".22" stroke-width=".7"/>'
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// --- Static art ---------------------------------------------------------------
|
|
186
|
+
|
|
187
|
+
// The card's top edge runs at y 11 of every snow layer, which is what the
|
|
188
|
+
// pseudo's `top: -11px` lines up. The band stretches to any width, the lumps
|
|
189
|
+
// repeat at their own size so they stay round - two tiles of unrelated widths,
|
|
190
|
+
// so the row never visibly repeats. One gradient in user space for all of
|
|
191
|
+
// them, or each layer shades on its own and the joins show.
|
|
192
|
+
$_snow-shade: '<defs><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="0" y2="26"><stop offset=".1" stop-color="#fff"/><stop offset=".6" stop-color="#e8f0f8"/><stop offset=".7" stop-color="#cbdaea"/></linearGradient></defs>';
|
|
193
|
+
|
|
194
|
+
$_snow-band: _svg(
|
|
195
|
+
'0 0 400 26',
|
|
196
|
+
$_snow-shade +
|
|
197
|
+
'<path fill="#7f98b3" fill-opacity=".35" d="M0 13C80 17 320 17 400 13V15C320 19 80 19 0 15Z"/>' +
|
|
198
|
+
'<path fill="url(#a)" d="M0 13C0 9.5 4 8 12 8H388C396 8 400 9.5 400 13C320 16.5 80 16.5 0 13Z"/>',
|
|
199
|
+
'preserveAspectRatio="none"'
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
$_snow-lumps: _svg(
|
|
203
|
+
'0 0 86 26',
|
|
204
|
+
$_snow-shade +
|
|
205
|
+
'<path fill="url(#a)" d="M0 9C7 9 9 3.5 19 3.5C28 3.5 31 7 39 7C46 7 49 1.5 60 1.5C71 1.5 75 8.5 86 9V13H0Z"/>'
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
$_snow-lumps-small: _svg(
|
|
209
|
+
'0 0 53 26',
|
|
210
|
+
$_snow-shade +
|
|
211
|
+
'<path fill="url(#a)" d="M0 9C5 9 8 5 14 5C21 5 24 8.5 31 8.5C38 8.5 41 4 47 4C50 4 51.5 7 53 9V13H0Z"/>'
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
// Tapers the lumps into the band towards both ends of the card
|
|
215
|
+
$_snow-taper: _svg(
|
|
216
|
+
'0 0 400 26',
|
|
217
|
+
'<path d="M0 26V13C4 6 18 0 40 0H360C382 0 396 6 400 13V26Z"/>',
|
|
218
|
+
'preserveAspectRatio="none"'
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
$_snow-drip: _svg(
|
|
222
|
+
'0 0 12 12',
|
|
223
|
+
'<defs><linearGradient id="a" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#e3ecf6"/><stop offset="1" stop-color="#c3d3e5"/></linearGradient></defs>' +
|
|
224
|
+
'<path fill="url(#a)" d="M0 0H12C12 2 11 3 10 5C9 8.5 8.6 11 6 11C3.4 11 3 8.5 2 5C1 3 0 2 0 0Z"/>'
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
$_garland: _svg(
|
|
228
|
+
'0 0 48 24',
|
|
229
|
+
'<defs><radialGradient id="l"><stop offset="0" stop-color="#fffbe6"/><stop offset=".35" stop-color="#ffe08a"/><stop offset="1" stop-color="#ffd166" stop-opacity="0"/></radialGradient></defs>' +
|
|
230
|
+
_garland-needles() +
|
|
231
|
+
'<circle cx="10" cy="8.5" r="3.6" fill="url(#l)"/><circle cx="34" cy="15.5" r="3.6" fill="url(#l)"/>'
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
$_bauble-red: _bauble('#ff9d9d', '#cf1b30', '#650715');
|
|
235
|
+
$_bauble-gold: _bauble('#fff1b8', '#d9a520', '#825d07');
|
|
236
|
+
$_bauble-silver: _bauble('#ffffff', '#b9c2cd', '#5c6572');
|
|
237
|
+
|
|
238
|
+
$_gold: '<defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#fff4c2"/><stop offset=".5" stop-color="#efc34a"/><stop offset="1" stop-color="#b38209"/></linearGradient></defs>';
|
|
239
|
+
|
|
240
|
+
$_sparkles: _svg(
|
|
241
|
+
'0 0 64 42',
|
|
242
|
+
$_gold +
|
|
243
|
+
'<path d="M3 40C9 31 18 41 23 33S33 27 29 22" fill="none" stroke="#b9c2cf" stroke-width="1.4" stroke-linecap="round"/>' +
|
|
244
|
+
'<g fill="url(#g)">' + _sparkle(42, 16, 13) + _sparkle(20, 26, 7.5) +
|
|
245
|
+
_sparkle(55, 33, 5) +
|
|
246
|
+
'<circle cx="29" cy="9" r="1.6"/><circle cx="59" cy="9" r="1.2"/><circle cx="11" cy="15" r="1.1"/><circle cx="36" cy="34" r="1"/></g>'
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
$_blossoms: _svg(
|
|
250
|
+
'0 0 84 40',
|
|
251
|
+
'<g fill="none" stroke="#6b4a36" stroke-linecap="round"><path stroke-width="2.4" d="M86 7C72 9 60 13 46 16S22 21 6 29"/><path stroke-width="1.5" d="M54 14C56 20 53 26 49 30"/><path stroke-width="1.3" d="M28 19C26 14 22 11 17 9"/></g>' +
|
|
252
|
+
'<g fill="#8fbf73"><ellipse cx="64" cy="9" rx="4.6" ry="2" transform="rotate(-24 64 9)"/><ellipse cx="38" cy="21.5" rx="4.2" ry="1.8" transform="rotate(28 38 21.5)"/><ellipse cx="21" cy="25" rx="3.6" ry="1.6" transform="rotate(-20 21 25)"/></g>' +
|
|
253
|
+
'<g fill="#ec8fab"><ellipse cx="74" cy="6" rx="2.2" ry="3" transform="rotate(62 74 6)"/><ellipse cx="9" cy="27.5" rx="2" ry="2.8" transform="rotate(-42 9 27.5)"/></g>' +
|
|
254
|
+
'<defs>#{_blossom()}</defs>' +
|
|
255
|
+
'<use href="#f" transform="translate(56 11)"/><use href="#f" transform="translate(31 17) scale(.85)"/>' +
|
|
256
|
+
'<use href="#f" transform="translate(49 30) scale(.7)"/><use href="#f" transform="translate(16 9) scale(.62)"/>'
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
@function _grass() {
|
|
260
|
+
$back: '';
|
|
261
|
+
$front: '';
|
|
262
|
+
|
|
263
|
+
@for $k from 0 through 20 {
|
|
264
|
+
$x: 3 + $k * 3.5;
|
|
265
|
+
$h: 4 + ($k * 7) % 6;
|
|
266
|
+
$lean: (($k * 5) % 7) - 3;
|
|
267
|
+
$blade: 'M#{$x} 30Q#{$x + $lean * 0.3} #{30 - $h * 0.6} #{$x + $lean * 0.6} #{30 - $h}';
|
|
268
|
+
|
|
269
|
+
@if $k % 2 == 0 {
|
|
270
|
+
$front: $front + $blade;
|
|
271
|
+
} @else {
|
|
272
|
+
$back: $back + $blade;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
@return '<g fill="none" stroke-width="1.5" stroke-linecap="round"><path d="#{$back}" stroke="#4f8a3a"/><path d="#{$front}" stroke="#7cbf5a"/></g>';
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Two lying, one standing behind them - upright eggs would tower over the card
|
|
280
|
+
$_eggs: _svg(
|
|
281
|
+
'0 0 80 34',
|
|
282
|
+
_egg(
|
|
283
|
+
41,
|
|
284
|
+
13,
|
|
285
|
+
8,
|
|
286
|
+
0.85,
|
|
287
|
+
'#f7dc7c',
|
|
288
|
+
'<path d="M-7 3.5H7" stroke="#fff" stroke-width="1.6"/><path d="M-6.5 6.5H6.5" stroke="#9fd39a" stroke-width="1.2"/>'
|
|
289
|
+
) +
|
|
290
|
+
_egg(
|
|
291
|
+
27,
|
|
292
|
+
19,
|
|
293
|
+
-72,
|
|
294
|
+
1,
|
|
295
|
+
'#a9d8f2',
|
|
296
|
+
'<path d="M-6.8 1l2.3-2 2.3 2 2.2-2 2.3 2 2.2-2 2.3 2" fill="none" stroke="#fff" stroke-width="1.3"/>'
|
|
297
|
+
) +
|
|
298
|
+
_egg(
|
|
299
|
+
55,
|
|
300
|
+
20,
|
|
301
|
+
76,
|
|
302
|
+
0.95,
|
|
303
|
+
'#f6b6cc',
|
|
304
|
+
'<g fill="#fff" fill-opacity=".85"><circle cx="-3" cy="2" r="1.2"/><circle cx="1.5" cy="-1" r="1.2"/><circle cx="3" cy="4.5" r="1.1"/><circle cx="-1" cy="6" r="1"/></g>'
|
|
305
|
+
) +
|
|
306
|
+
_grass()
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
$_sun: _svg(
|
|
310
|
+
'0 0 40 40',
|
|
311
|
+
'<defs><radialGradient id="h"><stop offset=".3" stop-color="#ffe27a" stop-opacity=".55"/><stop offset="1" stop-color="#ffe27a" stop-opacity="0"/></radialGradient><radialGradient id="s" cx=".4" cy=".38"><stop offset="0" stop-color="#fffbe0"/><stop offset=".55" stop-color="#ffd84d"/><stop offset="1" stop-color="#ffb52e"/></radialGradient></defs>' +
|
|
312
|
+
'<circle cx="20" cy="20" r="20" fill="url(#h)"/>' +
|
|
313
|
+
'<circle cx="20" cy="20" r="15.5" fill="none" stroke="#ffc83a" stroke-width="4" stroke-dasharray="2.2 5.92"/>' +
|
|
314
|
+
'<circle cx="20" cy="20" r="9" fill="url(#s)"/>'
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
$_leaves: _svg(
|
|
318
|
+
'0 0 96 46',
|
|
319
|
+
'<defs><g id="m"><path d="#{$_maple}"/><path d="#{$_maple-veins}" fill="none" stroke="#000" stroke-opacity=".22" stroke-width=".7"/></g>' +
|
|
320
|
+
'<g id="o"><path d="#{$_oak}"/><path d="#{$_oak-veins}" fill="none" stroke="#000" stroke-opacity=".22" stroke-width=".7"/></g>' +
|
|
321
|
+
'<g id="b"><path d="#{$_birch}"/><path d="#{$_birch-veins}" fill="none" stroke="#000" stroke-opacity=".22" stroke-width=".7"/></g></defs>' +
|
|
322
|
+
'<g stroke="#4a1a08" stroke-opacity=".25" stroke-width=".5">' +
|
|
323
|
+
'<use href="#m" fill="#c2341d" transform="translate(70 3) rotate(-38 12 12) scale(.72)"/>' +
|
|
324
|
+
'<use href="#o" fill="#a8421e" transform="translate(6 6) rotate(-26 12 12) scale(1.1)"/>' +
|
|
325
|
+
'<use href="#b" fill="#e3b21f" transform="translate(58 18) rotate(72 12 12) scale(.95)"/>' +
|
|
326
|
+
'<use href="#m" fill="#e8772a" transform="translate(30 -1) rotate(16 12 12) scale(1.3)"/></g>'
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
$_ball: _football();
|
|
330
|
+
|
|
331
|
+
$_bunting: _svg(
|
|
332
|
+
'0 0 100 19',
|
|
333
|
+
'<path d="M0 0H100V1.6H0ZM2 1H18L10 17ZM22 1H38L30 17ZM42 1H58L50 17ZM62 1H78L70 17ZM82 1H98L90 17Z"/>'
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
$_rosette: _svg(
|
|
337
|
+
'0 0 34 44',
|
|
338
|
+
'<defs><radialGradient id="g" cx=".4" cy=".35" r=".7"><stop offset="0" stop-color="#fff3b8"/><stop offset=".6" stop-color="#e2b33c"/><stop offset="1" stop-color="#a87a14"/></radialGradient></defs>' +
|
|
339
|
+
'<path fill="#8e1b2a" d="M11 18L5 42L9.5 38.5L13 43L18 22Z"/><path fill="#b02a40" d="M23 18L29 42L24.5 38.5L21 43L16 22Z"/>' +
|
|
340
|
+
'<circle cx="17" cy="16" r="12" fill="#c9951f" stroke="#c9951f" stroke-width="5.6" stroke-dasharray="0 5.03" stroke-linecap="round"/>' +
|
|
341
|
+
'<circle cx="17" cy="16" r="9.4" fill="url(#g)" stroke="#fff4c7" stroke-opacity=".7" stroke-width=".8"/>' +
|
|
342
|
+
'<g fill="#fff7dc" fill-opacity=".92">' + _star(17, 16.4, 5.2, 2.2) + '</g>'
|
|
343
|
+
);
|
|
344
|
+
|
|
345
|
+
// --- Particle art -------------------------------------------------------------
|
|
346
|
+
|
|
347
|
+
$_crystal: _svg(
|
|
348
|
+
'-12 -12 24 24',
|
|
349
|
+
'<g fill="none" stroke-linecap="round">' +
|
|
350
|
+
'<path id="a" d="M0 0V-10M0 -6L-3 -8.6M0 -6L3 -8.6M0 -2.8L-2 -4.4M0 -2.8L2 -4.4" stroke="#8ea6bf" stroke-opacity=".55" stroke-width="2.8"/>' +
|
|
351
|
+
'<use href="#a" transform="rotate(60)"/><use href="#a" transform="rotate(120)"/><use href="#a" transform="rotate(180)"/><use href="#a" transform="rotate(240)"/><use href="#a" transform="rotate(300)"/>' +
|
|
352
|
+
'<path id="b" d="M0 0V-10M0 -6L-3 -8.6M0 -6L3 -8.6M0 -2.8L-2 -4.4M0 -2.8L2 -4.4" stroke="#fff" stroke-width="1.4"/>' +
|
|
353
|
+
'<use href="#b" transform="rotate(60)"/><use href="#b" transform="rotate(120)"/><use href="#b" transform="rotate(180)"/><use href="#b" transform="rotate(240)"/><use href="#b" transform="rotate(300)"/></g>'
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
$_gold-star: _svg(
|
|
357
|
+
'0 0 24 24',
|
|
358
|
+
$_gold + '<g fill="url(#g)">' + _star(12, 12.6, 11, 4.6) + '</g>'
|
|
359
|
+
);
|
|
360
|
+
$_glint: _svg(
|
|
361
|
+
'0 0 24 24',
|
|
362
|
+
$_gold + '<g fill="url(#g)">' + _sparkle(12, 12, 11.5) + '</g>'
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
$_petal: _svg(
|
|
366
|
+
'0 0 20 24',
|
|
367
|
+
'<path d="M10 0C16 4 20 11 17 18C15 22 12 24 10 21.5C8 24 5 22 3 18C0 11 4 4 10 0Z"/>'
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
$_balloon: _svg(
|
|
371
|
+
'0 0 24 31',
|
|
372
|
+
'<path d="M12 0C18.6 0 24 5.6 24 12.6C24 20.4 17.4 27 12.8 28.6L14 31H10L11.2 28.6C6.6 27 0 20.4 0 12.6C0 5.6 5.4 0 12 0Z"/>'
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
$_maple-leaf: _leaf($_maple, $_maple-veins, '#e36d23');
|
|
376
|
+
$_oak-leaf: _leaf($_oak, $_oak-veins, '#a8431e');
|
|
377
|
+
$_birch-leaf: _leaf($_birch, $_birch-veins, '#e2b21c');
|
|
378
|
+
|
|
379
|
+
// --- Effects ------------------------------------------------------------------
|
|
380
|
+
|
|
381
|
+
$_effects: (
|
|
382
|
+
'snow',
|
|
383
|
+
christmas,
|
|
384
|
+
newyear,
|
|
385
|
+
spring,
|
|
386
|
+
easter,
|
|
387
|
+
summer,
|
|
388
|
+
autumn,
|
|
389
|
+
football,
|
|
390
|
+
birthday,
|
|
391
|
+
anniversary
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
// Cards, panels and testimonials, unless inside one another - a nested card
|
|
395
|
+
// would stack a second garland into the first - plus whatever opts in
|
|
396
|
+
$_surfaces: '.mw-card, .mw-panel, .mw-testimonial';
|
|
397
|
+
$_surface: ':is(#{$_surfaces}):not(:is(#{$_surfaces}) *, .mw-occasion-skip)';
|
|
398
|
+
$_host: '#{$_surface}, .mw-occasion-spot';
|
|
399
|
+
|
|
400
|
+
@function _on($effect, $mode: '') {
|
|
401
|
+
@return ':root#{$mode}.mw-occasion-#{$effect} :is(#{$_host})';
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
@function _list-classes() {
|
|
405
|
+
$classes: ();
|
|
406
|
+
|
|
407
|
+
@each $effect in $_effects {
|
|
408
|
+
$classes: list.append($classes, '.mw-occasion-#{$effect}', comma);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
@return $classes;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
@function _scaled($value) {
|
|
415
|
+
@return calc(#{$value} * var(--mw-occasion-scale));
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
@function _deep($value) {
|
|
419
|
+
@return calc(#{$value} * var(--mw-occasion-depth));
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// The top right corner belongs to the card - its signature arc, often a badge.
|
|
423
|
+
// So every piece sits top left, mirrored because the art is drawn for a right
|
|
424
|
+
// corner. transform and not `scale`: the arrival animations own that one.
|
|
425
|
+
@mixin _corner($effect, $top, $width, $height, $side: -4px) {
|
|
426
|
+
#{_on($effect)}::before {
|
|
427
|
+
top: _scaled($top);
|
|
428
|
+
left: _scaled($side);
|
|
429
|
+
width: _scaled($width);
|
|
430
|
+
height: _scaled($height);
|
|
431
|
+
transform: scaleX(-1);
|
|
432
|
+
@content;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Along the top edge from the left, and only part of it: half a narrow surface,
|
|
437
|
+
// 40% of a wide one, never more than 400px. One formula instead of a
|
|
438
|
+
// breakpoint - min() holds 50% up to 384px, max() hands over to 40% past 960px,
|
|
439
|
+
// and the width in between stays at 384px - so nothing jumps, and it reads the
|
|
440
|
+
// surface's own width, which a viewport query cannot: a card in a three-column
|
|
441
|
+
// grid is as narrow as a phone.
|
|
442
|
+
@mixin _edge($effect, $top, $height, $left: 4px) {
|
|
443
|
+
#{_on($effect)}::before {
|
|
444
|
+
top: $top;
|
|
445
|
+
left: $left;
|
|
446
|
+
width: min(
|
|
447
|
+
400px,
|
|
448
|
+
calc(var(--mw-occasion-scale) * max(40%, min(50%, 384px)))
|
|
449
|
+
);
|
|
450
|
+
height: $height;
|
|
451
|
+
@content;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Three drip layers, of which the size step shows one, two or three - a
|
|
456
|
+
// layer at 0 0 is not drawn, and the image itself is only in the CSS once
|
|
457
|
+
@function _snow-sizes($drips) {
|
|
458
|
+
$sizes: ();
|
|
459
|
+
$widths: (12px, 10px, 11px);
|
|
460
|
+
|
|
461
|
+
@for $i from 1 through 3 {
|
|
462
|
+
$size: 0 0;
|
|
463
|
+
|
|
464
|
+
@if $i <= $drips {
|
|
465
|
+
$w: _deep(list.nth($widths, $i));
|
|
466
|
+
$size: $w $w;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
$sizes: list.append($sizes, $size, comma);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
@return list.join(
|
|
473
|
+
$sizes,
|
|
474
|
+
(_deep(53px) _deep(26px), _deep(86px) _deep(26px), 100% _deep(26px)),
|
|
475
|
+
comma
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// Same idea for the baubles: four layers, two, three or four of them shown
|
|
480
|
+
@function _bauble-sizes($count) {
|
|
481
|
+
$sizes: ();
|
|
482
|
+
$shapes: (15px 20.6px, 12.5px 17px, 14px 19.2px, 13px 17.8px);
|
|
483
|
+
|
|
484
|
+
@for $i from 1 through 4 {
|
|
485
|
+
$size: 0 0;
|
|
486
|
+
|
|
487
|
+
@if $i <= $count {
|
|
488
|
+
$shape: list.nth($shapes, $i);
|
|
489
|
+
$size: _scaled(list.nth($shape, 1)) _scaled(list.nth($shape, 2));
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
$sizes: list.append($sizes, $size, comma);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
@return list.append($sizes, _scaled(48px) _scaled(24px), comma);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
@function _bauble-positions($xs) {
|
|
499
|
+
$positions: ();
|
|
500
|
+
|
|
501
|
+
@each $x in $xs {
|
|
502
|
+
$positions: list.append($positions, $x _scaled(15px), comma);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
@return list.append($positions, 0 0, comma);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
@layer mw.components {
|
|
509
|
+
:root {
|
|
510
|
+
// Confetti, bunting and balloons. Point them at the brand colours to make
|
|
511
|
+
// a birthday look like the site's own party.
|
|
512
|
+
--mw-occasion-color-1: #ff6b6b;
|
|
513
|
+
--mw-occasion-color-2: #ffd166;
|
|
514
|
+
--mw-occasion-color-3: #06d6a0;
|
|
515
|
+
--mw-occasion-color-4: #4cc9f0;
|
|
516
|
+
--mw-occasion-color-5: #9b5de5;
|
|
517
|
+
|
|
518
|
+
// The football stripe and confetti - Germany by default.
|
|
519
|
+
--mw-occasion-flag-1: #000;
|
|
520
|
+
--mw-occasion-flag-2: #dd0000;
|
|
521
|
+
--mw-occasion-flag-3: #ffce00;
|
|
522
|
+
|
|
523
|
+
// Two dials: how big the pieces on the cards are, and how much there is
|
|
524
|
+
// of everything else - snow depth, baubles, particles in the intro and in
|
|
525
|
+
// the scroll. mw-occasion-sm and -lg turn both; the script reads the
|
|
526
|
+
// amount from here, so any other value set in CSS reaches it too.
|
|
527
|
+
--mw-occasion-scale: 1;
|
|
528
|
+
--mw-occasion-amount: 1;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
:root.mw-occasion-sm {
|
|
532
|
+
--mw-occasion-scale: 0.88;
|
|
533
|
+
--mw-occasion-amount: 0.55;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
:root.mw-occasion-lg {
|
|
537
|
+
--mw-occasion-scale: 1.1;
|
|
538
|
+
--mw-occasion-amount: 1.3;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// How far each piece hangs into its surface, a little short of it: a panel
|
|
542
|
+
// or a testimonial makes that much room above its first line where its own
|
|
543
|
+
// padding is tighter, and the piece may touch the heading - it lies on top.
|
|
544
|
+
// A card's padding is deep enough for all of them.
|
|
545
|
+
$_reach: (
|
|
546
|
+
'snow': 12px,
|
|
547
|
+
christmas: 18px,
|
|
548
|
+
newyear: 12px,
|
|
549
|
+
spring: 14px,
|
|
550
|
+
easter: 0px,
|
|
551
|
+
summer: 8px,
|
|
552
|
+
autumn: 10px,
|
|
553
|
+
football: 0px,
|
|
554
|
+
birthday: 16px,
|
|
555
|
+
anniversary: 14px,
|
|
556
|
+
);
|
|
557
|
+
|
|
558
|
+
@each $effect, $reach in $_reach {
|
|
559
|
+
:root.mw-occasion-#{$effect} {
|
|
560
|
+
--mw-occasion-reach: #{$reach};
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
:root:is(#{_list-classes()}) {
|
|
565
|
+
// Room above for what rises over the top edge - stacked in one column on a
|
|
566
|
+
// phone, the piece would otherwise reach into the surface above
|
|
567
|
+
#{$_surface} {
|
|
568
|
+
margin-top: calc(6px + 30px * (var(--mw-occasion-scale) - 1));
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// A panel clips for its rounded header, which rounds itself - the same
|
|
572
|
+
// escape the dropdown uses, for as long as an occasion is on
|
|
573
|
+
.mw-panel:not(:is(#{$_surfaces}) *, .mw-occasion-skip) {
|
|
574
|
+
overflow: visible;
|
|
575
|
+
|
|
576
|
+
> :is(.mw-panel-header, .mw-panel-body):first-child {
|
|
577
|
+
padding-top: max(
|
|
578
|
+
#{spacing('4')},
|
|
579
|
+
calc(var(--mw-occasion-reach) * var(--mw-occasion-scale))
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
.mw-testimonial:not(:is(#{$_surfaces}) *, .mw-occasion-skip) {
|
|
585
|
+
padding-top: max(
|
|
586
|
+
#{spacing('5')},
|
|
587
|
+
calc(var(--mw-occasion-reach) * var(--mw-occasion-scale))
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
:where(.mw-occasion-spot) {
|
|
593
|
+
position: relative;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// Shared by every effect. z-index 1 keeps the piece above the text and the
|
|
597
|
+
// corner arc, and the card badge - also 1, but later - above the piece.
|
|
598
|
+
@each $effect in $_effects {
|
|
599
|
+
#{_on($effect)}::before {
|
|
600
|
+
content: '';
|
|
601
|
+
position: absolute;
|
|
602
|
+
z-index: 1;
|
|
603
|
+
pointer-events: none;
|
|
604
|
+
background-repeat: no-repeat;
|
|
605
|
+
animation-name: mw-occasion-appear;
|
|
606
|
+
animation-duration: var(--mw-duration-slow);
|
|
607
|
+
animation-timing-function: var(--mw-ease-out);
|
|
608
|
+
animation-fill-mode: backwards;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Snow: a cap along the top edge with drips over it. The amount sets the
|
|
613
|
+
// depth - a thin dusting at -sm, a fuller cap at -lg - and the drip count.
|
|
614
|
+
@include _edge('snow', _deep(-11px), _deep(26px)) {
|
|
615
|
+
--mw-occasion-depth: calc(0.35 + 0.65 * var(--mw-occasion-amount));
|
|
616
|
+
--mw-occasion-drip: #{$_snow-drip};
|
|
617
|
+
|
|
618
|
+
background-image:
|
|
619
|
+
var(--mw-occasion-drip), var(--mw-occasion-drip), var(--mw-occasion-drip),
|
|
620
|
+
$_snow-lumps-small, $_snow-lumps, $_snow-band;
|
|
621
|
+
background-size: _snow-sizes(2);
|
|
622
|
+
background-position:
|
|
623
|
+
28% _deep(13px),
|
|
624
|
+
68% _deep(13px),
|
|
625
|
+
48% _deep(13px),
|
|
626
|
+
_deep(20px) 0,
|
|
627
|
+
0 0,
|
|
628
|
+
0 0;
|
|
629
|
+
background-repeat:
|
|
630
|
+
no-repeat, no-repeat, no-repeat, repeat-x, repeat-x, no-repeat;
|
|
631
|
+
mask: $_snow-taper 0 0 / 100% 100% no-repeat;
|
|
632
|
+
// A white cap on a white card takes its outline from the shadow alone
|
|
633
|
+
filter: drop-shadow(0 1px 1.5px rgb(30 50 80 / 0.3));
|
|
634
|
+
transform-origin: 50% _deep(11px);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
#{_on('snow')}:nth-child(even)::before {
|
|
638
|
+
background-position:
|
|
639
|
+
40% _deep(13px),
|
|
640
|
+
76% _deep(13px),
|
|
641
|
+
16% _deep(13px),
|
|
642
|
+
_deep(47px) 0,
|
|
643
|
+
_deep(-30px) 0,
|
|
644
|
+
0 0;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
#{_on('snow', '.mw-occasion-sm')}::before {
|
|
648
|
+
background-size: _snow-sizes(1);
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
#{_on('snow', '.mw-occasion-lg')}::before {
|
|
652
|
+
background-size: _snow-sizes(3);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// Christmas: a fir garland along the edge, baubles hanging off it
|
|
656
|
+
@include _edge(christmas, _scaled(-12px), _scaled(36px), 0) {
|
|
657
|
+
--mw-occasion-red: #{$_bauble-red};
|
|
658
|
+
|
|
659
|
+
background-image:
|
|
660
|
+
var(--mw-occasion-red), $_bauble-gold, $_bauble-silver,
|
|
661
|
+
var(--mw-occasion-red), $_garland;
|
|
662
|
+
background-size: _bauble-sizes(3);
|
|
663
|
+
background-position: _bauble-positions(24% 52% 80% 0);
|
|
664
|
+
background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, repeat-x;
|
|
665
|
+
mask-image: linear-gradient(
|
|
666
|
+
90deg,
|
|
667
|
+
transparent,
|
|
668
|
+
#000 14px,
|
|
669
|
+
#000 calc(100% - 14px),
|
|
670
|
+
transparent
|
|
671
|
+
);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// Same baubles, shuffled - repeating the images would double their weight
|
|
675
|
+
#{_on(christmas)}:nth-child(even)::before {
|
|
676
|
+
background-position: _bauble-positions(62% 34% 88% 0);
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
#{_on(christmas, '.mw-occasion-sm')}::before {
|
|
680
|
+
background-size: _bauble-sizes(2);
|
|
681
|
+
background-position: _bauble-positions(34% 74% 0 0);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
#{_on(christmas, '.mw-occasion-lg')}::before {
|
|
685
|
+
background-size: _bauble-sizes(4);
|
|
686
|
+
background-position: _bauble-positions(18% 40% 62% 84%);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// New year: gold glints and a streamer on the corner
|
|
690
|
+
@include _corner(newyear, -25px, 80px, 52px) {
|
|
691
|
+
background-image: $_sparkles;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// Spring: a flowering cherry twig laid over the corner
|
|
695
|
+
@include _corner(spring, -20px, 105px, 50px, -6px) {
|
|
696
|
+
background-image: $_blossoms;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// Easter: three eggs in a tuft of grass, sitting on the edge
|
|
700
|
+
@include _corner(easter, -30px, 92px, 39px, 8px) {
|
|
701
|
+
background-image: $_eggs;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// Summer: a small sun on the corner and its light inside the card
|
|
705
|
+
@include _corner(summer, -18px, 40px, 40px, -6px) {
|
|
706
|
+
background-image: $_sun;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
:root.mw-occasion-summer #{$_surface} {
|
|
710
|
+
background-image: radial-gradient(
|
|
711
|
+
26rem 16rem at 0 0,
|
|
712
|
+
rgb(255 214 90 / calc(0.13 * var(--mw-occasion-amount))),
|
|
713
|
+
transparent 70%
|
|
714
|
+
);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
// Autumn: three leaves come to rest on the corner
|
|
718
|
+
@include _corner(autumn, -22px, 96px, 46px) {
|
|
719
|
+
background-image: $_leaves;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
// Football: a ball on the edge and a short flag along the top left
|
|
723
|
+
@include _corner(football, -29px, 30px, 30px, 20px) {
|
|
724
|
+
background-image: $_ball;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
:root.mw-occasion-football #{$_surface} {
|
|
728
|
+
background-image: linear-gradient(
|
|
729
|
+
90deg,
|
|
730
|
+
var(--mw-occasion-flag-1) 0 33.34%,
|
|
731
|
+
var(--mw-occasion-flag-2) 0 66.67%,
|
|
732
|
+
var(--mw-occasion-flag-3) 0
|
|
733
|
+
);
|
|
734
|
+
background-size: min(45%, _scaled(12rem))
|
|
735
|
+
calc(2px + 2px * var(--mw-occasion-amount));
|
|
736
|
+
background-position: left top;
|
|
737
|
+
background-repeat: no-repeat;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// Birthday: bunting in the five party colours. The colours are stripes the
|
|
741
|
+
// width of one pennant, cut to shape by the mask, so the tokens reach them.
|
|
742
|
+
@include _edge(birthday, 0, _scaled(19px), 10px) {
|
|
743
|
+
background-image:
|
|
744
|
+
linear-gradient(
|
|
745
|
+
color-mix(in srgb, var(--mw-text-color) 55%, transparent) 0 1.6px,
|
|
746
|
+
transparent 0
|
|
747
|
+
),
|
|
748
|
+
linear-gradient(
|
|
749
|
+
rgb(255 255 255 / 0.2),
|
|
750
|
+
transparent 45%,
|
|
751
|
+
rgb(0 0 0 / 0.14)
|
|
752
|
+
),
|
|
753
|
+
linear-gradient(
|
|
754
|
+
90deg,
|
|
755
|
+
var(--mw-occasion-color-1) 0 20%,
|
|
756
|
+
var(--mw-occasion-color-2) 0 40%,
|
|
757
|
+
var(--mw-occasion-color-3) 0 60%,
|
|
758
|
+
var(--mw-occasion-color-4) 0 80%,
|
|
759
|
+
var(--mw-occasion-color-5) 0
|
|
760
|
+
);
|
|
761
|
+
background-size:
|
|
762
|
+
100% 100%,
|
|
763
|
+
100% 100%,
|
|
764
|
+
_scaled(100px) 100%;
|
|
765
|
+
background-repeat: no-repeat, no-repeat, repeat-x;
|
|
766
|
+
mask:
|
|
767
|
+
$_bunting repeat-x 0 0 / _scaled(100px) _scaled(19px),
|
|
768
|
+
linear-gradient(90deg, #000 80%, transparent);
|
|
769
|
+
mask-composite: intersect;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
// Anniversary: a gold rosette pinned to the corner
|
|
773
|
+
@include _corner(anniversary, -15px, 29px, 37.5px, -3px) {
|
|
774
|
+
background-image: $_rosette;
|
|
775
|
+
rotate: -8deg;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// --- Arriving with the scroll ----------------------------------------------
|
|
779
|
+
|
|
780
|
+
// Each piece moves only while its card crosses the viewport and stands still
|
|
781
|
+
// otherwise - no cost at rest, and the snow reads as settling on the card the
|
|
782
|
+
// reader just reached. The arrivals move translate, rotate and opacity; the
|
|
783
|
+
// loops below keep to scale, so both can run on the same piece.
|
|
784
|
+
$_arrivals: (
|
|
785
|
+
'snow': settle,
|
|
786
|
+
christmas: drop,
|
|
787
|
+
newyear: bloom,
|
|
788
|
+
spring: bloom,
|
|
789
|
+
easter: drop,
|
|
790
|
+
summer: rise,
|
|
791
|
+
autumn: tumble,
|
|
792
|
+
football: roll,
|
|
793
|
+
birthday: drop,
|
|
794
|
+
anniversary: bloom,
|
|
795
|
+
);
|
|
796
|
+
|
|
797
|
+
@supports (animation-timeline: view()) {
|
|
798
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
799
|
+
@each $effect, $arrival in $_arrivals {
|
|
800
|
+
#{_on($effect, '.mw-occasion-scroll')}::before {
|
|
801
|
+
animation-name: mw-occasion-#{$arrival};
|
|
802
|
+
animation-duration: auto;
|
|
803
|
+
animation-timing-function: linear;
|
|
804
|
+
animation-fill-mode: both;
|
|
805
|
+
animation-timeline: view();
|
|
806
|
+
animation-range: entry 30% cover 40%;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
@keyframes mw-occasion-appear {
|
|
813
|
+
from {
|
|
814
|
+
opacity: 0;
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
@keyframes mw-occasion-settle {
|
|
819
|
+
from {
|
|
820
|
+
scale: 1 0;
|
|
821
|
+
opacity: 0;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
30% {
|
|
825
|
+
opacity: 1;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
to {
|
|
829
|
+
scale: 1 1;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
@keyframes mw-occasion-drop {
|
|
834
|
+
0% {
|
|
835
|
+
translate: 0 -22px;
|
|
836
|
+
opacity: 0;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
55% {
|
|
840
|
+
translate: 0 3px;
|
|
841
|
+
opacity: 1;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
75% {
|
|
845
|
+
translate: 0 -1px;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
100% {
|
|
849
|
+
translate: 0 0;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
@keyframes mw-occasion-bloom {
|
|
854
|
+
from {
|
|
855
|
+
translate: 6px -6px;
|
|
856
|
+
rotate: -24deg;
|
|
857
|
+
opacity: 0;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
@keyframes mw-occasion-rise {
|
|
862
|
+
from {
|
|
863
|
+
translate: 0 16px;
|
|
864
|
+
opacity: 0;
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
@keyframes mw-occasion-tumble {
|
|
869
|
+
0% {
|
|
870
|
+
translate: -26px -44px;
|
|
871
|
+
rotate: -50deg;
|
|
872
|
+
opacity: 0;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
25% {
|
|
876
|
+
opacity: 1;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
60% {
|
|
880
|
+
translate: 6px -8px;
|
|
881
|
+
rotate: 12deg;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
100% {
|
|
885
|
+
translate: 0 0;
|
|
886
|
+
rotate: 0deg;
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
@keyframes mw-occasion-roll {
|
|
891
|
+
from {
|
|
892
|
+
translate: calc(100cqi - 3rem) 0;
|
|
893
|
+
rotate: 2.5turn;
|
|
894
|
+
opacity: 0;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
15% {
|
|
898
|
+
opacity: 1;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// --- Particles --------------------------------------------------------------
|
|
903
|
+
|
|
904
|
+
// Both layers are created by the script and never by the markup. Fixed,
|
|
905
|
+
// click-through and contained, so the page underneath stays usable while
|
|
906
|
+
// they run and nothing inside them reaches layout outside.
|
|
907
|
+
.mw-occasion-intro,
|
|
908
|
+
.mw-occasion-drift {
|
|
909
|
+
position: fixed;
|
|
910
|
+
inset: 0;
|
|
911
|
+
pointer-events: none;
|
|
912
|
+
overflow: hidden;
|
|
913
|
+
contain: strict;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
// Above everything, modals and toasts included - it is gone in five seconds.
|
|
917
|
+
.mw-occasion-intro {
|
|
918
|
+
--mw-occasion-hold: 3.8s;
|
|
919
|
+
|
|
920
|
+
z-index: z-index('occasion');
|
|
921
|
+
animation-name: mw-occasion-out;
|
|
922
|
+
animation-duration: 800ms;
|
|
923
|
+
animation-timing-function: ease-in;
|
|
924
|
+
animation-delay: var(--mw-occasion-hold);
|
|
925
|
+
animation-fill-mode: forwards;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
// Any click, key or scroll takes it away early.
|
|
929
|
+
.mw-occasion-intro.mw-occasion-leaving {
|
|
930
|
+
animation-duration: 300ms;
|
|
931
|
+
animation-delay: 0s;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// Below the header, so the bar stays clean, above cards and sections.
|
|
935
|
+
.mw-occasion-drift {
|
|
936
|
+
--mw-occasion-laps: 3;
|
|
937
|
+
|
|
938
|
+
z-index: z-index('header') - 20;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
@supports not (animation-timeline: scroll()) {
|
|
942
|
+
.mw-occasion-drift {
|
|
943
|
+
display: none;
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
@media (prefers-reduced-motion: reduce) {
|
|
948
|
+
.mw-occasion-intro,
|
|
949
|
+
.mw-occasion-drift {
|
|
950
|
+
display: none;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
// The span moves, its ::before carries the shape and spins - one transform
|
|
955
|
+
// each, or a spin would turn the direction of travel with it.
|
|
956
|
+
// The defaults stand for what the script sets on every particle.
|
|
957
|
+
.mw-occasion-particle {
|
|
958
|
+
--mw-occasion-x: 0vw;
|
|
959
|
+
--mw-occasion-y: 0vh;
|
|
960
|
+
--mw-occasion-dx: 0vw;
|
|
961
|
+
--mw-occasion-dy: 0vh;
|
|
962
|
+
--mw-occasion-drift: 0vw;
|
|
963
|
+
--mw-occasion-peak: 70vh;
|
|
964
|
+
--mw-occasion-size: 10px;
|
|
965
|
+
--mw-occasion-time: 4s;
|
|
966
|
+
--mw-occasion-delay: 0s;
|
|
967
|
+
--mw-occasion-sway: 12px;
|
|
968
|
+
--mw-occasion-sway-time: 1.6s;
|
|
969
|
+
--mw-occasion-spin: 0turn;
|
|
970
|
+
--mw-occasion-spin-time: 4s;
|
|
971
|
+
--mw-occasion-axis: z;
|
|
972
|
+
--mw-occasion-angle: 0deg;
|
|
973
|
+
--mw-occasion-tint: #fff;
|
|
974
|
+
--mw-occasion-start: 0%;
|
|
975
|
+
--mw-occasion-lap: 0;
|
|
976
|
+
|
|
977
|
+
position: absolute;
|
|
978
|
+
top: 0;
|
|
979
|
+
left: 0;
|
|
980
|
+
width: var(--mw-occasion-size);
|
|
981
|
+
height: var(--mw-occasion-size);
|
|
982
|
+
animation-delay: var(--mw-occasion-delay);
|
|
983
|
+
animation-fill-mode: both;
|
|
984
|
+
|
|
985
|
+
&::before {
|
|
986
|
+
content: '';
|
|
987
|
+
position: absolute;
|
|
988
|
+
inset: 0;
|
|
989
|
+
background: center / contain no-repeat;
|
|
990
|
+
animation-name: mw-occasion-spin;
|
|
991
|
+
animation-duration: var(--mw-occasion-spin-time);
|
|
992
|
+
animation-timing-function: linear;
|
|
993
|
+
animation-iteration-count: infinite;
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
.mw-occasion-falling,
|
|
998
|
+
.mw-occasion-rising {
|
|
999
|
+
animation-name: mw-occasion-travel, mw-occasion-sway;
|
|
1000
|
+
animation-duration: var(--mw-occasion-time), var(--mw-occasion-sway-time);
|
|
1001
|
+
animation-timing-function: linear, ease-in-out;
|
|
1002
|
+
animation-iteration-count: 1, infinite;
|
|
1003
|
+
animation-direction: normal, alternate;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
.mw-occasion-falling {
|
|
1007
|
+
--mw-occasion-y0: -10vh;
|
|
1008
|
+
--mw-occasion-y1: 110vh;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
.mw-occasion-rising {
|
|
1012
|
+
--mw-occasion-y0: 110vh;
|
|
1013
|
+
--mw-occasion-y1: -20vh;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
// The same travel, scrubbed by the page scroll instead of the clock. The
|
|
1017
|
+
// script sets the laps from the page length; each particle starts at its own
|
|
1018
|
+
// point of the scroll and runs zero to two laps more than the others.
|
|
1019
|
+
@supports (animation-timeline: scroll()) {
|
|
1020
|
+
.mw-occasion-drift > .mw-occasion-particle {
|
|
1021
|
+
$laps: calc(var(--mw-occasion-laps) + var(--mw-occasion-lap));
|
|
1022
|
+
|
|
1023
|
+
animation-duration: auto;
|
|
1024
|
+
animation-delay: 0s;
|
|
1025
|
+
animation-iteration-count: $laps, calc(#{$laps} * 4);
|
|
1026
|
+
animation-timeline: scroll(root);
|
|
1027
|
+
animation-range: var(--mw-occasion-start) 100%;
|
|
1028
|
+
|
|
1029
|
+
&::before {
|
|
1030
|
+
animation-duration: auto;
|
|
1031
|
+
animation-iteration-count: $laps;
|
|
1032
|
+
animation-timeline: scroll(root);
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
// Thrown from a bottom corner: sideways with drag, up and back down on
|
|
1038
|
+
// separate properties so each keeps its own easing.
|
|
1039
|
+
.mw-occasion-bursting {
|
|
1040
|
+
animation-name: mw-occasion-throw, mw-occasion-arc;
|
|
1041
|
+
animation-duration: var(--mw-occasion-time);
|
|
1042
|
+
animation-timing-function: cubic-bezier(0.15, 0.7, 0.35, 1), linear;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
.mw-occasion-launching {
|
|
1046
|
+
height: calc(var(--mw-occasion-size) * 7);
|
|
1047
|
+
animation-name: mw-occasion-launch;
|
|
1048
|
+
animation-duration: 700ms;
|
|
1049
|
+
animation-timing-function: cubic-bezier(0.3, 0.6, 0.4, 1);
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
.mw-occasion-exploding {
|
|
1053
|
+
translate: var(--mw-occasion-x) var(--mw-occasion-y);
|
|
1054
|
+
animation-name: mw-occasion-explode;
|
|
1055
|
+
animation-duration: var(--mw-occasion-time);
|
|
1056
|
+
animation-timing-function: cubic-bezier(0.1, 0.8, 0.3, 1);
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
.mw-occasion-twinkling {
|
|
1060
|
+
translate: var(--mw-occasion-x) var(--mw-occasion-y);
|
|
1061
|
+
animation-name: mw-occasion-sparkle;
|
|
1062
|
+
animation-duration: var(--mw-occasion-time);
|
|
1063
|
+
animation-timing-function: ease-in-out;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
.mw-occasion-beaming {
|
|
1067
|
+
animation-name: mw-occasion-beam;
|
|
1068
|
+
animation-timing-function: ease-in-out;
|
|
1069
|
+
animation-direction: alternate;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
.mw-occasion-flashing {
|
|
1073
|
+
translate: var(--mw-occasion-x) var(--mw-occasion-y);
|
|
1074
|
+
margin: calc(var(--mw-occasion-size) / -2);
|
|
1075
|
+
animation-name: mw-occasion-flash;
|
|
1076
|
+
animation-duration: 900ms;
|
|
1077
|
+
animation-timing-function: ease-out;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
// Shapes. Everything that has to show on a white page too carries a rim.
|
|
1081
|
+
.mw-occasion-flake::before {
|
|
1082
|
+
border-radius: 50%;
|
|
1083
|
+
background: radial-gradient(
|
|
1084
|
+
circle,
|
|
1085
|
+
#fff 0 36%,
|
|
1086
|
+
rgb(255 255 255 / 0.75) 50%,
|
|
1087
|
+
rgb(140 165 195 / 0.5) 60%,
|
|
1088
|
+
transparent 70%
|
|
1089
|
+
);
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
.mw-occasion-crystal::before {
|
|
1093
|
+
background-image: $_crystal;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
.mw-occasion-star::before {
|
|
1097
|
+
background-image: $_gold-star;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
.mw-occasion-glint::before {
|
|
1101
|
+
background-image: $_glint;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
// Cherry pink with a shaded tip - a pale pink falls on a dark page as snow
|
|
1105
|
+
.mw-occasion-petal {
|
|
1106
|
+
--mw-occasion-tint: #f48fb1;
|
|
1107
|
+
|
|
1108
|
+
&:nth-child(3n + 1) {
|
|
1109
|
+
--mw-occasion-tint: #f7a6c3;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
&:nth-child(3n + 2) {
|
|
1113
|
+
--mw-occasion-tint: #e96b98;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
&::before {
|
|
1117
|
+
background-color: var(--mw-occasion-tint);
|
|
1118
|
+
background-image: linear-gradient(
|
|
1119
|
+
160deg,
|
|
1120
|
+
rgb(255 255 255 / 0.4),
|
|
1121
|
+
transparent 50%,
|
|
1122
|
+
rgb(110 20 60 / 0.3)
|
|
1123
|
+
);
|
|
1124
|
+
mask: $_petal center / contain no-repeat;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
:root.mw-occasion-easter .mw-occasion-petal {
|
|
1129
|
+
&:nth-child(4n + 1) {
|
|
1130
|
+
--mw-occasion-tint: #f5cf52;
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
&:nth-child(4n + 2) {
|
|
1134
|
+
--mw-occasion-tint: #b59bec;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
&:nth-child(4n + 3) {
|
|
1138
|
+
--mw-occasion-tint: #7fd2ad;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
&:nth-child(4n) {
|
|
1142
|
+
--mw-occasion-tint: #f49ac1;
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
// Summer's drift: long soft rays from a sun above the top right corner.
|
|
1147
|
+
// Pinned at their top end, they swing with the scroll instead of travelling.
|
|
1148
|
+
.mw-occasion-beam {
|
|
1149
|
+
height: 180vh;
|
|
1150
|
+
translate: calc(102vw - var(--mw-occasion-size) / 2) -8vh;
|
|
1151
|
+
transform-origin: 50% 0;
|
|
1152
|
+
|
|
1153
|
+
&::before {
|
|
1154
|
+
background: linear-gradient(
|
|
1155
|
+
90deg,
|
|
1156
|
+
transparent,
|
|
1157
|
+
rgb(255 222 130 / 0.24),
|
|
1158
|
+
transparent
|
|
1159
|
+
);
|
|
1160
|
+
mask-image: linear-gradient(#000 15%, transparent 85%);
|
|
1161
|
+
animation-name: none;
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
.mw-occasion-maple::before {
|
|
1166
|
+
background-image: $_maple-leaf;
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
.mw-occasion-oak::before {
|
|
1170
|
+
background-image: $_oak-leaf;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
.mw-occasion-birch::before {
|
|
1174
|
+
background-image: $_birch-leaf;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
.mw-occasion-confetti::before {
|
|
1178
|
+
inset: 22% 0;
|
|
1179
|
+
border-radius: 1px;
|
|
1180
|
+
background: var(--mw-occasion-tint);
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
.mw-occasion-confetti:nth-child(7n + 3)::before {
|
|
1184
|
+
inset: 0;
|
|
1185
|
+
border-radius: 50%;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
@for $k from 1 through 5 {
|
|
1189
|
+
.mw-occasion-confetti:nth-child(5n + #{$k}),
|
|
1190
|
+
.mw-occasion-balloon:nth-child(5n + #{$k}) {
|
|
1191
|
+
--mw-occasion-tint: var(--mw-occasion-color-#{$k});
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
$_gold-tints: (#f7d774, #e2b33c, #fff1c1, #c9951f, #dfe3ea);
|
|
1196
|
+
|
|
1197
|
+
@for $k from 1 through 5 {
|
|
1198
|
+
:root.mw-occasion-anniversary .mw-occasion-confetti:nth-child(5n + #{$k}) {
|
|
1199
|
+
--mw-occasion-tint: #{list.nth($_gold-tints, $k)};
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
.mw-occasion-strip::before {
|
|
1204
|
+
inset: 0 34%;
|
|
1205
|
+
background: var(--mw-occasion-tint);
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
@for $k from 1 through 3 {
|
|
1209
|
+
.mw-occasion-strip:nth-child(3n + #{$k}) {
|
|
1210
|
+
--mw-occasion-tint: var(--mw-occasion-flag-#{$k});
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
.mw-occasion-balloon {
|
|
1215
|
+
&::before {
|
|
1216
|
+
inset: 0 0 22%;
|
|
1217
|
+
background-color: var(--mw-occasion-tint);
|
|
1218
|
+
background-image: radial-gradient(
|
|
1219
|
+
circle at 32% 26%,
|
|
1220
|
+
rgb(255 255 255 / 0.55) 0 9%,
|
|
1221
|
+
transparent 24%
|
|
1222
|
+
);
|
|
1223
|
+
mask: $_balloon center / contain no-repeat;
|
|
1224
|
+
animation-name: none;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
&::after {
|
|
1228
|
+
content: '';
|
|
1229
|
+
position: absolute;
|
|
1230
|
+
top: 78%;
|
|
1231
|
+
left: 50%;
|
|
1232
|
+
width: 1px;
|
|
1233
|
+
height: 90%;
|
|
1234
|
+
background: color-mix(in srgb, var(--mw-text-color) 45%, transparent);
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
.mw-occasion-ball::before {
|
|
1239
|
+
background-image: $_ball;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
.mw-occasion-spark::before {
|
|
1243
|
+
inset: 0 calc(50% - 1.5px);
|
|
1244
|
+
border-radius: 3px;
|
|
1245
|
+
background: linear-gradient(
|
|
1246
|
+
to top,
|
|
1247
|
+
transparent,
|
|
1248
|
+
var(--mw-occasion-tint) 60%,
|
|
1249
|
+
#fff
|
|
1250
|
+
);
|
|
1251
|
+
box-shadow: 0 0 6px 1px var(--mw-occasion-tint);
|
|
1252
|
+
rotate: var(--mw-occasion-angle);
|
|
1253
|
+
animation-name: none;
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
.mw-occasion-flash::before {
|
|
1257
|
+
border-radius: 50%;
|
|
1258
|
+
background: radial-gradient(
|
|
1259
|
+
circle,
|
|
1260
|
+
rgb(255 255 255 / 0.95) 0 8%,
|
|
1261
|
+
rgb(255 225 150 / 0.5) 25%,
|
|
1262
|
+
transparent 65%
|
|
1263
|
+
);
|
|
1264
|
+
animation-name: none;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
.mw-occasion-trail::before {
|
|
1268
|
+
inset: 0 40%;
|
|
1269
|
+
border-radius: 2px;
|
|
1270
|
+
background: linear-gradient(to top, transparent, #fff3c4);
|
|
1271
|
+
animation-name: none;
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
// Christmas: the tree lights up in the middle of the screen
|
|
1275
|
+
.mw-occasion-intro-christmas {
|
|
1276
|
+
--mw-occasion-hold: 4.4s;
|
|
1277
|
+
background: radial-gradient(
|
|
1278
|
+
ellipse 60% 55% at 50% 100%,
|
|
1279
|
+
rgb(8 16 30 / 0.4),
|
|
1280
|
+
transparent 75%
|
|
1281
|
+
);
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
.mw-occasion-tree {
|
|
1285
|
+
position: absolute;
|
|
1286
|
+
bottom: 3vh;
|
|
1287
|
+
left: 50%;
|
|
1288
|
+
height: min(48vh, 84vw);
|
|
1289
|
+
aspect-ratio: 120 / 150;
|
|
1290
|
+
translate: -50% 0;
|
|
1291
|
+
filter: drop-shadow(0 10px 30px rgb(0 0 0 / 0.35));
|
|
1292
|
+
animation-name: mw-occasion-tree-in;
|
|
1293
|
+
animation-duration: 900ms;
|
|
1294
|
+
animation-timing-function: cubic-bezier(0.2, 0.8, 0.3, 1);
|
|
1295
|
+
animation-fill-mode: both;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
.mw-occasion-tree-light {
|
|
1299
|
+
animation-name: mw-occasion-light-on, mw-occasion-twinkle;
|
|
1300
|
+
animation-duration: 400ms, 1.1s;
|
|
1301
|
+
animation-timing-function: ease-out, ease-in-out;
|
|
1302
|
+
animation-iteration-count: 1, infinite;
|
|
1303
|
+
animation-direction: normal, alternate;
|
|
1304
|
+
animation-fill-mode: both;
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
@for $i from 1 through 12 {
|
|
1308
|
+
.mw-occasion-tree-light:nth-child(#{$i}) {
|
|
1309
|
+
animation-delay:
|
|
1310
|
+
600ms + $i * 90ms,
|
|
1311
|
+
1000ms + $i * 90ms;
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
.mw-occasion-tree-star {
|
|
1316
|
+
transform-box: fill-box;
|
|
1317
|
+
transform-origin: center;
|
|
1318
|
+
animation-name: mw-occasion-star;
|
|
1319
|
+
animation-duration: 900ms;
|
|
1320
|
+
animation-timing-function: var(--mw-ease-spring);
|
|
1321
|
+
animation-delay: 1.8s;
|
|
1322
|
+
animation-fill-mode: both;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
.mw-occasion-tree-glow {
|
|
1326
|
+
animation-name: mw-occasion-light-on;
|
|
1327
|
+
animation-duration: 1.2s;
|
|
1328
|
+
animation-timing-function: ease-out;
|
|
1329
|
+
animation-delay: 2s;
|
|
1330
|
+
animation-fill-mode: both;
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
// Summer: the sun rises in the top right corner, its rays turning slowly
|
|
1334
|
+
.mw-occasion-intro-summer {
|
|
1335
|
+
background: linear-gradient(
|
|
1336
|
+
200deg,
|
|
1337
|
+
rgb(255 200 80 / 0.14),
|
|
1338
|
+
transparent 60%
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
.mw-occasion-sun {
|
|
1343
|
+
position: absolute;
|
|
1344
|
+
top: 0;
|
|
1345
|
+
right: 0;
|
|
1346
|
+
width: 70vmax;
|
|
1347
|
+
aspect-ratio: 1;
|
|
1348
|
+
translate: 45% -45%;
|
|
1349
|
+
border-radius: 50%;
|
|
1350
|
+
background: radial-gradient(
|
|
1351
|
+
circle,
|
|
1352
|
+
rgb(255 251 225 / 0.95) 0 6%,
|
|
1353
|
+
rgb(255 218 110 / 0.6) 15%,
|
|
1354
|
+
rgb(255 190 70 / 0.2) 34%,
|
|
1355
|
+
transparent 62%
|
|
1356
|
+
);
|
|
1357
|
+
animation-name: mw-occasion-sun-in;
|
|
1358
|
+
animation-duration: 1.6s;
|
|
1359
|
+
animation-timing-function: cubic-bezier(0.2, 0.8, 0.3, 1);
|
|
1360
|
+
animation-fill-mode: both;
|
|
1361
|
+
|
|
1362
|
+
&::before {
|
|
1363
|
+
content: '';
|
|
1364
|
+
position: absolute;
|
|
1365
|
+
inset: 0;
|
|
1366
|
+
border-radius: 50%;
|
|
1367
|
+
background: repeating-conic-gradient(
|
|
1368
|
+
rgb(255 232 150 / 0.45) 0 3deg,
|
|
1369
|
+
transparent 3deg 15deg
|
|
1370
|
+
);
|
|
1371
|
+
mask-image: radial-gradient(
|
|
1372
|
+
circle,
|
|
1373
|
+
transparent 7%,
|
|
1374
|
+
#000 12%,
|
|
1375
|
+
transparent 58%
|
|
1376
|
+
);
|
|
1377
|
+
animation-name: mw-occasion-turn;
|
|
1378
|
+
animation-duration: 6s;
|
|
1379
|
+
animation-timing-function: linear;
|
|
1380
|
+
animation-fill-mode: both;
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
@keyframes mw-occasion-out {
|
|
1385
|
+
to {
|
|
1386
|
+
opacity: 0;
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
@keyframes mw-occasion-spin {
|
|
1391
|
+
from {
|
|
1392
|
+
rotate: var(--mw-occasion-axis) 0deg;
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
to {
|
|
1396
|
+
rotate: var(--mw-occasion-axis) var(--mw-occasion-spin);
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
@keyframes mw-occasion-travel {
|
|
1401
|
+
from {
|
|
1402
|
+
translate: var(--mw-occasion-x) var(--mw-occasion-y0);
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
to {
|
|
1406
|
+
translate: calc(var(--mw-occasion-x) + var(--mw-occasion-drift))
|
|
1407
|
+
var(--mw-occasion-y1);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
@keyframes mw-occasion-sway {
|
|
1412
|
+
from {
|
|
1413
|
+
transform: translateX(calc(var(--mw-occasion-sway) * -1));
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
to {
|
|
1417
|
+
transform: translateX(var(--mw-occasion-sway));
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
@keyframes mw-occasion-throw {
|
|
1422
|
+
from {
|
|
1423
|
+
translate: var(--mw-occasion-x) 102vh;
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
to {
|
|
1427
|
+
translate: calc(var(--mw-occasion-x) + var(--mw-occasion-dx)) 102vh;
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
@keyframes mw-occasion-arc {
|
|
1432
|
+
0% {
|
|
1433
|
+
transform: translateY(0);
|
|
1434
|
+
animation-timing-function: cubic-bezier(0.2, 0.8, 0.4, 1);
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
38% {
|
|
1438
|
+
transform: translateY(calc(var(--mw-occasion-peak) * -1));
|
|
1439
|
+
animation-timing-function: cubic-bezier(0.5, 0, 0.8, 0.6);
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
100% {
|
|
1443
|
+
transform: translateY(calc(var(--mw-occasion-peak) * -1 + 80vh));
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
@keyframes mw-occasion-launch {
|
|
1448
|
+
from {
|
|
1449
|
+
translate: var(--mw-occasion-x) 102vh;
|
|
1450
|
+
opacity: 0;
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
20% {
|
|
1454
|
+
opacity: 1;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
to {
|
|
1458
|
+
translate: var(--mw-occasion-x) var(--mw-occasion-y);
|
|
1459
|
+
opacity: 0;
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
@keyframes mw-occasion-explode {
|
|
1464
|
+
0% {
|
|
1465
|
+
transform: translate(0, 0) scale(0.4);
|
|
1466
|
+
opacity: 0;
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
8% {
|
|
1470
|
+
opacity: 1;
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
65% {
|
|
1474
|
+
transform: translate(var(--mw-occasion-dx), var(--mw-occasion-dy))
|
|
1475
|
+
scale(1);
|
|
1476
|
+
opacity: 1;
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
100% {
|
|
1480
|
+
transform: translate(
|
|
1481
|
+
var(--mw-occasion-dx),
|
|
1482
|
+
calc(var(--mw-occasion-dy) + 6vh)
|
|
1483
|
+
)
|
|
1484
|
+
scale(0.5);
|
|
1485
|
+
opacity: 0;
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
@keyframes mw-occasion-flash {
|
|
1490
|
+
from {
|
|
1491
|
+
scale: 0.2;
|
|
1492
|
+
opacity: 1;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
to {
|
|
1496
|
+
scale: 1;
|
|
1497
|
+
opacity: 0;
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
@keyframes mw-occasion-tree-in {
|
|
1502
|
+
from {
|
|
1503
|
+
translate: -50% 8%;
|
|
1504
|
+
scale: 0.92;
|
|
1505
|
+
opacity: 0;
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
@keyframes mw-occasion-light-on {
|
|
1510
|
+
from {
|
|
1511
|
+
opacity: 0;
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
@keyframes mw-occasion-twinkle {
|
|
1516
|
+
to {
|
|
1517
|
+
opacity: 0.45;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
@keyframes mw-occasion-star {
|
|
1522
|
+
from {
|
|
1523
|
+
scale: 0;
|
|
1524
|
+
rotate: -90deg;
|
|
1525
|
+
opacity: 0;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
@keyframes mw-occasion-turn {
|
|
1530
|
+
to {
|
|
1531
|
+
rotate: 40deg;
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
@keyframes mw-occasion-sparkle {
|
|
1536
|
+
0%,
|
|
1537
|
+
100% {
|
|
1538
|
+
scale: 0;
|
|
1539
|
+
opacity: 0;
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
50% {
|
|
1543
|
+
scale: 1;
|
|
1544
|
+
opacity: 1;
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
@keyframes mw-occasion-beam {
|
|
1549
|
+
from {
|
|
1550
|
+
rotate: calc(var(--mw-occasion-angle) - 5deg);
|
|
1551
|
+
opacity: 0.45;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
to {
|
|
1555
|
+
rotate: calc(var(--mw-occasion-angle) + 5deg);
|
|
1556
|
+
opacity: 1;
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
@keyframes mw-occasion-sun-in {
|
|
1561
|
+
from {
|
|
1562
|
+
scale: 0.4;
|
|
1563
|
+
opacity: 0;
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
@media print, (forced-colors: active) {
|
|
1568
|
+
:is(#{$_host})::before,
|
|
1569
|
+
.mw-occasion-intro,
|
|
1570
|
+
.mw-occasion-drift {
|
|
1571
|
+
display: none;
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
}
|